diff --git a/.gitignore b/.gitignore index e57e32fd38..417e06fcf4 100644 --- a/.gitignore +++ b/.gitignore @@ -53,9 +53,12 @@ tarballs/ # Ignore Kdevelop project file .kdev4 +3rdparty/ + util/*/.dependencies util/*/.test util/cbfstool/cbfstool +util/cbfstool/rmodtool util/cbmem/.dependencies util/cbmem/cbmem util/dumpmmcr/dumpmmcr diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 25ba6e3c67..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,5 +0,0 @@ -[submodule "3rdparty"] - path = 3rdparty - url = ../blobs.git - update = none - ignore = all diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 20191c7298..0000000000 --- a/.gitreview +++ /dev/null @@ -1,5 +0,0 @@ -[gerrit] -host=review.coreboot.org -port=29418 -project=coreboot -defaultbranch=master diff --git a/3rdparty b/3rdparty deleted file mode 160000 index ba8caa30bd..0000000000 --- a/3rdparty +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ba8caa30bd5ed6d89dbfd40e17c75c94d43804c6 diff --git a/COMMIT-QUEUE.ini b/COMMIT-QUEUE.ini new file mode 100644 index 0000000000..96600d2ea2 --- /dev/null +++ b/COMMIT-QUEUE.ini @@ -0,0 +1,12 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Per-project Commit Queue settings. +# Documentation: http://goo.gl/4rZhAx + +[GENERAL] + +# Stages to ignore in the commit queue. If these steps break, your CL will be +# submitted anyway. Use with caution. +ignored-stages: HWTest VMTest diff --git a/Makefile b/Makefile index 9aafe7cd6c..b71b93cb43 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,9 @@ HOSTCXX = g++ HOSTCFLAGS := -g HOSTCXXFLAGS := -g +# Pass -undef to avoid predefined legacy macros like 'i386' +PREPROCESS_ONLY := -E -P -x assembler-with-cpp -undef + DOXYGEN := doxygen DOXYGEN_OUTPUT_DIR := doxygen @@ -113,37 +116,22 @@ else include $(HAVE_DOTCONFIG) -ARCHDIR-$(CONFIG_ARCH_ARMV7) := armv7 -ARCHDIR-$(CONFIG_ARCH_X86) := x86 +include toolchain.inc -ARCH-y := $(ARCHDIR-y) +COMMA:=, -# If architecture folder name is different from GCC binutils architecture name, -# override here. -ARCH-$(CONFIG_ARCH_ARMV7) := armv7 -ARCH-$(CONFIG_ARCH_X86) := i386 - -ifneq ($(INNER_SCANBUILD),y) -CC := $(CC_$(ARCH-y)) -endif -AS := $(AS_$(ARCH-y)) -LD := $(LD_$(ARCH-y)) -NM := $(NM_$(ARCH-y)) -OBJCOPY := $(OBJCOPY_$(ARCH-y)) -OBJDUMP := $(OBJDUMP_$(ARCH-y)) -READELF := $(READELF_$(ARCH-y)) -STRIP := $(STRIP_$(ARCH-y)) -AR := $(AR_$(ARCH-y)) - -CFLAGS += $(CFLAGS_$(ARCH-y)) - -LIBGCC_FILE_NAME := $(shell test -r `$(CC) -print-libgcc-file-name` && \ - $(CC) -print-libgcc-file-name) +# Function to wrap calls to the linker (will be overridden for CLANG) +# $1 stage +# $2 objects to link (will be wrapped in --start-group and --end-group) +# $3 options passed directly (to GCC or LD) (-nostdlib and -static are default) +# $4 options passed to LD (wrapped with -Wl, for GCC) +link=$(CC_$(1)) $(CFLAGS_$(1)) -nostdlib -static $(3) $(foreach opt,$(4),-Wl$(COMMA)$(opt)) -Wl,--start-group $(2) -Wl,--end-group ifneq ($(INNER_SCANBUILD),y) ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) CC:=clang -m32 -mno-mmx -mno-sse HOSTCC:=clang +link:=$(LD_$(1)) -nostdlib -static $(3) $(4) --start-group $(2) --end-group endif endif @@ -190,6 +178,13 @@ endif $(obj)/config.h: $(MAKE) oldconfig +# Dependencies that should be built before all files in all classes +# Careful: interpreted as order-only prerequisites, use only for header files! +generic-deps = $(obj)/config.h + +# Every file can append to this string. It is simply eval'ed after the scan. +postprocessors := + # Add a new class of source/object files to the build system add-class= \ $(eval $(1)-srcs:=) \ @@ -239,12 +234,16 @@ endif # Eliminate duplicate mentions of source files in a class $(foreach class,$(classes),$(eval $(class)-srcs:=$(sort $($(class)-srcs)))) -src-to-obj=$(addsuffix .$(1).o, $(basename $(patsubst src/%, $(obj)/%, $($(1)-srcs)))) -$(foreach class,$(classes),$(eval $(class)-objs:=$(call src-to-obj,$(class)))) +# Converts one or more source file paths to their corresponding build/ paths. +# Only .c and .S get converted to .o, other files (like .ld) keep their name. +# $1 stage name +# $2 file path (list) +src-to-obj=$(foreach file,$(2),$(basename $(patsubst src/%,$(obj)/%,$(file))).$(1)$(patsubst %.c,%.o,$(patsubst %.S,%.o,$(suffix $(file))))) + +$(foreach class,$(classes),$(eval $(class)-objs+=$(call src-to-obj,$(class),$($(class)-srcs)))) # Call post-processors if they're defined -$(foreach class,$(classes),\ - $(if $(value $(class)-postprocess),$(eval $(call $(class)-postprocess,$($(class)-objs))))) +$(eval $(postprocessors)) allsrcs:=$(foreach var, $(addsuffix -srcs,$(classes)), $($(var))) allobjs:=$(foreach var, $(addsuffix -objs,$(classes)), $($(var))) @@ -253,14 +252,14 @@ alldirs:=$(sort $(abspath $(dir $(allobjs)))) # macro to define template macros that are used by use_template macro define create_cc_template # $1 obj class -# $2 source suffix (c, S) +# $2 source suffix (c, S, ld) # $3 additional compiler flags # $4 additional dependencies ifn$(EMPTY)def $(1)-objs_$(2)_template de$(EMPTY)fine $(1)-objs_$(2)_template -$(obj)/$$(1).$(1).o: src/$$(1).$(2) $(obj)/config.h $(4) +$$(call src-to-obj,$1,$$(1)): $$(1) $(4) | $$$$(generic-deps) @printf " CC $$$$(subst $$$$(obj)/,,$$$$(@))\n" - $(CC) $(3) -MMD $$$$(CFLAGS) -c -o $$$$@ $$$$< + $(CC_$(1)) -MMD $$$$(CFLAGS_$(1)) -MT $$$$(@) $(3) -c -o $$$$@ $$$$< en$(EMPTY)def end$(EMPTY)if endef @@ -268,20 +267,21 @@ endef filetypes-of-class=$(subst .,,$(sort $(suffix $($(1)-srcs)))) $(foreach class,$(classes), \ $(foreach type,$(call filetypes-of-class,$(class)), \ + $(eval $(class)-$(type)-ccopts += $(generic-$(type)-ccopts) $($(class)-generic-ccopts)) \ $(eval $(call create_cc_template,$(class),$(type),$($(class)-$(type)-ccopts),$($(class)-$(type)-deps))))) -foreach-src=$(foreach file,$($(1)-srcs),$(eval $(call $(1)-objs_$(subst .,,$(suffix $(file)))_template,$(subst src/,,$(basename $(file)))))) +foreach-src=$(foreach file,$($(1)-srcs),$(eval $(call $(1)-objs_$(subst .,,$(suffix $(file)))_template,$(file)))) $(eval $(foreach class,$(classes),$(call foreach-src,$(class)))) -DEPENDENCIES = $(allobjs:.o=.d) +DEPENDENCIES += $(addsuffix .d,$(basename $(allobjs))) -include $(DEPENDENCIES) printall: - @$(foreach class,$(classes),echo $(class)-objs:=$($(class)-objs); ) + @$(foreach class,$(classes),echo $(class)-objs=$($(class)-objs); ) @echo alldirs:=$(alldirs) @echo allsrcs=$(allsrcs) @echo DEPENDENCIES=$(DEPENDENCIES) - @echo LIBGCC_FILE_NAME=$(LIBGCC_FILE_NAME) + @echo LIBGCC_FILE_NAME=$(LIBGCC_FILE_NAME_$(class)) @$(foreach class,$(special-classes),echo $(class):='$($(class))'; ) endif diff --git a/Makefile.inc b/Makefile.inc index da350d196a..b216995433 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -41,7 +41,7 @@ export objgenerated := $(obj)/generated ####################################################################### # root rule to resolve if in build mode (ie. configuration exists) -real-target: $(obj)/config.h coreboot +real-target: coreboot coreboot: build-dirs $(obj)/coreboot.rom ####################################################################### @@ -50,96 +50,63 @@ PHONY+= clean-abuild coreboot lint lint-stable build-dirs ####################################################################### # root source directories of coreboot -subdirs-y := src/lib src/console src/device src/ec src/southbridge +subdirs-y := src/lib src/console src/device src/ec src/southbridge src/soc subdirs-y += src/northbridge src/superio src/drivers src/cpu src/vendorcode subdirs-y += util/cbfstool util/sconfig util/nvramtool -subdirs-y += src/arch/$(ARCHDIR-y) +subdirs-y += src/arch/arm src/arch/arm64 src/arch/mips src/arch/x86 subdirs-y += src/mainboard/$(MAINBOARDDIR) subdirs-y += site-local ####################################################################### # Add source classes and their build options -classes-y := ramstage romstage bootblock smm smmstub cpu_microcode rmodules +classes-y := ramstage romstage bootblock smm smmstub cpu_microcode verstage secmon +# Add dynamic classes for rmodules +$(foreach supported_arch,$(ARCH_SUPPORTED), \ + $(eval $(call define_class,rmodules_$(ARCH_TO_TOOLCHAIN_$(supported_arch)),$(ARCH_TO_TOOLCHAIN_$(supported_arch))))) ####################################################################### # Helper functions for ramstage postprocess spc := spc += -$(spc) := -$(spc) += +comma := , -# files-in-dir-recursive,dir,files -files-in-dir-recursive=$(filter $(1)%,$(2)) +# Returns all files and dirs below `dir` (recursively). +# files-below-dir,dir,files +files-below-dir=$(filter $(1)%,$(2)) -# parent-dir,dir/ -parent-dir=$(dir $(subst $( ),/,$(strip $(subst /, ,$(1))))) - -# filters out exactly the directory specified -# filter-out-dir,dir_to_keep,dirs -filter-out-dir=$(filter-out $(1),$(2)) - -# filters out dir_to_keep and all its parents -# filter-out-dirs,dir_to_keep,dirs -filter-out-dirs=$(if $(filter-out ./,$(1)),$(call filter-out-dirs,$(call parent-dir,$(1)),$(call filter-out-dir,$(1),$(2))),$(call filter-out-dir,$(1),$(2))) - -# dir-wildcards,dirs -dir-wildcards=$(addsuffix %,$(1)) +# Returns all dirs below `dir` (recursively). +# dirs-below-dir,dir,files +dirs-below-dir=$(filter-out $(1),$(sort $(dir $(call files-below-dir,$(1),$(2))))) +# Returns all files directly in `dir` (non-recursively). # files-in-dir,dir,files -files-in-dir=$(filter-out $(call dir-wildcards,$(call filter-out-dirs,$(1),$(dir $(2)))),$(call files-in-dir-recursive,$(1),$(2))) +files-in-dir=$(filter-out $(addsuffix %,$(call dirs-below-dir,$(1),$(2))),$(call files-below-dir,$(1),$(2))) ####################################################################### # reduce command line length by linking the objects of each # directory into an intermediate file -ramstage-postprocess=$(foreach d,$(sort $(dir $(1))), \ - $(eval $(d)ramstage.o: $(call files-in-dir,$(d),$(1)); $$(LD) -o $$@ -r $$^ ) \ - $(eval ramstage-objs:=$(d)ramstage.o $(filter-out $(call files-in-dir,$(d),$(1)),$(ramstage-objs)))) +postprocessors += $$(eval DEPENDENCIES+=$$(addsuffix .d,$$(basename $$(ramstage-objs)))) \ + $$(foreach d,$$(sort $$(dir $$(filter %.o %.a,$$(ramstage-objs)))), \ + $$(eval $$(d)ramstage.o: $$(call files-in-dir,$$(d),$$(ramstage-objs)); $$$$(call link,ramstage,$$$$(filter %.o %.a,$$$$(^)),-o $$$$(@),-r)) \ + $$(eval ramstage-objs:=$$(d)ramstage.o $$(filter-out $$(call files-in-dir,$$(d),$$(filter %.o %.a,$$(ramstage-objs))),$$(ramstage-objs)))) -romstage-c-ccopts:=-D__PRE_RAM__ -romstage-S-ccopts:=-D__PRE_RAM__ +bootblock-generic-ccopts += -D__PRE_RAM__ -D__BOOTBLOCK__ +romstage-generic-ccopts += -D__PRE_RAM__ -D__ROMSTAGE__ +ramstage-generic-ccopts += -D__RAMSTAGE__ ifeq ($(CONFIG_TRACE),y) -ramstage-c-ccopts:= -finstrument-functions +ramstage-c-ccopts += -finstrument-functions endif ifeq ($(CONFIG_COVERAGE),y) -ramstage-c-ccopts+=-fprofile-arcs -ftest-coverage +ramstage-c-ccopts += -fprofile-arcs -ftest-coverage endif ifeq ($(CONFIG_USE_BLOBS),y) forgetthis:=$(shell git submodule update --init --checkout 3rdparty) endif -bootblock-c-ccopts:=-D__BOOT_BLOCK__ -D__PRE_RAM__ -bootblock-S-ccopts:=-D__BOOT_BLOCK__ -D__PRE_RAM__ - -smmstub-c-ccopts:=-D__SMM__ -smmstub-S-ccopts:=-D__SMM__ -smm-c-ccopts:=-D__SMM__ -smm-S-ccopts:=-D__SMM__ - -# SMM TSEG base is dynamic -ifneq ($(CONFIG_SMM_MODULES),y) -ifeq ($(CONFIG_SMM_TSEG),y) -smm-c-ccopts += -fpic -endif -endif - -ramstage-c-deps:=$$(OPTION_TABLE_H) -romstage-c-deps:=$$(OPTION_TABLE_H) -bootblock-c-deps:=$$(OPTION_TABLE_H) - -####################################################################### -# Add handler to compile ACPI's ASL -define ramstage-objs_asl_template -$(obj)/$(1).ramstage.o: src/$(1).asl $(obj)/config.h - @printf " IASL $$(subst $(top)/,,$$(@))\n" - $(CC) -x assembler-with-cpp -E -MMD -MT $$(@) -D__ACPI__ -P -include $(src)/include/kconfig.h -I$(obj) -I$(src) -I$(src)/include -I$(src)/arch/$(ARCHDIR-y)/include -I$(src)/mainboard/$(MAINBOARDDIR) $$< -o $$(basename $$@).asl - cd $$(dir $$@); $(IASL) -p $$(notdir $$@) -tc $$(notdir $$(basename $$@)).asl - mv $$(basename $$@).hex $$(basename $$@).c - $(CC) $$(CFLAGS) $$(if $$(subst dsdt,,$$(basename $$(notdir $(1)))), -DAmlCode=AmlCode_$$(basename $$(notdir $(1)))) -c -o $$@ $$(basename $$@).c - # keep %.o: %.c rule from catching the temporary .c file after a make clean - mv $$(basename $$@).c $$(basename $$@).hex -endef +# Linker scripts are just preprocessed, not compiled +generic-ld-ccopts += $(PREPROCESS_ONLY) ####################################################################### # Parse plaintext cmos defaults into binary format @@ -155,7 +122,7 @@ cbfs-files-processor-nvramtool= \ # arg2: binary file name cbfs-files-processor-vsa= \ $(eval $(2): $(1) ; \ - printf " CREATE $(2) (from $(1))\n"; $(OBJCOPY) --set-start 0x20 --adjust-vma 0x60000 -I binary -O elf32-i386 -B i386 $(1) $(2).tmp && $(LD) -m elf_i386 -e 0x60020 --section-start .data=0x60000 $(2).tmp -o $(2)) + printf " CREATE $(2) (from $(1))\n"; $(OBJCOPY_ramstage) --set-start 0x20 --adjust-vma 0x60000 -I binary -O elf32-i386 -B i386 $(1) $(2).tmp && $(LD_ramstage) -m elf_i386 -e 0x60020 --section-start .data=0x60000 $(2).tmp -o $(2)) ####################################################################### # Add handler for arbitrary files in CBFS @@ -198,21 +165,27 @@ ifneq ($(CONFIG_LOCALVERSION),"") COREBOOT_EXTRA_VERSION := -$(call strip_quotes,$(CONFIG_LOCALVERSION)) endif -INCLUDES := -Isrc -Isrc/include -I$(obj) -Isrc/arch/$(ARCHDIR-y)/include +INCLUDES := -Isrc -Isrc/include -I$(obj) INCLUDES += -Isrc/device/oprom/include # abspath is a workaround for romcc INCLUDES += -include $(src)/include/kconfig.h -CFLAGS = $(INCLUDES) -Os -pipe -g -nostdinc -CFLAGS += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes -CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -CFLAGS += -Wstrict-aliasing -Wshadow +CFLAGS_common = -pipe -g -nostdinc +CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes +CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs +CFLAGS_common += -Wstrict-aliasing -Wshadow ifeq ($(CONFIG_WARNINGS_ARE_ERRORS),y) -CFLAGS += -Werror +CFLAGS_common += -Werror +endif +CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer +ifneq ($(SOURCE_DEBUG),) +CFLAGS_common += -O0 +else +CFLAGS_common += -Os endif -CFLAGS += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer -additional-dirs := $(objutil)/cbfstool $(objutil)/romcc $(objutil)/ifdtool $(objutil)/options +additional-dirs := $(objutil)/cbfstool $(objutil)/romcc $(objutil)/ifdtool \ + $(objutil)/options $(objutil)/bimgtool ####################################################################### # generate build support files @@ -231,9 +204,6 @@ $(obj)/build.h: .xcompile printf "#define COREBOOT_BUILD_WEEKDAY_BCD 0x`LANG= date +"%w"`\n" >> $(obj)/build.ht printf "#define COREBOOT_DMI_DATE \"`LANG= date +"%m/%d/%Y"`\"\n" >> $(obj)/build.ht printf "\n" >> $(obj)/build.ht - printf "#define COREBOOT_COMPILER \"$(shell LANG= $(CC) --version | head -n1)\"\n" >> $(obj)/build.ht - printf "#define COREBOOT_ASSEMBLER \"$(shell LANG= $(AS) --version | head -n1)\"\n" >> $(obj)/build.ht - printf "#define COREBOOT_LINKER \"$(shell LANG= $(LD) --version | head -n1)\"\n" >> $(obj)/build.ht printf "#define COREBOOT_COMPILE_TIME \"`LANG= date +%T`\"\n" >> $(obj)/build.ht printf "#define COREBOOT_COMPILE_BY \"$(subst \,@,$(shell PATH=$$PATH:/usr/ucb whoami))\"\n" >> $(obj)/build.ht printf "#define COREBOOT_COMPILE_HOST \"$(shell hostname -s 2>/dev/null || hostname 2>/dev/null)\"\n" >> $(obj)/build.ht @@ -241,8 +211,7 @@ $(obj)/build.h: .xcompile printf "#endif\n" >> $(obj)/build.ht mv $(obj)/build.ht $(obj)/build.h -$(obj)/ldoptions: $(obj)/config.h - awk '/^#define ([^"])* ([^"])*$$/ {gsub("\\r","",$$3); print $$2 " = " $$3 ";";}' $< > $@ +generic-deps += $(obj)/build.h build-dirs: mkdir -p $(objcbfs) $(objgenerated) @@ -250,10 +219,14 @@ build-dirs: ####################################################################### # Build the tools CBFSTOOL:=$(obj)/cbfstool +RMODTOOL:=$(obj)/rmodtool $(CBFSTOOL): $(objutil)/cbfstool/cbfstool cp $< $@ +$(RMODTOOL): $(objutil)/cbfstool/rmodtool + cp $< $@ + _WINCHECK=$(shell uname -o 2> /dev/null) STACK= ifeq ($(_WINCHECK),Msys) @@ -275,6 +248,11 @@ $(IFDTOOL): $(top)/util/ifdtool/ifdtool.c @printf " HOSTCC $(subst $(obj)/,,$(@))\n" $(HOSTCC) $(HOSTCFLAGS) -o $@ $< +BIMGTOOL:=$(objutil)/bimgtool/bimgtool +$(BIMGTOOL): $(top)/util/bimgtool/bimgtool.c + @printf " HOSTCC $(subst $(obj)/,,$(@))\n" + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + ####################################################################### # needed objects that every mainboard uses # Creation of these is architecture and mainboard independent @@ -290,25 +268,13 @@ $(objutil)/%.o: $(objutil)/%.c @printf " HOSTCC $(subst $(objutil)/,,$(@))\n" $(HOSTCC) -MMD -I$(subst $(objutil)/,util/,$(dir $<)) -I$(dir $<) $(HOSTCFLAGS) -c -o $@ $< -$(obj)/%.ramstage.o $(abspath $(obj))/%.ramstage.o: $(obj)/%.c $(obj)/config.h $(OPTION_TABLE_H) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD $(CFLAGS) -c -o $@ $< - -$(obj)/%.romstage.o $(abspath $(obj))/%.romstage.o: $(obj)/%.c $(obj)/config.h $(OPTION_TABLE_H) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD -D__PRE_RAM__ $(CFLAGS) -c -o $@ $< - -$(obj)/%.bootblock.o $(abspath $(obj))/%.bootblock.o: $(obj)/%.c $(obj)/config.h $(OPTION_TABLE_H) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD $(bootblock-c-ccopts) $(CFLAGS) -c -o $@ $< - ####################################################################### # Clean up rules clean-abuild: rm -rf coreboot-builds clean-for-update-target: - rm -f $(obj)/coreboot_ram* $(obj)/coreboot.romstage $(obj)/coreboot.pre* $(obj)/coreboot.bootblock $(obj)/coreboot.a + rm -f $(obj)/ramstage* $(obj)/coreboot.romstage $(obj)/coreboot.pre* $(obj)/coreboot.bootblock $(obj)/coreboot.a rm -rf $(obj)/bootblock* $(obj)/romstage* $(obj)/location.* rm -f $(obj)/option_table.* $(obj)/crt0.S $(obj)/ldscript rm -f $(obj)/mainboard/$(MAINBOARDDIR)/static.c $(obj)/mainboard/$(MAINBOARDDIR)/config.py $(obj)/mainboard/$(MAINBOARDDIR)/static.dot @@ -316,7 +282,7 @@ clean-for-update-target: rm -f $(obj)/mainboard/$(MAINBOARDDIR)/romstage.inc rm -f $(obj)/mainboard/$(MAINBOARDDIR)/bootblock.* $(obj)/mainboard/$(MAINBOARDDIR)/dsdt.* rm -f $(obj)/cpu/x86/smm/smm_bin.c $(obj)/cpu/x86/smm/smm.* $(obj)/cpu/x86/smm/smm - $(MAKE) -C payloads/external/SeaBIOS -f Makefile.inc clean OUT=$(abspath $(obj)) HOSTCC="$(HOSTCC)" CC="$(CC)" LD="$(LD)" + $(MAKE) -C payloads/external/SeaBIOS -f Makefile.inc clean OUT=$(abspath $(obj)) HOSTCC="$(HOSTCC)" CC="$(CC_x86_32)" LD="$(LD_x86_32)" clean-target: rm -f $(obj)/coreboot* @@ -371,5 +337,166 @@ crosstools: clean-for-update crossgcc-clean: clean-for-update $(MAKE) -C util/crossgcc clean -tools: $(objutil)/kconfig/conf $(objutil)/cbfstool/cbfstool $(objutil)/nvramtool/nvramtool $(objutil)/romcc/romcc $(objutil)/sconfig/sconfig +tools: $(objutil)/kconfig/conf $(objutil)/cbfstool/cbfstool $(objutil)/cbfstool/rmodtool $(objutil)/nvramtool/nvramtool $(objutil)/romcc/romcc $(objutil)/sconfig/sconfig + +############################################################################### +# Common recipes for all stages +############################################################################### + +# loadaddr can determine the load address of a stage, which may be needed for +# platform-specific image headers (only works *after* the stage has been built) +loadaddr = $(shell $(OBJDUMP_$(1)) -p $(objcbfs)/$(1).debug | \ + sed -ne '/LOAD/s/^.*vaddr 0x\([0-9a-fA-F]\{8\}\).*$$/0x\1/p') + +# find-substr is required for stages like romstage_null and romstage_xip to +# eliminate the _* part of the string +find-substr = $(word 1,$(subst _, ,$(1))) + +# find-class is used to identify the class from the name of the stage +# romstage.x will return romstage, romstage.x.y will remove .x.y and return +# romstage. Hence the recursion + +find-class = $(if $(filter $(1),$(basename $(1))),$(if $(CC_$(1)), $(1), $(call find-substr,$(1))),$(call find-class,$(basename $(1)))) + +$(objcbfs)/%.bin: $(objcbfs)/%.elf + $(eval class := $(call find-class,$(@F))) + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + $(OBJCOPY_$(class)) -O binary $< $@ + +$(objcbfs)/%.elf: $(objcbfs)/%.debug + $(eval class := $(call find-class,$(@F))) + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + cp $< $@.tmp + $(NM_$(class)) -n $@.tmp | sort > $(basename $@).map + $(OBJCOPY_$(class)) --strip-debug $@.tmp + $(OBJCOPY_$(class)) --add-gnu-debuglink=$< $@.tmp + mv $@.tmp $@ + + +############################################################################### +# Build the final rom image +############################################################################### + +COREBOOT_ROM_DEPENDENCIES:= +ifeq ($(CONFIG_PAYLOAD_ELF),y) +COREBOOT_ROM_DEPENDENCIES+=$(CONFIG_PAYLOAD_FILE) +endif +ifeq ($(CONFIG_PAYLOAD_SEABIOS),y) +COREBOOT_ROM_DEPENDENCIES+=seabios +endif +ifeq ($(CONFIG_PAYLOAD_FILO),y) +COREBOOT_ROM_DEPENDENCIES+=filo +endif + +extract_nth=$(word $(1), $(subst |, ,$(2))) + +ifneq ($(CONFIG_UPDATE_IMAGE),y) +prebuild-files = \ + $(foreach file,$(cbfs-files), \ + $(CBFSTOOL) $@.tmp \ + add$(if $(filter stage,$(call extract_nth,3,$(file))),-stage)$(if $(filter payload,$(call extract_nth,3,$(file))),-payload) \ + -f $(call extract_nth,1,$(file)) \ + -n $(call extract_nth,2,$(file)) $(if $(filter-out stage,$(call extract_nth,3,$(file))),-t $(call extract_nth,3,$(file))) \ + $(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&) +prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) + +$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $$(cpu_ucode_cbfs_file) + $(CBFSTOOL) $@.tmp create \ + -B $(objcbfs)/bootblock.bin -a 64 \ + $(CBFSTOOL_PRE1_OPTS) + $(prebuild-files) true + $(call add-cpu-microcode-to-cbfs,$@.tmp) + mv $@.tmp $@ +else +.PHONY: $(obj)/coreboot.pre1 +$(obj)/coreboot.pre1: $(CBFSTOOL) + mv $(obj)/coreboot.rom $@ +endif + +ifeq ($(CONFIG_HAVE_REFCODE_BLOB),y) +REFCODE_BLOB=$(obj)/refcode.rmod +$(REFCODE_BLOB): $(RMODTOOL) + $(RMODTOOL) -i $(CONFIG_REFCODE_BLOB_FILE) -o $@ +endif + +ifeq ($(CONFIG_PAYLOAD_LINUX),y) +LINUX_ADDITIONAL_CONFIG:= +ifneq ($(strip $(call strip_quotes,$(CONFIG_LINUX_COMMAND_LINE))),) + LINUX_ADDITIONAL_CONFIG+=-C $(CONFIG_LINUX_COMMAND_LINE) +endif +ifneq ($(strip $(call strip_quotes,$(CONFIG_LINUX_INITRD))),) + LINUX_ADDITIONAL_CONFIG+=-I $(CONFIG_LINUX_INITRD) +endif +endif + +$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/ramstage.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) $$(VBOOT_STUB) $(REFCODE_BLOB) + @printf " CBFS $(subst $(obj)/,,$(@))\n" +# The full ROM may be larger than the CBFS part, so create an empty +# file (filled with \377 = 0xff) and copy the CBFS image over it. + tr '\000' '\377' < /dev/zero 2> /dev/null | dd of=$@.tmp bs=8192 iflag=fullblock count=$$(($(CONFIG_ROM_SIZE) / 8192)) 2> /dev/null + dd if=$(obj)/coreboot.pre of=$@.tmp bs=8192 conv=notrunc 2> /dev/null + $(CBFSTOOL) $@.tmp add-stage -f $(objcbfs)/ramstage.elf -n $(CONFIG_CBFS_PREFIX)/ramstage -c $(CBFS_COMPRESS_FLAG) +ifeq ($(CONFIG_PAYLOAD_NONE),y) + @printf " PAYLOAD none (as specified by user)\n" +endif +ifeq ($(CONFIG_PAYLOAD_ELF),y) + @printf " PAYLOAD $(CONFIG_PAYLOAD_FILE) (compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" + $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_PAYLOAD_LINUX),y) + @printf " PAYLOAD $(CONFIG_PAYLOAD_FILE) (compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" + $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) $(LINUX_ADDITIONAL_CONFIG) +endif +ifeq ($(CONFIG_PAYLOAD_SEABIOS),y) + @printf " PAYLOAD SeaBIOS (internal, compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" + $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_PAYLOAD_FILO),y) + @printf " PAYLOAD FILO (internal, compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" + $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_PAYLOAD_TIANOCORE),y) + @printf " PAYLOAD Tiano Core (compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" + $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_INCLUDE_CONFIG_FILE),y) + @printf " CONFIG $(DOTCONFIG)\n" + if [ -f $(DOTCONFIG) ]; then \ + echo "# This image was built using git revision" `git rev-parse HEAD` > $(obj)/config.tmp ; \ + sed -e '/^#/d' -e '/^ *$$/d' $(DOTCONFIG) >> $(obj)/config.tmp ; \ + $(CBFSTOOL) $@.tmp add -f $(obj)/config.tmp -n config -t raw; rm -f $(obj)/config.tmp ; fi +endif +ifeq ($(CONFIG_VBOOT_VERIFY_FIRMWARE),y) + $(CBFSTOOL) $@.tmp add-stage -f $(VBOOT_STUB) -n $(CONFIG_CBFS_PREFIX)/vboot -c $(CBFS_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_HAVE_REFCODE_BLOB),y) + $(CBFSTOOL) $@.tmp add-stage -f $(REFCODE_BLOB) -n $(CONFIG_CBFS_PREFIX)/refcode -c $(CBFS_COMPRESS_FLAG) +endif +ifeq ($(CONFIG_PXE_ROM),y) + $(CBFSTOOL) $@.tmp add -f $(CONFIG_PXE_ROM_FILE) -n pci$(CONFIG_PXE_ROM_ID).rom -t raw +endif +ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) +ifeq ($(CONFIG_CPU_MICROCODE_IN_CBFS),y) + @printf " UPDATE-FIT \n" + $(CBFSTOOL) $@.tmp update-fit -n cpu_microcode_blob.bin -x $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) +endif +endif + mv $@.tmp $@ + @printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n" + $(CBFSTOOL) $@ print + +ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y) +ROMSTAGE_ELF := romstage_xip.elf +else +ROMSTAGE_ELF := romstage.elf +endif + +$(obj)/coreboot.pre: $(objcbfs)/$(ROMSTAGE_ELF) $(obj)/coreboot.pre1 $(CBFSTOOL) + @printf " CBFS $(subst $(obj)/,,$(@))\n" + cp $(obj)/coreboot.pre1 $@.tmp + $(CBFSTOOL) $@.tmp add-stage \ + -f $(objcbfs)/$(ROMSTAGE_ELF) \ + -n $(CONFIG_CBFS_PREFIX)/romstage -c none \ + $(CBFSTOOL_PRE_OPTS) + mv $@.tmp $@ diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg new file mode 100644 index 0000000000..f7eb63e6a1 --- /dev/null +++ b/PRESUBMIT.cfg @@ -0,0 +1,9 @@ +# This config file disables some of the ChromiumOS source style checks for +# coreboot as they are directly conflicting with the coreboot coding +# guidelines. + +[Hook Overrides] +#stray_whitespace_check: false +#long_line_check: false +cros_license_check: false +tab_check: false diff --git a/configs/config.arm64-generic b/configs/config.arm64-generic new file mode 100644 index 0000000000..168f854028 --- /dev/null +++ b/configs/config.arm64-generic @@ -0,0 +1,4 @@ +CONFIG_VENDOR_EMULATION=y +CONFIG_BOARD_EMULATION_FOUNDATION_ARMV8=y +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/config.auron b/configs/config.auron new file mode 100644 index 0000000000..2fb66af362 --- /dev/null +++ b/configs/config.auron @@ -0,0 +1,38 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_AURON=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/auron/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/auron/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/auron/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.auron_pearlvalley b/configs/config.auron_pearlvalley new file mode 100644 index 0000000000..c5750e93d9 --- /dev/null +++ b/configs/config.auron_pearlvalley @@ -0,0 +1,37 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_INTEL=y +CONFIG_BOARD_INTEL_PEARLVALLEY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/auron_pearlvalley/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/auron_pearlvalley/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/intel/pearlvalley/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.bayleybay b/configs/config.bayleybay new file mode 100644 index 0000000000..6360b9d964 --- /dev/null +++ b/configs/config.bayleybay @@ -0,0 +1,36 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_INTEL=y +CONFIG_BOARD_INTEL_BAYLEYBAY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/bayleybay/firmware/mrc.bin" +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/bayleybay/firmware/efi.elf" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0f31" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/intel/bayleybay/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.beltino b/configs/config.beltino new file mode 100644 index 0000000000..74b76d4cd3 --- /dev/null +++ b/configs/config.beltino @@ -0,0 +1,36 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_BELTINO=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/beltino/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/beltino/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.bolt b/configs/config.bolt new file mode 100644 index 0000000000..4d6ac34eba --- /dev/null +++ b/configs/config.bolt @@ -0,0 +1,36 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_BOLT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/bolt/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/bolt/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.butterfly b/configs/config.butterfly new file mode 100644 index 0000000000..f94c3d98e8 --- /dev/null +++ b/configs/config.butterfly @@ -0,0 +1,29 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_BUTTERFLY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/butterfly/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/butterfly/snm_2130_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.cosmos b/configs/config.cosmos new file mode 100644 index 0000000000..d2033d18ca --- /dev/null +++ b/configs/config.cosmos @@ -0,0 +1,5 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_COSMOS=y +CONFIG_CBFS_SIZE=0x80000 +CONFIG_VBOOT2_VERIFY_FIRMWARE=y +# CONFIG_CONSOLE_SERIAL is not set diff --git a/configs/config.daisy b/configs/config.daisy new file mode 100644 index 0000000000..37d04d61bd --- /dev/null +++ b/configs/config.daisy @@ -0,0 +1,5 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_DAISY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y diff --git a/configs/config.emeraldlake2 b/configs/config.emeraldlake2 new file mode 100644 index 0000000000..e94bd84b4a --- /dev/null +++ b/configs/config.emeraldlake2 @@ -0,0 +1,30 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_INTEL=y +CONFIG_BOARD_INTEL_EMERALDLAKE2=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/emeraldlake2/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0166" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/intel/emeraldlake2/snm_2120.dat" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.falco b/configs/config.falco new file mode 100644 index 0000000000..1e33f6e934 --- /dev/null +++ b/configs/config.falco @@ -0,0 +1,40 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_FALCO=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/falco/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/falco/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_MAINBOARD_VENDOR="Hewlett-Packard" +CONFIG_SUBSYSTEM_VENDOR_ID=0x103c +CONFIG_SUBSYSTEM_DEVICE_ID=0x21ed +CONFIG_LOCK_MANAGEMENT_ENGINE=y diff --git a/configs/config.fox_baskingridge b/configs/config.fox_baskingridge new file mode 100644 index 0000000000..f4c9e1ca0e --- /dev/null +++ b/configs/config.fox_baskingridge @@ -0,0 +1,35 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_INTEL=y +CONFIG_BOARD_INTEL_BASKING_RIDGE=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/fox_baskingridge/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0416" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/intel/baskingridge/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.fox_wtm2 b/configs/config.fox_wtm2 new file mode 100644 index 0000000000..be5a402dfc --- /dev/null +++ b/configs/config.fox_wtm2 @@ -0,0 +1,37 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_INTEL=y +CONFIG_BOARD_INTEL_WTM2=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/fox_wtm2/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/fox_wtm2/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/intel/wtm2/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.gizmo b/configs/config.gizmo new file mode 100644 index 0000000000..eccd5a128b --- /dev/null +++ b/configs/config.gizmo @@ -0,0 +1,23 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GIZMOSPHERE=y +CONFIG_BOARD_GIZMOSPHERE_GIZMO=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_CBMEM is not set +CONFIG_CONSOLE_SERIAL=y +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="1002,9804" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/amd/gizmo/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.jecht b/configs/config.jecht new file mode 100644 index 0000000000..1c4de3148f --- /dev/null +++ b/configs/config.jecht @@ -0,0 +1,38 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_JECHT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/jecht/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/jecht/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/jecht/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.link b/configs/config.link new file mode 100644 index 0000000000..2e100ef9c7 --- /dev/null +++ b/configs/config.link @@ -0,0 +1,29 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_LINK=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/link/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_USER=y +CONFIG_FRAMEBUFFER_VESA_MODE=0x164 +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0166" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/link/snm_2137.dat" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.lumpy b/configs/config.lumpy new file mode 100644 index 0000000000..576f6edb5a --- /dev/null +++ b/configs/config.lumpy @@ -0,0 +1,26 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_SAMSUNG=y +CONFIG_BOARD_SAMSUNG_LUMPY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/lumpy/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/samsung/lumpy/snm_2130_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_SPI_FLASH_NO_FAST_READ=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.nyan b/configs/config.nyan new file mode 100644 index 0000000000..9b61ea8792 --- /dev/null +++ b/configs/config.nyan @@ -0,0 +1,10 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_NYAN=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_ELOG=y +CONFIG_DRIVERS_AS3722_RTC=y +CONFIG_DRIVERS_AS3722_RTC_BUS=4 +CONFIG_DRIVERS_AS3722_RTC_ADDR=0x40 diff --git a/configs/config.nyan_big b/configs/config.nyan_big new file mode 100644 index 0000000000..1763e9849e --- /dev/null +++ b/configs/config.nyan_big @@ -0,0 +1,10 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_NYAN_BIG=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_ELOG=y +CONFIG_DRIVERS_AS3722_RTC=y +CONFIG_DRIVERS_AS3722_RTC_BUS=4 +CONFIG_DRIVERS_AS3722_RTC_ADDR=0x40 diff --git a/configs/config.nyan_blaze b/configs/config.nyan_blaze new file mode 100644 index 0000000000..45f09e7641 --- /dev/null +++ b/configs/config.nyan_blaze @@ -0,0 +1,10 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_NYAN_BLAZE=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_ELOG=y +CONFIG_DRIVERS_AS3722_RTC=y +CONFIG_DRIVERS_AS3722_RTC_BUS=4 +CONFIG_DRIVERS_AS3722_RTC_ADDR=0x40 diff --git a/configs/config.panther b/configs/config.panther new file mode 100644 index 0000000000..ab256e25db --- /dev/null +++ b/configs/config.panther @@ -0,0 +1,37 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PANTHER=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/panther/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/panther/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_PRE_GRAPHICS_DELAY=300 diff --git a/configs/config.parrot b/configs/config.parrot new file mode 100644 index 0000000000..7ce7b5f0b4 --- /dev/null +++ b/configs/config.parrot @@ -0,0 +1,30 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PARROT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/parrot/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/parrot/snm_2130_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.parrot32 b/configs/config.parrot32 new file mode 100644 index 0000000000..642d6ae4ca --- /dev/null +++ b/configs/config.parrot32 @@ -0,0 +1,30 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PARROT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/parrot32/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/parrot/snm_2130_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.parrot64 b/configs/config.parrot64 new file mode 100644 index 0000000000..a3d6713b67 --- /dev/null +++ b/configs/config.parrot64 @@ -0,0 +1,30 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PARROT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/parrot64/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/parrot/snm_2130_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.peach_pit b/configs/config.peach_pit new file mode 100644 index 0000000000..d0dac7c34f --- /dev/null +++ b/configs/config.peach_pit @@ -0,0 +1,5 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PEACH_PIT=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y diff --git a/configs/config.peppy b/configs/config.peppy new file mode 100644 index 0000000000..9225550fdd --- /dev/null +++ b/configs/config.peppy @@ -0,0 +1,40 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_PEPPY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/peppy/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/peppy/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_MAINBOARD_VENDOR="Acer" +CONFIG_SUBSYSTEM_VENDOR_ID=0x1025 +CONFIG_SUBSYSTEM_DEVICE_ID=0x0a11 +CONFIG_LOCK_MANAGEMENT_ENGINE=y diff --git a/configs/config.rambi b/configs/config.rambi new file mode 100644 index 0000000000..a39d1a23b7 --- /dev/null +++ b/configs/config.rambi @@ -0,0 +1,37 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_RAMBI=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/rambi/firmware/mrc.elf" +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/rambi/firmware/efi.elf" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0f31" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/rambi/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_CHROMEOS_RAMOOPS_DYNAMIC=y diff --git a/configs/config.rush b/configs/config.rush new file mode 100644 index 0000000000..6e9c3656d2 --- /dev/null +++ b/configs/config.rush @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_RUSH=y +CONFIG_CBFS_SIZE=0x200000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM=y +CONFIG_MTS_DIRECTORY="3rdparty/mainboard/google/rush" +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.rush_ryu b/configs/config.rush_ryu new file mode 100644 index 0000000000..b86e9db472 --- /dev/null +++ b/configs/config.rush_ryu @@ -0,0 +1,11 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_RUSH_RYU=y +CONFIG_CBFS_SIZE=0x200000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_CONSOLE_CBMEM=y +CONFIG_MTS_DIRECTORY="3rdparty/mainboard/google/rush_ryu" +CONFIG_VBOOT2_VERIFY_FIRMWARE=y +CONFIG_ELOG=y +CONFIG_DRIVERS_TI_TPS65913_RTC=y +CONFIG_DRIVERS_TI_TPS65913_RTC_BUS=4 +CONFIG_DRIVERS_TI_TPS65913_RTC_ADDR=0x58 diff --git a/configs/config.samus b/configs/config.samus new file mode 100644 index 0000000000..3c2f45db6f --- /dev/null +++ b/configs/config.samus @@ -0,0 +1,41 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_SAMUS=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/samus/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/samus/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_USER=y +CONFIG_FRAMEBUFFER_VESA_MODE=0x161 +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/samus/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_PRE_GRAPHICS_DELAY=200 +# CONFIG_LOCK_MANAGEMENT_ENGINE is not set diff --git a/configs/config.samus.fsp b/configs/config.samus.fsp new file mode 100644 index 0000000000..8e0bf99f5a --- /dev/null +++ b/configs/config.samus.fsp @@ -0,0 +1,73 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_SAMUS=y +CONFIG_CBFS_SIZE=0x100000 +CONFIG_HAVE_REFCODE_BLOB=y +CONFIG_REFCODE_BLOB_FILE="/build/samus/firmware/efi.elf" +CONFIG_CONSOLE_CBMEM=y + +# Enable Serial Debugging +CONFIG_CONSOLE_SERIAL=y +CONFIG_MAXIMUM_CONSOLE_LOGLEVEL=8 +CONFIG_DEFAULT_CONSOLE_LOGLEVEL=8 +CONFIG_DEBUG_CAR=y +CONFIG_DEBUG_CBFS=y +CONFIG_DEBUG_COVERAGE=y +CONFIG_DEBUG_MALLOC=y +CONFIG_DEBUG_INTEL_ME=y +CONFIG_DEBUG_PIRQ=y +#CONFIG_DEBUG_RAM_SETUP=y +CONFIG_DEBUG_SMBUS=y +CONFIG_DEBUG_SMI=y +CONFIG_DEBUG_SMM_RELOCATION=y +#CONFIG_DEBUG_SPI=y +CONFIG_DEBUG_SPI_FLASH=y +CONFIG_DEBUG_TPM=y + +# Enable FSP +CONFIG_CPU_MICROCODE_CBFS_LEN=0xd040 +CONFIG_CPU_MICROCODE_CBFS_LOC=0xffe11540 +CONFIG_DCACHE_RAM_BASE=0xfef00000 +CONFIG_DCACHE_RAM_SIZE=0x00004000 +CONFIG_FSP_FILE="3rdparty/mainboard/google/samus/fsp/FSP.fd" +CONFIG_FSP_IMAGE_ID_DWORD0=0x2d574442 +CONFIG_FSP_IMAGE_ID_DWORD1=0x30505346 +CONFIG_FSP_INCLUDE_PATH="3rdparty/mainboard/google/samus/fsp" +CONFIG_FSP_LOC=0xfff30000 +CONFIG_FSP_RESERVED_MEM_SIZE=0x00400000 +CONFIG_HAVE_FSP_BIN=y +CONFIG_MMCONF_BASE_ADDRESS=0xe0000000 +CONFIG_PLATFORM_USES_FSP=y +CONFIG_HEAP_SIZE=0x00080000 + +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_USER=y +CONFIG_FRAMEBUFFER_VESA_MODE=0x161 +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/samus/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y +CONFIG_PRE_GRAPHICS_DELAY=200 +# CONFIG_LOCK_MANAGEMENT_ENGINE is not set diff --git a/configs/config.slippy b/configs/config.slippy new file mode 100644 index 0000000000..eeb22705cc --- /dev/null +++ b/configs/config.slippy @@ -0,0 +1,35 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_SLIPPY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/slippy/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0406" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/slippy/vgabios.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +CONFIG_CMOS_POST_EXTRA=y +CONFIG_RELOCATABLE_RAMSTAGE=y +CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE=y +CONFIG_VBOOT_VERIFY_FIRMWARE=y +CONFIG_FLASHMAP_OFFSET=0x00610000 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.storm b/configs/config.storm new file mode 100644 index 0000000000..062abc338b --- /dev/null +++ b/configs/config.storm @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_STORM=y +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_USE_BLOBS=y +CONFIG_CBFS_SIZE=0x002c0000 +CONFIG_FLASHMAP_OFFSET=0x00300000 diff --git a/configs/config.stout b/configs/config.stout new file mode 100644 index 0000000000..3b33cdd11e --- /dev/null +++ b/configs/config.stout @@ -0,0 +1,29 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_STOUT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/stout/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/stout/snm_2137.dat" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.stout32 b/configs/config.stout32 new file mode 100644 index 0000000000..7f05a32bb7 --- /dev/null +++ b/configs/config.stout32 @@ -0,0 +1,29 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_STOUT=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/stout32/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_117=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/google/stout/snm_2137.dat" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_ELOG=y +CONFIG_ELOG_GSMI=y +CONFIG_ELOG_BOOT_COUNT=y +CONFIG_ELOG_BOOT_COUNT_CMOS_OFFSET=144 +CONFIG_SPI_FLASH_SMM=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.stumpy b/configs/config.stumpy new file mode 100644 index 0000000000..216b8bcddc --- /dev/null +++ b/configs/config.stumpy @@ -0,0 +1,26 @@ +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_SAMSUNG=y +CONFIG_BOARD_SAMSUNG_STUMPY=y +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="/build/stumpy/firmware/mrc.bin" +CONFIG_CBFS_SIZE=0x100000 +CONFIG_CONSOLE_CBMEM=y +# CONFIG_CONSOLE_SERIAL is not set +# CONFIG_PCI_ROM_RUN is not set +# CONFIG_ON_DEVICE_ROM_RUN is not set +# CONFIG_S3_VGA_ROM_RUN is not set +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_114=y +CONFIG_FRAMEBUFFER_KEEP_VESA_MODE=y +CONFIG_VGA_BIOS_ID="8086,0106" +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_FILE="3rdparty/mainboard/samsung/stumpy/snm_2124_coreboot.bin" +CONFIG_CPU_ADDR_BITS=36 +CONFIG_CACHE_ROM=y +CONFIG_MARK_GRAPHICS_MEM_WRCOMB=y +CONFIG_SPI_FLASH_NO_FAST_READ=y +CONFIG_CMOS_POST=y +CONFIG_CMOS_POST_OFFSET=0x70 +# CONFIG_MULTIBOOT is not set +CONFIG_PAYLOAD_NONE=y diff --git a/configs/config.urara b/configs/config.urara new file mode 100644 index 0000000000..afd6863f1e --- /dev/null +++ b/configs/config.urara @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_URARA=y +CONFIG_COREBOOT_ROMSIZE_KB_512=y +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_FLASHMAP_OFFSET=0x000e0000 + diff --git a/configs/config.veyron_brain b/configs/config.veyron_brain new file mode 100644 index 0000000000..3c19b8a88f --- /dev/null +++ b/configs/config.veyron_brain @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_BRAIN=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_danger b/configs/config.veyron_danger new file mode 100644 index 0000000000..846c9477eb --- /dev/null +++ b/configs/config.veyron_danger @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_DANGER=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_fievel b/configs/config.veyron_fievel new file mode 100644 index 0000000000..964e115076 --- /dev/null +++ b/configs/config.veyron_fievel @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_FIEVEL=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_gus b/configs/config.veyron_gus new file mode 100644 index 0000000000..995b0af1e2 --- /dev/null +++ b/configs/config.veyron_gus @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_GUS=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_jaq b/configs/config.veyron_jaq new file mode 100644 index 0000000000..5b68d7dd3e --- /dev/null +++ b/configs/config.veyron_jaq @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_JAQ=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_jerry b/configs/config.veyron_jerry new file mode 100644 index 0000000000..a06bfe5313 --- /dev/null +++ b/configs/config.veyron_jerry @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_JERRY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_mickey b/configs/config.veyron_mickey new file mode 100644 index 0000000000..5d2a083258 --- /dev/null +++ b/configs/config.veyron_mickey @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_MICKEY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_mighty b/configs/config.veyron_mighty new file mode 100644 index 0000000000..725314a8c0 --- /dev/null +++ b/configs/config.veyron_mighty @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_MIGHTY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_minnie b/configs/config.veyron_minnie new file mode 100644 index 0000000000..ccffe05de9 --- /dev/null +++ b/configs/config.veyron_minnie @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_MINNIE=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_nicky b/configs/config.veyron_nicky new file mode 100644 index 0000000000..8157a594f1 --- /dev/null +++ b/configs/config.veyron_nicky @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_NICKY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_pinky b/configs/config.veyron_pinky new file mode 100644 index 0000000000..0790461cab --- /dev/null +++ b/configs/config.veyron_pinky @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_PINKY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_rialto b/configs/config.veyron_rialto new file mode 100644 index 0000000000..f4de1713c0 --- /dev/null +++ b/configs/config.veyron_rialto @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_RIALTO=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_romy b/configs/config.veyron_romy new file mode 100644 index 0000000000..1acd6bc627 --- /dev/null +++ b/configs/config.veyron_romy @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_ROMY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_speedy b/configs/config.veyron_speedy new file mode 100644 index 0000000000..327c1e8a5c --- /dev/null +++ b/configs/config.veyron_speedy @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_SPEEDY=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_thea b/configs/config.veyron_thea new file mode 100644 index 0000000000..93b4464af2 --- /dev/null +++ b/configs/config.veyron_thea @@ -0,0 +1,8 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_THEA=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +# CONFIG_ELOG=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/config.veyron_tiger b/configs/config.veyron_tiger new file mode 100644 index 0000000000..49ac469a44 --- /dev/null +++ b/configs/config.veyron_tiger @@ -0,0 +1,7 @@ +CONFIG_VENDOR_GOOGLE=y +CONFIG_BOARD_GOOGLE_VEYRON_TIGER=y +CONFIG_CBFS_SIZE=0x100000 +# CONFIG_CONSOLE_SERIAL is not set +CONFIG_COLLECT_TIMESTAMPS=y +CONFIG_CONSOLE_CBMEM=y +CONFIG_VBOOT2_VERIFY_FIRMWARE=y diff --git a/configs/fwserial.auron b/configs/fwserial.auron new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.auron @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.auron_pearlvalley b/configs/fwserial.auron_pearlvalley new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.auron_pearlvalley @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.bayleybay b/configs/fwserial.bayleybay new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.bayleybay @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.beltino b/configs/fwserial.beltino new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.beltino @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.bolt b/configs/fwserial.bolt new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.bolt @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.butterfly b/configs/fwserial.butterfly new file mode 100644 index 0000000000..08ee7dce3c --- /dev/null +++ b/configs/fwserial.butterfly @@ -0,0 +1,11 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250MEM=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y +CONFIG_DRIVERS_OXFORD_OXPCIE=y +CONFIG_OXFORD_OXPCIE_BRIDGE_BUS=0 +CONFIG_OXFORD_OXPCIE_BRIDGE_DEVICE=0x1c +CONFIG_OXFORD_OXPCIE_BRIDGE_FUNCTION=0x0 +CONFIG_OXFORD_OXPCIE_BRIDGE_SUBORDINATE=0x1 +CONFIG_OXFORD_OXPCIE_BASE_ADDRESS=0xe0400000 diff --git a/configs/fwserial.cosmos b/configs/fwserial.cosmos new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.cosmos @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.daisy b/configs/fwserial.daisy new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.daisy @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.falco b/configs/fwserial.falco new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.falco @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.fox_baskingridge b/configs/fwserial.fox_baskingridge new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.fox_baskingridge @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.fox_wtm2 b/configs/fwserial.fox_wtm2 new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.fox_wtm2 @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.gizmo b/configs/fwserial.gizmo new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.gizmo @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.jecht b/configs/fwserial.jecht new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.jecht @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.link b/configs/fwserial.link new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.link @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.lumpy b/configs/fwserial.lumpy new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.lumpy @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.nyan b/configs/fwserial.nyan new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.nyan @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.nyan_big b/configs/fwserial.nyan_big new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.nyan_big @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.nyan_blaze b/configs/fwserial.nyan_blaze new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.nyan_blaze @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.panther b/configs/fwserial.panther new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.panther @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.parrot b/configs/fwserial.parrot new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.parrot @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.peach_pit b/configs/fwserial.peach_pit new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.peach_pit @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.peppy b/configs/fwserial.peppy new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.peppy @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.rambi b/configs/fwserial.rambi new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.rambi @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.rush b/configs/fwserial.rush new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.rush @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.rush_ryu b/configs/fwserial.rush_ryu new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.rush_ryu @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.samus b/configs/fwserial.samus new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.samus @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.slippy b/configs/fwserial.slippy new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.slippy @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.storm b/configs/fwserial.storm new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.storm @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.stout b/configs/fwserial.stout new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.stout @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.stout32 b/configs/fwserial.stout32 new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.stout32 @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.stumpy b/configs/fwserial.stumpy new file mode 100644 index 0000000000..ca7e7ce57b --- /dev/null +++ b/configs/fwserial.stumpy @@ -0,0 +1,4 @@ +CONFIG_CONSOLE_SERIAL=y +CONFIG_CONSOLE_SERIAL8250=y +CONFIG_CONSOLE_SERIAL_COM1=y +CONFIG_CONSOLE_SERIAL_115200=y diff --git a/configs/fwserial.urara b/configs/fwserial.urara new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.urara @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_brain b/configs/fwserial.veyron_brain new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_brain @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_danger b/configs/fwserial.veyron_danger new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_danger @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_fievel b/configs/fwserial.veyron_fievel new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_fievel @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_gus b/configs/fwserial.veyron_gus new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_gus @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_jaq b/configs/fwserial.veyron_jaq new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_jaq @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_jerry b/configs/fwserial.veyron_jerry new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_jerry @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_mickey b/configs/fwserial.veyron_mickey new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_mickey @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_mighty b/configs/fwserial.veyron_mighty new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_mighty @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_minnie b/configs/fwserial.veyron_minnie new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_minnie @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_nicky b/configs/fwserial.veyron_nicky new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_nicky @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_pinky b/configs/fwserial.veyron_pinky new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_pinky @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_rialto b/configs/fwserial.veyron_rialto new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_rialto @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_romy b/configs/fwserial.veyron_romy new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_romy @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_speedy b/configs/fwserial.veyron_speedy new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_speedy @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_thea b/configs/fwserial.veyron_thea new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_thea @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/configs/fwserial.veyron_tiger b/configs/fwserial.veyron_tiger new file mode 100644 index 0000000000..7e9268b3d2 --- /dev/null +++ b/configs/fwserial.veyron_tiger @@ -0,0 +1 @@ +CONFIG_CONSOLE_SERIAL=y diff --git a/documentation/timestamp_library.txt b/documentation/timestamp_library.txt new file mode 100644 index 0000000000..ef4f051e27 --- /dev/null +++ b/documentation/timestamp_library.txt @@ -0,0 +1,445 @@ +=========================== Table of Contents ================================== +Introduction + +Data structures used + cache_state + cbmem_state + table + entries + +Internal Functions + timestamp_cache_init + timestamp_cache_get + timestamp_alloc_cbmem_table + timestamp_table_get + timestamp_add_table_entry + +Function APIs + timestamp_early_init + timestamp_init + timestamp_add + timestamp_add_now + timestamp_sync + +Use / Test Cases + Case 1: Timestamp Region Exists + Case 2: No timestamp region, fresh boot, cbmem_initialize called after + timestamp_init + Case 3: No timestamp region, fresh boot, cbmem_initialize called before + timestamp_init + Case 4: No timestamp region, resume, cbmem_initialize called after + timestamp_init + Case 5: No timestamp region, resume, cbmem_initialize called before + timestamp_init + + +============================== Introduction ==================================== + + The aim of timestamp library is to make it easier for different boards +to save timestamps in cbmem / stash (until cbmem is brought up) by providing a +simple API to initalize, add and sync timestamps. In order to make the +timestamps persistent and accessible from the kernel, we need to ensure that all +the saved timestamps end up in cbmem area under the CBMEM_ID_TIMESTAMP +tag. However, until the cbmem area is available, the timestamps can be saved to +board/SOC-defined _timestamp region or in a local stage-specific stash. The work +of identifying the right location for storing timestamps is done by the library +and is not exposed to the user. + + Working of timestamp library from a user perspective can be outlined in +the following steps: +1. Initialize the _timestamp cache (if any used) +2. Initialize the base time and reset cbmem timestamp area +3. Start adding timestamps + + Steps 1) and 2) above can be performed in a single API call as explained +in later sections. Behind the scenes, the timestamp library takes care of: +1. Identifying the correct location for storing timestamps (cbmem or _timestamp +region or local stash). +2. Once cbmem is up, ensure that all timestamps are synced from _timestamp +region or local stash into the cbmem area. +3. Add a new cbmem timestamp area based on whether a reset of cbmem timestamp +region is required / not. + +========================== Data structures used ================================ + + The main structure that maintains information about the timestamp cache +is: +struct __attribute__((__packed__)) timestamp_cache { + uint16_t cache_state; + uint16_t cbmem_state; + struct timestamp_table table; + struct timestamp_entry entries[MAX_TIMESTAMP_CACHE]; +}; + +1. cache_state + The state of the cache is maintained by cache_state attribute which can +be any one of the following: + +enum { + TIMESTAMP_CACHE_UNINITIALIZED = 0, + TIMESTAMP_CACHE_INITIALIZED, + TIMESTAMP_CACHE_NOT_NEEDED, +}; + + By default, if the cache is stored in local stash (bss area), then it +will be reset to uninitialized state. However, if the cache is stored in +_timestamp region, then it might have garbage in any of the attributes. Thus, if +_timestamp region is being used by any board, it is important to call +timestamp_early_init which provides the initialization of timestamp cache. + + Once the cache is initialized, its state is set to +cache_initialized. Henceforth, the calls to cache i.e. timestamp_add know that +the state reflected is valid and timestamps can be directly saved in the cache. + + When cbmem area is up (i.e. call to cbmem_initialize), we do not need to +store the timestamps in local stash / _timestamp area anymore. Thus, the cache +state is set to cache_not_needed, which allows timestamp_add to store all +timestamps directly into cbmem area. + + +2. cbmem_state + This attribute indicates if we need to reset the timestamp area in +cbmem. This needs to be done for fresh boot (when there is no timestamp area +allocated in cbmem) or during resume (to clean out timestamps from earlier +boot). This can be set to any one of the following values: + +enum { + TIMESTAMP_CBMEM_RESET_NOT_REQD = 0, + TIMESTAMP_CBMEM_RESET_REQD, +}; + + If _timestamp region is being used, the call to timestamp_early_init +sets this field to reset_reqd. If this region is not being used, then instead +the call to timestamp_init sets this field to reset_reqd. Thus, when cbmem +initialization is complete, the timestamp library ensures that the cbmem +timestamp area is properly set as per the value of this attribute and resets +this field to reset_not_reqd. In case of resume path, this field would be set +accordingly by timestamp_early_init / timestamp_init thus ensuring that +timestamps from earlier boot dont float around into current boot logs. Also, +during early ramstage, when cbmem is not yet up, local stash would be used which +is in the bss area and thus this field is set to reset_not_reqd (unless +timestamp_init is called before or after cbmem_intiialize). Hence, when ramstage +brings up cbmem and syncs timestamps, the cbmem timestamp area is not reset. If +ramstage is the first stage where timestamp_init is called, then the cbmem area +is accordingly reset in timestamp_sync or timestamp_init based on the order in +which calls are made. Details are explained in the use cases towards the end. + + +3. table + This field is represented by a structure which provides overall +information about the entries in the timestamp area: + +struct timestamp_table { + uint64_t base_time; + uint32_t max_entries; + uint32_t num_entries; + struct timestamp_entry entries[0]; /* Variable number of entries */ +} __attribute__((packed)); + + It indicates the base time for all timestamp entries, maximum number of +entries that can be stored, total number of entries that currently exist and an +entry structure to hold variable number of entries. + + +4. entries + This field holds the details of each timestamp entry, upto a maximum of +MAX_TIMESTAMP_CACHE which is defined as 16 entries. Each entry is defined by: + +struct timestamp_entry { + uint32_t entry_id; + uint64_t entry_stamp; +} __attribute__((packed)); + + entry_id holds the timestamp id corresponding to this entry and +entry_stamp holds the actual timestamp. + + + For timestamps stored in the cbmem area, a timestamp_table is allocated +with space for MAX_TIMESTAMPS equal to 30. Thus, the cbmem area holds base_time, +max_entries (which is 30), current number of entries and the actual entries +represented by timestamp_entry. + + +========================== Internal Functions ================================== + +1. timestamp_cache_init + Initializes the timestamp cache to a known state by setting num_entries +to 0, base_entries to MAX_TIMESTAMP_CACHE, base_time to caller-provided base, +cache_state to TIMESTAMP_CACHE_INITIALIZED and cbmem_state to caller-provided +state. + + +2. timestamp_cache_get + This function returns a pointer to timestamp cache. It basically +identifies what cache to use based on following parameters: +a. If __PRE_RAM__ is true i.e. we are in pre-ramstage step and _timestamp region +is provided, use _timestamp region. +b. Otherwise use local stash + + If using _timestamp region, it ensures that the size of the region is +big enough to hold all of timestamp_cache structure and MAX_TIMESTAMP_CACHE +timestamp entries. Once the location of cache is decided, it checks to see if +cache is not yet initialized, and calls timestamp_cache_init if required. + + +3. timestamp_alloc_cbmem_table + This function exists only in romstage and ramstage since only these two +stages access cbmem area. It allocates a new table for MAX_TIMESTAMPS number of +entries in the cbmem area using CBMEM_ID_TIMESTAMP tag. It also resets the +base_time and num_entries to 0. + + +4. timestamp_table_get + This function returns a pointer to the timestamp table. Based on the +value of cache_state in timestamp_cache, it provides a pointer either to the +cache (in stash or _timestamp region) or the cbmem timestamp table. If a pointer +to the cbmem timestamp table is returned, it checks to see if cbmem_state +indicates a reset of the cbmem timestamp area. If required, it makes a call to +timestamp_alloc_cbmem_table. + + +5. timestamp_add_table_entry + This function adds a new entry to the timestamp table obtained by making +a call to timestamp_table_get. It sets the id based on user-provided id and the +stamp is set to user-provided time - table base time. This is to normalize all +the timestamps. + + +============================= Function APIs ==================================== + +1. timestamp_early_init + It is essential to call this function only if _timestamp region is being +used. This should be the first call made to the timestamp library. Since +_timestamp region can contain arbitary values in the different fields of the +cache, this function initializes the fields properly by calling +timestamp_cache_init with the cache pointer, user-provided base time and +cbmem_state as TIMESTAMP_CBMEM_RESET_REQD. This will provide an indication that +cbmem timestamp area needs to be added (in case of fresh boot) or reset to 0 +entries(in case of resume). + + +2. timestamp_init + It is essential to call this function before any call to timestamp_add +is made. In case of _timestamp region being used, only a call to +timestamp_early_init is required. In all other cases, it is essential to call +timestamp_init to set the cbmem_state to TIMESTAMP_CBMEM_RESET_REQD. This will +provide an indication that cbmem timestamp area needs to be added (in case of +fresh boot) or reset to 0 entries(in case of resume). + + +3. timestamp_add + This function accepts from user a timestamp id and time to record in the +timestamp table. Based on the table provided by timestamp_table_get, it stores +the entry in the appropriate table in cbmem or _timestamp region or local +stash. + + +4. timestamp_add_now + This function calls timestamp_add with user-provided id and current +time. + + +5. timestamp_sync + This is one of the most important functions required to ensure the +proper functioning of the timestamp library across cbmem, _timestamp region and +local stash with minimal interference for the user. It is important to note that +this function is called only by cbmem_initialize to ensure that once the cbmem +area is ready, we automatically sync all the timestamps saved in the cache to +cbmem area. Thus, the user never has to call the timestamp_sync function. + + This function checks to see if the cache state indicates that a cbmem +reset of timestamp area is required or no timestamp area exists in cbmem at +all. In that case, it allocates a new cbmem area by calling +timestamp_alloc_cbmem_table. + + Otherwise, it uses cbmem_find to use the timestamp area in cbmem. It +then uses timestamp_add_table_entry to move all the entries from cache to cbmem +area. Here, two cases can occur with respect to the base time subtraction: + +a. Newly added cbmem table will have a base time of 0. Thus, no adjustments are +required for the timestamps being added from cache to cbmem table. + +b. Timestamps added to cache before ramstage: In this case, the base time in +cache table will be 0 and timestamp_add_table_entry will take care of +subtracting the correct base_time. Finally, it resets the timestamp cache to: + + cache_state: TIMESTAMP_CACHE_NOT_NEEDED + cbmem_state: TIMESTAMP_CBMEM_RESET_NOT_REQD + num_entries: 0 + + Also, the base_time in cbmem table is update if it is currently zero +indicating that it needs to inherit base time from cache table since +cbmem table might be newly allocated. + + +============================= Use / Test Cases ================================= + + The following cases have been considered while designing the timestamp +library. It is important to ensure that any changes made to this library satisfy +each of the following use cases: + +Case 1: Timestamp Region Exists (Fresh Boot / Resume) + + +1. timestamp_early_init is called to setup the cache state and cbmem_state is +set to reset_reqd. These properties are set in the timestamp cache which is part +of _timestamp region. + +2. : All saved in _timestamp +region + +3. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +_timestamp region to check the cbmem_state field. Since it says reset_reqd, a +new area for timestamp is setup in cbmem by calling cbmem_add. The value of +cbmem_state is set to reset_not_reqd in _timestamp region cache. + +4. After entering ramstage, the local stash acts as the timestamp cache. Since +it is in BSS area, the cache_state field is set to uninitialized and cbmem_state +field is set to reset_not_reqd. + +5. On any call to timestamp_add / timestamp_add_now, it initializes the cache +and sets cache_state field to initialized whereas cbmem_state is still set to +reset_not_reqd. + +6. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +local stash to check the cbmem_state field. Since it says reset_not_reqd, it +uses cbmem_find to find already allocated timestamp area in cbmem. If none is +found, it allocates a new one. + +7. : All saved in +cbmem + + +Case 2: No timestamp region, fresh boot, cbmem_initialize called after +timestamp_init + +1. Since timestamp_init is called before cbmem_initialize, it will set the cache +field attributes to: cache_state as initialized and cbmem_state as +reset_reqd. This ensures that timestamp_sync sets up a new cbmem area for +timestamps. + +2. < Any number of calls to timestamp_add / timestamp_add_now> : All saved in +stash + +3. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +stash cache to check the cbmem_state field. Since it says reset_reqd, a new area +for timestamp is setup in cbmem by calling cbmem_add. The value of cbmem_state +is set to reset_not_reqd in stash cache. + +4. After entering ramstage, a new local stash acts as the timestamp cache. Since +it is in BSS area, the cache_state field is set to uninitialized and cbmem_state +field is set to reset_not_reqd. + +5. On any call to timestamp_add / timestamp_add_now, it initializes the cache +and sets cache_state field to initialized whereas cbmem_state is still set to +reset_not_reqd. + +6. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +local stash to check the cbmem_state field. Since it says reset_not_reqd, it +uses cbmem_find to find already allocated timestamp area in cbmem. If none is +found, it allocates a new one. + +7. : All saved in +cbmem + + +Case 3: No timestamp region, fresh boot, cbmem_initialize called before +timestamp_init + +1. Since cbmem_initialize is called before timestamp_init, it will call +timestamp_sync which checks local stash to check for cbmem_state field. Since, +cbmem_state says no_reset_reqd, it uses cbmem_find to look for a timestamp area +in cbmem. Since, it is a fresh boot, none will be found and it uses cbmem_add to +create a new area on cbmem. + +2. timestamp_init is called, which sets local cache state to reset required. It +then calls timestamp_table_get which sees that cache_state is cache_not_needed +and cbmem_state is reset_reqd. Thus, it calls timestamp_alloc_cbmem_table to +reset the cbmem area which is as good as no change in the state of cbmem +area. Then, the cbmem_state is set to reset_not_reqd. + +3. : All saved in +cbmem + +4. After entering ramstage, a new local stash acts as the timestamp cache. Since +it is in BSS area, the cache_state field is set to uninitialized and cbmem_state +field is set to reset_not_reqd. + +5. On any call to timestamp_add / timestamp_add_now, it initializes the cache +and sets cache_state field to initialized whereas cbmem_state is still set to +reset_not_reqd. + +6. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +local stash to check the cbmem_state field. Since it says reset_not_reqd, it +uses cbmem_find to find already allocated timestamp area in cbmem. If none is +found, it allocates a new one. + +7. : All saved in +cbmem + + +Case 4: No timestamp region, resume, cbmem_initialize called after +timestamp_init + +1. Since timestamp_init is called before cbmem_initialize, it will set the cache +field attributes to: cache_state as initialized and cbmem_state as reset_reqd. + +2. < Any number of calls to timestamp_add / timestamp_add_now> : All saved in +stash + +3. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +stash cache to check the cbmem_state field. Since it says reset_reqd, +timestamp_sync resets cbmem area to num_entries=0, thus flushing timestamps from +earlier boot. The value of cbmem_state is set to reset_not_reqd in stash cache. + +4. After entering ramstage, a new local stash acts as the timestamp cache. Since +it is in BSS area, the cache_state field is set to uninitialized and cbmem_state +field is set to reset_not_reqd. + +5. On any call to timestamp_add / timestamp_add_now, it initializes the cache +and sets cache_state field to initialized whereas cbmem_state is still set to +reset_not_reqd. + +6. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +local stash to check the cbmem_state field. Since it says reset_not_reqd, it +uses cbmem_find to find already allocated timestamp area in cbmem. If none is +found, it allocates a new one. + +7. : All saved in +cbmem + + +Case 5: No timestamp region, resume, cbmem_initialize called before +timestamp_init + +1. Since cbmem_initialize is called before timestamp_init, it will call +timestamp_sync which checks local stash to check for cbmem_state field. Since, +cbmem_state says no_reset_reqd, it uses cbmem_find to look for a timestamp area +in cbmem. Since, it is resume, it will find the older cbmem timestamp area from +earlier boot. However, nothing is added to cbmem area since timestamp_add / +timestamp_add_now is expected to be used only after call to timestamp_init. + +2. timestamp_init is called, which sets local cache state to reset required. It +then calls timestamp_table_get which sees that cache_state is cache_not_needed +and cbmem_state is reset_reqd. Thus, it calls timestamp_alloc_cbmem_table to +reset the cbmem area which sets num_entries to 0. Thus, flushing timestamps from +earlier boot. Then, the cbmem_state is set to reset_not_reqd. + +3. : All saved in +cbmem + +4. After entering ramstage, a new local stash acts as the timestamp cache. Since +it is in BSS area, the cache_state field is set to uninitialized and cbmem_state +field is set to reset_not_reqd. + +5. On any call to timestamp_add / timestamp_add_now, it initializes the cache +and sets cache_state field to initialized whereas cbmem_state is still set to +reset_not_reqd. + +6. Once cbmem_initiliaze is complete, it calls timestamp_sync, which checks the +local stash to check the cbmem_state field. Since it says reset_not_reqd, it +uses cbmem_find to find already allocated timestamp area in cbmem. If none is +found, it allocates a new one. + +7. : All saved in +cbmem diff --git a/payloads/libpayload/Config.in b/payloads/libpayload/Config.in index 9d083ea239..8d5ac1d93b 100644 --- a/payloads/libpayload/Config.in +++ b/payloads/libpayload/Config.in @@ -32,6 +32,15 @@ mainmenu "Libpayload Configuration" menu "Generic Options" +config GPL + bool "GPLv2-licensed Options" + default n + help + Prompt for options that will build code licensed under the GNU General + Public License (version 2). This will subject the whole payload to the + terms of this license (including its provision to release all sources, + please see the LICENSE_GPL file for details). + config EXPERIMENTAL bool "Experimental Options" default n @@ -53,6 +62,13 @@ config DEVELOPER Prompt for developer options. These options are only interesting for libpayload developers. +config REMOTEGDB + bool "Remote GDB stub" + default n + depends on GPL + help + Enable Remote GDB debugging support. + config CHROMEOS bool "ChromeOS specific features" default n @@ -67,21 +83,21 @@ choice prompt "Target Architecture" default ARCH_X86 -config ARCH_ARMV7 - bool "ARMv7" +config ARCH_ARM + bool "ARM" help - Support the x86 architecture - -config ARCH_POWERPC - bool "PowerPC" - help - Support the PowerPC architecture + Support the ARM architecture config ARCH_X86 bool "x86" help Support the x86 architecture +config ARCH_ARM64 + bool "ARM64" + help + Support the ARM64 architecture + endchoice config MEMMAP_RAM_ONLY @@ -167,14 +183,41 @@ config SERIAL_CONSOLE bool "See output on the serial port console" default y -config X86_SERIAL_CONSOLE - bool - depends on ARCH_X86 && SERIAL_CONSOLE - default y +config 8250_SERIAL_CONSOLE + bool "8250, 16450, 16550, 16550A compatible serial port driver" + depends on SERIAL_CONSOLE + default y if ARCH_X86 + default n if !ARCH_X86 + +config S5P_SERIAL_CONSOLE + bool "Exynos SOC, S5P compatible serial port driver" + depends on SERIAL_CONSOLE + default n + +config 8250_MMIO32_SERIAL_CONSOLE + bool "Memory-mapped 8250-compatible serial port driver with 32-bit regs" + depends on SERIAL_CONSOLE + default n + +config IPQ806X_SERIAL_CONSOLE + bool "IPQ806x SOC compatible serial port driver" + depends on SERIAL_CONSOLE + default n + +config BG4CD_SERIAL_CONSOLE + bool "Serial port driver for Marvell's BG4CD" + depends on SERIAL_CONSOLE + default n + +config PL011_SERIAL_CONSOLE + bool "PL011 compatible serial port driver" + depends on 8250_SERIAL_CONSOLE + default n config SERIAL_IOBASE - hex "I/O base for the serial port (default 0x3f8)" - depends on X86_SERIAL_CONSOLE + ## This default is currently not used on non-x86 systems. + hex "Default I/O base for the serial port (default 0x3f8)" + depends on SERIAL_CONSOLE && ARCH_X86 default 0x3f8 config SERIAL_SET_SPEED @@ -320,13 +363,79 @@ config STORAGE_AHCI_ONLY_TESTED If this option is selected only AHCI controllers which are known to work will be used. +config TIMER_RDTSC + bool + default y + depends on ARCH_X86 + +choice + prompt "Timer driver" + default TIMER_NONE + depends on !ARCH_X86 + +config TIMER_NONE + bool "None" + help + The timer driver is provided by the payload itself. + +config TIMER_MCT + bool "Exynos MCT" + +config TIMER_TEGRA_1US + bool "Tegra 1us" + +config TIMER_IPQ806X + bool "Timer for ipq806x platforms" + +config TIMER_RK + bool "Timer for Rockchip" + +config TIMER_BG4CD + bool "Marvell BG4CD" +endchoice + +config TIMER_MCT_HZ + int "Exynos MCT frequency" + depends on TIMER_MCT + default 24000000 + +config TIMER_MCT_ADDRESS + hex "Exynos MCT base address" + depends on TIMER_MCT + default 0x101c0000 + +config TIMER_RK_ADDRESS + hex "Rockchip timer base address" + depends on TIMER_RK + default 0xff810020 + +config TIMER_TEGRA_1US_ADDRESS + hex "Tegra u1s timer base address" + depends on TIMER_TEGRA_1US + default 0x60005010 + +config IPQ806X_TIMER_FREQ + int "Hardware timer frequency" + default 32000 + depends on TIMER_IPQ806X + help + IPQ hardware presently provides a single timer running at 32KHz, a + finer granulariry timer is available but is not yet enabled. + +config IPQ806X_TIMER_REG + hex "Timer register address" + default 0x0200A008 + depends on TIMER_IPQ806X + help + Address of the register to read a free running timer value. + config USB bool "USB Support" default n config USB_UHCI bool "Support for USB UHCI controllers" - depends on USB + depends on USB && ARCH_X86 help Select this option if you are going to use USB 1.1 on an Intel based system. @@ -335,7 +444,7 @@ config USB_OHCI bool "Support for USB OHCI controllers" depends on USB help - Select this option if you are going to use USB 1.1 on an AMD based + Select this option if you are going to use USB 1.1 on a non-Intel based system. config USB_EHCI @@ -351,6 +460,12 @@ config USB_XHCI Select this option if you want to use USB 3.0 NOTE: This option is not (fully) implemented yet +config USB_DWC2 + bool "Support for USB DesignWare HCD controllers" + depends on USB + help + Select this option if you want to use DesignWare USB 2.0 host controller + config USB_HID bool "Support for USB keyboards" depends on USB @@ -369,6 +484,16 @@ config USB_HUB Select this option if you want to compile in support for USB hubs. Say Y here unless you know exactly what you are doing. +config USB_EHCI_HOSTPC_ROOT_HUB_TT + bool "Support for USB EHCI ROOT HUB that has TT" + depends on USB_EHCI + default n + help + Select this option if USB EHCI root hub supports TT (Transaction + Translator). + To support this TT feature we read port-speed from non-standard + register HOSTPC (offset 84h of Operational Register base). + config USB_MSC bool "Support for USB storage" depends on USB @@ -378,6 +503,17 @@ config USB_MSC storage devices (USB memory sticks, hard drives, CDROM/DVD drives) Say Y here unless you know exactly what you are doing. +config USB_PCI + bool "Auto-scan PCI bus for USB host controllers" + depends on USB + default y if ARCH_X86 + default n + +config USB_GEN_HUB + bool + default n if (!USB_HUB && !USB_XHCI) + default y if (USB_HUB || USB_XHCI) + endmenu menu "Debugging" diff --git a/payloads/libpayload/LICENSES b/payloads/libpayload/LICENSES index 49388923b9..f340eadb7d 100644 --- a/payloads/libpayload/LICENSES +++ b/payloads/libpayload/LICENSES @@ -34,8 +34,20 @@ BSD license: For some parts, which were taken from external projects, other (compatible) licenses may apply. Please check the individual source files for details, -or see the section below for an overview of third-party code in libpayload. +or see the section at the bottom of this file for an overview of third-party +code in libpayload. +Some parts of libpayload are licensed under the GNU General Public License +(version 2). These parts are clearly separated by the CONFIG_GPL Kconfig +option (default off), and will not be linked into the output payload unless +that option has been chosen. The full text of that license is provided in the +LICENSE_GPL file. + +(Please note that the coreboot project makes a best effort to keep licensing +information up to date and accurate, but provides no legal guarantees to that +regard. If you redistribute libpayload code in source or binary form, it is +your liability to ensure that you conform to all legal requirements that this +might entail.) Third-party Code and License Overview ------------------------------------- @@ -110,3 +122,12 @@ holders, and the exact license terms that apply. Original files: src/lib/libc/hash/sha1.c Current version we use: CVS revision 1.20 2005/08/08 +* arch/arm/mem*.S: GPLv2 + Source: Linux, http://www.kernel.org + Original files: arch/arm/lib/mem*.S + Current version we use: 3.9 (418df63adac56841ef6b0f1fcf435bc64d4ed177) + +* arch/x86/string.c: LGPLv2.1, modified to GPLv2 under the terms of section 3 + Source: GNU C Library (glibc), http://www.gnu.org/software/libc/libc.html + Original files: sysdeps/i386/memset.c + Current version we use: 2.14 diff --git a/payloads/libpayload/LICENSE_GPL b/payloads/libpayload/LICENSE_GPL new file mode 100644 index 0000000000..2686f8d990 --- /dev/null +++ b/payloads/libpayload/LICENSE_GPL @@ -0,0 +1,345 @@ +This file reproduces the full text of the GNU General Public License +(version 2). Please note that only parts of libpayload are subject to +this license, which are guarded by the CONFIG_GPL Kconfig option. See +the LICENSES file for details. + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/payloads/libpayload/Makefile b/payloads/libpayload/Makefile index bfa1abf481..d8cdfe03ad 100644 --- a/payloads/libpayload/Makefile +++ b/payloads/libpayload/Makefile @@ -57,7 +57,7 @@ export KCONFIG_AUTOCONFIG := $(obj)/auto.conf # directory containing the toplevel Makefile.inc TOPLEVEL := . -CONFIG_SHELL := sh +CONFIG_LP_SHELL := sh KBUILD_DEFCONFIG := configs/defconfig UNAME_RELEASE := $(shell uname -r) DOTCONFIG ?= .config @@ -91,17 +91,17 @@ include util/kconfig/Makefile include $(HAVE_DOTCONFIG) -ARCHDIR-$(CONFIG_ARCH_ARMV7) := armv7 -ARCHDIR-$(CONFIG_ARCH_POWERPC) := powerpc -ARCHDIR-$(CONFIG_ARCH_X86) := x86 +ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm +ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64 +ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86 ARCH-y := $(ARCHDIR-y) # If architecture folder name is different from GCC binutils architecture name, # override here. -ARCH-$(CONFIG_ARCH_ARMV7) := armv7 -ARCH-$(CONFIG_ARCH_POWERPC) := powerpc -ARCH-$(CONFIG_ARCH_X86) := i386 +ARCH-$(CONFIG_LP_ARCH_ARM) := arm +ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64 +ARCH-$(CONFIG_LP_ARCH_X86) := i386 CC := $(CC_$(ARCH-y)) AS := $(AS_$(ARCH-y)) @@ -139,13 +139,13 @@ real-all: config else ifneq ($(INNER_SCANBUILD),y) -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) +ifeq ($(CONFIG_LP_COMPILER_LLVM_CLANG),y) CC:=clang -m32 HOSTCC:=clang endif endif -ifeq ($(CONFIG_CCACHE),y) +ifeq ($(CONFIG_LP_CCACHE),y) CCACHE:=$(word 1,$(wildcard $(addsuffix /ccache,$(subst :, ,$(PATH))))) ifeq ($(CCACHE),) $(error ccache selected, but not found in PATH) @@ -163,12 +163,12 @@ strip_quotes = $(subst ",,$(subst \",,$(1))) # other files ifeq ($(INNER_SCANBUILD),y) -CONFIG_SCANBUILD_ENABLE:= +CONFIG_LP_SCANBUILD_ENABLE:= endif -ifeq ($(CONFIG_SCANBUILD_ENABLE),y) -ifneq ($(CONFIG_SCANBUILD_REPORT_LOCATION),) -CONFIG_SCANBUILD_REPORT_LOCATION:=-o $(CONFIG_SCANBUILD_REPORT_LOCATION) +ifeq ($(CONFIG_LP_SCANBUILD_ENABLE),y) +ifneq ($(CONFIG_LP_SCANBUILD_REPORT_LOCATION),) +CONFIG_LP_SCANBUILD_REPORT_LOCATION:=-o $(CONFIG_LP_SCANBUILD_REPORT_LOCATION) endif real-all: echo '#!/bin/sh' > .ccwrap @@ -177,7 +177,7 @@ real-all: echo 'if [ "$$1" = "--hostcxx" ]; then shift; CC="$(HOSTCXX)"; fi' >> .ccwrap echo 'eval $$CC $$*' >> .ccwrap chmod +x .ccwrap - scan-build $(CONFIG_SCANBUILD_REPORT_LOCATION) -analyze-headers --use-cc=$(top)/.ccwrap --use-c++=$(top)/.ccwrap $(MAKE) INNER_SCANBUILD=y + scan-build $(CONFIG_LP_SCANBUILD_REPORT_LOCATION) -analyze-headers --use-cc=$(top)/.ccwrap --use-c++=$(top)/.ccwrap $(MAKE) INNER_SCANBUILD=y else real-all: real-target endif diff --git a/payloads/libpayload/Makefile.inc b/payloads/libpayload/Makefile.inc index 9e6dc75d1e..f03968492d 100644 --- a/payloads/libpayload/Makefile.inc +++ b/payloads/libpayload/Makefile.inc @@ -31,35 +31,41 @@ export KERNELVERSION := 0.2.0 -ARCHDIR-$(CONFIG_ARCH_ARMV7) := armv7 -ARCHDIR-$(CONFIG_ARCH_X86) := x86 -ARCHDIR-$(CONFIG_ARCH_POWERPC) := powerpc +ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm +ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64 +ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86 DESTDIR ?= install real-target: lib -classes-$(CONFIG_PCI) += libpci -classes-$(CONFIG_LIBC) += libc -classes-$(CONFIG_CURSES) += libcurses -classes-$(CONFIG_PDCURSES) += libmenu libform libpanel -classes-$(CONFIG_CBFS) += libcbfs -classes-$(CONFIG_LZMA) += liblzma +classes-$(CONFIG_LP_PCI) += libpci +classes-$(CONFIG_LP_LIBC) += libc +classes-$(CONFIG_LP_CURSES) += libcurses +classes-$(CONFIG_LP_PDCURSES) += libmenu libform libpanel +classes-$(CONFIG_LP_CBFS) += libcbfs +classes-$(CONFIG_LP_LZMA) += liblzma +classes-$(CONFIG_LP_REMOTEGDB) += libgdb libraries := $(classes-y) classes-y += head.o subdirs-y := arch/$(ARCHDIR-y) -subdirs-y += crypto libc drivers libpci -subdirs-$(CONFIG_CURSES) += curses -subdirs-$(CONFIG_CBFS) += libcbfs -subdirs-$(CONFIG_LZMA) += liblzma +subdirs-y += crypto libc drivers libpci gdb +subdirs-$(CONFIG_LP_CURSES) += curses +subdirs-$(CONFIG_LP_CBFS) += libcbfs +subdirs-$(CONFIG_LP_LZMA) += liblzma -CC_INCLUDE = $(shell $(CC) -print-search-dirs | head -n 1 | cut -d' ' -f2)include - -INCLUDES := -Iinclude -Iinclude/$(ARCHDIR-y) -I$(obj) -I$(CC_INCLUDE) -CFLAGS = $(EXTRA_CFLAGS) $(INCLUDES) -Os -pipe -nostdinc -CFLAGS += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes +INCLUDES := -Iinclude -Iinclude/$(ARCHDIR-y) -I$(obj) +CFLAGS = $(EXTRA_CFLAGS) $(INCLUDES) -pipe -nostdinc -ggdb3 +CFLAGS += -nostdlib -fno-builtin -ffreestanding -fomit-frame-pointer +CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -CFLAGS += -Wstrict-aliasing -Wshadow -fno-builtin +CFLAGS += -Wstrict-aliasing -Wshadow -Werror + +ifneq ($(SOURCE_DEBUG),) +CFLAGS += -O0 -g +else +CFLAGS += -Os +endif $(obj)/libpayload-config.h: $(KCONFIG_AUTOHEADER) cmp $@ $< 2>/dev/null || cp $< $@ diff --git a/payloads/libpayload/arch/Config.in b/payloads/libpayload/arch/Config.in index ebc03c6137..3d3d0b5cf2 100644 --- a/payloads/libpayload/arch/Config.in +++ b/payloads/libpayload/arch/Config.in @@ -27,6 +27,6 @@ ## SUCH DAMAGE. ## -source "arch/armv7/Config.in" -source "arch/powerpc/Config.in" +source "arch/arm/Config.in" source "arch/x86/Config.in" +source "arch/arm64/Config.in" diff --git a/payloads/libpayload/arch/armv7/Config.in b/payloads/libpayload/arch/arm/Config.in similarity index 99% rename from payloads/libpayload/arch/armv7/Config.in rename to payloads/libpayload/arch/arm/Config.in index 6c1bf44985..b1f2bb4a80 100644 --- a/payloads/libpayload/arch/armv7/Config.in +++ b/payloads/libpayload/arch/arm/Config.in @@ -27,7 +27,7 @@ ## SUCH DAMAGE. ## -if ARCH_ARMV7 +if ARCH_ARM config ARCH_SPECIFIC_OPTIONS # dummy def_bool y diff --git a/payloads/libpayload/arch/arm/Makefile.inc b/payloads/libpayload/arch/arm/Makefile.inc new file mode 100644 index 0000000000..6c8667adc6 --- /dev/null +++ b/payloads/libpayload/arch/arm/Makefile.inc @@ -0,0 +1,51 @@ +## +## This file is part of the libpayload project. +## +## Copyright (C) 2008 Advanced Micro Devices, Inc. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. The name of the author may not be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## + +CFLAGS += -mthumb -march=armv7-a +arm_asm_flags = -Wa,-mthumb -Wa,-mimplicit-it=always -Wa,-mno-warn-deprecated + +head.o-y += head.S +libc-y += eabi_compat.c +libc-y += main.c sysinfo.c +libc-y += timer.c coreboot.c util.S +libc-y += virtual.c +libc-y += exception_asm.S exception.c +libc-y += cache.c cpu.S +libc-y += selfboot.c + +# Will fall back to default_memXXX() in libc/memory.c if GPL not allowed. +libc-$(CONFIG_LP_GPL) += memcpy.S memset.S memmove.S + +libgdb-y += gdb.c + +libcbfs-$(CONFIG_LP_CBFS) += dummy_media.c + +# Add other classes here when you put assembly files into them! +head.o-S-ccopts += $(arm_asm_flags) +libc-S-ccopts += $(arm_asm_flags) diff --git a/src/arch/armv7/include/assembler.h b/payloads/libpayload/arch/arm/asmlib.h similarity index 60% rename from src/arch/armv7/include/assembler.h rename to payloads/libpayload/arch/arm/asmlib.h index 5e4789b145..8b3fa22cc2 100644 --- a/src/arch/armv7/include/assembler.h +++ b/payloads/libpayload/arch/arm/asmlib.h @@ -1,5 +1,7 @@ /* - * arch/arm/include/asm/assembler.h + * arch/arm/asmlib.h + * + * Adapted from Linux arch/arm/include/assembler.h * * Copyright (C) 1996-2000 Russell King * @@ -14,6 +16,16 @@ * assembler source. */ +/* + * WARNING: This file is *only* meant for memcpy.S and friends which were copied + * from Linux and require some weird macros. It does unspeakable things like + * redefining "push", so do *not* try to turn it into a general assembly macro + * file, and keep it out of global include directories. + */ + +#ifndef __ARM_ASMLIB_H__ +#define __ARM_ASMLIB_H__ + /* * Endian independent macros for shifting bytes within registers. */ @@ -44,17 +56,17 @@ /* * Data preload for architectures that support it */ -#if defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_7A__) || \ - defined(__ARM_ARCH_7R__) +#if 1 /* TODO: differentiate once libpayload supports more ARM versions */ #define PLD(code...) code #else #define PLD(code...) #endif /* - * Cache alligned + * This can be used to enable code to cacheline align the destination + * pointer when bulk writing to memory. Linux doesn't enable this except + * for the "Feroceon" processor, so we better just leave it out. */ -#define CALGN(code...) code +#define CALGN(code...) + +#endif /* __ARM_ASMLIB_H */ diff --git a/payloads/libpayload/arch/arm/cache.c b/payloads/libpayload/arch/arm/cache.c new file mode 100644 index 0000000000..31819f7f48 --- /dev/null +++ b/payloads/libpayload/arch/arm/cache.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R + * + * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition + */ + +#include + +#include + +void tlb_invalidate_all(void) +{ + /* TLBIALL includes dTLB and iTLB on systems that have them. */ + tlbiall(); + dsb(); + isb(); +} + +enum dcache_op { + OP_DCCSW, + OP_DCCISW, + OP_DCISW, + OP_DCCIMVAC, + OP_DCCMVAC, + OP_DCIMVAC, +}; + +unsigned int dcache_line_bytes(void) +{ + uint32_t ccsidr; + static unsigned int line_bytes = 0; + + if (line_bytes) + return line_bytes; + + ccsidr = read_ccsidr(); + /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ + line_bytes = 1 << ((ccsidr & 0x7) + 2); /* words per line */ + line_bytes *= sizeof(unsigned int); /* bytes per line */ + + return line_bytes; +} + +/* + * Do a dcache operation by modified virtual address. This is useful for + * maintaining coherency in drivers which do DMA transfers and only need to + * perform cache maintenance on a particular memory range rather than the + * entire cache. + */ +static void dcache_op_mva(void const *addr, size_t len, enum dcache_op op) +{ + unsigned long line, linesize; + + linesize = dcache_line_bytes(); + line = (uint32_t)addr & ~(linesize - 1); + + dsb(); + while ((void *)line < addr + len) { + switch(op) { + case OP_DCCIMVAC: + dccimvac(line); + break; + case OP_DCCMVAC: + dccmvac(line); + break; + case OP_DCIMVAC: + dcimvac(line); + break; + default: + break; + } + line += linesize; + } + isb(); +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCMVAC); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCIMVAC); +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCIMVAC); +} + +/* + * CAUTION: This implementation assumes that coreboot never uses non-identity + * page tables for pages containing executed code. If you ever want to violate + * this assumption, have fun figuring out the associated problems on your own. + */ +void dcache_mmu_disable(void) +{ + uint32_t sctlr; + + dcache_clean_invalidate_all(); + sctlr = read_sctlr(); + sctlr &= ~(SCTLR_C | SCTLR_M); + write_sctlr(sctlr); +} + +void dcache_mmu_enable(void) +{ + uint32_t sctlr; + + sctlr = read_sctlr(); + sctlr |= SCTLR_C | SCTLR_M; + write_sctlr(sctlr); +} + +void cache_sync_instructions(void) +{ + dcache_clean_all(); /* includes trailing DSB (in assembly) */ + iciallu(); /* includes BPIALLU (architecturally) */ + dsb(); + isb(); +} diff --git a/payloads/libpayload/arch/arm/coreboot.c b/payloads/libpayload/arch/arm/coreboot.c new file mode 100644 index 0000000000..d7fcb27b7e --- /dev/null +++ b/payloads/libpayload/arch/arm/coreboot.c @@ -0,0 +1,62 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +/* This pointer gets set in head.S and is passed in from coreboot. */ +void *cb_header_ptr; + +static void cb_parse_dma(void *ptr) +{ + struct cb_range *dma = (struct cb_range *)ptr; + init_dma_memory(phys_to_virt(dma->range_start), dma->range_size); +} + +int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info) +{ + switch(rec->tag) { + case CB_TAG_DMA: + cb_parse_dma(rec); + break; + default: + return 0; + } + return 1; +} + +/* == Architecture specific == */ +/* FIXME put in actual address range */ + +int get_coreboot_info(struct sysinfo_t *info) +{ + return cb_parse_header(cb_header_ptr, 1, info); +} diff --git a/payloads/libpayload/arch/arm/cpu.S b/payloads/libpayload/arch/arm/cpu.S new file mode 100644 index 0000000000..4a1d41dc4d --- /dev/null +++ b/payloads/libpayload/arch/arm/cpu.S @@ -0,0 +1,117 @@ +/* + * Optimized assembly for low-level CPU operations on ARMv7 processors. + * + * Cache flushing code based off sys/arch/arm/arm/cpufunc_asm_armv7.S in NetBSD + * + * Copyright (c) 2010 Per Odlund + * Copyright (c) 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * Dcache invalidations by set/way work by passing a [way:sbz:set:sbz:level:0] + * bitfield in a register to the appropriate MCR instruction. This algorithm + * works by initializing a bitfield with the highest-numbered set and way, and + * generating a "set decrement" and a "way decrement". The former just contains + * the LSB of the set field, but the latter contains the LSB of the way field + * minus the highest valid set field... such that when you subtract it from a + * [way:0:level] field you end up with a [way - 1:highest_set:level] field + * through the magic of double subtraction. It's quite ingenius, really. + * Takes care to only use r0-r3 and ip so it's pefectly ABI-compatible without + * needing to write to memory. + */ + +.macro dcache_apply_all crm + dsb + mov r3, #-2 @ initialize level so that we start at 0 + +1: @next_level + add r3, r3, #2 @ increment level + + mrc p15, 1, r0, c0, c0, 1 @ read CLIDR + and ip, r0, #0x07000000 @ narrow to LoC + lsr ip, ip, #23 @ left align LoC (low 4 bits) + cmp r3, ip @ compare + bge 3f @done @ else fall through (r0 == CLIDR) + + add r2, r3, r3, lsr #1 @ r2 = (level << 1) * 3 / 2 + mov r1, r0, lsr r2 @ r1 = cache type + and r1, r1, #7 + cmp r1, #2 @ is it data or i&d? + blt 1b @next_level @ nope, skip level + + mcr p15, 2, r3, c0, c0, 0 @ select cache level + isb + mrc p15, 1, r0, c0, c0, 0 @ read CCSIDR + + ubfx ip, r0, #0, #3 @ get linesize from CCSIDR + add ip, ip, #4 @ apply bias + ubfx r2, r0, #13, #15 @ get numsets - 1 from CCSIDR + lsl r2, r2, ip @ shift to set position + orr r3, r3, r2 @ merge set into way/set/level + mov r1, #1 + lsl r1, r1, ip @ r1 = set decr + + ubfx ip, r0, #3, #10 @ get numways - 1 from [to be discarded] CCSIDR + clz r2, ip @ number of bits to MSB of way + lsl ip, ip, r2 @ shift by that into way position + mov r0, #1 + lsl r2, r0, r2 @ r2 now contains the way decr + mov r0, r3 @ get sets/level (no way yet) + orr r3, r3, ip @ merge way into way/set/level + bfc r0, #0, #4 @ clear low 4 bits (level) to get numset - 1 + sub r2, r2, r0 @ subtract from way decr + + /* r3 = ways/sets/level, r2 = way decr, r1 = set decr, r0 and ip are free */ +2: mcr p15, 0, r3, c7, \crm, 2 @ writeback and/or invalidate line + cmp r3, #15 @ are we done with this level (way/set == 0) + bls 1b @next_level @ yes, go to next level + lsr r0, r3, #4 @ clear level bits leaving only way/set bits + lsls r0, r0, #14 @ clear way bits leaving only set bits + subne r3, r3, r1 @ non-zero?, decrement set # + subeq r3, r3, r2 @ zero?, decrement way # and restore set count + b 2b + +3: @done + mov r0, #0 @ default back to cache level 0 + mcr p15, 2, r0, c0, c0, 0 @ select cache level + dsb + isb + bx lr +.endm + +ENTRY(dcache_invalidate_all) + dcache_apply_all crm=c6 +ENDPROC(dcache_invalidate_all) + +ENTRY(dcache_clean_all) + dcache_apply_all crm=c10 +ENDPROC(dcache_clean_all) + +ENTRY(dcache_clean_invalidate_all) + dcache_apply_all crm=c14 +ENDPROC(dcache_clean_invalidate_all) diff --git a/payloads/libpayload/arch/arm/dummy_media.c b/payloads/libpayload/arch/arm/dummy_media.c new file mode 100644 index 0000000000..7926976422 --- /dev/null +++ b/payloads/libpayload/arch/arm/dummy_media.c @@ -0,0 +1,42 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define LIBPAYLOAD + +#include +#include + +/* The generic cbfs code relies on the libpayload_init_default_cbfs_media + * symbol. Therefore, provide an implementation that just throws an error. */ + +int libpayload_init_default_cbfs_media(struct cbfs_media *media); + +int libpayload_init_default_cbfs_media(struct cbfs_media *media) +{ + return -1; +} diff --git a/payloads/libpayload/arch/arm/eabi_compat.c b/payloads/libpayload/arch/arm/eabi_compat.c new file mode 100644 index 0000000000..0df9509d6d --- /dev/null +++ b/payloads/libpayload/arch/arm/eabi_compat.c @@ -0,0 +1,56 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2014 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Function(s) needed for some EABI conformant tool chains (ex GCC). + */ + +#include + +int raise(int signum) __attribute__((weak)); +int raise(int signum) +{ + die("signal %d raised.\n", signum); + return -1; +} + +/* ARM-defined Personality Routines, currently 3 in ARM EHABI. */ + +void __aeabi_unwind_cpp_pr0(void) __attribute__((weak)); +void __aeabi_unwind_cpp_pr0(void) +{ +} + +void __aeabi_unwind_cpp_pr1(void) __attribute__((weak)); +void __aeabi_unwind_cpp_pr1(void) +{ +} + +void __aeabi_unwind_cpp_pr2(void) __attribute__((weak)); +void __aeabi_unwind_cpp_pr2(void) +{ +} diff --git a/payloads/libpayload/arch/armv7/exception.c b/payloads/libpayload/arch/arm/exception.c similarity index 50% rename from payloads/libpayload/arch/armv7/exception.c rename to payloads/libpayload/arch/arm/exception.c index 5e4e23d6a6..6f1796018b 100644 --- a/payloads/libpayload/arch/armv7/exception.c +++ b/payloads/libpayload/arch/arm/exception.c @@ -27,130 +27,103 @@ * SUCH DAMAGE. */ +#include #include +#include #include #include -void exception_test(void); +u32 exception_stack[0x400] __attribute__((aligned(8))); +struct exception_state exception_state; -static int test_abort; +static exception_hook hook; +static const char *names[EXC_COUNT] = { + [EXC_UNDEF] = "Undefined Instruction", + [EXC_SWI] = "Software Interrupt", + [EXC_PABORT] = "Prefetch Abort", + [EXC_DABORT] = "Data Abort", + [EXC_IRQ] = "Interrupt", + [EXC_FIQ] = "Fast Interrupt", +}; -void exception_undefined_instruction(uint32_t *); -void exception_software_interrupt(uint32_t *); -void exception_prefetch_abort(uint32_t *); -void exception_data_abort(uint32_t *); -void exception_not_used(uint32_t *); -void exception_irq(uint32_t *); -void exception_fiq(uint32_t *); +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); -static void print_regs(uint32_t *regs) + printf("Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printf("%p: ", ptr + i); + for (j = i; j < i + line; j++) + printf("%08x ", *(ptr + j)); + printf("\n"); + } +} + +static void print_regs(void) { int i; - /* Don't print the link register and stack pointer since we don't have their - * actual value. They are hidden by the 'shadow' registers provided - * by the trap hardware. - */ + for (i = 0; i < 16; i++) { if (i == 15) printf("PC"); else if (i == 14) - continue; /* LR */ + printf("LR"); else if (i == 13) - continue; /* SP */ + printf("SP"); else if (i == 12) printf("IP"); else printf("R%d", i); - printf(" = 0x%08x\n", regs[i]); + printf(" = 0x%08x\n", exception_state.regs[i]); } + printf("CPSR = 0x%08x\n", exception_state.cpsr); } -void exception_undefined_instruction(uint32_t *regs) +void exception_dispatch(u32 idx) { - printf("exception _undefined_instruction\n"); - print_regs(regs); - halt(); -} + die_if(idx >= EXC_COUNT || !names[idx], "Bad exception index %u!", idx); -void exception_software_interrupt(uint32_t *regs) -{ - printf("exception _software_interrupt\n"); - print_regs(regs); - halt(); -} - -void exception_prefetch_abort(uint32_t *regs) -{ - printf("exception _prefetch_abort\n"); - print_regs(regs); - halt(); -} - -void exception_data_abort(uint32_t *regs) -{ - if (test_abort) { - regs[15] = regs[0]; + if (hook && hook(idx)) return; - } else { - printf("exception _data_abort\n"); - print_regs(regs); - } + + printf("%s Exception\n", names[idx]); + print_regs(); + switch (idx) { + case EXC_PABORT: + printf("IFAR = %#.8x\n", read_ifar()); + printf("IFSR = %#.8x\n", read_ifsr()); + printf("AIFSR = %#.8x\n", read_aifsr()); + break; + case EXC_DABORT: + printf("DFAR = %#.8x\n", read_dfar()); + printf("DFSR = %#.8x\n", read_dfsr()); + printf("ADFSR = %#.8x\n", read_adfsr()); + break; + }; + dump_stack(exception_state.regs[13], 512); halt(); } -void exception_not_used(uint32_t *regs) -{ - printf("exception _not_used\n"); - print_regs(regs); - halt(); -} - -void exception_irq(uint32_t *regs) -{ - printf("exception _irq\n"); - print_regs(regs); - halt(); -} - -void exception_fiq(uint32_t *regs) -{ - printf("exception _fiq\n"); - print_regs(regs); - halt(); -} - -static inline uint32_t get_sctlr(void) -{ - uint32_t val; - asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (val)); - return val; -} - -static inline void set_sctlr(uint32_t val) -{ - asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r" (val)); - asm volatile("" ::: "memory"); -} - void exception_init(void) { - static const uint32_t sctlr_te = (0x1 << 30); - static const uint32_t sctlr_v = (0x1 << 13); - static const uint32_t sctlr_a = (0x1 << 1); - - uint32_t sctlr = get_sctlr(); + uint32_t sctlr = read_sctlr(); /* Handle exceptions in ARM mode. */ - sctlr &= ~sctlr_te; + sctlr &= ~SCTLR_TE; /* Set V=0 in SCTLR so VBAR points to the exception vector table. */ - sctlr &= ~sctlr_v; - /* Enforce alignment. */ - sctlr |= sctlr_a; - set_sctlr(sctlr); + sctlr &= ~SCTLR_V; + write_sctlr(sctlr); extern uint32_t exception_table[]; set_vbar((uintptr_t)exception_table); - test_abort = 1; - exception_test(); - test_abort = 0; + exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack); + exception_state_ptr = &exception_state; +} + +void exception_install_hook(exception_hook h) +{ + die_if(hook, "Implement support for a list of hooks if you need it."); + hook = h; } diff --git a/src/arch/armv7/exception_asm.S b/payloads/libpayload/arch/arm/exception_asm.S similarity index 59% rename from src/arch/armv7/exception_asm.S rename to payloads/libpayload/arch/arm/exception_asm.S index e46f4bcf6b..8715955de2 100644 --- a/src/arch/armv7/exception_asm.S +++ b/payloads/libpayload/arch/arm/exception_asm.S @@ -27,15 +27,7 @@ * SUCH DAMAGE. */ -exception_stack: - .align 5 - .skip 0x2000, 0xa5 -exception_stack_end: - .word exception_stack_end - -exception_handler: - .word 0 - + .text .align 6 .arm @@ -51,51 +43,79 @@ exception_table: b 8f 1: - ldr sp, _not_used + mov sp, #0 b exception_common + +/* Undefined Instruction (CAREFUL: the PC offset is specific to thumb mode!) */ 2: - ldr sp, _undefined_instruction + sub lr, lr, #2 + mov sp, #1 b exception_common + +/* Software Interrupt (no PC offset necessary) */ 3: - ldr sp, _software_interrupt + mov sp, #2 b exception_common + +/* Prefetch Abort */ 4: - ldr sp, _prefetch_abort + sub lr, lr, #4 + mov sp, #3 b exception_common + +/* Data Abort */ 5: - ldr sp, _data_abort + sub lr, lr, #8 + mov sp, #4 b exception_common + +/* (not used) */ 6: - ldr sp, _not_used + mov sp, #5 b exception_common + +/* Interrupt */ 7: - ldr sp, _irq + sub lr, lr, #4 + mov sp, #6 b exception_common + +/* Fast Interrupt */ 8: - ldr sp, _fiq + sub lr, lr, #4 + mov sp, #7 b exception_common exception_common: - str sp, exception_handler - ldr sp, exception_stack_end - push { lr } - sub sp, sp, $8 - push { r0 - r12 } - mov r0, sp - mov lr, pc - ldr pc, exception_handler - pop { r0 - r12 } - add sp, sp, $8 - ldm sp!, { pc }^ + str sp, exception_idx + ldr sp, exception_state_ptr + stmia sp!, { r0 - r12 } /* Save regs from bottom to top */ + stmia sp, { sp, lr }^ /* Save banked SP/LR (no writeback) */ + str lr, [sp, #(4 * 2)] /* Save PC to ®s[13] + 2 */ + mrs r0, SPSR + str r0, [sp, #(4 * 3)] /* Save SPSR to ®s[13] + 3 */ + ldr sp, exception_stack_end /* Point SP to the stack for C code */ + ldr r0, exception_idx + blx exception_dispatch + ldr sp, exception_state_ptr + ldr r0, [sp, #(4 * 16)] /* Load SPSR from ®s[0] + 16... */ + msr SPSR_cxsf, r0 /* ...and get it out of the way */ + ldmia sp!, { r0 - r12 } /* Restore regs from bottom to top */ + ldmia sp, { sp, lr }^ /* Restore SP/LR to banked location */ + add sp, sp, #8 /* Adjust SP (no writeback allowed) */ + ldmia sp!, { pc }^ /* Do exception return (mode switch) */ -_undefined_instruction: .word exception_undefined_instruction -_software_interrupt: .word exception_software_interrupt -_prefetch_abort: .word exception_prefetch_abort -_data_abort: .word exception_data_abort -_not_used: .word exception_not_used -_irq: .word exception_irq -_fiq: .word exception_fiq + .align 2 + .global exception_stack_end +exception_stack_end: + .word 0 + .global exception_state_ptr +exception_state_ptr: + .word 0 + +exception_idx: + .word 0 .thumb .global set_vbar @@ -104,12 +124,3 @@ set_vbar: mcr p15, 0, r0, c12, c0, 0 bx lr - .global exception_test - .thumb_func -exception_test: - mov r1, $1 - mov r0, pc - add r0, $3 - ldr r1, [r1] - bx lr - diff --git a/payloads/libpayload/arch/arm/gdb.c b/payloads/libpayload/arch/arm/gdb.c new file mode 100644 index 0000000000..faf9eb48f2 --- /dev/null +++ b/payloads/libpayload/arch/arm/gdb.c @@ -0,0 +1,114 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +struct gdb_regs +{ + u32 r[16]; + struct fp_reg + { + u8 byte[12]; + } __attribute__((packed)) f[8]; + u32 fps; + u32 cpsr; +} __attribute__((packed)); + +static const u8 type_to_signal[] = { + [EXC_UNDEF] = GDB_SIGILL, + [EXC_SWI] = GDB_SIGTRAP, + [EXC_PABORT] = GDB_SIGSEGV, + [EXC_DABORT] = GDB_SIGSEGV, +}; + +/* Scratch value to write reentrant exception states to. We never read it. */ +static struct exception_state sentinel_exception_state; + +static int gdb_exception_hook(u32 type) +{ + /* + * If we were not resumed we are in deep trouble here. GDB probably told + * us to do something stupid and caused a reentrant exception. All we + * can do is just blindly send an error code and keep going. Eventually + * GDB will tell us to resume and we return right back to the original + * exception state ("jumping over" all the nested ones). + */ + if (gdb_state.connected && !gdb_state.resumed) { + static const char error_code[] = "E22"; /* EINVAL? */ + static const struct gdb_message tmp_reply = { + .buf = (u8 *)error_code, + .used = sizeof(error_code), + .size = sizeof(error_code), + }; + gdb_send_reply(&tmp_reply); + gdb_command_loop(gdb_state.signal); /* preserve old signal */ + } else { + if (type >= ARRAY_SIZE(type_to_signal) || !type_to_signal[type]) + return 0; + exception_state_ptr = &sentinel_exception_state; + gdb_command_loop(type_to_signal[type]); + } + + exception_state_ptr = &exception_state; + return 1; +} + +void gdb_arch_init(void) +{ + exception_install_hook(&gdb_exception_hook); +} + +void gdb_arch_enter(void) +{ + u32 *sp; + + asm volatile ("mov %0, %%sp" : "=r"(sp) ); + + /* Avoid reentrant exceptions, just call the hook if in one already. */ + if (sp >= exception_stack && sp <= exception_stack_end) + gdb_exception_hook(EXC_SWI); + else + asm volatile ("svc #0"); +} + +int gdb_arch_set_single_step(int on) +{ + /* GDB seems to only need this on x86, ARM works fine without it. */ + return -1; +} + +void gdb_arch_encode_regs(struct gdb_message *message) +{ + gdb_message_encode_bytes(message, exception_state.regs, + sizeof(exception_state.regs)); + gdb_message_encode_zero_bytes(message, + offsetof(struct gdb_regs, cpsr) - offsetof(struct gdb_regs, f)); + gdb_message_encode_bytes(message, &exception_state.cpsr, + sizeof(exception_state.cpsr)); +} + +void gdb_arch_decode_regs(int offset, struct gdb_message *message) +{ + const int cpsr_hex_offset = offsetof(struct gdb_regs, cpsr) * 2; + gdb_message_decode_bytes(message, offset, + exception_state.regs, sizeof(exception_state.regs)); + gdb_message_decode_bytes(message, offset + cpsr_hex_offset, + &exception_state.cpsr, sizeof(exception_state.cpsr)); +} diff --git a/payloads/libpayload/arch/arm/head.S b/payloads/libpayload/arch/arm/head.S new file mode 100644 index 0000000000..788e328322 --- /dev/null +++ b/payloads/libpayload/arch/arm/head.S @@ -0,0 +1,79 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * Our entry point + */ +ENTRY(_entry) + + /* TODO: disable interrupts */ + + /* Clear BSS */ + mov r12, #0 + ldr r2, bss_boundaries + ldr r3, bss_boundaries + 4 + cmp r2, r3 + beq no_bss + + sub r3, #4 /* Account for late condition check. */ +loop: + cmp r2, r3 + str r12, [r2], #4 + blt loop +no_bss: + /* Save off the location of the coreboot tables */ + ldr r1, 1f + str r0, [r1] + + /* Setup new stack */ + ldr sp, 2f + + /* TODO: Save old stack pointer and link register */ + + /* Let's rock. */ + bl start_main + + /* %r0 has the return value - pass it on unmolested */ + + /* TODO: restore old stack pointer and link register */ + + /* Return to the original context. */ + bx lr +ENDPROC(_entry) + +.align 4 +bss_boundaries: + .word _edata + .word _end +1: +.word cb_header_ptr +2: +.word _stack diff --git a/payloads/libpayload/arch/armv7/libpayload.ldscript b/payloads/libpayload/arch/arm/libpayload.ldscript similarity index 100% rename from payloads/libpayload/arch/armv7/libpayload.ldscript rename to payloads/libpayload/arch/arm/libpayload.ldscript diff --git a/payloads/libpayload/arch/armv7/main.c b/payloads/libpayload/arch/arm/main.c similarity index 97% rename from payloads/libpayload/arch/armv7/main.c rename to payloads/libpayload/arch/arm/main.c index 93cfce5c63..cff992fce6 100644 --- a/payloads/libpayload/arch/armv7/main.c +++ b/payloads/libpayload/arch/arm/main.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ -#include +#include #include unsigned int main_argc; /**< The argc value to pass to main() */ @@ -48,7 +48,7 @@ void start_main(void) lib_get_sysinfo(); /* Optionally set up the consoles. */ -#ifndef CONFIG_SKIP_CONSOLE_INIT +#ifndef CONFIG_LP_SKIP_CONSOLE_INIT console_init(); #endif diff --git a/src/arch/armv7/lib/memcpy.S b/payloads/libpayload/arch/arm/memcpy.S similarity index 97% rename from src/arch/armv7/lib/memcpy.S rename to payloads/libpayload/arch/arm/memcpy.S index f04113f279..1388d05ad9 100644 --- a/src/arch/armv7/lib/memcpy.S +++ b/payloads/libpayload/arch/arm/memcpy.S @@ -10,9 +10,8 @@ * published by the Free Software Foundation. */ -#include - -#define W(instr) instr +#include +#include "asmlib.h" #define LDR1W_SHIFT 0 #define STR1W_SHIFT 0 @@ -53,15 +52,9 @@ ldmfd sp!, {r0, \reg1, \reg2} .endm - .text - /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ -.globl memcpy -memcpy: - - cmp r0, r1 - moveq pc, lr +ENTRY(memcpy) enter r4, lr @@ -241,3 +234,4 @@ memcpy: 17: forward_copy_shift pull=16 push=16 18: forward_copy_shift pull=24 push=8 +ENDPROC(memcpy) diff --git a/payloads/libpayload/arch/arm/memmove.S b/payloads/libpayload/arch/arm/memmove.S new file mode 100644 index 0000000000..bd5f8f1ac5 --- /dev/null +++ b/payloads/libpayload/arch/arm/memmove.S @@ -0,0 +1,197 @@ +/* + * linux/arch/arm/lib/memmove.S + * + * Author: Nicolas Pitre + * Created: Sep 28, 2005 + * Copyright: (C) MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "asmlib.h" + +/* + * Prototype: void *memmove(void *dest, const void *src, size_t n); + * + * Note: + * + * If the memory regions don't overlap, we simply branch to memcpy which is + * normally a bit faster. Otherwise the copy is done going downwards. This + * is a transposition of the code from copy_template.S but with the copy + * occurring in the opposite direction. + */ + +ENTRY(memmove) + + subs ip, r0, r1 + cmphi r2, ip + bls memcpy + + stmfd sp!, {r0, r4, lr} + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + PLD( pld [r1, #-4] ) + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + + CALGN( ands ip, r0, #31 ) + CALGN( sbcnes r4, ip, r2 ) @ C is always set here + CALGN( bcs 2f ) + CALGN( adr r4, 6f ) + CALGN( subs r2, r2, ip ) @ C is set here + CALGN( rsb ip, ip, #32 ) + CALGN( add pc, r4, ip ) + + PLD( pld [r1, #-4] ) +2: PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 4f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +3: PLD( pld [r1, #-128] ) +4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} + bge 3b + PLD( cmn r2, #96 ) + PLD( bge 4b ) + +5: ands ip, r2, #28 + rsb ip, ip, #32 + addne pc, pc, ip @ C is always clear here + b 7f +6: W(nop) + W(ldr) r3, [r1, #-4]! + W(ldr) r4, [r1, #-4]! + W(ldr) r5, [r1, #-4]! + W(ldr) r6, [r1, #-4]! + W(ldr) r7, [r1, #-4]! + W(ldr) r8, [r1, #-4]! + W(ldr) lr, [r1, #-4]! + + add pc, pc, ip + nop + W(nop) + W(str) r3, [r0, #-4]! + W(str) r4, [r0, #-4]! + W(str) r5, [r0, #-4]! + W(str) r6, [r0, #-4]! + W(str) r7, [r0, #-4]! + W(str) r8, [r0, #-4]! + W(str) lr, [r0, #-4]! + + CALGN( bcs 2b ) + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldrneb r3, [r1, #-1]! + ldrcsb r4, [r1, #-1]! + ldrcsb ip, [r1, #-1] + strneb r3, [r0, #-1]! + strcsb r4, [r0, #-1]! + strcsb ip, [r0, #-1] + ldmfd sp!, {r0, r4, pc} + +9: cmp ip, #2 + ldrgtb r3, [r1, #-1]! + ldrgeb r4, [r1, #-1]! + ldrb lr, [r1, #-1]! + strgtb r3, [r0, #-1]! + strgeb r4, [r0, #-1]! + subs r2, r2, ip + strb lr, [r0, #-1]! + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr r3, [r1, #0] + beq 17f + blt 18f + + + .macro backward_copy_shift push pull + + subs r2, r2, #28 + blt 14f + + CALGN( ands ip, r0, #31 ) + CALGN( sbcnes r4, ip, r2 ) @ C is always set here + CALGN( subcc r2, r2, ip ) + CALGN( bcc 15f ) + +11: stmfd sp!, {r5 - r9} + + PLD( pld [r1, #-4] ) + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 13f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +12: PLD( pld [r1, #-128] ) +13: ldmdb r1!, {r7, r8, r9, ip} + mov lr, r3, push #\push + subs r2, r2, #32 + ldmdb r1!, {r3, r4, r5, r6} + orr lr, lr, ip, pull #\pull + mov ip, ip, push #\push + orr ip, ip, r9, pull #\pull + mov r9, r9, push #\push + orr r9, r9, r8, pull #\pull + mov r8, r8, push #\push + orr r8, r8, r7, pull #\pull + mov r7, r7, push #\push + orr r7, r7, r6, pull #\pull + mov r6, r6, push #\push + orr r6, r6, r5, pull #\pull + mov r5, r5, push #\push + orr r5, r5, r4, pull #\pull + mov r4, r4, push #\push + orr r4, r4, r3, pull #\pull + stmdb r0!, {r4 - r9, ip, lr} + bge 12b + PLD( cmn r2, #96 ) + PLD( bge 13b ) + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov lr, r3, push #\push + ldr r3, [r1, #-4]! + subs ip, ip, #4 + orr lr, lr, r3, pull #\pull + str lr, [r0, #-4]! + bgt 15b + CALGN( cmp r2, #0 ) + CALGN( bge 11b ) + +16: add r1, r1, #(\pull / 8) + b 8b + + .endm + + + backward_copy_shift push=8 pull=24 + +17: backward_copy_shift push=16 pull=16 + +18: backward_copy_shift push=24 pull=8 + +ENDPROC(memmove) diff --git a/payloads/libpayload/arch/arm/memset.S b/payloads/libpayload/arch/arm/memset.S new file mode 100644 index 0000000000..0c1102deb4 --- /dev/null +++ b/payloads/libpayload/arch/arm/memset.S @@ -0,0 +1,121 @@ +/* + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ASM optimised string functions + */ + +#include +#include "asmlib.h" + +ENTRY(memset) + ands r3, r0, #3 @ 1 unaligned? + mov ip, r0 @ preserve r0 as return value + bne 6f @ 1 +/* + * we know that the pointer in ip is aligned to a word boundary. + */ +1: orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + mov r3, r1 + cmp r2, #16 + blt 4f + +#if ! CALGN(1)+0 + +/* + * We need 2 extra registers for this loop - use r8 and the LR + */ + stmfd sp!, {r8, lr} + mov r8, r1 + mov lr, r1 + +2: subs r2, r2, #64 + stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + bgt 2b + ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. +/* + * No need to correct the count; we're only testing bits from now on + */ + tst r2, #32 + stmneia ip!, {r1, r3, r8, lr} + stmneia ip!, {r1, r3, r8, lr} + tst r2, #16 + stmneia ip!, {r1, r3, r8, lr} + ldmfd sp!, {r8, lr} + +#else + +/* + * This version aligns the destination pointer in order to write + * whole cache lines at once. + */ + + stmfd sp!, {r4-r8, lr} + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov lr, r1 + + cmp r2, #96 + tstgt ip, #31 + ble 3f + + and r8, ip, #31 + rsb r8, r8, #32 + sub r2, r2, r8 + movs r8, r8, lsl #(32 - 4) + stmcsia ip!, {r4, r5, r6, r7} + stmmiia ip!, {r4, r5} + tst r8, #(1 << 30) + mov r8, r1 + strne r1, [ip], #4 + +3: subs r2, r2, #64 + stmgeia ip!, {r1, r3-r8, lr} + stmgeia ip!, {r1, r3-r8, lr} + bgt 3b + ldmeqfd sp!, {r4-r8, pc} + + tst r2, #32 + stmneia ip!, {r1, r3-r8, lr} + tst r2, #16 + stmneia ip!, {r4-r7} + ldmfd sp!, {r4-r8, lr} + +#endif + +4: tst r2, #8 + stmneia ip!, {r1, r3} + tst r2, #4 + strne r1, [ip], #4 +/* + * When we get here, we've got less than 4 bytes to zero. We + * may have an unaligned pointer as well. + */ +5: tst r2, #2 + strneb r1, [ip], #1 + strneb r1, [ip], #1 + tst r2, #1 + strneb r1, [ip], #1 + mov pc, lr + +6: subs r2, r2, #4 @ 1 do we have enough + blt 5b @ 1 bytes to align with? + cmp r3, #2 @ 1 + strltb r1, [ip], #1 @ 1 + strleb r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) + b 1b +ENDPROC(memset) diff --git a/payloads/libpayload/arch/arm/selfboot.c b/payloads/libpayload/arch/arm/selfboot.c new file mode 100644 index 0000000000..70cc79e08f --- /dev/null +++ b/payloads/libpayload/arch/arm/selfboot.c @@ -0,0 +1,40 @@ +/* + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +extern void *cb_header_ptr; + +void selfboot(void *entry) +{ + __asm__ __volatile__( + "mov r0, %[cb_header_ptr]\n" + "bx %[entry]\n" + :: [cb_header_ptr]"r"(cb_header_ptr), [entry]"r"(entry) + : "r0" + ); +} diff --git a/payloads/libpayload/arch/armv7/sysinfo.c b/payloads/libpayload/arch/arm/sysinfo.c similarity index 100% rename from payloads/libpayload/arch/armv7/sysinfo.c rename to payloads/libpayload/arch/arm/sysinfo.c diff --git a/payloads/libpayload/arch/armv7/timer.c b/payloads/libpayload/arch/arm/timer.c similarity index 97% rename from payloads/libpayload/arch/armv7/timer.c rename to payloads/libpayload/arch/arm/timer.c index 9449c9feff..3902308562 100644 --- a/payloads/libpayload/arch/armv7/timer.c +++ b/payloads/libpayload/arch/arm/timer.c @@ -28,8 +28,8 @@ */ /** - * @file armv7/timer.c - * ARMv7 specific timer routines + * @file arm/timer.c + * ARM specific timer routines */ #include diff --git a/payloads/libpayload/arch/armv7/util.S b/payloads/libpayload/arch/arm/util.S similarity index 96% rename from payloads/libpayload/arch/armv7/util.S rename to payloads/libpayload/arch/arm/util.S index e3f173eb2d..7c14a39a4f 100644 --- a/payloads/libpayload/arch/armv7/util.S +++ b/payloads/libpayload/arch/arm/util.S @@ -27,11 +27,9 @@ * SUCH DAMAGE. */ - .global halt - .text - .align 4 +#include /* This function puts the system into a halt. */ - .type halt, function -halt: +ENTRY(halt) b halt +ENDPROC(halt) diff --git a/payloads/libpayload/arch/arm/virtual.c b/payloads/libpayload/arch/arm/virtual.c new file mode 100644 index 0000000000..0d53e50616 --- /dev/null +++ b/payloads/libpayload/arch/arm/virtual.c @@ -0,0 +1,153 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +unsigned long virtual_offset = 0; +extern char _end[]; + +/* + * MAIR Index + * (Originally defined in src/arch/arm/include/armv7/arch/cache.h) + */ +#define MAIR_INDX_NC 0 +#define MAIR_INDX_WT 1 +#define MAIR_INDX_WB 2 + +/* + * Translation Table Attribute + * (Originally defined in src/arch/arm/include/armv7/arch/cache.h) + */ +#define ATTR_BASE (\ + 0ULL << 54 | /* PN. 0:Not restricted */ \ + 0ULL << 53 | /* PXN. 0:Not restricted */ \ + 1 << 10 | /* AF. 1:Accessed. This is to prevent access \ + * fault when accessed for the first time */ \ + 0 << 6 | /* AP[2:1]. 0b00:full access from PL1 */ \ + 0 << 5 | /* NS. 0:Output address is in Secure space */ \ + 0 << 1 | /* block/table. 0:block entry */ \ + 1 << 0 /* validity. 1:valid */ \ + ) +#define ATTR_NC (ATTR_BASE | (MAIR_INDX_NC << 2)) +#define ATTR_WT (ATTR_BASE | (MAIR_INDX_WT << 2)) +#define ATTR_WB (ATTR_BASE | (MAIR_INDX_WB << 2)) + +/* Translation Table Entry */ +typedef uint64_t pmd_t; +typedef uint64_t pgd_t; + +#define SECTION_SHIFT 30 +#define BLOCK_SHIFT 21 +#define PAGE_SHIFT 12 +#define PGD_MASK (~0 << PAGE_SHIFT) + +static pmd_t *ttb_buff = 0; +static uintptr_t work_block; +static pmd_t original_map; + +int getpagesize(void) +{ + return 1 << PAGE_SHIFT; +} + +static void lpae_map_init(void) +{ + pgd_t *pgd; + + die_if(!(read_ttbcr() >> 31), "LPAE is not enabled\n"); + + /* get work block address */ + work_block = ALIGN_UP((uintptr_t)_end, 2*MiB); + assert(work_block); + printf("Work block for LPAE mapping is @ 0x%p\n", (void *)work_block); + + /* get the address of the 1st pmd from pgd[0] */ + pgd = (pgd_t *)((uintptr_t)read_ttbr0() & PGD_MASK); + ttb_buff = (pmd_t *)((uintptr_t)pgd[0] & PGD_MASK); + assert(ttb_buff); + + original_map = ttb_buff[work_block >> BLOCK_SHIFT]; +} + +static void lpae_flush_work_block(void) +{ + dccmvac((uintptr_t)&ttb_buff[work_block >> BLOCK_SHIFT]); + dsb(); + tlbimvaa(work_block); + dsb(); + isb(); +} + +/** + * Maps a 2MB designated block to a requested physical address, and returns + * the address to the block or NULL on error. + * + * pa_mb: Physical address in MB. Has to be on a 2MB boundary. + * policy: Data chache policy + */ +void *lpae_map_phys_addr(unsigned long pa_mb, enum dcache_policy policy) +{ + pmd_t attr; + + if (!ttb_buff) + lpae_map_init(); + + switch(policy) { + case DCACHE_OFF: + attr = ATTR_NC; + break; + case DCACHE_WRITEBACK: + attr = ATTR_WB; + break; + case DCACHE_WRITETHROUGH: + attr = ATTR_WT; + break; + default: + return NULL; + } + + ttb_buff[work_block >> BLOCK_SHIFT] = + ((pmd_t)pa_mb/2 << BLOCK_SHIFT) | attr; + + lpae_flush_work_block(); + + return (void *)work_block; +} + +void lpae_restore_map(void) +{ + ttb_buff[work_block >> BLOCK_SHIFT] = original_map; + lpae_flush_work_block(); +} diff --git a/payloads/libpayload/arch/powerpc/Config.in b/payloads/libpayload/arch/arm64/Config.in similarity index 96% rename from payloads/libpayload/arch/powerpc/Config.in rename to payloads/libpayload/arch/arm64/Config.in index f64f0066f9..0f2596c452 100644 --- a/payloads/libpayload/arch/powerpc/Config.in +++ b/payloads/libpayload/arch/arm64/Config.in @@ -27,11 +27,10 @@ ## SUCH DAMAGE. ## -if ARCH_POWERPC +if ARCH_ARM64 config ARCH_SPECIFIC_OPTIONS # dummy def_bool y - select BIG_ENDIAN - select IO_ADDRESS_SPACE + select LITTLE_ENDIAN endif diff --git a/payloads/libpayload/arch/armv7/Makefile.inc b/payloads/libpayload/arch/arm64/Makefile.inc similarity index 82% rename from payloads/libpayload/arch/armv7/Makefile.inc rename to payloads/libpayload/arch/arm64/Makefile.inc index 9c7fe838cc..ddf0550984 100644 --- a/payloads/libpayload/arch/armv7/Makefile.inc +++ b/payloads/libpayload/arch/arm64/Makefile.inc @@ -27,10 +27,24 @@ ## SUCH DAMAGE. ## +CFLAGS += -march=armv8-a +arm64_asm_flags = + +subdirs-y += lib/ + head.o-y += head.S libc-y += main.c sysinfo.c libc-y += timer.c coreboot.c util.S libc-y += virtual.c -libc-y += memcpy.S memset.S +libc-y += memcpy.S memset.S memmove.S libc-y += exception_asm.S exception.c -libc-y += cache.c +libc-y += cache.c cpu.S +libc-y += selfboot.c +libc-y += mmu.c +libcbfs-$(CONFIG_LP_CBFS) += dummy_media.c + +libgdb-y += gdb.c + +# Add other classes here when you put assembly files into them! + head.o-S-ccopts += $(arm64_asm_flags) + libc-S-ccopts += $(arm64_asm_flags) diff --git a/payloads/libpayload/arch/arm64/cache.c b/payloads/libpayload/arch/arm64/cache.c new file mode 100644 index 0000000000..2ce1cc4a06 --- /dev/null +++ b/payloads/libpayload/arch/arm64/cache.c @@ -0,0 +1,126 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARM64-A and ARM64-R + * + * Reference: ARM64 Architecture Reference Manual, ARM64-A and ARM64-R edition + */ + +#include + +#include +#include + +void tlb_invalidate_all(void) +{ + /* TLBIALL includes dTLB and iTLB on systems that have them. */ + tlbiall_current(); + dsb(); + isb(); +} + +enum dcache_op { + OP_DCCSW, + OP_DCCISW, + OP_DCISW, + OP_DCCIVAC, + OP_DCCVAC, + OP_DCIVAC, +}; + +unsigned int dcache_line_bytes(void) +{ + uint32_t ccsidr; + static unsigned int line_bytes = 0; + + if (line_bytes) + return line_bytes; + + ccsidr = raw_read_ccsidr_el1(); + /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ + line_bytes = 1 << ((ccsidr & 0x7) + 2); /* words per line */ + line_bytes *= sizeof(unsigned int); /* bytes per word */ + + return line_bytes; +} + +/* + * Do a dcache operation by virtual address. This is useful for + * maintaining coherency in drivers which do DMA transfers and only need to + * perform cache maintenance on a particular memory range rather than the + * entire cache. + */ +static void dcache_op_va(void const *addr, size_t len, enum dcache_op op) +{ + unsigned long line, linesize; + + linesize = dcache_line_bytes(); + line = (uintptr_t)addr & ~(linesize - 1); + + dsb(); + while (line < (uintptr_t)addr + len) { + switch(op) { + case OP_DCCIVAC: + dccivac(line); + break; + case OP_DCCVAC: + dccvac(line); + break; + case OP_DCIVAC: + dcivac(line); + break; + default: + break; + } + line += linesize; + } + isb(); +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCCVAC); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCCIVAC); +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCIVAC); +} + +void cache_sync_instructions(void) +{ + dcache_clean_all(); /* includes trailing DSB (in assembly) */ + iciallu(); /* includes BPIALLU (architecturally) */ + dsb(); + isb(); +} diff --git a/payloads/libpayload/arch/arm64/coreboot.c b/payloads/libpayload/arch/arm64/coreboot.c new file mode 100644 index 0000000000..a25c51adff --- /dev/null +++ b/payloads/libpayload/arch/arm64/coreboot.c @@ -0,0 +1,57 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +/* This pointer gets set in head.S and is passed in from coreboot. */ +void *cb_header_ptr; + +/* == Architecture specific == */ + +int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info) +{ + switch(rec->tag) { + default: + return 0; + } + return 1; +} + +int get_coreboot_info(struct sysinfo_t *info) +{ + return cb_parse_header(cb_header_ptr, 1, info); +} + +void *get_cb_header_ptr(void) +{ + return cb_header_ptr; +} diff --git a/payloads/libpayload/arch/arm64/cpu.S b/payloads/libpayload/arch/arm64/cpu.S new file mode 100644 index 0000000000..d80f73c112 --- /dev/null +++ b/payloads/libpayload/arch/arm64/cpu.S @@ -0,0 +1,98 @@ +/* + * Optimized assembly for low-level CPU operations on ARM64 processors. + * + * Copyright (c) 2010 Per Odlund + * Copyright (c) 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +.macro dcache_apply_all crm + dsb sy + mrs x0, clidr_el1 // read CLIDR + and w3, w0, #0x07000000 // narrow to LoC + lsr w3, w3, #23 // left align LoC (low 4 bits) + cbz w3, 5f //done + + mov w10, #0 // w10 = 2 * cache level + mov w8, #1 // w8 = constant 0b1 + +1: //next_level + add w2, w10, w10, lsr #1 // calculate 3 * cache level + lsr w1, w0, w2 // extract 3-bit cache type for this level + and w1, w1, #0x7 // w1 = cache type + cmp w1, #2 // is it data or i&d? + b.lt 4f //skip + msr csselr_el1, x10 // select current cache level + isb // sync change of csselr + mrs x1, ccsidr_el1 // w1 = read ccsidr + and w2, w1, #7 // w2 = log2(linelen_bytes) - 4 + add w2, w2, #4 // w2 = log2(linelen_bytes) + ubfx w4, w1, #3, #10 // w4 = associativity - 1 (also + // max way number) + clz w5, w4 // w5 = 32 - log2(ways) + // (bit position of way in DC) + lsl w9, w4, w5 // w9 = max way number + // (aligned for DC) + lsl w16, w8, w5 // w16 = amount to decrement (way + // number per iteration) +2: //next_way + ubfx w7, w1, #13, #15 // w7 = max set #, right aligned + lsl w7, w7, w2 // w7 = max set #, DC aligned + lsl w17, w8, w2 // w17 = amount to decrement (set + // number per iteration) + +3: //next_set + orr w11, w10, w9 // w11 = combine way # & cache # + orr w11, w11, w7 // ... and set # + dc \crm, x11 // clean and/or invalidate line + subs w7, w7, w17 // decrement set number + b.ge 3b //next_set + subs x9, x9, x16 // decrement way number + b.ge 2b //next_way + +4: //skip + add w10, w10, #2 // increment 2 *cache level + cmp w3, w10 // Went beyond LoC? + b.gt 1b //next_level + +5: //done + dsb sy + isb + ret +.endm + +ENTRY(dcache_invalidate_all) + dcache_apply_all crm=isw +ENDPROC(dcache_invalidate_all) + +ENTRY(dcache_clean_all) + dcache_apply_all crm=csw +ENDPROC(dcache_clean_all) + +ENTRY(dcache_clean_invalidate_all) + dcache_apply_all crm=cisw +ENDPROC(dcache_clean_invalidate_all) diff --git a/payloads/libpayload/arch/arm64/dummy_media.c b/payloads/libpayload/arch/arm64/dummy_media.c new file mode 100644 index 0000000000..7926976422 --- /dev/null +++ b/payloads/libpayload/arch/arm64/dummy_media.c @@ -0,0 +1,42 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define LIBPAYLOAD + +#include +#include + +/* The generic cbfs code relies on the libpayload_init_default_cbfs_media + * symbol. Therefore, provide an implementation that just throws an error. */ + +int libpayload_init_default_cbfs_media(struct cbfs_media *media); + +int libpayload_init_default_cbfs_media(struct cbfs_media *media) +{ + return -1; +} diff --git a/payloads/libpayload/arch/arm64/exception.c b/payloads/libpayload/arch/arm64/exception.c new file mode 100644 index 0000000000..2330a98456 --- /dev/null +++ b/payloads/libpayload/arch/arm64/exception.c @@ -0,0 +1,112 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +extern unsigned int test_exc; + +struct exception_handler_info +{ + const char *name; +}; + +static exception_hook hook; +struct exception_state *exception_state; + +static struct exception_handler_info exceptions[EXC_COUNT] = { + [EXC_SYNC_SP0] = { "_sync_sp_el0" }, + [EXC_IRQ_SP0] = { "_irq_sp_el0" }, + [EXC_FIQ_SP0] = { "_fiq_sp_el0" }, + [EXC_SERROR_SP0] = {"_serror_sp_el0"}, + [EXC_SYNC_SPX] = { "_sync_spx" }, + [EXC_IRQ_SPX] = { "_irq_spx" }, + [EXC_FIQ_SPX] = { "_fiq_spx" }, + [EXC_SERROR_SPX] = {"_serror_spx"}, + [EXC_SYNC_ELX_64] = { "_sync_elx_64" }, + [EXC_IRQ_ELX_64] = { "_irq_elx_64" }, + [EXC_FIQ_ELX_64] = { "_fiq_elx_64" }, + [EXC_SERROR_ELX_64] = {"_serror_elx_64"}, + [EXC_SYNC_ELX_32] = { "_sync_elx_32" }, + [EXC_IRQ_ELX_32] = { "_irq_elx_32" }, + [EXC_FIQ_ELX_32] = { "_fiq_elx_32" }, + [EXC_SERROR_ELX_32] = {"_serror_elx_32"}, +}; + +static void print_regs(struct exception_state *state) +{ + int i; + + printf("ELR = 0x%016llx\n",state->elr); + printf("ESR = 0x%08llx\n",state->esr); + for (i = 0; i < 31; i++) { + printf("X%02d = 0x%016llx\n", i, state->regs[i]); + } +} + +void exception_dispatch(struct exception_state *state, int idx); +void exception_dispatch(struct exception_state *state, int idx) +{ + exception_state = state; + + if (idx >= EXC_COUNT) { + printf("Bad exception index %d.\n", idx); + } else { + struct exception_handler_info *info = &exceptions[idx]; + if (hook && hook(idx)) + return; + + if (info->name) + printf("exception %s\n", info->name); + else + printf("exception _not_used.\n"); + } + print_regs(state); + + if (test_exc) { + state->elr += 4; + test_exc = 0; + printf("returning back now\n"); + } + else + halt(); +} + +void exception_init(void) +{ + extern void* exception_table; + set_vbar(&exception_table); +} + +void exception_install_hook(exception_hook h) +{ + die_if(hook, "Implement support for a list of hooks if you need it."); + hook = h; +} diff --git a/payloads/libpayload/arch/arm64/exception_asm.S b/payloads/libpayload/arch/arm64/exception_asm.S new file mode 100644 index 0000000000..c9e694ac5f --- /dev/null +++ b/payloads/libpayload/arch/arm64/exception_asm.S @@ -0,0 +1,136 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __ASSEMBLY__ +#include + + .text + + /* Macro for exception entry + * Store x30 before any branch + * Branch to exception_prologue to save rest of the registers + * Move exception id into x1 + * Branch to exception_handler + */ +.macro eentry lbl id + .align 7 +\lbl: + stp x30, xzr, [sp, #-16]! + bl exception_prologue + mov x1, \id + bl exception_handler +.endm + + /* Exception table has 16 entries and each of 128 bytes + * Hence, 16 * 128 = 2048. Thus, 11 passed as parameter + * to align + */ + + .align 11 + .global exception_table +exception_table: + +eentry sync_sp0,#0 +eentry irq_sp0,#1 +eentry fiq_sp0,#2 +eentry serror_sp0,#3 +eentry sync_spx,#4 +eentry irq_spx,#5 +eentry fiq_spx,#6 +eentry serror_spx,#7 +eentry sync_elx_64,#8 +eentry irq_elx_64,#9 +eentry fiq_elx_64,#10 +eentry serror_elx_64,#11 +eentry sync_elx_32,#12 +eentry irq_elx_32,#13 +eentry fiq_elx_32,#14 +eentry serror_elx_32,#15 + +exception_prologue: + /* Save all registers x0-x29 */ + stp x28, x29, [sp, #-16]! + stp x26, x27, [sp, #-16]! + stp x24, x25, [sp, #-16]! + stp x22, x23, [sp, #-16]! + stp x20, x21, [sp, #-16]! + stp x18, x19, [sp, #-16]! + stp x16, x17, [sp, #-16]! + stp x14, x15, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x10, x11, [sp, #-16]! + stp x8, x9, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x4, x5, [sp, #-16]! + stp x2, x3, [sp, #-16]! + stp x0, x1, [sp, #-16]! + + /* Save the exception reason on stack */ + read_current x1, esr + + /* Save the return address on stack */ + read_current x0, elr + stp x0, x1, [sp, #-16]! + + ret + +exception_handler: + /* Save address of saved registers into x0 + * This acts as first argument to exception_dispatch + */ + mov x0, sp + bl exception_dispatch + + /* Pop return address saved on stack */ + ldp x0, x1, [sp], #16 + write_current elr, x0, x2 + write_current esr, x1, x2 + /* Pop exception reason saved on stack, followed by regs x0-x30 */ + ldp x0, x1, [sp], #16 + ldp x2, x3, [sp], #16 + ldp x4, x5, [sp], #16 + ldp x6, x7, [sp], #16 + ldp x8, x9, [sp], #16 + ldp x10, x11, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x14, x15, [sp], #16 + ldp x16, x17, [sp], #16 + ldp x18, x19, [sp], #16 + ldp x20, x21, [sp], #16 + ldp x22, x23, [sp], #16 + ldp x24, x25, [sp], #16 + ldp x26, x27, [sp], #16 + ldp x28, x29, [sp], #16 + ldp x30, xzr, [sp], #16 + eret + + .global set_vbar +set_vbar: + write_current vbar, x0, x1 + ret diff --git a/payloads/libpayload/arch/arm64/gdb.c b/payloads/libpayload/arch/arm64/gdb.c new file mode 100644 index 0000000000..c976483f04 --- /dev/null +++ b/payloads/libpayload/arch/arm64/gdb.c @@ -0,0 +1,80 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +struct gdb_regs +{ + u64 x[32]; + struct fp_reg + { + u64 quad[2]; + } __attribute__((packed)) f[32]; + u32 fpcr; + u32 fpsr; + u32 spsr; +} __attribute__((packed)); + +static const u8 type_to_signal[] = { + [EXC_SYNC_SP0] = GDB_SIGTRAP, + [EXC_IRQ_SP0] = GDB_SIGSEGV, + [EXC_FIQ_SP0] = GDB_SIGSEGV, + [EXC_SERROR_SP0] = GDB_SIGSEGV, + [EXC_SYNC_SPX] = GDB_SIGTRAP, + [EXC_IRQ_SPX] = GDB_SIGSEGV, + [EXC_FIQ_SPX] = GDB_SIGSEGV, + [EXC_SERROR_SPX] = GDB_SIGSEGV, + [EXC_SYNC_ELX_64] = GDB_SIGTRAP, + [EXC_IRQ_ELX_64] = GDB_SIGSEGV, + [EXC_FIQ_ELX_64] = GDB_SIGSEGV, + [EXC_SERROR_ELX_64] = GDB_SIGSEGV, + [EXC_SYNC_ELX_32] = GDB_SIGTRAP, + [EXC_IRQ_ELX_32] = GDB_SIGSEGV, + [EXC_FIQ_ELX_32] = GDB_SIGSEGV, + [EXC_SERROR_ELX_32] = GDB_SIGSEGV +}; + +static int gdb_exception_hook(u32 type) +{ + return -1; +} + +void gdb_arch_init(void) +{ + exception_install_hook(&gdb_exception_hook); +} + +void gdb_arch_enter(void) +{ +} + +int gdb_arch_set_single_step(int on) +{ + /* GDB seems to only need this on x86, ARM works fine without it. */ + return -1; +} + +void gdb_arch_encode_regs(struct gdb_message *message) +{ +} + +void gdb_arch_decode_regs(int offset, struct gdb_message *message) +{ +} diff --git a/payloads/libpayload/arch/armv7/head.S b/payloads/libpayload/arch/arm64/head.S similarity index 82% rename from payloads/libpayload/arch/armv7/head.S rename to payloads/libpayload/arch/arm64/head.S index 7a706e3aa6..349dfd43ee 100644 --- a/payloads/libpayload/arch/armv7/head.S +++ b/payloads/libpayload/arch/arm64/head.S @@ -27,33 +27,41 @@ * SUCH DAMAGE. */ - .global _entry, _leave - .text - .align 4 - -1: -.word _stack +#include /* * Our entry point */ -_entry: +ENTRY(_entry) - /* TODO: disable interrupts */ + /* Save off the location of the coreboot tables */ + ldr x1, 1f + str x0, [x1] - /* TODO: Clear BSS */ + /* Setup exception stack */ + ldr x1, 3f + msr SPSel, #1 + isb + + mov sp, x1 /* Setup new stack */ - ldr sp, 1b + ldr x1, 2f + msr SPSel, #0 + isb - /* TODO: Save old stack pointer */ + mov sp, x1 /* Let's rock. */ - b start_main + bl start_main - /* %eax has the return value - pass it on unmolested */ -_leave: - /* TODO: restore old stack pointer. */ + ret +ENDPROC(_entry) - /* Return to the original context. */ - mov pc, lr +.align 4 +1: +.quad cb_header_ptr +2: +.quad _stack +3: +.quad _exc_stack diff --git a/payloads/libpayload/arch/powerpc/Makefile.inc b/payloads/libpayload/arch/arm64/lib/Makefile.inc similarity index 81% rename from payloads/libpayload/arch/powerpc/Makefile.inc rename to payloads/libpayload/arch/arm64/lib/Makefile.inc index 44ce431092..a7b7f576b4 100644 --- a/payloads/libpayload/arch/powerpc/Makefile.inc +++ b/payloads/libpayload/arch/arm64/lib/Makefile.inc @@ -1,7 +1,7 @@ +##################################################################################### +## This file is part of the coreboot project. ## -## This file is part of the libpayload project. -## -## Copyright (C) 2008 Advanced Micro Devices, Inc. +## Copyright 2014 Google Inc. ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted provided that the following conditions @@ -26,9 +26,8 @@ ## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## +##################################################################################### -head.o-y := head.S -libc-y += main.c sysinfo.c -libc-y += timer.c coreboot.c util.S -libc-y += exec.S virtual.c +lib_access = pstate.c sysctrl.c cache.c tlb.c clock.c +libc-y += $(lib_access) \ No newline at end of file diff --git a/payloads/libpayload/arch/arm64/lib/cache.c b/payloads/libpayload/arch/arm64/lib/cache.c new file mode 100644 index 0000000000..53dff5759e --- /dev/null +++ b/payloads/libpayload/arch/arm64/lib/cache.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache Maintenance Instructions + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include + +void dccisw(uint64_t cisw) +{ + __asm__ __volatile__("dc cisw, %0\n\t" : : "r" (cisw) :"memory"); +} + +void dccivac(uint64_t civac) +{ + __asm__ __volatile__("dc civac, %0\n\t" : : "r" (civac) :"memory"); +} + +void dccsw(uint64_t csw) +{ + __asm__ __volatile__("dc csw, %0\n\t" : : "r" (csw) :"memory"); +} + +void dccvac(uint64_t cvac) +{ + __asm__ __volatile__("dc cvac, %0\n\t" : : "r" (cvac) :"memory"); +} + +void dccvau(uint64_t cvau) +{ + __asm__ __volatile__("dc cvau, %0\n\t" : : "r" (cvau) :"memory"); +} + +void dcisw(uint64_t isw) +{ + __asm__ __volatile__("dc isw, %0\n\t" : : "r" (isw) :"memory"); +} + +void dcivac(uint64_t ivac) +{ + __asm__ __volatile__("dc ivac, %0\n\t" : : "r" (ivac) :"memory"); +} + +void dczva(uint64_t zva) +{ + __asm__ __volatile__("dc zva, %0\n\t" : : "r" (zva) :"memory"); +} + +void iciallu(void) +{ + __asm__ __volatile__("ic iallu\n\t" : : :"memory"); +} + +void icialluis(void) +{ + __asm__ __volatile__("ic ialluis\n\t" : : :"memory"); +} + +void icivau(uint64_t ivau) +{ + __asm__ __volatile__("ic ivau, %0\n\t" : : "r" (ivau) :"memory"); +} + + + diff --git a/payloads/libpayload/arch/arm64/lib/clock.c b/payloads/libpayload/arch/arm64/lib/clock.c new file mode 100644 index 0000000000..9f06f0828c --- /dev/null +++ b/payloads/libpayload/arch/arm64/lib/clock.c @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * clock.c: Functions for accessing clock and timer related registers + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include + +void set_cntfrq(uint32_t freq) +{ + __asm__ __volatile__("msr cntfrq_el0, %0" :: "r"(freq)); +} diff --git a/payloads/libpayload/arch/arm64/lib/pstate.c b/payloads/libpayload/arch/arm64/lib/pstate.c new file mode 100644 index 0000000000..27554f7f1f --- /dev/null +++ b/payloads/libpayload/arch/arm64/lib/pstate.c @@ -0,0 +1,432 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + * pstate.c: This file defines all the library functions for accessing + * PSTATE and special purpose registers + */ + +#include + +#include + +/* CurrentEL */ +uint32_t raw_read_current_el(void) +{ + uint32_t current_el; + + __asm__ __volatile__("mrs %0, CurrentEL\n\t" : "=r" (current_el) : : "memory"); + + return current_el; +} + +uint32_t get_current_el(void) +{ + uint32_t current_el = raw_read_current_el(); + return ((current_el >> CURRENT_EL_SHIFT) & CURRENT_EL_MASK); +} + +/* DAIF */ +uint32_t raw_read_daif(void) +{ + uint32_t daif; + + __asm__ __volatile__("mrs %0, DAIF\n\t" : "=r" (daif) : : "memory"); + + return daif; +} + +void raw_write_daif(uint32_t daif) +{ + __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); +} + +void enable_debug_exceptions(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_DBG_BIT) : "memory"); +} + +void enable_serror_exceptions(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_ABT_BIT) : "memory"); +} + +void enable_irq(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_IRQ_BIT) : "memory"); +} + +void enable_fiq(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_FIQ_BIT) : "memory"); +} + +void disable_debug_exceptions(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_DBG_BIT) : "memory"); +} + +void disable_serror_exceptions(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_ABT_BIT) : "memory"); +} + +void disable_irq(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_IRQ_BIT) : "memory"); +} + +void disable_fiq(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_FIQ_BIT) : "memory"); +} + +/* DLR_EL0 */ +uint64_t raw_read_dlr_el0(void) +{ + uint64_t dlr_el0; + + __asm__ __volatile__("mrs %0, DLR_EL0\n\t" : "=r" (dlr_el0) : : "memory"); + + return dlr_el0; +} +void raw_write_dlr_el0(uint64_t dlr_el0) +{ + __asm__ __volatile__("msr DLR_EL0, %0\n\t" : : "r" (dlr_el0) : "memory"); +} + +/* DSPSR_EL0 */ +uint64_t raw_read_dspsr_el0(void) +{ + uint64_t dspsr_el0; + + __asm__ __volatile__("mrs %0, DSPSR_EL0\n\t" : "=r" (dspsr_el0) : : "memory"); + + return dspsr_el0; +} +void raw_write_dspsr_el0(uint64_t dspsr_el0) +{ + __asm__ __volatile__("msr DSPSR_EL0, %0\n\t" : : "r" (dspsr_el0) : "memory"); +} + +/* ELR */ +uint64_t raw_read_elr_el1(void) +{ + uint64_t elr_el1; + + __asm__ __volatile__("mrs %0, ELR_EL1\n\t" : "=r" (elr_el1) : : "memory"); + + return elr_el1; +} + +void raw_write_elr_el1(uint64_t elr_el1) +{ + __asm__ __volatile__("msr ELR_EL1, %0\n\t" : : "r" (elr_el1) : "memory"); +} + +uint64_t raw_read_elr_el2(void) +{ + uint64_t elr_el2; + + __asm__ __volatile__("mrs %0, ELR_EL2\n\t" : "=r" (elr_el2) : : "memory"); + + return elr_el2; +} + +void raw_write_elr_el2(uint64_t elr_el2) +{ + __asm__ __volatile__("msr ELR_EL2, %0\n\t" : : "r" (elr_el2) : "memory"); +} + +uint64_t raw_read_elr_el3(void) +{ + uint64_t elr_el3; + + __asm__ __volatile__("mrs %0, ELR_EL3\n\t" : "=r" (elr_el3) : : "memory"); + + return elr_el3; +} + +void raw_write_elr_el3(uint64_t elr_el3) +{ + __asm__ __volatile__("msr ELR_EL3, %0\n\t" : : "r" (elr_el3) : "memory"); +} + +uint64_t raw_read_elr_current(void) +{ + SWITCH_CASE_READ(raw_read_elr,elr,uint64_t); +} + +void raw_write_elr_current(uint64_t elr) +{ + SWITCH_CASE_WRITE(raw_write_elr,elr); +} + +/* FPCR */ +uint32_t raw_read_fpcr(void) +{ + uint32_t fpcr; + + __asm__ __volatile__("mrs %0, FPCR\n\t" : "=r" (fpcr) : : "memory"); + + return fpcr; +} + +void raw_write_fpcr(uint32_t fpcr) +{ + __asm__ __volatile__("msr FPCR, %0\n\t" : : "r" (fpcr) : "memory"); +} + +/* FPSR */ +uint32_t raw_read_fpsr(void) +{ + uint32_t fpsr; + + __asm__ __volatile__("mrs %0, FPSR\n\t" : "=r" (fpsr) : : "memory"); + + return fpsr; +} + +void raw_write_fpsr(uint32_t fpsr) +{ + __asm__ __volatile__("msr FPSR, %0\n\t" : : "r" (fpsr) : "memory"); +} + +/* NZCV */ +uint32_t raw_read_nzcv(void) +{ + uint32_t nzcv; + + __asm__ __volatile__("mrs %0, NZCV\n\t" : "=r" (nzcv) : : "memory"); + + return nzcv; +} + +void raw_write_nzcv(uint32_t nzcv) +{ + __asm__ __volatile__("msr NZCV, %0\n\t" : : "r" (nzcv) : "memory"); +} + +/* SP */ +uint64_t raw_read_sp_el0(void) +{ + uint64_t sp_el0; + + __asm__ __volatile__("mrs %0, SP_EL0\n\t" : "=r" (sp_el0) : : "memory"); + + return sp_el0; +} + +void raw_write_sp_el0(uint64_t sp_el0) +{ + __asm__ __volatile__("msr SP_EL0, %0\n\t" : : "r" (sp_el0) : "memory"); +} + +uint64_t raw_read_sp_el1(void) +{ + uint64_t sp_el1; + + __asm__ __volatile__("mrs %0, SP_EL1\n\t" : "=r" (sp_el1) : : "memory"); + + return sp_el1; +} + +void raw_write_sp_el1(uint64_t sp_el1) +{ + __asm__ __volatile__("msr SP_EL1, %0\n\t" : : "r" (sp_el1) : "memory"); +} + +uint64_t raw_read_sp_el2(void) +{ + uint64_t sp_el2; + + __asm__ __volatile__("mrs %0, SP_EL2\n\t" : "=r" (sp_el2) : : "memory"); + + return sp_el2; +} + +void raw_write_sp_el2(uint64_t sp_el2) +{ + __asm__ __volatile__("msr SP_EL2, %0\n\t" : : "r" (sp_el2) : "memory"); +} + +/* SPSel */ +uint32_t raw_read_spsel(void) +{ + uint32_t spsel; + + __asm__ __volatile__("mrs %0, SPSel\n\t" : "=r" (spsel) : : "memory"); + + return spsel; +} + +void raw_write_spsel(uint32_t spsel) +{ + __asm__ __volatile__("msr SPSel, %0\n\t" : : "r" (spsel) : "memory"); +} + +uint64_t raw_read_sp_el3(void) +{ + uint64_t sp_el3; + uint32_t spsel; + + spsel = raw_read_spsel(); + if (!spsel) + raw_write_spsel(1); + + __asm__ __volatile__("mov %0, sp\n\t" : "=r" (sp_el3) : : "memory"); + + if (!spsel) + raw_write_spsel(spsel); + + return sp_el3; +} + +void raw_write_sp_el3(uint64_t sp_el3) +{ + uint32_t spsel; + + spsel = raw_read_spsel(); + if (!spsel) + raw_write_spsel(1); + + __asm__ __volatile__("mov sp, %0\n\t" : "=r" (sp_el3) : : "memory"); + + if (!spsel) + raw_write_spsel(spsel); +} + +/* SPSR */ +uint32_t raw_read_spsr_abt(void) +{ + uint32_t spsr_abt; + + __asm__ __volatile__("mrs %0, SPSR_abt\n\t" : "=r" (spsr_abt) : : "memory"); + + return spsr_abt; +} + +void raw_write_spsr_abt(uint32_t spsr_abt) +{ + __asm__ __volatile__("msr SPSR_abt, %0\n\t" : : "r" (spsr_abt) : "memory"); +} + +uint32_t raw_read_spsr_el1(void) +{ + uint32_t spsr_el1; + + __asm__ __volatile__("mrs %0, SPSR_EL1\n\t" : "=r" (spsr_el1) : : "memory"); + + return spsr_el1; +} + +void raw_write_spsr_el1(uint32_t spsr_el1) +{ + __asm__ __volatile__("msr SPSR_EL1, %0\n\t" : : "r" (spsr_el1) : "memory"); +} + +uint32_t raw_read_spsr_el2(void) +{ + uint32_t spsr_el2; + + __asm__ __volatile__("mrs %0, SPSR_EL2\n\t" : "=r" (spsr_el2) : : "memory"); + + return spsr_el2; +} + +void raw_write_spsr_el2(uint32_t spsr_el2) +{ + __asm__ __volatile__("msr SPSR_EL2, %0\n\t" : : "r" (spsr_el2) : "memory"); +} + +uint32_t raw_read_spsr_el3(void) +{ + uint32_t spsr_el3; + + __asm__ __volatile__("mrs %0, SPSR_EL3\n\t" : "=r" (spsr_el3) : : "memory"); + + return spsr_el3; +} + +void raw_write_spsr_el3(uint32_t spsr_el3) +{ + __asm__ __volatile__("msr SPSR_EL3, %0\n\t" : : "r" (spsr_el3) : "memory"); +} + +uint32_t raw_read_spsr_current(void) +{ + SWITCH_CASE_READ(raw_read_spsr,spsr,uint32_t); +} + +void raw_write_spsr_current(uint32_t spsr) +{ + SWITCH_CASE_WRITE(raw_write_spsr,spsr); +} + +uint32_t raw_read_spsr_fiq(void) +{ + uint32_t spsr_fiq; + + __asm__ __volatile__("mrs %0, SPSR_fiq\n\t" : "=r" (spsr_fiq) : : "memory"); + + return spsr_fiq; +} + +void raw_write_spsr_fiq(uint32_t spsr_fiq) +{ + __asm__ __volatile__("msr SPSR_fiq, %0\n\t" : : "r" (spsr_fiq) : "memory"); +} + +uint32_t raw_read_spsr_irq(void) +{ + uint32_t spsr_irq; + + __asm__ __volatile__("mrs %0, SPSR_irq\n\t" : "=r" (spsr_irq) : : "memory"); + + return spsr_irq; +} + +void raw_write_spsr_irq(uint32_t spsr_irq) +{ + __asm__ __volatile__("msr SPSR_irq, %0\n\t" : : "r" (spsr_irq) : "memory"); +} + +uint32_t raw_read_spsr_und(void) +{ + uint32_t spsr_und; + + __asm__ __volatile__("mrs %0, SPSR_und\n\t" : "=r" (spsr_und) : : "memory"); + + return spsr_und; +} + +void raw_write_spsr_und(uint32_t spsr_und) +{ + __asm__ __volatile__("msr SPSR_und, %0\n\t" : : "r" (spsr_und) : "memory"); +} + diff --git a/payloads/libpayload/arch/arm64/lib/sysctrl.c b/payloads/libpayload/arch/arm64/lib/sysctrl.c new file mode 100644 index 0000000000..13c9309f08 --- /dev/null +++ b/payloads/libpayload/arch/arm64/lib/sysctrl.c @@ -0,0 +1,889 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + * sysctrl.c: This file defines all the library functions for accessing system + * control registers in Aarch64 + */ + +#include + +#include + +/* ACTLR */ +uint32_t raw_read_actlr_el1(void) +{ + uint32_t actlr_el1; + + __asm__ __volatile__("mrs %0, ACTLR_EL1\n\t" : "=r" (actlr_el1) : : "memory"); + + return actlr_el1; +} + +void raw_write_actlr_el1(uint32_t actlr_el1) +{ + __asm__ __volatile__("msr ACTLR_EL1, %0\n\t" : : "r" (actlr_el1) : "memory"); +} + +uint32_t raw_read_actlr_el2(void) +{ + uint32_t actlr_el2; + + __asm__ __volatile__("mrs %0, ACTLR_EL2\n\t" : "=r" (actlr_el2) : : "memory"); + + return actlr_el2; +} + +void raw_write_actlr_el2(uint32_t actlr_el2) +{ + __asm__ __volatile__("msr ACTLR_EL2, %0\n\t" : : "r" (actlr_el2) : "memory"); +} + +uint32_t raw_read_actlr_el3(void) +{ + uint32_t actlr_el3; + + __asm__ __volatile__("mrs %0, ACTLR_EL3\n\t" : "=r" (actlr_el3) : : "memory"); + + return actlr_el3; +} + +void raw_write_actlr_el3(uint32_t actlr_el3) +{ + __asm__ __volatile__("msr ACTLR_EL3, %0\n\t" : : "r" (actlr_el3) : "memory"); +} + +uint32_t raw_read_actlr_current(void) +{ + SWITCH_CASE_READ(raw_read_actlr,actlr,uint32_t); +} + +void raw_write_actlr_current(uint32_t actlr) +{ + SWITCH_CASE_WRITE(raw_write_actlr,actlr); +} + +/* AFSR0 */ +uint32_t raw_read_afsr0_el1(void) +{ + uint32_t afsr0_el1; + + __asm__ __volatile__("mrs %0, AFSR0_EL1\n\t" : "=r" (afsr0_el1) : : "memory"); + + return afsr0_el1; +} + +void raw_write_afsr0_el1(uint32_t afsr0_el1) +{ + __asm__ __volatile__("msr AFSR0_EL1, %0\n\t" : : "r" (afsr0_el1) : "memory"); +} + +uint32_t raw_read_afsr0_el2(void) +{ + uint32_t afsr0_el2; + + __asm__ __volatile__("mrs %0, AFSR0_EL2\n\t" : "=r" (afsr0_el2) : : "memory"); + + return afsr0_el2; +} + +void raw_write_afsr0_el2(uint32_t afsr0_el2) +{ + __asm__ __volatile__("msr AFSR0_EL2, %0\n\t" : : "r" (afsr0_el2) : "memory"); +} + +uint32_t raw_read_afsr0_el3(void) +{ + uint32_t afsr0_el3; + + __asm__ __volatile__("mrs %0, AFSR0_EL3\n\t" : "=r" (afsr0_el3) : : "memory"); + + return afsr0_el3; +} + +void raw_write_afsr0_el3(uint32_t afsr0_el3) +{ + __asm__ __volatile__("msr AFSR0_EL3, %0\n\t" : : "r" (afsr0_el3) : "memory"); +} + +uint32_t raw_read_afsr0_current(void) +{ + SWITCH_CASE_READ(raw_read_afsr0,afsr0,uint32_t); +} + +void raw_write_afsr0_current(uint32_t afsr0) +{ + SWITCH_CASE_WRITE(raw_write_afsr0,afsr0); +} + +/* AFSR1 */ +uint32_t raw_read_afsr1_el1(void) +{ + uint32_t afsr1_el1; + + __asm__ __volatile__("mrs %0, AFSR1_EL1\n\t" : "=r" (afsr1_el1) : : "memory"); + + return afsr1_el1; +} + +void raw_write_afsr1_el1(uint32_t afsr1_el1) +{ + __asm__ __volatile__("msr AFSR1_EL1, %0\n\t" : : "r" (afsr1_el1) : "memory"); +} + +uint32_t raw_read_afsr1_el2(void) +{ + uint32_t afsr1_el2; + + __asm__ __volatile__("mrs %0, AFSR1_EL2\n\t" : "=r" (afsr1_el2) : : "memory"); + + return afsr1_el2; +} + +void raw_write_afsr1_el2(uint32_t afsr1_el2) +{ + __asm__ __volatile__("msr AFSR1_EL2, %0\n\t" : : "r" (afsr1_el2) : "memory"); +} + +uint32_t raw_read_afsr1_el3(void) +{ + uint32_t afsr1_el3; + + __asm__ __volatile__("mrs %0, AFSR1_EL3\n\t" : "=r" (afsr1_el3) : : "memory"); + + return afsr1_el3; +} + +void raw_write_afsr1_el3(uint32_t afsr1_el3) +{ + __asm__ __volatile__("msr AFSR1_EL3, %0\n\t" : : "r" (afsr1_el3) : "memory"); +} + +uint32_t raw_read_afsr1_current(void) +{ + SWITCH_CASE_READ(raw_read_afsr1,afsr1,uint32_t); +} + +void raw_write_afsr1_current(uint32_t afsr1) +{ + SWITCH_CASE_WRITE(raw_write_afsr1,afsr1); +} + +/* AIDR */ +uint32_t raw_read_aidr_el1(void) +{ + uint32_t aidr_el1; + + __asm__ __volatile__("mrs %0, AIDR_EL1\n\t" : "=r" (aidr_el1) : : "memory"); + + return aidr_el1; +} + +/* AMAIR */ +uint64_t raw_read_amair_el1(void) +{ + uint64_t amair_el1; + + __asm__ __volatile__("mrs %0, AMAIR_EL1\n\t" : "=r" (amair_el1) : : "memory"); + + return amair_el1; +} + +void raw_write_amair_el1(uint64_t amair_el1) +{ + __asm__ __volatile__("msr AMAIR_EL1, %0\n\t" : : "r" (amair_el1) : "memory"); +} + +uint64_t raw_read_amair_el2(void) +{ + uint64_t amair_el2; + + __asm__ __volatile__("mrs %0, AMAIR_EL2\n\t" : "=r" (amair_el2) : : "memory"); + + return amair_el2; +} + +void raw_write_amair_el2(uint64_t amair_el2) +{ + __asm__ __volatile__("msr AMAIR_EL2, %0\n\t" : : "r" (amair_el2) : "memory"); +} + +uint64_t raw_read_amair_el3(void) +{ + uint64_t amair_el3; + + __asm__ __volatile__("mrs %0, AMAIR_EL3\n\t" : "=r" (amair_el3) : : "memory"); + + return amair_el3; +} + +void raw_write_amair_el3(uint64_t amair_el3) +{ + __asm__ __volatile__("msr AMAIR_EL3, %0\n\t" : : "r" (amair_el3) : "memory"); +} + +uint64_t raw_read_amair_current(void) +{ + SWITCH_CASE_READ(raw_read_amair,amair,uint64_t); +} + +void raw_write_amair_current(uint64_t amair) +{ + SWITCH_CASE_WRITE(raw_write_amair,amair); +} + +/* CCSIDR */ +uint32_t raw_read_ccsidr_el1(void) +{ + uint32_t ccsidr_el1; + + __asm__ __volatile__("mrs %0, CCSIDR_EL1\n\t" : "=r" (ccsidr_el1) : : "memory"); + + return ccsidr_el1; +} + +/* CLIDR */ +uint32_t raw_read_clidr_el1(void) +{ + uint32_t clidr_el1; + + __asm__ __volatile__("mrs %0, CLIDR_EL1\n\t" : "=r" (clidr_el1) : : "memory"); + + return clidr_el1; +} + +/* CPACR */ +uint32_t raw_read_cpacr_el1(void) +{ + uint32_t cpacr_el1; + + __asm__ __volatile__("mrs %0, CPACR_EL1\n\t" : "=r" (cpacr_el1) : : "memory"); + + return cpacr_el1; +} + +void raw_write_cpacr_el1(uint32_t cpacr_el1) +{ + __asm__ __volatile__("msr CPACR_EL1, %0\n\t" : : "r" (cpacr_el1) : "memory"); +} + +/* CPTR */ +uint32_t raw_read_cptr_el2(void) +{ + uint32_t cptr_el2; + + __asm__ __volatile__("mrs %0, CPTR_EL2\n\t" : "=r" (cptr_el2) : : "memory"); + + return cptr_el2; +} + +void raw_write_cptr_el2(uint32_t cptr_el2) +{ + __asm__ __volatile__("msr CPTR_EL2, %0\n\t" : : "r" (cptr_el2) : "memory"); +} + +uint32_t raw_read_cptr_el3(void) +{ + uint32_t cptr_el3; + + __asm__ __volatile__("mrs %0, CPTR_EL3\n\t" : "=r" (cptr_el3) : : "memory"); + + return cptr_el3; +} + +void raw_write_cptr_el3(uint32_t cptr_el3) +{ + __asm__ __volatile__("msr CPTR_EL3, %0\n\t" : : "r" (cptr_el3) : "memory"); +} + +/* CSSELR */ +uint32_t raw_read_csselr_el1(void) +{ + uint32_t csselr_el1; + + __asm__ __volatile__("mrs %0, CSSELR_EL1\n\t" : "=r" (csselr_el1) : : "memory"); + + return csselr_el1; +} + +void raw_write_csselr_el1(uint32_t csselr_el1) +{ + __asm__ __volatile__("msr CSSELR_EL1, %0\n\t" : : "r" (csselr_el1) : "memory"); +} + +/* CTR */ +uint32_t raw_read_ctr_el0(void) +{ + uint32_t ctr_el0; + + __asm__ __volatile__("mrs %0, CTR_EL0\n\t" : "=r" (ctr_el0) : : "memory"); + + return ctr_el0; +} + +/* ESR */ +uint32_t raw_read_esr_el1(void) +{ + uint32_t esr_el1; + + __asm__ __volatile__("mrs %0, ESR_EL1\n\t" : "=r" (esr_el1) : : "memory"); + + return esr_el1; +} + +void raw_write_esr_el1(uint32_t esr_el1) +{ + __asm__ __volatile__("msr ESR_EL1, %0\n\t" : : "r" (esr_el1) : "memory"); +} + +uint32_t raw_read_esr_el2(void) +{ + uint32_t esr_el2; + + __asm__ __volatile__("mrs %0, ESR_EL2\n\t" : "=r" (esr_el2) : : "memory"); + + return esr_el2; +} + +void raw_write_esr_el2(uint32_t esr_el2) +{ + __asm__ __volatile__("msr ESR_EL2, %0\n\t" : : "r" (esr_el2) : "memory"); +} + +uint32_t raw_read_esr_el3(void) +{ + uint32_t esr_el3; + + __asm__ __volatile__("mrs %0, ESR_EL3\n\t" : "=r" (esr_el3) : : "memory"); + + return esr_el3; +} + +void raw_write_esr_el3(uint32_t esr_el3) +{ + __asm__ __volatile__("msr ESR_EL3, %0\n\t" : : "r" (esr_el3) : "memory"); +} + +uint32_t raw_read_esr_current(void) +{ + SWITCH_CASE_READ(raw_read_esr,esr,uint32_t); +} + +void raw_write_esr_current(uint32_t esr) +{ + SWITCH_CASE_WRITE(raw_write_esr,esr); +} + +/* FAR */ +uint64_t raw_read_far_el1(void) +{ + uint64_t far_el1; + + __asm__ __volatile__("mrs %0, FAR_EL1\n\t" : "=r" (far_el1) : : "memory"); + + return far_el1; +} + +void raw_write_far_el1(uint64_t far_el1) +{ + __asm__ __volatile__("msr FAR_EL1, %0\n\t" : : "r" (far_el1) : "memory"); +} + +uint64_t raw_read_far_el2(void) +{ + uint64_t far_el2; + + __asm__ __volatile__("mrs %0, FAR_EL2\n\t" : "=r" (far_el2) : : "memory"); + + return far_el2; +} + +void raw_write_far_el2(uint64_t far_el2) +{ + __asm__ __volatile__("msr FAR_EL2, %0\n\t" : : "r" (far_el2) : "memory"); +} + +uint64_t raw_read_far_el3(void) +{ + uint64_t far_el3; + + __asm__ __volatile__("mrs %0, FAR_EL3\n\t" : "=r" (far_el3) : : "memory"); + + return far_el3; +} + +void raw_write_far_el3(uint64_t far_el3) +{ + __asm__ __volatile__("msr FAR_EL3, %0\n\t" : : "r" (far_el3) : "memory"); +} + +uint64_t raw_read_far_current(void) +{ + SWITCH_CASE_READ(raw_read_far,far,uint64_t); +} + +void raw_write_far_current(uint64_t far) +{ + SWITCH_CASE_WRITE(raw_write_far,far); +} + +/* HCR */ +uint64_t raw_read_hcr_el2(void) +{ + uint64_t hcr_el2; + + __asm__ __volatile__("mrs %0, HCR_EL2\n\t" : "=r" (hcr_el2) : : "memory"); + + return hcr_el2; +} + +void raw_write_hcr_el2(uint64_t hcr_el2) +{ + __asm__ __volatile__("msr HCR_EL2, %0\n\t" : : "r" (hcr_el2) : "memory"); +} + +/* AA64PFR0 */ +uint64_t raw_read_aa64pfr0_el1(void) +{ + uint64_t aa64pfr0_el1; + + __asm__ __volatile__("mrs %0, ID_AA64PFR0_EL1\n\t" : "=r" (aa64pfr0_el1) : : "memory"); + + return aa64pfr0_el1; +} + +/* MAIR */ +uint64_t raw_read_mair_el1(void) +{ + uint64_t mair_el1; + + __asm__ __volatile__("mrs %0, MAIR_EL1\n\t" : "=r" (mair_el1) : : "memory"); + + return mair_el1; +} + +void raw_write_mair_el1(uint64_t mair_el1) +{ + __asm__ __volatile__("msr MAIR_EL1, %0\n\t" : : "r" (mair_el1) : "memory"); +} + +uint64_t raw_read_mair_el2(void) +{ + uint64_t mair_el2; + + __asm__ __volatile__("mrs %0, MAIR_EL2\n\t" : "=r" (mair_el2) : : "memory"); + + return mair_el2; +} + +void raw_write_mair_el2(uint64_t mair_el2) +{ + __asm__ __volatile__("msr MAIR_EL2, %0\n\t" : : "r" (mair_el2) : "memory"); +} + +uint64_t raw_read_mair_el3(void) +{ + uint64_t mair_el3; + + __asm__ __volatile__("mrs %0, MAIR_EL3\n\t" : "=r" (mair_el3) : : "memory"); + + return mair_el3; +} + +void raw_write_mair_el3(uint64_t mair_el3) +{ + __asm__ __volatile__("msr MAIR_EL3, %0\n\t" : : "r" (mair_el3) : "memory"); +} + +uint64_t raw_read_mair_current(void) +{ + SWITCH_CASE_READ(raw_read_mair,mair,uint64_t); +} + +void raw_write_mair_current(uint64_t mair) +{ + SWITCH_CASE_WRITE(raw_write_mair,mair); +} + +/* MPIDR */ +uint64_t raw_read_mpidr_el1(void) +{ + uint64_t mpidr_el1; + + __asm__ __volatile__("mrs %0, MPIDR_EL1\n\t" : "=r" (mpidr_el1) : : "memory"); + + return mpidr_el1; +} + +/* RMR */ +uint32_t raw_read_rmr_el1(void) +{ + uint32_t rmr_el1; + + __asm__ __volatile__("mrs %0, RMR_EL1\n\t" : "=r" (rmr_el1) : : "memory"); + + return rmr_el1; +} + +void raw_write_rmr_el1(uint32_t rmr_el1) +{ + __asm__ __volatile__("msr RMR_EL1, %0\n\t" : : "r" (rmr_el1) : "memory"); +} + +uint32_t raw_read_rmr_el2(void) +{ + uint32_t rmr_el2; + + __asm__ __volatile__("mrs %0, RMR_EL2\n\t" : "=r" (rmr_el2) : : "memory"); + + return rmr_el2; +} + +void raw_write_rmr_el2(uint32_t rmr_el2) +{ + __asm__ __volatile__("msr RMR_EL2, %0\n\t" : : "r" (rmr_el2) : "memory"); +} + +uint32_t raw_read_rmr_el3(void) +{ + uint32_t rmr_el3; + + __asm__ __volatile__("mrs %0, RMR_EL3\n\t" : "=r" (rmr_el3) : : "memory"); + + return rmr_el3; +} + +void raw_write_rmr_el3(uint32_t rmr_el3) +{ + __asm__ __volatile__("msr RMR_EL3, %0\n\t" : : "r" (rmr_el3) : "memory"); +} + +uint32_t raw_read_rmr_current(void) +{ + SWITCH_CASE_READ(raw_read_rmr,rmr,uint32_t); +} + +void raw_write_rmr_current(uint32_t rmr) +{ + SWITCH_CASE_WRITE(raw_write_rmr,rmr); +} + +/* RVBAR */ +uint64_t raw_read_rvbar_el1(void) +{ + uint64_t rvbar_el1; + + __asm__ __volatile__("mrs %0, RVBAR_EL1\n\t" : "=r" (rvbar_el1) : : "memory"); + + return rvbar_el1; +} + +void raw_write_rvbar_el1(uint64_t rvbar_el1) +{ + __asm__ __volatile__("msr RVBAR_EL1, %0\n\t" : : "r" (rvbar_el1) : "memory"); +} + +uint64_t raw_read_rvbar_el2(void) +{ + uint64_t rvbar_el2; + + __asm__ __volatile__("mrs %0, RVBAR_EL2\n\t" : "=r" (rvbar_el2) : : "memory"); + + return rvbar_el2; +} + +void raw_write_rvbar_el2(uint64_t rvbar_el2) +{ + __asm__ __volatile__("msr RVBAR_EL2, %0\n\t" : : "r" (rvbar_el2) : "memory"); +} + +uint64_t raw_read_rvbar_el3(void) +{ + uint64_t rvbar_el3; + + __asm__ __volatile__("mrs %0, RVBAR_EL3\n\t" : "=r" (rvbar_el3) : : "memory"); + + return rvbar_el3; +} + +void raw_write_rvbar_el3(uint64_t rvbar_el3) +{ + __asm__ __volatile__("msr RVBAR_EL3, %0\n\t" : : "r" (rvbar_el3) : "memory"); +} + +uint64_t raw_read_rvbar_current(void) +{ + SWITCH_CASE_READ(raw_read_rvbar,rvbar,uint64_t); +} + +void raw_write_rvbar_current(uint64_t rvbar) +{ + SWITCH_CASE_WRITE(raw_write_rvbar,rvbar); +} + +/* SCR */ +uint32_t raw_read_scr_el3(void) +{ + uint32_t scr_el3; + + __asm__ __volatile__("mrs %0, SCR_EL3\n\t" : "=r" (scr_el3) : : "memory"); + + return scr_el3; +} + +void raw_write_scr_el3(uint32_t scr_el3) +{ + __asm__ __volatile__("msr SCR_EL3, %0\n\t" : : "r" (scr_el3) : "memory"); +} + +/* SCTLR */ +uint32_t raw_read_sctlr_el1(void) +{ + uint32_t sctlr_el1; + + __asm__ __volatile__("mrs %0, SCTLR_EL1\n\t" : "=r" (sctlr_el1) : : "memory"); + + return sctlr_el1; +} + +void raw_write_sctlr_el1(uint32_t sctlr_el1) +{ + __asm__ __volatile__("msr SCTLR_EL1, %0\n\t" : : "r" (sctlr_el1) : "memory"); +} + +uint32_t raw_read_sctlr_el2(void) +{ + uint32_t sctlr_el2; + + __asm__ __volatile__("mrs %0, SCTLR_EL2\n\t" : "=r" (sctlr_el2) : : "memory"); + + return sctlr_el2; +} + +void raw_write_sctlr_el2(uint32_t sctlr_el2) +{ + __asm__ __volatile__("msr SCTLR_EL2, %0\n\t" : : "r" (sctlr_el2) : "memory"); +} + +uint32_t raw_read_sctlr_el3(void) +{ + uint32_t sctlr_el3; + + __asm__ __volatile__("mrs %0, SCTLR_EL3\n\t" : "=r" (sctlr_el3) : : "memory"); + + return sctlr_el3; +} + +void raw_write_sctlr_el3(uint32_t sctlr_el3) +{ + __asm__ __volatile__("msr SCTLR_EL3, %0\n\t" : : "r" (sctlr_el3) : "memory"); +} + +uint32_t raw_read_sctlr_current(void) +{ + SWITCH_CASE_READ(raw_read_sctlr,sctlr,uint32_t); +} + +void raw_write_sctlr_current(uint32_t sctlr) +{ + SWITCH_CASE_WRITE(raw_write_sctlr,sctlr); +} + +/* TCR */ +uint64_t raw_read_tcr_el1(void) +{ + uint64_t tcr_el1; + + __asm__ __volatile__("mrs %0, TCR_EL1\n\t" : "=r" (tcr_el1) : : "memory"); + + return tcr_el1; +} + +void raw_write_tcr_el1(uint64_t tcr_el1) +{ + __asm__ __volatile__("msr TCR_EL1, %0\n\t" : : "r" (tcr_el1) : "memory"); +} + +uint32_t raw_read_tcr_el2(void) +{ + uint32_t tcr_el2; + + __asm__ __volatile__("mrs %0, TCR_EL2\n\t" : "=r" (tcr_el2) : : "memory"); + + return tcr_el2; +} + +void raw_write_tcr_el2(uint32_t tcr_el2) +{ + __asm__ __volatile__("msr TCR_EL2, %0\n\t" : : "r" (tcr_el2) : "memory"); +} + +uint32_t raw_read_tcr_el3(void) +{ + uint32_t tcr_el3; + + __asm__ __volatile__("mrs %0, TCR_EL3\n\t" : "=r" (tcr_el3) : : "memory"); + + return tcr_el3; +} + +void raw_write_tcr_el3(uint32_t tcr_el3) +{ + __asm__ __volatile__("msr TCR_EL3, %0\n\t" : : "r" (tcr_el3) : "memory"); +} + +uint64_t raw_read_tcr_current(void) +{ + SWITCH_CASE_READ(raw_read_tcr, tcr, uint64_t); +} + +void raw_write_tcr_current(uint64_t tcr) +{ + SWITCH_CASE_WRITE(raw_write_tcr, tcr); +} + +/* TTBR0 */ +uint64_t raw_read_ttbr0_el1(void) +{ + uint64_t ttbr0_el1; + + __asm__ __volatile__("mrs %0, TTBR0_EL1\n\t" : "=r" (ttbr0_el1) : : "memory"); + + return ttbr0_el1; +} + +void raw_write_ttbr0_el1(uint64_t ttbr0_el1) +{ + __asm__ __volatile__("msr TTBR0_EL1, %0\n\t" : : "r" (ttbr0_el1) : "memory"); +} + +uint64_t raw_read_ttbr0_el2(void) +{ + uint64_t ttbr0_el2; + + __asm__ __volatile__("mrs %0, TTBR0_EL2\n\t" : "=r" (ttbr0_el2) : : "memory"); + + return ttbr0_el2; +} + +void raw_write_ttbr0_el2(uint64_t ttbr0_el2) +{ + __asm__ __volatile__("msr TTBR0_EL2, %0\n\t" : : "r" (ttbr0_el2) : "memory"); +} + +uint64_t raw_read_ttbr0_el3(void) +{ + uint64_t ttbr0_el3; + + __asm__ __volatile__("mrs %0, TTBR0_EL3\n\t" : "=r" (ttbr0_el3) : : "memory"); + + return ttbr0_el3; +} + +void raw_write_ttbr0_el3(uint64_t ttbr0_el3) +{ + __asm__ __volatile__("msr TTBR0_EL3, %0\n\t" : : "r" (ttbr0_el3) : "memory"); +} + +uint64_t raw_read_ttbr0_current(void) +{ + SWITCH_CASE_READ(raw_read_ttbr0,ttbr0,uint64_t); +} + +void raw_write_ttbr0_current(uint64_t ttbr0) +{ + SWITCH_CASE_WRITE(raw_write_ttbr0,ttbr0); +} + +/* TTBR1 */ +uint64_t raw_read_ttbr1_el1(void) +{ + uint64_t ttbr1_el1; + + __asm__ __volatile__("mrs %0, TTBR1_EL1\n\t" : "=r" (ttbr1_el1) : : "memory"); + + return ttbr1_el1; +} + +void raw_write_ttbr1_el1(uint64_t ttbr1_el1) +{ + __asm__ __volatile__("msr TTBR1_EL1, %0\n\t" : : "r" (ttbr1_el1) : "memory"); +} + +/* VBAR */ +uint64_t raw_read_vbar_el1(void) +{ + uint64_t vbar_el1; + + __asm__ __volatile__("mrs %0, VBAR_EL1\n\t" : "=r" (vbar_el1) : : "memory"); + + return vbar_el1; +} + +void raw_write_vbar_el1(uint64_t vbar_el1) +{ + __asm__ __volatile__("msr VBAR_EL1, %0\n\t" : : "r" (vbar_el1) : "memory"); +} + +uint64_t raw_read_vbar_el2(void) +{ + uint64_t vbar_el2; + + __asm__ __volatile__("mrs %0, VBAR_EL2\n\t" : "=r" (vbar_el2) : : "memory"); + + return vbar_el2; +} + +void raw_write_vbar_el2(uint64_t vbar_el2) +{ + __asm__ __volatile__("msr VBAR_EL2, %0\n\t" : : "r" (vbar_el2) : "memory"); +} + +uint64_t raw_read_vbar_el3(void) +{ + uint64_t vbar_el3; + + __asm__ __volatile__("mrs %0, VBAR_EL3\n\t" : "=r" (vbar_el3) : : "memory"); + + return vbar_el3; +} + +void raw_write_vbar_el3(uint64_t vbar_el3) +{ + __asm__ __volatile__("msr VBAR_EL3, %0\n\t" : : "r" (vbar_el3) : "memory"); +} + +uint64_t raw_read_vbar_current(void) +{ + SWITCH_CASE_READ(raw_read_vbar,vbar,uint64_t); +} + +void raw_write_vbar_current(uint64_t vbar) +{ + SWITCH_CASE_WRITE(raw_write_vbar,vbar); +} diff --git a/payloads/libpayload/arch/arm64/lib/tlb.c b/payloads/libpayload/arch/arm64/lib/tlb.c new file mode 100644 index 0000000000..d5afc1796b --- /dev/null +++ b/payloads/libpayload/arch/arm64/lib/tlb.c @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * tlb.c: System intructions for TLB maintenance. + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include + +/* TLBIALL */ +void tlbiall_el1(void) +{ + __asm__ __volatile__("tlbi alle1\n\t" : : : "memory"); +} + +void tlbiall_el2(void) +{ + __asm__ __volatile__("tlbi alle2\n\t" : : : "memory"); +} + +void tlbiall_el3(void) +{ + __asm__ __volatile__("tlbi alle3\n\t" : : : "memory"); +} + +void tlbiall_current(void) +{ + SWITCH_CASE_TLBI(tlbiall); +} + +/* TLBIALLIS */ +void tlbiallis_el1(void) +{ + __asm__ __volatile__("tlbi alle1is\n\t" : : : "memory"); +} + +void tlbiallis_el2(void) +{ + __asm__ __volatile__("tlbi alle2is\n\t" : : : "memory"); +} + +void tlbiallis_el3(void) +{ + __asm__ __volatile__("tlbi alle3is\n\t" : : : "memory"); +} + +void tlbiallis_current(void) +{ + SWITCH_CASE_TLBI(tlbiallis); +} + +/* TLBIVAA */ +void tlbivaa_el1(uint64_t va) +{ + __asm__ __volatile__("tlbi vaae1, %0\n\t" : : "r" (va) : "memory"); +} diff --git a/payloads/libpayload/arch/arm64/libpayload.ldscript b/payloads/libpayload/arch/arm64/libpayload.ldscript new file mode 100644 index 0000000000..1b4395f7b6 --- /dev/null +++ b/payloads/libpayload/arch/arm64/libpayload.ldscript @@ -0,0 +1,98 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +BASE_ADDRESS = 0x80100000; + +OUTPUT_FORMAT("elf64-littleaarch64","elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(arm64) + +ENTRY(_entry) + +HEAP_SIZE = 2*64*1024; +STACK_SIZE = 16384; + +SECTIONS +{ + . = BASE_ADDRESS; + + . = ALIGN(16); + _start = .; + + .text : { + *(.text._entry) + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + .data : { + *(.data) + *(.data.*) + } + + _edata = .; + + .bss : { + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + *(COMMON) + + /* Stack and heap */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _estack = .; + . += STACK_SIZE; + . = ALIGN(16); + _stack = .; + + _exc_estack = .; + . += STACK_SIZE; + . = ALIGN(16); + _exc_stack = .; + } + + _end = .; + + /DISCARD/ : { + *(.comment) + *(.note*) + } +} diff --git a/payloads/libpayload/arch/arm64/main.c b/payloads/libpayload/arch/arm64/main.c new file mode 100644 index 0000000000..aa02ff7289 --- /dev/null +++ b/payloads/libpayload/arch/arm64/main.c @@ -0,0 +1,150 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +unsigned int main_argc; /**< The argc value to pass to main() */ + +/** The argv value to pass to main() */ +char *main_argv[MAX_ARGC_COUNT]; + +unsigned int test_exc; + +static int test_exception(void) +{ + uint64_t *a = (uint64_t *)0xfffffffff0000000ULL; + + test_exc = 1; + + printf("%llx\n", *a); + + return 0; +} + +/* + * Func: pre_sysinfo_scan_mmu_setup + * Desc: We need to setup and enable MMU before we can go to scan coreboot + * tables. However, we are not sure what all memory regions to map. Thus, + * initializing minimum required memory ranges + */ +static void pre_sysinfo_scan_mmu_setup(void) +{ + uint64_t start = (uint64_t)&_start; + uint64_t end = (uint64_t)&_end; + + /* Memory range 1: Covers the area occupied by payload */ + mmu_presysinfo_memory_used(start, end - start); + + /* + * Memory range 2: Coreboot tables + * + * Maximum size is assumed 2 pages in case it crosses the GRANULE_SIZE + * boundary + */ + mmu_presysinfo_memory_used((uint64_t)get_cb_header_ptr(), + 2 * GRANULE_SIZE); + + mmu_presysinfo_enable(); +} + +/* + * Func: post_sysinfo_scan_mmu_setup + * Desc: Once we have scanned coreboot tables, we have complete information + * about different memory ranges. Thus, we can perform a complete mmu + * initialization. Also, this takes care of DMA area setup + */ +static void post_sysinfo_scan_mmu_setup(void) +{ + struct memrange *ranges; + uint64_t nranges; + struct mmu_ranges mmu_ranges; + struct mmu_memrange *dma_range; + + /* Get memrange info from lib_sysinfo */ + lib_sysinfo_get_memranges(&ranges, &nranges); + + /* Get memory ranges for mmu init from lib_sysinfo memrange */ + dma_range = mmu_init_ranges_from_sysinfo(ranges, nranges, &mmu_ranges); + + /* Disable mmu */ + mmu_disable(); + + /* Init mmu */ + mmu_init(&mmu_ranges); + + /* Enable mmu */ + mmu_enable(); + + /* Init dma memory */ + init_dma_memory((void *)dma_range->base, dma_range->size); +} + +/** + * This is our C entry function - set up the system + * and jump into the payload entry point. + */ +void start_main(void); +void start_main(void) +{ + extern int main(int argc, char **argv); + + pre_sysinfo_scan_mmu_setup(); + + /* Gather system information. */ + lib_get_sysinfo(); + + post_sysinfo_scan_mmu_setup(); + +#ifndef CONFIG_LP_SKIP_CONSOLE_INIT + console_init(); +#endif + + printf("ARM64: Libpayload %s\n",__func__); + exception_init(); + + test_exception(); + /* + * Any other system init that has to happen before the + * user gets control goes here. + */ + + /* + * Go to the entry point. + * In the future we may care about the return value. + */ + + (void) main(main_argc, (main_argc != 0) ? main_argv : NULL); + + /* + * Returning here will go to the _leave function to return + * us to the original context. + */ +} diff --git a/payloads/libpayload/arch/arm64/memcpy.S b/payloads/libpayload/arch/arm64/memcpy.S new file mode 100644 index 0000000000..1c8e55dea7 --- /dev/null +++ b/payloads/libpayload/arch/arm64/memcpy.S @@ -0,0 +1,189 @@ +/* Copyright (c) 2012-2013, Linaro Limited + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Linaro nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE, + DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* Assumptions: + * + * ARMv8-a, AArch64 + * Unaligned accesses + * + */ + +#define dstin x0 +#define src x1 +#define count x2 +#define tmp1 x3 +#define tmp1w w3 +#define tmp2 x4 +#define tmp2w w4 +#define tmp3 x5 +#define tmp3w w5 +#define dst x6 + +#define A_l x7 +#define A_h x8 +#define B_l x9 +#define B_h x10 +#define C_l x11 +#define C_h x12 +#define D_l x13 +#define D_h x14 + +.macro def_fn f p2align=0 +.text +.p2align \p2align +.global \f +.type \f, %function +\f: +.endm + +def_fn memcpy p2align=6 + + mov dst, dstin + cmp count, #64 + b.ge .Lcpy_not_short + cmp count, #15 + b.le .Ltail15tiny + + /* Deal with small copies quickly by dropping straight into the + * exit block. */ +.Ltail63: + /* Copy up to 48 bytes of data. At this point we only need the + * bottom 6 bits of count to be accurate. */ + ands tmp1, count, #0x30 + b.eq .Ltail15 + add dst, dst, tmp1 + add src, src, tmp1 + cmp tmp1w, #0x20 + b.eq 1f + b.lt 2f + ldp A_l, A_h, [src, #-48] + stp A_l, A_h, [dst, #-48] +1: + ldp A_l, A_h, [src, #-32] + stp A_l, A_h, [dst, #-32] +2: + ldp A_l, A_h, [src, #-16] + stp A_l, A_h, [dst, #-16] + +.Ltail15: + ands count, count, #15 + beq 1f + add src, src, count + ldp A_l, A_h, [src, #-16] + add dst, dst, count + stp A_l, A_h, [dst, #-16] +1: + ret + +.Ltail15tiny: + /* Copy up to 15 bytes of data. Does not assume additional data + being copied. */ + tbz count, #3, 1f + ldr tmp1, [src], #8 + str tmp1, [dst], #8 +1: + tbz count, #2, 1f + ldr tmp1w, [src], #4 + str tmp1w, [dst], #4 +1: + tbz count, #1, 1f + ldrh tmp1w, [src], #2 + strh tmp1w, [dst], #2 +1: + tbz count, #0, 1f + ldrb tmp1w, [src] + strb tmp1w, [dst] +1: + ret + +.Lcpy_not_short: + /* We don't much care about the alignment of DST, but we want SRC + * to be 128-bit (16 byte) aligned so that we don't cross cache line + * boundaries on both loads and stores. */ + neg tmp2, src + ands tmp2, tmp2, #15 /* Bytes to reach alignment. */ + b.eq 2f + sub count, count, tmp2 + /* Copy more data than needed; it's faster than jumping + * around copying sub-Quadword quantities. We know that + * it can't overrun. */ + ldp A_l, A_h, [src] + add src, src, tmp2 + stp A_l, A_h, [dst] + add dst, dst, tmp2 + /* There may be less than 63 bytes to go now. */ + cmp count, #63 + b.le .Ltail63 +2: + subs count, count, #128 + b.ge .Lcpy_body_large + /* Less than 128 bytes to copy, so handle 64 here and then jump + * to the tail. */ + ldp A_l, A_h, [src] + ldp B_l, B_h, [src, #16] + ldp C_l, C_h, [src, #32] + ldp D_l, D_h, [src, #48] + stp A_l, A_h, [dst] + stp B_l, B_h, [dst, #16] + stp C_l, C_h, [dst, #32] + stp D_l, D_h, [dst, #48] + tst count, #0x3f + add src, src, #64 + add dst, dst, #64 + b.ne .Ltail63 + ret + + /* Critical loop. Start at a new cache line boundary. Assuming + * 64 bytes per line this ensures the entire loop is in one line. */ + .p2align 6 +.Lcpy_body_large: + /* There are at least 128 bytes to copy. */ + ldp A_l, A_h, [src, #0] + sub dst, dst, #16 /* Pre-bias. */ + ldp B_l, B_h, [src, #16] + ldp C_l, C_h, [src, #32] + ldp D_l, D_h, [src, #48]! /* src += 64 - Pre-bias. */ +1: + stp A_l, A_h, [dst, #16] + ldp A_l, A_h, [src, #16] + stp B_l, B_h, [dst, #32] + ldp B_l, B_h, [src, #32] + stp C_l, C_h, [dst, #48] + ldp C_l, C_h, [src, #48] + stp D_l, D_h, [dst, #64]! + ldp D_l, D_h, [src, #64]! + subs count, count, #64 + b.ge 1b + stp A_l, A_h, [dst, #16] + stp B_l, B_h, [dst, #32] + stp C_l, C_h, [dst, #48] + stp D_l, D_h, [dst, #64] + add src, src, #16 + add dst, dst, #64 + 16 + tst count, #0x3f + b.ne .Ltail63 + ret + .size memcpy, .-memcpy diff --git a/payloads/libpayload/arch/arm64/memmove.S b/payloads/libpayload/arch/arm64/memmove.S new file mode 100644 index 0000000000..d79316e007 --- /dev/null +++ b/payloads/libpayload/arch/arm64/memmove.S @@ -0,0 +1,324 @@ +/* Copyright (c) 2013, Linaro Limited + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Linaro nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE, + DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* Assumptions: + * + * ARMv8-a, AArch64 + * Unaligned accesses + */ + +.macro def_fn f p2align=0 +.text +.p2align \p2align +.global \f +.type \f, %function +\f: +.endm + +/* Parameters and result. */ +#define dstin x0 +#define src x1 +#define count x2 +#define tmp1 x3 +#define tmp1w w3 +#define tmp2 x4 +#define tmp2w w4 +#define tmp3 x5 +#define tmp3w w5 +#define dst x6 + +#define A_l x7 +#define A_h x8 +#define B_l x9 +#define B_h x10 +#define C_l x11 +#define C_h x12 +#define D_l x13 +#define D_h x14 + +def_fn memmove, 6 + cmp dstin, src + b.lo .Ldownwards + add tmp1, src, count + cmp dstin, tmp1 + b.hs memcpy /* No overlap. */ + + /* Upwards move with potential overlap. + * Need to move from the tail backwards. SRC and DST point one + * byte beyond the remaining data to move. */ + add dst, dstin, count + add src, src, count + cmp count, #64 + b.ge .Lmov_not_short_up + + /* Deal with small moves quickly by dropping straight into the + * exit block. */ +.Ltail63up: + /* Move up to 48 bytes of data. At this point we only need the + * bottom 6 bits of count to be accurate. */ + ands tmp1, count, #0x30 + b.eq .Ltail15up + sub dst, dst, tmp1 + sub src, src, tmp1 + cmp tmp1w, #0x20 + b.eq 1f + b.lt 2f + ldp A_l, A_h, [src, #32] + stp A_l, A_h, [dst, #32] +1: + ldp A_l, A_h, [src, #16] + stp A_l, A_h, [dst, #16] +2: + ldp A_l, A_h, [src] + stp A_l, A_h, [dst] +.Ltail15up: + /* Move up to 15 bytes of data. Does not assume additional data + * being moved. */ + tbz count, #3, 1f + ldr tmp1, [src, #-8]! + str tmp1, [dst, #-8]! +1: + tbz count, #2, 1f + ldr tmp1w, [src, #-4]! + str tmp1w, [dst, #-4]! +1: + tbz count, #1, 1f + ldrh tmp1w, [src, #-2]! + strh tmp1w, [dst, #-2]! +1: + tbz count, #0, 1f + ldrb tmp1w, [src, #-1] + strb tmp1w, [dst, #-1] +1: + ret + +.Lmov_not_short_up: + /* We don't much care about the alignment of DST, but we want SRC + * to be 128-bit (16 byte) aligned so that we don't cross cache line + * boundaries on both loads and stores. */ + ands tmp2, src, #15 /* Bytes to reach alignment. */ + b.eq 2f + sub count, count, tmp2 + /* Move enough data to reach alignment; unlike memcpy, we have to + * be aware of the overlap, which means we can't move data twice. */ + tbz tmp2, #3, 1f + ldr tmp1, [src, #-8]! + str tmp1, [dst, #-8]! +1: + tbz tmp2, #2, 1f + ldr tmp1w, [src, #-4]! + str tmp1w, [dst, #-4]! +1: + tbz tmp2, #1, 1f + ldrh tmp1w, [src, #-2]! + strh tmp1w, [dst, #-2]! +1: + tbz tmp2, #0, 1f + ldrb tmp1w, [src, #-1]! + strb tmp1w, [dst, #-1]! +1: + + /* There may be less than 63 bytes to go now. */ + cmp count, #63 + b.le .Ltail63up +2: + subs count, count, #128 + b.ge .Lmov_body_large_up + /* Less than 128 bytes to move, so handle 64 here and then jump + * to the tail. */ + ldp A_l, A_h, [src, #-64]! + ldp B_l, B_h, [src, #16] + ldp C_l, C_h, [src, #32] + ldp D_l, D_h, [src, #48] + stp A_l, A_h, [dst, #-64]! + stp B_l, B_h, [dst, #16] + stp C_l, C_h, [dst, #32] + stp D_l, D_h, [dst, #48] + tst count, #0x3f + b.ne .Ltail63up + ret + + /* Critical loop. Start at a new Icache line boundary. Assuming + * 64 bytes per line this ensures the entire loop is in one line. */ + .p2align 6 +.Lmov_body_large_up: + /* There are at least 128 bytes to move. */ + ldp A_l, A_h, [src, #-16] + ldp B_l, B_h, [src, #-32] + ldp C_l, C_h, [src, #-48] + ldp D_l, D_h, [src, #-64]! +1: + stp A_l, A_h, [dst, #-16] + ldp A_l, A_h, [src, #-16] + stp B_l, B_h, [dst, #-32] + ldp B_l, B_h, [src, #-32] + stp C_l, C_h, [dst, #-48] + ldp C_l, C_h, [src, #-48] + stp D_l, D_h, [dst, #-64]! + ldp D_l, D_h, [src, #-64]! + subs count, count, #64 + b.ge 1b + stp A_l, A_h, [dst, #-16] + stp B_l, B_h, [dst, #-32] + stp C_l, C_h, [dst, #-48] + stp D_l, D_h, [dst, #-64]! + tst count, #0x3f + b.ne .Ltail63up + ret + + +.Ldownwards: + /* For a downwards move we can safely use memcpy provided that + * DST is more than 16 bytes away from SRC. */ + sub tmp1, src, #16 + cmp dstin, tmp1 + b.ls memcpy /* May overlap, but not critically. */ + + mov dst, dstin /* Preserve DSTIN for return value. */ + cmp count, #64 + b.ge .Lmov_not_short_down + + /* Deal with small moves quickly by dropping straight into the + * exit block. */ +.Ltail63down: + /* Move up to 48 bytes of data. At this point we only need the + * bottom 6 bits of count to be accurate. */ + ands tmp1, count, #0x30 + b.eq .Ltail15down + add dst, dst, tmp1 + add src, src, tmp1 + cmp tmp1w, #0x20 + b.eq 1f + b.lt 2f + ldp A_l, A_h, [src, #-48] + stp A_l, A_h, [dst, #-48] +1: + ldp A_l, A_h, [src, #-32] + stp A_l, A_h, [dst, #-32] +2: + ldp A_l, A_h, [src, #-16] + stp A_l, A_h, [dst, #-16] +.Ltail15down: + /* Move up to 15 bytes of data. Does not assume additional data + being moved. */ + tbz count, #3, 1f + ldr tmp1, [src], #8 + str tmp1, [dst], #8 +1: + tbz count, #2, 1f + ldr tmp1w, [src], #4 + str tmp1w, [dst], #4 +1: + tbz count, #1, 1f + ldrh tmp1w, [src], #2 + strh tmp1w, [dst], #2 +1: + tbz count, #0, 1f + ldrb tmp1w, [src] + strb tmp1w, [dst] +1: + ret + +.Lmov_not_short_down: + /* We don't much care about the alignment of DST, but we want SRC + * to be 128-bit (16 byte) aligned so that we don't cross cache line + * boundaries on both loads and stores. */ + neg tmp2, src + ands tmp2, tmp2, #15 /* Bytes to reach alignment. */ + b.eq 2f + sub count, count, tmp2 + /* Move enough data to reach alignment; unlike memcpy, we have to + * be aware of the overlap, which means we can't move data twice. */ + tbz tmp2, #3, 1f + ldr tmp1, [src], #8 + str tmp1, [dst], #8 +1: + tbz tmp2, #2, 1f + ldr tmp1w, [src], #4 + str tmp1w, [dst], #4 +1: + tbz tmp2, #1, 1f + ldrh tmp1w, [src], #2 + strh tmp1w, [dst], #2 +1: + tbz tmp2, #0, 1f + ldrb tmp1w, [src], #1 + strb tmp1w, [dst], #1 +1: + + /* There may be less than 63 bytes to go now. */ + cmp count, #63 + b.le .Ltail63down +2: + subs count, count, #128 + b.ge .Lmov_body_large_down + /* Less than 128 bytes to move, so handle 64 here and then jump + * to the tail. */ + ldp A_l, A_h, [src] + ldp B_l, B_h, [src, #16] + ldp C_l, C_h, [src, #32] + ldp D_l, D_h, [src, #48] + stp A_l, A_h, [dst] + stp B_l, B_h, [dst, #16] + stp C_l, C_h, [dst, #32] + stp D_l, D_h, [dst, #48] + tst count, #0x3f + add src, src, #64 + add dst, dst, #64 + b.ne .Ltail63down + ret + + /* Critical loop. Start at a new cache line boundary. Assuming + * 64 bytes per line this ensures the entire loop is in one line. */ + .p2align 6 +.Lmov_body_large_down: + /* There are at least 128 bytes to move. */ + ldp A_l, A_h, [src, #0] + sub dst, dst, #16 /* Pre-bias. */ + ldp B_l, B_h, [src, #16] + ldp C_l, C_h, [src, #32] + ldp D_l, D_h, [src, #48]! /* src += 64 - Pre-bias. */ +1: + stp A_l, A_h, [dst, #16] + ldp A_l, A_h, [src, #16] + stp B_l, B_h, [dst, #32] + ldp B_l, B_h, [src, #32] + stp C_l, C_h, [dst, #48] + ldp C_l, C_h, [src, #48] + stp D_l, D_h, [dst, #64]! + ldp D_l, D_h, [src, #64]! + subs count, count, #64 + b.ge 1b + stp A_l, A_h, [dst, #16] + stp B_l, B_h, [dst, #32] + stp C_l, C_h, [dst, #48] + stp D_l, D_h, [dst, #64] + add src, src, #16 + add dst, dst, #64 + 16 + tst count, #0x3f + b.ne .Ltail63down + ret + .size memmove, . - memmove diff --git a/payloads/libpayload/arch/arm64/memset.S b/payloads/libpayload/arch/arm64/memset.S new file mode 100644 index 0000000000..15ab5903f6 --- /dev/null +++ b/payloads/libpayload/arch/arm64/memset.S @@ -0,0 +1,136 @@ +/* Copyright (c) 2012-2013, Linaro Limited + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Linaro nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE, + DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +/* Assumptions: + * + * ARMv8-a, AArch64 + * Unaligned accesses + * + */ + +#define dstin x0 +#define val w1 +#define count x2 +#define tmp1 x3 +#define tmp1w w3 +#define tmp2 x4 +#define tmp2w w4 +#define zva_len_x x5 +#define zva_len w5 +#define zva_bits_x x6 + +#define A_l x7 +#define A_lw w7 +#define dst x8 +#define tmp3w w9 + +.macro def_fn f p2align=0 +.text +.p2align \p2align +.global \f +.type \f, %function +\f: +.endm + +def_fn memset p2align=6 + + mov dst, dstin /* Preserve return value. */ + ands A_lw, val, #255 + orr A_lw, A_lw, A_lw, lsl #8 + orr A_lw, A_lw, A_lw, lsl #16 + orr A_l, A_l, A_l, lsl #32 +.Ltail_maybe_long: + cmp count, #64 + b.ge .Lnot_short +.Ltail_maybe_tiny: + cmp count, #15 + b.le .Ltail15tiny +.Ltail63: + ands tmp1, count, #0x30 + b.eq .Ltail15 + add dst, dst, tmp1 + cmp tmp1w, #0x20 + b.eq 1f + b.lt 2f + stp A_l, A_l, [dst, #-48] +1: + stp A_l, A_l, [dst, #-32] +2: + stp A_l, A_l, [dst, #-16] + +.Ltail15: + and count, count, #15 + add dst, dst, count + stp A_l, A_l, [dst, #-16] /* Repeat some/all of last store. */ + ret + +.Ltail15tiny: + /* Set up to 15 bytes. Does not assume earlier memory + being set. */ + tbz count, #3, 1f + str A_l, [dst], #8 +1: + tbz count, #2, 1f + str A_lw, [dst], #4 +1: + tbz count, #1, 1f + strh A_lw, [dst], #2 +1: + tbz count, #0, 1f + strb A_lw, [dst] +1: + ret + + /* Critical loop. Start at a new cache line boundary. Assuming + * 64 bytes per line, this ensures the entire loop is in one line. */ + .p2align 6 +.Lnot_short: + neg tmp2, dst + ands tmp2, tmp2, #15 + b.eq 2f + /* Bring DST to 128-bit (16-byte) alignment. We know that there's + * more than that to set, so we simply store 16 bytes and advance by + * the amount required to reach alignment. */ + sub count, count, tmp2 + stp A_l, A_l, [dst] + add dst, dst, tmp2 + /* There may be less than 63 bytes to go now. */ + cmp count, #63 + b.le .Ltail63 +2: + sub dst, dst, #16 /* Pre-bias. */ + sub count, count, #64 +1: + stp A_l, A_l, [dst, #16] + stp A_l, A_l, [dst, #32] + stp A_l, A_l, [dst, #48] + stp A_l, A_l, [dst, #64]! + subs count, count, #64 + b.ge 1b + tst count, #0x3f + add dst, dst, #16 + b.ne .Ltail63 + ret diff --git a/payloads/libpayload/arch/arm64/mmu.c b/payloads/libpayload/arch/arm64/mmu.c new file mode 100644 index 0000000000..86d9fc5ee5 --- /dev/null +++ b/payloads/libpayload/arch/arm64/mmu.c @@ -0,0 +1,764 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* Maximum number of XLAT Tables available based on ttb buffer size */ +static unsigned int max_tables; +/* Address of ttb buffer */ +static uint64_t *xlat_addr; + +static int free_idx; +static uint8_t ttb_buffer[TTB_DEFAULT_SIZE] __attribute__((aligned(GRANULE_SIZE))); + +/* + * The usedmem_ranges is used to describe all the memory ranges that are + * actually used by payload i.e. _start -> _end in linker script and the + * coreboot tables. This is required for two purposes: + * 1) During the pre_sysinfo_scan_mmu_setup, these are the only ranges + * initialized in the page table as we do not know the entire memory map. + * 2) During the post_sysinfo_scan_mmu_setup, these ranges are used to check if + * the DMA buffer is being placed in a sane location and does not overlap any of + * the used mem ranges. + */ +static struct mmu_ranges usedmem_ranges; + +static const uint64_t level_to_addr_mask[] = { + L1_ADDR_MASK, + L2_ADDR_MASK, + L3_ADDR_MASK, +}; + +static const uint64_t level_to_addr_shift[] = { + L1_ADDR_SHIFT, + L2_ADDR_SHIFT, + L3_ADDR_SHIFT, +}; + +static void __attribute__((noreturn)) mmu_error(void) +{ + halt(); +} + +/* + * Func : get_block_attr + * Desc : Get block descriptor attributes based on the value of tag in memrange + * region + */ +static uint64_t get_block_attr(unsigned long tag) +{ + uint64_t attr; + + /* We should be in EL2(which is non-secure only) or EL1(non-secure) */ + attr = BLOCK_NS; + + /* Assuming whole memory is read-write */ + attr |= BLOCK_AP_RW; + + attr |= BLOCK_ACCESS; + + switch (tag) { + + case TYPE_NORMAL_MEM: + attr |= (BLOCK_INDEX_MEM_NORMAL << BLOCK_INDEX_SHIFT); + break; + case TYPE_DEV_MEM: + attr |= BLOCK_INDEX_MEM_DEV_NGNRNE << BLOCK_INDEX_SHIFT; + break; + case TYPE_DMA_MEM: + attr |= BLOCK_INDEX_MEM_NORMAL_NC << BLOCK_INDEX_SHIFT; + break; + } + + return attr; +} + +/* + * Func : get_index_from_addr + * Desc : Get index into table at a given level using appropriate bits from the + * base address + */ +static uint64_t get_index_from_addr(uint64_t addr, uint8_t level) +{ + uint64_t mask = level_to_addr_mask[level-1]; + uint8_t shift = level_to_addr_shift[level-1]; + + return ((addr & mask) >> shift); +} + +/* + * Func : table_desc_valid + * Desc : Check if a table entry contains valid desc + */ +static uint64_t table_desc_valid(uint64_t desc) +{ + return((desc & TABLE_DESC) == TABLE_DESC); +} + +/* + * Func : get_new_table + * Desc : Return the next free XLAT table from ttb buffer + */ +static uint64_t *get_new_table(void) +{ + uint64_t *new; + + if (free_idx >= max_tables) { + printf("ARM64 MMU: No free table\n"); + return NULL; + } + + new = (uint64_t*)((unsigned char *)xlat_addr + free_idx * GRANULE_SIZE); + free_idx++; + + memset(new, 0, GRANULE_SIZE); + + return new; +} + +/* + * Func : get_table_from_desc + * Desc : Get next level table address from table descriptor + */ +static uint64_t *get_table_from_desc(uint64_t desc) +{ + uint64_t *ptr = (uint64_t*)(desc & XLAT_TABLE_MASK); + return ptr; +} + +/* + * Func: get_next_level_table + * Desc: Check if the table entry is a valid descriptor. If not, allocate new + * table, update the entry and return the table addr. If valid, return the addr. + */ +static uint64_t *get_next_level_table(uint64_t *ptr) +{ + uint64_t desc = *ptr; + + if (!table_desc_valid(desc)) { + uint64_t *new_table = get_new_table(); + if (new_table == NULL) + return NULL; + desc = ((uint64_t)new_table) | TABLE_DESC; + *ptr = desc; + } + return get_table_from_desc(desc); +} + +/* + * Func : init_xlat_table + * Desc : Given a base address and size, it identifies the indices within + * different level XLAT tables which map the given base addr. Similar to table + * walk, except that all invalid entries during the walk are updated + * accordingly. On success, it returns the size of the block/page addressed by + * the final table. + */ +static uint64_t init_xlat_table(uint64_t base_addr, + uint64_t size, + uint64_t tag) +{ + uint64_t l1_index = get_index_from_addr(base_addr,1); + uint64_t l2_index = get_index_from_addr(base_addr,2); + uint64_t l3_index = get_index_from_addr(base_addr,3); + uint64_t *table = xlat_addr; + uint64_t desc; + uint64_t attr = get_block_attr(tag); + + /* + * L1 table lookup + * If VA has bits more than 41, lookup starts at L1 + */ + if (l1_index) { + table = get_next_level_table(&table[l1_index]); + if (!table) + return 0; + } + + /* + * L2 table lookup + * If lookup was performed at L1, L2 table addr is obtained from L1 desc + * else, lookup starts at ttbr address + */ + if (!l3_index && (size >= L2_XLAT_SIZE)) { + /* + * If block address is aligned and size is greater than or equal + * to 512MiB i.e. size addressed by each L2 entry, we can + * directly store a block desc + */ + desc = base_addr | BLOCK_DESC | attr; + table[l2_index] = desc; + /* L3 lookup is not required */ + return L2_XLAT_SIZE; + } else { + /* L2 entry stores a table descriptor */ + table = get_next_level_table(&table[l2_index]); + if (!table) + return 0; + } + + /* L3 table lookup */ + desc = base_addr | PAGE_DESC | attr; + table[l3_index] = desc; + return L3_XLAT_SIZE; +} + +/* + * Func : sanity_check + * Desc : Check if the address is aligned and size is atleast the granule size + */ +static uint64_t sanity_check(uint64_t addr, + uint64_t size) +{ + /* Address should be atleast 64 KiB aligned */ + if (addr & GRANULE_SIZE_MASK) + return 1; + + /* Size should be atleast granule size */ + if (size < GRANULE_SIZE) + return 1; + + return 0; +} + +/* + * Func : init_mmap_entry + * Desc : For each mmap entry, this function calls init_xlat_table with the base + * address. Based on size returned from init_xlat_table, base_addr is updated + * and subsequent calls are made for initializing the xlat table until the whole + * region is initialized. + */ +static void init_mmap_entry(struct mmu_memrange *r) +{ + uint64_t base_addr = r->base; + uint64_t size = r->size; + uint64_t tag = r->type; + uint64_t temp_size = size; + + while (temp_size) { + uint64_t ret; + + if (sanity_check(base_addr,temp_size)) { + printf("Libpayload: ARM64 MMU: sanity check failed\n"); + return; + } + + ret = init_xlat_table(base_addr + (size - temp_size), + temp_size, tag); + + if (ret == 0) + return; + + temp_size -= ret; + } +} + +/* + * Func : mmu_init + * Desc : Initialize mmu based on the mmu_memrange passed. ttb_buffer is used as + * the base address for xlat tables. TTB_DEFAULT_SIZE defines the max number of + * tables that can be used + * Assuming that memory 0-2GiB is device memory. + */ +uint64_t mmu_init(struct mmu_ranges *mmu_ranges) +{ + struct mmu_memrange devrange = { 0, 0x80000000, TYPE_DEV_MEM }; + + int i = 0; + + xlat_addr = (uint64_t *)&ttb_buffer; + + memset((void*)xlat_addr, 0, GRANULE_SIZE); + max_tables = (TTB_DEFAULT_SIZE >> GRANULE_SIZE_SHIFT); + free_idx = 1; + + printf("Libpayload ARM64: TTB_BUFFER: 0x%p Max Tables: %d\n", + (void*)xlat_addr, max_tables); + + init_mmap_entry(&devrange); + + for (; i < mmu_ranges->used; i++) { + init_mmap_entry(&mmu_ranges->entries[i]); + } + + printf("Libpayload ARM64: MMU init done\n"); + return 0; +} + +static uint32_t is_mmu_enabled(void) +{ + uint32_t sctlr; + + sctlr = raw_read_sctlr_current(); + + return (sctlr & SCTLR_M); +} + +/* + * Func: mmu_disable + * Desc: Invalidate caches and disable mmu + */ +void mmu_disable(void) +{ + uint32_t sctlr; + + sctlr = raw_read_sctlr_current(); + sctlr &= ~(SCTLR_C | SCTLR_M | SCTLR_I); + + tlbiall_current(); + dcache_clean_invalidate_all(); + + dsb(); + isb(); + + raw_write_sctlr_current(sctlr); + + dcache_clean_invalidate_all(); + dsb(); + isb(); +} + +/* + * Func: mmu_enable + * Desc: Initialize MAIR, TCR, TTBR and enable MMU by setting appropriate bits + * in SCTLR + */ +void mmu_enable(void) +{ + uint32_t sctlr; + + /* Initialize MAIR indices */ + raw_write_mair_current(MAIR_ATTRIBUTES); + + /* Invalidate TLBs */ + tlbiall_current(); + + /* Initialize TCR flags */ + raw_write_tcr_current(TCR_TOSZ | TCR_IRGN0_NM_WBWAC | TCR_ORGN0_NM_WBWAC | + TCR_SH0_IS | TCR_TG0_64KB | TCR_PS_64GB | + TCR_TBI_USED); + + /* Initialize TTBR */ + raw_write_ttbr0_current((uintptr_t)xlat_addr); + + /* Ensure all translation table writes are committed before enabling MMU */ + dsb(); + isb(); + + /* Enable MMU */ + sctlr = raw_read_sctlr_current(); + sctlr |= SCTLR_C | SCTLR_M | SCTLR_I; + raw_write_sctlr_current(sctlr); + + isb(); + + if(is_mmu_enabled()) + printf("ARM64: MMU enable done\n"); + else + printf("ARM64: MMU enable failed\n"); +} + +/* + * Func: mmu_add_memrange + * Desc: Adds a new memory range + */ +static struct mmu_memrange *mmu_add_memrange(struct mmu_ranges *r, + uint64_t base, uint64_t size, + uint64_t type) +{ + struct mmu_memrange *curr = NULL; + int i = r->used; + + if (i < ARRAY_SIZE(r->entries)) { + curr = &r->entries[i]; + curr->base = base; + curr->size = size; + curr->type = type; + + r->used = i + 1; + } + + return curr; +} + +/* Structure to define properties of new memrange request */ +struct mmu_new_range_prop { + /* Type of memrange */ + uint64_t type; + /* Size of the range */ + uint64_t size; + /* + * If any restrictions on the max addr limit(This addr is exclusive for + * the range), else 0 + */ + uint64_t lim_excl; + /* If any restrictions on alignment of the range base, else 0 */ + uint64_t align; + /* + * Function to test whether selected range is fine. + * NULL=any range is fine + * Return value 1=valid range, 0=otherwise + */ + int (*is_valid_range)(uint64_t, uint64_t); + /* From what type of source range should this range be extracted */ + uint64_t src_type; +}; + +/* + * Func: mmu_is_range_free + * Desc: We need to ensure that the new range being allocated doesnt overlap + * with any used memory range. Basically: + * 1. Memory ranges used by the payload (usedmem_ranges) + * 2. Any area that falls below _end symbol in linker script (Kernel needs to be + * loaded in lower areas of memory, So, the payload linker script can have + * kernel memory below _start and _end. Thus, we want to make sure we do not + * step in those areas as well. + * Returns: 1 on success, 0 on error + * ASSUMPTION: All the memory used by payload resides below the program + * proper. If there is any memory used above the _end symbol, then it should be + * marked as used memory in usedmem_ranges during the presysinfo_scan. + */ +static int mmu_is_range_free(uint64_t r_base, + uint64_t r_end) +{ + uint64_t payload_end = (uint64_t)&_end; + uint64_t i; + struct mmu_memrange *r = &usedmem_ranges.entries[0]; + + /* Allocate memranges only above payload */ + if ((r_base <= payload_end) || (r_end <= payload_end)) + return 0; + + for (i = 0; i < usedmem_ranges.used; i++) { + uint64_t start = r[i].base; + uint64_t end = start + r[i].size; + + if (((r_base >= start) && (r_base <= end)) || + ((r_end >= start) && (r_end <= end))) + return 0; + } + + return 1; +} + +/* + * Func: mmu_get_new_range + * Desc: Add a requested new memrange. We take as input set of all memranges and + * a structure to define the new memrange properties i.e. its type, size, + * max_addr it can grow upto, alignment restrictions, source type to take range + * from and finally a function pointer to check if the chosen range is valid. + */ +static struct mmu_memrange *mmu_get_new_range(struct mmu_ranges *mmu_ranges, + struct mmu_new_range_prop *new) +{ + int i = 0; + struct mmu_memrange *r = &mmu_ranges->entries[0]; + + if (new->size == 0) { + printf("MMU Error: Invalid range size\n"); + return NULL; + } + + for (; i < mmu_ranges->used; i++) { + + if ((r[i].type != new->src_type) || + (r[i].size < new->size) || + (new->lim_excl && (r[i].base >= new->lim_excl))) + continue; + + uint64_t base_addr; + uint64_t range_end_addr = r[i].base + r[i].size; + uint64_t end_addr = range_end_addr; + + /* Make sure we do not go above max if it is non-zero */ + if (new->lim_excl && (end_addr >= new->lim_excl)) + end_addr = new->lim_excl; + + while (1) { + /* + * In case of alignment requirement, + * if end_addr is aligned, then base_addr will be too. + */ + if (new->align) + end_addr = ALIGN_DOWN(end_addr, new->align); + + base_addr = end_addr - new->size; + + if (base_addr < r[i].base) + break; + + /* + * If the selected range is not used and valid for the + * user, move ahead with it + */ + if (mmu_is_range_free(base_addr, end_addr) && + ((new->is_valid_range == NULL) || + new->is_valid_range(base_addr, end_addr))) + break; + + /* Drop to the next address. */ + end_addr -= 1; + } + + if (base_addr < r[i].base) + continue; + + if (end_addr != range_end_addr) { + /* Add a new memrange since we split up one + * range crossing the 4GiB boundary or doing an + * ALIGN_DOWN on end_addr. + */ + r[i].size -= (range_end_addr - end_addr); + if (mmu_add_memrange(mmu_ranges, end_addr, + range_end_addr - end_addr, + r[i].type) == NULL) + mmu_error(); + } + + if (r[i].size == new->size) { + r[i].type = new->type; + return &r[i]; + } + + r[i].size -= new->size; + + r = mmu_add_memrange(mmu_ranges, base_addr, new->size, + new->type); + + if (r == NULL) + mmu_error(); + + return r; + } + + /* Should never reach here if everything went fine */ + printf("ARM64 ERROR: No region allocated\n"); + return NULL; +} + +/* + * Func: mmu_alloc_range + * Desc: Call get_new_range to get a new memrange which is unused and mark it as + * used to avoid same range being allocated for different purposes. + */ +static struct mmu_memrange *mmu_alloc_range(struct mmu_ranges *mmu_ranges, + struct mmu_new_range_prop *p) +{ + struct mmu_memrange *r = mmu_get_new_range(mmu_ranges, p); + + if (r == NULL) + return NULL; + + /* + * Mark this memrange as used memory. Important since function + * can be called multiple times and we do not want to reuse some + * range already allocated. + */ + if (mmu_add_memrange(&usedmem_ranges, r->base, r->size, r->type) + == NULL) + mmu_error(); + + return r; +} + +/* + * Func: mmu_add_dma_range + * Desc: Add a memrange for dma operations. This is special because we want to + * initialize this memory as non-cacheable. We have a constraint that the DMA + * buffer should be below 4GiB(32-bit only). So, we lookup a TYPE_NORMAL_MEM + * from the lowest available addresses and align it to page size i.e. 64KiB. + */ +static struct mmu_memrange *mmu_add_dma_range(struct mmu_ranges *mmu_ranges) +{ + struct mmu_new_range_prop prop; + + prop.type = TYPE_DMA_MEM; + /* DMA_DEFAULT_SIZE is multiple of GRANULE_SIZE */ + assert((DMA_DEFAULT_SIZE % GRANULE_SIZE) == 0); + prop.size = DMA_DEFAULT_SIZE; + prop.lim_excl = MIN_64_BIT_ADDR; + prop.align = GRANULE_SIZE; + prop.is_valid_range = NULL; + prop.src_type = TYPE_NORMAL_MEM; + + return mmu_alloc_range(mmu_ranges, &prop); +} + +static struct mmu_memrange *_mmu_add_fb_range( + uint32_t size, + struct mmu_ranges *mmu_ranges) +{ + struct mmu_new_range_prop prop; + + prop.type = TYPE_DMA_MEM; + + /* make sure to allocate a size of multiple of GRANULE_SIZE */ + size = ALIGN_UP(size, GRANULE_SIZE); + prop.size = size; + prop.lim_excl = MIN_64_BIT_ADDR; + prop.align = MB_SIZE; + prop.is_valid_range = NULL; + prop.src_type = TYPE_NORMAL_MEM; + + return mmu_alloc_range(mmu_ranges, &prop); +} + +/* + * Func: mmu_extract_ranges + * Desc: Assumption is that coreboot tables have memranges in sorted + * order. So, if there is an opportunity to combine ranges, we do that as + * well. Memranges are initialized for both CB_MEM_RAM and CB_MEM_TABLE as + * TYPE_NORMAL_MEM. + */ +static void mmu_extract_ranges(struct memrange *cb_ranges, + uint64_t ncb, + struct mmu_ranges *mmu_ranges) +{ + int i = 0; + struct mmu_memrange *prev_range = NULL; + + /* Extract memory ranges to be mapped */ + for (; i < ncb; i++) { + switch (cb_ranges[i].type) { + case CB_MEM_RAM: + case CB_MEM_TABLE: + if (prev_range && (prev_range->base + prev_range->size + == cb_ranges[i].base)) { + prev_range->size += cb_ranges[i].size; + } else { + prev_range = mmu_add_memrange(mmu_ranges, + cb_ranges[i].base, + cb_ranges[i].size, + TYPE_NORMAL_MEM); + if (prev_range == NULL) + mmu_error(); + } + break; + default: + break; + } + } +} + +static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges) +{ + struct mmu_memrange *fb_range; + static struct cb_framebuffer modified_fb; + struct cb_framebuffer *framebuffer = lib_sysinfo.framebuffer; + uint32_t fb_size; + + /* + * Check whether framebuffer is needed + * or framebuffer address has been set already + */ + if (framebuffer == NULL) + return; + if (framebuffer->physical_address) + return; + fb_size = framebuffer->bytes_per_line * framebuffer->y_resolution; + if (!fb_size) + return; + + /* Allocate framebuffer */ + fb_range = _mmu_add_fb_range(fb_size, mmu_ranges); + if (fb_range == NULL) + mmu_error(); + + /* + * Set framebuffer address. However, one needs to use a freshly + * allocated framebuffer structure because the one in the coreboot + * table is part of a checksum calculation. Therefore, one cannot + * modify a field without recomputing the necessary checksum + * calcuation. + */ + modified_fb = *framebuffer; + modified_fb.physical_address = fb_range->base; + lib_sysinfo.framebuffer = &modified_fb; +} + +/* + * Func: mmu_init_ranges + * Desc: Initialize mmu_memranges based on the memranges obtained from coreboot + * tables. Also, initialize dma memrange and xlat_addr for ttb buffer. + */ +struct mmu_memrange *mmu_init_ranges_from_sysinfo(struct memrange *cb_ranges, + uint64_t ncb, + struct mmu_ranges *mmu_ranges) +{ + struct mmu_memrange *dma_range; + + /* Initialize mmu_ranges to contain no entries. */ + mmu_ranges->used = 0; + + /* Extract ranges from memrange in lib_sysinfo */ + mmu_extract_ranges(cb_ranges, ncb, mmu_ranges); + + /* Get a range for dma */ + dma_range = mmu_add_dma_range(mmu_ranges); + + /* Get a range for framebuffer */ + mmu_add_fb_range(mmu_ranges); + + if (dma_range == NULL) + mmu_error(); + + return dma_range; +} + +/* + * Func: mmu_presysinfo_memory_used + * Desc: Initializes all the memory used for presysinfo page table + * initialization and enabling of MMU. All these ranges are stored in + * usedmem_ranges. usedmem_ranges plays an important role in selecting the dma + * buffer as well since we check the dma buffer range against the used memory + * ranges to prevent any overstepping. + */ +void mmu_presysinfo_memory_used(uint64_t base, uint64_t size) +{ + uint64_t range_base; + + range_base = ALIGN_DOWN(base, GRANULE_SIZE); + + size += (base - range_base); + size = ALIGN_UP(size, GRANULE_SIZE); + + mmu_add_memrange(&usedmem_ranges, range_base, size, TYPE_NORMAL_MEM); +} + +void mmu_presysinfo_enable(void) +{ + mmu_init(&usedmem_ranges); + mmu_enable(); +} diff --git a/payloads/libpayload/arch/arm64/selfboot.c b/payloads/libpayload/arch/arm64/selfboot.c new file mode 100644 index 0000000000..5c3e4459e9 --- /dev/null +++ b/payloads/libpayload/arch/arm64/selfboot.c @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +void selfboot(void *entry) +{ + void (*entry_func)(void) = entry; + entry_func(); +} diff --git a/payloads/libpayload/arch/powerpc/sysinfo.c b/payloads/libpayload/arch/arm64/sysinfo.c similarity index 82% rename from payloads/libpayload/arch/powerpc/sysinfo.c rename to payloads/libpayload/arch/arm64/sysinfo.c index 6c1ef3fc1c..28d3c4be55 100644 --- a/payloads/libpayload/arch/powerpc/sysinfo.c +++ b/payloads/libpayload/arch/arm64/sysinfo.c @@ -30,7 +30,6 @@ #include #include #include -#include /** * This is a global structure that is used through the library - we set it @@ -38,11 +37,6 @@ */ struct sysinfo_t lib_sysinfo = { .cpu_khz = 200, -#ifdef CONFIG_SERIAL_CONSOLE - .ser_ioport = CONFIG_SERIAL_IOBASE, -#else - .ser_ioport = 0x3f8, -#endif }; int lib_get_sysinfo(void) @@ -52,12 +46,6 @@ int lib_get_sysinfo(void) /* Get the CPU speed (for delays). */ lib_sysinfo.cpu_khz = get_cpu_speed(); -#ifdef CONFIG_MULTIBOOT - /* Get the information from the multiboot tables, - * if they exist */ - get_multiboot_info(&lib_sysinfo); -#endif - /* Get information from the coreboot tables, * if they exist */ @@ -65,16 +53,19 @@ int lib_get_sysinfo(void) if (!lib_sysinfo.n_memranges) { /* If we can't get a good memory range, use the default. */ - lib_sysinfo.n_memranges = 2; + lib_sysinfo.n_memranges = 1; lib_sysinfo.memrange[0].base = 0; - lib_sysinfo.memrange[0].size = 640 * 1024; + lib_sysinfo.memrange[0].size = 1024 * 1024; lib_sysinfo.memrange[0].type = CB_MEM_RAM; - - lib_sysinfo.memrange[1].base = 1024 * 1024; - lib_sysinfo.memrange[1].size = 31 * 1024 * 1024; - lib_sysinfo.memrange[1].type = CB_MEM_RAM; } return ret; } + +void lib_sysinfo_get_memranges(struct memrange **ranges, + uint64_t *nranges) +{ + *ranges = &lib_sysinfo.memrange[0]; + *nranges = lib_sysinfo.n_memranges; +} diff --git a/payloads/libpayload/arch/powerpc/timer.c b/payloads/libpayload/arch/arm64/timer.c similarity index 90% rename from payloads/libpayload/arch/powerpc/timer.c rename to payloads/libpayload/arch/arm64/timer.c index fb181a4d63..4587f31ae7 100644 --- a/payloads/libpayload/arch/powerpc/timer.c +++ b/payloads/libpayload/arch/arm64/timer.c @@ -28,8 +28,8 @@ */ /** - * @file i386/timer.c - * i386 specific timer routines + * @file arm64/timer.c + * ARM64 specific timer routines */ #include @@ -48,18 +48,7 @@ u32 cpu_khz; unsigned int get_cpu_speed(void) { /* FIXME */ - cpu_khz = 200 * 1024; + cpu_khz = 1000000U; + return cpu_khz; } - -uint64_t timer_hz(void) -{ - /* FIXME */ - return 0; -} - -uint64_t timer_raw_value(void) -{ - /* FIXME */ - return 0; -} diff --git a/payloads/libpayload/arch/powerpc/util.S b/payloads/libpayload/arch/arm64/util.S similarity index 92% rename from payloads/libpayload/arch/powerpc/util.S rename to payloads/libpayload/arch/arm64/util.S index 2905be7d8c..7c14a39a4f 100644 --- a/payloads/libpayload/arch/powerpc/util.S +++ b/payloads/libpayload/arch/arm64/util.S @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2012 Google, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,14 +27,9 @@ * SUCH DAMAGE. */ - .globl halt - .text - .align 4 +#include /* This function puts the system into a halt. */ -halt: -#if 0 - cli - hlt - jmp halt -#endif +ENTRY(halt) + b halt +ENDPROC(halt) diff --git a/payloads/libpayload/arch/armv7/virtual.c b/payloads/libpayload/arch/arm64/virtual.c similarity index 100% rename from payloads/libpayload/arch/armv7/virtual.c rename to payloads/libpayload/arch/arm64/virtual.c diff --git a/payloads/libpayload/arch/armv7/cache.c b/payloads/libpayload/arch/armv7/cache.c deleted file mode 100644 index 9fac442f17..0000000000 --- a/payloads/libpayload/arch/armv7/cache.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R - * - * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition - */ - -#include - -#include - -#define bitmask(high, low) ((1UL << (high)) + \ - ((1UL << (high)) - 1) - ((1UL << (low)) - 1)) - -/* Basic log2() implementation. Note: log2(0) is 0 for our purposes. */ -/* FIXME: src/include/lib.h is difficult to work with due to romcc */ -static unsigned long log2(unsigned long u) -{ - int i = 0; - - while (u >>= 1) - i++; - - return i; -} - -void tlb_invalidate_all(void) -{ - /* - * FIXME: ARMv7 Architecture Ref. Manual claims that the distinction - * instruction vs. data TLBs is deprecated in ARMv7, however this does - * not seem to be the case as of Cortex-A15. - */ - tlbiall(); - dtlbiall(); - itlbiall(); - isb(); - dsb(); -} - -void icache_invalidate_all(void) -{ - /* - * icache can be entirely invalidated with one operation. - * Note: If branch predictors are architecturally-visible, ICIALLU - * also performs a BPIALL operation (B2-1283 in arch manual) - */ - iciallu(); - isb(); -} - -enum dcache_op { - OP_DCCISW, - OP_DCISW, - OP_DCCIMVAC, - OP_DCCMVAC, -}; - -/* - * Do a dcache operation on entire cache by set/way. This is done for - * portability because mapping of memory address to cache location is - * implementation defined (See note on "Requirements for operations by - * set/way" in arch ref. manual). - */ -static void dcache_op_set_way(enum dcache_op op) -{ - uint32_t ccsidr; - unsigned int associativity, num_sets, linesize_bytes; - unsigned int set, way; - unsigned int level; - - level = (read_csselr() >> 1) & 0x7; - - /* - * dcache must be invalidated by set/way for portability since virtual - * memory mapping is system-defined. The number of sets and - * associativity is given by CCSIDR. We'll use DCISW to invalidate the - * dcache. - */ - ccsidr = read_ccsidr(); - - /* FIXME: rounding up required here? */ - num_sets = ((ccsidr & bitmask(27, 13)) >> 13) + 1; - associativity = ((ccsidr & bitmask(12, 3)) >> 3) + 1; - /* FIXME: do we need to use CTR.DminLine here? */ - linesize_bytes = (1 << ((ccsidr & 0x7) + 2)) * 4; - - dsb(); - - /* - * Set/way operations require an interesting bit packing. See section - * B4-35 in the ARMv7 Architecture Reference Manual: - * - * A: Log2(associativity) - * B: L+S - * L: Log2(linesize) - * S: Log2(num_sets) - * - * The bits are packed as follows: - * 31 31-A B B-1 L L-1 4 3 1 0 - * |---|-------------|--------|-------|-----|-| - * |Way| zeros | Set | zeros |level|0| - * |---|-------------|--------|-------|-----|-| - */ - for (way = 0; way < associativity; way++) { - for (set = 0; set < num_sets; set++) { - uint32_t val = 0; - val |= way << (32 - log2(associativity)); - val |= set << log2(linesize_bytes); - val |= level << 1; - switch(op) { - case OP_DCCISW: - dccisw(val); - break; - case OP_DCISW: - dcisw(val); - break; - default: - break; - } - } - } - isb(); -} - -void dcache_clean_invalidate_all(void) -{ - dcache_op_set_way(OP_DCCISW); -} - -void dcache_invalidate_all(void) -{ - dcache_op_set_way(OP_DCISW); -} - -static unsigned int line_bytes(void) -{ - uint32_t ccsidr; - unsigned int size; - - ccsidr = read_ccsidr(); - /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ - size = 1 << ((ccsidr & 0x7) + 2); /* words per line */ - size *= sizeof(unsigned int); /* bytes per line */ - - return size; -} - -/* - * Do a dcache operation by modified virtual address. This is useful for - * maintaining coherency in drivers which do DMA transfers and only need to - * perform cache maintenance on a particular memory range rather than the - * entire cache. - */ -static void dcache_op_mva(unsigned long addr, - unsigned long len, enum dcache_op op) -{ - unsigned long line, linesize; - - linesize = line_bytes(); - line = addr & ~(linesize - 1); - - dsb(); - while (line < addr + len) { - switch(op) { - case OP_DCCIMVAC: - dccimvac(line); - break; - default: - break; - } - line += linesize; - } - isb(); -} - -void dcache_clean_by_mva(unsigned long addr, unsigned long len) -{ - dcache_op_mva(addr, len, OP_DCCMVAC); -} - -void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len) -{ - dcache_op_mva(addr, len, OP_DCCIMVAC); -} - -void dcache_mmu_disable(void) -{ - uint32_t sctlr, csselr; - - /* ensure L1 data/unified cache is selected */ - csselr = read_csselr(); - csselr &= ~0xf; - write_csselr(csselr); - - dcache_clean_invalidate_all(); - - sctlr = read_sctlr(); - sctlr &= ~(SCTLR_C | SCTLR_M); - write_sctlr(sctlr); -} - - -void dcache_mmu_enable(void) -{ - uint32_t sctlr; - - sctlr = read_sctlr(); - dcache_clean_invalidate_all(); - sctlr |= SCTLR_C | SCTLR_M; - write_sctlr(sctlr); -} - -void armv7_invalidate_caches(void) -{ - uint32_t clidr; - int level; - - /* Invalidate branch predictor */ - bpiall(); - - /* Iterate thru each cache identified in CLIDR and invalidate */ - clidr = read_clidr(); - for (level = 0; level < 7; level++) { - unsigned int ctype = (clidr >> (level * 3)) & 0x7; - uint32_t csselr; - - switch(ctype) { - case 0x0: - /* no cache */ - break; - case 0x1: - /* icache only */ - csselr = (level << 1) | 1; - write_csselr(csselr); - icache_invalidate_all(); - break; - case 0x2: - case 0x4: - /* dcache only or unified cache */ - dcache_invalidate_all(); - break; - case 0x3: - /* separate icache and dcache */ - csselr = (level << 1) | 1; - write_csselr(csselr); - icache_invalidate_all(); - - csselr = level < 1; - write_csselr(csselr); - dcache_invalidate_all(); - break; - default: - /* reserved */ - break; - } - } - - /* Invalidate TLB */ - tlb_invalidate_all(); -} diff --git a/payloads/libpayload/arch/armv7/memset.S b/payloads/libpayload/arch/armv7/memset.S deleted file mode 100644 index 4ff4c3ce93..0000000000 --- a/payloads/libpayload/arch/armv7/memset.S +++ /dev/null @@ -1,126 +0,0 @@ -/* - * linux/arch/arm/lib/memset.S - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include "assembler.h" - - .text - .align 5 - .word 0 - -1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 - strltb r1, [r0], #1 @ 1 - strleb r1, [r0], #1 @ 1 - strb r1, [r0], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -/* - * The pointer is now aligned and the length is adjusted. Try doing the - * memset again. - */ - -.globl memset -memset: - ands r3, r0, #3 @ 1 unaligned? - bne 1b @ 1 -/* - * we know that the pointer in r0 is aligned to a word boundary. - */ - orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - mov r3, r1 - cmp r2, #16 - blt 4f - -#if ! CALGN(1)+0 - -/* - * We need an extra register for this loop - save the return address and - * use the LR - */ - str lr, [sp, #-4]! - mov ip, r1 - mov lr, r1 - -2: subs r2, r2, #64 - stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - bgt 2b - ldmeqfd sp!, {pc} @ Now <64 bytes to go. -/* - * No need to correct the count; we're only testing bits from now on - */ - tst r2, #32 - stmneia r0!, {r1, r3, ip, lr} - stmneia r0!, {r1, r3, ip, lr} - tst r2, #16 - stmneia r0!, {r1, r3, ip, lr} - ldr lr, [sp], #4 - -#else - -/* - * This version aligns the destination pointer in order to write - * whole cache lines at once. - */ - - stmfd sp!, {r4-r7, lr} - mov r4, r1 - mov r5, r1 - mov r6, r1 - mov r7, r1 - mov ip, r1 - mov lr, r1 - - cmp r2, #96 - tstgt r0, #31 - ble 3f - - and ip, r0, #31 - rsb ip, ip, #32 - sub r2, r2, ip - movs ip, ip, lsl #(32 - 4) - stmcsia r0!, {r4, r5, r6, r7} - stmmiia r0!, {r4, r5} - tst ip, #(1 << 30) - mov ip, r1 - strne r1, [r0], #4 - -3: subs r2, r2, #64 - stmgeia r0!, {r1, r3-r7, ip, lr} - stmgeia r0!, {r1, r3-r7, ip, lr} - bgt 3b - ldmeqfd sp!, {r4-r7, pc} - - tst r2, #32 - stmneia r0!, {r1, r3-r7, ip, lr} - tst r2, #16 - stmneia r0!, {r4-r7} - ldmfd sp!, {r4-r7, lr} - -#endif - -4: tst r2, #8 - stmneia r0!, {r1, r3} - tst r2, #4 - strne r1, [r0], #4 -/* - * When we get here, we've got less than 4 bytes to zero. We - * may have an unaligned pointer as well. - */ -5: tst r2, #2 - strneb r1, [r0], #1 - strneb r1, [r0], #1 - tst r2, #1 - strneb r1, [r0], #1 - mov pc, lr diff --git a/payloads/libpayload/arch/powerpc/coreboot.c b/payloads/libpayload/arch/powerpc/coreboot.c deleted file mode 100644 index 7da87ed2f2..0000000000 --- a/payloads/libpayload/arch/powerpc/coreboot.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2009 coresystems GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -/* - * Some of this is x86 specific, and the rest of it is generic. Right now, - * since we only support x86, we'll avoid trying to make lots of infrastructure - * we don't need. If in the future, we want to use coreboot on some other - * architecture, then take out the generic parsing code and move it elsewhere. - */ - -/* === Parsing code === */ -/* This is the generic parsing code. */ - -static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_memory *mem = (struct cb_memory *)ptr; - int count = MEM_RANGE_COUNT(mem); - int i; - - if (count > SYSINFO_MAX_MEM_RANGES) - count = SYSINFO_MAX_MEM_RANGES; - - info->n_memranges = 0; - - for (i = 0; i < count; i++) { - struct cb_memory_range *range = - (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); - -#ifdef CONFIG_MEMMAP_RAM_ONLY - if (range->type != CB_MEM_RAM) - continue; -#endif - - info->memrange[info->n_memranges].base = - UNPACK_CB64(range->start); - - info->memrange[info->n_memranges].size = - UNPACK_CB64(range->size); - - info->memrange[info->n_memranges].type = range->type; - - info->n_memranges++; - } -} - -static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_serial *ser = (struct cb_serial *)ptr; - if (ser->type != CB_SERIAL_TYPE_IO_MAPPED) - return; - info->ser_ioport = ser->baseaddr; -} - -#ifdef CONFIG_NVRAM -static void cb_parse_optiontable(unsigned char *ptr, struct sysinfo_t *info) -{ - info->option_table = (struct cb_cmos_option_table *)ptr; -} - -static void cb_parse_checksum(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cmos_checksum *cmos_cksum = (struct cb_cmos_checksum *)ptr; - info->cmos_range_start = cmos_cksum->range_start; - info->cmos_range_end = cmos_cksum->range_end; - info->cmos_checksum_location = cmos_cksum->location; -} -#endif - -static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) -{ - struct cb_header *header; - unsigned char *ptr = (unsigned char *)addr; - int i; - - for (i = 0; i < len; i += 16, ptr += 16) { - header = (struct cb_header *)ptr; - if (!strncmp((const char *)header->signature, "LBIO", 4)) - break; - } - - /* We walked the entire space and didn't find anything. */ - if (i >= len) - return -1; - - if (!header->table_bytes) - return 0; - - /* Make sure the checksums match. */ - if (ipchksum((u16 *) header, sizeof(*header)) != 0) - return -1; - - if (ipchksum((u16 *) (ptr + sizeof(*header)), - header->table_bytes) != header->table_checksum) - return -1; - - /* Now, walk the tables. */ - ptr += header->header_bytes; - - for (i = 0; i < header->table_entries; i++) { - struct cb_record *rec = (struct cb_record *)ptr; - - /* We only care about a few tags here (maybe more later). */ - switch (rec->tag) { - case CB_TAG_FORWARD: - return cb_parse_header((void *)(unsigned long)((struct cb_forward *)rec)->forward, len, info); - continue; - case CB_TAG_MEMORY: - cb_parse_memory(ptr, info); - break; - case CB_TAG_SERIAL: - cb_parse_serial(ptr, info); - break; -#ifdef CONFIG_NVRAM - case CB_TAG_CMOS_OPTION_TABLE: - cb_parse_optiontable(ptr, info); - break; - case CB_TAG_OPTION_CHECKSUM: - cb_parse_checksum(ptr, info); - break; -#endif - } - - ptr += rec->size; - } - - return 1; -} - -/* == Architecture specific == */ -/* This is the x86 specific stuff. */ - -int get_coreboot_info(struct sysinfo_t *info) -{ - int ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info); - - if (ret != 1) - ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info); - - return (ret == 1) ? 0 : -1; -} diff --git a/payloads/libpayload/arch/powerpc/exec.S b/payloads/libpayload/arch/powerpc/exec.S deleted file mode 100644 index 45672cba3e..0000000000 --- a/payloads/libpayload/arch/powerpc/exec.S +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* calling syntax: i386_do_exec(long addr, int argc, char **argv, int *ret) */ - -/* This implements the payload API detailed here: - * http://www.coreboot.org/Payload_API - */ - -.align 4 -.text - -.globl powerpc_do_exec - .type powerpc_do_exec,@function - -powerpc_do_exec: -#if 0 - pushl %ebp - movl %esp, %ebp - pushl %eax - - /* Put the run address in %eax */ - movl 8(%ebp), %eax - - /* Save off the rest of the registers */ - - pushl %esi - pushl %ecx - pushl %ebp - - /* Push the argc and argv pointers on to the stack */ - - movl 12(%ebp), %esi - movl 16(%ebp), %ecx - - pushl %esi - pushl %ecx - - /* Move a "magic" number on the stack - the other - * payload will use this as a clue that the argc - * and argv are sane - */ - - movl $12345678, %ecx - pushl %ecx - - /* Jump to the code */ - call *%eax - - /* %eax has the return value */ - - /* Skip over the argc/argv stuff still on the stack */ - addl $12, %esp - - /* Get back %ebp */ - popl %ebp - - /* Get the pointer to the return value - * and save the return value in it - */ - - movl 20(%ebp), %ecx - movl %eax, (%eax) - - /* Get the rest of the saved registers */ - popl %ecx - popl %esi - popl %eax - - /* Restore the stack pointer */ - movl %ebp,%esp - popl %ebp - ret -#endif diff --git a/payloads/libpayload/arch/x86/Makefile.inc b/payloads/libpayload/arch/x86/Makefile.inc index 0977eb1638..87b3e9e842 100644 --- a/payloads/libpayload/arch/x86/Makefile.inc +++ b/payloads/libpayload/arch/x86/Makefile.inc @@ -31,9 +31,15 @@ head.o-y += head.S libc-y += main.c sysinfo.c libc-y += timer.c coreboot.c util.S libc-y += exec.S virtual.c -libc-y += string.c +libc-y += selfboot.c +libc-y += exception_asm.S exception.c -libcbfs-$(CONFIG_CBFS) += rom_media.c +# Will fall back to default_memXXX() in libc/memory.c if GPL not allowed. +libc-$(CONFIG_LP_GPL) += string.c + +libgdb-y += gdb.c + +libcbfs-$(CONFIG_LP_CBFS) += rom_media.c # Multiboot support is configurable -libc-$(CONFIG_MULTIBOOT) += multiboot.c +libc-$(CONFIG_LP_MULTIBOOT) += multiboot.c diff --git a/payloads/libpayload/arch/x86/coreboot.c b/payloads/libpayload/arch/x86/coreboot.c index 6c6122d26c..3a9eb1a7be 100644 --- a/payloads/libpayload/arch/x86/coreboot.c +++ b/payloads/libpayload/arch/x86/coreboot.c @@ -42,265 +42,33 @@ /* === Parsing code === */ /* This is the generic parsing code. */ -static void cb_parse_memory(void *ptr, struct sysinfo_t *info) -{ - struct cb_memory *mem = ptr; - int count = MEM_RANGE_COUNT(mem); - int i; - - if (count > SYSINFO_MAX_MEM_RANGES) - count = SYSINFO_MAX_MEM_RANGES; - - info->n_memranges = 0; - - for (i = 0; i < count; i++) { - struct cb_memory_range *range = MEM_RANGE_PTR(mem, i); - -#ifdef CONFIG_MEMMAP_RAM_ONLY - if (range->type != CB_MEM_RAM) - continue; -#endif - - info->memrange[info->n_memranges].base = - cb_unpack64(range->start); - - info->memrange[info->n_memranges].size = - cb_unpack64(range->size); - - info->memrange[info->n_memranges].type = range->type; - - info->n_memranges++; - } -} - -static void cb_parse_serial(void *ptr, struct sysinfo_t *info) -{ - info->serial = ((struct cb_serial *)ptr); -} - -#ifdef CONFIG_CHROMEOS -static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vboot_handoff *vbho = (struct cb_vboot_handoff *)ptr; - - info->vboot_handoff = vbho->vboot_handoff_addr; - info->vboot_handoff_size = vbho->vboot_handoff_size; -} - -static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; - - info->vbnv_start = vbnv->vbnv_start; - info->vbnv_size = vbnv->vbnv_size; -} - -static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) -{ - int i; - struct cb_gpios *gpios = (struct cb_gpios *)ptr; - - info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? - (gpios->count) : SYSINFO_MAX_GPIOS; - - for (i = 0; i < info->num_gpios; i++) - info->gpios[i] = gpios->gpios[i]; -} - -static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vdat *vdat = (struct cb_vdat *) ptr; - - info->vdat_addr = phys_to_virt(vdat->vdat_addr); - info->vdat_size = vdat->vdat_size; -} -#endif - -static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; - info->tstamp_table = phys_to_virt(cbmem->cbmem_tab); -} - -static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; - info->cbmem_cons = phys_to_virt(cbmem->cbmem_tab); -} - -static void cb_parse_mrc_cache(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; - info->mrc_cache = phys_to_virt(cbmem->cbmem_tab); -} - -#ifdef CONFIG_NVRAM -static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info) -{ - /* ptr points to a coreboot table entry and is already virtual */ - info->option_table = ptr; -} - -static void cb_parse_checksum(void *ptr, struct sysinfo_t *info) -{ - struct cb_cmos_checksum *cmos_cksum = ptr; - info->cmos_range_start = cmos_cksum->range_start; - info->cmos_range_end = cmos_cksum->range_end; - info->cmos_checksum_location = cmos_cksum->location; -} -#endif - -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE -static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) -{ - /* ptr points to a coreboot table entry and is already virtual */ - info->framebuffer = ptr; -} -#endif - static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info) { struct cb_x86_rom_mtrr *rom_mtrr = ptr; info->x86_rom_var_mtrr_index = rom_mtrr->index; } -static void cb_parse_string(unsigned char *ptr, char **info) +static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info) { - *info = (char *)((struct cb_string *)ptr)->string; + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + info->mrc_cache = phys_to_virt(cbmem->cbmem_tab); } -static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info) { - struct cb_header *header; - unsigned char *ptr = addr; - void *forward; - int i; - - for (i = 0; i < len; i += 16, ptr += 16) { - header = (struct cb_header *)ptr; - if (!strncmp((const char *)header->signature, "LBIO", 4)) - break; - } - - /* We walked the entire space and didn't find anything. */ - if (i >= len) - return -1; - - if (!header->table_bytes) + switch(rec->tag) { + case CB_TAG_X86_ROM_MTRR: + cb_parse_x86_rom_var_mtrr(rec, info); + break; + case CB_TAG_MRC_CACHE: + cb_parse_mrc_cache(rec, info); + break; + default: return 0; - - /* Make sure the checksums match. */ - if (ipchksum((u16 *) header, sizeof(*header)) != 0) - return -1; - - if (ipchksum((u16 *) (ptr + sizeof(*header)), - header->table_bytes) != header->table_checksum) - return -1; - - info->header = header; - - /* Now, walk the tables. */ - ptr += header->header_bytes; - - for (i = 0; i < header->table_entries; i++) { - struct cb_record *rec = (struct cb_record *)ptr; - - /* We only care about a few tags here (maybe more later). */ - switch (rec->tag) { - case CB_TAG_FORWARD: - forward = phys_to_virt((void *)(unsigned long)((struct cb_forward *)rec)->forward); - return cb_parse_header(forward, len, info); - continue; - case CB_TAG_MEMORY: - cb_parse_memory(ptr, info); - break; - case CB_TAG_SERIAL: - cb_parse_serial(ptr, info); - break; - case CB_TAG_VERSION: - cb_parse_string(ptr, &info->cb_version); - break; - case CB_TAG_EXTRA_VERSION: - cb_parse_string(ptr, &info->extra_version); - break; - case CB_TAG_BUILD: - cb_parse_string(ptr, &info->build); - break; - case CB_TAG_COMPILE_TIME: - cb_parse_string(ptr, &info->compile_time); - break; - case CB_TAG_COMPILE_BY: - cb_parse_string(ptr, &info->compile_by); - break; - case CB_TAG_COMPILE_HOST: - cb_parse_string(ptr, &info->compile_host); - break; - case CB_TAG_COMPILE_DOMAIN: - cb_parse_string(ptr, &info->compile_domain); - break; - case CB_TAG_COMPILER: - cb_parse_string(ptr, &info->compiler); - break; - case CB_TAG_LINKER: - cb_parse_string(ptr, &info->linker); - break; - case CB_TAG_ASSEMBLER: - cb_parse_string(ptr, &info->assembler); - break; -#ifdef CONFIG_NVRAM - case CB_TAG_CMOS_OPTION_TABLE: - cb_parse_optiontable(ptr, info); - break; - case CB_TAG_OPTION_CHECKSUM: - cb_parse_checksum(ptr, info); - break; -#endif -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE - // FIXME we should warn on serial if coreboot set up a - // framebuffer buf the payload does not know about it. - case CB_TAG_FRAMEBUFFER: - cb_parse_framebuffer(ptr, info); - break; -#endif - case CB_TAG_MAINBOARD: - info->mainboard = (struct cb_mainboard *)ptr; -#ifdef CONFIG_CHROMEOS - case CB_TAG_GPIO: - cb_parse_gpios(ptr, info); - break; - case CB_TAG_VDAT: - cb_parse_vdat(ptr, info); - break; - case CB_TAG_VBNV: - cb_parse_vbnv(ptr, info); - break; - case CB_TAG_VBOOT_HANDOFF: - cb_parse_vboot_handoff(ptr, info); - break; -#endif - case CB_TAG_TIMESTAMPS: - cb_parse_tstamp(ptr, info); - break; - case CB_TAG_CBMEM_CONSOLE: - cb_parse_cbmem_cons(ptr, info); - break; - case CB_TAG_MRC_CACHE: - cb_parse_mrc_cache(ptr, info); - break; - case CB_TAG_X86_ROM_MTRR: - cb_parse_x86_rom_var_mtrr(ptr, info); - break; - } - - ptr += rec->size; } - return 1; } -/* == Architecture specific == */ -/* This is the x86 specific stuff. */ - int get_coreboot_info(struct sysinfo_t *info) { int ret; @@ -311,8 +79,8 @@ int get_coreboot_info(struct sysinfo_t *info) ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info); - if (ret != 1) + if (ret) ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info); - return (ret == 1) ? 0 : -1; + return ret; } diff --git a/payloads/libpayload/arch/x86/exception.c b/payloads/libpayload/arch/x86/exception.c new file mode 100644 index 0000000000..f6bb8c9ccf --- /dev/null +++ b/payloads/libpayload/arch/x86/exception.c @@ -0,0 +1,184 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +u32 exception_stack[0x400] __attribute__((aligned(8))); + +static exception_hook hook; +static const char *names[EXC_COUNT] = { + [EXC_DE] = "Divide by Zero", + [EXC_DB] = "Debug", + [EXC_NMI] = "Non-Maskable-Interrupt", + [EXC_BP] = "Breakpoint", + [EXC_OF] = "Overflow", + [EXC_BR] = "Bound Range", + [EXC_UD] = "Invalid Opcode", + [EXC_NM] = "Device Not Available", + [EXC_DF] = "Double Fault", + [EXC_TS] = "Invalid TSS", + [EXC_NP] = "Segment Not Present", + [EXC_SS] = "Stack Fault", + [EXC_GP] = "General Protection Fault", + [EXC_PF] = "Page Fault", + [EXC_MF] = "x87 Floating Point", + [EXC_AC] = "Alignment Check", + [EXC_MC] = "Machine Check", + [EXC_XF] = "SIMD Floating Point", + [EXC_SX] = "Security", +}; + +static void print_segment_error_code(u32 code) +{ + printf("%#x - descriptor %#x in the ", code, (code >> 3) & 0x1f); + if (code & (0x1 << 1)) { + printf("IDT"); + } else { + if (code & 0x04) + printf("LDT"); + else + printf("GDT"); + } + if (code & (0x1 << 0)) + printf(", external to the CPU"); + else + printf(", internal to the CPU"); +} + +static void print_page_fault_error_code(u32 code) +{ + printf("%#x -", code); + if (code & (0x1 << 0)) + printf(" page protection"); + else + printf(" page not present"); + if (code & (0x1 << 1)) + printf(", write"); + else + printf(", read"); + if (code & (0x1 << 2)) + printf(", user"); + else + printf(", supervisor"); + if (code & (0x1 << 3)) + printf(", reserved bits set"); + if (code & (0x1 << 4)) + printf(", instruction fetch"); +} + +static void print_raw_error_code(u32 code) +{ + printf("%#x", code); +} + +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printf("Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printf("%p: ", ptr + i); + for (j = i; j < i + line; j++) + printf("%08x ", *(ptr + j)); + printf("\n"); + } +} + +static void dump_exception_state(void) +{ + printf("%s Exception\n", names[exception_state->vector]); + + printf("Error code: "); + switch (exception_state->vector) { + case EXC_PF: + print_page_fault_error_code(exception_state->error_code); + break; + case EXC_TS: + case EXC_NP: + case EXC_SS: + case EXC_GP: + print_segment_error_code(exception_state->error_code); + break; + case EXC_DF: + case EXC_AC: + case EXC_SX: + print_raw_error_code(exception_state->error_code); + break; + default: + printf("n/a"); + break; + } + printf("\n"); + printf("EIP: 0x%08x\n", exception_state->regs.eip); + printf("CS: 0x%04x\n", exception_state->regs.cs); + printf("EFLAGS: 0x%08x\n", exception_state->regs.eflags); + printf("EAX: 0x%08x\n", exception_state->regs.eax); + printf("ECX: 0x%08x\n", exception_state->regs.ecx); + printf("EDX: 0x%08x\n", exception_state->regs.edx); + printf("EBX: 0x%08x\n", exception_state->regs.ebx); + printf("ESP: 0x%08x\n", exception_state->regs.esp); + printf("EBP: 0x%08x\n", exception_state->regs.ebp); + printf("ESI: 0x%08x\n", exception_state->regs.esi); + printf("EDI: 0x%08x\n", exception_state->regs.edi); + printf("DS: 0x%04x\n", exception_state->regs.ds); + printf("ES: 0x%04x\n", exception_state->regs.es); + printf("SS: 0x%04x\n", exception_state->regs.ss); + printf("FS: 0x%04x\n", exception_state->regs.fs); + printf("GS: 0x%04x\n", exception_state->regs.gs); +} + +void exception_dispatch(void) +{ + u32 vec = exception_state->vector; + die_if(vec >= EXC_COUNT || !names[vec], "Bad exception vector %u", vec); + + if (hook && hook(vec)) + return; + + dump_exception_state(); + dump_stack(exception_state->regs.esp, 512); + halt(); +} + +void exception_init(void) +{ + exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack); + exception_init_asm(); +} + +void exception_install_hook(exception_hook h) +{ + die_if(hook, "Implement support for a list of hooks if you need it."); + hook = h; +} diff --git a/payloads/libpayload/arch/x86/exception_asm.S b/payloads/libpayload/arch/x86/exception_asm.S new file mode 100644 index 0000000000..a8f9a1d254 --- /dev/null +++ b/payloads/libpayload/arch/x86/exception_asm.S @@ -0,0 +1,296 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + .align 4 + .global exception_stack_end +exception_stack_end: + .long 0 + .global exception_state +exception_state: + .long 0 + +/* Some temporary variables which are used while saving exception state. */ +vector: + .long 0 +error_code: + .long 0 +old_esp: + .long 0 +old_eax: + .long 0 + + .align 8 + +/* + * Each exception vector has a small stub associated with it which sets aside + * the error code, if any, records which vector we entered from, and calls + * the common exception entry point. Some exceptions have error codes and some + * don't, so we have a macro for each type. + */ + + .macro stub num +exception_stub_\num: + movl $0, error_code + movl $\num, vector + jmp exception_common + .endm + + .macro stub_err num +exception_stub_\num: + popl error_code + movl $\num, vector + jmp exception_common + .endm + + stub 0 + stub 1 + stub 2 + stub 3 + stub 4 + stub 5 + stub 6 + stub 7 + stub_err 8 + stub 9 + stub_err 10 + stub_err 11 + stub_err 12 + stub_err 13 + stub_err 14 + stub 15 + stub 16 + stub_err 17 + stub 18 + stub 19 + stub 20 + stub 21 + stub 22 + stub 23 + stub 24 + stub 25 + stub 26 + stub 27 + stub 28 + stub 29 + stub_err 30 + stub 31 + +exception_common: + /* + * Save off the stack pointer and old eax value and install the + * exception stack. eax points to the old stack which has the + * exception ip, cs, and flags. + */ + mov %esp, old_esp + addl $12, old_esp + mov %eax, old_eax + mov %esp, %eax + mov exception_stack_end, %esp + + /* + * Push values onto the top of the exception stack to form an + * exception state structure. + */ + pushl vector + pushl error_code + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl %ss + pushl 4(%eax) + pushl 8(%eax) + pushl (%eax) + pushl %edi + pushl %esi + pushl %ebp + pushl old_esp + pushl %ebx + pushl %edx + pushl %ecx + pushl old_eax + + /* + * Call the C exception handler. It will find the exception state + * using the exception_state global pointer. Not + * passing parameters means we don't have to worry about what ABI + * is being used. + */ + mov %esp, exception_state + call exception_dispatch + + /* + * Restore state from the exception state structure, including any + * changes that might have been made. + */ + popl old_eax + popl %ecx + popl %edx + popl %ebx + popl old_esp + + mov old_esp, %eax + subl $12, %eax + + popl %ebp + popl %esi + popl %edi + popl (%eax) + popl 8(%eax) + popl 4(%eax) + popl %ss + popl %ds + popl %es + popl %fs + popl %gs + + mov %eax, %esp + mov old_eax, %eax + + /* Return from the exception. */ + iretl + +/* + * We need segment selectors for the IDT, so we need to know where things are + * in the GDT. We set one up here which is pretty standard and largely copied + * from coreboot. + */ + .align 8 +gdt: + /* selgdt 0, unused */ + .word 0x0000, 0x0000 + .byte 0x00, 0x00, 0x00, 0x00 + + /* selgdt 8, unused */ + .word 0x0000, 0x0000 + .byte 0x00, 0x00, 0x00, 0x00 + + /* selgdt 0x10, flat 4GB code segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x9b, 0xcf, 0x00 + + /* selgdt 0x18, flat 4GB data segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x93, 0xcf, 0x00 +gdt_end: + +/* GDT pointer for use with lgdt */ +gdt_ptr: + .word gdt_end - gdt - 1 + .long gdt + + /* + * Record the target and construct the actual entry at init time. This + * is necessary because the linker doesn't want to construct the entry + * for us. + */ + .macro interrupt_gate target + .long \target + .long \target + .endm + + .align 8 + .global idt +idt: + interrupt_gate exception_stub_0 + interrupt_gate exception_stub_1 + interrupt_gate exception_stub_2 + interrupt_gate exception_stub_3 + interrupt_gate exception_stub_4 + interrupt_gate exception_stub_5 + interrupt_gate exception_stub_6 + interrupt_gate exception_stub_7 + interrupt_gate exception_stub_8 + interrupt_gate exception_stub_9 + interrupt_gate exception_stub_10 + interrupt_gate exception_stub_11 + interrupt_gate exception_stub_12 + interrupt_gate exception_stub_13 + interrupt_gate exception_stub_14 + interrupt_gate exception_stub_15 + interrupt_gate exception_stub_16 + interrupt_gate exception_stub_17 + interrupt_gate exception_stub_18 + interrupt_gate exception_stub_19 + interrupt_gate exception_stub_20 + interrupt_gate exception_stub_21 + interrupt_gate exception_stub_22 + interrupt_gate exception_stub_23 + interrupt_gate exception_stub_24 + interrupt_gate exception_stub_25 + interrupt_gate exception_stub_26 + interrupt_gate exception_stub_27 + interrupt_gate exception_stub_28 + interrupt_gate exception_stub_29 + interrupt_gate exception_stub_30 + interrupt_gate exception_stub_31 +idt_end: + +/* IDT pointer for use with lidt */ +idt_ptr: + .word idt_end - idt - 1 + .long idt + + .global exception_init_asm +exception_init_asm: + /* Save eax so we can use it as a temporary variable. */ + pushl %eax + + /* Install the GDT. */ + lgdt gdt_ptr + /* Load the segment registers from it. */ + ljmp $0x10, $1f +1: movl $0x18, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %ss + movl %eax, %fs + movl %eax, %gs + + /* + * Loop over the entries which start out as two copies of the target + * address. We can turn them into real interrupt gates by selectively + * replacing certain bit fields. + */ + movl $idt, %eax +1: + andl $0x0000ffff, (%eax) + orl $0x00100000, (%eax) + andl $0xffff0000, 4(%eax) + orl $0x0000ee00, 4(%eax) + addl $8, %eax + cmp $idt_end, %eax + jne 1b + + /* Install the IDT. */ + lidt idt_ptr + + /* Restore eax and return to the caller. */ + popl %eax + ret diff --git a/payloads/libpayload/arch/x86/gdb.c b/payloads/libpayload/arch/x86/gdb.c new file mode 100644 index 0000000000..99db78f29b --- /dev/null +++ b/payloads/libpayload/arch/x86/gdb.c @@ -0,0 +1,93 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static const u8 type_to_signal[] = { + [EXC_DE] = GDB_SIGFPE, + [EXC_DB] = GDB_SIGTRAP, + [EXC_NMI] = GDB_SIGKILL, + [EXC_BP] = GDB_SIGTRAP, + [EXC_OF] = GDB_SIGFPE, + [EXC_BR] = GDB_SIGSEGV, + [EXC_UD] = GDB_SIGILL, + [EXC_NM] = GDB_SIGEMT, + [EXC_DF] = GDB_SIGKILL, + [EXC_TS] = GDB_SIGSEGV, + [EXC_NP] = GDB_SIGSEGV, + [EXC_SS] = GDB_SIGBUS, + [EXC_GP] = GDB_SIGSEGV, + [EXC_PF] = GDB_SIGSEGV, + [EXC_MF] = GDB_SIGEMT, + [EXC_AC] = GDB_SIGBUS, + [EXC_MC] = GDB_SIGKILL, + [EXC_XF] = GDB_SIGFPE, + [EXC_SX] = GDB_SIGFPE, +}; + +static int gdb_exception_hook(u32 type) +{ + if (type >= ARRAY_SIZE(type_to_signal) || !type_to_signal[type]) + return 0; + gdb_command_loop(type_to_signal[type]); + return 1; +} + +void gdb_arch_init(void) +{ + exception_install_hook(&gdb_exception_hook); +} + +void gdb_arch_enter(void) +{ + u32 *esp; + + asm volatile ("mov %%esp, %0" : "=r"(esp) ); + + /* Avoid reentrant exceptions, just call the hook if in one already. */ + if (esp >= exception_stack && esp <= exception_stack_end) + gdb_exception_hook(EXC_BP); + else + asm volatile ("int3"); +} + +int gdb_arch_set_single_step(int on) +{ + const u32 tf_bit = 1 << 8; + + if (on) + exception_state->regs.eflags |= tf_bit; + else + exception_state->regs.eflags &= ~tf_bit; + + return 0; +} + +void gdb_arch_encode_regs(struct gdb_message *message) +{ + gdb_message_encode_bytes(message, &exception_state->regs, + sizeof(exception_state->regs)); +} + +void gdb_arch_decode_regs(int offset, struct gdb_message *message) +{ + gdb_message_decode_bytes(message, offset, &exception_state->regs, + sizeof(exception_state->regs)); +} diff --git a/payloads/libpayload/arch/x86/main.c b/payloads/libpayload/arch/x86/main.c index 1bac7a8aaa..ee52a937e6 100644 --- a/payloads/libpayload/arch/x86/main.c +++ b/payloads/libpayload/arch/x86/main.c @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +#include #include unsigned long loader_eax; /**< The value of EAX passed from the loader */ @@ -50,10 +51,12 @@ void start_main(void) lib_get_sysinfo(); /* Optionally set up the consoles. */ -#ifndef CONFIG_SKIP_CONSOLE_INIT +#ifndef CONFIG_LP_SKIP_CONSOLE_INIT console_init(); #endif + exception_init(); + /* * Any other system init that has to happen before the * user gets control goes here. diff --git a/payloads/libpayload/arch/x86/multiboot.c b/payloads/libpayload/arch/x86/multiboot.c index fa0c576dc9..c2c360732f 100644 --- a/payloads/libpayload/arch/x86/multiboot.c +++ b/payloads/libpayload/arch/x86/multiboot.c @@ -45,7 +45,7 @@ static void mb_parse_mmap(struct multiboot_header *table, while(ptr < (start + table->mmap_length)) { struct multiboot_mmap *mmap = (struct multiboot_mmap *) ptr; -#ifdef CONFIG_MEMMAP_RAM_ONLY +#ifdef CONFIG_LP_MEMMAP_RAM_ONLY /* 1 == normal RAM. Ignore everything else for now */ if (mmap->type == 1) { @@ -56,7 +56,7 @@ static void mb_parse_mmap(struct multiboot_header *table, if (++info->n_memranges == SYSINFO_MAX_MEM_RANGES) return; -#ifdef CONFIG_MEMMAP_RAM_ONLY +#ifdef CONFIG_LP_MEMMAP_RAM_ONLY } #endif diff --git a/payloads/libpayload/arch/x86/rom_media.c b/payloads/libpayload/arch/x86/rom_media.c index e338d1ca1b..5b8cbade1f 100644 --- a/payloads/libpayload/arch/x86/rom_media.c +++ b/payloads/libpayload/arch/x86/rom_media.c @@ -83,19 +83,19 @@ int init_x86rom_cbfs_media(struct cbfs_media *media) { struct cbfs_header *header = (struct cbfs_header*) *(uint32_t*)(0xfffffffc); if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { -#if defined(CONFIG_ROM_SIZE) +#if defined(CONFIG_LP_ROM_SIZE) printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header); - media->context = (void*)CONFIG_ROM_SIZE; + media->context = (void*)CONFIG_LP_ROM_SIZE; #else return -1; #endif } else { uint32_t romsize = ntohl(header->romsize); media->context = (void*)romsize; -#if defined(CONFIG_ROM_SIZE) - if (CONFIG_ROM_SIZE != romsize) +#if defined(CONFIG_LP_ROM_SIZE) + if (CONFIG_LP_ROM_SIZE != romsize) printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n", - CONFIG_ROM_SIZE, romsize); + CONFIG_LP_ROM_SIZE, romsize); #endif } media->open = x86_rom_open; diff --git a/payloads/libpayload/arch/x86/selfboot.c b/payloads/libpayload/arch/x86/selfboot.c new file mode 100644 index 0000000000..5c3e4459e9 --- /dev/null +++ b/payloads/libpayload/arch/x86/selfboot.c @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +void selfboot(void *entry) +{ + void (*entry_func)(void) = entry; + entry_func(); +} diff --git a/payloads/libpayload/arch/x86/sysinfo.c b/payloads/libpayload/arch/x86/sysinfo.c index 6c1ef3fc1c..8e8b1c8d0a 100644 --- a/payloads/libpayload/arch/x86/sysinfo.c +++ b/payloads/libpayload/arch/x86/sysinfo.c @@ -38,8 +38,8 @@ */ struct sysinfo_t lib_sysinfo = { .cpu_khz = 200, -#ifdef CONFIG_SERIAL_CONSOLE - .ser_ioport = CONFIG_SERIAL_IOBASE, +#ifdef CONFIG_LP_SERIAL_CONSOLE + .ser_ioport = CONFIG_LP_SERIAL_IOBASE, #else .ser_ioport = 0x3f8, #endif @@ -52,7 +52,7 @@ int lib_get_sysinfo(void) /* Get the CPU speed (for delays). */ lib_sysinfo.cpu_khz = get_cpu_speed(); -#ifdef CONFIG_MULTIBOOT +#ifdef CONFIG_LP_MULTIBOOT /* Get the information from the multiboot tables, * if they exist */ get_multiboot_info(&lib_sysinfo); diff --git a/payloads/libpayload/arch/x86/timer.c b/payloads/libpayload/arch/x86/timer.c index e0cefb819a..bf0c30a873 100644 --- a/payloads/libpayload/arch/x86/timer.c +++ b/payloads/libpayload/arch/x86/timer.c @@ -76,13 +76,3 @@ unsigned int get_cpu_speed(void) return cpu_khz; } - -uint64_t timer_hz(void) -{ - return lib_sysinfo.cpu_khz * 1000; -} - -uint64_t timer_raw_value(void) -{ - return rdtsc(); -} diff --git a/payloads/libpayload/bin/lpgcc b/payloads/libpayload/bin/lpgcc index 06b9021fbf..6a71c44f7e 100755 --- a/payloads/libpayload/bin/lpgcc +++ b/payloads/libpayload/bin/lpgcc @@ -27,7 +27,7 @@ ## SUCH DAMAGE. # GCC wrapper for libpayload -if [ -z "${V}" ] && [ "${V}" = 1 ]; then +if [ "${V}" = "1" ]; then DEBUGME=1 else DEBUGME=0 @@ -107,19 +107,19 @@ while [ $# -gt 0 ]; do shift done -if [ "$CONFIG_ARCH_ARMV7" = "y" ]; then - _ARCHINCDIR=$_INCDIR/armv7 - _ARCHLIBDIR=$_LIBDIR/armv7 +if [ "$CONFIG_LP_ARCH_ARM" = "y" ]; then + _ARCHINCDIR=$_INCDIR/arm + _ARCHLIBDIR=$_LIBDIR/arm _ARCHEXTRA="" fi -if [ "$CONFIG_ARCH_POWERPC" = "y" ]; then - _ARCHINCDIR=$_INCDIR/powerpc - _ARCHLIBDIR=$_LIBDIR/powerpc +if [ "$CONFIG_LP_ARCH_ARM64" = "y" ]; then + _ARCHINCDIR=$_INCDIR/arm64 + _ARCHLIBDIR=$_LIBDIR/arm64 _ARCHEXTRA="" fi -if [ "$CONFIG_ARCH_X86" = "y" ]; then +if [ "$CONFIG_LP_ARCH_X86" = "y" ]; then _ARCHINCDIR=$_INCDIR/x86 _ARCHLIBDIR=$_LIBDIR/x86 _ARCHEXTRA="-m32 " diff --git a/payloads/libpayload/configs/config.arm64-generic b/payloads/libpayload/configs/config.arm64-generic new file mode 100644 index 0000000000..dce01f2b46 --- /dev/null +++ b/payloads/libpayload/configs/config.arm64-generic @@ -0,0 +1,67 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:49 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +# CONFIG_LP_ARCH_X86 is not set +CONFIG_LP_ARCH_ARM64=y +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +# CONFIG_LP_SERIAL_CONSOLE is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_NONE=y +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.auron b/payloads/libpayload/configs/config.auron new file mode 100644 index 0000000000..15bcb19848 --- /dev/null +++ b/payloads/libpayload/configs/config.auron @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:54 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.auron_pearlvalley b/payloads/libpayload/configs/config.auron_pearlvalley new file mode 100644 index 0000000000..d5c035971e --- /dev/null +++ b/payloads/libpayload/configs/config.auron_pearlvalley @@ -0,0 +1,78 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Tue Jun 24 10:49:18 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.bayleybay b/payloads/libpayload/configs/config.bayleybay new file mode 100644 index 0000000000..45f426ae8f --- /dev/null +++ b/payloads/libpayload/configs/config.bayleybay @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.beltino b/payloads/libpayload/configs/config.beltino new file mode 100644 index 0000000000..67a52f323a --- /dev/null +++ b/payloads/libpayload/configs/config.beltino @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:56 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.bolt b/payloads/libpayload/configs/config.bolt new file mode 100644 index 0000000000..520e8e5562 --- /dev/null +++ b/payloads/libpayload/configs/config.bolt @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:56 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.cosmos b/payloads/libpayload/configs/config.cosmos new file mode 100644 index 0000000000..9ced385768 --- /dev/null +++ b/payloads/libpayload/configs/config.cosmos @@ -0,0 +1,73 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:57 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +CONFIG_LP_BG4CD_SERIAL_CONSOLE=y +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +# CONFIG_LP_VIDEO_CONSOLE is not set +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +CONFIG_LP_TIMER_BG4CD=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +# CONFIG_LP_USB_XHCI is not set +# CONFIG_LP_USB_DWC2 is not set +# CONFIG_LP_USB_HID is not set +# CONFIG_LP_USB_HUB is not set +# CONFIG_LP_USB_MSC is not set +# CONFIG_LP_USB_PCI is not set +# CONFIG_LP_USB_GEN_HUB is not set +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.daisy b/payloads/libpayload/configs/config.daisy new file mode 100644 index 0000000000..37a9a41191 --- /dev/null +++ b/payloads/libpayload/configs/config.daisy @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:02 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +CONFIG_LP_S5P_SERIAL_CONSOLE=y +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +CONFIG_LP_TIMER_MCT=y +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_MCT_HZ=24000000 +CONFIG_LP_TIMER_MCT_ADDRESS=0x101c0000 +CONFIG_LP_USB=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.falco b/payloads/libpayload/configs/config.falco new file mode 100644 index 0000000000..90058b2573 --- /dev/null +++ b/payloads/libpayload/configs/config.falco @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:03 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.fox_baskingridge b/payloads/libpayload/configs/config.fox_baskingridge new file mode 100644 index 0000000000..acdc75b5f8 --- /dev/null +++ b/payloads/libpayload/configs/config.fox_baskingridge @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:04 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.fox_wtm2 b/payloads/libpayload/configs/config.fox_wtm2 new file mode 100644 index 0000000000..be090ef6e9 --- /dev/null +++ b/payloads/libpayload/configs/config.fox_wtm2 @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:05 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.gizmo b/payloads/libpayload/configs/config.gizmo new file mode 100644 index 0000000000..0e4597c776 --- /dev/null +++ b/payloads/libpayload/configs/config.gizmo @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:05 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.jecht b/payloads/libpayload/configs/config.jecht new file mode 100644 index 0000000000..15bcb19848 --- /dev/null +++ b/payloads/libpayload/configs/config.jecht @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:53:54 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.link b/payloads/libpayload/configs/config.link new file mode 100644 index 0000000000..c4b5db1e3f --- /dev/null +++ b/payloads/libpayload/configs/config.link @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:06 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.lumpy b/payloads/libpayload/configs/config.lumpy new file mode 100644 index 0000000000..71a4380e78 --- /dev/null +++ b/payloads/libpayload/configs/config.lumpy @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:07 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.nyan b/payloads/libpayload/configs/config.nyan new file mode 100644 index 0000000000..bff4fe9dec --- /dev/null +++ b/payloads/libpayload/configs/config.nyan @@ -0,0 +1,75 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:13 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +CONFIG_LP_TIMER_TEGRA_1US=y +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_TEGRA_1US_ADDRESS=0x60005010 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT=y +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.nyan_big b/payloads/libpayload/configs/config.nyan_big new file mode 100644 index 0000000000..8900d6ea7b --- /dev/null +++ b/payloads/libpayload/configs/config.nyan_big @@ -0,0 +1,75 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:18 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +CONFIG_LP_TIMER_TEGRA_1US=y +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_TEGRA_1US_ADDRESS=0x60005010 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT=y +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.nyan_blaze b/payloads/libpayload/configs/config.nyan_blaze new file mode 100644 index 0000000000..4a93ce3f1c --- /dev/null +++ b/payloads/libpayload/configs/config.nyan_blaze @@ -0,0 +1,75 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:23 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +CONFIG_LP_TIMER_TEGRA_1US=y +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_TEGRA_1US_ADDRESS=0x60005010 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT=y +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.panther b/payloads/libpayload/configs/config.panther new file mode 100644 index 0000000000..929427c13f --- /dev/null +++ b/payloads/libpayload/configs/config.panther @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:25 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.peach_pit b/payloads/libpayload/configs/config.peach_pit new file mode 100644 index 0000000000..9526313aa5 --- /dev/null +++ b/payloads/libpayload/configs/config.peach_pit @@ -0,0 +1,75 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:28 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +CONFIG_LP_S5P_SERIAL_CONSOLE=y +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +CONFIG_LP_TIMER_MCT=y +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_MCT_HZ=24000000 +CONFIG_LP_TIMER_MCT_ADDRESS=0x101c0000 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.peppy b/payloads/libpayload/configs/config.peppy new file mode 100644 index 0000000000..c40a4d5de4 --- /dev/null +++ b/payloads/libpayload/configs/config.peppy @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:31 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.rambi b/payloads/libpayload/configs/config.rambi new file mode 100644 index 0000000000..f50927ba88 --- /dev/null +++ b/payloads/libpayload/configs/config.rambi @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:32 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.rush b/payloads/libpayload/configs/config.rush new file mode 100644 index 0000000000..709414ae85 --- /dev/null +++ b/payloads/libpayload/configs/config.rush @@ -0,0 +1,75 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:44 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +# CONFIG_LP_ARCH_X86 is not set +CONFIG_LP_ARCH_ARM64=y +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +CONFIG_LP_TIMER_TEGRA_1US=y +# CONFIG_LP_TIMER_IPQ806X is not set +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_TEGRA_1US_ADDRESS=0x60005010 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.samus b/payloads/libpayload/configs/config.samus new file mode 100644 index 0000000000..5318abd0d6 --- /dev/null +++ b/payloads/libpayload/configs/config.samus @@ -0,0 +1,79 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:46 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +# CONFIG_LP_USB_UHCI is not set +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.slippy b/payloads/libpayload/configs/config.slippy new file mode 100644 index 0000000000..db1e13d534 --- /dev/null +++ b/payloads/libpayload/configs/config.slippy @@ -0,0 +1,80 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:48 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +# CONFIG_LP_ARCH_ARM is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_PL011_SERIAL_CONSOLE is not set +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +# CONFIG_LP_VGA_VIDEO_CONSOLE is not set +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set + +# +# Drivers +# +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_SPEAKER is not set +# CONFIG_LP_STORAGE is not set +CONFIG_LP_TIMER_RDTSC=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.storm b/payloads/libpayload/configs/config.storm new file mode 100644 index 0000000000..a5d3909738 --- /dev/null +++ b/payloads/libpayload/configs/config.storm @@ -0,0 +1,74 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:51 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +# CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE is not set +CONFIG_LP_IPQ806X_SERIAL_CONSOLE=y +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +# CONFIG_LP_VIDEO_CONSOLE is not set +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +CONFIG_LP_TIMER_IPQ806X=y +# CONFIG_LP_TIMER_RK is not set +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_IPQ806X_TIMER_FREQ=6250000 +CONFIG_LP_IPQ806X_TIMER_REG=0x0200A028 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +# CONFIG_LP_USB_EHCI is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_brain b/payloads/libpayload/configs/config.veyron_brain new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_brain @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_danger b/payloads/libpayload/configs/config.veyron_danger new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_danger @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_fievel b/payloads/libpayload/configs/config.veyron_fievel new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_fievel @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_gus b/payloads/libpayload/configs/config.veyron_gus new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_gus @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_jaq b/payloads/libpayload/configs/config.veyron_jaq new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_jaq @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_jerry b/payloads/libpayload/configs/config.veyron_jerry new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_jerry @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_mickey b/payloads/libpayload/configs/config.veyron_mickey new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_mickey @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_mighty b/payloads/libpayload/configs/config.veyron_mighty new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_mighty @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_minnie b/payloads/libpayload/configs/config.veyron_minnie new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_minnie @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_nicky b/payloads/libpayload/configs/config.veyron_nicky new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_nicky @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_pinky b/payloads/libpayload/configs/config.veyron_pinky new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_pinky @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_rialto b/payloads/libpayload/configs/config.veyron_rialto new file mode 100644 index 0000000000..4c67205290 --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_rialto @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +# CONFIG_LP_VIDEO_CONSOLE is not set +# CONFIG_LP_COREBOOT_VIDEO_CONSOLE is not set +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_romy b/payloads/libpayload/configs/config.veyron_romy new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_romy @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_speedy b/payloads/libpayload/configs/config.veyron_speedy new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_speedy @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_thea b/payloads/libpayload/configs/config.veyron_thea new file mode 100644 index 0000000000..fb721be77c --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_thea @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +# CONFIG_LP_USB_HID is not set +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/config.veyron_tiger b/payloads/libpayload/configs/config.veyron_tiger new file mode 100644 index 0000000000..9dd1680aca --- /dev/null +++ b/payloads/libpayload/configs/config.veyron_tiger @@ -0,0 +1,76 @@ +# +# Automatically generated make config: don't edit +# libpayload version: 0.2.0 +# Wed Oct 15 20:54:55 2014 +# + +# +# Generic Options +# +CONFIG_LP_GPL=y +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_REMOTEGDB is not set +CONFIG_LP_CHROMEOS=y + +# +# Architecture Options +# +CONFIG_LP_ARCH_ARM=y +# CONFIG_LP_ARCH_X86 is not set +# CONFIG_LP_ARCH_ARM64 is not set +# CONFIG_LP_MEMMAP_RAM_ONLY is not set + +# +# Standard Libraries +# +CONFIG_LP_LIBC=y +# CONFIG_LP_CURSES is not set +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y + +# +# Console Options +# +CONFIG_LP_SKIP_CONSOLE_INIT=y +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +# CONFIG_LP_8250_SERIAL_CONSOLE is not set +# CONFIG_LP_S5P_SERIAL_CONSOLE is not set +CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE=y +# CONFIG_LP_IPQ806X_SERIAL_CONSOLE is not set +# CONFIG_LP_BG4CD_SERIAL_CONSOLE is not set +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +# CONFIG_LP_PC_KEYBOARD is not set + +# +# Drivers +# +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +# CONFIG_LP_STORAGE is not set +# CONFIG_LP_TIMER_NONE is not set +# CONFIG_LP_TIMER_MCT is not set +# CONFIG_LP_TIMER_TEGRA_1US is not set +# CONFIG_LP_TIMER_IPQ806X is not set +CONFIG_LP_TIMER_RK=y +# CONFIG_LP_TIMER_BG4CD is not set +CONFIG_LP_TIMER_RK_ADDRESS=0xff810020 +CONFIG_LP_USB=y +# CONFIG_LP_USB_OHCI is not set +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_XHCI is not set +CONFIG_LP_USB_DWC2=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_MSC=y +# CONFIG_LP_USB_PCI is not set +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +# CONFIG_LP_IO_ADDRESS_SPACE is not set +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/configs/defconfig b/payloads/libpayload/configs/defconfig index 2a2e90b42d..948b63bc28 100644 --- a/payloads/libpayload/configs/defconfig +++ b/payloads/libpayload/configs/defconfig @@ -1,74 +1,81 @@ # # Automatically generated make config: don't edit # libpayload version: 0.2.0 -# Mon Dec 17 14:39:45 2012 +# Thu May 2 16:10:03 2013 # # # Generic Options # -# CONFIG_EXPERIMENTAL is not set -# CONFIG_OBSOLETE is not set -# CONFIG_DEVELOPER is not set -# CONFIG_CHROMEOS is not set +# CONFIG_LP_GPL is not set +# CONFIG_LP_EXPERIMENTAL is not set +# CONFIG_LP_OBSOLETE is not set +# CONFIG_LP_DEVELOPER is not set +# CONFIG_LP_CHROMEOS is not set # # Architecture Options # -# CONFIG_ARCH_ARMV7 is not set -# CONFIG_ARCH_POWERPC is not set -CONFIG_ARCH_X86=y -# CONFIG_MEMMAP_RAM_ONLY is not set -# CONFIG_MULTIBOOT is not set +# CONFIG_LP_ARCH_ARM is not set +# CONFIG_LP_ARCH_POWERPC is not set +# CONFIG_LP_ARCH_ARM64 is not set +CONFIG_LP_ARCH_X86=y +# CONFIG_LP_MEMMAP_RAM_ONLY is not set +# CONFIG_LP_MULTIBOOT is not set # # Standard Libraries # -CONFIG_LIBC=y -CONFIG_CURSES=y -# CONFIG_TINYCURSES is not set -CONFIG_PDCURSES=y -CONFIG_CBFS=y -CONFIG_LZMA=y +CONFIG_LP_LIBC=y +CONFIG_LP_CURSES=y +# CONFIG_LP_TINYCURSES is not set +CONFIG_LP_PDCURSES=y +CONFIG_LP_CBFS=y +CONFIG_LP_LZMA=y # # Console Options # -# CONFIG_SKIP_CONSOLE_INIT is not set -CONFIG_CBMEM_CONSOLE=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_IOBASE=0x3f8 -# CONFIG_SERIAL_SET_SPEED is not set -# CONFIG_SERIAL_ACS_FALLBACK is not set -CONFIG_VIDEO_CONSOLE=y -CONFIG_VGA_VIDEO_CONSOLE=y -# CONFIG_GEODELX_VIDEO_CONSOLE is not set -CONFIG_COREBOOT_VIDEO_CONSOLE=y -CONFIG_PC_KEYBOARD=y -CONFIG_PC_KEYBOARD_LAYOUT_US=y -# CONFIG_PC_KEYBOARD_LAYOUT_DE is not set +# CONFIG_LP_SKIP_CONSOLE_INIT is not set +CONFIG_LP_CBMEM_CONSOLE=y +CONFIG_LP_SERIAL_CONSOLE=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +CONFIG_LP_SERIAL_IOBASE=0x3f8 +# CONFIG_LP_SERIAL_SET_SPEED is not set +# CONFIG_LP_SERIAL_ACS_FALLBACK is not set +CONFIG_LP_VIDEO_CONSOLE=y +CONFIG_LP_VGA_VIDEO_CONSOLE=y +# CONFIG_LP_GEODELX_VIDEO_CONSOLE is not set +CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y +CONFIG_LP_PC_KEYBOARD=y +CONFIG_LP_PC_KEYBOARD_LAYOUT_US=y +# CONFIG_LP_PC_KEYBOARD_LAYOUT_DE is not set # # Drivers # -CONFIG_PCI=y -CONFIG_NVRAM=y -# CONFIG_RTC_PORT_EXTENDED_VIA is not set -CONFIG_SPEAKER=y -CONFIG_STORAGE=y -# CONFIG_STORAGE_64BIT_LBA is not set -CONFIG_STORAGE_ATA=y -CONFIG_STORAGE_ATAPI=y -CONFIG_STORAGE_AHCI=y -CONFIG_STORAGE_AHCI_ONLY_TESTED=y -CONFIG_USB=y -CONFIG_USB_UHCI=y -CONFIG_USB_OHCI=y -CONFIG_USB_EHCI=y -CONFIG_USB_XHCI=y -CONFIG_USB_HID=y -CONFIG_USB_HUB=y -CONFIG_USB_MSC=y -# CONFIG_BIG_ENDIAN is not set -CONFIG_LITTLE_ENDIAN=y -CONFIG_ARCH_SPECIFIC_OPTIONS=y +CONFIG_LP_PCI=y +CONFIG_LP_NVRAM=y +# CONFIG_LP_RTC_PORT_EXTENDED_VIA is not set +CONFIG_LP_SPEAKER=y +CONFIG_LP_STORAGE=y +# CONFIG_LP_STORAGE_64BIT_LBA is not set +CONFIG_LP_STORAGE_ATA=y +CONFIG_LP_STORAGE_ATAPI=y +CONFIG_LP_STORAGE_AHCI=y +CONFIG_LP_STORAGE_AHCI_ONLY_TESTED=y +CONFIG_LP_USB=y +CONFIG_LP_USB_UHCI=y +CONFIG_LP_USB_OHCI=y +CONFIG_LP_USB_EHCI=y +# CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT is not set +CONFIG_LP_USB_XHCI=y +CONFIG_LP_USB_HID=y +CONFIG_LP_USB_HUB=y +CONFIG_LP_USB_MSC=y +CONFIG_LP_USB_PCI=y +CONFIG_LP_USB_GEN_HUB=y +# CONFIG_LP_BIG_ENDIAN is not set +CONFIG_LP_LITTLE_ENDIAN=y +CONFIG_LP_IO_ADDRESS_SPACE=y +CONFIG_LP_ARCH_SPECIFIC_OPTIONS=y diff --git a/payloads/libpayload/crypto/sha1.c b/payloads/libpayload/crypto/sha1.c index 3c97bf1895..615ed7222f 100644 --- a/payloads/libpayload/crypto/sha1.c +++ b/payloads/libpayload/crypto/sha1.c @@ -30,18 +30,12 @@ typedef unsigned int u_int; /* Moved from libpayload.h */ -#ifdef CONFIG_ARCH_X86 +#ifdef CONFIG_LP_LITTLE_ENDIAN #define BYTE_ORDER LITTLE_ENDIAN #else #define BYTE_ORDER BIG_ENDIAN #endif -#if 0 -#include -#include -#include -#endif - #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* diff --git a/payloads/libpayload/curses/Makefile.inc b/payloads/libpayload/curses/Makefile.inc index 5d14431cda..025a0511d3 100644 --- a/payloads/libpayload/curses/Makefile.inc +++ b/payloads/libpayload/curses/Makefile.inc @@ -27,142 +27,142 @@ ## SUCH DAMAGE. ## -ifeq ($(CONFIG_TINYCURSES),y) +ifeq ($(CONFIG_LP_TINYCURSES),y) INCLUDES += -Icurses endif -libcurses-$(CONFIG_TINYCURSES) += keyboard.c -libcurses-$(CONFIG_TINYCURSES) += tinycurses.c -libcurses-$(CONFIG_TINYCURSES) += colors.c +libcurses-$(CONFIG_LP_TINYCURSES) += keyboard.c +libcurses-$(CONFIG_LP_TINYCURSES) += tinycurses.c +libcurses-$(CONFIG_LP_TINYCURSES) += colors.c -includes-$(CONFIG_TINYCURSES) += curses.h +includes-$(CONFIG_LP_TINYCURSES) += curses.h -ifeq ($(CONFIG_PDCURSES),y) +ifeq ($(CONFIG_LP_PDCURSES),y) INCLUDES += -D_LP64=0 -Icurses/PDCurses-3.4 -Icurses/pdcurses-backend -Icurses/menu -Icurses/form endif -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdcdisp.c -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdcgetsc.c -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdckbd.c -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdcscrn.c -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdcsetsc.c -libcurses-$(CONFIG_PDCURSES) += pdcurses-backend/pdcutil.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/addch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/move.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/overlay.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/refresh.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/terminfo.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/window.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/util.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/inopts.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/addstr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/keyname.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/instr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/clear.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/addchstr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/kernel.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/pad.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/insstr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/border.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/getyx.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/getstr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/getch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/termattr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/outopts.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/color.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/deleteln.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/initscr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/slk.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/delch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/touch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/mouse.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/scanw.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/scroll.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/printw.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/bkgd.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/inch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/attr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/insch.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/inchstr.c -libcurses-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/beep.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdcdisp.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdcgetsc.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdckbd.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdcscrn.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdcsetsc.c +libcurses-$(CONFIG_LP_PDCURSES) += pdcurses-backend/pdcutil.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/addch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/move.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/overlay.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/refresh.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/terminfo.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/window.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/util.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/inopts.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/addstr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/keyname.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/instr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/clear.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/addchstr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/kernel.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/pad.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/insstr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/border.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/getyx.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/getstr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/getch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/termattr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/outopts.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/color.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/deleteln.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/initscr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/slk.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/delch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/touch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/mouse.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/scanw.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/scroll.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/printw.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/bkgd.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/inch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/attr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/insch.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/inchstr.c +libcurses-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/beep.c -includes-$(CONFIG_PDCURSES) += pdcurses-backend/nc_alloc.h -includes-$(CONFIG_PDCURSES) += pdcurses-backend/ncurses_cfg.h -includes-$(CONFIG_PDCURSES) += PDCurses-3.4/curses.h -includes-$(CONFIG_PDCURSES) += PDCurses-3.4/term.h -includes-$(CONFIG_PDCURSES) += PDCurses-3.4/panel.h -includes-$(CONFIG_PDCURSES) += menu/eti.h -includes-$(CONFIG_PDCURSES) += menu/menu.h -includes-$(CONFIG_PDCURSES) += menu/mf_common.h -includes-$(CONFIG_PDCURSES) += form/form.h +includes-$(CONFIG_LP_PDCURSES) += pdcurses-backend/nc_alloc.h +includes-$(CONFIG_LP_PDCURSES) += pdcurses-backend/ncurses_cfg.h +includes-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/curses.h +includes-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/term.h +includes-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/panel.h +includes-$(CONFIG_LP_PDCURSES) += menu/eti.h +includes-$(CONFIG_LP_PDCURSES) += menu/menu.h +includes-$(CONFIG_LP_PDCURSES) += menu/mf_common.h +includes-$(CONFIG_LP_PDCURSES) += form/form.h -libpanel-$(CONFIG_PDCURSES) += PDCurses-3.4/pdcurses/panel.c +libpanel-$(CONFIG_LP_PDCURSES) += PDCurses-3.4/pdcurses/panel.c -libmenu-$(CONFIG_PDCURSES) += menu/m_req_name.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_nam.c -libmenu-$(CONFIG_PDCURSES) += menu/m_pad.c -libmenu-$(CONFIG_PDCURSES) += menu/m_cursor.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_new.c -libmenu-$(CONFIG_PDCURSES) += menu/m_attribs.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_opt.c -libmenu-$(CONFIG_PDCURSES) += menu/m_format.c -libmenu-$(CONFIG_PDCURSES) += menu/m_post.c -libmenu-$(CONFIG_PDCURSES) += menu/m_userptr.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_cur.c -libmenu-$(CONFIG_PDCURSES) += menu/m_driver.c -libmenu-$(CONFIG_PDCURSES) += menu/m_sub.c -libmenu-$(CONFIG_PDCURSES) += menu/m_win.c -libmenu-$(CONFIG_PDCURSES) += menu/m_global.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_vis.c -libmenu-$(CONFIG_PDCURSES) += menu/m_new.c -libmenu-$(CONFIG_PDCURSES) += menu/m_scale.c -libmenu-$(CONFIG_PDCURSES) += menu/m_spacing.c -libmenu-$(CONFIG_PDCURSES) += menu/m_opts.c -libmenu-$(CONFIG_PDCURSES) += menu/m_pattern.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_val.c -libmenu-$(CONFIG_PDCURSES) += menu/m_hook.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_use.c -libmenu-$(CONFIG_PDCURSES) += menu/m_items.c -libmenu-$(CONFIG_PDCURSES) += menu/m_item_top.c -libform-$(CONFIG_PDCURSES) += form/frm_page.c -libform-$(CONFIG_PDCURSES) += form/frm_opts.c -libform-$(CONFIG_PDCURSES) += form/frm_def.c -libform-$(CONFIG_PDCURSES) += form/frm_req_name.c -libform-$(CONFIG_PDCURSES) += form/fty_alpha.c -libform-$(CONFIG_PDCURSES) += form/frm_driver.c -libform-$(CONFIG_PDCURSES) += form/fld_user.c -libform-$(CONFIG_PDCURSES) += form/frm_win.c -libform-$(CONFIG_PDCURSES) += form/fld_newftyp.c -#libform-$(CONFIG_PDCURSES) += form/fty_regex.c -libform-$(CONFIG_PDCURSES) += form/fld_stat.c -libform-$(CONFIG_PDCURSES) += form/fld_pad.c -libform-$(CONFIG_PDCURSES) += form/fld_current.c -libform-$(CONFIG_PDCURSES) += form/frm_post.c -#libform-$(CONFIG_PDCURSES) += form/f_trace.c -libform-$(CONFIG_PDCURSES) += form/fty_generic.c -libform-$(CONFIG_PDCURSES) += form/fld_page.c -libform-$(CONFIG_PDCURSES) += form/frm_hook.c -libform-$(CONFIG_PDCURSES) += form/frm_scale.c -libform-$(CONFIG_PDCURSES) += form/fty_int.c -libform-$(CONFIG_PDCURSES) += form/fty_alnum.c -libform-$(CONFIG_PDCURSES) += form/frm_cursor.c -#libform-$(CONFIG_PDCURSES) += form/fty_ipv4.c -libform-$(CONFIG_PDCURSES) += form/fld_link.c -libform-$(CONFIG_PDCURSES) += form/fld_arg.c -libform-$(CONFIG_PDCURSES) += form/fld_move.c -libform-$(CONFIG_PDCURSES) += form/fld_def.c -libform-$(CONFIG_PDCURSES) += form/fld_type.c -libform-$(CONFIG_PDCURSES) += form/fld_max.c -libform-$(CONFIG_PDCURSES) += form/fld_ftlink.c -libform-$(CONFIG_PDCURSES) += form/fld_ftchoice.c -libform-$(CONFIG_PDCURSES) += form/fld_info.c -libform-$(CONFIG_PDCURSES) += form/frm_user.c -#libform-$(CONFIG_PDCURSES) += form/fty_num.c -libform-$(CONFIG_PDCURSES) += form/frm_sub.c -libform-$(CONFIG_PDCURSES) += form/fty_enum.c -libform-$(CONFIG_PDCURSES) += form/frm_data.c -libform-$(CONFIG_PDCURSES) += form/fld_opts.c -libform-$(CONFIG_PDCURSES) += form/fld_attr.c -libform-$(CONFIG_PDCURSES) += form/fld_dup.c -libform-$(CONFIG_PDCURSES) += form/fld_just.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_req_name.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_nam.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_pad.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_cursor.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_new.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_attribs.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_opt.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_format.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_post.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_userptr.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_cur.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_driver.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_sub.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_win.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_global.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_vis.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_new.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_scale.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_spacing.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_opts.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_pattern.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_val.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_hook.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_use.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_items.c +libmenu-$(CONFIG_LP_PDCURSES) += menu/m_item_top.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_page.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_opts.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_def.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_req_name.c +libform-$(CONFIG_LP_PDCURSES) += form/fty_alpha.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_driver.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_user.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_win.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_newftyp.c +#libform-$(CONFIG_LP_PDCURSES) += form/fty_regex.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_stat.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_pad.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_current.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_post.c +#libform-$(CONFIG_LP_PDCURSES) += form/f_trace.c +libform-$(CONFIG_LP_PDCURSES) += form/fty_generic.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_page.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_hook.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_scale.c +libform-$(CONFIG_LP_PDCURSES) += form/fty_int.c +libform-$(CONFIG_LP_PDCURSES) += form/fty_alnum.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_cursor.c +#libform-$(CONFIG_LP_PDCURSES) += form/fty_ipv4.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_link.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_arg.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_move.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_def.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_type.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_max.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_ftlink.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_ftchoice.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_info.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_user.c +#libform-$(CONFIG_LP_PDCURSES) += form/fty_num.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_sub.c +libform-$(CONFIG_LP_PDCURSES) += form/fty_enum.c +libform-$(CONFIG_LP_PDCURSES) += form/frm_data.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_opts.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_attr.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_dup.c +libform-$(CONFIG_LP_PDCURSES) += form/fld_just.c diff --git a/payloads/libpayload/curses/keyboard.c b/payloads/libpayload/curses/keyboard.c index 7ebb04f111..1e87f8ffa0 100644 --- a/payloads/libpayload/curses/keyboard.c +++ b/payloads/libpayload/curses/keyboard.c @@ -45,7 +45,7 @@ static int _halfdelay = 0; /* ============== Serial ==================== */ -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE /* We treat serial like a vt100 terminal. For now we do the cooking in here, but we should probably eventually pass it to dedicated vt100 code */ @@ -146,12 +146,12 @@ static int cook_serial(unsigned char ch) static int curses_getchar(int _delay) { -#if defined(CONFIG_USB_HID) || defined(CONFIG_PC_KEYBOARD) || defined(CONFIG_SERIAL_CONSOLE) +#if defined(CONFIG_LP_USB_HID) || defined(CONFIG_LP_PC_KEYBOARD) || defined(CONFIG_LP_SERIAL_CONSOLE) unsigned short c; #endif do { -#ifdef CONFIG_USB_HID +#ifdef CONFIG_LP_USB_HID usb_poll(); if ((curses_flags & F_ENABLE_CONSOLE) && usbhid_havechar()) { @@ -159,7 +159,7 @@ static int curses_getchar(int _delay) if (c != 0) return c; } #endif -#ifdef CONFIG_PC_KEYBOARD +#ifdef CONFIG_LP_PC_KEYBOARD if ((curses_flags & F_ENABLE_CONSOLE) && keyboard_havechar()) { c = keyboard_getchar(); @@ -167,7 +167,7 @@ static int curses_getchar(int _delay) } #endif -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if ((curses_flags & F_ENABLE_SERIAL) && serial_havechar()) { c = serial_getchar(); @@ -225,7 +225,7 @@ int nocbreak(void) return 0; } -#ifdef CONFIG_VGA_VIDEO_CONSOLE +#ifdef CONFIG_LP_VGA_VIDEO_CONSOLE void curses_enable_vga(int state) { if (state) @@ -243,7 +243,7 @@ void curses_enable_vga(int state) { } int curses_vga_enabled(void) { return 0; } #endif -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE void curses_enable_serial(int state) { if (state) diff --git a/payloads/libpayload/curses/local.h b/payloads/libpayload/curses/local.h index b7c459d2a0..73fb005c5a 100644 --- a/payloads/libpayload/curses/local.h +++ b/payloads/libpayload/curses/local.h @@ -70,13 +70,13 @@ /* Flags used to determine what output methods are available */ -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE #define F_ENABLE_CONSOLE 0x01 #else #define F_ENABLE_CONSOLE 0x00 #endif -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE #define F_ENABLE_SERIAL 0x02 #else #define F_ENABLE_SERIAL 0x00 diff --git a/payloads/libpayload/curses/pdcurses-backend/pdcdisp.c b/payloads/libpayload/curses/pdcurses-backend/pdcdisp.c index ab73831aa6..308370e5bf 100644 --- a/payloads/libpayload/curses/pdcurses-backend/pdcdisp.c +++ b/payloads/libpayload/curses/pdcurses-backend/pdcdisp.c @@ -66,8 +66,8 @@ chtype fallback_acs_map[128] = '|', '<', '>', '*', '!', 'f', 'o', ' ', }; -#ifdef CONFIG_SERIAL_CONSOLE -#ifdef CONFIG_SERIAL_ACS_FALLBACK +#ifdef CONFIG_LP_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_ACS_FALLBACK chtype serial_acs_map[128]; #else /* See acsc of vt100. */ @@ -93,7 +93,7 @@ chtype serial_acs_map[128] = #endif #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE /* See acsc of linux. */ chtype console_acs_map[128] = { @@ -122,10 +122,10 @@ void PDC_gotoyx(int row, int col) { PDC_LOG(("PDC_gotoyx() - called: row %d col %d\n", row, col)); -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE serial_set_cursor(col, row); #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE video_console_set_cursor(col, row); #endif } @@ -139,7 +139,7 @@ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) PDC_LOG(("PDC_transform_line() - called: line %d, len %d, curses_flags %d\n", lineno, len, curses_flags)); -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE int serial_is_bold = 0; int serial_is_reverse = 0; int serial_is_altcharset = 0; @@ -157,7 +157,7 @@ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) { ch = srcp[j]; attr = ch; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) { if (attr & A_BOLD) { if (!serial_is_bold) { @@ -222,7 +222,7 @@ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) } #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE unsigned char c = pdc_atrtab[srcp[j] >> PDC_ATTR_SHIFT]; if (curses_flags & F_ENABLE_CONSOLE) { diff --git a/payloads/libpayload/curses/pdcurses-backend/pdckbd.c b/payloads/libpayload/curses/pdcurses-backend/pdckbd.c index 49b80c74fc..d1061b2499 100644 --- a/payloads/libpayload/curses/pdcurses-backend/pdckbd.c +++ b/payloads/libpayload/curses/pdcurses-backend/pdckbd.c @@ -5,7 +5,7 @@ unsigned long pdc_key_modifiers = 0L; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE /* We treat serial like a vt100 terminal. For now we do the cooking in here, but we should probably eventually pass it to dedicated vt100 code */ @@ -108,7 +108,7 @@ void PDC_set_keyboard_binary(bool on) bool PDC_check_key(void) { -#ifdef CONFIG_USB_HID +#ifdef CONFIG_LP_USB_HID usb_poll(); if ((curses_flags & F_ENABLE_CONSOLE) && usbhid_havechar()) { @@ -116,14 +116,14 @@ bool PDC_check_key(void) } #endif -#ifdef CONFIG_PC_KEYBOARD +#ifdef CONFIG_LP_PC_KEYBOARD if ((curses_flags & F_ENABLE_CONSOLE) && keyboard_havechar()) { return TRUE; } #endif -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if ((curses_flags & F_ENABLE_SERIAL) && serial_havechar()) { return TRUE; @@ -139,7 +139,7 @@ int PDC_get_key(void) { int c = 0; -#ifdef CONFIG_USB_HID +#ifdef CONFIG_LP_USB_HID usb_poll(); if ((curses_flags & F_ENABLE_CONSOLE) && usbhid_havechar()) { @@ -147,14 +147,14 @@ int PDC_get_key(void) } #endif -#ifdef CONFIG_PC_KEYBOARD +#ifdef CONFIG_LP_PC_KEYBOARD if ((curses_flags & F_ENABLE_CONSOLE) && keyboard_havechar() && (c==0)) { c = keyboard_getchar(); } #endif -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if ((curses_flags & F_ENABLE_SERIAL) && serial_havechar() && (c==0)) { c = cook_serial(serial_getchar()); diff --git a/payloads/libpayload/curses/pdcurses-backend/pdcscrn.c b/payloads/libpayload/curses/pdcurses-backend/pdcscrn.c index e741b15d09..c4922ec409 100644 --- a/payloads/libpayload/curses/pdcurses-backend/pdcscrn.c +++ b/payloads/libpayload/curses/pdcurses-backend/pdcscrn.c @@ -72,7 +72,7 @@ int PDC_scr_open(int argc, char **argv) SP->lines = PDC_get_rows(); SP->cols = PDC_get_columns(); -#ifdef CONFIG_SPEAKER +#ifdef CONFIG_LP_SPEAKER SP->audible = TRUE; #endif diff --git a/payloads/libpayload/curses/pdcurses-backend/pdcsetsc.c b/payloads/libpayload/curses/pdcurses-backend/pdcsetsc.c index d016063ff0..b2997a16f9 100644 --- a/payloads/libpayload/curses/pdcurses-backend/pdcsetsc.c +++ b/payloads/libpayload/curses/pdcurses-backend/pdcsetsc.c @@ -13,12 +13,12 @@ int PDC_curs_set(int visibility) ret_vis = SP->visibility; SP->visibility = visibility; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) { serial_cursor_enable(visibility); } #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE if (curses_flags & F_ENABLE_CONSOLE) { video_console_cursor_enable(visibility); } diff --git a/payloads/libpayload/curses/pdcurses-backend/pdcutil.c b/payloads/libpayload/curses/pdcurses-backend/pdcutil.c index 030f4622e2..c40e2ed1eb 100644 --- a/payloads/libpayload/curses/pdcurses-backend/pdcutil.c +++ b/payloads/libpayload/curses/pdcurses-backend/pdcutil.c @@ -11,7 +11,7 @@ void PDC_beep(void) { PDC_LOG(("PDC_beep() - called\n")); -#ifdef CONFIG_SPEAKER +#ifdef CONFIG_LP_SPEAKER speaker_tone(1760, 500); /* 1760 == note A6 */ #endif } diff --git a/payloads/libpayload/curses/tinycurses.c b/payloads/libpayload/curses/tinycurses.c index fe6e7dee41..d5bf23f1af 100644 --- a/payloads/libpayload/curses/tinycurses.c +++ b/payloads/libpayload/curses/tinycurses.c @@ -111,8 +111,8 @@ chtype fallback_acs_map[128] = '|', '<', '>', '*', '!', 'f', 'o', ' ', }; -#ifdef CONFIG_SERIAL_CONSOLE -#ifdef CONFIG_SERIAL_ACS_FALLBACK +#ifdef CONFIG_LP_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_ACS_FALLBACK chtype serial_acs_map[128]; #else /* See acsc of vt100. */ @@ -138,7 +138,7 @@ chtype serial_acs_map[128] = #endif #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE /* See acsc of linux. */ chtype console_acs_map[128] = { @@ -191,7 +191,7 @@ NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch) int beep(void) { /* TODO: Flash the screen if beeping fails? */ -#ifdef CONFIG_SPEAKER +#ifdef CONFIG_LP_SPEAKER speaker_tone(1760, 500); /* 1760 == note A6 */ #endif return OK; @@ -202,12 +202,12 @@ int cbreak(void) { /* TODO */ return 0; } // int color_content(short color, short *r, short *g, short *b) {} int curs_set(int on) { -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) { serial_cursor_enable(on); } #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE if (curses_flags & F_ENABLE_CONSOLE) { video_console_cursor_enable(on); } @@ -315,12 +315,12 @@ WINDOW *initscr(void) for (i = 0; i < 128; i++) acs_map[i] = (chtype) i | A_ALTCHARSET; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) { serial_clear(); } #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE if (curses_flags & F_ENABLE_CONSOLE) { /* Clear the screen and kill the cursor */ @@ -719,7 +719,7 @@ int whline(WINDOW *win, chtype ch, int n) (((c) & 0x4400) >> 2) | ((c) & 0xAA00) | (((c) & 0x1100) << 2) int wnoutrefresh(WINDOW *win) { -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE // FIXME. int serial_is_bold = 0; int serial_is_reverse = 0; @@ -732,7 +732,7 @@ int wnoutrefresh(WINDOW *win) int x, y; chtype ch; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE serial_end_bold(); serial_end_altcharset(); #endif @@ -744,7 +744,7 @@ int wnoutrefresh(WINDOW *win) /* Position the serial cursor */ -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) serial_set_cursor(win->_begy + y, win->_begx + win->_line[y].firstchar); @@ -753,7 +753,7 @@ int wnoutrefresh(WINDOW *win) for (x = win->_line[y].firstchar; x <= win->_line[y].lastchar; x++) { attr_t attr = win->_line[y].text[x].attr; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) { ch = win->_line[y].text[x].chars[0]; @@ -819,7 +819,7 @@ int wnoutrefresh(WINDOW *win) } #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE unsigned int c = ((int)color_pairs[PAIR_NUMBER(attr)]) << 8; @@ -860,12 +860,12 @@ int wnoutrefresh(WINDOW *win) win->_line[y].lastchar = _NOCHANGE; } -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_LP_SERIAL_CONSOLE if (curses_flags & F_ENABLE_SERIAL) serial_set_cursor(win->_begy + win->_cury, win->_begx + win->_curx); #endif -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE if (curses_flags & F_ENABLE_CONSOLE) video_console_set_cursor(win->_begx + win->_curx, win->_begy + win->_cury); #endif diff --git a/payloads/libpayload/drivers/Makefile.inc b/payloads/libpayload/drivers/Makefile.inc index 60e0fab369..2712f048be 100644 --- a/payloads/libpayload/drivers/Makefile.inc +++ b/payloads/libpayload/drivers/Makefile.inc @@ -29,52 +29,70 @@ ## SUCH DAMAGE. ## -libc-$(CONFIG_PCI) += pci.c +libc-$(CONFIG_LP_PCI) += pci.c -libc-$(CONFIG_SPEAKER) += speaker.c +libc-$(CONFIG_LP_SPEAKER) += speaker.c -libc-$(CONFIG_X86_SERIAL_CONSOLE) += serial.c +libc-$(CONFIG_LP_8250_SERIAL_CONSOLE) += serial/8250.c +libc-$(CONFIG_LP_S5P_SERIAL_CONSOLE) += serial/s5p.c +libc-$(CONFIG_LP_8250_MMIO32_SERIAL_CONSOLE) += serial/8250_mmio32.c +libc-$(CONFIG_LP_IPQ806X_SERIAL_CONSOLE) += serial/ipq806x.c +libc-$(CONFIG_LP_BG4CD_SERIAL_CONSOLE) += serial/bg4cd.c +libc-$(CONFIG_LP_PC_KEYBOARD) += keyboard.c -libc-$(CONFIG_PC_KEYBOARD) += keyboard.c +libc-$(CONFIG_LP_CBMEM_CONSOLE) += cbmem_console.c -libc-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.c +libc-$(CONFIG_LP_NVRAM) += nvram.c +libc-$(CONFIG_LP_NVRAM) += options.c -libc-$(CONFIG_NVRAM) += nvram.c -libc-$(CONFIG_NVRAM) += options.c +# Timer drivers +libc-$(CONFIG_LP_TIMER_MCT) += timer/mct.c +libc-$(CONFIG_LP_TIMER_RDTSC) += timer/rdtsc.c +libc-$(CONFIG_LP_TIMER_TEGRA_1US) += timer/tegra_1us.c +libc-$(CONFIG_LP_TIMER_IPQ806X) += timer/ipq806x.c +libc-$(CONFIG_LP_TIMER_RK) += timer/rktimer.c +libc-$(CONFIG_LP_TIMER_BG4CD) += timer/bg4cd.c # Video console drivers -libc-$(CONFIG_VIDEO_CONSOLE) += video/video.c -libc-$(CONFIG_VGA_VIDEO_CONSOLE) += video/vga.c +libc-$(CONFIG_LP_VIDEO_CONSOLE) += video/video.c +libc-$(CONFIG_LP_VGA_VIDEO_CONSOLE) += video/vga.c # Geode LX console drivers -libc-$(CONFIG_GEODELX_VIDEO_CONSOLE) += video/geodelx.c -libc-$(CONFIG_GEODELX_VIDEO_CONSOLE) += video/font8x16.c +libc-$(CONFIG_LP_GEODELX_VIDEO_CONSOLE) += video/geodelx.c +libc-$(CONFIG_LP_GEODELX_VIDEO_CONSOLE) += video/font8x16.c # coreboot generic framebuffer driver -libc-$(CONFIG_COREBOOT_VIDEO_CONSOLE) += video/corebootfb.c -libc-$(CONFIG_COREBOOT_VIDEO_CONSOLE) += video/font8x16.c +libc-$(CONFIG_LP_COREBOOT_VIDEO_CONSOLE) += video/corebootfb.c +libc-$(CONFIG_LP_COREBOOT_VIDEO_CONSOLE) += video/font8x16.c -libc-$(CONFIG_STORAGE) += storage/storage.c -libc-$(CONFIG_STORAGE_ATA) += storage/ata.c -libc-$(CONFIG_STORAGE_ATAPI) += storage/atapi.c -libc-$(CONFIG_STORAGE_AHCI) += storage/ahci.c +libc-$(CONFIG_LP_STORAGE) += storage/storage.c +libc-$(CONFIG_LP_STORAGE_ATA) += storage/ata.c +libc-$(CONFIG_LP_STORAGE_ATAPI) += storage/atapi.c +libc-$(CONFIG_LP_STORAGE_AHCI) += storage/ahci.c # USB stack -libc-$(CONFIG_USB) += usb/usbinit.c -libc-$(CONFIG_USB) += usb/usb.c -libc-$(CONFIG_USB) += usb/usb_dev.c -libc-$(CONFIG_USB) += usb/quirks.c -libc-$(CONFIG_USB_HUB) += usb/usbhub.c -libc-$(CONFIG_USB_UHCI) += usb/uhci.c -libc-$(CONFIG_USB_UHCI) += usb/uhci_rh.c -libc-$(CONFIG_USB_OHCI) += usb/ohci.c -libc-$(CONFIG_USB_OHCI) += usb/ohci_rh.c -libc-$(CONFIG_USB_EHCI) += usb/ehci.c -libc-$(CONFIG_USB_EHCI) += usb/ehci_rh.c -libc-$(CONFIG_USB_XHCI) += usb/xhci.c -libc-$(CONFIG_USB_XHCI) += usb/xhci_rh.c -libc-$(CONFIG_USB_HID) += usb/usbhid.c -libc-$(CONFIG_USB_MSC) += usb/usbmsc.c +libc-$(CONFIG_LP_USB) += usb/usbinit.c +libc-$(CONFIG_LP_USB) += usb/usb.c +libc-$(CONFIG_LP_USB) += usb/usb_dev.c +libc-$(CONFIG_LP_USB) += usb/quirks.c +libc-$(CONFIG_LP_USB_GEN_HUB) += usb/generic_hub.c +libc-$(CONFIG_LP_USB_HUB) += usb/usbhub.c +libc-$(CONFIG_LP_USB_UHCI) += usb/uhci.c +libc-$(CONFIG_LP_USB_UHCI) += usb/uhci_rh.c +libc-$(CONFIG_LP_USB_OHCI) += usb/ohci.c +libc-$(CONFIG_LP_USB_OHCI) += usb/ohci_rh.c +libc-$(CONFIG_LP_USB_EHCI) += usb/ehci.c +libc-$(CONFIG_LP_USB_EHCI) += usb/ehci_rh.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci_debug.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci_devconf.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci_events.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci_commands.c +libc-$(CONFIG_LP_USB_XHCI) += usb/xhci_rh.c +libc-$(CONFIG_LP_USB_HID) += usb/usbhid.c +libc-$(CONFIG_LP_USB_MSC) += usb/usbmsc.c +libc-$(CONFIG_LP_USB_DWC2) += usb/dwc2.c +libc-$(CONFIG_LP_USB_DWC2) += usb/dwc2_rh.c # used by both USB HID and keyboard libc-y += hid.c diff --git a/payloads/libpayload/drivers/cbmem_console.c b/payloads/libpayload/drivers/cbmem_console.c index 0d3b35fccb..687344400c 100644 --- a/payloads/libpayload/drivers/cbmem_console.c +++ b/payloads/libpayload/drivers/cbmem_console.c @@ -40,7 +40,7 @@ static struct cbmem_console *cbmem_console_p; static struct console_output_driver cbmem_console_driver = { - .putchar = &cbmem_console_putc + .write = &cbmem_console_write, }; void cbmem_console_init(void) @@ -50,11 +50,11 @@ void cbmem_console_init(void) console_add_output_driver(&cbmem_console_driver); } -void cbmem_console_putc(unsigned int data) +void cbmem_console_write(const void *buffer, size_t count) { - // Bail out if the buffer is full. - if (cbmem_console_p->cursor >= cbmem_console_p->size) + if (cbmem_console_p->cursor + count >= cbmem_console_p->size) return; - cbmem_console_p->body[cbmem_console_p->cursor++] = data; + memcpy(cbmem_console_p->body + cbmem_console_p->cursor, buffer, count); + cbmem_console_p->cursor += count; } diff --git a/payloads/libpayload/drivers/keyboard.c b/payloads/libpayload/drivers/keyboard.c index cfb4d0bf49..8525a3e7fa 100644 --- a/payloads/libpayload/drivers/keyboard.c +++ b/payloads/libpayload/drivers/keyboard.c @@ -31,10 +31,7 @@ #include #include -#define I8042_CMD_READ_MODE 0x20 -#define I8042_CMD_WRITE_MODE 0x60 - -#define I8042_MODE_XLATE 0x40 +#define I8042_CMD_DIS_KB 0xad struct layout_maps { const char *country; @@ -44,7 +41,7 @@ struct layout_maps { static struct layout_maps *map; static struct layout_maps keyboard_layouts[] = { -#ifdef CONFIG_PC_KEYBOARD_LAYOUT_US +#ifdef CONFIG_LP_PC_KEYBOARD_LAYOUT_US { .country = "us", .map = { { /* No modifier */ 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, @@ -100,7 +97,7 @@ static struct layout_maps keyboard_layouts[] = { } }}, #endif -#ifdef CONFIG_PC_KEYBOARD_LAYOUT_DE +#ifdef CONFIG_LP_PC_KEYBOARD_LAYOUT_DE { .country = "de", .map = { { /* No modifier */ 0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, @@ -261,16 +258,6 @@ int keyboard_getchar(void) return ret; } -static int keyboard_wait_read(void) -{ - int retries = 10000; - - while(retries-- && !(inb(0x64) & 0x01)) - udelay(50); - - return (retries <= 0) ? -1 : 0; -} - static int keyboard_wait_write(void) { int retries = 10000; @@ -281,20 +268,6 @@ static int keyboard_wait_write(void) return (retries <= 0) ? -1 : 0; } -static unsigned char keyboard_get_mode(void) -{ - outb(I8042_CMD_READ_MODE, 0x64); - keyboard_wait_read(); - return inb(0x60); -} - -static void keyboard_set_mode(unsigned char mode) -{ - outb(I8042_CMD_WRITE_MODE, 0x64); - keyboard_wait_write(); - outb(mode, 0x60); -} - /** * Set keyboard layout * @param country string describing the keyboard layout language. @@ -326,29 +299,35 @@ static struct console_input_driver cons = { void keyboard_init(void) { - u8 mode; map = &keyboard_layouts[0]; /* If 0x64 returns 0xff, then we have no keyboard * controller */ - if (inb(0x64) == 0xFF) return; /* Empty keyboard buffer */ while (keyboard_havechar()) keyboard_getchar(); - /* Read the current mode */ - mode = keyboard_get_mode(); - - /* Turn on scancode translate mode so that we can - use the scancode set 1 tables */ - - mode |= I8042_MODE_XLATE; - - /* Write the new mode */ - keyboard_set_mode(mode); - console_add_input_driver(&cons); } +void keyboard_disconnect(void) +{ + /* If 0x64 returns 0xff, then we have no keyboard + * controller */ + if (inb(0x64) == 0xFF) + return; + + /* Empty keyboard buffer */ + while (keyboard_havechar()) + keyboard_getchar(); + + /* Send keyboard disconnect command */ + outb(I8042_CMD_DIS_KB, 0x64); + keyboard_wait_write(); + + /* Hand off with empty buffer */ + while (keyboard_havechar()) + keyboard_getchar(); +} diff --git a/payloads/libpayload/drivers/nvram.c b/payloads/libpayload/drivers/nvram.c index 86ff670425..a046c8e6cd 100644 --- a/payloads/libpayload/drivers/nvram.c +++ b/payloads/libpayload/drivers/nvram.c @@ -60,7 +60,7 @@ * doesn't try to do this on its own. */ #define RTC_PORT_STANDARD 0x70 -#ifdef CONFIG_RTC_PORT_EXTENDED_VIA +#ifdef CONFIG_LP_RTC_PORT_EXTENDED_VIA #define RTC_PORT_EXTENDED 0x74 #else #define RTC_PORT_EXTENDED 0x72 diff --git a/payloads/libpayload/drivers/serial.c b/payloads/libpayload/drivers/serial/8250.c similarity index 92% rename from payloads/libpayload/drivers/serial.c rename to payloads/libpayload/drivers/serial/8250.c index df0f2e3438..921f47fe4f 100644 --- a/payloads/libpayload/drivers/serial.c +++ b/payloads/libpayload/drivers/serial/8250.c @@ -39,7 +39,7 @@ static int serial_is_mem_mapped = 0; static uint8_t serial_read_reg(int offset) { -#ifdef CONFIG_IO_ADDRESS_SPACE +#ifdef CONFIG_LP_IO_ADDRESS_SPACE if (!serial_is_mem_mapped) return inb(IOBASE + offset); else @@ -49,7 +49,7 @@ static uint8_t serial_read_reg(int offset) static void serial_write_reg(uint8_t val, int offset) { -#ifdef CONFIG_IO_ADDRESS_SPACE +#ifdef CONFIG_LP_IO_ADDRESS_SPACE if (!serial_is_mem_mapped) outb(val, IOBASE + offset); else @@ -57,12 +57,13 @@ static void serial_write_reg(uint8_t val, int offset) writeb(val, MEMBASE + offset); } -#ifdef CONFIG_SERIAL_SET_SPEED +#ifdef CONFIG_LP_SERIAL_SET_SPEED static void serial_hardware_init(int speed, int word_bits, int parity, int stop_bits) { unsigned char reg; +#ifndef PL011_SERIAL_CONSOLE /* Disable interrupts. */ serial_write_reg(0, 0x01); @@ -81,6 +82,7 @@ static void serial_hardware_init(int speed, int word_bits, /* Restore the previous value of the divisor. * And set 8 bits per character */ serial_write_reg((reg & ~0x80) | 3, 0x03); +#endif } #endif @@ -102,7 +104,7 @@ void serial_init(void) (lib_sysinfo.serial->type == CB_SERIAL_TYPE_MEMORY_MAPPED); if (!serial_is_mem_mapped) { -#ifdef CONFIG_IO_ADDRESS_SPACE +#ifdef CONFIG_LP_IO_ADDRESS_SPACE if ((inb(IOBASE + 0x05) == 0xFF) && (inb(IOBASE + 0x06) == 0xFF)) { return; @@ -116,9 +118,18 @@ void serial_init(void) serial_hardware_is_present = 1; -#ifdef CONFIG_SERIAL_SET_SPEED - serial_hardware_init(CONFIG_SERIAL_BAUD_RATE, 8, 0, 1); +#ifdef CONFIG_LP_SERIAL_SET_SPEED + serial_hardware_init(CONFIG_LP_SERIAL_BAUD_RATE, 8, 0, 1); #endif +} + +void serial_console_init(void) +{ + if (!lib_sysinfo.serial) + return; + + serial_init(); + console_add_input_driver(&consin); console_add_output_driver(&consout); } @@ -127,8 +138,12 @@ void serial_putchar(unsigned int c) { if (!serial_hardware_is_present) return; +#ifndef CONFIG_LP_PL011_SERIAL_CONSOLE while ((serial_read_reg(0x05) & 0x20) == 0) ; +#endif serial_write_reg(c, 0x00); + if (c == '\n') + serial_putchar('\r'); } int serial_havechar(void) diff --git a/payloads/libpayload/drivers/serial/8250_mmio32.c b/payloads/libpayload/drivers/serial/8250_mmio32.c new file mode 100644 index 0000000000..285f7f6dac --- /dev/null +++ b/payloads/libpayload/drivers/serial/8250_mmio32.c @@ -0,0 +1,113 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +struct mmio32_uart { + union { + uint32_t thr; // Transmit holding register. + uint32_t rbr; // Receive buffer register. + uint32_t dll; // Divisor latch lsb. + }; + union { + uint32_t ier; // Interrupt enable register. + uint32_t dlm; // Divisor latch msb. + }; + union { + uint32_t iir; // Interrupt identification register. + uint32_t fcr; // FIFO control register. + }; + uint32_t lcr; // Line control register. + uint32_t mcr; // Modem control register. + uint32_t lsr; // Line status register. + uint32_t msr; // Modem status register. +} __attribute__ ((packed)); + +enum { + LSR_DR = 0x1 << 0, // Data ready. + LSR_OE = 0x1 << 1, // Overrun. + LSR_PE = 0x1 << 2, // Parity error. + LSR_FE = 0x1 << 3, // Framing error. + LSR_BI = 0x1 << 4, // Break. + LSR_THRE = 0x1 << 5, // Xmit holding register empty. + LSR_TEMT = 0x1 << 6, // Xmitter empty. + LSR_ERR = 0x1 << 7 // Error. +}; + +static struct mmio32_uart *uart = NULL; + +void serial_putchar(unsigned int c) +{ + while (!(readl(&uart->lsr) & LSR_THRE)) + /* wait for transmit register to clear */; + + writel((char)c, &uart->thr); + if (c == '\n') + serial_putchar('\r'); +} + +int serial_havechar(void) +{ + uint8_t lsr = readl(&uart->lsr); + return (lsr & LSR_DR) == LSR_DR; +} + +int serial_getchar(void) +{ + while (!serial_havechar()) + /* wait for character */; + + return readl(&uart->rbr); +} + +static struct console_output_driver mmio32_serial_output = { + .putchar = &serial_putchar +}; + +static struct console_input_driver mmio32_serial_input = { + .havekey = &serial_havechar, + .getchar = &serial_getchar +}; + +void serial_init(void) +{ + if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr) + return; + + uart = (struct mmio32_uart *)(uintptr_t)lib_sysinfo.serial->baseaddr; +} + +void serial_console_init(void) +{ + serial_init(); + + if (uart) { + console_add_output_driver(&mmio32_serial_output); + console_add_input_driver(&mmio32_serial_input); + } +} diff --git a/payloads/libpayload/drivers/serial/bg4cd.c b/payloads/libpayload/drivers/serial/bg4cd.c new file mode 100644 index 0000000000..9dfa996b39 --- /dev/null +++ b/payloads/libpayload/drivers/serial/bg4cd.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +void serial_putchar(unsigned int c) +{ +} + +int serial_havechar(void) +{ + return 0; +} + +int serial_getchar(void) +{ + return 0; +} + +static struct console_input_driver consin = { + .havekey = &serial_havechar, + .getchar = &serial_getchar +}; + +static struct console_output_driver consout = { + .putchar = &serial_putchar +}; + +void serial_console_init(void) +{ + console_add_input_driver(&consin); + console_add_output_driver(&consout); +} diff --git a/payloads/libpayload/drivers/serial/ipq806x.c b/payloads/libpayload/drivers/serial/ipq806x.c new file mode 100644 index 0000000000..912893d7e2 --- /dev/null +++ b/payloads/libpayload/drivers/serial/ipq806x.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2014 Chromium OS authors + */ + +#include + +enum IPQ_UART_DM_PARITY_MODE { + IPQ_UART_DM_NO_PARITY, + IPQ_UART_DM_ODD_PARITY, + IPQ_UART_DM_EVEN_PARITY, + IPQ_UART_DM_SPACE_PARITY +}; + +/* UART Stop Bit Length */ +enum IPQ_UART_DM_STOP_BIT_LEN { + IPQ_UART_DM_SBL_9_16, + IPQ_UART_DM_SBL_1, + IPQ_UART_DM_SBL_1_9_16, + IPQ_UART_DM_SBL_2 +}; + +/* UART Bits per Char */ +enum IPQ_UART_DM_BITS_PER_CHAR { + IPQ_UART_DM_5_BPS, + IPQ_UART_DM_6_BPS, + IPQ_UART_DM_7_BPS, + IPQ_UART_DM_8_BPS +}; + +#define IPQ_UART_DM_CR(base) (((u8 *)(base)) + 0x10) +#define IPQ_UART_DM_DMEN(base) (((u8 *)(base)) + 0x3C) +#define IPQ_UART_DM_DMRX(base) (((u8 *)(base)) + 0x34) +#define IPQ_UART_DM_HCR(base) (((u8 *)(base)) + 0x24) +#define IPQ_UART_DM_IMR(base) (((u8 *)(base)) + 0x14) +#define IPQ_UART_DM_IPR(base) (((u8 *)(base)) + 0x18) +#define IPQ_UART_DM_IRDA(base) (((u8 *)(base)) + 0x38) +#define IPQ_UART_DM_MISR(base) (((u8 *)(base)) + 0x10) +#define IPQ_UART_DM_MR1(base) (((u8 *)(base)) + 0x00) +#define IPQ_UART_DM_MR2(base) (((u8 *)(base)) + 0x04) +#define IPQ_UART_DM_NO_CHARS_FOR_TX(base) (((u8 *)(base)) + 0x040) +#define IPQ_UART_DM_RF(base, x) (((u8 *)(base)) + 0x70 + 4*(x)) +#define IPQ_UART_DM_RFWR(base) (((u8 *)(base)) + 0x20) +#define IPQ_UART_DM_RX_TOTAL_SNAP(base) (((u8 *)(base)) + 0x38) +#define IPQ_UART_DM_SR(base) (((u8 *)(base)) + 0x008) +#define IPQ_UART_DM_TF(base, x) (((u8 *)(base)) + 0x70 + 4*(x)) +#define IPQ_UART_DM_TFWR(base) (((u8 *)(base)) + 0x1C) + +#define IPQ_UART_DM_TXLEV (1 << 0) +#define IPQ_UART_DM_TX_READY (1 << 7) + +#define IPQ_UART_DM_CR_CH_CMD_LSB(x) ((x & 0x0f) << 4) +#define IPQ_UART_DM_CR_CH_CMD_MSB(x) ((x >> 4 ) << 11 ) +#define IPQ_UART_DM_CR_CH_CMD(x) (IPQ_UART_DM_CR_CH_CMD_LSB(x)\ + | IPQ_UART_DM_CR_CH_CMD_MSB(x)) + +#define IPQ_UART_DM_CR_GENERAL_CMD(x) ((x) << 8) + +#define IPQ_UART_DM_8_N_1_MODE (IPQ_UART_DM_NO_PARITY | \ + (IPQ_UART_DM_SBL_1 << 2) | \ + (IPQ_UART_DM_8_BPS << 4)) +#define IPQ_UART_DM_CR_RX_ENABLE (1 << 0) +#define IPQ_UART_DM_CR_TX_ENABLE (1 << 2) +#define IPQ_UART_DM_CMD_RESET_RX IPQ_UART_DM_CR_CH_CMD(1) +#define IPQ_UART_DM_CMD_RESET_TX IPQ_UART_DM_CR_CH_CMD(2) +#define IPQ_UART_DM_CMD_RESET_ERR_STAT IPQ_UART_DM_CR_CH_CMD(3) +#define IPQ_UART_DM_CMD_RES_STALE_INT IPQ_UART_DM_CR_CH_CMD(8) +#define IPQ_UART_DM_CMD_RES_TX_ERR IPQ_UART_DM_CR_CH_CMD(10) +#define IPQ_UART_DM_GCMD_ENA_STALE_EVT IPQ_UART_DM_CR_GENERAL_CMD(5) +#define IPQ_UART_DM_RXSTALE (1 << 3) +#define IPQ_UART_DM_IMR_ENABLED (IPQ_UART_DM_TX_READY | \ + IPQ_UART_DM_TXLEV | \ + IPQ_UART_DM_RXSTALE) +#define IPQ_UART_DM_TFW_VALUE 0 +#define IPQ_UART_DM_RFW_VALUE 1 +#define IPQ_UART_DM_DMRX_DEF_VALUE 0x220 +#define IPQ_UART_DM_SR_TXEMT (1 << 3) +#define IPQ_UART_DM_SR_UART_OVERRUN (1 << 4) +#define IPQ_UART_DM_E_SUCCESS 0 +#define IPQ_UART_DM_E_INVAL 3 +#define IPQ_UART_DM_E_RX_NOT_READY 5 + +#define IPQ_UART_DM_STALE_TIMEOUT_LSB 0x0f + +static struct console_input_driver consin = {}; +static struct console_output_driver consout = {}; + +#define FIFO_DATA_SIZE 4 + +static void *base_uart_addr; + +/* + * All constants lifted from u-boot's + * board/qcom/ipq806x_cdp/ipq806x_board_param.h + */ +static unsigned int msm_boot_uart_dm_init(void *uart_dm_base); + +/* Number of pending received characters */ +static int uart_ready_data_count; + +/* Received data as it came from 32 bit wide FIFO */ +static unsigned int uart_rx_fifo_word; + +/** + * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer + * @uart_dm_base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base) +{ + /* Reset receiver */ + writel(IPQ_UART_DM_CMD_RESET_RX, + IPQ_UART_DM_CR(uart_dm_base)); + + /* Enable receiver */ + writel(IPQ_UART_DM_CR_RX_ENABLE, + IPQ_UART_DM_CR(uart_dm_base)); + writel(IPQ_UART_DM_DMRX_DEF_VALUE, + IPQ_UART_DM_DMRX(uart_dm_base)); + + /* Clear stale event */ + writel(IPQ_UART_DM_CMD_RES_STALE_INT, + IPQ_UART_DM_CR(uart_dm_base)); + + /* Enable stale event */ + writel(IPQ_UART_DM_GCMD_ENA_STALE_EVT, + IPQ_UART_DM_CR(uart_dm_base)); + + return IPQ_UART_DM_E_SUCCESS; +} + +/** + * Reads a word from the RX FIFO or returns not ready. + */ +static unsigned msm_boot_uart_dm_read(void) +{ + static int total_rx_data = 0; + static int rx_data_read = 0; + void *base = base_uart_addr; + uint32_t status_reg; + + /* RXSTALE means RX FIFO is not empty. */ + status_reg = readl(IPQ_UART_DM_MISR(base)); + if (!(status_reg & IPQ_UART_DM_RXSTALE)) + return IPQ_UART_DM_E_RX_NOT_READY; + + /* Check for Overrun error. We'll just reset Error Status */ + if (readl(IPQ_UART_DM_SR(base)) & + IPQ_UART_DM_SR_UART_OVERRUN) { + writel(IPQ_UART_DM_CMD_RESET_ERR_STAT, + IPQ_UART_DM_CR(base)); + total_rx_data = rx_data_read = 0; + msm_boot_uart_dm_init(base); + return IPQ_UART_DM_E_RX_NOT_READY; + } + + /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */ + if (total_rx_data == 0) + total_rx_data = readl(IPQ_UART_DM_RX_TOTAL_SNAP(base)); + + /* Data available in FIFO; read a word. */ + uart_rx_fifo_word = readl(IPQ_UART_DM_RF(base, 0)); + + /* + * TODO(vbendeb): this is wrong and will be addressed shortly: there + * should be no zeros returned from the FIFO in case there are + * received characters (we don't expect to be receiving zeros). + * See http://crosbug.com/p/29313 + */ + if (uart_rx_fifo_word == 0) { + return IPQ_UART_DM_E_RX_NOT_READY; + } + + /* increment the total count of chars we've read so far */ + rx_data_read += FIFO_DATA_SIZE; + + /* Actual count of valid data in word */ + uart_ready_data_count = + ((total_rx_data < rx_data_read) ? + (FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) : + FIFO_DATA_SIZE); + + /* If there are still data left in FIFO we'll read them before + * initializing RX Transfer again + */ + if (rx_data_read < total_rx_data) + return IPQ_UART_DM_E_SUCCESS; + + msm_boot_uart_dm_init_rx_transfer(base); + total_rx_data = rx_data_read = 0; + + return IPQ_UART_DM_E_SUCCESS; +} + +void serial_putchar(unsigned data) +{ + int num_of_chars = 0; + unsigned tx_data = 0; + void *base = base_uart_addr; + + if (data == '\n') { + num_of_chars++; + tx_data = '\r'; + } + + tx_data |= data << (8 * num_of_chars++); + + /* Wait until transmit FIFO is empty. */ + while (!(readl(IPQ_UART_DM_SR(base)) & + IPQ_UART_DM_SR_TXEMT)) + udelay(1); + + /* + * TX FIFO is ready to accept new character(s). First write number of + * characters to be transmitted. + */ + writel(num_of_chars, IPQ_UART_DM_NO_CHARS_FOR_TX(base)); + + /* And now write the character(s) */ + writel(tx_data, IPQ_UART_DM_TF(base, 0)); +} + +/* + * msm_boot_uart_dm_reset - resets UART controller + * @base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_reset(void *base) +{ + writel(IPQ_UART_DM_CMD_RESET_RX, IPQ_UART_DM_CR(base)); + writel(IPQ_UART_DM_CMD_RESET_TX, IPQ_UART_DM_CR(base)); + writel(IPQ_UART_DM_CMD_RESET_ERR_STAT, + IPQ_UART_DM_CR(base)); + writel(IPQ_UART_DM_CMD_RES_TX_ERR, IPQ_UART_DM_CR(base)); + writel(IPQ_UART_DM_CMD_RES_STALE_INT, IPQ_UART_DM_CR(base)); + + return IPQ_UART_DM_E_SUCCESS; +} + +/* + * msm_boot_uart_dm_init - initilaizes UART controller + * @uart_dm_base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_init(void *uart_dm_base) +{ + /* Configure UART mode registers MR1 and MR2 */ + /* Hardware flow control isn't supported */ + writel(0x0, IPQ_UART_DM_MR1(uart_dm_base)); + + /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */ + writel(IPQ_UART_DM_8_N_1_MODE, + IPQ_UART_DM_MR2(uart_dm_base)); + + /* Configure Interrupt Mask register IMR */ + writel(IPQ_UART_DM_IMR_ENABLED, + IPQ_UART_DM_IMR(uart_dm_base)); + + /* + * Configure Tx and Rx watermarks configuration registers + * TX watermark value is set to 0 - interrupt is generated when + * FIFO level is less than or equal to 0 + */ + writel(IPQ_UART_DM_TFW_VALUE, + IPQ_UART_DM_TFWR(uart_dm_base)); + + /* RX watermark value */ + writel(IPQ_UART_DM_RFW_VALUE, + IPQ_UART_DM_RFWR(uart_dm_base)); + + /* Configure Interrupt Programming Register */ + /* Set initial Stale timeout value */ + writel(IPQ_UART_DM_STALE_TIMEOUT_LSB, + IPQ_UART_DM_IPR(uart_dm_base)); + + /* Configure IRDA if required */ + /* Disabling IRDA mode */ + writel(0x0, IPQ_UART_DM_IRDA(uart_dm_base)); + + /* Configure hunt character value in HCR register */ + /* Keep it in reset state */ + writel(0x0, IPQ_UART_DM_HCR(uart_dm_base)); + + /* + * Configure Rx FIFO base address + * Both TX/RX shares same SRAM and default is half-n-half. + * Sticking with default value now. + * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries). + * We have found RAM_ADDR_WIDTH = 0x7f + */ + + /* Issue soft reset command */ + msm_boot_uart_dm_reset(uart_dm_base); + + /* Enable/Disable Rx/Tx DM interfaces */ + /* Data Mover not currently utilized. */ + writel(0, IPQ_UART_DM_DMEN(uart_dm_base)); + + /* Enable transmitter */ + writel(IPQ_UART_DM_CR_TX_ENABLE, + IPQ_UART_DM_CR(uart_dm_base)); + + /* Initialize Receive Path */ + msm_boot_uart_dm_init_rx_transfer(uart_dm_base); + + return 0; +} + +/** + * serial_havechar - checks if data available for reading + * + * Returns 1 if data available, 0 otherwise + */ +int serial_havechar(void) +{ + /* Return if data is already read */ + if (uart_ready_data_count) + return 1; + + /* Read data from the FIFO */ + if (msm_boot_uart_dm_read() != IPQ_UART_DM_E_SUCCESS) + return 0; + + return 1; +} + +/** + * ipq806x_serial_getc - reads a character + * + * Returns the character read from serial port. + */ +int serial_getchar(void) +{ + uint8_t byte; + + while (!serial_havechar()) { + /* wait for incoming data */ + } + + byte = (uint8_t)(uart_rx_fifo_word & 0xff); + uart_rx_fifo_word = uart_rx_fifo_word >> 8; + uart_ready_data_count--; + + return byte; +} + +/* For simplicity sake let's rely on coreboot initalizing the UART. */ +void serial_console_init(void) +{ + struct cb_serial *sc_ptr = lib_sysinfo.serial; + + if (!sc_ptr) + return; + + base_uart_addr = (void *) sc_ptr->baseaddr; + + consin.havekey = serial_havechar; + consin.getchar = serial_getchar; + + consout.putchar = serial_putchar; + + console_add_output_driver(&consout); + console_add_input_driver(&consin); +} diff --git a/payloads/libpayload/drivers/serial/s5p.c b/payloads/libpayload/drivers/serial/s5p.c new file mode 100644 index 0000000000..1d23352ec4 --- /dev/null +++ b/payloads/libpayload/drivers/serial/s5p.c @@ -0,0 +1,106 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +struct s5p_uart +{ + uint32_t ulcon; // line control + uint32_t ucon; // control + uint32_t ufcon; // FIFO control + uint32_t umcon; // modem control + uint32_t utrstat; // Tx/Rx status + uint32_t uerstat; // Rx error status + uint32_t ufstat; // FIFO status + uint32_t umstat; // modem status + uint32_t utxh; // transmit buffer + uint32_t urxh; // receive buffer + uint32_t ubrdiv; // baud rate divisor + uint32_t ufracval; // divisor fractional value + uint32_t uintp; // interrupt pending + uint32_t uints; // interrupt source + uint32_t uintm; // interrupt mask +}; + +static struct s5p_uart *uart_regs; + +void serial_putchar(unsigned int c) +{ + const uint32_t TxFifoFullBit = (0x1 << 24); + + while (readl(&uart_regs->ufstat) & TxFifoFullBit) + {;} + + writeb(c, &uart_regs->utxh); + if (c == '\n') + serial_putchar('\r'); +} + +int serial_havechar(void) +{ + const uint32_t DataReadyMask = (0xf << 0) | (0x1 << 8); + + return (readl(&uart_regs->ufstat) & DataReadyMask) != 0; +} + +int serial_getchar(void) +{ + while (!serial_havechar()) + {;} + + return readb(&uart_regs->urxh); +} + +static struct console_output_driver s5p_serial_output = +{ + .putchar = &serial_putchar +}; + +static struct console_input_driver s5p_serial_input = +{ + .havekey = &serial_havechar, + .getchar = &serial_getchar +}; + +void serial_init(void) +{ + if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr) + return; + + uart_regs = (struct s5p_uart *)lib_sysinfo.serial->baseaddr; +} + +void serial_console_init(void) +{ + serial_init(); + + if (uart_regs) { + console_add_output_driver(&s5p_serial_output); + console_add_input_driver(&s5p_serial_input); + } +} diff --git a/payloads/libpayload/drivers/storage/ahci.c b/payloads/libpayload/drivers/storage/ahci.c index b33cc708b6..0ba33f1b20 100644 --- a/payloads/libpayload/drivers/storage/ahci.c +++ b/payloads/libpayload/drivers/storage/ahci.c @@ -274,7 +274,7 @@ static ssize_t ahci_ata_read_sectors(ata_dev_t *const ata_dev, printf("ahci: Sector count too high (max. 256).\n"); count = 256; } -#ifdef CONFIG_STORAGE_64BIT_LBA +#ifdef CONFIG_LP_STORAGE_64BIT_LBA } else if (ata_dev->read_cmd == ATA_READ_DMA_EXT) { if (start >= (1ULL << 48)) { printf("ahci: Sector is not 48-bit addressable.\n"); @@ -302,7 +302,7 @@ static ssize_t ahci_ata_read_sectors(ata_dev_t *const ata_dev, dev->cmdtable->fis[ 6] = (start >> 16) & 0xff; dev->cmdtable->fis[ 7] = FIS_H2D_DEV_LBA; dev->cmdtable->fis[ 8] = (start >> 24) & 0xff; -#ifdef CONFIG_STORAGE_64BIT_LBA +#ifdef CONFIG_LP_STORAGE_64BIT_LBA if (ata_dev->read_cmd == ATA_READ_DMA_EXT) { dev->cmdtable->fis[ 9] = (start >> 32) & 0xff; dev->cmdtable->fis[10] = (start >> 40) & 0xff; @@ -404,7 +404,7 @@ static int ahci_dev_init(hba_ctrl_t *const ctrl, switch (port->signature) { case HBA_PxSIG_ATA: printf("ahci: ATA drive on port #%d.\n", portnum); -#ifdef CONFIG_STORAGE_ATA +#ifdef CONFIG_LP_STORAGE_ATA dev->ata_dev.identify = ahci_identify_device; dev->ata_dev.read_sectors = ahci_ata_read_sectors; return ata_attach_device(&dev->ata_dev, PORT_TYPE_SATA); @@ -412,7 +412,7 @@ static int ahci_dev_init(hba_ctrl_t *const ctrl, break; case HBA_PxSIG_ATAPI: printf("ahci: ATAPI drive on port #%d.\n", portnum); -#ifdef CONFIG_STORAGE_ATAPI +#ifdef CONFIG_LP_STORAGE_ATAPI dev->atapi_dev.identify = ahci_identify_device; dev->atapi_dev.packet_read_cmd = ahci_packet_read_cmd; return atapi_attach_device(&dev->atapi_dev, PORT_TYPE_SATA); @@ -469,7 +469,7 @@ static void ahci_port_probe(hba_ctrl_t *const ctrl, ahci_dev_init(ctrl, port, portnum); } -#ifdef CONFIG_STORAGE_AHCI_ONLY_TESTED +#ifdef CONFIG_LP_STORAGE_AHCI_ONLY_TESTED static u32 working_controllers[] = { 0x8086 | 0x2929 << 16, }; @@ -484,7 +484,7 @@ static void ahci_init_pci(pcidev_t dev) const u16 vendor = pci_read_config16(dev, 0x00); const u16 device = pci_read_config16(dev, 0x02); -#ifdef CONFIG_STORAGE_AHCI_ONLY_TESTED +#ifdef CONFIG_LP_STORAGE_AHCI_ONLY_TESTED const u32 vendor_device = pci_read_config32(dev, 0x0); for (i = 0; i < ARRAY_SIZE(working_controllers); ++i) if (vendor_device == working_controllers[i]) diff --git a/payloads/libpayload/drivers/storage/ata.c b/payloads/libpayload/drivers/storage/ata.c index e7d45fd8cd..f1cf28f91e 100644 --- a/payloads/libpayload/drivers/storage/ata.c +++ b/payloads/libpayload/drivers/storage/ata.c @@ -212,7 +212,7 @@ int ata_attach_device(ata_dev_t *const dev, const storage_port_t port_type) ata_strncpy(model, id + 27, sizeof(model)); printf("ata: Identified %s [%s]\n", model, fw); -#ifdef CONFIG_STORAGE_64BIT_LBA +#ifdef CONFIG_LP_STORAGE_64BIT_LBA if (id[ATA_CMDS_AND_FEATURE_SETS + 1] & (1 << 10)) { printf("ata: Support for LBA-48 enabled.\n"); dev->read_cmd = ATA_READ_DMA_EXT; diff --git a/payloads/libpayload/drivers/storage/storage.c b/payloads/libpayload/drivers/storage/storage.c index f623077733..d56da9f2d0 100644 --- a/payloads/libpayload/drivers/storage/storage.c +++ b/payloads/libpayload/drivers/storage/storage.c @@ -28,7 +28,7 @@ */ #include -#ifdef CONFIG_STORAGE_AHCI +#ifdef CONFIG_LP_STORAGE_AHCI # include #endif #include @@ -110,7 +110,7 @@ ssize_t storage_read_blocks512(const size_t dev_num, */ void storage_initialize(void) { -#ifdef CONFIG_STORAGE_AHCI +#ifdef CONFIG_LP_STORAGE_AHCI ahci_initialize(); #endif } diff --git a/src/arch/x86/init/ldscript_apc.lb b/payloads/libpayload/drivers/timer/bg4cd.c similarity index 74% rename from src/arch/x86/init/ldscript_apc.lb rename to payloads/libpayload/drivers/timer/bg4cd.c index 1c64c69551..34872a3149 100644 --- a/src/arch/x86/init/ldscript_apc.lb +++ b/payloads/libpayload/drivers/timer/bg4cd.c @@ -1,8 +1,8 @@ + /* * This file is part of the coreboot project. * - * Copyright (C) 2006 Advanced Micro Devices, Inc. - * Copyright (C) 2008-2010 coresystems GmbH + * Copyright (C) 2014 Google Electronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,15 +17,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include -INCLUDE "ldoptions" -SECTIONS +uint64_t timer_hz(void) { - .apcrom . : { - _apcrom = .; - *(.text) - *(.rodata) - *(.rodata.*) - _eapcrom = .; - } + return 0; +} + +uint64_t timer_raw_value(void) +{ + return 0; } diff --git a/payloads/libpayload/drivers/timer/ipq806x.c b/payloads/libpayload/drivers/timer/ipq806x.c new file mode 100644 index 0000000000..0d70a86813 --- /dev/null +++ b/payloads/libpayload/drivers/timer/ipq806x.c @@ -0,0 +1,59 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * TODO(vbendeb): reverted this hack once proper timer code is in place (see + * http://crosbug.com/p/28880 for details. + */ +#define MIN_TIMER_FREQ 1000000 + +uint64_t timer_hz(void) +{ + return (CONFIG_LP_IPQ806X_TIMER_FREQ >= MIN_TIMER_FREQ) ? + CONFIG_LP_IPQ806X_TIMER_FREQ : MIN_TIMER_FREQ; +} + +uint64_t timer_raw_value(void) +{ + uint64_t rawv = readl((void *)CONFIG_LP_IPQ806X_TIMER_REG); + + /* + * This is extremely crude, but it kicks in only for the case when the + * timer clock frequency is below 1MHz, which should never be the case + * on a properly configured system. The compiler will eliminate the + * check as long as config value exceeds 1MHz. + */ + if (CONFIG_LP_IPQ806X_TIMER_FREQ < MIN_TIMER_FREQ) + rawv *= (MIN_TIMER_FREQ / CONFIG_LP_IPQ806X_TIMER_FREQ); + + return rawv; +} + diff --git a/payloads/libpayload/drivers/timer/mct.c b/payloads/libpayload/drivers/timer/mct.c new file mode 100644 index 0000000000..992643d774 --- /dev/null +++ b/payloads/libpayload/drivers/timer/mct.c @@ -0,0 +1,115 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "config.h" + +struct __attribute__((packed)) mct_regs +{ + uint32_t mct_cfg; + uint8_t reserved0[0xfc]; + uint32_t g_cnt_l; + uint32_t g_cnt_u; + uint8_t reserved1[0x8]; + uint32_t g_cnt_wstat; + uint8_t reserved2[0xec]; + uint32_t g_comp0_l; + uint32_t g_comp0_u; + uint32_t g_comp0_addr_incr; + uint8_t reserved3[0x4]; + uint32_t g_comp1_l; + uint32_t g_comp1_u; + uint32_t g_comp1_addr_incr; + uint8_t reserved4[0x4]; + uint32_t g_comp2_l; + uint32_t g_comp2_u; + uint32_t g_comp2_addr_incr; + uint8_t reserved5[0x4]; + uint32_t g_comp3_l; + uint32_t g_comp3_u; + uint32_t g_comp3_addr_incr; + uint8_t reserved6[0x4]; + uint32_t g_tcon; + uint32_t g_int_cstat; + uint32_t g_int_enb; + uint32_t g_wstat; + uint8_t reserved7[0xb0]; + uint32_t l0_tcntb; + uint32_t l0_tcnto; + uint32_t l0_icntb; + uint32_t l0_icnto; + uint32_t l0_frcntb; + uint32_t l0_frcnto; + uint8_t reserved8[0x8]; + uint32_t l0_tcon; + uint8_t reserved9[0xc]; + uint32_t l0_int_cstat; + uint32_t l0_int_enb; + uint8_t reserved10[0x8]; + uint32_t l0_wstat; + uint8_t reserved11[0xbc]; + uint32_t l1_tcntb; + uint32_t l1_tcnto; + uint32_t l1_icntb; + uint32_t l1_icnto; + uint32_t l1_frcntb; + uint32_t l1_frcnto; + uint8_t reserved12[0x8]; + uint32_t l1_tcon; + uint8_t reserved13[0xc]; + uint32_t l1_int_cstat; + uint32_t l1_int_enb; + uint8_t reserved14[0x8]; + uint32_t l1_wstat; +}; + +uint64_t timer_hz(void) +{ + return CONFIG_LP_TIMER_MCT_HZ; +} + +uint64_t timer_raw_value(void) +{ + static int enabled = 0; + + struct mct_regs * const mct = + (struct mct_regs *)(uintptr_t)CONFIG_LP_TIMER_MCT_ADDRESS; + + if (!enabled) { + writel(readl(&mct->g_tcon) | (0x1 << 8), &mct->g_tcon); + enabled = 1; + } + + uint64_t upper = readl(&mct->g_cnt_u); + uint64_t lower = readl(&mct->g_cnt_l); + + return (upper << 32) | lower; +} diff --git a/payloads/libpayload/drivers/timer/rdtsc.c b/payloads/libpayload/drivers/timer/rdtsc.c new file mode 100644 index 0000000000..4a425a5bbd --- /dev/null +++ b/payloads/libpayload/drivers/timer/rdtsc.c @@ -0,0 +1,46 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * @file x86/timer.c + * x86 specific timer routines + */ + +#include +#include + +uint64_t timer_hz(void) +{ + return lib_sysinfo.cpu_khz * 1000; +} + +uint64_t timer_raw_value(void) +{ + return rdtsc(); +} diff --git a/payloads/libpayload/drivers/timer/rktimer.c b/payloads/libpayload/drivers/timer/rktimer.c new file mode 100644 index 0000000000..1634b77539 --- /dev/null +++ b/payloads/libpayload/drivers/timer/rktimer.c @@ -0,0 +1,44 @@ + +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Rockchip Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +struct rk_timer { + u32 timer_load_count0; + u32 timer_load_count1; + u32 timer_curr_value0; + u32 timer_curr_value1; + u32 timer_ctrl_reg; + u32 timer_int_status; +}; +uint64_t timer_hz(void) +{ + return 24000000; +} +uint64_t timer_raw_value(void) +{ + uint64_t upper; + uint64_t lower; + struct rk_timer *rk_timer; + rk_timer = (struct rk_timer *)CONFIG_LP_TIMER_RK_ADDRESS; + lower = (uint64_t) rk_timer->timer_curr_value0; + upper = (uint64_t) rk_timer->timer_curr_value1; + return (upper << 32) | lower; +} diff --git a/payloads/libpayload/drivers/timer/tegra_1us.c b/payloads/libpayload/drivers/timer/tegra_1us.c new file mode 100644 index 0000000000..f227ad0fdf --- /dev/null +++ b/payloads/libpayload/drivers/timer/tegra_1us.c @@ -0,0 +1,41 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +static uint32_t * const tegra_tmrus = (void *)CONFIG_LP_TIMER_TEGRA_1US_ADDRESS; + +uint64_t timer_hz(void) +{ + return 1000 * 1000; +} + +uint64_t timer_raw_value(void) +{ + return readl(tegra_tmrus); +} diff --git a/payloads/libpayload/drivers/usb/dwc2.c b/payloads/libpayload/drivers/usb/dwc2.c new file mode 100644 index 0000000000..20c55612bf --- /dev/null +++ b/payloads/libpayload/drivers/usb/dwc2.c @@ -0,0 +1,609 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Rockchip Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "dwc2.h" +#include "dwc2_private.h" + +static void dummy(hci_t *controller) +{ +} + +static void dwc2_reinit(hci_t *controller) +{ + dwc2_reg_t *reg = DWC2_REG(controller); + gusbcfg_t gusbcfg = { .d32 = 0 }; + grstctl_t grstctl = { .d32 = 0 }; + gintsts_t gintsts = { .d32 = 0 }; + gahbcfg_t gahbcfg = { .d32 = 0 }; + grxfsiz_t grxfsiz = { .d32 = 0 }; + ghwcfg3_t hwcfg3 = { .d32 = 0 }; + hcintmsk_t hcintmsk = { .d32 = 0 }; + gnptxfsiz_t gnptxfsiz = { .d32 = 0 }; + gnptxfsiz_t hptxfsiz = { .d32 = 0 }; + + const int timeout = 10000; + int i, fifo_blocks, tx_blocks; + + /* Wait for AHB idle */ + for (i = 0; i < timeout; i++) { + udelay(1); + grstctl.d32 = readl(®->core.grstctl); + if (grstctl.ahbidle) + break; + } + if (i == timeout) + fatal("DWC2 Init error AHB Idle\n"); + + /* Restart the Phy Clock */ + writel(0x0, ®->pcgr.pcgcctl); + /* Core soft reset */ + grstctl.csftrst = 1; + writel(grstctl.d32, ®->core.grstctl); + for (i = 0; i < timeout; i++) { + udelay(1); + grstctl.d32 = readl(®->core.grstctl); + if (!grstctl.csftrst) + break; + } + if (i == timeout) + fatal("DWC2 Init error reset fail\n"); + + /* Set 16bit PHY if & Force host mode */ + gusbcfg.d32 = readl(®->core.gusbcfg); + gusbcfg.phyif = 1; + gusbcfg.forcehstmode = 1; + gusbcfg.forcedevmode = 0; + writel(gusbcfg.d32, ®->core.gusbcfg); + /* Wait for force host mode effect, it may takes 100ms */ + for (i = 0; i < timeout; i++) { + udelay(10); + gintsts.d32 = readl(®->core.gintsts); + if (gintsts.curmod) + break; + } + if (i == timeout) + fatal("DWC2 Init error force host mode fail\n"); + + /* + * Config FIFO + * The non-periodic tx fifo and rx fifo share one continuous + * piece of IP-internal SRAM. + */ + + /* + * Read total data FIFO depth from HWCFG3 + * this value is in terms of 32-bit words + */ + hwcfg3.d32 = readl(®->core.ghwcfg3); + /* + * Reserve 2 spaces for the status entries of receive packets + * and 2 spaces for bulk an control OUT endpoints. Calculate how + * many blocks can be alloted, assume largest packet size is 512. + * 16 locations reserved for periodic TX . + */ + fifo_blocks = (hwcfg3.dfifodepth - 4 - 16) / (512 / 4); + tx_blocks = fifo_blocks / 2; + + grxfsiz.rxfdep = (fifo_blocks - tx_blocks) * (512 / 4) + 4; + writel(grxfsiz.d32, ®->core.grxfsiz); + gnptxfsiz.nptxfstaddr = grxfsiz.rxfdep; + gnptxfsiz.nptxfdep = tx_blocks * (512 / 4); + writel(gnptxfsiz.d32, ®->core.gnptxfsiz); + hptxfsiz.nptxfstaddr = gnptxfsiz.nptxfstaddr + gnptxfsiz.nptxfdep; + hptxfsiz.nptxfdep = 16; + writel(hptxfsiz.d32, ®->core.hptxfsiz); + + /* Init host channels */ + hcintmsk.xfercomp = 1; + hcintmsk.xacterr = 1; + hcintmsk.stall = 1; + hcintmsk.chhltd = 1; + hcintmsk.bblerr = 1; + for (i = 0; i < MAX_EPS_CHANNELS; i++) + writel(hcintmsk.d32, ®->host.hchn[i].hcintmaskn); + + /* Unmask interrupt & Use configure dma mode */ + gahbcfg.glblintrmsk = 1; + gahbcfg.hbstlen = DMA_BURST_INCR8; + gahbcfg.dmaen = 1; + writel(gahbcfg.d32, ®->core.gahbcfg); + + DWC2_INST(controller)->hprt0 = ®->host.hprt; + + usb_debug("DWC2 init finished!\n"); +} + +static void dwc2_shutdown(hci_t *controller) +{ + detach_controller(controller); + free(DWC2_INST(controller)->dma_buffer); + free(DWC2_INST(controller)); + free(controller); +} + +/* Test root port device connect status */ +static int dwc2_disconnected(hci_t *controller) +{ + dwc2_reg_t *reg = DWC2_REG(controller); + hprt_t hprt; + + hprt.d32 = readl(®->host.hprt); + return !(hprt.prtena && hprt.prtconnsts); +} + +/* + * This function return the actual transfer length when the transfer successe + * and if the transfer fail return an error code + */ +static int +wait_for_complete(endpoint_t *ep, uint32_t ch_num) +{ + hcint_t hcint; + hcchar_t hcchar; + hctsiz_t hctsiz; + dwc2_reg_t *reg = DWC2_REG(ep->dev->controller); + int timeout = 600000; /* time out after 600000 * 5us == 3s */ + + /* + * TODO: We should take care of up to three times of transfer error + * retry here, according to the USB 2.0 spec 4.5.2 + */ + do { + udelay(5); + hcint.d32 = readl(®->host.hchn[ch_num].hcintn); + hctsiz.d32 = readl(®->host.hchn[ch_num].hctsizn); + + if (hcint.chhltd) { + writel(hcint.d32, ®->host.hchn[ch_num].hcintn); + if (hcint.xfercomp || hcint.ack) + return hctsiz.xfersize; + else if (hcint.nak || hcint.frmovrun) + return -HCSTAT_NAK; + else if (hcint.xacterr) + return -HCSTAT_XFERERR; + else if (hcint.bblerr) + return -HCSTAT_BABBLE; + else if (hcint.stall) + return -HCSTAT_STALL; + else if (hcint.nyet) + return -HCSTAT_NYET; + else + return -HCSTAT_UNKNOW; + } + + if (dwc2_disconnected(ep->dev->controller)) + return -HCSTAT_DISCONNECTED; + } while (timeout--); + /* Release the channel when hit timeout condition */ + hcchar.d32 = readl(®->host.hchn[ch_num].hccharn); + if (hcchar.chen) { + /* + * Programming the HCCHARn register with the chdis and + * chena bits set to 1 at the same time to disable the + * channel and the core will generate a channel halted + * interrupt. + */ + hcchar.chdis = 1; + writel(hcchar.d32, ®->host.hchn[ch_num].hccharn); + do { + hcchar.d32 = readl(®->host.hchn[ch_num].hccharn); + } while (hcchar.chen); + + } + + /* Clear all pending interrupt flags */ + hcint.d32 = ~0; + writel(hcint.d32, ®->host.hchn[ch_num].hcintn); + + return -HCSTAT_TIMEOUT; +} + +static int +dwc2_do_xfer(endpoint_t *ep, int size, int pid, ep_dir_t dir, + uint32_t ch_num, u8 *data_buf, int *short_pkt) +{ + uint32_t do_copy; + int ret; + uint32_t packet_cnt; + uint32_t packet_size; + uint32_t transferred = 0; + uint32_t inpkt_length; + hctsiz_t hctsiz = { .d32 = 0 }; + hcchar_t hcchar = { .d32 = 0 }; + void *aligned_buf; + dwc2_reg_t *reg = DWC2_REG(ep->dev->controller); + + packet_size = ep->maxpacketsize; + packet_cnt = ALIGN_UP(size, packet_size) / packet_size; + inpkt_length = packet_cnt * packet_size; + /* At least 1 packet should be programed */ + packet_cnt = (packet_cnt == 0) ? 1 : packet_cnt; + + /* + * For an IN, this field is the buffer size that the application has + * reserved for the transfer. The application should program this field + * as integer multiple of the maximum packet size for IN transactions. + */ + hctsiz.xfersize = (dir == EPDIR_OUT) ? size : inpkt_length; + hctsiz.pktcnt = packet_cnt; + hctsiz.pid = pid; + + hcchar.mps = packet_size; + hcchar.epnum = ep->endpoint & 0xf; + hcchar.epdir = dir; + hcchar.eptype = ep->type; + hcchar.multicnt = 1; + hcchar.devaddr = ep->dev->address; + hcchar.chdis = 0; + hcchar.chen = 1; + if (ep->dev->speed == LOW_SPEED) + hcchar.lspddev = 1; + + if (size > DMA_SIZE) { + usb_debug("Transfer too large: %d\n", size); + return -1; + } + + /* + * Check the buffer address which should be 4-byte aligned and DMA + * coherent + */ + do_copy = !dma_coherent(data_buf) || ((uintptr_t)data_buf & 0x3); + aligned_buf = do_copy ? DWC2_INST(ep->dev->controller)->dma_buffer : + data_buf; + + if (do_copy && (dir == EPDIR_OUT)) + memcpy(aligned_buf, data_buf, size); + + if (dwc2_disconnected(ep->dev->controller)) + return -HCSTAT_DISCONNECTED; + + writel(hctsiz.d32, ®->host.hchn[ch_num].hctsizn); + writel((uint32_t)aligned_buf, ®->host.hchn[ch_num].hcdman); + writel(hcchar.d32, ®->host.hchn[ch_num].hccharn); + + ret = wait_for_complete(ep, ch_num); + + if (ret >= 0) { + /* Calculate actual transferred length */ + transferred = (dir == EPDIR_IN) ? inpkt_length - ret : size; + + if (do_copy && (dir == EPDIR_IN)) + memcpy(data_buf, aligned_buf, transferred); + + if ((short_pkt != NULL) && (dir == EPDIR_IN)) + *short_pkt = (ret > 0) ? 1 : 0; + + } + + /* Save data toggle */ + hctsiz.d32 = readl(®->host.hchn[ch_num].hctsizn); + ep->toggle = hctsiz.pid; + + if (ret < 0) { + usb_debug("%s Transfer stop code: %x\n", __func__, ret); + return ret; + } + return transferred; +} + +static int +dwc2_split_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir, + uint32_t ch_num, u8 *data_buf, split_info_t *split, + int *short_pkt) +{ + dwc2_reg_t *reg = DWC2_REG(ep->dev->controller); + hfnum_t hfnum; + hcsplit_t hcsplit = { .d32 = 0 }; + int ret, transferred = 0; + + hcsplit.hubaddr = split->hubaddr; + hcsplit.prtaddr = split->hubport; + hcsplit.spltena = 1; + writel(hcsplit.d32, ®->host.hchn[ch_num].hcspltn); + + /* Wait for next frame boundary */ + do { + hfnum.d32 = readl(®->host.hfnum); + + if (dwc2_disconnected(ep->dev->controller)) { + ret = -HCSTAT_DISCONNECTED; + goto out; + } + } while (hfnum.frnum % 8 != 0); + + /* Handle Start-Split */ + ret = dwc2_do_xfer(ep, dir == EPDIR_IN ? 0 : size, pid, dir, ch_num, + data_buf, NULL); + if (ret < 0) + goto out; + + hcsplit.spltena = 1; + hcsplit.compsplt = 1; + writel(hcsplit.d32, ®->host.hchn[ch_num].hcspltn); + ep->toggle = pid; + + if (dir == EPDIR_OUT) + transferred += ret; + + /* Handle Complete-Split */ + do { + ret = dwc2_do_xfer(ep, dir == EPDIR_OUT ? 0 : size, ep->toggle, + dir, ch_num, data_buf, short_pkt); + } while (ret == -HCSTAT_NYET); + + if (dir == EPDIR_IN) + transferred += ret; + +out: + /* Clear hcsplit reg */ + hcsplit.spltena = 0; + hcsplit.compsplt = 0; + writel(hcsplit.d32, ®->host.hchn[ch_num].hcspltn); + + if (ret < 0) + return ret; + + return transferred; +} + +static int dwc2_need_split(usbdev_t *dev, split_info_t *split) +{ + if (dev->speed == HIGH_SPEED) + return 0; + + if (closest_usb2_hub(dev, &split->hubaddr, &split->hubport)) + return 0; + + return 1; +} + +static int +dwc2_transfer(endpoint_t *ep, int size, int pid, ep_dir_t dir, uint32_t ch_num, + u8 *src, uint8_t skip_nak) +{ + split_info_t split; + int ret, short_pkt, transferred = 0, timeout = 3000; + + ep->toggle = pid; + + do { + short_pkt = 0; + if (dwc2_need_split(ep->dev, &split)) { +nak_retry: + ret = dwc2_split_transfer(ep, MIN(ep->maxpacketsize, + size), ep->toggle, dir, 0, src, &split, + &short_pkt); + + /* + * dwc2_split_transfer() waits for the next FullSpeed + * frame boundary, so we have one try per millisecond. + * It's 3s timeout for each split transfer. + */ + if (ret == -HCSTAT_NAK && !skip_nak && --timeout) { + udelay(500); + goto nak_retry; + } + } else { + ret = dwc2_do_xfer(ep, MIN(DMA_SIZE, size), pid, dir, 0, + src, &short_pkt); + } + + if (ret < 0) + return ret; + + size -= ret; + src += ret; + transferred += ret; + + } while (size > 0 && !short_pkt); + + return transferred; +} + +static int +dwc2_bulk(endpoint_t *ep, int size, u8 *src, int finalize) +{ + ep_dir_t data_dir; + + if (ep->direction == IN) + data_dir = EPDIR_IN; + else if (ep->direction == OUT) + data_dir = EPDIR_OUT; + else + return -1; + + return dwc2_transfer(ep, size, ep->toggle, data_dir, 0, src, 0); +} + +static int +dwc2_control(usbdev_t *dev, direction_t dir, int drlen, void *setup, + int dalen, u8 *src) +{ + int ret = 0; + ep_dir_t data_dir; + endpoint_t *ep = &dev->endpoints[0]; + + if (dir == IN) + data_dir = EPDIR_IN; + else if (dir == OUT) + data_dir = EPDIR_OUT; + else + return -1; + + /* Setup Phase */ + if (dwc2_transfer(ep, drlen, PID_SETUP, EPDIR_OUT, 0, setup, 0) < 0) + return -1; + + /* Data Phase */ + ep->toggle = PID_DATA1; + if (dalen > 0) { + ret = dwc2_transfer(ep, dalen, ep->toggle, data_dir, 0, src, 0); + if (ret < 0) + return -1; + } + + /* Status Phase */ + if (dwc2_transfer(ep, 0, PID_DATA1, !data_dir, 0, NULL, 0) < 0) + return -1; + + return ret; +} + +static int +dwc2_intr(endpoint_t *ep, int size, u8 *src) +{ + ep_dir_t data_dir; + + if (ep->direction == IN) + data_dir = EPDIR_IN; + else if (ep->direction == OUT) + data_dir = EPDIR_OUT; + else + return -1; + + return dwc2_transfer(ep, size, ep->toggle, data_dir, 0, src, 1); +} + +static u32 dwc2_intr_get_timestamp(intr_queue_t *q) +{ + hprt_t hprt; + hfnum_t hfnum; + hci_t *controller = q->endp->dev->controller; + dwc_ctrl_t *dwc2 = DWC2_INST(controller); + dwc2_reg_t *reg = DWC2_REG(controller); + + hfnum.d32 = readl(®->host.hfnum); + hprt.d32 = readl(dwc2->hprt0); + + /* + * hfnum.frnum increments when a new SOF is transmitted on + * the USB, and is reset to 0 when it reaches 16'h3FFF + */ + switch (hprt.prtspd) { + case PRTSPD_HIGH: + /* 8 micro-frame per ms for high-speed */ + return hfnum.frnum / 8; + case PRTSPD_FULL: + case PRTSPD_LOW: + default: + /* 1 micro-frame per ms for high-speed */ + return hfnum.frnum / 1; + } +} + +/* create and hook-up an intr queue into device schedule */ +static void * +dwc2_create_intr_queue(endpoint_t *ep, const int reqsize, + const int reqcount, const int reqtiming) +{ + intr_queue_t *q = (intr_queue_t *)xzalloc(sizeof(intr_queue_t)); + + q->data = dma_memalign(4, reqsize); + q->endp = ep; + q->reqsize = reqsize; + q->reqtiming = reqtiming; + + return q; +} + +static void +dwc2_destroy_intr_queue(endpoint_t *ep, void *_q) +{ + intr_queue_t *q = (intr_queue_t *)_q; + + free(q->data); + free(q); +} + +/* + * read one intr-packet from queue, if available. extend the queue for + * new input. Return NULL if nothing new available. + * Recommended use: while (data=poll_intr_queue(q)) process(data); + */ +static u8 * +dwc2_poll_intr_queue(void *_q) +{ + intr_queue_t *q = (intr_queue_t *)_q; + int ret = 0; + u32 timestamp = dwc2_intr_get_timestamp(q); + + /* + * If hfnum.frnum run overflow it will schedule + * an interrupt transfer immediately + */ + if (timestamp - q->timestamp < q->reqtiming) + return NULL; + + q->timestamp = timestamp; + + ret = dwc2_intr(q->endp, q->reqsize, q->data); + + if (ret > 0) + return q->data; + else + return NULL; +} + +hci_t *dwc2_init(void *bar) +{ + hci_t *controller = new_controller(); + controller->instance = xzalloc(sizeof(dwc_ctrl_t)); + + DWC2_INST(controller)->dma_buffer = dma_malloc(DMA_SIZE); + if (!DWC2_INST(controller)->dma_buffer) { + usb_debug("Not enough DMA memory for DWC2 bounce buffer\n"); + goto free_dwc2; + } + + controller->type = DWC2; + controller->start = dummy; + controller->stop = dummy; + controller->reset = dummy; + controller->init = dwc2_reinit; + controller->shutdown = dwc2_shutdown; + controller->bulk = dwc2_bulk; + controller->control = dwc2_control; + controller->set_address = generic_set_address; + controller->finish_device_config = NULL; + controller->destroy_device = NULL; + controller->create_intr_queue = dwc2_create_intr_queue; + controller->destroy_intr_queue = dwc2_destroy_intr_queue; + controller->poll_intr_queue = dwc2_poll_intr_queue; + controller->reg_base = (uintptr_t)bar; + init_device_entry(controller, 0); + + /* Init controller */ + controller->init(controller); + + /* Setup up root hub */ + controller->devices[0]->controller = controller; + controller->devices[0]->init = dwc2_rh_init; + controller->devices[0]->init(controller->devices[0]); + return controller; + +free_dwc2: + detach_controller(controller); + free(DWC2_INST(controller)); + free(controller); + return NULL; +} diff --git a/payloads/libpayload/drivers/usb/dwc2.h b/payloads/libpayload/drivers/usb/dwc2.h new file mode 100644 index 0000000000..e9ca39db86 --- /dev/null +++ b/payloads/libpayload/drivers/usb/dwc2.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Rockchip Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __DWC2_HCD_H__ +#define __DWC2_HCD_H__ +#include + +hci_t *dwc2_init(void *bar); +void dwc2_rh_init (usbdev_t *dev); + +#endif diff --git a/payloads/libpayload/drivers/usb/dwc2_private.h b/payloads/libpayload/drivers/usb/dwc2_private.h new file mode 100644 index 0000000000..381d244f11 --- /dev/null +++ b/payloads/libpayload/drivers/usb/dwc2_private.h @@ -0,0 +1,714 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Rockchip Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __DWC2_REGS_H__ +#define __DWC2_REGS_H__ +#define MAX_EPS_CHANNELS 16 + +typedef struct core_reg { + uint32_t gotgctl; + uint32_t gotgint; + uint32_t gahbcfg; + uint32_t gusbcfg; + uint32_t grstctl; + uint32_t gintsts; + uint32_t gintmsk; + uint32_t grxstsr; + uint32_t grxstsp; + uint32_t grxfsiz; + uint32_t gnptxfsiz; + uint32_t gnptxsts; + uint32_t gi2cctl; + uint32_t gpvndctl; + uint32_t ggpio; + uint32_t guid; + uint32_t gsnpsid; + uint32_t ghwcfg1; + uint32_t ghwcfg2; + uint32_t ghwcfg3; + uint32_t ghwcfg4; + uint32_t reserved1[(0x100 - 0x54) / 4]; + uint32_t hptxfsiz; + uint32_t dptxfsiz_dieptxf[15]; + uint32_t reserved2[(0x400 - 0x140) / 4]; +} core_reg_t; + +typedef struct hc_reg { + uint32_t hccharn; + uint32_t hcspltn; + uint32_t hcintn; + uint32_t hcintmaskn; + uint32_t hctsizn; + uint32_t hcdman; + uint32_t reserved[2]; +} hc_reg_t; + +/* Host Mode Register Structures */ +typedef struct host_reg { + uint32_t hcfg; + uint32_t hfir; + uint32_t hfnum; + uint32_t reserved0; + uint32_t hptxsts; + uint32_t haint; + uint32_t haintmsk; + uint32_t reserved1[(0x440 - 0x41c) / 4]; + uint32_t hprt; + uint32_t reserved2[(0x500 - 0x444) / 4]; + hc_reg_t hchn[MAX_EPS_CHANNELS]; + uint32_t reserved3[(0x800 - 0x700) / 4]; +} host_reg_t; + +/* Device IN ep reg */ +typedef struct in_ep_reg { + uint32_t diepctl; + uint32_t reserved04; + uint32_t diepint; + uint32_t reserved0c; + uint32_t dieptsiz; + uint32_t diepdma; + uint32_t dtxfsts; + uint32_t diepdmab; +} in_ep_reg_t; + +typedef struct out_ep_reg { + uint32_t doepctl; + uint32_t reserved04; + uint32_t doepint; + uint32_t reserved0c; + uint32_t doeptsiz; + uint32_t doepdma; + uint32_t reserved18; + uint32_t doepdmab; +} out_ep_reg_t; + +/* Device Mode Registers Structures */ +typedef struct device_reg { + uint32_t dcfg; + uint32_t dctl; + uint32_t dsts; + uint32_t unused; + uint32_t diepmsk; + uint32_t doepmsk; + uint32_t daint; + uint32_t daintmsk; + uint32_t dtknqr1; + uint32_t dtknqr2; + uint32_t dvbusdis; + uint32_t dvbuspulse; + uint32_t dtknqr3_dthrctl; + uint32_t dtknqr4_fifoemptymsk; + uint32_t reserved1[(0x900 - 0x838) / 4]; + + in_ep_reg_t inep[MAX_EPS_CHANNELS]; + out_ep_reg_t outep[MAX_EPS_CHANNELS]; + uint32_t reserved8[(0xe00 - 0xd00) / 4]; +} device_reg_t; + +typedef struct pwr_clk_ctrl_reg { + uint32_t pcgcctl; + uint32_t reserved[(0x1000 - 0xe04) / 4]; +} pwr_clk_ctrl_reg_t; + +typedef struct data_fifo { + uint32_t dataport; + uint32_t reserved[(0x1000 - 0x004) / 4]; +} data_fifo_t; + +typedef struct dwc2_otg_reg { + core_reg_t core; + host_reg_t host; + device_reg_t device; + pwr_clk_ctrl_reg_t pcgr; + data_fifo_t dfifo[MAX_EPS_CHANNELS]; + uint32_t reserved[(0x40000 - 0x11000) / 4]; +} dwc2_reg_t; + +/** + * This union represents the bit fields of the Core AHB Configuration + * Register (GAHBCFG). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned glblintrmsk:1; +#define GLBINT_ENABLE 1 + + unsigned hbstlen:4; +#define DMA_BURST_SINGLE 0 +#define DMA_BURST_INCR 1 +#define DMA_BURST_INCR4 3 +#define DMA_BURST_INCR8 5 +#define DMA_BURST_INCR16 7 + + unsigned dmaen:1; + unsigned reserved:1; + unsigned nptxfemplvl:1; + unsigned ptxfemplvl:1; + unsigned reserved9_31:23; + }; +} gahbcfg_t; + +/** + * This union represents the bit fields of the Core USB Configuration + * Register (GUSBCFG). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned toutcal:3; + unsigned phyif:1; + unsigned ulpiutmisel:1; + unsigned fsintf:1; + unsigned physel:1; + unsigned ddrsel:1; + unsigned srpcap:1; + unsigned hnpcap:1; + unsigned usbtrdtim:4; + unsigned reserved14:1; + unsigned phylpwrclksel:1; + unsigned otgi2csel:1; + unsigned ulpifsls:1; + unsigned ulpiautores:1; + unsigned ulpiclksusm:1; + unsigned ulpiextvbusdrv:1; + unsigned ulpiextvbusindicator:1; + unsigned termseldlpulse:1; + unsigned reserved23_28:6; + unsigned forcehstmode:1; + unsigned forcedevmode:1; + unsigned cortxpkt:1; + }; +} gusbcfg_t; + +/** + * This union represents the bit fields of the Core Reset Register + * (GRSTCTL). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + /** Core Soft Reset (CSftRst) (Device and Host) + * + * The application can flush the control logic in the + * entire core using this bit. This bit resets the + * pipelines in the AHB Clock domain as well as the + * PHY Clock domain. + * + * The state machines are reset to an IDLE state, the + * control bits in the CSRs are cleared, all the + * transmit FIFOs and the receive FIFO are flushed. + * + * The status mask bits that control the generation of + * the interrupt, are cleared, to clear the + * interrupt. The interrupt status bits are not + * cleared, so the application can get the status of + * any events that occurred in the core after it has + * set this bit. + * + * Any transactions on the AHB are terminated as soon + * as possible following the protocol. Any + * transactions on the USB are terminated immediately. + * + * The configuration settings in the CSRs are + * unchanged, so the software doesn't have to + * reprogram these registers (Device + * Configuration/Host Configuration/Core System + * Configuration/Core PHY Configuration). + * + * The application can write to this bit, any time it + * wants to reset the core. This is a self clearing + * bit and the core clears this bit after all the + * necessary logic is reset in the core, which may + * take several clocks, depending on the current state + * of the core. + */ + unsigned csftrst:1; + /** Hclk Soft Reset + * + * The application uses this bit to reset the control logic in + * the AHB clock domain. Only AHB clock domain pipelines are + * reset. + */ + unsigned hsftrst:1; + /** Host Frame Counter Reset (Host Only)
+ * + * The application can reset the (micro)frame number + * counter inside the core, using this bit. When the + * (micro)frame counter is reset, the subsequent SOF + * sent out by the core, will have a (micro)frame + * number of 0. + */ + unsigned frmcntrrst:1; + /** In Token Sequence Learning Queue Flush + * (INTknQFlsh) (Device Only) + */ + unsigned intknqflsh:1; + /** RxFIFO Flush (RxFFlsh) (Device and Host) + * + * The application can flush the entire Receive FIFO + * using this bit.

The application must first + * ensure that the core is not in the middle of a + * transaction.

The application should write into + * this bit, only after making sure that neither the + * DMA engine is reading from the RxFIFO nor the MAC + * is writing the data in to the FIFO.

The + * application should wait until the bit is cleared + * before performing any other operations. This bit + * will takes 8 clocks (slowest of PHY or AHB clock) + * to clear. + */ + unsigned rxfflsh:1; + /** TxFIFO Flush (TxFFlsh) (Device and Host). + * + * This bit is used to selectively flush a single or + * all transmit FIFOs. The application must first + * ensure that the core is not in the middle of a + * transaction.

The application should write into + * this bit, only after making sure that neither the + * DMA engine is writing into the TxFIFO nor the MAC + * is reading the data out of the FIFO.

The + * application should wait until the core clears this + * bit, before performing any operations. This bit + * will takes 8 clocks (slowest of PHY or AHB clock) + * to clear. + */ + unsigned txfflsh:1; + + /** TxFIFO Number (TxFNum) (Device and Host). + * + * This is the FIFO number which needs to be flushed, + * using the TxFIFO Flush bit. This field should not + * be changed until the TxFIFO Flush bit is cleared by + * the core. + * - 0x0 : Non Periodic TxFIFO Flush + * - 0x1 : Periodic TxFIFO #1 Flush in device mode + * or Periodic TxFIFO in host mode + * - 0x2 : Periodic TxFIFO #2 Flush in device mode. + * - ... + * - 0xF : Periodic TxFIFO #15 Flush in device mode + * - 0x10: Flush all the Transmit NonPeriodic and + * Transmit Periodic FIFOs in the core + */ + unsigned txfnum:5; + /** Reserved */ + unsigned reserved11_29:19; + /** DMA Request Signal. Indicated DMA request is in + * probress. Used for debug purpose. */ + unsigned dmareq:1; + /** AHB Master Idle. Indicates the AHB Master State + * Machine is in IDLE condition. */ + unsigned ahbidle:1; + } ; +} grstctl_t; + +/** + * This union represents the bit fields of the Core Interrupt Mask + * Register (GINTMSK). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned curmod:1; + unsigned modemis:1; + unsigned otgint:1; + unsigned sof:1; + unsigned rxflvl:1; + unsigned nptxfemp:1; + unsigned ginnakeff:1; + unsigned goutnakeff:1; + unsigned reserved8:1; + unsigned i2cint:1; + unsigned erlysusp:1; + unsigned usbsusp:1; + unsigned usbrst:1; + unsigned enumdone:1; + unsigned isooutdrop:1; + unsigned eopf:1; + unsigned reserved16_20:5; + unsigned incompip:1; + unsigned reserved22_23:2; + unsigned prtint:1; + unsigned hchint:1; + unsigned ptxfemp:1; + unsigned reserved27:1; + unsigned conidstschng:1; + unsigned disconnint:1; + unsigned sessreqint:1; + unsigned wkupint:1; + } ; +} gintmsk_t; + +/** +* This union represents the bit fields of the Core Non-Periodic +* Transmit FIFO Size Register(GNPTXFSIZ). +*/ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned nptxfstaddr:16; + unsigned nptxfdep:16; + }; +} gnptxfsiz_t; + +/** + * This union represents the bit fields of the Core Receive FIFO Size + * Register(GRXFSIZ). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + /*The value in this fieles is in terms of 32-bit words size. + */ + struct { + unsigned rxfdep:16; + unsigned reserved:16; + }; +} grxfsiz_t; + +/** + * This union represents the bit fields of the Core Interrupt Register + * (GINTSTS). + */ +typedef union { + /* raw register data */ + uint32_t d32; +#define SOF_INTR_MASK 0x0008 + /* register bits */ + struct { + unsigned curmod:1; +#define HOST_MODE 1 +#define DEVICE_MODE 0 + unsigned modemis:1; + unsigned otgint:1; + unsigned sof:1; + unsigned rxflvl:1; + unsigned nptxfemp:1; + unsigned ginnakeff:1; + unsigned goutnakeff:1; + unsigned reserved8:1; + unsigned i2cint:1; + unsigned erlysusp:1; + unsigned usbsusp:1; + unsigned usbrst:1; + unsigned enumdone:1; + unsigned isooutdrop:1; + unsigned eopf:1; + unsigned reserved16_20:5; + unsigned incompip:1; + unsigned reserved22_23:2; + unsigned prtint:1; + unsigned hchint:1; + unsigned ptxfemp:1; + unsigned reserved27:1; + unsigned conidstschng:1; + unsigned disconnint:1; + unsigned sessreqint:1; + unsigned wkupint:1; + }; +} gintsts_t; + +/** + * This union represents the bit fields of the User HW Config3 Register + * (GHWCFG3). + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned reserved:16; + unsigned dfifodepth:16; + }; +} ghwcfg3_t; + +/** + * This union represents the bit fields in the Host Configuration Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + + /* register bits */ + struct { + /** FS/LS Phy Clock Select */ + unsigned fslspclksel:2; +#define PHYCLK_30_60_MHZ 0 +#define PHYCLK_48_MHZ 1 +#define PHYCLK_6_MHZ 2 + + /** FS/LS Only Support */ + unsigned fslssupp:1; + }; +} hcfg_t; + +/** + * This union represents the bit fields in the Host Frame Number/Frame Time + * Remaining Register + */ +typedef union { + /* raw register data */ + uint32_t d32; + + /* register bits */ + struct { + /** Frame Number */ + unsigned frnum:16; + /** Frame Time Remaining */ + unsigned frrem:16; + }; +} hfnum_t; + +/** + * This union represents the bit fields in the Host Port Control and status + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned prtconnsts:1; + unsigned prtconndet:1; + unsigned prtena:1; + unsigned prtenchng:1; + unsigned prtovrcurract:1; + unsigned prtovrcurrchng:1; + unsigned prtres:1; + unsigned prtsusp:1; + unsigned prtrst:1; + unsigned reserved9:1; + unsigned prtlnsts:2; + unsigned prtpwr:1; + unsigned prttstctl:4; + unsigned prtspd:2; +#define PRTSPD_HIGH 0 +#define PRTSPD_FULL 1 +#define PRTSPD_LOW 2 + unsigned reserved19_31:13; + }; +} hprt_t; +/* Mask W1C bits */ +#define HPRT_W1C_MASK (~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5))) + +/** + * This union represents the bit fields in the Host Channel Characteristics + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + + /* register bits */ + struct { + /** Maximum packet size in bytes */ + unsigned mps:11; + /** Endpoint number */ + unsigned epnum:4; + /** 0: OUT, 1: IN */ + unsigned epdir:1; + unsigned reserved:1; + /** 0: Full/high speed device, 1: Low speed device */ + unsigned lspddev:1; + /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ + unsigned eptype:2; + /** Packets per frame for periodic transfers. 0 is reserved. */ + unsigned multicnt:2; + /** Device address */ + unsigned devaddr:7; + /** + * Frame to transmit periodic transaction. + * 0: even, 1: odd + */ + unsigned oddfrm:1; + /** Channel disable */ + unsigned chdis:1; + /** Channel enable */ + unsigned chen:1; + }; +} hcchar_t; + +/** + * This union represents the bit fields in the Host Channel-n Split Control + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + + /* register bits */ + struct { + /** Port Address */ + unsigned prtaddr:7; + /** Hub Address */ + unsigned hubaddr:7; + /** Transaction Position */ + unsigned xactpos:2; + /** Do Complete Split */ + unsigned compsplt:1; + unsigned reserved:14; + /** Split Enable */ + unsigned spltena:1; + }; +} hcsplit_t; + +typedef enum { + EPDIR_OUT = 0, + EPDIR_IN, +} ep_dir_t; + +/** + * This union represents the bit fields in the Host All Interrupt + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + /** Transfer Complete */ + unsigned xfercomp:1; + /** Channel Halted */ + unsigned chhltd:1; + /** AHB Error */ + unsigned ahberr:1; + /** STALL Response Received */ + unsigned stall:1; + /** NAK Response Received */ + unsigned nak:1; + /** ACK Response Received */ + unsigned ack:1; + /** NYET Response Received */ + unsigned nyet:1; + /** Transaction Err */ + unsigned xacterr:1; + /** Babble Error */ + unsigned bblerr:1; + /** Frame Overrun */ + unsigned frmovrun:1; + /** Data Toggle Error */ + unsigned datatglerr:1; + /** Reserved */ + unsigned reserved:21; + }; +} hcint_t; + +/** + * This union represents the bit fields in the Host Channel Transfer Size + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + + /* register bits */ + struct { + /* Total transfer size in bytes */ + unsigned xfersize:19; + /** Data packets to transfer */ + unsigned pktcnt:10; + /** + * Packet ID for next data packet + * 0: DATA0 + * 1: DATA2 + * 2: DATA1 + * 3: MDATA (non-Control), SETUP (Control) + */ + unsigned pid:2; +#define PID_DATA0 0 +#define PID_DATA1 2 +#define PID_DATA2 1 +#define PID_MDATA 3 +#define PID_SETUP 3 + /* Do PING protocol when 1 */ + unsigned dopng:1; + }; +} hctsiz_t; + +/** + * This union represents the bit fields in the Host Channel Interrupt Mask + * Register. + */ +typedef union { + /* raw register data */ + uint32_t d32; + /* register bits */ + struct { + unsigned xfercomp:1; + unsigned chhltd:1; + unsigned ahberr:1; + unsigned stall:1; + unsigned nak:1; + unsigned ack:1; + unsigned nyet:1; + unsigned xacterr:1; + unsigned bblerr:1; + unsigned frmovrun:1; + unsigned datatglerr:1; + unsigned reserved:21; + }; +} hcintmsk_t; + +typedef struct dwc_ctrl { +#define DMA_SIZE (64 * 1024) + void *dma_buffer; + u32 *hprt0; + u32 frame; +} dwc_ctrl_t; + +typedef struct { + u8 *data; + endpoint_t *endp; + int reqsize; + u32 reqtiming; + u32 timestamp; +} intr_queue_t; + +typedef struct { + int hubaddr; + int hubport; +} split_info_t; + +#define DWC2_INST(controller) ((dwc_ctrl_t *)((controller)->instance)) +#define DWC2_REG(controller) ((dwc2_reg_t *)((controller)->reg_base)) + +typedef enum { + HCSTAT_DONE = 0, + HCSTAT_XFERERR, + HCSTAT_BABBLE, + HCSTAT_STALL, + HCSTAT_ACK, + HCSTAT_NAK, + HCSTAT_NYET, + HCSTAT_UNKNOW, + HCSTAT_TIMEOUT, + HCSTAT_DISCONNECTED, +} hcstat_t; +#endif diff --git a/payloads/libpayload/drivers/usb/dwc2_rh.c b/payloads/libpayload/drivers/usb/dwc2_rh.c new file mode 100644 index 0000000000..3dd504279b --- /dev/null +++ b/payloads/libpayload/drivers/usb/dwc2_rh.c @@ -0,0 +1,188 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Rockchip Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include "generic_hub.h" +#include "dwc2_private.h" +#include "dwc2.h" + +static int +dwc2_rh_port_status_changed(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + int changed; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + changed = hprt.prtconndet; + + /* Clear connect detect flag */ + if (changed) { + hprt.d32 &= HPRT_W1C_MASK; + hprt.prtconndet = 1; + writel(hprt.d32, dwc2->hprt0); + } + return changed; +} + +static int +dwc2_rh_port_connected(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + return hprt.prtconnsts; +} + +static int +dwc2_rh_port_in_reset(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + return hprt.prtrst; +} + +static int +dwc2_rh_port_enabled(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + return hprt.prtena; +} + +static usb_speed +dwc2_rh_port_speed(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + if (hprt.prtena) { + switch (hprt.prtspd) { + case PRTSPD_HIGH: + return HIGH_SPEED; + case PRTSPD_FULL: + return FULL_SPEED; + case PRTSPD_LOW: + return LOW_SPEED; + } + } + return -1; +} + +static int +dwc2_rh_reset_port(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + hprt.d32 &= HPRT_W1C_MASK; + hprt.prtrst = 1; + writel(hprt.d32, dwc2->hprt0); + + /* Wait a bit while reset is active. */ + mdelay(50); + + /* Deassert reset. */ + hprt.prtrst = 0; + writel(hprt.d32, dwc2->hprt0); + + /* + * If reset and speed enum success the DWC2 core will set enable bit + * after port reset bit is deasserted + */ + mdelay(1); + hprt.d32 = readl(dwc2->hprt0); + usb_debug("%s reset port ok, hprt = 0x%08x\n", __func__, hprt.d32); + + if (!hprt.prtena) { + usb_debug("%s enable port fail! hprt = 0x%08x\n", + __func__, hprt.d32); + return -1; + } + + return 0; +} + +static int +dwc2_rh_enable_port(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + /* Power on the port */ + hprt.d32 = readl(dwc2->hprt0); + hprt.d32 &= HPRT_W1C_MASK; + hprt.prtpwr = 1; + writel(hprt.d32, dwc2->hprt0); + return 0; +} + +static int +dwc2_rh_disable_port(usbdev_t *const dev, const int port) +{ + hprt_t hprt; + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + hprt.d32 = readl(dwc2->hprt0); + hprt.d32 &= HPRT_W1C_MASK; + /* Disable the port*/ + hprt.prtena = 1; + /* Power off the port */ + hprt.prtpwr = 0; + writel(hprt.d32, dwc2->hprt0); + return 0; +} + +static const generic_hub_ops_t dwc2_rh_ops = { + .hub_status_changed = NULL, + .port_status_changed = dwc2_rh_port_status_changed, + .port_connected = dwc2_rh_port_connected, + .port_in_reset = dwc2_rh_port_in_reset, + .port_enabled = dwc2_rh_port_enabled, + .port_speed = dwc2_rh_port_speed, + .enable_port = dwc2_rh_enable_port, + .disable_port = dwc2_rh_disable_port, + .start_port_reset = NULL, + .reset_port = dwc2_rh_reset_port, +}; + +void +dwc2_rh_init(usbdev_t *dev) +{ + dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller); + + /* we can set them here because a root hub _really_ shouldn't + appear elsewhere */ + dev->address = 0; + dev->hub = -1; + dev->port = -1; + + generic_hub_init(dev, 1, &dwc2_rh_ops); + usb_debug("dwc2_rh_init HPRT 0x%08x p = %p\n ", + readl(dwc2->hprt0), dwc2->hprt0); + usb_debug("DWC2: root hub init done\n"); +} diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c index 5af99e0f53..4ac59b5665 100644 --- a/payloads/libpayload/drivers/usb/ehci.c +++ b/payloads/libpayload/drivers/usb/ehci.c @@ -30,6 +30,8 @@ //#define USB_DEBUG #include +#include +#include #include "ehci.h" #include "ehci_private.h" @@ -53,7 +55,7 @@ static void dump_td(u32 addr) usb_debug("|:+-----------------------------------------------+:|\n"); usb_debug("|:| Alt. Next qTD [0x%08lx] |:|\n", td->alt_next_qtd); usb_debug("|:+-----------------------------------------------+:|\n"); - usb_debug("|:| | Bytes to Transfer | [%04ld] |:|\n", (td->token & (0x7FUL << 16)) >> 16); + usb_debug("|:| | Bytes to Transfer |[%05ld] |:|\n", (td->token & QTD_TOTAL_LEN_MASK) >> 16); usb_debug("|:| | PID CODE: | [%ld] |:|\n", (td->token & (3UL << 8)) >> 8); usb_debug("|:| | Interrupt On Complete (IOC) | [%ld] |:|\n", (td->token & (1UL << 15)) >> 15); usb_debug("|:| | Status Active | [%ld] |:|\n", (td->token & (1UL << 7)) >> 7); @@ -69,7 +71,7 @@ static void dump_td(u32 addr) usb_debug("+---------------------------------------------------+\n"); } -#ifdef USB_DEBUG +#if 0 && defined(USB_DEBUG) static void dump_qh(ehci_qh_t *cur) { qtd_t *tmp_qtd = NULL; @@ -175,46 +177,23 @@ static int ehci_set_periodic_schedule(ehci_t *ehcic, int enable) static void ehci_shutdown (hci_t *controller) { detach_controller(controller); + /* Make sure periodic schedule is disabled */ ehci_set_periodic_schedule(EHCI_INST(controller), 0); - /* Free periodic frame list */ - free(phys_to_virt(EHCI_INST(controller)->operation->periodiclistbase)); - - /* Free dummy QH */ - free((void *)EHCI_INST(controller)->dummy_qh); + /* Give all ports back to companion controller */ EHCI_INST(controller)->operation->configflag = 0; + /* Free all dynamic allocations */ + free(EHCI_INST(controller)->dma_buffer); + free(phys_to_virt(EHCI_INST(controller)->operation->periodiclistbase)); + free((void *)EHCI_INST(controller)->dummy_qh); free(EHCI_INST(controller)); free(controller); } enum { EHCI_OUT=0, EHCI_IN=1, EHCI_SETUP=2 }; -/* - * returns the address of the closest USB2.0 hub, which is responsible for - * split transactions, along with the number of the used downstream port - */ -static int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const port) -{ - const usbdev_t *usb1dev; - do { - usb1dev = dev; - if ((dev->hub > 0) && (dev->hub < 128)) - dev = dev->controller->devices[dev->hub]; - else - dev = NULL; - } while (dev && (dev->speed < 2)); - if (dev) { - *addr = usb1dev->hub; - *port = usb1dev->port; - return 0; - } else { - usb_debug("ehci: Couldn't find closest USB2.0 hub.\n"); - return 1; - } -} - /* returns handled bytes. assumes that the fields it writes are empty on entry */ static int fill_td(qtd_t *td, void* data, int datalen) { @@ -270,6 +249,7 @@ static void free_qh_and_tds(ehci_qh_t *qh, qtd_t *cur) static int wait_for_tds(qtd_t *head) { + /* returns the amount of bytes *not* transmitted, or -1 for error */ int result = 0; qtd_t *cur = head; while (1) { @@ -279,28 +259,30 @@ static int wait_for_tds(qtd_t *head) /* how long to wait? * tested with some USB2.0 flash sticks: * TUR turn around took - * about 2s for the slowest (14cd:121c) + * about 2.2s for the slowest (13fe:3800) * max. 250ms for the others * slowest non-TUR turn around took about 1.3s - * try 2s for now as a failed TUR is not fatal + * set to 3s to be safe as a failed TUR can be fatal */ - int timeout = 40000; /* time out after 40000 * 50us == 2s */ + int timeout = 60000; /* time out after 60000 * 50us == 3s */ while ((cur->token & QTD_ACTIVE) && !(cur->token & QTD_HALTED) && timeout--) udelay(50); if (timeout < 0) { usb_debug("Error: ehci: queue transfer " "processing timed out.\n"); - return 1; + return -1; } if (cur->token & QTD_HALTED) { usb_debug("ERROR with packet\n"); dump_td(virt_to_phys(cur)); usb_debug("-----------------\n"); - return 1; + return -1; } + result += (cur->token & QTD_TOTAL_LEN_MASK) + >> QTD_TOTAL_LEN_SHIFT; if (cur->next_qtd & 1) { - return 0; + break; } if (0) dump_td(virt_to_phys(cur)); /* helps debugging the TD chain */ @@ -312,6 +294,14 @@ static int wait_for_tds(qtd_t *head) static int ehci_set_async_schedule(ehci_t *ehcic, int enable) { + + /* Memory barrier to ensure that all memory accesses before we set the + * async schedule are complete. It was observed especially in the case of + * arm64, that netboot and usb stuff resulted in lot of errors possibly + * due to CPU reordering. Hence, enforcing strict CPU ordering. + */ + mb(); + /* Set async schedule status. */ if (enable) ehcic->operation->usbcmd |= HC_OP_ASYNC_SCHED_EN; @@ -338,13 +328,13 @@ static int ehci_process_async_schedule( int result; /* make sure async schedule is disabled */ - if (ehci_set_async_schedule(ehcic, 0)) return 1; + if (ehci_set_async_schedule(ehcic, 0)) return -1; /* hook up QH */ ehcic->operation->asynclistaddr = virt_to_phys(qhead); /* start async schedule */ - if (ehci_set_async_schedule(ehcic, 1)) return 1; + if (ehci_set_async_schedule(ehcic, 1)) return -1; /* wait for result */ result = wait_for_tds(head); @@ -355,9 +345,11 @@ static int ehci_process_async_schedule( return result; } -static int ehci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) +static int ehci_bulk (endpoint_t *ep, int size, u8 *src, int finalize) { int result = 0; + u8 *end = src + size; + int remaining = size; int endp = ep->endpoint & 0xf; int pid = (ep->direction==IN)?EHCI_IN:EHCI_OUT; @@ -365,33 +357,45 @@ static int ehci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) if (ep->dev->speed < 2) { /* we need a split transaction */ if (closest_usb2_hub(ep->dev, &hubaddr, &hubport)) - return 1; + return -1; } - qtd_t *head = memalign(64, sizeof(qtd_t)); + if (!dma_coherent(src)) { + end = EHCI_INST(ep->dev->controller)->dma_buffer + size; + if (size > DMA_SIZE) { + usb_debug("EHCI bulk transfer too large for DMA buffer: %d\n", size); + return -1; + } + if (pid == EHCI_OUT) + memcpy(end - size, src, size); + } + + ehci_qh_t *qh = dma_memalign(64, sizeof(ehci_qh_t)); + qtd_t *head = dma_memalign(64, sizeof(qtd_t)); qtd_t *cur = head; + if (!qh || !head) + goto oom; while (1) { memset((void *)cur, 0, sizeof(qtd_t)); cur->token = QTD_ACTIVE | (pid << QTD_PID_SHIFT) | (0 << QTD_CERR_SHIFT); - u32 chunk = fill_td(cur, data, size); - size -= chunk; - data += chunk; + remaining -= fill_td(cur, end - remaining, remaining); cur->alt_next_qtd = QTD_TERMINATE; - if (size == 0) { + if (remaining <= 0) { cur->next_qtd = virt_to_phys(0) | QTD_TERMINATE; break; } else { - qtd_t *next = memalign(64, sizeof(qtd_t)); + qtd_t *next = dma_memalign(64, sizeof(qtd_t)); + if (!next) + goto oom; cur->next_qtd = virt_to_phys(next); cur = next; } } /* create QH */ - ehci_qh_t *qh = memalign(64, sizeof(ehci_qh_t)); memset((void *)qh, 0, sizeof(ehci_qh_t)); qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH; qh->epchar = ep->dev->address | @@ -411,18 +415,31 @@ static int ehci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) result = ehci_process_async_schedule( EHCI_INST(ep->dev->controller), qh, head); + if (result >= 0) { + result = size - result; + if (pid == EHCI_IN && end != src + size) + memcpy(src, end - size, result); + } ep->toggle = (cur->token & QTD_TOGGLE_MASK) >> QTD_TOGGLE_SHIFT; free_qh_and_tds(qh, head); + return result; + +oom: + usb_debug("Not enough DMA memory for EHCI control structures!\n"); + free_qh_and_tds(qh, head); + return -1; } /* FIXME: Handle control transfers as 3 QHs, so the 2nd stage can be >0x4000 bytes */ -static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, - int dalen, u8 *data) +static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, + int dalen, u8 *src) { + u8 *data = src; + u8 *devreq = setup; int endp = 0; // this is control. always 0 (for now) int toggle = 0; int mlen = dev->endpoints[0].maxpacketsize; @@ -432,13 +449,30 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq if (dev->speed < 2) { /* we need a split transaction */ if (closest_usb2_hub(dev, &hubaddr, &hubport)) - return 1; + return -1; non_hs_ctrl_ep = 1; } + if (!dma_coherent(setup)) { + devreq = EHCI_INST(dev->controller)->dma_buffer; + memcpy(devreq, setup, drlen); + } + if (dalen > 0 && !dma_coherent(src)) { + data = EHCI_INST(dev->controller)->dma_buffer + drlen; + if (drlen + dalen > DMA_SIZE) { + usb_debug("EHCI control transfer too large for DMA buffer: %d\n", drlen + dalen); + return -1; + } + if (dir == OUT) + memcpy(data, src, dalen); + } + /* create qTDs */ - qtd_t *head = memalign(64, sizeof(qtd_t)); + qtd_t *head = dma_memalign(64, sizeof(qtd_t)); + ehci_qh_t *qh = dma_memalign(64, sizeof(ehci_qh_t)); qtd_t *cur = head; + if (!qh || !head) + goto oom; memset((void *)cur, 0, sizeof(qtd_t)); cur->token = QTD_ACTIVE | (toggle?QTD_TOGGLE_DATA1:0) | @@ -447,9 +481,11 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq if (fill_td(cur, devreq, drlen) != drlen) { usb_debug("ERROR: couldn't send the entire device request\n"); } - qtd_t *next = memalign(64, sizeof(qtd_t)); + qtd_t *next = dma_memalign(64, sizeof(qtd_t)); cur->next_qtd = virt_to_phys(next); cur->alt_next_qtd = QTD_TERMINATE; + if (!next) + goto oom; /* FIXME: We're limited to 16-20K (depending on alignment) for payload for now. * Figure out, how toggle can be set sensibly in this scenario */ @@ -464,7 +500,9 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq if (fill_td(cur, data, dalen) != dalen) { usb_debug("ERROR: couldn't send the entire control payload\n"); } - next = memalign(64, sizeof(qtd_t)); + next = dma_memalign(64, sizeof(qtd_t)); + if (!next) + goto oom; cur->next_qtd = virt_to_phys(next); cur->alt_next_qtd = QTD_TERMINATE; } @@ -481,7 +519,6 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq cur->alt_next_qtd = QTD_TERMINATE; /* create QH */ - ehci_qh_t *qh = memalign(64, sizeof(ehci_qh_t)); memset((void *)qh, 0, sizeof(ehci_qh_t)); qh->horiz_link_ptr = virt_to_phys(qh) | QH_QH; qh->epchar = dev->address | @@ -499,9 +536,19 @@ static int ehci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq result = ehci_process_async_schedule( EHCI_INST(dev->controller), qh, head); + if (result >= 0) { + result = dalen - result; + if (dir == IN && data != src) + memcpy(src, data, result); + } free_qh_and_tds(qh, head); return result; + +oom: + usb_debug("Not enough DMA memory for EHCI control structures!\n"); + free_qh_and_tds(qh, head); + return -1; } @@ -572,13 +619,13 @@ static void *ehci_create_intr_queue( return NULL; } - intr_queue_t *const intrq = - (intr_queue_t *)memalign(64, sizeof(intr_queue_t)); + intr_queue_t *const intrq = (intr_queue_t *)dma_memalign(64, + sizeof(intr_queue_t)); /* * reqcount data chunks * plus one more spare, which we'll leave out of queue */ - u8 *data = (u8 *)malloc(reqsize * (reqcount + 1)); + u8 *data = (u8 *)dma_malloc(reqsize * (reqcount + 1)); if (!intrq || !data) fatal("Not enough memory to create USB interrupt queue.\n"); intrq->data = data; @@ -586,7 +633,7 @@ static void *ehci_create_intr_queue( intrq->reqsize = reqsize; /* create #reqcount transfer descriptors (qTDs) */ - intrq->head = (intr_qtd_t *)memalign(64, sizeof(intr_qtd_t)); + intrq->head = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); intr_qtd_t *cur_td = intrq->head; for (i = 0; i < reqcount; ++i) { fill_intr_queue_td(intrq, cur_td, data); @@ -594,7 +641,7 @@ static void *ehci_create_intr_queue( if (i < reqcount - 1) { /* create one more qTD */ intr_qtd_t *const next_td = - (intr_qtd_t *)memalign(64, sizeof(intr_qtd_t)); + (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); cur_td->td.next_qtd = virt_to_phys(&next_td->td); cur_td->next = next_td; cur_td = next_td; @@ -603,8 +650,8 @@ static void *ehci_create_intr_queue( intrq->tail = cur_td; /* create spare qTD */ - intrq->spare = (intr_qtd_t *)memalign(64, sizeof(intr_qtd_t)); - fill_intr_queue_td(intrq, intrq->spare, data); + intrq->spare = (intr_qtd_t *)dma_memalign(64, sizeof(intr_qtd_t)); + intrq->spare->data = data; /* initialize QH */ const int endp = ep->endpoint & 0xf; @@ -724,29 +771,12 @@ static u8 *ehci_poll_intr_queue(void *const queue) } hci_t * -ehci_init (pcidev_t addr) +ehci_init (void *bar) { int i; hci_t *controller = new_controller (); - - if (!controller) - fatal("Could not create USB controller instance.\n"); - - controller->instance = malloc (sizeof (ehci_t)); - if(!controller->instance) - fatal("Not enough memory creating USB controller instance.\n"); - -#define PCI_COMMAND 4 -#define PCI_COMMAND_IO 1 -#define PCI_COMMAND_MEMORY 2 -#define PCI_COMMAND_MASTER 4 - - u32 pci_command = pci_read_config32(addr, PCI_COMMAND); - pci_command = (pci_command | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_IO ; - pci_write_config32(addr, PCI_COMMAND, pci_command); - + controller->instance = xzalloc(sizeof (ehci_t)); controller->type = EHCI; - controller->start = ehci_start; controller->stop = ehci_stop; controller->reset = ehci_reset; @@ -754,22 +784,18 @@ ehci_init (pcidev_t addr) controller->shutdown = ehci_shutdown; controller->bulk = ehci_bulk; controller->control = ehci_control; + controller->set_address = generic_set_address; + controller->finish_device_config = NULL; + controller->destroy_device = NULL; controller->create_intr_queue = ehci_create_intr_queue; controller->destroy_intr_queue = ehci_destroy_intr_queue; controller->poll_intr_queue = ehci_poll_intr_queue; - controller->bus_address = addr; - controller->reg_base = pci_read_config32 (controller->bus_address, USBBASE); - for (i = 0; i < 128; i++) { - controller->devices[i] = 0; - } + controller->reg_base = (u32)(unsigned long)bar; init_device_entry (controller, 0); EHCI_INST(controller)->capabilities = phys_to_virt(controller->reg_base); EHCI_INST(controller)->operation = (hc_op_t *)(phys_to_virt(controller->reg_base) + EHCI_INST(controller)->capabilities->caplength); - /* default value for frame length adjust */ - pci_write_config8(addr, FLADJ, FLADJ_framelength(60000)); - /* Set the high address word (aka segment) if controller is 64-bit */ if (EHCI_INST(controller)->capabilities->hccparams & 1) EHCI_INST(controller)->operation->ctrldssegment = 0; @@ -782,19 +808,27 @@ ehci_init (pcidev_t addr) /* Initialize periodic frame list */ /* 1024 32-bit pointers, 4kb aligned */ - u32 *const periodic_list = (u32 *)memalign(4096, 1024 * sizeof(u32)); + u32 *const periodic_list = (u32 *)dma_memalign(4096, 1024 * sizeof(u32)); if (!periodic_list) fatal("Not enough memory creating EHCI periodic frame list.\n"); + if (dma_initialized()) { + EHCI_INST(controller)->dma_buffer = dma_memalign(4096, DMA_SIZE); + if (!EHCI_INST(controller)->dma_buffer) + fatal("Not enough DMA memory for EHCI bounce buffer.\n"); + } + /* * Insert dummy QH in periodic frame list * This helps with broken host controllers * and doesn't violate the standard. */ - EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)memalign(64, sizeof(ehci_qh_t)); + EHCI_INST(controller)->dummy_qh = (ehci_qh_t *)dma_memalign(64, sizeof(ehci_qh_t)); memset((void *)EHCI_INST(controller)->dummy_qh, 0, sizeof(*EHCI_INST(controller)->dummy_qh)); EHCI_INST(controller)->dummy_qh->horiz_link_ptr = QH_TERMINATE; + EHCI_INST(controller)->dummy_qh->td.next_qtd = QH_TERMINATE; + EHCI_INST(controller)->dummy_qh->td.alt_next_qtd = QH_TERMINATE; for (i = 0; i < 1024; ++i) periodic_list[i] = virt_to_phys(EHCI_INST(controller)->dummy_qh) | PS_TYPE_QH; @@ -815,3 +849,25 @@ ehci_init (pcidev_t addr) return controller; } + +#ifdef CONFIG_LP_USB_PCI +hci_t * +ehci_pci_init (pcidev_t addr) +{ + hci_t *controller; + u32 reg_base; + + u32 pci_command = pci_read_config32(addr, PCI_COMMAND); + pci_command = (pci_command | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_IO ; + pci_write_config32(addr, PCI_COMMAND, pci_command); + + reg_base = pci_read_config32 (addr, USBBASE); + + /* default value for frame length adjust */ + pci_write_config8(addr, FLADJ, FLADJ_framelength(60000)); + + controller = ehci_init((void *)(unsigned long)reg_base); + + return controller; +} +#endif diff --git a/payloads/libpayload/drivers/usb/ehci.h b/payloads/libpayload/drivers/usb/ehci.h index c66643c702..c1b1fa9f70 100644 --- a/payloads/libpayload/drivers/usb/ehci.h +++ b/payloads/libpayload/drivers/usb/ehci.h @@ -33,7 +33,8 @@ #include #include -hci_t *ehci_init (pcidev_t addr); +hci_t *ehci_pci_init (pcidev_t addr); +hci_t *ehci_init (void *bar); void ehci_rh_init (usbdev_t *dev); diff --git a/payloads/libpayload/drivers/usb/ehci_private.h b/payloads/libpayload/drivers/usb/ehci_private.h index 3b9faf6d31..8519c0f2af 100644 --- a/payloads/libpayload/drivers/usb/ehci_private.h +++ b/payloads/libpayload/drivers/usb/ehci_private.h @@ -30,7 +30,6 @@ #ifndef __EHCI_PRIVATE_H #define __EHCI_PRIVATE_H -#include #include #define USBBASE 0x10 @@ -78,10 +77,13 @@ typedef volatile struct { u32 ctrldssegment; u32 periodiclistbase; u32 asynclistaddr; - u8 res1[0x3f-0x1c]; + u8 res1[0x40-0x1c]; u32 configflag; portsc_t portsc[0]; -} hc_op_t; + u8 res2[0x40]; + u32 hostpc; + /* hostpc register is used for CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT */ +} __attribute__ ((packed)) hc_op_t; typedef volatile struct { #define QTD_TERMINATE 1 @@ -130,19 +132,20 @@ typedef volatile struct { #define QH_PIPE_MULTIPLIER_SHIFT 30 volatile u32 current_td_ptr; volatile qtd_t td; -} ehci_qh_t; +} __attribute__ ((packed)) ehci_qh_t; typedef struct ehci { hc_cap_t *capabilities; hc_op_t *operation; ehci_qh_t *dummy_qh; +#define DMA_SIZE (64 * 1024) + void *dma_buffer; } ehci_t; #define PS_TERMINATE 1 #define PS_TYPE_QH 1 << 1 #define PS_PTR_MASK ~0x1f - #define EHCI_INST(controller) ((ehci_t*)((controller)->instance)) #endif diff --git a/payloads/libpayload/drivers/usb/ehci_rh.c b/payloads/libpayload/drivers/usb/ehci_rh.c index 89828040d1..da8d8aff8b 100644 --- a/payloads/libpayload/drivers/usb/ehci_rh.c +++ b/payloads/libpayload/drivers/usb/ehci_rh.c @@ -27,7 +27,10 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG + #include +#include #include "ehci.h" #include "ehci_private.h" @@ -46,6 +49,17 @@ typedef struct { static void ehci_rh_destroy (usbdev_t *dev) { + int port; + + /* Tear down all devices below the root hub (in bottom-up order). */ + for (port = 0; port < RH_INST(dev)->n_ports; port++) { + if (RH_INST(dev)->devices[port] != -1) { + usb_detach_device(dev->controller, + RH_INST(dev)->devices[port]); + RH_INST(dev)->devices[port] = -1; + } + } + free (RH_INST(dev)->devices); free (RH_INST(dev)); } @@ -78,6 +92,8 @@ ehci_rh_hand_over_port (usbdev_t *dev, int port) static void ehci_rh_scanport (usbdev_t *dev, int port) { + usb_speed port_speed; + if (RH_INST(dev)->devices[port]!=-1) { usb_debug("Unregister device at port %x\n", port+1); usb_detach_device(dev->controller, RH_INST(dev)->devices[port]); @@ -86,7 +102,9 @@ ehci_rh_scanport (usbdev_t *dev, int port) /* device connected, handle */ if (RH_INST(dev)->ports[port] & P_CURR_CONN_STATUS) { mdelay(100); // usb20 spec 9.1.2 - if ((RH_INST(dev)->ports[port] & P_LINE_STATUS) == P_LINE_STATUS_LOWSPEED) { + if (!IS_ENABLED(CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT) && + (RH_INST(dev)->ports[port] & P_LINE_STATUS) == + P_LINE_STATUS_LOWSPEED) { ehci_rh_hand_over_port(dev, port); return; } @@ -96,8 +114,8 @@ ehci_rh_scanport (usbdev_t *dev, int port) */ RH_INST(dev)->ports[port] = (RH_INST(dev)->ports[port] & ~P_PORT_ENABLE) | P_PORT_RESET; - /* Wait a bit while reset is active. */ - mdelay(50); // usb20 spec 7.1.7.5 (TDRSTR) + /* Wait a bit while reset is active (+1 to avoid Tegra race). */ + mdelay(50 + 1); // usb20 spec 7.1.7.5 (TDRSTR) /* Deassert reset. */ RH_INST(dev)->ports[port] &= ~P_PORT_RESET; @@ -111,6 +129,8 @@ ehci_rh_scanport (usbdev_t *dev, int port) return; } + mdelay(10); /* TRSTRCY (USB 2.0 spec 7.1.7.5) */ + /* If the host controller enabled the port, it's a high-speed * device, otherwise it's full-speed. */ @@ -118,8 +138,16 @@ ehci_rh_scanport (usbdev_t *dev, int port) ehci_rh_hand_over_port(dev, port); return; } - usb_debug("port %x hosts a USB2 device\n", port+1); - RH_INST(dev)->devices[port] = usb_attach_device(dev->controller, dev->address, port, 2); + if (IS_ENABLED(CONFIG_LP_USB_EHCI_HOSTPC_ROOT_HUB_TT)) { + port_speed = (usb_speed) + ((EHCI_INST(dev->controller)->operation->hostpc + >> 25) & 0x03); + } else { + usb_debug("port %x hosts a USB2 device\n", port+1); + port_speed = HIGH_SPEED; + } + RH_INST(dev)->devices[port] = usb_attach_device(dev->controller + , dev->address, port, port_speed); } /* RW/C register, so clear it by writing 1 */ RH_INST(dev)->ports[port] |= P_CONN_STATUS_CHANGE; @@ -152,10 +180,10 @@ ehci_rh_init (usbdev_t *dev) dev->destroy = ehci_rh_destroy; dev->poll = ehci_rh_poll; - dev->data = malloc(sizeof(rh_inst_t)); - + dev->data = xmalloc(sizeof(rh_inst_t)); RH_INST(dev)->n_ports = EHCI_INST(dev->controller)->capabilities->hcsparams & HCS_NPORTS_MASK; RH_INST(dev)->ports = EHCI_INST(dev->controller)->operation->portsc; + RH_INST(dev)->devices = xmalloc(RH_INST(dev)->n_ports * sizeof(int)); usb_debug("root hub has %x ports\n", RH_INST(dev)->n_ports); @@ -171,13 +199,12 @@ ehci_rh_init (usbdev_t *dev) } mdelay(20); // ehci spec 2.3.9 - RH_INST(dev)->devices = malloc(RH_INST(dev)->n_ports * sizeof(int)); + dev->speed = HIGH_SPEED; + dev->address = 0; + dev->hub = -1; + dev->port = -1; for (i=0; i < RH_INST(dev)->n_ports; i++) { RH_INST(dev)->devices[i] = -1; ehci_rh_scanport(dev, i); } - - dev->address = 0; - dev->hub = -1; - dev->port = -1; } diff --git a/payloads/libpayload/drivers/usb/generic_hub.c b/payloads/libpayload/drivers/usb/generic_hub.c new file mode 100644 index 0000000000..9f8670597e --- /dev/null +++ b/payloads/libpayload/drivers/usb/generic_hub.c @@ -0,0 +1,265 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#define USB_DEBUG + +#include +#include +#include "generic_hub.h" + +void +generic_hub_destroy(usbdev_t *const dev) +{ + generic_hub_t *const hub = GEN_HUB(dev); + if (!hub) + return; + + /* First, detach all devices behind this hub */ + int port; + for (port = 1; port <= hub->num_ports; ++port) { + if (hub->ports[port] >= 0) { + usb_debug("generic_hub: Detachment at port %d\n", port); + usb_detach_device(dev->controller, hub->ports[port]); + hub->ports[port] = NO_DEV; + } + } + + /* Disable all ports */ + if (hub->ops->disable_port) { + for (port = 1; port <= hub->num_ports; ++port) + hub->ops->disable_port(dev, port); + } + + free(hub->ports); + free(hub); +} + +static int +generic_hub_debounce(usbdev_t *const dev, const int port) +{ + generic_hub_t *const hub = GEN_HUB(dev); + + const int step_ms = 1; /* linux uses 25ms, we're busy anyway */ + const int at_least_ms = 100; /* 100ms as in usb20 spec 9.1.2 */ + const int timeout_ms = 1500; /* linux uses this value */ + + int total_ms = 0; + int stable_ms = 0; + while (stable_ms < at_least_ms && total_ms < timeout_ms) { + mdelay(step_ms); + + const int changed = hub->ops->port_status_changed(dev, port); + const int connected = hub->ops->port_connected(dev, port); + if (changed < 0 || connected < 0) + return -1; + + if (!changed && connected) { + stable_ms += step_ms; + } else { + usb_debug("generic_hub: Unstable connection at %d\n", + port); + stable_ms = 0; + } + total_ms += step_ms; + } + if (total_ms >= timeout_ms) + usb_debug("generic_hub: Debouncing timed out at %d\n", port); + return 0; /* ignore timeouts, try to always go on */ +} + +int +generic_hub_wait_for_port(usbdev_t *const dev, const int port, + const int wait_for, + int (*const port_op)(usbdev_t *, int), + int timeout_steps, const int step_us) +{ + int state; + do { + state = port_op(dev, port); + if (state < 0) + return -1; + else if (!!state == wait_for) + return timeout_steps; + udelay(step_us); + --timeout_steps; + } while (timeout_steps); + return 0; +} + +int +generic_hub_resetport(usbdev_t *const dev, const int port) +{ + generic_hub_t *const hub = GEN_HUB(dev); + + if (hub->ops->start_port_reset(dev, port) < 0) + return -1; + + /* wait for 10ms (usb20 spec 11.5.1.5: reset should take 10 to 20ms) */ + mdelay(10); + + /* now wait 12ms for the hub to finish the reset */ + const int ret = generic_hub_wait_for_port( + /* time out after 120 * 100us = 12ms */ + dev, port, 0, hub->ops->port_in_reset, 120, 100); + if (ret < 0) + return -1; + else if (!ret) + usb_debug("generic_hub: Reset timed out at port %d\n", port); + + return 0; /* ignore timeouts, try to always go on */ +} + +static int +generic_hub_detach_dev(usbdev_t *const dev, const int port) +{ + generic_hub_t *const hub = GEN_HUB(dev); + + usb_detach_device(dev->controller, hub->ports[port]); + hub->ports[port] = NO_DEV; + + return 0; +} + +static int +generic_hub_attach_dev(usbdev_t *const dev, const int port) +{ + generic_hub_t *const hub = GEN_HUB(dev); + + if (generic_hub_debounce(dev, port) < 0) + return -1; + + if (hub->ops->reset_port) { + if (hub->ops->reset_port(dev, port) < 0) + return -1; + /* after reset the port will be enabled automatically */ + const int ret = generic_hub_wait_for_port( + /* time out after 1,000 * 10us = 10ms */ + dev, port, 1, hub->ops->port_enabled, 1000, 10); + if (ret < 0) + return -1; + else if (!ret) + usb_debug("generic_hub: Port %d still " + "disabled after 10ms\n", port); + } + + const usb_speed speed = hub->ops->port_speed(dev, port); + if (speed >= 0) { + usb_debug("generic_hub: Success at port %d\n", port); + if (hub->ops->reset_port) + mdelay(10); /* Reset recovery time + (usb20 spec 7.1.7.5) */ + hub->ports[port] = usb_attach_device( + dev->controller, dev->address, port, speed); + } + return 0; +} + +int +generic_hub_scanport(usbdev_t *const dev, const int port) +{ + generic_hub_t *const hub = GEN_HUB(dev); + + if (hub->ports[port] >= 0) { + usb_debug("generic_hub: Detachment at port %d\n", port); + + const int ret = generic_hub_detach_dev(dev, port); + if (ret < 0) + return ret; + } + + if (hub->ops->port_connected(dev, port)) { + usb_debug("generic_hub: Attachment at port %d\n", port); + + return generic_hub_attach_dev(dev, port); + } + + return 0; +} + +static void +generic_hub_poll(usbdev_t *const dev) +{ + generic_hub_t *const hub = GEN_HUB(dev); + if (!hub) + return; + + if (hub->ops->hub_status_changed && + hub->ops->hub_status_changed(dev) != 1) + return; + + int port; + for (port = 1; port <= hub->num_ports; ++port) { + const int ret = hub->ops->port_status_changed(dev, port); + if (ret < 0) { + return; + } else if (ret == 1) { + usb_debug("generic_hub: Port change at %d\n", port); + if (generic_hub_scanport(dev, port) < 0) + return; + } + } +} + +int +generic_hub_init(usbdev_t *const dev, const int num_ports, + const generic_hub_ops_t *const ops) +{ + int port; + + dev->destroy = generic_hub_destroy; + dev->poll = generic_hub_poll; + dev->data = malloc(sizeof(generic_hub_t)); + if (!dev->data) { + usb_debug("generic_hub: ERROR: Out of memory\n"); + return -1; + } + + generic_hub_t *const hub = GEN_HUB(dev); + hub->num_ports = num_ports; + hub->ports = malloc(sizeof(*hub->ports) * (num_ports + 1)); + hub->ops = ops; + if (!hub->ports) { + usb_debug("generic_hub: ERROR: Out of memory\n"); + free(dev->data); + dev->data = NULL; + return -1; + } + for (port = 1; port <= num_ports; ++port) + hub->ports[port] = NO_DEV; + + /* Enable all ports */ + if (ops->enable_port) { + for (port = 1; port <= num_ports; ++port) + ops->enable_port(dev, port); + /* wait once for all ports */ + mdelay(20); + } + + return 0; +} diff --git a/payloads/libpayload/drivers/usb/generic_hub.h b/payloads/libpayload/drivers/usb/generic_hub.h new file mode 100644 index 0000000000..21536c0ecf --- /dev/null +++ b/payloads/libpayload/drivers/usb/generic_hub.h @@ -0,0 +1,86 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __USB_HUB_H +#define __USB_HUB_H + +#include + +typedef struct generic_hub_ops { + /* negative results denote an error */ + + /* returns 1 if the hub's status changed since the last call (optional) */ + int (*hub_status_changed)(usbdev_t *); + /* returns 1 if the port's status changed since the last call */ + int (*port_status_changed)(usbdev_t *, int port); + /* returns 1 if something is connected to the port */ + int (*port_connected)(usbdev_t *, int port); + /* returns 1 if port is currently resetting */ + int (*port_in_reset)(usbdev_t *, int port); + /* returns 1 if the port is enabled */ + int (*port_enabled)(usbdev_t *, int port); + /* returns speed if port is enabled, negative value if not */ + usb_speed (*port_speed)(usbdev_t *, int port); + + /* enables (powers up) a port (optional) */ + int (*enable_port)(usbdev_t *, int port); + /* disables (powers down) a port (optional) */ + int (*disable_port)(usbdev_t *, int port); + /* starts a port reset (required if reset_port is set to a generic one from below) */ + int (*start_port_reset)(usbdev_t *, int port); + + /* performs a port reset (optional, generic implementations below) */ + int (*reset_port)(usbdev_t *, int port); +} generic_hub_ops_t; + +typedef struct generic_hub { + int num_ports; + /* port numbers are always 1 based, + so we waste one int for convenience */ + int *ports; /* allocated to sizeof(*ports)*(num_ports+1) */ +#define NO_DEV -1 + + const generic_hub_ops_t *ops; + + void *data; +} generic_hub_t; + +void generic_hub_destroy(usbdev_t *); +int generic_hub_wait_for_port(usbdev_t *const dev, const int port, + const int wait_for, + int (*const port_op)(usbdev_t *, int), + int timeout_steps, const int step_us); +int generic_hub_resetport(usbdev_t *, int port); +int generic_hub_scanport(usbdev_t *, int port); +/* the provided generic_hub_ops struct has to be static */ +int generic_hub_init(usbdev_t *, int num_ports, const generic_hub_ops_t *); + +#define GEN_HUB(usbdev) ((generic_hub_t *)(usbdev)->data) + +#endif diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c index 44eba310c3..c2ab674789 100644 --- a/payloads/libpayload/drivers/usb/ohci.c +++ b/payloads/libpayload/drivers/usb/ohci.c @@ -44,7 +44,7 @@ static int ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq static void* ohci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); static void ohci_destroy_intr_queue (endpoint_t *ep, void *queue); static u8* ohci_poll_intr_queue (void *queue); -static void ohci_process_done_queue(ohci_t *ohci, int spew_debug); +static int ohci_process_done_queue(ohci_t *ohci, int spew_debug); #ifdef USB_DEBUG static void @@ -136,7 +136,7 @@ ohci_reinit (hci_t *controller) { } -#ifdef USB_DEBUG +#if 0 && defined(USB_DEBUG) /* Section 4.3.3 */ static const char *completion_codes[] = { "No error", @@ -167,21 +167,13 @@ static const char *direction[] = { #endif hci_t * -ohci_init (pcidev_t addr) +ohci_init (void *bar) { int i; hci_t *controller = new_controller (); - - if (!controller) - fatal("Could not create USB controller instance.\n"); - - controller->instance = malloc (sizeof (ohci_t)); - if(!controller->instance) - fatal("Not enough memory creating USB controller instance.\n"); - + controller->instance = xzalloc(sizeof (ohci_t)); controller->type = OHCI; - controller->start = ohci_start; controller->stop = ohci_stop; controller->reset = ohci_reset; @@ -189,19 +181,16 @@ ohci_init (pcidev_t addr) controller->shutdown = ohci_shutdown; controller->bulk = ohci_bulk; controller->control = ohci_control; + controller->set_address = generic_set_address; + controller->finish_device_config = NULL; + controller->destroy_device = NULL; controller->create_intr_queue = ohci_create_intr_queue; controller->destroy_intr_queue = ohci_destroy_intr_queue; controller->poll_intr_queue = ohci_poll_intr_queue; - for (i = 0; i < 128; i++) { - controller->devices[i] = 0; - } init_device_entry (controller, 0); OHCI_INST (controller)->roothub = controller->devices[0]; - controller->bus_address = addr; - /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4 - * BASE ADDRESS only [31-12] bits. All other usually 0, but not all */ - controller->reg_base = pci_read_config32 (controller->bus_address, 0x10) & 0xfffff000; // OHCI mandates MMIO, so bit 0 is clear + controller->reg_base = (u32)(unsigned long)bar; OHCI_INST (controller)->opreg = (opreg_t*)phys_to_virt(controller->reg_base); usb_debug("OHCI Version %x.%x\n", (OHCI_INST (controller)->opreg->HcRevision >> 4) & 0xf, OHCI_INST (controller)->opreg->HcRevision & 0xf); @@ -222,12 +211,18 @@ ohci_init (pcidev_t addr) OHCI_INST (controller)->opreg->HcCommandStatus = HostControllerReset; udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */ OHCI_INST (controller)->opreg->HcFmInterval = interval; - OHCI_INST (controller)->hcca = memalign(256, 256); + OHCI_INST (controller)->hcca = dma_memalign(256, 256); memset((void*)OHCI_INST (controller)->hcca, 0, 256); + if (dma_initialized()) { + OHCI_INST(controller)->dma_buffer = dma_memalign(4096, DMA_SIZE); + if (!OHCI_INST(controller)->dma_buffer) + fatal("Not enough DMA memory for OHCI bounce buffer.\n"); + } + /* Initialize interrupt table. */ u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable; - ed_t *const periodic_ed = memalign(sizeof(ed_t), sizeof(ed_t)); + ed_t *const periodic_ed = dma_memalign(sizeof(ed_t), sizeof(ed_t)); memset((void *)periodic_ed, 0, sizeof(*periodic_ed)); for (i = 0; i < 32; ++i) intr_table[i] = virt_to_phys(periodic_ed); @@ -252,6 +247,21 @@ ohci_init (pcidev_t addr) return controller; } +#ifdef CONFIG_LP_USB_PCI +hci_t * +ohci_pci_init (pcidev_t addr) +{ + u32 reg_base; + + /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4 + * BASE ADDRESS only [31-12] bits. All other usually 0, but not all. + * OHCI mandates MMIO, so bit 0 is clear */ + reg_base = pci_read_config32 (addr, 0x10) & 0xfffff000; + + return ohci_init((void *)(unsigned long)reg_base); +} +#endif + static void ohci_shutdown (hci_t *controller) { @@ -259,8 +269,7 @@ ohci_shutdown (hci_t *controller) return; detach_controller (controller); ohci_stop(controller); - OHCI_INST (controller)->roothub->destroy (OHCI_INST (controller)-> - roothub); + free (OHCI_INST (controller)->hcca); free ((void *)OHCI_INST (controller)->periodic_ed); free (OHCI_INST (controller)); free (controller); @@ -269,13 +278,13 @@ ohci_shutdown (hci_t *controller) static void ohci_start (hci_t *controller) { -// TODO: turn on all operation of OHCI, but assume that it's initialized. + OHCI_INST (controller)->opreg->HcControl |= PeriodicListEnable; } static void ohci_stop (hci_t *controller) { -// TODO: turn off all operation of OHCI + OHCI_INST (controller)->opreg->HcControl &= ~PeriodicListEnable; } static int @@ -307,13 +316,13 @@ wait_for_ed(usbdev_t *dev, ed_t *head, int pages) usb_debug("Error: ohci: endpoint " "descriptor processing timed out.\n"); /* Clear the done queue. */ - ohci_process_done_queue(OHCI_INST(dev->controller), 1); + int result = ohci_process_done_queue(OHCI_INST(dev->controller), 1); if (head->head_pointer & 1) { usb_debug("HALTED!\n"); - return 1; + return -1; } - return 0; + return result; } static void @@ -338,11 +347,28 @@ ohci_free_ed (ed_t *const head) } static int -ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, - unsigned char *data) +ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *setup, int dalen, + unsigned char *src) { + u8 *data = src; + u8 *devreq = setup; + int remaining = dalen; td_t *cur; + if (!dma_coherent(devreq)) { + devreq = OHCI_INST(dev->controller)->dma_buffer; + memcpy(devreq, setup, drlen); + } + if (dalen > 0 && !dma_coherent(src)) { + data = OHCI_INST(dev->controller)->dma_buffer + drlen; + if (drlen + dalen > DMA_SIZE) { + usb_debug("OHCI control transfer too large for DMA buffer: %d\n", drlen + dalen); + return -1; + } + if (dir == OUT) + memcpy(data, src, dalen); + } + // pages are specified as 4K in OHCI, so don't use getpagesize() int first_page = (unsigned long)data / 4096; int last_page = (unsigned long)(data+dalen-1)/4096; @@ -350,7 +376,7 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen int pages = (dalen==0)?0:(last_page - first_page + 1); /* First TD. */ - td_t *const first_td = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)first_td, 0, sizeof(*first_td)); cur = first_td; @@ -364,7 +390,7 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen while (pages > 0) { /* One more TD. */ - td_t *const next = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + td_t *const next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)next, 0, sizeof(*next)); /* Linked to the previous. */ cur->next_td = virt_to_phys(next); @@ -378,27 +404,27 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen cur->current_buffer_pointer = virt_to_phys(data); pages--; int consumed = (4096 - ((unsigned long)data % 4096)); - if (consumed >= dalen) { + if (consumed >= remaining) { // end of data is within same page - cur->buffer_end = virt_to_phys(data + dalen - 1); - dalen = 0; + cur->buffer_end = virt_to_phys(data + remaining - 1); + remaining = 0; /* assert(pages == 0); */ } else { - dalen -= consumed; + remaining -= consumed; data += consumed; pages--; - int second_page_size = dalen; - if (dalen > 4096) { + int second_page_size = remaining; + if (remaining > 4096) { second_page_size = 4096; } cur->buffer_end = virt_to_phys(data + second_page_size - 1); - dalen -= second_page_size; + remaining -= second_page_size; data += second_page_size; } } /* One more TD. */ - td_t *const next_td = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + td_t *const next_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)next_td, 0, sizeof(*next_td)); /* Linked to the previous. */ cur->next_td = virt_to_phys(next_td); @@ -413,13 +439,13 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen cur->buffer_end = 0; /* Final dummy TD. */ - td_t *const final_td = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + td_t *const final_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)final_td, 0, sizeof(*final_td)); /* Linked to the previous. */ cur->next_td = virt_to_phys(final_td); /* Data structures */ - ed_t *head = memalign(sizeof(ed_t), sizeof(ed_t)); + ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t)); memset((void*)head, 0, sizeof(*head)); head->config = (dev->address << ED_FUNC_SHIFT) | (0 << ED_EP_SHIFT) | @@ -440,7 +466,7 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen OHCI_INST(dev->controller)->opreg->HcControl |= ControlListEnable; OHCI_INST(dev->controller)->opreg->HcCommandStatus = ControlListFilled; - int failure = wait_for_ed(dev, head, + int result = wait_for_ed(dev, head, (dalen==0)?0:(last_page - first_page + 1)); /* Wait some frames before and one after disabling list access. */ mdelay(4); @@ -450,17 +476,34 @@ ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen /* free memory */ ohci_free_ed(head); - return failure; + if (result >= 0) { + result = dalen - result; + if (dir == IN && data != src) + memcpy(src, data, result); + } + + return result; } /* finalize == 1: if data is of packet aligned size, add a zero length packet */ static int -ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) +ohci_bulk (endpoint_t *ep, int dalen, u8 *src, int finalize) { int i; - usb_debug("bulk: %x bytes from %x, finalize: %x, maxpacketsize: %x\n", dalen, data, finalize, ep->maxpacketsize); - td_t *cur, *next; + int remaining = dalen; + u8 *data = src; + usb_debug("bulk: %x bytes from %x, finalize: %x, maxpacketsize: %x\n", dalen, src, finalize, ep->maxpacketsize); + + if (!dma_coherent(src)) { + data = OHCI_INST(ep->dev->controller)->dma_buffer; + if (dalen > DMA_SIZE) { + usb_debug("OHCI bulk transfer too large for DMA buffer: %d\n", dalen); + return -1; + } + if (ep->direction == OUT) + memcpy(data, src, dalen); + } // pages are specified as 4K in OHCI, so don't use getpagesize() int first_page = (unsigned long)data / 4096; @@ -474,7 +517,7 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) } /* First TD. */ - td_t *const first_td = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + td_t *const first_td = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)first_td, 0, sizeof(*first_td)); cur = next = first_td; @@ -487,32 +530,32 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) TD_CC_NOACCESS; cur->current_buffer_pointer = virt_to_phys(data); pages--; - if (dalen == 0) { + if (remaining == 0) { /* magic TD for empty packet transfer */ cur->current_buffer_pointer = 0; cur->buffer_end = 0; /* assert((pages == 0) && finalize); */ } int consumed = (4096 - ((unsigned long)data % 4096)); - if (consumed >= dalen) { + if (consumed >= remaining) { // end of data is within same page - cur->buffer_end = virt_to_phys(data + dalen - 1); - dalen = 0; + cur->buffer_end = virt_to_phys(data + remaining - 1); + remaining = 0; /* assert(pages == finalize); */ } else { - dalen -= consumed; + remaining -= consumed; data += consumed; pages--; - int second_page_size = dalen; - if (dalen > 4096) { + int second_page_size = remaining; + if (remaining > 4096) { second_page_size = 4096; } cur->buffer_end = virt_to_phys(data + second_page_size - 1); - dalen -= second_page_size; + remaining -= second_page_size; data += second_page_size; } /* One more TD. */ - next = (td_t *)memalign(sizeof(td_t), sizeof(td_t)); + next = (td_t *)dma_memalign(sizeof(td_t), sizeof(td_t)); memset((void *)next, 0, sizeof(*next)); /* Linked to the previous. */ cur->next_td = virt_to_phys(next); @@ -524,7 +567,7 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) cur = next; /* Data structures */ - ed_t *head = memalign(sizeof(ed_t), sizeof(ed_t)); + ed_t *head = dma_memalign(sizeof(ed_t), sizeof(ed_t)); memset((void*)head, 0, sizeof(*head)); head->config = (ep->dev->address << ED_FUNC_SHIFT) | ((ep->endpoint & 0xf) << ED_EP_SHIFT) | @@ -544,7 +587,7 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) OHCI_INST(ep->dev->controller)->opreg->HcControl |= BulkListEnable; OHCI_INST(ep->dev->controller)->opreg->HcCommandStatus = BulkListFilled; - int failure = wait_for_ed(ep->dev, head, + int result = wait_for_ed(ep->dev, head, (dalen==0)?0:(last_page - first_page + 1)); /* Wait some frames before and one after disabling list access. */ mdelay(4); @@ -556,12 +599,13 @@ ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) /* free memory */ ohci_free_ed(head); - if (failure) { - /* try cleanup */ - clear_stall(ep); + if (result >= 0) { + result = dalen - result; + if (ep->direction == IN && data != src) + memcpy(src, data, result); } - return failure; + return result; } @@ -619,16 +663,16 @@ ohci_create_intr_queue(endpoint_t *const ep, const int reqsize, return NULL; intr_queue_t *const intrq = - (intr_queue_t *)memalign(sizeof(intrq->ed), sizeof(*intrq)); + (intr_queue_t *)dma_memalign(sizeof(intrq->ed), sizeof(*intrq)); memset(intrq, 0, sizeof(*intrq)); - intrq->data = (u8 *)malloc(reqcount * reqsize); + intrq->data = (u8 *)dma_malloc(reqcount * reqsize); intrq->reqsize = reqsize; intrq->endp = ep; /* Create #reqcount TDs. */ u8 *cur_data = intrq->data; for (i = 0; i < reqcount; ++i) { - intrq_td_t *const td = memalign(sizeof(td->td), sizeof(*td)); + intrq_td_t *const td = dma_memalign(sizeof(td->td), sizeof(*td)); ++intrq->remaining_tds; ohci_fill_intrq_td(td, intrq, cur_data); cur_data += reqsize; @@ -640,7 +684,7 @@ ohci_create_intr_queue(endpoint_t *const ep, const int reqsize, } /* Create last, dummy TD. */ - intrq_td_t *dummy_td = memalign(sizeof(dummy_td->td), sizeof(*dummy_td)); + intrq_td_t *dummy_td = dma_memalign(sizeof(dummy_td->td), sizeof(*dummy_td)); memset(dummy_td, 0, sizeof(*dummy_td)); dummy_td->intrq = intrq; if (last_td) @@ -766,9 +810,11 @@ ohci_poll_intr_queue(void *const q_) return data; } -static void +static int ohci_process_done_queue(ohci_t *const ohci, const int spew_debug) { + /* returns the amount of bytes *not* transmitted for short packets */ + int result = 0; int i, j; /* Temporary queue of interrupt queue TDs (to reverse order). */ @@ -776,7 +822,7 @@ ohci_process_done_queue(ohci_t *const ohci, const int spew_debug) /* Check if done head has been written. */ if (!(ohci->opreg->HcInterruptStatus & WritebackDoneHead)) - return; + return 0; /* Fetch current done head. Lsb is only interesting for hw interrupts. */ u32 phys_done_queue = ohci->hcca->HccaDoneHead & ~1; @@ -793,7 +839,11 @@ ohci_process_done_queue(ohci_t *const ohci, const int spew_debug) switch (done_td->config & TD_QUEUETYPE_MASK) { case TD_QUEUETYPE_ASYNC: - /* Free processed async TDs. */ + /* Free processed async TDs and count short transfer. */ + if (done_td->current_buffer_pointer) + result += (done_td->buffer_end & 0xfff) - + (done_td->current_buffer_pointer + & 0xfff) + 1; free((void *)done_td); break; case TD_QUEUETYPE_INTR: { @@ -850,5 +900,7 @@ ohci_process_done_queue(ohci_t *const ohci, const int spew_debug) } if (spew_debug) usb_debug("processed %d done tds, %d intr tds thereof.\n", i, j); + + return result; } diff --git a/payloads/libpayload/drivers/usb/ohci.h b/payloads/libpayload/drivers/usb/ohci.h index f5011676a1..9c31d9c015 100644 --- a/payloads/libpayload/drivers/usb/ohci.h +++ b/payloads/libpayload/drivers/usb/ohci.h @@ -33,8 +33,9 @@ #include #include - hci_t *ohci_init (pcidev_t addr); +hci_t *ohci_pci_init (pcidev_t addr); +hci_t *ohci_init (void *bar); - void ohci_rh_init (usbdev_t *dev); +void ohci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/drivers/usb/ohci_private.h b/payloads/libpayload/drivers/usb/ohci_private.h index a32203c582..e912837413 100644 --- a/payloads/libpayload/drivers/usb/ohci_private.h +++ b/payloads/libpayload/drivers/usb/ohci_private.h @@ -30,7 +30,6 @@ #ifndef __OHCI_PRIVATE_H #define __OHCI_PRIVATE_H -#include #include #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) @@ -258,6 +257,8 @@ hcca_t *hcca; usbdev_t *roothub; ed_t *periodic_ed; +#define DMA_SIZE (64 * 1024) + void *dma_buffer; } ohci_t; typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; diff --git a/payloads/libpayload/drivers/usb/ohci_rh.c b/payloads/libpayload/drivers/usb/ohci_rh.c index aa44f338ec..5d82bd59e0 100644 --- a/payloads/libpayload/drivers/usb/ohci_rh.c +++ b/payloads/libpayload/drivers/usb/ohci_rh.c @@ -83,6 +83,11 @@ ohci_rh_enable_port (usbdev_t *dev, int port) static void ohci_rh_disable_port (usbdev_t *dev, int port) { + if (RH_INST (dev)->port[port] != -1) { + usb_detach_device(dev->controller, RH_INST (dev)->port[port]); + RH_INST (dev)->port[port] = -1; + } + OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] = ClearPortEnable; // disable port int timeout = 50; /* timeout after 50 * 100us == 5ms */ while ((OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] @@ -121,7 +126,7 @@ ohci_rh_scanport (usbdev_t *dev, int port) return; } - int speed = (OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] & LowSpeedDeviceAttached) != 0; + usb_speed speed = (OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] & LowSpeedDeviceAttached) != 0; RH_INST (dev)->port[port] = usb_attach_device(dev->controller, dev->address, port, speed); } @@ -180,12 +185,9 @@ ohci_rh_init (usbdev_t *dev) dev->destroy = ohci_rh_destroy; dev->poll = ohci_rh_poll; - dev->data = malloc (sizeof (rh_inst_t)); - if (!dev->data) - fatal("Not enough memory for OHCI RH.\n"); - + dev->data = xmalloc (sizeof (rh_inst_t)); RH_INST (dev)->numports = OHCI_INST (dev->controller)->opreg->HcRhDescriptorA & NumberDownstreamPortsMask; - RH_INST (dev)->port = malloc(sizeof(int) * RH_INST (dev)->numports); + RH_INST (dev)->port = xmalloc(sizeof(int) * RH_INST (dev)->numports); usb_debug("%d ports registered\n", RH_INST (dev)->numports); for (i = 0; i < RH_INST (dev)->numports; i++) { diff --git a/payloads/libpayload/drivers/usb/quirks.c b/payloads/libpayload/drivers/usb/quirks.c index a8f2622e31..a426a8f8de 100644 --- a/payloads/libpayload/drivers/usb/quirks.c +++ b/payloads/libpayload/drivers/usb/quirks.c @@ -47,10 +47,11 @@ usb_quirks_t usb_quirks[] = { { 0x13fd, 0x0841, USB_QUIRK_NONE, 0 }, // Samsung SE-S084 /* Silence the warning for known devices with more - * than one interface + * than one interface. The 'interface' value should specify the + * interface we want to use (interface numbers usually start at 0). */ - { 0x1267, 0x0103, USB_QUIRK_NONE, 1 }, // Keyboard Trust KB-1800S - { 0x0a12, 0x0001, USB_QUIRK_NONE, 1 }, // Bluetooth Allnet ALL1575 + { 0x1267, 0x0103, USB_QUIRK_NONE, 0 }, // Keyboard Trust KB-1800S + { 0x0a12, 0x0001, USB_QUIRK_NONE, 0 }, // Bluetooth Allnet ALL1575 /* Currently unsupported, possibly interesting devices: * FTDI serial: device 0x0403:0x6001 is USB 1.10 (class ff) @@ -83,6 +84,6 @@ int usb_interface_check(u16 vendor, u16 device) } } - return 0; + return -1; } diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c index bfa1b57d43..cdba3de101 100644 --- a/payloads/libpayload/drivers/usb/uhci.c +++ b/payloads/libpayload/drivers/usb/uhci.c @@ -147,22 +147,14 @@ uhci_reinit (hci_t *controller) } hci_t * -uhci_init (pcidev_t addr) +uhci_pci_init (pcidev_t addr) { int i; u16 reg16; hci_t *controller = new_controller (); - - if (!controller) - fatal("Could not create USB controller instance.\n"); - - controller->instance = malloc (sizeof (uhci_t)); - if(!controller->instance) - fatal("Not enough memory creating USB controller instance.\n"); - + controller->instance = xzalloc(sizeof (uhci_t)); controller->type = UHCI; - controller->start = uhci_start; controller->stop = uhci_stop; controller->reset = uhci_reset; @@ -170,25 +162,26 @@ uhci_init (pcidev_t addr) controller->shutdown = uhci_shutdown; controller->bulk = uhci_bulk; controller->control = uhci_control; + controller->set_address = generic_set_address; + controller->finish_device_config = NULL; + controller->destroy_device = NULL; controller->create_intr_queue = uhci_create_intr_queue; controller->destroy_intr_queue = uhci_destroy_intr_queue; controller->poll_intr_queue = uhci_poll_intr_queue; - for (i = 0; i < 128; i++) { - controller->devices[i] = 0; - } init_device_entry (controller, 0); UHCI_INST (controller)->roothub = controller->devices[0]; - controller->bus_address = addr; - controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1; /* ~1 clears the register type indicator that is set to 1 for IO space */ + /* ~1 clears the register type indicator that is set to 1 + * for IO space */ + controller->reg_base = pci_read_config32 (addr, 0x20) & ~1; /* kill legacy support handler */ uhci_stop (controller); mdelay (1); uhci_reg_write16 (controller, USBSTS, 0x3f); - reg16 = pci_read_config16(controller->bus_address, 0xc0); + reg16 = pci_read_config16(addr, 0xc0); reg16 &= 0xdf80; - pci_write_config16 (controller->bus_address, 0xc0, reg16); + pci_write_config16 (addr, 0xc0, reg16); UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t)); /* 4kb aligned to 4kb */ if (! UHCI_INST (controller)->framelistptr) @@ -253,8 +246,6 @@ uhci_shutdown (hci_t *controller) if (controller == 0) return; detach_controller (controller); - UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)-> - roothub); uhci_reg_write16(controller, USBCMD, uhci_reg_read16(controller, USBCMD) & 0); // stop work free (UHCI_INST (controller)->framelistptr); @@ -382,7 +373,7 @@ uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen } else { usb_debug ("control packet, req %x\n", req); td_dump (td); - result = 1; + result = -1; } free (tds); return result; @@ -461,10 +452,8 @@ uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) size -= maxpsize; } if (run_schedule (ep->dev, tds) == 1) { - usb_debug("Stalled. Trying to clean up.\n"); - clear_stall (ep); free (tds); - return 1; + return -1; } ep->toggle = toggle; free (tds); diff --git a/payloads/libpayload/drivers/usb/uhci.h b/payloads/libpayload/drivers/usb/uhci.h index 2ef3f0b499..6bb5c17528 100644 --- a/payloads/libpayload/drivers/usb/uhci.h +++ b/payloads/libpayload/drivers/usb/uhci.h @@ -33,8 +33,8 @@ #include #include - hci_t *uhci_init (pcidev_t addr); +hci_t *uhci_pci_init (pcidev_t addr); - void uhci_rh_init (usbdev_t *dev); +void uhci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/drivers/usb/uhci_rh.c b/payloads/libpayload/drivers/usb/uhci_rh.c index 44ba498274..4668c4ecae 100644 --- a/payloads/libpayload/drivers/usb/uhci_rh.c +++ b/payloads/libpayload/drivers/usb/uhci_rh.c @@ -133,7 +133,7 @@ uhci_rh_scanport (usbdev_t *dev, int port) uhci_rh_disable_port (dev, port); uhci_rh_enable_port (dev, port); - int speed = ((uhci_reg_read16 (dev->controller, portsc) >> 8) & 1); + usb_speed speed = ((uhci_reg_read16 (dev->controller, portsc) >> 8) & 1); RH_INST (dev)->port[offset] = usb_attach_device(dev->controller, dev->address, portsc, speed); } @@ -176,6 +176,8 @@ uhci_rh_report_port_changes (usbdev_t *dev) static void uhci_rh_destroy (usbdev_t *dev) { + usb_detach_device (dev->controller, 1); + usb_detach_device (dev->controller, 2); uhci_rh_disable_port (dev, 1); uhci_rh_disable_port (dev, 2); free (RH_INST (dev)); @@ -197,9 +199,7 @@ uhci_rh_init (usbdev_t *dev) uhci_rh_enable_port (dev, 1); uhci_rh_enable_port (dev, 2); - dev->data = malloc (sizeof (rh_inst_t)); - if (!dev->data) - fatal("Not enough memory for UHCI RH.\n"); + dev->data = xmalloc (sizeof (rh_inst_t)); RH_INST (dev)->port[0] = -1; RH_INST (dev)->port[1] = -1; diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c index 23561c40aa..68f13c0e50 100644 --- a/payloads/libpayload/drivers/usb/usb.c +++ b/payloads/libpayload/drivers/usb/usb.c @@ -32,20 +32,16 @@ #include #include +#define DR_DESC gen_bmRequestType(device_to_host, standard_type, dev_recp) + hci_t *usb_hcs = 0; hci_t * new_controller (void) { - hci_t *controller = malloc (sizeof (hci_t)); - - if (controller) { - /* atomic */ - controller->next = usb_hcs; - usb_hcs = controller; - /* atomic end */ - } - + hci_t *controller = xzalloc(sizeof (hci_t)); + controller->next = usb_hcs; + usb_hcs = controller; return controller; } @@ -54,6 +50,9 @@ detach_controller (hci_t *controller) { if (controller == NULL) return; + + usb_detach_device(controller, 0); /* tear down root hub tree */ + if (usb_hcs == controller) { usb_hcs = controller->next; } else { @@ -100,21 +99,27 @@ usb_poll (void) } } -void +usbdev_t * init_device_entry (hci_t *controller, int i) { + usbdev_t *dev = calloc(1, sizeof(usbdev_t)); + if (!dev) { + usb_debug("no memory to allocate device structure\n"); + return NULL; + } if (controller->devices[i] != 0) usb_debug("warning: device %d reassigned?\n", i); - controller->devices[i] = malloc(sizeof(usbdev_t)); - controller->devices[i]->controller = controller; - controller->devices[i]->address = -1; - controller->devices[i]->hub = -1; - controller->devices[i]->port = -1; - controller->devices[i]->init = usb_nop_init; - controller->devices[i]->init (controller->devices[i]); + controller->devices[i] = dev; + dev->controller = controller; + dev->address = -1; + dev->hub = -1; + dev->port = -1; + dev->init = usb_nop_init; + dev->init (controller->devices[i]); + return dev; } -void +int set_feature (usbdev_t *dev, int endp, int feature, int rtype) { dev_req_t dr; @@ -125,10 +130,11 @@ set_feature (usbdev_t *dev, int endp, int feature, int rtype) dr.wValue = feature; dr.wIndex = endp; dr.wLength = 0; - dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); + + return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); } -void +int get_status (usbdev_t *dev, int intf, int rtype, int len, void *data) { dev_req_t dr; @@ -139,67 +145,37 @@ get_status (usbdev_t *dev, int intf, int rtype, int len, void *data) dr.wValue = 0; dr.wIndex = intf; dr.wLength = len; - dev->controller->control (dev, IN, sizeof (dr), &dr, len, data); + + return dev->controller->control (dev, IN, sizeof (dr), &dr, len, data); } -u8 * -get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, - int descIdx, int langID) +int +get_descriptor (usbdev_t *dev, int rtype, int descType, int descIdx, + void *data, size_t len) { - u8 buf[8]; - u8 *result; dev_req_t dr; - int size; - dr.bmRequestType = bmRequestType; - dr.data_dir = device_to_host; // always like this for descriptors + dr.bmRequestType = rtype; dr.bRequest = GET_DESCRIPTOR; - dr.wValue = (descType << 8) | descIdx; - dr.wIndex = langID; - dr.wLength = 8; - if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) { - usb_debug ("getting descriptor size (type %x) failed\n", - descType); - } + dr.wValue = descType << 8 | descIdx; + dr.wIndex = 0; + dr.wLength = len; - if (descType == 1) { - device_descriptor_t *dd = (device_descriptor_t *) buf; - usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); - if (dd->bMaxPacketSize0 != 0) - dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; - } - - /* special case for configuration descriptors: they carry all their - subsequent descriptors with them, and keep the entire size at a - different location */ - size = buf[0]; - if (buf[1] == 2) { - int realsize = ((unsigned short *) (buf + 2))[0]; - size = realsize; - } - result = malloc (size); - memset (result, 0, size); - dr.wLength = size; - if (dev->controller-> - control (dev, IN, sizeof (dr), &dr, size, result)) { - usb_debug ("getting descriptor (type %x, size %x) failed\n", - descType, size); - } - - return result; + return dev->controller->control (dev, IN, sizeof (dr), &dr, len, data); } -void +int set_configuration (usbdev_t *dev) { dev_req_t dr; dr.bmRequestType = 0; dr.bRequest = SET_CONFIGURATION; - dr.wValue = dev->configuration[5]; + dr.wValue = dev->configuration->bConfigurationValue; dr.wIndex = 0; dr.wLength = 0; - dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); + + return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); } int @@ -213,18 +189,15 @@ clear_feature (usbdev_t *dev, int endp, int feature, int rtype) dr.wValue = feature; dr.wIndex = endp; dr.wLength = 0; - return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); + + return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0; } int clear_stall (endpoint_t *ep) { - usbdev_t *dev = ep->dev; - int endp = ep->endpoint; - int rtype = gen_bmRequestType (host_to_device, standard_type, - endp ? endp_recp : dev_recp); - - int ret = clear_feature (dev, endp, ENDPOINT_HALT, rtype); + int ret = clear_feature (ep->dev, ep->endpoint, ENDPOINT_HALT, + gen_bmRequestType (host_to_device, standard_type, endp_recp)); ep->toggle = 0; return ret; } @@ -233,22 +206,106 @@ clear_stall (endpoint_t *ep) static int get_free_address (hci_t *controller) { - int i; - for (i = 1; i < 128; i++) { - if (controller->devices[i] == 0) + int i = controller->latest_address + 1; + for (; i != controller->latest_address; i++) { + if (i >= ARRAY_SIZE(controller->devices) || i < 1) { + usb_debug("WARNING: Device addresses for controller %#x" + " wrapped around!\n", controller->reg_base); + i = 0; + continue; + } + if (controller->devices[i] == 0) { + controller->latest_address = i; return i; + } } usb_debug ("no free address found\n"); return -1; // no free address } +int +usb_decode_mps0(usb_speed speed, u8 bMaxPacketSize0) +{ + switch (speed) { + case LOW_SPEED: + if (bMaxPacketSize0 != 8) { + usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0); + bMaxPacketSize0 = 8; + } + return bMaxPacketSize0; + case FULL_SPEED: + switch (bMaxPacketSize0) { + case 8: case 16: case 32: case 64: + return bMaxPacketSize0; + default: + usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0); + return 8; + } + case HIGH_SPEED: + if (bMaxPacketSize0 != 64) { + usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0); + bMaxPacketSize0 = 64; + } + return bMaxPacketSize0; + case SUPER_SPEED: + if (bMaxPacketSize0 != 9) { + usb_debug("Invalid MPS0: 0x%02x\n", bMaxPacketSize0); + bMaxPacketSize0 = 9; + } + return 2 << bMaxPacketSize0; + default: /* GCC is stupid and cannot deal with enums correctly */ + return 8; + } +} + +/* Normalize bInterval to log2 of microframes */ static int -set_address (hci_t *controller, int speed, int hubport, int hubaddr) +usb_decode_interval(usb_speed speed, const endpoint_type type, const unsigned char bInterval) +{ +#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1) + switch (speed) { + case LOW_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case FULL_SPEED: + switch (type) { + case ISOCHRONOUS: + return (bInterval - 1) + 3; + case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case HIGH_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return LOG2(bInterval); + } + case SUPER_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return 0; + } + default: + return 0; + } +#undef LOG2 +} + +usbdev_t * +generic_set_address (hci_t *controller, usb_speed speed, + int hubport, int hubaddr) { int adr = get_free_address (controller); // address to set dev_req_t dr; - configuration_descriptor_t *cd; - device_descriptor_t *dd; memset (&dr, 0, sizeof (dr)); dr.data_dir = host_to_device; @@ -259,8 +316,10 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) dr.wIndex = 0; dr.wLength = 0; - init_device_entry(controller, adr); - usbdev_t *dev = controller->devices[adr]; + usbdev_t *dev = init_device_entry(controller, adr); + if (!dev) + return NULL; + // dummy values for registering the address dev->address = 0; dev->hub = hubaddr; @@ -271,102 +330,177 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) dev->endpoints[0].maxpacketsize = 8; dev->endpoints[0].toggle = 0; dev->endpoints[0].direction = SETUP; - mdelay (50); - if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) { + dev->endpoints[0].type = CONTROL; + if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0) { + usb_debug ("set_address failed\n"); + usb_detach_device (controller, adr); + return NULL; + } + mdelay (SET_ADDRESS_MDELAY); + + u8 buf[8]; + dev->address = adr; + if (get_descriptor (dev, DR_DESC, DT_DEV, 0, buf, sizeof(buf)) + != sizeof(buf)) { + usb_debug("first get_descriptor(DT_DEV) failed\n"); + usb_detach_device (controller, adr); + return NULL; + } + dev->endpoints[0].maxpacketsize = usb_decode_mps0(speed, buf[7]); + + return dev; +} + +static int +set_address (hci_t *controller, usb_speed speed, int hubport, int hubaddr) +{ + usbdev_t *dev = controller->set_address(controller, speed, + hubport, hubaddr); + if (!dev) { usb_debug ("set_address failed\n"); return -1; } - mdelay (50); - dev->address = adr; - dev->descriptor = get_descriptor (dev, gen_bmRequestType - (device_to_host, standard_type, dev_recp), 1, 0, 0); - dd = (device_descriptor_t *) dev->descriptor; - usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x)", - dd->idVendor, dd->idProduct, - dd->bcdUSB >> 8, dd->bcdUSB & 0xff); - dev->quirks = usb_quirk_check(dd->idVendor, dd->idProduct); - - usb_debug ("\ndevice has %x configurations\n", dd->bNumConfigurations); - if (dd->bNumConfigurations == 0) { - /* device isn't usable */ - usb_debug ("... no usable configuration!\n"); - dev->address = 0; + dev->descriptor = malloc(sizeof(*dev->descriptor)); + if (!dev->descriptor || get_descriptor (dev, DR_DESC, DT_DEV, 0, + dev->descriptor, sizeof(*dev->descriptor)) + != sizeof(*dev->descriptor)) { + usb_debug ("get_descriptor(DT_DEV) failed\n"); + usb_detach_device (controller, dev->address); return -1; } - dev->configuration = get_descriptor (dev, gen_bmRequestType - (device_to_host, standard_type, dev_recp), 2, 0, 0); - cd = (configuration_descriptor_t *) dev->configuration; - set_configuration (dev); - interface_descriptor_t *interface = - (interface_descriptor_t *) (((char *) cd) + cd->bLength); - { - int i; - int num = cd->bNumInterfaces; - interface_descriptor_t *current = interface; - usb_debug ("device has %x interfaces\n", num); - if (num > 1) { - int interfaces = usb_interface_check(dd->idVendor, dd->idProduct); - if (interfaces) { - /* Well known device, don't warn */ - num = interfaces; - } else { + usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x, MPS0: %d)\n", + dev->descriptor->idVendor, dev->descriptor->idProduct, + dev->descriptor->bcdUSB >> 8, dev->descriptor->bcdUSB & 0xff, + dev->endpoints[0].maxpacketsize); + dev->quirks = usb_quirk_check(dev->descriptor->idVendor, + dev->descriptor->idProduct); - usb_debug ("\nNOTICE: This driver defaults to using the first interface.\n" - "This might be the wrong choice and lead to limited functionality\n" - "of the device. Please report such a case to coreboot@coreboot.org\n" - "as you might be the first.\n"); - /* we limit to the first interface, as there was no need to - * implement something else for the time being. If you need - * it, see the SetInterface and GetInterface functions in - * the USB specification, and adapt appropriately. - */ - num = (num > 1) ? 1 : num; - } - } - for (i = 0; i < num; i++) { - int j; - usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n", - current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); - endpoint_descriptor_t *endp = - (endpoint_descriptor_t *) (((char *) current) - + current->bLength); - if (interface->bInterfaceClass == 0x3) - endp = (endpoint_descriptor_t *) (((char *) endp) + ((char *) endp)[0]); // ignore HID descriptor - memset (dev->endpoints, 0, sizeof (dev->endpoints)); - dev->num_endp = 1; // 0 always exists - dev->endpoints[0].dev = dev; - dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; - dev->endpoints[0].direction = SETUP; - dev->endpoints[0].type = CONTROL; - for (j = 1; j <= current->bNumEndpoints; j++) { -#ifdef USB_DEBUG - static const char *transfertypes[4] = { - "control", "isochronous", "bulk", "interrupt" - }; - usb_debug (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", endp->wMaxPacketSize, transfertypes[endp->bmAttributes]); -#endif - endpoint_t *ep = - &dev->endpoints[dev->num_endp++]; - ep->dev = dev; - ep->endpoint = endp->bEndpointAddress; - ep->toggle = 0; - ep->maxpacketsize = endp->wMaxPacketSize; - ep->direction = - ((endp->bEndpointAddress & 0x80) == - 0) ? OUT : IN; - ep->type = endp->bmAttributes; - endp = (endpoint_descriptor_t - *) (((char *) endp) + endp->bLength); - } - current = (interface_descriptor_t *) endp; - } + usb_debug ("device has %d configurations\n", + dev->descriptor->bNumConfigurations); + if (dev->descriptor->bNumConfigurations == 0) { + /* device isn't usable */ + usb_debug ("... no usable configuration!\n"); + usb_detach_device (controller, dev->address); + return -1; } - int class = dd->bDeviceClass; + u16 buf[2]; + if (get_descriptor (dev, DR_DESC, DT_CFG, 0, buf, sizeof(buf)) + != sizeof(buf)) { + usb_debug ("first get_descriptor(DT_CFG) failed\n"); + usb_detach_device (controller, dev->address); + return -1; + } + /* workaround for some USB devices: wait until they're ready, or + * they send a NAK when they're not allowed to do. 1ms is enough */ + mdelay(1); + dev->configuration = malloc(buf[1]); + if (!dev->configuration) { + usb_debug ("could not allocate %d bytes for DT_CFG\n", buf[1]); + usb_detach_device (controller, dev->address); + return -1; + } + if (get_descriptor (dev, DR_DESC, DT_CFG, 0, dev->configuration, + buf[1]) != buf[1]) { + usb_debug ("get_descriptor(DT_CFG) failed\n"); + usb_detach_device (controller, dev->address); + return -1; + } + configuration_descriptor_t *cd = dev->configuration; + if (cd->wTotalLength != buf[1]) { + usb_debug ("configuration descriptor size changed, aborting\n"); + usb_detach_device (controller, dev->address); + return -1; + } + + /* + * If the device is not well known (ifnum == -1), we use the first + * interface we encounter, as there was no need to implement something + * else for the time being. If you need it, see the SetInterface and + * GetInterface functions in the USB specification and set it yourself. + */ + usb_debug ("device has %x interfaces\n", cd->bNumInterfaces); + int ifnum = usb_interface_check(dev->descriptor->idVendor, + dev->descriptor->idProduct); + if (cd->bNumInterfaces > 1 && ifnum < 0) + usb_debug ("NOTICE: Your device has multiple interfaces and\n" + "this driver will only use the first one. That may\n" + "be the wrong choice and cause the device to not\n" + "work correctly. Please report this case\n" + "(including the above debugging output) to\n" + "coreboot@coreboot.org to have the device added to\n" + "the list of well-known quirks.\n"); + + u8 *end = (void *)dev->configuration + cd->wTotalLength; + interface_descriptor_t *intf; + u8 *ptr; + + /* Find our interface (or the first good one if we don't know) */ + for (ptr = (void *)dev->configuration + sizeof(*cd); ; ptr += ptr[0]) { + if (ptr + 2 > end || !ptr[0] || ptr + ptr[0] > end) { + usb_debug ("Couldn't find usable DT_INTF\n"); + usb_detach_device (controller, dev->address); + return -1; + } + if (ptr[1] != DT_INTF) + continue; + intf = (void *)ptr; + if (intf->bLength != sizeof(*intf)) { + usb_debug ("Skipping broken DT_INTF\n"); + continue; + } + if (ifnum >= 0 && intf->bInterfaceNumber != ifnum) + continue; + usb_debug ("Interface %d: class 0x%x, sub 0x%x. proto 0x%x\n", + intf->bInterfaceNumber, intf->bInterfaceClass, + intf->bInterfaceSubClass, intf->bInterfaceProtocol); + ptr += sizeof(*intf); + break; + } + + /* Gather up all endpoints belonging to this inteface */ + dev->num_endp = 1; + for (; ptr + 2 <= end && ptr[0] && ptr + ptr[0] <= end; ptr += ptr[0]) { + if (ptr[1] == DT_INTF || ptr[1] == DT_CFG || + dev->num_endp >= ARRAY_SIZE(dev->endpoints)) + break; + if (ptr[1] != DT_ENDP) + continue; + + endpoint_descriptor_t *desc = (void *)ptr; + static const char *transfertypes[4] = { + "control", "isochronous", "bulk", "interrupt" + }; + usb_debug (" #Endpoint %d (%s), max packet size %x, type %s\n", + desc->bEndpointAddress & 0x7f, + (desc->bEndpointAddress & 0x80) ? "in" : "out", + desc->wMaxPacketSize, + transfertypes[desc->bmAttributes & 0x3]); + + endpoint_t *ep = &dev->endpoints[dev->num_endp++]; + ep->dev = dev; + ep->endpoint = desc->bEndpointAddress; + ep->toggle = 0; + ep->maxpacketsize = desc->wMaxPacketSize; + ep->direction = (desc->bEndpointAddress & 0x80) ? IN : OUT; + ep->type = desc->bmAttributes & 0x3; + ep->interval = usb_decode_interval (dev->speed, ep->type, + desc->bInterval); + } + + if ((controller->finish_device_config && + controller->finish_device_config(dev)) || + set_configuration(dev) < 0) { + usb_debug ("Could not finalize device configuration\n"); + usb_detach_device (controller, dev->address); + return -1; + } + + int class = dev->descriptor->bDeviceClass; if (class == 0) - class = interface->bInterfaceClass; + class = intf->bInterfaceClass; enum { audio_device = 0x01, @@ -386,7 +520,7 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) wireless_device = 0xe0, misc_device = 0xef, }; - usb_debug(", class: "); + usb_debug("Class: "); switch (class) { case audio_device: usb_debug("audio\n"); @@ -396,9 +530,9 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) break; case hid_device: usb_debug ("HID\n"); -#ifdef CONFIG_USB_HID - controller->devices[adr]->init = usb_hid_init; - return adr; +#ifdef CONFIG_LP_USB_HID + dev->init = usb_hid_init; + return dev->address; #else usb_debug ("NOTICE: USB HID support not compiled in\n"); #endif @@ -414,21 +548,25 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) break; case msc_device: usb_debug ("MSC\n"); -#ifdef CONFIG_USB_MSC - controller->devices[adr]->init = usb_msc_init; - return adr; +#ifdef CONFIG_LP_USB_MSC + dev->init = usb_msc_init; + return dev->address; #else usb_debug ("NOTICE: USB MSC support not compiled in\n"); #endif break; case hub_device: - usb_debug ("hub\n"); -#ifdef CONFIG_USB_HUB - controller->devices[adr]->init = usb_hub_init; - return adr; + if (speed < SUPER_SPEED) { + usb_debug ("hub (2.0)\n"); +#ifdef CONFIG_LP_USB_HUB + dev->init = usb_hub_init; + return dev->address; #else - usb_debug ("NOTICE: USB hub support not compiled in.\n"); + usb_debug ("NOTICE: USB hub support not compiled in\n"); #endif + } else { + usb_debug ("hub (3.0) - not yet supported!\n"); + } break; case cdc_device: usb_debug("CDC\n"); @@ -455,8 +593,8 @@ set_address (hci_t *controller, int speed, int hubport, int hubaddr) usb_debug("unsupported class %x\n", class); break; } - controller->devices[adr]->init = usb_generic_init; - return adr; + dev->init = usb_generic_init; + return dev->address; } /* @@ -471,16 +609,23 @@ usb_detach_device(hci_t *controller, int devno) been called yet by the usb class driver */ if (controller->devices[devno]) { controller->devices[devno]->destroy (controller->devices[devno]); + if (controller->destroy_device) + controller->destroy_device(controller, devno); + if (controller->devices[devno]->configuration) + free(controller->devices[devno]->configuration); + if (controller->devices[devno]->descriptor) + free(controller->devices[devno]->descriptor); free(controller->devices[devno]); controller->devices[devno] = NULL; } } int -usb_attach_device(hci_t *controller, int hubaddress, int port, int speed) +usb_attach_device(hci_t *controller, int hubaddress, int port, usb_speed speed) { - static const char* speeds[] = { "full", "low", "high" }; - usb_debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no"); + static const char* speeds[] = { "full", "low", "high", "super" }; + usb_debug ("%sspeed device\n", (speed < sizeof(speeds) / sizeof(char*)) + ? speeds[speed] : "invalid value - no"); int newdev = set_address (controller, speed, port, hubaddress); if (newdev == -1) return -1; @@ -506,4 +651,35 @@ usb_generic_init (usbdev_t *dev) if (usb_generic_create) usb_generic_create(dev); + + if (dev->data == NULL) { + usb_debug("Detaching device not used by payload\n"); + usb_detach_device(dev->controller, dev->address); + } +} + +/* + * returns the address of the closest USB2.0 hub, which is responsible for + * split transactions, along with the number of the used downstream port + */ +int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const port) +{ + const usbdev_t *usb1dev; + + do { + usb1dev = dev; + if ((dev->hub >= 0) && (dev->hub < 128)) + dev = dev->controller->devices[dev->hub]; + else + dev = NULL; + } while (dev && (dev->speed < 2)); + + if (dev) { + *addr = usb1dev->hub; + *port = usb1dev->port; + return 0; + } + + usb_debug("Couldn't find closest USB2.0 hub.\n"); + return 1; } diff --git a/payloads/libpayload/drivers/usb/usbhid.c b/payloads/libpayload/drivers/usb/usbhid.c index f14bda0c04..74b6d5d591 100644 --- a/payloads/libpayload/drivers/usb/usbhid.c +++ b/payloads/libpayload/drivers/usb/usbhid.c @@ -138,7 +138,7 @@ struct layout_maps { static const struct layout_maps *map; static const struct layout_maps keyboard_layouts[] = { -// #ifdef CONFIG_PC_KEYBOARD_LAYOUT_US +// #ifdef CONFIG_LP_PC_KEYBOARD_LAYOUT_US { .country = "us", .map = { { /* No modifier */ -1, -1, -1, -1, 'a', 'b', 'c', 'd', @@ -391,7 +391,8 @@ usb_hid_set_protocol (usbdev_t *dev, interface_descriptor_t *interface, hid_prot static struct console_input_driver cons = { .havekey = usbhid_havechar, - .getchar = usbhid_getchar + .getchar = usbhid_getchar, + .input_type = CONSOLE_INPUT_TYPE_USB, }; @@ -448,14 +449,18 @@ usb_hid_init (usbdev_t *dev) usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS); usb_debug (" activating...\n"); - HID_INST (dev)->descriptor = - (hid_descriptor_t *) - get_descriptor(dev, gen_bmRequestType - (device_to_host, standard_type, iface_recp), - 0x21, 0, 0); - countrycode = HID_INST(dev)->descriptor->bCountryCode; + hid_descriptor_t *desc = malloc(sizeof(hid_descriptor_t)); + if (!desc || get_descriptor(dev, gen_bmRequestType( + device_to_host, standard_type, iface_recp), + 0x21, 0, desc, sizeof(*desc)) != sizeof(*desc)) { + usb_debug ("get_descriptor(HID) failed\n"); + usb_detach_device (dev->controller, dev->address); + return; + } + HID_INST (dev)->descriptor = desc; + countrycode = desc->bCountryCode; /* 35 countries defined: */ - if (countrycode > 35) + if (countrycode >= ARRAY_SIZE(countries)) countrycode = 0; usb_debug (" Keyboard has %s layout (country code %02x)\n", countries[countrycode][0], countrycode); @@ -467,15 +472,18 @@ usb_hid_init (usbdev_t *dev) dev->destroy = usb_hid_destroy; dev->poll = usb_hid_poll; int i; - for (i = 0; i <= dev->num_endp; i++) { - if (dev->endpoints[i].endpoint == 0) - continue; + for (i = 1; i < dev->num_endp; i++) { if (dev->endpoints[i].type != INTERRUPT) continue; if (dev->endpoints[i].direction != IN) continue; break; } + if (i >= dev->num_endp) { + usb_debug ("Could not find HID endpoint\n"); + usb_detach_device (dev->controller, dev->address); + return; + } usb_debug (" found endpoint %x for interrupt-in\n", i); /* 20 buffers of 8 bytes, for every 10 msecs */ HID_INST(dev)->queue = dev->controller->create_intr_queue (&dev->endpoints[i], 8, 20, 10); diff --git a/payloads/libpayload/drivers/usb/usbhub.c b/payloads/libpayload/drivers/usb/usbhub.c index 90e08dbde4..e12fd92c3f 100644 --- a/payloads/libpayload/drivers/usb/usbhub.c +++ b/payloads/libpayload/drivers/usb/usbhub.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008-2010 coresystems GmbH + * Copyright (C) 2013 secunet Security Networks AG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,171 +27,120 @@ * SUCH DAMAGE. */ -#include +//#define USB_DEBUG -// assume that host_to_device is overwritten if necessary +#include +#include "generic_hub.h" + +/* assume that host_to_device is overwritten if necessary */ #define DR_PORT gen_bmRequestType(host_to_device, class_type, other_recp) -/* status bits */ +/* status (and status change) bits */ #define PORT_CONNECTION 0x1 #define PORT_ENABLE 0x2 #define PORT_RESET 0x10 -/* status change bits */ -#define C_PORT_CONNECTION 0x1 /* feature selectors (for setting / clearing features) */ #define SEL_PORT_RESET 0x4 #define SEL_PORT_POWER 0x8 #define SEL_C_PORT_CONNECTION 0x10 -typedef struct { - int num_ports; - int *ports; - hub_descriptor_t *descriptor; -} usbhub_inst_t; - -#define HUB_INST(dev) ((usbhub_inst_t*)(dev)->data) - -static void -usb_hub_destroy (usbdev_t *dev) +static int +usb_hub_port_status_changed(usbdev_t *const dev, const int port) { - int i; - - /* First, detach all devices behind this hub. */ - int *const ports = HUB_INST (dev)->ports; - for (i = 1; i <= HUB_INST (dev)->num_ports; i++) { - if (ports[i] != -1) { - usb_detach_device(dev->controller, ports[i]); - ports[i] = -1; - } - } - - free (HUB_INST (dev)->ports); - free (HUB_INST (dev)->descriptor); - free (HUB_INST (dev)); -} - -static void -usb_hub_scanport (usbdev_t *dev, int port) -{ - int timeout; - unsigned short buf[2]; - get_status (dev, port, DR_PORT, 4, buf); - if (!(buf[1] & C_PORT_CONNECTION)) - /* no change */ - return; - - /* clear Port Connection status change */ - clear_feature (dev, port, SEL_C_PORT_CONNECTION, DR_PORT); - - int devno = HUB_INST (dev)->ports[port]; - if (devno != -1) { - /* detach device, either because of re-/ or disconnect */ - usb_detach_device(dev->controller, devno); - HUB_INST (dev)->ports[port] = -1; + int ret = get_status (dev, port, DR_PORT, sizeof(buf), buf); + if (ret >= 0) { + ret = buf[1] & PORT_CONNECTION; + if (ret) + clear_feature (dev, port, SEL_C_PORT_CONNECTION, + DR_PORT); } - - if (!(buf[0] & PORT_CONNECTION)) - /* no device connected, nothing to do */ - return; - - /* wait 100ms for port to become stable */ - mdelay (100); // usb20 spec 9.1.2 - - /* reset port */ - set_feature (dev, port, SEL_PORT_RESET, DR_PORT); - /* wait at least 10ms (usb2.0 spec 11.5.1.5: 10ms to 20ms) */ - mdelay (10); - /* wait for hub to finish reset */ - timeout = 30; /* time out after 10ms (spec) + 20ms (kindly) */ - do { - get_status (dev, port, DR_PORT, 4, buf); - mdelay(1); timeout--; - } while ((buf[0] & PORT_RESET) && timeout); - if (!timeout) - usb_debug("Warning: usbhub: port reset timed out.\n"); - - /* wait for port to be enabled. the hub is responsible for this */ - timeout = 500; /* time out after 500ms */ - do { - get_status (dev, port, DR_PORT, 4, buf); - mdelay(1); timeout--; - } while (!(buf[0] & PORT_ENABLE) && timeout); - if (!timeout) - usb_debug("Warning: usbhub: port enabling timed out.\n"); - - get_status (dev, port, DR_PORT, 4, buf); - /* bit 10 9 - * 0 0 full speed - * 0 1 low speed - * 1 0 high speed - */ - int speed = ((buf[0] >> 9) & 3) ; - - HUB_INST (dev)->ports[port] = usb_attach_device(dev->controller, dev->address, port, speed); - - /* clear Port Connection status change */ - clear_feature (dev, port, SEL_C_PORT_CONNECTION, DR_PORT); + return ret; } static int -usb_hub_report_port_changes (usbdev_t *dev) +usb_hub_port_connected(usbdev_t *const dev, const int port) { - int port; unsigned short buf[2]; - for (port = 1; port <= HUB_INST (dev)->num_ports; port++) { - get_status (dev, port, DR_PORT, 4, buf); - if (buf[1] & C_PORT_CONNECTION) - return port; + int ret = get_status (dev, port, DR_PORT, sizeof(buf), buf); + if (ret >= 0) + ret = buf[0] & PORT_CONNECTION; + return ret; +} + +static int +usb_hub_port_in_reset(usbdev_t *const dev, const int port) +{ + unsigned short buf[2]; + int ret = get_status (dev, port, DR_PORT, sizeof(buf), buf); + if (ret >= 0) + ret = buf[0] & PORT_RESET; + return ret; +} + +static int +usb_hub_port_enabled(usbdev_t *const dev, const int port) +{ + unsigned short buf[2]; + int ret = get_status (dev, port, DR_PORT, sizeof(buf), buf); + if (ret >= 0) + ret = buf[0] & PORT_ENABLE; + return ret; +} + +static usb_speed +usb_hub_port_speed(usbdev_t *const dev, const int port) +{ + unsigned short buf[2]; + int ret = get_status (dev, port, DR_PORT, sizeof(buf), buf); + if (ret >= 0 && (buf[0] & PORT_ENABLE)) { + /* bit 10 9 + * 0 0 full speed + * 0 1 low speed + * 1 0 high speed + * 1 1 super speed (hack, not in spec!) + */ + ret = (buf[0] >> 9) & 0x3; + } else { + ret = -1; } - - // no change - return -1; + return ret; } -static void -usb_hub_enable_port (usbdev_t *dev, int port) +static int +usb_hub_enable_port(usbdev_t *const dev, const int port) { - set_feature (dev, port, SEL_PORT_POWER, DR_PORT); - mdelay (20); + return set_feature(dev, port, SEL_PORT_POWER, DR_PORT); } -#if 0 -static void -usb_hub_disable_port (usbdev_t *dev, int port) +static int +usb_hub_start_port_reset(usbdev_t *const dev, const int port) { + return set_feature (dev, port, SEL_PORT_RESET, DR_PORT); } -#endif -static void -usb_hub_poll (usbdev_t *dev) -{ - int port; - while ((port = usb_hub_report_port_changes (dev)) != -1) - usb_hub_scanport (dev, port); -} +static const generic_hub_ops_t usb_hub_ops = { + .hub_status_changed = NULL, + .port_status_changed = usb_hub_port_status_changed, + .port_connected = usb_hub_port_connected, + .port_in_reset = usb_hub_port_in_reset, + .port_enabled = usb_hub_port_enabled, + .port_speed = usb_hub_port_speed, + .enable_port = usb_hub_enable_port, + .disable_port = NULL, + .start_port_reset = usb_hub_start_port_reset, + .reset_port = generic_hub_resetport, +}; void -usb_hub_init (usbdev_t *dev) +usb_hub_init(usbdev_t *const dev) { - int i; - dev->destroy = usb_hub_destroy; - dev->poll = usb_hub_poll; + hub_descriptor_t desc; /* won't fit the whole thing, we don't care */ + if (get_descriptor(dev, gen_bmRequestType(device_to_host, class_type, + dev_recp), 0x29, 0, &desc, sizeof(desc)) != sizeof(desc)) { + usb_debug("get_descriptor(HUB) failed\n"); + usb_detach_device(dev->controller, dev->address); + return; + } - dev->data = malloc (sizeof (usbhub_inst_t)); - - if (!dev->data) - fatal("Not enough memory for USB hub.\n"); - - HUB_INST (dev)->descriptor = (hub_descriptor_t *) get_descriptor(dev, - gen_bmRequestType(device_to_host, class_type, dev_recp), 0x29, 0, 0); - HUB_INST (dev)->num_ports = HUB_INST (dev)->descriptor->bNbrPorts; - HUB_INST (dev)->ports = - malloc (sizeof (int) * (HUB_INST (dev)->num_ports + 1)); - if (! HUB_INST (dev)->ports) - fatal("Not enough memory for USB hub ports.\n"); - - for (i = 1; i <= HUB_INST (dev)->num_ports; i++) - HUB_INST (dev)->ports[i] = -1; - for (i = 1; i <= HUB_INST (dev)->num_ports; i++) - usb_hub_enable_port (dev, i); + generic_hub_init(dev, desc.bNbrPorts, &usb_hub_ops); } diff --git a/payloads/libpayload/drivers/usb/usbinit.c b/payloads/libpayload/drivers/usb/usbinit.c index 76653ff0d0..b1b66b4342 100644 --- a/payloads/libpayload/drivers/usb/usbinit.c +++ b/payloads/libpayload/drivers/usb/usbinit.c @@ -27,14 +27,17 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG #include #include #include "uhci.h" #include "ohci.h" #include "ehci.h" #include "xhci.h" +#include "dwc2.h" #include +#ifdef CONFIG_LP_USB_PCI /** * Initializes USB controller attached to PCI * @@ -58,8 +61,6 @@ static int usb_controller_initialize(int bus, int dev, int func) prog_if = (class >> 8) & 0xff; /* enable busmaster */ -#define PCI_COMMAND 4 -#define PCI_COMMAND_MASTER 4 if (devclass == 0xc03) { u32 pci_command; @@ -71,36 +72,36 @@ static int usb_controller_initialize(int bus, int dev, int func) pciid >> 16, pciid & 0xFFFF, func); switch (prog_if) { case 0x00: -#ifdef CONFIG_USB_UHCI +#ifdef CONFIG_LP_USB_UHCI usb_debug("UHCI controller\n"); - uhci_init (pci_device); + uhci_pci_init (pci_device); #else usb_debug("UHCI controller (not supported)\n"); #endif break; case 0x10: -#ifdef CONFIG_USB_OHCI +#ifdef CONFIG_LP_USB_OHCI usb_debug("OHCI controller\n"); - ohci_init(pci_device); + ohci_pci_init(pci_device); #else usb_debug("OHCI controller (not supported)\n"); #endif break; case 0x20: -#ifdef CONFIG_USB_EHCI +#ifdef CONFIG_LP_USB_EHCI usb_debug("EHCI controller\n"); - ehci_init(pci_device); + ehci_pci_init(pci_device); #else usb_debug("EHCI controller (not supported)\n"); #endif break; case 0x30: -#ifdef CONFIG_USB_XHCI +#ifdef CONFIG_LP_USB_XHCI usb_debug("xHCI controller\n"); - xhci_init(pci_device); + xhci_pci_init(pci_device); #else usb_debug("xHCI controller (not supported)\n"); #endif @@ -154,12 +155,40 @@ static void usb_scan_pci_bus(int bus) } } } +#endif /** * Initialize all USB controllers attached to PCI. */ int usb_initialize(void) { +#ifdef CONFIG_LP_USB_PCI usb_scan_pci_bus(0); +#endif return 0; } + +hci_t *usb_add_mmio_hc(hc_type type, void *bar) +{ + switch (type) { +#ifdef CONFIG_LP_USB_OHCI + case OHCI: + return ohci_init(bar); +#endif +#ifdef CONFIG_LP_USB_EHCI + case EHCI: + return ehci_init(bar); +#endif +#ifdef CONFIG_LP_USB_DWC2 + case DWC2: + return dwc2_init(bar); +#endif +#ifdef CONFIG_LP_USB_XHCI + case XHCI: + return xhci_init(bar); +#endif + default: + usb_debug("HC type %d (at %p) is not supported!\n", type, bar); + return NULL; + } +} diff --git a/payloads/libpayload/drivers/usb/usbmsc.c b/payloads/libpayload/drivers/usb/usbmsc.c index 16af44888e..62428b6ebe 100644 --- a/payloads/libpayload/drivers/usb/usbmsc.c +++ b/payloads/libpayload/drivers/usb/usbmsc.c @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG #include #include #include @@ -66,25 +67,37 @@ static const char *msc_protocol_strings[0x51] = { "Bulk-Only Transport" }; +static void +usb_msc_create_disk (usbdev_t *dev) +{ + if (usbdisk_create) { + usbdisk_create (dev); + MSC_INST (dev)->usbdisk_created = 1; + } +} + +static void +usb_msc_remove_disk (usbdev_t *dev) +{ + if (MSC_INST (dev)->usbdisk_created && usbdisk_remove) + usbdisk_remove (dev); +} static void usb_msc_destroy (usbdev_t *dev) { if (dev->data) { - if (MSC_INST (dev)->usbdisk_created && usbdisk_remove) - usbdisk_remove (dev); + usb_msc_remove_disk (dev); free (dev->data); } dev->data = 0; } -static void -usb_msc_poll (usbdev_t *dev) -{ -} - const int DEV_RESET = 0xff; const int GET_MAX_LUN = 0xfe; +/* Many USB3 devices do not work with large transfer requests. + * Limit the request size to 64KB chunks to ensure maximum compatibility. */ +const int MAX_CHUNK_BYTES = 1024 * 64; const unsigned int cbw_signature = 0x43425355; const unsigned int csw_signature = 0x53425355; @@ -113,7 +126,8 @@ enum { * MSC commands can be * successful, * fail with proper response or - * fail totally, which results in detaching of the usb device. + * fail totally, which results in detaching of the usb device + * and immediate cleanup of the usbdev_t structure. * In the latter case the caller has to make sure, that he won't * use the device any more. */ @@ -122,6 +136,10 @@ enum { static int request_sense (usbdev_t *dev); +static int +request_sense_no_media (usbdev_t *dev); +static void +usb_msc_poll (usbdev_t *dev); static int reset_transport (usbdev_t *dev) @@ -140,7 +158,7 @@ reset_transport (usbdev_t *dev) dr.wLength = 0; /* if any of these fails, detach device, as we are lost */ - if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) || + if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0 || clear_stall (MSC_INST (dev)->bulk_in) || clear_stall (MSC_INST (dev)->bulk_out)) { usb_debug ("Detaching unresponsive device.\n"); @@ -152,10 +170,10 @@ reset_transport (usbdev_t *dev) } /* device may stall this command, so beware! */ -static int -get_max_luns (usbdev_t *dev) +static void +initialize_luns (usbdev_t *dev) { - unsigned char luns = 75; + usbmsc_inst_t *msc = MSC_INST (dev); dev_req_t dr; dr.bmRequestType = 0; dr.data_dir = device_to_host; @@ -167,38 +185,38 @@ get_max_luns (usbdev_t *dev) dr.wValue = 0; dr.wIndex = 0; dr.wLength = 1; - if (dev->controller->control (dev, IN, sizeof (dr), &dr, 1, &luns)) { - luns = 0; // assume only 1 lun if req fails - } - return luns; + if (dev->controller->control (dev, IN, sizeof (dr), &dr, + sizeof (msc->num_luns), &msc->num_luns) < 0) + msc->num_luns = 0; /* assume only 1 lun if req fails */ + msc->num_luns++; /* Get Max LUN returns number of last LUN */ + msc->lun = 0; } unsigned int tag; -unsigned char lun = 0; static void wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd, - int cmdlen) + int cmdlen, u8 lun) { memset (cbw, 0, sizeof (cbw_t)); cbw->dCBWSignature = cbw_signature; cbw->dCBWTag = ++tag; - cbw->bCBWLUN = lun; // static value per device + cbw->bCBWLUN = lun; cbw->dCBWDataTransferLength = datalen; cbw->bmCBWFlags = dir; - memcpy (cbw->CBWCB, cmd, sizeof (cbw->CBWCB)); + memcpy (cbw->CBWCB, cmd, cmdlen); cbw->bCBWCBLength = cmdlen; } static int get_csw (endpoint_t *ep, csw_t *csw) { - if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) { + if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) { clear_stall (ep); if (ep->dev->controller->bulk - (ep, sizeof (csw_t), (u8 *) csw, 1)) { + (ep, sizeof (csw_t), (u8 *) csw, 1) < 0) { return reset_transport (ep->dev); } } @@ -219,19 +237,19 @@ execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen, if ((cb[0] == 0x1b) && (cb[4] == 1)) { //start command, always succeed always_succeed = 1; } - wrap_cbw (&cbw, buflen, dir, cb, cblen); + wrap_cbw (&cbw, buflen, dir, cb, cblen, MSC_INST (dev)->lun); if (dev->controller-> - bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0)) { + bulk (MSC_INST (dev)->bulk_out, sizeof (cbw), (u8 *) &cbw, 0) < 0) { return reset_transport (dev); } if (buflen > 0) { if (dir == cbw_direction_data_in) { if (dev->controller-> - bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) + bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0) < 0) clear_stall (MSC_INST (dev)->bulk_in); } else { if (dev->controller-> - bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) + bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0) < 0) clear_stall (MSC_INST (dev)->bulk_out); } } @@ -255,6 +273,11 @@ execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen, if (cb[0] == 0x03) /* requesting sense failed, that's bad */ return MSC_COMMAND_FAIL; + else if (cb[0] == 0) + /* If command was TEST UNIT READY determine if the + * device is of removable type indicating no media + * found. */ + return request_sense_no_media (dev); /* error "check condition" or reserved error */ ret = request_sense (dev); /* return fail or the status of request_sense if it's worse */ @@ -268,7 +291,7 @@ typedef struct { unsigned int block; //2-5 unsigned char res2; //6 unsigned short numblocks; //7-8 - unsigned char res3; //9 - the block is 10 bytes long + unsigned char control; //9 - the block is 10 bytes long } __attribute__ ((packed)) cmdblock_t; typedef struct { @@ -276,8 +299,14 @@ typedef struct { unsigned char res1; //1 unsigned char res2; //2 unsigned char res3; //3 - unsigned char lun; //4 - unsigned char res4; //5 + union { //4 + struct { + unsigned long start:1; // for START STOP UNIT + unsigned long:7; + }; + unsigned char length; // for REQUEST SENSE + }; + unsigned char control; //5 } __attribute__ ((packed)) cmdblock6_t; /** @@ -314,8 +343,8 @@ readwrite_blocks_512 (usbdev_t *dev, int start, int n, * @param buf buffer to read into or write from. Must be at least n*sectorsize bytes * @return 0 on success, 1 on failure */ -int -readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf) +static int +readwrite_chunk (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf) { cmdblock_t cb; memset (&cb, 0, sizeof (cb)); @@ -334,6 +363,49 @@ readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf) != MSC_COMMAND_OK ? 1 : 0; } +/** + * Reads or writes a number of sequential blocks on a USB storage device + * that is split into MAX_CHUNK_BYTES size requests. + * + * As it uses the READ(10) SCSI-2 command, it's limited to storage devices + * of at most 2TB. It assumes sectors of 512 bytes. + * + * @param dev device to access + * @param start first sector to access + * @param n number of sectors to access + * @param dir direction of access: cbw_direction_data_in == read, + * cbw_direction_data_out == write + * @param buf buffer to read into or write from. + * Must be at least n*sectorsize bytes + * @return 0 on success, 1 on failure + */ +int +readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf) +{ + int chunk_size = MAX_CHUNK_BYTES / MSC_INST(dev)->blocksize; + int chunk; + + /* Read as many full chunks as needed. */ + for (chunk = 0; chunk < (n / chunk_size); chunk++) { + if (readwrite_chunk (dev, start + (chunk * chunk_size), + chunk_size, dir, + buf + (chunk * MAX_CHUNK_BYTES)) + != MSC_COMMAND_OK) + return 1; + } + + /* Read any remaining partial chunk at the end. */ + if (n % chunk_size) { + if (readwrite_chunk (dev, start + (chunk * chunk_size), + n % chunk_size, dir, + buf + (chunk * MAX_CHUNK_BYTES)) + != MSC_COMMAND_OK) + return 1; + } + + return 0; +} + /* Only request it, we don't interpret it. On certain errors, that's necessary to get devices out of a special state called "Contingent Allegiance Condition" */ @@ -344,9 +416,40 @@ request_sense (usbdev_t *dev) cmdblock6_t cb; memset (&cb, 0, sizeof (cb)); cb.command = 0x3; + cb.length = sizeof (buf); return execute_command (dev, cbw_direction_data_in, (u8 *) &cb, - sizeof (cb), buf, 19, 1); + sizeof (cb), buf, sizeof (buf), 1); +} + +static int request_sense_no_media (usbdev_t *dev) +{ + u8 buf[19]; + int ret; + cmdblock6_t cb; + memset (&cb, 0, sizeof (cb)); + cb.command = 0x3; + cb.length = sizeof (buf); + + ret = execute_command (dev, cbw_direction_data_in, (u8 *) &cb, + sizeof (cb), buf, sizeof (buf), 1); + + if (ret) + return ret; + + /* Check if sense key is set to NOT READY. */ + if ((buf[2] & 0xf) != 2) + return MSC_COMMAND_FAIL; + + /* Check if additional sense code is 0x3a. */ + if (buf[12] != 0x3a) + return MSC_COMMAND_FAIL; + + /* No media is present. Return MSC_COMMAND_OK while marking the disk + * not ready. */ + usb_debug ("Empty media found.\n"); + MSC_INST (dev)->ready = USB_MSC_NOT_READY; + return MSC_COMMAND_OK; } static int @@ -364,7 +467,7 @@ spin_up (usbdev_t *dev) cmdblock6_t cb; memset (&cb, 0, sizeof (cb)); cb.command = 0x1b; - cb.lun = 1; + cb.start = 1; return execute_command (dev, cbw_direction_data_out, (u8 *) &cb, sizeof (cb), 0, 0, 0); } @@ -410,10 +513,80 @@ read_capacity (usbdev_t *dev) return MSC_COMMAND_OK; } +static int +usb_msc_test_unit_ready (usbdev_t *dev) +{ + int i; + time_t start_time_secs; + struct timeval tv; + /* SCSI/ATA specs say we have to wait up to 30s, but most devices + * are ready much sooner. Use a 5 sec timeout to better accomodate + * devices which fail to respond. */ + const int timeout_secs = 5; + + usb_debug (" Waiting for device to become ready..."); + + /* Initially mark the device ready. */ + MSC_INST (dev)->ready = USB_MSC_READY; + gettimeofday (&tv, NULL); + start_time_secs = tv.tv_sec; + + while (tv.tv_sec - start_time_secs < timeout_secs) { + switch (test_unit_ready (dev)) { + case MSC_COMMAND_OK: + break; + case MSC_COMMAND_FAIL: + mdelay (100); + usb_debug ("."); + gettimeofday (&tv, NULL); + continue; + default: + /* Device detached, return immediately */ + return USB_MSC_DETACHED; + } + break; + } + if (!(tv.tv_sec - start_time_secs < timeout_secs)) { + usb_debug ("timeout. Device not ready.\n"); + MSC_INST (dev)->ready = USB_MSC_NOT_READY; + } + + /* Don't bother spinning up the stroage device if the device is not + * ready. This can happen when empty card readers are present. + * Polling will pick it back up if readiness changes. */ + if (!MSC_INST (dev)->ready) + return MSC_INST (dev)->ready; + + usb_debug ("ok.\n"); + + usb_debug (" spin up"); + for (i = 0; i < 30; i++) { + usb_debug ("."); + switch (spin_up (dev)) { + case MSC_COMMAND_OK: + usb_debug (" OK."); + break; + case MSC_COMMAND_FAIL: + mdelay (100); + continue; + default: + /* Device detached, return immediately */ + return USB_MSC_DETACHED; + } + break; + } + usb_debug ("\n"); + + if (read_capacity (dev) == MSC_COMMAND_DETACHED) + return USB_MSC_DETACHED; + + return MSC_INST (dev)->ready; +} + void usb_msc_init (usbdev_t *dev) { - int i, timeout; + int i; /* init .data before setting .destroy */ dev->data = NULL; @@ -434,6 +607,7 @@ usb_msc_init (usbdev_t *dev) if (interface->bInterfaceProtocol != 0x50) { usb_debug (" Protocol not supported.\n"); + usb_detach_device (dev->controller, dev->address); return; } @@ -442,6 +616,7 @@ usb_msc_init (usbdev_t *dev) (interface->bInterfaceSubClass != 6)) { // SCSI /* Other protocols, such as ATAPI don't seem to be very popular. looks like ATAPI would be really easy to add, if necessary. */ usb_debug (" Interface SubClass not supported.\n"); + usb_detach_device (dev->controller, dev->address); return; } @@ -449,7 +624,6 @@ usb_msc_init (usbdev_t *dev) if (!dev->data) fatal("Not enough memory for USB MSC device.\n"); - MSC_INST (dev)->protocol = interface->bInterfaceSubClass; MSC_INST (dev)->bulk_in = 0; MSC_INST (dev)->bulk_out = 0; MSC_INST (dev)->usbdisk_created = 0; @@ -468,60 +642,49 @@ usb_msc_init (usbdev_t *dev) } if (MSC_INST (dev)->bulk_in == 0) { - usb_debug("couldn't find bulk-in endpoint"); + usb_debug("couldn't find bulk-in endpoint.\n"); + usb_detach_device (dev->controller, dev->address); return; } if (MSC_INST (dev)->bulk_out == 0) { - usb_debug("couldn't find bulk-out endpoint"); + usb_debug("couldn't find bulk-out endpoint.\n"); + usb_detach_device (dev->controller, dev->address); return; } usb_debug (" using endpoint %x as in, %x as out\n", MSC_INST (dev)->bulk_in->endpoint, MSC_INST (dev)->bulk_out->endpoint); - usb_debug (" has %d luns\n", get_max_luns (dev) + 1); + initialize_luns (dev); + usb_debug (" has %d luns\n", MSC_INST (dev)->num_luns); - usb_debug (" Waiting for device to become ready..."); - timeout = 30 * 10; /* SCSI/ATA specs say we have to wait up to 30s. Ugh */ - while (timeout--) { - switch (test_unit_ready (dev)) { - case MSC_COMMAND_OK: - break; - case MSC_COMMAND_FAIL: - mdelay (100); - if (!(timeout % 10)) - usb_debug ("."); - continue; - default: /* if it's worse return */ - return; - } - break; - } - if (timeout < 0) { - usb_debug ("timeout. Device not ready. Still trying...\n"); - } else { - usb_debug ("ok.\n"); - } + /* Test if unit is ready (nothing to do if it isn't). */ + if (usb_msc_test_unit_ready (dev) != USB_MSC_READY) + return; - usb_debug (" spin up"); - for (i = 0; i < 30; i++) { - usb_debug ("."); - switch (spin_up (dev)) { - case MSC_COMMAND_OK: - usb_debug (" OK."); - break; - case MSC_COMMAND_FAIL: - mdelay (100); - continue; - default: /* if it's worse return */ - return; - } - break; - } - usb_debug ("\n"); + /* Create the disk. */ + usb_msc_create_disk (dev); +} - if ((read_capacity (dev) == MSC_COMMAND_OK) && usbdisk_create) { - usbdisk_create (dev); - MSC_INST (dev)->usbdisk_created = 1; +static void +usb_msc_poll (usbdev_t *dev) +{ + usbmsc_inst_t *msc = MSC_INST (dev); + int prev_ready = msc->ready; + + if (usb_msc_test_unit_ready (dev) == USB_MSC_DETACHED) + return; + + if (!prev_ready && msc->ready) { + usb_debug ("usb msc: not ready -> ready (lun %d)\n", msc->lun); + usb_msc_create_disk (dev); + } else if (prev_ready && !msc->ready) { + usb_debug ("usb msc: ready -> not ready (lun %d)\n", msc->lun); + usb_msc_remove_disk (dev); + } else if (!prev_ready && !msc->ready) { + u8 new_lun = (msc->lun + 1) % msc->num_luns; + usb_debug("usb msc: not ready (lun %d) -> lun %d\n", msc->lun, + new_lun); + msc->lun = new_lun; } } diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c index 083b331548..cdd7aa81ad 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2010 Patrick Georgi + * Copyright (C) 2013 secunet Security Networks AG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,15 +28,17 @@ * SUCH DAMAGE. */ -#define USB_DEBUG +//#define XHCI_SPEW_DEBUG +#include #include -#include "xhci.h" #include "xhci_private.h" +#include "xhci.h" static void xhci_start (hci_t *controller); static void xhci_stop (hci_t *controller); static void xhci_reset (hci_t *controller); +static void xhci_reinit (hci_t *controller); static void xhci_shutdown (hci_t *controller); static int xhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize); static int xhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, @@ -44,226 +47,856 @@ static void* xhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, static void xhci_destroy_intr_queue (endpoint_t *ep, void *queue); static u8* xhci_poll_intr_queue (void *queue); -static void -xhci_reset (hci_t *controller) +/* + * Some structures must not cross page boundaries. To get this, + * we align them by their size (or the next greater power of 2). + */ +void * +xhci_align(const size_t min_align, const size_t size) { + size_t align; + if (!(size & (size - 1))) + align = size; /* It's a power of 2 */ + else + align = 1 << ((sizeof(unsigned) << 3) - __builtin_clz(size)); + if (align < min_align) + align = min_align; + xhci_spew("Aligning %zu to %zu\n", size, align); + return dma_memalign(align, size); } +void +xhci_clear_trb(trb_t *const trb, const int pcs) +{ + trb->ptr_low = 0; + trb->ptr_high = 0; + trb->status = 0; + trb->control = !pcs; +} + +void +xhci_init_cycle_ring(transfer_ring_t *const tr, const size_t ring_size) +{ + memset((void *)tr->ring, 0, ring_size * sizeof(*tr->ring)); + TRB_SET(TT, &tr->ring[ring_size - 1], TRB_LINK); + TRB_SET(TC, &tr->ring[ring_size - 1], 1); + /* only one segment that points to itself */ + tr->ring[ring_size - 1].ptr_low = virt_to_phys(tr->ring); + + tr->pcs = 1; + tr->cur = tr->ring; +} + +static long +xhci_handshake(volatile u32 *const reg, u32 mask, u32 wait_for, long timeout_us) +{ + while ((*reg & mask) != wait_for && timeout_us--) udelay(1); + return timeout_us; +} + +static int +xhci_wait_ready(xhci_t *const xhci) +{ + xhci_debug("Waiting for controller to be ready... "); + if (!xhci_handshake(&xhci->opreg->usbsts, USBSTS_CNR, 0, 100000L)) { + usb_debug("timeout!\n"); + return -1; + } + usb_debug("ok.\n"); + return 0; +} + +hci_t * +xhci_init (void *bar) +{ + int i; + + hci_t *const controller = new_controller(); + controller->type = XHCI; + controller->start = xhci_start; + controller->stop = xhci_stop; + controller->reset = xhci_reset; + controller->init = xhci_reinit; + controller->shutdown = xhci_shutdown; + controller->bulk = xhci_bulk; + controller->control = xhci_control; + controller->set_address = xhci_set_address; + controller->finish_device_config= xhci_finish_device_config; + controller->destroy_device = xhci_destroy_dev; + controller->create_intr_queue = xhci_create_intr_queue; + controller->destroy_intr_queue = xhci_destroy_intr_queue; + controller->poll_intr_queue = xhci_poll_intr_queue; + + controller->reg_base = (uintptr_t)bar; + controller->instance = xzalloc(sizeof(xhci_t)); + xhci_t *const xhci = (xhci_t *)controller->instance; + + init_device_entry(controller, 0); + xhci->roothub = controller->devices[0]; + xhci->cr.ring = xhci_align(64, COMMAND_RING_SIZE * sizeof(trb_t)); + xhci->er.ring = xhci_align(64, EVENT_RING_SIZE * sizeof(trb_t)); + xhci->ev_ring_table = xhci_align(64, sizeof(erst_entry_t)); + if (!xhci->roothub || !xhci->cr.ring || + !xhci->er.ring || !xhci->ev_ring_table) { + xhci_debug("Out of memory\n"); + goto _free_xhci; + } + + xhci->capreg = phys_to_virt(controller->reg_base); + xhci->opreg = ((void *)xhci->capreg) + xhci->capreg->caplength; + xhci->hcrreg = ((void *)xhci->capreg) + xhci->capreg->rtsoff; + xhci->dbreg = ((void *)xhci->capreg) + xhci->capreg->dboff; + xhci_debug("regbase: 0x%"PRIx32"\n", controller->reg_base); + xhci_debug("caplen: 0x%"PRIx32"\n", xhci->capreg->caplength); + xhci_debug("rtsoff: 0x%"PRIx32"\n", xhci->capreg->rtsoff); + xhci_debug("dboff: 0x%"PRIx32"\n", xhci->capreg->dboff); + + xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n", + xhci->capreg->hciver_hi, xhci->capreg->hciver_lo); + if ((xhci->capreg->hciversion < 0x96) || + (xhci->capreg->hciversion > 0x100)) { + xhci_debug("Unsupported xHCI version\n"); + goto _free_xhci; + } + + xhci_debug("context size: %dB\n", CTXSIZE(xhci)); + xhci_debug("maxslots: 0x%02lx\n", xhci->capreg->MaxSlots); + xhci_debug("maxports: 0x%02lx\n", xhci->capreg->MaxPorts); + const unsigned pagesize = xhci->opreg->pagesize << 12; + xhci_debug("pagesize: 0x%04x\n", pagesize); + + /* + * We haven't touched the hardware yet. So we allocate all dynamic + * structures at first and can still chicken out easily if we run out + * of memory. + */ + xhci->max_slots_en = xhci->capreg->MaxSlots & CONFIG_LP_MASK_MaxSlotsEn; + xhci->dcbaa = xhci_align(64, (xhci->max_slots_en + 1) * sizeof(u64)); + xhci->dev = malloc((xhci->max_slots_en + 1) * sizeof(*xhci->dev)); + if (!xhci->dcbaa || !xhci->dev) { + xhci_debug("Out of memory\n"); + goto _free_xhci; + } + memset(xhci->dcbaa, 0x00, (xhci->max_slots_en + 1) * sizeof(u64)); + memset(xhci->dev, 0x00, (xhci->max_slots_en + 1) * sizeof(*xhci->dev)); + + /* + * Let dcbaa[0] point to another array of pointers, sp_ptrs. + * The pointers therein point to scratchpad buffers (pages). + */ + const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs; + xhci_debug("max scratchpad bufs: 0x%zx\n", max_sp_bufs); + if (max_sp_bufs) { + const size_t sp_ptrs_size = max_sp_bufs * sizeof(u64); + xhci->sp_ptrs = xhci_align(64, sp_ptrs_size); + if (!xhci->sp_ptrs) { + xhci_debug("Out of memory\n"); + goto _free_xhci_structs; + } + memset(xhci->sp_ptrs, 0x00, sp_ptrs_size); + for (i = 0; i < max_sp_bufs; ++i) { + /* Could use mmap() here if we had it. + Maybe there is another way. */ + void *const page = memalign(pagesize, pagesize); + if (!page) { + xhci_debug("Out of memory\n"); + goto _free_xhci_structs; + } + xhci->sp_ptrs[i] = virt_to_phys(page); + } + xhci->dcbaa[0] = virt_to_phys(xhci->sp_ptrs); + } + + if (dma_initialized()) { + xhci->dma_buffer = dma_memalign(64 * 1024, DMA_SIZE); + if (!xhci->dma_buffer) { + xhci_debug("Not enough memory for DMA bounce buffer\n"); + goto _free_xhci_structs; + } + } + + /* Now start working on the hardware */ + + if (xhci_wait_ready(xhci)) + goto _free_xhci_structs; + + /* TODO: Check if BIOS claims ownership (and hand over) */ + + xhci_reset(controller); + xhci_reinit(controller); + + xhci->roothub->controller = controller; + xhci->roothub->init = xhci_rh_init; + xhci->roothub->init(xhci->roothub); + + return controller; + +_free_xhci_structs: + free(xhci->dma_buffer); + if (xhci->sp_ptrs) { + for (i = 0; i < max_sp_bufs; ++i) { + if (xhci->sp_ptrs[i]) + free(phys_to_virt(xhci->sp_ptrs[i])); + } + } + free(xhci->sp_ptrs); + free(xhci->dcbaa); +_free_xhci: + free((void *)xhci->ev_ring_table); + free((void *)xhci->er.ring); + free((void *)xhci->cr.ring); + free(xhci->roothub); + free(xhci->dev); + free(xhci); + detach_controller(controller); + free(controller); + return NULL; +} + +static void +xhci_reset(hci_t *const controller) +{ + xhci_t *const xhci = XHCI_INST(controller); + + xhci_stop(controller); + + xhci->opreg->usbcmd |= USBCMD_HCRST; + xhci_debug("Resetting controller... "); + if (!xhci_handshake(&xhci->opreg->usbcmd, USBCMD_HCRST, 0, 1000000L)) + usb_debug("timeout!\n"); + else + usb_debug("ok.\n"); +} + +#ifdef CONFIG_LP_USB_PCI +/* On Panther Point: switch ports shared with EHCI to xHCI */ +static void +xhci_switch_ppt_ports(pcidev_t addr) +{ + if (pci_read_config32(addr, 0x00) == 0x1e318086) { + u32 reg32 = pci_read_config32(addr, 0xdc) & 0xf; + xhci_debug("Ports capable of SuperSpeed: 0x%"PRIx32"\n", reg32); + + /* For now, do not enable SuperSpeed on any ports */ + //pci_write_config32(addr, 0xd8, reg32); + pci_write_config32(addr, 0xd8, 0x00000000); + reg32 = pci_read_config32(addr, 0xd8) & 0xf; + xhci_debug("Configured for SuperSpeed: 0x%"PRIx32"\n", reg32); + + reg32 = pci_read_config32(addr, 0xd4) & 0xf; + xhci_debug("Trying to switch over: 0x%"PRIx32"\n", reg32); + + pci_write_config32(addr, 0xd0, reg32); + reg32 = pci_read_config32(addr, 0xd0) & 0xf; + xhci_debug("Actually switched over: 0x%"PRIx32"\n", reg32); + } +} + +hci_t * +xhci_pci_init (pcidev_t addr) +{ + u32 reg_addr; + + reg_addr = pci_read_config32(addr, REG_BAR0) & ~0xf; + if (pci_read_config32(addr, REG_BAR1) > 0) { + xhci_debug("We don't do 64bit addressing.\n"); + return NULL; + } + + xhci_switch_ppt_ports(addr); + + return xhci_init((void *)reg_addr); +} +#endif + static void xhci_reinit (hci_t *controller) { -} + xhci_t *const xhci = XHCI_INST(controller); -hci_t * -xhci_init (pcidev_t addr) -{ + if (xhci_wait_ready(xhci)) + return; + + /* Enable all available slots */ + xhci->opreg->config = xhci->max_slots_en; + + /* Set DCBAA */ + xhci->opreg->dcbaap_lo = virt_to_phys(xhci->dcbaa); + xhci->opreg->dcbaap_hi = 0; + + /* Initialize command ring */ + xhci_init_cycle_ring(&xhci->cr, COMMAND_RING_SIZE); + xhci_debug("command ring @%p (0x%08x)\n", + xhci->cr.ring, virt_to_phys(xhci->cr.ring)); + xhci->opreg->crcr_lo = virt_to_phys(xhci->cr.ring) | CRCR_RCS; + xhci->opreg->crcr_hi = 0; + + /* Make sure interrupts are disabled */ + xhci->opreg->usbcmd &= ~USBCMD_INTE; + + /* Initialize event ring */ + xhci_reset_event_ring(&xhci->er); + xhci_debug("event ring @%p (0x%08x)\n", + xhci->er.ring, virt_to_phys(xhci->er.ring)); + xhci_debug("ERST Max: 0x%lx -> 0x%lx entries\n", + xhci->capreg->ERST_Max, 1 << xhci->capreg->ERST_Max); + memset((void*)xhci->ev_ring_table, 0x00, sizeof(erst_entry_t)); + xhci->ev_ring_table[0].seg_base_lo = virt_to_phys(xhci->er.ring); + xhci->ev_ring_table[0].seg_base_hi = 0; + xhci->ev_ring_table[0].seg_size = EVENT_RING_SIZE; + + /* Initialize primary interrupter */ + xhci->hcrreg->intrrs[0].erstsz = 1; + xhci_update_event_dq(xhci); + /* erstba has to be written at last */ + xhci->hcrreg->intrrs[0].erstba_lo = virt_to_phys(xhci->ev_ring_table); + xhci->hcrreg->intrrs[0].erstba_hi = 0; + + xhci_start(controller); + +#ifdef USB_DEBUG int i; + for (i = 0; i < 32; ++i) { + xhci_debug("NOOP run #%d\n", i); + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_NOOP); - hci_t *controller = new_controller (); + xhci_post_command(xhci); - if (!controller) - fatal("Could not create USB controller instance.\n"); - - controller->instance = malloc (sizeof (xhci_t)); - if(!controller->instance) - fatal("Not enough memory creating USB controller instance.\n"); - - controller->type = XHCI; - - controller->start = xhci_start; - controller->stop = xhci_stop; - controller->reset = xhci_reset; - controller->init = xhci_reinit; - controller->shutdown = xhci_shutdown; - controller->bulk = xhci_bulk; - controller->control = xhci_control; - controller->create_intr_queue = xhci_create_intr_queue; - controller->destroy_intr_queue = xhci_destroy_intr_queue; - controller->poll_intr_queue = xhci_poll_intr_queue; - for (i = 0; i < 128; i++) { - controller->devices[i] = 0; + /* Wait for result in event ring */ + xhci_wait_for_command_done(xhci, cmd, 1); + xhci_debug("Command ring is %srunning\n", + (xhci->opreg->crcr_lo & CRCR_CRR) ? "" : "not "); } - init_device_entry (controller, 0); - XHCI_INST (controller)->roothub = controller->devices[0]; - - controller->bus_address = addr; - controller->reg_base = (u32)phys_to_virt(pci_read_config32 (controller->bus_address, 0x10) & ~0xf); - //controller->reg_base = pci_read_config32 (controller->bus_address, 0x14) & ~0xf; - if (pci_read_config32 (controller->bus_address, 0x14) > 0) { - fatal("We don't do 64bit addressing.\n"); - } - usb_debug("regbase: %lx\n", controller->reg_base); - - XHCI_INST (controller)->capreg = (void*)controller->reg_base; - XHCI_INST (controller)->opreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->caplength); - XHCI_INST (controller)->hcrreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->rtsoff); - XHCI_INST (controller)->dbreg = (void*)(controller->reg_base + XHCI_INST (controller)->capreg->dboff); - usb_debug("caplen: %lx\nrtsoff: %lx\ndboff: %lx\n", XHCI_INST (controller)->capreg->caplength, XHCI_INST (controller)->capreg->rtsoff, XHCI_INST (controller)->capreg->dboff); - usb_debug("caplength: %x\n", XHCI_INST (controller)->capreg->caplength); - usb_debug("hciversion: %x.%x\n", XHCI_INST (controller)->capreg->hciver_hi, XHCI_INST (controller)->capreg->hciver_lo); - if ((XHCI_INST (controller)->capreg->hciversion < 0x96) || (XHCI_INST (controller)->capreg->hciversion > 0x100)) { - fatal("Unsupported xHCI version\n"); - } - usb_debug("maxslots: %x\n", XHCI_INST (controller)->capreg->MaxSlots); - usb_debug("maxports: %x\n", XHCI_INST (controller)->capreg->MaxPorts); - int pagesize = XHCI_INST (controller)->opreg->pagesize << 12; - usb_debug("pagesize: %x\n", pagesize); - - XHCI_INST (controller)->dcbaa = memalign(64, (XHCI_INST (controller)->capreg->MaxSlots+1)*sizeof(devctxp_t)); - memset((void*)XHCI_INST (controller)->dcbaa, 0, (XHCI_INST (controller)->capreg->MaxSlots+1)*sizeof(devctxp_t)); - - usb_debug("max scratchpad bufs: %x\n", XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs); - if (XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs > 0) { - XHCI_INST (controller)->dcbaa->ptr = memalign(64, XHCI_INST (controller)->capreg->Max_Scratchpad_Bufs * 8); - } - - XHCI_INST (controller)->opreg->dcbaap_lo = virt_to_phys(XHCI_INST (controller)->dcbaa); - XHCI_INST (controller)->opreg->dcbaap_hi = 0; - - usb_debug("waiting for controller to be ready - "); - while ((XHCI_INST (controller)->opreg->usbsts & USBSTS_CNR) != 0) mdelay(1); - usb_debug("ok.\n"); - - usb_debug("ERST Max: %lx -> %lx entries\n", XHCI_INST (controller)->capreg->ERST_Max, 1<<(XHCI_INST (controller)->capreg->ERST_Max)); - - // enable all available slots - XHCI_INST (controller)->opreg->config = XHCI_INST (controller)->capreg->MaxSlots & CONFIG_MASK_MaxSlotsEn; - - XHCI_INST (controller)->cmd_ring = memalign(64, 16*sizeof(trb_t)); /* TODO: make sure not to cross 64k page boundary */ - memset((void*)XHCI_INST (controller)->cmd_ring, 0, 16*sizeof(trb_t)); - - XHCI_INST (controller)->ev_ring = memalign(64, 16*sizeof(trb_t)); /* TODO: make sure not to cross 64k page boundary */ - memset((void*)XHCI_INST (controller)->ev_ring, 0, 16*sizeof(trb_t)); - - XHCI_INST (controller)->ev_ring_table = memalign(64, sizeof(erst_entry_t)); - memset((void*)XHCI_INST (controller)->ev_ring_table, 0, sizeof(erst_entry_t)); - XHCI_INST (controller)->ev_ring_table[0].seg_base_lo = virt_to_phys(XHCI_INST (controller)->ev_ring); - XHCI_INST (controller)->ev_ring_table[0].seg_base_hi = 0; - XHCI_INST (controller)->ev_ring_table[0].seg_size = 16; - - // init command ring - XHCI_INST (controller)->opreg->crcr_lo = virt_to_phys(XHCI_INST (controller)->cmd_ring) | CRCR_RCS; - XHCI_INST (controller)->opreg->crcr_hi = 0; - XHCI_INST (controller)->cmd_ccs = 1; - XHCI_INST (controller)->ev_ccs = 1; - - // init primary interrupter - XHCI_INST (controller)->hcrreg->intrrs[0].erstsz = 1; - XHCI_INST (controller)->hcrreg->intrrs[0].erdp_lo = virt_to_phys(XHCI_INST (controller)->ev_ring); - XHCI_INST (controller)->hcrreg->intrrs[0].erdp_hi = 0; - XHCI_INST (controller)->hcrreg->intrrs[0].erstba_lo = virt_to_phys(XHCI_INST (controller)->ev_ring_table); - XHCI_INST (controller)->hcrreg->intrrs[0].erstba_hi = 0; - - XHCI_INST (controller)->opreg->usbcmd |= USBCMD_RS; /* start USB controller */ - XHCI_INST (controller)->dbreg[0] = 0; // and tell controller to consume commands - - /* TODO: TEST */ - // setup noop command - trb_t *cmd = &XHCI_INST (controller)->cmd_ring[0]; - ((u32*)cmd)[3] = 1-XHCI_INST (controller)->cmd_ccs; // disable command descriptor - ((u32*)cmd)[0] = 0; - ((u32*)cmd)[1] = 0; - ((u32*)cmd)[2] = 0; - cmd->cmd_No_Op.TRB_Type = TRB_CMD_NOOP; - - // ring the HC doorbell - usb_debug("Posting command at %lx\n", virt_to_phys(cmd)); - cmd->cmd_No_Op.C = XHCI_INST (controller)->cmd_ccs; // enable command - XHCI_INST (controller)->dbreg[0] = 0; // and tell controller to consume commands - - // wait for result in event ring - trb_t *ev = &XHCI_INST (controller)->ev_ring[0]; - trb_t *ev1 = &XHCI_INST (controller)->ev_ring[1]; - while (ev->event_cmd_cmpl.C != XHCI_INST (controller)->ev_ccs) { - usb_debug("CRCR: %lx, USBSTS: %lx\n", XHCI_INST (controller)->opreg->crcr_lo, XHCI_INST (controller)->opreg->usbsts); - usb_debug("ev0.C %x, ev1.C %x\n", ev->event_cmd_cmpl.C, ev1->event_cmd_cmpl.C); - mdelay(100); - } - usb_debug("command ring is %srunning\n", (XHCI_INST (controller)->opreg->crcr_lo & CRCR_CRR)?"":"not "); - switch (ev->event_cmd_cmpl.TRB_Type) { - case TRB_EV_CMD_CMPL: - usb_debug("Completed command TRB at %lx. Code: %d\n", - ev->event_cmd_cmpl.Cmd_TRB_Pointer_lo, ev->event_cmd_cmpl.Completion_Code); - break; - case TRB_EV_PORTSC: - usb_debug("Port Status Change Event. Completion Code: %d\n Port: %d. Ignoring.\n", - ev->event_cmd_cmpl.Completion_Code, ev->event_portsc.Port); - // we ignore the event as we look for the PORTSC registers instead, at a time when it suits _us_ - break; - default: - usb_debug("Unknown event: %d, Completion Code: %d\n", ev->event_cmd_cmpl.TRB_Type, ev->event_cmd_cmpl.Completion_Code); - break; - } - usb_debug("CRCR: %lx, USBSTS: %lx\n", XHCI_INST (controller)->opreg->crcr_lo, XHCI_INST (controller)->opreg->usbsts); - usb_debug("ev0.C %x, ev1.C %x, ev1.CC %d\n", ev->event_cmd_cmpl.C, ev1->event_cmd_cmpl.C, ev1->event_cmd_cmpl.Completion_Code); - - controller->devices[0]->controller = controller; - controller->devices[0]->init = xhci_rh_init; - controller->devices[0]->init (controller->devices[0]); - - return controller; +#endif } static void -xhci_shutdown (hci_t *controller) +xhci_shutdown(hci_t *const controller) { + int i; + if (controller == 0) return; - detach_controller (controller); - XHCI_INST (controller)->roothub->destroy (XHCI_INST (controller)-> - roothub); - /* TODO: stop hardware, kill data structures */ - free (XHCI_INST (controller)); - free (controller); + + detach_controller(controller); + + xhci_t *const xhci = XHCI_INST(controller); + xhci_stop(controller); + + if (xhci->sp_ptrs) { + const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs; + for (i = 0; i < max_sp_bufs; ++i) { + if (xhci->sp_ptrs[i]) + free(phys_to_virt(xhci->sp_ptrs[i])); + } + } + free(xhci->sp_ptrs); + free(xhci->dma_buffer); + free(xhci->dcbaa); + free(xhci->dev); + free((void *)xhci->ev_ring_table); + free((void *)xhci->er.ring); + free((void *)xhci->cr.ring); + free(xhci); + free(controller); } static void xhci_start (hci_t *controller) { + xhci_t *const xhci = XHCI_INST(controller); + + xhci->opreg->usbcmd |= USBCMD_RS; + if (!xhci_handshake(&xhci->opreg->usbsts, USBSTS_HCH, 0, 1000000L)) + xhci_debug("Controller didn't start within 1s\n"); } static void xhci_stop (hci_t *controller) { + xhci_t *const xhci = XHCI_INST(controller); + + xhci->opreg->usbcmd &= ~USBCMD_RS; + if (!xhci_handshake(&xhci->opreg->usbsts, + USBSTS_HCH, USBSTS_HCH, 1000000L)) + xhci_debug("Controller didn't halt within 1s\n"); } static int -xhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, - unsigned char *data) +xhci_reset_endpoint(usbdev_t *const dev, endpoint_t *const ep) { - return 1; + xhci_t *const xhci = XHCI_INST(dev->controller); + const int slot_id = dev->address; + const int ep_id = ep ? xhci_ep_id(ep) : 1; + epctx_t *const epctx = xhci->dev[slot_id].ctx.ep[ep_id]; + + xhci_debug("Resetting ID %d EP %d (ep state: %d)\n", + slot_id, ep_id, EC_GET(STATE, epctx)); + + /* Run Reset Endpoint Command if the EP is in Halted state */ + if (EC_GET(STATE, epctx) == 2) { + const int cc = xhci_cmd_reset_endpoint(xhci, slot_id, ep_id); + if (cc != CC_SUCCESS) { + xhci_debug("Reset Endpoint Command failed: %d\n", cc); + return 1; + } + } + + /* Clear TT buffer for bulk and control endpoints behind a TT */ + const int hub = dev->hub; + if (hub && dev->speed < HIGH_SPEED && + dev->controller->devices[hub]->speed == HIGH_SPEED) + /* TODO */; + + /* Reset transfer ring if the endpoint is in the right state */ + const unsigned ep_state = EC_GET(STATE, epctx); + if (ep_state == 3 || ep_state == 4) { + transfer_ring_t *const tr = + xhci->dev[slot_id].transfer_rings[ep_id]; + const int cc = xhci_cmd_set_tr_dq(xhci, slot_id, ep_id, + tr->ring, 1); + if (cc != CC_SUCCESS) { + xhci_debug("Set TR Dequeue Command failed: %d\n", cc); + return 1; + } + xhci_init_cycle_ring(tr, TRANSFER_RING_SIZE); + } + + xhci_debug("Finished resetting ID %d EP %d (ep state: %d)\n", + slot_id, ep_id, EC_GET(STATE, epctx)); + + return 0; +} + +static void +xhci_enqueue_trb(transfer_ring_t *const tr) +{ + const int chain = TRB_GET(CH, tr->cur); + TRB_SET(C, tr->cur, tr->pcs); + ++tr->cur; + + while (TRB_GET(TT, tr->cur) == TRB_LINK) { + xhci_spew("Handling LINK pointer\n"); + const int tc = TRB_GET(TC, tr->cur); + TRB_SET(CH, tr->cur, chain); + TRB_SET(C, tr->cur, tr->pcs); + tr->cur = phys_to_virt(tr->cur->ptr_low); + if (tc) + tr->pcs ^= 1; + } +} + +static void +xhci_enqueue_td(transfer_ring_t *const tr, const int ep, const size_t mps, + const int dalen, void *const data, const int dir) +{ + trb_t *trb = NULL; /* cur TRB */ + u8 *cur_start = data; /* cur data pointer */ + size_t length = dalen; /* remaining bytes */ + size_t packets = (length + mps - 1) / mps; /* remaining packets */ + size_t residue = 0; /* residue from last TRB */ + size_t trb_count = 0; /* TRBs added so far */ + + while (length || !trb_count /* enqueue at least one */) { + const size_t cur_end = ((size_t)cur_start + 0x10000) & ~0xffff; + size_t cur_length = cur_end - (size_t)cur_start; + if (length < cur_length) { + cur_length = length; + packets = 0; + length = 0; + } else { + packets -= (residue + cur_length) / mps; + residue = (residue + cur_length) % mps; + length -= cur_length; + } + + trb = tr->cur; + xhci_clear_trb(trb, tr->pcs); + trb->ptr_low = virt_to_phys(cur_start); + TRB_SET(TL, trb, cur_length); + TRB_SET(TDS, trb,((packets > TRB_MAX_TD_SIZE) ? TRB_MAX_TD_SIZE : packets)); + TRB_SET(CH, trb, 1); + + /* Check for first, data stage TRB */ + if (!trb_count && ep == 1) { + TRB_SET(DIR, trb, dir); + TRB_SET(TT, trb, TRB_DATA_STAGE); + } else { + TRB_SET(TT, trb, TRB_NORMAL); + } + /* + * This is a workaround for Synopsys DWC3. If the ENT flag is + * not set for the Normal and Data Stage TRBs. We get Event TRB + * with length 0x20d from the controller when We enqueue a TRB + * for the IN endpoint with length 0x200. + */ + if (!length) + TRB_SET(ENT, trb, 1); + + xhci_enqueue_trb(tr); + + cur_start += cur_length; + ++trb_count; + } + + trb = tr->cur; + xhci_clear_trb(trb, tr->pcs); + trb->ptr_low = virt_to_phys(trb); /* for easier debugging only */ + TRB_SET(TT, trb, TRB_EVENT_DATA); + TRB_SET(IOC, trb, 1); + + xhci_enqueue_trb(tr); +} + +static int +xhci_control(usbdev_t *const dev, const direction_t dir, + const int drlen, void *const devreq, + const int dalen, unsigned char *const src) +{ + unsigned char *data = src; + xhci_t *const xhci = XHCI_INST(dev->controller); + epctx_t *const epctx = xhci->dev[dev->address].ctx.ep0; + transfer_ring_t *const tr = xhci->dev[dev->address].transfer_rings[1]; + + const size_t off = (size_t)data & 0xffff; + if ((off + dalen) > ((TRANSFER_RING_SIZE - 4) << 16)) { + xhci_debug("Unsupported transfer size\n"); + return -1; + } + + /* Reset endpoint if it's not running */ + const unsigned ep_state = EC_GET(STATE, epctx); + if (ep_state > 1) { + if (xhci_reset_endpoint(dev, NULL)) + return -1; + } + + if (dalen && !dma_coherent(src)) { + data = xhci->dma_buffer; + if (dalen > DMA_SIZE) { + xhci_debug("Control transfer too large: %d\n", dalen); + return -1; + } + if (dir == OUT) + memcpy(data, src, dalen); + } + + /* Fill and enqueue setup TRB */ + trb_t *const setup = tr->cur; + xhci_clear_trb(setup, tr->pcs); + setup->ptr_low = ((u32 *)devreq)[0]; + setup->ptr_high = ((u32 *)devreq)[1]; + TRB_SET(TL, setup, 8); + TRB_SET(TRT, setup, (dalen) + ? ((dir == OUT) ? TRB_TRT_OUT_DATA : TRB_TRT_IN_DATA) + : TRB_TRT_NO_DATA); + TRB_SET(TT, setup, TRB_SETUP_STAGE); + TRB_SET(IDT, setup, 1); + TRB_SET(IOC, setup, 1); + xhci_enqueue_trb(tr); + + /* Fill and enqueue data TRBs (if any) */ + if (dalen) { + const unsigned mps = EC_GET(MPS, epctx); + const unsigned dt_dir = (dir == OUT) ? TRB_DIR_OUT : TRB_DIR_IN; + xhci_enqueue_td(tr, 1, mps, dalen, data, dt_dir); + } + + /* Fill status TRB */ + trb_t *const status = tr->cur; + xhci_clear_trb(status, tr->pcs); + TRB_SET(DIR, status, (dir == OUT) ? TRB_DIR_IN : TRB_DIR_OUT); + TRB_SET(TT, status, TRB_STATUS_STAGE); + TRB_SET(IOC, status, 1); + xhci_enqueue_trb(tr); + + /* Ring doorbell for EP0 */ + xhci->dbreg[dev->address] = 1; + + /* Wait for transfer events */ + int i, transferred = 0; + const int n_stages = 2 + !!dalen; + for (i = 0; i < n_stages; ++i) { + const int ret = xhci_wait_for_transfer(xhci, dev->address, 1); + transferred += ret; + if (ret < 0) { + if (ret == TIMEOUT) { + xhci_debug("Stopping ID %d EP 1\n", + dev->address); + xhci_cmd_stop_endpoint(xhci, dev->address, 1); + } + xhci_debug("Stage %d/%d failed: %d\n" + " trb ring: @%p\n" + " setup trb: @%p\n" + " status trb: @%p\n" + " ep state: %d -> %d\n" + " usbsts: 0x%08"PRIx32"\n", + i, n_stages, ret, + tr->ring, setup, status, + ep_state, EC_GET(STATE, epctx), + xhci->opreg->usbsts); + return ret; + } + } + + if (dir == IN && data != src) + memcpy(src, data, transferred); + return transferred; } /* finalize == 1: if data is of packet aligned size, add a zero length packet */ static int -xhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) +xhci_bulk(endpoint_t *const ep, const int size, u8 *const src, + const int finalize) { - int maxpsize = ep->maxpacketsize; - if (maxpsize == 0) - fatal("MaxPacketSize == 0!!!"); - return 1; + /* finalize: Hopefully the xHCI controller always does this. + We have no control over the packets. */ + + u8 *data = src; + xhci_t *const xhci = XHCI_INST(ep->dev->controller); + const int slot_id = ep->dev->address; + const int ep_id = xhci_ep_id(ep); + epctx_t *const epctx = xhci->dev[slot_id].ctx.ep[ep_id]; + transfer_ring_t *const tr = xhci->dev[slot_id].transfer_rings[ep_id]; + + const size_t off = (size_t)data & 0xffff; + if ((off + size) > ((TRANSFER_RING_SIZE - 2) << 16)) { + xhci_debug("Unsupported transfer size\n"); + return -1; + } + + if (!dma_coherent(src)) { + data = xhci->dma_buffer; + if (size > DMA_SIZE) { + xhci_debug("Bulk transfer too large: %d\n", size); + return -1; + } + if (ep->direction == OUT) + memcpy(data, src, size); + } + + /* Reset endpoint if it's not running */ + const unsigned ep_state = EC_GET(STATE, epctx); + if (ep_state > 1) { + if (xhci_reset_endpoint(ep->dev, ep)) + return -1; + } + + /* Enqueue transfer and ring doorbell */ + const unsigned mps = EC_GET(MPS, epctx); + const unsigned dir = (ep->direction == OUT) ? TRB_DIR_OUT : TRB_DIR_IN; + xhci_enqueue_td(tr, ep_id, mps, size, data, dir); + xhci->dbreg[ep->dev->address] = ep_id; + + /* Wait for transfer event */ + const int ret = xhci_wait_for_transfer(xhci, ep->dev->address, ep_id); + if (ret < 0) { + if (ret == TIMEOUT) { + xhci_debug("Stopping ID %d EP %d\n", + ep->dev->address, ep_id); + xhci_cmd_stop_endpoint(xhci, ep->dev->address, ep_id); + } + xhci_debug("Bulk transfer failed: %d\n" + " ep state: %d -> %d\n" + " usbsts: 0x%08"PRIx32"\n", + ret, ep_state, + EC_GET(STATE, epctx), + xhci->opreg->usbsts); + return ret; + } + + if (ep->direction == IN && data != src) + memcpy(src, data, ret); + return ret; +} + +static trb_t * +xhci_next_trb(trb_t *cur, int *const pcs) +{ + ++cur; + while (TRB_GET(TT, cur) == TRB_LINK) { + if (pcs && TRB_GET(TC, cur)) + *pcs ^= 1; + cur = phys_to_virt(cur->ptr_low); + } + return cur; } /* create and hook-up an intr queue into device schedule */ -static void* -xhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming) +static void * +xhci_create_intr_queue(endpoint_t *const ep, + const int reqsize, const int reqcount, + const int reqtiming) { + /* reqtiming: We ignore it and use the interval from the + endpoint descriptor configured earlier. */ + + xhci_t *const xhci = XHCI_INST(ep->dev->controller); + const int slot_id = ep->dev->address; + const int ep_id = xhci_ep_id(ep); + transfer_ring_t *const tr = xhci->dev[slot_id].transfer_rings[ep_id]; + + if (reqcount > (TRANSFER_RING_SIZE - 2)) { + xhci_debug("reqcount is too high, at most %d supported\n", + TRANSFER_RING_SIZE - 2); + return NULL; + } + if (reqsize > 0x10000) { + xhci_debug("reqsize is too large, at most 64KiB supported\n"); + return NULL; + } + if (xhci->dev[slot_id].interrupt_queues[ep_id]) { + xhci_debug("Only one interrupt queue per endpoint supported\n"); + return NULL; + } + + /* Allocate intrq structure and reqdata chunks */ + + intrq_t *const intrq = malloc(sizeof(*intrq)); + if (!intrq) { + xhci_debug("Out of memory\n"); + return NULL; + } + + int i; + int pcs = tr->pcs; + trb_t *cur = tr->cur; + for (i = 0; i < reqcount; ++i) { + if (TRB_GET(C, cur) == pcs) { + xhci_debug("Not enough empty TRBs\n"); + goto _free_return; + } + void *const reqdata = xhci_align(1, reqsize); + if (!reqdata) { + xhci_debug("Out of memory\n"); + goto _free_return; + } + xhci_clear_trb(cur, pcs); + cur->ptr_low = virt_to_phys(reqdata); + cur->ptr_high = 0; + TRB_SET(TL, cur, reqsize); + TRB_SET(TT, cur, TRB_NORMAL); + TRB_SET(ISP, cur, 1); + TRB_SET(IOC, cur, 1); + + cur = xhci_next_trb(cur, &pcs); + } + + intrq->size = reqsize; + intrq->count = reqcount; + intrq->next = tr->cur; + intrq->ready = NULL; + intrq->ep = ep; + xhci->dev[slot_id].interrupt_queues[ep_id] = intrq; + + /* Now enqueue all the prepared TRBs but the last + and ring the doorbell. */ + for (i = 0; i < (reqcount - 1); ++i) + xhci_enqueue_trb(tr); + xhci->dbreg[slot_id] = ep_id; + + return intrq; + +_free_return: + cur = tr->cur; + for (--i; i >= 0; --i) { + free(phys_to_virt(cur->ptr_low)); + cur = xhci_next_trb(cur, NULL); + } + free(intrq); return NULL; } /* remove queue from device schedule, dropping all data that came in */ static void -xhci_destroy_intr_queue (endpoint_t *ep, void *q_) +xhci_destroy_intr_queue(endpoint_t *const ep, void *const q) { - //free(q); + xhci_t *const xhci = XHCI_INST(ep->dev->controller); + const int slot_id = ep->dev->address; + const int ep_id = xhci_ep_id(ep); + transfer_ring_t *const tr = xhci->dev[slot_id].transfer_rings[ep_id]; + + intrq_t *const intrq = (intrq_t *)q; + + /* Make sure the endpoint is stopped */ + if (EC_GET(STATE, xhci->dev[slot_id].ctx.ep[ep_id]) == 1) { + const int cc = xhci_cmd_stop_endpoint(xhci, slot_id, ep_id); + if (cc != CC_SUCCESS) + xhci_debug("Warning: Failed to stop endpoint\n"); + } + + /* Process all remaining transfer events */ + xhci_handle_events(xhci); + + /* Free all pending transfers and the interrupt queue structure */ + int i; + for (i = 0; i < intrq->count; ++i) { + free(phys_to_virt(intrq->next->ptr_low)); + intrq->next = xhci_next_trb(intrq->next, NULL); + } + xhci->dev[slot_id].interrupt_queues[ep_id] = NULL; + free((void *)intrq); + + /* Reset the controller's dequeue pointer and reinitialize the ring */ + xhci_cmd_set_tr_dq(xhci, slot_id, ep_id, tr->ring, 1); + xhci_init_cycle_ring(tr, TRANSFER_RING_SIZE); } /* read one intr-packet from queue, if available. extend the queue for new input. return NULL if nothing new available. Recommended use: while (data=poll_intr_queue(q)) process(data); */ -static u8* -xhci_poll_intr_queue (void *q_) +static u8 * +xhci_poll_intr_queue(void *const q) { - return NULL; + if (!q) + return NULL; + + intrq_t *const intrq = (intrq_t *)q; + endpoint_t *const ep = intrq->ep; + xhci_t *const xhci = XHCI_INST(ep->dev->controller); + + /* TODO: Reset interrupt queue if it gets halted? */ + + xhci_handle_events(xhci); + + u8 *reqdata = NULL; + while (!reqdata && intrq->ready) { + const int ep_id = xhci_ep_id(ep); + transfer_ring_t *const tr = + xhci->dev[ep->dev->address].transfer_rings[ep_id]; + + /* Fetch the request's buffer */ + reqdata = phys_to_virt(intrq->next->ptr_low); + + /* Enqueue the last (spare) TRB and ring doorbell */ + xhci_enqueue_trb(tr); + xhci->dbreg[ep->dev->address] = ep_id; + + /* Reuse the current buffer for the next spare TRB */ + xhci_clear_trb(tr->cur, tr->pcs); + tr->cur->ptr_low = virt_to_phys(reqdata); + tr->cur->ptr_high = 0; + TRB_SET(TL, tr->cur, intrq->size); + TRB_SET(TT, tr->cur, TRB_NORMAL); + TRB_SET(ISP, tr->cur, 1); + TRB_SET(IOC, tr->cur, 1); + + /* Check if anything was transferred */ + const size_t read = TRB_GET(TL, intrq->next); + if (!read) + reqdata = NULL; + else if (read < intrq->size) + /* At least zero it, poll interface is rather limited */ + memset(reqdata + read, 0x00, intrq->size - read); + + /* Advance the interrupt queue */ + if (intrq->ready == intrq->next) + /* This was last TRB being ready */ + intrq->ready = NULL; + intrq->next = xhci_next_trb(intrq->next, NULL); + } + + return reqdata; } diff --git a/payloads/libpayload/drivers/usb/xhci.h b/payloads/libpayload/drivers/usb/xhci.h index b900b12200..b76c9829b3 100644 --- a/payloads/libpayload/drivers/usb/xhci.h +++ b/payloads/libpayload/drivers/usb/xhci.h @@ -33,8 +33,9 @@ #include #include - hci_t *xhci_init (pcidev_t addr); +hci_t *xhci_pci_init (pcidev_t addr); +hci_t *xhci_init (void *bar); - void xhci_rh_init (usbdev_t *dev); +void xhci_rh_init (usbdev_t *dev); #endif diff --git a/payloads/libpayload/drivers/usb/xhci_commands.c b/payloads/libpayload/drivers/usb/xhci_commands.c new file mode 100644 index 0000000000..009a69c812 --- /dev/null +++ b/payloads/libpayload/drivers/usb/xhci_commands.c @@ -0,0 +1,204 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "xhci_private.h" + +trb_t * +xhci_next_command_trb(xhci_t *const xhci) +{ + xhci_clear_trb(xhci->cr.cur, xhci->cr.pcs); + return xhci->cr.cur; +} + +void +xhci_post_command(xhci_t *const xhci) +{ + xhci_debug("Command %d (@%p)\n", + TRB_GET(TT, xhci->cr.cur), xhci->cr.cur); + + TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); + ++xhci->cr.cur; + + /* Ring the doorbell */ + xhci->dbreg[0] = 0; + + while (TRB_GET(TT, xhci->cr.cur) == TRB_LINK) { + xhci_debug("Handling LINK pointer (@%p)\n", xhci->cr.cur); + const int tc = TRB_GET(TC, xhci->cr.cur); + TRB_SET(C, xhci->cr.cur, xhci->cr.pcs); + xhci->cr.cur = phys_to_virt(xhci->cr.cur->ptr_low); + if (tc) + xhci->cr.pcs ^= 1; + } +} + +static int +xhci_wait_for_command(xhci_t *const xhci, + const trb_t *const cmd_trb, + const int clear_event) +{ + int cc; + + cc = xhci_wait_for_command_done(xhci, cmd_trb, clear_event); + if (cc != TIMEOUT) + return cc; + + /* Abort command on timeout */ + xhci_debug("Aborting command (@%p), CRCR: 0x%"PRIx32"\n", + cmd_trb, xhci->opreg->crcr_lo); + xhci->opreg->crcr_lo |= CRCR_CS | CRCR_CA; + xhci->opreg->crcr_hi = 0; + cc = xhci_wait_for_command_aborted(xhci, cmd_trb); + + if (xhci->opreg->crcr_lo & CRCR_CRR) + fatal("xhci_wait_for_command: Command ring still running\n"); + + return cc; +} + +/* + * xhci_cmd_* return >= 0: xhci completion code (cc) + * < 0: driver error code + */ + +int +xhci_cmd_enable_slot(xhci_t *const xhci, int *const slot_id) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_ENABLE_SLOT); + xhci_post_command(xhci); + + int cc = xhci_wait_for_command(xhci, cmd, 0); + if (cc >= 0) { + if (cc == CC_SUCCESS) { + *slot_id = TRB_GET(ID, xhci->er.cur); + if (*slot_id > xhci->max_slots_en) + cc = CONTROLLER_ERROR; + } + xhci_advance_event_ring(xhci); + xhci_handle_events(xhci); + } + return cc; +} + +int +xhci_cmd_disable_slot(xhci_t *const xhci, const int slot_id) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_DISABLE_SLOT); + TRB_SET(ID, cmd, slot_id); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_address_device(xhci_t *const xhci, + const int slot_id, + inputctx_t *const ic) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_ADDRESS_DEV); + TRB_SET(ID, cmd, slot_id); + cmd->ptr_low = virt_to_phys(ic->raw); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_configure_endpoint(xhci_t *const xhci, + const int slot_id, + const int config_id, + inputctx_t *const ic) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_CONFIGURE_EP); + TRB_SET(ID, cmd, slot_id); + cmd->ptr_low = virt_to_phys(ic->raw); + if (config_id == 0) + TRB_SET(DC, cmd, 1); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_evaluate_context(xhci_t *const xhci, + const int slot_id, + inputctx_t *const ic) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_EVAL_CTX); + TRB_SET(ID, cmd, slot_id); + cmd->ptr_low = virt_to_phys(ic->raw); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_reset_endpoint(xhci_t *const xhci, const int slot_id, const int ep) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_RESET_EP); + TRB_SET(ID, cmd, slot_id); + TRB_SET(EP, cmd, ep); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_stop_endpoint(xhci_t *const xhci, const int slot_id, const int ep) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_STOP_EP); + TRB_SET(ID, cmd, slot_id); + TRB_SET(EP, cmd, ep); + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} + +int +xhci_cmd_set_tr_dq(xhci_t *const xhci, const int slot_id, const int ep, + trb_t *const dq_trb, const int dcs) +{ + trb_t *const cmd = xhci_next_command_trb(xhci); + TRB_SET(TT, cmd, TRB_CMD_SET_TR_DQ); + TRB_SET(ID, cmd, slot_id); + TRB_SET(EP, cmd, ep); + cmd->ptr_low = virt_to_phys(dq_trb) | dcs; + xhci_post_command(xhci); + + return xhci_wait_for_command(xhci, cmd, 1); +} diff --git a/payloads/libpayload/drivers/usb/xhci_debug.c b/payloads/libpayload/drivers/usb/xhci_debug.c new file mode 100644 index 0000000000..913b545bd9 --- /dev/null +++ b/payloads/libpayload/drivers/usb/xhci_debug.c @@ -0,0 +1,136 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "xhci_private.h" + +#ifdef XHCI_DUMPS + +void +xhci_dump_slotctx(const slotctx_t *const sc) +{ + xhci_debug("Slot Context (@%p):\n", sc); + usb_debug(" FIELD1\t0x%08"PRIx32"\n", sc->f1); + usb_debug(" FIELD2\t0x%08"PRIx32"\n", sc->f2); + usb_debug(" FIELD3\t0x%08"PRIx32"\n", sc->f3); + usb_debug(" FIELD4\t0x%08"PRIx32"\n", sc->f4); + SC_DUMP(ROUTE, sc); + SC_DUMP(SPEED, sc); + SC_DUMP(MTT, sc); + SC_DUMP(HUB, sc); + SC_DUMP(CTXENT, sc); + SC_DUMP(RHPORT, sc); + SC_DUMP(NPORTS, sc); + SC_DUMP(TTID, sc); + SC_DUMP(TTPORT, sc); + SC_DUMP(TTT, sc); + SC_DUMP(UADDR, sc); + SC_DUMP(STATE, sc); +} + +void +xhci_dump_epctx(const epctx_t *const ec) +{ + xhci_debug("Endpoint Context (@%p):\n", ec); + usb_debug(" FIELD1\t0x%08"PRIx32"\n", ec->f1); + usb_debug(" FIELD2\t0x%08"PRIx32"\n", ec->f2); + usb_debug(" TRDQ_L\t0x%08"PRIx32"\n", ec->tr_dq_low); + usb_debug(" TRDQ_H\t0x%08"PRIx32"\n", ec->tr_dq_high); + usb_debug(" FIELD5\t0x%08"PRIx32"\n", ec->f5); + EC_DUMP(STATE, ec); + EC_DUMP(INTVAL, ec); + EC_DUMP(CERR, ec); + EC_DUMP(TYPE, ec); + EC_DUMP(MBS, ec); + EC_DUMP(MPS, ec); + EC_DUMP(DCS, ec); + EC_DUMP(AVRTRB, ec); + EC_DUMP(MXESIT, ec); +} + +void +xhci_dump_devctx(const devctx_t *const dc, const u32 ctx_mask) +{ + int i; + if (ctx_mask & 1) + xhci_dump_slotctx(dc->slot); + for (i = 0; i < SC_GET(CTXENT, dc->slot); ++i) { + if (ctx_mask & (2 << i)) + xhci_dump_epctx(dc->ep[i]); + } +} + +void +xhci_dump_inputctx(const inputctx_t *const ic) +{ + xhci_debug("Input Control add: 0x%08"PRIx32"\n", *ic->add); + xhci_debug("Input Control drop: 0x%08"PRIx32"\n", *ic->drop); + xhci_dump_devctx(&ic->dev, *ic->add); +} + +void +xhci_dump_transfer_trb(const trb_t *const cur) +{ + xhci_debug("Transfer TRB (@%p):\n", cur); + usb_debug(" PTR_L\t0x%08"PRIx32"\n", cur->ptr_low); + usb_debug(" PTR_H\t0x%08"PRIx32"\n", cur->ptr_high); + usb_debug(" STATUS\t0x%08"PRIx32"\n", cur->status); + usb_debug(" CNTRL\t0x%08"PRIx32"\n", cur->control); + TRB_DUMP(TL, cur); + TRB_DUMP(TDS, cur); + TRB_DUMP(C, cur); + TRB_DUMP(ISP, cur); + TRB_DUMP(CH, cur); + TRB_DUMP(IOC, cur); + TRB_DUMP(IDT, cur); + TRB_DUMP(TT, cur); + TRB_DUMP(DIR, cur); +} + +static const trb_t * +xhci_next_trb(const trb_t *const cur) +{ + if (TRB_GET(TT, cur) == TRB_LINK) + return (!cur->ptr_low) ? NULL : phys_to_virt(cur->ptr_low); + else + return cur + 1; +} + +void +xhci_dump_transfer_trbs(const trb_t *const first, const trb_t *const last) +{ + const trb_t *cur; + for (cur = first; cur; cur = xhci_next_trb(cur)) { + xhci_dump_transfer_trb(cur); + if (cur == last) + break; + } +} + +#endif diff --git a/payloads/libpayload/drivers/usb/xhci_devconf.c b/payloads/libpayload/drivers/usb/xhci_devconf.c new file mode 100644 index 0000000000..5699499f26 --- /dev/null +++ b/payloads/libpayload/drivers/usb/xhci_devconf.c @@ -0,0 +1,405 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#define XHCI_SPEW_DEBUG + +#include +#include +#include "xhci_private.h" + +static u32 +xhci_gen_route(xhci_t *const xhci, const int hubport, const int hubaddr) +{ + if (!hubaddr) + return 0; + u32 route_string = SC_GET(ROUTE, xhci->dev[hubaddr].ctx.slot); + int i; + for (i = 0; i < 20; i += 4) { + if (!(route_string & (0xf << i))) { + route_string |= (hubport & 0xf) << i; + break; + } + } + return route_string; +} + +static int +xhci_get_rh_port(xhci_t *const xhci, const int hubport, const int hubaddr) +{ + if (!hubaddr) + return hubport; + return SC_GET(RHPORT, xhci->dev[hubaddr].ctx.slot); +} + +static int +xhci_get_tt(xhci_t *const xhci, const usb_speed speed, + const int hubport, const int hubaddr, + int *const tt, int *const tt_port) +{ + if (!hubaddr) + return 0; + const slotctx_t *const slot = xhci->dev[hubaddr].ctx.slot; + if ((*tt = SC_GET(TTID, slot))) { + *tt_port = SC_GET(TTPORT, slot); + } else if (speed < HIGH_SPEED && + SC_GET(SPEED1, slot) - 1 == HIGH_SPEED) { + *tt = hubaddr; + *tt_port = hubport; + } + return *tt != 0; +} + +static inputctx_t * +xhci_make_inputctx(const size_t ctxsize) +{ + int i; + const size_t size = (1 + NUM_EPS) * ctxsize; + inputctx_t *const ic = malloc(sizeof(*ic)); + void *dma_buffer = dma_memalign(64, size); + + if (!ic || !dma_buffer) { + free(ic); + free(dma_buffer); + return NULL; + } + + memset(dma_buffer, 0, size); + ic->drop = dma_buffer + 0; + ic->add = dma_buffer + 4; + dma_buffer += ctxsize; + for (i = 0; i < NUM_EPS; i++, dma_buffer += ctxsize) + ic->dev.ep[i] = dma_buffer; + + return ic; +} + +usbdev_t * +xhci_set_address (hci_t *controller, usb_speed speed, int hubport, int hubaddr) +{ + xhci_t *const xhci = XHCI_INST(controller); + const size_t ctxsize = CTXSIZE(xhci); + devinfo_t *di = NULL; + usbdev_t *dev = NULL; + int i; + + inputctx_t *const ic = xhci_make_inputctx(ctxsize); + transfer_ring_t *const tr = malloc(sizeof(*tr)); + if (tr) + tr->ring = xhci_align(16, TRANSFER_RING_SIZE * sizeof(trb_t)); + if (!ic || !tr || !tr->ring) { + xhci_debug("Out of memory\n"); + goto _free_return; + } + + int slot_id; + int cc = xhci_cmd_enable_slot(xhci, &slot_id); + if (cc != CC_SUCCESS) { + xhci_debug("Enable slot failed: %d\n", cc); + goto _free_return; + } else { + xhci_debug("Enabled slot %d\n", slot_id); + } + + di = &xhci->dev[slot_id]; + void *dma_buffer = dma_memalign(64, NUM_EPS * ctxsize); + if (!dma_buffer) + goto _disable_return; + memset(dma_buffer, 0, NUM_EPS * ctxsize); + for (i = 0; i < NUM_EPS; i++, dma_buffer += ctxsize) + di->ctx.ep[i] = dma_buffer; + + *ic->add = (1 << 0) /* Slot Context */ | (1 << 1) /* EP0 Context */ ; + + SC_SET(ROUTE, ic->dev.slot, xhci_gen_route(xhci, hubport, hubaddr)); + SC_SET(SPEED1, ic->dev.slot, speed + 1); + SC_SET(CTXENT, ic->dev.slot, 1); /* the endpoint 0 context */ + SC_SET(RHPORT, ic->dev.slot, xhci_get_rh_port(xhci, hubport, hubaddr)); + + int tt, tt_port; + if (xhci_get_tt(xhci, speed, hubport, hubaddr, &tt, &tt_port)) { + xhci_debug("TT for %d: %d[%d]\n", slot_id, tt, tt_port); + SC_SET(MTT, ic->dev.slot, SC_GET(MTT, xhci->dev[tt].ctx.slot)); + SC_SET(TTID, ic->dev.slot, tt); + SC_SET(TTPORT, ic->dev.slot, tt_port); + } + + di->transfer_rings[1] = tr; + xhci_init_cycle_ring(tr, TRANSFER_RING_SIZE); + + ic->dev.ep0->tr_dq_low = virt_to_phys(tr->ring); + ic->dev.ep0->tr_dq_high = 0; + EC_SET(TYPE, ic->dev.ep0, EP_CONTROL); + EC_SET(AVRTRB, ic->dev.ep0, 8); + EC_SET(MPS, ic->dev.ep0, 8); + EC_SET(CERR, ic->dev.ep0, 3); + EC_SET(DCS, ic->dev.ep0, 1); + + xhci->dcbaa[slot_id] = virt_to_phys(di->ctx.raw); + + cc = xhci_cmd_address_device(xhci, slot_id, ic); + if (cc != CC_SUCCESS) { + xhci_debug("Address device failed: %d\n", cc); + goto _disable_return; + } else { + xhci_debug("Addressed device %d (USB: %d)\n", + slot_id, SC_GET(UADDR, di->ctx.slot)); + } + mdelay(SET_ADDRESS_MDELAY); + + dev = init_device_entry(controller, slot_id); + if (!dev) + goto _disable_return; + + dev->address = slot_id; + dev->hub = hubaddr; + dev->port = hubport; + dev->speed = speed; + dev->endpoints[0].dev = dev; + dev->endpoints[0].endpoint = 0; + dev->endpoints[0].toggle = 0; + dev->endpoints[0].direction = SETUP; + dev->endpoints[0].type = CONTROL; + + u8 buf[8]; + if (get_descriptor(dev, gen_bmRequestType(device_to_host, standard_type, + dev_recp), DT_DEV, 0, buf, sizeof(buf)) != sizeof(buf)) { + usb_debug("first get_descriptor(DT_DEV) failed\n"); + goto _disable_return; + } + + dev->endpoints[0].maxpacketsize = usb_decode_mps0(speed, buf[7]); + if (dev->endpoints[0].maxpacketsize != 8) { + memset((void *)ic->dev.ep0, 0x00, ctxsize); + *ic->add = (1 << 1); /* EP0 Context */ + EC_SET(MPS, ic->dev.ep0, dev->endpoints[0].maxpacketsize); + cc = xhci_cmd_evaluate_context(xhci, slot_id, ic); + if (cc != CC_SUCCESS) { + xhci_debug("Context evaluation failed: %d\n", cc); + goto _disable_return; + } + } + + goto _free_ic_return; + +_disable_return: + xhci_cmd_disable_slot(xhci, slot_id); + xhci->dcbaa[slot_id] = 0; + usb_detach_device(controller, slot_id); + dev = NULL; +_free_return: + if (tr) + free((void *)tr->ring); + free(tr); + if (di) + free(di->ctx.raw); + free((void *)di); +_free_ic_return: + if (ic) + free(ic->raw); + free(ic); + return dev; +} + +static int +xhci_finish_hub_config(usbdev_t *const dev, inputctx_t *const ic) +{ + hub_descriptor_t desc; + + if (get_descriptor(dev, gen_bmRequestType(device_to_host, class_type, + dev_recp), 0x29, 0, &desc, sizeof(desc)) != sizeof(desc)) { + xhci_debug("Failed to fetch hub descriptor\n"); + return COMMUNICATION_ERROR; + } + + SC_SET(HUB, ic->dev.slot, 1); + SC_SET(MTT, ic->dev.slot, 0); /* No support for Multi-TT */ + SC_SET(NPORTS, ic->dev.slot, desc.bNbrPorts); + if (dev->speed == HIGH_SPEED) + SC_SET(TTT, ic->dev.slot, + (desc.wHubCharacteristics >> 5) & 0x0003); + + return 0; +} + +static size_t +xhci_bound_interval(const endpoint_t *const ep) +{ + if ( (ep->dev->speed == LOW_SPEED && + (ep->type == ISOCHRONOUS || + ep->type == INTERRUPT)) || + (ep->dev->speed == FULL_SPEED && + ep->type == INTERRUPT)) + { + if (ep->interval < 3) + return 3; + else if (ep->interval > 11) + return 11; + else + return ep->interval; + } else { + if (ep->interval < 0) + return 0; + else if (ep->interval > 15) + return 15; + else + return ep->interval; + } +} + +static int +xhci_finish_ep_config(const endpoint_t *const ep, inputctx_t *const ic) +{ + xhci_t *const xhci = XHCI_INST(ep->dev->controller); + const int ep_id = xhci_ep_id(ep); + xhci_debug("ep_id: %d\n", ep_id); + if (ep_id <= 1 || 32 <= ep_id) + return DRIVER_ERROR; + + transfer_ring_t *const tr = malloc(sizeof(*tr)); + if (tr) + tr->ring = xhci_align(16, TRANSFER_RING_SIZE * sizeof(trb_t)); + if (!tr || !tr->ring) { + free(tr); + xhci_debug("Out of memory\n"); + return OUT_OF_MEMORY; + } + xhci->dev[ep->dev->address].transfer_rings[ep_id] = tr; + xhci_init_cycle_ring(tr, TRANSFER_RING_SIZE); + + *ic->add |= (1 << ep_id); + if (SC_GET(CTXENT, ic->dev.slot) < ep_id) + SC_SET(CTXENT, ic->dev.slot, ep_id); + + epctx_t *const epctx = ic->dev.ep[ep_id]; + xhci_debug("Filling epctx (@%p)\n", epctx); + epctx->tr_dq_low = virt_to_phys(tr->ring); + epctx->tr_dq_high = 0; + EC_SET(INTVAL, epctx, xhci_bound_interval(ep)); + EC_SET(CERR, epctx, 3); + EC_SET(TYPE, epctx, ep->type | ((ep->direction != OUT) << 2)); + EC_SET(MPS, epctx, ep->maxpacketsize); + EC_SET(DCS, epctx, 1); + size_t avrtrb; + switch (ep->type) { + case BULK: case ISOCHRONOUS: avrtrb = 3 * 1024; break; + case INTERRUPT: avrtrb = 1024; break; + default: avrtrb = 8; break; + } + EC_SET(AVRTRB, epctx, avrtrb); + EC_SET(MXESIT, epctx, EC_GET(MPS, epctx) * EC_GET(MBS, epctx)); + + return 0; +} + +int +xhci_finish_device_config(usbdev_t *const dev) +{ + xhci_t *const xhci = XHCI_INST(dev->controller); + devinfo_t *const di = &xhci->dev[dev->address]; + + int i, ret = 0; + + inputctx_t *const ic = xhci_make_inputctx(CTXSIZE(xhci)); + if (!ic) { + xhci_debug("Out of memory\n"); + return OUT_OF_MEMORY; + } + + *ic->add = (1 << 0); /* Slot Context */ + + xhci_dump_slotctx(di->ctx.slot); + ic->dev.slot->f1 = di->ctx.slot->f1; + ic->dev.slot->f2 = di->ctx.slot->f2; + ic->dev.slot->f3 = di->ctx.slot->f3; + + if (dev->descriptor->bDeviceClass == 0x09 && dev->speed < SUPER_SPEED) { + ret = xhci_finish_hub_config(dev, ic); + if (ret) + goto _free_return; + } + + for (i = 1; i < dev->num_endp; ++i) { + ret = xhci_finish_ep_config(&dev->endpoints[i], ic); + if (ret) + goto _free_ep_ctx_return; + } + + xhci_dump_inputctx(ic); + + const int config_id = dev->configuration->bConfigurationValue; + xhci_debug("config_id: %d\n", config_id); + const int cc = + xhci_cmd_configure_endpoint(xhci, dev->address, config_id, ic); + if (cc != CC_SUCCESS) { + xhci_debug("Configure endpoint failed: %d\n", cc); + ret = CONTROLLER_ERROR; + goto _free_ep_ctx_return; + } else { + xhci_debug("Endpoints configured\n"); + } + + goto _free_return; + +_free_ep_ctx_return: + for (i = 2; i < 31; ++i) { + if (di->transfer_rings[i]) + free((void *)di->transfer_rings[i]->ring); + free(di->transfer_rings[i]); + di->transfer_rings[i] = NULL; + } +_free_return: + free(ic->raw); + free(ic); + return ret; +} + +void +xhci_destroy_dev(hci_t *const controller, const int slot_id) +{ + xhci_t *const xhci = XHCI_INST(controller); + + if (slot_id <= 0 || slot_id > xhci->max_slots_en) + return; + + int i; + + const int cc = xhci_cmd_disable_slot(xhci, slot_id); + if (cc != CC_SUCCESS) + xhci_debug("Failed to disable slot %d: %d\n", slot_id, cc); + + devinfo_t *const di = &xhci->dev[slot_id]; + for (i = 1; i < 31; ++i) { + if (di->transfer_rings[i]) + free((void *)di->transfer_rings[i]->ring); + free(di->transfer_rings[i]); + + free(di->interrupt_queues[i]); + } + xhci->dcbaa[slot_id] = 0; +} diff --git a/payloads/libpayload/drivers/usb/xhci_events.c b/payloads/libpayload/drivers/usb/xhci_events.c new file mode 100644 index 0000000000..dacb5d8618 --- /dev/null +++ b/payloads/libpayload/drivers/usb/xhci_events.c @@ -0,0 +1,333 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 secunet Security Networks AG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +//#define XHCI_SPEW_DEBUG + +#include +#include +#include "xhci_private.h" + +void +xhci_reset_event_ring(event_ring_t *const er) +{ + int i; + for (i = 0; i < EVENT_RING_SIZE; ++i) + er->ring[i].control &= ~TRB_CYCLE; + er->cur = er->ring; + er->last = er->ring + EVENT_RING_SIZE; + er->ccs = 1; + er->adv = 1; +} + +static inline int +xhci_event_ready(const event_ring_t *const er) +{ + return (er->cur->control & TRB_CYCLE) == er->ccs; +} + +void +xhci_update_event_dq(xhci_t *const xhci) +{ + if (xhci->er.adv) { + xhci_spew("Updating dq ptr: @%p(0x%08"PRIx32") -> %p\n", + phys_to_virt(xhci->hcrreg->intrrs[0].erdp_lo), + xhci->hcrreg->intrrs[0].erdp_lo, xhci->er.cur); + xhci->hcrreg->intrrs[0].erdp_lo = virt_to_phys(xhci->er.cur); + xhci->hcrreg->intrrs[0].erdp_hi = 0; + xhci->er.adv = 0; + } +} + +void +xhci_advance_event_ring(xhci_t *const xhci) +{ + xhci->er.cur++; + xhci->er.adv = 1; + if (xhci->er.cur == xhci->er.last) { + xhci_spew("Roll over in event ring\n"); + xhci->er.cur = xhci->er.ring; + xhci->er.ccs ^= 1; + xhci_update_event_dq(xhci); + } +} + +static void +xhci_handle_transfer_event(xhci_t *const xhci) +{ + const trb_t *const ev = xhci->er.cur; + + const int cc = TRB_GET(CC, ev); + const int id = TRB_GET(ID, ev); + const int ep = TRB_GET(EP, ev); + + intrq_t *intrq; + + if (id && id <= xhci->max_slots_en && + (intrq = xhci->dev[id].interrupt_queues[ep])) { + /* It's a running interrupt endpoint */ + intrq->ready = phys_to_virt(ev->ptr_low); + if (cc == CC_SUCCESS || cc == CC_SHORT_PACKET) { + TRB_SET(TL, intrq->ready, + intrq->size - TRB_GET(EVTL, ev)); + } else { + xhci_debug("Interrupt Transfer failed: %d\n", + cc); + TRB_SET(TL, intrq->ready, 0); + } + } else if (cc == CC_STOPPED || cc == CC_STOPPED_LENGTH_INVALID) { + /* Ignore 'Forced Stop Events' */ + } else { + xhci_debug("Warning: " + "Spurious transfer event for ID %d, EP %d:\n" + " Pointer: 0x%08x%08x\n" + " TL: 0x%06x\n" + " CC: %d\n", + id, ep, + ev->ptr_high, ev->ptr_low, + TRB_GET(EVTL, ev), cc); + } + xhci_advance_event_ring(xhci); +} + +static void +xhci_handle_command_completion_event(xhci_t *const xhci) +{ + const trb_t *const ev = xhci->er.cur; + + xhci_debug("Warning: Spurious command completion event:\n" + " Pointer: 0x%08x%08x\n" + " CC: %d\n" + " Slot ID: %d\n" + " Cycle: %d\n", + ev->ptr_high, ev->ptr_low, + TRB_GET(CC, ev), TRB_GET(ID, ev), ev->control & TRB_CYCLE); + xhci_advance_event_ring(xhci); +} + +static void +xhci_handle_host_controller_event(xhci_t *const xhci) +{ + const trb_t *const ev = xhci->er.cur; + + const int cc = TRB_GET(CC, ev); + switch (cc) { + case CC_EVENT_RING_FULL_ERROR: + xhci_debug("Event ring full! (@%p)\n", xhci->er.cur); + /* + * If we get here, we have processed the whole queue: + * xHC pushes this event, when it sees the ring full, + * full of other events. + * IMO it's save and necessary to update the dequeue + * pointer here. + */ + xhci_advance_event_ring(xhci); + xhci_update_event_dq(xhci); + break; + default: + xhci_debug("Warning: Spurious host controller event: %d\n", cc); + xhci_advance_event_ring(xhci); + break; + } +} + +/* handle standard types: + * - command completion event + * - port status change event + * - transfer event + * - host controller event + */ +static void +xhci_handle_event(xhci_t *const xhci) +{ + const trb_t *const ev = xhci->er.cur; + + const int trb_type = TRB_GET(TT, ev); + switch (trb_type) { + /* Either pass along the event or advance event ring */ + case TRB_EV_TRANSFER: + xhci_handle_transfer_event(xhci); + break; + case TRB_EV_CMD_CMPL: + xhci_handle_command_completion_event(xhci); + break; + case TRB_EV_PORTSC: + xhci_debug("Port Status Change Event for %d: %d\n", + TRB_GET(PORT, ev), TRB_GET(CC, ev)); + /* We ignore the event as we look for the PORTSC + registers instead, at a time when it suits _us_. */ + xhci_advance_event_ring(xhci); + break; + case TRB_EV_HOST: + xhci_handle_host_controller_event(xhci); + break; + default: + xhci_debug("Warning: Spurious event: %d, Completion Code: %d\n", + trb_type, TRB_GET(CC, ev)); + xhci_advance_event_ring(xhci); + break; + } +} + +void +xhci_handle_events(xhci_t *const xhci) +{ + while (xhci_event_ready(&xhci->er)) + xhci_handle_event(xhci); + xhci_update_event_dq(xhci); +} + +static unsigned long +xhci_wait_for_event(const event_ring_t *const er, + unsigned long *const timeout_us) +{ + while (!xhci_event_ready(er) && *timeout_us) { + --*timeout_us; + udelay(1); + } + return *timeout_us; +} + +static unsigned long +xhci_wait_for_event_type(xhci_t *const xhci, + const int trb_type, + unsigned long *const timeout_us) +{ + while (xhci_wait_for_event(&xhci->er, timeout_us)) { + if (TRB_GET(TT, xhci->er.cur) == trb_type) + break; + + xhci_handle_event(xhci); + } + return *timeout_us; +} + +/* returns cc of command in question (pointed to by `address`) */ +int +xhci_wait_for_command_aborted(xhci_t *const xhci, const trb_t *const address) +{ + /* + * Specification says that something might be seriously wrong, if + * we don't get a response after 5s. Still, let the caller decide, + * what to do then. + */ + unsigned long timeout_us = 5 * 1000 * 1000; /* 5s */ + int cc = TIMEOUT; + /* + * Expects two command completion events: + * The first with CC == COMMAND_ABORTED should point to address, + * the second with CC == COMMAND_RING_STOPPED should point to new dq. + */ + while (xhci_wait_for_event_type(xhci, TRB_EV_CMD_CMPL, &timeout_us)) { + if ((xhci->er.cur->ptr_low == virt_to_phys(address)) && + (xhci->er.cur->ptr_high == 0)) { + cc = TRB_GET(CC, xhci->er.cur); + xhci_advance_event_ring(xhci); + break; + } + + xhci_handle_command_completion_event(xhci); + } + if (!timeout_us) + xhci_debug("Warning: Timed out waiting for COMMAND_ABORTED.\n"); + while (xhci_wait_for_event_type(xhci, TRB_EV_CMD_CMPL, &timeout_us)) { + if (TRB_GET(CC, xhci->er.cur) == CC_COMMAND_RING_STOPPED) { + xhci->cr.cur = phys_to_virt(xhci->er.cur->ptr_low); + xhci_advance_event_ring(xhci); + break; + } + + xhci_handle_command_completion_event(xhci); + } + if (!timeout_us) + xhci_debug("Warning: Timed out " + "waiting for COMMAND_RING_STOPPED.\n"); + xhci_update_event_dq(xhci); + return cc; +} + +/* + * returns cc of command in question (pointed to by `address`) + * caller should abort command if cc is TIMEOUT + */ +int +xhci_wait_for_command_done(xhci_t *const xhci, + const trb_t *const address, + const int clear_event) +{ + /* + * The Address Device Command should take most time, as it has to + * communicate with the USB device. Set address processing shouldn't + * take longer than 50ms (at the slave). Let's take a timeout of + * 100ms. + */ + unsigned long timeout_us = 100 * 1000; /* 100ms */ + int cc = TIMEOUT; + while (xhci_wait_for_event_type(xhci, TRB_EV_CMD_CMPL, &timeout_us)) { + if ((xhci->er.cur->ptr_low == virt_to_phys(address)) && + (xhci->er.cur->ptr_high == 0)) { + cc = TRB_GET(CC, xhci->er.cur); + break; + } + + xhci_handle_command_completion_event(xhci); + } + if (!timeout_us) { + xhci_debug("Warning: Timed out waiting for TRB_EV_CMD_CMPL.\n"); + } else if (clear_event) { + xhci_advance_event_ring(xhci); + } + xhci_update_event_dq(xhci); + return cc; +} + +/* returns amount of bytes transferred on success, negative CC on error */ +int +xhci_wait_for_transfer(xhci_t *const xhci, const int slot_id, const int ep_id) +{ + xhci_spew("Waiting for transfer on ID %d EP %d\n", slot_id, ep_id); + /* 3s for all types of transfers */ /* TODO: test, wait longer? */ + unsigned long timeout_us = 3 * 1000 * 1000; + int ret = TIMEOUT; + while (xhci_wait_for_event_type(xhci, TRB_EV_TRANSFER, &timeout_us)) { + if (TRB_GET(ID, xhci->er.cur) == slot_id && + TRB_GET(EP, xhci->er.cur) == ep_id) { + ret = -TRB_GET(CC, xhci->er.cur); + if (ret == -CC_SUCCESS || ret == -CC_SHORT_PACKET) + ret = TRB_GET(EVTL, xhci->er.cur); + xhci_advance_event_ring(xhci); + break; + } + + xhci_handle_transfer_event(xhci); + } + if (!timeout_us) + xhci_debug("Warning: Timed out waiting for TRB_EV_TRANSFER.\n"); + xhci_update_event_dq(xhci); + return ret; +} diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h index 16834f77cc..7cfb71f5f4 100644 --- a/payloads/libpayload/drivers/usb/xhci_private.h +++ b/payloads/libpayload/drivers/usb/xhci_private.h @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2010 Patrick Georgi + * Copyright (C) 2013 secunet Security Networks AG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,159 +31,276 @@ #ifndef __XHCI_PRIVATE_H #define __XHCI_PRIVATE_H +//#define USB_DEBUG #include +//#define XHCI_DUMPS +#define xhci_debug(fmt, args...) usb_debug("%s: " fmt, __func__, ## args) +#ifdef XHCI_SPEW_DEBUG +# define xhci_spew(fmt, args...) xhci_debug(fmt, ##args) +#else +# define xhci_spew(fmt, args...) do {} while(0) +#endif + #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) -typedef volatile union trb { - // transfer +/* Make these high enough to not collide with negative XHCI CCs */ +#define TIMEOUT -65 +#define CONTROLLER_ERROR -66 +#define COMMUNICATION_ERROR -67 +#define OUT_OF_MEMORY -68 +#define DRIVER_ERROR -69 - // events -#define TRB_EV_CMD_CMPL 33 - struct { - u32 Cmd_TRB_Pointer_lo; - u32 Cmd_TRB_Pointer_hi; - struct { - unsigned long:24; - unsigned long Completion_Code:8; - } __attribute__ ((packed)); - struct { - unsigned long C:1; - unsigned long:9; - unsigned long TRB_Type:6; - unsigned long VF_ID:8; - unsigned long Slot_ID:8; - } __attribute__ ((packed)); - } __attribute__ ((packed)) event_cmd_cmpl; +#define CC_SUCCESS 1 +#define CC_TRB_ERROR 5 +#define CC_STALL_ERROR 6 +#define CC_SHORT_PACKET 13 +#define CC_EVENT_RING_FULL_ERROR 21 +#define CC_COMMAND_RING_STOPPED 24 +#define CC_COMMAND_ABORTED 25 +#define CC_STOPPED 26 +#define CC_STOPPED_LENGTH_INVALID 27 -#define TRB_EV_PORTSC 34 - struct { - struct { - unsigned long:24; - unsigned long Port:8; - } __attribute__ ((packed)); - u32 rsvd; - struct { - unsigned long:24; - unsigned long Completion_Code:8; - } __attribute__ ((packed)); - struct { - unsigned long C:1; - unsigned long:9; - unsigned long TRB_Type:6; - unsigned long:16; - } __attribute__ ((packed)); - } __attribute__ ((packed)) event_portsc; +enum { + TRB_NORMAL = 1, + TRB_SETUP_STAGE = 2, TRB_DATA_STAGE = 3, TRB_STATUS_STAGE = 4, + TRB_LINK = 6, TRB_EVENT_DATA = 7, + TRB_CMD_ENABLE_SLOT = 9, TRB_CMD_DISABLE_SLOT = 10, TRB_CMD_ADDRESS_DEV = 11, + TRB_CMD_CONFIGURE_EP = 12, TRB_CMD_EVAL_CTX = 13, TRB_CMD_RESET_EP = 14, + TRB_CMD_STOP_EP = 15, TRB_CMD_SET_TR_DQ = 16, TRB_CMD_NOOP = 23, + TRB_EV_TRANSFER = 32, TRB_EV_CMD_CMPL = 33, TRB_EV_PORTSC = 34, TRB_EV_HOST = 37, +}; +enum { TRB_TRT_NO_DATA = 0, TRB_TRT_OUT_DATA = 2, TRB_TRT_IN_DATA = 3 }; +enum { TRB_DIR_OUT = 0, TRB_DIR_IN = 1 }; - // commands -#define TRB_CMD_NOOP 23 - struct { - u32 rsvd[3]; - struct { - unsigned long C:1; - unsigned long:9; - unsigned long TRB_Type:6; - unsigned long:16; - } __attribute__ ((packed)); - } __attribute__ ((packed)) cmd_No_Op; +#define TRB_PORT_FIELD ptr_low +#define TRB_PORT_START 24 +#define TRB_PORT_LEN 8 +#define TRB_TL_FIELD status /* TL - Transfer Length */ +#define TRB_TL_START 0 +#define TRB_TL_LEN 17 +#define TRB_EVTL_FIELD status /* EVTL - (Event TRB) Transfer Length */ +#define TRB_EVTL_START 0 +#define TRB_EVTL_LEN 24 +#define TRB_TDS_FIELD status /* TDS - TD Size */ +#define TRB_TDS_START 17 +#define TRB_TDS_LEN 5 +#define TRB_CC_FIELD status /* CC - Completion Code */ +#define TRB_CC_START 24 +#define TRB_CC_LEN 8 +#define TRB_C_FIELD control /* C - Cycle Bit */ +#define TRB_C_START 0 +#define TRB_C_LEN 1 +#define TRB_TC_FIELD control /* TC - Toggle Cycle */ +#define TRB_TC_START 1 +#define TRB_TC_LEN 1 +#define TRB_ENT_FIELD control /* ENT - Evaluate Next TRB */ +#define TRB_ENT_START 1 +#define TRB_ENT_LEN 1 +#define TRB_ISP_FIELD control /* ISP - Interrupt-on Short Packet */ +#define TRB_ISP_START 2 +#define TRB_ISP_LEN 1 +#define TRB_CH_FIELD control /* CH - Chain Bit */ +#define TRB_CH_START 4 +#define TRB_CH_LEN 1 +#define TRB_IOC_FIELD control /* IOC - Interrupt On Completion */ +#define TRB_IOC_START 5 +#define TRB_IOC_LEN 1 +#define TRB_IDT_FIELD control /* IDT - Immediate Data */ +#define TRB_IDT_START 6 +#define TRB_IDT_LEN 1 +#define TRB_DC_FIELD control /* DC - Deconfigure */ +#define TRB_DC_START 9 +#define TRB_DC_LEN 1 +#define TRB_TT_FIELD control /* TT - TRB Type */ +#define TRB_TT_START 10 +#define TRB_TT_LEN 6 +#define TRB_TRT_FIELD control /* TRT - Transfer Type */ +#define TRB_TRT_START 16 +#define TRB_TRT_LEN 2 +#define TRB_DIR_FIELD control /* DIR - Direction */ +#define TRB_DIR_START 16 +#define TRB_DIR_LEN 1 +#define TRB_EP_FIELD control /* EP - Endpoint ID */ +#define TRB_EP_START 16 +#define TRB_EP_LEN 5 +#define TRB_ID_FIELD control /* ID - Slot ID */ +#define TRB_ID_START 24 +#define TRB_ID_LEN 8 +#define TRB_MASK(tok) MASK(TRB_##tok##_START, TRB_##tok##_LEN) +#define TRB_GET(tok, trb) (((trb)->TRB_##tok##_FIELD & TRB_MASK(tok)) \ + >> TRB_##tok##_START) +#define TRB_SET(tok, trb, to) (trb)->TRB_##tok##_FIELD = \ + (((trb)->TRB_##tok##_FIELD & ~TRB_MASK(tok)) | \ + (((to) << TRB_##tok##_START) & TRB_MASK(tok))) +#define TRB_DUMP(tok, trb) usb_debug(" "#tok"\t0x%04"PRIx32"\n", TRB_GET(tok, trb)) - // "others" - struct { - u32 Ring_Segment_Ptr_lo; - u32 Ring_Segment_Ptr_hi; - struct { - unsigned long:22; - unsigned long Interrupter_Target; - } __attribute__ ((packed)); - struct { - unsigned long C:1; - unsigned long TC:1; - unsigned long:2; - unsigned long CH:1; - unsigned long IOC:1; - unsigned long:4; - unsigned long TRB_Type:6; - unsigned long:16; - } __attribute__ ((packed)); - } __attribute__ ((packed)) link; +#define TRB_CYCLE (1 << 0) +typedef volatile struct trb { + u32 ptr_low; + u32 ptr_high; + u32 status; + u32 control; } trb_t; -typedef struct slotctx { - struct { - unsigned long Route_String:20; - unsigned long Speed:4; - unsigned long:1; - unsigned long MTT:1; - unsigned long Hub:1; - unsigned long Context_Entries:5; - } __attribute__ ((packed)); - struct { - unsigned long Max_Exit_Latency:16; - unsigned long Root_Hub_Port_Number:8; - unsigned long Number_of_Ports:8; - } __attribute__ ((packed)); - struct { - unsigned long TT_Hub_Slot_ID:8; - unsigned long TT_Port_Number:8; - unsigned long TTT:2; - unsigned long:4; - unsigned long Interrupter_Target:10; - } __attribute__ ((packed)); - struct { - unsigned long USB_Device_Address:8; - unsigned long:19; - unsigned long Slot_State:5; - } __attribute__ ((packed)); +#define TRB_MAX_TD_SIZE 0x1F /* bits 21:17 of TD Size in TRB */ + +#define EVENT_RING_SIZE 64 +typedef struct { + trb_t *ring; + trb_t *cur; + trb_t *last; + u8 ccs; + u8 adv; +} event_ring_t; + +/* Never raise this above 256 to prevent transfer event length overflow! */ +#define TRANSFER_RING_SIZE 32 +typedef struct { + trb_t *ring; + trb_t *cur; + u8 pcs; +} __attribute__ ((packed)) transfer_ring_t; + +#define COMMAND_RING_SIZE 4 +typedef transfer_ring_t command_ring_t; + +#define SC_ROUTE_FIELD f1 /* ROUTE - Route String */ +#define SC_ROUTE_START 0 +#define SC_ROUTE_LEN 20 +#define SC_SPEED1_FIELD f1 /* SPEED - Port speed plus one (compared to usb_speed enum) */ +#define SC_SPEED1_START 20 +#define SC_SPEED1_LEN 4 +#define SC_MTT_FIELD f1 /* MTT - Multi Transaction Translator */ +#define SC_MTT_START 25 +#define SC_MTT_LEN 1 +#define SC_HUB_FIELD f1 /* HUB - Is this a hub? */ +#define SC_HUB_START 26 +#define SC_HUB_LEN 1 +#define SC_CTXENT_FIELD f1 /* CTXENT - Context Entries (number of following ep contexts) */ +#define SC_CTXENT_START 27 +#define SC_CTXENT_LEN 5 +#define SC_RHPORT_FIELD f2 /* RHPORT - Root Hub Port Number */ +#define SC_RHPORT_START 16 +#define SC_RHPORT_LEN 8 +#define SC_NPORTS_FIELD f2 /* NPORTS - Number of Ports */ +#define SC_NPORTS_START 24 +#define SC_NPORTS_LEN 8 +#define SC_TTID_FIELD f3 /* TTID - TT Hub Slot ID */ +#define SC_TTID_START 0 +#define SC_TTID_LEN 8 +#define SC_TTPORT_FIELD f3 /* TTPORT - TT Port Number */ +#define SC_TTPORT_START 8 +#define SC_TTPORT_LEN 8 +#define SC_TTT_FIELD f3 /* TTT - TT Think Time */ +#define SC_TTT_START 16 +#define SC_TTT_LEN 2 +#define SC_UADDR_FIELD f4 /* UADDR - USB Device Address */ +#define SC_UADDR_START 0 +#define SC_UADDR_LEN 8 +#define SC_STATE_FIELD f4 /* STATE - Slot State */ +#define SC_STATE_START 27 +#define SC_STATE_LEN 8 +#define SC_MASK(tok) MASK(SC_##tok##_START, SC_##tok##_LEN) +#define SC_GET(tok, sc) (((sc)->SC_##tok##_FIELD & SC_MASK(tok)) \ + >> SC_##tok##_START) +#define SC_SET(tok, sc, to) (sc)->SC_##tok##_FIELD = \ + (((sc)->SC_##tok##_FIELD & ~SC_MASK(tok)) | \ + (((to) << SC_##tok##_START) & SC_MASK(tok))) +#define SC_DUMP(tok, sc) usb_debug(" "#tok"\t0x%04"PRIx32"\n", SC_GET(tok, sc)) +typedef volatile struct slotctx { + u32 f1; + u32 f2; + u32 f3; + u32 f4; u32 rsvd[4]; } slotctx_t; -typedef struct epctx { - struct { - unsigned long EP_State:3; - unsigned long:5; - unsigned long Mult:2; - unsigned long MaxPStreams:5; - unsigned long LSA:1; - unsigned long Interval:8; - unsigned long:8; - } __attribute__ ((packed)); - struct { - unsigned long:1; - unsigned long CErr:2; - unsigned long EP_Type:3; - unsigned long:1; - unsigned long HID:1; - unsigned long Max_Burst_Size:8; - unsigned long Max_Packet_Size:16; - } __attribute__ ((packed)); - union { - u32 TR_Dequeue_Pointer_lo; - struct { - unsigned long DCS:1; - unsigned long:3; - } __attribute__ ((packed)); - } __attribute__ ((packed)); - u32 TR_Dequeue_Pointer_hi; - struct { - unsigned long Average_TRB_Length:16; - unsigned long Max_ESIT_Payload:16; - } __attribute__ ((packed)); +#define EC_STATE_FIELD f1 /* STATE - Endpoint State */ +#define EC_STATE_START 0 +#define EC_STATE_LEN 3 +#define EC_INTVAL_FIELD f1 /* INTVAL - Interval */ +#define EC_INTVAL_START 16 +#define EC_INTVAL_LEN 8 +#define EC_CERR_FIELD f2 /* CERR - Error Count */ +#define EC_CERR_START 1 +#define EC_CERR_LEN 2 +#define EC_TYPE_FIELD f2 /* TYPE - EP Type */ +#define EC_TYPE_START 3 +#define EC_TYPE_LEN 3 +#define EC_MBS_FIELD f2 /* MBS - Max Burst Size */ +#define EC_MBS_START 8 +#define EC_MBS_LEN 8 +#define EC_MPS_FIELD f2 /* MPS - Max Packet Size */ +#define EC_MPS_START 16 +#define EC_MPS_LEN 16 +#define EC_DCS_FIELD tr_dq_low /* DCS - Dequeue Cycle State */ +#define EC_DCS_START 0 +#define EC_DCS_LEN 1 +#define EC_AVRTRB_FIELD f5 /* AVRTRB - Average TRB Length */ +#define EC_AVRTRB_START 0 +#define EC_AVRTRB_LEN 16 +#define EC_MXESIT_FIELD f5 /* MXESIT - Max ESIT Payload */ +#define EC_MXESIT_START 16 +#define EC_MXESIT_LEN 16 +#define EC_MASK(tok) MASK(EC_##tok##_START, EC_##tok##_LEN) +#define EC_GET(tok, ec) (((ec)->EC_##tok##_FIELD & EC_MASK(tok)) \ + >> EC_##tok##_START) +#define EC_SET(tok, ec, to) (ec)->EC_##tok##_FIELD = \ + (((ec)->EC_##tok##_FIELD & ~EC_MASK(tok)) | \ + (((to) << EC_##tok##_START) & EC_MASK(tok))) +#define EC_DUMP(tok, ec) usb_debug(" "#tok"\t0x%04"PRIx32"\n", EC_GET(tok, ec)) +enum { EP_ISOC_OUT = 1, EP_BULK_OUT = 2, EP_INTR_OUT = 3, + EP_CONTROL = 4, EP_ISOC_IN = 5, EP_BULK_IN = 6, EP_INTR_IN = 7 }; +typedef volatile struct epctx { + u32 f1; + u32 f2; + u32 tr_dq_low; + u32 tr_dq_high; + u32 f5; u32 rsvd[3]; } epctx_t; -typedef struct devctx { - slotctx_t slot; - epctx_t ep0; +#define NUM_EPS 32 +#define CTXSIZE(xhci) ((xhci)->capreg->csz ? 64 : 32) + +typedef union devctx { + /* set of pointers, so we can dynamically adjust Slot/EP context size */ struct { - epctx_t out; - epctx_t in; - } eps[15]; + union { + slotctx_t *slot; + void *raw; /* Pointer to the whole dev context. */ + }; + epctx_t *ep0; + epctx_t *eps1_30[NUM_EPS - 2]; + }; + epctx_t *ep[NUM_EPS]; /* At index 0 it's actually the slotctx, + we have it like that so we can use + the ep_id directly as index. */ } devctx_t; -typedef struct devctxp { - devctx_t *ptr; - void *upper; -} devctxp_t; +typedef struct inputctx { + union { /* The drop flags are located at the start of the */ + u32 *drop; /* structure, so a pointer to them is equivalent */ + void *raw; /* to a pointer to the whole (raw) input context. */ + }; + u32 *add; + devctx_t dev; +} inputctx_t; + +typedef struct intrq { + size_t size; /* Size of each transfer */ + size_t count; /* The number of TRBs to fill at once */ + trb_t *next; /* The next TRB expected to be processed by the controller */ + trb_t *ready; /* The last TRB in the transfer ring processed by the controller */ + endpoint_t *ep; +} intrq_t; + +typedef struct devinfo { + devctx_t ctx; + transfer_ring_t *transfer_rings[NUM_EPS]; + intrq_t *interrupt_queues[32]; +} devinfo_t; typedef struct erst_entry { u32 seg_base_lo; @@ -258,12 +376,14 @@ typedef struct xhci { u32 usbcmd; #define USBCMD_RS 1<<0 #define USBCMD_HCRST 1<<1 +#define USBCMD_INTE 1<<2 u32 usbsts; #define USBSTS_HCH 1<<0 #define USBSTS_HSE 1<<2 #define USBSTS_EINT 1<<3 #define USBSTS_PCD 1<<4 #define USBSTS_CNR 1<<11 +#define USBSTS_PRSRV_MASK ((1 << 1) | 0xffffe000) u32 pagesize; u8 res1[0x13-0x0c+1]; u32 dnctrl; @@ -277,38 +397,39 @@ typedef struct xhci { u32 dcbaap_lo; u32 dcbaap_hi; u32 config; -#define CONFIG_MASK_MaxSlotsEn 0xff +#define CONFIG_LP_MASK_MaxSlotsEn 0xff u8 res3[0x3ff-0x3c+1]; struct { u32 portsc; -#define PORTSC_CCS 1<<0 -#define PORTSC_PED 1<<1 +#define PORTSC_CCS (1<<0) +#define PORTSC_PED (1<<1) // BIT 2 rsvdZ -#define PORTSC_OCA 1<<3 -#define PORTSC_PR 1<<4 -#define PORTSC_PLS 1<<5 +#define PORTSC_OCA (1<<3) +#define PORTSC_PR (1<<4) +#define PORTSC_PLS (1<<5) #define PORTSC_PLS_MASK MASK(5, 4) -#define PORTSC_PP 1<<9 -#define PORTSC_PORT_SPEED 1<<10 -#define PORTSC_PORT_SPEED_MASK MASK(10, 4) -#define PORTSC_PIC 1<<14 +#define PORTSC_PP (1<<9) +#define PORTSC_PORT_SPEED_START 10 +#define PORTSC_PORT_SPEED (1< bitfields allowed */ - volatile devctxp_t *dcbaa; + u64 *dcbaa; /* pointers to sp_ptrs and output (device) contexts */ + u64 *sp_ptrs; /* pointers to scratchpad buffers */ - trb_t *cmd_ring; - trb_t *ev_ring; + command_ring_t cr; + event_ring_t er; volatile erst_entry_t *ev_ring_table; - int cmd_ccs, ev_ccs; usbdev_t *roothub; + + u8 max_slots_en; + devinfo_t *dev; /* array of devinfos by slot_id */ + +#define DMA_SIZE (64 * 1024) + void *dma_buffer; } xhci_t; #define XHCI_INST(controller) ((xhci_t*)((controller)->instance)) +void *xhci_align(const size_t min_align, const size_t size); +void xhci_init_cycle_ring(transfer_ring_t *, const size_t ring_size); +usbdev_t *xhci_set_address (hci_t *, usb_speed speed, int hubport, int hubaddr); +int xhci_finish_device_config(usbdev_t *); +void xhci_destroy_dev(hci_t *, int slot_id); + +void xhci_reset_event_ring(event_ring_t *); +void xhci_advance_event_ring(xhci_t *); +void xhci_update_event_dq(xhci_t *); +void xhci_handle_events(xhci_t *); +int xhci_wait_for_command_aborted(xhci_t *, const trb_t *); +int xhci_wait_for_command_done(xhci_t *, const trb_t *, int clear_event); +int xhci_wait_for_transfer(xhci_t *, const int slot_id, const int ep_id); + +void xhci_clear_trb(trb_t *, int pcs); + +trb_t *xhci_next_command_trb(xhci_t *); +void xhci_post_command(xhci_t *); +int xhci_cmd_enable_slot(xhci_t *, int *slot_id); +int xhci_cmd_disable_slot(xhci_t *, int slot_id); +int xhci_cmd_address_device(xhci_t *, int slot_id, inputctx_t *); +int xhci_cmd_configure_endpoint(xhci_t *, int slot_id, int config_id, inputctx_t *); +int xhci_cmd_evaluate_context(xhci_t *, int slot_id, inputctx_t *); +int xhci_cmd_reset_endpoint(xhci_t *, int slot_id, int ep); +int xhci_cmd_stop_endpoint(xhci_t *, int slot_id, int ep); +int xhci_cmd_set_tr_dq(xhci_t *, int slot_id, int ep, trb_t *, int dcs); + +static inline int xhci_ep_id(const endpoint_t *const ep) { + return ((ep->endpoint & 0x7f) << 1) + (ep->direction == IN); +} + + +#ifdef XHCI_DUMPS +void xhci_dump_slotctx(const slotctx_t *); +void xhci_dump_epctx(const epctx_t *); +void xhci_dump_devctx(const devctx_t *, const u32 ctx_mask); +void xhci_dump_inputctx(const inputctx_t *); +void xhci_dump_transfer_trb(const trb_t *); +void xhci_dump_transfer_trbs(const trb_t *first, const trb_t *last); +#else +#define xhci_dump_slotctx(args...) do {} while(0) +#define xhci_dump_epctx(args...) do {} while(0) +#define xhci_dump_devctx(args...) do {} while(0) +#define xhci_dump_inputctx(args...) do {} while(0) +#define xhci_dump_transfer_trb(args...) do {} while(0) +#define xhci_dump_transfer_trbs(args...) do {} while(0) +#endif + #endif diff --git a/payloads/libpayload/drivers/usb/xhci_rh.c b/payloads/libpayload/drivers/usb/xhci_rh.c index 58eb6c328d..fa118fe460 100644 --- a/payloads/libpayload/drivers/usb/xhci_rh.c +++ b/payloads/libpayload/drivers/usb/xhci_rh.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2010 Patrick Georgi + * Copyright (C) 2013 secunet Security Networks AG * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,107 +27,123 @@ * SUCH DAMAGE. */ -#define USB_DEBUG +//#define USB_DEBUG -#include +#include +#include "generic_hub.h" #include "xhci_private.h" #include "xhci.h" -typedef struct { - int numports; - int *port; -} rh_inst_t; - -#define RH_INST(dev) ((rh_inst_t*)(dev)->data) - -static void -xhci_rh_enable_port (usbdev_t *dev, int port) +static int +xhci_rh_hub_status_changed(usbdev_t *const dev) { - // FIXME: check power situation? - // enable slot - // attach device context to slot - // address device -} - -/* disable root hub */ -static void -xhci_rh_disable_port (usbdev_t *dev, int port) -{ -} - -static void -xhci_rh_scanport (usbdev_t *dev, int port) -{ - // clear CSC - int val = XHCI_INST (dev->controller)->opreg->prs[port].portsc; - val &= PORTSC_RW_MASK; - val |= PORTSC_CSC; - XHCI_INST (dev->controller)->opreg->prs[port].portsc = val; - - usb_debug("device attach status on port %x: %x\n", port, XHCI_INST (dev->controller)->opreg->prs[port].portsc & PORTSC_CCS); + xhci_t *const xhci = XHCI_INST(dev->controller); + const int changed = !!(xhci->opreg->usbsts & USBSTS_PCD); + if (changed) + xhci->opreg->usbsts = + (xhci->opreg->usbsts & USBSTS_PRSRV_MASK) | USBSTS_PCD; + return changed; } static int -xhci_rh_report_port_changes (usbdev_t *dev) +xhci_rh_port_status_changed(usbdev_t *const dev, const int port) { - int i; - // no change - if (!(XHCI_INST (dev->controller)->opreg->usbsts & USBSTS_PCD)) + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + const int changed = !!(*portsc & (PORTSC_CSC | PORTSC_PRC)); + /* always clear all the status change bits */ + *portsc = (*portsc & PORTSC_RW_MASK) | 0x00ef0000; + return changed; +} + +static int +xhci_rh_port_connected(usbdev_t *const dev, const int port) +{ + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + return *portsc & PORTSC_CCS; +} + +static int +xhci_rh_port_in_reset(usbdev_t *const dev, const int port) +{ + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + return !!(*portsc & PORTSC_PR); +} + +static int +xhci_rh_port_enabled(usbdev_t *const dev, const int port) +{ + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + return !!(*portsc & PORTSC_PED); +} + +static usb_speed +xhci_rh_port_speed(usbdev_t *const dev, const int port) +{ + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + if (*portsc & PORTSC_PED) { + return ((*portsc & PORTSC_PORT_SPEED_MASK) + >> PORTSC_PORT_SPEED_START) + - 1; + } else { return -1; - - for (i = 0; i < RH_INST (dev)->numports; i++) { - if (XHCI_INST (dev->controller)->opreg->prs[i].portsc & PORTSC_CSC) { - usb_debug("found connect status change on port %d\n", i); - return i; - } } - - return -1; // shouldn't ever happen } -static void -xhci_rh_destroy (usbdev_t *dev) +static int +xhci_rh_reset_port(usbdev_t *const dev, const int port) { - int i; - for (i = 0; i < RH_INST (dev)->numports; i++) - xhci_rh_disable_port (dev, i); - free (RH_INST (dev)); + xhci_t *const xhci = XHCI_INST(dev->controller); + volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc; + + /* Trigger port reset. */ + *portsc = (*portsc & PORTSC_RW_MASK) | PORTSC_PR; + + /* Wait for port_in_reset == 0, up to 150 * 1000us = 150ms */ + if (generic_hub_wait_for_port(dev, port, 0, xhci_rh_port_in_reset, + 150, 1000) == 0) + usb_debug("xhci_rh: Reset timed out at port %d\n", port); + else + /* Clear reset status bits, since port is out of reset. */ + *portsc = (*portsc & PORTSC_RW_MASK) | PORTSC_PRC | PORTSC_WRC; + + return 0; } -static void -xhci_rh_poll (usbdev_t *dev) -{ - int port; - while ((port = xhci_rh_report_port_changes (dev)) != -1) - xhci_rh_scanport (dev, port); -} +static const generic_hub_ops_t xhci_rh_ops = { + .hub_status_changed = xhci_rh_hub_status_changed, + .port_status_changed = xhci_rh_port_status_changed, + .port_connected = xhci_rh_port_connected, + .port_in_reset = xhci_rh_port_in_reset, + .port_enabled = xhci_rh_port_enabled, + .port_speed = xhci_rh_port_speed, + .enable_port = NULL, + .disable_port = NULL, + .start_port_reset = NULL, + .reset_port = xhci_rh_reset_port, +}; void xhci_rh_init (usbdev_t *dev) { - int i; - - dev->destroy = xhci_rh_destroy; - dev->poll = xhci_rh_poll; - - dev->data = malloc (sizeof (rh_inst_t)); - if (!dev->data) - fatal("Not enough memory for XHCI RH.\n"); - - RH_INST (dev)->numports = XHCI_INST (dev->controller)->capreg->MaxPorts; - RH_INST (dev)->port = malloc(sizeof(int) * RH_INST (dev)->numports); - usb_debug("%d ports registered\n", RH_INST (dev)->numports); - - for (i = 0; i < RH_INST (dev)->numports; i++) { - xhci_rh_enable_port (dev, i); - RH_INST (dev)->port[i] = -1; - } - /* we can set them here because a root hub _really_ shouldn't appear elsewhere */ dev->address = 0; dev->hub = -1; dev->port = -1; - usb_debug("rh init done\n"); + const int num_ports = /* TODO: maybe we need to read extended caps */ + (XHCI_INST(dev->controller)->capreg->hcsparams1 >> 24) & 0xff; + generic_hub_init(dev, num_ports, &xhci_rh_ops); + + usb_debug("xHCI: root hub init done\n"); } diff --git a/payloads/libpayload/drivers/video/corebootfb.c b/payloads/libpayload/drivers/video/corebootfb.c index faf9e2c0f8..1a38c4cb08 100644 --- a/payloads/libpayload/drivers/video/corebootfb.c +++ b/payloads/libpayload/drivers/video/corebootfb.c @@ -244,10 +244,6 @@ static int corebootfb_init(void) // clear boot splash screen if there is one. corebootfb_clear(); - - corebootfb_set_cursor(0, 0); - corebootfb_enable_cursor(1); - return 0; } diff --git a/payloads/libpayload/drivers/video/video.c b/payloads/libpayload/drivers/video/video.c index b8fe5d9687..5f76a3075a 100644 --- a/payloads/libpayload/drivers/video/video.c +++ b/payloads/libpayload/drivers/video/video.c @@ -31,27 +31,27 @@ #include #include -#ifdef CONFIG_GEODELX_VIDEO_CONSOLE +#ifdef CONFIG_LP_GEODELX_VIDEO_CONSOLE extern struct video_console geodelx_video_console; #endif -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE extern struct video_console coreboot_video_console; #endif -#ifdef CONFIG_VGA_VIDEO_CONSOLE +#ifdef CONFIG_LP_VGA_VIDEO_CONSOLE extern struct video_console vga_video_console; #endif static struct video_console *console_list[] = { -#ifdef CONFIG_GEODELX_VIDEO_CONSOLE +#ifdef CONFIG_LP_GEODELX_VIDEO_CONSOLE &geodelx_video_console, #endif -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE &coreboot_video_console, #endif -#ifdef CONFIG_VGA_VIDEO_CONSOLE +#ifdef CONFIG_LP_VGA_VIDEO_CONSOLE &vga_video_console, #endif }; @@ -60,7 +60,6 @@ static struct video_console *console; static int cursorx; static int cursory; -static unsigned int cursor_enabled = 1; void video_get_rows_cols(unsigned int *rows, unsigned int *cols) { @@ -74,7 +73,7 @@ void video_get_rows_cols(unsigned int *rows, unsigned int *cols) static void video_console_fixup_cursor(void) { - if (!cursor_enabled) + if (!console) return; if (cursorx < 0) @@ -93,7 +92,7 @@ static void video_console_fixup_cursor(void) cursory--; } - if (console && console->set_cursor) + if (console->set_cursor) console->set_cursor(cursorx, cursory); } @@ -101,11 +100,6 @@ void video_console_cursor_enable(int state) { if (console && console->enable_cursor) console->enable_cursor(state); - - cursor_enabled = state; - - if (cursor_enabled) - video_console_fixup_cursor(); } void video_console_clear(void) @@ -128,6 +122,9 @@ void video_console_putc(u8 row, u8 col, unsigned int ch) void video_console_putchar(unsigned int ch) { + if (!console) + return; + /* replace black-on-black with light-gray-on-black. * do it here, instead of in libc/console.c */ @@ -141,6 +138,7 @@ void video_console_putchar(unsigned int ch) break; case '\n': + cursorx = 0; cursory++; break; @@ -153,16 +151,11 @@ void video_console_putchar(unsigned int ch) break; case '\t': - while(cursorx % 8 && cursorx < console->columns) { - if (console) - console->putc(cursory, cursorx, (ch & 0xFF00) | ' '); - - cursorx++; - } + while(cursorx % 8 && cursorx < console->columns) + console->putc(cursory, cursorx++, (ch & 0xFF00) | ' '); break; default: - if (console) - console->putc(cursory, cursorx++, ch); + console->putc(cursory, cursorx++, ch); break; } @@ -175,7 +168,7 @@ void video_console_get_cursor(unsigned int *x, unsigned int *y, unsigned int *en *y=0; *en=0; - if (console->get_cursor) + if (console && console->get_cursor) console->get_cursor(x, y, en); *x = cursorx; @@ -196,6 +189,7 @@ static struct console_output_driver cons = { int video_init(void) { int i; + unsigned int dummy_cursor_enabled; for (i = 0; i < ARRAY_SIZE(console_list); i++) { if (console_list[i]->init()) @@ -206,7 +200,7 @@ int video_init(void) if (console->get_cursor) console->get_cursor((unsigned int*)&cursorx, (unsigned int*)&cursory, - &cursor_enabled); + &dummy_cursor_enabled); if (cursorx) { cursorx = 0; @@ -221,9 +215,10 @@ int video_init(void) int video_console_init(void) { - video_init(); - if (console) - console_add_output_driver(&cons); + int ret = video_init(); + if (ret) + return ret; + console_add_output_driver(&cons); return 0; } diff --git a/payloads/libpayload/gdb/Makefile.inc b/payloads/libpayload/gdb/Makefile.inc new file mode 100644 index 0000000000..cacd0d02f3 --- /dev/null +++ b/payloads/libpayload/gdb/Makefile.inc @@ -0,0 +1,20 @@ +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation; either version 2 of +## the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but without any warranty; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +libgdb-y += commands.c +libgdb-y += stub.c +libgdb-y += transport.c diff --git a/payloads/libpayload/gdb/commands.c b/payloads/libpayload/gdb/commands.c new file mode 100644 index 0000000000..5137dfd9f5 --- /dev/null +++ b/payloads/libpayload/gdb/commands.c @@ -0,0 +1,101 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static void gdb_get_last_signal(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + gdb_message_add_string(reply, "S"); + gdb_message_encode_bytes(reply, &gdb_state.signal, 1); +} + +static void gdb_read_general_registers(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + gdb_arch_encode_regs(reply); +} + +static void gdb_write_general_registers(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + gdb_arch_decode_regs(offset, command); + gdb_message_add_string(reply, "OK"); +} + +static void gdb_read_memory(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + int tok = gdb_message_tokenize(command, &offset); + uintptr_t addr = gdb_message_decode_int(command, tok, offset - 1 - tok); + size_t length = gdb_message_decode_int(command, offset, + command->used - offset); + + gdb_message_encode_bytes(reply, (void *)addr, length); +} + +static void gdb_write_memory(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + int tok = gdb_message_tokenize(command, &offset); + uintptr_t addr = gdb_message_decode_int(command, tok, offset - 1 - tok); + tok = gdb_message_tokenize(command, &offset); + size_t length = gdb_message_decode_int(command, tok, offset - 1 - tok); + + die_if(length * 2 != command->used - offset, "Invalid length field in " + "GDB command: %.*s", command->used, command->buf); + + gdb_message_decode_bytes(command, offset, (void *)addr, length); + cache_sync_instructions(); + gdb_message_add_string(reply, "OK"); +} + +static void gdb_continue(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + /* Disable single step if it's still on. */ + gdb_arch_set_single_step(0); + + /* No need to support the extension that passes in new EIP/PC. */ + if (command->used > offset) + gdb_message_add_string(reply, "E00"); + else + gdb_state.resumed = 1; +} + +static void gdb_single_step(struct gdb_message *command, + int offset, struct gdb_message *reply) +{ + if (command->used > offset || gdb_arch_set_single_step(1)) + gdb_message_add_string(reply, "E00"); + else + gdb_state.resumed = 1; +} + +struct gdb_command gdb_commands[] = { + { "?", &gdb_get_last_signal }, + { "g", &gdb_read_general_registers }, + { "G", &gdb_write_general_registers }, + { "m", &gdb_read_memory }, + { "M", &gdb_write_memory }, + { "c", &gdb_continue }, + { "s", &gdb_single_step } +}; +const int gdb_command_count = ARRAY_SIZE(gdb_commands); diff --git a/payloads/libpayload/gdb/stub.c b/payloads/libpayload/gdb/stub.c new file mode 100644 index 0000000000..73afa70c47 --- /dev/null +++ b/payloads/libpayload/gdb/stub.c @@ -0,0 +1,124 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +struct gdb_state gdb_state; + +static u8 reply_buf[2048]; +static u8 command_buf[2048]; + +static struct gdb_message command = { + .buf = command_buf, + .used = 0, + .size = sizeof(command_buf), +}; +static struct gdb_message reply = { + .buf = reply_buf, + .used = 0, + .size = sizeof(reply_buf), +}; + +void gdb_command_loop(u8 signal) +{ + if (gdb_state.resumed) { + /* We were just running. Send a stop reply. */ + reply.used = 0; + gdb_message_add_string(&reply, "S"); + gdb_message_encode_bytes(&reply, &signal, 1); + gdb_send_reply(&reply); + + } + gdb_state.signal = signal; + gdb_state.resumed = 0; + gdb_state.connected = 1; + + while (1) { + int i; + + gdb_get_command(&command); + + reply.used = 0; + for (i = 0; i < gdb_command_count; i++) { + int clen = strlen(gdb_commands[i].str); + if (!strncmp(gdb_commands[i].str, (char *)command.buf, + MIN(clen, command.used))) { + gdb_commands[i].handler(&command, clen, &reply); + break; + } + } + + /* If we're resuming, we won't send a reply until we stop. */ + if (gdb_state.resumed) + return; + + gdb_send_reply(&reply); + } +} + +static void gdb_output_write(const void *buffer, size_t count) +{ + if (!gdb_state.resumed) { + /* Must be a die_if() in GDB (or a bug), so bail out and die. */ + gdb_exit(-1); + video_console_init(); + puts("GDB died, redirecting its last words to the screen:\n"); + console_write(buffer, count); + } else { + reply.used = 0; + reply.buf[reply.used++] = 'O'; + gdb_message_encode_bytes(&reply, buffer, count); + gdb_send_reply(&reply); + } +} + +static struct console_output_driver gdb_output_driver = { + .write = &gdb_output_write +}; + +static void gdb_init(void) +{ + printf("Ready for GDB connection.\n"); + gdb_transport_init(); + gdb_arch_init(); + console_add_output_driver(&gdb_output_driver); +} + +void gdb_enter(void) +{ + if (!gdb_state.connected) + gdb_init(); + gdb_arch_enter(); +} + +void gdb_exit(s8 exit_status) +{ + if (!gdb_state.connected) + return; + + reply.used = 0; + gdb_message_add_string(&reply, "W"); + gdb_message_encode_bytes(&reply, &exit_status, 1); + gdb_send_reply(&reply); + + console_remove_output_driver(&gdb_output_write); + gdb_transport_teardown(); + gdb_state.connected = 0; + printf("Detached from GDB connection.\n"); +} diff --git a/payloads/libpayload/gdb/transport.c b/payloads/libpayload/gdb/transport.c new file mode 100644 index 0000000000..22983e1bc0 --- /dev/null +++ b/payloads/libpayload/gdb/transport.c @@ -0,0 +1,252 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +/* MMIO word size is not standardized, but *usually* 32 (even on ARM64) */ +typedef u32 mmio_word_t; + +static const int timeout_us = 100 * 1000; +static const char output_overrun[] = "GDB output buffer overrun (try " + "increasing reply.size)!\n"; +static const char input_underrun[] = "GDB input message truncated (bug or " + "communication problem)?\n"; + +/* Serial-specific glue code... add more transport layers here when desired. */ + +static void gdb_raw_putchar(u8 c) +{ + serial_putchar(c); +} + +static int gdb_raw_getchar(void) +{ + u64 start = timer_us(0); + + while (!serial_havechar()) + if (timer_us(start) > timeout_us) + return -1; + + return serial_getchar(); +} + +void gdb_transport_init(void) +{ + console_remove_output_driver(serial_putchar); +} + +void gdb_transport_teardown(void) +{ + serial_console_init(); +} + +/* Hex digit character <-> number conversion (illegal chars undefined!). */ + +static u8 from_hex(unsigned char c) +{ + static const s8 values[] = { + -1, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + }; + + return values[c & 0x1f]; +} + +static char to_hex(u8 v) +{ + static const char digits[] = "0123456789abcdef"; + + return digits[v & 0xf]; +} + +/* Message encode/decode functions (must access whole aligned words for MMIO) */ + +void gdb_message_encode_bytes(struct gdb_message *message, const void *data, + int length) +{ + die_if(message->used + length * 2 > message->size, output_overrun); + const mmio_word_t *aligned = + (mmio_word_t *)ALIGN_DOWN((uintptr_t)data, sizeof(*aligned)); + mmio_word_t word = be32toh(readl(aligned++)); + while (length--) { + u8 byte = (word >> ((((void *)aligned - data) - 1) * 8)); + message->buf[message->used++] = to_hex(byte >> 4); + message->buf[message->used++] = to_hex(byte & 0xf); + if (length && ++data == (void *)aligned) + word = be32toh(readl(aligned++)); + } +} + +void gdb_message_decode_bytes(const struct gdb_message *message, int offset, + void *data, int length) +{ + die_if(offset + 2 * length > message->used, "Decode overrun in GDB " + "message: %.*s", message->used, message->buf); + mmio_word_t *aligned = + (mmio_word_t *)ALIGN_DOWN((uintptr_t)data, sizeof(*aligned)); + int shift = ((void *)(aligned + 1) - data) * 8; + mmio_word_t word = be32toh(readl(aligned)) >> shift; + while (length--) { + word <<= 8; + word |= from_hex(message->buf[offset++]) << 4; + word |= from_hex(message->buf[offset++]); + if (++data - (void *)aligned == sizeof(*aligned)) + writel(htobe32(word), aligned++); + } + if (data != (void *)aligned) { + shift = ((void *)(aligned + 1) - data) * 8; + clrsetbits_be32(aligned, ~((1 << shift) - 1), word << shift); + } +} + +void gdb_message_encode_zero_bytes(struct gdb_message *message, int length) +{ + die_if(message->used + length * 2 > message->size, output_overrun); + memset(message->buf + message->used, '0', length * 2); + message->used += length * 2; +} + +void gdb_message_add_string(struct gdb_message *message, const char *string) +{ + message->used += strlcpy((char *)message->buf + message->used, + string, message->size - message->used); + + /* Check >= instead of > to account for strlcpy's trailing '\0'. */ + die_if(message->used >= message->size, output_overrun); +} + +void gdb_message_encode_int(struct gdb_message *message, uintptr_t val) +{ + int length = sizeof(uintptr_t) * 2 - __builtin_clz(val) / 4; + die_if(message->used + length > message->size, output_overrun); + while (length--) + message->buf[message->used++] = + to_hex((val >> length * 4) & 0xf); +} + +uintptr_t gdb_message_decode_int(const struct gdb_message *message, int offset, + int length) +{ + uintptr_t val = 0; + + die_if(length > sizeof(uintptr_t) * 2, "GDB decoding invalid number: " + "%.*s", message->used, message->buf); + + while (length--) { + val <<= 4; + val |= from_hex(message->buf[offset++]); + } + + return val; +} + +/* Like strtok/strsep: writes back offset argument, returns original offset. */ +int gdb_message_tokenize(const struct gdb_message *message, int *offset) +{ + int token = *offset; + while (!strchr(",;:", message->buf[(*offset)++])) + die_if(*offset >= message->used, "Undelimited token in GDB " + "message at offset %d: %.*s", + token, message->used, message->buf); + return token; +} + +/* High-level send/receive functions. */ + +void gdb_get_command(struct gdb_message *command) +{ + enum command_state { + STATE_WAITING, + STATE_COMMAND, + STATE_CHECKSUM0, + STATE_CHECKSUM1, + }; + + u8 checksum = 0; + u8 running_checksum = 0; + enum command_state state = STATE_WAITING; + + while (1) { + int c = gdb_raw_getchar(); + if (c < 0) { + /* + * Timeout waiting for a byte. Reset the + * state machine. + */ + state = STATE_WAITING; + continue; + } + + switch (state) { + case STATE_WAITING: + if (c == '$') { + running_checksum = 0; + command->used = 0; + state = STATE_COMMAND; + } + break; + case STATE_COMMAND: + if (c == '#') { + state = STATE_CHECKSUM0; + break; + } + die_if(command->used >= command->size, "GDB input buf" + "fer overrun (try increasing command.size)!\n"); + command->buf[command->used++] = c; + running_checksum += c; + break; + case STATE_CHECKSUM0: + checksum = from_hex(c) << 4; + state = STATE_CHECKSUM1; + break; + case STATE_CHECKSUM1: + checksum += from_hex(c); + if (running_checksum == checksum) { + gdb_raw_putchar('+'); + return; + } else { + state = STATE_WAITING; + gdb_raw_putchar('-'); + } + break; + } + } +} + +void gdb_send_reply(const struct gdb_message *reply) +{ + int i; + int retries = 1 * 1000 * 1000 / timeout_us; + u8 checksum = 0; + + for (i = 0; i < reply->used; i++) + checksum += reply->buf[i]; + + do { + gdb_raw_putchar('$'); + for (i = 0; i < reply->used; i++) + gdb_raw_putchar(reply->buf[i]); + gdb_raw_putchar('#'); + gdb_raw_putchar(to_hex(checksum >> 4)); + gdb_raw_putchar(to_hex(checksum & 0xf)); + } while (gdb_raw_getchar() != '+' && retries--); +} diff --git a/payloads/libpayload/include/arm/arch/asm.h b/payloads/libpayload/include/arm/arch/asm.h new file mode 100644 index 0000000000..7bf2aa8974 --- /dev/null +++ b/payloads/libpayload/include/arm/arch/asm.h @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_ASM_H +#define __ARM_ASM_H + +/* __arm__ is defined regardless of Thumb mode, so need to order this right */ +#if defined __thumb2__ +# define ARM(x...) +# define THUMB(x...) x +# define W(instr) instr.w +#elif defined __thumb__ +# error You are not compiling Thumb2, this won't work! +#else +# define ARM(x...) x +# define THUMB(x...) +# define W(instr) instr +#endif + +#define ALIGN .align 0 + +#define ENDPROC(name) \ + .type name, %function; \ + END(name) + +#define ENTRY(name) \ + .section .text.name, "ax", %progbits; \ + .global name; \ + ALIGN; \ + name: + +#define END(name) \ + .size name, .-name + +/* Thumb code uses the (new) unified assembly syntax. */ +THUMB( .syntax unified ) + +#endif /* __ARM_ASM_H */ diff --git a/payloads/libpayload/include/arm/arch/barrier.h b/payloads/libpayload/include/arm/arch/barrier.h new file mode 100644 index 0000000000..fde55fa3c9 --- /dev/null +++ b/payloads/libpayload/include/arm/arch/barrier.h @@ -0,0 +1,66 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (C) 2003-2004 Olivier Houchard + * Copyright (C) 1994-1997 Mark Brinicombe + * Copyright (C) 1994 Brini + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef __ARCH_BARRIER_H_ +#define __ARCH_BARRIER_H__ + +#include + +/* + * Description of different memory barriers introduced: + * + * Memory barrier(mb) - Guarantees that all memory accesses specified before the + * barrier will happen before all memory accesses specified after the barrier + * + * Read memory barrier (rmb) - Guarantees that all read memory accesses + * specified before the barrier will happen before all read memory accesses + * specified after the barrier + * + * Write memory barrier (wmb) - Guarantees that all write memory accesses + * specified before the barrier will happen before all write memory accesses + * specified after the barrier + */ + +/* + * According to ARM Reference Manual (ARMv7-A), by default dmb ensures: + * Full system is the required shareability domain + * Reads and writes are the required access types. + */ +#define mb() dmb() +#define rmb() dmb() +#define wmb() dmb() + +#endif /* __ARCH_BARRIER_H__ */ diff --git a/src/arch/armv7/include/arch/cache.h b/payloads/libpayload/include/arm/arch/cache.h similarity index 72% rename from src/arch/armv7/include/arch/cache.h rename to payloads/libpayload/include/arm/arch/cache.h index 1db86dc57c..b258185b9b 100644 --- a/src/arch/armv7/include/arch/cache.h +++ b/payloads/libpayload/include/arm/arch/cache.h @@ -26,11 +26,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * cache.h: Cache maintenance API for ARMv7 + * cache.h: Cache maintenance API for ARM */ -#ifndef ARMV7_CACHE_H -#define ARMV7_CACHE_H +#ifndef ARM_CACHE_H +#define ARM_CACHE_H + +#include +#include /* SCTLR bits */ #define SCTLR_M (1 << 0) /* MMU enable */ @@ -67,47 +70,29 @@ /* * Sync primitives */ - /* data memory barrier */ -static inline void dmb(void) -{ - asm volatile ("dmb" : : : "memory"); -} - +#define dmb() asm volatile ("dmb" : : : "memory") /* data sync barrier */ -static inline void dsb(void) -{ - asm volatile ("dsb" : : : "memory"); -} - +#define dsb() asm volatile ("dsb" : : : "memory") /* instruction sync barrier */ -static inline void isb(void) -{ - asm volatile ("isb" : : : "memory"); -} +#define isb() asm volatile ("isb" : : : "memory") /* * Low-level TLB maintenance operations */ -/* invalidate entire data TLB */ -static inline void dtlbiall(void) -{ - asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0) : "memory"); -} - -/* invalidate entire instruction TLB */ -static inline void itlbiall(void) -{ - asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); -} - /* invalidate entire unified TLB */ static inline void tlbiall(void) { asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0) : "memory"); } +/* invalidate unified TLB by MVA, all ASID */ +static inline void tlbimvaa(unsigned long mva) +{ + asm volatile ("mcr p15, 0, %0, c8, c7, 3" : : "r" (mva) : "memory"); +} + /* write data access control register (DACR) */ static inline void write_dacr(uint32_t val) { @@ -120,6 +105,15 @@ static inline void write_ttbr0(uint32_t val) asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (val) : "memory"); } +/* read translation table base register 0 (TTBR0) */ +static inline uint64_t read_ttbr0(void) +{ + uint32_t low, high; + asm volatile ("mrrc p15, 0, %[low], %[high], c2" : + [low] "=r" (low), [high] "=r" (high)); + return ((uint64_t)high << 32) | low; +} + /* read translation table base control register (TTBCR) */ static inline uint32_t read_ttbcr(void) { @@ -162,6 +156,12 @@ static inline void dccmvac(unsigned long mva) asm volatile ("mcr p15, 0, %0, c7, c10, 1" : : "r" (mva) : "memory"); } +/* data cache clean by set/way */ +static inline void dccsw(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c7, c10, 2" : : "r" (val) : "memory"); +} + /* data cache invalidate by MVA to PoC */ static inline void dcimvac(unsigned long mva) { @@ -238,6 +238,21 @@ static inline void write_l2ctlr(uint32_t val) isb(); } +/* read L2 Auxiliary Control Register (L2ACTLR) */ +static inline uint32_t read_l2actlr(void) +{ + uint32_t val = 0; + asm volatile ("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); + return val; +} + +/* write L2 Auxiliary Control Register (L2ACTLR) */ +static inline void write_l2actlr(uint32_t val) +{ + asm volatile ("mcr p15, 1, %0, c15, c0, 0" : : "r" (val) : "memory" ); + isb(); +} + /* read system control register (SCTLR) */ static inline uint32_t read_sctlr(void) { @@ -253,6 +268,54 @@ static inline void write_sctlr(uint32_t val) isb(); } +/* read data fault address register (DFAR) */ +static inline uint32_t read_dfar(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c6, c0, 0" : "=r" (val)); + return val; +} + +/* read data fault status register (DFSR) */ +static inline uint32_t read_dfsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r" (val)); + return val; +} + +/* read instruction fault address register (IFAR) */ +static inline uint32_t read_ifar(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c6, c0, 2" : "=r" (val)); + return val; +} + +/* read instruction fault status register (IFSR) */ +static inline uint32_t read_ifsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c0, 1" : "=r" (val)); + return val; +} + +/* read auxiliary data fault status register (ADFSR) */ +static inline uint32_t read_adfsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c1, 0" : "=r" (val)); + return val; +} + +/* read auxiliary instruction fault status register (AIFSR) */ +static inline uint32_t read_aifsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c1, 1" : "=r" (val)); + return val; +} + /* * Cache maintenance API */ @@ -261,22 +324,30 @@ static inline void write_sctlr(uint32_t val) void dcache_clean_invalidate_all(void); /* dcache clean by modified virtual address to PoC */ -void dcache_clean_by_mva(unsigned long addr, unsigned long len); +void dcache_clean_by_mva(void const *addr, size_t len); /* dcache clean and invalidate by modified virtual address to PoC */ -void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len); +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate by modified virtual address to PoC */ +void dcache_invalidate_by_mva(void const *addr, size_t len); + +void dcache_clean_all(void); /* dcache invalidate all (on current level given by CCSELR) */ void dcache_invalidate_all(void); +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + /* dcache and MMU disable */ void dcache_mmu_disable(void); /* dcache and MMU enable */ void dcache_mmu_enable(void); -/* icache invalidate all (on current level given by CSSELR) */ -void icache_invalidate_all(void); +/* perform all icache/dcache maintenance needed after loading new code */ +void cache_sync_instructions(void); /* tlb invalidate all */ void tlb_invalidate_all(void); @@ -285,9 +356,6 @@ void tlb_invalidate_all(void); * Generalized setup/init functions */ -/* invalidate all caches on ARMv7 */ -void armv7_invalidate_caches(void); - /* mmu initialization (set page table address, set permissions, etc) */ void mmu_init(void); @@ -297,8 +365,10 @@ enum dcache_policy { DCACHE_WRITETHROUGH, }; +/* disable the mmu for a range. Primarily useful to lock out address 0. */ +void mmu_disable_range(unsigned long start_mb, unsigned long size_mb); /* mmu range configuration (set dcache policy) */ void mmu_config_range(unsigned long start_mb, unsigned long size_mb, enum dcache_policy policy); -#endif /* ARMV7_CACHE_H */ +#endif /* ARM_CACHE_H */ diff --git a/payloads/libpayload/include/armv7/arch/io.h b/payloads/libpayload/include/arm/arch/exception.h similarity index 74% rename from payloads/libpayload/include/armv7/arch/io.h rename to payloads/libpayload/include/arm/arch/exception.h index 807dc1d2fb..fbbce5ed3d 100644 --- a/payloads/libpayload/include/armv7/arch/io.h +++ b/payloads/libpayload/include/arm/arch/exception.h @@ -1,8 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2008 coresystems GmbH + * Copyright 2013 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,15 +27,33 @@ * SUCH DAMAGE. */ -#ifndef _ARCH_IO_H -#define _ARCH_IO_H +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H -#define readb(_a) (*(volatile unsigned char *) (_a)) -#define readw(_a) (*(volatile unsigned short *) (_a)) -#define readl(_a) (*(volatile unsigned int *) (_a)) +#include -#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v)) -#define writew(_v, _a) (*(volatile unsigned short *) (_a) = (_v)) -#define writel(_v, _a) (*(volatile unsigned int *) (_a) = (_v)) +void exception_dispatch(u32 idx); +void set_vbar(uint32_t vbar); + +struct exception_state +{ + u32 regs[16]; + u32 cpsr; +} __attribute__((packed)); +extern struct exception_state exception_state; + +extern u32 exception_stack[]; +extern u32 *exception_stack_end; +extern struct exception_state *exception_state_ptr; + +enum { + EXC_UNDEF = 1, + EXC_SWI = 2, + EXC_PABORT = 3, + EXC_DABORT = 4, + EXC_IRQ = 6, + EXC_FIQ = 7, + EXC_COUNT +}; #endif diff --git a/payloads/libpayload/include/arm/arch/io.h b/payloads/libpayload/include/arm/arch/io.h new file mode 100644 index 0000000000..4b0a687c7b --- /dev/null +++ b/payloads/libpayload/include/arm/arch/io.h @@ -0,0 +1,77 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARCH_IO_H +#define _ARCH_IO_H + +#include +#include + +static inline uint8_t readb(volatile const void *_a) +{ + dmb(); + return *(volatile const uint8_t *)_a; +} + +static inline uint16_t readw(volatile const void *_a) +{ + dmb(); + return *(volatile const uint16_t *)_a; +} + +static inline uint32_t readl(volatile const void *_a) +{ + dmb(); + return *(volatile const uint32_t *)_a; +} + +static inline void writeb(uint8_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint8_t *)_a = _v; + dmb(); +} + +static inline void writew(uint16_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint16_t *)_a = _v; + dmb(); +} + +static inline void writel(uint32_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint32_t *)_a = _v; + dmb(); +} + +#endif + diff --git a/payloads/libpayload/include/powerpc/arch/types.h b/payloads/libpayload/include/arm/arch/types.h similarity index 100% rename from payloads/libpayload/include/powerpc/arch/types.h rename to payloads/libpayload/include/arm/arch/types.h diff --git a/payloads/libpayload/include/powerpc/arch/virtual.h b/payloads/libpayload/include/arm/arch/virtual.h similarity index 93% rename from payloads/libpayload/include/powerpc/arch/virtual.h rename to payloads/libpayload/include/arm/arch/virtual.h index 328c3aa34e..e51530d252 100644 --- a/payloads/libpayload/include/powerpc/arch/virtual.h +++ b/payloads/libpayload/include/arm/arch/virtual.h @@ -30,6 +30,8 @@ #ifndef _ARCH_VIRTUAL_H #define _ARCH_VIRTUAL_H +#include + extern unsigned long virtual_offset; #define virt_to_phys(virt) ((unsigned long) (virt) + virtual_offset) @@ -38,4 +40,7 @@ extern unsigned long virtual_offset; #define virt_to_bus(addr) virt_to_phys(addr) #define bus_to_virt(addr) phys_to_virt(addr) +void *lpae_map_phys_addr(unsigned long pa_mb, enum dcache_policy policy); +void lpae_restore_map(void); + #endif diff --git a/payloads/libpayload/include/arm64/arch/asm.h b/payloads/libpayload/include/arm64/arch/asm.h new file mode 100644 index 0000000000..de44482793 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/asm.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + */ + +#ifndef __ARM64_ASM_H +#define __ARM64_ASM_H + +# define ARM64(x...) x +# define W(instr) instr + +#define ALIGN .align 2 + +#define ENDPROC(name) \ + .type name, %function; \ + END(name) + +#define ENTRY(name) \ + .section .text.name, "ax", %progbits; \ + .global name; \ + ALIGN; \ + name: + +#define END(name) \ + .size name, .-name + +#endif /* __ARM64_ASM_H */ diff --git a/payloads/libpayload/include/arm64/arch/barrier.h b/payloads/libpayload/include/arm64/arch/barrier.h new file mode 100644 index 0000000000..de1b165aa1 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/barrier.h @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (C) 2003-2004 Olivier Houchard + * Copyright (C) 1994-1997 Mark Brinicombe + * Copyright (C) 1994 Brini + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef __ARCH_BARRIER_H_ +#define __ARCH_BARRIER_H__ + +#include + +/* + * Description of different memory barriers introduced: + * + * Memory barrier(mb) - Guarantees that all memory accesses specified before the + * barrier will happen before all memory accesses specified after the barrier + * + * Read memory barrier (rmb) - Guarantees that all read memory accesses + * specified before the barrier will happen before all read memory accesses + * specified after the barrier + * + * Write memory barrier (wmb) - Guarantees that all write memory accesses + * specified before the barrier will happen before all write memory accesses + * specified after the barrier + */ + +/* + * According to ARMv8 Instruction Set Overview: + * Options specified to dmb instruction have the following meaning: + * Option Ordered accesses + * sy any-any + * ld load-load, load-store + * st store-store + */ + +#define mb() dmb_opt(sy) +#define rmb() dmb_opt(ld) +#define wmb() dmb_opt(st) + +#endif /* __ARCH_BARRIER_H__ */ diff --git a/payloads/libpayload/include/arm64/arch/cache.h b/payloads/libpayload/include/arm64/arch/cache.h new file mode 100644 index 0000000000..cfd3109559 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/cache.h @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.h: Cache maintenance API for ARM64 + */ + +#ifndef ARM64_CACHE_H +#define ARM64_CACHE_H + +#include +#include + +/* SCTLR bits */ +#define SCTLR_M (1 << 0) /* MMU enable */ +#define SCTLR_A (1 << 1) /* Alignment check enable */ +#define SCTLR_C (1 << 2) /* Data/unified cache enable */ +/* Bits 4:3 are reserved */ +#define SCTLR_CP15BEN (1 << 5) /* CP15 barrier enable */ +/* Bit 6 is reserved */ +#define SCTLR_B (1 << 7) /* Endianness */ +/* Bits 9:8 */ +#define SCTLR_SW (1 << 10) /* SWP and SWPB enable */ +#define SCTLR_Z (1 << 11) /* Branch prediction enable */ +#define SCTLR_I (1 << 12) /* Instruction cache enable */ +#define SCTLR_V (1 << 13) /* Low/high exception vectors */ +#define SCTLR_RR (1 << 14) /* Round Robin select */ +/* Bits 16:15 are reserved */ +#define SCTLR_HA (1 << 17) /* Hardware Access flag enable */ +/* Bit 18 is reserved */ +/* Bits 20:19 reserved virtualization not supported */ +#define SCTLR_WXN (1 << 19) /* Write permission implies XN */ +#define SCTLR_UWXN (1 << 20) /* Unprivileged write permission + implies PL1 XN */ +#define SCTLR_FI (1 << 21) /* Fast interrupt config enable */ +#define SCTLR_U (1 << 22) /* Unaligned access behavior */ +#define SCTLR_VE (1 << 24) /* Interrupt vectors enable */ +#define SCTLR_EE (1 << 25) /* Exception endianness */ +/* Bit 26 is reserved */ +#define SCTLR_NMFI (1 << 27) /* Non-maskable FIQ support */ +#define SCTLR_TRE (1 << 28) /* TEX remap enable */ +#define SCTLR_AFE (1 << 29) /* Access flag enable */ +#define SCTLR_TE (1 << 30) /* Thumb exception enable */ +/* Bit 31 is reserved */ + +/* + * Cache maintenance API + */ + +/* dcache clean and invalidate all (on current level given by CCSELR) */ +void dcache_clean_invalidate_all(void); + +/* dcache clean by virtual address to PoC */ +void dcache_clean_by_mva(void const *addr, size_t len); + +/* dcache clean and invalidate by virtual address to PoC */ +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate by virtual address to PoC */ +void dcache_invalidate_by_mva(void const *addr, size_t len); + +void dcache_clean_all(void); + +/* dcache invalidate all (on current level given by CCSELR) */ +void dcache_invalidate_all(void); + +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + +/* dcache and MMU disable */ +void dcache_mmu_disable(void); + +/* dcache and MMU enable */ +void dcache_mmu_enable(void); + +/* perform all icache/dcache maintenance needed after loading new code */ +void cache_sync_instructions(void); + +/* tlb invalidate all */ +void tlb_invalidate_all(void); + +/* + * Generalized setup/init functions + */ + +enum dcache_policy { + DCACHE_OFF, + DCACHE_WRITEBACK, + DCACHE_WRITETHROUGH, +}; + +/* disable the mmu for a range. Primarily useful to lock out address 0. */ +void mmu_disable_range(unsigned long start_mb, unsigned long size_mb); +/* mmu range configuration (set dcache policy) */ +void mmu_config_range(unsigned long start_mb, unsigned long size_mb, + enum dcache_policy policy); + +#endif /* ARM64_CACHE_H */ diff --git a/payloads/libpayload/include/arm64/arch/exception.h b/payloads/libpayload/include/arm64/arch/exception.h new file mode 100644 index 0000000000..f5026f8402 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/exception.h @@ -0,0 +1,66 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H + +#include + +void set_vbar(void* vbar); + +struct exception_state +{ + uint64_t elr; + uint64_t esr; + uint64_t regs[31]; +} __attribute__((packed)); + +extern struct exception_state *exception_state; + +enum { + EXC_SYNC_SP0 = 0, + EXC_IRQ_SP0, + EXC_FIQ_SP0, + EXC_SERROR_SP0, + EXC_SYNC_SPX, + EXC_IRQ_SPX, + EXC_FIQ_SPX, + EXC_SERROR_SPX, + EXC_SYNC_ELX_64, + EXC_IRQ_ELX_64, + EXC_FIQ_ELX_64, + EXC_SERROR_ELX_64, + EXC_SYNC_ELX_32, + EXC_IRQ_ELX_32, + EXC_FIQ_ELX_32, + EXC_SERROR_ELX_32, + EXC_COUNT +}; + +#endif diff --git a/payloads/libpayload/include/arm64/arch/io.h b/payloads/libpayload/include/arm64/arch/io.h new file mode 100644 index 0000000000..f8be1aec95 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/io.h @@ -0,0 +1,77 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARCH_IO_H +#define _ARCH_IO_H + +#include +#include +#include + +static inline uint8_t readb(volatile const void *_a) +{ + dmb(); + return *(volatile const uint8_t *)_a; +} + +static inline uint16_t readw(volatile const void *_a) +{ + dmb(); + return *(volatile const uint16_t *)_a; +} + +static inline uint32_t readl(volatile const void *_a) +{ + dmb(); + return *(volatile const uint32_t *)_a; +} + +static inline void writeb(uint8_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint8_t *)_a = _v; + dmb(); +} + +static inline void writew(uint16_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint16_t *)_a = _v; + dmb(); +} + +static inline void writel(uint32_t _v, volatile void *_a) +{ + dmb(); + *(volatile uint32_t *)_a = _v; + dmb(); +} + +#endif diff --git a/payloads/libpayload/include/arm64/arch/lib_helpers.h b/payloads/libpayload/include/arm64/arch/lib_helpers.h new file mode 100644 index 0000000000..d98d6f7d6b --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/lib_helpers.h @@ -0,0 +1,378 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * lib_helpers.h: All library function prototypes and macros are defined in this + * file. + */ + +#ifndef __ARCH_LIB_HELPERS_H__ +#define __ARCH_LIB_HELPERS_H__ + +#ifdef __ASSEMBLY__ + +/* Macro to switch to label based on current el */ +.macro switch_el xreg label1 label2 label3 + mrs \xreg, CurrentEL + /* Currently at EL1 */ + cmp \xreg, 0x4 + b.eq \label1 + /* Currently at EL2 */ + cmp \xreg, 0x8 + b.eq \label2 + /* Currently at EL3 */ + cmp \xreg, 0xc + b.eq \label3 +.endm + +/* Macro to read sysreg at current EL + xreg - reg in which read value needs to be stored + sysreg - system reg that is to be read +*/ +.macro read_current xreg sysreg + switch_el \xreg, 101f, 102f, 103f +101: + mrs \xreg, \sysreg\()_el1 + b 104f +102: + mrs \xreg, \sysreg\()_el2 + b 104f +103: + mrs \xreg, \sysreg\()_el3 + b 104f +104: +.endm + +/* Macro to write sysreg at current EL + xreg - reg from which value needs to be written + sysreg - system reg that is to be written + temp - temp reg that can be used to read current EL +*/ +.macro write_current sysreg xreg temp + switch_el \temp, 101f, 102f, 103f +101: + msr \sysreg\()_el1, \xreg + b 104f +102: + msr \sysreg\()_el2, \xreg + b 104f +103: + msr \sysreg\()_el3, \xreg + b 104f +104: +.endm + +#else + +#define EL0 0 +#define EL1 1 +#define EL2 2 +#define EL3 3 + +#define CURRENT_EL_MASK 0x3 +#define CURRENT_EL_SHIFT 2 + +#define DAIF_DBG_BIT (1<<3) +#define DAIF_ABT_BIT (1<<2) +#define DAIF_IRQ_BIT (1<<1) +#define DAIF_FIQ_BIT (1<<0) + +#define SWITCH_CASE_READ(func,var,type) do { \ + type var = -1; \ + uint8_t current_el = get_current_el(); \ + switch(current_el) { \ + case EL1: \ + var = func##_el1(); \ + break; \ + case EL2: \ + var = func##_el2(); \ + break; \ + case EL3: \ + var = func##_el3(); \ + break; \ + } \ + return var; \ + } while(0) + +#define SWITCH_CASE_WRITE(func,var) do { \ + uint8_t current_el = get_current_el(); \ + switch(current_el) { \ + case EL1: \ + func##_el1(var); \ + break; \ + case EL2: \ + func##_el2(var); \ + break; \ + case EL3: \ + func##_el3(var); \ + break; \ + } \ + } while(0) + +#define SWITCH_CASE_TLBI(func) do { \ + uint8_t current_el = get_current_el(); \ + switch(current_el) { \ + case EL1: \ + func##_el1(); \ + break; \ + case EL2: \ + func##_el2(); \ + break; \ + case EL3: \ + func##_el3(); \ + break; \ + } \ + } while(0) + +/* PSTATE and special purpose register access functions */ +uint32_t raw_read_current_el(void); +uint32_t get_current_el(void); +uint32_t raw_read_daif(void); +void raw_write_daif(uint32_t daif); +void enable_debug_exceptions(void); +void enable_serror_exceptions(void); +void enable_irq(void); +void enable_fiq(void); +void disable_debug_exceptions(void); +void disable_serror_exceptions(void); +void disable_irq(void); +void disable_fiq(void); +uint64_t raw_read_dlr_el0(void); +void raw_write_dlr_el0(uint64_t dlr_el0); +uint64_t raw_read_dspsr_el0(void); +void raw_write_dspsr_el0(uint64_t dspsr_el0); +uint64_t raw_read_elr_el1(void); +void raw_write_elr_el1(uint64_t elr_el1); +uint64_t raw_read_elr_el2(void); +void raw_write_elr_el2(uint64_t elr_el2); +uint64_t raw_read_elr_el3(void); +void raw_write_elr_el3(uint64_t elr_el3); +uint64_t raw_read_elr_current(void); +void raw_write_elr_current(uint64_t elr); +uint32_t raw_read_fpcr(void); +void raw_write_fpcr(uint32_t fpcr); +uint32_t raw_read_fpsr(void); +void raw_write_fpsr(uint32_t fpsr); +uint32_t raw_read_nzcv(void); +void raw_write_nzcv(uint32_t nzcv); +uint64_t raw_read_sp_el0(void); +void raw_write_sp_el0(uint64_t sp_el0); +uint64_t raw_read_sp_el1(void); +void raw_write_sp_el1(uint64_t sp_el1); +uint64_t raw_read_sp_el2(void); +void raw_write_sp_el2(uint64_t sp_el2); +uint32_t raw_read_spsel(void); +void raw_write_spsel(uint32_t spsel); +uint64_t raw_read_sp_el3(void); +void raw_write_sp_el3(uint64_t sp_el3); +uint32_t raw_read_spsr_abt(void); +void raw_write_spsr_abt(uint32_t spsr_abt); +uint32_t raw_read_spsr_el1(void); +void raw_write_spsr_el1(uint32_t spsr_el1); +uint32_t raw_read_spsr_el2(void); +void raw_write_spsr_el2(uint32_t spsr_el2); +uint32_t raw_read_spsr_el3(void); +void raw_write_spsr_el3(uint32_t spsr_el3); +uint32_t raw_read_spsr_current(void); +void raw_write_spsr_current(uint32_t spsr); +uint32_t raw_read_spsr_fiq(void); +void raw_write_spsr_fiq(uint32_t spsr_fiq); +uint32_t raw_read_spsr_irq(void); +void raw_write_spsr_irq(uint32_t spsr_irq); +uint32_t raw_read_spsr_und(void); +void raw_write_spsr_und(uint32_t spsr_und); + +/* System control register access */ +uint32_t raw_read_actlr_el1(void); +void raw_write_actlr_el1(uint32_t actlr_el1); +uint32_t raw_read_actlr_el2(void); +void raw_write_actlr_el2(uint32_t actlr_el2); +uint32_t raw_read_actlr_el3(void); +void raw_write_actlr_el3(uint32_t actlr_el3); +uint32_t raw_read_actlr_current(void); +void raw_write_actlr_current(uint32_t actlr); +uint32_t raw_read_afsr0_el1(void); +void raw_write_afsr0_el1(uint32_t afsr0_el1); +uint32_t raw_read_afsr0_el2(void); +void raw_write_afsr0_el2(uint32_t afsr0_el2); +uint32_t raw_read_afsr0_el3(void); +void raw_write_afsr0_el3(uint32_t afsr0_el3); +uint32_t raw_read_afsr0_current(void); +void raw_write_afsr0_current(uint32_t afsr0); +uint32_t raw_read_afsr1_el1(void); +void raw_write_afsr1_el1(uint32_t afsr1_el1); +uint32_t raw_read_afsr1_el2(void); +void raw_write_afsr1_el2(uint32_t afsr1_el2); +uint32_t raw_read_afsr1_el3(void); +void raw_write_afsr1_el3(uint32_t afsr1_el3); +uint32_t raw_read_afsr1_current(void); +void raw_write_afsr1_current(uint32_t afsr1); +uint32_t raw_read_aidr_el1(void); +uint64_t raw_read_amair_el1(void); +void raw_write_amair_el1(uint64_t amair_el1); +uint64_t raw_read_amair_el2(void); +void raw_write_amair_el2(uint64_t amair_el2); +uint64_t raw_read_amair_el3(void); +void raw_write_amair_el3(uint64_t amair_el3); +uint64_t raw_read_amair_current(void); +void raw_write_amair_current(uint64_t amair); +uint32_t raw_read_ccsidr_el1(void); +uint32_t raw_read_clidr_el1(void); +uint32_t raw_read_cpacr_el1(void); +void raw_write_cpacr_el1(uint32_t cpacr_el1); +uint32_t raw_read_cptr_el2(void); +void raw_write_cptr_el2(uint32_t cptr_el2); +uint32_t raw_read_cptr_el3(void); +void raw_write_cptr_el3(uint32_t cptr_el3); +uint32_t raw_read_cptr_current(void); +void raw_write_cptr_current(uint32_t cptr); +uint32_t raw_read_csselr_el1(void); +void raw_write_csselr_el1(uint32_t csselr_el1); +uint32_t raw_read_ctr_el0(void); +uint32_t raw_read_esr_el1(void); +void raw_write_esr_el1(uint32_t esr_el1); +uint32_t raw_read_esr_el2(void); +void raw_write_esr_el2(uint32_t esr_el2); +uint32_t raw_read_esr_el3(void); +void raw_write_esr_el3(uint32_t esr_el3); +uint32_t raw_read_esr_current(void); +void raw_write_esr_current(uint32_t esr); +uint64_t raw_read_far_el1(void); +void raw_write_far_el1(uint64_t far_el1); +uint64_t raw_read_far_el2(void); +void raw_write_far_el2(uint64_t far_el2); +uint64_t raw_read_far_el3(void); +void raw_write_far_el3(uint64_t far_el3); +uint64_t raw_read_far_current(void); +void raw_write_far_current(uint64_t far); +uint64_t raw_read_hcr_el2(void); +void raw_write_hcr_el2(uint64_t hcr_el2); +uint64_t raw_read_aa64pfr0_el1(void); +uint64_t raw_read_mair_el1(void); +void raw_write_mair_el1(uint64_t mair_el1); +uint64_t raw_read_mair_el2(void); +void raw_write_mair_el2(uint64_t mair_el2); +uint64_t raw_read_mair_el3(void); +void raw_write_mair_el3(uint64_t mair_el3); +uint64_t raw_read_mair_current(void); +void raw_write_mair_current(uint64_t mair); +uint64_t raw_read_mpidr_el1(void); +uint32_t raw_read_rmr_el1(void); +void raw_write_rmr_el1(uint32_t rmr_el1); +uint32_t raw_read_rmr_el2(void); +void raw_write_rmr_el2(uint32_t rmr_el2); +uint32_t raw_read_rmr_el3(void); +void raw_write_rmr_el3(uint32_t rmr_el3); +uint32_t raw_read_rmr_current(void); +void raw_write_rmr_current(uint32_t rmr); +uint64_t raw_read_rvbar_el1(void); +void raw_write_rvbar_el1(uint64_t rvbar_el1); +uint64_t raw_read_rvbar_el2(void); +void raw_write_rvbar_el2(uint64_t rvbar_el2); +uint64_t raw_read_rvbar_el3(void); +void raw_write_rvbar_el3(uint64_t rvbar_el3); +uint64_t raw_read_rvbar_current(void); +void raw_write_rvbar_current(uint64_t rvbar); +uint32_t raw_read_scr_el3(void); +void raw_write_scr_el3(uint32_t scr_el3); +uint32_t raw_read_sctlr_el1(void); +void raw_write_sctlr_el1(uint32_t sctlr_el1); +uint32_t raw_read_sctlr_el2(void); +void raw_write_sctlr_el2(uint32_t sctlr_el2); +uint32_t raw_read_sctlr_el3(void); +void raw_write_sctlr_el3(uint32_t sctlr_el3); +uint32_t raw_read_sctlr_current(void); +void raw_write_sctlr_current(uint32_t sctlr); +uint64_t raw_read_tcr_el1(void); +void raw_write_tcr_el1(uint64_t tcr_el1); +uint32_t raw_read_tcr_el2(void); +void raw_write_tcr_el2(uint32_t tcr_el2); +uint32_t raw_read_tcr_el3(void); +void raw_write_tcr_el3(uint32_t tcr_el3); +uint64_t raw_read_tcr_current(void); +void raw_write_tcr_current(uint64_t tcr); +uint64_t raw_read_ttbr0_el1(void); +void raw_write_ttbr0_el1(uint64_t ttbr0_el1); +uint64_t raw_read_ttbr0_el2(void); +void raw_write_ttbr0_el2(uint64_t ttbr0_el2); +uint64_t raw_read_ttbr0_el3(void); +void raw_write_ttbr0_el3(uint64_t ttbr0_el3); +uint64_t raw_read_ttbr0_current(void); +void raw_write_ttbr0_current(uint64_t ttbr0); +uint64_t raw_read_ttbr1_el1(void); +void raw_write_ttbr1_el1(uint64_t ttbr1_el1); +uint64_t raw_read_vbar_el1(void); +void raw_write_vbar_el1(uint64_t vbar_el1); +uint64_t raw_read_vbar_el2(void); +void raw_write_vbar_el2(uint64_t vbar_el2); +uint64_t raw_read_vbar_el3(void); +void raw_write_vbar_el3(uint64_t vbar_el3); +uint64_t raw_read_vbar_current(void); +void raw_write_vbar_current(uint64_t vbar); + +/* Cache maintenance system instructions */ +void dccisw(uint64_t cisw); +void dccivac(uint64_t civac); +void dccsw(uint64_t csw); +void dccvac(uint64_t cvac); +void dccvau(uint64_t cvau); +void dcisw(uint64_t isw); +void dcivac(uint64_t ivac); +void dczva(uint64_t zva); +void iciallu(void); +void icialluis(void); +void icivau(uint64_t ivau); + +/* TLB maintenance instructions */ +void tlbiall_el1(void); +void tlbiall_el2(void); +void tlbiall_el3(void); +void tlbiall_current(void); +void tlbiallis_el1(void); +void tlbiallis_el2(void); +void tlbiallis_el3(void); +void tlbiallis_current(void); +void tlbivaa_el1(uint64_t va); + +/* Memory barrier */ +/* data memory barrier */ +#define dmb_opt(opt) asm volatile ("dmb " #opt : : : "memory") +/* data sync barrier */ +#define dsb_opt(opt) asm volatile ("dsb " #opt : : : "memory") +/* instruction sync barrier */ +#define isb_opt(opt) asm volatile ("isb " #opt : : : "memory") + +#define dmb() dmb_opt(sy) +#define dsb() dsb_opt(sy) +#define isb() isb_opt() + +/* Clock */ +void set_cntfrq(uint32_t freq); + +#endif // __ASSEMBLY__ + +#endif //__ARCH_LIB_HELPERS_H__ diff --git a/payloads/libpayload/include/arm64/arch/mmu.h b/payloads/libpayload/include/arm64/arch/mmu.h new file mode 100644 index 0000000000..abd29f5ad4 --- /dev/null +++ b/payloads/libpayload/include/arm64/arch/mmu.h @@ -0,0 +1,211 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __ARCH_ARM64_MMU_H__ +#define __ARCH_ARM64_MMU_H__ + +#include + +struct mmu_memrange { + uint64_t base; + uint64_t size; + uint64_t type; +}; + +struct mmu_ranges { + struct mmu_memrange entries[SYSINFO_MAX_MEM_RANGES]; + size_t used; +}; + +/* + * Symbols taken from linker script + * They mark the start and end of the region used by payload + */ +extern char _start[], _end[]; + +/* IMPORTANT!!!!!!! + * Assumptions made: + * Granule size is 64KiB + * BITS per Virtual address is 33 + * All the calculations for tables L1,L2 and L3 are based on these assumptions + * If these values are changed, recalculate the other macros as well + */ + +/* Memory attributes for mmap regions + * These attributes act as tag values for memrange regions + */ + +#define TYPE_NORMAL_MEM 1 +#define TYPE_DEV_MEM 2 +#define TYPE_DMA_MEM 3 + +/* Descriptor attributes */ + +#define INVALID_DESC 0x0 +#define BLOCK_DESC 0x1 +#define TABLE_DESC 0x3 +#define PAGE_DESC 0x3 + +/* Block descriptor */ +#define BLOCK_NS (1 << 5) + +#define BLOCK_AP_RW (0 << 7) +#define BLOCK_AP_RO (1 << 7) + +#define BLOCK_ACCESS (1 << 10) + +/* XLAT Table Init Attributes */ + +#define VA_START 0x0 +/* If BITS_PER_VA or GRANULE_SIZE are changed, recalculate and change the + macros following them */ +#define BITS_PER_VA 33 +/* Granule size of 64KB is being used */ +#define MIN_64_BIT_ADDR (1UL << 32) +#define XLAT_TABLE_MASK ~(0xffffUL) +#define GRANULE_SIZE_SHIFT 16 +#define GRANULE_SIZE (1 << GRANULE_SIZE_SHIFT) +#define GRANULE_SIZE_MASK ((1 << 16) - 1) + +#define L1_ADDR_SHIFT 42 +#define L2_ADDR_SHIFT 29 +#define L3_ADDR_SHIFT 16 + +#define L1_ADDR_MASK (0UL << L1_ADDR_SHIFT) +#define L2_ADDR_MASK (0xfUL << L2_ADDR_SHIFT) +#define L3_ADDR_MASK (0x1fffUL << L3_ADDR_SHIFT) + +/* Dependent on BITS_PER_VA and GRANULE_SIZE */ +#define INIT_LEVEL 2 +#define XLAT_MAX_LEVEL 3 + +/* Each entry in XLAT table is 8 bytes */ +#define XLAT_ENTRY_SHIFT 3 +#define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SHIFT) + +#define XLAT_TABLE_SHIFT GRANULE_SIZE_SHIFT +#define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SHIFT) + +#define XLAT_NUM_ENTRIES_SHIFT (XLAT_TABLE_SHIFT - XLAT_ENTRY_SHIFT) +#define XLAT_NUM_ENTRIES (1 << XLAT_NUM_ENTRIES_SHIFT) + +#define L3_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT) +#define L2_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT + XLAT_NUM_ENTRIES_SHIFT) +#define L1_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT + XLAT_NUM_ENTRIES_SHIFT) + +/* These macros give the size of the region addressed by each entry of a xlat + table at any given level */ +#define L3_XLAT_SIZE (1 << L3_XLAT_SIZE_SHIFT) +#define L2_XLAT_SIZE (1 << L2_XLAT_SIZE_SHIFT) +#define L1_XLAT_SIZE (1 << L1_XLAT_SIZE_SHIFT) + +/* Block indices required for MAIR */ +#define BLOCK_INDEX_MEM_DEV_NGNRNE 0 +#define BLOCK_INDEX_MEM_DEV_NGNRE 1 +#define BLOCK_INDEX_MEM_DEV_GRE 2 +#define BLOCK_INDEX_MEM_NORMAL_NC 3 +#define BLOCK_INDEX_MEM_NORMAL 4 + +#define BLOCK_INDEX_SHIFT 2 + +/* MAIR attributes */ +#define MAIR_ATTRIBUTES ((0x00 << (BLOCK_INDEX_MEM_DEV_NGNRNE*8)) | \ + (0x04 << (BLOCK_INDEX_MEM_DEV_NGNRE*8)) | \ + (0x0c << (BLOCK_INDEX_MEM_DEV_GRE*8)) | \ + (0x44 << (BLOCK_INDEX_MEM_NORMAL_NC*8)) | \ + (0xffUL << (BLOCK_INDEX_MEM_NORMAL*8))) + +/* TCR attributes */ +#define TCR_TOSZ (64 - BITS_PER_VA) + +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_NM_NC (0x00 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WBWAC (0x01 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WTC (0x02 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WBNWAC (0x03 << TCR_IRGN0_SHIFT) + +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_NM_NC (0x00 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WBWAC (0x01 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WTC (0x02 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WBNWAC (0x03 << TCR_ORGN0_SHIFT) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_NC (0x0 << TCR_SH0_SHIFT) +#define TCR_SH0_OS (0x2 << TCR_SH0_SHIFT) +#define TCR_SH0_IS (0x3 << TCR_SH0_SHIFT) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_4KB (0x0 << TCR_TG0_SHIFT) +#define TCR_TG0_64KB (0x1 << TCR_TG0_SHIFT) +#define TCR_TG0_16KB (0x2 << TCR_TG0_SHIFT) + +#define TCR_PS_SHIFT 16 +#define TCR_PS_4GB (0x0 << TCR_PS_SHIFT) +#define TCR_PS_64GB (0x1 << TCR_PS_SHIFT) +#define TCR_PS_1TB (0x2 << TCR_PS_SHIFT) +#define TCR_PS_4TB (0x3 << TCR_PS_SHIFT) +#define TCR_PS_16TB (0x4 << TCR_PS_SHIFT) +#define TCR_PS_256TB (0x5 << TCR_PS_SHIFT) + +#define TCR_TBI_SHIFT 20 +#define TCR_TBI_USED (0x0 << TCR_TBI_SHIFT) +#define TCR_TBI_IGNORED (0x1 << TCR_TBI_SHIFT) + +#define DMA_DEFAULT_SIZE (0x20 * GRANULE_SIZE) +#define TTB_DEFAULT_SIZE 0x100000 + +#define MB_SIZE (1UL << 20) + +/* Initialize the MMU TTB tables using the mmu_ranges */ +uint64_t mmu_init(struct mmu_ranges *mmu_ranges); + +/* Enable the mmu based on previous mmu_init(). */ +void mmu_enable(void); + +/* Disable mmu */ +void mmu_disable(void); + +/* + * Based on the memory ranges provided in coreboot tables, + * initialize the mmu_memranges used for mmu initialization + * cb_ranges -> Memory ranges present in cb tables + * mmu_ranges -> mmu_memranges initialized by this function + */ +struct mmu_memrange* mmu_init_ranges_from_sysinfo(struct memrange *cb_ranges, + uint64_t ncb, + struct mmu_ranges *mmu_ranges); + +/* + * Functions for handling the initialization of memory ranges and enabling mmu + * before coreboot tables are parsed + */ +void mmu_presysinfo_memory_used(uint64_t base, uint64_t size); +void mmu_presysinfo_enable(void); +#endif // __ARCH_ARM64_MMU_H__ diff --git a/payloads/libpayload/include/armv7/arch/types.h b/payloads/libpayload/include/arm64/arch/types.h similarity index 97% rename from payloads/libpayload/include/armv7/arch/types.h rename to payloads/libpayload/include/arm64/arch/types.h index bb4025714f..1bd815bb44 100644 --- a/payloads/libpayload/include/armv7/arch/types.h +++ b/payloads/libpayload/include/arm64/arch/types.h @@ -53,9 +53,6 @@ typedef signed long long s64; typedef long time_t; typedef long suseconds_t; -typedef unsigned long size_t; -typedef long ssize_t; - #ifndef NULL #define NULL ((void *)0) #endif diff --git a/payloads/libpayload/include/armv7/arch/virtual.h b/payloads/libpayload/include/arm64/arch/virtual.h similarity index 100% rename from payloads/libpayload/include/armv7/arch/virtual.h rename to payloads/libpayload/include/arm64/arch/virtual.h diff --git a/payloads/libpayload/include/cbfs.h b/payloads/libpayload/include/cbfs.h index df3bb1c8c8..1b5c51a669 100644 --- a/payloads/libpayload/include/cbfs.h +++ b/payloads/libpayload/include/cbfs.h @@ -81,10 +81,6 @@ void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer, // Utility functions int run_address(void *f); -/* Defined in src/lib/selfboot.c */ -struct lb_memory; -int selfboot(struct lb_memory *mem, struct cbfs_payload *payload); - /* Defined in individual arch / board implementation. */ int init_default_cbfs_media(struct cbfs_media *media); diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h index 2dc1992bc7..0408ba1f59 100644 --- a/payloads/libpayload/include/cbfs_core.h +++ b/payloads/libpayload/include/cbfs_core.h @@ -85,10 +85,9 @@ #define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff)) -/** this is the master cbfs header - it needs to be located somewhere available - to bootblock (to load romstage). Where it actually lives is up to coreboot. - On x86, a pointer to this header will live at 0xFFFFFFFC. - For other platforms, you need to define CONFIG_CBFS_HEADER_ROM_OFFSET */ +/* this is the master cbfs header - it must be located somewhere available + * to bootblock (to load romstage). The last 4 bytes in the image contain its + * relative offset from the end of the image (as a 32-bit signed integer). */ struct cbfs_header { uint32_t magic; @@ -106,7 +105,8 @@ struct cbfs_header { */ #define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF #define CBFS_ARCHITECTURE_X86 0x00000001 -#define CBFS_ARCHITECTURE_ARMV7 0x00000010 +#define CBFS_ARCHITECTURE_ARM 0x00000010 +#define CBFS_ARCHITECTURE_ARM64 0x00000011 /** This is a component header - every entry in the CBFS will have this header. diff --git a/payloads/libpayload/include/cbfs_ram.h b/payloads/libpayload/include/cbfs_ram.h new file mode 100644 index 0000000000..defe823b05 --- /dev/null +++ b/payloads/libpayload/include/cbfs_ram.h @@ -0,0 +1,61 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 Google, Inc. + * + * This file is dual-licensed. You can choose between: + * - The GNU GPL, version 2, as published by the Free Software Foundation + * - The revised BSD license (without advertising clause) + * + * --------------------------------------------------------------------------- + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * --------------------------------------------------------------------------- + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * --------------------------------------------------------------------------- + */ + +#ifndef _CBFS_RAM_H_ +#define _CBFS_RAM_H_ + +#include + +struct cbfs_media; + +/* The following functions return 0 for success. None-zero on error. */ +int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size); +int setup_cbfs_from_ram(void *start, uint32_t size); +int setup_cbfs_from_flash(void); + +#endif /* _CBFS_RAM_H_ */ diff --git a/payloads/libpayload/include/coreboot_tables.h b/payloads/libpayload/include/coreboot_tables.h index 02c9449b08..f97f4d30d9 100644 --- a/payloads/libpayload/include/coreboot_tables.h +++ b/payloads/libpayload/include/coreboot_tables.h @@ -133,7 +133,7 @@ struct cb_console { #define CB_TAG_CONSOLE_SERIAL8250 0 #define CB_TAG_CONSOLE_VGA 1 // OBSOLETE #define CB_TAG_CONSOLE_BTEXT 2 // OBSOLETE -#define CB_TAG_CONSOLE_LOGBUF 3 +#define CB_TAG_CONSOLE_LOGBUF 3 // OBSOLETE #define CB_TAG_CONSOLE_SROM 4 // OBSOLETE #define CB_TAG_CONSOLE_EHCI 5 @@ -184,37 +184,35 @@ struct cb_gpios { struct cb_gpio gpios[0]; }; -#define CB_TAG_VDAT 0x0015 -struct cb_vdat { +#define CB_TAG_VDAT 0x0015 +#define CB_TAG_VBNV 0x0019 +#define CB_TAG_VBOOT_HANDOFF 0x0020 +#define CB_TAG_DMA 0x0022 +#define CB_TAG_RAM_OOPS 0x0023 +struct cb_range { uint32_t tag; - uint32_t size; /* size of the entire entry */ - void *vdat_addr; - uint32_t vdat_size; + uint32_t size; + uint64_t range_start; + uint32_t range_size; }; #define CB_TAG_TIMESTAMPS 0x0016 #define CB_TAG_CBMEM_CONSOLE 0x0017 #define CB_TAG_MRC_CACHE 0x0018 +#define CB_TAG_ACPI_GNVS 0x0024 +#define CB_TAG_WIFI_CALIBRATION 0x0027 struct cb_cbmem_tab { uint32_t tag; uint32_t size; - void *cbmem_tab; + uint64_t cbmem_tab; }; -#define CB_TAG_VBNV 0x0019 -struct cb_vbnv { +#define CB_TAG_BOARD_ID 0x0025 +struct cb_board_id { uint32_t tag; uint32_t size; - uint32_t vbnv_start; - uint32_t vbnv_size; -}; - -#define CB_TAG_VBOOT_HANDOFF 0x0020 -struct cb_vboot_handoff { - uint32_t tag; - uint32_t size; - void *vboot_handoff_addr; - uint32_t vboot_handoff_size; + /* Board ID as retrieved from the board revision GPIOs. */ + uint32_t board_id; }; #define CB_TAG_X86_ROM_MTRR 0x0021 @@ -228,6 +226,25 @@ struct cb_x86_rom_mtrr { uint32_t index; }; +#define CB_TAG_MAC_ADDRS 0x0026 +struct mac_address { + uint8_t mac_addr[6]; + uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ +}; + +struct cb_macs { + uint32_t tag; + uint32_t size; + uint32_t count; + struct mac_address mac_addrs[0]; +}; + +#define CB_TAG_RAM_CODE 0x0028 +struct cb_ram_code { + uint32_t tag; + uint32_t size; + uint32_t ram_code; +}; #define CB_TAG_CMOS_OPTION_TABLE 0x00c8 struct cb_cmos_option_table { diff --git a/payloads/libpayload/include/die.h b/payloads/libpayload/include/die.h new file mode 100644 index 0000000000..6dff6a89b4 --- /dev/null +++ b/payloads/libpayload/include/die.h @@ -0,0 +1,45 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2013 coresystems GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __DIE_H__ +#define __DIE_H__ + +void die_work(const char *file, const char *func, const int line, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))) + __attribute__((noreturn)); + +#define die(fmt, args...) \ + do { die_work(__FILE__, __FUNCTION__, __LINE__, fmt, ##args); } \ + while (0) + +#define die_if(condition, fmt, args...) \ + do { if (condition) die(fmt, ##args); } while (0) + +#endif /* __DIE_H__ */ diff --git a/payloads/libpayload/include/endian.h b/payloads/libpayload/include/endian.h index cb5044380b..dffaa55795 100644 --- a/payloads/libpayload/include/endian.h +++ b/payloads/libpayload/include/endian.h @@ -1,28 +1,36 @@ /* + * This file is part of the libpayload project. + * * Copyright (c) 2012 The Chromium OS Authors. * - * See file CREDITS for list of people who contributed to this - * project. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but without any warranty; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef _ENDIAN_H_ #define _ENDIAN_H_ +#include #include #include @@ -45,7 +53,7 @@ static inline uint64_t swap_bytes64(uint64_t in) /* Endian functions from glibc 2.9 / BSD "endian.h" */ -#if defined CONFIG_BIG_ENDIAN +#if defined CONFIG_LP_BIG_ENDIAN #define htobe16(in) (in) #define htobe32(in) (in) @@ -55,7 +63,7 @@ static inline uint64_t swap_bytes64(uint64_t in) #define htole32(in) swap_bytes32(in) #define htole64(in) swap_bytes64(in) -#elif defined CONFIG_LITTLE_ENDIAN +#elif defined CONFIG_LP_LITTLE_ENDIAN #define htobe16(in) swap_bytes16(in) #define htobe32(in) swap_bytes32(in) @@ -101,4 +109,20 @@ static inline uint64_t swap_bytes64(uint64_t in) #define letohl(in) le32toh(in) #define letohll(in) le64toh(in) +/* Handy bit manipulation macros */ + +#define clrsetbits_le32(addr, clear, set) writel(htole32((le32toh(readl(addr)) \ + & ~(clear)) | (set)), (addr)) +#define setbits_le32(addr, set) writel(htole32(le32toh(readl(addr)) \ + | (set)), (addr)) +#define clrbits_le32(addr, clear) writel(htole32(le32toh(readl(addr)) \ + & ~(clear)), (addr)) + +#define clrsetbits_be32(addr, clear, set) writel(htobe32((be32toh(readl(addr)) \ + & ~(clear)) | (set)), (addr)) +#define setbits_be32(addr, set) writel(htobe32(be32toh(readl(addr)) \ + | (set)), (addr)) +#define clrbits_be32(addr, clear) writel(htobe32(be32toh(readl(addr)) \ + & ~(clear)), (addr)) + #endif diff --git a/payloads/libpayload/include/exception.h b/payloads/libpayload/include/exception.h new file mode 100644 index 0000000000..67923ea9af --- /dev/null +++ b/payloads/libpayload/include/exception.h @@ -0,0 +1,41 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _EXCEPTION_H +#define _EXCEPTION_H + +#include + +/* Return 1 if the exception was handled, 0 to proceed to the next handler. */ +typedef int (*exception_hook)(u32 type); + +void exception_init(void); +void exception_install_hook(exception_hook h); + +#endif diff --git a/payloads/libpayload/include/gdb.h b/payloads/libpayload/include/gdb.h new file mode 100644 index 0000000000..283ca045ec --- /dev/null +++ b/payloads/libpayload/include/gdb.h @@ -0,0 +1,241 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _GDB_H_ +#define _GDB_H_ + +#include + +struct gdb_message +{ + u8 *buf; + int used; + const int size; +}; + +struct gdb_state +{ + u8 signal; + u8 resumed : 1; + u8 connected : 1; +}; +extern struct gdb_state gdb_state; + +typedef void (*gdb_command_handler)(struct gdb_message *command, + int offset, struct gdb_message *reply); +struct gdb_command +{ + const char *str; + gdb_command_handler handler; +}; +extern struct gdb_command gdb_commands[]; +extern const int gdb_command_count; + +/* arch/gdb.c */ + +void gdb_arch_init(void); +void gdb_arch_enter(void); + +int gdb_arch_set_single_step(int on); + +void gdb_arch_encode_regs(struct gdb_message *message); +void gdb_arch_decode_regs(int offset, struct gdb_message *message); + +/* gdb/transport.c */ + +void gdb_transport_init(void); +void gdb_transport_teardown(void); + +void gdb_message_encode_bytes(struct gdb_message *message, const void *data, + int length); +void gdb_message_decode_bytes(const struct gdb_message *message, int offset, + void *data, int length); +void gdb_message_encode_zero_bytes(struct gdb_message *message, int length); + +void gdb_message_add_string(struct gdb_message *message, const char *string); + +void gdb_message_encode_int(struct gdb_message *message, uintptr_t val); +uintptr_t gdb_message_decode_int(const struct gdb_message *message, int offset, + int length); + +int gdb_message_tokenize(const struct gdb_message *message, int *offset); + +void gdb_get_command(struct gdb_message *command); +void gdb_send_reply(const struct gdb_message *reply); + +/* gdb/stub.c */ + +void gdb_command_loop(uint8_t signal); + +enum { + GDB_SIG0 = 0, /* Signal 0 */ + GDB_SIGHUP = 1, /* Hangup */ + GDB_SIGINT = 2, /* Interrupt */ + GDB_SIGQUIT = 3, /* Quit */ + GDB_SIGILL = 4, /* Illegal instruction */ + GDB_SIGTRAP = 5, /* Trace/breakpoint trap */ + GDB_SIGABRT = 6, /* Aborted */ + GDB_SIGEMT = 7, /* Emulation trap */ + GDB_SIGFPE = 8, /* Arithmetic exception */ + GDB_SIGKILL = 9, /* Killed */ + GDB_SIGBUS = 10, /* Bus error */ + GDB_SIGSEGV = 11, /* Segmentation fault */ + GDB_SIGSYS = 12, /* Bad system call */ + GDB_SIGPIPE = 13, /* Broken pipe */ + GDB_SIGALRM = 14, /* Alarm clock */ + GDB_SIGTERM = 15, /* Terminated */ + GDB_SIGURG = 16, /* Urgent I/O condition */ + GDB_SIGSTOP = 17, /* Stopped (signal) */ + GDB_SIGTSTP = 18, /* Stopped (user) */ + GDB_SIGCONT = 19, /* Continued */ + GDB_SIGCHLD = 20, /* Child status changed */ + GDB_SIGTTIN = 21, /* Stopped (ttyinput) */ + GDB_SIGTTOU = 22, /* Stopped (ttyoutput) */ + GDB_SIGIO = 23, /* I/O possible */ + GDB_SIGXCPU = 24, /* CPU time limit exceeded */ + GDB_SIGXFSZ = 25, /* File size limit exceeded */ + GDB_SIGVTALRM = 26, /* Virtual timer expired */ + GDB_SIGPROF = 27, /* Profiling timer expired */ + GDB_SIGWINCH = 28, /* Window size changed */ + GDB_SIGLOST = 29, /* Resource lost */ + GDB_SIGUSR1 = 30, /* User defined signal1 */ + GDB_SUGUSR2 = 31, /* User defined signal2 */ + GDB_SIGPWR = 32, /* Powerfail/restart */ + GDB_SIGPOLL = 33, /* Pollable event occurred */ + GDB_SIGWIND = 34, /* SIGWIND */ + GDB_SIGPHONE = 35, /* SIGPHONE */ + GDB_SIGWAITING = 36, /* Process's LWPs are blocked */ + GDB_SIGLWP = 37, /* Signal LWP */ + GDB_SIGDANGER = 38, /* Swap space dangerously low */ + GDB_SIGGRANT = 39, /* Monitor mode granted */ + GDB_SIGRETRACT = 40, /* Need to relinquish monitor mode */ + GDB_SIGMSG = 41, /* Monitor mode data available */ + GDB_SIGSOUND = 42, /* Sound completed */ + GDB_SIGSAK = 43, /* Secure attention */ + GDB_SIGPRIO = 44, /* SIGPRIO */ + + GDB_SIG33 = 45, /* Real-timeevent 33 */ + GDB_SIG34 = 46, /* Real-timeevent 34 */ + GDB_SIG35 = 47, /* Real-timeevent 35 */ + GDB_SIG36 = 48, /* Real-timeevent 36 */ + GDB_SIG37 = 49, /* Real-timeevent 37 */ + GDB_SIG38 = 50, /* Real-timeevent 38 */ + GDB_SIG39 = 51, /* Real-timeevent 39 */ + GDB_SIG40 = 52, /* Real-timeevent 40 */ + GDB_SIG41 = 53, /* Real-timeevent 41 */ + GDB_SIG42 = 54, /* Real-timeevent 42 */ + GDB_SIG43 = 55, /* Real-timeevent 43 */ + GDB_SIG44 = 56, /* Real-timeevent 44 */ + GDB_SIG45 = 57, /* Real-timeevent 45 */ + GDB_SIG46 = 58, /* Real-timeevent 46 */ + GDB_SIG47 = 59, /* Real-timeevent 47 */ + GDB_SIG48 = 60, /* Real-timeevent 48 */ + GDB_SIG49 = 61, /* Real-timeevent 49 */ + GDB_SIG50 = 62, /* Real-timeevent 50 */ + GDB_SIG51 = 63, /* Real-timeevent 51 */ + GDB_SIG52 = 64, /* Real-timeevent 52 */ + GDB_SIG53 = 65, /* Real-timeevent 53 */ + GDB_SIG54 = 66, /* Real-timeevent 54 */ + GDB_SIG55 = 67, /* Real-timeevent 55 */ + GDB_SIG56 = 68, /* Real-timeevent 56 */ + GDB_SIG57 = 69, /* Real-timeevent 57 */ + GDB_SIG58 = 70, /* Real-timeevent 58 */ + GDB_SIG59 = 71, /* Real-timeevent 59 */ + GDB_SIG60 = 72, /* Real-timeevent 60 */ + GDB_SIG61 = 73, /* Real-timeevent 61 */ + GDB_SIG62 = 74, /* Real-timeevent 62 */ + GDB_SIG63 = 75, /* Real-timeevent 63 */ + GDB_SIGCANCEL = 76, /* LWP internal signal */ + GDB_SIG32 = 77, /* Real-timeevent 32 */ + GDB_SIG64 = 78, /* Real-timeevent 64 */ + GDB_SIG65 = 79, /* Real-timeevent 65 */ + GDB_SIG66 = 80, /* Real-timeevent 66 */ + GDB_SIG67 = 81, /* Real-timeevent 67 */ + GDB_SIG68 = 82, /* Real-timeevent 68 */ + GDB_SIG69 = 83, /* Real-timeevent 69 */ + GDB_SIG70 = 84, /* Real-timeevent 70 */ + GDB_SIG71 = 85, /* Real-timeevent 71 */ + GDB_SIG72 = 86, /* Real-timeevent 72 */ + GDB_SIG73 = 87, /* Real-timeevent 73 */ + GDB_SIG74 = 88, /* Real-timeevent 74 */ + GDB_SIG75 = 89, /* Real-timeevent 75 */ + GDB_SIG76 = 90, /* Real-timeevent 76 */ + GDB_SIG77 = 91, /* Real-timeevent 77 */ + GDB_SIG78 = 92, /* Real-timeevent 78 */ + GDB_SIG79 = 93, /* Real-timeevent 79 */ + GDB_SIG80 = 94, /* Real-timeevent 80 */ + GDB_SIG81 = 95, /* Real-timeevent 81 */ + GDB_SIG82 = 96, /* Real-timeevent 82 */ + GDB_SIG83 = 97, /* Real-timeevent 83 */ + GDB_SIG84 = 98, /* Real-timeevent 84 */ + GDB_SIG85 = 99, /* Real-timeevent 85 */ + GDB_SIG86 = 100, /* Real-timeevent 86 */ + GDB_SIG87 = 101, /* Real-timeevent 87 */ + GDB_SIG88 = 102, /* Real-timeevent 88 */ + GDB_SIG89 = 103, /* Real-timeevent 89 */ + GDB_SIG90 = 104, /* Real-timeevent 90 */ + GDB_SIG91 = 105, /* Real-timeevent 91 */ + GDB_SIG92 = 106, /* Real-timeevent 92 */ + GDB_SIG93 = 107, /* Real-timeevent 93 */ + GDB_SIG94 = 108, /* Real-timeevent 94 */ + GDB_SIG95 = 109, /* Real-timeevent 95 */ + GDB_SIG96 = 110, /* Real-timeevent 96 */ + GDB_SIG97 = 111, /* Real-timeevent 97 */ + GDB_SIG98 = 112, /* Real-timeevent 98 */ + GDB_SIG99 = 113, /* Real-timeevent 99 */ + GDB_SIG100 = 114, /* Real-timeevent 100 */ + GDB_SIG101 = 115, /* Real-timeevent 101 */ + GDB_SIG102 = 116, /* Real-timeevent 102 */ + GDB_SIG103 = 117, /* Real-timeevent 103 */ + GDB_SIG104 = 118, /* Real-timeevent 104 */ + GDB_SIG105 = 119, /* Real-timeevent 105 */ + GDB_SIG106 = 120, /* Real-timeevent 106 */ + GDB_SIG107 = 121, /* Real-timeevent 107 */ + GDB_SIG108 = 122, /* Real-timeevent 108 */ + GDB_SIG109 = 123, /* Real-timeevent 109 */ + GDB_SIG110 = 124, /* Real-timeevent 110 */ + GDB_SIG111 = 125, /* Real-timeevent 111 */ + GDB_SIG112 = 126, /* Real-timeevent 112 */ + GDB_SIG113 = 127, /* Real-timeevent 113 */ + GDB_SIG114 = 128, /* Real-timeevent 114 */ + GDB_SIG115 = 129, /* Real-timeevent 115 */ + GDB_SIG116 = 130, /* Real-timeevent 116 */ + GDB_SIG117 = 131, /* Real-timeevent 117 */ + GDB_SIG118 = 132, /* Real-timeevent 118 */ + GDB_SIG119 = 133, /* Real-timeevent 119 */ + GDB_SIG120 = 134, /* Real-timeevent 120 */ + GDB_SIG121 = 135, /* Real-timeevent 121 */ + GDB_SIG122 = 136, /* Real-timeevent 122 */ + GDB_SIG123 = 137, /* Real-timeevent 123 */ + GDB_SIG124 = 138, /* Real-timeevent 124 */ + GDB_SIG125 = 139, /* Real-timeevent 125 */ + GDB_SIG126 = 140, /* Real-timeevent 126 */ + GDB_SIG127 = 141, /* Real-timeevent 127 */ + GDB_SIGINFO = 142, /* Information request */ + GDB_UNKNOWN1 = 43, /* Unknownsignal */ + GDB_DEFAULT = 144, /* error:defaultsignal */ + /* Machexceptions */ + GDB_EXC_BAD_ACCESS = 145, /* Could not access memory */ + GDB_EXC_BAD_INSTRCTION = 146, /* Illegal instruction/operand */ + GDB_EXC_ARITHMETIC = 147, /* Arithmetic exception */ + GDB_EXC_EMULATION = 148, /* Emulation instruction */ + GDB_EXC_SOFTWARE = 149, /* Software generated exception */ + GDB_EXC_BREAKPOINT = 150, /* Breakpoint */ +}; + +#endif /* _GDB_H_ */ diff --git a/payloads/libpayload/include/ipchksum.h b/payloads/libpayload/include/ipchksum.h index b7ded0843d..1ce13cda17 100644 --- a/payloads/libpayload/include/ipchksum.h +++ b/payloads/libpayload/include/ipchksum.h @@ -1,23 +1,30 @@ /* + * This file is part of the libpayload project. + * * Copyright (c) 2012 The Chromium OS Authors. * - * See file CREDITS for list of people who contributed to this - * project. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but without any warranty; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef __IPCHKSUM_H__ diff --git a/payloads/libpayload/include/kconfig.h b/payloads/libpayload/include/kconfig.h index 3d7d768f9c..adb3403cf2 100644 --- a/payloads/libpayload/include/kconfig.h +++ b/payloads/libpayload/include/kconfig.h @@ -5,10 +5,10 @@ /* * Getting something that works in C and CPP for an arg that may or may - * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" + * not be defined is tricky. Here, if we have "#define CONFIG_LP_BOOGER 1" * we match on the placeholder define, insert the "0," for arg1 and generate * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). - * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when + * When CONFIG_LP_BOOGER is not defined, we generate a (... 1, 0) pair, and when * the last step cherry picks the 2nd arg, we get a zero. */ #define __ARG_PLACEHOLDER_1 0, diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h index f23fb8763b..af8cf57d01 100644 --- a/payloads/libpayload/include/libpayload.h +++ b/payloads/libpayload/include/libpayload.h @@ -45,6 +45,8 @@ #include #include +#include +#include #include #include #include @@ -56,7 +58,7 @@ #include #include #include -#ifdef CONFIG_LAR +#ifdef CONFIG_LP_LAR #include #endif @@ -150,6 +152,7 @@ int add_reset_handler(void (*new_handler)(void)); * @{ */ void keyboard_init(void); +void keyboard_disconnect(void); int keyboard_havechar(void); unsigned char keyboard_get_scancode(void); int keyboard_getchar(void); @@ -162,6 +165,7 @@ int keyboard_set_layout(char *country); * @{ */ void serial_init(void); +void serial_console_init(void); void serial_putchar(unsigned int c); int serial_havechar(void); int serial_getchar(void); @@ -209,7 +213,7 @@ void video_console_set_cursor(unsigned int cursorx, unsigned int cursory); * @{ */ void cbmem_console_init(void); -void cbmem_console_putc(unsigned int data); +void cbmem_console_write(const void *buffer, size_t count); /** @} */ /* drivers/option.c */ @@ -246,12 +250,19 @@ int set_option_from_string(const struct nvram_accessor *nvram, struct cb_cmos_op * @defgroup console Console functions * @{ */ +typedef enum { + CONSOLE_INPUT_TYPE_UNKNOWN = 0, + CONSOLE_INPUT_TYPE_USB, +} console_input_type; + void console_init(void); +void console_write(const void *buffer, size_t count); int putchar(unsigned int c); int puts(const char *s); int havekey(void); int getchar(void); int getchar_timeout(int *ms); +console_input_type last_key_input_type(void); extern int last_putchar; @@ -260,16 +271,19 @@ struct console_input_driver { struct console_input_driver *next; int (*havekey) (void); int (*getchar) (void); + console_input_type input_type; }; struct console_output_driver; struct console_output_driver { struct console_output_driver *next; void (*putchar) (unsigned int); + void (*write) (const void *, size_t); }; void console_add_output_driver(struct console_output_driver *out); void console_add_input_driver(struct console_input_driver *in); +int console_remove_output_driver(void *function); #define havechar havekey /** @} */ @@ -293,6 +307,7 @@ long int labs(long int j); long long int llabs(long long int j); u8 bin2hex(u8 b); u8 hex2bin(u8 h); +void hexdump(unsigned long memory, int length); void fatal(const char *msg) __attribute__ ((noreturn)); /** @} */ @@ -330,7 +345,7 @@ struct timeval { int gettimeofday(struct timeval *tv, void *tz); /** @} */ -#ifdef CONFIG_LAR +#ifdef CONFIG_LP_LAR /** * @defgroup lar LAR functions * @{ @@ -404,14 +419,18 @@ int sysinfo_have_multiboot(unsigned long *addr); */ int get_coreboot_info(struct sysinfo_t *info); int get_multiboot_info(struct sysinfo_t *info); +void *get_cb_header_ptr(void); int lib_get_sysinfo(void); +void lib_sysinfo_get_memranges(struct memrange **ranges, + uint64_t *nranges); /* Timer functions. */ /* Defined by each architecture. */ unsigned int get_cpu_speed(void); uint64_t timer_hz(void); uint64_t timer_raw_value(void); +uint64_t timer_us(uint64_t base); /* Generic. */ void ndelay(unsigned int n); void udelay(unsigned int n); @@ -428,4 +447,12 @@ char *readline(const char *prompt); int getline(char *buffer, int len); /** @} */ +/* Defined in arch/${ARCH}/selfboot.c */ +void selfboot(void *entry); + +/* Enter remote GDB mode. Will initialize connection if not already up. */ +void gdb_enter(void); +/* Disconnect existing GDB connection if one exists. */ +void gdb_exit(s8 exit_status); + #endif diff --git a/payloads/libpayload/include/lzma.h b/payloads/libpayload/include/lzma.h index 818c16da1e..523bc8c99e 100644 --- a/payloads/libpayload/include/lzma.h +++ b/payloads/libpayload/include/lzma.h @@ -30,10 +30,18 @@ #ifndef _LZMA_H #define _LZMA_H -/* decompresses the data stream at src to dst, determining its length from +/* Decompresses the data stream at src to dst. The sizes of the source and + * destination buffers are in srcn and dstn. + * + * Returns the decompressed size, or 0 on error + */ +unsigned long ulzman(const unsigned char *src, unsigned long srcn, + unsigned char *dst, unsigned long dstn); + +/* Decompresses the data stream at src to dst, determining its length from * the data stream itself. * - * returns the decompressed size, or 0 on error + * Returns the decompressed size, or 0 on error */ unsigned long ulzma(const unsigned char *src, unsigned char *dst); diff --git a/payloads/libpayload/include/powerpc/arch/io.h b/payloads/libpayload/include/powerpc/arch/io.h deleted file mode 100644 index 1676a8a119..0000000000 --- a/payloads/libpayload/include/powerpc/arch/io.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2008-2009 coresystems GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARCH_IO_H -#define _ARCH_IO_H - -extern uint32_t isa_io_base; - -#define readb(_a) (*(volatile unsigned char *) (_a)) -#define readw(_a) (*(volatile unsigned short *) (_a)) -#define readl(_a) (*(volatile unsigned long *) (_a)) - -#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v)) -#define writew(_v, _a) (*(volatile unsigned short *) (_a) = (_v)) -#define writel(_v, _a) (*(volatile unsigned long *) (_a) = (_v)) - -static inline unsigned long inl(int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - unsigned long val; - __asm__ __volatile__("lhbrx %0,0,%1; eieio":"=r"(val): - "r"(addr), "m"(*addr)); - return val; -} - -static inline unsigned short inw(int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - unsigned short val; - __asm__ __volatile__("lwbrx %0,0,%1; eieio":"=r"(val):"r"(addr), "m"(*addr)); - return val; -} - -static inline unsigned char inb(int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - unsigned char val; - __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio":"=r"(val):"m"(*addr)); - return val; -} - -static inline void outl(unsigned long val, int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - __asm__ __volatile__("stb%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val)); -} - -static inline void outw(unsigned short val, int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - __asm__ __volatile__("sthbrx %1,0,%2; eieio":"=m"(*addr):"r"(val),"r"(addr)); -} - -static inline void outb(unsigned char val, int port) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - __asm__ __volatile__("stwbrx %1,0,%2; eieio":"=m"(*addr):"r"(val), "r"(addr)); -} - -static inline void outsl(int port, const void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; outsl" : "+S"(addr), "+c"(count) : "d"(port)); -} - -static inline void outsw(int port, const void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; outsw" : "+S"(addr), "+c"(count) : "d"(port)); -} - -static inline void outsb(int port, const void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; outsb" : "+S"(addr), "+c"(count) : "d"(port)); -} - -static inline void insl(int port, void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; insl" : "+D"(addr), "+c"(count) : "d"(port)); -} - -static inline void insw(int port, void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; insw" : "+D"(addr), "+c"(count) : "d"(port)); -} - -static inline void insb(int port, void *addr, unsigned long count) -{ - volatile unsigned char *addr = (volatile unsigned char *)(isa_io_base + port); - //__asm__ __volatile__("rep; insb" : "+D"(addr), "+c"(count) : "d"(port)); -} - -#endif diff --git a/payloads/libpayload/include/stdarg.h b/payloads/libpayload/include/stdarg.h index 077645f227..1d7ac051f4 100644 --- a/payloads/libpayload/include/stdarg.h +++ b/payloads/libpayload/include/stdarg.h @@ -31,7 +31,20 @@ #define _LIBPAYLOAD_STDARG_H #include + +/* With GCC we use -nostdinc -ffreestanding to keep out system includes. + * Unfortunately this also gets us rid of the _compiler_ includes, like + * stdarg.h. To work around the issue, we define varargs directly here. + * On LLVM we can still just include stdarg.h. + */ +#ifdef __GNUC__ +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +typedef __builtin_va_list va_list; +#else #include_next +#endif /** * @defgroup vprintf Varargs print functions diff --git a/payloads/libpayload/include/stddef.h b/payloads/libpayload/include/stddef.h new file mode 100644 index 0000000000..fca66ed247 --- /dev/null +++ b/payloads/libpayload/include/stddef.h @@ -0,0 +1,21 @@ + +#include + +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned long +#endif +typedef __SIZE_TYPE__ size_t; +/* There is a GCC macro for a size_t type, but not + * for a ssize_t type. Below construct tricks GCC + * into making __SIZE_TYPE__ signed. + */ +#define unsigned signed +typedef __SIZE_TYPE__ ssize_t; +#undef unsigned + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER) + +/* Standard units. */ +#define KiB (1<<10) +#define MiB (1<<20) +#define GiB (1<<30) diff --git a/payloads/libpayload/include/stdlib.h b/payloads/libpayload/include/stdlib.h index cf37c8056f..04acec54e1 100644 --- a/payloads/libpayload/include/stdlib.h +++ b/payloads/libpayload/include/stdlib.h @@ -2,6 +2,7 @@ * This file is part of the libpayload project. * * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright 2013 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,13 +31,20 @@ #ifndef _STDLIB_H #define _STDLIB_H +#include #include +#include + +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1UL) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN_UP(x,a) ALIGN((x),(a)) +#define ALIGN_DOWN(x,a) ((x) & ~((typeof(x))(a)-1UL)) /** * @defgroup malloc Memory allocation functions * @{ */ -#if defined(CONFIG_DEBUG_MALLOC) && !defined(IN_MALLOC_C) +#if defined(CONFIG_LP_DEBUG_MALLOC) && !defined(IN_MALLOC_C) #define free(p) \ ({ \ extern void print_malloc_map(void); \ @@ -101,7 +109,35 @@ printf("PRE memalign\n"); \ print_malloc_map(); \ ptr = memalign(a,s); \ - printf("POST realloc (ptr = %p)\n", ptr); \ + printf("POST memalign (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#define dma_malloc(s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *dma_malloc(size_t); \ + void *ptr; \ + printf("dma_malloc(%u) called from %s:%s:%d...\n", s, __FILE__, \ + __func__, __LINE__);\ + printf("PRE dma_malloc\n"); \ + print_malloc_map(); \ + ptr = dma_malloc(s); \ + printf("POST dma_malloc (ptr = %p)\n", ptr); \ + print_malloc_map(); \ + ptr; \ + }) +#define dma_memalign(a,s) \ + ({ \ + extern void print_malloc_map(void); \ + extern void *dma_memalign(size_t, size_t); \ + void *ptr; \ + printf("dma_memalign(%u, %u) called from %s:%s:%d...\n", a, s, \ + __FILE__, __func__, __LINE__);\ + printf("PRE dma_memalign\n"); \ + print_malloc_map(); \ + ptr = dma_memalign(a,s); \ + printf("POST dma_memalign (ptr = %p)\n", ptr); \ print_malloc_map(); \ ptr; \ }) @@ -111,7 +147,33 @@ void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *memalign(size_t align, size_t size); +void *dma_malloc(size_t size); +void *dma_memalign(size_t align, size_t size); #endif +void init_dma_memory(void *start, u32 size); +int dma_initialized(void); +int dma_coherent(void *ptr); + +static inline void *xmalloc_work(size_t size, const char *file, + const char *func, int line) +{ + void *ret = malloc(size); + if (!ret && size) { + die_work(file, func, line, "Failed to malloc %zu bytes.\n", + size); + } + return ret; +} +#define xmalloc(size) xmalloc_work((size), __FILE__, __FUNCTION__, __LINE__) + +static inline void *xzalloc_work(size_t size, const char *file, + const char *func, int line) +{ + void *ret = xmalloc_work(size, file, func, line); + memset(ret, 0, size); + return ret; +} +#define xzalloc(size) xzalloc_work((size), __FILE__, __FUNCTION__, __LINE__) /** @} */ /** @@ -140,6 +202,10 @@ void srand(unsigned int seed); void halt(void) __attribute__ ((noreturn)); void exit(int status) __attribute__ ((noreturn)); #define abort() halt() /**< Alias for the halt() function */ +#ifdef CONFIG_LP_REMOTEGDB +/* Override abort()/halt() to trap into GDB if it is enabled. */ +#define halt() do { gdb_enter(); halt(); } while (0) +#endif /** @} */ diff --git a/payloads/libpayload/include/storage/storage.h b/payloads/libpayload/include/storage/storage.h index ef61cd287d..a3cebd90bd 100644 --- a/payloads/libpayload/include/storage/storage.h +++ b/payloads/libpayload/include/storage/storage.h @@ -34,7 +34,7 @@ #include -#ifndef CONFIG_STORAGE_64BIT_LBA +#ifndef CONFIG_LP_STORAGE_64BIT_LBA typedef u32 lba_t; #else typedef u64 lba_t; diff --git a/payloads/libpayload/include/string.h b/payloads/libpayload/include/string.h index 9e4f791a7d..b75128a5ee 100644 --- a/payloads/libpayload/include/string.h +++ b/payloads/libpayload/include/string.h @@ -67,6 +67,13 @@ char* strtok(char *str, const char *delim); char* strtok_r(char *str, const char *delim, char **ptr); /** @} */ +/** + * @defgroup string Unicode functions + * @{ + */ +char *utf16le_to_ascii(uint16_t *utf16_string, int maxlen); +/** @} */ + /** * @defgroup string OpenBSD based safe string functions * @{ diff --git a/payloads/libpayload/include/sysinfo.h b/payloads/libpayload/include/sysinfo.h index fd60dc34d9..fa4a098046 100644 --- a/payloads/libpayload/include/sysinfo.h +++ b/payloads/libpayload/include/sysinfo.h @@ -30,11 +30,14 @@ #ifndef _SYSINFO_H #define _SYSINFO_H -/* Allow a maximum of 16 memory range definitions. */ -#define SYSINFO_MAX_MEM_RANGES 16 +/* Maximum number of memory range definitions. */ +#define SYSINFO_MAX_MEM_RANGES 32 /* Allow a maximum of 8 GPIOs */ #define SYSINFO_MAX_GPIOS 8 +/* Up to 10 MAC addresses */ +#define SYSINFO_MAX_MACS 10 + #include struct cb_serial; @@ -63,7 +66,7 @@ struct sysinfo_t { u32 cmos_range_start; u32 cmos_range_end; u32 cmos_checksum_location; -#ifdef CONFIG_CHROMEOS +#ifdef CONFIG_LP_CHROMEOS u32 vbnv_start; u32 vbnv_size; #endif @@ -83,9 +86,11 @@ struct sysinfo_t { struct cb_framebuffer *framebuffer; -#ifdef CONFIG_CHROMEOS +#ifdef CONFIG_LP_CHROMEOS int num_gpios; struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; + int num_macs; + struct mac_address macs[SYSINFO_MAX_MACS]; #endif unsigned long *mbtable; /** Pointer to the multiboot table */ @@ -93,23 +98,43 @@ struct sysinfo_t { struct cb_header *header; struct cb_mainboard *mainboard; -#ifdef CONFIG_CHROMEOS +#ifdef CONFIG_LP_CHROMEOS void *vboot_handoff; u32 vboot_handoff_size; void *vdat_addr; u32 vdat_size; #endif -#ifdef CONFIG_ARCH_X86 +#ifdef CONFIG_LP_ARCH_X86 int x86_rom_var_mtrr_index; #endif void *tstamp_table; void *cbmem_cons; void *mrc_cache; + void *acpi_gnvs; + u32 board_id; + u32 ram_code; + void *wifi_calibration; + uint64_t ramoops_buffer; + uint32_t ramoops_buffer_size; }; extern struct sysinfo_t lib_sysinfo; +/* + * Check if this is an architecture specific coreboot table record and process + * it, if it is. Returns 1 if record type was recognized, 0 otherwise. + */ +int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info); + +/* + * Check if the region in range addr..addr+len contains a 16 byte aligned + * coreboot table. If it does - process the table filling up the sysinfo + * structure with information from the table. Return 0 on success and -1 on + * failure. + */ +int cb_parse_header(void *addr, int len, struct sysinfo_t *info); + #endif diff --git a/payloads/libpayload/include/unistd.h b/payloads/libpayload/include/unistd.h index 1e39aeb058..6b4dcf47e2 100644 --- a/payloads/libpayload/include/unistd.h +++ b/payloads/libpayload/include/unistd.h @@ -32,8 +32,6 @@ #include -typedef ptrdiff_t ssize_t; - int getpagesize(void); #endif diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h index d82ce2710f..0069d07b4a 100644 --- a/payloads/libpayload/include/usb/usb.h +++ b/payloads/libpayload/include/usb/usb.h @@ -30,7 +30,8 @@ #ifndef __USB_H #define __USB_H #include -#include +#include +#include typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir; typedef enum { standard_type = 0, class_type = 1, vendor_type = @@ -39,6 +40,14 @@ typedef enum { standard_type = 0, class_type = 1, vendor_type = typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3 } dev_req_recp; +enum { + DT_DEV = 1, + DT_CFG = 2, + DT_STR = 3, + DT_INTF = 4, + DT_ENDP = 5, +}; + typedef enum { GET_STATUS = 0, CLEAR_FEATURE = 1, @@ -59,90 +68,8 @@ typedef enum { TEST_MODE = 2 } feature_selectors; -typedef struct { - union { - struct { - dev_req_recp req_recp:5; - dev_req_type req_type:2; - dev_req_dir data_dir:1; - } __attribute__ ((packed)); - unsigned char bmRequestType; - } __attribute__ ((packed)); - unsigned char bRequest; - unsigned short wValue; - unsigned short wIndex; - unsigned short wLength; -} __attribute__ ((packed)) dev_req_t; - -struct usbdev_hc; -typedef struct usbdev_hc hci_t; - -struct usbdev; -typedef struct usbdev usbdev_t; - -typedef enum { SETUP, IN, OUT } direction_t; -typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3 -} endpoint_type; - -typedef struct { - usbdev_t *dev; - int endpoint; - direction_t direction; - int toggle; - int maxpacketsize; - endpoint_type type; -} endpoint_t; - - -struct usbdev { - hci_t *controller; - endpoint_t endpoints[32]; - int num_endp; - int address; // usb address - int hub; // hub, device is attached to - int port; // port where device is attached - int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed - u32 quirks; // quirks field. got to love usb - void *data; - u8 *descriptor; - u8 *configuration; - void (*init) (usbdev_t *dev); - void (*destroy) (usbdev_t *dev); - void (*poll) (usbdev_t *dev); -}; - -typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type; - -struct usbdev_hc { - struct usbdev_hc *next; - pcidev_t bus_address; - u32 reg_base; - hc_type type; - usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable - - /* start(): Resume operation. */ - void (*start) (hci_t *controller); - /* stop(): Stop operation but keep controller initialized. */ - void (*stop) (hci_t *controller); - /* reset(): Perform a controller reset. The controller needs to - be (re)initialized afterwards to work (again). */ - void (*reset) (hci_t *controller); - /* init(): Initialize a (previously reset) controller - to a working state. */ - void (*init) (hci_t *controller); - /* shutdown(): Stop operation, detach host controller and shutdown - this driver instance. After calling shutdown() any - other usage of this hci_t* is invalid. */ - void (*shutdown) (hci_t *controller); - - int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize); - int (*control) (usbdev_t *dev, direction_t pid, int dr_length, - void *devreq, int data_length, u8 *data); - void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); - void (*destroy_intr_queue) (endpoint_t *ep, void *queue); - u8* (*poll_intr_queue) (void *queue); - void *instance; -}; +/* SetAddress() recovery interval (USB 2.0 specification 9.2.6.3 */ +#define SET_ADDRESS_MDELAY 2 typedef struct { unsigned char bDescLength; @@ -223,14 +150,123 @@ typedef struct { unsigned short wReportDescriptorLength; } __attribute__ ((packed)) hid_descriptor_t; +typedef struct { + union { + struct { + dev_req_recp req_recp:5; + dev_req_type req_type:2; + dev_req_dir data_dir:1; + } __attribute__ ((packed)); + unsigned char bmRequestType; + } __attribute__ ((packed)); + unsigned char bRequest; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; +} __attribute__ ((packed)) dev_req_t; + +struct usbdev_hc; +typedef struct usbdev_hc hci_t; + +struct usbdev; +typedef struct usbdev usbdev_t; + +typedef enum { SETUP, IN, OUT } direction_t; +typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3 +} endpoint_type; + +typedef struct { + usbdev_t *dev; + int endpoint; + direction_t direction; + int toggle; + int maxpacketsize; + endpoint_type type; + int interval; /* expressed as binary logarithm of the number + of microframes (i.e. t = 125us * 2^interval) */ +} endpoint_t; + +typedef enum { + FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3, +} usb_speed; + +struct usbdev { + hci_t *controller; + endpoint_t endpoints[32]; + int num_endp; + int address; // usb address + int hub; // hub, device is attached to + int port; // port where device is attached + usb_speed speed; + u32 quirks; // quirks field. got to love usb + void *data; + device_descriptor_t *descriptor; + configuration_descriptor_t *configuration; + void (*init) (usbdev_t *dev); + void (*destroy) (usbdev_t *dev); + void (*poll) (usbdev_t *dev); +}; + +typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3, DWC2 = 4} hc_type; + +struct usbdev_hc { + hci_t *next; + uintptr_t reg_base; + hc_type type; + int latest_address; + usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable + + /* start(): Resume operation. */ + void (*start) (hci_t *controller); + /* stop(): Stop operation but keep controller initialized. */ + void (*stop) (hci_t *controller); + /* reset(): Perform a controller reset. The controller needs to + be (re)initialized afterwards to work (again). */ + void (*reset) (hci_t *controller); + /* init(): Initialize a (previously reset) controller + to a working state. */ + void (*init) (hci_t *controller); + /* shutdown(): Stop operation, detach host controller and shutdown + this driver instance. After calling shutdown() any + other usage of this hci_t* is invalid. */ + void (*shutdown) (hci_t *controller); + + int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize); + int (*control) (usbdev_t *dev, direction_t pid, int dr_length, + void *devreq, int data_length, u8 *data); + void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); + void (*destroy_intr_queue) (endpoint_t *ep, void *queue); + u8* (*poll_intr_queue) (void *queue); + void *instance; + + /* set_address(): Tell the usb device its address (xHCI + controllers want to do this by + themselves). Also, allocate the usbdev + structure, initialize enpoint 0 + (including MPS) and return it. */ + usbdev_t *(*set_address) (hci_t *controller, usb_speed speed, + int hubport, int hubaddr); + /* finish_device_config(): Another hook for xHCI, + returns 0 on success. */ + int (*finish_device_config) (usbdev_t *dev); + /* destroy_device(): Finally, destroy all structures that + were allocated during set_address() + and finish_device_config(). */ + void (*destroy_device) (hci_t *controller, int devaddr); +}; + +hci_t *usb_add_mmio_hc(hc_type type, void *bar); hci_t *new_controller (void); void detach_controller (hci_t *controller); void usb_poll (void); -void init_device_entry (hci_t *controller, int num); +usbdev_t *init_device_entry (hci_t *controller, int num); -void set_feature (usbdev_t *dev, int endp, int feature, int rtype); -void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data); -void set_configuration (usbdev_t *dev); +int usb_decode_mps0 (usb_speed speed, u8 bMaxPacketSize0); +int set_feature (usbdev_t *dev, int endp, int feature, int rtype); +int get_status (usbdev_t *dev, int endp, int rtype, int len, void *data); +int get_descriptor (usbdev_t *dev, int rtype, int descType, int descIdx, + void *data, size_t len); +int set_configuration (usbdev_t *dev); int clear_feature (usbdev_t *dev, int endp, int feature, int rtype); int clear_stall (endpoint_t *ep); @@ -240,8 +276,7 @@ void usb_hid_init (usbdev_t *dev); void usb_msc_init (usbdev_t *dev); void usb_generic_init (usbdev_t *dev); -u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType, - int descType, int descIdx, int langID); +int closest_usb2_hub(const usbdev_t *dev, int *const addr, int *const port); static inline unsigned char gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp) @@ -249,8 +284,13 @@ gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp) return (dir << 7) | (type << 5) | recp; } +/* default "set address" handler */ +usbdev_t *generic_set_address (hci_t *controller, usb_speed speed, + int hubport, int hubaddr); + void usb_detach_device(hci_t *controller, int devno); -int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed); +int usb_attach_device(hci_t *controller, int hubaddress, int port, + usb_speed speed); u32 usb_quirk_check(u16 vendor, u16 device); int usb_interface_check(u16 vendor, u16 device); diff --git a/payloads/libpayload/include/usb/usbmsc.h b/payloads/libpayload/include/usb/usbmsc.h index 5c3dadc180..f4562a56d5 100644 --- a/payloads/libpayload/include/usb/usbmsc.h +++ b/payloads/libpayload/include/usb/usbmsc.h @@ -32,13 +32,22 @@ typedef struct { unsigned int blocksize; unsigned int numblocks; - unsigned int protocol; endpoint_t *bulk_in; endpoint_t *bulk_out; - int usbdisk_created; + u8 usbdisk_created; + s8 ready; + u8 lun; + u8 num_luns; void *data; /* For use by consumers of libpayload. */ } usbmsc_inst_t; +/* Possible values for ready field. */ +enum { + USB_MSC_DETACHED = -1, /* Disk detached or out to lunch. */ + USB_MSC_NOT_READY = 0, /* Disk not ready yet -- empty card reader */ + USB_MSC_READY = 1, /* Disk ready to communicate. */ +}; + #define MSC_INST(dev) ((usbmsc_inst_t*)(dev)->data) typedef enum { cbw_direction_data_in = 0x80, cbw_direction_data_out = 0 diff --git a/payloads/libpayload/include/x86/arch/barrier.h b/payloads/libpayload/include/x86/arch/barrier.h new file mode 100644 index 0000000000..5e2cfec186 --- /dev/null +++ b/payloads/libpayload/include/x86/arch/barrier.h @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef __ARCH_BARRIER_H_ +#define __ARCH_BARRIER_H__ + +#define mb() +#define rmb() +#define wmb() + +#endif /* __ARCH_BARRIER_H__ */ diff --git a/payloads/libpayload/include/x86/arch/cache.h b/payloads/libpayload/include/x86/arch/cache.h new file mode 100644 index 0000000000..ffefcdbe19 --- /dev/null +++ b/payloads/libpayload/include/x86/arch/cache.h @@ -0,0 +1,46 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.h: Cache maintenance API for x86 + */ + +#ifndef __ARCH_CACHE_H__ +#define __ARCH_CACHE_H__ + +/* NOOPs mirroring ARM's cache API, since x86 devices usually cache snoop */ +#define dmb() +#define dsb() +#define dcache_clean_all() +#define dcache_clean_by_mva(addr, len) +#define dcache_invalidate_all() +#define dcache_invalidate_by_mva(addr, len) +#define dcache_clean_invalidate_all() +#define dcache_clean_invalidate_by_mva(addr, len) +#define cache_sync_instructions() + +#endif diff --git a/payloads/libpayload/include/x86/arch/exception.h b/payloads/libpayload/include/x86/arch/exception.h new file mode 100644 index 0000000000..fe222aa4f2 --- /dev/null +++ b/payloads/libpayload/include/x86/arch/exception.h @@ -0,0 +1,90 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H + +#include + +void exception_init_asm(void); +void exception_dispatch(void); + +struct exception_state +{ + /* Careful: x86/gdb.c currently relies on the size and order of regs. */ + struct { + u32 eax; + u32 ecx; + u32 edx; + u32 ebx; + u32 esp; + u32 ebp; + u32 esi; + u32 edi; + u32 eip; + u32 eflags; + u32 cs; + u32 ss; + u32 ds; + u32 es; + u32 fs; + u32 gs; + } regs; + u32 error_code; + u32 vector; +} __attribute__((packed)); +extern struct exception_state *exception_state; + +extern u32 exception_stack[]; +extern u32 *exception_stack_end; + +enum { + EXC_DE = 0, /* Divide by zero */ + EXC_DB = 1, /* Debug */ + EXC_NMI = 2, /* Non maskable interrupt */ + EXC_BP = 3, /* Breakpoint */ + EXC_OF = 4, /* Overflow */ + EXC_BR = 5, /* Bound range */ + EXC_UD = 6, /* Invalid opcode */ + EXC_NM = 7, /* Device not available */ + EXC_DF = 8, /* Double fault */ + EXC_TS = 10, /* Invalid TSS */ + EXC_NP = 11, /* Segment not present */ + EXC_SS = 12, /* Stack */ + EXC_GP = 13, /* General protection */ + EXC_PF = 14, /* Page fault */ + EXC_MF = 16, /* x87 floating point */ + EXC_AC = 17, /* Alignment check */ + EXC_MC = 18, /* Machine check */ + EXC_XF = 19, /* SIMD floating point */ + EXC_SX = 30, /* Security */ + EXC_COUNT +}; + +#endif diff --git a/payloads/libpayload/include/x86/arch/io.h b/payloads/libpayload/include/x86/arch/io.h index 31a8f88410..ff7c2310fb 100644 --- a/payloads/libpayload/include/x86/arch/io.h +++ b/payloads/libpayload/include/x86/arch/io.h @@ -31,15 +31,15 @@ #ifndef _ARCH_IO_H #define _ARCH_IO_H -#define readb(_a) (*(volatile unsigned char *) (_a)) -#define readw(_a) (*(volatile unsigned short *) (_a)) -#define readl(_a) (*(volatile unsigned long *) (_a)) +#define readb(_a) (*(volatile const unsigned char *) (_a)) +#define readw(_a) (*(volatile const unsigned short *) (_a)) +#define readl(_a) (*(volatile const unsigned int *) (_a)) #define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v)) #define writew(_v, _a) (*(volatile unsigned short *) (_a) = (_v)) -#define writel(_v, _a) (*(volatile unsigned long *) (_a) = (_v)) +#define writel(_v, _a) (*(volatile unsigned int *) (_a) = (_v)) -static inline unsigned long inl(int port) +static inline unsigned int inl(int port) { unsigned long val; __asm__ __volatile__("inl %w1, %0" : "=a"(val) : "Nd"(port)); @@ -60,7 +60,7 @@ static inline unsigned char inb(int port) return val; } -static inline void outl(unsigned long val, int port) +static inline void outl(unsigned int val, int port) { __asm__ __volatile__("outl %0, %w1" : : "a"(val), "Nd"(port)); } diff --git a/payloads/libpayload/include/x86/arch/types.h b/payloads/libpayload/include/x86/arch/types.h index bb4025714f..1bd815bb44 100644 --- a/payloads/libpayload/include/x86/arch/types.h +++ b/payloads/libpayload/include/x86/arch/types.h @@ -53,9 +53,6 @@ typedef signed long long s64; typedef long time_t; typedef long suseconds_t; -typedef unsigned long size_t; -typedef long ssize_t; - #ifndef NULL #define NULL ((void *)0) #endif diff --git a/payloads/libpayload/libc/Makefile.inc b/payloads/libpayload/libc/Makefile.inc index eef4f46a7e..bd2a6f7595 100644 --- a/payloads/libpayload/libc/Makefile.inc +++ b/payloads/libpayload/libc/Makefile.inc @@ -28,13 +28,16 @@ ## SUCH DAMAGE. ## -libc-$(CONFIG_LIBC) += malloc.c printf.c console.c string.c -libc-$(CONFIG_LIBC) += memory.c ctype.c ipchecksum.c lib.c -libc-$(CONFIG_LIBC) += rand.c time.c exec.c -libc-$(CONFIG_LIBC) += readline.c getopt_long.c sysinfo.c -libc-$(CONFIG_LIBC) += args.c strings.c -libc-$(CONFIG_LIBC) += strlcpy.c -libc-$(CONFIG_LIBC) += qsort.c +libc-$(CONFIG_LP_LIBC) += malloc.c printf.c console.c string.c +libc-$(CONFIG_LP_LIBC) += memory.c ctype.c ipchecksum.c lib.c +libc-$(CONFIG_LP_LIBC) += rand.c time.c exec.c +libc-$(CONFIG_LP_LIBC) += readline.c getopt_long.c sysinfo.c +libc-$(CONFIG_LP_LIBC) += args.c strings.c +libc-$(CONFIG_LP_LIBC) += strlcpy.c +libc-$(CONFIG_LP_LIBC) += qsort.c +libc-$(CONFIG_LP_LIBC) += hexdump.c +libc-$(CONFIG_LP_LIBC) += die.c +libc-$(CONFIG_LP_LIBC) += coreboot.c # should be moved to coreboot directory -libc-$(CONFIG_LAR) += lar.c +libc-$(CONFIG_LP_LAR) += lar.c diff --git a/payloads/libpayload/libc/console.c b/payloads/libpayload/libc/console.c index fce6de4fa0..7717daf5d1 100644 --- a/payloads/libpayload/libc/console.c +++ b/payloads/libpayload/libc/console.c @@ -33,67 +33,118 @@ struct console_output_driver *console_out; struct console_input_driver *console_in; +static console_input_type last_getchar_input_type; + +static int output_driver_exists(struct console_output_driver *out) +{ + struct console_output_driver *head = console_out; + + while (head) { + if (head == out) + return 1; + head = head->next; + } + + return 0; +} + +static int input_driver_exists(struct console_input_driver *in) +{ + struct console_input_driver *head = console_in; + + while (head) { + if (head == in) + return 1; + head = head->next; + } + + return 0; +} void console_add_output_driver(struct console_output_driver *out) { + die_if(!out->putchar && !out->write, "Need at least one output func\n"); + /* Check if this driver was already added to the console list */ + if (output_driver_exists(out)) + return; out->next = console_out; console_out = out; } void console_add_input_driver(struct console_input_driver *in) { + /* Check if this driver was already added to the console list */ + if (input_driver_exists(in)) + return; in->next = console_in; console_in = in; } +/* + * For when you really need to silence an output driver (e.g. to avoid ugly + * recursions). Takes the pointer of either of the two output functions, since + * the struct console_output_driver itself is often static and inaccessible. + */ +int console_remove_output_driver(void *function) +{ + struct console_output_driver **out; + for (out = &console_out; *out; out = &(*out)->next) + if ((*out)->putchar == function || (*out)->write == function) { + *out = (*out)->next; + return 1; + } + + return 0; +} + void console_init(void) { -#ifdef CONFIG_VIDEO_CONSOLE +#ifdef CONFIG_LP_VIDEO_CONSOLE video_console_init(); #endif -#ifdef CONFIG_SERIAL_CONSOLE - serial_init(); +#ifdef CONFIG_LP_SERIAL_CONSOLE + serial_console_init(); #endif -#ifdef CONFIG_PC_KEYBOARD +#ifdef CONFIG_LP_PC_KEYBOARD keyboard_init(); #endif -#ifdef CONFIG_CBMEM_CONSOLE +#ifdef CONFIG_LP_CBMEM_CONSOLE cbmem_console_init(); #endif } -static void device_putchar(unsigned char c) +void console_write(const void *buffer, size_t count) { + const char *ptr; struct console_output_driver *out; for (out = console_out; out != 0; out = out->next) - out->putchar(c); + if (out->write) + out->write(buffer, count); + else + for (ptr = buffer; (void *)ptr < buffer + count; ptr++) + out->putchar(*ptr); } -int putchar(unsigned int c) +int putchar(unsigned int i) { - c &= 0xff; - if (c == '\n') - device_putchar('\r'); - device_putchar(c); - return c; + unsigned char c = (unsigned char)i; + console_write(&c, 1); + return (int)c; } int puts(const char *s) { - int n = 0; + size_t size = strlen(s); - while (*s) { - putchar(*s++); - n++; - } + console_write(s, size); putchar('\n'); - return n + 1; + return size + 1; } int havekey(void) { -#ifdef CONFIG_USB +#ifdef CONFIG_LP_USB usb_poll(); #endif struct console_input_driver *in; @@ -110,13 +161,15 @@ int havekey(void) int getchar(void) { while (1) { -#ifdef CONFIG_USB +#ifdef CONFIG_LP_USB usb_poll(); #endif struct console_input_driver *in; for (in = console_in; in != 0; in = in->next) - if (in->havechar()) + if (in->havechar()) { + last_getchar_input_type = in->input_type; return in->getchar(); + } } } @@ -135,3 +188,8 @@ int getchar_timeout(int *ms) return 0; } + +console_input_type last_key_input_type(void) +{ + return last_getchar_input_type; +} diff --git a/payloads/libpayload/arch/armv7/coreboot.c b/payloads/libpayload/libc/coreboot.c similarity index 68% rename from payloads/libpayload/arch/armv7/coreboot.c rename to payloads/libpayload/libc/coreboot.c index 9545f29d68..fd56aa640c 100644 --- a/payloads/libpayload/arch/armv7/coreboot.c +++ b/payloads/libpayload/libc/coreboot.c @@ -31,12 +31,12 @@ #include #include #include +#include /* - * Some of this is x86 specific, and the rest of it is generic. Right now, - * since we only support x86, we'll avoid trying to make lots of infrastructure - * we don't need. If in the future, we want to use coreboot on some other - * architecture, then take out the generic parsing code and move it elsewhere. + * The code in this file applies to all coreboot architectures. Some coreboot + * table tags are architecture specific, they are handled by their respective + * cb_parse_arch_specific() functions. */ /* === Parsing code === */ @@ -56,7 +56,7 @@ static void cb_parse_memory(void *ptr, struct sysinfo_t *info) for (i = 0; i < count; i++) { struct cb_memory_range *range = MEM_RANGE_PTR(mem, i); -#ifdef CONFIG_MEMMAP_RAM_ONLY +#ifdef CONFIG_LP_MEMMAP_RAM_ONLY if (range->type != CB_MEM_RAM) continue; #endif @@ -78,13 +78,21 @@ static void cb_parse_serial(void *ptr, struct sysinfo_t *info) info->serial = ((struct cb_serial *)ptr); } -#ifdef CONFIG_CHROMEOS +#ifdef CONFIG_LP_CHROMEOS +static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_range *vbho = (struct cb_range *)ptr; + + info->vboot_handoff = (void *)(uintptr_t)vbho->range_start; + info->vboot_handoff_size = vbho->range_size; +} + static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) { - struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; + struct cb_range *vbnv = (struct cb_range *)ptr; - info->vbnv_start = vbnv->vbnv_start; - info->vbnv_size = vbnv->vbnv_size; + info->vbnv_start = vbnv->range_start; + info->vbnv_size = vbnv->range_size; } static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) @@ -101,11 +109,25 @@ static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) { - struct cb_vdat *vdat = (struct cb_vdat *) ptr; + struct cb_range *vdat = (struct cb_range *) ptr; - info->vdat_addr = phys_to_virt(vdat->vdat_addr); - info->vdat_size = vdat->vdat_size; + info->vdat_addr = phys_to_virt(vdat->range_start); + info->vdat_size = vdat->range_size; } + +static void cb_parse_mac_addresses(unsigned char *ptr, + struct sysinfo_t *info) +{ + struct cb_macs *macs = (struct cb_macs *)ptr; + int i; + + info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ? + macs->count : ARRAY_SIZE(info->macs); + + for (i = 0; i < info->num_macs; i++) + info->macs[i] = macs->mac_addrs[i]; +} + #endif static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) @@ -120,13 +142,25 @@ static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) info->cbmem_cons = phys_to_virt(cbmem->cbmem_tab); } -static void cb_parse_mrc_cache(unsigned char *ptr, struct sysinfo_t *info) +static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info) { struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; - info->mrc_cache = phys_to_virt(cbmem->cbmem_tab); + info->acpi_gnvs = phys_to_virt(cbmem->cbmem_tab); } -#ifdef CONFIG_NVRAM +static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_board_id *const cbbid = (struct cb_board_id *)ptr; + info->board_id = cbbid->board_id; +} + +static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr; + info->ram_code = ram_code->ram_code; +} + +#ifdef CONFIG_LP_NVRAM static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info) { /* ptr points to a coreboot table entry and is already virtual */ @@ -142,7 +176,7 @@ static void cb_parse_checksum(void *ptr, struct sysinfo_t *info) } #endif -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) { /* ptr points to a coreboot table entry and is already virtual */ @@ -155,7 +189,21 @@ static void cb_parse_string(unsigned char *ptr, char **info) *info = (char *)((struct cb_string *)ptr)->string; } -static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + info->wifi_calibration = phys_to_virt(cbmem->cbmem_tab); +} + +static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info) +{ + struct cb_range *ramoops = (struct cb_range *)ptr; + + info->ramoops_buffer = ramoops->range_start; + info->ramoops_buffer_size = ramoops->range_size; +} + +int cb_parse_header(void *addr, int len, struct sysinfo_t *info) { struct cb_header *header; unsigned char *ptr = addr; @@ -172,19 +220,27 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) if (i >= len) return -1; - if (!header->table_bytes) - return 0; - /* Make sure the checksums match. */ if (ipchksum((u16 *) header, sizeof(*header)) != 0) return -1; + if (!header->table_bytes) + return 0; + if (ipchksum((u16 *) (ptr + sizeof(*header)), header->table_bytes) != header->table_checksum) return -1; info->header = header; + /* + * Board straps represented by numerical values are small numbers. + * Preset them to an invalid value in case the firmware does not + * supply the info. + */ + info->board_id = ~0; + info->ram_code = ~0; + /* Now, walk the tables. */ ptr += header->header_bytes; @@ -194,7 +250,8 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) /* We only care about a few tags here (maybe more later). */ switch (rec->tag) { case CB_TAG_FORWARD: - forward = phys_to_virt((void *)(unsigned long)((struct cb_forward *)rec)->forward); + forward = phys_to_virt((void *)(unsigned long) + ((struct cb_forward *)rec)->forward); return cb_parse_header(forward, len, info); continue; case CB_TAG_MEMORY: @@ -233,7 +290,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_ASSEMBLER: cb_parse_string(ptr, &info->assembler); break; -#ifdef CONFIG_NVRAM +#ifdef CONFIG_LP_NVRAM case CB_TAG_CMOS_OPTION_TABLE: cb_parse_optiontable(ptr, info); break; @@ -241,7 +298,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) cb_parse_checksum(ptr, info); break; #endif -#ifdef CONFIG_COREBOOT_VIDEO_CONSOLE +#ifdef CONFIG_LP_COREBOOT_VIDEO_CONSOLE // FIXME we should warn on serial if coreboot set up a // framebuffer buf the payload does not know about it. case CB_TAG_FRAMEBUFFER: @@ -250,7 +307,8 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) #endif case CB_TAG_MAINBOARD: info->mainboard = (struct cb_mainboard *)ptr; -#ifdef CONFIG_CHROMEOS + break; +#ifdef CONFIG_LP_CHROMEOS case CB_TAG_GPIO: cb_parse_gpios(ptr, info); break; @@ -260,6 +318,12 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_VBNV: cb_parse_vbnv(ptr, info); break; + case CB_TAG_VBOOT_HANDOFF: + cb_parse_vboot_handoff(ptr, info); + break; + case CB_TAG_MAC_ADDRS: + cb_parse_mac_addresses(ptr, info); + break; #endif case CB_TAG_TIMESTAMPS: cb_parse_tstamp(ptr, info); @@ -267,23 +331,28 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_CBMEM_CONSOLE: cb_parse_cbmem_cons(ptr, info); break; - case CB_TAG_MRC_CACHE: - cb_parse_mrc_cache(ptr, info); + case CB_TAG_ACPI_GNVS: + cb_parse_acpi_gnvs(ptr, info); + break; + case CB_TAG_BOARD_ID: + cb_parse_board_id(ptr, info); + break; + case CB_TAG_RAM_CODE: + cb_parse_ram_code(ptr, info); + break; + case CB_TAG_WIFI_CALIBRATION: + cb_parse_wifi_calibration(ptr, info); + break; + case CB_TAG_RAM_OOPS: + cb_parse_ramoops(ptr, info); + break; + default: + cb_parse_arch_specific(rec, info); break; } ptr += rec->size; } - return 1; -} - -/* == Architecture specific == */ -/* FIXME put in actual address range */ - -int get_coreboot_info(struct sysinfo_t *info) -{ - int ret = cb_parse_header(phys_to_virt(0xbff00000), 0x100000, info); - - return (ret == 1) ? 0 : -1; + return 0; } diff --git a/payloads/libpayload/libc/die.c b/payloads/libpayload/libc/die.c new file mode 100644 index 0000000000..62e98b3b9b --- /dev/null +++ b/payloads/libpayload/libc/die.c @@ -0,0 +1,42 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +void die_work(const char *file, const char *func, const int line, + const char *fmt, ...) +{ + va_list args; + + printf("%s:%d %s(): ", file, line, func); + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + abort(); +} diff --git a/payloads/libpayload/libc/exec.c b/payloads/libpayload/libc/exec.c index 13a1e5a8cd..4360bd595c 100644 --- a/payloads/libpayload/libc/exec.c +++ b/payloads/libpayload/libc/exec.c @@ -30,7 +30,7 @@ #include #include -#ifdef CONFIG_ARCH_X86 +#ifdef CONFIG_LP_ARCH_X86 extern void i386_do_exec(long addr, int argc, char **argv, int *ret); #endif @@ -46,7 +46,7 @@ int exec(long addr, int argc, char **argv) { int val = -1; -#ifdef CONFIG_ARCH_X86 +#ifdef CONFIG_LP_ARCH_X86 i386_do_exec(addr, argc, argv, &val); #endif return val; diff --git a/payloads/libpayload/libc/hexdump.c b/payloads/libpayload/libc/hexdump.c new file mode 100644 index 0000000000..1b4772370c --- /dev/null +++ b/payloads/libpayload/libc/hexdump.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +void hexdump(unsigned long memory, int length) +{ + int i; + uint8_t *m; + int all_zero = 0; + + m = (uint8_t *)memory; + + for (i = 0; i < length; i += 16) { + int j; + + all_zero++; + for (j = 0; j < 16; j++) { + if(m[i+j] != 0) { + all_zero = 0; + break; + } + } + + if (all_zero < 2) { + printf("%08lx:", memory + i); + for (j = 0; j < 16; j++) + printf(" %02x", m[i+j]); + printf(" "); + for (j = 0; j < 16; j++) + printf("%c", isprint(m[i+j]) ? m[i+j] : '.'); + printf("\n"); + } else if (all_zero == 2) { + printf("...\n"); + } + } +} + + diff --git a/payloads/libpayload/libc/malloc.c b/payloads/libpayload/libc/malloc.c index 7756a3bc49..d538e62f6e 100644 --- a/payloads/libpayload/libc/malloc.c +++ b/payloads/libpayload/libc/malloc.c @@ -44,11 +44,29 @@ #define IN_MALLOC_C #include +#include + +struct memory_type { + void *start; + void *end; + struct align_region_t* align_regions; +#ifdef CONFIG_LP_DEBUG_MALLOC + int magic_initialized; + size_t minimal_free; + const char *name; +#endif +}; extern char _heap, _eheap; /* Defined in the ldscript. */ -static void *hstart = (void *)&_heap; -static void *hend = (void *)&_eheap; +static struct memory_type default_type = + { (void *)&_heap, (void *)&_eheap, NULL +#ifdef CONFIG_LP_DEBUG_MALLOC + , 0, 0, "HEAP" +#endif + }; +static struct memory_type *const heap = &default_type; +static struct memory_type *dma = &default_type; typedef unsigned int hdrtype_t; @@ -69,28 +87,51 @@ typedef unsigned int hdrtype_t; #define IS_FREE(_h) (((_h) & (MAGIC | FLAG_FREE)) == (MAGIC | FLAG_FREE)) #define HAS_MAGIC(_h) (((_h) & MAGIC) == MAGIC) -static int free_aligned(void* addr); +static int free_aligned(void* addr, struct memory_type *type); void print_malloc_map(void); -#ifdef CONFIG_DEBUG_MALLOC -static int heap_initialized = 0; -static int minimal_free = 0; -#endif - -static void setup(hdrtype_t volatile *start, int size) +void init_dma_memory(void *start, u32 size) { - *start = FREE_BLOCK(size); + if (dma_initialized()) { + printf("ERROR: %s called twice!\n", __func__); + return; + } -#ifdef CONFIG_DEBUG_MALLOC - heap_initialized = 1; - minimal_free = size; + /* + * DMA memory might not be zeroed by Coreboot on stage loading, so make + * sure we clear the magic cookie from last boot. + */ + *(hdrtype_t *)start = 0; + + dma = malloc(sizeof(*dma)); + dma->start = start; + dma->end = start + size; + dma->align_regions = NULL; + +#ifdef CONFIG_LP_DEBUG_MALLOC + dma->minimal_free = 0; + dma->magic_initialized = 0; + dma->name = "DMA"; + + printf("Initialized cache-coherent DMA memory at [%p:%p]\n", start, start + size); #endif } -static void *alloc(int len) +int dma_initialized() +{ + return dma != heap; +} + +/* For boards that don't initialize DMA we assume all locations are coherent */ +int dma_coherent(void *ptr) +{ + return !dma_initialized() || (dma->start <= ptr && dma->end > ptr); +} + +static void *alloc(int len, struct memory_type *type) { hdrtype_t header; - hdrtype_t volatile *ptr = (hdrtype_t volatile *) hstart; + hdrtype_t volatile *ptr = (hdrtype_t volatile *)type->start; /* Align the size. */ len = (len + 3) & ~3; @@ -99,8 +140,14 @@ static void *alloc(int len) return (void *)NULL; /* Make sure the region is setup correctly. */ - if (!HAS_MAGIC(*ptr)) - setup(ptr, (int)((&_eheap - &_heap) - HDRSIZE)); + if (!HAS_MAGIC(*ptr)) { + size_t size = (type->end - type->start) - HDRSIZE; + *ptr = FREE_BLOCK(size); +#ifdef CONFIG_LP_DEBUG_MALLOC + type->magic_initialized = 1; + type->minimal_free = size; +#endif + } /* Find some free space. */ do { @@ -116,7 +163,7 @@ static void *alloc(int len) if (header & FLAG_FREE) { if (len <= size) { - hdrtype_t volatile *nptr = (hdrtype_t volatile *)((int)ptr + HDRSIZE + len); + hdrtype_t volatile *nptr = (hdrtype_t volatile *)((uintptr_t)ptr + HDRSIZE + len); int nsize = size - (HDRSIZE + len); /* If there is still room in this block, @@ -135,23 +182,23 @@ static void *alloc(int len) *ptr = USED_BLOCK(size); } - return (void *)((int)ptr + HDRSIZE); + return (void *)((uintptr_t)ptr + HDRSIZE); } } - ptr = (hdrtype_t volatile *)((int)ptr + HDRSIZE + size); + ptr = (hdrtype_t volatile *)((uintptr_t)ptr + HDRSIZE + size); - } while (ptr < (hdrtype_t *) hend); + } while (ptr < (hdrtype_t *) type->end); /* Nothing available. */ return (void *)NULL; } -static void _consolidate(void) +static void _consolidate(struct memory_type *type) { - void *ptr = hstart; + void *ptr = type->start; - while (ptr < hend) { + while (ptr < type->end) { void *nptr; hdrtype_t hdr = *((hdrtype_t *) ptr); unsigned int size = 0; @@ -164,7 +211,7 @@ static void _consolidate(void) size = SIZE(hdr); nptr = ptr + HDRSIZE + SIZE(hdr); - while (nptr < hend) { + while (nptr < type->end) { hdrtype_t nhdr = *((hdrtype_t *) nptr); if (!(IS_FREE(nhdr))) @@ -185,15 +232,18 @@ static void _consolidate(void) void free(void *ptr) { hdrtype_t hdr; - - if (free_aligned(ptr)) return; - - ptr -= HDRSIZE; + struct memory_type *type = heap; /* Sanity check. */ - if (ptr < hstart || ptr >= hend) - return; + if (ptr < type->start || ptr >= type->end) { + type = dma; + if (ptr < type->start || ptr >= type->end) + return; + } + if (free_aligned(ptr, type)) return; + + ptr -= HDRSIZE; hdr = *((hdrtype_t *) ptr); /* Not our header (we're probably poisoned). */ @@ -205,18 +255,23 @@ void free(void *ptr) return; *((hdrtype_t *) ptr) = FREE_BLOCK(SIZE(hdr)); - _consolidate(); + _consolidate(type); } void *malloc(size_t size) { - return alloc(size); + return alloc(size, heap); +} + +void *dma_malloc(size_t size) +{ + return alloc(size, dma); } void *calloc(size_t nmemb, size_t size) { size_t total = nmemb * size; - void *ptr = alloc(total); + void *ptr = alloc(total, heap); if (ptr) memset(ptr, 0, total); @@ -228,15 +283,19 @@ void *realloc(void *ptr, size_t size) { void *ret, *pptr; unsigned int osize; + struct memory_type *type = heap; if (ptr == NULL) - return alloc(size); + return alloc(size, type); pptr = ptr - HDRSIZE; if (!HAS_MAGIC(*((hdrtype_t *) pptr))) return NULL; + if (ptr < type->start || ptr >= type->end) + type = dma; + /* Get the original size of the block. */ osize = SIZE(*((hdrtype_t *) pptr)); @@ -246,7 +305,7 @@ void *realloc(void *ptr, size_t size) * reallocated the new space. */ free(ptr); - ret = alloc(size); + ret = alloc(size, type); /* * if ret == NULL, then doh - failure. @@ -281,14 +340,12 @@ struct align_region_t struct align_region_t *next; }; -static struct align_region_t* align_regions = 0; - -static struct align_region_t *allocate_region(int alignment, int num_elements) +static struct align_region_t *allocate_region(int alignment, int num_elements, struct memory_type *type) { struct align_region_t *new_region; -#ifdef CONFIG_DEBUG_MALLOC +#ifdef CONFIG_LP_DEBUG_MALLOC printf("%s(old align_regions=%p, alignment=%u, num_elements=%u)\n", - __func__, align_regions, alignment, num_elements); + __func__, type->align_regions, alignment, num_elements); #endif new_region = malloc(sizeof(struct align_region_t)); @@ -296,24 +353,24 @@ static struct align_region_t *allocate_region(int alignment, int num_elements) if (!new_region) return NULL; new_region->alignment = alignment; - new_region->start = malloc((num_elements+1) * alignment + num_elements); + new_region->start = alloc((num_elements+1) * alignment + num_elements, type); if (!new_region->start) { free(new_region); return NULL; } - new_region->start_data = (void*)((u32)(new_region->start + num_elements + alignment - 1) & (~(alignment-1))); + new_region->start_data = (void*)((uintptr_t)(new_region->start + num_elements + alignment - 1) & (~(alignment-1))); new_region->size = num_elements * alignment; new_region->free = num_elements; - new_region->next = align_regions; + new_region->next = type->align_regions; memset(new_region->start, 0, num_elements); - align_regions = new_region; + type->align_regions = new_region; return new_region; } -static int free_aligned(void* addr) +static int free_aligned(void* addr, struct memory_type *type) { - struct align_region_t *reg = align_regions; + struct align_region_t *reg = type->align_regions; while (reg != 0) { if ((addr >= reg->start_data) && (addr < reg->start_data + reg->size)) @@ -333,22 +390,22 @@ static int free_aligned(void* addr) return 0; } -void *memalign(size_t align, size_t size) +static void *alloc_aligned(size_t align, size_t size, struct memory_type *type) { if (size == 0) return 0; - if (align_regions == 0) { - align_regions = malloc(sizeof(struct align_region_t)); - if (align_regions == NULL) + if (type->align_regions == 0) { + type->align_regions = malloc(sizeof(struct align_region_t)); + if (type->align_regions == NULL) return NULL; - memset(align_regions, 0, sizeof(struct align_region_t)); + memset(type->align_regions, 0, sizeof(struct align_region_t)); } - struct align_region_t *reg = align_regions; + struct align_region_t *reg = type->align_regions; look_further: while (reg != 0) { if ((reg->alignment == align) && (reg->free >= (size + align - 1)/align)) { -#ifdef CONFIG_DEBUG_MALLOC +#ifdef CONFIG_LP_DEBUG_MALLOC printf(" found memalign region. %x free, %x required\n", reg->free, (size + align - 1)/align); #endif break; @@ -357,13 +414,13 @@ look_further: } if (reg == 0) { -#ifdef CONFIG_DEBUG_MALLOC +#ifdef CONFIG_LP_DEBUG_MALLOC printf(" need to allocate a new memalign region\n"); #endif /* get align regions */ - reg = allocate_region(align, (size<1024)?(1024/align):(((size-1)/align)+1)); -#ifdef CONFIG_DEBUG_MALLOC - printf(" ... returned %p\n", align_regions); + reg = allocate_region(align, (size<1024)?(1024/align):(((size-1)/align)+1), type); +#ifdef CONFIG_LP_DEBUG_MALLOC + printf(" ... returned %p\n", reg); #endif } if (reg == 0) { @@ -397,28 +454,43 @@ look_further: goto look_further; // end condition is once a new region is allocated - it always has enough space } +void *memalign(size_t align, size_t size) +{ + return alloc_aligned(align, size, heap); +} + +void *dma_memalign(size_t align, size_t size) +{ + return alloc_aligned(align, size, dma); +} + /* This is for debugging purposes. */ -#ifdef CONFIG_DEBUG_MALLOC +#ifdef CONFIG_LP_DEBUG_MALLOC void print_malloc_map(void) { - void *ptr = hstart; - int free_memory = 0; + struct memory_type *type = heap; + void *ptr; + int free_memory; - while (ptr < hend) { +again: + ptr = type->start; + free_memory = 0; + + while (ptr < type->end) { hdrtype_t hdr = *((hdrtype_t *) ptr); if (!HAS_MAGIC(hdr)) { - if (heap_initialized) - printf("Poisoned magic - we're toast\n"); + if (type->magic_initialized) + printf("%s: Poisoned magic - we're toast\n", type->name); else - printf("No magic yet - going to initialize\n"); + printf("%s: No magic yet - going to initialize\n", type->name); break; } /* FIXME: Verify the size of the block. */ - printf("%x: %s (%x bytes)\n", - (unsigned int)(ptr - hstart), + printf("%s %x: %s (%x bytes)\n", type->name, + (unsigned int)(ptr - type->start), hdr & FLAG_FREE ? "FREE" : "USED", SIZE(hdr)); if (hdr & FLAG_FREE) @@ -427,9 +499,14 @@ void print_malloc_map(void) ptr += HDRSIZE + SIZE(hdr); } - if (free_memory && (minimal_free > free_memory)) - minimal_free = free_memory; - printf("Maximum memory consumption: %d bytes\n", - (unsigned int)(&_eheap - &_heap) - HDRSIZE - minimal_free); + if (free_memory && (type->minimal_free > free_memory)) + type->minimal_free = free_memory; + printf("%s: Maximum memory consumption: %u bytes\n", type->name, + (type->end - type->start) - HDRSIZE - type->minimal_free); + + if (type != dma) { + type = dma; + goto again; + } } #endif diff --git a/payloads/libpayload/libc/memory.c b/payloads/libpayload/libc/memory.c index 12d7e33dfd..aec60e4eb8 100644 --- a/payloads/libpayload/libc/memory.c +++ b/payloads/libpayload/libc/memory.c @@ -35,12 +35,22 @@ static void *default_memset(void *s, int c, size_t n) { - char *os = s; + size_t i; + void *ret = s; + unsigned long w = c & 0xff; - while (n--) - *(os++) = c; + for (i = 1; i < sizeof(unsigned long); i <<= 1) + w = (w << (i * 8)) | w; - return s; + for (i = 0; i < n / sizeof(unsigned long); i++) + ((unsigned long *)s)[i] = w; + + s += i * sizeof(unsigned long); + + for (i = 0; i < n % sizeof(unsigned long); i++) + ((u8 *)s)[i] = (u8)c; + + return ret; } void *memset(void *s, int c, size_t n) @@ -48,18 +58,17 @@ void *memset(void *s, int c, size_t n) static void *default_memcpy(void *dst, const void *src, size_t n) { - int i; + size_t i; void *ret = dst; - for(i = 0; i < n % sizeof(unsigned long); i++) - ((unsigned char *) dst)[i] = ((unsigned char *) src)[i]; - - n -= i; - src += i; - dst += i; - for(i = 0; i < n / sizeof(unsigned long); i++) - ((unsigned long *) dst)[i] = ((unsigned long *) src)[i]; + ((unsigned long *)dst)[i] = ((unsigned long *)src)[i]; + + src += i * sizeof(unsigned long); + dst += i * sizeof(unsigned long); + + for(i = 0; i < n % sizeof(unsigned long); i++) + ((u8 *)dst)[i] = ((u8 *)src)[i]; return ret; } @@ -69,8 +78,7 @@ void *memcpy(void *dst, const void *src, size_t n) static void *default_memmove(void *dst, const void *src, size_t n) { - int i; - unsigned long offs; + size_t i, offs; if (src > dst) return memcpy(dst, src, n); @@ -78,8 +86,7 @@ static void *default_memmove(void *dst, const void *src, size_t n) offs = n - (n % sizeof(unsigned long)); for (i = (n % sizeof(unsigned long)) - 1; i >= 0; i--) - ((unsigned char *)dst)[i + offs] = - ((unsigned char *)src)[i + offs]; + ((u8 *)dst)[i + offs] = ((u8 *)src)[i + offs]; for (i = n / sizeof(unsigned long) - 1; i >= 0; i--) ((unsigned long *)dst)[i] = ((unsigned long *)src)[i]; @@ -95,17 +102,27 @@ void *memmove(void *dst, const void *src, size_t n) * * @param s1 Pointer to the first area to compare. * @param s2 Pointer to the second area to compare. - * @param len Size of the first area in bytes (both must have the same length). - * @return If len is 0, return zero. If the areas match, return zero. - * Otherwise return non-zero. + * @param n Size of the first area in bytes (both must have the same length). + * @return If n is 0, return zero. Otherwise, return a value less than, equal + * to, or greater than zero if s1 is found less than, equal to, or + * greater than s2 respectively. */ -static int default_memcmp(const void *s1, const void *s2, size_t len) +static int default_memcmp(const void *s1, const void *s2, size_t n) { - for (; len && *(char *)s1++ == *(char *)s2++; len--) ; - return len; + size_t i; + + for (i = 0; i < n / sizeof(unsigned long); i++) + if (((unsigned long *)s1)[i] != ((unsigned long *)s2)[i]) + break; /* fall through to find differing byte */ + + for (i *= sizeof(unsigned long); i < n; i++) + if (((u8 *)s1)[i] != ((u8 *)s2)[i]) + return ((u8 *)s1)[i] - ((u8 *)s2)[i]; + + return 0; } -int memcmp(const void *s1, const void *s2, size_t len) +int memcmp(const void *s1, const void *s2, size_t n) __attribute__((weak, alias("default_memcmp"))); diff --git a/payloads/libpayload/libc/printf.c b/payloads/libpayload/libc/printf.c index bc2c41c255..8f76ccf286 100644 --- a/payloads/libpayload/libc/printf.c +++ b/payloads/libpayload/libc/printf.c @@ -69,11 +69,10 @@ struct printf_spec { #define __PRINTF_FLAG_NEGATIVE 0x00000100 /** - * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0 - * to terminate string (last one is only for better testing end of buffer by - * zero-filling subroutine). + * Buffer big enough for 64-bit number printed in base 2, sign, and prefix. + * Add some more to support sane amounts of zero-padding. */ -#define PRINT_NUMBER_BUFFER_SIZE (64 + 5) +#define PRINT_BUFFER_SIZE (64 + 1 + 2 + 13) /** Enumeration of possible arguments types. */ typedef enum { @@ -128,6 +127,26 @@ static int printf_putchar(int c, struct printf_spec *ps) return ps->write(&ch, 1, ps->data); } +/* Print spaces for padding. Ignores negative counts. */ +static int print_spaces(int count, struct printf_spec *ps) +{ + int tmp, ret; + char buffer[PRINT_BUFFER_SIZE]; + + if (count <= 0) + return 0; + + memset(buffer, ' ', MIN(PRINT_BUFFER_SIZE, count)); + for (tmp = count; tmp > PRINT_BUFFER_SIZE; tmp -= PRINT_BUFFER_SIZE) + if ((ret = printf_putnchars(buffer, PRINT_BUFFER_SIZE, ps)) < 0) + return ret; + + if ((ret = printf_putnchars(buffer, tmp, ps)) < 0) + return ret; + + return count; +} + /** * Print one formatted character. * @@ -139,21 +158,24 @@ static int printf_putchar(int c, struct printf_spec *ps) */ static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps) { - int counter = 0; + int retval; + int counter = 1; if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { - while (--width > 0) { - if (printf_putchar(' ', ps) > 0) - ++counter; - } + if ((retval = print_spaces(width - 1, ps)) < 0) + return retval; + else + counter += retval; } - if (printf_putchar(c, ps) > 0) - counter++; + if ((retval = printf_putchar(c, ps)) < 0) + return retval; - while (--width > 0) { - if (printf_putchar(' ', ps) > 0) - ++counter; + if (flags & __PRINTF_FLAG_LEFTALIGNED) { + if ((retval = print_spaces(width - 1, ps)) < 0) + return retval; + else + counter += retval; } return counter; @@ -185,19 +207,21 @@ static int print_string(char *s, int width, unsigned int precision, width -= precision; if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { - while (width-- > 0) { - if (printf_putchar(' ', ps) == 1) - counter++; - } + if ((retval = print_spaces(width, ps)) < 0) + return retval; + else + counter += retval; } if ((retval = printf_putnchars(s, MIN(size, precision), ps)) < 0) - return -counter; + return retval; counter += retval; - while (width-- > 0) { - if (printf_putchar(' ', ps) == 1) - ++counter; + if (flags & __PRINTF_FLAG_LEFTALIGNED) { + if ((retval = print_spaces(width, ps)) < 0) + return retval; + else + counter += retval; } return counter; @@ -209,7 +233,7 @@ static int print_string(char *s, int width, unsigned int precision, * Print significant digits of a number in given base. * * @param num Number to print. - * @param width Width modifier.h + * @param width Width modifier. * @param precision Precision modifier. * @param base Base to print the number in (must be between 2 and 16). * @param flags Flags that modify the way the number is printed. @@ -220,49 +244,34 @@ static int print_number(uint64_t num, int width, int precision, int base, uint64_t flags, struct printf_spec *ps) { const char *digits = digits_small; - char d[PRINT_NUMBER_BUFFER_SIZE]; - char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1]; - int size = 0; /* Size of number with all prefixes and signs. */ - int number_size; /* Size of plain number. */ + char d[PRINT_BUFFER_SIZE]; + char *ptr = &d[PRINT_BUFFER_SIZE]; + int size = 0; /* Size of the string in ptr */ + int counter = 0; /* Amount of actually printed bytes. */ char sgn; int retval; - int counter = 0; if (flags & __PRINTF_FLAG_BIGCHARS) digits = digits_big; - *ptr-- = 0; /* Put zero at end of string. */ - if (num == 0) { - *ptr-- = '0'; + *--ptr = '0'; size++; } else { do { - *ptr-- = digits[num % base]; + *--ptr = digits[num % base]; size++; } while (num /= base); } - number_size = size; + /* Both precision and LEFTALIGNED overrule ZEROPADDED. */ + if ((flags & __PRINTF_FLAG_LEFTALIGNED) || precision) + flags &= ~__PRINTF_FLAG_ZEROPADDED; - /* - * Collect the sum of all prefixes/signs/... to calculate padding and - * leading zeroes. - */ - if (flags & __PRINTF_FLAG_PREFIX) { - switch (base) { - case 2: /* Binary formating is not standard, but useful. */ - size += 2; - break; - case 8: - size++; - break; - case 16: - size += 2; - break; - } - } + /* Fix precision now since it doesn't count prefixes/signs. */ + precision -= size; + /* Reserve size for prefixes/signs before filling up padding. */ sgn = 0; if (flags & __PRINTF_FLAG_SIGNED) { if (flags & __PRINTF_FLAG_NEGATIVE) { @@ -276,87 +285,75 @@ static int print_number(uint64_t num, int width, int precision, int base, size++; } } - - if (flags & __PRINTF_FLAG_LEFTALIGNED) - flags &= ~__PRINTF_FLAG_ZEROPADDED; - - /* - * If the number is left-aligned or precision is specified then - * zero-padding is ignored. - */ - if (flags & __PRINTF_FLAG_ZEROPADDED) { - if ((precision == 0) && (width > size)) - precision = width - size + number_size; - } - - /* Print leading spaces. */ - if (number_size > precision) { - /* Print the whole number not only a part. */ - precision = number_size; - } - - width -= precision + size - number_size; - - if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { - while (width-- > 0) { - if (printf_putchar(' ', ps) == 1) - counter++; - } - } - - /* Print sign. */ - if (sgn) { - if (printf_putchar(sgn, ps) == 1) - counter++; - } - - /* Print prefix. */ if (flags & __PRINTF_FLAG_PREFIX) { switch (base) { case 2: /* Binary formating is not standard, but useful. */ - if (printf_putchar('0', ps) == 1) - counter++; - if (flags & __PRINTF_FLAG_BIGCHARS) { - if (printf_putchar('B', ps) == 1) - counter++; - } else { - if (printf_putchar('b', ps) == 1) - counter++; - } + size += 2; break; case 8: - if (printf_putchar('o', ps) == 1) - counter++; + size++; break; case 16: - if (printf_putchar('0', ps) == 1) - counter++; - if (flags & __PRINTF_FLAG_BIGCHARS) { - if (printf_putchar('X', ps) == 1) - counter++; - } else { - if (printf_putchar('x', ps) == 1) - counter++; - } + size += 2; break; } } - /* Print leading zeroes. */ - precision -= number_size; - while (precision-- > 0) { - if (printf_putchar('0', ps) == 1) - counter++; + /* If this is still set we didn't have a precision, so repurpose it */ + if (flags & __PRINTF_FLAG_ZEROPADDED) + precision = width - size; + + /* Pad smaller numbers with 0 (larger numbers lead to precision < 0). */ + if (precision > 0) { + precision = MIN(precision, PRINT_BUFFER_SIZE - size); + ptr -= precision; + size += precision; + memset(ptr, '0', precision); } - /* Print number itself. */ - if ((retval = printf_putstr(++ptr, ps)) > 0) - counter += retval; + /* Add sign and prefix (we adjusted size for this beforehand). */ + if (flags & __PRINTF_FLAG_PREFIX) { + switch (base) { + case 2: /* Binary formating is not standard, but useful. */ + *--ptr = (flags & __PRINTF_FLAG_BIGCHARS) ? 'B' : 'b'; + *--ptr = '0'; + break; + case 8: + *--ptr = '0'; + break; + case 16: + *--ptr = (flags & __PRINTF_FLAG_BIGCHARS) ? 'X' : 'x'; + *--ptr = '0'; + break; + } + } + if (sgn) + *--ptr = sgn; - /* Print ending spaces. */ - while (width-- > 0) { - if (printf_putchar(' ', ps) == 1) - counter++; + /* Pad with spaces up to width, try to avoid extra putnchar if we can */ + width -= size; + if (width > 0 && !(flags & __PRINTF_FLAG_LEFTALIGNED)) { + int tmp = MIN(width, PRINT_BUFFER_SIZE - size); + ptr -= tmp; + size += tmp; + memset(ptr, ' ', tmp); + if ((retval = print_spaces(width - tmp, ps)) < 0) + return retval; + else + counter += retval; + } + + /* Now print the whole thing at once. */ + if ((retval = printf_putnchars(ptr, size, ps)) < 0) + return retval; + counter += retval; + + /* Edge case: left-aligned with width (should be rare). */ + if (flags & __PRINTF_FLAG_LEFTALIGNED) { + if ((retval = print_spaces(width, ps)) < 0) + return retval; + else + counter += retval; } return counter; @@ -468,10 +465,8 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) /* Print common characters if any processed. */ if (i > j) { if ((retval = printf_putnchars(&fmt[j], - (size_t) (i - j), ps)) < 0) { - counter = -counter; - goto out; /* Error */ - } + (size_t) (i - j), ps)) < 0) + return retval; counter += retval; } @@ -574,20 +569,15 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) /* String and character conversions */ case 's': if ((retval = print_string(va_arg(ap, char *), - width, precision, flags, ps)) < 0) { - counter = -counter; - goto out; - }; + width, precision, flags, ps)) < 0) + return retval; counter += retval; j = i + 1; goto next_char; case 'c': c = va_arg(ap, unsigned int); - retval = print_char(c, width, flags, ps); - if (retval < 0) { - counter = -counter; - goto out; - }; + if ((retval = print_char(c, width, flags, ps)) < 0) + return retval; counter += retval; j = i + 1; goto next_char; @@ -654,9 +644,6 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) size = sizeof(void *); number = (uint64_t) (unsigned long)va_arg(ap, void *); break; - default: /* Unknown qualifier */ - counter = -counter; - goto out; } if (flags & __PRINTF_FLAG_SIGNED) { @@ -674,10 +661,8 @@ static int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) } if ((retval = print_number(number, width, precision, - base, flags, ps)) < 0) { - counter = -counter; - goto out; - } + base, flags, ps)) < 0) + return retval; counter += retval; j = i + 1; @@ -688,15 +673,11 @@ next_char: if (i > j) { if ((retval = printf_putnchars(&fmt[j], - (u64) (i - j), ps)) < 0) { - counter = -counter; - goto out; /* Error */ - - } + (u64) (i - j), ps)) < 0) + return retval; counter += retval; } -out: return counter; } @@ -830,12 +811,8 @@ int printf(const char *fmt, ...) static int vprintf_write(const char *str, size_t count, void *unused) { - size_t i; - - for (i = 0; i < count; i++) - putchar(str[i]); - - return i; + console_write(str, count); + return count; } int vprintf(const char *fmt, va_list ap) diff --git a/payloads/libpayload/libc/string.c b/payloads/libpayload/libc/string.c index cfa0b4ada4..883d158222 100644 --- a/payloads/libpayload/libc/string.c +++ b/payloads/libpayload/libc/string.c @@ -643,3 +643,22 @@ void perror(const char *s) { printf("%s: %d\n", s?s:"(none)", errno); } + +/** + * Simple routine to convert UTF-16 to ASCII, giving up with ? if too high. + * A single code point may convert to ?? if in not in the BMP. + * @param utf16_string A string encoded in UTF-16LE + * @param maxlen Maximum possible length of the string in code points + * @return Newly allocated ASCII string + */ +char *utf16le_to_ascii(uint16_t *utf16_string, int maxlen) +{ + char *ascii_string = xmalloc(maxlen + 1); /* +1 for trailing \0 */ + ascii_string[maxlen] = '\0'; + int i; + for (i = 0; i < maxlen; i++) { + uint16_t wchar = utf16_string[i]; + ascii_string[i] = wchar > 0x7f ? '?' : (char)wchar; + } + return ascii_string; +} diff --git a/payloads/libpayload/libc/time.c b/payloads/libpayload/libc/time.c index 7b6bf47cdf..8d07c4f172 100644 --- a/payloads/libpayload/libc/time.c +++ b/payloads/libpayload/libc/time.c @@ -34,7 +34,7 @@ #include #include -#ifdef CONFIG_ARCH_X86 +#ifdef CONFIG_LP_ARCH_X86 #include #endif @@ -70,7 +70,7 @@ static void update_clock(void) } } -#ifdef CONFIG_NVRAM +#ifdef CONFIG_LP_NVRAM static unsigned int day_of_year(int mon, int day, int year) { @@ -189,3 +189,20 @@ void delay(unsigned int s) { _delay((uint64_t)s * timer_hz()); } + +u64 timer_us(u64 base) +{ + static u64 hz; + + // Only check timer_hz once. Assume it doesn't change. + if (hz == 0) { + hz = timer_hz(); + if (hz < 1000000) { + printf("Timer frequency %lld is too low, " + "must be at least 1MHz.\n", hz); + halt(); + } + } + + return (1000000 * timer_raw_value()) / hz - base; +} diff --git a/payloads/libpayload/libcbfs/Makefile.inc b/payloads/libpayload/libcbfs/Makefile.inc index 0d3e1ec59a..72f6b790ad 100644 --- a/payloads/libpayload/libcbfs/Makefile.inc +++ b/payloads/libpayload/libcbfs/Makefile.inc @@ -27,6 +27,6 @@ ## SUCH DAMAGE. ## -libcbfs-$(CONFIG_CBFS) += cbfs.c -libcbfs-$(CONFIG_CBFS) += ram_media.c +libcbfs-$(CONFIG_LP_CBFS) += cbfs.c +libcbfs-$(CONFIG_LP_CBFS) += ram_media.c diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c index 2fb91bf2d2..806299f299 100644 --- a/payloads/libpayload/libcbfs/cbfs.c +++ b/payloads/libpayload/libcbfs/cbfs.c @@ -31,7 +31,7 @@ #ifdef LIBPAYLOAD # include -# ifdef CONFIG_LZMA +# ifdef CONFIG_LP_LZMA # include # define CBFS_CORE_WITH_LZMA # endif @@ -55,26 +55,13 @@ # include # define ERROR(x...) printk(BIOS_ERR, "CBFS: " x) # define LOG(x...) printk(BIOS_INFO, "CBFS: " x) -# if CONFIG_DEBUG_CBFS +# if CONFIG_LP_DEBUG_CBFS # define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x) # else # define DEBUG(x...) # endif #endif -#if defined(CONFIG_CBFS_HEADER_ROM_OFFSET) && (CONFIG_CBFS_HEADER_ROM_OFFSET) -# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET) -#else -/* ugly hack: this assumes that "media" exists - in the scope where the macro is used. */ -static uint32_t fetch_x86_header(struct cbfs_media *media) -{ - uint32_t *header_ptr = media->map(media, 0xfffffffc, 4); - return *header_ptr; -} -# define CBFS_HEADER_ROM_ADDRESS fetch_x86_header(media) -#endif - #include "cbfs_core.c" #ifndef __SMM__ @@ -135,21 +122,21 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name) cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); /* this is a mess. There is no ntohll. */ /* for now, assume compatible byte order until we solve this. */ - uint32_t entry; + uintptr_t entry; if (stage == NULL) return (void *) -1; - LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", + LOG("loading stage %s @ 0x%p (%d bytes), entry @ 0x%llx\n", name, - (uint32_t) stage->load, stage->memlen, + (void*)(uintptr_t) stage->load, stage->memlen, stage->entry); - memset((void *) (uint32_t) stage->load, 0, stage->memlen); + memset((void *) (uintptr_t) stage->load, 0, stage->memlen); if (cbfs_decompress(stage->compression, ((unsigned char *) stage) + sizeof(struct cbfs_stage), - (void *) (uint32_t) stage->load, + (void *) (uintptr_t) stage->load, stage->len)) return (void *) -1; @@ -175,8 +162,7 @@ int cbfs_execute_stage(struct cbfs_media *media, const char *name) return 1; } - /* FIXME: This isn't right */ - LOG("run @ %p\n", (void *) ntohl((uint32_t) stage->entry)); + LOG("run @ %p\n", (void *)(uintptr_t)ntohll(stage->entry)); return run_address((void *)(uintptr_t)ntohll(stage->entry)); } diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c index a714b91367..4bb8dca285 100644 --- a/payloads/libpayload/libcbfs/cbfs_core.c +++ b/payloads/libpayload/libcbfs/cbfs_core.c @@ -34,10 +34,6 @@ * CBFS_CORE_WITH_LZMA (must be #define) * if defined, ulzma() must exist for decompression of data streams * - * CBFS_HEADER_ROM_ADDRESS - * ROM address (offset) of CBFS header. Underlying CBFS media may interpret - * it in other way so we call this "address". - * * ERROR(x...) * print an error message x (in printf format) * @@ -56,6 +52,7 @@ * on failure */ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) { + int32_t rel_offset; const struct cbfs_header *header; struct cbfs_media default_media; @@ -66,22 +63,28 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) return CBFS_HEADER_INVALID_ADDRESS; } } - media->open(media); - DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS, - CONFIG_ROM_SIZE); - header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header)); + + if (!media->read(media, &rel_offset, (size_t)(0 - sizeof(int32_t)), + sizeof(int32_t))) { + ERROR("Could not read CBFS master header offset!\n"); + return CBFS_HEADER_INVALID_ADDRESS; + } + header = media->map(media, (size_t)rel_offset, sizeof(*header)); + DEBUG("CBFS header at %#zx (-%#zx from end of image).\n", + (size_t)rel_offset, (size_t)-rel_offset); media->close(media); if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("Failed to load CBFS header from 0x%x\n", - CBFS_HEADER_ROM_ADDRESS); + ERROR("Failed to load CBFS header from %#zx(-%#zx)\n", + (size_t)rel_offset, (size_t)-rel_offset); return CBFS_HEADER_INVALID_ADDRESS; } if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { - ERROR("Could not find valid CBFS master header at %x: " - "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC, + ERROR("Could not find valid CBFS master header at %#zx(-%#zx): " + "magic %#.8x vs %#.8x.\n", (size_t)rel_offset, + (size_t)-rel_offset, CBFS_HEADER_MAGIC, ntohl(header->magic)); if (header->magic == 0xffffffff) { ERROR("Maybe ROM is not mapped properly?\n"); @@ -118,12 +121,23 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) // TODO Add a "size" in CBFS header for a platform independent way to // determine the end of CBFS data. -#if defined(CONFIG_ARCH_X86) && CONFIG_ARCH_X86 - romsize -= htonl(header->bootblocksize); -#endif - DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); +#if defined(CONFIG_LP_ARCH_X86) && CONFIG_LP_ARCH_X86 + // resolve actual length of ROM used for CBFS components + // the bootblock size was not taken into account + romsize -= ntohl(header->bootblocksize); + + // fine tune the length to handle alignment positioning. + // using (bootblock size) % align, to derive the + // number of bytes the bootblock is off from the alignment size. + if ((ntohl(header->bootblocksize) % align)) + romsize -= (align - (ntohl(header->bootblocksize) % align)); + else + romsize -= 1; +#endif + + DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); + DEBUG("Looking for '%s' starting from 0x%x.\n", name, offset); - LOG("Looking for '%s' starting from 0x%x.\n", name, offset); media->open(media); while (offset < romsize && media->read(media, &file, offset, sizeof(file)) == sizeof(file)) { @@ -150,7 +164,7 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) } else if (strcmp(file_name, name) == 0) { int file_offset = ntohl(file.offset), file_len = ntohl(file.len); - LOG("Found file (offset=0x%x, len=%d).\n", + DEBUG("Found file (offset=0x%x, len=%d).\n", offset + file_offset, file_len); media->unmap(media, file_name); file_ptr = media->map(media, offset, @@ -158,7 +172,8 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) media->close(media); return file_ptr; } else { - LOG(" (unmatched file @0x%x: %s)\n", offset, file_name); + DEBUG(" (unmatched file @0x%x: %s)\n", offset, + file_name); media->unmap(media, file_name); } @@ -168,7 +183,7 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) offset += align - (offset % align); } media->close(media); - LOG("WARNING: Not found.\n"); + LOG("WARNING: '%s' not found.\n", name); return NULL; } diff --git a/payloads/libpayload/libcbfs/ram_media.c b/payloads/libpayload/libcbfs/ram_media.c index 859555c6f4..3658d3d1af 100644 --- a/payloads/libpayload/libcbfs/ram_media.c +++ b/payloads/libpayload/libcbfs/ram_media.c @@ -27,6 +27,7 @@ * SUCH DAMAGE. */ #include +#include #include #include #include @@ -43,6 +44,7 @@ static int ram_open(struct cbfs_media *media) { static void *ram_map(struct cbfs_media *media, size_t offset, size_t count) { struct ram_media *m = (struct ram_media*)media->context; + /* assume addressing from top of image in this case */ if (offset > 0xf0000000) { offset = m->size + offset; @@ -50,7 +52,7 @@ static void *ram_map(struct cbfs_media *media, size_t offset, size_t count) { if (offset + count > m->size) { printf("ERROR: ram_map: request out of range (0x%zx+0x%zx)\n", offset, count); - return NULL; + return CBFS_MEDIA_INVALID_MAP_ADDRESS; } return (void*)(m->start + offset); } @@ -62,6 +64,8 @@ static void *ram_unmap(struct cbfs_media *media, const void *address) { static size_t ram_read(struct cbfs_media *media, void *dest, size_t offset, size_t count) { void *ptr = ram_map(media, offset, count); + if (ptr == CBFS_MEDIA_INVALID_MAP_ADDRESS) + return 0; memcpy(dest, ptr, count); ram_unmap(media, ptr); return count; @@ -71,7 +75,6 @@ static int ram_close(struct cbfs_media *media) { return 0; } -int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size); int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size) { // TODO Find a way to release unused media. Maybe adding media->destroy. struct ram_media *m = (struct ram_media*)malloc(sizeof(*m)); @@ -90,7 +93,6 @@ int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size) { static int is_default_cbfs_media_initialized; static struct cbfs_media default_cbfs_media; -int setup_cbfs_from_ram(void *start, uint32_t size); int setup_cbfs_from_ram(void *start, uint32_t size) { int result = init_cbfs_ram_media(&default_cbfs_media, start, size); if (result == 0) @@ -99,7 +101,6 @@ int setup_cbfs_from_ram(void *start, uint32_t size) { } extern int libpayload_init_default_cbfs_media(struct cbfs_media *media); -int setup_cbfs_from_flash(void); int setup_cbfs_from_flash(void) { int result = libpayload_init_default_cbfs_media(&default_cbfs_media); if (result == 0) diff --git a/payloads/libpayload/liblzma/Makefile.inc b/payloads/libpayload/liblzma/Makefile.inc index 2dd4a2d900..7df45f2014 100644 --- a/payloads/libpayload/liblzma/Makefile.inc +++ b/payloads/libpayload/liblzma/Makefile.inc @@ -27,5 +27,5 @@ ## SUCH DAMAGE. ## -liblzma-$(CONFIG_LZMA) += lzma.c +liblzma-$(CONFIG_LP_LZMA) += lzma.c diff --git a/payloads/libpayload/liblzma/lzma.c b/payloads/libpayload/liblzma/lzma.c index 0b97213070..23c95620ce 100644 --- a/payloads/libpayload/liblzma/lzma.c +++ b/payloads/libpayload/liblzma/lzma.c @@ -14,9 +14,11 @@ #include #include "lzmadecode.c" -unsigned long ulzma(const unsigned char * src, unsigned char * dst) +unsigned long ulzman(const unsigned char *src, unsigned long srcn, + unsigned char *dst, unsigned long dstn) { unsigned char properties[LZMA_PROPERTIES_SIZE]; + const int data_offset = LZMA_PROPERTIES_SIZE + 8; UInt32 outSize; SizeT inProcessed; SizeT outProcessed; @@ -27,7 +29,10 @@ unsigned long ulzma(const unsigned char * src, unsigned char * dst) memcpy(properties, src, LZMA_PROPERTIES_SIZE); memcpy(&outSize, src + LZMA_PROPERTIES_SIZE, sizeof(outSize)); - if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) { + if (outSize > dstn) + outSize = dstn; + if (LzmaDecodeProperties(&state.Properties, properties, + LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) { printf("lzma: Incorrect stream properties.\n"); return 0; } @@ -37,11 +42,16 @@ unsigned long ulzma(const unsigned char * src, unsigned char * dst) return 0; } state.Probs = (CProb *)scratchpad; - res = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, (SizeT)0xffffffff, &inProcessed, - dst, outSize, &outProcessed); + res = LzmaDecode(&state, src + data_offset, srcn - data_offset, + &inProcessed, dst, outSize, &outProcessed); if (res != 0) { printf("lzma: Decoding error = %d\n", res); return 0; } return outSize; } + +unsigned long ulzma(const unsigned char *src, unsigned char *dst) +{ + return ulzman(src, (unsigned long)(-1), dst, (unsigned long)(-1)); +} diff --git a/payloads/libpayload/tests/libpayload-config.h b/payloads/libpayload/tests/libpayload-config.h index 6fe99a9a79..cce7c4cf8a 100644 --- a/payloads/libpayload/tests/libpayload-config.h +++ b/payloads/libpayload/tests/libpayload-config.h @@ -4,27 +4,27 @@ * Sat Mar 9 10:22:45 2013 */ #define AUTOCONF_INCLUDED -#define CONFIG_SPEAKER 1 -#define CONFIG_STORAGE 1 -#define CONFIG_LIBC 1 -#define CONFIG_CBFS 1 -#define CONFIG_VGA_VIDEO_CONSOLE 1 -#define CONFIG_SERIAL_CONSOLE 1 -#define CONFIG_PC_KEYBOARD 1 -#define CONFIG_ARCH_X86 1 -#define CONFIG_STORAGE_ATA 1 -#define CONFIG_ARCH_SPECIFIC_OPTIONS 1 -#define CONFIG_STORAGE_AHCI_ONLY_TESTED 1 -#define CONFIG_X86_SERIAL_CONSOLE 1 -#define CONFIG_PDCURSES 1 -#define CONFIG_NVRAM 1 -#define CONFIG_PC_KEYBOARD_LAYOUT_US 1 -#define CONFIG_STORAGE_AHCI 1 -#define CONFIG_MULTIBOOT 1 -#define CONFIG_SERIAL_IOBASE 0x3f8 -#define CONFIG_CURSES 1 -#define CONFIG_CBMEM_CONSOLE 1 -#define CONFIG_LITTLE_ENDIAN 1 -#define CONFIG_PCI 1 -#define CONFIG_STORAGE_ATAPI 1 -#define CONFIG_VIDEO_CONSOLE 1 +#define CONFIG_LP_SPEAKER 1 +#define CONFIG_LP_STORAGE 1 +#define CONFIG_LP_LIBC 1 +#define CONFIG_LP_CBFS 1 +#define CONFIG_LP_VGA_VIDEO_CONSOLE 1 +#define CONFIG_LP_SERIAL_CONSOLE 1 +#define CONFIG_LP_PC_KEYBOARD 1 +#define CONFIG_LP_ARCH_X86 1 +#define CONFIG_LP_STORAGE_ATA 1 +#define CONFIG_LP_ARCH_SPECIFIC_OPTIONS 1 +#define CONFIG_LP_STORAGE_AHCI_ONLY_TESTED 1 +#define CONFIG_LP_8250_SERIAL_CONSOLE 1 +#define CONFIG_LP_PDCURSES 1 +#define CONFIG_LP_NVRAM 1 +#define CONFIG_LP_PC_KEYBOARD_LAYOUT_US 1 +#define CONFIG_LP_STORAGE_AHCI 1 +#define CONFIG_LP_MULTIBOOT 1 +#define CONFIG_LP_SERIAL_IOBASE 0x3f8 +#define CONFIG_LP_CURSES 1 +#define CONFIG_LP_CBMEM_CONSOLE 1 +#define CONFIG_LP_LITTLE_ENDIAN 1 +#define CONFIG_LP_PCI 1 +#define CONFIG_LP_STORAGE_ATAPI 1 +#define CONFIG_LP_VIDEO_CONSOLE 1 diff --git a/payloads/libpayload/util/kconfig/confdata.c b/payloads/libpayload/util/kconfig/confdata.c index b1f31d8d5e..a28b930ff0 100644 --- a/payloads/libpayload/util/kconfig/confdata.c +++ b/payloads/libpayload/util/kconfig/confdata.c @@ -219,22 +219,22 @@ load: sym = NULL; switch (line[0]) { case '#': - if (memcmp(line + 2, "CONFIG_", 7)) + if (memcmp(line + 2, "CONFIG_LP_", 10)) continue; - p = strchr(line + 9, ' '); + p = strchr(line + 12, ' '); if (!p) continue; *p++ = 0; if (strncmp(p, "is not set", 10)) continue; if (def == S_DEF_USER) { - sym = sym_find(line + 9); + sym = sym_find(line + 12); if (!sym) { - conf_warning("trying to assign nonexistent symbol %s", line + 9); + conf_warning("trying to assign nonexistent symbol %s", line + 12); break; } } else { - sym = sym_lookup(line + 9, 0); + sym = sym_lookup(line + 12, 0); if (sym->type == S_UNKNOWN) sym->type = S_BOOLEAN; } @@ -252,11 +252,11 @@ load: } break; case 'C': - if (memcmp(line, "CONFIG_", 7)) { + if (memcmp(line, "CONFIG_LP_", 10)) { conf_warning("unexpected data"); continue; } - p = strchr(line + 7, '='); + p = strchr(line + 10, '='); if (!p) continue; *p++ = 0; @@ -267,13 +267,13 @@ load: *p2 = 0; } if (def == S_DEF_USER) { - sym = sym_find(line + 7); + sym = sym_find(line + 10); if (!sym) { - conf_warning("trying to assign nonexistent symbol %s", line + 7); + conf_warning("trying to assign nonexistent symbol %s", line + 10); break; } } else { - sym = sym_lookup(line + 7, 0); + sym = sym_lookup(line + 10, 0); if (sym->type == S_UNKNOWN) sym->type = S_OTHER; } @@ -489,19 +489,19 @@ int conf_write(const char *name) case S_TRISTATE: switch (sym_get_tristate_value(sym)) { case no: - fprintf(out, "# CONFIG_%s is not set\n", sym->name); + fprintf(out, "# CONFIG_LP_%s is not set\n", sym->name); break; case mod: - fprintf(out, "CONFIG_%s=m\n", sym->name); + fprintf(out, "CONFIG_LP_%s=m\n", sym->name); break; case yes: - fprintf(out, "CONFIG_%s=y\n", sym->name); + fprintf(out, "CONFIG_LP_%s=y\n", sym->name); break; } break; case S_STRING: str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=\"", sym->name); + fprintf(out, "CONFIG_LP_%s=\"", sym->name); while (1) { l = strcspn(str, "\"\\"); if (l) { @@ -517,12 +517,12 @@ int conf_write(const char *name) case S_HEX: str = sym_get_string_value(sym); if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + fprintf(out, "CONFIG_LP_%s=%s\n", sym->name, str); break; } case S_INT: str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + fprintf(out, "CONFIG_LP_%s=%s\n", sym->name, str); break; } } @@ -730,19 +730,19 @@ int conf_write_autoconf(void) case no: break; case mod: - fprintf(out, "CONFIG_%s=m\n", sym->name); - fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); + fprintf(out, "CONFIG_LP_%s=m\n", sym->name); + fprintf(out_h, "#define CONFIG_LP_%s_MODULE 1\n", sym->name); break; case yes: - fprintf(out, "CONFIG_%s=y\n", sym->name); - fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); + fprintf(out, "CONFIG_LP_%s=y\n", sym->name); + fprintf(out_h, "#define CONFIG_LP_%s 1\n", sym->name); break; } break; case S_STRING: str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=\"", sym->name); - fprintf(out_h, "#define CONFIG_%s \"", sym->name); + fprintf(out, "CONFIG_LP_%s=\"", sym->name); + fprintf(out_h, "#define CONFIG_LP_%s \"", sym->name); while (1) { l = strcspn(str, "\"\\"); if (l) { @@ -762,14 +762,14 @@ int conf_write_autoconf(void) case S_HEX: str = sym_get_string_value(sym); if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); - fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); + fprintf(out, "CONFIG_LP_%s=%s\n", sym->name, str); + fprintf(out_h, "#define CONFIG_LP_%s 0x%s\n", sym->name, str); break; } case S_INT: str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); - fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); + fprintf(out, "CONFIG_LP_%s=%s\n", sym->name, str); + fprintf(out_h, "#define CONFIG_LP_%s %s\n", sym->name, str); break; default: break; diff --git a/payloads/libpayload/util/kconfig/lxdialog/check-lxdialog.sh b/payloads/libpayload/util/kconfig/lxdialog/check-lxdialog.sh old mode 100644 new mode 100755 diff --git a/payloads/libpayload/util/kconfig/mconf.c b/payloads/libpayload/util/kconfig/mconf.c index 5e93a308d8..fcebc50001 100644 --- a/payloads/libpayload/util/kconfig/mconf.c +++ b/payloads/libpayload/util/kconfig/mconf.c @@ -232,7 +232,7 @@ save_config_help[] = N_( "leave this blank.\n"), search_help[] = N_( "\n" - "Search for CONFIG_ symbols and display their relations.\n" + "Search for CONFIG_LP_ symbols and display their relations.\n" "Regular expressions are allowed.\n" "Example: search for \"^FOO\"\n" "Result:\n" @@ -249,7 +249,7 @@ search_help[] = N_( "Selected by: BAR\n" "-----------------------------------------------------------------\n" "o The line 'Prompt:' shows the text used in the menu structure for\n" - " this CONFIG_ symbol\n" + " this CONFIG_LP_ symbol\n" "o The 'Defined at' line tell at what file / line number the symbol\n" " is defined\n" "o The 'Depends on:' line tell what symbols needs to be defined for\n" @@ -265,9 +265,9 @@ search_help[] = N_( "Only relevant lines are shown.\n" "\n\n" "Search examples:\n" - "Examples: USB => find all CONFIG_ symbols containing USB\n" - " ^USB => find all CONFIG_ symbols starting with USB\n" - " USB$ => find all CONFIG_ symbols ending with USB\n" + "Examples: USB => find all CONFIG_LP_ symbols containing USB\n" + " ^USB => find all CONFIG_LP_ symbols starting with USB\n" + " USB$ => find all CONFIG_LP_ symbols ending with USB\n" "\n"); static int indent; @@ -388,8 +388,8 @@ static void search_conf(void) again: dialog_clear(); dres = dialog_inputbox(_("Search Configuration Parameter"), - _("Enter CONFIG_ (sub)string to search for " - "(with or without \"CONFIG\")"), + _("Enter CONFIG_LP_ (sub)string to search for " + "(with or without \"CONFIG_LP\")"), 10, 75, ""); switch (dres) { case 0: @@ -401,9 +401,9 @@ again: return; } - /* strip CONFIG_ if necessary */ + /* strip CONFIG_LP_ if necessary */ dialog_input = dialog_input_result; - if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) + if (strncasecmp(dialog_input_result, "CONFIG_LP_", 10) == 0) dialog_input += 7; sym_arr = sym_re_search(dialog_input); @@ -704,7 +704,7 @@ static void show_help(struct menu *menu) if (menu_has_help(menu)) { if (sym->name) { - str_printf(&help, "CONFIG_%s:\n\n", sym->name); + str_printf(&help, "CONFIG_LP_%s:\n\n", sym->name); str_append(&help, _(menu_get_help(menu))); str_append(&help, "\n"); } diff --git a/payloads/libpayload/util/xcompile/xcompile b/payloads/libpayload/util/xcompile/xcompile index 58f086f235..ee7997dcf4 100644 --- a/payloads/libpayload/util/xcompile/xcompile +++ b/payloads/libpayload/util/xcompile/xcompile @@ -109,9 +109,11 @@ detect_special_flags() { arm ) # testcc "$CC" "$CFLAGS -mcpu=cortex-a9" && # CFLAGS="$CFLAGS -mcpu=cortex-a9" - testcc "$CC" \ -"$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux -march=armv7" && -CFLAGS="$CFLAGS -ffixed-r8 -msoft-float -marm -mabi=aapcs-linux -march=armv7" + ;; + esac + + case "$architecture" in + arm64-generic ) ;; esac } @@ -138,13 +140,19 @@ touch "$TMPFILE" trap clean_up EXIT # Architecture definition -SUPPORTED_ARCHITECTURE="x86 armv7" +SUPPORTED_ARCHITECTURE="x86 arm arm64" # ARM Architecture -TARCH_armv7="armv7" -TBFDARCH_armv7="littlearm" -TCLIST_armv7="armv7a" -TWIDTH_armv7="32" +TARCH_arm="arm" +TBFDARCH_arm="littlearm" +TCLIST_arm="armv7a" +TWIDTH_arm="32" + +# ARM64 Architecture +TARCH_arm64="arm64" +TBFDARCH_arm64="littleaarch64" +TCLIST_arm64="aarch64" +TWIDTH_arm64="64" # X86 Architecture TARCH_x86="i386" diff --git a/payloads/tianocoreboot/libpayload.config b/payloads/tianocoreboot/libpayload.config index c7c0720b9c..e63fee8314 100644 --- a/payloads/tianocoreboot/libpayload.config +++ b/payloads/tianocoreboot/libpayload.config @@ -15,7 +15,7 @@ # # Architecture Options # -# CONFIG_ARCH_ARMV7 is not set +# CONFIG_ARCH_ARM is not set # CONFIG_ARCH_POWERPC is not set CONFIG_ARCH_X86=y # CONFIG_MEMMAP_RAM_ONLY is not set diff --git a/payloads/ubootcli/Makefile b/payloads/ubootcli/Makefile new file mode 100644 index 0000000000..4477acef23 --- /dev/null +++ b/payloads/ubootcli/Makefile @@ -0,0 +1,86 @@ +## +## This file is part of the bayou project. +## +## Copyright (C) 2008 Advanced Micro Devices, Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License version 2 as +## published by the Free Software Foundation. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +export src := $(shell pwd) +export obj := $(src)/build + +LIBPAYLOAD_DIR ?= $(src)/../libpayload/install/libpayload + +include $(LIBPAYLOAD_DIR)/libpayload.config + +$(if $(wildcard .xcompile),,$(eval $(shell bash ../libpayload/util/xcompile/xcompile > .xcompile))) +include .xcompile + +ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm +ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86 + +ARCH-y := $(ARCHDIR-y) + +classes-y += $(LIBPAYLOAD_DIR)/lib/libpayload.a +headdoto= $(LIBPAYLOAD_DIR)/lib/$(ARCHDIR-y)/head.o +libraries := $(classes-y) + +# If architecture folder name is different from GCC binutils architecture name, +# override here. +ARCH-$(CONFIG_LP_ARCH_ARM) := arm +ARCH-$(CONFIG_LP_ARCH_X86) := i386 + +LPCC := $(CC_$(ARCH-y)) +LPAS := $(AS_$(ARCH-y)) +LPLD := $(LD_$(ARCH-y)) +LPNM := $(NM_$(ARCH-y)) +OBJCOPY := $(OBJCOPY_$(ARCH-y)) +OBJDUMP := $(OBJDUMP_$(ARCH-y)) +READELF := $(READELF_$(ARCH-y)) +STRIP := $(STRIP_$(ARCH-y)) +AR := $(AR_$(ARCH-y)) + +CFLAGS_arm = -mthumb -march=armv7-a + +LIBGCC_FILE_NAME := $(shell test -r `$(LPCC) -print-libgcc-file-name` && \ + $(LPCC) -print-libgcc-file-name) + +OBJECTS-y := main.o command.o cmd_help.o cmd_license.o +OBJECTS-y += $(libraries) $(LIBGCC_FILE_NAME) + +# Common build params from Depthcharge +ABI_FLAGS := $(ARCH_ABI_FLAGS) -ffreestanding -fno-builtin \ + -fno-stack-protector -fomit-frame-pointer + +CFLAGS= -Wall -Werror -g -Os $(FFLAGS-y) -I$(LIBPAYLOAD_DIR)/include -I. +CFLAGS+= -I$(LIBPAYLOAD_DIR)/include/$(ARCHDIR-y) +CFLAGS+= $(CFLAGS_$(ARCH-y)) $(ABI_FLAGS) +CFLAGS+= -fdata-sections -ffunction-sections -std=gnu99 + +LDFLAGS=-Wl,-T,ubootcli.ldscript.$(ARCH-y) -static -nostartfiles -nostdlib +LDFLAGS+=$(ARCH_LINK_FLAGS) $(ABI_FLAGS) -fuse-ld=bfd +LDFLAGS+=-Wl,--gc-sections -Wl,-Map=$@.map +LIBGCC=$(shell $(CC) -m32 -print-libgcc-file-name) + + +ubootcli.elf: $(OBJECTS-y) + $(LPCC) $(LDFLAGS) -o $@ $(headdoto) $(OBJECTS-y) $(libraries) + @$(STRIP) $@ + +%.o: %.c + $(LPCC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f *.o ubootcli.elf + diff --git a/src/cpu/samsung/exynos5-common/wdt.c b/payloads/ubootcli/cmd_help.c similarity index 50% rename from src/cpu/samsung/exynos5-common/wdt.c rename to payloads/ubootcli/cmd_help.c index dbeefec49a..994138de9c 100644 --- a/src/cpu/samsung/exynos5-common/wdt.c +++ b/payloads/ubootcli/cmd_help.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2012 Samsung Electronics - * Minkyu Kang + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -21,39 +21,27 @@ * MA 02111-1307 USA */ -#include -#include -#include +#include "ubootcli.h" -#define PRESCALER_VAL 255 - -void wdt_stop(void) +static int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct s5p_watchdog *wdt = - samsung_get_base_watchdog(); - unsigned int wtcon; - - wtcon = readl(&wdt->wtcon); - wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); - - writel(wtcon, &wdt->wtcon); + cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd); + const int len = ll_entry_count(cmd_tbl_t, cmd); + return _do_help(start, len, cmdtp, flag, argc, argv); } -void wdt_start(unsigned int timeout) -{ - struct s5p_watchdog *wdt = - samsung_get_base_watchdog(); - unsigned int wtcon; +U_BOOT_CMD( + help, CONFIG_SYS_MAXARGS, 1, do_help, + "print command description/usage", + "\n" + " - print brief description of all commands\n" + "help command ...\n" + " - print detailed usage of 'command'" +); - wdt_stop(); - - wtcon = readl(&wdt->wtcon); - wtcon |= (WTCON_EN | WTCON_CLK(WTCON_CLK_128)); - wtcon &= ~WTCON_INT; - wtcon |= WTCON_RESET; - wtcon |= WTCON_PRESCALER(PRESCALER_VAL); - - writel(timeout, &wdt->wtdat); - writel(timeout, &wdt->wtcnt); - writel(wtcon, &wdt->wtcon); -} +/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */ +ll_entry_declare(cmd_tbl_t, question_mark, cmd) = { + "?", CONFIG_SYS_MAXARGS, 1, do_help, + "alias for 'help'", + "" +}; diff --git a/src/cpu/samsung/exynos5-common/i2c.h b/payloads/ubootcli/cmd_license.c similarity index 65% rename from src/cpu/samsung/exynos5-common/i2c.h rename to payloads/ubootcli/cmd_license.c index eb68af78f0..5509d67f80 100644 --- a/src/cpu/samsung/exynos5-common/i2c.h +++ b/payloads/ubootcli/cmd_license.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2012 Samsung Electronics + * (C) Copyright 2007 by OpenMoko, Inc. + * Author: Harald Welte * * See file CREDITS for list of people who contributed to this * project. @@ -20,24 +21,20 @@ * MA 02111-1307 USA */ -#ifndef _S3C24X0_I2C_H -#define _S3C24X0_I2C_H +#include "ubootcli.h" -/* FIXME: gross hack */ -#include "cpu/samsung/exynos5250/periph.h" +/* COPYING is currently 15951 bytes in size */ +#define LICENSE_MAX 20480 -struct s3c24x0_i2c { - u32 iiccon; - u32 iicstat; - u32 iicadd; - u32 iicds; - u32 iiclc; -}; +int do_license(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + puts("Go read the GPL you lazy sod. I won't print it for you\n"); -struct s3c24x0_i2c_bus { - int node; /* device tree node */ - int bus_num; /* i2c bus number */ - struct s3c24x0_i2c *regs; - enum periph_id id; -}; -#endif /* _S3C24X0_I2C_H */ + return 0; +} + +U_BOOT_CMD( + license, 1, 1, do_license, + "print GPL license text", + "" +); diff --git a/payloads/ubootcli/command.c b/payloads/ubootcli/command.c new file mode 100644 index 0000000000..6dc57df7ee --- /dev/null +++ b/payloads/ubootcli/command.c @@ -0,0 +1,562 @@ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Command Processor Table + */ + +#include "ubootcli.h" + +/* + * Use printf() instead of printf() to avoid printf buffer overflow + * for long help messages + */ + +int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int + flag, int argc, char * const argv[]) +{ + int i; + int rcode = 0; + + if (argc == 1) { /*show list of commands */ + cmd_tbl_t *cmd_array[cmd_items]; + int i, j, swaps; + + /* Make array of commands from .uboot_cmd section */ + cmdtp = cmd_start; + for (i = 0; i < cmd_items; i++) { + cmd_array[i] = cmdtp++; + } + + /* Sort command list (trivial bubble sort) */ + for (i = cmd_items - 1; i > 0; --i) { + swaps = 0; + for (j = 0; j < i; ++j) { + if (strcmp (cmd_array[j]->name, + cmd_array[j + 1]->name) > 0) { + cmd_tbl_t *tmp; + tmp = cmd_array[j]; + cmd_array[j] = cmd_array[j + 1]; + cmd_array[j + 1] = tmp; + ++swaps; + } + } + if (!swaps) + break; + } + + /* print short help (usage) */ + for (i = 0; i < cmd_items; i++) { + const char *usage = cmd_array[i]->usage; + + /* allow user abort */ + /* later + if (ctrlc ()) + return 1; + */ + if (usage == NULL) + continue; + printf("%-*s- %s\n", CONFIG_SYS_HELP_CMD_WIDTH, + cmd_array[i]->name, usage); + } + return 0; + } + /* + * command help (long version) + */ + for (i = 1; i < argc; ++i) { + if ((cmdtp = find_cmd_tbl (argv[i], cmd_start, cmd_items )) != NULL) { + rcode |= cmd_usage(cmdtp); + } else { + printf ("Unknown command '%s' - try 'help'" + " without arguments for list of all" + " known commands\n\n", argv[i] + ); + rcode = 1; + } + } + return rcode; +} + +/*************************************************************************** + * find command table entry for a command + */ +cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len) +{ +#ifdef CONFIG_CMDLINE + cmd_tbl_t *cmdtp; + cmd_tbl_t *cmdtp_temp = table; /*Init value */ + const char *p; + int len; + int n_found = 0; + + if (!cmd) + return NULL; + /* + * Some commands allow length modifiers (like "cp.b"); + * compare command name only until first dot. + */ + len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); + + for (cmdtp = table; + cmdtp != table + table_len; + cmdtp++) { + if (strncmp (cmd, cmdtp->name, len) == 0) { + if (len == strlen (cmdtp->name)) + return cmdtp; /* full match */ + + cmdtp_temp = cmdtp; /* abbreviated command ? */ + n_found++; + } + } + if (n_found == 1) { /* exactly one match */ + return cmdtp_temp; + } +#endif /* CONFIG_CMDLINE */ + + return NULL; /* not found or ambiguous command */ +} + +cmd_tbl_t *find_cmd (const char *cmd) +{ + cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd); + const int len = ll_entry_count(cmd_tbl_t, cmd); + return find_cmd_tbl(cmd, start, len); +} + +int cmd_usage(const cmd_tbl_t *cmdtp) +{ + printf("%s - %s\n\n", cmdtp->name, cmdtp->usage); + +#ifdef CONFIG_SYS_LONGHELP + printf("Usage:\n%s ", cmdtp->name); + + if (!cmdtp->help) { + printf ("- No additional help available.\n"); + return 1; + } + + printf (cmdtp->help); + putc ('\n'); +#endif /* CONFIG_SYS_LONGHELP */ + return 1; +} + +int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) +{ + //static char tmp_buf[512]; + int space; + + space = last_char == '\0' || isblank(last_char); + + //if (space && argc == 1) + // return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf); + + //if (!space && argc == 2) + // return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf); + + return 0; +} + +/*************************************************************************************/ + +static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) +{ + cmd_tbl_t *cmdtp = ll_entry_start(cmd_tbl_t, cmd); + const int count = ll_entry_count(cmd_tbl_t, cmd); + const cmd_tbl_t *cmdend = cmdtp + count; + const char *p; + int len, clen; + int n_found = 0; + const char *cmd; + + /* sanity? */ + if (maxv < 2) + return -2; + + cmdv[0] = NULL; + + if (argc == 0) { + /* output full list of commands */ + for (; cmdtp != cmdend; cmdtp++) { + if (n_found >= maxv - 2) { + cmdv[n_found] = "..."; + break; + } + cmdv[n_found] = cmdtp->name; + } + cmdv[n_found] = NULL; + return n_found; + } + + /* more than one arg or one but the start of the next */ + if (argc > 1 || (last_char == '\0' || isblank(last_char))) { + cmdtp = find_cmd(argv[0]); + if (cmdtp == NULL || cmdtp->complete == NULL) { + cmdv[0] = NULL; + return 0; + } + return (*cmdtp->complete)(argc, argv, last_char, maxv, cmdv); + } + + cmd = argv[0]; + /* + * Some commands allow length modifiers (like "cp.b"); + * compare command name only until first dot. + */ + p = strchr(cmd, '.'); + if (p == NULL) + len = strlen(cmd); + else + len = p - cmd; + + /* return the partial matches */ + for (; cmdtp != cmdend; cmdtp++) { + + clen = strlen(cmdtp->name); + if (clen < len) + continue; + + if (memcmp(cmd, cmdtp->name, len) != 0) + continue; + + /* too many! */ + if (n_found >= maxv - 2) { + cmdv[n_found++] = "..."; + break; + } + + cmdv[n_found++] = cmdtp->name; + } + + cmdv[n_found] = NULL; + return n_found; +} + +static int make_argv(char *s, int argvsz, char *argv[]) +{ + int argc = 0; + + /* split into argv */ + while (argc < argvsz - 1) { + + /* skip any white space */ + while (isblank(*s)) + ++s; + + if (*s == '\0') /* end of s, no more args */ + break; + + argv[argc++] = s; /* begin of argument string */ + + /* find end of string */ + while (*s && !isblank(*s)) + ++s; + + if (*s == '\0') /* end of s, no more args */ + break; + + *s++ = '\0'; /* terminate current arg */ + } + argv[argc] = NULL; + + return argc; +} + +static void print_argv(const char *banner, const char *leader, const char *sep, int linemax, char * const argv[]) +{ + int ll = leader != NULL ? strlen(leader) : 0; + int sl = sep != NULL ? strlen(sep) : 0; + int len, i; + + if (banner) { + printf("\n"); + printf(banner); + } + + i = linemax; /* force leader and newline */ + while (*argv != NULL) { + len = strlen(*argv) + sl; + if (i + len >= linemax) { + printf("\n"); + if (leader) + printf(leader); + i = ll - sl; + } else if (sep) + printf(sep); + printf(*argv++); + i += len; + } + printf("\n"); +} + +static int find_common_prefix(char * const argv[]) +{ + int i, len; + char *anchor, *s, *t; + + if (*argv == NULL) + return 0; + + /* begin with max */ + anchor = *argv++; + len = strlen(anchor); + while ((t = *argv++) != NULL) { + s = anchor; + for (i = 0; i < len; i++, t++, s++) { + if (*t != *s) + break; + } + len = s - anchor; + } + return len; +} + +static char tmp_buf[CONFIG_SYS_CBSIZE]; /* copy of console I/O buffer */ + +int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp) +{ + int n = *np, col = *colp; + char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ + char *cmdv[20]; + char *s, *t; + const char *sep; + int i, j, k, len, seplen, argc; + int cnt; + char last_char; + + if (strcmp(prompt, CONFIG_SYS_PROMPT) != 0) + return 0; /* not in normal console */ + + cnt = strlen(buf); + if (cnt >= 1) + last_char = buf[cnt - 1]; + else + last_char = '\0'; + + /* copy to secondary buffer which will be affected */ + strcpy(tmp_buf, buf); + + /* separate into argv */ + argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv); + + /* do the completion and return the possible completions */ + i = complete_cmdv(argc, argv, last_char, sizeof(cmdv)/sizeof(cmdv[0]), cmdv); + + /* no match; bell and out */ + if (i == 0) { + if (argc > 1) /* allow tab for non command */ + return 0; + serial_putchar('\a'); + return 1; + } + + s = NULL; + len = 0; + sep = NULL; + seplen = 0; + if (i == 1) { /* one match; perfect */ + k = strlen(argv[argc - 1]); + s = cmdv[0] + k; + len = strlen(s); + sep = " "; + seplen = 1; + } else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) { /* more */ + k = strlen(argv[argc - 1]); + j -= k; + if (j > 0) { + s = cmdv[0] + k; + len = j; + } + } + + if (s != NULL) { + k = len + seplen; + /* make sure it fits */ + if (n + k >= CONFIG_SYS_CBSIZE - 2) { + serial_putchar('\a'); + return 1; + } + + t = buf + cnt; + for (i = 0; i < len; i++) + *t++ = *s++; + if (sep != NULL) + for (i = 0; i < seplen; i++) + *t++ = sep[i]; + *t = '\0'; + n += k; + col += k; + printf(t - k); + if (sep == NULL) + serial_putchar('\a'); + *np = n; + *colp = col; + } else { + print_argv(NULL, " ", " ", 78, cmdv); + + printf(prompt); + printf(buf); + } + return 1; +} + +#ifdef CMD_DATA_SIZE +int cmd_get_data_size(char* arg, int default_size) +{ + /* Check for a size specification .b, .w or .l. + */ + int len = strlen(arg); + if (len > 2 && arg[len-2] == '.') { + switch(arg[len-1]) { + case 'b': + return 1; + case 'w': + return 2; + case 'l': + return 4; + case 's': + return -2; + default: + return -1; + } + } + return default_size; +} +#endif + +#if defined(CONFIG_NEEDS_MANUAL_RELOC) +DECLARE_GLOBAL_DATA_PTR; + +void fixup_cmdtable(cmd_tbl_t *cmdtp, int size) +{ + int i; + + if (gd->reloc_off == 0) + return; + + for (i = 0; i < size; i++) { + uint32_t addr; + + addr = (uint32_t) (cmdtp->cmd) + gd->reloc_off; +#if DEBUG_COMMANDS + printf("Command \"%s\": 0x%08lx => 0x%08lx\n", + cmdtp->name, (uint32_t) (cmdtp->cmd), addr); +#endif + cmdtp->cmd = + (int (*)(struct cmd_tbl_s *, int, int, char * const []))addr; + addr = (uint32_t)(cmdtp->name) + gd->reloc_off; + cmdtp->name = (char *)addr; + if (cmdtp->usage) { + addr = (uint32_t)(cmdtp->usage) + gd->reloc_off; + cmdtp->usage = (char *)addr; + } +#ifdef CONFIG_SYS_LONGHELP + if (cmdtp->help) { + addr = (uint32_t)(cmdtp->help) + gd->reloc_off; + cmdtp->help = (char *)addr; + } +#endif +#ifdef CONFIG_AUTO_COMPLETE + if (cmdtp->complete) { + addr = (uint32_t)(cmdtp->complete) + gd->reloc_off; + cmdtp->complete = + (int (*)(int, char * const [], char, int, char * []))addr; + } +#endif + cmdtp++; + } +} +#endif + +#ifdef CONFIG_CMDLINE +/** + * Call a command function. This should be the only route in U-Boot to call + * a command, so that we can track whether we are waiting for input or + * executing a command. + * + * @param cmdtp Pointer to the command to execute + * @param flag Some flags normally 0 (see CMD_FLAG_.. above) + * @param argc Number of arguments (arg 0 must be the command text) + * @param argv Arguments + * @return 0 if command succeeded, else non-zero (CMD_RET_...) + */ +static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int result; + + result = (cmdtp->cmd)(cmdtp, flag, argc, argv); + if (result) + debug("Command failed, result=%d", result); + return result; +} +#endif /* CONFIG_CMDLINE */ + +int cmd_process(int flag, int argc, char * const argv[], + int *repeatable, unsigned long *ticks) +{ + enum command_ret_t rc = CMD_RET_SUCCESS; + +#ifdef CONFIG_CMDLINE + cmd_tbl_t *cmdtp; + + /* Look up command in command table */ + cmdtp = find_cmd(argv[0]); + if (cmdtp == NULL) { + printf("Unknown command '%s' - try 'help'\n", argv[0]); + return 1; + } + + /* found - check max args */ + if (argc > cmdtp->maxargs) + rc = CMD_RET_USAGE; + +#if defined(CONFIG_CMD_BOOTD) + /* avoid "bootd" recursion */ + else if (cmdtp->cmd == do_bootd) { + if (flag & CMD_FLAG_BOOTD) { + printf("'bootd' recursion detected\n"); + rc = CMD_RET_FAILURE; + } else { + flag |= CMD_FLAG_BOOTD; + } + } +#endif + + /* If OK so far, then do the command */ + if (!rc) { + if (ticks) + ; //*ticks = get_timer(0); + rc = cmd_call(cmdtp, flag, argc, argv); + if (ticks) + ; //*ticks = get_timer(*ticks); + if (!(cmdtp->info & CMD_INFO_REPEATABLE)) + *repeatable = 0; + } + if (rc == CMD_RET_USAGE) + rc = cmd_usage(cmdtp); +#else + rc = board_run_command(argv[0]); +#endif + return rc; +} diff --git a/payloads/ubootcli/command.h b/payloads/ubootcli/command.h new file mode 100644 index 0000000000..5d3380571f --- /dev/null +++ b/payloads/ubootcli/command.h @@ -0,0 +1,250 @@ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Definitions for Command Processor + */ +#ifndef __COMMAND_H +#define __COMMAND_H + +/* Default to a width of 8 characters for help message command width */ +#ifndef CONFIG_SYS_HELP_CMD_WIDTH +#define CONFIG_SYS_HELP_CMD_WIDTH 8 +#endif + +#ifndef __ASSEMBLY__ +enum { + CMD_INFO_MASK = 0xffffff, /* user data */ + CMD_INFO_REPEATABLE_SHIFT = 24, /* commaand is repeatable */ + CMD_INFO_REPEATABLE = 1U << CMD_INFO_REPEATABLE_SHIFT, +}; + +/* + * Monitor Command Table + */ + +struct cmd_tbl_s { + char *name; /* Command Name */ + int maxargs; /* maximum number of arguments */ + int info; /* CMD_INFO_... flags */ + /* Implementation function */ + int (*cmd)(struct cmd_tbl_s *, int, int, char * const []); + char *usage; /* Usage message (short) */ + char *help; /* Help message (long) */ + /* do auto completion on the arguments */ + int (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]); +}; + +typedef struct cmd_tbl_s cmd_tbl_t; + +/* Returns the info word for a command */ +static inline int cmd_get_info(struct cmd_tbl_s *cmd) +{ + return cmd->info & CMD_INFO_MASK; +} + + +#if defined(CONFIG_CMD_RUN) +extern int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +#endif + +/* common/command.c */ +int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int + flag, int argc, char * const argv[]); +cmd_tbl_t *find_cmd(const char *cmd); +cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len); + +extern int cmd_usage(const cmd_tbl_t *cmdtp); + +extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]); +extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp); + +/* + * Monitor Command + * + * All commands use a common argument format: + * + * void function (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + */ + +#if defined(CONFIG_CMD_MEMORY) \ + || defined(CONFIG_CMD_I2C) \ + || defined(CONFIG_CMD_ITEST) \ + || defined(CONFIG_CMD_PCI) \ + || defined(CONFIG_CMD_PORTIO) +#define CMD_DATA_SIZE +extern int cmd_get_data_size(char* arg, int default_size); +#endif + +#ifdef CONFIG_CMD_BOOTD +extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +#endif +#ifdef CONFIG_CMD_BOOTM +extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +extern int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd); +#else +static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd) +{ + return 0; +} +#endif + +extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, + char *const argv[]); + +extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +/* + * Error codes that commands return to cmd_process(). We use the standard 0 + * and 1 for success and failure, but add one more case - failure with a + * request to call cmd_usage(). But the cmd_process() function handles + * CMD_RET_USAGE itself and after calling cmd_usage() it will return 1. + * This is just a convenience for commands to avoid them having to call + * cmd_usage() all over the place. + */ +enum command_ret_t { + CMD_RET_SUCCESS, /* 0 = Success */ + CMD_RET_FAILURE, /* 1 = Failure */ + CMD_RET_USAGE = -1, /* Failure, please report 'usage' error */ +}; + +/** + * Process a command with arguments. We look up the command and execute it + * if valid. Otherwise we print a usage message. + * + * @param flag Some flags normally 0 (see CMD_FLAG_.. above) + * @param argc Number of arguments (arg 0 must be the command text) + * @param argv Arguments + * @param repeatable This function sets this to 0 if the command is not + * repeatable. If the command is repeatable, the value + * is left unchanged. + * @param ticks If ticks is not null, this function set it to the + * number of ticks the command took to complete. + * @return 0 if the command succeeded, 1 if it failed + */ +int cmd_process(int flag, int argc, char * const argv[], + int *repeatable, unsigned long *ticks); + +#endif /* __ASSEMBLY__ */ + +/* + * Command Flags: + */ +#define CMD_FLAG_REPEAT 0x0001 /* repeat last command */ +#define CMD_FLAG_BOOTD 0x0002 /* command is from bootd */ + +#ifdef CONFIG_AUTO_COMPLETE +# define _CMD_COMPLETE(x) x, +#else +# define _CMD_COMPLETE(x) +#endif +#ifdef CONFIG_SYS_LONGHELP +# define _CMD_HELP(x) x, +#else +# define _CMD_HELP(x) +#endif + +/* + * These macros help declare commands. They are set up in such as way that + * it is possible to completely remove all commands when CONFIG_CMDLINE is + * not defined. + * + * Usage is: + * U_BOOT_SUBCMD_START(name) + * U_BOOT_CMD_MKENT(...) (or U_BOOT_CMD_MKENT_COMPLETE) + * U_BOOT_CMD_MKENT(...) + * ... + * U_BOOT_SUBCMD_END + * + * We need to ensure that a command is placed between each entry + */ +#ifdef CONFIG_CMDLINE +#define U_BOOT_SUBCMD_START(name) static cmd_tbl_t name[] = { +#define U_BOOT_SUBCMD_END }; +#define U_BOOT_CMD_MKENT_LINE(_name, _maxargs, _rep, _cmd, _usage, \ + _help, _comp, _info) \ + { #_name, _maxargs, (_rep) << CMD_INFO_REPEATABLE_SHIFT | (_info), \ + _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) } + +/* Add a comma to separate lines */ +#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, \ + _help, _comp, _info) \ + U_BOOT_CMD_MKENT_LINE(_name, _maxargs, _rep, _cmd, _usage, \ + _help, _comp, _info), + +/* Here we want a semicolon after the (single) entry */ +#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \ + _comp, _info) \ + ll_entry_declare(cmd_tbl_t, _name, cmd) = \ + U_BOOT_CMD_MKENT_LINE(_name, _maxargs, _rep, _cmd, \ + _usage, _help, _comp, _info); +#else +#define U_BOOT_SUBCMD_START(name) static cmd_tbl_t name[] = {}; +#define U_BOOT_SUBCMD_END + +#define _CMD_REMOVE(_name, _cmd) \ + int __remove_ ## _name(void) \ + { \ + if (0) \ + _cmd(NULL, 0, 0, NULL); \ + return 0; \ + } +#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, \ + _help, _comp, _info) \ + _CMD_REMOVE(_name ## _cmd, _cmd) + +#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \ + _comp, _info) \ + _CMD_REMOVE(sub_ ## _name, _cmd) + +#endif /* CONFIG_CMDLINE */ + +#define U_BOOT_CMD_MKENT(_name, _maxargs, _rep, _cmd, _usage, _help) \ + U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ + _usage, _help, NULL, 0) + +#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \ + U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \ + NULL, 0) + +#if defined(CONFIG_NEEDS_MANUAL_RELOC) +void fixup_cmdtable(cmd_tbl_t *cmdtp, int size); +#endif + +/* Dummy command for use in U_BOOT_CMD_MKENT() when none is needed */ +static inline int cmd_dummy(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return 0; +} + +/* + * When there is no U-Boot command line, the board must provide a way of + * executing commands. + * + * @cmd: Command string to execute + * @return Result of command, CMD_RET_... + */ +int board_run_command(const char *cmd); + +#endif /* __COMMAND_H */ diff --git a/payloads/ubootcli/common.h b/payloads/ubootcli/common.h new file mode 100644 index 0000000000..703b8b1602 --- /dev/null +++ b/payloads/ubootcli/common.h @@ -0,0 +1,242 @@ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __COMMON_H_ +#define __COMMON_H_ 1 + +//#include +//#include +//#include +//#include +//#include +#include +#include +#include +//#include +#include +#include +#include "linker_lists.h" + +/* + * Output a debug text when condition "cond" is met. The "cond" should be + * computed by a preprocessor in the best case, allowing for the best + * optimization. + */ +#define debug_cond(cond, fmt, args...) \ + do { \ + if (cond) \ + printf(fmt, ##args); \ + } while (0) + +#define debug(fmt, args...) \ + debug_cond(_DEBUG, fmt, ##args) + +/* + * General Purpose Utilities + */ +#define min(X, Y) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + (__x < __y) ? __x : __y; }) + +#define max(X, Y) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + (__x > __y) ? __x : __y; }) + +#define min3(X, Y, Z) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + typeof(Z) __z = (Z); \ + __x < __y ? (__x < __z ? __x : __z) : \ + (__y < __z ? __y : __z); }) + +#define max3(X, Y, Z) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + typeof(Z) __z = (Z); \ + __x > __y ? (__x > __z ? __x : __z) : \ + (__y > __z ? __y : __z); }) + +#define MIN3(x, y, z) min3(x, y, z) +#define MAX3(x, y, z) max3(x, y, z) + +/* + * Return the absolute value of a number. + * + * This handles unsigned and signed longs, ints, shorts and chars. For all + * input types abs() returns a signed long. + * + * For 64-bit types, use abs64() + */ +#define abs(x) ({ \ + long ret; \ + if (sizeof(x) == sizeof(long)) { \ + long __x = (x); \ + ret = (__x < 0) ? -__x : __x; \ + } else { \ + int __x = (x); \ + ret = (__x < 0) ? -__x : __x; \ + } \ + ret; \ + }) + +#define abs64(x) ({ \ + s64 __x = (x); \ + (__x < 0) ? -__x : __x; \ + }) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Function Prototypes + */ + +/* common/main.c */ +void main_loop (void); +int run_command(const char *cmd, int flag); + +/** + * Run a list of commands separated by ; or even \0 + * + * Note that if 'len' is not -1, then the command does not need to be nul + * terminated, Memory will be allocated for the command in that case. + * + * @param cmd List of commands to run, each separated bu semicolon + * @param len Length of commands excluding terminator if known (-1 if not) + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +int run_command_list(const char *cmd, int len, int flag); +int ubreadline (const char *const prompt); +int ubreadline_into_buffer(const char *const prompt, char *buffer, + int timeout); +int parse_line (char *, char *[]); +void init_cmd_timeout(void); +void reset_cmd_timeout(void); +extern char console_buffer[]; + +/** + * Show the DRAM size in a board-specific way + * + * This is used by boards to display DRAM information in their own way. + * + * @param size Size of DRAM (which should be displayed along with other info) + */ +void board_show_dram(uint32_t size); +/* + * + * Defined in arch/$(ARCH)/lib/bootm.c + * + * @blob: FDT blob to write to + * @return 0 if ok, or -ve FDT_ERR_... on failure + */ +int arch_fixup_memory_node(void *blob); + +/* common/flash.c */ +void flash_perror (int); + +/* common/cmd_source.c */ +int source (uint32_t addr, const char *fit_uname); + +extern uint32_t load_addr; /* Default Load Address */ +extern uint32_t save_addr; /* Default Save Address */ +extern uint32_t save_size; /* Default Save Size */ + +/* common/cmd_doc.c */ +void doc_probe(unsigned long physadr); + +/* common/cmd_net.c */ +int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +/* common/cmd_fat.c */ +int do_fat_fsload(cmd_tbl_t *, int, int, char * const []); + +/* common/cmd_ext2.c */ +int do_ext2load(cmd_tbl_t *, int, int, char * const []); + +/* common/cmd_nvedit.c */ +int env_init (void); +void env_relocate (void); +int envmatch (uint8_t *, int); + +/* Avoid unfortunate conflict with libc's getenv() */ +#ifdef CONFIG_SANDBOX +#define getenv uboot_getenv +#endif +char *getenv (const char *); +int getenv_f (const char *name, char *buf, unsigned len); +uint32_t getenv_ulong(const char *name, int base, uint32_t default_val); + +/** + * getenv_hex() - Return an environment variable as a hex value + * + * Decode an environment as a hex number (it may or may not have a 0x + * prefix). If the environment variable cannot be found, or does not start + * with hex digits, the default value is returned. + * + * @varname: Variable to decode + * @default_val: Value to return on error + */ +uint32_t getenv_hex(const char *varname, uint32_t default_val); + +/* + * Read an environment variable as a boolean + * Return -1 if variable does not exist (default to true) + */ +int getenv_yesno(const char *var); +int saveenv (void); +//int setenv (const char *, const char *); +int setenv_ulong(const char *varname, uint32_t value); +int setenv_hex(const char *varname, uint32_t value); +/** + * setenv_addr - Set an environment variable to an address in hex + * + * @varname: Environmet variable to set + * @addr: Value to set it to + * @return 0 if ok, 1 on error + +static inline int setenv_addr(const char *varname, const void *addr) +{ + uint32_t stupid_u_boot = (uint32_t) addr; + return setenv_hex(varname, stupid_u_boot); +} + */ +/* HACK */ +#define _DEBUG 1 +#define CONFIG_CMDLINE 1 +#define CONFIG_SYS_CBSIZE 512 +#define CONFIG_SYS_PROMPT "C: " +#define CONFIG_SYS_MAXARGS 32 +#define CONFIG_CMDLINE_EDITING 1 +#define WATCHDOG_RESET() +#endif /* __COMMON_H_ */ diff --git a/payloads/ubootcli/linker_lists.h b/payloads/ubootcli/linker_lists.h new file mode 100644 index 0000000000..245ab47b61 --- /dev/null +++ b/payloads/ubootcli/linker_lists.h @@ -0,0 +1,294 @@ +/* + * include/linker_lists.h + * + * Implementation of linker-generated arrays + * + * Copyright (C) 2012 Marek Vasut + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +/* + * There is no use in including this from ASM files, but that happens + * anyway, e.g. PPC kgdb.S includes command.h which incluse us. + * So just don't define anything when included from ASM. + */ + +#if !defined(__ASSEMBLY__) + +/** + * A linker list is constructed by grouping together linker input + * sections, each containning one entry of the list. Each input section + * contains a constant initialized variable which holds the entry's + * content. Linker list input sections are constructed from the list + * and entry names, plus a prefix which allows grouping all lists + * together. Assuming _list and _entry are the list and entry names, + * then the corresponding input section name is + * + * _u_boot_list + _2_ + @_list + _2_ + @_entry + * + * and the C variable name is + * + * .u_boot_list_ + 2_ + @_list + _2_ + @_entry + * + * This ensures uniqueness for both input section and C variable name. + * + * Note that the names differ only in the first character, "." for the + * setion and "_" for the variable, so that the linker cannot confuse + * section and symbol names. From now on, both names will be referred + * to as + * + * %u_boot_list_ + 2_ + @_list + _2_ + @_entry + * + * Entry variables need never be referred to directly. + * + * The naming scheme for input sections allows grouping all linker lists + * into a single linker output section and grouping all entries for a + * single list. + * + * Note the two '_2_' constant components in the names: their presence + * allows putting a start and end symbols around a list, by mapping + * these symbols to sections names with components "1" (before) and + * "3" (after) instead of "2" (within). + * Start and end symbols for a list can generally be defined as + * + * %u_boot_list_2_ + @_list + _1_... + * %u_boot_list_2_ + @_list + _3_... + * + * Start and end symbols for the whole of the linker lists area can be + * defined as + * + * %u_boot_list_1_... + * %u_boot_list_3_... + * + * Here is an example of the sorted sections which result from a list + * "array" made up of three entries : "first", "second" and "third", + * iterated at least once. + * + * .u_boot_list_2_array_1 + * .u_boot_list_2_array_2_first + * .u_boot_list_2_array_2_second + * .u_boot_list_2_array_2_third + * .u_boot_list_2_array_3 + * + * If lists must be divided into sublists (e.g. for iterating only on + * part of a list), one can simply give the list a name of the form + * 'outer_2_inner', where 'outer' is the global list name and 'inner' + * is the sub-list name. Iterators for the whole list should use the + * global list name ("outer"); iterators for only a sub-list should use + * the full sub-list name ("outer_2_inner"). + * + * Here is an example of the sections generated from a global list + * named "drivers", two sub-lists named "i2c" and "pci", and iterators + * defined for the whole list and each sub-list: + * + * %u_boot_list_2_drivers_1 + * %u_boot_list_2_drivers_2_i2c_1 + * %u_boot_list_2_drivers_2_i2c_2_first + * %u_boot_list_2_drivers_2_i2c_2_first + * %u_boot_list_2_drivers_2_i2c_2_second + * %u_boot_list_2_drivers_2_i2c_2_third + * %u_boot_list_2_drivers_2_i2c_3 + * %u_boot_list_2_drivers_2_pci_1 + * %u_boot_list_2_drivers_2_pci_2_first + * %u_boot_list_2_drivers_2_pci_2_second + * %u_boot_list_2_drivers_2_pci_2_third + * %u_boot_list_2_drivers_2_pci_3 + * %u_boot_list_2_drivers_3 + */ + +#ifndef __LINKER_LISTS_H__ +#define __LINKER_LISTS_H__ + +/** + * ll_entry_declare() - Declare linker-generated array entry + * @_type: Data type of the entry + * @_name: Name of the entry + * @_list: name of the list. Should contain only characters allowed + * in a C variable name! + * + * This macro declares a variable that is placed into a linker-generated + * array. This is a basic building block for more advanced use of linker- + * generated arrays. The user is expected to build their own macro wrapper + * around this one. + * + * A variable declared using this macro must be compile-time initialized. + * + * Special precaution must be made when using this macro: + * + * 1) The _type must not contain the "static" keyword, otherwise the + * entry is generated and can be iterated but is listed in the map + * file and cannot be retrieved by name. + * + * 2) In case a section is declared that contains some array elements AND + * a subsection of this section is declared and contains some elements, + * it is imperative that the elements are of the same type. + * + * 4) In case an outer section is declared that contains some array elements + * AND an inner subsection of this section is declared and contains some + * elements, then when traversing the outer section, even the elements of + * the inner sections are present in the array. + * + * Example: + * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = { + * .x = 3, + * .y = 4, + * }; + */ +#define ll_entry_declare(_type, _name, _list) \ + _type _u_boot_list_2_##_list##_2_##_name /*__aligned(4)*/ \ + __attribute__((unused, \ + section(".u_boot_list_2_"#_list"_2_"#_name))) + +/** + * We need a 0-byte-size type for iterator symbols, and the compiler + * does not allow defining objects of C type 'void'. Using an empty + * struct is allowed by the compiler, but causes gcc versions 4.4 and + * below to complain about aliasing. Therefore we use the next best + * thing: zero-sized arrays, which are both 0-byte-size and exempt from + * aliasing warnings. + */ + +/** + * ll_entry_start() - Point to first entry of linker-generated array + * @_type: Data type of the entry + * @_list: Name of the list in which this entry is placed + * + * This function returns (_type *) pointer to the very first entry of a + * linker-generated array placed into subsection of .u_boot_list section + * specified by _list argument. + * + * Since this macro defines an array start symbol, its leftmost index + * must be 2 and its rightmost index must be 1. + * + * Example: + * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); + */ +#define ll_entry_start(_type, _list) \ +({ \ + static char start[0] __attribute__((/*__aligned(4) ,*/ unused, \ + section(".u_boot_list_2_"#_list"_1"))); \ + (_type *)&start; \ +}) + +/** + * ll_entry_end() - Point after last entry of linker-generated array + * @_type: Data type of the entry + * @_list: Name of the list in which this entry is placed + * (with underscores instead of dots) + * + * This function returns (_type *) pointer after the very last entry of + * a linker-generated array placed into subsection of .u_boot_list + * section specified by _list argument. + * + * Since this macro defines an array end symbol, its leftmost index + * must be 2 and its rightmost index must be 3. + * + * Example: + * struct my_sub_cmd *msc = ll_entry_end(struct my_sub_cmd, cmd_sub); + */ +#define ll_entry_end(_type, _list) \ +({ \ + static char end[0] __attribute__((/*__aligned(4) ,*/ unused, \ + section(".u_boot_list_2_"#_list"_3"))); \ + (_type *)&end; \ +}) +/** + * ll_entry_count() - Return the number of elements in linker-generated array + * @_type: Data type of the entry + * @_list: Name of the list of which the number of elements is computed + * + * This function returns the number of elements of a linker-generated array + * placed into subsection of .u_boot_list section specified by _list + * argument. The result is of an unsigned int type. + * + * Example: + * int i; + * const unsigned int count = ll_entry_count(struct my_sub_cmd, cmd_sub); + * struct my_sub_cmd *msc = ll_entry_start(struct my_sub_cmd, cmd_sub); + * for (i = 0; i < count; i++, msc++) + * printf("Entry %i, x=%i y=%i\n", i, msc->x, msc->y); + */ +#define ll_entry_count(_type, _list) \ + ({ \ + _type *start = ll_entry_start(_type, _list); \ + _type *end = ll_entry_end(_type, _list); \ + unsigned int _ll_result = end - start; \ + _ll_result; \ + }) + +/** + * ll_entry_get() - Retrieve entry from linker-generated array by name + * @_type: Data type of the entry + * @_name: Name of the entry + * @_list: Name of the list in which this entry is placed + * + * This function returns a pointer to a particular entry in LG-array + * identified by the subsection of u_boot_list where the entry resides + * and it's name. + * + * Example: + * ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = { + * .x = 3, + * .y = 4, + * }; + * ... + * struct my_sub_cmd *c = ll_entry_get(struct my_sub_cmd, my_sub_cmd, cmd_sub); + */ +#define ll_entry_get(_type, _name, _list) \ + ({ \ + extern _type _u_boot_list_2_##_list##_2_##_name; \ + _type *_ll_result = \ + &_u_boot_list_2_##_list##_2_##_name; \ + _ll_result; \ + }) + +/** + * ll_start() - Point to first entry of first linker-generated array + * @_type: Data type of the entry + * + * This function returns (_type *) pointer to the very first entry of + * the very first linker-generated array. + * + * Since this macro defines the start of the linker-generated arrays, + * its leftmost index must be 1. + * + * Example: + * struct my_sub_cmd *msc = ll_start(struct my_sub_cmd); + */ +#define ll_start(_type) \ +({ \ + static char start[0] /*__aligned(4)*/ __attribute__((unused, \ + section(".u_boot_list_1"))); \ + (_type *)&start; \ +}) + +/** + * ll_entry_end() - Point after last entry of last linker-generated array + * @_type: Data type of the entry + * + * This function returns (_type *) pointer after the very last entry of + * the very last linker-generated array. + * + * Since this macro defines the end of the linker-generated arrays, + * its leftmost index must be 3. + * + * Example: + * struct my_sub_cmd *msc = ll_end(struct my_sub_cmd); + */ +#define ll_end(_type) \ +({ \ + static char end[0] /*__aligned(4)*/ __attribute__((unused, \ + section(".u_boot_list_3"))); \ + (_type *)&end; \ +}) + +#endif /* __ASSEMBLY__ */ + +#endif /* __LINKER_LISTS_H__ */ diff --git a/payloads/ubootcli/main.c b/payloads/ubootcli/main.c new file mode 100644 index 0000000000..2d7dab187d --- /dev/null +++ b/payloads/ubootcli/main.c @@ -0,0 +1,1098 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Add to readline cmdline-editing by + * (C) Copyright 2005 + * JinHua Luo, GuangDong Linux Center, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* #define DEBUG */ + +#include "ubootcli.h" + +/* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +void __show_boot_progress (int val) {} +void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); + +#define MAX_DELAY_STOP_STR 32 + +#define DEBUG_PARSER 0 /* set to 1 to debug */ + +#define debug_parser(fmt, args...) \ + debug_cond(DEBUG_PARSER, fmt, ##args) + +#ifndef DEBUG_BOOTKEYS +#define DEBUG_BOOTKEYS 0 +#endif +#define debug_bootkeys(fmt, args...) \ + debug_cond(DEBUG_BOOTKEYS, fmt, ##args) + +char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ + +#ifdef CONFIG_CMDLINE +static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); +#endif +static const char erase_seq[] = "\b \b"; /* erase sequence */ +static const char tab_seq[] = " "; /* used to expand TABs */ + +#ifdef CONFIG_BOOT_RETRY_TIME +static uint64_t endtime = 0; /* must be set, default is instant timeout */ +static int retry_time = -1; /* -1 so can call readline before main_loop */ +#endif + +#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) + +#ifndef CONFIG_BOOT_RETRY_MIN +#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME +#endif + +#ifdef CONFIG_MODEM_SUPPORT +int do_mdm_init = 0; +extern void mdm_init(void); /* defined in board.c */ +#endif + + +void main_loop(void) +{ + int len, flag, rc = 0; + char lastcommand[128]; + /* + * Main Loop for Monitor Command Processing + */ + for (;;) { + len = ubreadline (CONFIG_SYS_PROMPT); + + flag = 0; /* assume no special flags for now */ + if (len > 0) + strcpy (lastcommand, console_buffer); + else if (len == 0) + flag |= CMD_FLAG_REPEAT; + + if (len == -1) + printf ("\n"); + else + rc = run_command(lastcommand, flag); + + if (rc <= 0) { + /* invalid command or not repeatable, forget it */ + lastcommand[0] = 0; + } + } +} + +#ifdef CONFIG_CMDLINE_EDITING + +/* + * cmdline-editing related codes from vivi. + * Author: Janghoon Lyu + */ + +#define putnstr(str,n) do { \ + printf ("%.*s", (int)n, str); \ + } while (0) + +#define CTL_CH(c) ((c) - 'a' + 1) +#define CTL_BACKSPACE ('\b') +#define DEL ((char)255) +#define DEL7 ((char)127) +#define CREAD_HIST_CHAR ('!') + +#define getcmd_putch(ch) serial_putchar(ch) +#define getcmd_getch() serial_getchar() +#define getcmd_cbeep() getcmd_putch('\a') + +#define HIST_MAX 20 +#define HIST_SIZE CONFIG_SYS_CBSIZE + +static int hist_max; +static int hist_add_idx; +static int hist_cur = -1; +static unsigned hist_num; + +static char *hist_list[HIST_MAX]; +static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */ + +#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1) + +static void hist_init(void) +{ + int i; + + hist_max = 0; + hist_add_idx = 0; + hist_cur = -1; + hist_num = 0; + + for (i = 0; i < HIST_MAX; i++) { + hist_list[i] = hist_lines[i]; + hist_list[i][0] = '\0'; + } +} + +static void cread_add_to_hist(char *line) +{ + strcpy(hist_list[hist_add_idx], line); + + if (++hist_add_idx >= HIST_MAX) + hist_add_idx = 0; + + if (hist_add_idx > hist_max) + hist_max = hist_add_idx; + + hist_num++; +} + +static char* hist_prev(void) +{ + char *ret; + int old_cur; + + if (hist_cur < 0) + return NULL; + + old_cur = hist_cur; + if (--hist_cur < 0) + hist_cur = hist_max; + + if (hist_cur == hist_add_idx) { + hist_cur = old_cur; + ret = NULL; + } else + ret = hist_list[hist_cur]; + + return (ret); +} + +static char* hist_next(void) +{ + char *ret; + + if (hist_cur < 0) + return NULL; + + if (hist_cur == hist_add_idx) + return NULL; + + if (++hist_cur > hist_max) + hist_cur = 0; + + if (hist_cur == hist_add_idx) { + ret = ""; + } else + ret = hist_list[hist_cur]; + + return (ret); +} + +#ifndef CONFIG_CMDLINE_EDITING +static void cread_print_hist_list(void) +{ + int i; + unsigned long n; + + n = hist_num - hist_max; + + i = hist_add_idx + 1; + while (1) { + if (i > hist_max) + i = 0; + if (i == hist_add_idx) + break; + printf("%s\n", hist_list[i]); + n++; + i++; + } +} +#endif /* CONFIG_CMDLINE_EDITING */ + +#define BEGINNING_OF_LINE() { \ + while (num) { \ + getcmd_putch(CTL_BACKSPACE); \ + num--; \ + } \ +} + +#define ERASE_TO_EOL() { \ + if (num < eol_num) { \ + printf("%*s", (int)(eol_num - num), ""); \ + do { \ + getcmd_putch(CTL_BACKSPACE); \ + } while (--eol_num > num); \ + } \ +} + +#define REFRESH_TO_EOL() { \ + if (num < eol_num) { \ + wlen = eol_num - num; \ + putnstr(buf + num, wlen); \ + num = eol_num; \ + } \ +} + +static void cread_add_char(char ichar, int insert, unsigned long *num, + unsigned long *eol_num, char *buf, unsigned long len) +{ + unsigned long wlen; + + /* room ??? */ + if (insert || *num == *eol_num) { + if (*eol_num > len - 1) { + getcmd_cbeep(); + return; + } + (*eol_num)++; + } + + if (insert) { + wlen = *eol_num - *num; + if (wlen > 1) { + memmove(&buf[*num+1], &buf[*num], wlen-1); + } + + buf[*num] = ichar; + putnstr(buf + *num, wlen); + (*num)++; + while (--wlen) { + getcmd_putch(CTL_BACKSPACE); + } + } else { + /* echo the character */ + wlen = 1; + buf[*num] = ichar; + putnstr(buf + *num, wlen); + (*num)++; + } +} + +static void cread_add_str(char *str, int strsize, int insert, unsigned long *num, + unsigned long *eol_num, char *buf, unsigned long len) +{ + while (strsize--) { + cread_add_char(*str, insert, num, eol_num, buf, len); + str++; + } +} + +static int cread_line(const char *const prompt, char *buf, unsigned int *len, + int timeout) +{ + unsigned long num = 0; + unsigned long eol_num = 0; + unsigned long wlen; + char ichar; + int insert = 1; + int esc_len = 0; + char esc_save[8]; + int init_len = strlen(buf); + //int first = 1; + + if (init_len) + cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); + + while (1) { +#if 0 +#ifdef CONFIG_BOOT_RETRY_TIME + while (!tstc()) { /* while no incoming data */ + if (retry_time >= 0 && get_ticks() > endtime) + return (-2); /* timed out */ +// WATCHDOG_RESET(); + } +#endif + if (first && timeout) { + uint64_t etime = endtick(timeout); + + while (!tstc()) { /* while no incoming data */ + if (get_ticks() >= etime) + return -2; /* timed out */ + WATCHDOG_RESET(); + } + first = 0; + } +#endif + ichar = getcmd_getch(); + + if ((ichar == '\n') || (ichar == '\r')) { + serial_putchar('\n'); + break; + } + + /* + * handle standard linux xterm esc sequences for arrow key, etc. + */ + if (esc_len != 0) { + if (esc_len == 1) { + if (ichar == '[') { + esc_save[esc_len] = ichar; + esc_len = 2; + } else { + cread_add_str(esc_save, esc_len, insert, + &num, &eol_num, buf, *len); + esc_len = 0; + } + continue; + } + + switch (ichar) { + + case 'D': /* <- key */ + ichar = CTL_CH('b'); + esc_len = 0; + break; + case 'C': /* -> key */ + ichar = CTL_CH('f'); + esc_len = 0; + break; /* pass off to ^F handler */ + case 'H': /* Home key */ + ichar = CTL_CH('a'); + esc_len = 0; + break; /* pass off to ^A handler */ + case 'A': /* up arrow */ + ichar = CTL_CH('p'); + esc_len = 0; + break; /* pass off to ^P handler */ + case 'B': /* down arrow */ + ichar = CTL_CH('n'); + esc_len = 0; + break; /* pass off to ^N handler */ + default: + esc_save[esc_len++] = ichar; + cread_add_str(esc_save, esc_len, insert, + &num, &eol_num, buf, *len); + esc_len = 0; + continue; + } + } + + switch (ichar) { + case 0x1b: + if (esc_len == 0) { + esc_save[esc_len] = ichar; + esc_len = 1; + } else { + printf("impossible condition #876\n"); + esc_len = 0; + } + break; + + case CTL_CH('a'): + BEGINNING_OF_LINE(); + break; + case CTL_CH('c'): /* ^C - break */ + *buf = '\0'; /* discard input */ + return (-1); + case CTL_CH('f'): + if (num < eol_num) { + getcmd_putch(buf[num]); + num++; + } + break; + case CTL_CH('b'): + if (num) { + getcmd_putch(CTL_BACKSPACE); + num--; + } + break; + case CTL_CH('d'): + if (num < eol_num) { + wlen = eol_num - num - 1; + if (wlen) { + memmove(&buf[num], &buf[num+1], wlen); + putnstr(buf + num, wlen); + } + + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (wlen--); + eol_num--; + } + break; + case CTL_CH('k'): + ERASE_TO_EOL(); + break; + case CTL_CH('e'): + REFRESH_TO_EOL(); + break; + case CTL_CH('o'): + insert = !insert; + break; + case CTL_CH('x'): + case CTL_CH('u'): + BEGINNING_OF_LINE(); + ERASE_TO_EOL(); + break; + case DEL: + case DEL7: + case 8: + if (num) { + wlen = eol_num - num; + num--; + memmove(&buf[num], &buf[num+1], wlen); + getcmd_putch(CTL_BACKSPACE); + putnstr(buf + num, wlen); + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (wlen--); + eol_num--; + } + break; + case CTL_CH('p'): + case CTL_CH('n'): + { + char * hline; + + esc_len = 0; + + if (ichar == CTL_CH('p')) + hline = hist_prev(); + else + hline = hist_next(); + + if (!hline) { + getcmd_cbeep(); + continue; + } + + /* nuke the current line */ + /* first, go home */ + BEGINNING_OF_LINE(); + + /* erase to end of line */ + ERASE_TO_EOL(); + + /* copy new line into place and display */ + strcpy(buf, hline); + eol_num = strlen(buf); + REFRESH_TO_EOL(); + continue; + } +#ifdef CONFIG_AUTO_COMPLETE + case '\t': { + int num2, col; + + /* do not autocomplete when in the middle */ + if (num < eol_num) { + getcmd_cbeep(); + break; + } + + buf[num] = '\0'; + col = strlen(prompt) + eol_num; + num2 = num; + if (cmd_auto_complete(prompt, buf, &num2, &col)) { + col = num2 - num; + num += col; + eol_num += col; + } + break; + } +#endif + default: + cread_add_char(ichar, insert, &num, &eol_num, buf, *len); + break; + } + } + *len = eol_num; + buf[eol_num] = '\0'; /* lose the newline */ + + if (buf[0] && buf[0] != CREAD_HIST_CHAR) + cread_add_to_hist(buf); + hist_cur = hist_add_idx; + + return 0; +} + +#endif /* CONFIG_CMDLINE_EDITING */ + +/****************************************************************************/ + +#ifdef CONFIG_CMDLINE +/* + * Prompt for input and read a line. + * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, + * time out when time goes past endtime (timebase time in ticks). + * Return: number of read characters + * -1 if break + * -2 if timed out + */ +int ubreadline (const char *const prompt) +{ + /* + * If console_buffer isn't 0-length the user will be prompted to modify + * it instead of entering it from scratch as desired. + */ + console_buffer[0] = '\0'; + + return ubreadline_into_buffer(prompt, console_buffer, 0); +} + + +int ubreadline_into_buffer(const char *const prompt, char *buffer, int timeout) +{ + char *p = buffer; + unsigned int len = CONFIG_SYS_CBSIZE; + int rc; + static int initted = 0; + + /* + * History uses a global array which is not + * writable until after relocation to RAM. + * Revert to non-history version if still + * running from flash. + */ + if (0) { + if (!initted) { + hist_init(); + initted = 1; + } + + if (prompt) + printf (prompt); + + rc = cread_line(prompt, p, &len, timeout); + return rc < 0 ? rc : len; + + } else { + char * p_buf = p; + int n = 0; /* buffer index */ + int plen = 0; /* prompt length */ + int col; /* output column cnt */ + char c; + + /* print prompt */ + if (prompt) { + plen = strlen (prompt); + printf (prompt); + } + col = plen; + + for (;;) { + + c = serial_getchar(); + + /* + * Special character handling + */ + switch (c) { + case '\r': /* Enter */ + case '\n': + *p = '\0'; + printf ("\r\n"); + return p - p_buf; + + case '\0': /* nul */ + continue; + + case 0x03: /* ^C - break */ + p_buf[0] = '\0'; /* discard input */ + return -1; + + case 0x15: /* ^U - erase line */ + while (col > plen) { + printf (erase_seq); + --col; + } + p = p_buf; + n = 0; + continue; + + case 0x17: /* ^W - erase word */ + p=delete_char(p_buf, p, &col, &n, plen); + while ((n > 0) && (*p != ' ')) { + p=delete_char(p_buf, p, &col, &n, plen); + } + continue; + + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + p=delete_char(p_buf, p, &col, &n, plen); + continue; + + default: + /* + * Must be a normal character then + */ + if (n < CONFIG_SYS_CBSIZE-2) { + if (c == '\t') { /* expand TABs */ + /* if auto completion triggered just continue */ + *p = '\0'; + if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { + p = p_buf + n; /* reset */ + continue; + } + printf (tab_seq+(col&07)); + col += 8 - (col&07); + } else { + char buf[2]; + + /* + * Echo input using printf() to force an + * LCD flush if we are using an LCD + */ + ++col; + buf[0] = c; + buf[1] = '\0'; + printf(buf); + } + *p++ = c; + ++n; + } else { /* Buffer full */ + serial_putchar('\a'); + } + } + } + } +} + +/****************************************************************************/ + +static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) +{ + char *s; + + if (*np == 0) { + return (p); + } + + if (*(--p) == '\t') { /* will retype the whole line */ + while (*colp > plen) { + printf (erase_seq); + (*colp)--; + } + for (s=buffer; s= CONFIG_SYS_CBSIZE) { + printf ("## Command too long!\n"); + return -1; + } + + strcpy (cmdbuf, cmd); + + /* Process separators and check for invalid + * repeatable commands + */ + + debug_parser("[PROCESS_SEPARATORS] %s\n", cmd); + while (*str) { + + /* + * Find separator, or string end + * Allow simple escape of ';' by writing "\;" + */ + for (inquotes = 0, sep = str; *sep; sep++) { + if ((*sep=='\'') && + (*(sep-1) != '\\')) + inquotes=!inquotes; + + if (!inquotes && + (*sep == ';') && /* separator */ + ( sep != str) && /* past string start */ + (*(sep-1) != '\\')) /* and NOT escaped */ + break; + } + + /* + * Limit the token to data between separators + */ + token = str; + if (*sep) { + str = sep + 1; /* start of command for next pass */ + *sep = '\0'; + } + else + str = sep; /* no more commands for next pass */ + debug_parser("token: \"%s\"\n", token); + + /* find macros in this token and replace them */ + process_macros (token, finaltoken); + + /* Extract arguments */ + if ((argc = parse_line (finaltoken, argv)) == 0) { + rc = -1; /* no command at all */ + continue; + } + + if (cmd_process(flag, argc, argv, &repeatable, NULL)) + rc = -1; + + /* Did the user stop this? */ + //if (had_ctrlc ()) + // return -1; /* if stopped then not repeatable */ + } + + return rc ? rc : repeatable; +} +#endif + +#ifdef CONFIG_CMDLINE +/* + * Run a command using the selected parser. + * + * @param cmd Command to run + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +int run_command(const char *cmd, int flag) +{ +#ifndef CONFIG_SYS_HUSH_PARSER + /* + * builtin_run_command can return 0 or 1 for success, so clean up + * its result. + */ + if (builtin_run_command(cmd, flag) == -1) + return 1; + + return 0; +#else + return parse_string_outer(cmd, + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); +#endif +} +#endif + +#if !defined(CONFIG_SYS_HUSH_PARSER) && defined(CONFIG_CMDLINE) +/** + * Execute a list of command separated by ; or \n using the built-in parser. + * + * This function cannot take a const char * for the command, since if it + * finds newlines in the string, it replaces them with \0. + * + * @param cmd String containing list of commands + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +static int builtin_run_command_list(char *cmd, int flag) +{ + char *line, *next; + int rcode = 0; + + /* + * Break into individual lines, and execute each line; terminate on + * error. + */ + line = next = cmd; + while (*next) { + if (*next == '\n') { + *next = '\0'; + /* run only non-empty commands */ + if (*line) { + debug("** exec: \"%s\"\n", line); + if (builtin_run_command(line, 0) < 0) { + rcode = 1; + break; + } + } + line = next + 1; + } + ++next; + } + if (rcode == 0 && *line) + rcode = (builtin_run_command(line, 0) >= 0); + + return rcode; +} +#endif + +#ifdef CONFIG_CMDLINE +int run_command_list(const char *cmd, int len, int flag) +{ + int need_buff = 1; + char *buff = (char *)cmd; /* cast away const */ + int rcode = 0; + + if (len == -1) { + len = strlen(cmd); +#ifdef CONFIG_SYS_HUSH_PARSER + /* hush will never change our string */ + need_buff = 0; +#else + /* the built-in parser will change our string if it sees \n */ + need_buff = strchr(cmd, '\n') != NULL; +#endif + } + if (need_buff) { + buff = malloc(len + 1); + if (!buff) + return 1; + memcpy(buff, cmd, len); + buff[len] = '\0'; + } +#ifdef CONFIG_SYS_HUSH_PARSER + rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON); +#else + /* + * This function will overwrite any \n it sees with a \0, which + * is why it can't work with a const char *. Here we are making + * using of internal knowledge of this function, to avoid always + * doing a malloc() which is actually required only in a case that + * is pretty rare. + */ + rcode = builtin_run_command_list(buff, flag); + if (need_buff) + free(buff); +#endif + + return rcode; +} +#endif + +/****************************************************************************/ + +#if defined(CONFIG_CMD_RUN) +int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + + if (argc < 2) + return CMD_RET_USAGE; + + for (i=1; i +#include +#include +#include + +#endif diff --git a/payloads/ubootcli/ubootcli.ldscript.arm b/payloads/ubootcli/ubootcli.ldscript.arm new file mode 100644 index 0000000000..1717dee8cf --- /dev/null +++ b/payloads/ubootcli/ubootcli.ldscript.arm @@ -0,0 +1,93 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +BASE_ADDRESS = 0x81000000; + +/*OUTPUT_FORMAT(armv7a-eabi) +OUTPUT_ARCH(arm)*/ + +ENTRY(_entry) + +/* The heap size must be large enough to contain video console buffer. */ +HEAP_SIZE = 65536; +STACK_SIZE = 65536; + +SECTIONS +{ + . = BASE_ADDRESS; + + . = ALIGN(16); + _start = .; + + .text : { + *(.text._entry) + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + /* whatever. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + + .data : { + *(.data) + *(.data.*) + } + + _edata = .; + + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + + /* Stack and heap */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _estack = .; + . += STACK_SIZE; + . = ALIGN(16); + _stack = .; + } + + _end = .; + + /DISCARD/ : { *(.comment) *(.note) *(.note.*) } +} diff --git a/payloads/ubootcli/ubootcli.ldscript.i386 b/payloads/ubootcli/ubootcli.ldscript.i386 new file mode 100644 index 0000000000..9e2eeac6e6 --- /dev/null +++ b/payloads/ubootcli/ubootcli.ldscript.i386 @@ -0,0 +1,88 @@ +/* + * This file is part of the bayou project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +BASE_ADDRESS = 0x19000; + +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386) + +ENTRY(_entry) + +/* The heap size must be large enough to contain video console buffer. */ +HEAP_SIZE = 65536; +STACK_SIZE = 65536; + +SECTIONS +{ + . = BASE_ADDRESS; + + . = ALIGN(16); + _start = .; + + .text : { + *(.text._entry) + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + .data : { + *(.data) + *(.data.*) + } + + _edata = .; + + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + + /* Stack and heap */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _estack = .; + . += STACK_SIZE; + . = ALIGN(16); + _stack = .; + } + + _end = .; + + /DISCARD/ : { *(.comment) *(.note) *(.note.*) } +} diff --git a/src/Kconfig b/src/Kconfig index c3cc6bffc6..0f87099808 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -20,6 +20,49 @@ mainmenu "coreboot configuration" +source src/mainboard/Kconfig + +# This option is used to set the architecture of a mainboard to X86. +# It is usually set in mainboard/*/Kconfig. +config ARCH_X86 + bool + default n + select PCI + +config ARCH_ARM + bool + default n + +config ARCH_ARM64 + bool + default n + +config ARCH_MIPS + bool + default n + +source src/arch/x86/Kconfig +source src/arch/arm/Kconfig +source src/arch/arm64/Kconfig +source src/arch/mips/Kconfig + +menu "Chipset" + +comment "CPU" +source src/cpu/Kconfig +comment "Northbridge" +source src/northbridge/Kconfig +comment "Southbridge" +source src/southbridge/Kconfig +comment "Super I/O" +source src/superio/Kconfig +comment "Embedded Controllers" +source src/ec/Kconfig +comment "SoC" +source src/soc/Kconfig + +endmenu + menu "General setup" config EXPERT @@ -56,6 +99,14 @@ config ALT_CBFS_LOAD_PAYLOAD through memory-mapped I/O is slow and a faster alternative can be provided. +config COMMON_CBFS_SPI_WRAPPER + bool + default n + depends on SPI_FLASH + depends on !ARCH_X86 + help + Use common wrapper to interface CBFS to SPI bootprom. + choice prompt "Compiler to use" default COMPILER_GCC @@ -165,7 +216,7 @@ config INCLUDE_CONFIG_FILE Name Offset Type Size cmos_layout.bin 0x0 cmos layout 1159 fallback/romstage 0x4c0 stage 339756 - fallback/coreboot_ram 0x53440 stage 186664 + fallback/ramstage 0x53440 stage 186664 fallback/payload 0x80dc0 payload 51526 config 0x8d740 raw 3324 (empty) 0x8e480 null 3610440 @@ -194,6 +245,14 @@ config COLLECT_TIMESTAMPS Make coreboot create a table of timer-ID/timer-value pairs to allow measuring time spent at different phases of the boot process. +config HAS_PRECBMEM_TIMESTAMP_REGION + bool "Timestamp region exists for pre-cbmem timestamps" + depends on COLLECT_TIMESTAMPS + help + A separate region is maintained to allow storing of timestamps before + cbmem comes up. This is useful for storing timestamps across different + stage boundaries. + config USE_BLOBS bool "Allow use of binary-only repository" default n @@ -211,43 +270,14 @@ config COVERAGE coverage information in CBMEM for extraction from user space. If unsure, say N. -endmenu - -source src/mainboard/Kconfig - -# This option is used to set the architecture of a mainboard to X86. -# It is usually set in mainboard/*/Kconfig. -config ARCH_X86 - bool +config UPDATE_IMAGE + bool "Update existing coreboot.rom image" default n - select PCI - -config ARCH_ARMV7 - bool - default n - -# Warning: The file is included whether or not the if is here. -# but the if controls how the evaluation occurs. -if ARCH_X86 -source src/arch/x86/Kconfig -endif - -if ARCH_ARMV7 -source src/arch/armv7/Kconfig -endif - -menu "Chipset" - -comment "CPU" -source src/cpu/Kconfig -comment "Northbridge" -source src/northbridge/Kconfig -comment "Southbridge" -source src/southbridge/Kconfig -comment "Super I/O" -source src/superio/Kconfig -comment "Embedded Controllers" -source src/ec/Kconfig + help + If this option is enabled, no new coreboot.rom file + is created. Instead it is expected that there already + is a suitable file for further processing. + The bootblock will not be modified. endmenu @@ -257,10 +287,27 @@ menu "Generic Drivers" source src/drivers/Kconfig endmenu +config TPM + bool + default n + select LPC_TPM if ARCH_X86 + select I2C_TPM if ARCH_ARM + select I2C_TPM if ARCH_ARM64 + help + Enable this option to enable TPM support in coreboot. + + If unsure, say N. + config HEAP_SIZE - hex + hex "Heap size in bytes" default 0x4000 +# Size of per-cpu stacks in ramstage. Set to 0 for non-SMP architectures. +config STACK_SIZE + hex + default 0x0 if (ARCH_RAMSTAGE_ARM || ARCH_RAMSTAGE_MIPS) + default 0x1000 + config MAX_CPUS int default 1 @@ -279,7 +326,8 @@ source src/console/Kconfig config HAVE_UART_IO_MAPPED bool default y if ARCH_X86 - default n if ARCH_ARMV7 + default n if ARCH_ARM + default n if ARCH_ARM64 config HAVE_UART_MEMORY_MAPPED bool @@ -308,10 +356,39 @@ config HAVE_HARD_RESET This variable specifies whether a given board has a hard_reset function, no matter if it's provided by board code or chipset code. -config HAVE_INIT_TIMER - bool - default n if UDELAY_IO - default y +config HAVE_MONOTONIC_TIMER + def_bool n + help + The board/chipset provides a monotonic timer. + +config GENERIC_UDELAY + def_bool n + depends on HAVE_MONOTONIC_TIMER + help + The board/chipset uses a generic udelay function utilizing the + monotonic timer. + +config TIMER_QUEUE + def_bool n + depends on HAVE_MONOTONIC_TIMER + help + Provide a timer queue for performing time-based callbacks. + +config COOP_MULTITASKING + def_bool n + depends on TIMER_QUEUE && ARCH_X86 + help + Cooperative multitasking allows callbacks to be multiplexed on the + main thread of ramstage. With this enabled it allows for multiple + execution paths to take place when they have udelay() calls within + their code. + +config NUM_THREADS + int + default 4 + depends on COOP_MULTITASKING + help + How many execution threads to cooperatively multitask with. config HIGH_SCRATCH_MEMORY_SIZE hex @@ -346,8 +423,14 @@ config IOAPIC default n config CBFS_SIZE - hex + hex "Size of CBFS filesystem in ROM" default ROM_SIZE + help + This is the part of the ROM actually managed by CBFS, located at the + end of the ROM (passed through cbfstool -o) on x86 and at at the start + of the ROM (passed through cbfstool -s) everywhere else. Defaults to + span the whole ROM but can be overwritten to make coreboot live + alongside other components (like ChromeOS's vboot/FMAP). config CACHE_ROM_SIZE hex @@ -393,6 +476,31 @@ config RELOCATABLE_RAMSTAGE wake. When selecting this option the romstage is responsible for determing a stack location to use for loading the ramstage. +config CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM + depends on RELOCATABLE_RAMSTAGE + bool "Cache the relocated ramstage outside of cbmem." + default n + help + The relocated ramstage is saved in an area specified by the + by the board and/or chipset. + +config HAVE_REFCODE_BLOB + depends on ARCH_X86 + bool "An external reference code blob should be put into cbfs." + default n + help + The reference code blob will be placed into cbfs. + +if HAVE_REFCODE_BLOB + +config REFCODE_BLOB_FILE + string "Path and filename to reference code blob." + default "refcode.elf" + help + The path and filename to the file to be added to cbfs. + +endif # HAVE_REFCODE_BLOB + config HAVE_ACPI_TABLES bool help @@ -504,6 +612,17 @@ config PAYLOAD_ELF You will be able to specify the location and file name of the payload image later. +config PAYLOAD_LINUX + bool "A Linux payload" + help + Select this option if you have a Linux bzImage which coreboot + should run as soon as the basic hardware initialization + is completed. + + You will be able to specify the location and file name of the + payload image later. + + config PAYLOAD_SEABIOS bool "SeaBIOS" depends on ARCH_X86 @@ -571,6 +690,13 @@ config PAYLOAD_FILE help The path and filename of the ELF executable file to use as payload. + config PAYLOAD_FILE + string "Linux path and filename" + depends on PAYLOAD_LINUX + default "bzImage" + help + The path and filename of the bzImage kernel to use as payload. + config PAYLOAD_FILE depends on PAYLOAD_SEABIOS default "$(obj)/seabios/out/bios.bin.elf" @@ -595,6 +721,20 @@ config COMPRESSED_PAYLOAD_LZMA In order to reduce the size payloads take up in the ROM chip coreboot can compress them using the LZMA algorithm. +config LINUX_COMMAND_LINE + string "Linux command line" + depends on PAYLOAD_LINUX + default "" + help + A command line to add to the Linux kernel. + +config LINUX_INITRD + string "Linux initrd" + depends on PAYLOAD_LINUX + default "" + help + An initrd image to add to the Linux kernel. + config COMPRESSED_PAYLOAD_NRV2B bool default n @@ -929,13 +1069,33 @@ config DEBUG_COVERAGE If enabled, the code coverage hooks in coreboot will output some information about the coverage data that is dumped. +config GENERIC_GPIO_LIB + bool "Build generic GPIO library" + default n + help + If enabled, compile the generic GPIO library. A "generic" GPIO + implies configurability usually found on SoCs, particularly the + ability to control internal pull resistors. + +config BOARD_ID_SUPPORT + bool "Discover board ID and store it in coreboot table" + default n + select GENERIC_GPIO_LIB + help + If enabled, coreboot discovers the board id of the hardware it is + running on and reports it through the coreboot table to the rest of + the system. + +config RAM_CODE_SUPPORT + bool "Discover RAM configuration code and store it in coreboot table" + default n + help + If enabled, coreboot discovers RAM configuration (value obtained by + reading board straps) and stores it in coreboot table. + endmenu # These probably belong somewhere else, but they are needed somewhere. -config AP_CODE_IN_CAR - bool - default n - config RAMINIT_SYSINFO bool default n @@ -987,4 +1147,17 @@ config POWER_BUTTON_IS_OPTIONAL help Internal option that controls ENABLE_POWER_BUTTON visibility. +config REG_SCRIPT + bool + default y if ARCH_X86 + default n + help + Internal option that controls whether we compile in register scripts. + source src/vendorcode/Kconfig + +# Maximum reboot count +# TODO: Improve description. +config MAX_REBOOT_CNT + int + default 3 diff --git a/src/arch/arm/Kconfig b/src/arch/arm/Kconfig new file mode 100644 index 0000000000..25d959c2c2 --- /dev/null +++ b/src/arch/arm/Kconfig @@ -0,0 +1,33 @@ +menu "Architecture (arm)" + +config ARCH_BOOTBLOCK_ARM + bool + default n + select ARCH_ARM + +config ARCH_VERSTAGE_ARM + bool + default n + +config ARCH_ROMSTAGE_ARM + bool + default n + +config ARCH_RAMSTAGE_ARM + bool + default n + +source src/arch/arm/armv4/Kconfig +source src/arch/arm/armv7/Kconfig + +# If a custom bootblock is necessary, this option should be "select"-ed by +# the thing that needs it, probably the CPU. +config ARM_BOOTBLOCK_CUSTOM + bool + default n + +config ARM_LPAE + bool "Enable LPAE" + default n + +endmenu diff --git a/src/arch/arm/Makefile.inc b/src/arch/arm/Makefile.inc new file mode 100644 index 0000000000..5eb74fa7d6 --- /dev/null +++ b/src/arch/arm/Makefile.inc @@ -0,0 +1,142 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012-2013 The ChromiumOS Authors +## Copyright (C) 2012 Alexandru Gagniuc +## Copyright (C) 2009-2010 coresystems GmbH +## Copyright (C) 2009 Ronald G. Minnich +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +############################################################################### +# Take care of subdirectories +############################################################################### +subdirs-y += boot/ +subdirs-y += lib/ +subdirs-y += libgcc/ +subdirs-y += armv4/ armv7/ + +############################################################################### +# ARM specific options +############################################################################### + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM),y) +CBFSTOOL_PRE1_OPTS = -m arm -s $(CONFIG_CBFS_SIZE) +endif + +############################################################################### +# bootblock +############################################################################### + +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM),y) + +bootblock-y += div0.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += early_console.c +bootblock-y += id.S +bootblock-y += clock.c +bootblock-y += stages.c +bootblock-y += eabi_compat.c +bootblock-y += memset.S +bootblock-y += memcpy.S +bootblock-y += memmove.S +bootblock-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +$(objcbfs)/bootblock.debug: $$(bootblock-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,bootblock,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld,--gc-sections) + +endif # CONFIG_ARCH_BOOTBLOCK_ARM + +############################################################################### +# verification stage +############################################################################### + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM),y) + +$(objcbfs)/verstage.debug: $$(verstage-objs) $$(VB2_LIB) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,verstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.verstage.ld,--gc-sections) + +verstage-$(CONFIG_EARLY_CONSOLE) += early_console.c +verstage-y += div0.c +verstage-y += eabi_compat.c +verstage-y += memset.S +verstage-y += memcpy.S +verstage-y += memmove.S +verstage-y += stages.c +verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +endif # CONFIG_ARCH_VERSTAGE_ARM + +############################################################################### +# romstage +############################################################################### + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM),y) + +romstage-y += stages.c +romstage-y += div0.c +romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c +romstage-y += eabi_compat.c +romstage-y += memset.S +romstage-y += memcpy.S +romstage-y += memmove.S +romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +romstage-y += clock.c + +rmodules_arm-y += memset.S +rmodules_arm-y += memcpy.S +rmodules_arm-y += memmove.S +rmodules_arm-y += eabi_compat.c + +VBOOT_STUB_DEPS += $(obj)/arch/arm/eabi_compat.rmodules_arm.o + +$(objcbfs)/romstage.debug: $$(romstage-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,romstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld,--gc-sections) + +endif # CONFIG_ARCH_ROMSTAGE_ARM + +############################################################################### +# ramstage +############################################################################### + +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM),y) + +ramstage-y += stages.c +ramstage-y += div0.c +ramstage-$(CONFIG_COOP_MULTITASKING) += cpu.c +ramstage-y += eabi_compat.c +ramstage-y += boot.c +ramstage-y += tables.c +ramstage-y += memset.S +ramstage-y += memcpy.S +ramstage-y += memmove.S +ramstage-y += clock.c + +rmodules_arm-y += memset.S +rmodules_arm-y += memcpy.S +rmodules_arm-y += memmove.S +rmodules_arm-y += eabi_compat.c + +ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/mainboard.c + +$(objcbfs)/ramstage.debug: $$(ramstage-objs) + @printf " CC $(subst $(obj)/,,$(@))\n" + $(call link,ramstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld,--gc-sections) + +endif # CONFIG_ARCH_RAMSTAGE_ARM diff --git a/src/arch/arm/armv4/Kconfig b/src/arch/arm/armv4/Kconfig new file mode 100644 index 0000000000..6afce3a398 --- /dev/null +++ b/src/arch/arm/armv4/Kconfig @@ -0,0 +1,12 @@ +config ARCH_BOOTBLOCK_ARM_V4 + def_bool n + select ARCH_BOOTBLOCK_ARM +config ARCH_VERSTAGE_ARM_V4 + def_bool n + select ARCH_VERSTAGE_ARM +config ARCH_ROMSTAGE_ARM_V4 + def_bool n + select ARCH_ROMSTAGE_ARM +config ARCH_RAMSTAGE_ARM_V4 + def_bool n + select ARCH_RAMSTAGE_ARM diff --git a/src/arch/arm/armv4/Makefile.inc b/src/arch/arm/armv4/Makefile.inc new file mode 100644 index 0000000000..0932466d5a --- /dev/null +++ b/src/arch/arm/armv4/Makefile.inc @@ -0,0 +1,73 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +armv4_flags = -marm -march=armv4t -I$(src)/arch/arm/include/armv4/ \ + -D__COREBOOT_ARM_ARCH__=4 + +################################################################################ +## Bootblock +################################################################################ +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM_V4),y) + +ifneq ($(CONFIG_ARM_BOOTBLOCK_CUSTOM),y) +bootblock-y += bootblock.S +bootblock-y += bootblock_simple.c +endif +bootblock-y += cache.c + +bootblock-c-ccopts += $(armv4_flags) +bootblock-S-ccopts += $(armv4_flags) + +endif + +################################################################################ +## Verstage +################################################################################ + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM_V4),y) +verstage-c-ccopts += $(armv4_flags) +verstage-S-ccopts += $(armv4_flags) + +verstage-y += cache.c +endif + +################################################################################ +## ROM stage +################################################################################ +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM_V4),y) + +romstage-c-ccopts += $(armv4_flags) +romstage-S-ccopts += $(armv4_flags) +romstage-y += cache.c + +rmodules_arm-c-ccopts += $(armv4_flags) +rmodules_arm-S-ccopts += $(armv4_flags) + +endif +################################################################################ +## RAM stage +################################################################################ +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM_V4),y) + +ramstage-c-ccopts += $(armv4_flags) +ramstage-S-ccopts += $(armv4_flags) + +endif diff --git a/src/arch/arm/armv4/bootblock.S b/src/arch/arm/armv4/bootblock.S new file mode 100644 index 0000000000..1a30dda65e --- /dev/null +++ b/src/arch/arm/armv4/bootblock.S @@ -0,0 +1,75 @@ +/* + * Early initialization code for ARM architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +ENTRY(_start) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr_cxf, #0xdf + + /* + * Initialize the stack to a known value. This is used to check for + * stack overflow later in the boot process. + */ + ldr r0, =_stack + ldr r1, =_estack + ldr r2, =0xdeadbeef +init_stack_loop: + str r2, [r0] + add r0, #4 + cmp r0, r1 + bne init_stack_loop + +/* Set stackpointer in internal RAM to call bootblock main() */ +call_bootblock: + ldr sp, =_estack /* Set up stack pointer */ + ldr r0,=0x00000000 + /* + * The current design of cpu_info places the + * struct at the top of the stack. The number of + * words pushed must be at least as large as that + * struct. + */ + push {r0-r2} + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + /* + * Use "bl" instead of "b" even though we do not intend to return. + * "bl" gets compiled to "blx" if we're transitioning from ARM to + * Thumb. However, "b" will not and GCC may attempt to create a + * wrapper which is currently broken. + */ + bl main +ENDPROC(_start) diff --git a/src/arch/arm/armv4/bootblock_simple.c b/src/arch/arm/armv4/bootblock_simple.c new file mode 100644 index 0000000000..05075c4986 --- /dev/null +++ b/src/arch/arm/armv4/bootblock_simple.c @@ -0,0 +1,60 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2010 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +__attribute__((weak)) void bootblock_mainboard_early_init(void) { /* no-op */ } +__attribute__((weak)) void bootblock_soc_init(void) { /* do nothing */ } +__attribute__((weak)) void bootblock_mainboard_init(void) { /* do nothing */ } + +void main(void) +{ + const char *stage_name = "fallback/romstage"; + void *entry; + + init_timer(); + if (IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION)) + timestamp_early_init(timestamp_get()); + + bootblock_mainboard_early_init(); + + if (CONFIG_BOOTBLOCK_CONSOLE) { + console_init(); + exception_init(); + } + + bootblock_soc_init(); + bootblock_mainboard_init(); + + timestamp_add_now(TS_START_COPYROM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, stage_name); + timestamp_add_now(TS_END_COPYROM); + + if (entry) stage_exit(entry); + hlt(); +} diff --git a/src/arch/arm/armv4/cache.c b/src/arch/arm/armv4/cache.c new file mode 100644 index 0000000000..140beee060 --- /dev/null +++ b/src/arch/arm/armv4/cache.c @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R + * + * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition + */ + +#include + +#include + +void tlb_invalidate_all(void) +{ +} + +void dcache_clean_all(void) +{ +} + +void dcache_clean_invalidate_all(void) +{ +} + +void dcache_invalidate_all(void) +{ +} + +unsigned int dcache_line_bytes(void) +{ + /* + * TODO: Implement this correctly. For now we just return a + * reasonable value. It was added during Nyan development and + * may be used in bootblock code. It matters only if dcache is + * turned on. + */ + return 64; +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ +} + +void dcache_mmu_disable(void) +{ +} + +void dcache_mmu_enable(void) +{ +} + +void cache_sync_instructions(void) +{ +} diff --git a/src/arch/arm/armv7/Kconfig b/src/arch/arm/armv7/Kconfig new file mode 100644 index 0000000000..bf3d57f366 --- /dev/null +++ b/src/arch/arm/armv7/Kconfig @@ -0,0 +1,18 @@ +config ARCH_BOOTBLOCK_ARM_V7 + def_bool n + select ARCH_BOOTBLOCK_ARM +config ARCH_VERSTAGE_ARM_V7 + def_bool n + select ARCH_VERSTAGE_ARM +config ARCH_ROMSTAGE_ARM_V7 + def_bool n + select ARCH_ROMSTAGE_ARM +config ARCH_RAMSTAGE_ARM_V7 + def_bool n + select ARCH_RAMSTAGE_ARM +config ARCH_BOOTBLOCK_ARM_V7_M + def_bool n + select ARCH_BOOTBLOCK_ARM +config ARCH_VERSTAGE_ARM_V7_M + def_bool n + select ARCH_VERSTAGE_ARM diff --git a/src/arch/arm/armv7/Makefile.inc b/src/arch/arm/armv7/Makefile.inc new file mode 100644 index 0000000000..6d583ec3ce --- /dev/null +++ b/src/arch/arm/armv7/Makefile.inc @@ -0,0 +1,114 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +armv7_flags = -mthumb -I$(src)/arch/arm/include/armv7/ -D__COREBOOT_ARM_ARCH__=7 +armv7-a_flags = -march=armv7-a $(armv7_flags) +armv7-m_flags = -march=armv7-m $(armv7_flags) + +armv7_asm_flags = -Wa,-mthumb -Wa,-mimplicit-it=always -Wa,-mno-warn-deprecated +armv7-a_asm_flags = $(armv7-a_flags) $(armv7_asm_flags) +armv7-m_asm_flags = $(armv7-m_flags) $(armv7_asm_flags) + +################################################################################ +## Bootblock +################################################################################ +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM_V7),y) +bootblock-c-ccopts += $(armv7-a_flags) +bootblock-S-ccopts += $(armv7-a_asm_flags) + +ifneq ($(CONFIG_ARM_BOOTBLOCK_CUSTOM),y) +bootblock-y += bootblock.S +bootblock-y += bootblock_simple.c +endif +bootblock-y += cache.c +bootblock-y += cpu.S +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += exception.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += exception_asm.S +bootblock-y += mmu.c + +else ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM_V7_M),y) +bootblock-c-ccopts += $(armv7-m_flags) +bootblock-S-ccopts += $(armv7-m_asm_flags) + +ifneq ($(CONFIG_ARM_BOOTBLOCK_CUSTOM),y) +bootblock-y += bootblock_m.S +bootblock-y += bootblock_simple.c +endif +bootblock-y += exception_m.c +bootblock-y += cache_m.c + +endif + +################################################################################ +## Verification stage +################################################################################ + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM_V7),y) +verstage-c-ccopts += $(armv7-a_flags) +verstage-S-ccopts += $(armv7-a_asm_flags) + +verstage-y += cache.c +verstage-y += cpu.S +verstage-y += exception.c +verstage-y += exception_asm.S +verstage-y += mmu.c + +else ifeq ($(CONFIG_ARCH_VERSTAGE_ARM_V7_M),y) +verstage-c-ccopts += $(armv7-m_flags) +verstage-S-ccopts += $(armv7-m_asm_flags) + +endif + +################################################################################ +## ROM stage +################################################################################ +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM_V7),y) + +romstage-y += cache.c +romstage-y += cpu.S +romstage-y += exception.c +romstage-y += exception_asm.S +romstage-y += mmu.c + +romstage-c-ccopts += $(armv7-a_flags) +romstage-S-ccopts += $(armv7-a_asm_flags) + +rmodules_arm-c-ccopts += $(armv7-a_flags) +rmodules_arm-S-ccopts += $(armv7-a_asm_flags) + +endif +################################################################################ +## RAM stage +################################################################################ +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM_V7),y) + +ramstage-y += cache.c +ramstage-y += cpu.S +ramstage-y += exception.c +ramstage-y += exception_asm.S +ramstage-y += mmu.c + +ramstage-c-ccopts += $(armv7-a_flags) +ramstage-S-ccopts += $(armv7-a_asm_flags) + +rmodules_arm-c-ccopts += $(armv7-a_flags) +rmodules_arm-S-ccopts += $(armv7-a_asm_flags) +endif diff --git a/src/arch/armv7/bootblock.inc b/src/arch/arm/armv7/bootblock.S similarity index 58% rename from src/arch/armv7/bootblock.inc rename to src/arch/arm/armv7/bootblock.S index faf5475819..d2cbf750a4 100644 --- a/src/arch/armv7/bootblock.inc +++ b/src/arch/arm/armv7/bootblock.S @@ -1,5 +1,5 @@ /* - * Early initialization code for ARMv7 architecture. + * Early initialization code for ARM architecture. * * This file is based off of the OMAP3530/ARM Cortex start.S file from Das * U-Boot, which itself got the file from armboot. @@ -29,36 +29,23 @@ * MA 02111-1307 USA */ -#include +#include -.section ".bl1", "a", %progbits -_bl1: - /* For now we have to live with a first stage boot loader - * on ARM, which is 8KB in size and it is prepended to the - * reset vector - */ - .skip (CONFIG_BL1_SIZE_KB * 1024) - -.section ".start", "a", %progbits -.globl _start -_start: b reset - .balignl 16,0xdeadbeef - -_cbfs_master_header: - /* The CBFS master header is inserted by cbfstool at the first - * aligned offset after the above anchor string is found. - * Hence, we leave some space for it. - */ - .skip 128 @ Assumes 64-byte alignment - -reset: +.arm +ENTRY(_start) /* - * set the cpu to SVC32 mode + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - msr cpsr_cxsf,r0 + msr cpsr_cxf, #0xdf + bl _thumb_start +ENDPROC(_start) + +.thumb +ENTRY(_thumb_start) + bl arm_init_caches /* * From Cortex-A Series Programmer's Guide: @@ -75,10 +62,8 @@ reset: * Initialize the stack to a known value. This is used to check for * stack overflow later in the boot process. */ - ldr r0, .Stack - ldr r1, .Stack_size - sub r0, r0, r1 - ldr r1, .Stack + ldr r0, =_stack + ldr r1, =_estack ldr r2, =0xdeadbeef init_stack_loop: str r2, [r0] @@ -86,30 +71,19 @@ init_stack_loop: cmp r0, r1 bne init_stack_loop -/* Set stackpointer in internal RAM to call board_init_f */ +/* Set stackpointer in internal RAM to call bootblock main() */ call_bootblock: - ldr sp, .Stack /* Set up stack pointer */ - bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr sp, =_estack /* Set up stack pointer */ ldr r0,=0x00000000 - /* - * Use "bl" instead of "b" even though we do not intend to return. - * "bl" gets compiled to "blx" if we're transitioning from ARM to - * Thumb. However, "b" will not and GCC may attempt to create a - * wrapper which is currently broken. - */ + /* + * The current design of cpu_info places the struct at the top of the + * stack. Free enough space to accomodate for that, but make sure it's + * 8-byte aligned for ABI compliance. + */ + sub sp, sp, #16 bl main wait_for_interrupt: wfi mov pc, lr @ back to my caller - -/* we do it this way because it's a 32-bit constant and - * in some cases too far away to be loaded as just an offset - * from IP - */ -.align 2 -.Stack: - .word CONFIG_STACK_TOP -.align 2 -.Stack_size: - .word CONFIG_STACK_SIZE +ENDPROC(_thumb_start) diff --git a/src/arch/arm/armv7/bootblock_m.S b/src/arch/arm/armv7/bootblock_m.S new file mode 100644 index 0000000000..2e46ca064f --- /dev/null +++ b/src/arch/arm/armv7/bootblock_m.S @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include + +ENTRY(_start) + /* + * Initialize the stack to a known value. This is used to check for + * stack overflow later in the boot process. + */ + ldr r0, =_stack + ldr r1, =_estack + ldr r2, =0xdeadbeef +init_stack_loop: + str r2, [r0] + add r0, #4 + cmp r0, r1 + bne init_stack_loop + +call_bootblock: + ldr sp, =_estack /* Set up stack pointer */ + bl main +ENDPROC(_start) diff --git a/src/arch/arm/armv7/bootblock_simple.c b/src/arch/arm/armv7/bootblock_simple.c new file mode 100644 index 0000000000..7fb83c6921 --- /dev/null +++ b/src/arch/arm/armv7/bootblock_simple.c @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2010 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +__attribute__((weak)) void bootblock_mainboard_early_init(void) { /* no-op */ } +__attribute__((weak)) void bootblock_soc_init(void) { /* do nothing */ } +__attribute__((weak)) void bootblock_mainboard_init(void) { /* do nothing */ } + +void main(void) +{ + void *entry = (void *)-1; + + init_timer(); + if (IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION)) + timestamp_early_init(timestamp_get()); + + bootblock_mainboard_early_init(); + + if (CONFIG_BOOTBLOCK_CONSOLE) { + console_init(); + exception_init(); + } + + bootblock_soc_init(); + bootblock_mainboard_init(); + + if (IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE)) { + timestamp_add_now(TS_START_COPYVER); + if (IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) + entry = vboot2_verify_firmware(); + else + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/verstage"); + timestamp_add_now(TS_END_COPYVER); + } else { + timestamp_add_now(TS_START_COPYROM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/romstage"); + timestamp_add_now(TS_END_COPYROM); + } + + if (entry != (void *)-1) + stage_exit(entry); + hlt(); +} diff --git a/src/arch/arm/armv7/cache.c b/src/arch/arm/armv7/cache.c new file mode 100644 index 0000000000..31819f7f48 --- /dev/null +++ b/src/arch/arm/armv7/cache.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R + * + * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition + */ + +#include + +#include + +void tlb_invalidate_all(void) +{ + /* TLBIALL includes dTLB and iTLB on systems that have them. */ + tlbiall(); + dsb(); + isb(); +} + +enum dcache_op { + OP_DCCSW, + OP_DCCISW, + OP_DCISW, + OP_DCCIMVAC, + OP_DCCMVAC, + OP_DCIMVAC, +}; + +unsigned int dcache_line_bytes(void) +{ + uint32_t ccsidr; + static unsigned int line_bytes = 0; + + if (line_bytes) + return line_bytes; + + ccsidr = read_ccsidr(); + /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ + line_bytes = 1 << ((ccsidr & 0x7) + 2); /* words per line */ + line_bytes *= sizeof(unsigned int); /* bytes per line */ + + return line_bytes; +} + +/* + * Do a dcache operation by modified virtual address. This is useful for + * maintaining coherency in drivers which do DMA transfers and only need to + * perform cache maintenance on a particular memory range rather than the + * entire cache. + */ +static void dcache_op_mva(void const *addr, size_t len, enum dcache_op op) +{ + unsigned long line, linesize; + + linesize = dcache_line_bytes(); + line = (uint32_t)addr & ~(linesize - 1); + + dsb(); + while ((void *)line < addr + len) { + switch(op) { + case OP_DCCIMVAC: + dccimvac(line); + break; + case OP_DCCMVAC: + dccmvac(line); + break; + case OP_DCIMVAC: + dcimvac(line); + break; + default: + break; + } + line += linesize; + } + isb(); +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCMVAC); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCCIMVAC); +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_mva(addr, len, OP_DCIMVAC); +} + +/* + * CAUTION: This implementation assumes that coreboot never uses non-identity + * page tables for pages containing executed code. If you ever want to violate + * this assumption, have fun figuring out the associated problems on your own. + */ +void dcache_mmu_disable(void) +{ + uint32_t sctlr; + + dcache_clean_invalidate_all(); + sctlr = read_sctlr(); + sctlr &= ~(SCTLR_C | SCTLR_M); + write_sctlr(sctlr); +} + +void dcache_mmu_enable(void) +{ + uint32_t sctlr; + + sctlr = read_sctlr(); + sctlr |= SCTLR_C | SCTLR_M; + write_sctlr(sctlr); +} + +void cache_sync_instructions(void) +{ + dcache_clean_all(); /* includes trailing DSB (in assembly) */ + iciallu(); /* includes BPIALLU (architecturally) */ + dsb(); + isb(); +} diff --git a/src/arch/arm/armv7/cache_m.c b/src/arch/arm/armv7/cache_m.c new file mode 100644 index 0000000000..ec8a970167 --- /dev/null +++ b/src/arch/arm/armv7/cache_m.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARMv7-M + */ + +#include + +#include + +void tlb_invalidate_all(void) +{ +} + +void dcache_clean_all(void) +{ +} + +void dcache_clean_invalidate_all(void) +{ +} + +void dcache_invalidate_all(void) +{ +} + +unsigned int dcache_line_bytes(void) +{ + return 0; +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ +} + +void dcache_mmu_disable(void) +{ +} + +void dcache_mmu_enable(void) +{ +} + +void cache_sync_instructions(void) +{ +} diff --git a/src/arch/arm/armv7/cpu.S b/src/arch/arm/armv7/cpu.S new file mode 100644 index 0000000000..589bc07405 --- /dev/null +++ b/src/arch/arm/armv7/cpu.S @@ -0,0 +1,148 @@ +/* + * Optimized assembly for low-level CPU operations on ARMv7 processors. + * + * Cache flushing code based off sys/arch/arm/arm/cpufunc_asm_armv7.S in NetBSD + * + * Copyright (c) 2010 Per Odlund + * Copyright (c) 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * Dcache invalidations by set/way work by passing a [way:sbz:set:sbz:level:0] + * bitfield in a register to the appropriate MCR instruction. This algorithm + * works by initializing a bitfield with the highest-numbered set and way, and + * generating a "set decrement" and a "way decrement". The former just contains + * the LSB of the set field, but the latter contains the LSB of the way field + * minus the highest valid set field... such that when you subtract it from a + * [way:0:level] field you end up with a [way - 1:highest_set:level] field + * through the magic of double subtraction. It's quite ingenius, really. + * Takes care to only use r0-r3 and ip so it's pefectly ABI-compatible without + * needing to write to memory. + */ + +.macro dcache_apply_all crm + dsb + mov r3, #-2 @ initialize level so that we start at 0 + +1: @next_level + add r3, r3, #2 @ increment level + + mrc p15, 1, r0, c0, c0, 1 @ read CLIDR + and ip, r0, #0x07000000 @ narrow to LoC + lsr ip, ip, #23 @ left align LoC (low 4 bits) + cmp r3, ip @ compare + bge 3f @done @ else fall through (r0 == CLIDR) + + add r2, r3, r3, lsr #1 @ r2 = (level << 1) * 3 / 2 + mov r1, r0, lsr r2 @ r1 = cache type + and r1, r1, #7 + cmp r1, #2 @ is it data or i&d? + blt 1b @next_level @ nope, skip level + + mcr p15, 2, r3, c0, c0, 0 @ select cache level + isb + mrc p15, 1, r0, c0, c0, 0 @ read CCSIDR + + ubfx ip, r0, #0, #3 @ get linesize from CCSIDR + add ip, ip, #4 @ apply bias + ubfx r2, r0, #13, #15 @ get numsets - 1 from CCSIDR + lsl r2, r2, ip @ shift to set position + orr r3, r3, r2 @ merge set into way/set/level + mov r1, #1 + lsl r1, r1, ip @ r1 = set decr + + ubfx ip, r0, #3, #10 @ get numways - 1 from [to be discarded] CCSIDR + clz r2, ip @ number of bits to MSB of way + lsl ip, ip, r2 @ shift by that into way position + mov r0, #1 + lsl r2, r0, r2 @ r2 now contains the way decr + mov r0, r3 @ get sets/level (no way yet) + orr r3, r3, ip @ merge way into way/set/level + bfc r0, #0, #4 @ clear low 4 bits (level) to get numset - 1 + sub r2, r2, r0 @ subtract from way decr + + /* r3 = ways/sets/level, r2 = way decr, r1 = set decr, r0 and ip are free */ +2: mcr p15, 0, r3, c7, \crm, 2 @ writeback and/or invalidate line + cmp r3, #15 @ are we done with this level (way/set == 0) + bls 1b @next_level @ yes, go to next level + lsr r0, r3, #4 @ clear level bits leaving only way/set bits + lsls r0, r0, #14 @ clear way bits leaving only set bits + subne r3, r3, r1 @ non-zero?, decrement set # + subeq r3, r3, r2 @ zero?, decrement way # and restore set count + b 2b + +3: @done + mov r0, #0 @ default back to cache level 0 + mcr p15, 2, r0, c0, c0, 0 @ select cache level + dsb + isb + bx lr +.endm + +/* + * Bring an ARM processor we just gained control of (e.g. from IROM) into a + * known state regarding caches/SCTLR. Completely cleans and invalidates + * icache/dcache, disables MMU and dcache (if active), and enables unaligned + * accesses, icache and branch prediction (if inactive). Clobbers r4 and r5. + */ +ENTRY(arm_init_caches) + /* r4: SCTLR, return address: r5 (stay valid for the whole function) */ + mov r5, lr + mrc p15, 0, r4, c1, c0, 0 + + /* Activate ICache (12) and Branch Prediction (11) already for speed */ + orr r4, # (1 << 11) | (1 << 12) + mcr p15, 0, r4, c1, c0, 0 + + /* Flush and invalidate dcache in ascending order */ + bl dcache_clean_invalidate_all + + /* Deactivate MMU (0), Alignment Check (1) and DCache (2) */ + and r4, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2) + mcr p15, 0, r4, c1, c0, 0 + + /* Invalidate icache and TLB for good measure */ + mcr p15, 0, r0, c7, c5, 0 + mcr p15, 0, r0, c8, c7, 0 + dsb + isb + + bx r5 +ENDPROC(arm_init_caches) + +ENTRY(dcache_invalidate_all) + dcache_apply_all crm=c6 +ENDPROC(dcache_invalidate_all) + +ENTRY(dcache_clean_all) + dcache_apply_all crm=c10 +ENDPROC(dcache_clean_all) + +ENTRY(dcache_clean_invalidate_all) + dcache_apply_all crm=c14 +ENDPROC(dcache_clean_invalidate_all) diff --git a/src/arch/armv7/exception.c b/src/arch/arm/armv7/exception.c similarity index 68% rename from src/arch/armv7/exception.c rename to src/arch/arm/armv7/exception.c index 14f82163c6..4fac0bcd3c 100644 --- a/src/arch/armv7/exception.c +++ b/src/arch/arm/armv7/exception.c @@ -27,13 +27,14 @@ * SUCH DAMAGE. */ -#include -#include #include +#include +#include +#include +#include -void exception_test(void); - -static int test_abort; +uint8_t exception_stack[0x100] __attribute__((aligned(8))); +extern void *exception_stack_end; void exception_undefined_instruction(uint32_t *); void exception_software_interrupt(uint32_t *); @@ -43,20 +44,32 @@ void exception_not_used(uint32_t *); void exception_irq(uint32_t *); void exception_fiq(uint32_t *); +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printk(BIOS_ERR, "Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printk(BIOS_ERR, "%p: ", ptr + i); + for (j = i; j < i + line; j++) + printk(BIOS_ERR, "%08x ", *(ptr + j)); + printk(BIOS_ERR, "\n"); + } +} + static void print_regs(uint32_t *regs) { int i; - /* Don't print the link register and stack pointer since we don't have their - * actual value. They are hidden by the 'shadow' registers provided - * by the trap hardware. - */ + for (i = 0; i < 16; i++) { if (i == 15) printk(BIOS_ERR, "PC"); else if (i == 14) - continue; /* LR */ + printk(BIOS_ERR, "LR"); else if (i == 13) - continue; /* SP */ + printk(BIOS_ERR, "SP"); else if (i == 12) printk(BIOS_ERR, "IP"); else @@ -68,7 +81,9 @@ static void print_regs(uint32_t *regs) void exception_undefined_instruction(uint32_t *regs) { printk(BIOS_ERR, "exception _undefined_instruction\n"); + regs[15] -= 2; /* CAREFUL: specific to thumb mode (otherwise 4)! */ print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -76,25 +91,31 @@ void exception_software_interrupt(uint32_t *regs) { printk(BIOS_ERR, "exception _software_interrupt\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } void exception_prefetch_abort(uint32_t *regs) { printk(BIOS_ERR, "exception _prefetch_abort\n"); + regs[15] -= 4; print_regs(regs); + printk(BIOS_ERR, "IFAR = %#.8x\n", read_ifar()); + printk(BIOS_ERR, "IFSR = %#.8x\n", read_ifsr()); + printk(BIOS_ERR, "AIFSR = %#.8x\n", read_aifsr()); + dump_stack(regs[13], 512); die("exception"); } void exception_data_abort(uint32_t *regs) { - if (test_abort) { - regs[15] = regs[0]; - return; - } else { - printk(BIOS_ERR, "exception _data_abort\n"); - print_regs(regs); - } + printk(BIOS_ERR, "exception _data_abort\n"); + regs[15] -= 8; + print_regs(regs); + printk(BIOS_ERR, "DFAR = %#.8x\n", read_dfar()); + printk(BIOS_ERR, "DFSR = %#.8x\n", read_dfsr()); + printk(BIOS_ERR, "ADFSR = %#.8x\n", read_adfsr()); + dump_stack(regs[13], 512); die("exception"); } @@ -102,57 +123,41 @@ void exception_not_used(uint32_t *regs) { printk(BIOS_ERR, "exception _not_used\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } void exception_irq(uint32_t *regs) { printk(BIOS_ERR, "exception _irq\n"); + regs[15] -= 4; print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } void exception_fiq(uint32_t *regs) { printk(BIOS_ERR, "exception _fiq\n"); + regs[15] -= 4; print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } -static inline uint32_t get_sctlr(void) -{ - uint32_t val; - asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (val)); - return val; -} - -static inline void set_sctlr(uint32_t val) -{ - asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r" (val)); - asm volatile("" ::: "memory"); -} - void exception_init(void) { - static const uint32_t sctlr_te = (0x1 << 30); - static const uint32_t sctlr_v = (0x1 << 13); - static const uint32_t sctlr_a = (0x1 << 1); - - uint32_t sctlr = get_sctlr(); + uint32_t sctlr = read_sctlr(); /* Handle exceptions in ARM mode. */ - sctlr &= ~sctlr_te; + sctlr &= ~SCTLR_TE; /* Set V=0 in SCTLR so VBAR points to the exception vector table. */ - sctlr &= ~sctlr_v; - /* Enforce alignment. */ - sctlr |= sctlr_a; - set_sctlr(sctlr); + sctlr &= ~SCTLR_V; + /* Enforce alignment temporarily. */ + write_sctlr(sctlr); extern uint32_t exception_table[]; set_vbar((uintptr_t)exception_table); + exception_stack_end = exception_stack + sizeof(exception_stack); - test_abort = 1; - printk(BIOS_ERR, "Testing exceptions\n"); - exception_test(); - test_abort = 0; - printk(BIOS_ERR, "Testing exceptions: DONE\n"); + printk(BIOS_DEBUG, "Exception handlers installed.\n"); } diff --git a/payloads/libpayload/arch/armv7/exception_asm.S b/src/arch/arm/armv7/exception_asm.S similarity index 92% rename from payloads/libpayload/arch/armv7/exception_asm.S rename to src/arch/arm/armv7/exception_asm.S index e46f4bcf6b..1f369bcc05 100644 --- a/payloads/libpayload/arch/armv7/exception_asm.S +++ b/src/arch/arm/armv7/exception_asm.S @@ -27,15 +27,7 @@ * SUCH DAMAGE. */ -exception_stack: - .align 5 - .skip 0x2000, 0xa5 -exception_stack_end: - .word exception_stack_end - -exception_handler: - .word 0 - + .text .align 6 .arm @@ -79,6 +71,7 @@ exception_common: str sp, exception_handler ldr sp, exception_stack_end push { lr } + stmfd sp, { sp, lr }^ sub sp, sp, $8 push { r0 - r12 } mov r0, sp @@ -86,9 +79,10 @@ exception_common: ldr pc, exception_handler pop { r0 - r12 } add sp, sp, $8 - ldm sp!, { pc }^ + ldmfd sp!, { pc }^ + .align 2 _undefined_instruction: .word exception_undefined_instruction _software_interrupt: .word exception_software_interrupt _prefetch_abort: .word exception_prefetch_abort @@ -97,6 +91,13 @@ _not_used: .word exception_not_used _irq: .word exception_irq _fiq: .word exception_fiq + .global exception_stack_end +exception_stack_end: + .word 0 + +exception_handler: + .word 0 + .thumb .global set_vbar .thumb_func @@ -104,12 +105,3 @@ set_vbar: mcr p15, 0, r0, c12, c0, 0 bx lr - .global exception_test - .thumb_func -exception_test: - mov r1, $1 - mov r0, pc - add r0, $3 - ldr r1, [r1] - bx lr - diff --git a/payloads/libpayload/arch/powerpc/virtual.c b/src/arch/arm/armv7/exception_m.c similarity index 89% rename from payloads/libpayload/arch/powerpc/virtual.c rename to src/arch/arm/armv7/exception_m.c index 6ff588c504..d76cc6a739 100644 --- a/payloads/libpayload/arch/powerpc/virtual.c +++ b/src/arch/arm/armv7/exception_m.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 coresystems GmbH + * Copyright 2013 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,11 +27,10 @@ * SUCH DAMAGE. */ -#include +#include +#include -unsigned long virtual_offset = 0; - -int getpagesize(void) +void exception_init(void) { - return 4096; + printk(BIOS_DEBUG, "Exception handlers not installed.\n"); } diff --git a/src/arch/arm/armv7/mmu.c b/src/arch/arm/armv7/mmu.c new file mode 100644 index 0000000000..581c57244e --- /dev/null +++ b/src/arch/arm/armv7/mmu.c @@ -0,0 +1,307 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#if CONFIG_ARM_LPAE +/* See B3.6.2 of ARMv7 Architecture Reference Manual */ +/* TODO: Utilize the contiguous hint flag */ +#define ATTR_BLOCK (\ + 0ULL << 54 | /* XN. 0:Not restricted */ \ + 0ULL << 53 | /* PXN. 0:Not restricted */ \ + 1 << 10 | /* AF. 1:Accessed. This is to prevent access \ + * fault when accessed for the first time */ \ + 0 << 6 | /* AP[2:1]. 0b00:full access from PL1 */ \ + 0 << 5 | /* NS. 0:Output address is in Secure space */ \ + 0 << 1 | /* block/table. 0:block entry */ \ + 1 << 0 /* validity. 1:valid */ \ + ) +#define ATTR_PAGE (ATTR_BLOCK | 1 << 1) +#define ATTR_NEXTLEVEL (0x3) +#define ATTR_NC ((MAIR_INDX_NC << 2) | (1ULL << 53) | (1ULL << 54)) +#define ATTR_WT (MAIR_INDX_WT << 2) +#define ATTR_WB (MAIR_INDX_WB << 2) + +#define PAGE_MASK 0x000ffffffffff000ULL +#define BLOCK_MASK 0x000fffffffe00000ULL +#define NEXTLEVEL_MASK PAGE_MASK +#define BLOCK_SHIFT 21 + +typedef uint64_t pte_t; +#else /* CONFIG_ARM_LPAE */ + /* + * Section entry bits: + * 31:20 - section base address + * 18 - 0 to indicate normal section (versus supersection) + * 17 - nG, 0 to indicate page is global + * 16 - S, 0 for non-shareable (?) + * 15 - APX, 0 for full access + * 14:12 - TEX, 0b000 for outer and inner write-back + * 11:10 - AP, 0b11 for full access + * 9 - P, ? (FIXME: not described or possibly obsolete?) + * 8: 5 - Domain + * 4 - XN, 1 to set execute-never (and also avoid prefetches) + * 3 - C, 1 for cacheable + * 2 - B, 1 for bufferable + * 1: 0 - 0b10 to indicate section entry + */ +#define ATTR_BLOCK ((3 << 10) | 0x2) +#define ATTR_PAGE ((3 << 4) | 0x2) +#define ATTR_NEXTLEVEL (0x1) +#define ATTR_NC (1 << 4) +#define ATTR_WT (1 << 3) +#define ATTR_WB ((1 << 3) | (1 << 2)) + +#define PAGE_MASK 0xfffff000UL +#define BLOCK_MASK 0xfff00000UL +#define NEXTLEVEL_MASK 0xfffffc00UL +#define BLOCK_SHIFT 20 + +typedef uint32_t pte_t; +#endif /* CONFIG_ARM_LPAE */ + +/* + * mask/shift/size for pages and blocks + */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define BLOCK_SIZE (1UL << BLOCK_SHIFT) +#define SUBTABLE_SIZE ((1 << (BLOCK_SHIFT - PAGE_SHIFT)) * sizeof(pte_t)) + +/* + * MAIR Index + */ +#define MAIR_INDX_NC 0 +#define MAIR_INDX_WT 1 +#define MAIR_INDX_WB 2 + +static pte_t *const ttb_buff = (void *)_ttb; +static int used_tables = 0; + +/* Not all boards want to use subtables and declare them in memlayout.ld. This + * outputs two 0x00000000 symbols if they don't, making _ttb_subtables_size 0. + * (I would like to explicitly assign them to 0 here, but that triggers + * https://sourceware.org/bugzilla/show_bug.cgi?id=1038 in GNU as.) */ +asm (".weak _ttb_subtables, _ettb_subtables"); + +static struct { + pte_t value; + const char *name; +} attrs[] = { + [DCACHE_OFF] = {.value = ATTR_NC, .name = "uncached"}, + [DCACHE_WRITEBACK] = {.value = ATTR_WB, .name = "writeback"}, + [DCACHE_WRITETHROUGH] = {.value = ATTR_WT, .name = "writethrough"}, +}; + +/* Fills page table entries in |table| from |start_idx| to |end_idx| with |attr| + * and performs necessary invalidations. |offset| is the start address of the + * area described by |table|, and |shift| is the size-shift of each frame. */ +static void mmu_fill_table(pte_t *table, u32 start_idx, u32 end_idx, + uintptr_t offset, u32 shift, pte_t attr) +{ + int i; + + /* Write out page table entries. */ + for (i = start_idx; i < end_idx; i++) + table[i] = (offset + (i << shift)) | attr; + + /* Flush the page table entries from the dcache. */ + for (i = start_idx; i < end_idx; i++) + dccmvac((uintptr_t)&table[i]); + dsb(); + + /* Invalidate the TLB entries. */ + for (i = start_idx; i < end_idx; i++) + tlbimvaa(offset + (i << shift)); + dsb(); + isb(); +} + +static pte_t *mmu_create_subtable(pte_t *pgd_entry) +{ + if (used_tables >= _ttb_subtables_size / SUBTABLE_SIZE) + die("Not enough room for another sub-pagetable!"); + + /* We assume that *pgd_entry must already be a valid block mapping. */ + uintptr_t start_addr = (uintptr_t)(*pgd_entry & BLOCK_MASK); + pte_t *table = (void *)(_ttb_subtables + used_tables++ * SUBTABLE_SIZE); + printk(BIOS_DEBUG, "Creating new subtable @%p for [%#.8x:%#.8lx)\n", + table, start_addr, start_addr + BLOCK_SIZE); + + /* Initialize the new subtable with entries of the same attributes + * (XN bit moves from 4 to 0, set PAGE unless block was unmapped). */ + pte_t attr = *pgd_entry & ~(BLOCK_MASK); + if (!IS_ENABLED(CONFIG_ARM_LPAE) && (attr & (1 << 4))) + attr = ((attr & ~(1 << 4)) | (1 << 0)); + if (attr & ATTR_BLOCK) + attr = (attr & ~ATTR_BLOCK) | ATTR_PAGE; + mmu_fill_table(table, 0, SUBTABLE_SIZE / sizeof(pte_t), + start_addr, PAGE_SHIFT, attr); + + /* Replace old entry in upper level table to point at subtable. */ + *pgd_entry = (pte_t)(uintptr_t)table | ATTR_NEXTLEVEL; + dccmvac((uintptr_t)pgd_entry); + dsb(); + tlbimvaa(start_addr); + dsb(); + isb(); + + return table; +} + +void mmu_config_range_kb(u32 start_kb, u32 size_kb, enum dcache_policy policy) +{ + pte_t *pgd_entry = &ttb_buff[start_kb / (BLOCK_SIZE/KiB)]; + pte_t *table = (void *)(uintptr_t)(*pgd_entry & NEXTLEVEL_MASK); + + /* Make sure the range is contained within a single superpage. */ + assert(((start_kb + size_kb - 1) & (BLOCK_MASK/KiB)) + == (start_kb & (BLOCK_MASK/KiB)) && start_kb < 4 * (GiB/KiB)); + + if ((*pgd_entry & ~NEXTLEVEL_MASK) != ATTR_NEXTLEVEL) + table = mmu_create_subtable(pgd_entry); + + /* Always _one_ _damn_ bit that won't fit... (XN moves from 4 to 0) */ + pte_t attr = attrs[policy].value; + if (!IS_ENABLED(CONFIG_ARM_LPAE) && (attr & (1 << 4))) + attr = ((attr & ~(1 << 4)) | (1 << 0)); + + /* Mask away high address bits that are handled by upper level table. */ + u32 mask = BLOCK_SIZE/KiB - 1; + printk(BIOS_DEBUG, "Mapping address range [%#.8x:%#.8x) as %s\n", + start_kb * KiB, (start_kb + size_kb) * KiB, attrs[policy].name); + mmu_fill_table(table, (start_kb & mask) / (PAGE_SIZE/KiB), + div_round_up((start_kb + size_kb) & mask, PAGE_SIZE/KiB), + (start_kb & ~mask) * KiB, PAGE_SHIFT, ATTR_PAGE | attr); +} + +void mmu_disable_range(u32 start_mb, u32 size_mb) +{ + printk(BIOS_DEBUG, "Setting address range [%#.8x:%#.8x) as unmapped\n", + start_mb * MiB, (start_mb + size_mb) * MiB); + assert(start_mb + size_mb <= 4 * (GiB/MiB)); + mmu_fill_table(ttb_buff, start_mb / (BLOCK_SIZE/MiB), + div_round_up(start_mb + size_mb, BLOCK_SIZE/MiB), + 0, BLOCK_SHIFT, 0); +} + +void mmu_config_range(u32 start_mb, u32 size_mb, enum dcache_policy policy) +{ + printk(BIOS_DEBUG, "Mapping address range [%#.8x:%#.8x) as %s\n", + start_mb * MiB, (start_mb + size_mb) * MiB, attrs[policy].name); + assert(start_mb + size_mb <= 4 * (GiB/MiB)); + mmu_fill_table(ttb_buff, start_mb / (BLOCK_SIZE/MiB), + div_round_up(start_mb + size_mb, BLOCK_SIZE/MiB), + 0, BLOCK_SHIFT, ATTR_BLOCK | attrs[policy].value); +} + +/* + * For coreboot's purposes, we will create a simple identity map. + * + * If LPAE is disabled, we will create a L1 page + * table in RAM with 1MB section translation entries over the 4GB address space. + * (ref: section 10.2 and example 15-4 in Cortex-A series programmer's guide) + * + * If LPAE is enabled, we do two level translation with one L1 table with 4 + * entries, each covering a 1GB space, and four L2 tables with 512 entries, each + * covering a 2MB space. + */ +void mmu_init(void) +{ + if (CONFIG_ARM_LPAE) { + pte_t *const pgd_buff = (pte_t*)(_ttb + 16*KiB); + pte_t *pmd = ttb_buff; + int i; + + printk(BIOS_DEBUG, "LPAE Translation tables are @ %p\n", + ttb_buff); + ASSERT((read_mmfr0() & 0xf) >= 5); + + /* + * Set MAIR + * See B4.1.104 of ARMv7 Architecture Reference Manual + */ + write_mair0( + 0x00 << (MAIR_INDX_NC*8) | /* Strongly-ordered, + * Non-Cacheable */ + 0xaa << (MAIR_INDX_WT*8) | /* Write-Thru, + * Read-Allocate */ + 0xff << (MAIR_INDX_WB*8) /* Write-Back, + * Read/Write-Allocate */ + ); + + /* + * Set up L1 table + * Once set here, L1 table won't be modified by coreboot. + * See B3.6.1 of ARMv7 Architecture Reference Manual + */ + for (i = 0; i < 4; i++) { + pgd_buff[i] = ((uint32_t)pmd & NEXTLEVEL_MASK) | + ATTR_NEXTLEVEL; + pmd += BLOCK_SIZE / PAGE_SIZE; + } + + /* + * Set TTBR0 + */ + write_ttbr0((uintptr_t)pgd_buff); + } else { + printk(BIOS_DEBUG, "Translation table is @ %p\n", ttb_buff); + + /* + * Translation table base 0 address is in bits 31:14-N, where N + * is given by bits 2:0 in TTBCR (which we set to 0). All lower + * bits in this register should be zero for coreboot. + */ + write_ttbr0((uintptr_t)ttb_buff); + } + + /* + * Set TTBCR + * See B4.1.153 of ARMv7 Architecture Reference Manual + * See B3.5.4 and B3.6.4 for how TTBR0 or TTBR1 is selected. + */ + write_ttbcr( + CONFIG_ARM_LPAE << 31 | /* EAE. 1:Enable LPAE */ + 0 << 16 | 0 << 0 /* Use TTBR0 for all addresses */ + ); + + /* Set domain 0 to Client so XN bit works (to prevent prefetches) */ + write_dacr(0x5); +} diff --git a/src/arch/arm/armv7/thread.c b/src/arch/arm/armv7/thread.c new file mode 100644 index 0000000000..d0c23ff92d --- /dev/null +++ b/src/arch/arm/armv7/thread.c @@ -0,0 +1,127 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +/* The stack frame looks like the following. */ +struct pushed_regs { + u32 r4; + u32 r5; + u32 r6; + u32 r7; + u32 r8; + u32 r9; + u32 r10; + u32 r11; + u32 lr; +}; + +static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value) +{ + uintptr_t *addr; + + cur_stack -= sizeof(value); + addr = (uintptr_t *)cur_stack; + *addr = value; + return cur_stack; +} + +void arch_prepare_thread(struct thread *t, + void asmlinkage (*thread_entry)(void *), void *arg) +{ + uintptr_t stack = t->stack_current; + int i; + uintptr_t poison = 0xdeadbeef; + + /* Push the LR. thread_entry() + * is assumed to never return. + */ + stack = push_stack(stack, (uintptr_t)thread_entry); + /* Make room for the registers. + * Poison the initial stack. This is good hygiene and finds bugs. + * Poisoning the stack with different values helps when you're + * hunting for (e.g.) misaligned stacks or other such + * weirdness. The -1 is because we already pushed lr. + */ + for(i = 0; i < sizeof(struct pushed_regs)/sizeof(u32)-1; i++) + stack = push_stack(stack, poison++); + + t->stack_current = stack; +} + +/* We could write this as a .S and the first time around that's how we + * did it. But there's always the question of matching our ARM + * directives in the .S with how gcc is doing things. It seems best + * to follow the pattern of the rest of the ARM port and just use + * inline assembly and let gcc get all the ELF magic right. + */ +void __attribute__((naked)) +switch_to_thread(uintptr_t new_stack, uintptr_t *saved_stack) +{ + /* Defintions for those of us not totally familiar with ARM: + * R15 -- PC, R14 -- LR, R13 -- SP + * R0-R3 need not be saved, nor R12. + * on entry, the only saved state is in LR -- the old PC. + * The args are in R0,R1. + * R0 is the new stack + * R1 is a pointer to the old stack save location + * Push R4-R11 and LR + * then switch stacks + * then pop R0-R12 and LR + * then mov PC,LR + * + * stack layout + * +------------+ + * | LR | <-- sp + 0x20 + * +------------+ + * | R11 | <-- sp + 0x1c + * +------------+ + * | R10 | <-- sp + 0x18 + * +------------+ + * | R9 | <-- sp + 0x14 + * +------------+ + * | R8 | <-- sp + 0x10 + * +------------+ + * | R7 | <-- sp + 0x0c + * +------------+ + * | R6 | <-- sp + 0x08 + * +------------+ + * | R5 | <-- sp + 0x04 + * +------------+ + * | R4 | <-- sp + 0x00 + * +------------+ + */ + asm volatile ( + /* save context. */ + "push {r4-r11,lr}\n\t" + /* Save the current stack */ + "str sp,[r1]\n\t" + /* switch to the new stack */ + "mov sp,r0\n\t" + /* restore the registers */ + "pop {r4-r11,lr}\n\t" + /* resume other thread. */ + "mov pc,lr\n\t" + ); +} + +void *arch_get_thread_stackbase(void) +{ + return (void *)CONFIG_STACK_BOTTOM; +} diff --git a/payloads/libpayload/arch/armv7/assembler.h b/src/arch/arm/asmlib.h similarity index 61% rename from payloads/libpayload/arch/armv7/assembler.h rename to src/arch/arm/asmlib.h index 5e4789b145..cef0e7ea1a 100644 --- a/payloads/libpayload/arch/armv7/assembler.h +++ b/src/arch/arm/asmlib.h @@ -1,5 +1,7 @@ /* - * arch/arm/include/asm/assembler.h + * arch/arm/asmlib.h + * + * Adapted from Linux arch/arm/include/assembler.h * * Copyright (C) 1996-2000 Russell King * @@ -14,6 +16,16 @@ * assembler source. */ +/* + * WARNING: This file is *only* meant for memcpy.S and friends which were copied + * from Linux and require some weird macros. It does unspeakable things like + * redefining "push", so do *not* try to turn it into a general assembly macro + * file, and keep it out of global include directories. + */ + +#ifndef __ARM_ASMLIB_H__ +#define __ARM_ASMLIB_H__ + /* * Endian independent macros for shifting bytes within registers. */ @@ -44,17 +56,17 @@ /* * Data preload for architectures that support it */ -#if defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_7A__) || \ - defined(__ARM_ARCH_7R__) +#if __COREBOOT_ARM_ARCH__ >= 5 #define PLD(code...) code #else #define PLD(code...) #endif /* - * Cache alligned + * This can be used to enable code to cacheline align the destination + * pointer when bulk writing to memory. Linux doesn't enable this except + * for the "Feroceon" processor, so we better just leave it out. */ -#define CALGN(code...) code +#define CALGN(code...) + +#endif /* __ARM_ASMLIB_H */ diff --git a/src/arch/arm/boot.c b/src/arch/arm/boot.c new file mode 100644 index 0000000000..6fb0e650b5 --- /dev/null +++ b/src/arch/arm/boot.c @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) +{ + void (*doit)(void *) = entry; + void *cb_tables = cbmem_find(CBMEM_ID_CBTABLE); + + printk(BIOS_SPEW, "entry = %p\n", entry); + cache_sync_instructions(); + doit(cb_tables); +} diff --git a/src/arch/arm/clock.c b/src/arch/arm/clock.c new file mode 100644 index 0000000000..5f68e6fa9d --- /dev/null +++ b/src/arch/arm/clock.c @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +#include + +void set_cntfrq(uint32_t freq) +{ + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq)); +} diff --git a/src/arch/arm/cpu.c b/src/arch/arm/cpu.c new file mode 100644 index 0000000000..6e49e17402 --- /dev/null +++ b/src/arch/arm/cpu.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +#include + +/* Return the cpu struct which is at the high memory address of the stack. + */ +struct cpu_info *cpu_info(void) +{ +#error "This is BROKEN! ARM stacks are currently not guaranteed to be " \ + "STACK_SIZE-aligned in any way. If you ever plan to revive this " \ + "feature, make sure you add the proper assertions to memlayout " \ + "(and maybe consider revising the whole thing to work closer to what " \ + "arm64 is doing now)." + uintptr_t addr = ALIGN((uintptr_t)__builtin_frame_address(0), + CONFIG_STACK_SIZE); + addr -= sizeof(struct cpu_info); + return (void *)addr; +} + diff --git a/src/arch/armv7/lib/div0.c b/src/arch/arm/div0.c similarity index 100% rename from src/arch/armv7/lib/div0.c rename to src/arch/arm/div0.c diff --git a/src/arch/armv7/lib/eabi_compat.c b/src/arch/arm/eabi_compat.c similarity index 65% rename from src/arch/armv7/lib/eabi_compat.c rename to src/arch/arm/eabi_compat.c index 2772de6d04..c27c54e350 100644 --- a/src/arch/armv7/lib/eabi_compat.c +++ b/src/arch/arm/eabi_compat.c @@ -9,24 +9,20 @@ * License, or (at your option) any later version. */ -#include #include -/* FIXME(dhendrix): prototypes added for assembler */ -int raise (int signum); +int raise (int signum) __attribute__((used)); int raise (int signum) { - printk(BIOS_CRIT, "raise: Signal # %d caught\n", signum); return 0; } -/* Dummy function to avoid linker complaints */ -void __aeabi_unwind_cpp_pr0(void); +void __aeabi_unwind_cpp_pr0(void) __attribute__((used)); void __aeabi_unwind_cpp_pr0(void) { }; -void __aeabi_unwind_cpp_pr1(void); +void __aeabi_unwind_cpp_pr1(void) __attribute__((used)); void __aeabi_unwind_cpp_pr1(void) { }; diff --git a/src/arch/armv7/lib/early_console.c b/src/arch/arm/early_console.c similarity index 85% rename from src/arch/armv7/lib/early_console.c rename to src/arch/arm/early_console.c index 68e81c632e..59748eee72 100644 --- a/src/arch/armv7/lib/early_console.c +++ b/src/arch/arm/early_console.c @@ -46,7 +46,7 @@ void console_tx_byte(unsigned char byte) #endif } -static void _console_tx_flush(void) +void console_tx_flush(void) { #if CONFIG_CONSOLE_SERIAL8250MEM uart8250_mem_tx_flush(CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000); @@ -61,21 +61,3 @@ static void _console_tx_flush(void) usbdebug_tx_flush(0); #endif } - -int do_printk(int msg_level, const char *fmt, ...) -{ - va_list args; - int i; - - if (msg_level > console_loglevel) { - return 0; - } - - va_start(args, fmt); - i = vtxprintf(console_tx_byte, fmt, args); - va_end(args); - - _console_tx_flush(); - - return i; -} diff --git a/src/arch/armv7/lib/id.inc b/src/arch/arm/id.S similarity index 96% rename from src/arch/armv7/lib/id.inc rename to src/arch/arm/id.S index ffe547d748..a588f1e1da 100644 --- a/src/arch/armv7/lib/id.inc +++ b/src/arch/arm/id.S @@ -1,3 +1,5 @@ +#include + .section ".id", "a", %progbits .globl __id_start diff --git a/src/arch/arm/include/arch/asm.h b/src/arch/arm/include/arch/asm.h new file mode 100644 index 0000000000..420fa602a6 --- /dev/null +++ b/src/arch/arm/include/arch/asm.h @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_ASM_H +#define __ARM_ASM_H + +/* __arm__ is defined regardless of Thumb mode, so need to order this right */ +#if defined __thumb2__ +# define ARM(x...) +# define THUMB(x...) x +# define W(instr) instr.w +# if __COREBOOT_ARM_ARCH__ < 7 +# error thumb mode has not been tested with ARM < v7! +# endif +#elif defined __thumb__ +# error You are not compiling Thumb2, this won't work! +#else +# define ARM(x...) x +# define THUMB(x...) +# define W(instr) instr +#endif + +#define ALIGN .align 0 + +#define ENDPROC(name) \ + .type name, %function; \ + END(name) + +#define ENTRY(name) \ + .section .text.name, "ax", %progbits; \ + .global name; \ + ALIGN; \ + name: + +#define END(name) \ + .size name, .-name + +/* Thumb code uses the (new) unified assembly syntax. */ +THUMB( .syntax unified ) + +#endif /* __ARM_ASM_H */ diff --git a/src/arch/armv7/include/arch/boot/boot.h b/src/arch/arm/include/arch/boot/boot.h similarity index 100% rename from src/arch/armv7/include/arch/boot/boot.h rename to src/arch/arm/include/arch/boot/boot.h diff --git a/src/arch/armv7/include/arch/byteorder.h b/src/arch/arm/include/arch/byteorder.h similarity index 100% rename from src/arch/armv7/include/arch/byteorder.h rename to src/arch/arm/include/arch/byteorder.h diff --git a/src/arch/arm/include/arch/clock.h b/src/arch/arm/include/arch/clock.h new file mode 100644 index 0000000000..939aa208ce --- /dev/null +++ b/src/arch/arm/include/arch/clock.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_CLOCK_H_ +#define __ARM_CLOCK_H_ + +#include + +void set_cntfrq(uint32_t); + +#endif //__ARM_CLOCK_H_ diff --git a/src/include/cpu/x86/car.h b/src/arch/arm/include/arch/early_variables.h similarity index 70% rename from src/include/cpu/x86/car.h rename to src/arch/arm/include/arch/early_variables.h index 2d2af03a37..31b26c739a 100644 --- a/src/include/cpu/x86/car.h +++ b/src/arch/arm/include/arch/early_variables.h @@ -17,15 +17,18 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -#ifndef CPU_X86_CAR_H -#define CPU_X86_CAR_H +#ifndef ARCH_EARLY_VARIABLES_H +#define ARCH_EARLY_VARIABLES_H + +#if CONFIG_CAR_MIGRATION + #error "This is ARM, silly... we don't have CAR here." +#endif -#ifdef __PRE_RAM__ -#define CAR_GLOBAL __attribute__((section(".car.global_data,\"w\",@nobits#"))) -#define CAR_CBMEM __attribute__((section(".car.cbmem_console,\"w\",@nobits#"))) -#else #define CAR_GLOBAL -#define CAR_CBMEM -#endif + +static inline void *car_get_var_ptr(void *var) { return var; } +#define car_get_var(var) (var) +#define car_set_var(var, val) do { (var) = (val); } while (0) +static inline void car_migrate_variables(void) { } #endif diff --git a/src/arch/arm/include/arch/header.ld b/src/arch/arm/include/arch/header.ld new file mode 100644 index 0000000000..7c5046e611 --- /dev/null +++ b/src/arch/arm/include/arch/header.ld @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +PHDRS +{ + to_load PT_LOAD; +} + +#ifdef __BOOTBLOCK__ +ENTRY(_start) +TARGET(binary) +#else +ENTRY(stage_entry) +#endif diff --git a/src/arch/armv7/include/arch/hlt.h b/src/arch/arm/include/arch/hlt.h similarity index 100% rename from src/arch/armv7/include/arch/hlt.h rename to src/arch/arm/include/arch/hlt.h diff --git a/src/arch/arm/include/arch/io.h b/src/arch/arm/include/arch/io.h new file mode 100644 index 0000000000..e53729708d --- /dev/null +++ b/src/arch/arm/include/arch/io.h @@ -0,0 +1,94 @@ +/* + * Originally imported from linux/include/asm-arm/io.h. This file has changed + * substantially since then. + * + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 08-Apr-2013 G Replaced several macros with inlines for type safety. + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. + * 04-Apr-1999 PJB Added check_signature. + * 12-Dec-1999 RMK More cleanups + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions + */ +#ifndef __ASM_ARM_IO_H +#define __ASM_ARM_IO_H + +#include +#include +#include + +/* + * FIXME: These are to avoid breaking existing ARM code. We should eventually + * re-factor all code to specify the data length intended. + */ +#define readb(a) read8(a) +#define writeb(v,a) write8(v,a) +#define readl(a) read32(a) +#define writel(v,a) write32(v,a) + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define out_arch(type,endian,a,v) write##type(cpu_to_##endian(v),a) +#define in_arch(type,endian,a) endian##_to_cpu(read##type(a)) + +#define out_le32(a,v) out_arch(l,le32,a,v) +#define out_le16(a,v) out_arch(w,le16,a,v) + +#define in_le32(a) in_arch(l,le32,a) +#define in_le16(a) in_arch(w,le16,a) + +#define out_be32(a,v) out_arch(l,be32,a,v) +#define out_be16(a,v) out_arch(w,be16,a,v) + +#define in_be32(a) in_arch(l,be32,a) +#define in_be16(a) in_arch(w,be16,a) + +#define out_8(a,v) writeb(v,a) +#define in_8(a) readb(a) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#endif /* __ASM_ARM_IO_H */ diff --git a/src/arch/arm/include/arch/memlayout.h b/src/arch/arm/include/arch/memlayout.h new file mode 100644 index 0000000000..18a77d657f --- /dev/null +++ b/src/arch/arm/include/arch/memlayout.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file contains macro definitions for memlayout.ld linker scripts. */ + +#ifndef __ARCH_MEMLAYOUT_H +#define __ARCH_MEMLAYOUT_H + +#define SUPERPAGE_SIZE ((1 + IS_ENABLED(CONFIG_ARM_LPAE)) * 1M) + +#define TTB(addr, size) \ + REGION(ttb, addr, size, 16K) \ + _ = ASSERT(size >= 16K + IS_ENABLED(CONFIG_ARM_LPAE) * 32, \ + "TTB must be 16K (+ 32 for LPAE)!"); + +#define TTB_SUBTABLES(addr, size) \ + REGION(ttb_subtables, addr, size, IS_ENABLED(CONFIG_ARM_LPAE)*3K + 1K) \ + _ = ASSERT(size % (1K + 3K * IS_ENABLED(CONFIG_ARM_LPAE)) == 0, \ + "TTB subtable region must be evenly divisible by table size!"); + +/* ARM stacks need 8-byte alignment and stay in one place through ramstage. */ +#define STACK(addr, size) \ + REGION(stack, addr, size, 8) \ + _ = ASSERT(size >= 2K, "stack should be >= 2K, see toolchain.inc"); + +#define DMA_COHERENT(addr, size) \ + REGION(dma_coherent, addr, size, SUPERPAGE_SIZE) \ + _ = ASSERT(size % SUPERPAGE_SIZE == 0, \ + "DMA coherency buffer must fit exactly in full superpages!"); + +#define FRAMEBUFFER(addr, size) \ + REGION(framebuffer, addr, size, SUPERPAGE_SIZE) \ + _ = ASSERT(size % SUPERPAGE_SIZE == 0, \ + "Framebuffer must fit exactly in full superpages!"); + +#endif /* __ARCH_MEMLAYOUT_H */ diff --git a/src/arch/arm/include/arch/pci_ops.h b/src/arch/arm/include/arch/pci_ops.h new file mode 100644 index 0000000000..1a9b4a1db5 --- /dev/null +++ b/src/arch/arm/include/arch/pci_ops.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ARCH_ARM_PCI_OPS_H +#define ARCH_ARM_PCI_OPS_H + +static inline const struct pci_bus_operations *pci_config_default(void) +{ + return NULL; +} + +#endif diff --git a/src/arch/armv7/include/arch/stages.h b/src/arch/arm/include/arch/stages.h similarity index 89% rename from src/arch/armv7/include/arch/stages.h rename to src/arch/arm/include/arch/stages.h index 671c02b3dd..0f82450495 100644 --- a/src/arch/armv7/include/arch/stages.h +++ b/src/arch/arm/include/arch/stages.h @@ -22,7 +22,8 @@ extern void main(void); -void stage_entry(void) __attribute__((section(".text.stage_entry.armv7"))); +void stage_entry(void); void stage_exit(void *); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size); #endif diff --git a/src/arch/arm/include/armv4/arch/arch_io.h b/src/arch/arm/include/armv4/arch/arch_io.h new file mode 100644 index 0000000000..72653da3f3 --- /dev/null +++ b/src/arch/arm/include/armv4/arch/arch_io.h @@ -0,0 +1,58 @@ +/* + * Originally imported from linux/include/asm-arm/io.h. This file has changed + * substantially since then. + * + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 08-Apr-2013 G Replaced several macros with inlines for type safety. + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. + * 04-Apr-1999 PJB Added check_signature. + * 12-Dec-1999 RMK More cleanups + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#include + +static inline uint8_t read8(const void *addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(const void *addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(const void *addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void write8(uint8_t val, void *addr) +{ + *(volatile uint8_t *)addr = val; +} + +static inline void write16(uint16_t val, void *addr) +{ + *(volatile uint16_t *)addr = val; +} + +static inline void write32(uint32_t val, void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +#endif /* __ASM_ARM_ARCH_IO_H */ diff --git a/src/arch/arm/include/armv4/arch/cache.h b/src/arch/arm/include/armv4/arch/cache.h new file mode 100644 index 0000000000..65f59662a6 --- /dev/null +++ b/src/arch/arm/include/armv4/arch/cache.h @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.h: Cache maintenance API for ARM + */ + +#ifndef ARM_CACHE_H +#define ARM_CACHE_H + +#include +#include +#include + +/* + * Cache maintenance API + */ + +/* dcache clean and invalidate all (on current level given by CCSELR) */ +void dcache_clean_invalidate_all(void); + +/* dcache clean by modified virtual address to PoC */ +void dcache_clean_by_mva(void const *addr, size_t len); + +/* dcache clean and invalidate by modified virtual address to PoC */ +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate by modified virtual address to PoC */ +void dcache_invalidate_by_mva(void const *addr, size_t len); + +void dcache_clean_all(void); + +/* dcache invalidate all (on current level given by CCSELR) */ +void dcache_invalidate_all(void); + +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + +/* dcache and MMU disable */ +void dcache_mmu_disable(void); + +/* dcache and MMU enable */ +void dcache_mmu_enable(void); + +/* perform all icache/dcache maintenance needed after loading new code */ +void cache_sync_instructions(void); + +/* tlb invalidate all */ +void tlb_invalidate_all(void); + +#endif /* ARM_CACHE_H */ diff --git a/src/include/coverage.h b/src/arch/arm/include/armv4/arch/cpu.h similarity index 85% rename from src/include/coverage.h rename to src/arch/arm/include/armv4/arch/cpu.h index e1c50c5ee9..48f913ebc0 100644 --- a/src/include/coverage.h +++ b/src/arch/arm/include/armv4/arch/cpu.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2012 Google, Inc. + * Copyright 2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,5 +17,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -void coverage_init(void); -void coverage_exit(void); +#ifndef __ARCH_CPU_H__ +#define __ARCH_CPU_H__ + +#define asmlinkage + +#endif /* __ARCH_CPU_H__ */ diff --git a/src/arch/armv7/include/arch/exception.h b/src/arch/arm/include/armv4/arch/exception.h similarity index 92% rename from src/arch/armv7/include/arch/exception.h rename to src/arch/arm/include/armv4/arch/exception.h index 57076bd57b..d4e9658f75 100644 --- a/src/arch/armv7/include/arch/exception.h +++ b/src/arch/arm/include/armv4/arch/exception.h @@ -1,5 +1,5 @@ /* - * This file is part of the libpayload project. + * This file is part of the coreboot project. * * Copyright 2013 Google Inc. * @@ -30,9 +30,6 @@ #ifndef _ARCH_EXCEPTION_H #define _ARCH_EXCEPTION_H -#include - -void exception_init(void); -void set_vbar(uint32_t vbar); +static inline void exception_init(void) { /* not implemented */ } #endif diff --git a/src/arch/armv7/include/armv7.h b/src/arch/arm/include/armv7.h similarity index 100% rename from src/arch/armv7/include/armv7.h rename to src/arch/arm/include/armv7.h diff --git a/src/arch/arm/include/armv7/arch/arch_io.h b/src/arch/arm/include/armv7/arch/arch_io.h new file mode 100644 index 0000000000..360fa6425a --- /dev/null +++ b/src/arch/arm/include/armv7/arch/arch_io.h @@ -0,0 +1,68 @@ +/* + * Originally imported from linux/include/asm-arm/io.h. This file has changed + * substantially since then. + * + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 08-Apr-2013 G Replaced several macros with inlines for type safety. + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. + * 04-Apr-1999 PJB Added check_signature. + * 12-Dec-1999 RMK More cleanups + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#include /* for dmb() */ +#include + +static inline uint8_t read8(const void *addr) +{ + dmb(); + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(const void *addr) +{ + dmb(); + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(const void *addr) +{ + dmb(); + return *(volatile uint32_t *)addr; +} + +static inline void write8(uint8_t val, void *addr) +{ + dmb(); + *(volatile uint8_t *)addr = val; + dmb(); +} + +static inline void write16(uint16_t val, void *addr) +{ + dmb(); + *(volatile uint16_t *)addr = val; + dmb(); +} + +static inline void write32(uint32_t val, void *addr) +{ + dmb(); + *(volatile uint32_t *)addr = val; + dmb(); +} + +#endif /* __ASM_ARM_ARCH_IO_H */ diff --git a/payloads/libpayload/include/armv7/arch/cache.h b/src/arch/arm/include/armv7/arch/cache.h similarity index 63% rename from payloads/libpayload/include/armv7/arch/cache.h rename to src/arch/arm/include/armv7/arch/cache.h index f074a3b158..130cdee88e 100644 --- a/payloads/libpayload/include/armv7/arch/cache.h +++ b/src/arch/arm/include/armv7/arch/cache.h @@ -26,11 +26,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * cache.h: Cache maintenance API for ARMv7 + * cache.h: Cache maintenance API for ARM */ -#ifndef ARMV7_CACHE_H -#define ARMV7_CACHE_H +#ifndef ARM_CACHE_H +#define ARM_CACHE_H + +#include +#include +#include /* SCTLR bits */ #define SCTLR_M (1 << 0) /* MMU enable */ @@ -90,34 +94,52 @@ static inline void isb(void) * Low-level TLB maintenance operations */ -/* invalidate entire data TLB */ -static inline void dtlbiall(void) -{ - asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0) : "memory"); -} - -/* invalidate entire instruction TLB */ -static inline void itlbiall(void) -{ - asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); -} - /* invalidate entire unified TLB */ static inline void tlbiall(void) { asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0) : "memory"); } +/* invalidate unified TLB by MVA, all ASID */ +static inline void tlbimvaa(unsigned long mva) +{ + asm volatile ("mcr p15, 0, %0, c8, c7, 3" : : "r" (mva) : "memory"); +} + /* write data access control register (DACR) */ static inline void write_dacr(uint32_t val) { asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" (val)); } +/* read memory model feature register 0 (MMFR0) */ +static inline uint32_t read_mmfr0(void) +{ + uint32_t mmfr; + asm volatile ("mrc p15, 0, %0, c0, c1, 4" : "=r" (mmfr)); + return mmfr; +} +/* read MAIR0 (memory address indirection register 0) */ +static inline uint32_t read_mair0(void) +{ + uint32_t mair; + asm volatile ("mrc p15, 0, %0, c10, c2, 0" : "=r" (mair)); + return mair; +} +/* write MAIR0 (memory address indirection register 0) */ +static inline void write_mair0(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c10, c2, 0" : : "r" (val)); +} /* write translation table base register 0 (TTBR0) */ static inline void write_ttbr0(uint32_t val) { +#if CONFIG_ARM_LPAE + asm volatile ("mcrr p15, 0, %[val], %[zero], c2" : : + [val] "r" (val), [zero] "r" (0)); +#else asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (val) : "memory"); +#endif } /* read translation table base control register (TTBCR) */ @@ -162,6 +184,12 @@ static inline void dccmvac(unsigned long mva) asm volatile ("mcr p15, 0, %0, c7, c10, 1" : : "r" (mva) : "memory"); } +/* data cache clean by set/way */ +static inline void dccsw(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c7, c10, 2" : : "r" (val) : "memory"); +} + /* data cache invalidate by MVA to PoC */ static inline void dcimvac(unsigned long mva) { @@ -219,10 +247,44 @@ static inline void write_csselr(uint32_t val) isb(); /* ISB to sync the change to CCSIDR */ } -/* read system control register (SCTLR) */ -static inline unsigned int read_sctlr(void) +/* read L2 control register (L2CTLR) */ +static inline uint32_t read_l2ctlr(void) { - unsigned int val; + uint32_t val = 0; + asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val)); + return val; +} + +/* write L2 control register (L2CTLR) */ +static inline void write_l2ctlr(uint32_t val) +{ + /* + * Note: L2CTLR can only be written when the L2 memory system + * is idle, ie before the MMU is enabled. + */ + asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory" ); + isb(); +} + +/* read L2 Auxiliary Control Register (L2ACTLR) */ +static inline uint32_t read_l2actlr(void) +{ + uint32_t val = 0; + asm volatile ("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); + return val; +} + +/* write L2 Auxiliary Control Register (L2ACTLR) */ +static inline void write_l2actlr(uint32_t val) +{ + asm volatile ("mcr p15, 1, %0, c15, c0, 0" : : "r" (val) : "memory" ); + isb(); +} + +/* read system control register (SCTLR) */ +static inline uint32_t read_sctlr(void) +{ + uint32_t val; asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (val)); return val; } @@ -234,6 +296,54 @@ static inline void write_sctlr(uint32_t val) isb(); } +/* read data fault address register (DFAR) */ +static inline uint32_t read_dfar(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c6, c0, 0" : "=r" (val)); + return val; +} + +/* read data fault status register (DFSR) */ +static inline uint32_t read_dfsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r" (val)); + return val; +} + +/* read instruction fault address register (IFAR) */ +static inline uint32_t read_ifar(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c6, c0, 2" : "=r" (val)); + return val; +} + +/* read instruction fault status register (IFSR) */ +static inline uint32_t read_ifsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c0, 1" : "=r" (val)); + return val; +} + +/* read auxiliary data fault status register (ADFSR) */ +static inline uint32_t read_adfsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c1, 0" : "=r" (val)); + return val; +} + +/* read auxiliary instruction fault status register (AIFSR) */ +static inline uint32_t read_aifsr(void) +{ + uint32_t val; + asm volatile ("mrc p15, 0, %0, c5, c1, 1" : "=r" (val)); + return val; +} + /* * Cache maintenance API */ @@ -242,22 +352,30 @@ static inline void write_sctlr(uint32_t val) void dcache_clean_invalidate_all(void); /* dcache clean by modified virtual address to PoC */ -void dcache_clean_by_mva(unsigned long addr, unsigned long len); +void dcache_clean_by_mva(void const *addr, size_t len); /* dcache clean and invalidate by modified virtual address to PoC */ -void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len); +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate by modified virtual address to PoC */ +void dcache_invalidate_by_mva(void const *addr, size_t len); + +void dcache_clean_all(void); /* dcache invalidate all (on current level given by CCSELR) */ void dcache_invalidate_all(void); +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + /* dcache and MMU disable */ void dcache_mmu_disable(void); /* dcache and MMU enable */ void dcache_mmu_enable(void); -/* icache invalidate all (on current level given by CSSELR) */ -void icache_invalidate_all(void); +/* perform all icache/dcache maintenance needed after loading new code */ +void cache_sync_instructions(void); /* tlb invalidate all */ void tlb_invalidate_all(void); @@ -266,9 +384,6 @@ void tlb_invalidate_all(void); * Generalized setup/init functions */ -/* invalidate all caches on ARMv7 */ -void armv7_invalidate_caches(void); - /* mmu initialization (set page table address, set permissions, etc) */ void mmu_init(void); @@ -278,8 +393,15 @@ enum dcache_policy { DCACHE_WRITETHROUGH, }; +/* disable the mmu for a range. Primarily useful to lock out address 0. */ +void mmu_disable_range(u32 start_mb, u32 size_mb); /* mmu range configuration (set dcache policy) */ -void mmu_config_range(unsigned long start_mb, unsigned long size_mb, - enum dcache_policy policy); +void mmu_config_range(u32 start_mb, u32 size_mb, enum dcache_policy policy); -#endif /* ARMV7_CACHE_H */ +/* Reconfigure memory mappings at the fine-grained (4K) page level. Must be + * called on a range contained within a single, already mapped block/superpage. + * Careful: Do NOT map over this address range with mmu_config_range() again + * later, or you will leak resources and may desync your TLB! */ +void mmu_config_range_kb(u32 start_kb, u32 size_kb, enum dcache_policy policy); + +#endif /* ARM_CACHE_H */ diff --git a/src/arch/arm/include/armv7/arch/cpu.h b/src/arch/arm/include/armv7/arch/cpu.h new file mode 100644 index 0000000000..275bb8c909 --- /dev/null +++ b/src/arch/arm/include/armv7/arch/cpu.h @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __ARCH_CPU_H__ +#define __ARCH_CPU_H__ + +#include + +#define asmlinkage + +#if !defined(__PRE_RAM__) +#include + +struct cpu_driver { + struct device_operations *ops; + struct cpu_device_id *id_table; +}; + +struct thread; + +struct cpu_info { + device_t cpu; + unsigned long index; +#if CONFIG_COOP_MULTITASKING + struct thread *thread; +#endif +}; + +struct cpuinfo_arm { + uint8_t arm; /* CPU family */ + uint8_t arm_vendor; /* CPU vendor */ + uint8_t arm_model; +}; + +#endif + +/* Primitives for CPU and MP cores. */ + +/* read Main Id register (MIDR) */ +inline static uint32_t read_midr(void) +{ + uint32_t value; + asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r"(value)); + return value; +} + +/* read Multiprocessor Affinity Register (MPIDR) */ +inline static uint32_t read_mpidr(void) +{ + uint32_t value; + asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r"(value)); + return value; +} + +/* read Auxiliary Control Register (ACTLR) */ +inline static uint32_t read_actlr(void) +{ + uint32_t val = 0; + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r"(val)); + return val; +} + +/* write Auxiliary Control Register (ACTLR) */ +inline static void write_actlr(uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (val)); +} + +/* wait for interrupt. */ +inline static void wfi(void) +{ + asm volatile ("wfi" : : : "memory"); +} + +/* wait for event. */ +inline static void wfe(void) +{ + asm volatile ("wfe"); +} + +/* set event (to bring up cores in WFE state). */ +inline static void sev(void) +{ + asm volatile ("sev"); +} + +/* puts CPU into System mode and disable interrupts. */ +inline static void set_system_mode(void) +{ + asm volatile("msr cpsr_c, %0" :: "r"(0x1f | 0xc0)); +} + +struct cpu_info *cpu_info(void); +#endif /* __ARCH_CPU_H__ */ diff --git a/payloads/libpayload/include/armv7/arch/exception.h b/src/arch/arm/include/armv7/arch/exception.h similarity index 100% rename from payloads/libpayload/include/armv7/arch/exception.h rename to src/arch/arm/include/armv7/arch/exception.h diff --git a/src/arch/armv7/include/arch/types.h b/src/arch/arm/include/armv7/arch/types.h similarity index 100% rename from src/arch/armv7/include/arch/types.h rename to src/arch/arm/include/armv7/arch/types.h diff --git a/src/arch/arm/include/bootblock_common.h b/src/arch/arm/include/bootblock_common.h new file mode 100644 index 0000000000..06312928da --- /dev/null +++ b/src/arch/arm/include/bootblock_common.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_BOOTBLOCK_COMMON_H +#define __ARCH_BOOTBLOCK_COMMON_H + +/* These are defined as weak no-ops that can be overridden by mainboard/SoC. */ +void bootblock_mainboard_early_init(void); +void bootblock_mainboard_init(void); +void bootblock_soc_init(void); + +#endif /* __ARCH_BOOTBLOCK_COMMON_H */ diff --git a/src/arch/armv7/include/clocks.h b/src/arch/arm/include/clocks.h similarity index 100% rename from src/arch/armv7/include/clocks.h rename to src/arch/arm/include/clocks.h diff --git a/src/arch/armv7/include/smp/spinlock.h b/src/arch/arm/include/smp/spinlock.h similarity index 100% rename from src/arch/armv7/include/smp/spinlock.h rename to src/arch/arm/include/smp/spinlock.h diff --git a/src/arch/armv7/include/stdint.h b/src/arch/arm/include/stdint.h similarity index 88% rename from src/arch/armv7/include/stdint.h rename to src/arch/arm/include/stdint.h index a8a023059a..9d41e6359a 100644 --- a/src/arch/armv7/include/stdint.h +++ b/src/arch/arm/include/stdint.h @@ -75,6 +75,18 @@ typedef int8_t s8; typedef int16_t s16; typedef int32_t s32; +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif +#ifndef UINT64_MAX +# define UINT64_MAX (18446744073709551615ULL) +#endif +#ifndef UINT64_C +#define UINT64_C(c) c ## ULL +#endif +#ifndef PRIu64 +#define PRIu64 "llu" +#endif #undef __HAVE_LONG_LONG__ diff --git a/src/arch/armv7/include/utils.h b/src/arch/arm/include/utils.h similarity index 100% rename from src/arch/armv7/include/utils.h rename to src/arch/arm/include/utils.h diff --git a/src/arch/arm/libgcc/Makefile.inc b/src/arch/arm/libgcc/Makefile.inc new file mode 100644 index 0000000000..e49731220f --- /dev/null +++ b/src/arch/arm/libgcc/Makefile.inc @@ -0,0 +1,38 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +libgcc_files = ashldi3.S lib1funcs.S lshrdi3.S muldi3.S ucmpdi2.S uldivmod.S + +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM),y) +bootblock-y += $(libgcc_files) +endif + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM),y) +verstage-y += $(libgcc_files) +endif + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM),y) +romstage-y += $(libgcc_files) +endif + +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM),y) +ramstage-y += $(libgcc_files) +endif \ No newline at end of file diff --git a/src/arch/arm/libgcc/ashldi3.S b/src/arch/arm/libgcc/ashldi3.S new file mode 100644 index 0000000000..3009f18b83 --- /dev/null +++ b/src/arch/arm/libgcc/ashldi3.S @@ -0,0 +1,59 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#if defined __GNUC__ + +#include + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +ENTRY(__ashldi3) +.global __aeabi_llsl +__aeabi_llsl: + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi ah, ah, lsl r2 + movpl ah, al, lsl r3 + ARM( orrmi ah, ah, al, lsr ip ) + THUMB( lsrmi r3, al, ip ) + THUMB( orrmi ah, ah, r3 ) + mov al, al, lsl r2 + mov pc, lr + +.type __aeabi_llsl, %function +.size __aeabi_llsl, .-__aeabi_llsl +ENDPROC(__ashldi3) + +#endif diff --git a/src/arch/arm/libgcc/lib1funcs.S b/src/arch/arm/libgcc/lib1funcs.S new file mode 100644 index 0000000000..f78a937afc --- /dev/null +++ b/src/arch/arm/libgcc/lib1funcs.S @@ -0,0 +1,348 @@ +/* + * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines + * + * Author: Nicolas Pitre + * - contributed to gcc-3.4 on Sep 30, 2003 + * - adapted for the Linux kernel on Oct 2, 2003 + */ + +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +#if defined __GNUC__ + +#include + +.macro ARM_DIV_BODY dividend, divisor, result, curbit + +#if __COREBOOT_ARM_ARCH__ >= 5 + + clz \curbit, \divisor + clz \result, \dividend + sub \result, \curbit, \result + mov \curbit, #1 + mov \divisor, \divisor, lsl \result + mov \curbit, \curbit, lsl \result + mov \result, #0 + +#else + + @ Initially shift the divisor left 3 bits if possible, + @ set curbit accordingly. This allows for curbit to be located + @ at the left end of each 4 bit nibbles in the division loop + @ to save one loop in most cases. + tst \divisor, #0xe0000000 + moveq \divisor, \divisor, lsl #3 + moveq \curbit, #8 + movne \curbit, #1 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + movlo \curbit, \curbit, lsl #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + movlo \curbit, \curbit, lsl #1 + blo 1b + + mov \result, #0 + +#endif + + @ Division loop +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + orrhs \result, \result, \curbit + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + orrhs \result, \result, \curbit, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + orrhs \result, \result, \curbit, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + orrhs \result, \result, \curbit, lsr #3 + cmp \dividend, #0 @ Early termination? + movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? + movne \divisor, \divisor, lsr #4 + bne 1b + +.endm + + +.macro ARM_DIV2_ORDER divisor, order + +#if __COREBOOT_ARM_ARCH__ >= 5 + + clz \order, \divisor + rsb \order, \order, #31 + +#else + + cmp \divisor, #(1 << 16) + movhs \divisor, \divisor, lsr #16 + movhs \order, #16 + movlo \order, #0 + + cmp \divisor, #(1 << 8) + movhs \divisor, \divisor, lsr #8 + addhs \order, \order, #8 + + cmp \divisor, #(1 << 4) + movhs \divisor, \divisor, lsr #4 + addhs \order, \order, #4 + + cmp \divisor, #(1 << 2) + addhi \order, \order, #3 + addls \order, \order, \divisor, lsr #1 + +#endif + +.endm + + +.macro ARM_MOD_BODY dividend, divisor, order, spare + +#if __COREBOOT_ARM_ARCH__ >= 5 + + clz \order, \divisor + clz \spare, \dividend + sub \order, \order, \spare + mov \divisor, \divisor, lsl \order + +#else + + mov \order, #0 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + addlo \order, \order, #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + addlo \order, \order, #1 + blo 1b + +#endif + + @ Perform all needed substractions to keep only the reminder. + @ Do comparisons in batch of 4 first. + subs \order, \order, #3 @ yes, 3 is intended here + blt 2f + +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + cmp \dividend, #1 + mov \divisor, \divisor, lsr #4 + subges \order, \order, #4 + bge 1b + + tst \order, #3 + teqne \dividend, #0 + beq 5f + + @ Either 1, 2 or 3 comparison/substractions are left. +2: cmn \order, #2 + blt 4f + beq 3f + cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +3: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +4: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor +5: +.endm + + +ENTRY(__udivsi3) +.global __aeabi_uidiv +__aeabi_uidiv: + + subs r2, r1, #1 + moveq pc, lr + bcc Ldiv0 + cmp r0, r1 + bls 11f + tst r1, r2 + beq 12f + + ARM_DIV_BODY r0, r1, r2, r3 + + mov r0, r2 + mov pc, lr + +11: moveq r0, #1 + movne r0, #0 + mov pc, lr + +12: ARM_DIV2_ORDER r1, r2 + + mov r0, r0, lsr r2 + mov pc, lr + +.type __aeabi_uidiv, %function +.size __aeabi_uidiv, .-__aeabi_uidiv +ENDPROC(__udivsi3) + +ENTRY(__umodsi3) + + subs r2, r1, #1 @ compare divisor with 1 + bcc Ldiv0 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + movls pc, lr + + ARM_MOD_BODY r0, r1, r2, r3 + + mov pc, lr + +ENDPROC(__umodsi3) + +ENTRY(__divsi3) +.global __aeabi_idiv +__aeabi_idiv: + + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the result. + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + subs r2, r1, #1 @ division by 1 or -1 ? + beq 10f + movs r3, r0 + rsbmi r3, r0, #0 @ positive dividend value + cmp r3, r1 + bls 11f + tst r1, r2 @ divisor is power of 2 ? + beq 12f + + ARM_DIV_BODY r3, r1, r0, r2 + + cmp ip, #0 + rsbmi r0, r0, #0 + mov pc, lr + +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 + mov pc, lr + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 + mov pc, lr + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 + mov pc, lr + +.type __aeabi_idiv, %function +.size __aeabi_idiv, .-__aeabi_idiv +ENDPROC(__divsi3) + +ENTRY(__modsi3) + + cmp r1, #0 + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + movs ip, r0 @ preserve sign of dividend + rsbmi r0, r0, #0 @ if negative make positive + subs r2, r1, #1 @ compare divisor with 1 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + bls 10f + + ARM_MOD_BODY r0, r1, r2, r3 + +10: cmp ip, #0 + rsbmi r0, r0, #0 + mov pc, lr + +ENDPROC(__modsi3) + +ENTRY(__aeabi_uidivmod) + + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_uidiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + mov pc, lr + +ENDPROC(__aeabi_uidivmod) + +ENTRY(__aeabi_idivmod) + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_idiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + mov pc, lr + +ENDPROC(__aeabi_idivmod) + + +Ldiv0: + str lr, [sp, #-8]! + bl __div0 + mov r0, #0 @ About as wrong as it could be. + ldr pc, [sp], #8 +ENDPROC(Ldiv0) + +#endif diff --git a/src/arch/arm/libgcc/lshrdi3.S b/src/arch/arm/libgcc/lshrdi3.S new file mode 100644 index 0000000000..7af0c83123 --- /dev/null +++ b/src/arch/arm/libgcc/lshrdi3.S @@ -0,0 +1,59 @@ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + + +#if defined __GNUC__ + +#include + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +ENTRY(__lshrdi3) +.global __aeabi_llsr +__aeabi_llsr: + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, lsr r3 + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) + mov ah, ah, lsr r2 + mov pc, lr + +.type __aeabi_llsr, %function +.size __aeabi_llsr, .-__aeabi_llsr +ENDPROC(__lshrdi3) + +#endif diff --git a/src/arch/arm/libgcc/muldi3.S b/src/arch/arm/libgcc/muldi3.S new file mode 100644 index 0000000000..652dacab26 --- /dev/null +++ b/src/arch/arm/libgcc/muldi3.S @@ -0,0 +1,53 @@ +/* + * linux/arch/arm/lib/muldi3.S + * + * Author: Nicolas Pitre + * Created: Oct 19, 2005 + * Copyright: Monta Vista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#if defined __GNUC__ + +#include + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +ENTRY(__muldi3) +.global __aeabi_lmul +__aeabi_lmul: + + mul xh, yl, xh + mla xh, xl, yh, xh + mov ip, xl, lsr #16 + mov yh, yl, lsr #16 + bic xl, xl, ip, lsl #16 + bic yl, yl, yh, lsl #16 + mla xh, yh, ip, xh + mul yh, xl, yh + mul xl, yl, xl + mul ip, yl, ip + adds xl, xl, yh, lsl #16 + adc xh, xh, yh, lsr #16 + adds xl, xl, ip, lsl #16 + adc xh, xh, ip, lsr #16 + mov pc, lr + +.type __aeabi_lmul, %function +.size __aeabi_lmul, .-__aeabi_lmul +ENDPROC(__muldi3) + +#endif diff --git a/src/arch/arm/libgcc/ucmpdi2.S b/src/arch/arm/libgcc/ucmpdi2.S new file mode 100644 index 0000000000..01ce1b54c8 --- /dev/null +++ b/src/arch/arm/libgcc/ucmpdi2.S @@ -0,0 +1,51 @@ +/* + * linux/arch/arm/lib/ucmpdi2.S + * + * Author: Nicolas Pitre + * Created: Oct 19, 2005 + * Copyright: Monta Vista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#if defined __GNUC__ + +#include + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +ENTRY(__ucmpdi2) + + cmp xh, yh + cmpeq xl, yl + movlo r0, #0 + moveq r0, #1 + movhi r0, #2 + mov pc, lr + +ENDPROC(__ucmpdi2) + +ENTRY(__aeabi_ulcmp) + + cmp xh, yh + cmpeq xl, yl + movlo r0, #-1 + moveq r0, #0 + movhi r0, #1 + mov pc, lr + +ENDPROC(__aeabi_ulcmp) + +#endif diff --git a/src/arch/arm/libgcc/uldivmod.S b/src/arch/arm/libgcc/uldivmod.S new file mode 100644 index 0000000000..521a5d1e33 --- /dev/null +++ b/src/arch/arm/libgcc/uldivmod.S @@ -0,0 +1,268 @@ +/* + * Copyright 2010, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#include + +/* + * A, Q = r0 + (r1 << 32) + * B, R = r2 + (r3 << 32) + * A / B = Q ... R + */ + +A_0 .req r0 +A_1 .req r1 +B_0 .req r2 +B_1 .req r3 +C_0 .req r4 +C_1 .req r5 +D_0 .req r6 +D_1 .req r7 + +Q_0 .req r0 +Q_1 .req r1 +R_0 .req r2 +R_1 .req r3 + +THUMB( +TMP .req r8 +) + +ENTRY(__aeabi_uldivmod) + stmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) lr} + @ Test if B == 0 + orrs ip, B_0, B_1 @ Z set -> B == 0 + beq L_div_by_0 + @ Test if B is power of 2: (B & (B - 1)) == 0 + subs C_0, B_0, #1 + sbc C_1, B_1, #0 + tst C_0, B_0 + tsteq B_1, C_1 + beq L_pow2 + @ Test if A_1 == B_1 == 0 + orrs ip, A_1, B_1 + beq L_div_32_32 + +L_div_64_64: +/* CLZ only exists in ARM architecture version 5 and above. */ +#if __COREBOOT_ARM_ARCH__ >= 5 + mov C_0, #1 + mov C_1, #0 + @ D_0 = clz A + teq A_1, #0 + clz D_0, A_1 + clzeq ip, A_0 + addeq D_0, D_0, ip + @ D_1 = clz B + teq B_1, #0 + clz D_1, B_1 + clzeq ip, B_0 + addeq D_1, D_1, ip + @ if clz B - clz A > 0 + subs D_0, D_1, D_0 + bls L_done_shift + @ B <<= (clz B - clz A) + subs D_1, D_0, #32 + rsb ip, D_0, #32 + movmi B_1, B_1, lsl D_0 +ARM( orrmi B_1, B_1, B_0, lsr ip ) +THUMB( lsrmi TMP, B_0, ip ) +THUMB( orrmi B_1, B_1, TMP ) + movpl B_1, B_0, lsl D_1 + mov B_0, B_0, lsl D_0 + @ C = 1 << (clz B - clz A) + movmi C_1, C_1, lsl D_0 +ARM( orrmi C_1, C_1, C_0, lsr ip ) +THUMB( lsrmi TMP, C_0, ip ) +THUMB( orrmi C_1, C_1, TMP ) + movpl C_1, C_0, lsl D_1 + mov C_0, C_0, lsl D_0 +L_done_shift: + mov D_0, #0 + mov D_1, #0 + @ C: current bit; D: result +#else + @ C: current bit; D: result + mov C_0, #1 + mov C_1, #0 + mov D_0, #0 + mov D_1, #0 +L_lsl_4: + cmp B_1, #0x10000000 + cmpcc B_1, A_1 + cmpeq B_0, A_0 + bcs L_lsl_1 + @ B <<= 4 + mov B_1, B_1, lsl #4 + orr B_1, B_1, B_0, lsr #28 + mov B_0, B_0, lsl #4 + @ C <<= 4 + mov C_1, C_1, lsl #4 + orr C_1, C_1, C_0, lsr #28 + mov C_0, C_0, lsl #4 + b L_lsl_4 +L_lsl_1: + cmp B_1, #0x80000000 + cmpcc B_1, A_1 + cmpeq B_0, A_0 + bcs L_subtract + @ B <<= 1 + mov B_1, B_1, lsl #1 + orr B_1, B_1, B_0, lsr #31 + mov B_0, B_0, lsl #1 + @ C <<= 1 + mov C_1, C_1, lsl #1 + orr C_1, C_1, C_0, lsr #31 + mov C_0, C_0, lsl #1 + b L_lsl_1 +#endif +L_subtract: + @ if A >= B + cmp A_1, B_1 + cmpeq A_0, B_0 + bcc L_update + @ A -= B + subs A_0, A_0, B_0 + sbc A_1, A_1, B_1 + @ D |= C + orr D_0, D_0, C_0 + orr D_1, D_1, C_1 +L_update: + @ if A == 0: break + orrs ip, A_1, A_0 + beq L_exit + @ C >>= 1 + movs C_1, C_1, lsr #1 + movs C_0, C_0, rrx + @ if C == 0: break + orrs ip, C_1, C_0 + beq L_exit + @ B >>= 1 + movs B_1, B_1, lsr #1 + mov B_0, B_0, rrx + b L_subtract +L_exit: + @ Note: A, B & Q, R are aliases + mov R_0, A_0 + mov R_1, A_1 + mov Q_0, D_0 + mov Q_1, D_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} + +L_div_32_32: + @ Note: A_0 & r0 are aliases + @ Q_1 r1 + mov r1, B_0 + bl __aeabi_uidivmod + mov R_0, r1 + mov R_1, #0 + mov Q_1, #0 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} + +L_pow2: +/* CLZ only exists in ARM architecture version 5 and above. */ +#if __COREBOOT_ARM_ARCH__ >= 5 + @ Note: A, B and Q, R are aliases + @ R = A & (B - 1) + and C_0, A_0, C_0 + and C_1, A_1, C_1 + @ Q = A >> log2(B) + @ Note: B must not be 0 here! + clz D_0, B_0 + add D_1, D_0, #1 + rsbs D_0, D_0, #31 + bpl L_1 + clz D_0, B_1 + rsb D_0, D_0, #31 + mov A_0, A_1, lsr D_0 + add D_0, D_0, #32 +L_1: + movpl A_0, A_0, lsr D_0 +ARM( orrpl A_0, A_0, A_1, lsl D_1 ) +THUMB( lslpl TMP, A_1, D_1 ) +THUMB( orrpl A_0, A_0, TMP ) + mov A_1, A_1, lsr D_0 + @ Mov back C to R + mov R_0, C_0 + mov R_1, C_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +#else + @ Note: A, B and Q, R are aliases + @ R = A & (B - 1) + and C_0, A_0, C_0 + and C_1, A_1, C_1 + @ Q = A >> log2(B) + @ Note: B must not be 0 here! + @ Count the leading zeroes in B. + mov D_0, #0 + orrs B_0, B_0, B_0 + @ If B is greater than 1 << 31, divide A and B by 1 << 32. + moveq A_0, A_1 + moveq A_1, #0 + moveq B_0, B_1 + @ Count the remaining leading zeroes in B. + movs B_1, B_0, lsl #16 + addeq D_0, #16 + moveq B_0, B_0, lsr #16 + tst B_0, #0xff + addeq D_0, #8 + moveq B_0, B_0, lsr #8 + tst B_0, #0xf + addeq D_0, #4 + moveq B_0, B_0, lsr #4 + tst B_0, #0x3 + addeq D_0, #2 + moveq B_0, B_0, lsr #2 + tst B_0, #0x1 + addeq D_0, #1 + @ Shift A to the right by the appropriate amount. + rsb D_1, D_0, #32 + mov Q_0, A_0, lsr D_0 + orr Q_0, A_1, lsl D_1 + mov Q_1, A_1, lsr D_0 + @ Move C to R + mov R_0, C_0 + mov R_1, C_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +#endif + +L_div_by_0: + bl __div0 + @ As wrong as it could be + mov Q_0, #0 + mov Q_1, #0 + mov R_0, #0 + mov R_1, #0 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +ENDPROC(__aeabi_uldivmod) diff --git a/payloads/libpayload/arch/armv7/memcpy.S b/src/arch/arm/memcpy.S similarity index 97% rename from payloads/libpayload/arch/armv7/memcpy.S rename to src/arch/arm/memcpy.S index 549320c8d1..1388d05ad9 100644 --- a/payloads/libpayload/arch/armv7/memcpy.S +++ b/src/arch/arm/memcpy.S @@ -10,9 +10,8 @@ * published by the Free Software Foundation. */ -#include "assembler.h" - -#define W(instr) instr +#include +#include "asmlib.h" #define LDR1W_SHIFT 0 #define STR1W_SHIFT 0 @@ -53,15 +52,9 @@ ldmfd sp!, {r0, \reg1, \reg2} .endm - .text - /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ -.globl memcpy -memcpy: - - cmp r0, r1 - moveq pc, lr +ENTRY(memcpy) enter r4, lr @@ -241,3 +234,4 @@ memcpy: 17: forward_copy_shift pull=16 push=16 18: forward_copy_shift pull=24 push=8 +ENDPROC(memcpy) diff --git a/src/arch/arm/memmove.S b/src/arch/arm/memmove.S new file mode 100644 index 0000000000..bd5f8f1ac5 --- /dev/null +++ b/src/arch/arm/memmove.S @@ -0,0 +1,197 @@ +/* + * linux/arch/arm/lib/memmove.S + * + * Author: Nicolas Pitre + * Created: Sep 28, 2005 + * Copyright: (C) MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "asmlib.h" + +/* + * Prototype: void *memmove(void *dest, const void *src, size_t n); + * + * Note: + * + * If the memory regions don't overlap, we simply branch to memcpy which is + * normally a bit faster. Otherwise the copy is done going downwards. This + * is a transposition of the code from copy_template.S but with the copy + * occurring in the opposite direction. + */ + +ENTRY(memmove) + + subs ip, r0, r1 + cmphi r2, ip + bls memcpy + + stmfd sp!, {r0, r4, lr} + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + PLD( pld [r1, #-4] ) + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + + CALGN( ands ip, r0, #31 ) + CALGN( sbcnes r4, ip, r2 ) @ C is always set here + CALGN( bcs 2f ) + CALGN( adr r4, 6f ) + CALGN( subs r2, r2, ip ) @ C is set here + CALGN( rsb ip, ip, #32 ) + CALGN( add pc, r4, ip ) + + PLD( pld [r1, #-4] ) +2: PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 4f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +3: PLD( pld [r1, #-128] ) +4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} + bge 3b + PLD( cmn r2, #96 ) + PLD( bge 4b ) + +5: ands ip, r2, #28 + rsb ip, ip, #32 + addne pc, pc, ip @ C is always clear here + b 7f +6: W(nop) + W(ldr) r3, [r1, #-4]! + W(ldr) r4, [r1, #-4]! + W(ldr) r5, [r1, #-4]! + W(ldr) r6, [r1, #-4]! + W(ldr) r7, [r1, #-4]! + W(ldr) r8, [r1, #-4]! + W(ldr) lr, [r1, #-4]! + + add pc, pc, ip + nop + W(nop) + W(str) r3, [r0, #-4]! + W(str) r4, [r0, #-4]! + W(str) r5, [r0, #-4]! + W(str) r6, [r0, #-4]! + W(str) r7, [r0, #-4]! + W(str) r8, [r0, #-4]! + W(str) lr, [r0, #-4]! + + CALGN( bcs 2b ) + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldrneb r3, [r1, #-1]! + ldrcsb r4, [r1, #-1]! + ldrcsb ip, [r1, #-1] + strneb r3, [r0, #-1]! + strcsb r4, [r0, #-1]! + strcsb ip, [r0, #-1] + ldmfd sp!, {r0, r4, pc} + +9: cmp ip, #2 + ldrgtb r3, [r1, #-1]! + ldrgeb r4, [r1, #-1]! + ldrb lr, [r1, #-1]! + strgtb r3, [r0, #-1]! + strgeb r4, [r0, #-1]! + subs r2, r2, ip + strb lr, [r0, #-1]! + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr r3, [r1, #0] + beq 17f + blt 18f + + + .macro backward_copy_shift push pull + + subs r2, r2, #28 + blt 14f + + CALGN( ands ip, r0, #31 ) + CALGN( sbcnes r4, ip, r2 ) @ C is always set here + CALGN( subcc r2, r2, ip ) + CALGN( bcc 15f ) + +11: stmfd sp!, {r5 - r9} + + PLD( pld [r1, #-4] ) + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #-32] ) + PLD( blt 13f ) + PLD( pld [r1, #-64] ) + PLD( pld [r1, #-96] ) + +12: PLD( pld [r1, #-128] ) +13: ldmdb r1!, {r7, r8, r9, ip} + mov lr, r3, push #\push + subs r2, r2, #32 + ldmdb r1!, {r3, r4, r5, r6} + orr lr, lr, ip, pull #\pull + mov ip, ip, push #\push + orr ip, ip, r9, pull #\pull + mov r9, r9, push #\push + orr r9, r9, r8, pull #\pull + mov r8, r8, push #\push + orr r8, r8, r7, pull #\pull + mov r7, r7, push #\push + orr r7, r7, r6, pull #\pull + mov r6, r6, push #\push + orr r6, r6, r5, pull #\pull + mov r5, r5, push #\push + orr r5, r5, r4, pull #\pull + mov r4, r4, push #\push + orr r4, r4, r3, pull #\pull + stmdb r0!, {r4 - r9, ip, lr} + bge 12b + PLD( cmn r2, #96 ) + PLD( bge 13b ) + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov lr, r3, push #\push + ldr r3, [r1, #-4]! + subs ip, ip, #4 + orr lr, lr, r3, pull #\pull + str lr, [r0, #-4]! + bgt 15b + CALGN( cmp r2, #0 ) + CALGN( bge 11b ) + +16: add r1, r1, #(\pull / 8) + b 8b + + .endm + + + backward_copy_shift push=8 pull=24 + +17: backward_copy_shift push=16 pull=16 + +18: backward_copy_shift push=24 pull=8 + +ENDPROC(memmove) diff --git a/src/arch/arm/memset.S b/src/arch/arm/memset.S new file mode 100644 index 0000000000..0c1102deb4 --- /dev/null +++ b/src/arch/arm/memset.S @@ -0,0 +1,121 @@ +/* + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ASM optimised string functions + */ + +#include +#include "asmlib.h" + +ENTRY(memset) + ands r3, r0, #3 @ 1 unaligned? + mov ip, r0 @ preserve r0 as return value + bne 6f @ 1 +/* + * we know that the pointer in ip is aligned to a word boundary. + */ +1: orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + mov r3, r1 + cmp r2, #16 + blt 4f + +#if ! CALGN(1)+0 + +/* + * We need 2 extra registers for this loop - use r8 and the LR + */ + stmfd sp!, {r8, lr} + mov r8, r1 + mov lr, r1 + +2: subs r2, r2, #64 + stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + bgt 2b + ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. +/* + * No need to correct the count; we're only testing bits from now on + */ + tst r2, #32 + stmneia ip!, {r1, r3, r8, lr} + stmneia ip!, {r1, r3, r8, lr} + tst r2, #16 + stmneia ip!, {r1, r3, r8, lr} + ldmfd sp!, {r8, lr} + +#else + +/* + * This version aligns the destination pointer in order to write + * whole cache lines at once. + */ + + stmfd sp!, {r4-r8, lr} + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov lr, r1 + + cmp r2, #96 + tstgt ip, #31 + ble 3f + + and r8, ip, #31 + rsb r8, r8, #32 + sub r2, r2, r8 + movs r8, r8, lsl #(32 - 4) + stmcsia ip!, {r4, r5, r6, r7} + stmmiia ip!, {r4, r5} + tst r8, #(1 << 30) + mov r8, r1 + strne r1, [ip], #4 + +3: subs r2, r2, #64 + stmgeia ip!, {r1, r3-r8, lr} + stmgeia ip!, {r1, r3-r8, lr} + bgt 3b + ldmeqfd sp!, {r4-r8, pc} + + tst r2, #32 + stmneia ip!, {r1, r3-r8, lr} + tst r2, #16 + stmneia ip!, {r4-r7} + ldmfd sp!, {r4-r8, lr} + +#endif + +4: tst r2, #8 + stmneia ip!, {r1, r3} + tst r2, #4 + strne r1, [ip], #4 +/* + * When we get here, we've got less than 4 bytes to zero. We + * may have an unaligned pointer as well. + */ +5: tst r2, #2 + strneb r1, [ip], #1 + strneb r1, [ip], #1 + tst r2, #1 + strneb r1, [ip], #1 + mov pc, lr + +6: subs r2, r2, #4 @ 1 do we have enough + blt 5b @ 1 bytes to align with? + cmp r3, #2 @ 1 + strltb r1, [ip], #1 @ 1 + strleb r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) + b 1b +ENDPROC(memset) diff --git a/src/arch/arm/stages.c b/src/arch/arm/stages.c new file mode 100644 index 0000000000..11acc9bd7b --- /dev/null +++ b/src/arch/arm/stages.c @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This file contains entry/exit functions for each stage during coreboot + * execution (bootblock entry and ramstage exit will depend on external + * loading). + * + * Entry points should be set in the linker script and honored by CBFS, + * so text section layout shouldn't matter. Still, it doesn't hurt to put + * stage_entry first (which XXXstage.ld will do automatically through the + * .text.stage_entry section created by -ffunction-sections). + */ + +#include +#include + +void stage_entry(void) +{ + main(); +} + +/* we had marked 'doit' as 'noreturn'. + * There is no apparent harm in leaving it as something we can return from, and in the one + * case where we call a payload, the payload is allowed to return. + * Hence, leave it as something we can return from. + */ +void stage_exit(void *addr) +{ + void (*doit)(void) = addr; + /* + * Most stages load code so we need to sync caches here. Should maybe + * go into cbfs_load_stage() instead... + */ + cache_sync_instructions(); + doit(); +} diff --git a/src/arch/armv7/boot/tables.c b/src/arch/arm/tables.c similarity index 96% rename from src/arch/armv7/boot/tables.c rename to src/arch/arm/tables.c index 0fc7399c13..825d7a2427 100644 --- a/src/arch/armv7/boot/tables.c +++ b/src/arch/arm/tables.c @@ -29,26 +29,26 @@ #define MAX_COREBOOT_TABLE_SIZE (8 * 1024) +#if ! CONFIG_DYNAMIC_CBMEM /* * TODO: "High" tables are a convention used on x86. Maybe we can * clean up that naming at some point. */ uint64_t high_tables_base = 0; uint64_t high_tables_size; - -void cbmem_arch_init(void) -{ -} +#endif struct lb_memory *write_tables(void) { unsigned long table_pointer, new_table_pointer; +#if ! CONFIG_DYNAMIC_CBMEM if (!high_tables_base) { printk(BIOS_ERR, "ERROR: high_tables_base is not set.\n"); } printk(BIOS_DEBUG, "high_tables_base: %llx.\n", high_tables_base); +#endif post_code(0x9d); diff --git a/src/arch/arm/timestamp.c b/src/arch/arm/timestamp.c new file mode 100644 index 0000000000..07a209c6cd --- /dev/null +++ b/src/arch/arm/timestamp.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include + +uint64_t timestamp_get(void) +{ + struct mono_time timestamp; + timer_monotonic_get(×tamp); + return (uint64_t)timestamp.microseconds; +} + diff --git a/src/arch/arm64/Kconfig b/src/arch/arm64/Kconfig new file mode 100644 index 0000000000..efd596954d --- /dev/null +++ b/src/arch/arm64/Kconfig @@ -0,0 +1,34 @@ +config ARCH_BOOTBLOCK_ARM64 + bool + default n + select ARCH_ARM64 + +config ARCH_VERSTAGE_ARM64 + bool + default n + +config ARCH_ROMSTAGE_ARM64 + bool + default n + +config ARCH_RAMSTAGE_ARM64 + bool + default n + +config ARCH_USE_SECURE_MONITOR + bool + select RELOCATABLE_MODULES + default n + +config ARCH_SPINTABLE + bool + default n + depends on ARCH_RAMSTAGE_ARM64 + +source src/arch/arm64/armv8/Kconfig + +# If a custom bootblock is necessary, this option should be "select"-ed by +# the thing that needs it, probably the CPU. +config ARM64_BOOTBLOCK_CUSTOM + bool + default n diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc new file mode 100644 index 0000000000..67c7d2668f --- /dev/null +++ b/src/arch/arm64/Makefile.inc @@ -0,0 +1,167 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## Copyright (C) 2012-2013 The ChromiumOS Authors +## Copyright (C) 2012 Alexandru Gagniuc +## Copyright (C) 2009-2010 coresystems GmbH +## Copyright (C) 2009 Ronald G. Minnich +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +################################################################################ +# Take care of subdirectories +################################################################################ + +subdirs-y += armv8/ + +################################################################################ +# ARM specific options +################################################################################ + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM64),y) +CBFSTOOL_PRE1_OPTS = -m arm64 -s $(CONFIG_CBFS_SIZE) +endif + +################################################################################ +# bootblock +################################################################################ + +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM64),y) + +bootblock-y += div0.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += early_console.c + +bootblock-y += id.S +bootblock-y += c_entry.c +bootblock-y += stage_entry.S +bootblock-y += stages.c +bootblock-y += eabi_compat.c +bootblock-y += transition.c transition_asm.S +bootblock-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +bootblock-y += ../../lib/memset.c +bootblock-y += ../../lib/memcpy.c +bootblock-y += ../../lib/memmove.c + +# Build the bootblock + +$(objcbfs)/bootblock.debug: $$(bootblock-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,bootblock,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld,--gc-sections) + +endif # CONFIG_ARCH_BOOTBLOCK_ARM64 + +############################################################################### +# verification stage +############################################################################### + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM64),y) + +$(objcbfs)/verstage.debug: $$(verstage-objs) $$(VB2_LIB) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,verstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.verstage.ld,--gc-sections) + +verstage-$(CONFIG_EARLY_CONSOLE) += early_console.c +verstage-y += div0.c +verstage-y += eabi_compat.c +verstage-y += ../../lib/memset.c +verstage-y += ../../lib/memcpy.c +verstage-y += ../../lib/memmove.c +verstage-y += stages.c +verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +endif # CONFIG_ARCH_VERSTAGE_ARM64 + +################################################################################ +# romstage +################################################################################ + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM64),y) + +romstage-y += c_entry.c +romstage-y += stage_entry.S +romstage-y += stages.c +romstage-y += div0.c +romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c +romstage-y += eabi_compat.c +romstage-y += ../../lib/memset.c +romstage-y += ../../lib/memcpy.c +romstage-y += ../../lib/memmove.c +romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +romstage-y += transition.c transition_asm.S + +rmodules_arm64-y += ../../lib/memset.c +rmodules_arm64-y += ../../lib/memcpy.c +rmodules_arm64-y += ../../lib/memmove.c +rmodules_arm64-y += eabi_compat.c + +VBOOT_STUB_DEPS += $(obj)/arch/arm64/eabi_compat.rmodules_arm64.o + +# Build the romstage + +$(objcbfs)/romstage.debug: $$(romstage-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,romstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld,--gc-sections) + +endif # CONFIG_ARCH_ROMSTAGE_ARM64 + +################################################################################ +# ramstage +################################################################################ + +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM64),y) + +ramstage-y += c_entry.c +ramstage-y += stages.c +ramstage-y += startup.c +ramstage-y += div0.c +ramstage-y += cpu.c +ramstage-y += cpu_ramstage.c +ramstage-y += eabi_compat.c +ramstage-y += boot.c +ramstage-y += tables.c +ramstage-y += ../../lib/memset.c +ramstage-y += ../../lib/memcpy.c +ramstage-y += ../../lib/memmove.c +ramstage-y += stage_entry.S +ramstage-$(CONFIG_ARCH_SPINTABLE) += spintable.c spintable_asm.S +ramstage-y += transition.c transition_asm.S + +rmodules_arm64-y += ../../lib/memset.c +rmodules_arm64-y += ../../lib/memcpy.c +rmodules_arm64-y += ../../lib/memmove.c +rmodules_arm64-y += eabi_compat.c + +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += stage_entry.S +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += startup.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/malloc.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memset.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcmp.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcpy.c + +ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/mainboard.c + +# Build the ramstage + +$(objcbfs)/ramstage.debug: $$(ramstage-objs) + @printf " CC $(subst $(obj)/,,$(@))\n" + $(call link,ramstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld,--gc-sections) + +endif # CONFIG_ARCH_RAMSTAGE_ARM64 diff --git a/src/arch/arm64/armv8/Kconfig b/src/arch/arm64/armv8/Kconfig new file mode 100644 index 0000000000..5840e818ce --- /dev/null +++ b/src/arch/arm64/armv8/Kconfig @@ -0,0 +1,12 @@ +config ARCH_BOOTBLOCK_ARM_V8_64 + def_bool n + select ARCH_BOOTBLOCK_ARM64 +config ARCH_VERSTAGE_ARM_V8_64 + def_bool n + select ARCH_VERSTAGE_ARM64 +config ARCH_ROMSTAGE_ARM_V8_64 + def_bool n + select ARCH_ROMSTAGE_ARM64 +config ARCH_RAMSTAGE_ARM_V8_64 + def_bool n + select ARCH_RAMSTAGE_ARM64 diff --git a/src/arch/arm64/armv8/Makefile.inc b/src/arch/arm64/armv8/Makefile.inc new file mode 100644 index 0000000000..a9adbeb825 --- /dev/null +++ b/src/arch/arm64/armv8/Makefile.inc @@ -0,0 +1,97 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +subdirs-y += lib/ + +subdirs-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon/ + +armv8_flags = -march=armv8-a -I$(src)/arch/arm64/include/armv8/ -D__COREBOOT_ARM_ARCH__=8 + +armv8_asm_flags = $(armv8_flags) + +################################################################################ +## bootblock +################################################################################ +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM_V8_64),y) + +ifneq ($(CONFIG_ARM64_BOOTBLOCK_CUSTOM),y) +bootblock-y += bootblock.S +bootblock-y += bootblock_simple.c +endif +bootblock-y += cache.c +bootblock-y += cpu.S +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += exception.c + +bootblock-c-ccopts += $(armv8_flags) +bootblock-S-ccopts += $(armv8_asm_flags) + +endif + +################################################################################ +## verstage +################################################################################ +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM_V8_64),y) + +verstage-y += cache.c +verstage-y += cpu.S +verstage-y += exception.c + +verstage-c-ccopts += $(armv8_flags) +verstage-S-ccopts += $(armv8_asm_flags) + +endif + +################################################################################ +## romstage +################################################################################ +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM_V8_64),y) + +romstage-y += cache.c +romstage-y += cpu.S +romstage-y += exception.c + +romstage-c-ccopts += $(armv8_flags) +romstage-S-ccopts += $(armv8_asm_flags) + +rmodules_arm64-c-ccopts += $(armv8_flags) +rmodules_arm64-S-ccopts += $(armv8_asm_flags) + +endif + +################################################################################ +## ramstage +################################################################################ +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM_V8_64),y) + +ramstage-y += cache.c +ramstage-y += cpu.S +ramstage-y += exception.c +ramstage-y += mmu.c + +ramstage-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon_loader.c + +ramstage-c-ccopts += $(armv8_flags) +ramstage-S-ccopts += $(armv8_asm_flags) + +rmodules_arm64-c-ccopts += $(armv8_flags) +rmodules_arm64-S-ccopts += $(armv8_asm_flags) + +endif diff --git a/src/arch/arm64/armv8/bootblock.S b/src/arch/arm64/armv8/bootblock.S new file mode 100644 index 0000000000..ef7064580f --- /dev/null +++ b/src/arch/arm64/armv8/bootblock.S @@ -0,0 +1,39 @@ +/* + * Early initialization code for aarch64 (a.k.a. armv8) + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + .section ".id", "a", %progbits + + .globl __id_start +__id_start: +ver: + .asciz COREBOOT_VERSION +vendor: + .asciz CONFIG_MAINBOARD_VENDOR +part: + .asciz CONFIG_MAINBOARD_PART_NUMBER +.long __id_end - ver /* Reverse offset to the vendor id */ +.long __id_end - vendor /* Reverse offset to the vendor id */ +.long __id_end - part /* Reverse offset to the part number */ +.long CONFIG_ROM_SIZE /* Size of this romimage */ + .globl __id_end + +__id_end: +.previous diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/arm64/armv8/bootblock_simple.c similarity index 74% rename from src/arch/armv7/bootblock_simple.c rename to src/arch/arm64/armv8/bootblock_simple.c index f6134f75fb..d8339d1f76 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/arm64/armv8/bootblock_simple.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2010 Google Inc + * Copyright 2014 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,11 +23,10 @@ #include #include #include +#include #include #include -#include "stages.c" - static int boot_cpu(void) { /* @@ -40,17 +39,12 @@ static int boot_cpu(void) void main(void) { - const char *stage_name = "fallback/romstage"; - void *entry; - uint32_t sctlr; + const char *stage_name = CONFIG_CBFS_PREFIX"/romstage"; + void *entry = NULL; /* Globally disable MMU, caches, and branch prediction (these should * be disabled by default on reset) */ - sctlr = read_sctlr(); - sctlr &= ~(SCTLR_M | SCTLR_C | SCTLR_Z | SCTLR_I); - write_sctlr(sctlr); - - armv7_invalidate_caches(); + dcache_mmu_disable(); /* * Re-enable icache and branch prediction. MMU and dcache will be @@ -59,21 +53,21 @@ void main(void) * Note: If booting from USB, we need to disable branch prediction * before copying from USB into RAM (FIXME: why?) */ - sctlr = read_sctlr(); - sctlr |= SCTLR_Z | SCTLR_I; - write_sctlr(sctlr); if (boot_cpu()) { - bootblock_cpu_init(); - bootblock_mainboard_init(); + //bootblock_cpu_init(); + //bootblock_mainboard_init(); } +#ifdef CONFIG_BOOTBLOCK_CONSOLE console_init(); - printk(BIOS_INFO, "hello from bootblock\n"); - printk(BIOS_INFO, "bootblock main(): loading romstage\n"); + exception_init(); +#endif + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, stage_name); - printk(BIOS_INFO, "bootblock main(): jumping to romstage\n"); + printk(BIOS_SPEW, "stage_name %s, entry %p\n", stage_name, entry); + if (entry) stage_exit(entry); hlt(); } diff --git a/src/arch/arm64/armv8/cache.c b/src/arch/arm64/armv8/cache.c new file mode 100644 index 0000000000..c1dba9259a --- /dev/null +++ b/src/arch/arm64/armv8/cache.c @@ -0,0 +1,150 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache maintenance routines for ARMv8 (aarch64) + * + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include +#include + +void tlb_invalidate_all(void) +{ + /* TLBIALL includes dTLB and iTLB on systems that have them. */ + tlbiall_current(); + dsb(); + isb(); +} + +unsigned int dcache_line_bytes(void) +{ + uint32_t ctr_el0; + static unsigned int line_bytes = 0; + + if (line_bytes) + return line_bytes; + + ctr_el0 = raw_read_ctr_el0(); + /* [19:16] - Indicates (Log2(number of words in cache line) */ + line_bytes = 1 << ((ctr_el0 >> 16) & 0xf); + /* Bytes in a word (32-bit) */ + line_bytes *= sizeof(uint32_t); + + return line_bytes; +} + +enum dcache_op { + OP_DCCSW, + OP_DCCISW, + OP_DCISW, + OP_DCCIVAC, + OP_DCCVAC, + OP_DCIVAC, +}; + +/* + * Do a dcache operation by virtual address. This is useful for maintaining + * coherency in drivers which do DMA transfers and only need to perform + * cache maintenance on a particular memory range rather than the entire cache. + */ +static void dcache_op_va(void const *addr, size_t len, enum dcache_op op) +{ + uint64_t line, linesize; + + linesize = dcache_line_bytes(); + line = (uint64_t)addr & ~(linesize - 1); + + dsb(); + while ((void *)line < addr + len) { + switch(op) { + case OP_DCCIVAC: + dccivac(line); + break; + case OP_DCCVAC: + dccvac(line); + break; + case OP_DCIVAC: + dcivac(line); + break; + default: + break; + } + line += linesize; + } + isb(); +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCCVAC); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCCIVAC); +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + dcache_op_va(addr, len, OP_DCIVAC); +} + +/* + * CAUTION: This implementation assumes that coreboot never uses non-identity + * page tables for pages containing executed code. If you ever want to violate + * this assumption, have fun figuring out the associated problems on your own. + */ +void dcache_mmu_disable(void) +{ + uint32_t sctlr; + + flush_dcache_all(); + sctlr = raw_read_sctlr_current(); + sctlr &= ~(SCTLR_C | SCTLR_M); + raw_write_sctlr_current(sctlr); +} + +void dcache_mmu_enable(void) +{ + uint32_t sctlr; + + sctlr = raw_read_sctlr_current(); + sctlr |= SCTLR_C | SCTLR_M; + raw_write_sctlr_current(sctlr); +} + +void cache_sync_instructions(void) +{ + flush_dcache_all(); /* includes trailing DSB (in assembly) */ + iciallu(); /* includes BPIALLU (architecturally) */ + dsb(); + isb(); +} diff --git a/src/arch/arm64/armv8/cpu.S b/src/arch/arm64/armv8/cpu.S new file mode 100644 index 0000000000..1eecc2b0d7 --- /dev/null +++ b/src/arch/arm64/armv8/cpu.S @@ -0,0 +1,131 @@ +/* + * Based on arch/arm/include/asm/cacheflush.h + * + * Copyright (C) 1999-2002 Russell King. + * Copyright (C) 2012 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +/* + * flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: x0-x7, x9-x11 + * From: Linux arch/arm64/mm/cache.S + */ +ENTRY(flush_dcache_all) + dsb sy // ensure ordering with previous memory accesses + mrs x0, clidr_el1 // read clidr + and x3, x0, #0x7000000 // extract loc from clidr + lsr x3, x3, #23 // left align loc bit field + cbz x3, finished // if loc is 0, then no need to clean + mov x10, #0 // start clean at cache level 0 +loop1: + add x2, x10, x10, lsr #1 // work out 3x current cache level + lsr x1, x0, x2 // extract cache type bits from clidr + and x1, x1, #7 // mask of the bits for current cache only + cmp x1, #2 // see what cache we have at this level + b.lt skip // skip if no cache, or just i-cache + mrs x9, daif // make CSSELR and CCSIDR access atomic + msr csselr_el1, x10 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + mrs x1, ccsidr_el1 // read the new ccsidr + msr daif, x9 + and x2, x1, #7 // extract the length of the cache lines + add x2, x2, #4 // add 4 (line length offset) + mov x4, #0x3ff + and x4, x4, x1, lsr #3 // find maximum number on the way size + clz x5, x4 // find bit position of way size increment + mov x7, #0x7fff + and x7, x7, x1, lsr #13 // extract max number of the index size +loop2: + mov x9, x4 // create working copy of max way size +loop3: + lsl x6, x9, x5 + orr x11, x10, x6 // factor way and cache number into x11 + lsl x6, x7, x2 + orr x11, x11, x6 // factor index number into x11 + dc cisw, x11 // clean & invalidate by set/way + subs x9, x9, #1 // decrement the way + b.ge loop3 + subs x7, x7, #1 // decrement the index + b.ge loop2 +skip: + add x10, x10, #2 // increment cache number + cmp x3, x10 + b.gt loop1 +finished: + mov x10, #0 // swith back to cache level 0 + msr csselr_el1, x10 // select current cache level in csselr + dsb sy + isb + ret +ENDPROC(flush_dcache_all) + +/* + * Bring an ARMv8 processor we just gained control of (e.g. from IROM) into a + * known state regarding caches/SCTLR. Completely cleans and invalidates + * icache/dcache, disables MMU and dcache (if active), and enables unaligned + * accesses, icache and branch prediction (if inactive). Clobbers x4 and x5. + */ +ENTRY(arm_init_caches) + /* w4: SCTLR, return address: x8 (stay valid for the whole function) */ + mov x8, x30 + /* XXX: Assume that we always start running at EL3 */ + mrs x4, sctlr_el3 + + /* FIXME: How to enable branch prediction on ARMv8? */ + + /* Flush and invalidate dcache */ + bl flush_dcache_all + + /* Deactivate MMU (0), Alignment Check (1) and DCache (2) */ + and x4, x4, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2) + /* Activate ICache (12) already for speed */ + orr x4, x4, #(1 << 12) + msr sctlr_el3, x4 + + /* Invalidate icache and TLB for good measure */ + ic iallu + tlbi alle3 + dsb sy + isb + + ret x8 +ENDPROC(arm_init_caches) + +/* Based on u-boot transition.S */ +ENTRY(switch_el3_to_el2) + mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */ + msr scr_el3, x0 + msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ + mov x0, #0x33ff + msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ + + /* Return to the EL2_SP2 mode from EL3 */ + mov x0, sp + msr sp_el2, x0 /* Migrate SP */ + mrs x0, vbar_el3 + msr vbar_el2, x0 /* Migrate VBAR */ + mrs x0, sctlr_el3 + msr sctlr_el2, x0 /* Migrate SCTLR */ + mov x0, #0x3c9 + msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */ + msr elr_el3, x30 + eret +ENDPROC(switch_el3_to_el2) diff --git a/src/arch/arm64/armv8/exception.c b/src/arch/arm64/armv8/exception.c new file mode 100644 index 0000000000..a633e3afb8 --- /dev/null +++ b/src/arch/arm64/armv8/exception.c @@ -0,0 +1,210 @@ +/* + * This file is part of the libpayload project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *exception_names[NUM_EXC_VIDS] = { + [EXC_VID_CUR_SP_EL0_SYNC] = "_sync_sp_el0", + [EXC_VID_CUR_SP_EL0_IRQ] = "_irq_sp_el0", + [EXC_VID_CUR_SP_EL0_FIRQ] = "_fiq_sp_el0", + [EXC_VID_CUR_SP_EL0_SERR] = "_serror_sp_el0", + [EXC_VID_CUR_SP_ELX_SYNC] = "_sync_sp_el3", + [EXC_VID_CUR_SP_ELX_IRQ] = "_irq_sp_el3", + [EXC_VID_CUR_SP_ELX_FIQ] = "_fiq_sp_el3", + [EXC_VID_CUR_SP_ELX_SERR] = "_serror_sp_el3", + [EXC_VID_LOW64_SYNC] = "_sync_elx_64", + [EXC_VID_LOW64_IRQ] = "_irq_elx_64", + [EXC_VID_LOW64_FIQ] = "_fiq_elx_64", + [EXC_VID_LOW64_SERR] = "_serror_elx_64", + [EXC_VID_LOW32_SYNC] = "_sync_elx_32", + [EXC_VID_LOW32_IRQ] = "_irq_elx_32", + [EXC_VID_LOW32_FIQ] = "_fiq_elx_32", + [EXC_VID_LOW32_SERR] = "_serror_elx_32" +}; + +static void print_regs(struct exc_state *exc_state) +{ + int i; + struct elx_state *elx = &exc_state->elx; + struct regs *regs = &exc_state->regs; + + uint64_t elx_esr = raw_read_esr_current(); + uint64_t elx_far = raw_read_far_current(); + + printk(BIOS_DEBUG, "ELR = 0x%016llx\n", elx->elr); + printk(BIOS_DEBUG, "ESR = 0x%016llx\n", elx_esr); + printk(BIOS_DEBUG, "SPSR = 0x%08llx\n", elx->spsr); + printk(BIOS_DEBUG, "FAR = 0x%016llx\n", elx_far); + for (i = X0_INDEX; i < XMAX_INDEX; i++) + printk(BIOS_DEBUG, "X%02d = 0x%016llx\n", i, regs->x[i]); +} + + +static struct exception_handler *handlers[NUM_EXC_VIDS]; + + +int exception_handler_register(uint64_t vid, struct exception_handler *h) +{ + if (vid >= NUM_EXC_VIDS) + return -1; + + /* Just place at head of queue. */ + h->next = handlers[vid]; + store_release(&handlers[vid], h); + + return 0; +} + +int exception_handler_unregister(uint64_t vid, struct exception_handler *h) +{ + struct exception_handler *cur; + struct exception_handler **prev; + + if (vid >= NUM_EXC_VIDS) + return -1; + + prev = &handlers[vid]; + + for (cur = handlers[vid]; cur != NULL; cur = cur->next) { + if (cur != h) + continue; + /* Update previous pointer. */ + store_release(prev, cur->next); + return 0; + } + + /* Not found */ + return -1; +} + +static void print_exception_info(struct exc_state *state, uint64_t idx) +{ + if (idx < NUM_EXC_VIDS) + printk(BIOS_DEBUG, "exception %s\n", exception_names[idx]); + + print_regs(state); +} + +static void print_exception_and_die(struct exc_state *state, uint64_t idx) +{ + print_exception_info(state, idx); + die("exception death"); +} + + +static int handle_exception(struct exc_state *state, uint64_t idx) +{ + int ret = EXC_RET_ABORT; + + struct exception_handler *h; + + for (h = handlers[idx]; h != NULL; h = h->next) { + int hret; + + hret = h->handler(state, idx); + + if (hret > ret) + ret = hret; + } + + return ret; +} + +void exc_dispatch(struct exc_state *state, uint64_t idx) +{ + int ret; + + if (idx >= NUM_EXC_VIDS) { + printk(BIOS_DEBUG, "Bad exception index %x.\n", (int)idx); + print_exception_and_die(state, idx); + } + + ret = handle_exception(state, idx); + + if (ret == EXC_RET_ABORT) + print_exception_and_die(state, idx); + + if (ret == EXC_RET_IGNORED || ret == EXC_RET_HANDLED_DUMP_STATE) + print_exception_info(state, idx); + + exc_exit(&state->regs); +} + + +static int test_exception_handler(struct exc_state *state, uint64_t vector_id) +{ + /* Update instruction pointer to next instrution. */ + state->elx.elr += sizeof(uint32_t); + raw_write_elr_current(state->elx.elr); + return EXC_RET_HANDLED; +} + +static uint64_t test_exception(void) +{ + struct exception_handler sync_elx; + struct exception_handler sync_el0; + unsigned long long *a = (void *)0xffffffff00000000ULL; + + sync_elx.handler = &test_exception_handler; + sync_el0.handler = &test_exception_handler; + + exception_handler_register(EXC_VID_CUR_SP_ELX_SYNC, &sync_elx); + exception_handler_register(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0); + + force_read(*a); + + exception_handler_unregister(EXC_VID_CUR_SP_ELX_SYNC, &sync_elx); + exception_handler_unregister(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0); + + return 0; +} + +void exception_hwinit(void) +{ + exc_set_vbar(); +} + +void exception_init(void) +{ + /* Load the exception table. */ + exception_hwinit(); + + printk(BIOS_DEBUG, "ARM64: Exception handlers installed.\n"); + + printk(BIOS_DEBUG, "ARM64: Testing exception\n"); + test_exception(); + printk(BIOS_DEBUG, "ARM64: Done test exception\n"); +} diff --git a/src/arch/arm64/armv8/lib/Makefile.inc b/src/arch/arm64/armv8/lib/Makefile.inc new file mode 100644 index 0000000000..8a22391eb0 --- /dev/null +++ b/src/arch/arm64/armv8/lib/Makefile.inc @@ -0,0 +1,52 @@ +##################################################################################### +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. The name of the author may not be used to endorse or promote products +## derived from this software without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## +##################################################################################### + +lib_access = pstate.c sysctrl.c cache.c tlb.c clock.c + +ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARM_V8_64),y) +bootblock-y += $(lib_access) +endif + +ifeq ($(CONFIG_ARCH_VERSTAGE_ARM_V8_64),y) +verstage-y += $(lib_access) +endif + +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM_V8_64),y) +romstage-y += $(lib_access) +endif + +ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM_V8_64),y) +ramstage-y += $(lib_access) + +ifeq ($(CONFIG_ARCH_USE_SECURE_MONITOR),y) +secmon-y += $(lib_access) +endif + +endif diff --git a/src/arch/arm64/armv8/lib/cache.c b/src/arch/arm64/armv8/lib/cache.c new file mode 100644 index 0000000000..53dff5759e --- /dev/null +++ b/src/arch/arm64/armv8/lib/cache.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.c: Cache Maintenance Instructions + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include + +void dccisw(uint64_t cisw) +{ + __asm__ __volatile__("dc cisw, %0\n\t" : : "r" (cisw) :"memory"); +} + +void dccivac(uint64_t civac) +{ + __asm__ __volatile__("dc civac, %0\n\t" : : "r" (civac) :"memory"); +} + +void dccsw(uint64_t csw) +{ + __asm__ __volatile__("dc csw, %0\n\t" : : "r" (csw) :"memory"); +} + +void dccvac(uint64_t cvac) +{ + __asm__ __volatile__("dc cvac, %0\n\t" : : "r" (cvac) :"memory"); +} + +void dccvau(uint64_t cvau) +{ + __asm__ __volatile__("dc cvau, %0\n\t" : : "r" (cvau) :"memory"); +} + +void dcisw(uint64_t isw) +{ + __asm__ __volatile__("dc isw, %0\n\t" : : "r" (isw) :"memory"); +} + +void dcivac(uint64_t ivac) +{ + __asm__ __volatile__("dc ivac, %0\n\t" : : "r" (ivac) :"memory"); +} + +void dczva(uint64_t zva) +{ + __asm__ __volatile__("dc zva, %0\n\t" : : "r" (zva) :"memory"); +} + +void iciallu(void) +{ + __asm__ __volatile__("ic iallu\n\t" : : :"memory"); +} + +void icialluis(void) +{ + __asm__ __volatile__("ic ialluis\n\t" : : :"memory"); +} + +void icivau(uint64_t ivau) +{ + __asm__ __volatile__("ic ivau, %0\n\t" : : "r" (ivau) :"memory"); +} + + + diff --git a/src/arch/arm64/armv8/lib/clock.c b/src/arch/arm64/armv8/lib/clock.c new file mode 100644 index 0000000000..fddd2ad43d --- /dev/null +++ b/src/arch/arm64/armv8/lib/clock.c @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * clock.c: Functions for accessing clock and timer related registers + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include + +#include + +void set_cntfrq(uint32_t freq) +{ + __asm__ __volatile__("msr cntfrq_el0, %0" :: "r"(freq)); +} diff --git a/src/arch/arm64/armv8/lib/pstate.c b/src/arch/arm64/armv8/lib/pstate.c new file mode 100644 index 0000000000..6258a199d1 --- /dev/null +++ b/src/arch/arm64/armv8/lib/pstate.c @@ -0,0 +1,466 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + * pstate.c: This file defines all the library functions for accessing + * PSTATE and special purpose registers + */ + +#include + +#include + +/* CurrentEL */ +uint32_t raw_read_current_el(void) +{ + uint32_t current_el; + + __asm__ __volatile__("mrs %0, CurrentEL\n\t" : "=r" (current_el) : : "memory"); + + return current_el; +} + +uint32_t get_current_el(void) +{ + uint32_t current_el = raw_read_current_el(); + return ((current_el >> CURRENT_EL_SHIFT) & CURRENT_EL_MASK); +} + +/* DAIF */ +uint32_t raw_read_daif(void) +{ + uint32_t daif; + + __asm__ __volatile__("mrs %0, DAIF\n\t" : "=r" (daif) : : "memory"); + + return daif; +} + +void raw_write_daif(uint32_t daif) +{ + __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); +} + +void enable_debug_exceptions(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_DBG_BIT) : "memory"); +} + +void enable_serror_exceptions(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_ABT_BIT) : "memory"); +} + +void enable_irq(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_IRQ_BIT) : "memory"); +} + +void enable_fiq(void) +{ + __asm__ __volatile__("msr DAIFClr, %0\n\t" : : "i" (DAIF_FIQ_BIT) : "memory"); +} + +void disable_debug_exceptions(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_DBG_BIT) : "memory"); +} + +void disable_serror_exceptions(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_ABT_BIT) : "memory"); +} + +void disable_irq(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_IRQ_BIT) : "memory"); +} + +void disable_fiq(void) +{ + __asm__ __volatile__("msr DAIFSet, %0\n\t" : : "i" (DAIF_FIQ_BIT) : "memory"); +} + +/* DLR_EL0 */ +uint64_t raw_read_dlr_el0(void) +{ + uint64_t dlr_el0; + + __asm__ __volatile__("mrs %0, DLR_EL0\n\t" : "=r" (dlr_el0) : : "memory"); + + return dlr_el0; +} +void raw_write_dlr_el0(uint64_t dlr_el0) +{ + __asm__ __volatile__("msr DLR_EL0, %0\n\t" : : "r" (dlr_el0) : "memory"); +} + +/* DSPSR_EL0 */ +uint64_t raw_read_dspsr_el0(void) +{ + uint64_t dspsr_el0; + + __asm__ __volatile__("mrs %0, DSPSR_EL0\n\t" : "=r" (dspsr_el0) : : "memory"); + + return dspsr_el0; +} +void raw_write_dspsr_el0(uint64_t dspsr_el0) +{ + __asm__ __volatile__("msr DSPSR_EL0, %0\n\t" : : "r" (dspsr_el0) : "memory"); +} + +/* ELR */ +uint64_t raw_read_elr_el1(void) +{ + uint64_t elr_el1; + + __asm__ __volatile__("mrs %0, ELR_EL1\n\t" : "=r" (elr_el1) : : "memory"); + + return elr_el1; +} + +void raw_write_elr_el1(uint64_t elr_el1) +{ + __asm__ __volatile__("msr ELR_EL1, %0\n\t" : : "r" (elr_el1) : "memory"); +} + +uint64_t raw_read_elr_el2(void) +{ + uint64_t elr_el2; + + __asm__ __volatile__("mrs %0, ELR_EL2\n\t" : "=r" (elr_el2) : : "memory"); + + return elr_el2; +} + +void raw_write_elr_el2(uint64_t elr_el2) +{ + __asm__ __volatile__("msr ELR_EL2, %0\n\t" : : "r" (elr_el2) : "memory"); +} + +uint64_t raw_read_elr_el3(void) +{ + uint64_t elr_el3; + + __asm__ __volatile__("mrs %0, ELR_EL3\n\t" : "=r" (elr_el3) : : "memory"); + + return elr_el3; +} + +void raw_write_elr_el3(uint64_t elr_el3) +{ + __asm__ __volatile__("msr ELR_EL3, %0\n\t" : : "r" (elr_el3) : "memory"); +} + +uint64_t raw_read_elr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_elr(el); +} + +void raw_write_elr_current(uint64_t elr) +{ + uint32_t el = get_current_el(); + raw_write_elr(elr, el); +} + +uint64_t raw_read_elr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_elr, elr, uint64_t, el); +} + +void raw_write_elr(uint64_t elr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_elr, elr, el); +} + +/* FPCR */ +uint32_t raw_read_fpcr(void) +{ + uint32_t fpcr; + + __asm__ __volatile__("mrs %0, FPCR\n\t" : "=r" (fpcr) : : "memory"); + + return fpcr; +} + +void raw_write_fpcr(uint32_t fpcr) +{ + __asm__ __volatile__("msr FPCR, %0\n\t" : : "r" (fpcr) : "memory"); +} + +/* FPSR */ +uint32_t raw_read_fpsr(void) +{ + uint32_t fpsr; + + __asm__ __volatile__("mrs %0, FPSR\n\t" : "=r" (fpsr) : : "memory"); + + return fpsr; +} + +void raw_write_fpsr(uint32_t fpsr) +{ + __asm__ __volatile__("msr FPSR, %0\n\t" : : "r" (fpsr) : "memory"); +} + +/* NZCV */ +uint32_t raw_read_nzcv(void) +{ + uint32_t nzcv; + + __asm__ __volatile__("mrs %0, NZCV\n\t" : "=r" (nzcv) : : "memory"); + + return nzcv; +} + +void raw_write_nzcv(uint32_t nzcv) +{ + __asm__ __volatile__("msr NZCV, %0\n\t" : : "r" (nzcv) : "memory"); +} + +/* SP */ +uint64_t raw_read_sp_el0(void) +{ + uint64_t sp_el0; + + __asm__ __volatile__("mrs %0, SP_EL0\n\t" : "=r" (sp_el0) : : "memory"); + + return sp_el0; +} + +void raw_write_sp_el0(uint64_t sp_el0) +{ + __asm__ __volatile__("msr SP_EL0, %0\n\t" : : "r" (sp_el0) : "memory"); +} + +uint64_t raw_read_sp_el1(void) +{ + uint64_t sp_el1; + + __asm__ __volatile__("mrs %0, SP_EL1\n\t" : "=r" (sp_el1) : : "memory"); + + return sp_el1; +} + +void raw_write_sp_el1(uint64_t sp_el1) +{ + __asm__ __volatile__("msr SP_EL1, %0\n\t" : : "r" (sp_el1) : "memory"); +} + +uint64_t raw_read_sp_el2(void) +{ + uint64_t sp_el2; + + __asm__ __volatile__("mrs %0, SP_EL2\n\t" : "=r" (sp_el2) : : "memory"); + + return sp_el2; +} + +void raw_write_sp_el2(uint64_t sp_el2) +{ + __asm__ __volatile__("msr SP_EL2, %0\n\t" : : "r" (sp_el2) : "memory"); +} + +/* SPSel */ +uint32_t raw_read_spsel(void) +{ + uint32_t spsel; + + __asm__ __volatile__("mrs %0, SPSel\n\t" : "=r" (spsel) : : "memory"); + + return spsel; +} + +void raw_write_spsel(uint32_t spsel) +{ + __asm__ __volatile__("msr SPSel, %0\n\t" : : "r" (spsel) : "memory"); +} + +uint64_t raw_read_sp_el3(void) +{ + uint64_t sp_el3; + uint32_t spsel; + + spsel = raw_read_spsel(); + if (!spsel) + raw_write_spsel(1); + + __asm__ __volatile__("mov %0, sp\n\t" : "=r" (sp_el3) : : "memory"); + + if (!spsel) + raw_write_spsel(spsel); + + return sp_el3; +} + +void raw_write_sp_el3(uint64_t sp_el3) +{ + uint32_t spsel; + + spsel = raw_read_spsel(); + if (!spsel) + raw_write_spsel(1); + + __asm__ __volatile__("mov sp, %0\n\t" : "=r" (sp_el3) : : "memory"); + + if (!spsel) + raw_write_spsel(spsel); +} + +uint64_t raw_read_sp_elx(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_sp, sp, uint64_t, el); +} + +void raw_write_sp_elx(uint64_t sp_elx, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_sp, sp_elx, el); +} + +/* SPSR */ +uint32_t raw_read_spsr_abt(void) +{ + uint32_t spsr_abt; + + __asm__ __volatile__("mrs %0, SPSR_abt\n\t" : "=r" (spsr_abt) : : "memory"); + + return spsr_abt; +} + +void raw_write_spsr_abt(uint32_t spsr_abt) +{ + __asm__ __volatile__("msr SPSR_abt, %0\n\t" : : "r" (spsr_abt) : "memory"); +} + +uint32_t raw_read_spsr_el1(void) +{ + uint32_t spsr_el1; + + __asm__ __volatile__("mrs %0, SPSR_EL1\n\t" : "=r" (spsr_el1) : : "memory"); + + return spsr_el1; +} + +void raw_write_spsr_el1(uint32_t spsr_el1) +{ + __asm__ __volatile__("msr SPSR_EL1, %0\n\t" : : "r" (spsr_el1) : "memory"); +} + +uint32_t raw_read_spsr_el2(void) +{ + uint32_t spsr_el2; + + __asm__ __volatile__("mrs %0, SPSR_EL2\n\t" : "=r" (spsr_el2) : : "memory"); + + return spsr_el2; +} + +void raw_write_spsr_el2(uint32_t spsr_el2) +{ + __asm__ __volatile__("msr SPSR_EL2, %0\n\t" : : "r" (spsr_el2) : "memory"); +} + +uint32_t raw_read_spsr_el3(void) +{ + uint32_t spsr_el3; + + __asm__ __volatile__("mrs %0, SPSR_EL3\n\t" : "=r" (spsr_el3) : : "memory"); + + return spsr_el3; +} + +void raw_write_spsr_el3(uint32_t spsr_el3) +{ + __asm__ __volatile__("msr SPSR_EL3, %0\n\t" : : "r" (spsr_el3) : "memory"); +} + +uint32_t raw_read_spsr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_spsr(el); +} + +void raw_write_spsr_current(uint32_t spsr) +{ + uint32_t el = get_current_el(); + raw_write_spsr(spsr, el); +} + +uint32_t raw_read_spsr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_spsr, spsr, uint32_t, el); +} + +void raw_write_spsr(uint32_t spsr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_spsr, spsr, el); +} + +uint32_t raw_read_spsr_fiq(void) +{ + uint32_t spsr_fiq; + + __asm__ __volatile__("mrs %0, SPSR_fiq\n\t" : "=r" (spsr_fiq) : : "memory"); + + return spsr_fiq; +} + +void raw_write_spsr_fiq(uint32_t spsr_fiq) +{ + __asm__ __volatile__("msr SPSR_fiq, %0\n\t" : : "r" (spsr_fiq) : "memory"); +} + +uint32_t raw_read_spsr_irq(void) +{ + uint32_t spsr_irq; + + __asm__ __volatile__("mrs %0, SPSR_irq\n\t" : "=r" (spsr_irq) : : "memory"); + + return spsr_irq; +} + +void raw_write_spsr_irq(uint32_t spsr_irq) +{ + __asm__ __volatile__("msr SPSR_irq, %0\n\t" : : "r" (spsr_irq) : "memory"); +} + +uint32_t raw_read_spsr_und(void) +{ + uint32_t spsr_und; + + __asm__ __volatile__("mrs %0, SPSR_und\n\t" : "=r" (spsr_und) : : "memory"); + + return spsr_und; +} + +void raw_write_spsr_und(uint32_t spsr_und) +{ + __asm__ __volatile__("msr SPSR_und, %0\n\t" : : "r" (spsr_und) : "memory"); +} + diff --git a/src/arch/arm64/armv8/lib/sysctrl.c b/src/arch/arm64/armv8/lib/sysctrl.c new file mode 100644 index 0000000000..b07a64f222 --- /dev/null +++ b/src/arch/arm64/armv8/lib/sysctrl.c @@ -0,0 +1,1061 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + * sysctrl.c: This file defines all the library functions for accessing system + * control registers in Aarch64 + */ + +#include + +#include + +/* ACTLR */ +uint32_t raw_read_actlr_el1(void) +{ + uint32_t actlr_el1; + + __asm__ __volatile__("mrs %0, ACTLR_EL1\n\t" : "=r" (actlr_el1) : : "memory"); + + return actlr_el1; +} + +void raw_write_actlr_el1(uint32_t actlr_el1) +{ + __asm__ __volatile__("msr ACTLR_EL1, %0\n\t" : : "r" (actlr_el1) : "memory"); +} + +uint32_t raw_read_actlr_el2(void) +{ + uint32_t actlr_el2; + + __asm__ __volatile__("mrs %0, ACTLR_EL2\n\t" : "=r" (actlr_el2) : : "memory"); + + return actlr_el2; +} + +void raw_write_actlr_el2(uint32_t actlr_el2) +{ + __asm__ __volatile__("msr ACTLR_EL2, %0\n\t" : : "r" (actlr_el2) : "memory"); +} + +uint32_t raw_read_actlr_el3(void) +{ + uint32_t actlr_el3; + + __asm__ __volatile__("mrs %0, ACTLR_EL3\n\t" : "=r" (actlr_el3) : : "memory"); + + return actlr_el3; +} + +void raw_write_actlr_el3(uint32_t actlr_el3) +{ + __asm__ __volatile__("msr ACTLR_EL3, %0\n\t" : : "r" (actlr_el3) : "memory"); +} + +uint32_t raw_read_actlr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_actlr(el); +} + +void raw_write_actlr_current(uint32_t actlr) +{ + uint32_t el = get_current_el(); + raw_write_actlr(actlr, el); +} + +uint32_t raw_read_actlr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_actlr, actlr, uint32_t, el); +} + +void raw_write_actlr(uint32_t actlr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_actlr, actlr, el); +} + +/* AFSR0 */ +uint32_t raw_read_afsr0_el1(void) +{ + uint32_t afsr0_el1; + + __asm__ __volatile__("mrs %0, AFSR0_EL1\n\t" : "=r" (afsr0_el1) : : "memory"); + + return afsr0_el1; +} + +void raw_write_afsr0_el1(uint32_t afsr0_el1) +{ + __asm__ __volatile__("msr AFSR0_EL1, %0\n\t" : : "r" (afsr0_el1) : "memory"); +} + +uint32_t raw_read_afsr0_el2(void) +{ + uint32_t afsr0_el2; + + __asm__ __volatile__("mrs %0, AFSR0_EL2\n\t" : "=r" (afsr0_el2) : : "memory"); + + return afsr0_el2; +} + +void raw_write_afsr0_el2(uint32_t afsr0_el2) +{ + __asm__ __volatile__("msr AFSR0_EL2, %0\n\t" : : "r" (afsr0_el2) : "memory"); +} + +uint32_t raw_read_afsr0_el3(void) +{ + uint32_t afsr0_el3; + + __asm__ __volatile__("mrs %0, AFSR0_EL3\n\t" : "=r" (afsr0_el3) : : "memory"); + + return afsr0_el3; +} + +void raw_write_afsr0_el3(uint32_t afsr0_el3) +{ + __asm__ __volatile__("msr AFSR0_EL3, %0\n\t" : : "r" (afsr0_el3) : "memory"); +} + +uint32_t raw_read_afsr0_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_afsr0(el); +} + +void raw_write_afsr0_current(uint32_t afsr0) +{ + uint32_t el = get_current_el(); + raw_write_afsr0(afsr0, el); +} + +uint32_t raw_read_afsr0(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_afsr0, afsr0, uint32_t, el); +} + +void raw_write_afsr0(uint32_t afsr0, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_afsr0, afsr0, el); +} + +/* AFSR1 */ +uint32_t raw_read_afsr1_el1(void) +{ + uint32_t afsr1_el1; + + __asm__ __volatile__("mrs %0, AFSR1_EL1\n\t" : "=r" (afsr1_el1) : : "memory"); + + return afsr1_el1; +} + +void raw_write_afsr1_el1(uint32_t afsr1_el1) +{ + __asm__ __volatile__("msr AFSR1_EL1, %0\n\t" : : "r" (afsr1_el1) : "memory"); +} + +uint32_t raw_read_afsr1_el2(void) +{ + uint32_t afsr1_el2; + + __asm__ __volatile__("mrs %0, AFSR1_EL2\n\t" : "=r" (afsr1_el2) : : "memory"); + + return afsr1_el2; +} + +void raw_write_afsr1_el2(uint32_t afsr1_el2) +{ + __asm__ __volatile__("msr AFSR1_EL2, %0\n\t" : : "r" (afsr1_el2) : "memory"); +} + +uint32_t raw_read_afsr1_el3(void) +{ + uint32_t afsr1_el3; + + __asm__ __volatile__("mrs %0, AFSR1_EL3\n\t" : "=r" (afsr1_el3) : : "memory"); + + return afsr1_el3; +} + +void raw_write_afsr1_el3(uint32_t afsr1_el3) +{ + __asm__ __volatile__("msr AFSR1_EL3, %0\n\t" : : "r" (afsr1_el3) : "memory"); +} + +uint32_t raw_read_afsr1_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_afsr1(el); +} + +void raw_write_afsr1_current(uint32_t afsr1) +{ + uint32_t el = get_current_el(); + raw_write_afsr1(afsr1, el); +} + +uint32_t raw_read_afsr1(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_afsr1, afsr1, uint32_t, el); +} + +void raw_write_afsr1(uint32_t afsr1, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_afsr1, afsr1, el); +} + +/* AIDR */ +uint32_t raw_read_aidr_el1(void) +{ + uint32_t aidr_el1; + + __asm__ __volatile__("mrs %0, AIDR_EL1\n\t" : "=r" (aidr_el1) : : "memory"); + + return aidr_el1; +} + +/* AMAIR */ +uint64_t raw_read_amair_el1(void) +{ + uint64_t amair_el1; + + __asm__ __volatile__("mrs %0, AMAIR_EL1\n\t" : "=r" (amair_el1) : : "memory"); + + return amair_el1; +} + +void raw_write_amair_el1(uint64_t amair_el1) +{ + __asm__ __volatile__("msr AMAIR_EL1, %0\n\t" : : "r" (amair_el1) : "memory"); +} + +uint64_t raw_read_amair_el2(void) +{ + uint64_t amair_el2; + + __asm__ __volatile__("mrs %0, AMAIR_EL2\n\t" : "=r" (amair_el2) : : "memory"); + + return amair_el2; +} + +void raw_write_amair_el2(uint64_t amair_el2) +{ + __asm__ __volatile__("msr AMAIR_EL2, %0\n\t" : : "r" (amair_el2) : "memory"); +} + +uint64_t raw_read_amair_el3(void) +{ + uint64_t amair_el3; + + __asm__ __volatile__("mrs %0, AMAIR_EL3\n\t" : "=r" (amair_el3) : : "memory"); + + return amair_el3; +} + +void raw_write_amair_el3(uint64_t amair_el3) +{ + __asm__ __volatile__("msr AMAIR_EL3, %0\n\t" : : "r" (amair_el3) : "memory"); +} + +uint64_t raw_read_amair_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_amair(el); +} + +void raw_write_amair_current(uint64_t amair) +{ + uint32_t el = get_current_el(); + raw_write_amair(amair, el); +} + +uint64_t raw_read_amair(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_amair, amair, uint64_t, el); +} + +void raw_write_amair(uint64_t amair, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_amair, amair, el); +} + +/* CCSIDR */ +uint32_t raw_read_ccsidr_el1(void) +{ + uint32_t ccsidr_el1; + + __asm__ __volatile__("mrs %0, CCSIDR_EL1\n\t" : "=r" (ccsidr_el1) : : "memory"); + + return ccsidr_el1; +} + +/* CLIDR */ +uint32_t raw_read_clidr_el1(void) +{ + uint32_t clidr_el1; + + __asm__ __volatile__("mrs %0, CLIDR_EL1\n\t" : "=r" (clidr_el1) : : "memory"); + + return clidr_el1; +} + +/* CPACR */ +uint32_t raw_read_cpacr_el1(void) +{ + uint32_t cpacr_el1; + + __asm__ __volatile__("mrs %0, CPACR_EL1\n\t" : "=r" (cpacr_el1) : : "memory"); + + return cpacr_el1; +} + +void raw_write_cpacr_el1(uint32_t cpacr_el1) +{ + __asm__ __volatile__("msr CPACR_EL1, %0\n\t" : : "r" (cpacr_el1) : "memory"); +} + +/* CPTR */ +uint32_t raw_read_cptr_el2(void) +{ + uint32_t cptr_el2; + + __asm__ __volatile__("mrs %0, CPTR_EL2\n\t" : "=r" (cptr_el2) : : "memory"); + + return cptr_el2; +} + +void raw_write_cptr_el2(uint32_t cptr_el2) +{ + __asm__ __volatile__("msr CPTR_EL2, %0\n\t" : : "r" (cptr_el2) : "memory"); +} + +uint32_t raw_read_cptr_el3(void) +{ + uint32_t cptr_el3; + + __asm__ __volatile__("mrs %0, CPTR_EL3\n\t" : "=r" (cptr_el3) : : "memory"); + + return cptr_el3; +} + +void raw_write_cptr_el3(uint32_t cptr_el3) +{ + __asm__ __volatile__("msr CPTR_EL3, %0\n\t" : : "r" (cptr_el3) : "memory"); +} + +/* CSSELR */ +uint32_t raw_read_csselr_el1(void) +{ + uint32_t csselr_el1; + + __asm__ __volatile__("mrs %0, CSSELR_EL1\n\t" : "=r" (csselr_el1) : : "memory"); + + return csselr_el1; +} + +void raw_write_csselr_el1(uint32_t csselr_el1) +{ + __asm__ __volatile__("msr CSSELR_EL1, %0\n\t" : : "r" (csselr_el1) : "memory"); +} + +/* CTR */ +uint32_t raw_read_ctr_el0(void) +{ + uint32_t ctr_el0; + + __asm__ __volatile__("mrs %0, CTR_EL0\n\t" : "=r" (ctr_el0) : : "memory"); + + return ctr_el0; +} + +/* ESR */ +uint32_t raw_read_esr_el1(void) +{ + uint32_t esr_el1; + + __asm__ __volatile__("mrs %0, ESR_EL1\n\t" : "=r" (esr_el1) : : "memory"); + + return esr_el1; +} + +void raw_write_esr_el1(uint32_t esr_el1) +{ + __asm__ __volatile__("msr ESR_EL1, %0\n\t" : : "r" (esr_el1) : "memory"); +} + +uint32_t raw_read_esr_el2(void) +{ + uint32_t esr_el2; + + __asm__ __volatile__("mrs %0, ESR_EL2\n\t" : "=r" (esr_el2) : : "memory"); + + return esr_el2; +} + +void raw_write_esr_el2(uint32_t esr_el2) +{ + __asm__ __volatile__("msr ESR_EL2, %0\n\t" : : "r" (esr_el2) : "memory"); +} + +uint32_t raw_read_esr_el3(void) +{ + uint32_t esr_el3; + + __asm__ __volatile__("mrs %0, ESR_EL3\n\t" : "=r" (esr_el3) : : "memory"); + + return esr_el3; +} + +void raw_write_esr_el3(uint32_t esr_el3) +{ + __asm__ __volatile__("msr ESR_EL3, %0\n\t" : : "r" (esr_el3) : "memory"); +} + +uint32_t raw_read_esr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_esr(el); +} + +void raw_write_esr_current(uint32_t esr) +{ + uint32_t el = get_current_el(); + raw_write_esr(esr, el); +} + +uint32_t raw_read_esr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_esr, esr, uint32_t, el); +} + +void raw_write_esr(uint32_t esr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_esr, esr, el); +} + +/* FAR */ +uint64_t raw_read_far_el1(void) +{ + uint64_t far_el1; + + __asm__ __volatile__("mrs %0, FAR_EL1\n\t" : "=r" (far_el1) : : "memory"); + + return far_el1; +} + +void raw_write_far_el1(uint64_t far_el1) +{ + __asm__ __volatile__("msr FAR_EL1, %0\n\t" : : "r" (far_el1) : "memory"); +} + +uint64_t raw_read_far_el2(void) +{ + uint64_t far_el2; + + __asm__ __volatile__("mrs %0, FAR_EL2\n\t" : "=r" (far_el2) : : "memory"); + + return far_el2; +} + +void raw_write_far_el2(uint64_t far_el2) +{ + __asm__ __volatile__("msr FAR_EL2, %0\n\t" : : "r" (far_el2) : "memory"); +} + +uint64_t raw_read_far_el3(void) +{ + uint64_t far_el3; + + __asm__ __volatile__("mrs %0, FAR_EL3\n\t" : "=r" (far_el3) : : "memory"); + + return far_el3; +} + +void raw_write_far_el3(uint64_t far_el3) +{ + __asm__ __volatile__("msr FAR_EL3, %0\n\t" : : "r" (far_el3) : "memory"); +} + +uint64_t raw_read_far_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_far(el); +} + +void raw_write_far_current(uint64_t far) +{ + uint32_t el = get_current_el(); + raw_write_far(far, el); +} + +uint64_t raw_read_far(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_far, far, uint64_t, el); +} + +void raw_write_far(uint64_t far, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_far, far, el); +} + +/* HCR */ +uint64_t raw_read_hcr_el2(void) +{ + uint64_t hcr_el2; + + __asm__ __volatile__("mrs %0, HCR_EL2\n\t" : "=r" (hcr_el2) : : "memory"); + + return hcr_el2; +} + +void raw_write_hcr_el2(uint64_t hcr_el2) +{ + __asm__ __volatile__("msr HCR_EL2, %0\n\t" : : "r" (hcr_el2) : "memory"); +} + +/* AA64PFR0 */ +uint64_t raw_read_aa64pfr0_el1(void) +{ + uint64_t aa64pfr0_el1; + + __asm__ __volatile__("mrs %0, ID_AA64PFR0_EL1\n\t" : "=r" (aa64pfr0_el1) : : "memory"); + + return aa64pfr0_el1; +} + +/* MAIR */ +uint64_t raw_read_mair_el1(void) +{ + uint64_t mair_el1; + + __asm__ __volatile__("mrs %0, MAIR_EL1\n\t" : "=r" (mair_el1) : : "memory"); + + return mair_el1; +} + +void raw_write_mair_el1(uint64_t mair_el1) +{ + __asm__ __volatile__("msr MAIR_EL1, %0\n\t" : : "r" (mair_el1) : "memory"); +} + +uint64_t raw_read_mair_el2(void) +{ + uint64_t mair_el2; + + __asm__ __volatile__("mrs %0, MAIR_EL2\n\t" : "=r" (mair_el2) : : "memory"); + + return mair_el2; +} + +void raw_write_mair_el2(uint64_t mair_el2) +{ + __asm__ __volatile__("msr MAIR_EL2, %0\n\t" : : "r" (mair_el2) : "memory"); +} + +uint64_t raw_read_mair_el3(void) +{ + uint64_t mair_el3; + + __asm__ __volatile__("mrs %0, MAIR_EL3\n\t" : "=r" (mair_el3) : : "memory"); + + return mair_el3; +} + +void raw_write_mair_el3(uint64_t mair_el3) +{ + __asm__ __volatile__("msr MAIR_EL3, %0\n\t" : : "r" (mair_el3) : "memory"); +} + +uint64_t raw_read_mair_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_mair(el); +} + +void raw_write_mair_current(uint64_t mair) +{ + uint32_t el = get_current_el(); + raw_write_mair(mair, el); +} + +uint64_t raw_read_mair(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_mair, mair, uint64_t, el); +} + +void raw_write_mair(uint64_t mair, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_mair, mair, el); +} + +/* MIDR */ +uint32_t raw_read_midr_el1(void) +{ + uint32_t midr_el1; + + __asm__ __volatile__("mrs %0, MIDR_EL1\n\t" : "=r" (midr_el1) : : "memory"); + + return midr_el1; +} + +/* MPIDR */ +uint64_t raw_read_mpidr_el1(void) +{ + uint64_t mpidr_el1; + + __asm__ __volatile__("mrs %0, MPIDR_EL1\n\t" : "=r" (mpidr_el1) : : "memory"); + + return mpidr_el1; +} + +/* RMR */ +uint32_t raw_read_rmr_el1(void) +{ + uint32_t rmr_el1; + + __asm__ __volatile__("mrs %0, RMR_EL1\n\t" : "=r" (rmr_el1) : : "memory"); + + return rmr_el1; +} + +void raw_write_rmr_el1(uint32_t rmr_el1) +{ + __asm__ __volatile__("msr RMR_EL1, %0\n\t" : : "r" (rmr_el1) : "memory"); +} + +uint32_t raw_read_rmr_el2(void) +{ + uint32_t rmr_el2; + + __asm__ __volatile__("mrs %0, RMR_EL2\n\t" : "=r" (rmr_el2) : : "memory"); + + return rmr_el2; +} + +void raw_write_rmr_el2(uint32_t rmr_el2) +{ + __asm__ __volatile__("msr RMR_EL2, %0\n\t" : : "r" (rmr_el2) : "memory"); +} + +uint32_t raw_read_rmr_el3(void) +{ + uint32_t rmr_el3; + + __asm__ __volatile__("mrs %0, RMR_EL3\n\t" : "=r" (rmr_el3) : : "memory"); + + return rmr_el3; +} + +void raw_write_rmr_el3(uint32_t rmr_el3) +{ + __asm__ __volatile__("msr RMR_EL3, %0\n\t" : : "r" (rmr_el3) : "memory"); +} + +uint32_t raw_read_rmr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_rmr(el); +} + +void raw_write_rmr_current(uint32_t rmr) +{ + uint32_t el = get_current_el(); + raw_write_rmr(rmr, el); +} + +uint32_t raw_read_rmr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_rmr, rmr, uint32_t, el); +} + +void raw_write_rmr(uint32_t rmr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_rmr, rmr, el); +} + +/* RVBAR */ +uint64_t raw_read_rvbar_el1(void) +{ + uint64_t rvbar_el1; + + __asm__ __volatile__("mrs %0, RVBAR_EL1\n\t" : "=r" (rvbar_el1) : : "memory"); + + return rvbar_el1; +} + +void raw_write_rvbar_el1(uint64_t rvbar_el1) +{ + __asm__ __volatile__("msr RVBAR_EL1, %0\n\t" : : "r" (rvbar_el1) : "memory"); +} + +uint64_t raw_read_rvbar_el2(void) +{ + uint64_t rvbar_el2; + + __asm__ __volatile__("mrs %0, RVBAR_EL2\n\t" : "=r" (rvbar_el2) : : "memory"); + + return rvbar_el2; +} + +void raw_write_rvbar_el2(uint64_t rvbar_el2) +{ + __asm__ __volatile__("msr RVBAR_EL2, %0\n\t" : : "r" (rvbar_el2) : "memory"); +} + +uint64_t raw_read_rvbar_el3(void) +{ + uint64_t rvbar_el3; + + __asm__ __volatile__("mrs %0, RVBAR_EL3\n\t" : "=r" (rvbar_el3) : : "memory"); + + return rvbar_el3; +} + +void raw_write_rvbar_el3(uint64_t rvbar_el3) +{ + __asm__ __volatile__("msr RVBAR_EL3, %0\n\t" : : "r" (rvbar_el3) : "memory"); +} + +uint64_t raw_read_rvbar_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_rvbar(el); +} + +void raw_write_rvbar_current(uint64_t rvbar) +{ + uint32_t el = get_current_el(); + raw_write_rvbar(rvbar, el); +} + +uint64_t raw_read_rvbar(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_rvbar, rvbar, uint64_t, el); +} + +void raw_write_rvbar(uint64_t rvbar, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_rvbar, rvbar, el); +} + +/* Scr */ +uint32_t raw_read_scr_el3(void) +{ + uint32_t scr_el3; + + __asm__ __volatile__("mrs %0, SCR_EL3\n\t" : "=r" (scr_el3) : : "memory"); + + return scr_el3; +} + +void raw_write_scr_el3(uint32_t scr_el3) +{ + __asm__ __volatile__("msr SCR_EL3, %0\n\t" : : "r" (scr_el3) : "memory"); +} + +/* SCTLR */ +uint32_t raw_read_sctlr_el1(void) +{ + uint32_t sctlr_el1; + + __asm__ __volatile__("mrs %0, SCTLR_EL1\n\t" : "=r" (sctlr_el1) : : "memory"); + + return sctlr_el1; +} + +void raw_write_sctlr_el1(uint32_t sctlr_el1) +{ + __asm__ __volatile__("msr SCTLR_EL1, %0\n\t" : : "r" (sctlr_el1) : "memory"); +} + +uint32_t raw_read_sctlr_el2(void) +{ + uint32_t sctlr_el2; + + __asm__ __volatile__("mrs %0, SCTLR_EL2\n\t" : "=r" (sctlr_el2) : : "memory"); + + return sctlr_el2; +} + +void raw_write_sctlr_el2(uint32_t sctlr_el2) +{ + __asm__ __volatile__("msr SCTLR_EL2, %0\n\t" : : "r" (sctlr_el2) : "memory"); +} + +uint32_t raw_read_sctlr_el3(void) +{ + uint32_t sctlr_el3; + + __asm__ __volatile__("mrs %0, SCTLR_EL3\n\t" : "=r" (sctlr_el3) : : "memory"); + + return sctlr_el3; +} + +void raw_write_sctlr_el3(uint32_t sctlr_el3) +{ + __asm__ __volatile__("msr SCTLR_EL3, %0\n\t" : : "r" (sctlr_el3) : "memory"); +} + +uint32_t raw_read_sctlr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_sctlr(el); +} + +void raw_write_sctlr_current(uint32_t sctlr) +{ + uint32_t el = get_current_el(); + raw_write_sctlr(sctlr, el); +} + +uint32_t raw_read_sctlr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_sctlr, sctlr, uint32_t, el); +} + +void raw_write_sctlr(uint32_t sctlr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_sctlr, sctlr, el); +} + +/* TCR */ +uint64_t raw_read_tcr_el1(void) +{ + uint64_t tcr_el1; + + __asm__ __volatile__("mrs %0, TCR_EL1\n\t" : "=r" (tcr_el1) : : "memory"); + + return tcr_el1; +} + +void raw_write_tcr_el1(uint64_t tcr_el1) +{ + __asm__ __volatile__("msr TCR_EL1, %0\n\t" : : "r" (tcr_el1) : "memory"); +} + +uint32_t raw_read_tcr_el2(void) +{ + uint32_t tcr_el2; + + __asm__ __volatile__("mrs %0, TCR_EL2\n\t" : "=r" (tcr_el2) : : "memory"); + + return tcr_el2; +} + +void raw_write_tcr_el2(uint32_t tcr_el2) +{ + __asm__ __volatile__("msr TCR_EL2, %0\n\t" : : "r" (tcr_el2) : "memory"); +} + +uint32_t raw_read_tcr_el3(void) +{ + uint32_t tcr_el3; + + __asm__ __volatile__("mrs %0, TCR_EL3\n\t" : "=r" (tcr_el3) : : "memory"); + + return tcr_el3; +} + +void raw_write_tcr_el3(uint32_t tcr_el3) +{ + __asm__ __volatile__("msr TCR_EL3, %0\n\t" : : "r" (tcr_el3) : "memory"); +} + + +/* + * IMPORTANT: TCR_EL1 is 64-bit whereas TCR_EL2 and TCR_EL3 are 32-bit. Thus, + * 64-bit is used to read/write for tcr_current. tcr_el2 and tcr_el3 handle them + * with appropriate 32-bit types. + */ +uint64_t raw_read_tcr_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_tcr(el); +} + +void raw_write_tcr_current(uint64_t tcr) +{ + uint32_t el = get_current_el(); + raw_write_tcr(tcr, el); +} + +uint64_t raw_read_tcr(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_tcr, tcr, uint64_t, el); +} + +void raw_write_tcr(uint64_t tcr, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_tcr, tcr, el); +} + +/* TTBR0 */ +uint64_t raw_read_ttbr0_el1(void) +{ + uint64_t ttbr0_el1; + + __asm__ __volatile__("mrs %0, TTBR0_EL1\n\t" : "=r" (ttbr0_el1) : : "memory"); + + return ttbr0_el1; +} + +void raw_write_ttbr0_el1(uint64_t ttbr0_el1) +{ + __asm__ __volatile__("msr TTBR0_EL1, %0\n\t" : : "r" (ttbr0_el1) : "memory"); +} + +uint64_t raw_read_ttbr0_el2(void) +{ + uint64_t ttbr0_el2; + + __asm__ __volatile__("mrs %0, TTBR0_EL2\n\t" : "=r" (ttbr0_el2) : : "memory"); + + return ttbr0_el2; +} + +void raw_write_ttbr0_el2(uint64_t ttbr0_el2) +{ + __asm__ __volatile__("msr TTBR0_EL2, %0\n\t" : : "r" (ttbr0_el2) : "memory"); +} + +uint64_t raw_read_ttbr0_el3(void) +{ + uint64_t ttbr0_el3; + + __asm__ __volatile__("mrs %0, TTBR0_EL3\n\t" : "=r" (ttbr0_el3) : : "memory"); + + return ttbr0_el3; +} + +void raw_write_ttbr0_el3(uint64_t ttbr0_el3) +{ + __asm__ __volatile__("msr TTBR0_EL3, %0\n\t" : : "r" (ttbr0_el3) : "memory"); +} + +uint64_t raw_read_ttbr0_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_ttbr0(el); +} + +void raw_write_ttbr0_current(uint64_t ttbr0) +{ + uint32_t el = get_current_el(); + raw_write_ttbr0(ttbr0, el); +} + +uint64_t raw_read_ttbr0(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_ttbr0, ttbr0, uint64_t, el); +} + +void raw_write_ttbr0(uint64_t ttbr0, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_ttbr0, ttbr0, el); +} + +/* TTBR1 */ +uint64_t raw_read_ttbr1_el1(void) +{ + uint64_t ttbr1_el1; + + __asm__ __volatile__("mrs %0, TTBR1_EL1\n\t" : "=r" (ttbr1_el1) : : "memory"); + + return ttbr1_el1; +} + +void raw_write_ttbr1_el1(uint64_t ttbr1_el1) +{ + __asm__ __volatile__("msr TTBR1_EL1, %0\n\t" : : "r" (ttbr1_el1) : "memory"); +} + +/* VBAR */ +uint64_t raw_read_vbar_el1(void) +{ + uint64_t vbar_el1; + + __asm__ __volatile__("mrs %0, VBAR_EL1\n\t" : "=r" (vbar_el1) : : "memory"); + + return vbar_el1; +} + +void raw_write_vbar_el1(uint64_t vbar_el1) +{ + __asm__ __volatile__("msr VBAR_EL1, %0\n\t" : : "r" (vbar_el1) : "memory"); +} + +uint64_t raw_read_vbar_el2(void) +{ + uint64_t vbar_el2; + + __asm__ __volatile__("mrs %0, VBAR_EL2\n\t" : "=r" (vbar_el2) : : "memory"); + + return vbar_el2; +} + +void raw_write_vbar_el2(uint64_t vbar_el2) +{ + __asm__ __volatile__("msr VBAR_EL2, %0\n\t" : : "r" (vbar_el2) : "memory"); +} + +uint64_t raw_read_vbar_el3(void) +{ + uint64_t vbar_el3; + + __asm__ __volatile__("mrs %0, VBAR_EL3\n\t" : "=r" (vbar_el3) : : "memory"); + + return vbar_el3; +} + +void raw_write_vbar_el3(uint64_t vbar_el3) +{ + __asm__ __volatile__("msr VBAR_EL3, %0\n\t" : : "r" (vbar_el3) : "memory"); +} + +uint64_t raw_read_vbar_current(void) +{ + uint32_t el = get_current_el(); + return raw_read_vbar(el); +} + +void raw_write_vbar_current(uint64_t vbar) +{ + uint32_t el = get_current_el(); + raw_write_vbar(vbar, el); +} + +uint64_t raw_read_vbar(uint32_t el) +{ + SWITCH_CASE_READ(raw_read_vbar, vbar, uint64_t, el); +} + +void raw_write_vbar(uint64_t vbar, uint32_t el) +{ + SWITCH_CASE_WRITE(raw_write_vbar, vbar, el); +} diff --git a/payloads/libpayload/arch/powerpc/main.c b/src/arch/arm64/armv8/lib/tlb.c similarity index 55% rename from payloads/libpayload/arch/powerpc/main.c rename to src/arch/arm64/armv8/lib/tlb.c index 9722e0c0c5..d80783d4ee 100644 --- a/payloads/libpayload/arch/powerpc/main.c +++ b/src/arch/arm64/armv8/lib/tlb.c @@ -1,7 +1,7 @@ /* - * This file is part of the libpayload project. + * This file is part of the coreboot project. * - * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright 2014 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,49 +25,71 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * tlb.c: System intructions for TLB maintenance. + * Reference: ARM Architecture Reference Manual, ARMv8-A edition */ -#include +#include -unsigned long loader_eax; /**< The value of EAX passed from the loader */ -unsigned long loader_ebx; /**< The value of EBX passed from the loader */ +#include -unsigned int main_argc; /**< The argc value to pass to main() */ - -/** The argv value to pass to main() */ -char *main_argv[MAX_ARGC_COUNT]; - -/** - * This is our C entry function - set up the system - * and jump into the payload entry point. - */ -void start_main(void); -void start_main(void) +/* TLBIALL */ +void tlbiall_el1(void) { - extern int main(int argc, char **argv); - - /* Optionally set up the consoles. */ -#ifndef CONFIG_SKIP_CONSOLE_INIT - console_init(); -#endif - - /* Gather system information. */ - lib_get_sysinfo(); - - /* - * Any other system init that has to happen before the - * user gets control goes here. - */ - - /* - * Go to the entry point. - * In the future we may care about the return value. - */ - - (void) main(main_argc, (main_argc != 0) ? main_argv : NULL); - - /* - * Returning here will go to the _leave function to return - * us to the original context. - */ + __asm__ __volatile__("tlbi alle1\n\t" : : : "memory"); +} + +void tlbiall_el2(void) +{ + __asm__ __volatile__("tlbi alle2\n\t" : : : "memory"); +} + +void tlbiall_el3(void) +{ + __asm__ __volatile__("tlbi alle3\n\t" : : : "memory"); +} + +void tlbiall_current(void) +{ + uint32_t el = get_current_el(); + tlbiall(el); +} + +void tlbiall(uint32_t el) +{ + SWITCH_CASE_TLBI(tlbiall, el); +} + +/* TLBIALLIS */ +void tlbiallis_el1(void) +{ + __asm__ __volatile__("tlbi alle1is\n\t" : : : "memory"); +} + +void tlbiallis_el2(void) +{ + __asm__ __volatile__("tlbi alle2is\n\t" : : : "memory"); +} + +void tlbiallis_el3(void) +{ + __asm__ __volatile__("tlbi alle3is\n\t" : : : "memory"); +} + +void tlbiallis_current(void) +{ + uint32_t el = get_current_el(); + tlbiallis(el); +} + +void tlbiallis(uint32_t el) +{ + SWITCH_CASE_TLBI(tlbiallis, el); +} + +/* TLBIVAA */ +void tlbivaa_el1(uint64_t va) +{ + __asm__ __volatile__("tlbi vaae1, %0\n\t" : : "r" (va) : "memory"); } diff --git a/src/arch/arm64/armv8/mmu.c b/src/arch/arm64/armv8/mmu.c new file mode 100644 index 0000000000..8fde41f7f7 --- /dev/null +++ b/src/arch/arm64/armv8/mmu.c @@ -0,0 +1,297 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* Maximum number of XLAT Tables available based on ttb buffer size */ +static unsigned int max_tables; +/* Address of ttb buffer */ +static uint64_t *xlat_addr; +static int free_idx; + +static const uint64_t level_to_addr_mask[] = { + L1_ADDR_MASK, + L2_ADDR_MASK, + L3_ADDR_MASK, +}; + +static const uint64_t level_to_addr_shift[] = { + L1_ADDR_SHIFT, + L2_ADDR_SHIFT, + L3_ADDR_SHIFT, +}; + +/* Func : get_block_attr + * Desc : Get block descriptor attributes based on the value of tag in memrange + * region + */ +static uint64_t get_block_attr(unsigned long tag) +{ + uint64_t attr; + + attr = (tag & MA_NS)? BLOCK_NS : 0; + attr |= (tag & MA_RO)? BLOCK_AP_RO : BLOCK_AP_RW; + attr |= BLOCK_ACCESS; + + if (tag & MA_MEM) { + if (tag & MA_MEM_NC) + attr |= BLOCK_INDEX_MEM_NORMAL_NC << BLOCK_INDEX_SHIFT; + else + attr |= BLOCK_INDEX_MEM_NORMAL << BLOCK_INDEX_SHIFT; + } else { + attr |= BLOCK_INDEX_MEM_DEV_NGNRNE << BLOCK_INDEX_SHIFT; + } + + return attr; +} + +/* Func : get_index_from_addr + * Desc : Get index into table at a given level using appropriate bits from the + * base address + */ +static uint64_t get_index_from_addr(uint64_t addr, uint8_t level) +{ + uint64_t mask = level_to_addr_mask[level-1]; + uint8_t shift = level_to_addr_shift[level-1]; + + return ((addr & mask) >> shift); +} + +/* Func : table_desc_valid + * Desc : Check if a table entry contains valid desc + */ +static uint64_t table_desc_valid(uint64_t desc) +{ + return((desc & TABLE_DESC) == TABLE_DESC); +} + +/* Func : get_new_table + * Desc : Return the next free XLAT table from ttb buffer + */ +static uint64_t *get_new_table(void) +{ + uint64_t *new; + + if (free_idx >= max_tables) { + return NULL; + } + + new = (uint64_t*)((unsigned char *)xlat_addr + free_idx * GRANULE_SIZE); + free_idx++; + + memset(new, 0, GRANULE_SIZE); + + return new; +} + +/* Func : get_table_from_desc + * Desc : Get next level table address from table descriptor + */ +static uint64_t *get_table_from_desc(uint64_t desc) +{ + uint64_t *ptr = (uint64_t*)(desc & XLAT_TABLE_MASK); + return ptr; +} + +/* Func: get_next_level_table + * Desc: Check if the table entry is a valid descriptor. If not, allocate new + * table, update the entry and return the table addr. If valid, return the addr + */ +static uint64_t *get_next_level_table(uint64_t *ptr) +{ + uint64_t desc = *ptr; + + if (!table_desc_valid(desc)) { + uint64_t *new_table = get_new_table(); + if (new_table == NULL) + return NULL; + desc = ((uint64_t)new_table) | TABLE_DESC; + *ptr = desc; + } + return get_table_from_desc(desc); +} + +/* Func : init_xlat_table + * Desc : Given a base address and size, it identifies the indices within + * different level XLAT tables which map the given base addr. Similar to table + * walk, except that all invalid entries during the walk are updated + * accordingly. On success, it returns the size of the block/page addressed by + * the final table + */ +static uint64_t init_xlat_table(uint64_t base_addr, + uint64_t size, + uint64_t tag) +{ + uint64_t l1_index = get_index_from_addr(base_addr,1); + uint64_t l2_index = get_index_from_addr(base_addr,2); + uint64_t l3_index = get_index_from_addr(base_addr,3); + uint64_t *table = xlat_addr; + uint64_t desc; + uint64_t attr = get_block_attr(tag); + + /* L1 table lookup */ + /* If VA has bits more than 41, lookup starts at L1 */ + if (l1_index) { + table = get_next_level_table(&table[l1_index]); + if (!table) + return 0; + } + + /* L2 table lookup */ + /* If lookup was performed at L1, L2 table addr is obtained from L1 desc + else, lookup starts at ttbr address */ + if (!l3_index && (size >= L2_XLAT_SIZE)) { + /* If block address is aligned and size is greater than or equal + to 512MiB i.e. size addressed by each L2 entry, we can + directly store a block desc */ + desc = base_addr | BLOCK_DESC | attr; + table[l2_index] = desc; + /* L3 lookup is not required */ + return L2_XLAT_SIZE; + } else { + /* L2 entry stores a table descriptor */ + table = get_next_level_table(&table[l2_index]); + if (!table) + return 0; + } + + /* L3 table lookup */ + desc = base_addr | PAGE_DESC | attr; + table[l3_index] = desc; + return L3_XLAT_SIZE; +} + +/* Func : sanity_check + * Desc : Check if the address is aligned and size is atleast the granule size + */ +static uint64_t sanity_check(uint64_t addr, + uint64_t size) +{ + /* Address should be atleast 64 KiB aligned */ + if (addr & GRANULE_SIZE_MASK) + return 1; + + /* Size should be atleast granule size */ + if (size < GRANULE_SIZE) + return 1; + + return 0; +} + +/* Func : init_mmap_entry + * Desc : For each mmap entry, this function calls init_xlat_table with the base + * address. Based on size returned from init_xlat_table, base_addr is updated + * and subsequent calls are made for initializing the xlat table until the whole + * region is initialized. + */ +static void init_mmap_entry(struct range_entry *r) +{ + uint64_t base_addr = range_entry_base(r); + uint64_t size = range_entry_size(r); + uint64_t tag = range_entry_tag(r); + uint64_t temp_size = size; + + while (temp_size) { + uint64_t ret; + + if (sanity_check(base_addr,temp_size)) { + return; + } + + ret = init_xlat_table(base_addr + (size - temp_size), + temp_size,tag); + + if (ret == 0) + return; + + temp_size -= ret; + } +} + +/* Func : mmu_init + * Desc : Initialize mmu based on the mmap_ranges passed. ttb_buffer is used as + * the base address for xlat tables. ttb_size defines the max number of tables + * that can be used + */ +void mmu_init(struct memranges *mmap_ranges, + uint64_t *ttb_buffer, + uint64_t ttb_size) +{ + struct range_entry *mmap_entry; + + if (sanity_check((uint64_t)ttb_buffer, ttb_size)) { + return; + } + + memset((void*)ttb_buffer, 0, GRANULE_SIZE); + max_tables = (ttb_size >> GRANULE_SIZE_SHIFT); + xlat_addr = ttb_buffer; + free_idx = 1; + + memranges_each_entry(mmap_entry, mmap_ranges) { + init_mmap_entry(mmap_entry); + } +} + +void mmu_enable(void) +{ + uint32_t sctlr; + + /* Initialize MAIR indices */ + raw_write_mair_el3(MAIR_ATTRIBUTES); + + /* Invalidate TLBs */ + tlbiall_el3(); + + /* Initialize TCR flags */ + raw_write_tcr_el3(TCR_TOSZ | TCR_IRGN0_NM_WBWAC | TCR_ORGN0_NM_WBWAC | + TCR_SH0_IS | TCR_TG0_64KB | TCR_PS_64GB | + TCR_TBI_USED); + + /* Initialize TTBR */ + raw_write_ttbr0_el3((uintptr_t)xlat_addr); + + /* Ensure all translation table writes are committed before enabling MMU */ + dsb(); + isb(); + + /* Enable MMU */ + sctlr = raw_read_sctlr_el3(); + sctlr |= SCTLR_C | SCTLR_M | SCTLR_I; + raw_write_sctlr_el3(sctlr); + + isb(); +} diff --git a/src/arch/arm64/armv8/secmon/Makefile.inc b/src/arch/arm64/armv8/secmon/Makefile.inc new file mode 100644 index 0000000000..bfa76d9a66 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/Makefile.inc @@ -0,0 +1,53 @@ +################################################################################ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +$(eval $(call create_class_compiler,secmon,arm64)) + +SECMON_DIR=$(obj)/arch/arm64/armv8/secmon +SECMON_BIN=$(SECMON_DIR)/secmon +SECMON_ELF=$(SECMON_DIR)/secmon.elf +SECMON_RMOD=$(SECMON_DIR)/secmon.elf.rmod +SECMON_RAMSTAGE=$(SECMON_DIR)/secmon.ramstage.o + +secmon-generic-ccopts += -D__SECMON__ +secmon-c-ccopts += $(armv8_flags) +secmon-S-ccopts += $(armv8_asm_flags) + +secmon-y += secmon_init.c +secmon-y += psci.c +secmon-y += smc.c +secmon-y += trampoline.S +secmon-y += ../cache.c +secmon-y += ../cpu.S +secmon-y += ../exception.c +secmon-y += ../../cpu.c +secmon-y += ../../transition_asm.S ../../transition.c + +ramstage-objs += $(SECMON_RAMSTAGE) + +$(eval $(call rmodule_link,$(SECMON_ELF), $$$$(secmon-objs),8192,arm64)) + +$(SECMON_BIN): $(SECMON_RMOD) + $(OBJCOPY_secmon) -O binary $< $@ + +$(SECMON_RAMSTAGE): $(SECMON_BIN) + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + cd $(dir $@); $(OBJCOPY_secmon) -I binary $(notdir $<) -O elf64-littleaarch64 -B aarch64 $(notdir $@) diff --git a/src/arch/arm64/armv8/secmon/psci.c b/src/arch/arm64/armv8/secmon/psci.c new file mode 100644 index 0000000000..6047abd698 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/psci.c @@ -0,0 +1,571 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "secmon.h" + +DECLARE_SPIN_LOCK(psci_spinlock); + +/* Root of PSCI node tree. */ +static struct psci_node psci_root; + +/* Array of all the psci_nodes in system. */ +static size_t psci_num_nodes; +static struct psci_node **psci_nodes; + +static inline void psci_lock(void) +{ + spin_lock(&psci_spinlock); +} + +static inline void psci_unlock(void) +{ + spin_unlock(&psci_spinlock); +} + +static inline int psci_state_locked(const struct psci_node *e) +{ + return e->state; +} + +static inline void psci_set_state_locked(struct psci_node *e, int s) +{ + e->state = s; +} + +static struct psci_node *psci_node_lookup(uint64_t mpidr, int level) +{ + size_t i; + + /* The array of node pointers are in depth-first order of the tree. */ + for (i = 0; i < psci_num_nodes; i++) { + struct psci_node *current = psci_nodes[i]; + + if (current->mpidr > mpidr) + break; + if (current->mpidr < mpidr) + continue; + if (current->level == level) + return current; + } + return NULL; +} + +static inline struct psci_node *node_self(void) +{ + return psci_node_lookup(cpu_info()->mpidr, PSCI_AFFINITY_LEVEL_0); +} + +/* Find the ancestor of node affected by a state transition limited by level. */ +static struct psci_node *psci_find_ancestor(struct psci_node *e, int level, + int state) +{ + struct psci_node *p; + + /* If all siblings of the node are already off then parent can be + * set to off as well. */ + if (state == PSCI_STATE_OFF) { + while (1) { + size_t i; + struct psci_node *s; + + if (psci_root_node(e)) + return e; + + p = psci_node_parent(e); + + if (p->level > level) + return e; + + for (i = 0; i < p->children.num; i++) { + s = &p->children.nodes[i]; + /* Don't check target. */ + if (s == e) + continue; + if (psci_state_locked(s) != PSCI_STATE_OFF) + return e; + } + + e = p; + } + } + + /* All ancestors in state OFF are affected. */ + if (state == PSCI_STATE_ON_PENDING) { + while (1) { + /* At the root. Return last affected node. */ + if (psci_root_node(e)) + return e; + + p = psci_node_parent(e); + + if (p->level > level) + return e; + + /* This parent is already ON. */ + if (psci_state_locked(p) != PSCI_STATE_OFF) + return e; + + e = p; + } + } + + /* Default to returning node passed in. */ + return e; +} + +static void psci_set_hierarchy_state(struct psci_node *from, + struct psci_node *to, + int state) +{ + struct psci_node *end; + + end = psci_node_parent(to); + + while (from != end) { + /* Raced with another CPU as state is already set. */ + if (psci_state_locked(from) == state) + break; + psci_set_state_locked(from, state); + from = psci_node_parent(from); + } +} + +static void psci_cpu_on_callback(void *arg) +{ + struct exc_state state; + int target_el; + struct psci_node *e = arg; + + psci_lock(); + psci_set_hierarchy_state(e, e->cpu_state.ancestor, PSCI_STATE_ON); + psci_unlock(); + + /* Target EL is determined if HVC is enabled or not. */ + target_el = (raw_read_scr_el3() & SCR_HVC_ENABLE) ? EL2 : EL1; + + memset(&state, 0, sizeof(state)); + state.elx.spsr = get_eret_el(target_el, SPSR_USE_H); + transition_with_entry(e->cpu_state.startup.run, + e->cpu_state.startup.arg, &state); +} + +static void psci_cpu_on_prepare(struct psci_cmd *cmd, + const struct cpu_action *a) +{ + struct psci_node *ancestor; + struct psci_node *e; + int state = PSCI_STATE_ON_PENDING; + + e = cmd->target; + e->cpu_state.startup = *a; + ancestor = psci_find_ancestor(e, PSCI_AFFINITY_LEVEL_HIGHEST, state); + e->cpu_state.ancestor = ancestor; + cmd->ancestor = ancestor; +} + +static int psci_schedule_cpu_on(struct psci_node *e) +{ + struct cpu_info *ci; + struct cpu_action action = { + .run = &psci_cpu_on_callback, + .arg = e, + }; + + ci = e->cpu_state.ci; + if (ci == NULL || arch_run_on_cpu_async(ci->id, &action)) { + psci_set_hierarchy_state(e, e->cpu_state.ancestor, + PSCI_STATE_OFF); + return PSCI_RET_INTERNAL_FAILURE; + } + + return PSCI_RET_SUCCESS; +} + +void psci_turn_on_self(const struct cpu_action *action) +{ + struct psci_node *e = node_self(); + struct psci_cmd cmd = { + .type = PSCI_CMD_ON, + }; + + if (e == NULL) { + printk(BIOS_ERR, "Couldn't turn on self: mpidr %llx\n", + cpu_info()->mpidr); + return; + } + + cmd.target = e; + + psci_lock(); + psci_cpu_on_prepare(&cmd, action); + psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_ON_PENDING); + psci_unlock(); + + psci_schedule_cpu_on(e); +} + +void psci_cpu_entry(void) +{ + /* + * Just wait for an action to be performed. Only CPU_ON is supported + * initially. i.e. no power down then wake. + */ + secmon_wait_for_action(); +} + +static void psci_cpu_on(struct psci_func *pf) +{ + uint64_t entry; + uint64_t target_mpidr; + uint64_t context_id; + int cpu_state; + int ret; + struct psci_node *e; + struct cpu_action action; + struct psci_cmd cmd = { + .type = PSCI_CMD_ON, + }; + + target_mpidr = psci64_arg(pf, PSCI_PARAM_0); + entry = psci64_arg(pf, PSCI_PARAM_1); + context_id = psci64_arg(pf, PSCI_PARAM_2); + + e = psci_node_lookup(target_mpidr, PSCI_AFFINITY_LEVEL_0); + + if (e == NULL) { + psci32_return(pf, PSCI_RET_INVALID_PARAMETERS); + return; + } + + psci_lock(); + cpu_state = psci_state_locked(e); + + if (cpu_state == PSCI_STATE_ON_PENDING) { + psci32_return(pf, PSCI_RET_ON_PENDING); + psci_unlock(); + return; + } else if (cpu_state == PSCI_STATE_ON) { + psci32_return(pf, PSCI_RET_ALREADY_ON); + psci_unlock(); + return; + } + + cmd.target = e; + action.run = (void *)entry; + action.arg = (void *)context_id; + psci_cpu_on_prepare(&cmd, &action); + + ret = soc_psci_ops.cmd_prepare(&cmd); + + if (ret == PSCI_RET_SUCCESS) + psci_set_hierarchy_state(e, cmd.ancestor, + PSCI_STATE_ON_PENDING); + + psci_unlock(); + + if (ret != PSCI_RET_SUCCESS) + return psci32_return(pf, ret); + + ret = soc_psci_ops.cmd_commit(&cmd); + + if (ret != PSCI_RET_SUCCESS) { + psci_lock(); + psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_OFF); + psci_unlock(); + return psci32_return(pf, ret); + } + + psci32_return(pf, psci_schedule_cpu_on(e)); +} + +static int psci_turn_off_node(struct psci_node *e, int level, + int state_id) +{ + int ret; + struct psci_cmd cmd = { + .type = PSCI_CMD_OFF, + .state_id = state_id, + .target = e, + }; + + psci_lock(); + + cmd.ancestor = psci_find_ancestor(e, level, PSCI_STATE_OFF); + + ret = soc_psci_ops.cmd_prepare(&cmd); + + if (ret == PSCI_RET_SUCCESS) + psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_OFF); + + psci_unlock(); + + if (ret != PSCI_RET_SUCCESS) + return ret; + + /* Should never return. */ + ret = soc_psci_ops.cmd_commit(&cmd); + + /* Adjust ret to be an error. */ + if (ret == PSCI_RET_SUCCESS) + ret = PSCI_RET_INTERNAL_FAILURE; + + /* Turn things back on. */ + psci_lock(); + psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_ON); + psci_unlock(); + + return ret; +} + +int psci_turn_off_self(void) +{ + struct psci_node *e = node_self(); + + if (e == NULL) { + printk(BIOS_ERR, "No PSCI node for MPIDR %llx.\n", + cpu_info()->mpidr); + return PSCI_RET_INTERNAL_FAILURE; + } + + /* -1 state id indicates to SoC to make its own decision for + * internal state when powering off the node. */ + return psci_turn_off_node(e, PSCI_AFFINITY_LEVEL_HIGHEST, -1); +} + +static int psci_handler(struct smc_call *smc) +{ + struct psci_func pf_storage; + struct psci_func *pf = &pf_storage; + + psci_func_init(pf, smc); + + switch (pf->id) { + case PSCI_CPU_ON64: + psci_cpu_on(pf); + break; + case PSCI_CPU_OFF64: + psci32_return(pf, psci_turn_off_self()); + break; + default: + psci32_return(pf, PSCI_RET_NOT_SUPPORTED); + break; + } + + return 0; +} + +static void psci_link_cpu_info(void *arg) +{ + struct psci_node *e = node_self(); + + if (e == NULL) { + printk(BIOS_ERR, "No PSCI node for MPIDR %llx.\n", + cpu_info()->mpidr); + return; + } + + e->cpu_state.ci = cpu_info(); +} + +static int psci_init_node(struct psci_node *e, + struct psci_node *parent, + int level, uint64_t mpidr) +{ + size_t i; + uint64_t mpidr_inc; + struct psci_node_group *ng; + size_t num_children; + + memset(e, 0, sizeof(*e)); + e->mpidr = mpidr; + psci_set_state_locked(e, PSCI_STATE_OFF); + e->parent = parent; + e->level = level; + + if (level == PSCI_AFFINITY_LEVEL_0) + return 0; + + num_children = soc_psci_ops.children_at_level(level, mpidr); + + if (num_children == 0) + return 0; + + ng = &e->children; + ng->num = num_children; + ng->nodes = malloc(ng->num * sizeof(struct psci_node)); + if (ng->nodes == NULL) { + printk(BIOS_DEBUG, "PSCI: Allocation failure at level %d\n", + level); + return -1; + } + + /* Switch to next level below. */ + level = psci_level_below(level); + mpidr_inc = mpidr_mask(!!(level == PSCI_AFFINITY_LEVEL_3), + !!(level == PSCI_AFFINITY_LEVEL_2), + !!(level == PSCI_AFFINITY_LEVEL_1), + !!(level == PSCI_AFFINITY_LEVEL_0)); + + for (i = 0; i < ng->num; i++) { + struct psci_node *c = &ng->nodes[i]; + + /* Recursively initialize the nodes. */ + if (psci_init_node(c, e, level, mpidr)) + return -1; + mpidr += mpidr_inc; + } + + return 0; +} + +static size_t psci_count_children(struct psci_node *e) +{ + size_t i; + size_t count; + + if (e->level == PSCI_AFFINITY_LEVEL_0) + return 0; + + count = e->children.num; + for (i = 0; i < e->children.num; i++) + count += psci_count_children(&e->children.nodes[i]); + + return count; +} + +static size_t psci_write_nodes(struct psci_node *e, size_t index) +{ + size_t i; + + /* + * Recursively save node pointers in array. Node pointers are + * ordered in ascending mpidr and descending level within same mpidr. + * i.e. each node is saved in depth-first order of the tree. + */ + if (e->level != PSCI_AFFINITY_ROOT) { + psci_nodes[index] = e; + index++; + } + + if (e->level == PSCI_AFFINITY_LEVEL_0) + return index; + + for (i = 0; i < e->children.num; i++) + index = psci_write_nodes(&e->children.nodes[i], index); + + return index; +} + +static int psci_allocate_nodes(void) +{ + int level; + size_t num_children; + uint64_t mpidr; + struct psci_node *e; + + mpidr = 0; + level = PSCI_AFFINITY_ROOT; + + /* Find where the root should start. */ + while (psci_level_below(level) >= PSCI_AFFINITY_LEVEL_0) { + num_children = soc_psci_ops.children_at_level(level, mpidr); + + if (num_children == 0) { + printk(BIOS_ERR, "PSCI: No children at level %d!\n", + level); + return -1; + } + + /* The root starts where the affinity levels branch. */ + if (num_children > 1) + break; + + level = psci_level_below(level); + } + + if (psci_init_node(&psci_root, NULL, level, mpidr)) { + printk(BIOS_ERR, "PSCI init node failure.\n"); + return -1; + } + + num_children = psci_count_children(&psci_root); + /* Count the root node if isn't a fake node. */ + if (psci_root.level != PSCI_AFFINITY_ROOT) + num_children++; + + psci_nodes = malloc(num_children * sizeof(void *)); + psci_num_nodes = num_children; + + if (psci_nodes == NULL) { + printk(BIOS_ERR, "PSCI node pointer array failure.\n"); + return -1; + } + + num_children = psci_write_nodes(&psci_root, 0); + if (num_children != psci_num_nodes) { + printk(BIOS_ERR, "Wrong nodes written: %zd vs %zd.\n", + num_children, psci_num_nodes); + return -1; + } + + /* + * By default all nodes are set to PSCI_STATE_OFF. In order not + * to race with other CPUs turning themselves off set the BSPs + * affinity node to ON. + */ + e = node_self(); + if (e == NULL) { + printk(BIOS_ERR, "No PSCI node for BSP.\n"); + return -1; + } + psci_set_state_locked(e, PSCI_STATE_ON); + + return 0; +} + +void psci_init(uintptr_t cpu_on_entry) +{ + struct cpu_action action = { + .run = &psci_link_cpu_info, + }; + + if (psci_allocate_nodes()) { + printk(BIOS_ERR, "PSCI support not enabled.\n"); + return; + } + + if (arch_run_on_all_cpus_async(&action)) + printk(BIOS_ERR, "Error linking cpu_info to PSCI nodes.\n"); + + /* Register PSCI handlers. */ + if (smc_register_range(PSCI_CPU_OFF64, PSCI_CPU_ON64, &psci_handler)) + printk(BIOS_ERR, "Couldn't register PSCI handler.\n"); + + /* Inform SoC layer of CPU_ON entry point. */ + psci_soc_init(cpu_on_entry); +} diff --git a/src/arch/arm64/armv8/secmon/secmon.h b/src/arch/arm64/armv8/secmon/secmon.h new file mode 100644 index 0000000000..df57e98241 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/secmon.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef __SECMON_SECMON_H__ +#define __SECMON_SECMON_H__ + +/* + * The secmon_trampoline() switches mode to EL3t reinitializing the both + * EL3t and EL3h stacks. + */ +void secmon_trampoline(void *entry, void *arg); + +/* Wait for action to take place. */ +void secmon_wait_for_action(void); + +#endif /* __SECMON_SECMON_H__ */ diff --git a/src/arch/arm64/armv8/secmon/secmon_init.c b/src/arch/arm64/armv8/secmon/secmon_init.c new file mode 100644 index 0000000000..7d7f8bb811 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/secmon_init.c @@ -0,0 +1,137 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "secmon.h" + +static void secmon_init(struct secmon_params *params, int bsp); + +static void secmon_init_bsp(void *arg) +{ + secmon_init(arg, 1); +} + +static void secmon_init_nonbsp(void *arg) +{ + secmon_init(arg, 0); +} + +/* + * This variable holds entry point for secmon init code. Once the stacks are + * setup by the stage_entry.S, it jumps to c_entry. + */ +void (*c_entry[2])(void *) = { &secmon_init_bsp, &secmon_init_nonbsp }; + +static void cpu_resume(void *unused) +{ + psci_cpu_entry(); +} + +static void cpu_resume_init(void) +{ + /* Change entry points into secmon. */ + c_entry[0] = c_entry[1] = cpu_resume; + dcache_clean_by_mva(&c_entry, sizeof(c_entry)); + + /* Back up state. */ + startup_save_cpu_data(); +} + +static void start_up_cpu(void *arg) +{ + struct secmon_params *params = arg; + struct cpu_action *action; + + if (cpu_is_bsp()) + action = ¶ms->bsp; + else + action = ¶ms->secondary; + + + if (action->run == NULL) + psci_turn_off_self(); + + psci_turn_on_self(action); +} + +static void cpu_init(int bsp) +{ + struct cpu_info *ci = cpu_info(); + + ci->id = smp_processor_id(); + cpu_mark_online(ci); + + if (bsp) + cpu_set_bsp(); +} + +static void wait_for_all_cpus(size_t expected) +{ + while (cpus_online() != expected) + ; +} + +static void secmon_init(struct secmon_params *params, int bsp) +{ + struct cpu_action action = { + .run = start_up_cpu, + .arg = params, + }; + + exception_hwinit(); + cpu_init(bsp); + + if (!cpu_is_bsp()) + secmon_wait_for_action(); + + /* Wait for all CPUs to enter secmon. */ + wait_for_all_cpus(params->online_cpus); + + smc_init(); + psci_init((uintptr_t)arm64_cpu_startup_resume); + + /* Initialize the resume path. */ + cpu_resume_init(); + + /* Make sure all non-BSP CPUs take action before the BSP. */ + arch_run_on_all_cpus_but_self_async(&action); + /* Turn on BSP. */ + start_up_cpu(params); + + printk(BIOS_ERR, "CPU turn on failed for BSP.\n"); + + secmon_wait_for_action(); +} + +void secmon_wait_for_action(void) +{ + arch_cpu_wait_for_action(); +} diff --git a/src/arch/arm64/armv8/secmon/smc.c b/src/arch/arm64/armv8/secmon/smc.c new file mode 100644 index 0000000000..ae0f130179 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/smc.c @@ -0,0 +1,165 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +enum { + EC_SMC32 = 0x13, + EC_SMC64 = 0x17, + + SMC_NUM_RANGES = 8, +}; + +struct smc_range { + uint32_t func_begin; + uint32_t func_end; + int (*handler)(struct smc_call *); +}; + +struct smc_ranges { + size_t used; + struct smc_range handlers[SMC_NUM_RANGES]; +}; + +static struct smc_ranges smc_functions; + +static struct smc_range *smc_handler_by_function(uint32_t fid) +{ + int i; + + for (i = 0; i < smc_functions.used; i++) { + struct smc_range *r = &smc_functions.handlers[i]; + + if (fid >= r->func_begin && fid <= r->func_end) + return r; + } + + return NULL; +} + +int smc_register_range(uint32_t min, uint32_t max, int (*h)(struct smc_call *)) +{ + struct smc_range *r; + + if (smc_functions.used == SMC_NUM_RANGES) + return -1; + + if (min > max) + return -1; + + /* This check isn't exhaustive but it's fairly quick. */ + if (smc_handler_by_function(min) || smc_handler_by_function(max)) + return -1; + + r = &smc_functions.handlers[smc_functions.used]; + r->func_begin = min; + r->func_end = max; + r->handler = h; + smc_functions.used++; + + return 0; +} + +static int smc_cleanup(struct exc_state *state, struct smc_call *smc, int ret) +{ + memcpy(&state->regs.x, &smc->results, sizeof(smc->results)); + + return ret; +} + +static int smc_return_with_error(struct exc_state *state, struct smc_call *smc) +{ + smc32_return(smc, SMC_UNKNOWN_FUNC); + return smc_cleanup(state, smc, EXC_RET_HANDLED); +} + +static int smc_handler(struct exc_state *state, uint64_t vector_id) +{ + struct smc_call smc_storage; + struct smc_call *smc = &smc_storage; + uint32_t exception_class; + uint32_t esr; + struct smc_range *r; + + memcpy(&smc->args, &state->regs.x, sizeof(smc->args)); + memcpy(&smc->results, &state->regs.x, sizeof(smc->results)); + + esr = raw_read_esr_el3(); + exception_class = (esr >> 26) & 0x3f; + + /* No support for 32-bit SMC calls. */ + if (exception_class == EC_SMC32) + return smc_return_with_error(state, smc); + + /* Check to ensure this is an SMC from aarch64. */ + if (exception_class != EC_SMC64) + return EXC_RET_IGNORED; + + /* Ensure immediate value is 0. */ + if ((esr & 0xffff) != 0) + return smc_return_with_error(state, smc); + + r = smc_handler_by_function(smc_function_id(smc)); + + if (r != NULL) { + if (!r->handler(smc)) + return smc_cleanup(state, smc, EXC_RET_HANDLED); + } + + return smc_return_with_error(state, smc); +} + +/* SMC calls can be generated by 32-bit or 64-bit code. */ +static struct exception_handler smc_handler64 = { + .handler = &smc_handler, +}; + +static struct exception_handler smc_handler32 = { + .handler = &smc_handler, +}; + +static void enable_smc(void *arg) +{ + uint32_t scr; + + /* Enable SMC */ + scr = raw_read_scr_el3(); + scr &= ~(SCR_SMC_MASK); + scr |= SCR_SMC_ENABLE; + raw_write_scr_el3(scr); +} + +void smc_init(void) +{ + struct cpu_action action = { + .run = enable_smc, + }; + + arch_run_on_all_cpus_async(&action); + + /* Register SMC handlers. */ + exception_handler_register(EXC_VID_LOW64_SYNC, &smc_handler64); + exception_handler_register(EXC_VID_LOW32_SYNC, &smc_handler32); +} diff --git a/src/arch/arm64/armv8/secmon/trampoline.S b/src/arch/arm64/armv8/secmon/trampoline.S new file mode 100644 index 0000000000..cb6a4e4a93 --- /dev/null +++ b/src/arch/arm64/armv8/secmon/trampoline.S @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +/* + * Call entry(arg) after reinitializing stack state. + * void secmon_trampoline(void *entry, void *arg); + */ +ENTRY(secmon_trampoline) + mov x22, x0 /* x22 = function pointer */ + mov x23, x1 /* x23 = argument */ + bl smp_processor_id /* x0 = cpu */ + mov x24, x0 + + /* Set the exception stack for this cpu. */ + bl cpu_get_exception_stack + msr SPSel, #1 + isb + mov sp, x0 + + /* Have stack pointer use SP_EL0. */ + msr SPSel, #0 + isb + + /* Set stack for this cpu. */ + mov x0, x24 /* x0 = cpu */ + bl cpu_get_stack + mov sp, x0 + + /* Call the function with specified argument. */ + mov x1, x22 + mov x0, x23 + br x1 +ENDPROC(secmon_trampoline) diff --git a/src/arch/arm64/armv8/secmon_loader.c b/src/arch/arm64/armv8/secmon_loader.c new file mode 100644 index 0000000000..7a6e3ee738 --- /dev/null +++ b/src/arch/arm64/armv8/secmon_loader.c @@ -0,0 +1,159 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * secmon_loader.c: Responsible for loading the rmodule, providing entry point + * and parameter location for the rmodule. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* SECMON entry point encoded as an rmodule */ +extern unsigned char _binary_secmon_start[]; + +typedef void (*secmon_entry_t)(struct secmon_params *); + +void __attribute__((weak)) soc_get_secmon_base_size(uint64_t *secmon_base, size_t *secmon_size) +{ + /* Default weak implementation initializes to 0 */ + *secmon_base = 0; + *secmon_size = 0; +} + +static secmon_entry_t secmon_load_rmodule(void) +{ + struct rmodule secmon_mod; + uint64_t secmon_base; + size_t secmon_size; + + /* Get base address and size of the area available for secure monitor + * rmodule. + */ + soc_get_secmon_base_size(&secmon_base, &secmon_size); + + if ((secmon_base == 0) || (secmon_size == 0)) { + printk(BIOS_ERR, "ARM64: secmon_base / secmon_size invalid\n"); + return NULL; + } + + printk(BIOS_DEBUG,"secmon_base:%lx,secmon_size:%lx\n", + (unsigned long)secmon_base, (unsigned long)secmon_size); + + /* Fail if can't parse secmon module */ + if (rmodule_parse(&_binary_secmon_start, &secmon_mod)) { + printk(BIOS_ERR, "ARM64: secmon_mod not found\n"); + return NULL; + } + + /* Load rmodule at secmon_base */ + if (rmodule_load((void *)secmon_base, &secmon_mod)) { + printk(BIOS_ERR, "ARM64:secmon_mod cannot load\n"); + return NULL; + } + + /* Identify the entry point for secure monitor */ + return rmodule_entry(&secmon_mod); +} + +struct secmon_runit { + secmon_entry_t entry; + struct secmon_params params; +}; + +static void secmon_start(void *arg) +{ + uint32_t scr; + secmon_entry_t entry; + struct secmon_params *p; + struct secmon_runit *r = arg; + + entry = r->entry; + p = &r->params; + + /* Obtain secondary entry point for non-BSP CPUs. */ + if (!cpu_is_bsp()) + entry = secondary_entry_point(entry); + + printk(BIOS_DEBUG, "CPU%x entering secure monitor %p.\n", + cpu_info()->id, entry); + + /* We want to enforce the following policies: + * NS bit is set for lower EL + */ + scr = raw_read_scr_el3(); + scr |= SCR_NS; + raw_write_scr_el3(scr); + + entry(p); +} + +static void fill_secmon_params(struct secmon_params *p, + void (*bsp_entry)(void *), void *bsp_arg) +{ + const struct spintable_attributes *spin_attrs; + + memset(p, 0, sizeof(*p)); + + p->online_cpus = cpus_online(); + + spin_attrs = spintable_get_attributes(); + + if (spin_attrs != NULL) { + p->secondary.run = spin_attrs->entry; + p->secondary.arg = spin_attrs->addr; + } + + p->bsp.run = bsp_entry; + p->bsp.arg = bsp_arg; +} + +void secmon_run(void (*entry)(void *), void *cb_tables) +{ + static struct secmon_runit runit; + struct cpu_action action = { + .run = secmon_start, + .arg = &runit, + }; + + printk(BIOS_SPEW, "payload jump @ %p\n", entry); + + if (get_current_el() != EL3) { + printk(BIOS_DEBUG, "Secmon Error: Can only be loaded in EL3\n"); + return; + } + + runit.entry = secmon_load_rmodule(); + + if (runit.entry == NULL) + die("ARM64 Error: secmon load error"); + + printk(BIOS_DEBUG, "ARM64: Loaded the el3 monitor...jumping to %p\n", + runit.entry); + + fill_secmon_params(&runit.params, entry, cb_tables); + + arch_run_on_all_cpus_but_self_async(&action); + secmon_start(&runit); +} diff --git a/src/arch/arm64/boot.c b/src/arch/arm64/boot.c new file mode 100644 index 0000000000..ed650e57b6 --- /dev/null +++ b/src/arch/arm64/boot.c @@ -0,0 +1,60 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) +{ + void (*payload_entry)(void *) = entry; + + void *cb_tables = cbmem_find(CBMEM_ID_CBTABLE); + uint8_t current_el = get_current_el(); + + printk(BIOS_SPEW, "entry = %p\n", entry); + + secmon_run(payload_entry, cb_tables); + + /* Start the other CPUs spinning. */ + spintable_start(); + + /* If current EL is not EL3, jump to payload at same EL. */ + if (current_el != EL3) { + cache_sync_instructions(); + /* Point of no-return */ + payload_entry(cb_tables); + } + + /* If current EL is EL3, we transition to payload in EL2. */ + struct exc_state exc_state; + + memset(&exc_state, 0, sizeof(exc_state)); + + exc_state.elx.spsr = get_eret_el(EL2, SPSR_USE_L); + + cache_sync_instructions(); + transition_with_entry(entry, cb_tables, &exc_state); +} diff --git a/src/arch/arm64/c_entry.c b/src/arch/arm64/c_entry.c new file mode 100644 index 0000000000..bf7a3358ce --- /dev/null +++ b/src/arch/arm64/c_entry.c @@ -0,0 +1,69 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "cpu-internal.h" + +void __attribute__((weak)) arm64_soc_init(void) +{ + /* Default weak implementation does nothing. */ +} + +static void seed_stack(void) +{ + char *stack_begin; + uint64_t *slot; + int i; + int size; + + stack_begin = cpu_get_stack(smp_processor_id()); + stack_begin -= CONFIG_STACK_SIZE; + slot = (void *)stack_begin; + + /* Pad out 256 bytes for current usage. */ + size = CONFIG_STACK_SIZE - 256; + size /= sizeof(*slot); + for (i = 0; i < size; i++) + *slot++ = 0xdeadbeefdeadbeefULL; +} + +static void arm64_init(void) +{ + cpu_set_bsp(); + seed_stack(); + arm64_soc_init(); + main(); +} + +/* + * This variable holds entry point for CPUs starting up. The first + * element is the BSP path, and the second is the non-BSP path. + */ +void (*c_entry[2])(void) = { &arm64_init, &arch_secondary_cpu_init }; + +void *prepare_secondary_cpu_startup(void) +{ + startup_save_cpu_data(); + + return secondary_entry_point(&arm64_cpu_startup_resume); +} diff --git a/src/arch/arm64/cbmem.c b/src/arch/arm64/cbmem.c new file mode 100644 index 0000000000..b33e9b8cd8 --- /dev/null +++ b/src/arch/arm64/cbmem.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +unsigned long get_top_of_ram(void); + +unsigned long get_top_of_ram(void) +{ + return CONFIG_RAMTOP; +} + +void *cbmem_top(void) +{ + return (void *)get_top_of_ram(); +} diff --git a/src/arch/arm64/cpu-internal.h b/src/arch/arm64/cpu-internal.h new file mode 100644 index 0000000000..266dc633c6 --- /dev/null +++ b/src/arch/arm64/cpu-internal.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef ARCH_CPU_INTERNAL_H +#define ARCH_CPU_INTERNAL_H + +/* + * Do the necessary work to prepare for secondary CPUs coming up. The + * SoC will call this function before bringing up the other CPUs. The + * entry point for the seoncdary CPUs is returned. + */ +void *prepare_secondary_cpu_startup(void); + +/* + * Code path for the non-BSP CPUs. This is an internal function used. + */ +void arch_secondary_cpu_init(void); + +/* Return the top of the stack for the specified cpu. */ +void *cpu_get_stack(unsigned int cpu); + +/* Return the top of the exception stack for the specified cpu. */ +void *cpu_get_exception_stack(unsigned int cpu); + +#endif /* ARCH_CPU_INTERNAL_H */ diff --git a/src/arch/arm64/cpu.c b/src/arch/arm64/cpu.c new file mode 100644 index 0000000000..1427525839 --- /dev/null +++ b/src/arch/arm64/cpu.c @@ -0,0 +1,220 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "cpu-internal.h" + +struct cpu_info cpu_infos[CONFIG_MAX_CPUS]; +struct cpu_info *bsp_cpu_info; + +struct cpu_info *cpu_info(void) +{ + return cpu_info_for_cpu(smp_processor_id()); +} + +size_t cpus_online(void) +{ + int i; + size_t num = 0; + + for (i = 0; i < ARRAY_SIZE(cpu_infos); i++) { + if (cpu_online(cpu_info_for_cpu(i))) + num++; + } + + return num; +} + +static inline int action_queue_empty(struct cpu_action_queue *q) +{ + return load_acquire_exclusive(&q->todo) == NULL; +} + +static inline int action_completed(struct cpu_action_queue *q, + struct cpu_action *action) +{ + return load_acquire(&q->completed) == action; +} + +static inline void wait_for_action_queue_slot(struct cpu_action_queue *q) +{ + while (!action_queue_empty(q)) + wfe(); +} + +static void wait_for_action_complete(struct cpu_action_queue *q, + struct cpu_action *a) +{ + while (!action_completed(q, a)) + wfe(); +} + +static struct cpu_action *wait_for_action(struct cpu_action_queue *q, + struct cpu_action *local) +{ + struct cpu_action *action; + + while (action_queue_empty(q)) + wfe(); + + /* + * Keep original address, but use a local copy for async processing. + */ + do { + action = load_acquire_exclusive(&q->todo); + *local = *action; + } while (!store_release_exclusive(&q->todo, NULL)); + + return action; +} + +static void queue_action(struct cpu_action_queue *q, struct cpu_action *action) +{ + do { + wait_for_action_queue_slot(q); + if (load_acquire_exclusive(&q->todo) != NULL) + continue; + } while (!store_release_exclusive(&q->todo, action)); +} + +static void action_queue_complete(struct cpu_action_queue *q, + struct cpu_action *action) +{ + /* Mark completion and send events to waiters. */ + store_release(&q->completed, action); + sev(); +} + +static void action_run(struct cpu_action *action) +{ + action->run(action->arg); +} + +static void action_run_on_cpu(struct cpu_info *ci, struct cpu_action *action, + int sync) +{ + struct cpu_action_queue *q = &ci->action_queue; + + /* Don't run actions on non-online cpus. */ + if (!cpu_online(ci)) + return; + + if (ci->id == smp_processor_id()) { + action->run(action->arg); + return; + } + + queue_action(q, action); + /* Wait for CPU to pick it up. Empty slot means it was picked up. */ + wait_for_action_queue_slot(q); + /* Wait for completion if requested. */ + if (sync) + wait_for_action_complete(q, action); +} + +static int __arch_run_on_cpu(unsigned int cpu, struct cpu_action *action, + int sync) +{ + struct cpu_info *ci; + + if (cpu >= CONFIG_MAX_CPUS) + return -1; + + ci = cpu_info_for_cpu(cpu); + + action_run_on_cpu(ci, action, sync); + + return 0; +} + +int arch_run_on_cpu(unsigned int cpu, struct cpu_action *action) +{ + return __arch_run_on_cpu(cpu, action, 1); +} + +int arch_run_on_cpu_async(unsigned int cpu, struct cpu_action *action) +{ + return __arch_run_on_cpu(cpu, action, 0); +} + +static int __arch_run_on_all_cpus(struct cpu_action *action, int sync) +{ + int i; + + for (i = 0; i < CONFIG_MAX_CPUS; i++) + action_run_on_cpu(cpu_info_for_cpu(i), action, sync); + + return 0; +} + +static int __arch_run_on_all_cpus_but_self(struct cpu_action *action, int sync) +{ + int i; + struct cpu_info *me = cpu_info(); + + for (i = 0; i < CONFIG_MAX_CPUS; i++) { + struct cpu_info *ci = cpu_info_for_cpu(i); + if (ci == me) + continue; + action_run_on_cpu(ci, action, sync); + } + + return 0; +} + +int arch_run_on_all_cpus(struct cpu_action *action) +{ + return __arch_run_on_all_cpus(action, 1); +} + +int arch_run_on_all_cpus_async(struct cpu_action *action) +{ + return __arch_run_on_all_cpus(action, 0); +} + +int arch_run_on_all_cpus_but_self(struct cpu_action *action) +{ + return __arch_run_on_all_cpus_but_self(action, 1); +} + +int arch_run_on_all_cpus_but_self_async(struct cpu_action *action) +{ + return __arch_run_on_all_cpus_but_self(action, 0); +} + + +void arch_cpu_wait_for_action(void) +{ + struct cpu_info *ci = cpu_info(); + struct cpu_action_queue *q = &ci->action_queue; + + while (1) { + struct cpu_action *orig; + struct cpu_action action; + + orig = wait_for_action(q, &action); + + action_run(&action); + action_queue_complete(q, orig); + } +} diff --git a/src/arch/arm64/cpu_ramstage.c b/src/arch/arm64/cpu_ramstage.c new file mode 100644 index 0000000000..466ca0124f --- /dev/null +++ b/src/arch/arm64/cpu_ramstage.c @@ -0,0 +1,254 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cpu-internal.h" + +static inline void cpu_disable_dev(device_t dev) +{ + dev->enabled = 0; +} + +static struct cpu_driver *locate_cpu_driver(uint32_t midr) +{ + struct cpu_driver *cur; + + for (cur = cpu_drivers; cur != ecpu_drivers; cur++) { + const struct cpu_device_id *id_table = cur->id_table; + + for (; id_table->midr != CPU_ID_END; id_table++) { + if (id_table->midr == midr) + return cur; + } + } + return NULL; +} + +static int cpu_set_device_operations(device_t dev) +{ + uint32_t midr; + struct cpu_driver *driver; + + midr = raw_read_midr_el1(); + driver = locate_cpu_driver(midr); + + if (driver == NULL) { + printk(BIOS_WARNING, "No CPU driver for MIDR %08x\n", midr); + return -1; + } + dev->ops = driver->ops; + return 0; +} + +/* Set up default SCR values. */ +static void el3_init(void) +{ + uint32_t scr; + + if (get_current_el() != EL3) + return; + + scr = raw_read_scr_el3(); + /* Default to non-secure EL1 and EL0. */ + scr &= ~(SCR_NS_MASK); + scr |= SCR_NS_ENABLE; + /* Disable IRQ, FIQ, and external abort interrupt routing. */ + scr &= ~(SCR_IRQ_MASK | SCR_FIQ_MASK | SCR_EA_MASK); + scr |= SCR_IRQ_DISABLE | SCR_FIQ_DISABLE | SCR_EA_DISABLE; + /* Enable HVC */ + scr &= ~(SCR_HVC_MASK); + scr |= SCR_HVC_ENABLE; + /* Disable SMC */ + scr &= ~(SCR_SMC_MASK); + scr |= SCR_SMC_DISABLE; + /* Disable secure instruction fetches. */ + scr &= ~(SCR_SIF_MASK); + scr |= SCR_SIF_DISABLE; + /* All lower exception levels 64-bit by default. */ + scr &= ~(SCR_RW_MASK); + scr |= SCR_LOWER_AARCH64; + /* Disable secure EL1 access to secure timer. */ + scr &= ~(SCR_ST_MASK); + scr |= SCR_ST_DISABLE; + /* Don't trap on WFE or WFI instructions. */ + scr &= ~(SCR_TWI_MASK | SCR_TWE_MASK); + scr |= SCR_TWI_DISABLE | SCR_TWE_DISABLE; + raw_write_scr_el3(scr); + isb(); +} + +static void init_this_cpu(void *arg) +{ + struct cpu_info *ci = arg; + device_t dev = ci->cpu; + + cpu_set_device_operations(dev); + + printk(BIOS_DEBUG, "CPU%x: MPIDR: %llx\n", ci->id, ci->mpidr); + + /* Initialize the GIC. */ + gic_init(); + + if (dev->ops != NULL && dev->ops->init != NULL) { + dev->initialized = 1; + printk(BIOS_DEBUG, "%s init\n", dev_path(dev)); + dev->ops->init(dev); + } +} + +/* Fill in cpu_info structures according to device tree. */ +static void init_cpu_info(struct bus *bus) +{ + device_t cur; + + for (cur = bus->children; cur != NULL; cur = cur->sibling) { + struct cpu_info *ci; + unsigned int id = cur->path.cpu.id; + + if (cur->path.type != DEVICE_PATH_CPU) + continue; + + /* IDs are currently mapped 1:1 with logical CPU numbers. */ + if (id >= CONFIG_MAX_CPUS) { + printk(BIOS_WARNING, + "CPU id %x too large. Disabling.\n", id); + cpu_disable_dev(cur); + continue; + } + + ci = cpu_info_for_cpu(id); + if (ci->cpu != NULL) { + printk(BIOS_WARNING, + "Duplicate ID %x in device tree.\n", id); + cpu_disable_dev(cur); + } + + ci->cpu = cur; + ci->id = cur->path.cpu.id; + } +} + +void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops) +{ + size_t max_cpus; + size_t i; + struct cpu_info *ci; + void (*entry)(void); + struct bus *bus; + + if (cluster->path.type != DEVICE_PATH_CPU_CLUSTER) { + printk(BIOS_ERR, + "CPU init failed. Device is not a CPU_CLUSTER: %s\n", + dev_path(cluster)); + return; + } + + bus = cluster->link_list; + + /* Check if no children under this device. */ + if (bus == NULL) + return; + + /* + * el3_init must be performed prior to prepare_secondary_cpu_startup. + * This is important since el3_init initializes SCR values on BSP CPU + * and then prepare_secondary_cpu_startup reads the initialized SCR + * value and saves it for use by non-BSP CPUs. + */ + el3_init(); + /* Mark current cpu online. */ + cpu_mark_online(cpu_info()); + entry = prepare_secondary_cpu_startup(); + + /* Initialize the cpu_info structures. */ + init_cpu_info(bus); + max_cpus = cntrl_ops->total_cpus(); + + if (max_cpus > CONFIG_MAX_CPUS) { + printk(BIOS_WARNING, + "max_cpus (%zu) exceeds CONFIG_MAX_CPUS (%zu).\n", + max_cpus, (size_t)CONFIG_MAX_CPUS); + max_cpus = CONFIG_MAX_CPUS; + } + + for (i = 0; i < max_cpus; i++) { + device_t dev; + struct cpu_action action; + struct stopwatch sw; + + ci = cpu_info_for_cpu(i); + dev = ci->cpu; + + /* Disregard CPUs not in device tree. */ + if (dev == NULL) + continue; + + /* Skip disabled CPUs. */ + if (!dev->enabled) + continue; + + if (!cpu_online(ci)) { + /* Start the CPU. */ + printk(BIOS_DEBUG, "Starting CPU%x\n", ci->id); + + if (cntrl_ops->start_cpu(ci->id, entry)) { + printk(BIOS_ERR, + "Failed to start CPU%x\n", ci->id); + continue; + } + stopwatch_init_msecs_expire(&sw, 1000); + /* Wait for CPU to come online. */ + while (!stopwatch_expired(&sw)) { + if (!cpu_online(ci)) + continue; + printk(BIOS_DEBUG, + "CPU%x online in %ld usecs.\n", + ci->id, stopwatch_duration_usecs(&sw)); + break; + } + } + + if (!cpu_online(ci)) { + printk(BIOS_DEBUG, + "CPU%x failed to come online in %ld usecs.\n", + ci->id, stopwatch_duration_usecs(&sw)); + continue; + } + + /* Send it the init action. */ + action.run = init_this_cpu; + action.arg = ci; + arch_run_on_cpu(ci->id, &action); + } +} + +void arch_secondary_cpu_init(void) +{ + /* Mark this CPU online. */ + cpu_mark_online(cpu_info()); + + arch_cpu_wait_for_action(); +} diff --git a/src/cpu/samsung/exynos5250/sata.h b/src/arch/arm64/div0.c similarity index 67% rename from src/cpu/samsung/exynos5250/sata.h rename to src/arch/arm64/div0.c index 912228ea53..ab06ad3bee 100644 --- a/src/cpu/samsung/exynos5250/sata.h +++ b/src/arch/arm64/div0.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2012 The Chromium OS Authors. + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -19,9 +20,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ -#ifndef __EXYNOS5_SATA_H -#define __EXYNOS5_SATA_H -int exynos5_sata_init(const void *blob); -#endif +#include +void __div0(void); // called from asm so no need for a prototype in a header + +/* Replacement (=dummy) for GNU/Linux division-by zero handler */ +/* recursion is ok here because we have no formats ... */ +void __div0 (void) +{ + printk(BIOS_EMERG, "DIVIDE BY ZERO! continuing ... \n"); +} diff --git a/src/arch/arm64/eabi_compat.c b/src/arch/arm64/eabi_compat.c new file mode 100644 index 0000000000..c27c54e350 --- /dev/null +++ b/src/arch/arm64/eabi_compat.c @@ -0,0 +1,28 @@ +/* + * Utility functions needed for (some) EABI conformant tool chains. + * + * (C) Copyright 2009 Wolfgang Denk + * + * This program is Free Software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include + +int raise (int signum) __attribute__((used)); +int raise (int signum) +{ + return 0; +} + +void __aeabi_unwind_cpp_pr0(void) __attribute__((used)); +void __aeabi_unwind_cpp_pr0(void) +{ +}; + +void __aeabi_unwind_cpp_pr1(void) __attribute__((used)); +void __aeabi_unwind_cpp_pr1(void) +{ +}; diff --git a/src/arch/arm64/early_console.c b/src/arch/arm64/early_console.c new file mode 100644 index 0000000000..e78155ca8d --- /dev/null +++ b/src/arch/arm64/early_console.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +/* FIXME: need to make console driver more generic */ +void console_tx_byte(unsigned char byte) +{ + if (byte == '\n') + console_tx_byte('\r'); + +#if CONFIG_CONSOLE_SERIAL8250MEM + if (oxford_oxpcie_present) { + uart8250_mem_tx_byte( + CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000, byte); + } +#endif +#if CONFIG_CONSOLE_SERIAL_UART + uart_tx_byte(byte); +#endif +#if CONFIG_USBDEBUG + usbdebug_tx_byte(0, byte); +#endif +#if CONFIG_CONSOLE_CBMEM && !defined(__BOOTBLOCK__) + cbmemc_tx_byte(byte); +#endif +} + +void console_tx_flush(void) +{ +#if CONFIG_CONSOLE_SERIAL8250MEM + uart8250_mem_tx_flush(CONFIG_OXFORD_OXPCIE_BASE_ADDRESS + 0x1000); +#endif +#if CONFIG_CONSOLE_SERIAL_UART + uart_tx_flush(); +#endif +#if CONFIG_USBDEBUG + usbdebug_tx_flush(0); +#endif +} diff --git a/src/arch/arm64/id.S b/src/arch/arm64/id.S new file mode 100644 index 0000000000..a588f1e1da --- /dev/null +++ b/src/arch/arm64/id.S @@ -0,0 +1,20 @@ +#include + + .section ".id", "a", %progbits + + .globl __id_start +__id_start: +ver: + .asciz COREBOOT_VERSION +vendor: + .asciz CONFIG_MAINBOARD_VENDOR +part: + .asciz CONFIG_MAINBOARD_PART_NUMBER +.long __id_end - ver /* Reverse offset to the vendor id */ +.long __id_end - vendor /* Reverse offset to the vendor id */ +.long __id_end - part /* Reverse offset to the part number */ +.long CONFIG_ROM_SIZE /* Size of this romimage */ + .globl __id_end + +__id_end: +.previous diff --git a/src/arch/arm64/include/arch/asm.h b/src/arch/arm64/include/arch/asm.h new file mode 100644 index 0000000000..96c9d13957 --- /dev/null +++ b/src/arch/arm64/include/arch/asm.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_ARM64_ASM_H +#define __ARM_ARM64_ASM_H + +#define ENDPROC(name) \ + .type name, %function; \ + END(name) + +#define ENTRY_WITH_ALIGN(name, bits) \ + .section .text.name, "ax", %progbits; \ + .global name; \ + .align bits; \ + name: + +#define ENTRY(name) ENTRY_WITH_ALIGN(name, 0) + +#define END(name) \ + .size name, .-name + +/* + * Certain SoCs have an alignment requiremnt for the CPU reset vector. + * Align to a 64 byte typical cacheline for now. + */ +#define CPU_RESET_ENTRY(name) ENTRY_WITH_ALIGN(name, 6) + +#endif /* __ARM_ARM64_ASM_H */ diff --git a/src/arch/arm64/include/arch/boot/boot.h b/src/arch/arm64/include/arch/boot/boot.h new file mode 100644 index 0000000000..16763c68f6 --- /dev/null +++ b/src/arch/arm64/include/arch/boot/boot.h @@ -0,0 +1,8 @@ +#ifndef ASM_ARM64_BOOT_H +#define ASM_ARM64_BOOT_H + +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_AARCH64 + +#endif /* ASM_ARM_BOOT_H */ diff --git a/src/arch/arm64/include/arch/byteorder.h b/src/arch/arm64/include/arch/byteorder.h new file mode 100644 index 0000000000..8dc069f486 --- /dev/null +++ b/src/arch/arm64/include/arch/byteorder.h @@ -0,0 +1,27 @@ +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +#define __LITTLE_ENDIAN 1234 + +#include +#include + +#define cpu_to_le64(x) ((uint64_t)(x)) +#define le64_to_cpu(x) ((uint64_t)(x)) +#define cpu_to_le32(x) ((uint32_t)(x)) +#define le32_to_cpu(x) ((uint32_t)(x)) +#define cpu_to_le16(x) ((uint16_t)(x)) +#define le16_to_cpu(x) ((uint16_t)(x)) +#define cpu_to_be64(x) swab64(x) +#define be64_to_cpu(x) swab64(x) +#define cpu_to_be32(x) swab32((x)) +#define be32_to_cpu(x) swab32((x)) +#define cpu_to_be16(x) swab16((x)) +#define be16_to_cpu(x) swab16((x)) + +#define ntohll(x) be64_to_cpu(x) +#define htonll(x) cpu_to_be64(x) +#define ntohl(x) be32_to_cpu(x) +#define htonl(x) cpu_to_be32(x) + +#endif /* _BYTEORDER_H */ diff --git a/src/arch/arm64/include/arch/clock.h b/src/arch/arm64/include/arch/clock.h new file mode 100644 index 0000000000..939aa208ce --- /dev/null +++ b/src/arch/arm64/include/arch/clock.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_CLOCK_H_ +#define __ARM_CLOCK_H_ + +#include + +void set_cntfrq(uint32_t); + +#endif //__ARM_CLOCK_H_ diff --git a/src/arch/armv7/include/arch/cpu.h b/src/arch/arm64/include/arch/early_variables.h similarity index 60% rename from src/arch/armv7/include/arch/cpu.h rename to src/arch/arm64/include/arch/early_variables.h index 20a12c929e..31b26c739a 100644 --- a/src/arch/armv7/include/arch/cpu.h +++ b/src/arch/arm64/include/arch/early_variables.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2012 Google, Inc + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,30 +17,18 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -#ifndef __ARCH_CPU_H__ -#define __ARCH_CPU_H__ - -#define asmlinkage - -#if !defined(__PRE_RAM__) -#include - -struct cpu_driver { - struct device_operations *ops; - struct cpu_device_id *id_table; -}; - -struct cpu_info { - device_t cpu; - unsigned long index; -}; - -struct cpuinfo_arm { - uint8_t arm; /* CPU family */ - uint8_t arm_vendor; /* CPU vendor */ - uint8_t arm_model; -}; +#ifndef ARCH_EARLY_VARIABLES_H +#define ARCH_EARLY_VARIABLES_H +#if CONFIG_CAR_MIGRATION + #error "This is ARM, silly... we don't have CAR here." #endif -#endif /* __ARCH_CPU_H__ */ +#define CAR_GLOBAL + +static inline void *car_get_var_ptr(void *var) { return var; } +#define car_get_var(var) (var) +#define car_set_var(var, val) do { (var) = (val); } while (0) +static inline void car_migrate_variables(void) { } + +#endif diff --git a/src/arch/arm64/include/arch/header.ld b/src/arch/arm64/include/arch/header.ld new file mode 100644 index 0000000000..bb32a93554 --- /dev/null +++ b/src/arch/arm64/include/arch/header.ld @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +PHDRS +{ + to_load PT_LOAD; +} + +#ifdef __BOOTBLOCK__ +TARGET(binary) +#endif +ENTRY(stage_entry) diff --git a/src/arch/arm64/include/arch/hlt.h b/src/arch/arm64/include/arch/hlt.h new file mode 100644 index 0000000000..285b6f8786 --- /dev/null +++ b/src/arch/arm64/include/arch/hlt.h @@ -0,0 +1,9 @@ +#ifndef ARCH_HLT_H +#define ARCH_HLT_H + +static inline __attribute__((always_inline)) void hlt(void) +{ + for (;;) ; +} + +#endif /* ARCH_HLT_H */ diff --git a/src/arch/arm64/include/arch/io.h b/src/arch/arm64/include/arch/io.h new file mode 100644 index 0000000000..cd75fb8920 --- /dev/null +++ b/src/arch/arm64/include/arch/io.h @@ -0,0 +1,94 @@ +/* + * Originally imported from linux/include/asm-arm/io.h. This file has changed + * substantially since then. + * + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 08-Apr-2013 G Replaced several macros with inlines for type safety. + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. + * 04-Apr-1999 PJB Added check_signature. + * 12-Dec-1999 RMK More cleanups + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions + */ +#ifndef __ASM_ARM64_IO_H +#define __ASM_ARM64_IO_H + +#include +#include +#include + +/* + * FIXME: These are to avoid breaking existing ARM code. We should eventually + * re-factor all code to specify the data length intended. + */ +#define readb(a) read8(a) +#define writeb(v,a) write8(v,a) +#define readl(a) read32(a) +#define writel(v,a) write32(v,a) + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define out_arch(type,endian,a,v) write##type(cpu_to_##endian(v),a) +#define in_arch(type,endian,a) endian##_to_cpu(read##type(a)) + +#define out_le32(a,v) out_arch(l,le32,a,v) +#define out_le16(a,v) out_arch(w,le16,a,v) + +#define in_le32(a) in_arch(l,le32,a) +#define in_le16(a) in_arch(w,le16,a) + +#define out_be32(a,v) out_arch(l,be32,a,v) +#define out_be16(a,v) out_arch(w,be16,a,v) + +#define in_be32(a) in_arch(l,be32,a) +#define in_be16(a) in_arch(w,be16,a) + +#define out_8(a,v) writeb(v,a) +#define in_8(a) readb(a) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#endif /* __ASM_ARM64_IO_H */ diff --git a/src/arch/arm64/include/arch/memlayout.h b/src/arch/arm64/include/arch/memlayout.h new file mode 100644 index 0000000000..4cd5ded6b6 --- /dev/null +++ b/src/arch/arm64/include/arch/memlayout.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file contains macro definitions for memlayout.ld linker scripts. */ + +#ifndef __ARCH_MEMLAYOUT_H +#define __ARCH_MEMLAYOUT_H + +/* TODO: add SRAM TTB region and figure out the correct size/alignment for it */ + +/* ARM64 stacks need 16-byte alignment. The ramstage will set up its own stacks + * in BSS, so this is only used for the SRAM stages. */ +#ifdef __PRE_RAM__ +#define STACK(addr, size) \ + REGION(stack, addr, size, 16) \ + _ = ASSERT(size >= 2K, "stack should be >= 2K, see toolchain.inc"); +#else +#define STACK(addr, size) REGION(preram_stack, addr, size, 16) +#endif + +#endif /* __ARCH_MEMLAYOUT_H */ diff --git a/src/arch/arm64/include/arch/mpidr.h b/src/arch/arm64/include/arch/mpidr.h new file mode 100644 index 0000000000..0735a6a1b0 --- /dev/null +++ b/src/arch/arm64/include/arch/mpidr.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __ARCH_MPIDR_H__ +#define __ARCH_MPIDR_H__ + +#include +#include + +enum { + MPIDR_RES1_SHIFT = 31, + MPIDR_U_SHIFT = 30, + MPIDR_MT_SHIFT = 24, + + MPIDR_AFFINITY_0_SHIFT = 0, + MPIDR_AFFINITY_1_SHIFT = 8, + MPIDR_AFFINITY_2_SHIFT = 16, + MPIDR_AFFINITY_3_SHIFT = 32, + MPIDR_AFFINITY_MASK = 0xff, +}; + +static inline uint64_t mpidr_mask(uint8_t aff3, uint8_t aff2, + uint8_t aff1, uint8_t aff0) +{ + uint64_t mpidr = 0; + + mpidr |= (uint64_t)aff3 << MPIDR_AFFINITY_3_SHIFT; + mpidr |= (uint64_t)aff2 << MPIDR_AFFINITY_2_SHIFT; + mpidr |= (uint64_t)aff1 << MPIDR_AFFINITY_1_SHIFT; + mpidr |= (uint64_t)aff0 << MPIDR_AFFINITY_0_SHIFT; + + return mpidr; +} + +static inline uint64_t read_mpidr(void) +{ + return raw_read_mpidr_el1(); +} + +static inline uint64_t read_affinity_mpidr(void) +{ + uint64_t affinity_mask; + affinity_mask = mpidr_mask(MPIDR_AFFINITY_MASK, MPIDR_AFFINITY_MASK, + MPIDR_AFFINITY_MASK, MPIDR_AFFINITY_MASK); + return read_mpidr() & affinity_mask; +} + +#endif /* __ARCH_MPIDR_H__ */ diff --git a/src/arch/arm64/include/arch/pci_ops.h b/src/arch/arm64/include/arch/pci_ops.h new file mode 100644 index 0000000000..26a2c9b3ad --- /dev/null +++ b/src/arch/arm64/include/arch/pci_ops.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ARCH_ARM64_PCI_OPS_H +#define ARCH_ARM64_PCI_OPS_H + +/* V8 has PCI in some form. We will need to fill this in. */ +static inline const struct pci_bus_operations *pci_config_default(void) +{ + return NULL; +} + +#endif diff --git a/src/arch/arm64/include/arch/psci.h b/src/arch/arm64/include/arch/psci.h new file mode 100644 index 0000000000..b408f3d28c --- /dev/null +++ b/src/arch/arm64/include/arch/psci.h @@ -0,0 +1,234 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __ARCH_PSCI_H__ +#define __ARCH_PSCI_H__ + +#include +#include +#include + +/* Return Values */ +enum { + PSCI_RET_SUCCESS = 0, + PSCI_RET_NOT_SUPPORTED = -1, + PSCI_RET_INVALID_PARAMETERS = -2, + PSCI_RET_DENIED = -3, + PSCI_RET_ALREADY_ON = -4, + PSCI_RET_ON_PENDING = -5, + PSCI_RET_INTERNAL_FAILURE = -6, + PSCI_RET_NOT_PRESENT = -7, + PSCI_RET_DISABLED = -8, +}; + +/* Generic PSCI state. */ +enum { + PSCI_STATE_OFF = 0, + PSCI_STATE_ON_PENDING, + PSCI_STATE_ON, +}; + +/* Affinity level support. */ +enum { + PSCI_AFFINITY_LEVEL_0, + PSCI_AFFINITY_LEVEL_1, + PSCI_AFFINITY_LEVEL_2, + PSCI_AFFINITY_LEVEL_3, + PSCI_AFFINITY_ROOT, + PSCI_AFFINITY_LEVEL_HIGHEST = PSCI_AFFINITY_ROOT, +}; + +static inline int psci_level_below(int level) +{ + return level - 1; +} + +struct psci_node; + +struct psci_cpu_state { + struct cpu_info *ci; + struct cpu_action startup; + /* Ancestor of target to update state in CPU_ON case. */ + struct psci_node *ancestor; +}; + +struct psci_node_group { + size_t num; + struct psci_node *nodes; +}; + +struct psci_node { + uint64_t mpidr; + /* Affinity level of node. */ + int level; + /* Generic power state of this entity. */ + int state; + /* The SoC can stash its own state accounting in here. */ + int soc_state; + /* Parent of curernt entity. */ + struct psci_node *parent; + /* + * CPUs are leaves in the tree. They don't have children. The + * CPU-specific bits of storage can be shared with the children + * storage. + */ + union { + struct psci_node_group children; + struct psci_cpu_state cpu_state; + }; +}; + +static inline struct psci_node *psci_node_parent(const struct psci_node *n) +{ + return n->parent; +} + +static inline int psci_root_node(const struct psci_node *n) +{ + return psci_node_parent(n) == NULL; +} + +enum { + PSCI_CMD_ON, + PSCI_CMD_OFF, + PSCI_CMD_STANDBY, +}; + +/* + * PSCI actions are serialized into a command for the SoC to process. There are + * 2 phases of a command being processed: prepare and commit. The prepare() is + * called with the PSCI locks held for the state of the PSCI nodes. If + * successful, the appropriate locks will be dropped and commit() will be + * called with the same structure. It is permissible for the SoC support code + * to modify the struture passed in (e.g. to update the requested state_id to + * reflect dynamic constraints on how deep of a state to enter). + */ +struct psci_cmd { + /* Command type. */ + int type; + /* + * PSCI state id for PSCI_CMD_OFF and PSCI_CMD_STANDBY commands. + * A value of -1 indicates a CPU_OFF request. + */ + int state_id; + /* + * target is the command's target, but it can affect up to the + * ancestor entity. If target == ancestor then it only affects + * target, otherwise all entites up the hierarchy including ancestor. + */ + struct psci_node *target; + struct psci_node *ancestor; +}; + +struct psci_soc_ops { + /* + * Return number of entities one level below given parent affinitly + * level and mpidr. + */ + size_t (*children_at_level)(int parent_level, uint64_t mpidr); + + int (*cmd_prepare)(struct psci_cmd *cmd); + int (*cmd_commit)(struct psci_cmd *cmd); +}; + +/* Each SoC needs to provide the functions in the psci_soc_ops structure. */ +extern struct psci_soc_ops soc_psci_ops; + +/* PSCI Functions. */ +enum { + /* 32-bit System level functions. */ + PSCI_VERSION = SMC_FUNC_FAST32(0x4, 0x0), + PSCI_SYSTEM_OFF = SMC_FUNC_FAST32(0x4, 0x8), + PSCI_SYSTEM_RESET = SMC_FUNC_FAST32(0x4, 0x9), + + /* 32-bit CPU support functions. */ + PSCI_CPU_SUSPEND32 = SMC_FUNC_FAST32(0x4, 0x1), + PSCI_CPU_OFF32 = SMC_FUNC_FAST32(0x4, 0x2), + PSCI_CPU_ON32 = SMC_FUNC_FAST32(0x4, 0x3), + + /* 64-bit CPU support functions. */ + PSCI_CPU_SUSPEND64 = SMC_FUNC_FAST64(0x4, 0x1), + PSCI_CPU_OFF64 = SMC_FUNC_FAST64(0x4, 0x2), + PSCI_CPU_ON64 = SMC_FUNC_FAST64(0x4, 0x3), +}; + +/* Parameter arguments. */ +enum { + PSCI_PARAM_0 = 1, + PSCI_PARAM_1, + PSCI_PARAM_2, + PSCI_PARAM_3, + PSCI_RETURN_0 = 1, + PSCI_RETURN_1, + PSCI_RETURN_2, + PSCI_RETURN_3, +}; + +struct psci_func { + uint32_t id; + struct smc_call *smc; +}; + +static inline void psci_func_init(struct psci_func *pf, struct smc_call *smc) +{ + pf->id = smc_function_id(smc); + pf->smc = smc; +} + +static inline uint64_t psci64_arg(struct psci_func *pf, unsigned i) +{ + return smc64_arg(pf->smc, i); +} + +static inline uint32_t psci32_arg(struct psci_func *pf, unsigned i) +{ + return psci64_arg(pf, i); +} + +static inline void psci64_result(struct psci_func *pf, unsigned i, uint64_t v) +{ + smc64_result(pf->smc, i, v); +} + +static inline void psci32_result(struct psci_func *pf, unsigned i, uint32_t v) +{ + uint64_t v64 = v; + psci64_result(pf, i, v64); +} + +static inline void psci32_return(struct psci_func *pf, int32_t val) +{ + psci32_result(pf, 0, val); +} + +static inline void psci64_return(struct psci_func *pf, int64_t val) +{ + psci64_result(pf, 0, val); +} + +void psci_init(uintptr_t cpu_on_entry); +void psci_soc_init(uintptr_t cpu_on_entry); + +/* Turn on the current CPU within the PSCI subsystem. */ +void psci_turn_on_self(const struct cpu_action *action); +int psci_turn_off_self(void); +/* Entry point for CPUs just turning on or waking up. */ +void psci_cpu_entry(void); + +#endif /* __ARCH_PSCI_H__ */ diff --git a/src/arch/arm64/include/arch/smc.h b/src/arch/arm64/include/arch/smc.h new file mode 100644 index 0000000000..288459e6ba --- /dev/null +++ b/src/arch/arm64/include/arch/smc.h @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __ARCH_SMC_H__ +#define __ARCH_SMC_H__ + +#include + +enum { + FUNC_ID_CALL_TYPE_SHIFT = 31, + FUNC_ID_CALL_TYPE_MASK = (1 << FUNC_ID_CALL_TYPE_SHIFT), + FUNC_ID_FASTCALL = (1 << FUNC_ID_CALL_TYPE_SHIFT), + FUNC_ID_STDCALL = (0 << FUNC_ID_CALL_TYPE_SHIFT), + + FUNC_ID_CALL_CONVENTION_SHIFT = 30, + FUNC_ID_CALL_CONVENTION_MASK = (1 << FUNC_ID_CALL_CONVENTION_SHIFT), + FUNC_ID_SMC32 = (0 << FUNC_ID_CALL_CONVENTION_SHIFT), + FUNC_ID_SMC64 = (1 << FUNC_ID_CALL_CONVENTION_SHIFT), + + FUNC_ID_ENTITY_SHIFT = 24, + FUNC_ID_ENTITY_MASK = (0x3f << FUNC_ID_ENTITY_SHIFT), + + FUNC_ID_FUNC_NUMBER_SHIFT = 0, + FUNC_ID_FUNC_NUMBER_MASK = (0xffff << FUNC_ID_FUNC_NUMBER_SHIFT), + + FUNC_ID_MASK = FUNC_ID_CALL_TYPE_MASK | FUNC_ID_CALL_CONVENTION_MASK | + FUNC_ID_ENTITY_MASK | FUNC_ID_FUNC_NUMBER_MASK, + + SMC_NUM_ARGS = 8, /* The last is optional hypervisor id. */ + SMC_NUM_RESULTS = 4, + + SMC_UNKNOWN_FUNC = 0xffffffff, +}; + +#define SMC_FUNC(entity, number, call_convention, call_type) \ + ((call_type) | (call_convention) | \ + ((entity) << FUNC_ID_ENTITY_SHIFT) | (number)) + +#define SMC_FUNC_FAST(entity, number, call_convention) \ + SMC_FUNC((entity), (number), (call_convention), FUNC_ID_FASTCALL) + +#define SMC_FUNC_FAST32(entity, number) \ + SMC_FUNC_FAST((entity), (number), FUNC_ID_SMC32) + +#define SMC_FUNC_FAST64(entity, number) \ + SMC_FUNC_FAST((entity), (number), FUNC_ID_SMC64) + +struct smc_call { + uint64_t args[SMC_NUM_ARGS]; + uint64_t results[SMC_NUM_RESULTS]; +}; + +/* SMC immediate value needs to be 0. */ +/* Check mod AARCHx mode against calling convention. */ + +static inline uint64_t smc64_arg(const struct smc_call *smc, unsigned i) +{ + return smc->args[i]; +} + +static inline uint32_t smc32_arg(const struct smc_call *smc, unsigned i) +{ + return smc64_arg(smc, i); +} + +static inline void smc64_result(struct smc_call *smc, unsigned i, uint64_t v) +{ + smc->results[i] = v; +} + +static inline void smc32_result(struct smc_call *smc, unsigned i, uint32_t v) +{ + uint64_t v64 = v; + smc64_result(smc, i, v64); +} + +static inline void smc32_return(struct smc_call *smc, int32_t v) +{ + smc32_result(smc, 0, v); +} + +static inline uint32_t smc_hypervisor_id(const struct smc_call *smc) +{ + /* Set in W7 */ + return smc32_arg(smc, 7); +} + +static inline uint32_t smc_session_id(const struct smc_call *smc) +{ + /* Set in W6 */ + return smc32_arg(smc, 6); +} + +static inline uint32_t smc_function_id(const struct smc_call *smc) +{ + /* Function ID in W0. */ + return smc32_arg(smc, 0) & FUNC_ID_MASK; +} + +/* Initialize the SMC layer. */ +void smc_init(void); + +/* Register a handler for a given function range, inclusive. */ +int smc_register_range(uint32_t min, uint32_t max, int (*)(struct smc_call *)); + +#endif /* __ARCH_SMC_H__ */ diff --git a/src/arch/arm64/include/arch/spintable.h b/src/arch/arm64/include/arch/spintable.h new file mode 100644 index 0000000000..b583ddbeea --- /dev/null +++ b/src/arch/arm64/include/arch/spintable.h @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_SPINTABLE_H__ +#define __ARCH_SPINTABLE_H__ + +struct spintable_attributes { + void (*entry)(void *); + void *addr; +}; + +#if IS_ENABLED(CONFIG_ARCH_SPINTABLE) + +/* Initialize spintable with provided monitor address. */ +void spintable_init(void *monitor_address); + +/* Start spinning on the non-boot CPUS. */ +void spintable_start(void); + +/* Return NULL on failure, otherwise the spintable info. */ +const struct spintable_attributes *spintable_get_attributes(void); + +#else /* IS_ENABLED(CONFIG_SPINTABLE) */ + +static inline void spintable_init(void *monitor_address) {} +static inline void spintable_start(void) {} +static inline const struct spintable_attributes *spintable_get_attributes(void) +{ + return NULL; +} + +#endif /* IS_ENABLED(CONFIG_SPINTABLE) */ + +#endif /* __ARCH_SPINTABLE_H__ */ diff --git a/src/arch/arm64/include/arch/stages.h b/src/arch/arm64/include/arch/stages.h new file mode 100644 index 0000000000..28f1c8a310 --- /dev/null +++ b/src/arch/arm64/include/arch/stages.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 The ChromiumOS Authors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_STAGES_H +#define __ARCH_STAGES_H + +#include + +extern void main(void); + +void stage_entry(void); +void stage_exit(void *); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size); + +/* This function is called upon intial entry of each stage. It is called prior + * to main(). That means all of the common infrastructure will most likely not + * be available to be used (such as console). */ +void arm64_soc_init(void); + +#endif diff --git a/src/arch/arm64/include/arch/startup.h b/src/arch/arm64/include/arch/startup.h new file mode 100644 index 0000000000..bb3a863754 --- /dev/null +++ b/src/arch/arm64/include/arch/startup.h @@ -0,0 +1,46 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__ +#define __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__ + +/* Every element occupies 8 bytes (64-bit entries) */ +#define PER_ELEMENT_SIZE_BYTES 8 +#define MAIR_INDEX 0 +#define TCR_INDEX 1 +#define TTBR0_INDEX 2 +#define SCR_INDEX 3 +#define VBAR_INDEX 4 +/* IMPORTANT!!! If any new element is added please update NUM_ELEMENTS */ +#define NUM_ELEMENTS 5 + +#ifndef __ASSEMBLY__ + +/* + * startup_save_cpu_data is used to save register values that need to be setup + * when a CPU starts booting. This is used by secondary CPUs as well as resume + * path to directly setup MMU and other related registers. + */ +void startup_save_cpu_data(void); + +#endif + +#endif /* __ARCH_ARM64_INCLUDE_ARCH_STARTUP_H__ */ diff --git a/src/arch/arm64/include/arch/transition.h b/src/arch/arm64/include/arch/transition.h new file mode 100644 index 0000000000..9da6b36b87 --- /dev/null +++ b/src/arch/arm64/include/arch/transition.h @@ -0,0 +1,206 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_ARM64_TRANSITION_H__ +#define __ARCH_ARM64_TRANSITION_H__ + +/* ======================== Transition Library ================================= + * Transition library provides two main functionalities: + * 1) It allows any program X to be executed at EL Y using the state Z. It + * provides struct exc_state which holds the state of the EL to which we want to + * execute X at. Before performing an eret to the entry point of the program X, + * it initializes required registers using this exc_state structure. Here, X0 = + * args to the program X. IMP!!! : We do not initialize SP_EL0 for the program + * X, the program will have to handle that on its own. This is because while + * performing an eret to X, we could make SP_EL0 point to regs structure which + * then follows common exception exit path. + * 2) It serves as a common mechanism for handling exception entry and exit at + * any given EL. On entry to an exception, SP_ELx is selected by default. The + * exc entry routine stores all xregs and jumps to exc_entry which + * saves ELR, SPSR, EL, Mode and other information about the state from which + * exception was generated. On exit, xregs are restored by unwinding of SP_ELx. + * ============================================================================= + */ + +/* Macros for EL mode in SPSR */ +#define STACK_POP_BYTES 16 +#define STACK_PUSH_BYTES -16 + +#define EXC_VID_CUR_SP_EL0_SYNC 0 +#define EXC_VID_CUR_SP_EL0_IRQ 1 +#define EXC_VID_CUR_SP_EL0_FIRQ 2 +#define EXC_VID_CUR_SP_EL0_SERR 3 +#define EXC_VID_CUR_SP_ELX_SYNC 4 +#define EXC_VID_CUR_SP_ELX_IRQ 5 +#define EXC_VID_CUR_SP_ELX_FIQ 6 +#define EXC_VID_CUR_SP_ELX_SERR 7 +#define EXC_VID_LOW64_SYNC 8 +#define EXC_VID_LOW64_IRQ 9 +#define EXC_VID_LOW64_FIQ 10 +#define EXC_VID_LOW64_SERR 11 +#define EXC_VID_LOW32_SYNC 12 +#define EXC_VID_LOW32_IRQ 13 +#define EXC_VID_LOW32_FIQ 14 +#define EXC_VID_LOW32_SERR 15 +#define NUM_EXC_VIDS 16 + +#ifndef __ASSEMBLY__ + +#include +#include + +#define XI_INDEX(i) X##i##_INDEX = i + +enum { + XI_INDEX(0), + XI_INDEX(1), + XI_INDEX(2), + XI_INDEX(3), + XI_INDEX(4), + XI_INDEX(5), + XI_INDEX(6), + XI_INDEX(7), + XI_INDEX(8), + XI_INDEX(9), + XI_INDEX(10), + XI_INDEX(11), + XI_INDEX(12), + XI_INDEX(13), + XI_INDEX(14), + XI_INDEX(15), + XI_INDEX(16), + XI_INDEX(17), + XI_INDEX(18), + XI_INDEX(19), + XI_INDEX(20), + XI_INDEX(21), + XI_INDEX(22), + XI_INDEX(23), + XI_INDEX(24), + XI_INDEX(25), + XI_INDEX(26), + XI_INDEX(27), + XI_INDEX(28), + XI_INDEX(29), + XI_INDEX(30), + XMAX_INDEX, +}; + +/* + * Important: Any changes made to the two structures below should reflect in the + * exc_prologue and exc_exit routines in transition_asm.S + */ +struct regs { + uint64_t sp; + uint64_t x[31]; +}; + +struct elx_state { + uint64_t spsr; + uint64_t sp_el0; + uint64_t sp_elx; + uint64_t elr; +}; + +struct exc_state { + struct elx_state elx; + struct regs regs; +}; + +/* + * get_eret_EL returns the value of the exception state to which we will be + * returning. This value is saved in SPSR before performing an eret. + * + * Exception mode is defined by M[3:0] bits in SPSR: + * ( M[3:2] = EL, M[1] = unused, M[0] = t/h mode for stack + * + * 0b0000 EL0t + * 0b0100 EL1t + * 0b0101 EL1h + * 0b1000 EL2t + * 0b1001 EL2h + * 0b1100 EL3t + * 0b1101 EL3h + */ + +static inline uint8_t get_eret_el(uint8_t el, uint8_t l_or_h) +{ + uint8_t el_mode = el << CURRENT_EL_SHIFT; + + el_mode |= l_or_h; + + return el_mode; +} + +static inline uint8_t get_el_from_spsr(uint64_t spsr) +{ + return ((spsr >> CURRENT_EL_SHIFT) & CURRENT_EL_MASK); +} + +static inline uint8_t get_mode_from_spsr(uint64_t spsr) +{ + return (spsr & SPSR_L_H_MASK); +} + +/* Transitions supported are: + * 1. elx --> elx - 1 + * 2. Transitions to aarch64 state + * + * Other than this, if any transition needs to be supported, relevant changes + * need to be done to hcr/scr registers. + */ + +/* + * User of transition library can make a call to transition_with_entry and pass + * the entry point and its argument which are put into elr and x0 by this + * function. After that it makes a call to transition. + */ +void transition_with_entry(void *entry, void *arg, struct exc_state *exc_state); +/* + * transition function sets up all the registers as per the struct elx_state + * before jumping to trans_switch. + */ +void transition(struct exc_state *exc_state); + +/* + * exc_exit it called while returning from an exception. It expects pointer to + * the regs structure on stack so that it can unwind the used stack. + */ +void exc_exit(struct regs *regs); +/* + * trans_switch is called by the non-exception path i.e. transition C code + * while making a transition to lower EL. It select L mode so that SP_EL0 is + * used during the unwinding in exc_exit. + */ +void trans_switch(struct regs *regs); +/* exc_set_vbar sets up the vbar for exception vectors. */ +void exc_set_vbar(void); + +/* exc_dispatch is the user-defined exception handler. */ +void exc_dispatch(struct exc_state *exc_state, uint64_t id); +/* + * exc_entry is the C based component of the exception entry before we + * jump to user-defined handler. This initializes all the regs in elx_state and + * also sets the sp value in regs structure. + */ +void exc_entry(struct exc_state *exc_state, uint64_t id); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM64_TRANSITION_H__ */ diff --git a/src/arch/arm64/include/armv8/arch/arch_io.h b/src/arch/arm64/include/armv8/arch/arch_io.h new file mode 100644 index 0000000000..1659c59eea --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/arch_io.h @@ -0,0 +1,69 @@ +/* + * Originally imported from linux/include/asm-arm/io.h. This file has changed + * substantially since then. + * + * Copyright 2014 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 08-Apr-2013 G Replaced several macros with inlines for type safety. + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. + * 04-Apr-1999 PJB Added check_signature. + * 12-Dec-1999 RMK More cleanups + * 18-Jun-2000 RMK Removed virt_to_* and friends definitions + */ +#ifndef __ASM_ARM64_ARCH_IO_H +#define __ASM_ARM64_ARCH_IO_H + +#include +#include +#include + +static inline uint8_t read8(const void *addr) +{ + dmb(); + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(const void *addr) +{ + dmb(); + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(const void *addr) +{ + dmb(); + return *(volatile uint32_t *)addr; +} + +static inline void write8(uint8_t val, void *addr) +{ + dmb(); + *(volatile uint8_t *)addr = val; + dmb(); +} + +static inline void write16(uint16_t val, void *addr) +{ + dmb(); + *(volatile uint16_t *)addr = val; + dmb(); +} + +static inline void write32(uint32_t val, void *addr) +{ + dmb(); + *(volatile uint32_t *)addr = val; + dmb(); +} + +#endif /* __ASM_ARM64_ARCH_IO_H */ diff --git a/src/arch/arm64/include/armv8/arch/barrier.h b/src/arch/arm64/include/armv8/arch/barrier.h new file mode 100644 index 0000000000..313900ab22 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/barrier.h @@ -0,0 +1,111 @@ +/* + * Based on arch/arm/include/asm/barrier.h + * + * Copyright (C) 2012 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __ASM_ARM_BARRIER_H +#define __ASM_ARM_BARRIER_H + +#ifndef __ASSEMBLY__ + +#define sevl() asm volatile("sevl" : : : "memory") +#define sev() asm volatile("sev" : : : "memory") +#define wfe() asm volatile("wfe" : : : "memory") +#define wfi() asm volatile("wfi" : : : "memory") + +#define isb() asm volatile("isb" : : : "memory") +#define dsb() asm volatile("dsb sy" : : : "memory") +#define dmb() asm volatile("dmb sy" : : : "memory") + +#define mb() dsb() +#define rmb() asm volatile("dsb ld" : : : "memory") +#define wmb() asm volatile("dsb st" : : : "memory") + +#if IS_ENABLED(CONFIG_SMP) +#define barrier() __asm__ __volatile__("": : :"memory") +#endif + +#define nop() asm volatile("nop"); + +#define force_read(x) (*(volatile typeof(x) *)&(x)) + +#define load_acquire(p) \ +({ \ + typeof(*p) ___p1; \ + switch (sizeof(*p)) { \ + case 4: \ + asm volatile ("ldar %w0, %1" \ + : "=r" (___p1) : "Q" (*p) : "memory"); \ + break; \ + case 8: \ + asm volatile ("ldar %0, %1" \ + : "=r" (___p1) : "Q" (*p) : "memory"); \ + break; \ + } \ + ___p1; \ +}) + +#define store_release(p, v) \ +do { \ + switch (sizeof(*p)) { \ + case 4: \ + asm volatile ("stlr %w1, %0" \ + : "=Q" (*p) : "r" (v) : "memory"); \ + break; \ + case 8: \ + asm volatile ("stlr %1, %0" \ + : "=Q" (*p) : "r" (v) : "memory"); \ + break; \ + } \ +} while (0) + +#define load_acquire_exclusive(p) \ +({ \ + typeof(*p) ___p1; \ + switch (sizeof(*p)) { \ + case 4: \ + asm volatile ("ldaxr %w0, %1" \ + : "=r" (___p1) : "Q" (*p) : "memory"); \ + break; \ + case 8: \ + asm volatile ("ldaxr %0, %1" \ + : "=r" (___p1) : "Q" (*p) : "memory"); \ + break; \ + } \ + ___p1; \ +}) + +/* Returns 1 on success. */ +#define store_release_exclusive(p, v) \ +({ \ + int ret; \ + switch (sizeof(*p)) { \ + case 4: \ + asm volatile ("stlxr %w0, %w2, %1" \ + : "=&r" (ret), "=Q" (*p) : "r" (v) \ + : "memory"); \ + break; \ + case 8: \ + asm volatile ("stlxr %w0, %2, %1" \ + : "=&r" (ret), "=Q" (*p) : "r" (v) \ + : "memory"); \ + break; \ + } \ + !ret; \ +}) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARM_BARRIER_H */ diff --git a/src/arch/arm64/include/armv8/arch/cache.h b/src/arch/arm64/include/armv8/arch/cache.h new file mode 100644 index 0000000000..6ee6101256 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/cache.h @@ -0,0 +1,89 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * cache.h: Cache maintenance API for ARM64 + */ + +#ifndef ARM_ARM64_CACHE_H +#define ARM_ARM64_CACHE_H + +#include +#include +#include +#include + +/* SCTLR_ELx common bits */ +#define SCTLR_M (1 << 0) /* MMU enable */ +#define SCTLR_A (1 << 1) /* Alignment check enable */ +#define SCTLR_C (1 << 2) /* Data/unified cache enable */ +#define SCTLR_SA (1 << 3) /* Stack alignment check enable */ +#define SCTLR_I (1 << 12) /* Instruction cache enable */ +#define SCTLR_WXN (1 << 19) /* Write permission implies XN */ +#define SCTLR_EE (1 << 25) /* Exception endianness */ + +/* SCTLR_EL1 bits */ +#define SCTLR_EL1_CP15B (1 << 5) /* CP15 barrier enable */ +#define SCTLR_EL1_ITD (1 << 7) /* IT disable */ +#define SCTLR_EL1_SED (1 << 8) /* SETEND disable */ +#define SCTLR_EL1_UMA (1 << 9) /* User mask access */ +#define SCTLR_EL1_DZE (1 << 14) /* DC ZVA instruction at EL0 */ +#define SCTLR_EL1_UCT (1 << 15) /* CTR_EL0 register EL0 access */ +#define SCTLR_EL1_NTWI (1 << 16) /* Not trap WFI */ +#define SCTLR_EL1_NTWE (1 << 18) /* Not trap WFE */ +#define SCTLR_EL1_E0E (1 << 24) /* Exception endianness at EL0 */ +#define SCTLR_EL1_UCI (1 << 26) /* EL0 access to cache instructions */ + + +/* dcache clean by virtual address to PoC */ +void dcache_clean_by_mva(void const *addr, size_t len); + +/* dcache clean and invalidate by virtual address to PoC */ +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate by virtual address to PoC */ +void dcache_invalidate_by_mva(void const *addr, size_t len); + +/* dcache invalidate all */ +void flush_dcache_all(void); + +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + +/* dcache and MMU disable */ +void dcache_mmu_disable(void); + +/* dcache and MMU enable */ +void dcache_mmu_enable(void); + +/* perform all icache/dcache maintenance needed after loading new code */ +void cache_sync_instructions(void); + +/* tlb invalidate all */ +void tlb_invalidate_all(void); + +#endif /* ARM_ARM64_CACHE_H */ diff --git a/src/arch/arm64/include/armv8/arch/cpu.h b/src/arch/arm64/include/armv8/arch/cpu.h new file mode 100644 index 0000000000..34220d9792 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/cpu.h @@ -0,0 +1,184 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __ARCH_CPU_H__ +#define __ARCH_CPU_H__ + +#define asmlinkage + +#if !defined(__PRE_RAM__) +#include +#include +#include + +enum { + CPU_ID_END = 0x00000000, +}; + +struct cpu_device_id { + uint32_t midr; +}; + +struct cpu_driver { + /* This is excessive as init() is the only one called. */ + struct device_operations *ops; + const struct cpu_device_id *id_table; +}; + +/* Action to run. */ +struct cpu_action { + void (*run)(void *arg); + void *arg; +}; + +/* + * Actions are queued to 'todo'. When picked up 'todo' is cleared. The + * 'completed' field is set to the original 'todo' value when the action + * is complete. + */ +struct cpu_action_queue { + struct cpu_action *todo; + struct cpu_action *completed; +}; + +struct cpu_info { + device_t cpu; + struct cpu_action_queue action_queue; + unsigned int online; + /* Current assumption is that id matches smp_processor_id(). */ + unsigned int id; + uint64_t mpidr; +}; + +/* Obtain cpu_info for current executing CPU. */ +struct cpu_info *cpu_info(void); + +extern struct cpu_info *bsp_cpu_info; +extern struct cpu_info cpu_infos[CONFIG_MAX_CPUS]; + +static inline struct cpu_info *cpu_info_for_cpu(unsigned int id) +{ + return &cpu_infos[id]; +} + +/* Ran only by BSP at initial boot strapping. */ +static inline void cpu_set_bsp(void) +{ + bsp_cpu_info = cpu_info(); +} + +static inline int cpu_is_bsp(void) +{ + return cpu_info() == bsp_cpu_info; +} + +static inline int cpu_online(struct cpu_info *ci) +{ + return load_acquire(&ci->online) != 0; +} + +static inline void cpu_mark_online(struct cpu_info *ci) +{ + ci->mpidr = read_affinity_mpidr(); + store_release(&ci->online, 1); +} + +/* Provide number of CPUs online. */ +size_t cpus_online(void); + +/* Control routines for starting CPUs. */ +struct cpu_control_ops { + /* Return the maximum number of CPUs supported. */ + size_t (*total_cpus)(void); + /* + * Start the requested CPU and have it start running entry(). + * Returns 0 on success, < 0 on error. + */ + int (*start_cpu)(unsigned int id, void (*entry)(void)); +}; + +/* + * Initialize all DEVICE_PATH_CPUS under the DEVICE_PATH_CPU_CLUSTER cluster. + * type DEVICE_PATH_CPUS. Start up is controlled by cntrl_ops. + */ +void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops); + +/* + * Run cpu_action returning < 0 on error, 0 on success. There are synchronous + * and asynchronous methods. Both cases ensure the action has been picked up + * by the target cpu. The synchronous variants will wait for the action to + * be completed before returning. + * + * Though the current implementation allows queuing actions on the main cpu, + * the main cpu doesn't process its own queue. + */ +int arch_run_on_cpu(unsigned int cpu, struct cpu_action *action); +int arch_run_on_all_cpus(struct cpu_action *action); +int arch_run_on_all_cpus_but_self(struct cpu_action *action); +int arch_run_on_cpu_async(unsigned int cpu, struct cpu_action *action); +int arch_run_on_all_cpus_async(struct cpu_action *action); +int arch_run_on_all_cpus_but_self_async(struct cpu_action *action); + +/* Wait for actions to be perfomed. */ +void arch_cpu_wait_for_action(void); + +#endif /* !__PRE_RAM__ */ + +/* + * Returns logical cpu in range [0:MAX_CPUS). SoC should define this. + * Additionally, this is needed early in arm64 init so it should not + * rely on a stack. Standard clobber list is fair game: x0-x7 and x0 + * returns the logical cpu number. + */ +unsigned int smp_processor_id(void); + +/* + * Stages and rmodules have 2 entry points: BSP and non-BSP. Provided + * a pointer the correct non-BSP entry point will be returned. The + * first instruction is for BSP and the 2nd is for non-BSP. Instructions + * are all 32-bit on arm64. + */ +static inline void *secondary_entry_point(void *e) +{ + uintptr_t nonbsp = (uintptr_t)e; + + return (void *)(nonbsp + sizeof(uint32_t)); +} + +/* + * The arm64_cpu_startup() initializes a CPU's exception stack and regular + * stack as well initializing the C environment for the processor. It + * calls into the array of function pointers at symbol c_entry depending + * on BSP state. Note that arm64_cpu_startup contains secondary entry + * point which can be obtained by secondary_entry_point(). + */ +void arm64_cpu_startup(void); + +/* + * The arm64_cpu_startup_resume() initializes a CPU's exception stack and + * regular stack as well initializing the C environment for the processor. It + * calls into the array of function pointers at symbol c_entry depending + * on BSP state. Note that arm64_cpu_startup contains secondary entry + * point which can be obtained by secondary_entry_point(). + * Additionally, it also restores saved register data and enables MMU, caches + * and exceptions before jumping to C environment for both BSP and non-BSP CPUs. + */ +void arm64_cpu_startup_resume(void); + +#endif /* __ARCH_CPU_H__ */ diff --git a/payloads/libpayload/arch/powerpc/head.S b/src/arch/arm64/include/armv8/arch/exception.h similarity index 60% rename from payloads/libpayload/arch/powerpc/head.S rename to src/arch/arm64/include/armv8/arch/exception.h index de6edadaff..49ea747700 100644 --- a/payloads/libpayload/arch/powerpc/head.S +++ b/src/arch/arm64/include/armv8/arch/exception.h @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright 2013 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,61 +27,42 @@ * SUCH DAMAGE. */ - .globl _entry, _leave - .text - .align 4 +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H + +#include + +/* Initialize the exception handling on the current CPU. */ +void exception_hwinit(void); +void exception_init(void); /* - * Our entry point - assume that the CPU is in 32 bit protected mode and - * all segments are in a flat model. That's our operating mode, so we won't - * change anything. + * Order matters for handling return values. The larger the value the higher + * the precedence. */ -_entry: -#if 0 - call _init +enum { + EXC_RET_IGNORED, + EXC_RET_ABORT, + EXC_RET_HANDLED, + EXC_RET_HANDLED_DUMP_STATE, +}; - /* We're back - go back to the bootloader. */ - ret - .align 4 +struct exception_handler { + int (*handler)(struct exc_state *state, uint64_t vector_id); + struct exception_handler *next; +}; /* - * This function saves off the previous stack and switches us to our - * own execution environment. + * Register a handler provided with the associated vector id. Returns 0 on + * sucess, < 0 on error. Note that registration is not thread/interrupt safe. */ -_init: - /* No interrupts, please. */ - cli +int exception_handler_register(uint64_t vid, struct exception_handler *h); - /* Store current stack pointer. */ - movl %esp, %esi - - /* Store EAX and EBX */ - - movl %eax,loader_eax - movl %ebx,loader_ebx - - /* Setup new stack. */ - movl $_stack, %ebx - - movl %ebx, %esp - - /* Save old stack pointer. */ - pushl %esi - - /* Let's rock. */ - call start_main +/* + * Unregister a handler from the vector id. Return 0 on success, < 0 on error. + * Note that the unregistration is not thread/interrupt safe. + */ +int exception_handler_unregister(uint64_t vid, struct exception_handler *h); -#endif - /* %eax has the return value - pass it on unmolested */ -_leave: -#if 0 - /* Get old stack pointer. */ - popl %ebx - - /* Restore old stack. */ - movl %ebx, %esp - - /* Return to the original context. */ - ret #endif diff --git a/src/arch/arm64/include/armv8/arch/lib_helpers.h b/src/arch/arm64/include/armv8/arch/lib_helpers.h new file mode 100644 index 0000000000..31f4c86afb --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/lib_helpers.h @@ -0,0 +1,565 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * lib_helpers.h: All library function prototypes and macros are defined in this + * file. + */ + +#ifndef __ARCH_LIB_HELPERS_H__ +#define __ARCH_LIB_HELPERS_H__ + +#define EL0 0 +#define EL1 1 +#define EL2 2 +#define EL3 3 + +#define CURRENT_EL_MASK 0x3 +#define CURRENT_EL_SHIFT 2 + +#define SPSR_USE_L 0 +#define SPSR_USE_H 1 +#define SPSR_L_H_MASK 1 +#define SPSR_M_SHIFT 4 +#define SPSR_ERET_32 (1 << SPSR_M_SHIFT) +#define SPSR_ERET_64 (0 << SPSR_M_SHIFT) +#define SPSR_FIQ_SHIFT 6 +#define SPSR_FIQ_MASK (0 << SPSR_FIQ_SHIFT) +#define SPSR_FIQ_ENABLE (1 << SPSR_FIQ_SHIFT) +#define SPSR_IRQ_SHIFT 7 +#define SPSR_IRQ_MASK (0 << SPSR_IRQ_SHIFT) +#define SPSR_IRQ_ENABLE (1 << SPSR_IRQ_SHIFT) +#define SPSR_SERROR_SHIFT 8 +#define SPSR_SERROR_MASK (0 << SPSR_SERROR_SHIFT) +#define SPSR_SERROR_ENABLE (1 << SPSR_SERROR_SHIFT) +#define SPSR_DEBUG_SHIFT 9 +#define SPSR_DEBUG_MASK (0 << SPSR_DEBUG_SHIFT) +#define SPSR_DEBUG_ENABLE (1 << SPSR_DEBUG_SHIFT) + +#define SCR_NS_SHIFT 0 +#define SCR_NS_MASK (1 << SCR_NS_SHIFT) +#define SCR_NS_ENABLE (1 << SCR_NS_SHIFT) +#define SCR_NS_DISABLE (0 << SCR_NS_SHIFT) +#define SCR_NS SCR_NS_ENABLE +#define SCR_RES1 (0x3 << 4) +#define SCR_IRQ_SHIFT 2 +#define SCR_IRQ_MASK (1 << SCR_IRQ_SHIFT) +#define SCR_IRQ_ENABLE (1 << SCR_IRQ_SHIFT) +#define SCR_IRQ_DISABLE (0 << SCR_IRQ_SHIFT) +#define SCR_FIQ_SHIFT 2 +#define SCR_FIQ_MASK (1 << SCR_FIQ_SHIFT) +#define SCR_FIQ_ENABLE (1 << SCR_FIQ_SHIFT) +#define SCR_FIQ_DISABLE (0 << SCR_FIQ_SHIFT) +#define SCR_EA_SHIFT 3 +#define SCR_EA_MASK (1 << SCR_EA_SHIFT) +#define SCR_EA_ENABLE (1 << SCR_EA_SHIFT) +#define SCR_EA_DISABLE (0 << SCR_EA_SHIFT) +#define SCR_SMC_SHIFT 7 +#define SCR_SMC_MASK (1 << SCR_SMC_SHIFT) +#define SCR_SMC_DISABLE (1 << SCR_SMC_SHIFT) +#define SCR_SMC_ENABLE (0 << SCR_SMC_SHIFT) +#define SCR_HVC_SHIFT 8 +#define SCR_HVC_MASK (1 << SCR_HVC_SHIFT) +#define SCR_HVC_DISABLE (0 << SCR_HVC_SHIFT) +#define SCR_HVC_ENABLE (1 << SCR_HVC_SHIFT) +#define SCR_SIF_SHIFT 9 +#define SCR_SIF_MASK (1 << SCR_SIF_SHIFT) +#define SCR_SIF_ENABLE (1 << SCR_SIF_SHIFT) +#define SCR_SIF_DISABLE (0 << SCR_SIF_SHIFT) +#define SCR_RW_SHIFT 10 +#define SCR_RW_MASK (1 << SCR_RW_SHIFT) +#define SCR_LOWER_AARCH64 (1 << SCR_RW_SHIFT) +#define SCR_LOWER_AARCH32 (0 << SCR_RW_SHIFT) +#define SCR_ST_SHIFT 11 +#define SCR_ST_MASK (1 << SCR_ST_SHIFT) +#define SCR_ST_ENABLE (1 << SCR_ST_SHIFT) +#define SCR_ST_DISABLE (0 << SCR_ST_SHIFT) +#define SCR_TWI_SHIFT 12 +#define SCR_TWI_MASK (1 << SCR_TWI_SHIFT) +#define SCR_TWI_ENABLE (1 << SCR_TWI_SHIFT) +#define SCR_TWI_DISABLE (0 << SCR_TWI_SHIFT) +#define SCR_TWE_SHIFT 13 +#define SCR_TWE_MASK (1 << SCR_TWE_SHIFT) +#define SCR_TWE_ENABLE (1 << SCR_TWE_SHIFT) +#define SCR_TWE_DISABLE (0 << SCR_TWE_SHIFT) + +#define HCR_RW_SHIFT 31 +#define HCR_LOWER_AARCH64 (1 << HCR_RW_SHIFT) +#define HCR_LOWER_AARCH32 (0 << HCR_RW_SHIFT) + +#define SCTLR_MMU_ENABLE 1 +#define SCTLR_MMU_DISABLE 0 +#define SCTLR_ACE_SHIFT 1 +#define SCTLR_ACE_ENABLE (1 << SCTLR_ACE_SHIFT) +#define SCTLR_ACE_DISABLE (0 << SCTLR_ACE_SHIFT) +#define SCTLR_CACHE_SHIFT 2 +#define SCTLR_CACHE_ENABLE (1 << SCTLR_CACHE_SHIFT) +#define SCTLR_CACHE_DISABLE (0 << SCTLR_CACHE_SHIFT) +#define SCTLR_SAE_SHIFT 3 +#define SCTLR_SAE_ENABLE (1 << SCTLR_SAE_SHIFT) +#define SCTLR_SAE_DISABLE (0 << SCTLR_SAE_SHIFT) +#define SCTLR_RES1 ((0x3 << 4) | (0x1 << 11) | (0x1 << 16) | \ + (0x1 << 18) | (0x3 << 22) | (0x3 << 28)) +#define SCTLR_ICE_SHIFT 12 +#define SCTLR_ICE_ENABLE (1 << SCTLR_ICE_SHIFT) +#define SCTLR_ICE_DISABLE (0 << SCTLR_ICE_SHIFT) +#define SCTLR_WXN_SHIFT 19 +#define SCTLR_WXN_ENABLE (1 << SCTLR_WXN_SHIFT) +#define SCTLR_WXN_DISABLE (0 << SCTLR_WXN_SHIFT) +#define SCTLR_ENDIAN_SHIFT 25 +#define SCTLR_LITTLE_END (0 << SCTLR_ENDIAN_SHIFT) +#define SCTLR_BIG_END (1 << SCTLR_ENDIAN_SHIFT) + +#ifdef __ASSEMBLY__ + +/* Macro to switch to label based on current el */ +.macro switch_el xreg label1 label2 label3 + mrs \xreg, CurrentEL + /* Currently at EL1 */ + cmp \xreg, #(EL1 << CURRENT_EL_SHIFT) + b.eq \label1 + /* Currently at EL2 */ + cmp \xreg, #(EL2 << CURRENT_EL_SHIFT) + b.eq \label2 + /* Currently at EL3 */ + cmp \xreg, #(EL3 << CURRENT_EL_SHIFT) + b.eq \label3 +.endm + +/* Macro to read sysreg at current EL + xreg - reg in which read value needs to be stored + sysreg - system reg that is to be read +*/ +.macro read_current xreg sysreg + switch_el \xreg, 101f, 102f, 103f +101: + mrs \xreg, \sysreg\()_el1 + b 104f +102: + mrs \xreg, \sysreg\()_el2 + b 104f +103: + mrs \xreg, \sysreg\()_el3 + b 104f +104: +.endm + +/* Macro to write sysreg at current EL + xreg - reg from which value needs to be written + sysreg - system reg that is to be written + temp - temp reg that can be used to read current EL +*/ +.macro write_current sysreg xreg temp + switch_el \temp, 101f, 102f, 103f +101: + msr \sysreg\()_el1, \xreg + b 104f +102: + msr \sysreg\()_el2, \xreg + b 104f +103: + msr \sysreg\()_el3, \xreg + b 104f +104: +.endm + +/* Macro to read sysreg at current EL - 1 + xreg - reg in which read value needs to be stored + sysreg - system reg that is to be read +*/ +.macro read_lower xreg sysreg + switch_el \xreg, 101f, 102f, 103f +101: + b 104f +102: + mrs \xreg, \sysreg\()_el1 + b 104f +103: + mrs \xreg, \sysreg\()_el2 + b 104f +104: +.endm + +/* Macro to write sysreg at current EL - 1 + xreg - reg from which value needs to be written + sysreg - system reg that is to be written + temp - temp reg that can be used to read current EL +*/ +.macro write_lower sysreg xreg temp + switch_el \temp, 101f, 102f, 103f +101: + b 104f +102: + msr \sysreg\()_el1, \xreg + b 104f +103: + msr \sysreg\()_el2, \xreg + b 104f +104: +.endm + +/* Macro to read from a register at EL3 only if we are currently at that + level. This is required to ensure that we do not attempt to read registers + from a level lower than el3. e.g. SCR is available for read only at EL3. + IMPORTANT: if EL != EL3, macro silently doesn't perform the read. +*/ +.macro read_el3 xreg sysreg + switch_el \xreg, 402f, 402f, 401f +401: + mrs \xreg, \sysreg\()_el3 +402: +.endm + +/* Macro to write to a register at EL3 only if we are currently at that + level. This is required to ensure that we do not attempt to write to + registers from a level lower than el3. e.g. SCR is available to write only at + EL3. + IMPORTANT: if EL != EL3, macro silently doesn't perform the write. +*/ +.macro write_el3 sysreg xreg temp + switch_el \temp, 402f, 402f, 401f +401: + msr \sysreg\()_el3, \xreg +402: +.endm + +/* Macro to invalidate all stage 1 TLB entries for current EL */ +.macro tlbiall_current temp + switch_el \temp, 401f, 402f, 403f +401: + tlbi alle1 + b 404f +402: + tlbi alle2 + b 404f +403: + tlbi alle3 + b 404f +404: +.endm + +#else + +#include + +#define DAIF_DBG_BIT (1<<3) +#define DAIF_ABT_BIT (1<<2) +#define DAIF_IRQ_BIT (1<<1) +#define DAIF_FIQ_BIT (1<<0) + +#define SWITCH_CASE_READ(func, var, type, el) do { \ + type var = -1; \ + switch(el) { \ + case EL1: \ + var = func##_el1(); \ + break; \ + case EL2: \ + var = func##_el2(); \ + break; \ + case EL3: \ + var = func##_el3(); \ + break; \ + } \ + return var; \ + } while(0) + +#define SWITCH_CASE_WRITE(func, var, el) do { \ + switch(el) { \ + case EL1: \ + func##_el1(var); \ + break; \ + case EL2: \ + func##_el2(var); \ + break; \ + case EL3: \ + func##_el3(var); \ + break; \ + } \ + } while(0) + +#define SWITCH_CASE_TLBI(func, el) do { \ + switch(el) { \ + case EL1: \ + func##_el1(); \ + break; \ + case EL2: \ + func##_el2(); \ + break; \ + case EL3: \ + func##_el3(); \ + break; \ + } \ + } while(0) + +/* PSTATE and special purpose register access functions */ +uint32_t raw_read_current_el(void); +uint32_t get_current_el(void); +uint32_t raw_read_daif(void); +void raw_write_daif(uint32_t daif); +void enable_debug_exceptions(void); +void enable_serror_exceptions(void); +void enable_irq(void); +void enable_fiq(void); +void disable_debug_exceptions(void); +void disable_serror_exceptions(void); +void disable_irq(void); +void disable_fiq(void); +uint64_t raw_read_dlr_el0(void); +void raw_write_dlr_el0(uint64_t dlr_el0); +uint64_t raw_read_dspsr_el0(void); +void raw_write_dspsr_el0(uint64_t dspsr_el0); +uint64_t raw_read_elr_el1(void); +void raw_write_elr_el1(uint64_t elr_el1); +uint64_t raw_read_elr_el2(void); +void raw_write_elr_el2(uint64_t elr_el2); +uint64_t raw_read_elr_el3(void); +void raw_write_elr_el3(uint64_t elr_el3); +uint64_t raw_read_elr_current(void); +void raw_write_elr_current(uint64_t elr); +uint64_t raw_read_elr(uint32_t el); +void raw_write_elr(uint64_t elr, uint32_t el); +uint32_t raw_read_fpcr(void); +void raw_write_fpcr(uint32_t fpcr); +uint32_t raw_read_fpsr(void); +void raw_write_fpsr(uint32_t fpsr); +uint32_t raw_read_nzcv(void); +void raw_write_nzcv(uint32_t nzcv); +uint64_t raw_read_sp_el0(void); +void raw_write_sp_el0(uint64_t sp_el0); +uint64_t raw_read_sp_el1(void); +void raw_write_sp_el1(uint64_t sp_el1); +uint64_t raw_read_sp_el2(void); +void raw_write_sp_el2(uint64_t sp_el2); +uint32_t raw_read_spsel(void); +void raw_write_spsel(uint32_t spsel); +uint64_t raw_read_sp_el3(void); +void raw_write_sp_el3(uint64_t sp_el3); +uint64_t raw_read_sp_elx(uint32_t el); +void raw_write_sp_elx(uint64_t sp_elx, uint32_t el); +uint32_t raw_read_spsr_abt(void); +void raw_write_spsr_abt(uint32_t spsr_abt); +uint32_t raw_read_spsr_el1(void); +void raw_write_spsr_el1(uint32_t spsr_el1); +uint32_t raw_read_spsr_el2(void); +void raw_write_spsr_el2(uint32_t spsr_el2); +uint32_t raw_read_spsr_el3(void); +void raw_write_spsr_el3(uint32_t spsr_el3); +uint32_t raw_read_spsr_current(void); +void raw_write_spsr_current(uint32_t spsr); +uint32_t raw_read_spsr(uint32_t el); +void raw_write_spsr(uint32_t spsr, uint32_t el); +uint32_t raw_read_spsr_fiq(void); +void raw_write_spsr_fiq(uint32_t spsr_fiq); +uint32_t raw_read_spsr_irq(void); +void raw_write_spsr_irq(uint32_t spsr_irq); +uint32_t raw_read_spsr_und(void); +void raw_write_spsr_und(uint32_t spsr_und); + +/* System control register access */ +uint32_t raw_read_actlr_el1(void); +void raw_write_actlr_el1(uint32_t actlr_el1); +uint32_t raw_read_actlr_el2(void); +void raw_write_actlr_el2(uint32_t actlr_el2); +uint32_t raw_read_actlr_el3(void); +void raw_write_actlr_el3(uint32_t actlr_el3); +uint32_t raw_read_actlr_current(void); +void raw_write_actlr_current(uint32_t actlr); +uint32_t raw_read_actlr(uint32_t el); +void raw_write_actlr(uint32_t actlr, uint32_t el); +uint32_t raw_read_afsr0_el1(void); +void raw_write_afsr0_el1(uint32_t afsr0_el1); +uint32_t raw_read_afsr0_el2(void); +void raw_write_afsr0_el2(uint32_t afsr0_el2); +uint32_t raw_read_afsr0_el3(void); +void raw_write_afsr0_el3(uint32_t afsr0_el3); +uint32_t raw_read_afsr0_current(void); +void raw_write_afsr0_current(uint32_t afsr0); +uint32_t raw_read_afsr0(uint32_t el); +void raw_write_afsr0(uint32_t afsr0, uint32_t el); +uint32_t raw_read_afsr1_el1(void); +void raw_write_afsr1_el1(uint32_t afsr1_el1); +uint32_t raw_read_afsr1_el2(void); +void raw_write_afsr1_el2(uint32_t afsr1_el2); +uint32_t raw_read_afsr1_el3(void); +void raw_write_afsr1_el3(uint32_t afsr1_el3); +uint32_t raw_read_afsr1_current(void); +void raw_write_afsr1_current(uint32_t afsr1); +uint32_t raw_read_afsr1(uint32_t el); +void raw_write_afsr1(uint32_t afsr1, uint32_t el); +uint32_t raw_read_aidr_el1(void); +uint64_t raw_read_amair_el1(void); +void raw_write_amair_el1(uint64_t amair_el1); +uint64_t raw_read_amair_el2(void); +void raw_write_amair_el2(uint64_t amair_el2); +uint64_t raw_read_amair_el3(void); +void raw_write_amair_el3(uint64_t amair_el3); +uint64_t raw_read_amair_current(void); +void raw_write_amair_current(uint64_t amair); +uint64_t raw_read_amair(uint32_t el); +void raw_write_amair(uint64_t amair, uint32_t el); +uint32_t raw_read_ccsidr_el1(void); +uint32_t raw_read_clidr_el1(void); +uint32_t raw_read_cpacr_el1(void); +void raw_write_cpacr_el1(uint32_t cpacr_el1); +uint32_t raw_read_cptr_el2(void); +void raw_write_cptr_el2(uint32_t cptr_el2); +uint32_t raw_read_cptr_el3(void); +void raw_write_cptr_el3(uint32_t cptr_el3); +uint32_t raw_read_cptr_current(void); +void raw_write_cptr_current(uint32_t cptr); +uint32_t raw_read_csselr_el1(void); +void raw_write_csselr_el1(uint32_t csselr_el1); +uint32_t raw_read_ctr_el0(void); +uint32_t raw_read_esr_el1(void); +void raw_write_esr_el1(uint32_t esr_el1); +uint32_t raw_read_esr_el2(void); +void raw_write_esr_el2(uint32_t esr_el2); +uint32_t raw_read_esr_el3(void); +void raw_write_esr_el3(uint32_t esr_el3); +uint32_t raw_read_esr_current(void); +void raw_write_esr_current(uint32_t esr); +uint32_t raw_read_esr(uint32_t el); +void raw_write_esr(uint32_t esr, uint32_t el); +uint64_t raw_read_far_el1(void); +void raw_write_far_el1(uint64_t far_el1); +uint64_t raw_read_far_el2(void); +void raw_write_far_el2(uint64_t far_el2); +uint64_t raw_read_far_el3(void); +void raw_write_far_el3(uint64_t far_el3); +uint64_t raw_read_far_current(void); +void raw_write_far_current(uint64_t far); +uint64_t raw_read_far(uint32_t el); +void raw_write_far(uint64_t far, uint32_t el); +uint64_t raw_read_hcr_el2(void); +void raw_write_hcr_el2(uint64_t hcr_el2); +uint64_t raw_read_aa64pfr0_el1(void); +uint64_t raw_read_mair_el1(void); +void raw_write_mair_el1(uint64_t mair_el1); +uint64_t raw_read_mair_el2(void); +void raw_write_mair_el2(uint64_t mair_el2); +uint64_t raw_read_mair_el3(void); +void raw_write_mair_el3(uint64_t mair_el3); +uint64_t raw_read_mair_current(void); +void raw_write_mair_current(uint64_t mair); +uint64_t raw_read_mair(uint32_t el); +void raw_write_mair(uint64_t mair, uint32_t el); +uint32_t raw_read_midr_el1(void); +uint64_t raw_read_mpidr_el1(void); +uint32_t raw_read_rmr_el1(void); +void raw_write_rmr_el1(uint32_t rmr_el1); +uint32_t raw_read_rmr_el2(void); +void raw_write_rmr_el2(uint32_t rmr_el2); +uint32_t raw_read_rmr_el3(void); +void raw_write_rmr_el3(uint32_t rmr_el3); +uint32_t raw_read_rmr_current(void); +void raw_write_rmr_current(uint32_t rmr); +uint32_t raw_read_rmr(uint32_t el); +void raw_write_rmr(uint32_t rmr, uint32_t el); +uint64_t raw_read_rvbar_el1(void); +void raw_write_rvbar_el1(uint64_t rvbar_el1); +uint64_t raw_read_rvbar_el2(void); +void raw_write_rvbar_el2(uint64_t rvbar_el2); +uint64_t raw_read_rvbar_el3(void); +void raw_write_rvbar_el3(uint64_t rvbar_el3); +uint64_t raw_read_rvbar_current(void); +void raw_write_rvbar_current(uint64_t rvbar); +uint64_t raw_read_rvbar(uint32_t el); +void raw_write_rvbar(uint64_t rvbar, uint32_t el); +uint32_t raw_read_scr_el3(void); +void raw_write_scr_el3(uint32_t scr_el3); +uint32_t raw_read_sctlr_el1(void); +void raw_write_sctlr_el1(uint32_t sctlr_el1); +uint32_t raw_read_sctlr_el2(void); +void raw_write_sctlr_el2(uint32_t sctlr_el2); +uint32_t raw_read_sctlr_el3(void); +void raw_write_sctlr_el3(uint32_t sctlr_el3); +uint32_t raw_read_sctlr_current(void); +void raw_write_sctlr_current(uint32_t sctlr); +uint32_t raw_read_sctlr(uint32_t el); +void raw_write_sctlr(uint32_t sctlr, uint32_t el); +uint64_t raw_read_tcr_el1(void); +void raw_write_tcr_el1(uint64_t tcr_el1); +uint32_t raw_read_tcr_el2(void); +void raw_write_tcr_el2(uint32_t tcr_el2); +uint32_t raw_read_tcr_el3(void); +void raw_write_tcr_el3(uint32_t tcr_el3); +uint64_t raw_read_tcr_current(void); +void raw_write_tcr_current(uint64_t tcr); +uint64_t raw_read_tcr(uint32_t el); +void raw_write_tcr(uint64_t tcr, uint32_t el); +uint64_t raw_read_ttbr0_el1(void); +void raw_write_ttbr0_el1(uint64_t ttbr0_el1); +uint64_t raw_read_ttbr0_el2(void); +void raw_write_ttbr0_el2(uint64_t ttbr0_el2); +uint64_t raw_read_ttbr0_el3(void); +void raw_write_ttbr0_el3(uint64_t ttbr0_el3); +uint64_t raw_read_ttbr0_current(void); +void raw_write_ttbr0_current(uint64_t ttbr0); +uint64_t raw_read_ttbr0(uint32_t el); +void raw_write_ttbr0(uint64_t ttbr0, uint32_t el); +uint64_t raw_read_ttbr1_el1(void); +void raw_write_ttbr1_el1(uint64_t ttbr1_el1); +uint64_t raw_read_vbar_el1(void); +void raw_write_vbar_el1(uint64_t vbar_el1); +uint64_t raw_read_vbar_el2(void); +void raw_write_vbar_el2(uint64_t vbar_el2); +uint64_t raw_read_vbar_el3(void); +void raw_write_vbar_el3(uint64_t vbar_el3); +uint64_t raw_read_vbar_current(void); +void raw_write_vbar_current(uint64_t vbar); +uint64_t raw_read_vbar(uint32_t el); +void raw_write_vbar(uint64_t vbar, uint32_t el); + +/* Cache maintenance system instructions */ +void dccisw(uint64_t cisw); +void dccivac(uint64_t civac); +void dccsw(uint64_t csw); +void dccvac(uint64_t cvac); +void dccvau(uint64_t cvau); +void dcisw(uint64_t isw); +void dcivac(uint64_t ivac); +void dczva(uint64_t zva); +void iciallu(void); +void icialluis(void); +void icivau(uint64_t ivau); + +/* TLB maintenance instructions */ +void tlbiall_el1(void); +void tlbiall_el2(void); +void tlbiall_el3(void); +void tlbiall_current(void); +void tlbiall(uint32_t el); +void tlbiallis_el1(void); +void tlbiallis_el2(void); +void tlbiallis_el3(void); +void tlbiallis_current(void); +void tlbiallis(uint32_t el); +void tlbivaa_el1(uint64_t va); + +#endif // __ASSEMBLY__ + +#endif // __ARCH_LIB_HELPERS_H__ diff --git a/src/arch/arm64/include/armv8/arch/mmu.h b/src/arch/arm64/include/armv8/arch/mmu.h new file mode 100644 index 0000000000..a030b1bf73 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/mmu.h @@ -0,0 +1,170 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_ARM64_MMU_H__ +#define __ARCH_ARM64_MMU_H__ + +#include + +/* IMPORTANT!!!!!!! + * Assumptions made: + * Granule size is 64KiB + * BITS per Virtual address is 33 + * All the calculations for tables L1,L2 and L3 are based on these assumptions + * If these values are changed, recalculate the other macros as well + */ + + +/* Memory attributes for mmap regions + * These attributes act as tag values for memrange regions + */ + +/* Normal memory / device */ +#define MA_MEM (1 << 0) +#define MA_DEV (0 << 0) + +/* Secure / non-secure */ +#define MA_NS (1 << 1) +#define MA_S (0 << 1) + +/* Read only / Read-write */ +#define MA_RO (1 << 2) +#define MA_RW (0 << 2) + +/* Non-cacheable memory. */ +#define MA_MEM_NC (1 << 3) + +/* Descriptor attributes */ + +#define INVALID_DESC 0x0 +#define BLOCK_DESC 0x1 +#define TABLE_DESC 0x3 +#define PAGE_DESC 0x3 + +/* Block descriptor */ +#define BLOCK_NS (1 << 5) + +#define BLOCK_AP_RW (0 << 7) +#define BLOCK_AP_RO (1 << 7) + +#define BLOCK_ACCESS (1 << 10) + +/* XLAT Table Init Attributes */ + +#define VA_START 0x0 +/* If BITS_PER_VA or GRANULE_SIZE are changed, recalculate and change the + macros following them */ +#define BITS_PER_VA 33 +/* Granule size of 64KB is being used */ +#define GRANULE_SIZE_SHIFT 16 +#define GRANULE_SIZE (1 << GRANULE_SIZE_SHIFT) +#define XLAT_TABLE_MASK ~(0xffffUL) +#define GRANULE_SIZE_MASK ((1 << 16) - 1) + +#define L1_ADDR_SHIFT 42 +#define L2_ADDR_SHIFT 29 +#define L3_ADDR_SHIFT 16 + +#define L1_ADDR_MASK (0UL << L1_ADDR_SHIFT) +#define L2_ADDR_MASK (0xfUL << L2_ADDR_SHIFT) +#define L3_ADDR_MASK (0x1fffUL << L3_ADDR_SHIFT) + +/* Dependent on BITS_PER_VA and GRANULE_SIZE */ +#define INIT_LEVEL 2 +#define XLAT_MAX_LEVEL 3 + +/* Each entry in XLAT table is 8 bytes */ +#define XLAT_ENTRY_SHIFT 3 +#define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SHIFT) + +#define XLAT_TABLE_SHIFT GRANULE_SIZE_SHIFT +#define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SHIFT) + +#define XLAT_NUM_ENTRIES_SHIFT (XLAT_TABLE_SHIFT - XLAT_ENTRY_SHIFT) +#define XLAT_NUM_ENTRIES (1 << XLAT_NUM_ENTRIES_SHIFT) + +#define L3_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT) +#define L2_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT + XLAT_NUM_ENTRIES_SHIFT) +#define L1_XLAT_SIZE_SHIFT (GRANULE_SIZE_SHIFT + XLAT_NUM_ENTRIES_SHIFT) + +/* These macros give the size of the region addressed by each entry of a xlat + table at any given level */ +#define L3_XLAT_SIZE (1 << L3_XLAT_SIZE_SHIFT) +#define L2_XLAT_SIZE (1 << L2_XLAT_SIZE_SHIFT) +#define L1_XLAT_SIZE (1 << L1_XLAT_SIZE_SHIFT) + +/* Block indices required for MAIR */ +#define BLOCK_INDEX_MEM_DEV_NGNRNE 0 +#define BLOCK_INDEX_MEM_DEV_NGNRE 1 +#define BLOCK_INDEX_MEM_DEV_GRE 2 +#define BLOCK_INDEX_MEM_NORMAL_NC 3 +#define BLOCK_INDEX_MEM_NORMAL 4 + +#define BLOCK_INDEX_SHIFT 2 + +/* MAIR attributes */ +#define MAIR_ATTRIBUTES ((0x00 << (BLOCK_INDEX_MEM_DEV_NGNRNE*8)) | \ + (0x04 << (BLOCK_INDEX_MEM_DEV_NGNRE*8)) | \ + (0x0c << (BLOCK_INDEX_MEM_DEV_GRE*8)) | \ + (0x44 << (BLOCK_INDEX_MEM_NORMAL_NC*8)) | \ + (0xffUL << (BLOCK_INDEX_MEM_NORMAL*8))) + +/* TCR attributes */ +#define TCR_TOSZ (64 - BITS_PER_VA) + +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_NM_NC (0x00 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WBWAC (0x01 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WTC (0x02 << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NM_WBNWAC (0x03 << TCR_IRGN0_SHIFT) + +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_NM_NC (0x00 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WBWAC (0x01 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WTC (0x02 << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NM_WBNWAC (0x03 << TCR_ORGN0_SHIFT) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_NC (0x0 << TCR_SH0_SHIFT) +#define TCR_SH0_OS (0x2 << TCR_SH0_SHIFT) +#define TCR_SH0_IS (0x3 << TCR_SH0_SHIFT) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_4KB (0x0 << TCR_TG0_SHIFT) +#define TCR_TG0_64KB (0x1 << TCR_TG0_SHIFT) +#define TCR_TG0_16KB (0x2 << TCR_TG0_SHIFT) + +#define TCR_PS_SHIFT 16 +#define TCR_PS_4GB (0x0 << TCR_PS_SHIFT) +#define TCR_PS_64GB (0x1 << TCR_PS_SHIFT) +#define TCR_PS_1TB (0x2 << TCR_PS_SHIFT) +#define TCR_PS_4TB (0x3 << TCR_PS_SHIFT) +#define TCR_PS_16TB (0x4 << TCR_PS_SHIFT) +#define TCR_PS_256TB (0x5 << TCR_PS_SHIFT) + +#define TCR_TBI_SHIFT 20 +#define TCR_TBI_USED (0x0 << TCR_TBI_SHIFT) +#define TCR_TBI_IGNORED (0x1 << TCR_TBI_SHIFT) + +/* Initialize the MMU TTB tables provide the range sequence and ttb buffer. */ +void mmu_init(struct memranges *ranges, uint64_t *ttb, uint64_t ttb_size); +/* Enable the mmu based on previous mmu_init(). */ +void mmu_enable(void); + +#endif // __ARCH_ARM64_MMU_H__ diff --git a/src/arch/arm64/include/armv8/arch/rules.h b/src/arch/arm64/include/armv8/arch/rules.h new file mode 100644 index 0000000000..a790365118 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/rules.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _ARCH_RULES_H +#define _ARCH_RULES_H + +/* For romstage and ramstage always build with simple device model, ie. + * PCI, PNP and CPU functions operate without use of devicetree. + * + * For ramstage individual source file may define __SIMPLE_DEVICE__ + * before including any header files to force that particular source + * be built with simple device model. + */ + +#if defined(__PRE_RAM__) +#define __SIMPLE_DEVICE__ +#endif + +#endif /* _ARCH_RULES_H */ diff --git a/src/arch/arm64/include/armv8/arch/secmon.h b/src/arch/arm64/include/armv8/arch/secmon.h new file mode 100644 index 0000000000..3d368a70e5 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/secmon.h @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_ARM64_ARMV8_SECMON__ +#define __ARCH_ARM64_ARMV8_SECMON__ + +#include + +#if IS_ENABLED(CONFIG_ARCH_USE_SECURE_MONITOR) + +struct secmon_params { + size_t online_cpus; + struct cpu_action bsp; + struct cpu_action secondary; +}; + +void secmon_run(void (*entry)(void *), void *arg); +void soc_get_secmon_base_size(uint64_t *secmon_base, size_t *secmon_size); + +#else + +static inline void secmon_run(void (*entry)(void *), void *arg) {} + +#endif /* IS_ENABLED(CONFIG_ARCH_USE_SECURE_MONITOR) */ + +#endif /*__ARCH_ARM64_ARMV8_SECMON__ */ diff --git a/src/arch/arm64/include/armv8/arch/smp/spinlock.h b/src/arch/arm64/include/armv8/arch/smp/spinlock.h new file mode 100644 index 0000000000..10278e72ae --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/smp/spinlock.h @@ -0,0 +1,29 @@ +#ifndef ARCH_SMP_SPINLOCK_H +#define ARCH_SMP_SPINLOCK_H + +#include +#include + +typedef struct { + volatile uint32_t lock; +} spinlock_t; + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +#define DECLARE_SPIN_LOCK(x) static spinlock_t x = SPIN_LOCK_UNLOCKED; + +static inline void spin_lock(spinlock_t *spin) +{ + while (1) { + if (load_acquire_exclusive(&spin->lock) != 0) + continue; + if (store_release_exclusive(&spin->lock, 1)) + break; + } +} + +static inline void spin_unlock(spinlock_t *spin) +{ + store_release(&spin->lock, 0); +} + +#endif diff --git a/src/arch/armv7/include/bootblock_common.h b/src/arch/arm64/include/bootblock_common.h similarity index 77% rename from src/arch/armv7/include/bootblock_common.h rename to src/arch/arm64/include/bootblock_common.h index 39af4535e2..2fa705f5e1 100644 --- a/src/arch/armv7/include/bootblock_common.h +++ b/src/arch/arm64/include/bootblock_common.h @@ -7,8 +7,5 @@ #else static void bootblock_mainboard_init(void) { -#ifdef CONFIG_BOOTBLOCK_CPU_INIT - bootblock_cpu_init(); -#endif } #endif diff --git a/src/cpu/samsung/exynos5-common/reset.c b/src/arch/arm64/include/clocks.h similarity index 59% rename from src/cpu/samsung/exynos5-common/reset.c rename to src/arch/arm64/include/clocks.h index 6cbc1d88e5..8f35303fd3 100644 --- a/src/cpu/samsung/exynos5-common/reset.c +++ b/src/arch/arm64/include/clocks.h @@ -1,7 +1,5 @@ /* - * Copyright (c) 2010 Samsung Electronics. - * Minkyu Kang - * + * Copyright (c) 2011 The Chromium OS Authors. * See file CREDITS for list of people who contributed to this * project. * @@ -21,10 +19,26 @@ * MA 02111-1307 USA */ -#include -#include +/* Standard clock speeds */ + +/* + * We define some commonly-used clock speeds to avoid error since long + * numbers are hard to read. + * + * The format of the label is + * CLK_x_yU where: + * x is the integer speed + * y is the fractional part which can be omitted if 0 + * U is the units (blank for Hz, K or M for KHz and MHz) + * + * Please order the items by increasing Hz + */ +enum { + CLK_32768 = 32768, + CLK_20M = 20000000, + CLK_24M = 24000000, + CLK_144M = 144000000, + CLK_216M = 216000000, + CLK_300M = 300000000, +}; -void soft_reset(void) -{ - writel(0x1, samsung_get_base_swreset()); -} diff --git a/src/arch/arm64/include/stdint.h b/src/arch/arm64/include/stdint.h new file mode 100644 index 0000000000..6e7ee531f4 --- /dev/null +++ b/src/arch/arm64/include/stdint.h @@ -0,0 +1,69 @@ +#ifndef ARM64_STDINT_H +#define ARM64_STDINT_H + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; + +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +/* Types for `void *' pointers. */ +typedef s64 intptr_t; +typedef u64 uintptr_t; + +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif +#ifndef UINT64_MAX +# define UINT64_MAX (18446744073709551615ULL) +#endif +#ifndef PRIu64 +#define PRIu64 "llu" +#endif + +#endif /* ARM64_STDINT_H */ diff --git a/src/arch/arm64/spintable.c b/src/arch/arm64/spintable.c new file mode 100644 index 0000000000..7a1ab7f5b1 --- /dev/null +++ b/src/arch/arm64/spintable.c @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct spintable_attributes spin_attrs; + +void spintable_init(void *monitor_address) +{ + extern void __wait_for_spin_table_request(void); + const size_t code_size = 4096; + + if (monitor_address == NULL) { + printk(BIOS_ERR, "spintable: NULL address to monitor.\n"); + return; + } + + spin_attrs.entry = cbmem_add(CBMEM_ID_SPINTABLE, code_size); + + if (spin_attrs.entry == NULL) + return; + + spin_attrs.addr = monitor_address; + + printk(BIOS_INFO, "spintable @ %p will monitor %p\n", + spin_attrs.entry, spin_attrs.addr); + + /* Ensure the memory location is zero'd out. */ + *(uint64_t *)monitor_address = 0; + + memcpy(spin_attrs.entry, __wait_for_spin_table_request, code_size); + + dcache_clean_invalidate_by_mva(monitor_address, sizeof(uint64_t)); + dcache_clean_invalidate_by_mva(spin_attrs.entry, code_size); +} + +static void spintable_enter(void *unused) +{ + struct exc_state state; + const struct spintable_attributes *attrs; + int current_el; + + attrs = spintable_get_attributes(); + + current_el = get_current_el(); + + if (current_el != EL3) + attrs->entry(attrs->addr); + + memset(&state, 0, sizeof(state)); + state.elx.spsr = get_eret_el(EL2, SPSR_USE_L); + + transition_with_entry(attrs->entry, attrs->addr, &state); +} + +const struct spintable_attributes *spintable_get_attributes(void) +{ + if (spin_attrs.entry == NULL) { + printk(BIOS_ERR, "spintable: monitor code not present.\n"); + return NULL; + } + + return &spin_attrs; +} + +void spintable_start(void) +{ + struct cpu_action action = { + .run = spintable_enter, + }; + + if (spintable_get_attributes() == NULL) + return; + + printk(BIOS_INFO, "All non-boot CPUs to enter spintable.\n"); + + arch_run_on_all_cpus_but_self_async(&action); +} diff --git a/src/arch/arm64/spintable_asm.S b/src/arch/arm64/spintable_asm.S new file mode 100644 index 0000000000..3066b7e679 --- /dev/null +++ b/src/arch/arm64/spintable_asm.S @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +ENTRY(__wait_for_spin_table_request) + /* Entry here is in EL2 with the magic address in x0. */ + mov x28, x0 +1: + ldr x27, [x28] + cmp x27, xzr + b.ne 2f + wfe + b 1b +2: + /* Entry into the kernel. */ + mov x0, xzr + mov x1, xzr + mov x2, xzr + mov x3, xzr + br x27 +ENDPROC(__wait_for_spin_table_request) diff --git a/src/arch/arm64/stage_entry.S b/src/arch/arm64/stage_entry.S new file mode 100644 index 0000000000..fa2064e708 --- /dev/null +++ b/src/arch/arm64/stage_entry.S @@ -0,0 +1,222 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * ======================== stage_entry.S ===================================== + * This file acts as an entry point to the different stages of arm64 as well as + * for the secure monitor. They share the same process of setting up stacks and + * jumping to c code. It is important to save x25 from corruption as it contains + * the argument for secure monitor. + * ============================================================================= + */ + +#include +#define __ASSEMBLY__ +#include +#include + +#define STACK_SZ CONFIG_STACK_SIZE +#define EXCEPTION_STACK_SZ CONFIG_STACK_SIZE + +/* + * The stacks for each of the armv8 cores grows down from _estack. It is sized + * according to MAX_CPUS. Additionally provide exception stacks for each CPU. + */ +.section .bss, "aw", @nobits + +.global _arm64_startup_data +.balign 8 +_arm64_startup_data: +.space NUM_ELEMENTS*PER_ELEMENT_SIZE_BYTES + +.global _stack +.global _estack +.balign STACK_SZ +_stack: +.space CONFIG_MAX_CPUS*STACK_SZ +_estack: + +.global _stack_exceptions +.global _estack_exceptions +.balign EXCEPTION_STACK_SZ +_stack_exceptions: +.space CONFIG_MAX_CPUS*EXCEPTION_STACK_SZ +_estack_exceptions: + +ENTRY(cpu_get_stack) + mov x1, #STACK_SZ + mul x0, x0, x1 + ldr x1, 1f + sub x0, x1, x0 + ret +.align 3 +1: + .quad _estack +ENDPROC(cpu_get_stack) + +ENTRY(cpu_get_exception_stack) + mov x1, #EXCEPTION_STACK_SZ + mul x0, x0, x1 + ldr x1, 1f + sub x0, x1, x0 + ret +.align 3 +1: + .quad _estack_exceptions +ENDPROC(cpu_get_exception_stack) + +/* + * Boot strap the processor into a C environemnt. That consists of providing + * 16-byte aligned stack. The programming enviroment uses SP_EL0 as its main + * stack while keeping SP_ELx reserved for exception entry. + */ +/* + * IMPORTANT: Ensure x25 is not corrupted because it saves the argument to + * secmon + */ +ENTRY(arm64_c_environment) + bl smp_processor_id /* x0 = cpu */ + mov x24, x0 + + + /* Set the exception stack for this cpu. */ + bl cpu_get_exception_stack + msr SPSel, #1 + isb + mov sp, x0 + + /* Have stack pointer use SP_EL0. */ + msr SPSel, #0 + isb + + /* Set stack for this cpu. */ + mov x0, x24 /* x0 = cpu */ + bl cpu_get_stack + mov sp, x0 + + /* Get entry point by dereferencing c_entry. */ + ldr x1, 1f + /* Retrieve entry in c_entry array using x26 as the index. */ + adds x1, x1, x26, lsl #3 + ldr x1, [x1] + /* Move back the arguments from x25 to x0 */ + mov x0, x25 + br x1 +.align 3 + 1: + .quad c_entry +ENDPROC(arm64_c_environment) + +/* The first 2 instructions are for BSP and secondary CPUs, + * respectively. x26 holds the index into c_entry array. */ +.macro split_bsp_path + b 2000f + b 2001f + 2000: + mov x26, #0 + b 2002f + 2001: + mov x26, #1 + 2002: +.endm + +ENTRY(__rmodule_entry) + split_bsp_path + /* Save the arguments to secmon in x25 */ + mov x25, x0 + b arm64_c_environment +ENDPROC(__rmodule_entry) + +/* + * Setup SCTLR so that: + * Little endian mode is setup, XN is not enforced, MMU and caches are disabled. + * Alignment and stack alignment checks are disabled. + */ +.macro setup_sctlr + read_current x0, sctlr + bic x0, x0, #(1 << 25) /* Little Endian */ + bic x0, x0, #(1 << 19) /* XN not enforced */ + bic x0, x0, #(1 << 12) /* Disable Instruction Cache */ + bic x0, x0, #0xf /* Clear SA, C, A and M */ + write_current sctlr, x0, x1 +.endm + +/* + * This macro assumes x2 has base address and returns value read in x0 + * x1 is used as temporary register. + */ +.macro get_element_addr index + add x1, x2, #(\index * PER_ELEMENT_SIZE_BYTES) + ldr x0, [x1] +.endm + +/* + * Uses following registers: + * x0 = reading stored value + * x1 = temp reg + * x2 = base address of saved data region + */ +.macro startup_restore + adr x2, _arm64_startup_data + + get_element_addr MAIR_INDEX + write_current mair, x0, x1 + + get_element_addr TCR_INDEX + write_current tcr, x0, x1 + + get_element_addr TTBR0_INDEX + write_current ttbr0, x0, x1 + + get_element_addr SCR_INDEX + write_el3 scr, x0, x1 + + get_element_addr VBAR_INDEX + write_current vbar, x0, x1 + + dsb sy + isb + + tlbiall_current x1 + read_current x0, sctlr + orr x0, x0, #(1 << 12) /* Enable Instruction Cache */ + orr x0, x0, #(1 << 2) /* Enable Data/Unified Cache */ + orr x0, x0, #(1 << 0) /* Enable MMU */ + write_current sctlr, x0, x1 + + dsb sy + isb +.endm + +CPU_RESET_ENTRY(arm64_cpu_startup) + split_bsp_path + setup_sctlr + b arm64_c_environment +ENDPROC(arm64_cpu_startup) + +CPU_RESET_ENTRY(arm64_cpu_startup_resume) + split_bsp_path + setup_sctlr + startup_restore + b arm64_c_environment +ENDPROC(arm64_cpu_startup_resume) + +ENTRY(stage_entry) + b arm64_cpu_startup +ENDPROC(stage_entry) diff --git a/src/arch/armv7/stages.c b/src/arch/arm64/stages.c similarity index 69% rename from src/arch/armv7/stages.c rename to src/arch/arm64/stages.c index 038ed7c8af..8316b221fe 100644 --- a/src/arch/armv7/stages.c +++ b/src/arch/arm64/stages.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * Copyright 2014 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,15 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * + */ + +/* * This file contains entry/exit functions for each stage during coreboot * execution (bootblock entry and ramstage exit will depend on external - * loading. - * - * Unlike other files, this one should be compiled with a -m option to - * specify a pre-determined instruction set. This is to ensure consistency - * in the CPU operating mode (ARM or Thumb) when hand-off between stages - * occurs. + * loading). * * Entry points must be placed at the location the previous stage jumps * to (the lowest address in the stage image). This is done by giving @@ -32,14 +29,8 @@ */ #include -#include #include -void stage_entry(void) -{ - main(); -} - /* we had marked 'doit' as 'noreturn'. * There is no apparent harm in leaving it as something we can return from, and in the one * case where we call a payload, the payload is allowed to return. @@ -48,13 +39,10 @@ void stage_entry(void) void stage_exit(void *addr) { void (*doit)(void) = addr; - /* make sure any code we installed is written to memory. Not all ARM have - * unified caches. + /* + * Most stages load code so we need to sync caches here. Should maybe + * go into cbfs_load_stage() instead... */ - dcache_clean_invalidate_all(); - /* Because most stages copy code to memory, it's a safe and hygienic thing - * to flush the icache here. - */ - icache_invalidate_all(); + cache_sync_instructions(); doit(); } diff --git a/src/arch/arm64/startup.c b/src/arch/arm64/startup.c new file mode 100644 index 0000000000..d2b76913d2 --- /dev/null +++ b/src/arch/arm64/startup.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include + +/* This space is defined in stage_entry.S. */ +extern u8 _arm64_startup_data[]; + +static inline void save_element(size_t index, uint64_t val) +{ + uint64_t *ptr = (uint64_t *)_arm64_startup_data; + + ptr[index] = val; +} + +/* + * startup_save_cpu_data is used to save register values that need to be setup + * when a CPU starts booting. This is used by secondary CPUs as well as resume + * path to directly setup MMU and other related registers. + */ +void startup_save_cpu_data(void) +{ + save_element(MAIR_INDEX, raw_read_mair_current()); + save_element(TCR_INDEX, raw_read_tcr_current()); + save_element(TTBR0_INDEX, raw_read_ttbr0_current()); + save_element(VBAR_INDEX, raw_read_vbar_current()); + + if (get_current_el() == EL3) + save_element(SCR_INDEX, raw_read_scr_el3()); + + dcache_clean_by_mva(_arm64_startup_data, + NUM_ELEMENTS * PER_ELEMENT_SIZE_BYTES); +} diff --git a/src/arch/arm64/tables.c b/src/arch/arm64/tables.c new file mode 100644 index 0000000000..825d7a2427 --- /dev/null +++ b/src/arch/arm64/tables.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Eric Biederman + * Copyright (C) 2005 Steve Magnani + * Copyright (C) 2008-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_COREBOOT_TABLE_SIZE (8 * 1024) + +#if ! CONFIG_DYNAMIC_CBMEM +/* + * TODO: "High" tables are a convention used on x86. Maybe we can + * clean up that naming at some point. + */ +uint64_t high_tables_base = 0; +uint64_t high_tables_size; +#endif + +struct lb_memory *write_tables(void) +{ + unsigned long table_pointer, new_table_pointer; + +#if ! CONFIG_DYNAMIC_CBMEM + if (!high_tables_base) { + printk(BIOS_ERR, "ERROR: high_tables_base is not set.\n"); + } + + printk(BIOS_DEBUG, "high_tables_base: %llx.\n", high_tables_base); +#endif + + post_code(0x9d); + + table_pointer = (unsigned long)cbmem_add(CBMEM_ID_CBTABLE, + MAX_COREBOOT_TABLE_SIZE); + if (!table_pointer) { + printk(BIOS_ERR, "Could not add CBMEM for coreboot table.\n"); + return NULL; + } + + new_table_pointer = write_coreboot_table(0UL, 0UL, + table_pointer, table_pointer); + + if (new_table_pointer > (table_pointer + MAX_COREBOOT_TABLE_SIZE)) { + printk(BIOS_ERR, "coreboot table didn't fit (%lx/%x bytes)\n", + new_table_pointer - table_pointer, MAX_COREBOOT_TABLE_SIZE); + } + + printk(BIOS_DEBUG, "coreboot table: %ld bytes.\n", + new_table_pointer - table_pointer); + + post_code(0x9e); + + /* Print CBMEM sections */ + cbmem_list(); + + return get_lb_mem(); +} diff --git a/src/arch/arm64/timestamp.c b/src/arch/arm64/timestamp.c new file mode 100644 index 0000000000..e6a8159c95 --- /dev/null +++ b/src/arch/arm64/timestamp.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include + +uint64_t timestamp_get(void) +{ + struct mono_time timestamp; + timer_monotonic_get(×tamp); + return (uint64_t)timestamp.microseconds; +} + diff --git a/src/arch/arm64/transition.c b/src/arch/arm64/transition.c new file mode 100644 index 0000000000..523960e741 --- /dev/null +++ b/src/arch/arm64/transition.c @@ -0,0 +1,134 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +/* Mask out debug exceptions, serror, irq and fiq */ +#define SPSR_MASK (SPSR_FIQ_MASK | SPSR_IRQ_MASK | SPSR_SERROR_MASK | \ + SPSR_DEBUG_MASK) +/* Litte-endian, No XN-forced, Instr cache disabled, + * Stack alignment disabled, Data and unified cache + * disabled, Alignment check disabled, MMU disabled + */ +#define SCTLR_MASK (SCTLR_MMU_DISABLE | SCTLR_ACE_DISABLE | \ + SCTLR_CACHE_DISABLE | SCTLR_SAE_DISABLE | SCTLR_RES1 | \ + SCTLR_ICE_DISABLE | SCTLR_WXN_DISABLE | SCTLR_LITTLE_END) + +void __attribute__((weak)) exc_dispatch(struct exc_state *exc_state, uint64_t id) +{ + /* Default weak implementation does nothing. */ +} + +void exc_entry(struct exc_state *exc_state, uint64_t id) +{ + struct elx_state *elx = &exc_state->elx; + struct regs *regs = &exc_state->regs; + uint8_t elx_mode, elx_el; + + elx->spsr = raw_read_spsr_current(); + elx_mode = get_mode_from_spsr(elx->spsr); + elx_el = get_el_from_spsr(elx->spsr); + + if (elx_mode == SPSR_USE_H) { + if (elx_el == get_current_el()) + regs->sp = (uint64_t)&exc_state[1]; + else + regs->sp = raw_read_sp_elx(elx_el); + } else { + regs->sp = raw_read_sp_el0(); + } + + elx->elr = raw_read_elr_current(); + + exc_dispatch(exc_state, id); +} + +void transition_with_entry(void *entry, void *arg, struct exc_state *exc_state) +{ + /* Argument to entry point goes into X0 */ + exc_state->regs.x[X0_INDEX] = (uint64_t)arg; + /* Entry point goes into ELR */ + exc_state->elx.elr = (uint64_t)entry; + + transition(exc_state); +} + +void transition(struct exc_state *exc_state) +{ + uint32_t scr_mask; + uint64_t hcr_mask; + uint64_t sctlr; + uint32_t current_el = get_current_el(); + + struct elx_state *elx = &exc_state->elx; + struct regs *regs = &exc_state->regs; + + uint8_t elx_el = get_el_from_spsr(elx->spsr); + + /* + * Policies enforced: + * 1. We support only elx --> (elx - 1) transitions + * 2. We support transitions to Aarch64 mode only + * + * If any of the above conditions holds false, then we need a proper way + * to update SCR/HCR before removing the checks below + */ + if ((current_el - elx_el) != 1) + die("ARM64 Error: Do not support transition\n"); + + if (elx->spsr & SPSR_ERET_32) + die("ARM64 Error: Do not support eret to Aarch32\n"); + else { + scr_mask = SCR_LOWER_AARCH64; + hcr_mask = HCR_LOWER_AARCH64; + } + + /* SPSR: Mask out debug exceptions, serror, irq, fiq */ + elx->spsr |= SPSR_MASK; + raw_write_spsr_current(elx->spsr); + + /* SCR: Write to SCR if current EL is EL3 */ + if (current_el == EL3) { + uint32_t scr = raw_read_scr_el3(); + scr |= scr_mask; + raw_write_scr_el3(scr); + } + /* HCR: Write to HCR if current EL is EL2 */ + else if (current_el == EL2) { + uint64_t hcr = raw_read_hcr_el2(); + hcr |= hcr_mask; + raw_write_hcr_el2(hcr); + } + + /* ELR: Write entry point of program */ + raw_write_elr_current(elx->elr); + + /* SCTLR: Initialize EL with selected properties */ + sctlr = raw_read_sctlr(elx_el); + sctlr &= SCTLR_MASK; + raw_write_sctlr(sctlr, elx_el); + + /* SP_ELx: Initialize stack pointer */ + raw_write_sp_elx(elx->sp_elx, elx_el); + + /* Eret to the entry point */ + trans_switch(regs); +} diff --git a/src/arch/arm64/transition_asm.S b/src/arch/arm64/transition_asm.S new file mode 100644 index 0000000000..111efe0a8c --- /dev/null +++ b/src/arch/arm64/transition_asm.S @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * transition_asm.S: This file handles the entry and exit from an exception + * + * Flow: exception --> exc_vectors --> exc_entry --> exc_dispatch --> + * exc_exit + * Transition Flow: transition --> trans_switch --> exc_exit + * + * |---| Exception Entry |---| + * + * On exception entry, it saves all the xregs on SP_ELx since SP_ELx is + * selected on entry. Some dummy pushes are performed to create space for + * elx_state structure. It then passes pointer to this saved set of regs and + * a unique id(for identifying exception) to exc_entry. + * + * |---| Exception Transition Dispatch |---| + * + * This is the C-component of exception entry. It does the work of initializing + * the exc_state registers. Finally it calls exception dispatch implemented by + * the user. This is point of no-return. + * + * |---| Exception Dispatch |---| + * + * User of this functionality is expected to implement exc_dispatch which + * acts as entry point for it. Once exception handling is complete, the user + * needs to call exc_exit with pointer to struct regs. + * + * |---| Exception Exit |---| + * + * Once exc_dispatch is done with handling the exception based on the id passed + * to it, it needs to call exc_exit with pointer to struct regs. This is done to + * unwind the exception stack by popping off all the xregs. + * + * |---| Exception Transition Exit |---| + * + * This routine makes SP_EL0 point to the regs structure passed and continues + * onto the exception exit routine described above. This is the reason that + * transition library does not handle initialization of SP_EL0 for the program + * to be executed. + */ + +#define __ASSEMBLY__ +#include +#include +#include + +.macro eentry lbl id + .align 7 +\lbl: + stp x29, x30, [sp, #STACK_PUSH_BYTES]! + bl exc_prologue + mov x1, \id + mov x0, sp + b exc_entry +.endm + +/* + * exc_vectors: Entry point for an exception + */ +ENTRY_WITH_ALIGN(exc_vectors, 11) + +eentry sync_curr_sp0, #EXC_VID_CUR_SP_EL0_SYNC +eentry irq_curr_sp0, #EXC_VID_CUR_SP_EL0_IRQ +eentry fiq_curr_sp0, #EXC_VID_CUR_SP_EL0_FIRQ +eentry serror_curr_sp0, #EXC_VID_CUR_SP_EL0_SERR +eentry sync_curr_spx, #EXC_VID_CUR_SP_ELX_SYNC +eentry irq_curr_spx, #EXC_VID_CUR_SP_ELX_IRQ +eentry fiq_curr_spx, #EXC_VID_CUR_SP_ELX_FIQ +eentry serror_curr_spx, #EXC_VID_CUR_SP_ELX_SERR +eentry sync_lower_64, #EXC_VID_LOW64_SYNC +eentry irq_lower_64, #EXC_VID_LOW64_IRQ +eentry fiq_lower_64, #EXC_VID_LOW64_FIQ +eentry serror_lower_64, #EXC_VID_LOW64_SERR +eentry sync_lower_32, #EXC_VID_LOW32_SYNC +eentry irq_lower_32, #EXC_VID_LOW32_IRQ +eentry fiq_lower_32, #EXC_VID_LOW32_FIQ +eentry serror_lower_32, #EXC_VID_LOW32_SERR + +ENDPROC(exc_vectors) + +ENTRY(exc_prologue) + stp x27, x28, [sp, #STACK_PUSH_BYTES]! + stp x25, x26, [sp, #STACK_PUSH_BYTES]! + stp x23, x24, [sp, #STACK_PUSH_BYTES]! + stp x21, x22, [sp, #STACK_PUSH_BYTES]! + stp x19, x20, [sp, #STACK_PUSH_BYTES]! + stp x17, x18, [sp, #STACK_PUSH_BYTES]! + stp x15, x16, [sp, #STACK_PUSH_BYTES]! + stp x13, x14, [sp, #STACK_PUSH_BYTES]! + stp x11, x12, [sp, #STACK_PUSH_BYTES]! + stp x9, x10, [sp, #STACK_PUSH_BYTES]! + stp x7, x8, [sp, #STACK_PUSH_BYTES]! + stp x5, x6, [sp, #STACK_PUSH_BYTES]! + stp x3, x4, [sp, #STACK_PUSH_BYTES]! + stp x1, x2, [sp, #STACK_PUSH_BYTES]! + /* xzr pushed as place holder for sp */ + stp xzr, x0, [sp, #STACK_PUSH_BYTES]! + /* + * xzr pushed as place holder for: + * 1. sp_elx and elr + */ + stp xzr, xzr, [sp, #STACK_PUSH_BYTES]! + /* 2. spsr and sp_el0 */ + stp xzr, xzr, [sp, #STACK_PUSH_BYTES]! + ret +ENDPROC(exc_prologue) + +/* + * trans_switch: Set SPSel to use SP_EL0 + * x0 = regs structure + */ +ENTRY(trans_switch) + msr SPSel, #SPSR_USE_L + b exc_exit +ENDPROC(trans_switch) + +/* + * exc_exit: Return from exception by restoring saved state of xregs + * x0 = regs structure + */ +ENTRY(exc_exit) + /* Unwind the stack by making sp point to regs structure */ + mov sp, x0 + /* Load registers x0-x30 */ + ldp xzr, x0, [sp], #STACK_POP_BYTES + ldp x1, x2, [sp], #STACK_POP_BYTES + ldp x3, x4, [sp], #STACK_POP_BYTES + ldp x5, x6, [sp], #STACK_POP_BYTES + ldp x7, x8, [sp], #STACK_POP_BYTES + ldp x9, x10, [sp], #STACK_POP_BYTES + ldp x11, x12, [sp], #STACK_POP_BYTES + ldp x13, x14, [sp], #STACK_POP_BYTES + ldp x15, x16, [sp], #STACK_POP_BYTES + ldp x17, x18, [sp], #STACK_POP_BYTES + ldp x19, x20, [sp], #STACK_POP_BYTES + ldp x21, x22, [sp], #STACK_POP_BYTES + ldp x23, x24, [sp], #STACK_POP_BYTES + ldp x25, x26, [sp], #STACK_POP_BYTES + ldp x27, x28, [sp], #STACK_POP_BYTES + ldp x29, x30, [sp], #STACK_POP_BYTES + eret +ENDPROC(exc_exit) + +/* exc_set_vbar: Initialize the exception entry address in vbar */ +ENTRY(exc_set_vbar) + adr x0, exc_vectors + write_current vbar, x0, x1 + dsb sy + isb + ret +ENDPROC(exc_set_vbar) diff --git a/src/arch/armv7/Kconfig b/src/arch/armv7/Kconfig deleted file mode 100644 index 488ca97e4c..0000000000 --- a/src/arch/armv7/Kconfig +++ /dev/null @@ -1,52 +0,0 @@ -menu "Architecture (armv7)" - -config EABI_COMPAT - bool "Toolchain is EABI compatible" - default n - -# Maximum reboot count -# TODO: Improve description. -config MAX_REBOOT_CNT - int - default 3 - -choice - prompt "Bootblock behaviour" - default ARM_BOOTBLOCK_SIMPLE - -config ARM_BOOTBLOCK_SIMPLE - bool "Always load fallback" - -config ARM_BOOTBLOCK_NORMAL - bool "Switch to normal if non-volatile memory says so" - -endchoice - -config BOOTBLOCK_SOURCE - string - default "bootblock_simple.c" if ARM_BOOTBLOCK_SIMPLE - default "bootblock_normal.c" if ARM_BOOTBLOCK_NORMAL - -config UPDATE_IMAGE - bool "Update existing coreboot.rom image" - default n - help - If this option is enabled, no new coreboot.rom file - is created. Instead it is expected that there already - is a suitable file for further processing. - The bootblock will not be modified. - -config BOOTBLOCK_SOC_INIT - string - -# FIXME: Should cache policy be set on a per-CPU basis? -# FIXME(dhendrix): Stefan sayz to make a smart decision and not prompt the user. -config ARM_DCACHE_POLICY_WRITEBACK - bool - default y - -config ARM_DCACHE_POLICY_WRITETHROUGH - bool - default n - -endmenu diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc deleted file mode 100644 index fbf1cba187..0000000000 --- a/src/arch/armv7/Makefile.inc +++ /dev/null @@ -1,274 +0,0 @@ -################################################################################ -## -## This file is part of the coreboot project. -## -## Copyright (C) 2012 The ChromiumOS Authors -## Copyright (C) 2012 Alexandru Gagniuc -## Copyright (C) 2009-2010 coresystems GmbH -## Copyright (C) 2009 Ronald G. Minnich -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; version 2 of the License. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -## -################################################################################ - -# Take care of subdirectories -subdirs-y += boot/ -subdirs-y += lib/ - -################################################################################ -# Build the final rom image -COREBOOT_ROM_DEPENDENCIES:= -ifeq ($(CONFIG_PAYLOAD_ELF),y) -COREBOOT_ROM_DEPENDENCIES+=$(CONFIG_PAYLOAD_FILE) -endif - -extract_nth=$(word $(1), $(subst |, ,$(2))) - -ifneq ($(CONFIG_UPDATE_IMAGE),y) -prebuild-files = \ - $(foreach file,$(cbfs-files), \ - $(CBFSTOOL) $@.tmp \ - add$(if $(filter stage,$(call extract_nth,3,$(file))),-stage)$(if $(filter payload,$(call extract_nth,3,$(file))),-payload) \ - -f $(call extract_nth,1,$(file)) \ - -n $(call extract_nth,2,$(file)) $(if $(filter-out stage,$(call extract_nth,3,$(file))),-t $(call extract_nth,3,$(file))) \ - $(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&) -prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) - -# TODO Change -b to Kconfig variable. -$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) - $(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \ - -B $(objcbfs)/bootblock.bin -a 64 -b 0x0000 \ - -H $(CONFIG_CBFS_HEADER_ROM_OFFSET) \ - -o $(CONFIG_CBFS_ROM_OFFSET) - $(prebuild-files) true - mv $@.tmp $@ -else -.PHONY: $(obj)/coreboot.pre1 -$(obj)/coreboot.pre1: $(CBFSTOOL) - mv $(obj)/coreboot.rom $@ -endif - -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) - @printf " CBFS $(subst $(obj)/,,$(@))\n" - cp $(obj)/coreboot.pre $@.tmp - $(CBFSTOOL) $@.tmp add-stage -f $(objcbfs)/coreboot_ram.elf -n $(CONFIG_CBFS_PREFIX)/coreboot_ram -c $(CBFS_COMPRESS_FLAG) -ifeq ($(CONFIG_PAYLOAD_NONE),y) - @printf " PAYLOAD none (as specified by user)\n" -endif -ifeq ($(CONFIG_PAYLOAD_ELF),y) - @printf " PAYLOAD $(CONFIG_PAYLOAD_FILE) (compression: $(CBFS_PAYLOAD_COMPRESS_NAME))\n" - $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_INCLUDE_CONFIG_FILE),y) - @printf " CONFIG $(DOTCONFIG)\n" - if [ -f $(DOTCONFIG) ]; then \ - echo "# This image was built using git revision" `git rev-parse HEAD` > $(obj)/config.tmp ; \ - sed -e '/^#/d' -e '/^ *$$/d' $(DOTCONFIG) >> $(obj)/config.tmp ; \ - $(CBFSTOOL) $@.tmp add -f $(obj)/config.tmp -n config -t raw; rm -f $(obj)/config.tmp ; fi -endif - mv $@.tmp $@ - @printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n" - $(CBFSTOOL) $@ print - -bootsplash.jpg-file := $(call strip_quotes,$(CONFIG_BOOTSPLASH_FILE)) -bootsplash.jpg-type := bootsplash - -################################################################################ -# armv7 specific tools - -################################################################################ -# Common recipes for all stages - -$(objcbfs)/%.bin: $(objcbfs)/%.elf - @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - $(OBJCOPY) -O binary $< $@ - -$(objcbfs)/%.elf: $(objcbfs)/%.debug - @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cp $< $@.tmp - $(NM) -n $@.tmp | sort > $(basename $@).map - $(OBJCOPY) --strip-debug $@.tmp - $(OBJCOPY) --add-gnu-debuglink=$< $@.tmp - mv $@.tmp $@ - -stages_c = $(src)/arch/armv7/stages.c -stages_o = $(obj)/arch/armv7/stages.o - -$(stages_o): $(stages_c) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -I. $(INCLUDES) -c -o $@ $< -marm - - -################################################################################ -# Build the coreboot_ram (stage 2) - -$(objcbfs)/coreboot_ram.debug: $(objgenerated)/coreboot_ram.o $(src)/arch/armv7/coreboot_ram.ld - @printf " CC $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m armelf_linux_eabi -o $@ -L$(obj) $< -T $(src)/arch/armv7/coreboot_ram.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(src)/arch/armv7/coreboot_ram.ld $< -endif - -$(objgenerated)/coreboot_ram.o: $(stages_o) $$(ramstage-objs) $(LIBGCC_FILE_NAME) - @printf " CC $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m -m armelf_linux_eabi -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --wrap __uidiv --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group -else - $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--start-group $(stages_o) $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group -endif - -CFLAGS += \ - -ffixed-r8\ - -march=armv7-a\ - -marm\ - -mno-unaligned-access\ - -mthumb\ - -mthumb-interwork - -ldscripts = -ldscripts += $(src)/arch/armv7/romstage.ld - -#crt0s += $(src)/cpu/arm/fpu_enable.inc -# FIXME: CONFIG_NEON or something similar for ARM? -#ifeq ($(CONFIG_SSE),y) -#crt0s += $(src)/cpu/arm/sse_enable.inc -#endif - -crt0s += $(cpu_incs) -crt0s += $(cpu_incs-y) - -ifeq ($(CONFIG_LLSHELL),y) -crt0s += $(src)/arch/armv7/llshell/llshell.inc -endif - -$(obj)/mainboard/$(MAINBOARDDIR)/romstage.pre.inc: $(src)/mainboard/$(MAINBOARDDIR)/romstage.c $(OPTION_TABLE_H) $(obj)/build.h $(obj)/config.h - @printf " CC romstage.inc\n" - $(CC) -MMD $(CFLAGS) -D__PRE_RAM__ -I$(src) -I. -I$(obj) -c -S $< -o $@ - -# Things that appear in every board -ramstage-y += exception.c -ramstage-y += exception_asm.S - -romstage-srcs += $(objgenerated)/crt0.s -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/mainboard.c -ifeq ($(CONFIG_GENERATE_PIRQ_TABLE),y) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/irq_tables.c -endif -ifeq ($(CONFIG_BOARD_HAS_HARD_RESET),y) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/reset.c -endif -ifeq ($(CONFIG_GENERATE_ACPI_TABLES),y) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/acpi_tables.c -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/dsdt.asl -# make doesn't have arithmetic operators or greater-than comparisons -ifeq ($(subst 5,4,$(CONFIG_ACPI_SSDTX_NUM)),4) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/ssdt2.asl -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/ssdt3.asl -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/ssdt4.asl -endif -ifeq ($(CONFIG_ACPI_SSDTX_NUM),5) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/ssdt5.asl -endif -endif - -ifeq ($(CONFIG_HAVE_BUS_CONFIG),y) -ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/get_bus_conf.c -endif - -################################################################################ -# Build the final rom image - -$(obj)/coreboot.pre: $(objcbfs)/romstage.elf $(obj)/coreboot.pre1 $(CBFSTOOL) - @printf " CBFS $(subst $(obj)/,,$(@))\n" - cp $(obj)/coreboot.pre1 $@.tmp - $(CBFSTOOL) $@.tmp add-stage \ - -f $(objcbfs)/romstage.elf \ - -n $(CONFIG_CBFS_PREFIX)/romstage -c none - mv $@.tmp $@ - -################################################################################ -# Build the bootblock - -bootblock_lds = $(src)/arch/armv7/bootblock.lds -bootblock_lds += $(chipset_bootblock_lds) - -bootblock_inc += $(src)/arch/armv7/bootblock.inc -bootblock_inc += $(src)/arch/armv7/lib/id.inc -bootblock_inc += $(chipset_bootblock_inc) -bootblock_inc += $(objgenerated)/bootblock.inc - -bootblock_custom = $(src)/$(call strip_quotes,$(CONFIG_BOOTBLOCK_CPU_INIT)) -bootblock_custom += $(src)/$(call strip_quotes,$(CONFIG_BOOTBLOCK_MAINBOARD_INIT)) - -$(objgenerated)/bootblock.ld: $$(bootblock_lds) $(obj)/ldoptions - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach ldscript,ldoptions $(bootblock_lds),INCLUDE "$(ldscript)"\n)' > $@ - -$(objgenerated)/bootblock_inc.S: $$(bootblock_inc) - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach crt0,$(bootblock_inc),#include "$(crt0)"\n)' > $@ - -$(objgenerated)/bootblock.o: $(objgenerated)/bootblock.s - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) $(bootblock-S-ccopts) -Wa,-acdlns -c -o $@ $< > $(basename $@).disasm - -$(objgenerated)/bootblock.s: $(objgenerated)/bootblock_inc.S $(obj)/config.h $(obj)/build.h - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) $(bootblock-S-ccopts) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/armv7/include -I$(obj) -include $(obj)/build.h -include $(obj)/config.h -I. -I$(src) $< -o $@ - -$(objgenerated)/bootblock.inc: $(src)/arch/armv7/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(bootblock_custom) $(OPTION_TABLE_H) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) $(bootblock-c-ccopts) $(INCLUDES) -MM \ - -MT$(objgenerated)/bootblock.inc \ - $< > $(objgenerated)/bootblock.inc.d - $(CC) $(bootblock-c-ccopts) -c -S $(CFLAGS) -I. $(INCLUDES) $< -o $@ - -$(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.o $(objgenerated)/bootblock.ld $$(bootblock-objs) $(stages) - @printf " LINK $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m armelf_linux_eabi -include $(obj)/config.h -static -o $@.tmp -L$(obj) $< -T $(objgenerated)/bootblock.ld -else - $(CC) -nostdlib -nostartfiles -include $(obj)/config.h -static -o $@ -L$(obj) -T $(objgenerated)/bootblock.ld -Wl,--start-group $(objgenerated)/bootblock.o $(bootblock-objs) $(stages) $(LIBGCC_FILE_NAME) -Wl,--end-group -endif - -################################################################################ -# Build the romstage - -$(objcbfs)/romstage.debug: $$(romstage-objs) $(stages_o) $(objgenerated)/romstage.ld - @printf " LINK $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -nostdlib -nostartfiles -static -o $@ -L$(obj) $(romstage-objs) -T $(objgenerated)/romstage.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(objgenerated)/romstage.ld -Wl,--start-group $(romstage-objs) $(stages_o) $(LIBGCC_FILE_NAME) -Wl,--end-group -endif - -$(objgenerated)/romstage.ld: $$(ldscripts) $(obj)/ldoptions - @printf " GEN $(subst $(obj)/,,$(@))\n" - rm -f $@ - printf '$(foreach ldscript,ldoptions $(ldscripts),INCLUDE "$(ldscript:$(obj)/%=%)"\n)' >> $@.tmp - mv $@.tmp $@ - -$(objgenerated)/crt0.romstage.S: $$(crt0s) - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach crt0,$(crt0s),#include "$(crt0:$(obj)/%=%)"\n)' > $@ - -$(objgenerated)/crt0.romstage.o: $(objgenerated)/crt0.s - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -Wa,-acdlns -c -o $@ $< > $(basename $@).disasm - -$(objgenerated)/crt0.s: $(objgenerated)/crt0.romstage.S $(obj)/config.h $(obj)/build.h - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/armv7/include -I$(obj) -include $(obj)/config.h -include $(obj)/build.h -I. -I$(src) $< -o $@ - diff --git a/src/arch/armv7/boot/Makefile.inc b/src/arch/armv7/boot/Makefile.inc deleted file mode 100644 index 8d24fae10e..0000000000 --- a/src/arch/armv7/boot/Makefile.inc +++ /dev/null @@ -1,12 +0,0 @@ -ramstage-y += boot.c -#ramstage-$(CONFIG_MULTIBOOT) += multiboot.c -ramstage-y += tables.c -#ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c -#ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpigen.c -#ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S - -#FIXME(dhendrix): is there anything preventing multiboot from -#working on ARM? - -$(obj)/arch/armv7/boot/coreboot_table.ramstage.o : $(OPTION_TABLE_H) -#$(obj)/arch/x86/boot/smbios.ramstage.o: $(obj)/build.h diff --git a/src/arch/armv7/boot/boot.c b/src/arch/armv7/boot/boot.c deleted file mode 100644 index ab531be868..0000000000 --- a/src/arch/armv7/boot/boot.c +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -#ifndef CMD_LINE -#define CMD_LINE "" -#endif - - - -#define UPSZ(X) ((sizeof(X) + 3) &~3) - -static struct { - Elf_Bhdr hdr; - Elf_Nhdr ft_hdr; - unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)]; - Elf_Nhdr bl_hdr; - unsigned char bl_desc[UPSZ(BOOTLOADER)]; - Elf_Nhdr blv_hdr; - unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; - Elf_Nhdr cmd_hdr; - unsigned char cmd_desc[UPSZ(CMD_LINE)]; -} elf_boot_notes = { - .hdr = { - .b_signature = 0x0E1FB007, - .b_size = sizeof(elf_boot_notes), - .b_checksum = 0, - .b_records = 4, - }, - .ft_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(FIRMWARE_TYPE), - .n_type = EBN_FIRMWARE_TYPE, - }, - .ft_desc = FIRMWARE_TYPE, - .bl_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER), - .n_type = EBN_BOOTLOADER_NAME, - }, - .bl_desc = BOOTLOADER, - .blv_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER_VERSION), - .n_type = EBN_BOOTLOADER_VERSION, - }, - .blv_desc = BOOTLOADER_VERSION, - .cmd_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(CMD_LINE), - .n_type = EBN_COMMAND_LINE, - }, - .cmd_desc = CMD_LINE, -}; - - -int elf_check_arch(Elf_ehdr *ehdr) -{ - return ( - ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) && - (ehdr->e_ident[EI_CLASS] == ELFCLASS32) && - (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) - ); - -} - -void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) -{ - extern unsigned char _ram_seg, _eram_seg; - unsigned long lb_start, lb_size; - unsigned long adjust, adjusted_boot_notes; - - elf_boot_notes.hdr.b_checksum = - compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes)); - - lb_start = (unsigned long)&_ram_seg; - lb_size = (unsigned long)(&_eram_seg - &_ram_seg); - adjust = buffer + size - lb_start; - - adjusted_boot_notes = (unsigned long)&elf_boot_notes; - adjusted_boot_notes += adjust; - - printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry); - printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start); - printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size); - printk(BIOS_SPEW, "adjust = 0x%08lx\n", adjust); - printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer); - printk(BIOS_SPEW, " elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes); - printk(BIOS_SPEW, "adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes); - - stage_exit(entry); -#if 0 - /* FIXME: do we need any of this? */ - /* Jump to kernel */ - __asm__ __volatile__( - " cld \n\t" - /* Save the callee save registers... */ - " pushl %%esi\n\t" - " pushl %%edi\n\t" - " pushl %%ebx\n\t" - /* Save the parameters I was passed */ - " pushl $0\n\t" /* 20 adjust */ - " pushl %0\n\t" /* 16 lb_start */ - " pushl %1\n\t" /* 12 buffer */ - " pushl %2\n\t" /* 8 lb_size */ - " pushl %3\n\t" /* 4 entry */ - " pushl %4\n\t" /* 0 elf_boot_notes */ - /* Compute the adjustment */ - " xorl %%eax, %%eax\n\t" - " subl 16(%%esp), %%eax\n\t" - " addl 12(%%esp), %%eax\n\t" - " addl 8(%%esp), %%eax\n\t" - " movl %%eax, 20(%%esp)\n\t" - /* Place a copy of coreboot in its new location */ - /* Move ``longs'' the coreboot size is 4 byte aligned */ - " movl 12(%%esp), %%edi\n\t" - " addl 8(%%esp), %%edi\n\t" - " movl 16(%%esp), %%esi\n\t" - " movl 8(%%esp), %%ecx\n\n" - " shrl $2, %%ecx\n\t" - " rep movsl\n\t" - - /* Adjust the stack pointer to point into the new coreboot image */ - " addl 20(%%esp), %%esp\n\t" - /* Adjust the instruction pointer to point into the new coreboot image */ - " movl $1f, %%eax\n\t" - " addl 20(%%esp), %%eax\n\t" - " jmp *%%eax\n\t" - "1: \n\t" - - /* Copy the coreboot bounce buffer over coreboot */ - /* Move ``longs'' the coreboot size is 4 byte aligned */ - " movl 16(%%esp), %%edi\n\t" - " movl 12(%%esp), %%esi\n\t" - " movl 8(%%esp), %%ecx\n\t" - " shrl $2, %%ecx\n\t" - " rep movsl\n\t" - - /* Now jump to the loaded image */ - " movl %5, %%eax\n\t" - " movl 0(%%esp), %%ebx\n\t" - " call *4(%%esp)\n\t" - - /* The loaded image returned? */ - " cli \n\t" - " cld \n\t" - - /* Copy the saved copy of coreboot where coreboot runs */ - /* Move ``longs'' the coreboot size is 4 byte aligned */ - " movl 16(%%esp), %%edi\n\t" - " movl 12(%%esp), %%esi\n\t" - " addl 8(%%esp), %%esi\n\t" - " movl 8(%%esp), %%ecx\n\t" - " shrl $2, %%ecx\n\t" - " rep movsl\n\t" - - /* Adjust the stack pointer to point into the old coreboot image */ - " subl 20(%%esp), %%esp\n\t" - - /* Adjust the instruction pointer to point into the old coreboot image */ - " movl $1f, %%eax\n\t" - " subl 20(%%esp), %%eax\n\t" - " jmp *%%eax\n\t" - "1: \n\t" - - /* Drop the parameters I was passed */ - " addl $24, %%esp\n\t" - - /* Restore the callee save registers */ - " popl %%ebx\n\t" - " popl %%edi\n\t" - " popl %%esi\n\t" - - :: - "ri" (lb_start), "ri" (buffer), "ri" (lb_size), - "ri" (entry), -#if CONFIG_MULTIBOOT - "ri"(mbi), "ri" (MB_MAGIC2) -#else - "ri"(adjusted_boot_notes), "ri" (0x0E1FB007) -#endif - ); -#endif -} diff --git a/src/arch/armv7/coreboot_ram.ld b/src/arch/armv7/coreboot_ram.ld deleted file mode 100644 index c2ead7aa12..0000000000 --- a/src/arch/armv7/coreboot_ram.ld +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Memory map: - * - * CONFIG_RAMBASE : text segment - * : rodata segment - * : data segment - * : bss segment - * : stack - * : heap - */ -/* - * Bootstrap code for the STPC Consumer - * Copyright (c) 1999 by Net Insight AB. All Rights Reserved. - */ - -/* - * Written by Johan Rydberg, based on work by Daniel Kahlin. - * Rewritten by Eric Biederman - * 2005.12 yhlu add coreboot_ram cross the vga font buffer handling - */ - -/* We use ELF as output format. So that we can debug the code in some form. */ -INCLUDE ldoptions - -ENTRY(stage_entry) - -SECTIONS -{ - . = CONFIG_SYS_SDRAM_BASE; - /* First we place the code and read only data (typically const declared). - * This could theoretically be placed in rom. - */ - .text : { - _text = .; - _start = .; - *(.text.stage_entry.armv7); - *(.text); - *(.text.*); - . = ALIGN(16); - _etext = .; - } - - .ctors : { - . = ALIGN(0x100); - __CTOR_LIST__ = .; - *(.ctors); - LONG(0); - __CTOR_END__ = .; - } - - .rodata : { - _rodata = .; - . = ALIGN(4); - console_drivers = .; - *(.rodata.console_drivers) - econsole_drivers = . ; - . = ALIGN(4); - pci_drivers = . ; - *(.rodata.pci_driver) - epci_drivers = . ; - cpu_drivers = . ; - *(.rodata.cpu_driver) - ecpu_drivers = . ; - *(.rodata) - *(.rodata.*) - /* kevinh/Ispiri - Added an align, because the objcopy tool - * incorrectly converts sections that are not long word aligned. - */ - . = ALIGN(4); - - _erodata = .; - } - /* After the code we place initialized data (typically initialized - * global variables). This gets copied into ram by startup code. - * __data_start and __data_end shows where in ram this should be placed, - * whereas __data_loadstart and __data_loadend shows where in rom to - * copy from. - */ - .data : { - _data = .; - *(.data) - _edata = .; - } - - /* bss does not contain data, it is just a space that should be zero - * initialized on startup. (typically uninitialized global variables) - * crt0.S fills between _bss and _ebss with zeroes. - */ - _bss = .; - .bss . : { - *(.bss) - *(.sbss) - *(COMMON) - } - _ebss = .; - _end = .; - - /* coreboot really "ends" here. Only heap and stack are placed after - * this line. - */ - - _heap = .; - .heap . : { - /* Reserve CONFIG_HEAP_SIZE bytes for the heap */ - . = CONFIG_HEAP_SIZE ; - . = ALIGN(4); - } - _eheap = .; - - _stack = CONFIG_STACK_BOTTOM; - _estack = CONFIG_STACK_TOP; - - /* The ram segment. This includes all memory used by the memory - * resident copy of coreboot, except the tables that are produced on - * the fly, but including stack and heap. - */ - _ram_seg = _text; - _eram_seg = _eheap; - - /* Discard the sections we don't need/want */ - - /DISCARD/ : { - *(.comment) - *(.note) - *(.note.*) - } -} diff --git a/src/arch/armv7/include/arch/gpio.h b/src/arch/armv7/include/arch/gpio.h deleted file mode 100644 index b5dd9b7345..0000000000 --- a/src/arch/armv7/include/arch/gpio.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * Copyright (c) 2011, NVIDIA Corp. All rights reserved. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _ASM_GENERIC_GPIO_H_ -#define _ASM_GENERIC_GPIO_H_ - -/* - * Generic GPIO API for U-Boot - * - * GPIOs are numbered from 0 to GPIO_COUNT-1 which value is defined - * by the SOC/architecture. - * - * Each GPIO can be an input or output. If an input then its value can - * be read as 0 or 1. If an output then its value can be set to 0 or 1. - * If you try to write an input then the value is undefined. If you try - * to read an output, barring something very unusual, you will get - * back the value of the output that you previously set. - * - * In some cases the operation may fail, for example if the GPIO number - * is out of range, or the GPIO is not available because its pin is - * being used by another function. In that case, functions may return - * an error value of -1. - */ - -/** - * Stop using the GPIO. This function should not alter pin configuration. - * - * @param gpio GPIO number - * @return 0 if ok, -1 on error - */ -int gpio_free(unsigned gpio); - -/** - * Make a GPIO an input. - * - * @param gpio GPIO number - * @return 0 if ok, -1 on error - */ -int gpio_direction_input(unsigned gpio); - -/** - * Make a GPIO an output, and set its value. - * - * @param gpio GPIO number - * @param value GPIO value (0 for low or 1 for high) - * @return 0 if ok, -1 on error - */ -int gpio_direction_output(unsigned gpio, int value); - -/** - * Get a GPIO's value. This will work whether the GPIO is an input - * or an output. - * - * @param gpio GPIO number - * @return 0 if low, 1 if high, -1 on error - */ -int gpio_get_value(unsigned gpio); - -/** - * Set an output GPIO's value. The GPIO must already be an output or - * this function may have no effect. - * - * @param gpio GPIO number - * @param value GPIO value (0 for low or 1 for high) - * @return 0 if ok, -1 on error - */ -int gpio_set_value(unsigned gpio, int value); - -/** - * Request ownership of a gpio. This should be called before any of the other - * functions are used on this gpio. - * - * @param gp GPIO number - * @param label User label for this GPIO - * @return 0 if ok, -1 on error - */ -int gpio_request(unsigned gpio, const char *label); - -#endif /* _ASM_GENERIC_GPIO_H_ */ diff --git a/src/arch/armv7/include/arch/io.h b/src/arch/armv7/include/arch/io.h deleted file mode 100644 index b99e014392..0000000000 --- a/src/arch/armv7/include/arch/io.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * linux/include/asm-arm/io.h - * - * Copyright (C) 1996-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Modifications: - * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both - * constant addresses and variable addresses. - * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture - * specific IO header files. - * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. - * 04-Apr-1999 PJB Added check_signature. - * 12-Dec-1999 RMK More cleanups - * 18-Jun-2000 RMK Removed virt_to_* and friends definitions - */ -#ifndef __ASM_ARM_IO_H -#define __ASM_ARM_IO_H - -#include -#include /* for dmb() */ -#include - -static inline void sync(void) -{ -} - -/* - * Generic virtual read/write. Note that we don't support half-word - * read/writes. We define __arch_*[bl] here, and leave __arch_*w - * to the architecture specific code. - */ -#define __arch_getb(a) (*(volatile unsigned char *)(a)) -#define __arch_getw(a) (*(volatile unsigned short *)(a)) -#define __arch_getl(a) (*(volatile unsigned int *)(a)) - -#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v)) -#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) -#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) - -#if 0 -extern inline void __raw_writesb(unsigned int addr, const void *data, int bytelen) -{ - uint8_t *buf = (uint8_t *)data; - while(bytelen--) - __arch_putb(*buf++, addr); -} - -extern inline void __raw_writesw(unsigned int addr, const void *data, int wordlen) -{ - uint16_t *buf = (uint16_t *)data; - while(wordlen--) - __arch_putw(*buf++, addr); -} - -extern inline void __raw_writesl(unsigned int addr, const void *data, int longlen) -{ - uint32_t *buf = (uint32_t *)data; - while(longlen--) - __arch_putl(*buf++, addr); -} - -extern inline void __raw_readsb(unsigned int addr, void *data, int bytelen) -{ - uint8_t *buf = (uint8_t *)data; - while(bytelen--) - *buf++ = __arch_getb(addr); -} - -extern inline void __raw_readsw(unsigned int addr, void *data, int wordlen) -{ - uint16_t *buf = (uint16_t *)data; - while(wordlen--) - *buf++ = __arch_getw(addr); -} - -extern inline void __raw_readsl(unsigned int addr, void *data, int longlen) -{ - uint32_t *buf = (uint32_t *)data; - while(longlen--) - *buf++ = __arch_getl(addr); -} -#endif - -#define __raw_writeb(v,a) __arch_putb(v,a) -#define __raw_writew(v,a) __arch_putw(v,a) -#define __raw_writel(v,a) __arch_putl(v,a) - -#define __raw_readb(a) __arch_getb(a) -#define __raw_readw(a) __arch_getw(a) -#define __raw_readl(a) __arch_getl(a) - -/* - * TODO: The kernel offers some more advanced versions of barriers, it might - * have some advantages to use them instead of the simple one here. - */ -#define __iormb() dmb() -#define __iowmb() dmb() - -#define writeb(v,c) ({ u8 __v = v; __iowmb(); __arch_putb(__v,c); __v; }) -#define writew(v,c) ({ u16 __v = v; __iowmb(); __arch_putw(__v,c); __v; }) -#define writel(v,c) ({ u32 __v = v; __iowmb(); __arch_putl(__v,c); __v; }) - -#define readb(c) ({ u8 __v = __arch_getb(c); __iormb(); __v; }) -#define readw(c) ({ u16 __v = __arch_getw(c); __iormb(); __v; }) -#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; }) - -/* - * The compiler seems to be incapable of optimising constants - * properly. Spell it out to the compiler in some cases. - * These are only valid for small values of "off" (< 1<<12) - */ -#define __raw_base_writeb(val,base,off) __arch_base_putb(val,base,off) -#define __raw_base_writew(val,base,off) __arch_base_putw(val,base,off) -#define __raw_base_writel(val,base,off) __arch_base_putl(val,base,off) - -#define __raw_base_readb(base,off) __arch_base_getb(base,off) -#define __raw_base_readw(base,off) __arch_base_getw(base,off) -#define __raw_base_readl(base,off) __arch_base_getl(base,off) - -/* - * Clear and set bits in one shot. These macros can be used to clear and - * set multiple bits in a register using a single call. These macros can - * also be used to set a multiple-bit bit pattern using a mask, by - * specifying the mask in the 'clear' parameter and the new bit pattern - * in the 'set' parameter. - */ - -#define out_arch(type,endian,a,v) __raw_write##type(cpu_to_##endian(v),a) -#define in_arch(type,endian,a) endian##_to_cpu(__raw_read##type(a)) - -#define out_le32(a,v) out_arch(l,le32,a,v) -#define out_le16(a,v) out_arch(w,le16,a,v) - -#define in_le32(a) in_arch(l,le32,a) -#define in_le16(a) in_arch(w,le16,a) - -#define out_be32(a,v) out_arch(l,be32,a,v) -#define out_be16(a,v) out_arch(w,be16,a,v) - -#define in_be32(a) in_arch(l,be32,a) -#define in_be16(a) in_arch(w,be16,a) - -#define out_8(a,v) __raw_writeb(v,a) -#define in_8(a) __raw_readb(a) - -#define clrbits(type, addr, clear) \ - out_##type((addr), in_##type(addr) & ~(clear)) - -#define setbits(type, addr, set) \ - out_##type((addr), in_##type(addr) | (set)) - -#define clrsetbits(type, addr, clear, set) \ - out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) - -#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) -#define setbits_be32(addr, set) setbits(be32, addr, set) -#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) - -#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) -#define setbits_le32(addr, set) setbits(le32, addr, set) -#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) - -#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) -#define setbits_be16(addr, set) setbits(be16, addr, set) -#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) - -#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) -#define setbits_le16(addr, set) setbits(le16, addr, set) -#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) - -#define clrbits_8(addr, clear) clrbits(8, addr, clear) -#define setbits_8(addr, set) setbits(8, addr, set) -#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) - -/* - * Now, pick up the machine-defined IO definitions - */ -#if 0 /* XXX###XXX */ -#include -#endif /* XXX###XXX */ - -/* - * IO port access primitives - * ------------------------- - * - * The ARM doesn't have special IO access instructions; all IO is memory - * mapped. Note that these are defined to perform little endian accesses - * only. Their primary purpose is to access PCI and ISA peripherals. - * - * Note that for a big endian machine, this implies that the following - * big endian mode connectivity is in place, as described by numerous - * ARM documents: - * - * PCI: D0-D7 D8-D15 D16-D23 D24-D31 - * ARM: D24-D31 D16-D23 D8-D15 D0-D7 - * - * The machine specific io.h include defines __io to translate an "IO" - * address to a memory address. - * - * Note that we prevent GCC re-ordering or caching values in expressions - * by introducing sequence points into the in*() definitions. Note that - * __raw_* do not guarantee this behaviour. - * - * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space. - */ -#ifdef __io -#define outb(v,p) __raw_writeb(v,__io(p)) -#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p)) -#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p)) - -#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; }) -#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; }) -#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; }) - -#define outsb(p,d,l) __raw_writesb(__io(p),d,l) -#define outsw(p,d,l) __raw_writesw(__io(p),d,l) -#define outsl(p,d,l) __raw_writesl(__io(p),d,l) - -#define insb(p,d,l) __raw_readsb(__io(p),d,l) -#define insw(p,d,l) __raw_readsw(__io(p),d,l) -#define insl(p,d,l) __raw_readsl(__io(p),d,l) -#endif - -#define outb_p(val,port) outb((val),(port)) -#define outw_p(val,port) outw((val),(port)) -#define outl_p(val,port) outl((val),(port)) -#define inb_p(port) inb((port)) -#define inw_p(port) inw((port)) -#define inl_p(port) inl((port)) - -#define outsb_p(port,from,len) outsb(port,from,len) -#define outsw_p(port,from,len) outsw(port,from,len) -#define outsl_p(port,from,len) outsl(port,from,len) -#define insb_p(port,to,len) insb(port,to,len) -#define insw_p(port,to,len) insw(port,to,len) -#define insl_p(port,to,len) insl(port,to,len) - -/* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off,sz,nocache) \ - ({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off),_size,nocache); \ - _ret; \ - }) - -#define __arch_iounmap __iounmap -#endif - -/* - * String version of IO memory access ops: - */ -extern void _memcpy_fromio(void *, unsigned long, size_t); -extern void _memcpy_toio(unsigned long, const void *, size_t); -extern void _memset_io(unsigned long, int, size_t); - -extern void __readwrite_bug(const char *fn); - -/* - * If this architecture has PCI memory IO, then define the read/write - * macros. These should only be used with the cookie passed from - * ioremap. - */ -#ifdef __mem_pci - -#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; }) -#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; }) -#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; }) - -#define writeb(v,c) __raw_writeb(v,__mem_pci(c)) -#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c)) -#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c)) - -#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l)) -#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l)) -#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l)) - -#define eth_io_copy_and_sum(s,c,l,b) \ - eth_copy_and_sum((s),__mem_pci(c),(l),(b)) - -static inline int -check_signature(unsigned long io_addr, const unsigned char *signature, - int length) -{ - int retval = 0; - do { - if (readb(io_addr) != *signature) - goto out; - io_addr++; - signature++; - length--; - } while (length); - retval = 1; -out: - return retval; -} - -#elif !defined(readb) - -#define readb(addr) (__readwrite_bug("readb"),0) -#define readw(addr) (__readwrite_bug("readw"),0) -#define readl(addr) (__readwrite_bug("readl"),0) -#define writeb(v,addr) __readwrite_bug("writeb") -#define writew(v,addr) __readwrite_bug("writew") -#define writel(v,addr) __readwrite_bug("writel") - -#define eth_io_copy_and_sum(a,b,c,d) __readwrite_bug("eth_io_copy_and_sum") - -#define check_signature(io,sig,len) (0) - -#endif /* __mem_pci */ - -/* FIXME(dhendrix): added to make uart8250_mem code happy. Note: lL */ -static inline __attribute__((always_inline)) uint8_t read8(unsigned long addr) -{ - return readb(addr); -} - -static inline __attribute__((always_inline)) uint16_t read16(unsigned long addr) -{ - return readw(addr); -} - -static inline __attribute__((always_inline)) uint32_t read32(unsigned long addr) -{ - return readl(addr); -} - -static inline __attribute__((always_inline)) void write8(unsigned long addr, uint8_t value) -{ - writeb(value, addr); -} - -static inline __attribute__((always_inline)) void write16(unsigned long addr, uint16_t value) -{ - writew(value, addr); -} - -static inline __attribute__((always_inline)) void write32(unsigned long addr, uint32_t value) -{ - writel(value, addr); -} - - -/* - * If this architecture has ISA IO, then define the isa_read/isa_write - * macros. - */ -#ifdef __mem_isa - -#define isa_readb(addr) __raw_readb(__mem_isa(addr)) -#define isa_readw(addr) __raw_readw(__mem_isa(addr)) -#define isa_readl(addr) __raw_readl(__mem_isa(addr)) -#define isa_writeb(val,addr) __raw_writeb(val,__mem_isa(addr)) -#define isa_writew(val,addr) __raw_writew(val,__mem_isa(addr)) -#define isa_writel(val,addr) __raw_writel(val,__mem_isa(addr)) -#define isa_memset_io(a,b,c) _memset_io(__mem_isa(a),(b),(c)) -#define isa_memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_isa(b),(c)) -#define isa_memcpy_toio(a,b,c) _memcpy_toio(__mem_isa((a)),(b),(c)) - -#define isa_eth_io_copy_and_sum(a,b,c,d) \ - eth_copy_and_sum((a),__mem_isa(b),(c),(d)) - -static inline int -isa_check_signature(unsigned long io_addr, const unsigned char *signature, - int length) -{ - int retval = 0; - do { - if (isa_readb(io_addr) != *signature) - goto out; - io_addr++; - signature++; - length--; - } while (length); - retval = 1; -out: - return retval; -} - -#else /* __mem_isa */ - -#define isa_readb(addr) (__readwrite_bug("isa_readb"),0) -#define isa_readw(addr) (__readwrite_bug("isa_readw"),0) -#define isa_readl(addr) (__readwrite_bug("isa_readl"),0) -#define isa_writeb(val,addr) __readwrite_bug("isa_writeb") -#define isa_writew(val,addr) __readwrite_bug("isa_writew") -#define isa_writel(val,addr) __readwrite_bug("isa_writel") -#define isa_memset_io(a,b,c) __readwrite_bug("isa_memset_io") -#define isa_memcpy_fromio(a,b,c) __readwrite_bug("isa_memcpy_fromio") -#define isa_memcpy_toio(a,b,c) __readwrite_bug("isa_memcpy_toio") - -#define isa_eth_io_copy_and_sum(a,b,c,d) \ - __readwrite_bug("isa_eth_io_copy_and_sum") - -#define isa_check_signature(io,sig,len) (0) - -#endif /* __mem_isa */ -#endif /* __ASM_ARM_IO_H */ diff --git a/src/arch/armv7/include/arch/pci_ops.h b/src/arch/armv7/include/arch/pci_ops.h deleted file mode 100644 index eca939045f..0000000000 --- a/src/arch/armv7/include/arch/pci_ops.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ARCH_I386_PCI_OPS_H -#define ARCH_I386_PCI_OPS_H - -extern const struct pci_bus_operations pci_cf8_conf1; - -#if CONFIG_MMCONF_SUPPORT -extern const struct pci_bus_operations pci_ops_mmconf; -#endif - -static inline const struct pci_bus_operations *pci_config_default(void) -{ - return &pci_cf8_conf1; -} - -static inline void pci_set_method(device_t dev) -{ - dev->ops->ops_pci_bus = pci_config_default(); -} -#endif /* ARCH_I386_PCI_OPS_H */ diff --git a/src/arch/armv7/include/common.h b/src/arch/armv7/include/common.h deleted file mode 100644 index c02581338f..0000000000 --- a/src/arch/armv7/include/common.h +++ /dev/null @@ -1,445 +0,0 @@ -/* - * (C) Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __COMMON_H_ -#define __COMMON_H_ 1 - -#ifndef __ASSEMBLER__ /* put C only stuff in this section */ - -#include - -#ifdef DEBUG -#define debug(fmt,args...) printf (fmt ,##args) -#define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args); -#else -#define debug(fmt,args...) -#define debugX(level,fmt,args...) -#endif /* DEBUG */ - -#ifdef DEBUG -# define _DEBUG 1 -#else -# define _DEBUG 0 -#endif - -/* - * An assertion is run-time check done in debug mode only. If DEBUG is not - * defined then it is skipped. If DEBUG is defined and the assertion fails, - * then it calls panic*( which may or may not reset/halt U-Boot (see - * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found - * before release, and after release it is hoped that they don't matter. But - * in any case these failing assertions cannot be fixed with a reset (which - * may just do the same assertion again). - */ -void __assert_fail(const char *assertion, const char *file, unsigned line, - const char *function); -#define assert(x) \ - ({ if (!(x) && _DEBUG) \ - __assert_fail(#x, __FILE__, __LINE__, __func__); }) - -#define error(fmt, args...) do { \ - printf("ERROR: " fmt "\nat %s:%d/%s()\n", \ - ##args, __FILE__, __LINE__, __func__); \ -} while (0) - -#ifndef BUG -#define BUG() do { \ - printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ - panic("BUG!"); \ -} while (0) -#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -#endif /* BUG */ - -/* Force a compilation error if condition is true */ -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) - -typedef void (interrupt_handler_t)(void *); - -/* - * Return the time since boot in microseconds, This is needed for bootstage - * and should be defined in CPU- or board-specific code. If undefined then - * millisecond resolution will be used (the standard get_timer()). - */ -unsigned long timer_get_boot_us(void); - -/* - * Return the current value of a monotonically increasing microsecond timer. - * Granularity may be larger than 1us if hardware does not support this. - */ -unsigned long timer_get_us(void); - -/* - * General Purpose Utilities - */ -#if 0 -#define min(X, Y) \ - ({ typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ - (__x < __y) ? __x : __y; }) - -#define max(X, Y) \ - ({ typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ - (__x > __y) ? __x : __y; }) -#define MIN(x, y) min(x, y) -#define MAX(x, y) max(x, y) -#endif - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Function Prototypes - */ - -int init_timer(void); /* FIXME(dhendrix): used to be timer_init() */ -int cpu_init(void); - -/* */ -unsigned long long initdram (int); -int display_options (void); -void print_size(unsigned long long, const char *); -int print_buffer (unsigned long addr, void* data, unsigned int width, unsigned int count, unsigned int linelen); - -/* common/main.c */ -void main_loop (void); -int run_command (const char *cmd, int flag); -int readline (const char *const prompt); -int readline_into_buffer (const char *const prompt, char * buffer); -int parse_line (char *, char *[]); -void init_cmd_timeout(void); -void reset_cmd_timeout(void); - -/* arch/$(ARCH)/lib/board.c */ -void board_init_f (void); -int checkboard (void); -int checkflash (void); -int checkdram (void); -int last_stage_init(void); -extern unsigned long monitor_flash_len; -int mac_read_from_eeprom(void); - -#ifdef CONFIG_ARM -# include -# include -# include /* ARM version to be fixed! */ -#endif /* CONFIG_ARM */ - -int misc_init_f (void); -int misc_init_r (void); - -/* common/exports.c */ -void jumptable_init(void); - -/* common/kallsysm.c */ -const char *symbol_lookup(unsigned long addr, unsigned long *caddr); - -/* api/api.c */ -void api_init (void); - -/* common/memsize.c */ -long get_ram_size (long *, long); - -/* $(BOARD)/$(BOARD).c */ -void reset_phy (void); -void fdc_hw_init (void); - -/* $(BOARD)/eeprom.c */ -void eeprom_init (void); -#ifndef CONFIG_SPI -int eeprom_probe (unsigned dev_addr, unsigned offset); -#endif -int eeprom_read (unsigned dev_addr, unsigned offset, unsigned char *buffer, unsigned cnt); -int eeprom_write (unsigned dev_addr, unsigned offset, unsigned char *buffer, unsigned cnt); - -/* - * Set this up regardless of board - * type, to prevent errors. - */ -#if defined(CONFIG_SPI) || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) -# define CONFIG_SYS_DEF_EEPROM_ADDR 0 -#else -#if !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) -# define CONFIG_SYS_DEF_EEPROM_ADDR CONFIG_SYS_I2C_EEPROM_ADDR -#endif -#endif /* CONFIG_SPI || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) */ - -#if defined(CONFIG_SPI) -extern void spi_init_f (void); -extern void spi_init_r (void); -extern ssize_t spi_read (unsigned char *, int, unsigned char *, int); -extern ssize_t spi_write (unsigned char *, int, unsigned char *, int); -#endif - -/* $(BOARD)/$(BOARD).c */ -int board_early_init_f (void); -int board_late_init (void); -int board_postclk_init (void); /* after clocks/timebase, before env/serial */ -int board_early_init_r (void); -void board_poweroff (void); - -#if defined(CONFIG_SYS_DRAM_TEST) -int testdram(void); -#endif /* CONFIG_SYS_DRAM_TEST */ - -/* $(CPU)/start.S */ -#if defined(CONFIG_5xx) || \ - defined(CONFIG_8xx) -unsigned int get_immr (unsigned int); -#endif -unsigned int get_pir (void); -#if defined(CONFIG_MPC5xxx) -unsigned int get_svr (void); -#endif -unsigned int get_pvr (void); -unsigned int get_svr (void); -unsigned int rd_ic_cst (void); -void wr_ic_cst (unsigned int); -void wr_ic_adr (unsigned int); -unsigned int rd_dc_cst (void); -void wr_dc_cst (unsigned int); -void wr_dc_adr (unsigned int); -int icache_status (void); -void icache_enable (unsigned long start, unsigned long size); -void icache_disable(void); -int dcache_status (void); -void dcache_enable (unsigned long start, unsigned long size); -void dcache_disable(void); -void mmu_disable(void); -unsigned long get_endaddr (void); -void trap_init (unsigned long); -#if defined (CONFIG_4xx) || \ - defined (CONFIG_MPC5xxx) || \ - defined (CONFIG_74xx_7xx) || \ - defined (CONFIG_74x) || \ - defined (CONFIG_75x) || \ - defined (CONFIG_74xx) || \ - defined (CONFIG_MPC8220) || \ - defined (CONFIG_MPC85xx) || \ - defined (CONFIG_MPC86xx) || \ - defined (CONFIG_MPC83xx) -unsigned char in8(unsigned int); -void out8(unsigned int, unsigned char); -unsigned short in16(unsigned int); -unsigned short in16r(unsigned int); -void out16(unsigned int, unsigned short value); -void out16r(unsigned int, unsigned short value); -unsigned long in32(unsigned int); -unsigned long in32r(unsigned int); -void out32(unsigned int, unsigned long value); -void out32r(unsigned int, unsigned long value); -void ppcDcbf(unsigned long value); -void ppcDcbi(unsigned long value); -void ppcSync(void); -void ppcDcbz(unsigned long value); -#endif - -/* $(CPU)/cpu.c */ -static inline int cpumask_next(int cpu, unsigned int mask) -{ - for (cpu++; !((1 << cpu) & mask); cpu++) - ; - - return cpu; -} - -#define for_each_cpu(iter, cpu, num_cpus, mask) \ - for (iter = 0, cpu = cpumask_next(-1, mask); \ - iter < num_cpus; \ - iter++, cpu = cpumask_next(cpu, mask)) \ - -int cpu_numcores (void); -u32 cpu_mask (void); -int is_core_valid (unsigned int); -int probecpu (void); -int checkcpu (void); -int checkicache (void); -int checkdcache (void); -void upmconfig (unsigned int, unsigned int *, unsigned int); -unsigned long get_tbclk (void); -#if defined (CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP) -void ft_cpu_setup(void *blob, bd_t *bd); -#endif - - -/* $(CPU)/serial.c */ -int serial_init (void); -void serial_setbrg (void); -void serial_putc (const char); -void serial_putc_raw(const char); -void serial_puts (const char *); -int serial_getc (void); -int serial_tstc (void); - -void _serial_setbrg (const int); -void _serial_putc (const char, const int); -void _serial_putc_raw(const char, const int); -void _serial_puts (const char *, const int); -int _serial_getc (const int); -int _serial_tstc (const int); - -/* $(CPU)/speed.c */ -int get_clocks (void); -int get_clocks_866 (void); -int sdram_adjust_866 (void); -int adjust_sdram_tbs_8xx (void); -#if defined(CONFIG_8260) -int prt_8260_clks (void); -#elif defined(CONFIG_MPC5xxx) -int prt_mpc5xxx_clks (void); -#endif -#if defined(CONFIG_MPC512X) -int prt_mpc512xxx_clks (void); -#endif -#if defined(CONFIG_MPC8220) -int prt_mpc8220_clks (void); -#endif -#ifdef CONFIG_4xx -unsigned long get_OPB_freq (void); -unsigned long get_PCI_freq (void); -#endif -#if defined(CONFIG_S3C24X0) || \ - defined(CONFIG_LH7A40X) || \ - defined(CONFIG_S3C6400) || \ - defined(CONFIG_EP93XX) -unsigned long get_FCLK (void); -unsigned long get_HCLK (void); -unsigned long get_PCLK (void); -unsigned long get_UCLK (void); -#endif -#if defined(CONFIG_LH7A40X) -unsigned long get_PLLCLK (void); -#endif -#if defined CONFIG_INCA_IP -unsigned int incaip_get_cpuclk (void); -#endif -#if defined(CONFIG_IMX) -unsigned long get_systemPLLCLK(void); -unsigned long get_FCLK(void); -unsigned long get_HCLK(void); -unsigned long get_BCLK(void); -unsigned long get_PERCLK1(void); -unsigned long get_PERCLK2(void); -unsigned long get_PERCLK3(void); -#endif -unsigned long get_bus_freq (unsigned long); -int get_serial_clock(void); - -struct pt_regs; -/* $(CPU)/interrupts.c */ -int interrupt_init (void); -void timer_interrupt (struct pt_regs *); -void external_interrupt (struct pt_regs *); -void irq_install_handler(int, interrupt_handler_t *, void *); -void irq_free_handler (int); -void reset_timer (void); -unsigned long get_timer (unsigned long base); -void enable_interrupts (void); -int disable_interrupts (void); - -/* $(CPU)/.../commproc.c */ -int dpram_init (void); -unsigned int dpram_base(void); -unsigned int dpram_base_align(unsigned int align); -unsigned int dpram_alloc(unsigned int size); -unsigned int dpram_alloc_align(unsigned int size,unsigned int align); -void bootcount_store (unsigned long); -unsigned long bootcount_load (void); -#define BOOTCOUNT_MAGIC 0xB001C041 - -/* $(CPU)/.../ */ -void mii_init (void); - -/* $(CPU)/.../lcd.c */ -unsigned long lcd_setmem (unsigned long); - -/* $(CPU)/.../video.c */ -unsigned long video_setmem (unsigned long); - -/* arch/$(ARCH)/lib/cache.c */ -unsigned long dcache_get_line_size(void); -void enable_caches(void); -void flush_cache (unsigned long, unsigned long); -void flush_dcache_all(void); -void flush_dcache_range(unsigned long start, unsigned long stop); -void invalidate_dcache_range(unsigned long start, unsigned long stop); -void invalidate_dcache_all(void); -void invalidate_icache_all(void); - -/* arch/$(ARCH)/lib/ticks.S */ -unsigned long long get_ticks(void); -void wait_ticks (unsigned long); - -/* arch/$(ARCH)/lib/time.c */ -void __udelay (unsigned long); -unsigned long usec2ticks (unsigned long usec); -unsigned long ticks2usec (unsigned long ticks); -int init_timebase (void); - -/* lib/qsort.c */ -void qsort(void *base, size_t nmemb, size_t size, - int(*compar)(const void *, const void *)); -int strcmp_compar(const void *, const void *); - -/* lib/time.c */ -void udelay (unsigned long); - -/* lib/strmhz.c */ -char * strmhz(char *buf, unsigned long hz); - -/* Multicore arch functions */ -#ifdef CONFIG_MP -int cpu_status(int nr); -int cpu_reset(int nr); -int cpu_disable(int nr); -int cpu_release(int nr, int argc, char * const argv[]); -#endif - -#endif /* __ASSEMBLER__ */ - -/* Put only stuff here that the assembler can digest */ - -#ifdef CONFIG_POST -#define CONFIG_HAS_POST -#ifndef CONFIG_POST_ALT_LIST -#define CONFIG_POST_STD_LIST -#endif -#endif - -#define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1)) -#define DIV_ROUND(n,d) (((n) + ((d)/2)) / (d)) -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) -#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) - -//#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) -#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) - -#endif /* __COMMON_H_ */ diff --git a/src/arch/armv7/include/system.h b/src/arch/armv7/include/system.h deleted file mode 100644 index 0643852f76..0000000000 --- a/src/arch/armv7/include/system.h +++ /dev/null @@ -1,26 +0,0 @@ -/* FIXME(dhendrix): This is split out from asm/system.h. */ -#ifndef SYSTEM_H_ -#define SYSTEM_H_ - -/* - * This is used to ensure the compiler did actually allocate the register we - * asked it for some inline assembly sequences. Apparently we can't trust - * the compiler from one version to another so a bit of paranoia won't hurt. - * This string is meant to be concatenated with the inline asm string and - * will cause compilation to stop on mismatch. - * (for details, see gcc PR 15089) - */ -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" - -#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); - -#define arch_align_stack(x) (x) - -#ifndef __ASSEMBLER__ - /* - * FIXME: sdelay originally came from arch/arm/cpu/armv7/exynos5/setup.h in - * u-boot but does not seem specific to exynos5... - */ -void sdelay(unsigned long loops); -#endif // __ASSEMBLY__ -#endif /* SYSTEM_H_ */ diff --git a/src/arch/armv7/lib/Makefile.inc b/src/arch/armv7/lib/Makefile.inc deleted file mode 100644 index 56a1bb72aa..0000000000 --- a/src/arch/armv7/lib/Makefile.inc +++ /dev/null @@ -1,23 +0,0 @@ -#FIXME: cache_v7 and cache-cp15 will go away eventually - -bootblock-y += syslib.c -bootblock-$(CONFIG_EARLY_CONSOLE) += early_console.c -bootblock-y += cache.c - -romstage-y += cache.c -romstage-y += div0.c -romstage-y += syslib.c -romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c - -ramstage-y += div0.c -#ramstage-y += interrupts.c -#ramstage-y += memcpy.S -#ramstage-y += memset.S -ramstage-y += syslib.c -ramstage-y += cache.c -ramstage-y += mmu.c - -#FIXME(dhendrix): should this be a config option? -romstage-y += eabi_compat.c -ramstage-y += eabi_compat.c -bootblock-y += eabi_compat.c diff --git a/src/arch/armv7/lib/cache.c b/src/arch/armv7/lib/cache.c deleted file mode 100644 index 04eaa88c7c..0000000000 --- a/src/arch/armv7/lib/cache.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * cache.c: Cache maintenance routines for ARMv7-A and ARMv7-R - * - * Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition - */ - -#include - -#include - -#define bitmask(high, low) ((1UL << (high)) + \ - ((1UL << (high)) - 1) - ((1UL << (low)) - 1)) - -/* Basic log2() implementation. Note: log2(0) is 0 for our purposes. */ -/* FIXME: src/include/lib.h is difficult to work with due to romcc */ -static unsigned long log2(unsigned long u) -{ - int i = 0; - - while (u >>= 1) - i++; - - return i; -} - -void tlb_invalidate_all(void) -{ - /* - * FIXME: ARMv7 Architecture Ref. Manual claims that the distinction - * instruction vs. data TLBs is deprecated in ARMv7, however this does - * not seem to be the case as of Cortex-A15. - */ - tlbiall(); - dtlbiall(); - itlbiall(); - isb(); - dsb(); -} - -void icache_invalidate_all(void) -{ - /* - * icache can be entirely invalidated with one operation. - * Note: If branch predictors are architecturally-visible, ICIALLU - * also performs a BPIALL operation (B2-1283 in arch manual) - */ - iciallu(); - isb(); -} - -enum dcache_op { - OP_DCCISW, - OP_DCISW, - OP_DCCIMVAC, - OP_DCCMVAC, -}; - -/* - * Do a dcache operation on entire cache by set/way. This is done for - * portability because mapping of memory address to cache location is - * implementation defined (See note on "Requirements for operations by - * set/way" in arch ref. manual). - */ -static void dcache_op_set_way(enum dcache_op op) -{ - uint32_t ccsidr; - unsigned int associativity, num_sets, linesize_bytes; - unsigned int set, way; - unsigned int level; - - level = (read_csselr() >> 1) & 0x7; - - /* - * dcache must be invalidated by set/way for portability since virtual - * memory mapping is system-defined. The number of sets and - * associativity is given by CCSIDR. We'll use DCISW to invalidate the - * dcache. - */ - ccsidr = read_ccsidr(); - - /* FIXME: rounding up required here? */ - num_sets = ((ccsidr & bitmask(27, 13)) >> 13) + 1; - associativity = ((ccsidr & bitmask(12, 3)) >> 3) + 1; - /* FIXME: do we need to use CTR.DminLine here? */ - linesize_bytes = (1 << ((ccsidr & 0x7) + 2)) * 4; - - dsb(); - - /* - * Set/way operations require an interesting bit packing. See section - * B4-35 in the ARMv7 Architecture Reference Manual: - * - * A: Log2(associativity) - * B: L+S - * L: Log2(linesize) - * S: Log2(num_sets) - * - * The bits are packed as follows: - * 31 31-A B B-1 L L-1 4 3 1 0 - * |---|-------------|--------|-------|-----|-| - * |Way| zeros | Set | zeros |level|0| - * |---|-------------|--------|-------|-----|-| - */ - for (way = 0; way < associativity; way++) { - for (set = 0; set < num_sets; set++) { - uint32_t val = 0; - val |= way << (32 - log2(associativity)); - val |= set << log2(linesize_bytes); - val |= level << 1; - switch(op) { - case OP_DCCISW: - dccisw(val); - break; - case OP_DCISW: - dcisw(val); - break; - default: - break; - } - } - } - isb(); -} - -static void dcache_foreach(enum dcache_op op) -{ - uint32_t clidr; - int level; - - clidr = read_clidr(); - for (level = 0; level < 7; level++) { - unsigned int ctype = (clidr >> (level * 3)) & 0x7; - uint32_t csselr; - - switch(ctype) { - case 0x2: - case 0x3: - case 0x4: - csselr = level << 1; - write_csselr(csselr); - dcache_op_set_way(op); - break; - default: - /* no cache, icache only, or reserved */ - break; - } - } -} - -void dcache_clean_invalidate_all(void) -{ - dcache_foreach(OP_DCCISW); -} - -void dcache_invalidate_all(void) -{ - dcache_foreach(OP_DCISW); -} - -static unsigned int line_bytes(void) -{ - uint32_t ccsidr; - unsigned int size; - - ccsidr = read_ccsidr(); - /* [2:0] - Indicates (Log2(number of words in cache line)) - 2 */ - size = 1 << ((ccsidr & 0x7) + 2); /* words per line */ - size *= sizeof(unsigned int); /* bytes per line */ - - return size; -} - -/* - * Do a dcache operation by modified virtual address. This is useful for - * maintaining coherency in drivers which do DMA transfers and only need to - * perform cache maintenance on a particular memory range rather than the - * entire cache. - */ -static void dcache_op_mva(unsigned long addr, - unsigned long len, enum dcache_op op) -{ - unsigned long line, linesize; - - linesize = line_bytes(); - line = addr & ~(linesize - 1); - - dsb(); - while (line < addr + len) { - switch(op) { - case OP_DCCIMVAC: - dccimvac(line); - break; - default: - break; - } - line += linesize; - } - isb(); -} - -void dcache_clean_by_mva(unsigned long addr, unsigned long len) -{ - dcache_op_mva(addr, len, OP_DCCMVAC); -} - -void dcache_clean_invalidate_by_mva(unsigned long addr, unsigned long len) -{ - dcache_op_mva(addr, len, OP_DCCIMVAC); -} - -void dcache_mmu_disable(void) -{ - uint32_t sctlr; - - dcache_clean_invalidate_all(); - sctlr = read_sctlr(); - sctlr &= ~(SCTLR_C | SCTLR_M); - write_sctlr(sctlr); -} - - -void dcache_mmu_enable(void) -{ - uint32_t sctlr; - - sctlr = read_sctlr(); - dcache_clean_invalidate_all(); - sctlr |= SCTLR_C | SCTLR_M; - write_sctlr(sctlr); -} - -void armv7_invalidate_caches(void) -{ - uint32_t clidr; - int level; - - /* Invalidate branch predictor */ - bpiall(); - - /* Iterate thru each cache identified in CLIDR and invalidate */ - clidr = read_clidr(); - for (level = 0; level < 7; level++) { - unsigned int ctype = (clidr >> (level * 3)) & 0x7; - uint32_t csselr; - - switch(ctype) { - case 0x0: - /* no cache */ - break; - case 0x1: - /* icache only */ - csselr = (level << 1) | 1; - write_csselr(csselr); - icache_invalidate_all(); - break; - case 0x2: - case 0x4: - /* dcache only or unified cache */ - csselr = level << 1; - write_csselr(csselr); - dcache_invalidate_all(); - break; - case 0x3: - /* separate icache and dcache */ - csselr = (level << 1) | 1; - write_csselr(csselr); - icache_invalidate_all(); - - csselr = level << 1; - write_csselr(csselr); - dcache_invalidate_all(); - break; - default: - /* reserved */ - break; - } - } - - /* Invalidate TLB */ - tlb_invalidate_all(); -} diff --git a/src/arch/armv7/lib/interrupts.c b/src/arch/armv7/lib/interrupts.c deleted file mode 100644 index 4ac599d351..0000000000 --- a/src/arch/armv7/lib/interrupts.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * (C) Copyright 2003 - * Texas Instruments - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Marius Groeger - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Alex Zuepke - * - * (C) Copyright 2002-2004 - * Gary Jennejohn, DENX Software Engineering, - * - * (C) Copyright 2004 - * Philippe Robin, ARM Ltd. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#ifdef CONFIG_USE_IRQ -int interrupt_init (void) -{ - /* - * setup up stacks if necessary - */ - IRQ_STACK_START = gd->irq_sp - 4; - IRQ_STACK_START_IN = gd->irq_sp + 8; - FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; - - return arch_interrupt_init(); -} - -/* enable IRQ interrupts */ -void enable_interrupts (void) -{ - unsigned long temp; - __asm__ __volatile__("mrs %0, cpsr\n" - "bic %0, %0, #0x80\n" - "msr cpsr_c, %0" - : "=r" (temp) - : - : "memory"); -} - - -/* - * disable IRQ/FIQ interrupts - * returns true if interrupts had been enabled before we disabled them - */ -int disable_interrupts (void) -{ - unsigned long old,temp; - __asm__ __volatile__("mrs %0, cpsr\n" - "orr %1, %0, #0xc0\n" - "msr cpsr_c, %1" - : "=r" (old), "=r" (temp) - : - : "memory"); - return (old & 0x80) == 0; -} -#else -int interrupt_init (void) -{ - /* - * setup up stacks if necessary - */ - IRQ_STACK_START_IN = gd->irq_sp + 8; - - return 0; -} - -void enable_interrupts (void) -{ - return; -} -int disable_interrupts (void) -{ - return 0; -} -#endif - - -void bad_mode (void) -{ - panic ("Resetting CPU ...\n"); - soft_reset(); -} - -void show_regs (struct pt_regs *regs) -{ - unsigned long flags; - const char *processor_modes[] = { - "USER_26", "FIQ_26", "IRQ_26", "SVC_26", - "UK4_26", "UK5_26", "UK6_26", "UK7_26", - "UK8_26", "UK9_26", "UK10_26", "UK11_26", - "UK12_26", "UK13_26", "UK14_26", "UK15_26", - "USER_32", "FIQ_32", "IRQ_32", "SVC_32", - "UK4_32", "UK5_32", "UK6_32", "ABT_32", - "UK8_32", "UK9_32", "UK10_32", "UND_32", - "UK12_32", "UK13_32", "UK14_32", "SYS_32", - }; - - flags = condition_codes (regs); - - printf ("pc : [<%08lx>] lr : [<%08lx>]\n" - "sp : %08lx ip : %08lx fp : %08lx\n", - instruction_pointer (regs), - regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); - printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", - regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); - printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", - regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); - printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", - regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); - printf ("Flags: %c%c%c%c", - flags & CC_N_BIT ? 'N' : 'n', - flags & CC_Z_BIT ? 'Z' : 'z', - flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); - printf (" IRQs %s FIQs %s Mode %s%s\n", - interrupts_enabled (regs) ? "on" : "off", - fast_interrupts_enabled (regs) ? "on" : "off", - processor_modes[processor_mode (regs)], - thumb_mode (regs) ? " (T)" : ""); -} - -void do_undefined_instruction (struct pt_regs *pt_regs) -{ - printf ("undefined instruction\n"); - show_regs (pt_regs); - bad_mode (); -} - -void do_software_interrupt (struct pt_regs *pt_regs) -{ - printf ("software interrupt\n"); - show_regs (pt_regs); - bad_mode (); -} - -void do_prefetch_abort (struct pt_regs *pt_regs) -{ - printf ("prefetch abort\n"); - show_regs (pt_regs); - bad_mode (); -} - -void do_data_abort (struct pt_regs *pt_regs) -{ - printf ("data abort\n"); - show_regs (pt_regs); - bad_mode (); -} - -void do_not_used (struct pt_regs *pt_regs) -{ - printf ("not used\n"); - show_regs (pt_regs); - bad_mode (); -} - -void do_fiq (struct pt_regs *pt_regs) -{ - printf ("fast interrupt request\n"); - show_regs (pt_regs); - bad_mode (); -} - -#ifndef CONFIG_USE_IRQ -void do_irq (struct pt_regs *pt_regs) -{ - printf ("interrupt request\n"); - show_regs (pt_regs); - bad_mode (); -} -#endif diff --git a/src/arch/armv7/lib/memset.S b/src/arch/armv7/lib/memset.S deleted file mode 100644 index 3ea2721227..0000000000 --- a/src/arch/armv7/lib/memset.S +++ /dev/null @@ -1,126 +0,0 @@ -/* - * linux/arch/arm/lib/memset.S - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include - - .text - .align 5 - .word 0 - -1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 - strltb r1, [r0], #1 @ 1 - strleb r1, [r0], #1 @ 1 - strb r1, [r0], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -/* - * The pointer is now aligned and the length is adjusted. Try doing the - * memset again. - */ - -.globl memset -memset: - ands r3, r0, #3 @ 1 unaligned? - bne 1b @ 1 -/* - * we know that the pointer in r0 is aligned to a word boundary. - */ - orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - mov r3, r1 - cmp r2, #16 - blt 4f - -#if ! CALGN(1)+0 - -/* - * We need an extra register for this loop - save the return address and - * use the LR - */ - str lr, [sp, #-4]! - mov ip, r1 - mov lr, r1 - -2: subs r2, r2, #64 - stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - bgt 2b - ldmeqfd sp!, {pc} @ Now <64 bytes to go. -/* - * No need to correct the count; we're only testing bits from now on - */ - tst r2, #32 - stmneia r0!, {r1, r3, ip, lr} - stmneia r0!, {r1, r3, ip, lr} - tst r2, #16 - stmneia r0!, {r1, r3, ip, lr} - ldr lr, [sp], #4 - -#else - -/* - * This version aligns the destination pointer in order to write - * whole cache lines at once. - */ - - stmfd sp!, {r4-r7, lr} - mov r4, r1 - mov r5, r1 - mov r6, r1 - mov r7, r1 - mov ip, r1 - mov lr, r1 - - cmp r2, #96 - tstgt r0, #31 - ble 3f - - and ip, r0, #31 - rsb ip, ip, #32 - sub r2, r2, ip - movs ip, ip, lsl #(32 - 4) - stmcsia r0!, {r4, r5, r6, r7} - stmmiia r0!, {r4, r5} - tst ip, #(1 << 30) - mov ip, r1 - strne r1, [r0], #4 - -3: subs r2, r2, #64 - stmgeia r0!, {r1, r3-r7, ip, lr} - stmgeia r0!, {r1, r3-r7, ip, lr} - bgt 3b - ldmeqfd sp!, {r4-r7, pc} - - tst r2, #32 - stmneia r0!, {r1, r3-r7, ip, lr} - tst r2, #16 - stmneia r0!, {r4-r7} - ldmfd sp!, {r4-r7, lr} - -#endif - -4: tst r2, #8 - stmneia r0!, {r1, r3} - tst r2, #4 - strne r1, [r0], #4 -/* - * When we get here, we've got less than 4 bytes to zero. We - * may have an unaligned pointer as well. - */ -5: tst r2, #2 - strneb r1, [r0], #1 - strneb r1, [r0], #1 - tst r2, #1 - strneb r1, [r0], #1 - mov pc, lr diff --git a/src/arch/armv7/lib/mmu.c b/src/arch/armv7/lib/mmu.c deleted file mode 100644 index 224b566a50..0000000000 --- a/src/arch/armv7/lib/mmu.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include - -#include - -#define L1_TLB_ENTRIES 4096 /* 1 entry for each 1MB address space */ - -static uintptr_t ttb_addr; - -void mmu_config_range(unsigned long start_mb, unsigned long size_mb, - enum dcache_policy policy) -{ - unsigned int i; - uint32_t attr; - uint32_t *ttb_entry = (uint32_t *)ttb_addr; - const char *str = NULL; - - /* - * Section entry bits: - * 31:20 - section base address - * 18 - 0 to indicate normal section (versus supersection) - * 17 - nG, 0 to indicate page is global - * 16 - S, 0 for non-shareable (?) - * 15 - APX, 0 for full access - * 14:12 - TEX, 0b000 for outer and inner write-back - * 11:10 - AP, 0b11 for full access - * 9 - P, ? (FIXME: not described or possibly obsolete?) - * 8: 5 - Domain - * 4 - XN, 1 to set execute-never (and also avoid prefetches) - * 3 - C, 1 for cacheable - * 2 - B, 1 for bufferable - * 1: 0 - 0b10 to indicate section entry - */ - - switch(policy) { - case DCACHE_OFF: - /* XN set to avoid prefetches to uncached/unbuffered regions */ - attr = (0x3 << 10) | (1 << 4) | 0x2; - str = "off"; - break; - case DCACHE_WRITEBACK: - attr = (0x3 << 10) | (1 << 3) | (1 << 2) | 0x2; - str = "writeback"; - break; - case DCACHE_WRITETHROUGH: - attr = (0x3 << 10) | (1 << 3) | (1 << 2) | 0x2; - str = "writethrough"; - break; - default: - printk(BIOS_ERR, "unknown dcache policy: %02x\n", policy); - return; - } - - printk(BIOS_DEBUG, "Setting dcache policy: 0x%08lx:0x%08lx [%s]\n", - start_mb << 20, ((start_mb + size_mb) << 20) - 1, str); - - for (i = start_mb; i < start_mb + size_mb; i++) - ttb_entry[i] = (i << 20) | attr; - - /* TODO: add helper to invalidate TLB by MVA */ - tlb_invalidate_all(); -} - -void mmu_init(void) -{ - unsigned int ttb_size; - uint32_t ttbcr; - - /* - * For coreboot's purposes, we will create a simple L1 page table - * in RAM with 1MB section translation entries over the 4GB address - * space. - * (ref: section 10.2 and example 15-4 in Cortex-A series - * programmer's guide) - * - * FIXME: TLB needs to be aligned to 16KB, but cbmem_add() aligns to - * 512 bytes. So add double the space in cbmem and fix-up the pointer. - */ - ttb_size = L1_TLB_ENTRIES * sizeof(unsigned long); - ttb_addr = (uintptr_t)cbmem_add(CBMEM_ID_GDT, ttb_size * 2); - ttb_addr = ALIGN(ttb_addr + ttb_size, ttb_size); - printk(BIOS_DEBUG, "Translation table is @ 0x%08x\n", ttb_addr); - - /* - * Disable TTBR1 by setting TTBCR.N to 0b000, which means the TTBR0 - * table size is 16KB and has indices VA[31:20]. - * - * ref: Arch Ref. Manual for ARMv7-A, B3.5.4, - */ - ttbcr = read_ttbcr(); - ttbcr &= ~(0x3); - write_ttbcr(ttbcr); - - /* - * Translation table base 0 address is in bits 31:14-N, where N is given - * by bits 2:0 in TTBCR (which we set to 0). All lower bits in this - * register should be zero for coreboot. - */ - write_ttbr0(ttb_addr); - - /* disable domain-level checking of permissions */ - write_dacr(~0); -} diff --git a/src/arch/armv7/lib/syslib.c b/src/arch/armv7/lib/syslib.c deleted file mode 100644 index a6ed080157..0000000000 --- a/src/arch/armv7/lib/syslib.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * (C) Copyright 2008 - * Texas Instruments, - * - * Richard Woodruff - * Syed Mohammed Khasim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include /* FIXME: dumping ground for prototypes */ - -/************************************************************ - * sdelay() - simple spin loop. Will be constant time as - * its generally used in bypass conditions only. This - * is necessary until timers are accessible. - * - * not inline to increase chances its in cache when called - *************************************************************/ -void sdelay(unsigned long loops) -{ - __asm__ volatile ("1:\n" "subs %0, %1, #1\n" - "bne 1b":"=r" (loops):"0"(loops)); -} - diff --git a/src/arch/armv7/romstage.ld b/src/arch/armv7/romstage.ld deleted file mode 100644 index 568ac1aa94..0000000000 --- a/src/arch/armv7/romstage.ld +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Memory map: - * - * CONFIG_RAMBASE : text segment - * : rodata segment - * : data segment - * : bss segment - * : stack - * : heap - */ -/* - * Bootstrap code for the STPC Consumer - * Copyright (c) 1999 by Net Insight AB. All Rights Reserved. - */ - -/* - * Written by Johan Rydberg, based on work by Daniel Kahlin. - * Rewritten by Eric Biederman - * 2005.12 yhlu add coreboot_ram cross the vga font buffer handling - */ - -/* We use ELF as output format. So that we can debug the code in some form. */ -/* - INCLUDE ldoptions - */ - -/* We use ELF as output format. So that we can debug the code in some form. */ -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) - -ENTRY(stage_entry) - -SECTIONS -{ - /* TODO make this a configurable option (per chipset). */ - . = CONFIG_ROMSTAGE_BASE; - - .romtext . : { - _rom = .; - _start = .; - *(.text.stage_entry.armv7); - *(.text.startup); - *(.text); - } - - .romdata . : { - *(.rodata); - *(.machine_param); - *(.data); - . = ALIGN(8); - _erom = .; - } - - __image_copy_end = .; - - /* bss does not contain data, it is just a space that should be zero - * initialized on startup. (typically uninitialized global variables) - * crt0.S fills between _bss and _ebss with zeroes. - */ - .bss . : { - . = ALIGN(8); - _bss = .; - *(.bss) - *(.sbss) - *(COMMON) - } - _ebss = .; - _end = .; - - /* Discard the sections we don't need/want */ - /DISCARD/ : { - *(.comment) - *(.note) - *(.comment.*) - *(.note.*) - *(.eh_frame); - } -} diff --git a/src/arch/mips/Kconfig b/src/arch/mips/Kconfig new file mode 100644 index 0000000000..3d8e2c6bac --- /dev/null +++ b/src/arch/mips/Kconfig @@ -0,0 +1,37 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +menu "Architecture (mips)" + +config ARCH_BOOTBLOCK_MIPS + bool + default n + select ARCH_MIPS + +config ARCH_ROMSTAGE_MIPS + bool + default n + +config ARCH_RAMSTAGE_MIPS + bool + default n + +endmenu diff --git a/src/arch/mips/Makefile.inc b/src/arch/mips/Makefile.inc new file mode 100644 index 0000000000..d0014a2620 --- /dev/null +++ b/src/arch/mips/Makefile.inc @@ -0,0 +1,96 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +############################################################################### +# MIPS specific options +############################################################################### + +ifeq ($(CONFIG_ARCH_ROMSTAGE_MIPS),y) +CBFSTOOL_PRE1_OPTS = -m mips -s $(CONFIG_CBFS_SIZE) +endif + +############################################################################### +# bootblock +############################################################################### + +ifeq ($(CONFIG_ARCH_BOOTBLOCK_MIPS),y) + +bootblock-y += boot.c +bootblock-y += bootblock.S +bootblock-y += bootblock_simple.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += early_console.c +bootblock-y += stages.c +bootblock-y += ../../lib/memcpy.c +bootblock-y += ../../lib/memmove.c +bootblock-y += ../../lib/memset.c + +# Much of the assembly code is generated by the compiler, and may contain +# terms which the preprocessor will happily go on to replace. For example +# "mips" would be replaced with "1". Clear all the built in definitions to +# prevent that. +bootblock-S-ccopts += -undef + +$(objcbfs)/bootblock.debug: $$(bootblock-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,bootblock,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld,--gc-sections) + +endif # CONFIG_ARCH_BOOTBLOCK_MIPS + +############################################################################### +# romstage +############################################################################### + +ifeq ($(CONFIG_ARCH_ROMSTAGE_MIPS),y) + +romstage-y += boot.c +romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c +romstage-y += stages.c +romstage-y += ../../lib/memcpy.c +romstage-y += ../../lib/memmove.c +romstage-y += ../../lib/memset.c + +$(objcbfs)/romstage.debug: $$(romstage-objs) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,romstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld,--gc-sections) + +endif # CONFIG_ARCH_ROMSTAGE_MIPS + +############################################################################### +# ramstage +############################################################################### + +ifeq ($(CONFIG_ARCH_RAMSTAGE_MIPS),y) + +ramstage-y += ashldi3.c +ramstage-y += boot.c +ramstage-y += stages.c +ramstage-y += tables.c +ramstage-y += ../../lib/memcpy.c +ramstage-y += ../../lib/memmove.c +ramstage-y += ../../lib/memset.c + +ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c) + +$(objcbfs)/ramstage.debug: $$(ramstage-objs) + @printf " CC $(subst $(obj)/,,$(@))\n" + $(call link,ramstage,$(filter %.a %.o,$(^)),-o $(@) -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld,--gc-sections) + +endif # CONFIG_ARCH_RAMSTAGE_MIPS diff --git a/src/arch/mips/ashldi3.c b/src/arch/mips/ashldi3.c new file mode 100644 index 0000000000..caa69fa3e1 --- /dev/null +++ b/src/arch/mips/ashldi3.c @@ -0,0 +1,60 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * Based on linux arch/mips/lib/ashldi3.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ORDER_LITTLE_ENDIAN__ +#errror "What endian are you!?" +#endif + +typedef unsigned word_type; +long long __ashldi3(long long u, word_type b); + +struct DWstruct { + int low, high; +}; +typedef union { + struct DWstruct s; + long long ll; +} DWunion; + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} + diff --git a/src/arch/mips/boot.c b/src/arch/mips/boot.c new file mode 100644 index 0000000000..d322e99079 --- /dev/null +++ b/src/arch/mips/boot.c @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) +{ + printk(BIOS_SPEW, "entry = %p\n", entry); + stage_exit(entry); +} diff --git a/src/arch/mips/bootblock.S b/src/arch/mips/bootblock.S new file mode 100644 index 0000000000..ed31b24cfa --- /dev/null +++ b/src/arch/mips/bootblock.S @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.set noreorder /* Prevent assembler from "optimizing" this code. */ + +.section ".text._start", "ax", %progbits +.globl _start +_start: + /* Set the stack pointer */ + la $sp, _estack + + /* + * Initialise the stack to a known value, used later to check for + * overflow. + */ + la $t0, _stack + addi $t1, $sp, -4 + li $t2, 0xdeadbeef +1: sw $t2, 0($t0) + bne $t0, $t1, 1b + addi $t0, $t0, 4 + + /* + * Disable caches for now, proper cache management is coming soon. + * http://crosbug.com/p/34127 + */ + mfc0 $t0, $16 + li $t1, -8 + and $t0, $t0, $t1 + ori $t0, $t0, 2 + mtc0 $t0, $16 + + /* Run main */ + b main + + /* + * Should never return from main. Make sure there is no branch in the + * branch delay slot. + */ +2: nop + b 2b + nop /* Make sure there is no branch after this either. */ diff --git a/src/arch/mips/bootblock_simple.c b/src/arch/mips/bootblock_simple.c new file mode 100644 index 0000000000..49ea24d9d4 --- /dev/null +++ b/src/arch/mips/bootblock_simple.c @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void main(void) +{ + const char *stage_name = "fallback/romstage"; + void *entry; + + bootblock_cpu_init(); + bootblock_mainboard_init(); + +#if CONFIG_BOOTBLOCK_CONSOLE + console_init(); +#endif + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, stage_name); + if (entry != (void *)-1) + stage_exit(entry); + + hlt(); +} diff --git a/src/arch/mips/early_console.c b/src/arch/mips/early_console.c new file mode 100644 index 0000000000..c699abcf6a --- /dev/null +++ b/src/arch/mips/early_console.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +void console_tx_byte(unsigned char byte) +{ + if (byte == '\n') + console_tx_byte('\r'); + +#if CONFIG_CONSOLE_SERIAL_UART + uart_tx_byte(byte); +#endif +} + +void console_tx_flush(void) +{ +#if CONFIG_CONSOLE_SERIAL_UART + uart_tx_flush(); +#endif +} diff --git a/src/arch/mips/include/arch/byteorder.h b/src/arch/mips/include/arch/byteorder.h new file mode 100644 index 0000000000..90c375e691 --- /dev/null +++ b/src/arch/mips/include/arch/byteorder.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_BYTEORDER_H +#define __MIPS_ARCH_BYTEORDER_H + +#include +#include + +#ifndef __ORDER_LITTLE_ENDIAN__ +#errror "What endian are you!?" +#endif + +#define cpu_to_le64(x) ((uint64_t)(x)) +#define le64_to_cpu(x) ((uint64_t)(x)) +#define cpu_to_le32(x) ((uint32_t)(x)) +#define le32_to_cpu(x) ((uint32_t)(x)) +#define cpu_to_le16(x) ((uint16_t)(x)) +#define le16_to_cpu(x) ((uint16_t)(x)) +#define cpu_to_be64(x) swab64(x) +#define be64_to_cpu(x) swab64(x) +#define cpu_to_be32(x) swab32((x)) +#define be32_to_cpu(x) swab32((x)) +#define cpu_to_be16(x) swab16((x)) +#define be16_to_cpu(x) swab16((x)) + +#define ntohll(x) be64_to_cpu(x) +#define htonll(x) cpu_to_be64(x) +#define ntohl(x) be32_to_cpu(x) +#define htonl(x) cpu_to_be32(x) + +#endif /* __MIPS_ARCH_BYTEORDER_H */ diff --git a/src/arch/mips/include/arch/cache.h b/src/arch/mips/include/arch/cache.h new file mode 100644 index 0000000000..a9857414ce --- /dev/null +++ b/src/arch/mips/include/arch/cache.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_CACHE_H +#define __MIPS_ARCH_CACHE_H + +#endif /* __MIPS_ARCH_CACHE_H */ diff --git a/src/arch/mips/include/arch/cpu.h b/src/arch/mips/include/arch/cpu.h new file mode 100644 index 0000000000..4f4c376eee --- /dev/null +++ b/src/arch/mips/include/arch/cpu.h @@ -0,0 +1,91 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_CPU_H +#define __MIPS_ARCH_CPU_H + +#define asmlinkage + +#ifndef __PRE_RAM__ + +#include + +struct cpu_driver { + struct device_operations *ops; + struct cpu_device_id *id_table; +}; + +struct thread; + +struct cpu_info { + device_t cpu; + unsigned long index; +}; + +#endif /* !__PRE_RAM__ */ + +/*************************************************************************** + * The following section was copied from arch/mips/include/asm/mipsregs.h in + * the 3.14 kernel tree. + */ + +/* + * Macros to access the system control coprocessor + */ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define __write_32bit_c0_register(register, sel, value) \ +do { \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mtc0\t%z0, " #register "\n\t" \ + : : "Jr" ((unsigned int)(value))); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mtc0\t%z0, " #register ", " #sel "\n\t" \ + ".set\tmips0" \ + : : "Jr" ((unsigned int)(value))); \ +} while (0) + +/* Shortcuts to access various internal registers, keep adding as needed. */ +#define read_c0_count() __read_32bit_c0_register($9, 0) +#define write_c0_count(val) __write_32bit_c0_register($9, 0, (val)) + +#define read_c0_cause() __read_32bit_c0_register($13, 0) +#define write_c0_cause(val) __write_32bit_c0_register($13, 0, (val)) + +#define C0_CAUSE_DC (1 << 27) +/**************************************************************************/ + +#endif /* __MIPS_ARCH_CPU_H */ diff --git a/src/arch/mips/include/arch/early_variables.h b/src/arch/mips/include/arch/early_variables.h new file mode 100644 index 0000000000..4365cedd92 --- /dev/null +++ b/src/arch/mips/include/arch/early_variables.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_EARLY_VARIABLES_H +#define __MIPS_ARCH_EARLY_VARIABLES_H + +#define CAR_GLOBAL + +static inline void car_migrate_variables(void) {} +#define car_get_var(var) (var) +#define car_set_var(var, val) { (var) = (val); } + +#endif /* __MIPS_ARCH_EARLY_VARIABLES_H */ diff --git a/src/arch/mips/include/arch/exception.h b/src/arch/mips/include/arch/exception.h new file mode 100644 index 0000000000..ff92728005 --- /dev/null +++ b/src/arch/mips/include/arch/exception.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_EXCEPTION_H +#define __MIPS_ARCH_EXCEPTION_H + +static inline void exception_init(void) {} + +#endif /* __MIPS_ARCH_EXCEPTION_H */ diff --git a/src/arch/mips/include/arch/header.ld b/src/arch/mips/include/arch/header.ld new file mode 100644 index 0000000000..0c7d7a1582 --- /dev/null +++ b/src/arch/mips/include/arch/header.ld @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_ARCH(mips) + +PHDRS +{ + to_load PT_LOAD; +} + +#ifdef __BOOTBLOCK__ +ENTRY(_start) +#else +ENTRY(stage_entry) +#endif diff --git a/src/arch/mips/include/arch/hlt.h b/src/arch/mips/include/arch/hlt.h new file mode 100644 index 0000000000..851de56556 --- /dev/null +++ b/src/arch/mips/include/arch/hlt.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_HLT_H +#define __MIPS_ARCH_HLT_H + +static inline __attribute__((always_inline)) void hlt(void) +{ + for (;;) + ; +} + +#endif /* __MIPS_ARCH_HLT_H */ diff --git a/src/arch/mips/include/arch/io.h b/src/arch/mips/include/arch/io.h new file mode 100644 index 0000000000..d034b09dc5 --- /dev/null +++ b/src/arch/mips/include/arch/io.h @@ -0,0 +1,125 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * Based on arch/armv7/include/arch/io.h: + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_IO_H +#define __MIPS_ARCH_IO_H + +#include +#include +#include + +static inline uint8_t read8(unsigned long addr) +{ + asm("sync"); + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(unsigned long addr) +{ + asm("sync"); + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(unsigned long addr) +{ + asm("sync"); + return *(volatile uint32_t *)addr; +} + +static inline void write8(unsigned long addr, uint8_t val) +{ + asm("sync"); + *(volatile uint8_t *)addr = val; + asm("sync"); +} + +static inline void write16(unsigned long addr, uint16_t val) +{ + asm("sync"); + *(volatile uint16_t *)addr = val; + asm("sync"); +} + +static inline void write32(unsigned long addr, uint32_t val) +{ + asm("sync"); + *(volatile uint32_t *)addr = val; + asm("sync"); +} + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define out_arch(type, endian, a, v) write##type(cpu_to_##endian(v), a) +#define in_arch(type, endian, a) endian##_to_cpu(read##type(a)) + +#define out_le32(a, v) out_arch(l, le32, a, v) +#define out_le16(a, v) out_arch(w, le16, a, v) + +#define in_le32(a) in_arch(l, le32, a) +#define in_le16(a) in_arch(w, le16, a) + +#define out_be32(a, v) out_arch(l, be32, a, v) +#define out_be16(a, v) out_arch(w, be16, a, v) + +#define in_be32(a) in_arch(l, be32, a) +#define in_be16(a) in_arch(w, be16, a) + +#define out_8(a, v) writeb(v, a) +#define in_8(a) readb(a) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#endif /* __MIPS_ARCH_IO_H */ diff --git a/src/arch/mips/include/arch/memlayout.h b/src/arch/mips/include/arch/memlayout.h new file mode 100644 index 0000000000..36ac6de8f7 --- /dev/null +++ b/src/arch/mips/include/arch/memlayout.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file contains macro definitions for memlayout.ld linker scripts. */ + +#ifndef __ARCH_MEMLAYOUT_H +#define __ARCH_MEMLAYOUT_H + +/* MIPS stacks need 8-byte alignment and stay in one place through ramstage. */ +/* TODO: Double-check that that's the correct alignment for our ABI. */ +#define STACK(addr, size) \ + REGION(stack, addr, size, 8) \ + _ = ASSERT(size >= 2K, "stack should be >= 2K, see toolchain.inc"); + +/* TODO: Need to add DMA_COHERENT region like on ARM? */ + +#endif /* __ARCH_MEMLAYOUT_H */ diff --git a/src/arch/mips/include/arch/pci_ops.h b/src/arch/mips/include/arch/pci_ops.h new file mode 100644 index 0000000000..1b3f07417b --- /dev/null +++ b/src/arch/mips/include/arch/pci_ops.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ARCH_MIPS_PCI_OPS_H +#define ARCH_MIPS_PCI_OPS_H + +#include + +static inline const struct pci_bus_operations *pci_config_default(void) +{ + return NULL; +} + +#endif diff --git a/src/arch/mips/include/arch/stages.h b/src/arch/mips/include/arch/stages.h new file mode 100644 index 0000000000..b95ad1db4f --- /dev/null +++ b/src/arch/mips/include/arch/stages.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_STAGES_H +#define __MIPS_ARCH_STAGES_H + +extern void main(void); + +void stage_entry(void); +void stage_exit(void *); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size); + +#endif /* __MIPS_ARCH_STAGES_H */ diff --git a/src/arch/mips/include/arch/types.h b/src/arch/mips/include/arch/types.h new file mode 100644 index 0000000000..c3eae24e09 --- /dev/null +++ b/src/arch/mips/include/arch/types.h @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * Based on src/arch/armv7/include/arch/types.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_TYPES_H +#define __MIPS_ARCH_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#endif + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +typedef unsigned long phys_addr_t; +typedef unsigned long phys_size_t; + +#endif /* __MIPS_ARCH_TYPES_H */ diff --git a/src/arch/mips/include/bootblock_common.h b/src/arch/mips/include/bootblock_common.h new file mode 100644 index 0000000000..e1960ba6a4 --- /dev/null +++ b/src/arch/mips/include/bootblock_common.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef CONFIG_BOOTBLOCK_CPU_INIT +#include CONFIG_BOOTBLOCK_CPU_INIT +#endif + +#ifdef CONFIG_BOOTBLOCK_MAINBOARD_INIT +#include CONFIG_BOOTBLOCK_MAINBOARD_INIT +#else +static void bootblock_mainboard_init(void) +{ +} +#endif diff --git a/src/arch/mips/include/stdint.h b/src/arch/mips/include/stdint.h new file mode 100644 index 0000000000..5c21fe6742 --- /dev/null +++ b/src/arch/mips/include/stdint.h @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Based on src/arch/armv7/include/stdint.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_STDINT_H +#define __MIPS_STDINT_H + +#if defined(__GNUC__) +#define __HAVE_LONG_LONG__ 1 +#else +#define __HAVE_LONG_LONG__ 0 +#endif + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +#endif + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; +#endif + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; +#endif + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +#if __HAVE_LONG_LONG__ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; +#else +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +#endif + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#if __HAVE_LONG_LONG__ +typedef uint64_t u64; +#endif +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; + +#undef __HAVE_LONG_LONG__ + +#endif /* __MIPS_STDINT_H */ diff --git a/src/arch/mips/stages.c b/src/arch/mips/stages.c new file mode 100644 index 0000000000..79b2ea4cd8 --- /dev/null +++ b/src/arch/mips/stages.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void stage_entry(void) +{ + main(); +} + +void stage_exit(void *addr) +{ + void (*doit)(void) = addr; + + /* TODO: synci */ + + doit(); +} diff --git a/src/arch/mips/tables.c b/src/arch/mips/tables.c new file mode 100644 index 0000000000..0c17ff2a85 --- /dev/null +++ b/src/arch/mips/tables.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Based on src/arch/armv7/tables.c: + * Copyright (C) 2003 Eric Biederman + * Copyright (C) 2005 Steve Magnani + * Copyright (C) 2008-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_COREBOOT_TABLE_SIZE (8 * 1024) + +struct lb_memory *write_tables(void) +{ + unsigned long table_pointer, new_table_pointer; + + post_code(0x9d); + + table_pointer = (unsigned long)cbmem_add(CBMEM_ID_CBTABLE, + MAX_COREBOOT_TABLE_SIZE); + if (!table_pointer) { + printk(BIOS_ERR, "Could not add CBMEM for coreboot table.\n"); + return NULL; + } + + new_table_pointer = write_coreboot_table(0UL, 0UL, table_pointer, + table_pointer); + + if (new_table_pointer > (table_pointer + MAX_COREBOOT_TABLE_SIZE)) + printk(BIOS_ERR, "coreboot table didn't fit (%lx/%x bytes)\n", + new_table_pointer - table_pointer, + MAX_COREBOOT_TABLE_SIZE); + + printk(BIOS_DEBUG, "coreboot table: %ld bytes.\n", + new_table_pointer - table_pointer); + + post_code(0x9e); + + /* Print CBMEM sections */ + cbmem_list(); + + return get_lb_mem(); +} diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index 5f46145f8e..879fc57adc 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -1,5 +1,26 @@ menu "Architecture (x86)" +config ARCH_BOOTBLOCK_X86_32 + bool + default n + select ARCH_X86 + +config ARCH_ROMSTAGE_X86_32 + bool + default n + +config ARCH_RAMSTAGE_X86_32 + bool + default n + +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. + # This is an SMP option. It relates to starting up APs. # It is usually set in mainboard/*/Kconfig. # TODO: Improve description. @@ -23,16 +44,6 @@ config RAMTOP hex default 0x200000 -config STACK_SIZE - hex - default 0x1000 - -# Maximum reboot count -# TODO: Improve description. -config MAX_REBOOT_CNT - int - default 3 - # We had to rename the choice options under arch/ because otherwise # the options would conflict between different architectures despite # the if ARCH_xxx guarding the arch/xxx/Kconfig sourcing. @@ -53,22 +64,13 @@ config BOOTBLOCK_SOURCE default "bootblock_simple.c" if X86_BOOTBLOCK_SIMPLE default "bootblock_normal.c" if X86_BOOTBLOCK_NORMAL -config UPDATE_IMAGE - bool "Update existing coreboot.rom image" - default n - help - If this option is enabled, no new coreboot.rom file - is created. Instead it is expected that there already - is a suitable file for further processing. - The bootblock will not be modified. - config ROMCC bool default n config PC80_SYSTEM bool - default y + default y if ARCH_X86 config BOOTBLOCK_MAINBOARD_INIT string @@ -86,22 +88,6 @@ config CMOS_DEFAULT_FILE config BOOTBLOCK_SOUTHBRIDGE_INIT string -config HAVE_ARCH_MEMSET - bool - default y - -config HAVE_ARCH_MEMCPY - bool - default y - -config BIG_ENDIAN - bool - default n - -config LITTLE_ENDIAN - bool - default !BIG_ENDIAN - config IOAPIC_INTERRUPTS_ON_FSB bool default y if !IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS @@ -110,10 +96,6 @@ config IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS bool default n -config PCI_CONF2 - bool - default n - config HPET_ADDRESS hex default 0xfed00000 if !HPET_ADDRESS_OVERRIDE diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index ee2bc4713d..0c7d71d38b 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -19,106 +19,52 @@ ## along with this program; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -################################################################################ - +############################################################################### # Take care of subdirectories +############################################################################### subdirs-y += boot # subdirs-y += init subdirs-y += lib subdirs-y += smp +################################################################################ +# i386 specific tools +################################################################################ + +NVRAMTOOL:=$(objutil)/nvramtool/nvramtool + OPTION_TABLE_H:= ifeq ($(CONFIG_HAVE_OPTION_TABLE),y) + cbfs-files-y += cmos_layout.bin cmos_layout.bin-file = $(obj)/cmos_layout.bin cmos_layout.bin-type = 0x01aa +$(obj)/cmos_layout.bin: $(NVRAMTOOL) $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout + @printf " OPTION $(subst $(obj)/,,$(@))\n" + $(NVRAMTOOL) -y $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout -L $@ + OPTION_TABLE_H:=$(obj)/option_table.h -endif +generic-deps += $(OPTION_TABLE_H) + +$(OPTION_TABLE_H): $(NVRAMTOOL) $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout + @printf " OPTION $(subst $(obj)/,,$(@))\n" + $(NVRAMTOOL) -y $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout -H $@ + +endif # CONFIG_HAVE_OPTION_TABLE ################################################################################ -# Build the final rom image -COREBOOT_ROM_DEPENDENCIES:= -ifeq ($(CONFIG_PAYLOAD_ELF),y) -COREBOOT_ROM_DEPENDENCIES+=$(CONFIG_PAYLOAD_FILE) -endif -ifeq ($(CONFIG_PAYLOAD_SEABIOS),y) -COREBOOT_ROM_DEPENDENCIES+=seabios -endif -ifeq ($(CONFIG_PAYLOAD_FILO),y) -COREBOOT_ROM_DEPENDENCIES+=filo -endif -ifeq ($(CONFIG_AP_CODE_IN_CAR),y) -COREBOOT_ROM_DEPENDENCIES+=$(objcbfs)/coreboot_ap.elf +# X86 specific options +################################################################################ + +ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y) +CBFSTOOL_PRE1_OPTS = -m x86 -s $(CONFIG_ROM_SIZE) \ + -o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) )) +# Make sure that segment for .car.data is ignored while adding romstage. +CBFSTOOL_PRE_OPTS = -b $(shell cat $(objcbfs)/base_xip.txt) -S ".car.data" endif -extract_nth=$(word $(1), $(subst |, ,$(2))) - -ifneq ($(CONFIG_UPDATE_IMAGE),y) -prebuild-files = \ - $(foreach file,$(cbfs-files), \ - $(CBFSTOOL) $@.tmp \ - add$(if $(filter stage,$(call extract_nth,3,$(file))),-stage)$(if $(filter payload,$(call extract_nth,3,$(file))),-payload) \ - -f $(call extract_nth,1,$(file)) \ - -n $(call extract_nth,2,$(file)) $(if $(filter-out stage,$(call extract_nth,3,$(file))),-t $(call extract_nth,3,$(file))) \ - $(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&) -prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file))) - -$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) - $(CBFSTOOL) $@.tmp create -m x86 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \ - -B $(objcbfs)/bootblock.bin -a 64 \ - -o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) )) - $(prebuild-files) true - mv $@.tmp $@ -else -.PHONY: $(obj)/coreboot.pre1 -$(obj)/coreboot.pre1: $(CBFSTOOL) - mv $(obj)/coreboot.rom $@ -endif - -$(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/coreboot_ram.elf $(CBFSTOOL) $(call strip_quotes,$(COREBOOT_ROM_DEPENDENCIES)) $$(INTERMEDIATE) $$(VBOOT_STUB_ELF) - @printf " CBFS $(subst $(obj)/,,$(@))\n" - cp $(obj)/coreboot.pre $@.tmp - if [ -f $(objcbfs)/coreboot_ap.elf ]; \ - then \ - $(CBFSTOOL) $@.tmp add-stage -f $(objcbfs)/coreboot_ap.elf -n $(CONFIG_CBFS_PREFIX)/coreboot_ap -c $(CBFS_COMPRESS_FLAG); \ - fi - $(CBFSTOOL) $@.tmp add-stage -f $(objcbfs)/coreboot_ram.elf -n $(CONFIG_CBFS_PREFIX)/coreboot_ram -c $(CBFS_COMPRESS_FLAG) -ifeq ($(CONFIG_PAYLOAD_NONE),y) - @printf " PAYLOAD none (as specified by user)\n" -endif -ifeq ($(CONFIG_PAYLOAD_ELF),y) - @printf " PAYLOAD $(CONFIG_PAYLOAD_FILE) (compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" - $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_PAYLOAD_SEABIOS),y) - @printf " PAYLOAD SeaBIOS (internal, compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" - $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_PAYLOAD_FILO),y) - @printf " PAYLOAD FILO (internal, compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" - $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_PAYLOAD_TIANOCORE),y) - @printf " PAYLOAD Tiano Core (compression: $(CBFS_PAYLOAD_COMPRESS_FLAG))\n" - $(CBFSTOOL) $@.tmp add-payload -f $(CONFIG_PAYLOAD_FILE) -n $(CONFIG_CBFS_PREFIX)/payload -c $(CBFS_PAYLOAD_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_INCLUDE_CONFIG_FILE),y) - @printf " CONFIG $(DOTCONFIG)\n" - if [ -f $(DOTCONFIG) ]; then \ - echo "# This image was built using git revision" `git rev-parse HEAD` > $(obj)/config.tmp ; \ - sed -e '/^#/d' -e '/^ *$$/d' $(DOTCONFIG) >> $(obj)/config.tmp ; \ - $(CBFSTOOL) $@.tmp add -f $(obj)/config.tmp -n config -t raw; rm -f $(obj)/config.tmp ; fi -endif -ifeq ($(CONFIG_VBOOT_VERIFY_FIRMWARE),y) - $(CBFSTOOL) $@.tmp add-stage -f $(VBOOT_STUB_ELF) -n $(CONFIG_CBFS_PREFIX)/vboot -c $(CBFS_COMPRESS_FLAG) -endif -ifeq ($(CONFIG_PXE_ROM),y) - $(CBFSTOOL) $@.tmp add -f $(CONFIG_PXE_ROM_FILE) -n pci$(CONFIG_PXE_ROM_ID).rom -t raw -endif - mv $@.tmp $@ - @printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n" - $(CBFSTOOL) $@ print +LIBGCC_WRAP_LDFLAGS := --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 stripped_vgabios_id = $(call strip_quotes,$(CONFIG_VGA_BIOS_ID)) cbfs-files-$(CONFIG_VGA_BIOS) += pci$(stripped_vgabios_id).rom @@ -133,79 +79,77 @@ cbfs-files-$(CONFIG_BOOTSPLASH) += bootsplash.jpg bootsplash.jpg-file := $(call strip_quotes,$(CONFIG_BOOTSPLASH_FILE)) bootsplash.jpg-type := bootsplash -################################################################################ -# i386 specific tools -NVRAMTOOL:=$(objutil)/nvramtool/nvramtool +############################################################################### +# bootblock +############################################################################### -$(OPTION_TABLE_H): $(NVRAMTOOL) $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout - @printf " OPTION $(subst $(obj)/,,$(@))\n" - $(NVRAMTOOL) -y $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout -H $@ - -$(obj)/cmos_layout.bin: $(NVRAMTOOL) $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout - @printf " OPTION $(subst $(obj)/,,$(@))\n" - $(NVRAMTOOL) -y $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout -L $@ - -################################################################################ -# Common recipes for all stages - -$(objcbfs)/%.bin: $(objcbfs)/%.elf - @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - $(OBJCOPY) -O binary $< $@ - -$(objcbfs)/%.elf: $(objcbfs)/%.debug - @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cp $< $@.tmp - $(NM) -n $@.tmp | sort > $(basename $@).map - $(OBJCOPY) --strip-debug $@.tmp - $(OBJCOPY) --add-gnu-debuglink=$< $@.tmp - mv $@.tmp $@ - -################################################################################ -# Build the coreboot_ram (stage 2) - -ifeq ($(CONFIG_RELOCATABLE_RAMSTAGE),y) - -$(eval $(call rmodule_link,$(objcbfs)/coreboot_ram.debug, $(objgenerated)/coreboot_ram.o, $(CONFIG_HEAP_SIZE))) - -else - -$(objcbfs)/coreboot_ram.debug: $(objgenerated)/coreboot_ram.o $(src)/arch/x86/coreboot_ram.ld - @printf " CC $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m elf_i386 -o $@ -L$(obj) $< -T $(src)/arch/x86/coreboot_ram.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(src)/arch/x86/coreboot_ram.ld $< +ifeq ($(CONFIG_ARCH_BOOTBLOCK_X86_32),y) +bootblock-srcs += $(src)/arch/x86/init/failover.ld +bootblock-srcs += $(src)/cpu/x86/16bit/entry16.ld +bootblock-srcs += $(src)/cpu/x86/16bit/reset16.ld +bootblock-srcs += $(src)/arch/x86/lib/id.ld +ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) +bootblock-srcs += $(src)/cpu/intel/fit/fit.ld endif +# TODO: Why can't this use the real bootblock-y += xxx.S mechanism instead? +bootblock_inc = $(src)/arch/x86/init/prologue.inc +bootblock_inc += $(src)/cpu/x86/16bit/entry16.inc +bootblock_inc += $(src)/cpu/x86/16bit/reset16.inc +bootblock_inc += $(src)/cpu/x86/32bit/entry32.inc +bootblock_inc += $(src)/arch/x86/lib/id.inc +ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) +bootblock_inc += $(src)/cpu/intel/fit/fit.inc endif +bootblock_inc += $(chipset_bootblock_inc) -$(objgenerated)/coreboot_ram.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME) - @printf " CC $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m elf_i386 -r -o $@ --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) --end-group +ifeq ($(CONFIG_SSE),y) +bootblock_inc += $(src)/cpu/x86/sse_enable.inc +endif +bootblock_inc += $(objgenerated)/bootblock.inc +bootblock_inc += $(src)/arch/x86/lib/walkcbfs.S + +ifeq ($(CONFIG_SSE),y) +bootblock_romccflags = -mcpu=k7 -msse else - $(CC) $(CFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(ramstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group +bootblock_romccflags = -mcpu=i386 endif +bootblock_romccflags += -O2 $(bootblock-c-ccopts) $(bootblock-generic-ccopts) -################################################################################ -# Ramstage for AP CPU (AMD K8, obsolete?) +$(objgenerated)/bootblock.inc: $(src)/arch/x86/init/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(objutil)/romcc/romcc | $$(generic-deps) + @printf " ROMCC $(subst $(obj)/,,$(@))\n" + $(CC_bootblock) $(INCLUDES) $(INCLUDES_bootblock) -MM -MT$(objgenerated)/bootblock.inc \ + $< > $(objgenerated)/bootblock.inc.d + $(ROMCC) -c -S $(bootblock_romccflags) -I. $(INCLUDES) $(INCLUDES_bootblock) $< -o $@ -$(objcbfs)/coreboot_ap.debug: $(objgenerated)/coreboot_ap.o $(src)/arch/x86/init/ldscript_apc.lb - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(src)/arch/x86/init/ldscript_apc.lb $< +$(objgenerated)/bootblock.ld: $$(filter %.ld,$$(bootblock-objs)) + @printf " GEN $(subst $(obj)/,,$(@))\n" + printf '$(foreach ldscript,$(^),INCLUDE "$(ldscript)"\n)' > $@ -$(objgenerated)/coreboot_ap.o: $(src)/mainboard/$(MAINBOARDDIR)/ap_romstage.c $(OPTION_TABLE_H) - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD $(CFLAGS) -I$(src) -D__PRE_RAM__ -I. -I$(obj) -c $< -o $@ +$(objgenerated)/bootblock.S: $$(bootblock_inc) + @printf " GEN $(subst $(obj)/,,$(@))\n" + printf '$(foreach inc,$(bootblock_inc),#include "$(inc)"\n)' > $@ -################################################################################ -# done +bootblock-srcs += $(objgenerated)/bootblock.S + +bootblock-S-ccopts += -I. -Wa,-acdlns=$$$$(basename $$$$(@)).disasm + +$(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.bootblock.o $(objgenerated)/bootblock.ld + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,bootblock,$(<),-o $(@) -L$(obj) -T $(objgenerated)/bootblock.ld,) + +endif #CONFIG_ARCH_BOOTBLOCK_X86_32 + +############################################################################### +# romstage +############################################################################### + +ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y) crt0s = $(src)/arch/x86/init/prologue.inc -ldscripts = -ldscripts += $(src)/arch/x86/init/romstage.ld +romstage-srcs += $(src)/arch/x86/init/romstage.ld crt0s += $(src)/cpu/x86/32bit/entry32.inc -ldscripts += $(src)/cpu/x86/32bit/entry32.lds +romstage-srcs += $(src)/cpu/x86/32bit/entry32.ld crt0s += $(src)/cpu/x86/fpu_enable.inc ifeq ($(CONFIG_SSE),y) @@ -228,32 +172,93 @@ endif ifeq ($(CONFIG_ROMCC),y) ifeq ($(CONFIG_MMX),y) ifeq ($(CONFIG_SSE),y) - ROMCCFLAGS := -mcpu=p4 -O2 # MMX, SSE + ROMCCFLAGS = -mcpu=p4 -O2 # MMX, SSE else - ROMCCFLAGS := -mcpu=p2 -O2 # MMX, !SSE + ROMCCFLAGS = -mcpu=p2 -O2 # MMX, !SSE endif else - ROMCCFLAGS := -mcpu=i386 -O2 # !MMX, !SSE -endif + ROMCCFLAGS = -mcpu=i386 -O2 # !MMX, !SSE +endif # CONFIG_MMX +ROMCCFLAGS += $(romstage-c-ccopts) $(romstage-generic-ccopts) -$(obj)/mainboard/$(MAINBOARDDIR)/romstage.inc: $(src)/mainboard/$(MAINBOARDDIR)/romstage.c $(objutil)/romcc/romcc $(OPTION_TABLE_H) $(obj)/build.h $(obj)/config.h +$(objcbfs)/romstage_%.bin: $(objcbfs)/romstage_%.elf + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + $(OBJCOPY_romstage) -O binary $< $@ + +$(objcbfs)/romstage_%.elf: $(objcbfs)/romstage_%.debug + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + cp $< $@.tmp + $(NM_romstage) -n $@.tmp | sort > $(basename $@).map + $(OBJCOPY_romstage) --strip-debug $@.tmp + $(OBJCOPY_romstage) --add-gnu-debuglink=$< $@.tmp + mv $@.tmp $@ + +$(obj)/mainboard/$(MAINBOARDDIR)/romstage.inc: $(src)/mainboard/$(MAINBOARDDIR)/romstage.c $(objutil)/romcc/romcc | $$(generic-deps) printf " ROMCC romstage.inc\n" - $(ROMCC) -c -S $(ROMCCFLAGS) -D__PRE_RAM__ -I. $(INCLUDES) $< -o $@ -else + $(ROMCC) -c -S $(ROMCCFLAGS) -I. $(INCLUDES) $(INCLUDES_romstage) $< -o $@ +else # CONFIG_ROMCC -$(obj)/mainboard/$(MAINBOARDDIR)/romstage.pre.inc: $(src)/mainboard/$(MAINBOARDDIR)/romstage.c $(OPTION_TABLE_H) $(obj)/build.h $(obj)/config.h +$(obj)/mainboard/$(MAINBOARDDIR)/romstage.pre.inc: $(src)/mainboard/$(MAINBOARDDIR)/romstage.c | $$(generic-deps) @printf " CC romstage.inc\n" - $(CC) -MMD $(CFLAGS) -D__PRE_RAM__ -I$(src) -I. -I$(obj) -c -S $< -o $@ + $(CC_romstage) -MMD $(CFLAGS_romstage) $(romstage-c-ccopts) $(romstage-generic-ccopts) -I$(src) -I. -I$(obj) -c -S $< -o $@ $(obj)/mainboard/$(MAINBOARDDIR)/romstage.inc: $(obj)/mainboard/$(MAINBOARDDIR)/romstage.pre.inc @printf " POST romstage.inc\n" sed -e 's/\.rodata/.rom.data/g' -e 's/\^\.text/.section .rom.text/g' \ -e 's/\^\.section \.text/.section .rom.text/g' $^ > $@.tmp mv $@.tmp $@ -endif +endif # CONFIG_ROMCC + +$(objcbfs)/romstage_null.debug: $$(romstage-objs) $(LIBGCC_FILE_NAME_romstage) $(objgenerated)/romstage_null.ld + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,romstage,$(filter %.o %.a,$(^)),-o $(@) -L$(obj) -T $(objgenerated)/romstage_null.ld,$(LIBGCC_WRAP_LDFLAGS)) + $(OBJCOPY_romstage) --only-section .illegal_globals $(@) $(objcbfs)/romstage_null.offenders && \ + $(NM_romstage) $(objcbfs)/romstage_null.offenders | grep -q ""; if [ $$? -eq 0 ]; then \ + echo "Forbidden global variables in romstage:"; \ + $(NM_romstage) $(objcbfs)/romstage_null.offenders; test "$(CONFIG_CPU_AMD_AGESA)" = y; \ + else true; fi + +$(objcbfs)/romstage_xip.debug: $$(romstage-objs) $(LIBGCC_FILE_NAME_romstage) $(objgenerated)/romstage_xip.ld + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,romstage,$(filter %.o %.a,$(^)),-o $(@) -L$(obj) -T $(objgenerated)/romstage_xip.ld,$(LIBGCC_WRAP_LDFLAGS)) + +$(objgenerated)/romstage_null.ld: $$(filter %.ld,$$(romstage-objs)) + @printf " GEN $(subst $(obj)/,,$(@))\n" + rm -f $@ + printf "ROMSTAGE_BASE = 0x0;\n" > $@.tmp + printf '$(foreach ldscript,$(^),INCLUDE "$(ldscript)"\n)' >> $@.tmp + mv $@.tmp $@ + +$(objgenerated)/romstage_xip.ld: $(objgenerated)/romstage_null.ld $(objcbfs)/base_xip.txt + @printf " GEN $(subst $(obj)/,,$(@))\n" + rm -f $@ + sed -e 's/^/ROMSTAGE_BASE = /g' -e 's/$$/;/g' $(objcbfs)/base_xip.txt > $@.tmp + sed -e '/ROMSTAGE_BASE/d' $(objgenerated)/romstage_null.ld >> $@.tmp + mv $@.tmp $@ + +$(objcbfs)/base_xip.txt: $(obj)/coreboot.pre1 $(objcbfs)/romstage_null.bin + rm -f $@ + $(CBFSTOOL) $(obj)/coreboot.pre1 locate -T -f $(objcbfs)/romstage_null.bin -n $(CONFIG_CBFS_PREFIX)/romstage -P $(CONFIG_XIP_ROM_SIZE) > $@.tmp \ + || { echo "The romstage is larger than XIP size. Please expand the CONFIG_XIP_ROM_SIZE" ; exit 1; } + mv $@.tmp $@ + +$(objgenerated)/crt0.S: $$(crt0s) + @printf " GEN $(subst $(obj)/,,$(@))\n" + printf '$(foreach crt0,$(crt0s),#include "$(crt0)"\n)' > $@ + +romstage-srcs += $(objgenerated)/crt0.S + +# Compiling crt0 with -g seems to trigger https://sourceware.org/bugzilla/show_bug.cgi?id=6428 +romstage-S-ccopts += -I. -Wa,-acdlns=$$$$(basename $$$$(@)).disasm -g0 + +endif # CONFIG_ARCH_ROMSTAGE_X86_32 + +############################################################################### +# ramstage +############################################################################### + +ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) -# Things that appear in every board -romstage-srcs += $(objgenerated)/crt0.s ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c) ifeq ($(CONFIG_GENERATE_MP_TABLE),y) ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/mptable.c),) @@ -284,7 +289,7 @@ endif ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/fadt.c),) ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/fadt.c endif -endif +endif # CONFIG_GENERATE_ACPI_TABLES ifeq ($(CONFIG_HAVE_SMI_HANDLER),y) ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/smihandler.c),) smm-srcs += src/mainboard/$(MAINBOARDDIR)/smihandler.c @@ -294,140 +299,61 @@ ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/get_bus_conf.c),) ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/get_bus_conf.c endif -################################################################################ -# Build the final rom image +ifeq ($(CONFIG_RELOCATABLE_RAMSTAGE),y) + +$(eval $(call rmodule_link,$(objcbfs)/ramstage.debug, $(objgenerated)/ramstage.o, $(CONFIG_HEAP_SIZE),x86_32)) + +# The rmodule_link defintion creates an elf file with .rmod extension. +$(objcbfs)/ramstage.elf: $(objcbfs)/ramstage.debug.rmod + cp $< $@ + +else # CONFIG_RELOCATABLE_RAMSTAGE + +ramstage-srcs += $(src)/arch/x86/ramstage.ld + +$(objcbfs)/ramstage.debug: $(objgenerated)/ramstage.o + @printf " CC $(subst $(obj)/,,$(@))\n" + $(call link,ramstage,$(<),-o $(@) -L$(obj) -T $(obj)/arch/x86/ramstage.ramstage.ld,) + +endif # CONFIG_RELOCATABLE_RAMSTAGE + +$(objgenerated)/ramstage.o: $$(ramstage-objs) $(LIBGCC_FILE_NAME_ramstage) + @printf " CC $(subst $(obj)/,,$(@))\n" + $(call link,ramstage,$(filter %.o %.a,$(^)),-o $(@) -L$(obj),-r $(LIBGCC_WRAP_LDFLAGS)) + +endif # CONFIG_ARCH_ROMSTAGE_X86_32 -$(obj)/coreboot.pre: $(objcbfs)/romstage_xip.elf $(obj)/coreboot.pre1 $(CBFSTOOL) - @printf " CBFS $(subst $(obj)/,,$(@))\n" - cp $(obj)/coreboot.pre1 $@.tmp - $(CBFSTOOL) $@.tmp add-stage -f $(objcbfs)/romstage_xip.elf \ - -n $(CONFIG_CBFS_PREFIX)/romstage -c none \ - -b $(shell cat $(objcbfs)/base_xip.txt) - mv $@.tmp $@ ################################################################################ -# Build the bootblock +# ACPI ASL +################################################################################ -bootblock_lds = $(src)/arch/x86/init/ldscript_failover.lb -bootblock_lds += $(src)/cpu/x86/16bit/entry16.lds -bootblock_lds += $(src)/cpu/x86/16bit/reset16.lds -bootblock_lds += $(src)/arch/x86/lib/id.lds -bootblock_lds += $(chipset_bootblock_lds) -ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) -bootblock_lds += $(src)/cpu/intel/fit/fit.lds -endif +# Compile ASLs in three steps: src/%.asl -CPP-> obj/%..asl -IASL-> obj/%..c -CC-> obj/%..o +generic-asl-ccopts += $(PREPROCESS_ONLY) -D__ACPI__ -I$(src)/mainboard/$(MAINBOARDDIR) -bootblock_inc = $(src)/arch/x86/init/prologue.inc -bootblock_inc += $(src)/cpu/x86/16bit/entry16.inc -bootblock_inc += $(src)/cpu/x86/16bit/reset16.inc -bootblock_inc += $(src)/cpu/x86/32bit/entry32.inc -bootblock_inc += $(src)/arch/x86/lib/id.inc -ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) -bootblock_inc += $(src)/cpu/intel/fit/fit.inc -endif -bootblock_inc += $(chipset_bootblock_inc) +%.c: %.asl + @printf " IASL $(subst $(top)/,,$(@))\n" + cd $(dir $(<)); $(IASL) -p $(notdir $(<)) -tc $(notdir $(<)) + mv $(<:%.asl=%.hex) $(@) +# Change array identifier in generated files for everything but dsdt to avoid conflicts +# (TODO: Shouldn't we just call that one AmlCode_dsdt as well for consistency?) + $(if $(subst dsdt,,$(basename $(basename $(notdir $(<))))),sed -ie 's/AmlCode/AmlCode_$(basename $(basename $(notdir $(<))))/' $(@)) -ifeq ($(CONFIG_SSE),y) -bootblock_inc += $(src)/cpu/x86/sse_enable.inc -endif -bootblock_inc += $(objgenerated)/bootblock.inc -bootblock_inc += $(src)/arch/x86/lib/walkcbfs.S +# Prepend function that does equivalent of '-y += .o' for all .asl in to postprocessors +postprocessors := $$(foreach class,$$(classes), \ + $$(foreach asl,$$(filter %.asl,$$(call src-to-obj,$$(class),$$($$(class)-srcs))), \ + $$(eval ramstage-objs += $$(asl:%.asl=%.o)) \ + $$(eval ramstage-srcs += $$(asl:%.asl=%.c)))) \ + $(postprocessors) -bootblock_romccflags := -mcpu=i386 -O2 -D__PRE_RAM__ -ifeq ($(CONFIG_SSE),y) -bootblock_romccflags := -mcpu=k7 -msse -O2 -D__PRE_RAM__ -endif - -$(objgenerated)/bootblock.ld: $$(bootblock_lds) $(obj)/ldoptions - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach ldscript,ldoptions $(bootblock_lds),INCLUDE "$(ldscript)"\n)' > $@ - -$(objgenerated)/bootblock_inc.S: $$(bootblock_inc) - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach crt0,$(bootblock_inc),#include "$(crt0)"\n)' > $@ - -$(objgenerated)/bootblock.o: $(objgenerated)/bootblock.s - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -Wa,-acdlns -c -o $@ $< > $(basename $@).disasm - -$(objgenerated)/bootblock.s: $(objgenerated)/bootblock_inc.S $(obj)/config.h $(obj)/build.h - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/x86/include -I$(obj) -include $(obj)/build.h -include $(obj)/config.h -I. -I$(src) $< -o $@ - -$(objgenerated)/bootblock.inc: $(src)/arch/x86/init/$(subst ",,$(CONFIG_BOOTBLOCK_SOURCE)) $(objutil)/romcc/romcc $(OPTION_TABLE_H) - @printf " ROMCC $(subst $(obj)/,,$(@))\n" - $(CC) $(INCLUDES) -MM -MT$(objgenerated)/bootblock.inc \ - $< > $(objgenerated)/bootblock.inc.d - $(ROMCC) -c -S $(bootblock_romccflags) -I. $(INCLUDES) $< -o $@ - -$(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.o $(objgenerated)/bootblock.ld - @printf " LINK $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -m elf_i386 -static -o $@.tmp -L$(obj) $< -T $(objgenerated)/bootblock.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(objgenerated)/bootblock.ld $< -endif ################################################################################ -# Build the romstage - -$(objcbfs)/romstage_null.debug: $$(romstage-objs) $(objgenerated)/romstage_null.ld - @printf " LINK $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -nostdlib -nostartfiles -static -o $@ -L$(obj) --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(romstage-objs) $(LIBGCC_FILE_NAME) --end-group -T $(objgenerated)/romstage_null.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(objgenerated)/romstage_null.ld -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(romstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group -endif - $(NM) $@ | grep -q " [DdBb] "; if [ $$? -eq 0 ]; then \ - echo "Forbidden global variables in romstage:"; \ - $(NM) $@ | grep " [DdBb] "; test "$(CONFIG_CPU_AMD_AGESA)" = y; \ - else true; fi - -$(objcbfs)/romstage_xip.debug: $$(romstage-objs) $(objgenerated)/romstage_xip.ld - @printf " LINK $(subst $(obj)/,,$(@))\n" -ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y) - $(LD) -nostdlib -nostartfiles -static -o $@ -L$(obj) --wrap __divdi3 --wrap __udivdi3 --wrap __moddi3 --wrap __umoddi3 --start-group $(romstage-objs) $(LIBGCC_FILE_NAME) --end-group -T $(objgenerated)/romstage_xip.ld -else - $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(objgenerated)/romstage_xip.ld -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(romstage-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group -endif - -$(objgenerated)/romstage_null.ld: $$(ldscripts) $(obj)/ldoptions - @printf " GEN $(subst $(obj)/,,$(@))\n" - rm -f $@ - printf "ROMSTAGE_BASE = 0x0;\n" > $@.tmp - printf '$(foreach ldscript,ldoptions $(ldscripts),INCLUDE "$(ldscript:$(obj)/%=%)"\n)' >> $@.tmp - mv $@.tmp $@ - -$(objgenerated)/romstage_xip.ld: $(objgenerated)/romstage_null.ld $(objcbfs)/base_xip.txt - @printf " GEN $(subst $(obj)/,,$(@))\n" - rm -f $@ - sed -e 's/^/ROMSTAGE_BASE = /g' -e 's/$$/;/g' $(objcbfs)/base_xip.txt > $@.tmp - sed -e '/ROMSTAGE_BASE/d' $(objgenerated)/romstage_null.ld >> $@.tmp - mv $@.tmp $@ - -$(objcbfs)/base_xip.txt: $(obj)/coreboot.pre1 $(objcbfs)/romstage_null.bin - rm -f $@ - $(CBFSTOOL) $(obj)/coreboot.pre1 locate -T -f $(objcbfs)/romstage_null.bin -n $(CONFIG_CBFS_PREFIX)/romstage -P $(CONFIG_XIP_ROM_SIZE) > $@.tmp \ - || { echo "The romstage is larger than XIP size. Please expand the CONFIG_XIP_ROM_SIZE" ; exit 1; } - mv $@.tmp $@ - -$(objgenerated)/crt0.romstage.S: $$(crt0s) - @printf " GEN $(subst $(obj)/,,$(@))\n" - printf '$(foreach crt0,$(crt0s),#include "$(crt0:$(obj)/%=%)"\n)' > $@ - -$(objgenerated)/crt0.romstage.o: $(objgenerated)/crt0.s - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -Wa,-acdlns -c -o $@ $< > $(basename $@).disasm - -$(objgenerated)/crt0.s: $(objgenerated)/crt0.romstage.S $(obj)/config.h $(obj)/build.h - @printf " CC $(subst $(obj)/,,$(@))\n" - $(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/x86/include -I$(obj) -include $(obj)/config.h -include $(obj)/build.h -I. -I$(src) $< -o $@ seabios: $(MAKE) -C payloads/external/SeaBIOS -f Makefile.inc \ HOSTCC="$(HOSTCC)" \ - CC="$(CC)" LD="$(LD)" OBJDUMP="$(OBJDUMP)" \ - OBJCOPY="$(OBJCOPY)" STRIP="$(STRIP)" \ + CC="$(CC_x86_32)" LD="$(LD_x86_32)" OBJDUMP="$(OBJDUMP_x86_32)" \ + OBJCOPY="$(OBJCOPY_x86_32)" STRIP="$(STRIP_x86_32)" \ CONFIG_SEABIOS_MASTER=$(CONFIG_SEABIOS_MASTER) \ CONFIG_SEABIOS_STABLE=$(CONFIG_SEABIOS_STABLE) \ OUT=$(abspath $(obj)) IASL="$(IASL)" @@ -435,8 +361,7 @@ seabios: filo: $(MAKE) -C payloads/external/FILO -f Makefile.inc \ HOSTCC="$(HOSTCC)" \ - CC="$(CC)" LD="$(LD)" OBJDUMP="$(OBJDUMP)" \ - OBJCOPY="$(OBJCOPY)" STRIP="$(STRIP)" \ + CC="$(CC_x86_32)" LD="$(LD_x86_32)" OBJDUMP="$(OBJDUMP_x86_32)" \ + OBJCOPY="$(OBJCOPY_x86_32)" STRIP="$(STRIP_x86_32)" \ CONFIG_FILO_MASTER=$(CONFIG_FILO_MASTER) \ CONFIG_FILO_STABLE=$(CONFIG_FILO_STABLE) - diff --git a/src/arch/x86/boot/Makefile.inc b/src/arch/x86/boot/Makefile.inc index 7b67e49c1c..c4e8786248 100644 --- a/src/arch/x86/boot/Makefile.inc +++ b/src/arch/x86/boot/Makefile.inc @@ -1,3 +1,6 @@ + +ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) + ramstage-y += boot.c ramstage-$(CONFIG_MULTIBOOT) += multiboot.c ramstage-y += gdt.c @@ -8,8 +11,5 @@ ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpigen.c ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S -ramstage-$(CONFIG_RELOCATABLE_RAMSTAGE) += ramstage_module_header.c - -$(obj)/arch/x86/boot/coreboot_table.ramstage.o : $(OPTION_TABLE_H) -$(obj)/arch/x86/boot/smbios.ramstage.o: $(obj)/build.h +endif diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c index 96ece06af9..a875bee320 100644 --- a/src/arch/x86/boot/acpi.c +++ b/src/arch/x86/boot/acpi.c @@ -33,10 +33,7 @@ #include #include #include -#if CONFIG_COLLECT_TIMESTAMPS #include -#endif -#include /* FIXME: Kconfig doesn't support overridable defaults :-( */ #ifndef CONFIG_HPET_MIN_TICKS @@ -621,38 +618,29 @@ void acpi_write_hest(acpi_hest_t *hest) header->checksum = acpi_checksum((void *)hest, header->length); } -#if CONFIG_HAVE_ACPI_RESUME -void suspend_resume(void) +void __attribute__((weak)) mainboard_suspend_resume(void) { - void *wake_vec; +} - /* If we happen to be resuming find wakeup vector and jump to OS. */ - wake_vec = acpi_find_wakeup_vector(); - if (wake_vec) { +#if CONFIG_HAVE_ACPI_RESUME +void acpi_resume(void *wake_vec) +{ #if CONFIG_HAVE_SMI_HANDLER - u32 *gnvs_address = cbmem_find(CBMEM_ID_ACPI_GNVS_PTR); + u32 *gnvs_address = cbmem_find(CBMEM_ID_ACPI_GNVS_PTR); - /* Restore GNVS pointer in SMM if found */ - if (gnvs_address && *gnvs_address) { - printk(BIOS_DEBUG, "Restore GNVS pointer to 0x%08x\n", - *gnvs_address); - smm_setup_structures((void *)*gnvs_address, NULL, NULL); - } -#endif - - /* Call mainboard resume handler first, if defined. */ - if (mainboard_suspend_resume) - mainboard_suspend_resume(); -#if CONFIG_COVERAGE - coverage_exit(); -#endif - /* Tear down the caching of the ROM. */ - if (disable_cache_rom) - disable_cache_rom(); - - post_code(POST_OS_RESUME); - acpi_jump_to_wakeup(wake_vec); + /* Restore GNVS pointer in SMM if found */ + if (gnvs_address && *gnvs_address) { + printk(BIOS_DEBUG, "Restore GNVS pointer to 0x%08x\n", + *gnvs_address); + smm_setup_structures((void *)*gnvs_address, NULL, NULL); } +#endif + + /* Call mainboard resume handler first, if defined. */ + mainboard_suspend_resume(); + + post_code(POST_OS_RESUME); + acpi_jump_to_wakeup(wake_vec); } /* This is to be filled by SB code - startup value what was found. */ @@ -787,9 +775,7 @@ void acpi_jump_to_wakeup(void *vector) /* Copy wakeup trampoline in place. */ memcpy((void *)WAKEUP_BASE, &__wakeup, __wakeup_size); -#if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_ACPI_WAKE_JUMP); -#endif acpi_do_wakeup((u32)vector, acpi_backup_memory, CONFIG_RAMBASE, HIGH_MEMORY_SAVE); diff --git a/src/arch/x86/boot/boot.c b/src/arch/x86/boot/boot.c index 4892c5e009..5ce9c04edb 100644 --- a/src/arch/x86/boot/boot.c +++ b/src/arch/x86/boot/boot.c @@ -1,81 +1,15 @@ #include +#include #include -#include -#include #include +#include #include - -#ifndef CMD_LINE -#define CMD_LINE "" -#endif - - - -#define UPSZ(X) ((sizeof(X) + 3) &~3) - -static struct { - Elf_Bhdr hdr; - Elf_Nhdr ft_hdr; - unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)]; - Elf_Nhdr bl_hdr; - unsigned char bl_desc[UPSZ(BOOTLOADER)]; - Elf_Nhdr blv_hdr; - unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; - Elf_Nhdr cmd_hdr; - unsigned char cmd_desc[UPSZ(CMD_LINE)]; -} elf_boot_notes = { - .hdr = { - .b_signature = 0x0E1FB007, - .b_size = sizeof(elf_boot_notes), - .b_checksum = 0, - .b_records = 4, - }, - .ft_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(FIRMWARE_TYPE), - .n_type = EBN_FIRMWARE_TYPE, - }, - .ft_desc = FIRMWARE_TYPE, - .bl_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER), - .n_type = EBN_BOOTLOADER_NAME, - }, - .bl_desc = BOOTLOADER, - .blv_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(BOOTLOADER_VERSION), - .n_type = EBN_BOOTLOADER_VERSION, - }, - .blv_desc = BOOTLOADER_VERSION, - .cmd_hdr = { - .n_namesz = 0, - .n_descsz = sizeof(CMD_LINE), - .n_type = EBN_COMMAND_LINE, - }, - .cmd_desc = CMD_LINE, -}; - - -int elf_check_arch(Elf_ehdr *ehdr) -{ - return ( - ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) && - (ehdr->e_ident[EI_CLASS] == ELFCLASS32) && - (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) - ); - -} - #if CONFIG_RELOCATABLE_RAMSTAGE /* When the ramstage is relocatable the elf loading ensures an elf image cannot * be loaded over the ramstage code. */ void jmp_to_elf_entry(void *entry, unsigned long unused1, unsigned long unused2) { - elf_boot_notes.hdr.b_checksum = - compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes)); - /* Jump to kernel */ __asm__ __volatile__( " cld \n\t" @@ -87,38 +21,24 @@ void jmp_to_elf_entry(void *entry, unsigned long unused1, unsigned long unused2) " cld \n\t" :: - "r" (entry), + "r" (entry) #if CONFIG_MULTIBOOT - "b"(mbi), "a" (MB_MAGIC2) -#else - "b"(&elf_boot_notes), "a" (0x0E1FB007) + , "b"(mbi), "a" (MB_MAGIC2) #endif ); } #else void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) { - extern unsigned char _ram_seg, _eram_seg; unsigned long lb_start, lb_size; - unsigned long adjust, adjusted_boot_notes; - elf_boot_notes.hdr.b_checksum = - compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes)); - - lb_start = (unsigned long)&_ram_seg; - lb_size = (unsigned long)(&_eram_seg - &_ram_seg); - adjust = buffer + size - lb_start; - - adjusted_boot_notes = (unsigned long)&elf_boot_notes; - adjusted_boot_notes += adjust; + lb_start = (unsigned long)&_program; + lb_size = _program_size; printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry); printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start); printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size); - printk(BIOS_SPEW, "adjust = 0x%08lx\n", adjust); printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer); - printk(BIOS_SPEW, " elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes); - printk(BIOS_SPEW, "adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes); /* Jump to kernel */ __asm__ __volatile__( @@ -206,7 +126,7 @@ void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size) #if CONFIG_MULTIBOOT "ri"(mbi), "ri" (MB_MAGIC2) #else - "ri"(adjusted_boot_notes), "ri" (0x0E1FB007) + "ri"(0), "ri" (0) #endif ); } diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c index 308336a5e8..c58a95cdb0 100644 --- a/src/arch/x86/boot/smbios.c +++ b/src/arch/x86/boot/smbios.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #if CONFIG_CHROMEOS #include #endif @@ -118,6 +121,97 @@ static int smbios_processor_name(char *start) return smbios_add_string(start, tmp); } +/* this function will fill the corresponding manufacturer */ +static void fill_manu_for_dimm(uint16_t mod_id, struct smbios_type17 *t) +{ + switch (mod_id) { + case 0xad80: + t->manufacturer = smbios_add_string(t->eos, + "Hynix/Hyundai"); + break; + case 0xce80: + t->manufacturer = smbios_add_string(t->eos, + "Samsung"); + break; + case 0xfe02: + t->manufacturer = smbios_add_string(t->eos, + "Elpida"); + break; + default: + t->manufacturer = smbios_add_string(t->eos, + "Unknown"); + break; + } +} + +static int create_smbios_type17_for_dimm(struct dimm_info *dimm, + unsigned long *current, int *handle) +{ + struct smbios_type17 *t = (struct smbios_type17 *)*current; + uint8_t length; + char locator[40]; + + memset(t, 0, sizeof(struct smbios_type17)); + t->memory_type = dimm->ddr_type; + t->clock_speed = dimm->ddr_frequency; + t->speed = dimm->ddr_frequency; + t->type = SMBIOS_MEMORY_DEVICE; + t->size = dimm->dimm_size; + t->data_width = 8 * (1 << (dimm->bus_width & 0x7)); + t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3); + + switch (dimm->mod_type) { + case SPD_RDIMM: + case SPD_MINI_RDIMM: + t->form_factor = MEMORY_FORMFACTOR_RIMM; + break; + case SPD_UDIMM: + case SPD_MICRO_DIMM: + case SPD_MINI_UDIMM: + t->form_factor = MEMORY_FORMFACTOR_DIMM; + break; + case SPD_SODIMM: + t->form_factor = MEMORY_FORMFACTOR_SODIMM; + break; + default: + t->form_factor = MEMORY_FORMFACTOR_UNKNOWN; + break; + } + + fill_manu_for_dimm(dimm->mod_id, t); + /* put '\0' in the end of data */ + length = sizeof(dimm->serial); + dimm->serial[length - 1] = '\0'; + if (dimm->serial[0] == 0) { + t->serial_number = smbios_add_string(t->eos, "None"); + } else { + t->serial_number = smbios_add_string(t->eos, + (const char *)dimm->serial); + } + sprintf(locator, "Channel-%d-DIMM-%d", + dimm->channel_num, dimm->dimm_num); + t->device_locator = smbios_add_string(t->eos, locator); + + sprintf(locator, "BANK %d", dimm->bank_locator); + t->bank_locator = smbios_add_string(t->eos, locator); + + /* put '\0' in the end of data */ + length = sizeof(dimm->module_part_number); + dimm->module_part_number[length - 1] = '\0'; + t->part_number = smbios_add_string(t->eos, + (const char *)dimm->module_part_number); + + /* Synchronous = 1 */ + t->type_detail = 0x0080; + /* no handle for error information */ + t->memory_error_information_handle = 0xFFFE; + t->attributes = dimm->rank_per_dimm; + t->handle = *handle; + *handle += 1; + t->length = sizeof(struct smbios_type17) - 2; + return t->length + smbios_string_table_len(t->eos); +} + static int smbios_write_type0(unsigned long *current, int handle) { struct smbios_type0 *t = (struct smbios_type0 *)*current; @@ -183,6 +277,13 @@ const char *__attribute__((weak)) smbios_mainboard_version(void) return CONFIG_MAINBOARD_VERSION; } +#ifdef CONFIG_MAINBOARD_FAMILY +const char *smbios_mainboard_family(void) +{ + return CONFIG_MAINBOARD_FAMILY; +} +#endif /* CONFIG_MAINBOARD_FAMILY */ + static int smbios_write_type1(unsigned long *current, int handle) { struct smbios_type1 *t = (struct smbios_type1 *)*current; @@ -196,6 +297,9 @@ static int smbios_write_type1(unsigned long *current, int handle) t->product_name = smbios_add_string(t->eos, CONFIG_MAINBOARD_PART_NUMBER); t->serial_number = smbios_add_string(t->eos, smbios_mainboard_serial_number()); t->version = smbios_add_string(t->eos, smbios_mainboard_version()); +#ifdef CONFIG_MAINBOARD_FAMILY + t->family = smbios_add_string(t->eos, smbios_mainboard_family()); +#endif len = t->length + smbios_string_table_len(t->eos); *current += len; return len; @@ -214,7 +318,7 @@ static int smbios_write_type3(unsigned long *current, int handle) t->bootup_state = SMBIOS_STATE_SAFE; t->power_supply_state = SMBIOS_STATE_SAFE; t->thermal_state = SMBIOS_STATE_SAFE; - t->_type = 3; + t->_type = CONFIG_MAINBOARD_ENCLOSURE_TYPE; t->security_status = SMBIOS_STATE_SAFE; len = t->length + smbios_string_table_len(t->eos); *current += len; @@ -256,6 +360,29 @@ static int smbios_write_type4(unsigned long *current, int handle) return len; } +static int smbios_write_type17(unsigned long *current, int *handle) +{ + int len = sizeof(struct smbios_type17); + uint16_t i = 0, size; + + struct memory_info *meminfo; + meminfo = cbmem_find(CBMEM_ID_MEMINFO); + if (meminfo == NULL) { + /* can't find mem info in cbmem */ + return 0; + } + + printk(BIOS_INFO, "Create smbios type 17\n"); + size = ARRAY_SIZE(meminfo->dimm); + for (i = 0; i < meminfo->dimm_cnt && i < size; i++) { + struct dimm_info *dimm; + dimm = &meminfo->dimm[i]; + len = create_smbios_type17_for_dimm(dimm, current, handle); + *current += len; + } + return meminfo->dimm_cnt * len; +} + static int smbios_write_type32(unsigned long *current, int handle) { struct smbios_type32 *t = (struct smbios_type32 *)*current; @@ -269,6 +396,32 @@ static int smbios_write_type32(unsigned long *current, int handle) return len; } +int smbios_write_type41(unsigned long *current, int *handle, + const char *name, u8 instance, u16 segment, + u8 bus, u8 device, u8 function) +{ + struct smbios_type41 *t = (struct smbios_type41 *)*current; + int len = sizeof(struct smbios_type41); + + memset(t, 0, sizeof(struct smbios_type41)); + t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION; + t->handle = *handle; + t->length = len - 2; + t->reference_designation = smbios_add_string(t->eos, name); + t->device_type = SMBIOS_DEVICE_TYPE_OTHER; + t->device_status = 1; + t->device_type_instance = instance; + t->segment_group_number = segment; + t->bus_number = bus; + t->device_number = device; + t->function_number = function; + + len = t->length + smbios_string_table_len(t->eos); + *current += len; + *handle += 1; + return len; +} + static int smbios_write_type127(unsigned long *current, int handle) { struct smbios_type127 *t = (struct smbios_type127 *)*current; @@ -317,6 +470,7 @@ unsigned long smbios_write_tables(unsigned long current) #if CONFIG_ELOG len += elog_smbios_write_type15(¤t, handle++); #endif + len += smbios_write_type17(¤t, &handle); len += smbios_write_type32(¤t, handle++); len += smbios_walk_device_tree(all_devices, &handle, ¤t); diff --git a/src/arch/x86/boot/tables.c b/src/arch/x86/boot/tables.c index 6355a1b9dc..74607ccfce 100644 --- a/src/arch/x86/boot/tables.c +++ b/src/arch/x86/boot/tables.c @@ -35,11 +35,12 @@ uint64_t high_tables_base = 0; uint64_t high_tables_size; -void cbmem_arch_init(void) +static void cbmem_arch_init(void) { /* defined in gdt.c */ move_gdt(); } +RAMSTAGE_CBMEM_INIT_HOOK(cbmem_arch_init) struct lb_memory *write_tables(void) { diff --git a/src/arch/x86/coreboot_ram.ld b/src/arch/x86/coreboot_ram.ld deleted file mode 100644 index 2dd51d515b..0000000000 --- a/src/arch/x86/coreboot_ram.ld +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Memory map: - * - * CONFIG_RAMBASE : text segment - * : rodata segment - * : data segment - * : bss segment - * : stack - * : heap - */ -/* - * Bootstrap code for the STPC Consumer - * Copyright (c) 1999 by Net Insight AB. All Rights Reserved. - */ - -/* - * Written by Johan Rydberg, based on work by Daniel Kahlin. - * Rewritten by Eric Biederman - * 2005.12 yhlu add coreboot_ram cross the vga font buffer handling - */ - -/* We use ELF as output format. So that we can debug the code in some form. */ -INCLUDE ldoptions - -ENTRY(_start) - -SECTIONS -{ - . = CONFIG_RAMBASE; - /* First we place the code and read only data (typically const declared). - * This could theoretically be placed in rom. - */ - .text : { - _text = .; - *(.textfirst); - *(.text); - *(.text.*); - . = ALIGN(16); - _etext = .; - } - - .ctors : { - . = ALIGN(0x100); - __CTOR_LIST__ = .; - *(.ctors); - LONG(0); - __CTOR_END__ = .; - } - - .rodata : { - _rodata = .; - . = ALIGN(4); - - /* If any changes are made to the driver start/symbols or the - * section names the equivalent changes need to made to - * rmodule.ld. */ - console_drivers = .; - *(.rodata.console_drivers) - econsole_drivers = . ; - . = ALIGN(4); - pci_drivers = . ; - *(.rodata.pci_driver) - epci_drivers = . ; - cpu_drivers = . ; - *(.rodata.cpu_driver) - ecpu_drivers = . ; - - *(.rodata) - *(.rodata.*) - /* kevinh/Ispiri - Added an align, because the objcopy tool - * incorrectly converts sections that are not long word aligned. - */ - . = ALIGN(4); - - _erodata = .; - } - /* After the code we place initialized data (typically initialized - * global variables). This gets copied into ram by startup code. - * __data_start and __data_end shows where in ram this should be placed, - * whereas __data_loadstart and __data_loadend shows where in rom to - * copy from. - */ - .data : { - _data = .; - *(.data) - _edata = .; - } - - /* bss does not contain data, it is just a space that should be zero - * initialized on startup. (typically uninitialized global variables) - * crt0.S fills between _bss and _ebss with zeroes. - */ - _bss = .; - .bss . : { - *(.bss) - *(.sbss) - *(COMMON) - } - _ebss = .; - - _heap = .; - .heap . : { - /* Reserve CONFIG_HEAP_SIZE bytes for the heap */ - . = CONFIG_HEAP_SIZE ; - . = ALIGN(4); - } - _eheap = .; - - /* The ram segment. This includes all memory used by the memory - * resident copy of coreboot, except the tables that are produced on - * the fly, but including stack and heap. - */ - _ram_seg = _text; - _eram_seg = _eheap; - - /* CONFIG_RAMTOP is the upper address of cached memory (among other - * things). We must not exceed beyond that address, there be dragons. - */ - _bogus = ASSERT( ( _eram_seg < (CONFIG_RAMTOP)) , "Please increase CONFIG_RAMTOP"); - - /* Discard the sections we don't need/want */ - - /DISCARD/ : { - *(.comment) - *(.note) - *(.note.*) - } -} diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h index 022a45fd52..4ae63a0c9c 100644 --- a/src/arch/x86/include/arch/acpi.h +++ b/src/arch/x86/include/arch/acpi.h @@ -558,8 +558,8 @@ void acpi_save_gnvs(u32 gnvs_address); /* 0 = S0, 1 = S1 ...*/ extern u8 acpi_slp_type; -void suspend_resume(void); -void __attribute__((weak)) mainboard_suspend_resume(void); +void acpi_resume(void *wake_vec); +void mainboard_suspend_resume(void); void *acpi_find_wakeup_vector(void); void *acpi_get_wakeup_rsdp(void); void acpi_jump_to_wakeup(void *wakeup_addr); diff --git a/src/arch/x86/include/arch/cache.h b/src/arch/x86/include/arch/cache.h new file mode 100644 index 0000000000..687d3bf9d3 --- /dev/null +++ b/src/arch/x86/include/arch/cache.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef ARCH_CACHE_H +#define ARCH_CACHE_H + +/* + * For the purposes of the currently executing CPU loading code that will be + * run there aren't any cache coherency operations required. This just provides + * symmetry between architectures. + */ +static inline void cache_sync_instructions(void) {} + +#endif /* ARCH_CACHE_H */ diff --git a/src/arch/x86/include/arch/cpu.h b/src/arch/x86/include/arch/cpu.h index a3555d81d3..0ca8ada02a 100644 --- a/src/arch/x86/include/arch/cpu.h +++ b/src/arch/x86/include/arch/cpu.h @@ -140,7 +140,6 @@ static inline unsigned int cpuid_edx(unsigned int op) #define X86_VENDOR_SIS 10 #define X86_VENDOR_UNKNOWN 0xff -#if !defined(__ROMCC__) #if !defined(__PRE_RAM__) && !defined(__SMM__) #include @@ -158,15 +157,16 @@ struct cpu_driver { struct acpi_cstate *cstates; }; -struct device; struct cpu_driver *find_cpu_driver(struct device *cpu); -#else -#include -#endif + +struct thread; struct cpu_info { device_t cpu; unsigned int index; +#if CONFIG_COOP_MULTITASKING + struct thread *thread; +#endif }; static inline struct cpu_info *cpu_info(void) @@ -187,7 +187,11 @@ static inline unsigned long cpu_index(void) ci = cpu_info(); return ci->index; } +#else +#include +#endif +#ifndef __ROMCC__ // romcc is segfaulting in some cases struct cpuinfo_x86 { uint8_t x86; /* CPU family */ uint8_t x86_vendor; /* CPU vendor */ @@ -195,7 +199,7 @@ struct cpuinfo_x86 { uint8_t x86_mask; }; -static void inline get_fms(struct cpuinfo_x86 *c, uint32_t tfms) +static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms) { c->x86 = (tfms >> 8) & 0xf; c->x86_model = (tfms >> 4) & 0xf; @@ -206,9 +210,9 @@ static void inline get_fms(struct cpuinfo_x86 *c, uint32_t tfms) c->x86_model += ((tfms >> 16) & 0xF) << 4; } - -#define asmlinkage __attribute__((regparm(0))) - #endif +#define asmlinkage __attribute__((regparm(0))) +#define alwaysinline inline __attribute__((always_inline)) + #endif /* ARCH_CPU_H */ diff --git a/src/arch/x86/include/arch/early_variables.h b/src/arch/x86/include/arch/early_variables.h new file mode 100644 index 0000000000..830212def9 --- /dev/null +++ b/src/arch/x86/include/arch/early_variables.h @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef ARCH_EARLY_VARIABLES_H +#define ARCH_EARLY_VARIABLES_H + +#ifdef __PRE_RAM__ +#define CAR_GLOBAL __attribute__((section(".car.global_data,\"w\",@nobits#"))) +#else +#define CAR_GLOBAL +#endif + +#if CONFIG_CAR_MIGRATION && defined(__PRE_RAM__) + +/* Get the correct pointer for the CAR global variable. */ +void *car_get_var_ptr(void *var); + +/* Get and set a primitive type global variable. */ +#define car_get_var(var) \ + *(typeof(var) *)car_get_var_ptr(&(var)) +#define car_set_var(var, val) \ + do { car_get_var(var) = (val); } while(0) + +/* Migrate the CAR variables to memory. */ +void car_migrate_variables(void); + +#else +static inline void *car_get_var_ptr(void *var) { return var; } +#define car_get_var(var) (var) +#define car_set_var(var, val) do { (var) = (val); } while (0) +static inline void car_migrate_variables(void) { } +#endif + + +#endif diff --git a/src/arch/x86/include/arch/exception.h b/src/arch/x86/include/arch/exception.h new file mode 100644 index 0000000000..d4e9658f75 --- /dev/null +++ b/src/arch/x86/include/arch/exception.h @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H + +static inline void exception_init(void) { /* not implemented */ } + +#endif diff --git a/src/arch/x86/include/arch/interrupt.h b/src/arch/x86/include/arch/interrupt.h index 8c9b4a93d8..9753c502ee 100644 --- a/src/arch/x86/include/arch/interrupt.h +++ b/src/arch/x86/include/arch/interrupt.h @@ -23,9 +23,9 @@ /* setup interrupt handlers for mainboard */ #if CONFIG_PCI_OPTION_ROM_RUN_REALMODE -extern void mainboard_interrupt_handlers(int intXX, void *intXX_func); +extern void mainboard_interrupt_handlers(int intXX, int (*intXX_func)(void)); #elif CONFIG_PCI_OPTION_ROM_RUN_YABEL #include #else -static inline void mainboard_interrupt_handlers(int intXX, void *intXX_func) { } +static inline void mainboard_interrupt_handlers(int intXX, int (*intXX_func)(void)) { } #endif diff --git a/src/arch/x86/include/arch/ioapic.h b/src/arch/x86/include/arch/ioapic.h index b989e527b8..7ff47bb018 100644 --- a/src/arch/x86/include/arch/ioapic.h +++ b/src/arch/x86/include/arch/ioapic.h @@ -39,6 +39,8 @@ #define SMI (2 << 8) #define INT (1 << 8) +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); diff --git a/src/arch/x86/include/arch/smp/spinlock.h b/src/arch/x86/include/arch/smp/spinlock.h index 5c1dd94c36..32be2f25fb 100644 --- a/src/arch/x86/include/arch/smp/spinlock.h +++ b/src/arch/x86/include/arch/smp/spinlock.h @@ -1,6 +1,8 @@ #ifndef ARCH_SMP_SPINLOCK_H #define ARCH_SMP_SPINLOCK_H +#ifndef __PRE_RAM__ + /* * Your basic SMP spinlocks, allowing only a single CPU anywhere */ @@ -61,4 +63,16 @@ static inline __attribute__((always_inline)) void cpu_relax(void) __asm__ __volatile__("rep;nop": : :"memory"); } +#else /* !__PRE_RAM__ */ + +#define DECLARE_SPIN_LOCK(x) +#define barrier() do {} while(0) +#define spin_is_locked(lock) 0 +#define spin_unlock_wait(lock) do {} while(0) +#define spin_lock(lock) do {} while(0) +#define spin_unlock(lock) do {} while(0) +#define cpu_relax() do {} while(0) + +#endif /* !__PRE_RAM__ */ + #endif /* ARCH_SMP_SPINLOCK_H */ diff --git a/src/arch/x86/include/arch/stages.h b/src/arch/x86/include/arch/stages.h index 0d00144cba..91d0db6957 100644 --- a/src/arch/x86/include/arch/stages.h +++ b/src/arch/x86/include/arch/stages.h @@ -22,6 +22,14 @@ #include -void asmlinkage copy_and_run(unsigned cpu_reset); -void asmlinkage copy_and_run_ap_code_in_car(unsigned ret_addr); +void asmlinkage copy_and_run(void); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size); + +static inline void stage_exit(void *entry) +{ + __asm__ volatile ( + "jmp *%%edi\n" + :: "D"(entry) + ); +} #endif diff --git a/src/arch/x86/include/bootblock_common.h b/src/arch/x86/include/bootblock_common.h index 11fb230b58..4926086bce 100644 --- a/src/arch/x86/include/bootblock_common.h +++ b/src/arch/x86/include/bootblock_common.h @@ -65,6 +65,10 @@ static void cmos_post_init(void) /* Initialize to zero */ cmos_write(0, CMOS_POST_BANK_0_OFFSET); cmos_write(0, CMOS_POST_BANK_1_OFFSET); +#if CONFIG_CMOS_POST_EXTRA + cmos_write32(CMOS_POST_BANK_0_EXTRA, 0); + cmos_write32(CMOS_POST_BANK_1_EXTRA, 0); +#endif } cmos_write(magic, CMOS_POST_BANK_OFFSET); diff --git a/src/arch/x86/init/crt0_romcc_epilogue.inc b/src/arch/x86/init/crt0_romcc_epilogue.inc index b19f9687e9..419418d64e 100644 --- a/src/arch/x86/init/crt0_romcc_epilogue.inc +++ b/src/arch/x86/init/crt0_romcc_epilogue.inc @@ -7,17 +7,12 @@ */ #include - /* clear boot_complete flag */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* clear direction flag */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/arch/x86/init/ldscript_failover.lb b/src/arch/x86/init/failover.ld similarity index 100% rename from src/arch/x86/init/ldscript_failover.lb rename to src/arch/x86/init/failover.ld diff --git a/src/arch/x86/init/romstage.ld b/src/arch/x86/init/romstage.ld index 88c56573ae..3b5ccddb34 100644 --- a/src/arch/x86/init/romstage.ld +++ b/src/arch/x86/init/romstage.ld @@ -31,6 +31,10 @@ SECTIONS _rom = .; *(.rom.text); *(.rom.data); + . = ALIGN(4); + _cbmem_init_hooks = .; + KEEP(*(.rodata.cbmem_init_hooks)); + _ecbmem_init_hooks = .; *(.rodata); *(.rodata.*); *(.rom.data.*); @@ -38,6 +42,21 @@ SECTIONS _erom = .; } +#if !IS_ENABLED(CONFIG_CPU_AMD_AGESA) + /* Global variables are not allowed in romstage + * This section is checked during stage creation to ensure + * that there are no global variables present + */ + .illegal_globals . : { + *(.data) + *(.data.*) + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + } +#endif + /DISCARD/ : { *(.comment) *(.note) @@ -48,9 +67,22 @@ SECTIONS . = CONFIG_DCACHE_RAM_BASE; .car.data . (NOLOAD) : { + _car_data_start = .; *(.car.global_data); - *(.car.cbmem_console); +#if IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION) + _timestamp = .; + . = . + 0x180; + _etimestamp = .; +#endif + _car_data_end = .; + /* The preram cbmem console area comes last to take advantage + * of a zero-sized array to hold the memconsole contents. + * However, collisions within the cache-as-ram region cannot be + * statically checked because the cache-as-ram region usage is + * cpu/chipset dependent. */ + _preram_cbmem_console = .; + _epreram_cbmem_console = . + 0xc00; } - _bogus = ASSERT((SIZEOF(.car.data) <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full"); + _bogus = ASSERT((SIZEOF(.car.data) + 0xc00 <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full"); } diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc index 82f4e62d21..275be00dbf 100644 --- a/src/arch/x86/lib/Makefile.inc +++ b/src/arch/x86/lib/Makefile.inc @@ -1,26 +1,39 @@ -ramstage-y += c_start.S -ramstage-y += cpu.c -ramstage-y += pci_ops_conf1.c -ramstage-$(CONFIG_PCI_CONF2) += pci_ops_conf2.c -ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c -ramstage-y += exception.c -ramstage-$(CONFIG_IOAPIC) += ioapic.c -ramstage-y += memset.c -ramstage-y += memcpy.c -ramstage-y += ebda.c -ramstage-y += rom_media.c +ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y) romstage-$(CONFIG_EARLY_CONSOLE) += romstage_console.c romstage-y += cbfs_and_run.c romstage-y += memset.c romstage-y += memcpy.c +romstage-y += memmove.c romstage-y += rom_media.c +romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c + +endif + +ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) + +ramstage-y += c_start.S +ramstage-y += cpu.c +ramstage-y += pci_ops_conf1.c +ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c +ramstage-y += exception.c +ramstage-$(CONFIG_IOAPIC) += ioapic.c +ramstage-y += memset.c +ramstage-y += memcpy.c +ramstage-y += memmove.c +ramstage-y += ebda.c +ramstage-y += rom_media.c +ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c +ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S +ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c smm-y += memset.c smm-y += memcpy.c +smm-y += memmove.c smm-y += rom_media.c -rmodules-y += memset.c -rmodules-y += memcpy.c +rmodules_x86_32-y += memset.c +rmodules_x86_32-y += memcpy.c +rmodules_x86_32-y += memmove.c -$(obj)/arch/x86/lib/console.ramstage.o :: $(obj)/build.h +endif diff --git a/src/arch/x86/lib/c_start.S b/src/arch/x86/lib/c_start.S index 32af0ccdf9..8d25eb1669 100644 --- a/src/arch/x86/lib/c_start.S +++ b/src/arch/x86/lib/c_start.S @@ -10,10 +10,17 @@ _stack: .space CONFIG_MAX_CPUS*CONFIG_STACK_SIZE _estack: +#if CONFIG_COOP_MULTITASKING +.global thread_stacks +thread_stacks: +.space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS +#endif - .section ".textfirst", "ax", @progbits + .section ".text._start", "ax", @progbits .code32 .globl _start + .globl __rmodule_entry +__rmodule_entry: _start: cli lgdt %cs:gdtaddr @@ -45,16 +52,14 @@ _start: /* set new stack */ movl $_estack, %esp +#if CONFIG_COOP_MULTITASKING + /* Push the thread pointer. */ + pushl $0 +#endif /* Push the cpu index and struct cpu */ pushl $0 pushl $0 - /* push the boot_complete flag */ - pushl %ebp - - /* Save the stack location */ - movl %esp, %ebp - /* Initialize the Interrupt Descriptor table */ leal _idt, %edi leal vec0, %ebx @@ -80,14 +85,10 @@ _start: */ post_code(POST_PRE_HARDWAREMAIN) /* post fe */ - /* Restore the stack location */ - movl %ebp, %esp - #if CONFIG_GDB_WAIT call gdb_stub_breakpoint #endif - /* The boot_complete flag has already been pushed */ - call hardwaremain + call main /* NOTREACHED */ .Lhlt: post_code(POST_DEAD_CODE) /* post ee */ diff --git a/src/arch/x86/lib/cbfs_and_run.c b/src/arch/x86/lib/cbfs_and_run.c index a023141650..6173d03d58 100644 --- a/src/arch/x86/lib/cbfs_and_run.c +++ b/src/arch/x86/lib/cbfs_and_run.c @@ -22,7 +22,7 @@ #include #include -static void cbfs_and_run_core(const char *filename, unsigned ebp) +static void cbfs_and_run_core(const char *filename) { u8 *dst; @@ -34,25 +34,10 @@ static void cbfs_and_run_core(const char *filename, unsigned ebp) timestamp_add_now(TS_END_COPYRAM); print_debug("Jumping to image.\n"); - __asm__ volatile ( - "movl %%eax, %%ebp\n" - "jmp *%%edi\n" - :: "a"(ebp), "D"(dst) - ); + stage_exit(dst); } -void asmlinkage copy_and_run(unsigned cpu_reset) +void asmlinkage copy_and_run(void) { - // FIXME fix input parameters instead normalizing them here. - if (cpu_reset == 1) cpu_reset = -1; - else cpu_reset = 0; - - cbfs_and_run_core(CONFIG_CBFS_PREFIX "/coreboot_ram", cpu_reset); + cbfs_and_run_core(CONFIG_CBFS_PREFIX "/ramstage"); } - -#if CONFIG_AP_CODE_IN_CAR -void asmlinkage copy_and_run_ap_code_in_car(unsigned ret_addr) -{ - cbfs_and_run_core(CONFIG_CBFS_PREFIX "/coreboot_ap", ret_addr); -} -#endif diff --git a/src/arch/x86/lib/cpu.c b/src/arch/x86/lib/cpu.c index be8e38da13..44b32d5b15 100644 --- a/src/arch/x86/lib/cpu.c +++ b/src/arch/x86/lib/cpu.c @@ -254,6 +254,8 @@ void cpu_initialize(unsigned int index) die("CPU: missing cpu device structure"); } + post_log_path(cpu); + /* Find what type of cpu we are dealing with */ identify_cpu(cpu); printk(BIOS_DEBUG, "CPU: vendor %s device %x\n", @@ -283,6 +285,7 @@ void cpu_initialize(unsigned int index) cpu->initialized = 1; cpu->ops->init(cpu); } + post_log_clear(); printk(BIOS_INFO, "CPU #%d initialized\n", index); diff --git a/src/arch/x86/lib/id.inc b/src/arch/x86/lib/id.inc index f8aba0b946..7a2876c994 100644 --- a/src/arch/x86/lib/id.inc +++ b/src/arch/x86/lib/id.inc @@ -1,3 +1,4 @@ +#include .section ".id", "a", @progbits .globl __id_start diff --git a/src/arch/x86/lib/id.lds b/src/arch/x86/lib/id.ld similarity index 100% rename from src/arch/x86/lib/id.lds rename to src/arch/x86/lib/id.ld diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c index 389c48c111..4964af6757 100644 --- a/src/arch/x86/lib/ioapic.c +++ b/src/arch/x86/lib/ioapic.c @@ -22,13 +22,13 @@ #include #include -static u32 io_apic_read(u32 ioapic_base, u32 reg) +u32 io_apic_read(u32 ioapic_base, u32 reg) { write32(ioapic_base, reg); return read32(ioapic_base + 0x10); } -static void io_apic_write(u32 ioapic_base, u32 reg, u32 value) +void io_apic_write(u32 ioapic_base, u32 reg, u32 value) { write32(ioapic_base, reg); write32(ioapic_base + 0x10, value); diff --git a/src/arch/x86/lib/memmove.c b/src/arch/x86/lib/memmove.c new file mode 100644 index 0000000000..ba121278da --- /dev/null +++ b/src/arch/x86/lib/memmove.c @@ -0,0 +1,187 @@ +#include + +void *memmove(void *dest, const void *src, size_t n) +{ + int d0,d1,d2,d3,d4,d5; + char *ret = dest; + + __asm__ __volatile__( + /* Handle more 16bytes in loop */ + "cmp $0x10, %0\n\t" + "jb 1f\n\t" + + /* Decide forward/backward copy mode */ + "cmp %2, %1\n\t" + "jb 2f\n\t" + + /* + * movs instruction have many startup latency + * so we handle small size by general register. + */ + "cmp $680, %0\n\t" + "jb 3f\n\t" + /* + * movs instruction is only good for aligned case. + */ + "mov %1, %3\n\t" + "xor %2, %3\n\t" + "and $0xff, %3\n\t" + "jz 4f\n\t" + "3:\n\t" + "sub $0x10, %0\n\t" + + /* + * We gobble 16byts forward in each loop. + */ + "3:\n\t" + "sub $0x10, %0\n\t" + "mov 0*4(%1), %3\n\t" + "mov 1*4(%1), %4\n\t" + "mov %3, 0*4(%2)\n\t" + "mov %4, 1*4(%2)\n\t" + "mov 2*4(%1), %3\n\t" + "mov 3*4(%1), %4\n\t" + "mov %3, 2*4(%2)\n\t" + "mov %4, 3*4(%2)\n\t" + "lea 0x10(%1), %1\n\t" + "lea 0x10(%2), %2\n\t" + "jae 3b\n\t" + "add $0x10, %0\n\t" + "jmp 1f\n\t" + + /* + * Handle data forward by movs. + */ + ".p2align 4\n\t" + "4:\n\t" + "mov -4(%1, %0), %3\n\t" + "lea -4(%2, %0), %4\n\t" + "shr $2, %0\n\t" + "rep movsl\n\t" + "mov %3, (%4)\n\t" + "jmp 11f\n\t" + /* + * Handle data backward by movs. + */ + ".p2align 4\n\t" + "6:\n\t" + "mov (%1), %3\n\t" + "mov %2, %4\n\t" + "lea -4(%1, %0), %1\n\t" + "lea -4(%2, %0), %2\n\t" + "shr $2, %0\n\t" + "std\n\t" + "rep movsl\n\t" + "mov %3,(%4)\n\t" + "cld\n\t" + "jmp 11f\n\t" + + /* + * Start to prepare for backward copy. + */ + ".p2align 4\n\t" + "2:\n\t" + "cmp $680, %0\n\t" + "jb 5f\n\t" + "mov %1, %3\n\t" + "xor %2, %3\n\t" + "and $0xff, %3\n\t" + "jz 6b\n\t" + + /* + * Calculate copy position to tail. + */ + "5:\n\t" + "add %0, %1\n\t" + "add %0, %2\n\t" + "sub $0x10, %0\n\t" + + /* + * We gobble 16byts backward in each loop. + */ + "7:\n\t" + "sub $0x10, %0\n\t" + + "mov -1*4(%1), %3\n\t" + "mov -2*4(%1), %4\n\t" + "mov %3, -1*4(%2)\n\t" + "mov %4, -2*4(%2)\n\t" + "mov -3*4(%1), %3\n\t" + "mov -4*4(%1), %4\n\t" + "mov %3, -3*4(%2)\n\t" + "mov %4, -4*4(%2)\n\t" + "lea -0x10(%1), %1\n\t" + "lea -0x10(%2), %2\n\t" + "jae 7b\n\t" + /* + * Calculate copy position to head. + */ + "add $0x10, %0\n\t" + "sub %0, %1\n\t" + "sub %0, %2\n\t" + + /* + * Move data from 8 bytes to 15 bytes. + */ + ".p2align 4\n\t" + "1:\n\t" + "cmp $8, %0\n\t" + "jb 8f\n\t" + "mov 0*4(%1), %3\n\t" + "mov 1*4(%1), %4\n\t" + "mov -2*4(%1, %0), %5\n\t" + "mov -1*4(%1, %0), %1\n\t" + + "mov %3, 0*4(%2)\n\t" + "mov %4, 1*4(%2)\n\t" + "mov %5, -2*4(%2, %0)\n\t" + "mov %1, -1*4(%2, %0)\n\t" + "jmp 11f\n\t" + + /* + * Move data from 4 bytes to 7 bytes. + */ + ".p2align 4\n\t" + "8:\n\t" + "cmp $4, %0\n\t" + "jb 9f\n\t" + "mov 0*4(%1), %3\n\t" + "mov -1*4(%1, %0), %4\n\t" + "mov %3, 0*4(%2)\n\t" + "mov %4, -1*4(%2, %0)\n\t" + "jmp 11f\n\t" + + /* + * Move data from 2 bytes to 3 bytes. + */ + ".p2align 4\n\t" + "9:\n\t" + "cmp $2, %0\n\t" + "jb 10f\n\t" + "movw 0*2(%1), %%dx\n\t" + "movw -1*2(%1, %0), %%bx\n\t" + "movw %%dx, 0*2(%2)\n\t" + "movw %%bx, -1*2(%2, %0)\n\t" + "jmp 11f\n\t" + + /* + * Move data for 1 byte. + */ + ".p2align 4\n\t" + "10:\n\t" + "cmp $1, %0\n\t" + "jb 11f\n\t" + "movb (%1), %%cl\n\t" + "movb %%cl, (%2)\n\t" + ".p2align 4\n\t" + "11:" + : "=&c" (d0), "=&S" (d1), "=&D" (d2), + "=r" (d3),"=r" (d4), "=r"(d5) + :"0" (n), + "1" (src), + "2" (dest) + :"memory"); + + return ret; + +} diff --git a/src/arch/x86/lib/romstage_console.c b/src/arch/x86/lib/romstage_console.c index f53f5a9d75..a3e8be82ae 100644 --- a/src/arch/x86/lib/romstage_console.c +++ b/src/arch/x86/lib/romstage_console.c @@ -69,21 +69,3 @@ void console_tx_flush(void) usbdebug_tx_flush(0); #endif } - -int do_printk(int msg_level, const char *fmt, ...) -{ - va_list args; - int i; - - if (msg_level > console_loglevel) { - return 0; - } - - va_start(args, fmt); - i = vtxprintf(console_tx_byte, fmt, args); - va_end(args); - - console_tx_flush(); - - return i; -} diff --git a/src/arch/x86/lib/stages.c b/src/arch/x86/lib/stages.c index a6a232a04a..2da66d368d 100644 --- a/src/arch/x86/lib/stages.c +++ b/src/arch/x86/lib/stages.c @@ -20,8 +20,6 @@ static void skip_romstage(void) { asm volatile ( - "/* set the boot_complete flag */\n" - "movl $0xffffffff, %%ebp\n" "jmp __main\n" ); } diff --git a/src/arch/x86/lib/thread.c b/src/arch/x86/lib/thread.c new file mode 100644 index 0000000000..b1549b5e32 --- /dev/null +++ b/src/arch/x86/lib/thread.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +/* The stack frame looks like the following after a pushad instruction. */ +struct pushad_regs { + uint32_t edi; /* Offset 0x00 */ + uint32_t esi; /* Offset 0x04 */ + uint32_t ebp; /* Offset 0x08 */ + uint32_t esp; /* Offset 0x0c */ + uint32_t ebx; /* Offset 0x10 */ + uint32_t edx; /* Offset 0x14 */ + uint32_t ecx; /* Offset 0x18 */ + uint32_t eax; /* Offset 0x1c */ +}; + +static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value) +{ + uintptr_t *addr; + + cur_stack -= sizeof(value); + addr = (uintptr_t *)cur_stack; + *addr = value; + return cur_stack; +} + +void arch_prepare_thread(struct thread *t, + void asmlinkage (*thread_entry)(void *), void *arg) +{ + uintptr_t stack = t->stack_current; + + /* Imitate thread_entry(t) with return address of 0. thread_entry() + * is assumed to never return. */ + stack = push_stack(stack, (uintptr_t)arg); + stack = push_stack(stack, (uintptr_t)0); + stack = push_stack(stack, (uintptr_t)thread_entry); + /* Make room for the registers. Ignore intial values. */ + stack -= sizeof(struct pushad_regs); + + t->stack_current = stack; +} + +void *arch_get_thread_stackbase(void) +{ + /* defined in c_start.S */ + extern u8 thread_stacks[]; + return &thread_stacks[0]; +} diff --git a/src/arch/x86/lib/thread_switch.S b/src/arch/x86/lib/thread_switch.S new file mode 100644 index 0000000000..8de1948d46 --- /dev/null +++ b/src/arch/x86/lib/thread_switch.S @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +.code32 +.text + +/* + * stack layout after pushad: + * +------------+ + * | save stack | <-- esp + 0x28 + * +------------+ + * | new stack | <-- esp + 0x24 + * +------------+ + * | ret addr | <-- esp + 0x20 + * +------------+ + * | eax | <-- esp + 0x1c + * +------------+ + * | ecx | <-- esp + 0x18 + * +------------+ + * | edx | <-- esp + 0x14 + * +------------+ + * | ebx | <-- esp + 0x10 + * +------------+ + * | orig esp | <-- esp + 0x0c + * +------------+ + * | ebp | <-- esp + 0x08 + * +------------+ + * | esi | <-- esp + 0x04 + * +------------+ + * | edi | <-- esp + 0x00 + * +------------+ + */ +.globl switch_to_thread +switch_to_thread: + pusha + /* Save the current stack */ + movl 0x28(%esp), %ebx + movl %esp, (%ebx) + /* Switch to the new stack. */ + movl 0x24(%esp), %eax + movl %eax, %esp + popa + ret diff --git a/src/cpu/x86/smm/smm_module_header.c b/src/arch/x86/lib/timestamp.c similarity index 74% rename from src/cpu/x86/smm/smm_module_header.c rename to src/arch/x86/lib/timestamp.c index 3ee654f6cd..02582a5c3b 100644 --- a/src/cpu/x86/smm/smm_module_header.c +++ b/src/arch/x86/lib/timestamp.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 ChromeOS Authors + * Copyright 2013 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,11 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -#include +#include +#include -extern char smm_handler_start[]; +uint64_t timestamp_get(void) +{ + return rdtscll(); +} -DEFINE_RMODULE_HEADER(smm_module, smm_handler_start, RMODULE_TYPE_SMM); diff --git a/src/arch/x86/ramstage.ld b/src/arch/x86/ramstage.ld new file mode 100644 index 0000000000..3b448d1812 --- /dev/null +++ b/src/arch/x86/ramstage.ld @@ -0,0 +1,26 @@ +/* + * Memory map: + * + * CONFIG_RAMBASE : text segment + * : rodata segment + * : data segment + * : bss segment + * : stack + * : heap + */ + +ENTRY(_start) + +PHDRS +{ + to_load PT_LOAD; +} + +SECTIONS +{ + . = CONFIG_RAMBASE; + + INCLUDE "lib/ramstage.ramstage.ld" + + _ = ASSERT( ( _eprogram < (CONFIG_RAMTOP)) , "Please increase CONFIG_RAMTOP"); +} diff --git a/src/console/Kconfig b/src/console/Kconfig index d2cff572aa..03a79a0e6b 100644 --- a/src/console/Kconfig +++ b/src/console/Kconfig @@ -1,12 +1,15 @@ menu "Console" -config DEFAULT_EARLY_CONSOLE - bool +config BOOTBLOCK_CONSOLE + bool "Enable early (bootblock) console output." + depends on ARCH_ARM || ARCH_MIPS default n + help + Use console during the bootblock if supported config EARLY_CONSOLE bool "Enable early (pre-RAM) console output." - default DEFAULT_EARLY_CONSOLE + default n help Use console during early (pre-RAM) boot stages @@ -25,6 +28,23 @@ config CONSOLE_SERIAL8250 help Send coreboot debug output to an I/O mapped serial port console. +config CONSOLE_SERIAL_IPQ806X + bool "Serial port console output for Qualcomm SGMI port" + depends on CONSOLE_SERIAL + depends on SOC_QC_IPQ806X + default y + help + Send coreboot debug output to an SGMI based uart (ipq806x) + +config CONSOLE_SERIAL_BG4CD + bool "Serial port console output for Marvell BG4CD" + depends on CONSOLE_SERIAL + depends on SOC_MARVELL_BG4CD + default y + help + Enable use of Marvell BG4CD based uart for coreboot serial console + output. + config CONSOLE_SERIAL8250MEM bool "Serial port console output (memory mapped, 8250-compatible)" depends on CONSOLE_SERIAL @@ -66,7 +86,7 @@ endchoice config TTYS0_BASE hex - depends on CONSOLE_SERIAL8250 + depends on CONSOLE_SERIAL default 0x3f8 if CONSOLE_SERIAL_COM1 default 0x2f8 if CONSOLE_SERIAL_COM2 default 0x3e8 if CONSOLE_SERIAL_COM3 @@ -219,13 +239,18 @@ config CONSOLE_NE2K_IO_PORT boundary, qemu needs broader align) config CONSOLE_CBMEM - depends on (EARLY_CBMEM_INIT || DYNAMIC_CBMEM) + depends on EARLY_CBMEM_INIT || DYNAMIC_CBMEM bool "Send console output to a CBMEM buffer" default n help Enable this to save the console output in a CBMEM buffer. This would allow to see coreboot console output from Linux space. +config CONSOLE_FIXED_PRERAM_CBMEM_BUFFER + default n if ARCH_X86 + default y if !ARCH_X86 + bool "Assume the preram CBMEM console buffer is in a fixed location" + config CONSOLE_CBMEM_BUFFER_SIZE depends on CONSOLE_CBMEM hex "Room allocated for console output in CBMEM" @@ -235,16 +260,6 @@ config CONSOLE_CBMEM_BUFFER_SIZE value (64K or 0x10000 bytes) is large enough to accommodate even the BIOS_SPEW level. -config CONSOLE_CAR_BUFFER_SIZE - depends on CONSOLE_CBMEM - hex "Room allocated for console output in Cache as RAM" - default 0xc00 - help - Console is used before RAM is initialized. This is the room reserved - in the DCACHE based RAM to keep console output before it can be - saved in a CBMEM buffer. 3K bytes should be enough even for the - BIOS_SPEW level. - choice prompt "Maximum console log level" @@ -380,10 +395,6 @@ config DEFAULT_CONSOLE_LOGLEVEL help Map the log level config names to an integer. -config CONSOLE_LOGBUF - bool - default n - config NO_POST bool "Don't show any POST codes" default n @@ -416,6 +427,14 @@ config CMOS_POST_OFFSET If CONFIG_HAVE_OPTION_TABLE is enabled then it will use the value defined in the mainboard option table. +config CMOS_POST_EXTRA + bool "Store extra logging info into CMOS" + depends on CMOS_POST + default n + help + This will enable extra logging of work that happens between post + codes into CMOS for debug. This uses an additional 8 bytes of CMOS. + config IO_POST bool "Send POST codes to an IO port" depends on PC80_SYSTEM diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc index 40bf357abf..7db26637a8 100644 --- a/src/console/Makefile.inc +++ b/src/console/Makefile.inc @@ -9,23 +9,28 @@ smm-y += printk.c smm-y += vtxprintf.c smm-$(CONFIG_SMM_TSEG) += die.c -romstage-$(CONFIG_EARLY_CONSOLE) += vtxprintf.c +verstage-$(CONFIG_EARLY_CONSOLE) += vtxprintf.c early_console.c +verstage-y += console.c +verstage-y += die.c + +romstage-$(CONFIG_EARLY_CONSOLE) += vtxprintf.c early_console.c romstage-y += console.c romstage-y += post.c romstage-y += die.c -bootblock-$(CONFIG_EARLY_CONSOLE) += vtxprintf.c -bootblock-y += console.c -bootblock-y += die.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += vtxprintf.c early_console.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += console.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += die.c ramstage-$(CONFIG_CONSOLE_SERIAL8250) += uart8250_console.c ramstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem_console.c ramstage-$(CONFIG_USBDEBUG) += usbdebug_console.c -ramstage-$(CONFIG_CONSOLE_LOGBUF) += logbuf_console.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k_console.c ramstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c +ramstage-$(CONFIG_CONSOLE_SERIAL_IPQ806X) += uart_wrapper.c +ramstage-$(CONFIG_CONSOLE_SERIAL_BG4CD) += uart_wrapper.c - -$(obj)/console/console.ramstage.o : $(obj)/build.h -$(obj)/console/console.romstage.o : $(obj)/build.h -$(obj)/console/console.bootblock.o : $(obj)/build.h +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += vtxprintf.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += console.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += die.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += printk.c diff --git a/src/console/console.c b/src/console/console.c index afbba9dd4f..ba46713cbc 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -101,7 +101,8 @@ int console_tst_byte(void) void console_init(void) { -#if CONFIG_EARLY_CONSOLE +#if defined(__BOOTBLOCK__) && CONFIG_BOOTBLOCK_CONSOLE || \ + !defined(__BOOTBLOCK__) && CONFIG_EARLY_CONSOLE #if CONFIG_USBDEBUG enable_usbdebug(CONFIG_USBDEBUG_DEFAULT_PORT); @@ -123,7 +124,13 @@ void console_init(void) "\n\ncoreboot-" COREBOOT_VERSION COREBOOT_EXTRA_VERSION - " " +#if defined(__BOOTBLOCK__) + " bootblock " +#elif defined(__VERSTAGE__) + " verstage " +#else + " romstage " +#endif COREBOOT_BUILD " starting...\n"; print_info(console_test); diff --git a/src/console/early_console.c b/src/console/early_console.c new file mode 100644 index 0000000000..db46a4c644 --- /dev/null +++ b/src/console/early_console.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +int vprintk(int msg_level, const char *fmt, va_list args) +{ + int i; + + if (msg_level > console_loglevel) + return 0; + + i = vtxprintf(console_tx_byte, fmt, args); + + console_tx_flush(); + + return i; +} + +int do_printk(int msg_level, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vprintk(msg_level, fmt, args); + va_end(args); + + return i; +} diff --git a/src/console/logbuf_console.c b/src/console/logbuf_console.c deleted file mode 100644 index a76791d542..0000000000 --- a/src/console/logbuf_console.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#define LOGBUF_SIZE 1024 - -// KEEP THIS GLOBAL. -// I need the address so I can watch it with the ARIUM hardware. RGM. -char logbuf[LOGBUF_SIZE]; -int logbuf_offset = 0; - -static void logbuf_tx_byte(unsigned char byte) -{ - logbuf[logbuf_offset] = byte; - logbuf_offset = (logbuf_offset +1) % LOGBUF_SIZE; -} - -static const struct console_driver __console = { - .init = 0, - .tx_byte = logbuf_tx_byte, - .rx_byte = 0, - .tst_byte = 0, -};} diff --git a/src/console/post.c b/src/console/post.c index f55683e4d1..35cc0e85e1 100644 --- a/src/console/post.c +++ b/src/console/post.c @@ -23,6 +23,10 @@ #include #if CONFIG_CMOS_POST #include +#include +#endif +#if CONFIG_CMOS_POST_EXTRA +#include #endif #include @@ -44,23 +48,36 @@ void __attribute__((weak)) mainboard_post(uint8_t value) #if CONFIG_CMOS_POST +DECLARE_SPIN_LOCK(cmos_post_lock) + #if !defined(__PRE_RAM__) void cmos_post_log(void) { - u8 code; + u8 code = 0; +#if CONFIG_CMOS_POST_EXTRA + u32 extra = 0; +#endif + + spin_lock(&cmos_post_lock); /* Get post code from other bank */ switch (cmos_read(CMOS_POST_BANK_OFFSET)) { case CMOS_POST_BANK_0_MAGIC: code = cmos_read(CMOS_POST_BANK_1_OFFSET); +#if CONFIG_CMOS_POST_EXTRA + extra = cmos_read32(CMOS_POST_BANK_1_EXTRA); +#endif break; case CMOS_POST_BANK_1_MAGIC: code = cmos_read(CMOS_POST_BANK_0_OFFSET); +#if CONFIG_CMOS_POST_EXTRA + extra = cmos_read32(CMOS_POST_BANK_0_EXTRA); +#endif break; - default: - return; } + spin_unlock(&cmos_post_lock); + /* Check last post code in previous boot against normal list */ switch (code) { case POST_OS_BOOT: @@ -73,13 +90,53 @@ void cmos_post_log(void) "in previous boot: 0x%02x\n", code); #if CONFIG_ELOG elog_add_event_word(ELOG_TYPE_LAST_POST_CODE, code); +#if CONFIG_CMOS_POST_EXTRA + if (extra) + elog_add_event_dword(ELOG_TYPE_POST_EXTRA, extra); +#endif #endif } } + +#if CONFIG_CMOS_POST_EXTRA +void post_log_extra(u32 value) +{ + spin_lock(&cmos_post_lock); + + switch (cmos_read(CMOS_POST_BANK_OFFSET)) { + case CMOS_POST_BANK_0_MAGIC: + cmos_write32(CMOS_POST_BANK_0_EXTRA, value); + break; + case CMOS_POST_BANK_1_MAGIC: + cmos_write32(CMOS_POST_BANK_1_EXTRA, value); + break; + } + + spin_unlock(&cmos_post_lock); +} + +void post_log_path(struct device *dev) +{ + if (dev) { + /* Encode path into lower 3 bytes */ + u32 path = dev_path_encode(dev); + /* Upper byte contains the log type */ + path |= CMOS_POST_EXTRA_DEV_PATH << 24; + post_log_extra(path); + } +} + +void post_log_clear(void) +{ + post_log_extra(0); +} +#endif /* CONFIG_CMOS_POST_EXTRA */ #endif /* !__PRE_RAM__ */ static void cmos_post_code(u8 value) { + spin_lock(&cmos_post_lock); + switch (cmos_read(CMOS_POST_BANK_OFFSET)) { case CMOS_POST_BANK_0_MAGIC: cmos_write(value, CMOS_POST_BANK_0_OFFSET); @@ -88,6 +145,8 @@ static void cmos_post_code(u8 value) cmos_write(value, CMOS_POST_BANK_1_OFFSET); break; } + + spin_unlock(&cmos_post_lock); } #endif /* CONFIG_CMOS_POST */ diff --git a/src/console/printk.c b/src/console/printk.c index 75490881f6..a8998eef82 100644 --- a/src/console/printk.c +++ b/src/console/printk.c @@ -15,21 +15,17 @@ int default_console_loglevel = CONFIG_DEFAULT_CONSOLE_LOGLEVEL; DECLARE_SPIN_LOCK(console_lock) -int do_printk(int msg_level, const char *fmt, ...) +int vprintk(int msg_level, const char *fmt, va_list args) { - va_list args; int i; - if (msg_level > console_loglevel) { + if (msg_level > console_loglevel) return 0; - } DISABLE_TRACE; spin_lock(&console_lock); - va_start(args, fmt); i = vtxprintf(console_tx_byte, fmt, args); - va_end(args); console_tx_flush(); @@ -38,3 +34,15 @@ int do_printk(int msg_level, const char *fmt, ...) return i; } + +int do_printk(int msg_level, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vprintk(msg_level, fmt, args); + va_end(args); + + return i; +} diff --git a/src/console/uart_wrapper.c b/src/console/uart_wrapper.c new file mode 100644 index 0000000000..c7575205d5 --- /dev/null +++ b/src/console/uart_wrapper.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +static const struct console_driver uart_console __console = { + .init = uart_init, + .tx_byte = uart_tx_byte, + .tx_flush = uart_tx_flush, + .rx_byte = uart_rx_byte, + .tst_byte = uart_can_rx_byte, +}; diff --git a/src/console/vtxprintf.c b/src/console/vtxprintf.c index 4fc6f35bd1..7e6f4d295d 100644 --- a/src/console/vtxprintf.c +++ b/src/console/vtxprintf.c @@ -8,6 +8,10 @@ #include #include +#if !CONFIG_ARCH_MIPS +#define SUPPORT_64BIT_INTS +#endif + /* haha, don't need ctype.c */ #define isdigit(c) ((c) >= '0' && (c) <= '9') #define is_digit isdigit @@ -31,12 +35,24 @@ static int skip_atoi(const char **s) #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ static int number(void (*tx_byte)(unsigned char byte), - unsigned long long num, int base, int size, int precision, int type) + unsigned long long inum, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; int i; int count = 0; +#ifdef SUPPORT_64BIT_INTS + unsigned long long num = inum; +#else + unsigned long num = (long)inum; + + if (num != inum) { + /* Alert user to an incorrect result. */ + tx_byte('#'); + tx_byte('^'); + tx_byte('!'); + } +#endif if (type & LARGE) digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig index ed7d6ab3ac..76bbbea9ae 100644 --- a/src/cpu/Kconfig +++ b/src/cpu/Kconfig @@ -1,23 +1,19 @@ # Warning: This file is included whether or not the if is here. # The if controls how the evaluation occurs. # (See also src/Kconfig) -if ARCH_ARMV7 source src/cpu/armltd/Kconfig -source src/cpu/samsung/Kconfig - -endif # ARCH_ARM - -if ARCH_X86 - source src/cpu/amd/Kconfig source src/cpu/intel/Kconfig +source src/cpu/mips/Kconfig source src/cpu/via/Kconfig source src/cpu/x86/Kconfig +if ARCH_X86 + config CACHE_AS_RAM bool - select DEFAULT_EARLY_CONSOLE + select EARLY_CONSOLE default !ROMCC config DCACHE_RAM_BASE @@ -150,6 +146,14 @@ config CPU_MICROCODE_CBFS_NONE endchoice +config CAR_MIGRATION + def_bool n + depends on DYNAMIC_CBMEM || EARLY_CBMEM_INIT + help + Migrate the cache-as-ram variables to CBMEM once CBMEM is set up + in romstage. This option is only needed if one will be doing more + work in romstage after the cache-as-ram is torn down aside from + loading ramstage. config CPU_MICROCODE_FILE string "Path and filename of CPU microcode" depends on CPU_MICROCODE_CBFS_EXTERNAL diff --git a/src/cpu/Makefile.inc b/src/cpu/Makefile.inc index b48a803795..b11216a63f 100644 --- a/src/cpu/Makefile.inc +++ b/src/cpu/Makefile.inc @@ -3,25 +3,27 @@ ################################################################################ subdirs-y += amd subdirs-y += armltd +subdirs-y += imgtec subdirs-y += intel -subdirs-y += samsung subdirs-y += via +subdirs-y += x86 +$(eval $(call create_class_compiler,cpu_microcode,x86_32)) ################################################################################ ## Rules for building the microcode blob in CBFS ################################################################################ +cpu_ucode_cbfs_name = cpu_microcode_blob.bin + # External microcode file, or are we generating one ? ifeq ($(CONFIG_CPU_MICROCODE_CBFS_EXTERNAL), y) -cbfs-files-y += cpu_microcode_blob.bin -cpu_microcode_blob.bin-type = 0x53 -cpu_microcode_blob.bin-file = $(call strip_quotes,$(CONFIG_CPU_MICROCODE_FILE)) +cpu_ucode_cbfs_file = $(call strip_quotes,$(CONFIG_CPU_MICROCODE_FILE)) +cbfs_include_ucode = y endif ifeq ($(CONFIG_CPU_MICROCODE_CBFS_GENERATE), y) -cbfs-files-y += cpu_microcode_blob.bin -cpu_microcode_blob.bin-type = 0x53 -cpu_microcode_blob.bin-file = $(obj)/cpu_microcode_blob.bin +cpu_ucode_cbfs_file = $(obj)/cpu_microcode_blob.bin +cbfs_include_ucode = y endif # In case we have more than one "source" (cough) files containing microcode, we @@ -31,10 +33,18 @@ endif # final microcode file. $(obj)/cpu_microcode_blob.o: $$(cpu_microcode-objs) @printf " LD $(subst $(obj)/,,$(@))\n" - $(LD) -static --entry=0 $< -o $@ + $(LD_cpu_microcode) -static --entry=0 $< -o $@ # We have a lot of useless data in the large blob, and we are only interested in # the data section, so we only copy that part to the final microcode file $(obj)/cpu_microcode_blob.bin: $(obj)/cpu_microcode_blob.o @printf " MICROCODE $(subst $(obj)/,,$(@))\n" - $(OBJCOPY) -j .data -O binary $< $@ + $(OBJCOPY_cpu_microcode) -j .data -O binary $< $@ + +ifeq ($(cbfs_include_ucode),y) +# Add CPU microcode to specified rom image $(1) +add-cpu-microcode-to-cbfs = \ + $(CBFSTOOL) $(1) locate -f $(cpu_ucode_cbfs_file) -n $(cpu_ucode_cbfs_name) -a 16 | xargs $(CBFSTOOL) $(1) add -n $(cpu_ucode_cbfs_name) -f $(cpu_ucode_cbfs_file) -t 0x53 -b +else +add-cpu-microcode-to-cbfs = true +endif diff --git a/src/cpu/amd/agesa/Kconfig b/src/cpu/amd/agesa/Kconfig index 7b2f2eb903..b09f6b1c2e 100644 --- a/src/cpu/amd/agesa/Kconfig +++ b/src/cpu/amd/agesa/Kconfig @@ -25,6 +25,9 @@ config CPU_AMD_AGESA default y if CPU_AMD_AGESA_FAMILY15 default y if CPU_AMD_AGESA_FAMILY15_TN default n + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select TSC_SYNC_LFENCE select UDELAY_LAPIC diff --git a/src/cpu/amd/agesa/family10/Kconfig b/src/cpu/amd/agesa/family10/Kconfig index 621ee5813e..97802c7e78 100755 --- a/src/cpu/amd/agesa/family10/Kconfig +++ b/src/cpu/amd/agesa/family10/Kconfig @@ -45,10 +45,6 @@ config XIP_ROM_SIZE hex default 0x80000 -config HAVE_INIT_TIMER - bool - default y - config REDIRECT_IDS_HDT_CONSOLE_TO_SERIAL bool "Redirect AGESA IDS_HDT_CONSOLE to serial console" default n diff --git a/src/cpu/amd/agesa/family12/Kconfig b/src/cpu/amd/agesa/family12/Kconfig index 1adf5eca31..e52d8ee2dd 100755 --- a/src/cpu/amd/agesa/family12/Kconfig +++ b/src/cpu/amd/agesa/family12/Kconfig @@ -63,8 +63,4 @@ config XIP_ROM_SIZE default 0x80000 depends on CPU_AMD_AGESA_FAMILY12 -config HAVE_INIT_TIMER - bool - default y - depends on CPU_AMD_AGESA_FAMILY12 diff --git a/src/cpu/amd/agesa/family14/Kconfig b/src/cpu/amd/agesa/family14/Kconfig index dea839ea51..e45a1229d8 100644 --- a/src/cpu/amd/agesa/family14/Kconfig +++ b/src/cpu/amd/agesa/family14/Kconfig @@ -63,11 +63,6 @@ config XIP_ROM_SIZE default 0x80000 depends on CPU_AMD_AGESA_FAMILY14 -config HAVE_INIT_TIMER - bool - default y - depends on CPU_AMD_AGESA_FAMILY14 - config HIGH_SCRATCH_MEMORY_SIZE hex # Assume the maximum size of stack as (0xA0000 - 0x30000 + 0x1000) diff --git a/src/cpu/amd/agesa/family14/acpi/cpu.asl b/src/cpu/amd/agesa/family14/acpi/cpu.asl new file mode 100644 index 0000000000..79a3c8353e --- /dev/null +++ b/src/cpu/amd/agesa/family14/acpi/cpu.asl @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Processor Object + * + */ +Scope (\_PR) { /* define processor scope */ + Processor( + C000, /* name space name, align with BLDCFG_PROCESSOR_SCOPE_NAME[01] */ + 0, /* Unique number for this processor */ + 0x810, /* PBLK system I/O address !hardcoded! */ + 0x06 /* PBLKLEN for boot processor */ + ) { + } + + Processor( + C001, /* name space name */ + 1, /* Unique number for this processor */ + 0x810, /* PBLK system I/O address !hardcoded! */ + 0x06 /* PBLKLEN for boot processor */ + ) { + } +} /* End _PR scope */ + diff --git a/src/cpu/amd/agesa/family15/Kconfig b/src/cpu/amd/agesa/family15/Kconfig index e20cce8ab3..a0c1621b9a 100644 --- a/src/cpu/amd/agesa/family15/Kconfig +++ b/src/cpu/amd/agesa/family15/Kconfig @@ -67,10 +67,6 @@ config XIP_ROM_SIZE hex default 0x80000 -config HAVE_INIT_TIMER - bool - default y - config REDIRECT_IDS_HDT_CONSOLE_TO_SERIAL bool "Redirect AGESA IDS_HDT_CONSOLE to serial console" default n diff --git a/src/cpu/amd/agesa/family15tn/Kconfig b/src/cpu/amd/agesa/family15tn/Kconfig index d2f5a8c1b2..afe82403ff 100644 --- a/src/cpu/amd/agesa/family15tn/Kconfig +++ b/src/cpu/amd/agesa/family15tn/Kconfig @@ -68,11 +68,6 @@ config XIP_ROM_SIZE default 0x100000 depends on CPU_AMD_AGESA_FAMILY15_TN -config HAVE_INIT_TIMER - bool - default y - depends on CPU_AMD_AGESA_FAMILY15_TN - config HIGH_SCRATCH_MEMORY_SIZE hex # Assume the maximum size of stack as (0xA0000 - 0x30000 + 0x1000) diff --git a/src/cpu/amd/agesa/s3_resume.c b/src/cpu/amd/agesa/s3_resume.c index ada4d3ca72..4c70d38b75 100644 --- a/src/cpu/amd/agesa/s3_resume.c +++ b/src/cpu/amd/agesa/s3_resume.c @@ -157,7 +157,7 @@ void OemAgesaSaveMtrr(void) spi_init(); - flash = spi_flash_probe(0, 0, 0, 0); + flash = spi_flash_probe(0, 0); if (!flash) { printk(BIOS_DEBUG, "Could not find SPI device\n"); return; @@ -272,7 +272,7 @@ u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data) } spi_init(); - flash = spi_flash_probe(0, 0, 0, 0); + flash = spi_flash_probe(0, 0); if (!flash) { printk(BIOS_DEBUG, "Could not find SPI device\n"); /* Dont make flow stop. */ diff --git a/src/cpu/amd/car/disable_cache_as_ram.c b/src/cpu/amd/car/disable_cache_as_ram.c index 24533c7eb9..7776ae7224 100644 --- a/src/cpu/amd/car/disable_cache_as_ram.c +++ b/src/cpu/amd/car/disable_cache_as_ram.c @@ -36,7 +36,7 @@ static inline __attribute__((always_inline)) void disable_cache_as_ram(void) #if CONFIG_DCACHE_RAM_SIZE > 0x8000 wrmsr(MTRRfix4K_C0000_MSR, msr); #endif - /* disable fixed mtrr from now on, it will be enabled by coreboot_ram again*/ + /* disable fixed mtrr from now on, it will be enabled by ramstage again*/ msr = rdmsr(SYSCFG_MSR); msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn); diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c index 861948ff57..eae1933878 100644 --- a/src/cpu/amd/car/post_cache_as_ram.c +++ b/src/cpu/amd/car/post_cache_as_ram.c @@ -164,8 +164,8 @@ static void post_cache_as_ram(void) set_sysinfo_in_ram(1); // So other core0 could start to train mem - /*copy and execute coreboot_ram */ - copy_and_run(0); + /*copy and execute ramstage */ + copy_and_run(); /* We will not return */ print_debug("should not be here -\n"); diff --git a/src/cpu/amd/geode_gx1/Kconfig b/src/cpu/amd/geode_gx1/Kconfig index fa1d052a09..e1444e18ab 100644 --- a/src/cpu/amd/geode_gx1/Kconfig +++ b/src/cpu/amd/geode_gx1/Kconfig @@ -19,6 +19,9 @@ config CPU_AMD_GEODE_GX1 bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 if CPU_AMD_GEODE_GX1 diff --git a/src/cpu/amd/geode_gx2/Kconfig b/src/cpu/amd/geode_gx2/Kconfig index fe5a291066..baa1a7ce90 100644 --- a/src/cpu/amd/geode_gx2/Kconfig +++ b/src/cpu/amd/geode_gx2/Kconfig @@ -19,6 +19,9 @@ config CPU_AMD_GEODE_GX2 bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 if CPU_AMD_GEODE_GX2 diff --git a/src/cpu/amd/geode_gx2/cache_as_ram.inc b/src/cpu/amd/geode_gx2/cache_as_ram.inc index 941d507f9c..6a107fe5f1 100644 --- a/src/cpu/amd/geode_gx2/cache_as_ram.inc +++ b/src/cpu/amd/geode_gx2/cache_as_ram.inc @@ -182,8 +182,6 @@ done_cache_as_ram_main: xorl $(CR0_CD + CR0_NW), %eax /* clear the CD and NW bits */ movl %eax, %cr0 - /* clear boot_complete flag */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) @@ -197,8 +195,6 @@ __main: * the location it is compiled to run at. * Normally this is copying from FLASH ROM to RAM. */ - movl %ebp, %esi - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/amd/geode_lx/Kconfig b/src/cpu/amd/geode_lx/Kconfig index 7deb100fa3..ee1534d8cc 100644 --- a/src/cpu/amd/geode_lx/Kconfig +++ b/src/cpu/amd/geode_lx/Kconfig @@ -5,6 +5,9 @@ if CPU_AMD_GEODE_LX config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select CACHE_AS_RAM config DCACHE_RAM_BASE diff --git a/src/cpu/amd/geode_lx/cache_as_ram.inc b/src/cpu/amd/geode_lx/cache_as_ram.inc index 3146fd296c..d2c241565e 100644 --- a/src/cpu/amd/geode_lx/cache_as_ram.inc +++ b/src/cpu/amd/geode_lx/cache_as_ram.inc @@ -208,8 +208,6 @@ done_cache_as_ram_main: xorl $(CR0_CD + CR0_NW), %eax /* clear the CD and NW bits */ movl %eax, %cr0 - /* clear boot_complete flag */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) @@ -223,8 +221,6 @@ __main: * the location it is compiled to run at. * Normally this is copying from FLASH ROM to RAM. */ - movl %ebp, %esi - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/amd/geode_lx/msrinit.c b/src/cpu/amd/geode_lx/msrinit.c index 11182501c1..84fa548d59 100644 --- a/src/cpu/amd/geode_lx/msrinit.c +++ b/src/cpu/amd/geode_lx/msrinit.c @@ -42,11 +42,11 @@ static const msrinit_t msr_table[] = /* Pre-setup access to memory above 1Mb. Here we set up about 500Mb of memory. * It doesn't really matter in fact how much, however, because the only usage - * of this extended memory will be to host the coreboot_ram stage at RAMBASE, + * of this extended memory will be to host the ramstage stage at RAMBASE, * currently 1Mb. * These registers will be set to their correct value by the Northbridge init code. * - * WARNING: if coreboot_ram could not be loaded, these registers are probably + * WARNING: if ramstage could not be loaded, these registers are probably * incorrectly set here. You may comment the following two lines and set RAMBASE * to 0x4000 to revert to the previous behavior for LX-boards. */ diff --git a/src/cpu/amd/model_10xxx/Kconfig b/src/cpu/amd/model_10xxx/Kconfig index 23192f1a06..9a740ffb15 100644 --- a/src/cpu/amd/model_10xxx/Kconfig +++ b/src/cpu/amd/model_10xxx/Kconfig @@ -1,5 +1,8 @@ config CPU_AMD_MODEL_10XXX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SSE select SSE2 select MMCONF_SUPPORT_DEFAULT diff --git a/src/cpu/amd/model_fxx/Kconfig b/src/cpu/amd/model_fxx/Kconfig index fb094b1a5d..1479400c14 100644 --- a/src/cpu/amd/model_fxx/Kconfig +++ b/src/cpu/amd/model_fxx/Kconfig @@ -1,5 +1,8 @@ config CPU_AMD_MODEL_FXX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select MMX select SSE select SSE2 diff --git a/src/cpu/amd/sc520/Kconfig b/src/cpu/amd/sc520/Kconfig index 6d9494e32f..7696b5cdcd 100644 --- a/src/cpu/amd/sc520/Kconfig +++ b/src/cpu/amd/sc520/Kconfig @@ -1,2 +1,5 @@ config CPU_AMD_SC520 bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 diff --git a/src/cpu/armltd/Kconfig b/src/cpu/armltd/Kconfig index b1f4c2ee4e..fe41e475ae 100644 --- a/src/cpu/armltd/Kconfig +++ b/src/cpu/armltd/Kconfig @@ -1,8 +1,2 @@ -config CPU_ARMLTD_CORTEX_A9 - depends on ARCH_ARMV7 - bool - default n - -if CPU_ARMLTD_CORTEX_A9 source src/cpu/armltd/cortex-a9/Kconfig -endif +source src/cpu/armltd/armv8/Kconfig diff --git a/src/cpu/armltd/Makefile.inc b/src/cpu/armltd/Makefile.inc index 014742f056..294eddcf11 100644 --- a/src/cpu/armltd/Makefile.inc +++ b/src/cpu/armltd/Makefile.inc @@ -1 +1,2 @@ subdirs-$(CONFIG_CPU_ARMLTD_CORTEX_A9) += cortex-a9 +subdirs-$(CONFIG_CPU_ARMLTD_ARMV8) += armv8 diff --git a/src/cpu/armltd/armv8/Kconfig b/src/cpu/armltd/armv8/Kconfig new file mode 100644 index 0000000000..13a712c18f --- /dev/null +++ b/src/cpu/armltd/armv8/Kconfig @@ -0,0 +1,10 @@ +config CPU_ARMLTD_ARMV8 + bool + select ARCH_AARCH64 + select EARLY_CONSOLE + default n + +if CPU_ARMLTD_ARMV8 + +endif + diff --git a/src/mainboard/intel/wtm1/acpi/ec.asl b/src/cpu/armltd/armv8/Makefile.inc similarity index 100% rename from src/mainboard/intel/wtm1/acpi/ec.asl rename to src/cpu/armltd/armv8/Makefile.inc diff --git a/src/cpu/armltd/cortex-a9/Kconfig b/src/cpu/armltd/cortex-a9/Kconfig index 7f35cfd653..91dbdb9211 100644 --- a/src/cpu/armltd/cortex-a9/Kconfig +++ b/src/cpu/armltd/cortex-a9/Kconfig @@ -1,5 +1,11 @@ -config BOOTBLOCK_CPU_INIT - string - default "cpu/armltd/cortex-a9/bootblock.c" - help - CPU/SoC-specific bootblock code. +config CPU_ARMLTD_CORTEX_A9 + bool + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + select EARLY_CONSOLE + default n + +if CPU_ARMLTD_CORTEX_A9 + +endif diff --git a/src/cpu/armltd/cortex-a9/cache.c b/src/cpu/armltd/cortex-a9/cache.c index 957871dba7..7c91d69f9a 100644 --- a/src/cpu/armltd/cortex-a9/cache.c +++ b/src/cpu/armltd/cortex-a9/cache.c @@ -11,8 +11,6 @@ * GNU General Public License for more details. */ -#include -#include #include /* diff --git a/src/cpu/intel/Kconfig b/src/cpu/intel/Kconfig index 106ce1d0d4..14b37723d4 100644 --- a/src/cpu/intel/Kconfig +++ b/src/cpu/intel/Kconfig @@ -35,3 +35,4 @@ source src/cpu/intel/socket_LGA775/Kconfig source src/cpu/intel/socket_rPGA989/Kconfig # Architecture specific features source src/cpu/intel/fit/Kconfig +source src/cpu/intel/turbo/Kconfig diff --git a/src/cpu/intel/car/cache_as_ram.inc b/src/cpu/intel/car/cache_as_ram.inc index 781e48017b..1ea50b8b37 100644 --- a/src/cpu/intel/car/cache_as_ram.inc +++ b/src/cpu/intel/car/cache_as_ram.inc @@ -357,17 +357,12 @@ lout: andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax movl %eax, %cr0 - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/intel/car/cache_as_ram_ht.inc b/src/cpu/intel/car/cache_as_ram_ht.inc index 9ef69adfcb..8a845e954a 100644 --- a/src/cpu/intel/car/cache_as_ram_ht.inc +++ b/src/cpu/intel/car/cache_as_ram_ht.inc @@ -431,17 +431,12 @@ no_msr_11e: post_code(0x3c) - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/intel/ep80579/Kconfig b/src/cpu/intel/ep80579/Kconfig index 025ad3f81e..4820cf37ed 100644 --- a/src/cpu/intel/ep80579/Kconfig +++ b/src/cpu/intel/ep80579/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_EP80579 bool select SSE + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 \ No newline at end of file diff --git a/src/cpu/intel/fit/fit.lds b/src/cpu/intel/fit/fit.ld similarity index 100% rename from src/cpu/intel/fit/fit.lds rename to src/cpu/intel/fit/fit.ld diff --git a/src/cpu/intel/haswell/Kconfig b/src/cpu/intel/haswell/Kconfig index 5f27d4c7e1..0df560f05b 100644 --- a/src/cpu/intel/haswell/Kconfig +++ b/src/cpu/intel/haswell/Kconfig @@ -6,9 +6,13 @@ if CPU_INTEL_HASWELL config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 - select UDELAY_LAPIC + select UDELAY_TSC + select TSC_CONSTANT_RATE select SMM_TSEG select SMM_MODULES select RELOCATABLE_MODULES @@ -17,6 +21,9 @@ config CPU_SPECIFIC_OPTIONS #select AP_IN_SIPI_WAIT select TSC_SYNC_MFENCE select CPU_INTEL_FIRMWARE_INTERFACE_TABLE + select CAR_MIGRATION + select PARALLEL_MP + select HAS_PRECBMEM_TIMESTAMP_REGION config BOOTBLOCK_CPU_INIT string @@ -54,4 +61,11 @@ config RESET_ON_INVALID_RAMSTAGE_CACHE the system will reset otherwise the ramstage will be reloaded from cbfs. +config MONOTONIC_TIMER_MSR + def_bool n + depends on INTEL_LYNXPOINT_LP + select HAVE_MONOTONIC_TIMER + help + Provide a monotonic timer using the 24MHz MSR counter. + endif diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc index a19a8c5270..efed391a68 100644 --- a/src/cpu/intel/haswell/Makefile.inc +++ b/src/cpu/intel/haswell/Makefile.inc @@ -1,35 +1,15 @@ ramstage-y += haswell_init.c -subdirs-y += ../../x86/name -ramstage-y += mp_init.c +ramstage-y += tsc_freq.c romstage-y += romstage.c +romstage-y += tsc_freq.c ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c +ramstage-$(CONFIG_MONOTONIC_TIMER_MSR) += monotonic_timer.c cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c cpu_incs += $(src)/cpu/intel/haswell/cache_as_ram.inc - -# AP startub stub -SIPI_ELF=$(obj)/cpu/intel/haswell/sipi_vector.elf -SIPI_BIN=$(SIPI_ELF:.elf=) -SIPI_DOTO=$(SIPI_ELF:.elf=.o) - -ramstage-srcs += $(SIPI_BIN) -rmodules-y += sipi_vector.S -rmodules-y += sipi_header.c - -$(SIPI_DOTO): $(dir $(SIPI_ELF))sipi_vector.rmodules.o $(dir $(SIPI_ELF))sipi_header.rmodules.o - $(CC) $(LDFLAGS) -nostdlib -r -o $@ $^ - -$(eval $(call rmodule_link,$(SIPI_ELF), $(SIPI_ELF:.elf=.o), 0)) - -$(SIPI_BIN): $(SIPI_ELF) - $(OBJCOPY) -O binary $< $@ - -$(SIPI_BIN).ramstage.o: $(SIPI_BIN) - @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cd $(dir $@); $(OBJCOPY) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) - diff --git a/src/cpu/intel/haswell/acpi.c b/src/cpu/intel/haswell/acpi.c index a4d9cd9292..9e10c7527a 100644 --- a/src/cpu/intel/haswell/acpi.c +++ b/src/cpu/intel/haswell/acpi.c @@ -254,7 +254,7 @@ static int generate_P_state_entries(int core, int cores_per_package) len += acpigen_write_PPC_NVS(); /* Write PSD indicating configured coordination type */ - len += acpigen_write_PSD_package(core, cores_per_package, coord_type); + len += acpigen_write_PSD_package(core, 1, coord_type); /* Add P-state entries in _PSS table */ len += acpigen_write_name("_PSS"); @@ -346,7 +346,7 @@ void generate_cpu_entries(void) /* Generate P-state tables */ len_pr += generate_P_state_entries( - cpuID-1, cores_per_package); + coreID-1, cores_per_package); /* Generate C-state tables */ len_pr += generate_C_state_entries(); diff --git a/src/cpu/intel/haswell/bootblock.c b/src/cpu/intel/haswell/bootblock.c index bb065c808d..e502cfa392 100644 --- a/src/cpu/intel/haswell/bootblock.c +++ b/src/cpu/intel/haswell/bootblock.c @@ -112,10 +112,28 @@ static void set_flex_ratio_to_tdp_nominal(void) } } +static void check_for_clean_reset(void) +{ + msr_t msr; + msr = rdmsr(MTRRdefType_MSR); + + /* Use the MTRR default type MSR as a proxy for detecting INIT#. + * Reset the system if any known bits are set in that MSR. That is + * an indication of the CPU not being properly reset. */ + if (msr.lo & (MTRRdefTypeEn | MTRRdefTypeFixEn)) { + outb(0x0, 0xcf9); + outb(0x6, 0xcf9); + while (1) { + asm("hlt"); + } + } +} + static void bootblock_cpu_init(void) { /* Set flex ratio and reset if needed */ set_flex_ratio_to_tdp_nominal(); + check_for_clean_reset(); enable_rom_caching(); intel_update_microcode_from_cbfs(); } diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index a1c6f39ec2..e57673d335 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -22,8 +22,22 @@ #ifndef _CPU_INTEL_HASWELL_H #define _CPU_INTEL_HASWELL_H +#include + +/* Haswell CPU types */ +#define HASWELL_FAMILY_MOBILE 0x306c0 +#define HASWELL_FAMILY_ULT 0x40650 + +/* Haswell CPU steppings */ +#define HASWELL_STEPPING_MOBILE_A0 1 +#define HASWELL_STEPPING_MOBILE_B0 2 +#define HASWELL_STEPPING_MOBILE_C0 3 +#define HASWELL_STEPPING_MOBILE_D0 4 +#define HASWELL_STEPPING_ULT_B0 0 +#define HASWELL_STEPPING_ULT_C0 1 + /* Haswell bus clock is fixed at 100MHz */ -#define HASWELL_BCLK 100 +#define HASWELL_BCLK 100 #define CORE_THREAD_COUNT_MSR 0x35 #define IA32_FEATURE_CONTROL 0x3a @@ -57,9 +71,12 @@ #define MSR_TURBO_RATIO_LIMIT 0x1ad #define MSR_POWER_CTL 0x1fc -#define MSR_PKGC3_IRTL 0x60a -#define MSR_PKGC6_IRTL 0x60b -#define MSR_PKGC7_IRTL 0x60c +#define MSR_C_STATE_LATENCY_CONTROL_0 0x60a +#define MSR_C_STATE_LATENCY_CONTROL_1 0x60b +#define MSR_C_STATE_LATENCY_CONTROL_2 0x60c +#define MSR_C_STATE_LATENCY_CONTROL_3 0x633 +#define MSR_C_STATE_LATENCY_CONTROL_4 0x634 +#define MSR_C_STATE_LATENCY_CONTROL_5 0x635 #define IRTL_VALID (1 << 15) #define IRTL_1_NS (0 << 10) #define IRTL_32_NS (1 << 10) @@ -77,14 +94,12 @@ #define PKG_POWER_LIMIT_TIME_SHIFT 17 #define PKG_POWER_LIMIT_TIME_MASK 0x7f -#define MSR_PP0_CURRENT_CONFIG 0x601 #define MSR_VR_CURRENT_CONFIG 0x601 -#define PP0_CURRENT_LIMIT (112 << 3) /* 112 A */ -#define MSR_PP1_CURRENT_CONFIG 0x602 -#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */ -#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */ +#define MSR_VR_MISC_CONFIG 0x603 #define MSR_PKG_POWER_SKU_UNIT 0x606 #define MSR_PKG_POWER_SKU 0x614 +#define MSR_DDR_RAPL_LIMIT 0x618 +#define MSR_VR_MISC_CONFIG2 0x636 #define MSR_PP0_POWER_LIMIT 0x638 #define MSR_PP1_POWER_LIMIT 0x640 @@ -100,6 +115,27 @@ #define PSS_LATENCY_TRANSITION 10 #define PSS_LATENCY_BUSMASTER 10 +/* PCODE MMIO communications live in the MCHBAR. */ +#define BIOS_MAILBOX_INTERFACE 0x5da4 +#define MAILBOX_RUN_BUSY (1 << 31) +#define MAILBOX_BIOS_CMD_READ_PCS 1 +#define MAILBOX_BIOS_CMD_WRITE_PCS 2 +#define MAILBOX_BIOS_CMD_READ_CALIBRATION 0x509 +#define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909 +#define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa +#define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb +/* Errors are returned back in bits 7:0. */ +#define MAILBOX_BIOS_ERROR_NONE 0 +#define MAILBOX_BIOS_ERROR_INVALID_COMMAND 1 +#define MAILBOX_BIOS_ERROR_TIMEOUT 2 +#define MAILBOX_BIOS_ERROR_ILLEGAL_DATA 3 +#define MAILBOX_BIOS_ERROR_RESERVED 4 +#define MAILBOX_BIOS_ERROR_ILLEGAL_VR_ID 5 +#define MAILBOX_BIOS_ERROR_VR_INTERFACE_LOCKED 6 +#define MAILBOX_BIOS_ERROR_VR_ERROR 7 +/* Data is passed through bits 31:0 of the data register. */ +#define BIOS_MAILBOX_DATA 0x5da0 + /* Region of SMM space is reserved for multipurpose use. It falls below * the IED region and above the SMM handler. */ #define RESERVED_SMM_SIZE CONFIG_SMM_RESERVED_SIZE @@ -120,7 +156,7 @@ # error "CONFIG_IED_REGION_SIZE is not a power of 2" #endif -#ifndef __ROMCC__ +#if !defined(__ROMCC__) // FIXME romcc should handle below constructs #if defined(__PRE_RAM__) struct pei_data; @@ -130,6 +166,7 @@ struct romstage_params { const void *gpio_map; const struct rcba_config_instruction *rcba_config; unsigned long bist; + void (*copy_spd)(struct pei_data *); }; void mainboard_romstage_entry(unsigned long bist); void romstage_common(const struct romstage_params *params); @@ -148,7 +185,7 @@ void romstage_common(const struct romstage_params *params); * +32: MTTR mask 1 63:32 * ... */ -void * __attribute__((regparm(0))) romstage_main(unsigned long bist); +void * asmlinkage romstage_main(unsigned long bist); /* romstage_after_car() is the C function called after cache-as-ram has * been torn down. It is responsible for loading the ramstage. */ void romstage_after_car(void); @@ -163,33 +200,18 @@ void set_power_limits(u8 power_limit_1_time); int cpu_config_tdp_levels(void); /* Returns 0 on success, < 0 on failure. */ int smm_initialize(void); -void smm_initiate_relocation(void); -void smm_initiate_relocation_parallel(void); +void smm_relocate(void); struct bus; void bsp_init_and_start_aps(struct bus *cpu_bus); -/* Returns 0 on succes. < 0 on failure. */ -int setup_ap_init(struct bus *cpu_bus, int *max_cpus, - const void *microcode_patch); -/* Returns 0 on success, < 0 on failure. */ -int start_aps(struct bus *cpu_bus, int max_cpus); -void release_aps_for_smm_relocation(int do_parallel_relocation); +/* Determine if HyperThreading is disabled. The variable is not valid until + * setup_ap_init() has been called. */ +extern int ht_disabled; #endif -/* This structure is saved along with the relocated ramstage program in SMM - * space. It is used to protect the integrity of the ramstage program on S3 - * resume by saving a copy of the relocated ramstage in SMM space with the - * assumption that the SMM region cannot be altered from the OS. The magic - * value just serves as a quick sanity check. */ - -#define RAMSTAGE_CACHE_MAGIC 0xf3c3a02a - -struct ramstage_cache { - uint32_t magic; - uint32_t entry_point; - uint32_t load_address; - uint32_t size; - char program[0]; -} __attribute__((packed)); +/* CPU identification */ +int haswell_family_model(void); +int haswell_stepping(void); +int haswell_is_ult(void); #endif diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c index 18636b0840..2e49b261db 100644 --- a/src/cpu/intel/haswell/haswell_init.c +++ b/src/cpu/intel/haswell/haswell_init.c @@ -29,94 +29,127 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include +#include +#include #include "haswell.h" #include "chip.h" +/* Intel suggested latency times in units of 1024ns. */ +#define C_STATE_LATENCY_CONTROL_0_LIMIT 0x42 +#define C_STATE_LATENCY_CONTROL_1_LIMIT 0x73 +#define C_STATE_LATENCY_CONTROL_2_LIMIT 0x91 +#define C_STATE_LATENCY_CONTROL_3_LIMIT 0xe4 +#define C_STATE_LATENCY_CONTROL_4_LIMIT 0x145 +#define C_STATE_LATENCY_CONTROL_5_LIMIT 0x1ef + +#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \ + (((1 << ((base)*5)) * (limit)) / 1000) +#define C_STATE_LATENCY_FROM_LAT_REG(reg) \ + C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \ + (IRTL_1024_NS >> 10)) + /* - * List of suported C-states in this processor - * - * Latencies are typical worst-case package exit time in uS - * taken from the SandyBridge BIOS specification. + * List of suported C-states in this processor. Only the ULT parts support C8, + * C9, and C10. */ -#if 0 -static acpi_cstate_t cstate_map[] = { - { /* 0: C0 */ - },{ /* 1: C1 */ - .latency = 1, - .power = 1000, - .resource = { - .addrl = 0x00, /* MWAIT State 0 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { /* 2: C1E */ - .latency = 1, - .power = 1000, - .resource = { - .addrl = 0x01, /* MWAIT State 0 Sub-state 1 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { /* 3: C3 */ - .latency = 63, - .power = 500, - .resource = { - .addrl = 0x10, /* MWAIT State 1 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { /* 4: C6 */ - .latency = 87, - .power = 350, - .resource = { - .addrl = 0x20, /* MWAIT State 2 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { /* 5: C7 */ - .latency = 90, - .power = 200, - .resource = { - .addrl = 0x30, /* MWAIT State 3 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { /* 6: C7S */ - .latency = 90, - .power = 200, - .resource = { - .addrl = 0x31, /* MWAIT State 3 Sub-state 1 */ - .space_id = ACPI_ADDRESS_SPACE_FIXED, - .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, - .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, - .resv = ACPI_FFIXEDHW_FLAG_HW_COORD, - } - }, - { 0 } +enum { + C_STATE_C0, /* 0 */ + C_STATE_C1, /* 1 */ + C_STATE_C1E, /* 2 */ + C_STATE_C3, /* 3 */ + C_STATE_C6_SHORT_LAT, /* 4 */ + C_STATE_C6_LONG_LAT, /* 5 */ + C_STATE_C7_SHORT_LAT, /* 6 */ + C_STATE_C7_LONG_LAT, /* 7 */ + C_STATE_C7S_SHORT_LAT, /* 8 */ + C_STATE_C7S_LONG_LAT, /* 9 */ + C_STATE_C8, /* 10 */ + C_STATE_C9, /* 11 */ + C_STATE_C10, /* 12 */ + NUM_C_STATES +}; + +#define MWAIT_RES(state, sub_state) \ + { \ + .addrl = (((state) << 4) | (sub_state)), \ + .space_id = ACPI_ADDRESS_SPACE_FIXED, \ + .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \ + .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \ + .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \ + } + +static acpi_cstate_t cstate_map[NUM_C_STATES] = { + [C_STATE_C0] = { }, + [C_STATE_C1] = { + .latency = 0, + .power = 1000, + .resource = MWAIT_RES(0,0), + }, + [C_STATE_C1E] = { + .latency = 0, + .power = 1000, + .resource = MWAIT_RES(0,1), + }, + [C_STATE_C3] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(0), + .power = 900, + .resource = MWAIT_RES(1, 0), + }, + [C_STATE_C6_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 800, + .resource = MWAIT_RES(2, 0), + }, + [C_STATE_C6_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 800, + .resource = MWAIT_RES(2, 1), + }, + [C_STATE_C7_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 700, + .resource = MWAIT_RES(3, 0), + }, + [C_STATE_C7_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 700, + .resource = MWAIT_RES(3, 1), + }, + [C_STATE_C7S_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 700, + .resource = MWAIT_RES(3, 2), + }, + [C_STATE_C7S_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 700, + .resource = MWAIT_RES(3, 3), + }, + [C_STATE_C8] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(3), + .power = 600, + .resource = MWAIT_RES(4, 0), + }, + [C_STATE_C9] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(4), + .power = 500, + .resource = MWAIT_RES(5, 0), + }, + [C_STATE_C10] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(5), + .power = 400, + .resource = MWAIT_RES(6, 0), + }, }; -#endif /* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ static const u8 power_limit_time_sec_to_msr[] = { @@ -176,6 +209,199 @@ static const u8 power_limit_time_msr_to_sec[] = { [0x11] = 128, }; +int haswell_family_model(void) +{ + return cpuid_eax(1) & 0x0fff0ff0; +} + +int haswell_stepping(void) +{ + return cpuid_eax(1) & 0xf; +} + +/* Dynamically determine if the part is ULT. */ +int haswell_is_ult(void) +{ + static int ult = -1; + + if (ult < 0) + ult = !!(haswell_family_model() == HASWELL_FAMILY_ULT); + + return ult; +} + +/* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate + * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly + * when a core is woken up. */ +static int pcode_ready(void) +{ + int wait_count; + const int delay_step = 10; + + wait_count = 0; + do { + if (!(MCHBAR32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY)) + return 0; + wait_count += delay_step; + udelay(delay_step); + } while (wait_count < 1000); + + return -1; +} + +static void calibrate_24mhz_bclk(void) +{ + int err_code; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return; + } + + /* A non-zero value initiates the PCODE calibration. */ + MCHBAR32(BIOS_MAILBOX_DATA) = ~0; + MCHBAR32(BIOS_MAILBOX_INTERFACE) = + MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return; + } + + err_code = MCHBAR32(BIOS_MAILBOX_INTERFACE) & 0xff; + + printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration response: %d\n", + err_code); + + /* Read the calibrated value. */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = + MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on read.\n"); + return; + } + + printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration value: 0x%08x\n", + MCHBAR32(BIOS_MAILBOX_DATA)); +} + +static u32 pcode_mailbox_read(u32 command) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return 0; + } + + /* Send command and start transaction */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return 0; + } + + /* Read mailbox */ + return MCHBAR32(BIOS_MAILBOX_DATA); +} + +static void initialize_vr_config(void) +{ + msr_t msr; + + printk(BIOS_DEBUG, "Initializing VR config.\n"); + + /* Configure VR_CURRENT_CONFIG. */ + msr = rdmsr(MSR_VR_CURRENT_CONFIG); + /* Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid + * on ULT systems. */ + msr.hi &= 0xc0000000; + msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A. */ + msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A. */ + msr.hi |= (0x0f << (32 - 32)); /* PSI1 threshold - 15A. */ + + if (haswell_is_ult()) + msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */ + /* Leave the max instantaneous current limit (12:0) to default. */ + wrmsr(MSR_VR_CURRENT_CONFIG, msr); + + /* Configure VR_MISC_CONFIG MSR. */ + msr = rdmsr(MSR_VR_MISC_CONFIG); + /* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format. */ + msr.hi &= ~(0x3ff << (40 - 32)); + msr.hi |= (0x200 << (40 - 32)); /* 1.0 */ + /* Set IOUT_OFFSET to 0. */ + msr.hi &= ~0xff; + /* Set exit ramp rate to fast. */ + msr.hi |= (1 << (50 - 32)); + /* Set entry ramp rate to slow. */ + msr.hi &= ~(1 << (51 - 32)); + /* Enable decay mode on C-state entry. */ + msr.hi |= (1 << (52 - 32)); + /* Set the slow ramp rate to be fast ramp rate / 4 */ + msr.hi &= ~(0x3 << (53 - 32)); + msr.hi |= (0x01 << (53 - 32)); + /* Set MIN_VID (31:24) to allow CPU to have full control. */ + msr.lo &= ~0xff000000; + wrmsr(MSR_VR_MISC_CONFIG, msr); + + /* Configure VR_MISC_CONFIG2 MSR. */ + if (haswell_is_ult()) { + msr = rdmsr(MSR_VR_MISC_CONFIG2); + msr.lo &= ~0xffff; + /* Allow CPU to control minimum voltage completely (15:8) and + * set the fast ramp voltage to 1110mV (0x6f in 10mV steps). */ + msr.lo |= 0x006f; + wrmsr(MSR_VR_MISC_CONFIG2, msr); + } +} + +static void configure_pch_power_sharing(void) +{ + u32 pch_power, pch_power_ext, pmsync, pmsync2; + int i; + + /* Read PCH Power levels from PCODE */ + pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER); + pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT); + + printk(BIOS_INFO, "PCH Power: PCODE Levels 0x%08x 0x%08x\n", + pch_power, pch_power_ext); + + pmsync = RCBA32(PMSYNC_CONFIG); + pmsync2 = RCBA32(PMSYNC_CONFIG2); + + /* Program PMSYNC_TPR_CONFIG PCH power limit values + * pmsync[0:4] = mailbox[0:5] + * pmsync[8:12] = mailbox[6:11] + * pmsync[16:20] = mailbox[12:17] + */ + for (i = 0; i < 3; i++) { + u32 level = pch_power & 0x3f; + pch_power >>= 6; + pmsync &= ~(0x1f << (i * 8)); + pmsync |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG) = pmsync; + + /* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values + * pmsync2[0:4] = mailbox[23:18] + * pmsync2[8:12] = mailbox_ext[6:11] + * pmsync2[16:20] = mailbox_ext[12:17] + * pmsync2[24:28] = mailbox_ext[18:22] + */ + pmsync2 &= ~0x1f; + pmsync2 |= pch_power & 0x1f; + + for (i = 1; i < 4; i++) { + u32 level = pch_power_ext & 0x3f; + pch_power_ext >>= 6; + pmsync2 &= ~(0x1f << (i * 8)); + pmsync2 |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG2) = pmsync2; +} + int cpu_config_tdp_levels(void) { msr_t platform_info; @@ -198,7 +424,7 @@ void set_power_limits(u8 power_limit_1_time) u8 power_limit_1_val; if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr)) - return; + power_limit_1_time = 28; if (!(msr.lo & PLATFORM_INFO_SET_TDP)) return; @@ -238,10 +464,19 @@ void set_power_limits(u8 power_limit_1_time) limit.hi = 0; limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK; limit.hi |= PKG_POWER_LIMIT_EN; - /* Power limit 2 time is only programmable on SNB EP/EX */ + /* Power limit 2 time is only programmable on server SKU */ wrmsr(MSR_PKG_POWER_LIMIT, limit); + /* Set power limit values in MCHBAR as well */ + MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo; + MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi; + + /* Set DDR RAPL power limit by copying from MMIO to MSR */ + msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO); + msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI); + wrmsr(MSR_DDR_RAPL_LIMIT, msr); + /* Use nominal TDP values for CPUs with configurable TDP */ if (cpu_config_tdp_levels()) { msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); @@ -251,24 +486,25 @@ void set_power_limits(u8 power_limit_1_time) } } -#if 0 static void configure_c_states(void) { msr_t msr; msr = rdmsr(MSR_PMG_CST_CONFIG_CONTROL); + msr.lo |= (1 << 30); // Package c-state Undemotion Enable + msr.lo |= (1 << 29); // Package c-state Demotion Enable msr.lo |= (1 << 28); // C1 Auto Undemotion Enable msr.lo |= (1 << 27); // C3 Auto Undemotion Enable msr.lo |= (1 << 26); // C1 Auto Demotion Enable msr.lo |= (1 << 25); // C3 Auto Demotion Enable msr.lo &= ~(1 << 10); // Disable IO MWAIT redirection - msr.lo |= 7; // No package C-state limit + /* The deepest package c-state defaults to factory-configured value. */ wrmsr(MSR_PMG_CST_CONFIG_CONTROL, msr); msr = rdmsr(MSR_PMG_IO_CAPTURE_BASE); - msr.lo &= ~0x7ffff; - msr.lo |= (get_pmbase() + 4); // LVL_2 base address - msr.lo |= (2 << 16); // CST Range: C7 is max C-state + msr.lo &= ~0xffff; + msr.lo |= (get_pmbase() + 0x14); // LVL_2 base address + /* The deepest package c-state defaults to factory-configured value. */ wrmsr(MSR_PMG_IO_CAPTURE_BASE, msr); msr = rdmsr(MSR_MISC_PWR_MGMT); @@ -281,37 +517,42 @@ static void configure_c_states(void) msr.lo |= (1 << 0); // Bi-directional PROCHOT# wrmsr(MSR_POWER_CTL, msr); - /* C3 Interrupt Response Time Limit */ + /* C-state Interrupt Response Latency Control 0 - package C3 latency */ msr.hi = 0; - msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50; - wrmsr(MSR_PKGC3_IRTL, msr); + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_0, msr); - /* C6 Interrupt Response Time Limit */ + /* C-state Interrupt Response Latency Control 1 */ msr.hi = 0; - msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68; - wrmsr(MSR_PKGC6_IRTL, msr); + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_1, msr); - /* C7 Interrupt Response Time Limit */ + /* C-state Interrupt Response Latency Control 2 - package C6/C7 short */ msr.hi = 0; - msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D; - wrmsr(MSR_PKGC7_IRTL, msr); + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr); - /* Primary Plane Current Limit */ - msr = rdmsr(MSR_PP0_CURRENT_CONFIG); - msr.lo &= ~0x1fff; - msr.lo |= PP0_CURRENT_LIMIT; - wrmsr(MSR_PP0_CURRENT_CONFIG, msr); + /* Haswell ULT only supoprts the 3-5 latency response registers.*/ + if (haswell_is_ult()) { + /* C-state Interrupt Response Latency Control 3 - package C8 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_3_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr); - /* Secondary Plane Current Limit */ - msr = rdmsr(MSR_PP1_CURRENT_CONFIG); - msr.lo &= ~0x1fff; - if (cpuid_eax(1) >= 0x30600) - msr.lo |= PP1_CURRENT_LIMIT_IVB; - else - msr.lo |= PP1_CURRENT_LIMIT_SNB; - wrmsr(MSR_PP1_CURRENT_CONFIG, msr); + /* C-state Interrupt Response Latency Control 4 - package C9 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_4_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr); + + /* C-state Interrupt Response Latency Control 5 - package C10 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_5_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr); + } } -#endif static void configure_thermal_target(void) { @@ -444,28 +685,6 @@ static unsigned ehci_debug_addr; static void bsp_init_before_ap_bringup(struct bus *cpu_bus) { - struct device_path cpu_path; - struct cpu_info *info; - char processor_name[49]; - - /* Print processor name */ - fill_processor_name(processor_name); - printk(BIOS_INFO, "CPU: %s.\n", processor_name); - - /* Ensure the local apic is enabled */ - enable_lapic(); - - /* Set the device path of the boot cpu. */ - cpu_path.type = DEVICE_PATH_APIC; - cpu_path.apic.apic_id = lapicid(); - - /* Find the device structure for the boot cpu. */ - info = cpu_info(); - info->cpu = alloc_find_dev(cpu_bus, &cpu_path); - - if (info->index != 0) - printk(BIOS_CRIT, "BSP index(%d) != 0!\n", info->index); - #if CONFIG_USBDEBUG // Is this caution really needed? if(!ehci_debug_addr) @@ -482,8 +701,12 @@ static void bsp_init_before_ap_bringup(struct bus *cpu_bus) set_ehci_debug(ehci_debug_addr); #endif - /* Call through the cpu driver's initialization. */ - cpu_initialize(0); + initialize_vr_config(); + + if (haswell_is_ult()) { + calibrate_24mhz_bclk(); + configure_pch_power_sharing(); + } } /* All CPUs including BSP will run the following function. */ @@ -497,7 +720,7 @@ static void haswell_init(device_t cpu) setup_lapic(); /* Configure C States */ - //configure_c_states(); + configure_c_states(); /* Configure Enhanced SpeedStep and Thermal Sensors */ configure_misc(); @@ -518,11 +741,56 @@ static void haswell_init(device_t cpu) enable_turbo(); } +/* MP initialization support. */ +static const void *microcode_patch; +int ht_disabled; + +static int adjust_apic_id_ht_disabled(int index, int apic_id) +{ + return 2 * index; +} + +static void relocate_and_load_microcode(void *unused) +{ + /* Relocate the SMM handler. */ + smm_relocate(); + + /* After SMM relocation a 2nd microcode load is required. */ + intel_microcode_load_unlocked(microcode_patch); +} + +static void enable_smis(void *unused) +{ + /* Now that all APs have been relocated as well as the BSP let SMIs + * start flowing. */ + southbridge_smm_enable_smi(); + + /* Lock down the SMRAM space. */ + smm_lock(); +} + +static struct mp_flight_record mp_steps[] = { + MP_FR_NOBLOCK_APS(relocate_and_load_microcode, NULL, + relocate_and_load_microcode, NULL), + MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL), + /* Wait for APs to finish initialization before proceeding. */ + MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), +}; + void bsp_init_and_start_aps(struct bus *cpu_bus) { - int max_cpus; - int num_aps; - const void *microcode_patch; + int num_threads; + int num_cores; + msr_t msr; + struct mp_params mp_params; + + msr = rdmsr(CORE_THREAD_COUNT_MSR); + num_threads = (msr.lo >> 0) & 0xffff; + num_cores = (msr.lo >> 16) & 0xffff; + printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", + num_cores, num_threads); + + ht_disabled = num_threads == num_cores; /* Perform any necesarry BSP initialization before APs are brought up. * This call alos allows the BSP to prepare for any secondary effects @@ -531,26 +799,23 @@ void bsp_init_and_start_aps(struct bus *cpu_bus) microcode_patch = intel_microcode_find(); - /* This needs to be called after the mtrr setup so the BSP mtrrs - * can be mirrored by the APs. */ - if (setup_ap_init(cpu_bus, &max_cpus, microcode_patch)) { - printk(BIOS_CRIT, "AP setup initialization failed. " - "No APs will be brought up.\n"); - return; - } + mp_params.num_cpus = num_threads; + mp_params.parallel_microcode_load = 1; + if (ht_disabled) + mp_params.adjust_apic_id = adjust_apic_id_ht_disabled; + else + mp_params.adjust_apic_id = NULL; + mp_params.flight_plan = &mp_steps[0]; + mp_params.num_records = ARRAY_SIZE(mp_steps); + mp_params.microcode_pointer = microcode_patch; - num_aps = max_cpus - 1; - if (start_aps(cpu_bus, num_aps)) { - printk(BIOS_CRIT, "AP startup failed. Trying to continue.\n"); - } - - if (smm_initialize()) { + /* Load relocation and permeanent handlers. Then initiate relocation. */ + if (smm_initialize()) printk(BIOS_CRIT, "SMM Initialiazation failed...\n"); - return; - } - /* After SMM relocation a 2nd microcode load is required. */ - intel_microcode_load_unlocked(microcode_patch); + if (mp_init(cpu_bus, &mp_params)) { + printk(BIOS_ERR, "MP initialization failure.\n"); + } /* Enable ROM caching if option was selected. */ x86_mtrr_enable_rom_caching(); @@ -571,6 +836,6 @@ static struct cpu_device_id cpu_table[] = { static const struct cpu_driver driver __cpu_driver = { .ops = &cpu_dev_ops, .id_table = cpu_table, - /* .cstates = cstate_map, */ + .cstates = cstate_map, }; diff --git a/src/cpu/intel/haswell/microcode-M32306c3_0000001c.h b/src/cpu/intel/haswell/microcode-M32306c3_0000001c.h new file mode 100644 index 0000000000..33ef43190c --- /dev/null +++ b/src/cpu/intel/haswell/microcode-M32306c3_0000001c.h @@ -0,0 +1,5376 @@ +0x00000001, +0x0000001c, +0x07032014, +0x000306c3, +0x4cc7cd85, +0x00000001, +0x00000032, +0x000053d0, +0x00005400, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x000000a1, +0x00020001, +0x0000001c, +0x00000001, +0x00001481, +0x20140702, +0x00001481, +0x00000001, +0x000306c3, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x3469b78a, +0x5fb47585, +0xcadb1867, +0xe271798b, +0xdf37b777, +0xeadb4d9a, +0x08fe7723, +0x66bbeea9, +0xa19308a3, +0x5b19c4b7, +0x4a1b425b, +0x7d6a74f6, +0x81624193, +0x3a559605, +0x5475280b, +0xe7319d58, +0x48624ca7, +0x507af030, +0x3b32d96a, +0x30164068, +0x5284d2f5, +0x725b2915, +0xf63c9280, +0x44b7c142, +0xe67ca7b3, +0xd6f163e7, +0xcdf51f3c, +0x41d180a1, +0xcc3931b1, +0xf7a544a9, +0x7f6bf77d, +0xfc45a45f, +0xf0985836, +0x652d7e2e, +0x0324b1f3, +0x24b9548c, +0x7bcae7a5, +0xdcdebf79, +0x27015922, +0x0c83c606, +0x3d2ceeb7, +0x61c5eec8, +0x6b6899c6, +0x3e500531, +0xf08bfa44, +0xb304a8f4, +0xcee8f713, +0x2912c786, +0xfae6c34c, +0xa5292960, +0x7d63e389, +0xaa257a01, +0x1fb25054, +0x963fc676, +0x5bcb9fd3, +0x58f369a4, +0xf6e3beb2, +0xa58b5eb0, +0x33c7eba4, +0x37fe8b66, +0x00714403, +0xf0fd0c4e, +0xaa122996, +0x9a55b184, +0x00201507, +0xc9fb6e3a, +0x11ab60c8, +0x80ff6e84, +0xc37aabdd, +0x0fc23175, +0xb0b18c34, +0xf1ec806c, +0x00000011, +0xa4303311, +0xa634137d, +0x7f827f66, +0x7c9e42a6, +0x34394a35, +0xb87b55df, +0xb33fdc62, +0x3dfc85a3, +0x08c8dc45, +0xf1cb9cd8, +0x2e2af040, +0xfa2e47b2, +0x1784a824, +0x73571c8a, +0xafa98a38, +0x34e68899, +0x0c89121e, +0x7ad663a8, +0xeb4c4b2a, +0x62702cfc, +0x67bf6d74, +0xa1c27475, +0xdab881b9, +0xbdf68e4f, +0x45bbb94a, +0x4002bb35, +0xe6ee8124, +0x92f579c4, +0x0b9138a6, +0x8376a2bd, +0x59f6e1d3, +0x020c0c4f, +0x985114e2, +0xd9410ce9, +0x923add32, +0xa4282cf3, +0x5d2fcb0f, +0x582924e0, +0x97baf68d, +0xec510eed, +0x313346dc, +0x13939b64, +0x0ac66903, +0x574cc852, +0x972327c5, +0x7e400328, +0xfd96cfc4, +0x2a13c098, +0x7e2434fb, +0x39f48bfe, +0x17a864f7, +0x8b67ec3f, +0x9ff690d7, +0x927cc6ea, +0x333d73f4, +0xd445d529, +0xf13d035a, +0x0258fe2f, +0x3a09fd11, +0x73e49acf, +0x2c1244fb, +0xe4ea8840, +0xa3eaec76, +0xacacbed5, +0x627ad195, +0x49cd62cf, +0x4f8e4bfc, +0x9e1284a5, +0x3ca68b92, +0xc19b8e95, +0x7ba6d2ac, +0x4b25e188, +0x6bacfb63, +0x4cf67d66, +0x33505222, +0xaad85439, +0x4fa87c51, +0xeacbb3b3, +0x0a3852ee, +0x2e11419a, +0x34c519e6, +0xa350be33, +0x6486263f, +0x83519eff, +0xe4ef04f2, +0x01859f4f, +0x511978ea, +0xf88b8fad, +0x937539f7, +0x79845ba9, +0x7145e020, +0xdef67084, +0x6f453ebd, +0x494d9944, +0x7d57c09e, +0xcbf25a77, +0xcaa1ea4e, +0x1f097b59, +0xa0f12f4b, +0x8d55e5cc, +0x1e2afaed, +0x205c6445, +0xb3550d03, +0x74cbe172, +0x55239657, +0xc3f52d52, +0x9515d06b, +0x156dea21, +0x15343b6d, +0xe2eb8fcc, +0xc589b38d, +0x8dd53e60, +0xa14697ee, +0x8ac0f869, +0x0e595134, +0x1ab42a19, +0x0982fa3a, +0x03804d0f, +0xa58b59a2, +0xd7b66f6c, +0x46219f78, +0x37b40e55, +0x9aecdcb3, +0x58ca1785, +0x65856743, +0x4572ef85, +0x2c677f58, +0x55087fcc, +0x2c648812, +0x3c1511aa, +0xdea77e13, +0x6082fe9f, +0xb10fc6bf, +0x3020dede, +0x7b1cda6c, +0xdb1127d1, +0x0cd83186, +0x5d4e1227, +0x64bb2b68, +0x1943b700, +0xa9f531f1, +0x86ddb896, +0xe54ab072, +0xf5fa4963, +0x0025ae3e, +0xc420b193, +0x71e44f66, +0x7f1147b1, +0x4d478dd5, +0x5e98bc19, +0xd0d1c87d, +0x34bb4750, +0x9132bf0d, +0x0a758bc5, +0x6387dcd0, +0x031a8cbe, +0x41987abf, +0xe2cc7df5, +0x6b9218f0, +0xe4465e01, +0x2e87a12d, +0xdee0c0b4, +0xeb770eed, +0x3894f976, +0x2b836019, +0xe642aafc, +0x1279f388, +0x301eaed1, +0xdb7426e3, +0x9e1c3654, +0x60ab72d1, +0x826cd304, +0x4a374ab5, +0x22d253ce, +0x067b8be3, +0x6a4f0767, +0x5ae01344, +0x01838cae, +0x8a260f0d, +0x6addca9d, +0x38a14818, +0x314fc23b, +0x7cafdbfe, +0x80fcc784, +0xdb73a3f0, +0xaf98ea02, +0xf189a62f, +0x6344d97b, +0x63b60f6a, +0x81ae33da, +0x519ef51f, +0xa9414b77, +0x18bf77ef, +0x45b698e8, +0x7fffd7e6, +0xd786bc41, +0x271837d2, +0x9909bd9f, +0xb8c9308c, +0xe04b5665, +0xc4b01fc6, +0x6adfc1b5, +0x993e3b53, +0x05cbb36e, +0x000809f2, +0xee981032, +0xbee6cf75, +0xd563d510, +0x4530ac62, +0x4949687f, +0x2d36c775, +0x26d2307e, +0x05130617, +0xb3d0cd10, +0xcb54385c, +0xf3274b69, +0x72a1c547, +0x3a028cb0, +0x7239ec87, +0x7d23d13f, +0xaa64c071, +0x047a3c67, +0x231325b8, +0x421dd04d, +0x09d12c3e, +0xf86c9728, +0x582448db, +0x43e840fd, +0x73f66b33, +0x115228e8, +0x503c2c38, +0xb5007a08, +0x04368c81, +0xe0d929b1, +0x8b5003f6, +0x723a65b0, +0xe22ae9e1, +0xe8eb732c, +0xa35af6be, +0x31930a1e, +0xddb42af5, +0xb230b81e, +0x446d5c01, +0xf2ae52fd, +0xa06fa85b, +0x05f40168, +0x0618be6e, +0xcdc7a496, +0xbd8d4a36, +0xe994fe53, +0xf2a68d59, +0x0375e3ce, +0xcca64b05, +0xcd7e7f93, +0x65afe064, +0xc5042295, +0x27f28267, +0xc6d2b095, +0x36d92849, +0x7b690eac, +0xe99a2e9f, +0x37dfdcc3, +0x9814a48e, +0x066de266, +0x3a43449e, +0xa7a185e2, +0x8c879158, +0x3470b00c, +0xe56fd1e5, +0x8f394909, +0x421fe5ab, +0xaf15f097, +0x71f20902, +0xf70c5925, +0xae2b2ffc, +0xb740c5e9, +0x6073ad7f, +0x3272c8c1, +0x0fdbe360, +0xdddbadf6, +0xfe4d9502, +0x33e06d75, +0x947ca570, +0x74497547, +0xfe586567, +0x87036d2e, +0xea8df645, +0x3b1d66c3, +0x2b0610a3, +0x5171d063, +0x5bbd00d2, +0x3b6bf775, +0x419b33d9, +0xe60e3cc9, +0x65f16493, +0x1c50d173, +0xf2585592, +0x92b2fd98, +0x4a462253, +0xf348ab65, +0xbb012e61, +0x09f7bc60, +0xd82b2c87, +0x49fd8cfa, +0x84051ef4, +0x9f529d01, +0xda72a631, +0xfdfb4e67, +0xfd00f0d8, +0x9ae0dfaa, +0x80f45181, +0xbc2ebd5b, +0x48e991ec, +0xd138d727, +0x8e513f2a, +0xc2fd17c5, +0x897cdcb3, +0xf7e76dbd, +0x84b9380c, +0xaecc18aa, +0xcc07b877, +0x80bb4832, +0xe05ded5e, +0x12e66198, +0x23c123e7, +0xd9275f82, +0xea96de3b, +0x6949127e, +0x440d07ba, +0xc359dca0, +0x94b6c0eb, +0x5b106e08, +0x2ccbb459, +0x09e398bb, +0x1ebbf980, +0x11ff0869, +0xe3473e5e, +0xf0bd5a85, +0x1275b042, +0x4b368439, +0xab10a94b, +0x225cb75c, +0x652007f0, +0x5accde23, +0xdbf73e50, +0x366aaf02, +0x919fbd20, +0x6af74c04, +0x1799d05d, +0x98d1a814, +0x4027673a, +0xd0a2bfa7, +0x0cd94739, +0x31e768a2, +0xf02192be, +0x01e034d6, +0xb2518a3c, +0x85243683, +0x3172a561, +0x2dfcdbb4, +0x01bce4ed, +0x4e2bec0e, +0x9ccf66e6, +0x8dc93608, +0x89f2ee8f, +0x05c2a597, +0xbc96700d, +0x5b9c4813, +0xb555b35a, +0x91f79b51, +0x3e6f6be2, +0x601867d0, +0xd533e0d5, +0x5dec61f1, +0xa184c4d5, +0xb7550dca, +0xd94ba747, +0xa2b713fb, +0x96469dc5, +0xa345da28, +0x12862a1a, +0x41682485, +0xc2fb7a90, +0x6f4411b0, +0x4df74bb5, +0x0dbe2019, +0xa1c7913b, +0x8506dbdb, +0x2c906b16, +0x3ead00e1, +0x5c04ff59, +0xa244cb70, +0x1dfe3391, +0x5ccbd49f, +0xcfc00508, +0x0a1a587a, +0x011793ee, +0x245cc241, +0x041e25da, +0x7dfef068, +0x1aabc0b6, +0xeae496c3, +0x3753d555, +0xf40e0b59, +0x2a2f49e7, +0x49429fae, +0xb4ef028e, +0xd030c0f6, +0xe20687b9, +0xf613f28b, +0xc7f9131b, +0xf1a23bff, +0xbfc7d387, +0x7c55bc91, +0x69dc960d, +0x10099c0d, +0xcedd2435, +0x843645e9, +0xcfb890c5, +0x9cdf5ebe, +0x470be8d0, +0xe6d4551d, +0x8c45c41c, +0x8407af6f, +0x9eac57b3, +0x13668237, +0xd7c23680, +0xc1c01c82, +0x7d8456a3, +0x0c6e3408, +0x21694f0c, +0xf9a300b8, +0x00619951, +0x978f012e, +0x4383dee3, +0x68db8e89, +0x65171ba5, +0x8a42c1a3, +0xadb0024d, +0xf12c2947, +0x5baae7c4, +0x5ccfa8c3, +0x1f046ea5, +0x44cc2d96, +0xc351d46e, +0x500cdd1f, +0xe5b78c8b, +0xbb7c4824, +0xf1d3ffb9, +0x7307df6e, +0xdbb73b80, +0xe43975b4, +0xc0f2d8d1, +0x5e8ef720, +0xf93eca0b, +0xed497a8e, +0x9b843aff, +0xa9f89078, +0xfeda5092, +0xa135dbe6, +0xf3381335, +0x3211b443, +0x6d8848db, +0xb7b26f84, +0x919faba0, +0xc194567b, +0x66cd8734, +0x136891f7, +0x1a55d2aa, +0xee0f6e2a, +0x105b5f3a, +0x5c9cbada, +0xae39ce33, +0x1fab98ba, +0xc3b32ad9, +0xed76fe75, +0xedee05f7, +0x55338cc4, +0xed377bad, +0xe570b797, +0xe2815d8c, +0x5f7d130f, +0xca68dce1, +0x2c9535f0, +0xc039960f, +0xbfa4f06e, +0x80fd2abf, +0xc1841b87, +0x2fcd1d08, +0x87de25fd, +0xb048c3e7, +0x0e485d58, +0x13363c80, +0x34bf8f38, +0xbc42dd72, +0x54efae48, +0xe58b2be4, +0xba03e3e5, +0xa1e1557c, +0x447ef110, +0x5d0525a3, +0x487f788e, +0xe2c795f2, +0x72778e2d, +0xdb38a2b4, +0xd9f60cab, +0xfc83e11d, +0x09b63ec9, +0x6a9ecfa8, +0x9090e5d7, +0x93fb5b3c, +0x668972e4, +0xb203c27b, +0xe33b0e0f, +0x74244ecd, +0x251de3c7, +0x6be34adf, +0x850f84b8, +0xd153167b, +0x7a1e7712, +0xbe765d65, +0x1bec4f72, +0x33b39e1e, +0x97475bc1, +0xb888c16a, +0xb0faf186, +0xae31fb4c, +0x8e3f993e, +0xfa5f33e2, +0xd74a4955, +0x2ba5dcec, +0xbfb78c2f, +0xe16af604, +0xacdc9d51, +0x540b0fe0, +0x77bf8e1c, +0xec456fbc, +0x67ec3998, +0xed30678a, +0xad102aed, +0xfa300380, +0x7315bc8d, +0x13bdd919, +0xcb67b17c, +0x644459fa, +0xb3e73471, +0xa2564494, +0xe4b6313c, +0xd1c39f05, +0xa79c3cc4, +0xce489328, +0xf91ec914, +0x511e350a, +0x4e316573, +0x6c672f9d, +0xf390eb43, +0xea00c63e, +0x3047c39d, +0xb148fc32, +0xacae01d2, +0xe6beb8f2, +0x30811cef, +0x06811d47, +0x46a53051, +0xab255e92, +0xb8a16123, +0xa0f648fc, +0x59fb60b4, +0x3a93c47f, +0x664aec7d, +0x241df22b, +0x3e46a3b5, +0x4780a654, +0x4531c0e7, +0xdeb68370, +0xcc363252, +0xcafbf428, +0x220fcad1, +0xf4ed231e, +0xa3cea43c, +0x51eefc0a, +0x1b0d3296, +0x76067a7e, +0x868e4ff8, +0xdb9c6b31, +0x2b321e9c, +0xfb3c2493, +0xfb0f1f0c, +0x7fcf85ee, +0x07de486b, +0xf5075d74, +0xfa1214cc, +0xe2cc87d3, +0x89a3c9cf, +0x786dc6ca, +0x2265f0c6, +0x9629032c, +0x14754d9c, +0x2bb2b6dd, +0x1ed918b5, +0x61631d1f, +0x3f4cbeb9, +0xed26222c, +0x8be6cd7d, +0x30401e4e, +0x46eddafd, +0x4c6da760, +0x8c8028fa, +0xe7a4dcdd, +0x6cce86a5, +0x31345864, +0x65b816f9, +0x2ee7eaa3, +0x32779132, +0xa036ce1f, +0x466e131c, +0x624a24ad, +0xb928e17e, +0xa88f41c9, +0x840bfb6b, +0x55d18fd7, +0xe52ae03d, +0xcfb8fa7a, +0xbb1f491d, +0x05ae4e36, +0x2c79711a, +0x394dec95, +0xad76ef99, +0xa8f521e1, +0x39369e05, +0xb69dc954, +0xa4d2090a, +0xfc46cce2, +0x4f04dbde, +0x0dcf09e7, +0x7108e8e2, +0xff9f7132, +0xbc4e4ea6, +0x6a5f457b, +0x2a9f125d, +0x341648ad, +0xe21c4991, +0xf005e53b, +0xe99c5398, +0x6a408931, +0xd79dff9c, +0x7387f210, +0x54d06459, +0x894e7968, +0x553962f0, +0x8d5774e1, +0x901b23bc, +0x37d50929, +0x29261592, +0x672aff18, +0x520c147e, +0x762b5001, +0x7d4895a4, +0x8a275b28, +0xd11b0b31, +0x9b2e793f, +0x0a7c0e4a, +0xd069ff0a, +0xcb9e969f, +0x83e57c2c, +0x7a173e86, +0xc0b942b9, +0x9f92d7c1, +0xceb0dd48, +0x2288c23e, +0xf04f3aea, +0x7070dd8c, +0x9e6d3175, +0x0ef91868, +0x70afbbfa, +0xca4ab0e0, +0x4bce8d8b, +0xba451c73, +0x2226b1e0, +0xfab35b29, +0xa7080cd2, +0x40aec519, +0xddd5f555, +0x0ccf80cc, +0x3c41a5f6, +0x1087a842, +0xd360d9aa, +0x54ed0cf8, +0x30e84f3e, +0xe35ee179, +0xba77c7df, +0xc95b8718, +0x8f9e3326, +0x91a38541, +0x2e2c1417, +0x66fe4233, +0xccbe1dfa, +0xbc462bfa, +0x08b3491b, +0xd725b8ef, +0x40130b15, +0x9a1735b0, +0xfc8c712c, +0x957dc32e, +0x32469621, +0x8c206467, +0x3df9bc04, +0x8a7f64a1, +0x33e566ba, +0x8fef3592, +0x6eca8c9b, +0x568e8c3b, +0x8a7fca59, +0xcd08e64b, +0x9b0b50b6, +0xf8a06809, +0x48e4bcf0, +0x9cf3dea6, +0x05a362c7, +0x70344335, +0x158b6f75, +0x860203b2, +0x05d3d58c, +0xd0033840, +0x13df6905, +0x0bf2259e, +0x140ba661, +0xf2dd3003, +0x3d86b8f5, +0x83a01dab, +0xb27a1e3f, +0x166dfafe, +0xdfc863db, +0x662afc1d, +0x8818135d, +0x7f3e5dde, +0x93154f83, +0x99e0b7c0, +0x38262cc9, +0x4b79e817, +0x18be6c95, +0xc8b68a5c, +0x761938d8, +0x52c908ed, +0x497a3f27, +0x57703d83, +0x2871d504, +0x8fe1cb42, +0x5be574f8, +0xead2d54b, +0x9ef9f50e, +0x2eb219a8, +0x4e670af6, +0x9750959a, +0x8a02b796, +0x033510c8, +0x94d71241, +0xb3982fb7, +0xd859c810, +0x0b091eef, +0xc3ec2b08, +0x84ac0bff, +0x2fef7239, +0x997a69bf, +0x240484fd, +0x53750470, +0xf2c86f17, +0x1e50246e, +0x2556a05e, +0xa274663b, +0x494c7e36, +0x9b5d7265, +0xb8540ac8, +0x78bcc207, +0x698dd2f4, +0x031cc19f, +0x4de7a1f4, +0x3a328579, +0xb9debba8, +0x9cdb48c5, +0xcb9b99a3, +0x0967d913, +0x9523995a, +0x9fee74d5, +0x58afa619, +0xd0ca5b9a, +0x10b153c6, +0x6f438483, +0xd9cb5951, +0xef87c303, +0x6102423a, +0x4d94b250, +0x3ee93dbf, +0xcf35c626, +0x30dc3795, +0xb50dd24e, +0xacef6e7e, +0x470eed1b, +0x02885e5f, +0x91fea8f8, +0xa3be0169, +0xa031ba01, +0xaf0a23c4, +0x97680c12, +0x2ee5b1cf, +0x572b2b2a, +0x6680c962, +0x4653632c, +0x3305045f, +0x84d17612, +0x203e53d7, +0xe4820d71, +0xec5e56f4, +0x2ce2474a, +0x8a18e10b, +0xe227c2d6, +0xe5a43495, +0xbc983689, +0xb3e8b14d, +0x66ce29b3, +0x3a16aee9, +0x46143be1, +0x1f144d28, +0x61ed936e, +0x001ddee2, +0x5ba81c80, +0x88705e50, +0xeae436f9, +0xc7c78d65, +0x53901b1d, +0x18723060, +0x01e05845, +0x3a1e0ee3, +0x54655a01, +0x464e81b5, +0x5ed92869, +0xb9a41334, +0x37a08887, +0xead67c77, +0x81bf5637, +0x35b768bd, +0x165ecdcc, +0x87917610, +0x2bf6a464, +0xced655d5, +0x81648bf9, +0x91928304, +0x2fcd779a, +0xec1daf54, +0x37146397, +0xd5951e77, +0xc6f5a3a7, +0x69e3485e, +0x2f497763, +0x765447f7, +0x2af61481, +0x0bfbfc68, +0x26ba850c, +0x81a9fd83, +0x20915edf, +0xbc5691ee, +0x0777fc42, +0xb0dfd38a, +0x47008b6d, +0x4745d78d, +0x02b8b24e, +0x804f9919, +0xdeaae416, +0xff57680f, +0xde89d93e, +0x015fe7ae, +0x02d52f34, +0x9b9e1704, +0x399fd1a8, +0x2276e119, +0x8f8e11db, +0xc1c67a73, +0xae54d563, +0xcc091aab, +0x28e2a0d5, +0x26deea1d, +0x21e9ab32, +0x2e3d2a51, +0x4d275083, +0x1d06e495, +0x8393eea3, +0xce6e009d, +0xcee2deee, +0x0848ebfb, +0x71c08d4e, +0x3f795cb4, +0xaa8dbb35, +0xba5e118b, +0x0e2329c7, +0x4fe738e5, +0x53148868, +0xbfe7bf13, +0xee8f5321, +0x08b9fe2a, +0x86f18ae5, +0x4c018dce, +0xe12b095c, +0x08cd0522, +0x456990eb, +0xa2a01683, +0x8f205b75, +0x682320ed, +0x542e4e25, +0x631552af, +0x7958fa81, +0x1ca6bf18, +0x73f68b75, +0x477ba16c, +0xfb3558b3, +0x7db2348f, +0xe24927a7, +0xa11ad160, +0x2d8fc5af, +0x57827e91, +0xfaefd5c4, +0xeaf5a802, +0xcbb59a39, +0x324ff120, +0x1a99cb5a, +0x077fb217, +0x64a04405, +0x269fd81f, +0xe1b88b9d, +0x261625bd, +0xa5123433, +0x4823cece, +0x3dc175e6, +0xa72feb1f, +0xcbc0ed69, +0xcfa1490a, +0xf275e34a, +0x490a58a1, +0x4ca34898, +0xf349e73f, +0x336f8cde, +0x4de76f9b, +0x126afa68, +0x159a39ed, +0x36dd9714, +0x87012f30, +0x5aad2206, +0x8a56076a, +0x055fac3e, +0xefe3f459, +0x62edcb98, +0x45c063bb, +0x6ef4d6f9, +0xfc71ddb0, +0x03d1f624, +0x78e0c31f, +0xad4d56ab, +0x981be5d4, +0x97d7793f, +0x30c6fe68, +0xe8ef87bb, +0x30c871b1, +0xccb30ca5, +0xf34c4fae, +0xc3736416, +0x10d864bf, +0x1461802b, +0x2b36e157, +0xd0d72a7c, +0x4e749b89, +0x67c9a487, +0xc7d83b71, +0xf5fc81b2, +0x46fe296b, +0x8a65ee17, +0x29c6dc2c, +0x528978e6, +0xb1e4f9d0, +0x0d5f8d4a, +0xa8a047a3, +0x718b7760, +0x892c165f, +0xda3a1d52, +0xb643d4f4, +0x2da923b2, +0x93d31b7f, +0xbaab6351, +0x98a579fe, +0xe7c2eecb, +0x25608983, +0x93cfc214, +0x20147568, +0x124d8dfd, +0xa4da5a20, +0xd83943f6, +0xef6ada29, +0xb1e6531b, +0x7ce6378b, +0x55fa8d79, +0x5e5668bb, +0xa09ccef0, +0x595bfa40, +0xe1d06dbc, +0x6ad81c6f, +0x5e8f00f7, +0xad12cc68, +0x75271f12, +0x59bf6887, +0xdb9e0d67, +0x3012db0a, +0x097da918, +0xa7dfcea3, +0x7249fff7, +0xdd9d11c6, +0x039aa27f, +0xbc6cf81b, +0x43d9caea, +0x8289e30b, +0x24d72d74, +0x96b3a4b0, +0xc9972f5d, +0xa7643eff, +0x001d32c5, +0x9c81447b, +0xbb541cec, +0x80000f61, +0x8ff8deec, +0x92e17844, +0x5f1dd759, +0x7b99b8b4, +0x140ecacf, +0x654b81ea, +0x847dd9ff, +0xc8242802, +0xea3a15c3, +0x7713fad2, +0xceea2344, +0x25695dc4, +0x5d4af924, +0xc6bfcac9, +0x1067c10b, +0x5027caf5, +0xe051f97d, +0x9d9c127a, +0xaae9943d, +0x66648dcb, +0x70bb5e5b, +0xaaa872d0, +0x122d2c09, +0xfe12eadd, +0x5acfc75c, +0xcf30da23, +0x10ebc0a8, +0x6e028e5e, +0xbc7854c4, +0xc840899e, +0x65fc7b12, +0x95cb3525, +0x1ba5ab71, +0x56340059, +0x5d9785e6, +0x0925e381, +0xe4304166, +0x4ced0750, +0x533217ff, +0xbe1f316a, +0x9af2d67b, +0x81de4f87, +0x1709b31d, +0x6b1a69e1, +0x6e0a7de7, +0x9ba9d568, +0x265b5e71, +0xc6ef2fa1, +0xf50dd374, +0xa34d2f0c, +0x2642e98a, +0x86c229d5, +0xc2c510f2, +0x6864c530, +0xbc0d7e9f, +0xa5cec81e, +0x78400a2a, +0xd44c3b79, +0xe4d20237, +0x4fe7d0bf, +0x57b9251a, +0xc48070e4, +0xe42f3189, +0x40ac0603, +0xb2266e96, +0x822f0c90, +0x4335f5cd, +0xfdcafd26, +0xf33b8707, +0x11eb1c0c, +0xde714855, +0x430b6d20, +0x8d074a50, +0xb9c45216, +0xf4f2cf65, +0xc2d7b598, +0xbe71b2f5, +0x14fdb41e, +0x9a45afe2, +0xd9d56376, +0xfc3b13c1, +0x4bd73bb5, +0xe20786ef, +0x83f205b7, +0x48adbab3, +0x66e1cdb7, +0xd4f602d6, +0x8607f5e3, +0xb6b1b8cc, +0x39e903ed, +0x05eb03be, +0x241cdcaf, +0x8f5dfb46, +0x6ce3397c, +0x84fe110d, +0x602c2ea7, +0x00db6cfa, +0x17b06704, +0x1853ff0b, +0x737d53c8, +0x1a2512c8, +0x322f4d54, +0x0e782363, +0xd3ddbc76, +0x991e532d, +0xa6b3cba8, +0x64357f64, +0xbf76fde9, +0xe75ba5f0, +0xedd27e32, +0x83ced89b, +0xa8f8fa78, +0x691f2f08, +0x3b82a2b3, +0xc541bd42, +0x52a6ffee, +0x99811265, +0xf36edd5b, +0xa824be85, +0xb9f40e72, +0x6ae76061, +0x610b1521, +0x10aab6cb, +0xc1de6fc8, +0x30c389bb, +0x254c9ee8, +0x62a2e342, +0x2fb9aca2, +0xde7a0a19, +0x8a539255, +0x31623181, +0x62c2c33e, +0xb7f8f012, +0x5a63726b, +0xeebeb387, +0x1e093994, +0x22824099, +0x0e262dc0, +0x4053a119, +0x1908a913, +0x843e8856, +0xe448d338, +0x629b2e01, +0xbe3727d6, +0x4bf39a8a, +0x17e68fba, +0xbdbef3de, +0x64bef79d, +0xc2de3d5d, +0x7916a48b, +0xef1738e1, +0xe9279cf3, +0x9bd4db72, +0x0e94cf93, +0x3d1310ba, +0x63aa14fc, +0x8a3105c2, +0x794b5d9d, +0x58edb624, +0x97b9d64b, +0xfd3d67af, +0x5843b172, +0xc2936063, +0x6aac05c8, +0x24d04f1f, +0x4f52337e, +0xa86c00ef, +0x9419b175, +0x96c214f4, +0x4f8bd99f, +0xc2789376, +0xa8df4c1a, +0x9c957103, +0x70ee3f94, +0xc68ec0f0, +0x88e5b158, +0xe437553e, +0x6061b599, +0x49e16eda, +0x81a1a742, +0xb97d245e, +0x06540ace, +0xfec63700, +0x2fba1921, +0x606736fa, +0xacff32be, +0x320c9cbe, +0xa88792e2, +0xd8c30e3e, +0x37c29d31, +0x4725fc2d, +0xfde5761f, +0xf557589a, +0x3280ee0f, +0xb1970e55, +0xdd730861, +0x221715f6, +0xe4924bb5, +0x47cab452, +0x38da5f4e, +0x58ca678d, +0x79dbb8ae, +0x6c6073e0, +0x216e08ee, +0xb5607963, +0xb57e694e, +0x3b2881e7, +0x9ab3b9ca, +0x19af94e2, +0x2d7a2230, +0x928def90, +0xc4181aad, +0xc9140761, +0x1261c8d7, +0x27bd956b, +0xe7461d8a, +0x914657d7, +0xc0c9aedc, +0x54de374d, +0xdbb4b5e7, +0x7c90082c, +0x69c8dc9b, +0xafa47ea1, +0x9f41cd29, +0xaee1f198, +0xd5ebb222, +0xb58f057c, +0x5d5087ce, +0x84eeb97a, +0xb0a8f9dd, +0xc701d219, +0x2a495b6e, +0x5657ec99, +0xf753dad4, +0xdb95ea9f, +0x84d79e3a, +0x52c56fe3, +0x11d1327c, +0x9e13c93e, +0xa68dbab2, +0xba591db8, +0x1c13954f, +0xb142a5d0, +0x15623f94, +0xaf8e1e6d, +0x40b1fab2, +0x8f1813ab, +0xae7b2d21, +0xf750466c, +0x2296eac3, +0xa84e6594, +0x327e83dd, +0x87ba1d82, +0xb402620f, +0x61c951d3, +0xbe0ba060, +0x8104629f, +0x6a633fe8, +0x774011e3, +0x81b57af5, +0x615d8ae4, +0xef1baee7, +0x9a1b7ce9, +0x04b2d5e0, +0xdd30c496, +0xa7342a1b, +0x02bae8f3, +0x12dfeb1d, +0xfd0f92e1, +0x95996ef1, +0xcf5cbd44, +0xc4d6e248, +0x2068ccd7, +0xf1f27255, +0x03b4ad3d, +0xf76c2b1e, +0x5509f138, +0x7852596d, +0x64d936b8, +0x5e3ee042, +0xf1cd3813, +0xb764c1a3, +0x5e663585, +0x01c0b019, +0xe954d5f0, +0x555f2c2a, +0x4cee5ee3, +0xf34f1289, +0x8b970999, +0x1a8e737e, +0xd9692fbf, +0x9c9a63fe, +0x3adc1163, +0x7a0dcd14, +0xdc62abc2, +0x1d7da627, +0xbb59f89c, +0xfd18f37e, +0x648a65d3, +0x105cb71a, +0x003ea86b, +0x4420943c, +0xa450599e, +0x6ed9d057, +0x3d61a064, +0xd6cdd22b, +0xf9593522, +0xbba8503a, +0xbed44e34, +0xa4519fd3, +0x9548f99d, +0x0948fe6c, +0x4fb3daee, +0xf7346374, +0x61e9f994, +0xbbad0508, +0x44164123, +0x6f8221ee, +0x3c970da9, +0x7a75df43, +0x937ba5d0, +0x42b62427, +0x8ecd3023, +0xbedc6353, +0xc454ca87, +0xb5a3a80d, +0x2e84eaa8, +0x9dcbf4a7, +0x7df15491, +0xae6d2cdd, +0xef1faf4c, +0x76659acf, +0x63d9de60, +0xec0d238b, +0x18df2a7d, +0x42974743, +0x7e15e43a, +0x69a36679, +0x77930aab, +0x013ef608, +0xfea8a298, +0x66fbccc4, +0x8893cf60, +0xc1e77808, +0xf800d965, +0x0a682dd4, +0x96ba89c7, +0xd4bf7127, +0x39ea0678, +0x7bccc8cb, +0xf22d4336, +0x54bfd624, +0xf5fe5866, +0xfca92d4f, +0x3803d696, +0xfe311b23, +0x89411ca3, +0x14584a7f, +0x6a6bc816, +0x9179dbbd, +0x69295e19, +0x2dcf9e4b, +0x1c3cd0db, +0x17d80996, +0x61d9f4e9, +0xd1c9820d, +0x950a4880, +0x496bcbed, +0x12cf0c49, +0x6a87caab, +0xe9ea3a6f, +0x508b87c3, +0x415f90ab, +0x55b029c6, +0xa73a1f25, +0x14d30904, +0x11011bb0, +0xb6ac4579, +0x08e20284, +0x68b416f3, +0xdffea278, +0xaebb6f35, +0xe61cc5ce, +0x48bf9f14, +0xa5c4db52, +0x6d42f1ce, +0x789dde5b, +0x432c68b9, +0x01491413, +0x3126dda1, +0x39c0b531, +0xeeff5205, +0x370e0946, +0x94d1e3d2, +0xc2805835, +0xbc8d4cd6, +0x66a52646, +0x5d634b4d, +0x982ba1ff, +0x66539681, +0x2266e179, +0x9cca115d, +0x9a9097bc, +0x814f362e, +0xba78bd18, +0x867ad5c3, +0xcd74a1fc, +0x923399f2, +0x04cfe5e2, +0xf31e2a8a, +0xcebda3e5, +0xae458af7, +0x842c5840, +0x87a51389, +0xbe49776d, +0x795a7243, +0x78736876, +0x669951a6, +0x5bc8b0dc, +0xf4924126, +0x1c86df25, +0xc02a8149, +0x8105cb41, +0x29acabb7, +0x4aa5fe9f, +0x6b4bf8a9, +0xd352c6fe, +0x14d1f0cc, +0x796cc94a, +0x250a2644, +0x6d65365d, +0xceca455d, +0xbf90a06b, +0x6b8b5fc3, +0x0b9cdf01, +0x64268442, +0xbfb989d1, +0xa93c212a, +0x080cac0a, +0x42041dae, +0x8880f31e, +0x48ce099d, +0xdf9f4ab0, +0xd38bb7c9, +0x927fc6c3, +0xdd812f2d, +0xa3265578, +0x1fb22c75, +0x1d1fcfd9, +0x5f9a2bce, +0xf1db9b27, +0x799e3ae1, +0xd33e8a2d, +0x3d79e86b, +0x96564870, +0x466400c9, +0x56bd7357, +0x00a1df08, +0x4a588b54, +0x1539cc2c, +0x151fe1b1, +0x5969e86d, +0x19e6883a, +0x9d2d7ee5, +0xd6dce383, +0xa782e0cd, +0x7e90f248, +0x134f3896, +0x7f438215, +0x1170f924, +0xbeb73759, +0xacca3747, +0xfd50f8dc, +0x9d6e7eeb, +0xc5a7fac6, +0x817fc8eb, +0x658383db, +0xcd103989, +0xf5f3d4ed, +0x04f2a002, +0x5aef3dab, +0x7f60dbc0, +0xc18a3aaf, +0xd83c3852, +0xad3946c4, +0x9e9aa1a4, +0x758b7a60, +0x8db48c4c, +0x5a892d88, +0xac5e4cb4, +0x95a6b8b2, +0x4a038229, +0x61b02712, +0x6885c550, +0xa17acab2, +0x32e30c25, +0xd79f6a01, +0x45a447b3, +0x81115a47, +0x8cc0ae5e, +0xa20504e4, +0xc62dc958, +0xb2d4a0e9, +0x03301fd8, +0x384a5851, +0x089088a6, +0x3d6bfdfb, +0x4037055d, +0x1c5d1f63, +0x64890de7, +0x3a9f4e42, +0xef0e091b, +0xce710607, +0xf9178e71, +0x6b094cdf, +0xb015f4c3, +0x6ac6e9b8, +0x59084168, +0xec0ecb12, +0x49317cc6, +0x4b67cf18, +0x55f166c4, +0x1fb400a5, +0x3b123978, +0x8d93182a, +0xf44aa39f, +0x6beb51c7, +0x86e565ec, +0x13b7fab6, +0xfd0a10bf, +0x1ddca05e, +0xc9d0cf6b, +0x499aa2a6, +0x45d26774, +0x829cc560, +0xd5a8db57, +0x50a5f94c, +0x87c51c5a, +0x74b4338f, +0x4982a803, +0x41d71dc7, +0x664875db, +0x3d45902b, +0x9909a267, +0xc3019f3d, +0xebead312, +0x9c930acf, +0x1f2110f6, +0x6e7738da, +0x651cf45f, +0x21062f09, +0xd8e3ad6b, +0xfcb0fc54, +0x1739bfda, +0xde50a5d2, +0xdbbce590, +0x64ef866c, +0x8dc2a886, +0x998db8d4, +0x74e1db0a, +0x3114f719, +0x7b8119c2, +0xed92c437, +0x9050dfee, +0x622a2934, +0x3941c540, +0x9a1f7bd8, +0xf330c308, +0xb6913956, +0x67ee777e, +0xc87c9c77, +0x8ae280a7, +0x3b9e19b3, +0x5dc8b40b, +0xa8e203f5, +0x5c0b05a5, +0x0ba2cfec, +0x2cd44d60, +0x7bf21a07, +0xec01ae45, +0x8be5938d, +0x0a143c01, +0xac99d156, +0xc32ccf98, +0x2cc4bfb1, +0x0dadb011, +0xbe9622d2, +0xce6672b5, +0x8d9e2508, +0x7f5940e5, +0x9a835ba3, +0xe87fc4cc, +0xf553b901, +0xb4afefd9, +0x0b75b110, +0x249650f8, +0xd3cfaca0, +0x383bd397, +0x257f570d, +0x017653e1, +0x08e4af7f, +0x0e747d92, +0xc99b319c, +0x0d6d1bf0, +0xc8b5ef77, +0xbc7d2f13, +0x71bf4cbb, +0x25ad8329, +0x86526c02, +0xd5eabf73, +0x1c4101ea, +0x2076f5b4, +0x14c34dde, +0xd8f21798, +0xa803dfd7, +0x55f028c5, +0x7bbd9afd, +0xfca207a2, +0xa518fd29, +0xb5b94c54, +0xf4d5628b, +0xd57a1d46, +0x8cd84619, +0x19c7ce96, +0x0fff8347, +0xa9d0376b, +0xe82e4e82, +0x0338c4f4, +0xae64097c, +0x32e24343, +0x8d68d382, +0xda450cc8, +0xfa3c7140, +0xa44c58cb, +0x0a543b3d, +0xb0b17cde, +0x6e6852c0, +0x30e9e128, +0xa182e7e5, +0x225ce8b1, +0x360c311f, +0x434c79a3, +0x49244e8c, +0x0f8922db, +0xccab9eb9, +0xb43ac0d2, +0xa029d5f2, +0x39585abb, +0x650e899f, +0x1e49e177, +0x52fb2332, +0x3d6937de, +0x09a77f72, +0xcea46278, +0x4e63cbaf, +0xfe0b22d6, +0xf2370e35, +0x4f857ff2, +0x4c8b7629, +0xa63f572e, +0xc8687a0e, +0xf17a4cc7, +0xf42214ee, +0x4671c4ed, +0x108d8b6c, +0xffea7be7, +0x2f939565, +0x7f6d38fa, +0x217f6531, +0xb7e0e9e0, +0xc4899f8c, +0x1c8369a6, +0x461bc601, +0xd1b9db14, +0x2b7658fd, +0x72f2aa4d, +0x731d6dcc, +0x980bd60f, +0x47c63563, +0xa831bff4, +0x29a87985, +0x144a0b44, +0x973cd1fd, +0xc65183bb, +0x5f722726, +0xb81d7cc5, +0xbf6f8aeb, +0xf2f55377, +0x81ef0169, +0x2c38c831, +0xe46fbd12, +0x676363b1, +0xec49d143, +0x88dc8875, +0xad139d24, +0x152db365, +0xaf5140ec, +0x5c2a6f5e, +0x14c51977, +0x2cc3ca63, +0xb6e3333a, +0x5770c092, +0x8abaf722, +0x903e2689, +0x43aedb30, +0x801869f6, +0xe861d741, +0x1eb2f523, +0x5d127121, +0x5d234d6e, +0x7de96540, +0xd2d5b611, +0x174986ab, +0xbed059c1, +0x8ae404f2, +0x91a5d5fa, +0x685db3f2, +0xfbf781a4, +0x58772ac9, +0xaf43f6d3, +0xd42e9ec2, +0x2878a76c, +0xa3b464b2, +0xb4a5d783, +0xab53c4fc, +0xab8f4e52, +0xba696e64, +0x5910c6a2, +0x3da0bdfd, +0x9ad207f0, +0x955c3f26, +0x302d2944, +0x0f35cf2a, +0x5a01aad5, +0xe744604d, +0x80d2eb92, +0xa5196aee, +0x1d71baef, +0x1fc32ab3, +0xce146e62, +0x0a78342d, +0xe232c455, +0x9c4ba843, +0xd33a1d07, +0x20679223, +0x8dbcf689, +0x8c9c9537, +0x3ab3dda2, +0x1ab7a8e6, +0xe9bc8344, +0x1e9fc1f9, +0xb8b89183, +0x0431c758, +0x015e065f, +0xbbe3a055, +0xbdb48c63, +0xbc85c092, +0x3c515d0e, +0x758193a2, +0xb6c362f6, +0x02ac1026, +0xc6778959, +0x81b3dd4d, +0x3ea973c6, +0x6ae299cc, +0x25cfed87, +0x1eba458a, +0x82772273, +0x44050476, +0x6199fa7f, +0xd750b234, +0x06ea4750, +0x71a2489d, +0xd62a9f76, +0x62cd4aae, +0x532b8e79, +0xd142f52f, +0xad481bd5, +0x270eebfa, +0xa9ce6647, +0x2f78a75d, +0xfed42de5, +0xa174f0ba, +0xc8d48f77, +0xb661146e, +0xe242e149, +0x3237fbb3, +0xdb54bc1e, +0x96922120, +0x0a2b05aa, +0x2a0e1ea1, +0x6e2d0e72, +0x262578d7, +0xf42594fd, +0x19e222bf, +0x12faec09, +0x000585d7, +0xfeb9d6c8, +0x970e948a, +0xe396b594, +0x5653259f, +0x1c8ecf09, +0x6bc18547, +0x38b16ae8, +0x9cb53417, +0xabbdb26d, +0x124cfe90, +0x8d69e0fc, +0x514eebba, +0x65ab836c, +0x9a4c341a, +0xdb269c35, +0xbeb45119, +0x9cf31be1, +0x0e81ec2a, +0x7152516c, +0xa3688a21, +0xdd5b18b2, +0x7c30043f, +0x0584941e, +0x6e1fe654, +0xcdb2c3dd, +0xaceac30c, +0xe651d8b9, +0x5108747e, +0xc311b5bd, +0xa0b6c180, +0x4146661f, +0x205c9ac7, +0xd51ce235, +0xbacd748c, +0xc87abce0, +0x4af0e7ac, +0x23186ae7, +0x8a0b1305, +0xc5e6fcf3, +0x18c4ef8a, +0x1dccbb4c, +0xa38aa952, +0x90754ce3, +0xfee5e580, +0x92199e2a, +0xb7903c37, +0xc1bbf556, +0x319b7b35, +0x12184c2e, +0x017cbaad, +0xa2f43567, +0x808c169e, +0xacdbc255, +0xf93b60b2, +0xd76f0a6c, +0x8515e29f, +0x629c8494, +0xa5b14857, +0x207892c1, +0x72d5c2c3, +0x3192fb06, +0x5a72b653, +0xe28bb8e6, +0x4d8b0f6e, +0xcb75a618, +0x2aeba2c2, +0x384596a4, +0xb5a1d1d0, +0x3b201d3b, +0xd381c0c9, +0x2036e793, +0xa43e66ba, +0xcf418e19, +0xce204932, +0xb4dfbbba, +0x0f8bc38e, +0x42cc01b1, +0x0a7aa780, +0x754b3b20, +0x0c331205, +0xd4b09665, +0xabdfb8db, +0x510ca3e8, +0x87bba63a, +0x801fb97a, +0xd28a0b32, +0xe6a782e9, +0xa5aba294, +0xba7336f3, +0x000cec42, +0x01198687, +0xfd8dea1b, +0x43449099, +0xdb214387, +0x2ebaada5, +0x782c00cd, +0xf968dccc, +0xb57c9058, +0xbc1bc852, +0x2c895b8a, +0x099ed9ab, +0x0dd9e2da, +0x3122e20f, +0xc3c03d62, +0x664064aa, +0x529680eb, +0xe65dba62, +0x657e34fb, +0xf8f6a7db, +0xb2f5b2da, +0x09a288b9, +0x76ec4b94, +0x251864e8, +0xc6e7918e, +0xfc5703e1, +0xb20b64be, +0x6a17d3c4, +0xbb8d7797, +0x6f53766e, +0x6b101408, +0xde7d4449, +0x5f81fdfb, +0x872d4bab, +0xfc78f6b1, +0x2192a021, +0xba6d0fbe, +0x08029c97, +0x57726100, +0x034bdc74, +0xea13eaae, +0xdcd8b1a5, +0x0890a32a, +0x04797fe5, +0x296c290a, +0x2a690f91, +0xaf3ffa70, +0x1301490b, +0x5206b9c4, +0x6414cff7, +0x7682511d, +0x51455342, +0x9b3c1bcc, +0xfd991064, +0x37e35770, +0xa5887dd8, +0x30854728, +0x0fd0a46e, +0xbf338eae, +0xc1d88b92, +0xe2b89eff, +0x34d1f41f, +0x94bb0850, +0xcdaa693e, +0xc506d140, +0xf709bf8c, +0xcff02061, +0x09e44094, +0x750cb588, +0x29f54492, +0x999a2513, +0x957aadbd, +0x7dba5c8d, +0xf0fde33a, +0x05858736, +0xb698cd3e, +0x4ee6c9d1, +0x87ee8bb7, +0xe0904232, +0xc8380b62, +0xaeae98d3, +0x20c5ffc0, +0x4f2d26be, +0x749e7528, +0x7ff79a9d, +0xefb16238, +0x94ee8297, +0xdb610b18, +0x22791550, +0x39d92c01, +0x9b2b427f, +0xb660b990, +0x4a584c3c, +0x1ae2d3aa, +0x0e898286, +0x0951b531, +0x85bd395b, +0xc0991dc5, +0x7c326670, +0xc4d316e9, +0x59951801, +0x00310e16, +0x16c63f56, +0x776e3bda, +0x401db0af, +0xc9a58678, +0x5b396092, +0xa4b7ee45, +0x560ed7e5, +0x1aeb5071, +0x144f9e75, +0x0672b658, +0xfd7e0aab, +0xf7c7bb29, +0xa75add3e, +0x1b62165f, +0xaeeba3ef, +0x671c2cf0, +0xb91ef8c0, +0x23536d1c, +0x38126f99, +0xc952a5aa, +0xdc422896, +0x50d02584, +0x88dd5852, +0x48b35581, +0x3785fbf0, +0xc21b73c8, +0x8efa2499, +0x3a3a19da, +0x96effc9f, +0x8b657ade, +0xb66ed8b0, +0x95b402ad, +0x01c05932, +0x6dd63212, +0x8821c265, +0xe4ae80e6, +0x7ecdd5d0, +0x2a00e909, +0x8a915d11, +0xe0e8fd8b, +0xc2ef25d4, +0xa1399e74, +0x5b431c1b, +0x4191bb2f, +0xaa057d14, +0x63ffe2d2, +0x4eb74fc4, +0xd538bdeb, +0x6356c9f6, +0x7f88bf20, +0x311c5079, +0x5d0e3242, +0x4fd5df5d, +0x46858033, +0x5df48b89, +0xd1e61f4e, +0xea81b12d, +0x2f221848, +0xdcc36267, +0x03413ede, +0x0415b4df, +0xf8cbf4ff, +0x22a1a79b, +0xa47feb11, +0xc3b888e3, +0x681fc024, +0x88392152, +0xe9ec56f4, +0xd162c7d5, +0xb507c3cd, +0x13d94fd1, +0x55b61c58, +0x57f864ef, +0x41bf3ab3, +0x61090115, +0x68f09042, +0xac77badc, +0x2be78447, +0xfff8be92, +0x18628a5c, +0x1cac9670, +0xa2a93e52, +0xa5a0731b, +0x7634111d, +0xace41390, +0x8af0573d, +0xa4e0fb21, +0xf251b09b, +0x45632a24, +0xc17c2433, +0xdf65ea7f, +0x068abb04, +0xa137fa5c, +0xef4972ad, +0xac6faf35, +0x49ce9e8f, +0x1210b19a, +0x147632dc, +0x8c00fd54, +0xeb32458c, +0x42b3210f, +0x8f62e9f0, +0x865317a7, +0xcc8f1b82, +0x2fd8bf5a, +0x68d6d45f, +0xa9eadcc2, +0x2b093d5d, +0x8e2be89d, +0x95365a6c, +0x6cf41ac0, +0x641730fa, +0x6dd42e5b, +0xbac0d14b, +0x7ee9d6f3, +0xbfe2b1e4, +0xa3bf8144, +0x0278b03b, +0xe50f7bdc, +0xfd0ee450, +0x3bf5a255, +0xf1768173, +0x6babf575, +0xd22835f6, +0x4cb694d4, +0xbf21381a, +0x00342e1a, +0xaf3cd3db, +0x3927db7c, +0xffb9ba73, +0xf93ff570, +0x92abc6c1, +0x96d02678, +0x7be345f0, +0x0dd79ed5, +0x4727d538, +0x9488dd4e, +0x533d3829, +0x7cca4699, +0x6cd7aa97, +0x1598f3ba, +0x512d1e2a, +0xd81a3dbf, +0x60889f74, +0xe350e58d, +0x9fe89c95, +0x1dc56c74, +0x5f1f8ef1, +0x270f19ae, +0xae75f09b, +0xa5165dcf, +0xf3967e0a, +0xa4995ac9, +0x7e0d7334, +0x4fcf0472, +0x813a3870, +0x43b24adb, +0x57340d9c, +0x83b36708, +0x8a0f08eb, +0x08f455d1, +0x0a459e25, +0x9d113460, +0x3651093d, +0x96b4ceac, +0xe5776674, +0x3a0ae52e, +0x81f36b8d, +0x358bbaac, +0x951e03d1, +0xed734f18, +0x30cb221c, +0x6e101409, +0x71b11588, +0xa32fceaf, +0x6588b0bd, +0xaa38da15, +0x1d25c6c1, +0xda0f96ee, +0x4e0e5c0c, +0x31f67c1c, +0x4e6848b2, +0xe5e4a4fa, +0xbb5a7131, +0xc99c3710, +0xa36e8350, +0xe76acd94, +0x2e489e2e, +0x9e95bd2f, +0x3755d13e, +0x1bdefe00, +0xa725c338, +0xd880d570, +0xb501b101, +0xcc591bd0, +0xe6aa0a0c, +0x9ca86fbf, +0xe51bafa3, +0xe35898c1, +0xbaa85e23, +0x92cd6f9a, +0x5619ba9f, +0x95d18b38, +0x62ea27e8, +0xe9edb051, +0x2d955ce9, +0x8933f694, +0xc44bbb67, +0xfde799cf, +0x59db17e2, +0xb204b0fe, +0x6e1b0351, +0xa3e77069, +0x4fca6998, +0xd6cf2366, +0xfe495119, +0xab0609ba, +0x6e186cd9, +0xc058c7dd, +0xf2739d5c, +0xfe163244, +0x998ae99a, +0x32223bfb, +0x2f6715aa, +0x24fc0abd, +0xe3b9914e, +0xec29ad85, +0x0dfd84e6, +0x3c239a27, +0x6e190515, +0xefe85f88, +0xd592963c, +0x86910bda, +0x6e6d4fcc, +0x89ad3caa, +0x8210857b, +0x23b5632d, +0xbbea916f, +0xc24c5757, +0x6e305396, +0xe1bc5a34, +0x500282d3, +0xe6194de7, +0x3bebac67, +0xaa652e07, +0xbd9b70fa, +0x0a0636b2, +0x1b1bcfb0, +0x76e5d666, +0x47b0b5fe, +0x17b8b01b, +0xe2e75557, +0xada97a20, +0x0d5f1ad1, +0xcc8269fb, +0xa1299db4, +0x57e0e5ad, +0x7c6d12e0, +0x0abec5b7, +0x620e6a69, +0x4479f055, +0xf2d88f8d, +0xad565cd3, +0xa0aa91d9, +0xb5c0db92, +0x5679bf82, +0xb8734cda, +0x776e97c4, +0xc7905ba1, +0xaf8da4c9, +0xa3ee7b82, +0x33d0d097, +0x2b97ca1d, +0xef6f153b, +0x4fd309bc, +0x6c5de2d4, +0xcdafc76b, +0x705a8eb8, +0x51b9db16, +0x6b6cc250, +0x3a5dda52, +0xec49a447, +0x109e8b74, +0x99930c3e, +0x4d29ff3c, +0x24675c23, +0xf42b41a6, +0x71ae6ca3, +0x48cc16e9, +0x6e5c5eed, +0x8d355ea4, +0x4394845b, +0x8caee19b, +0xc150f8f0, +0xc63562f3, +0x72d7ba8b, +0x58cef581, +0x352cbe72, +0xbf902e86, +0x6eb773c7, +0xa458d5e8, +0xe68c7e76, +0x39af7076, +0x9b39a73e, +0xa3dd8d28, +0x18fc5c4d, +0x78036b40, +0x98181860, +0xc5490217, +0xd2b79891, +0x8a5963cd, +0xa1354cd8, +0x5a43eea4, +0x08931b31, +0x1ae88650, +0x6f74783b, +0x04893f68, +0x65975e21, +0x810fe6fa, +0xdb16c5af, +0x4f1c81a0, +0xce9c1291, +0x58d7c4ca, +0xb4f7510a, +0x8537a062, +0x5dfbaec4, +0x4f798a45, +0x2a94fae6, +0xb53b700e, +0x4dd3eb3e, +0x7104ea2f, +0x8771b1d4, +0xbf340d1c, +0x56e42542, +0x67783610, +0xabd591f1, +0xad237244, +0xca4ad81b, +0x165082a5, +0x159974cf, +0xac835491, +0xc08f694c, +0x9932cfcc, +0x1e7e1b69, +0x249cc41a, +0x6691cd73, +0x093f8406, +0x533d18a7, +0xc72a9129, +0xb27334ca, +0xc4e6e200, +0xa6adee54, +0x0e5ede2f, +0xf01a1699, +0xa96d63cb, +0x7854689b, +0x18c87946, +0x2327ccd0, +0x42578548, +0x24541719, +0x2db48b6f, +0xbacd5cca, +0xad8b6852, +0x3e7a177c, +0x68f61c29, +0x9904f185, +0xfb20d4cb, +0xa4c4f516, +0xed98de72, +0x69141650, +0x16a3a365, +0x8dfdd5dc, +0x9e281227, +0xcd08d03e, +0xf142a54c, +0x4cac9330, +0x8ac1856a, +0x03dc5480, +0x2c38f68b, +0x13aaf187, +0xbe343fdf, +0xba73535e, +0xeb53232a, +0x0b6edb4e, +0xb98d62a5, +0x694a51cb, +0x8e1bfe66, +0xa04aa534, +0x9f83a020, +0x9fc85b8b, +0x6c471208, +0x73d791a3, +0xe7085752, +0x1adffc08, +0x411080f6, +0x4eb21a03, +0x29a68e0c, +0xb85ca89b, +0x6bfe7872, +0x5e699155, +0x05ba32d5, +0xdd2e0f4d, +0xffe292b2, +0x18faeb96, +0x843c853a, +0xfff985c1, +0x7d76355c, +0x1b6e62e4, +0xce5170b5, +0xa5b03482, +0x31f4d72d, +0xb3f1a3ca, +0x517c2234, +0x60057b84, +0x014ab53f, +0xce8e2787, +0x67bf0309, +0xe0f6b5ee, +0x850aa1d8, +0xa625ffea, +0xbac0bdfb, +0x6bd6a87b, +0x2ec0fc74, +0x4a59bf85, +0xf05a8e93, +0xc63c7fb6, +0x9f442241, +0x518af319, +0x63f479b6, +0x76d88fe1, +0x94c751cf, +0x3f82ca1b, +0x1e2acc69, +0x82f32e99, +0x679462b6, +0x4208a2f8, +0xfa99492e, +0x4d14a239, +0x5f3bbbeb, +0xf545c5a7, +0x6d013dd2, +0xec004198, +0xa5f0b608, +0xe1b3cd5c, +0x764bc11f, +0xad5036da, +0x1107db44, +0x7360137c, +0x3988db16, +0x05db36f3, +0x13c7da82, +0xd149312c, +0x1aad0984, +0x4f0f2807, +0x0b012203, +0x7bb45bec, +0x531ac17f, +0x48a36fa6, +0x64397fda, +0x6a699de8, +0x319b372a, +0x87edf7e8, +0x11ae00b0, +0x81eea14c, +0x24ef0887, +0xcfbbc665, +0x3e0b1062, +0x23e0f545, +0x78d75000, +0x08410c6e, +0x570aba39, +0x20b11c4d, +0xb6ea580a, +0xca88b81f, +0xbc2e8cfc, +0xd866bb10, +0xa217db33, +0xdcce8c9b, +0xa9607f02, +0x83fab788, +0x1ca01b27, +0xd2ee044d, +0x1cfab78c, +0xc878d9bb, +0x431977b8, +0x0703817a, +0xbe3d124f, +0xedede69e, +0x945d9c98, +0x11ec0a3f, +0xfa1282ec, +0x18a9e594, +0x5e37ac88, +0xf475062c, +0x0d1c90cc, +0xe3e5ec12, +0x1ae8b129, +0x9cc2d33b, +0x1d15df41, +0x2cd68cc1, +0xc93ce32d, +0x4d4a9829, +0xe8137cb1, +0x735672fe, +0x197a6e45, +0x1448e416, +0xfc22a411, +0xb447a821, +0xfbba4874, +0x5d9a68f8, +0xdaa0f4aa, +0x744f7bc1, +0x571543f8, +0x4eca1a69, +0xc451d397, +0x674ba2b7, +0x0696803a, +0x7029efa7, +0x9d4e7b1f, +0x171e2a8e, +0x361fc178, +0xec7d9261, +0x5119ac5a, +0x4b58e5a0, +0x46229f11, +0xc245c936, +0x76672b52, +0x98180f35, +0xe705ef4e, +0x2f7ca1bb, +0xc7c48606, +0x4792fea1, +0x286c2848, +0x1254e23c, +0x7fac2594, +0x180b740a, +0x227376d7, +0xab52b80a, +0x9ec8e8fb, +0xbdb359ae, +0x7863b536, +0xbca1e81f, +0x7b7040c2, +0x9372710d, +0x293c686d, +0xbb443f18, +0x7bed421f, +0x8ae51ed8, +0x71975d4f, +0x3b6b209b, +0x78552e6d, +0xaeade0d7, +0xe8b0d2fd, +0xa731a07c, +0x4851e876, +0xef784810, +0xd5b90599, +0x82a93c0e, +0x8f026333, +0xe6192683, +0xb10d582f, +0x6a7bd80f, +0x191a803d, +0xd7dc5851, +0xb32e5a34, +0x0f3ada49, +0xa5e70bc0, +0xf2ebc9fc, +0x239dd30a, +0x823c2baf, +0xfbc6a10f, +0x3d797d45, +0xea7b99da, +0x73760b2e, +0xadb3a277, +0x0736bb65, +0x78ad7ed7, +0x786335ad, +0x9eb38905, +0xfe6bd405, +0xc453477f, +0x7eb7e5c3, +0xb5327675, +0x6003331b, +0x1a51f1ce, +0x812d944a, +0xbfff2e27, +0xe575761b, +0x07f68ad1, +0x381c1872, +0x81421018, +0x1649a1c8, +0x6d513363, +0xac9fe57e, +0x8b90c641, +0xf8ad49b5, +0x86c75d7f, +0xe95921e2, +0x55d57d15, +0x6ce49026, +0xb164bae3, +0xca136ae7, +0x21ab80f5, +0xcc9eb782, +0x2836852c, +0x50d741dc, +0x04a0d346, +0x4e4a66e9, +0x54f9980e, +0x33553865, +0xcd587dac, +0x6fd5b50e, +0xb1a87d5f, +0xb87cbdb9, +0x1cba4340, +0x31a1ecc9, +0x43e4cd5c, +0x5494cc9f, +0x5d5fb336, +0xfc150323, +0x7210715c, +0x26de83ae, +0x6c2c305d, +0xf258cf49, +0x5a345779, +0xdc903c6f, +0x72518eea, +0x2e504fc0, +0xdb1fb204, +0x97933bc4, +0xbe2a82d8, +0x641a3d74, +0xc84e3a0d, +0x82759e11, +0x3d11f41b, +0x150dc08c, +0xdec973cc, +0xaaad4f50, +0x10a2255c, +0x937a60f2, +0xddd00bce, +0x37b49509, +0x5311824c, +0xd59b52a8, +0xa2ff13ed, +0xadae24fc, +0x6ac8f67f, +0x2522e8a7, +0x8d5e86a6, +0x1ec4502a, +0xd02ea52f, +0xdc29c92b, +0xc1f35c41, +0x436aa522, +0x35699bda, +0xd3d67d66, +0x83028ed3, +0x7b65c29b, +0xbcdccb92, +0x06d79cfb, +0x649b141f, +0xdee7a5ca, +0x2bccf3ef, +0x10197aa7, +0x5913d7fc, +0x4f3afb0e, +0xee174801, +0xef5924b9, +0xbe7f0969, +0x0c3eeb6d, +0x91e0d055, +0xbb744498, +0x71375453, +0xc2b39597, +0xab7b8af0, +0xb2e6b06b, +0x84900f64, +0x712f7e3c, +0xefcb1d71, +0x71171d3b, +0xfec209dc, +0x695eb65b, +0x4abb499a, +0x535acf4c, +0x353ecdf5, +0xf1efbc16, +0xd9758b6a, +0x343bdcc5, +0xdc674ef1, +0xce2306d7, +0xa55641b7, +0x8c6bef4d, +0xf0af184d, +0x5455ce1a, +0x8ce1ea67, +0xd6aa90e9, +0x29aac726, +0x97a05617, +0xda01d0f3, +0x8e7238e1, +0xa8f1d957, +0x718d44b6, +0xa482fa96, +0x5e62f4cf, +0x54150617, +0xaf15308f, +0x072e85be, +0x7902d636, +0xc182abfe, +0x0803ebaa, +0xf2139e0c, +0x0e60592f, +0xbc5408cc, +0x11ff77ad, +0xf16dd718, +0xd9f1927e, +0x34c46a6d, +0xe9fd27eb, +0xad01a7d7, +0x5e59024b, +0xbb8a23ff, +0x9f70d5ca, +0x0262a31d, +0xd2c1a784, +0x9083ce64, +0xba6c1b8a, +0x93716cd1, +0xd7887863, +0xa7d93b3b, +0x6cbd943a, +0xb68ee379, +0x98d7fe86, +0x2987513f, +0x1e4f9291, +0xf21d682e, +0x42e9ce72, +0x1f602881, +0x1afad905, +0x1e15e04f, +0x42b53a5e, +0x035f8e7a, +0xbb3e3dcc, +0xf9cc4aa4, +0xbc6b0de8, +0x8f962921, +0x805261b3, +0x3206d9bd, +0x29ada35e, +0xe042f04a, +0xa00d53ca, +0x95ef48c7, +0xe8af1555, +0x071551bf, +0x9a52d72b, +0xfcd80629, +0x7ad10bf1, +0x375b56bd, +0xff60a801, +0x8b5874b1, +0xe053aa53, +0xdb30c68f, +0xb0fe4e2f, +0x411299db, +0x76474c40, +0x21a2f448, +0x1008e853, +0x60b00538, +0x5d3b9fb0, +0xc95a8b9e, +0xf8b41c55, +0x7bb6ac3f, +0xbb9abc48, +0x7346e671, +0x714f6551, +0x0ac00e46, +0x3d910c30, +0x9f7387bb, +0xd228489b, +0x4b08bd14, +0x6422bae0, +0x52a38977, +0xfb59aae7, +0x3e2b43a7, +0x28176005, +0xa5772d6a, +0x5dfb0a1f, +0x54028a09, +0x691d033f, +0x13fb0b2b, +0xd021e7dd, +0x60eff4f0, +0xa3e6a199, +0x4bdaf842, +0x835732ea, +0xe8bf39b2, +0x9709c990, +0x10b609be, +0x6a576784, +0x7e458c34, +0xeb1d6e1e, +0xffa17854, +0x7b256634, +0xdd5bed8e, +0x37fcfe0d, +0xaf79bc03, +0xb31fce8b, +0x06693c46, +0xebe44066, +0xc7f89861, +0x1d9fd4d2, +0x95dc1b05, +0x51320368, +0x220c179a, +0xbfd831e8, +0x64f4377e, +0xe57092d6, +0xce26d840, +0xc6a1fdf2, +0xa47b4e35, +0x7a75e17f, +0xd1c078d8, +0xb514ebce, +0x8e88b5b8, +0x19fefdff, +0x61fb6438, +0xe3ae9c29, +0x2a9a7250, +0x29e99a96, +0x76cedddf, +0xe0f71823, +0x0a54fc61, +0x1a978416, +0x00e60c16, +0x90fee4e0, +0x3c3fb4f1, +0xd9090ef9, +0xbd1aa434, +0xc1141e44, +0x16f1e37d, +0xa25206f6, +0xedb702cf, +0xca5ba51e, +0xee5ac49a, +0x303f4885, +0xb41838ea, +0x4a84314b, +0x0d3e2066, +0xb523f574, +0x4817972e, +0x538e90dc, +0xf1f3c0c3, +0xc82d70d6, +0xefc7c838, +0x78d59765, +0x4e8b240f, +0x4e60e46b, +0xc357be23, +0x12e4520e, +0x2c9e7904, +0x46e1201c, +0x8531cb9a, +0x488795da, +0xcf0bfc98, +0x4d5c376c, +0xeebfaa38, +0x05147ee6, +0x2580f2e3, +0x2e3f58e1, +0xab4265e4, +0xf4469bd1, +0x1bcce26b, +0x10637be7, +0xe8e32f99, +0x19ff0ed9, +0xf279d391, +0x4ccd6c19, +0x100a2453, +0xd069fa3d, +0xf6eaf1bf, +0xa43e85d4, +0xe9fb2063, +0x0cff5479, +0xda80ee1c, +0x30a4bb30, +0x03b72f76, +0xd08c2b52, +0x5ca843d5, +0x053b9f11, +0x31734b88, +0xd4a9ffb8, +0xd2452356, +0xe731ae66, +0xd70e6910, +0x5c55adde, +0xc08c7f7b, +0x032fde92, +0xb4a8b233, +0x279d880e, +0x471137aa, +0x39cc0c68, +0x59a72956, +0x2d6c598a, +0xa36c38ac, +0xeef31bb4, +0xc1c769a7, +0x5c3a76aa, +0x88ddf760, +0x8fdc5145, +0xeced3a16, +0x3909e107, +0x2c3fff18, +0xba0748e5, +0x9ea8fcc7, +0x27d5ce96, +0xfeb91b29, +0xac4eb04f, +0x981a55f5, +0xb951592f, +0x48e691d3, +0xb444d26a, +0x45da30f6, +0xb67b2895, +0xd4e387de, +0x30b4f5d5, +0x29aeb736, +0x25087109, +0x18ab530e, +0xdc9ab934, +0x7eb8348b, +0x08d6a2c2, +0x2ceddb38, +0xe683cca9, +0xd2e7c27e, +0xa36a0ddb, +0x0031b081, +0x9df9f288, +0xd0215f36, +0xf2b80bc4, +0xd6b3cf98, +0x533b7bde, +0x5aa8b426, +0xd9ef8592, +0x3003cd4b, +0xb835965f, +0x00b36ace, +0xb27c7c04, +0xe7a11919, +0x96d82c34, +0xd81ccacb, +0xb5deb048, +0x8b387d76, +0xdfa3fa62, +0xa5c89aba, +0xfc264eaa, +0xd71c174a, +0x222d0a16, +0x7526561a, +0x278e958d, +0xaa77afa6, +0x9a8f1381, +0x7050669b, +0xafeecad8, +0x3453904d, +0x19b78dae, +0x85eced10, +0xfb554007, +0x3a0ba88f, +0xe1a64d12, +0xdfd85bd4, +0x3d2169c4, +0xbb0c97df, +0x66abf51c, +0x185eb379, +0xf0a7a1ea, +0x1363979e, +0xcff35ad7, +0x5e55e393, +0x03ad6b6b, +0xb608aa60, +0xaaebd44c, +0x7a3e8b91, +0x5d7316b3, +0x86ff21d5, +0x306bfe87, +0x9f0c646e, +0x10d37d79, +0x834771a4, +0x14432c3c, +0x8daf4180, +0xcdfe001e, +0x32356263, +0xe6dd3e31, +0x7d93909f, +0xb5fae5e8, +0x737e59d2, +0x19fc602a, +0x46ce5e8e, +0x8e2e51e7, +0xfed5ca24, +0x6e8eeff0, +0xe5810f33, +0x52dcc3ce, +0x11abb306, +0x7cb29c00, +0xfabb89e7, +0xbc3853f2, +0x0801be2d, +0x0ab8bce7, +0xc655e320, +0xd31616a8, +0xd3d9533d, +0xfe1bd7c9, +0x45e110ef, +0x22bbe2fa, +0xb9ab6b6f, +0x1a9c66b0, +0x85357abd, +0x71459de5, +0xc31665b6, +0x71a200eb, +0x83b801a8, +0xf15413f7, +0x7bd2666b, +0x0454009b, +0xd019c42a, +0x327968ef, +0xca544894, +0x9bf7dbdd, +0x412bab4c, +0x0c1874d2, +0xc1725e79, +0x9661b9dc, +0x9d2401fb, +0x48d55093, +0xbcb463ae, +0x6367024f, +0xb1d17992, +0xf803cd30, +0x14972657, +0x1f4e4c57, +0x237e9b86, +0x97af92df, +0xb5e8f734, +0x9e3db86e, +0xc08c81da, +0x66b23952, +0x988055da, +0xbad6c09e, +0x10f359b2, +0xe332a951, +0x4756dd00, +0x4861c642, +0xf8272cac, +0x1a98d1b2, +0x8c212a8a, +0x852e32ef, +0x1564bdbc, +0x29482a49, +0x6f9b0496, +0xbc62a4db, +0x5ba9287a, +0xf0d9f898, +0x2ddaa644, +0x6904b968, +0xf4ca78c8, +0x06950a26, +0x24e9a4a2, +0x0f2c94b1, +0x9d621bab, +0xbb15190e, +0x8f9b6e06, +0xde46f3d1, +0xe955ac30, +0x93503db4, +0x9f99bb9e, +0xf524ecbf, +0xdb31fac7, +0x965e211a, +0xc9bc7224, +0x24ae7038, +0x000c7961, +0x4fd51613, +0x46e3d7c1, +0x6de44f2a, +0x2962a99b, +0xefc0cd8a, +0xce82755d, +0x1d742e6f, +0xa05eeddf, +0xcf807492, +0x3b9b6a89, +0x45614e96, +0x9453814f, +0x21826171, +0xcd0b602e, +0xe8bef1cf, +0x27209dfd, +0x3d6647a4, +0x026567bc, +0x2a245823, +0xe3cc5d60, +0xb0f56420, +0x2b146ecd, +0x3e7535c4, +0xca0acef6, +0xacded313, +0xd8b87868, +0xe9506e1d, +0x0eccf8ac, +0xba7503a2, +0x396e040e, +0x2b6c8edb, +0x328eaa19, +0x3da3b3cb, +0xbda0615e, +0x181fc07b, +0x0994e7ee, +0xb7a82614, +0x62af65ce, +0x371665ba, +0x729ce562, +0xe513cfea, +0x4ead9de9, +0xb37bf61b, +0x437330b6, +0xbc5cd948, +0xe305df8e, +0x1674fac9, +0xc7aca028, +0xebd03013, +0x82500e69, +0xbf6c7d5c, +0x2a23bdeb, +0xa6ff9367, +0xf0d232bd, +0x84e47319, +0x1c1b1c8b, +0xd627257a, +0x3d007bb4, +0x351c6e7f, +0xe6ea38c8, +0x8a9f8afa, +0x120fbf6e, +0xbe445dc1, +0x423b721e, +0x47fa486c, +0xda0e4aa5, +0x6babc32e, +0x1c1072a3, +0xe34b7f02, +0x1d451b24, +0x14d1f2b3, +0x28f6e0f0, +0x3066fb8c, +0x279240a1, +0xd29bd58a, +0x84eea0cc, +0x55362320, +0x76b84cc9, +0xd59869e4, +0xc581ad11, +0xe72a0a88, +0x619d7405, +0x6d868ef4, +0xcc5e1938, +0x3d4f5c61, +0xa447b8b4, +0x0f3a7708, +0xbe8f2d71, +0x9ff967e8, +0xd1ae1190, +0xe4d14566, +0x4c7cf7ea, +0x24f83964, +0x5a69a7d2, +0x0b6b950d, +0xf3a0730e, +0xdff02fe4, +0xcb52b02f, +0xccb81391, +0x96739685, +0xd4b80295, +0x8408b070, +0xe39ab84f, +0xa5eb52f1, +0xcf65bde1, +0x1fe0f3fd, +0x18ec50b8, +0xd53e6c29, +0x944c718b, +0xd6a89670, +0x0e9775aa, +0xf2553d48, +0x305a9c0b, +0x5267154c, +0xefa83eed, +0x75f87e79, +0x5fe04a4e, +0xcbd978ba, +0x5293946b, +0x0e22642e, +0x885c6920, +0xc4ef3fc6, +0xc1c89ac1, +0xe6a333b5, +0x1d966b80, +0x22dc7cdb, +0x1a9698fe, +0x2c3997b7, +0xb4fffd8e, +0xbb70cce2, +0xdfe48683, +0x2fb8885e, +0x68968a0b, +0x19b98e80, +0x3b4638f8, +0xe58b669e, +0xaf767861, +0x5865e374, +0x093db3d5, +0xa4439dc3, +0xe8398a3d, +0x465ebd10, +0xb26fa2fb, +0x01963569, +0x8671cd89, +0x152fa1c3, +0x0daf64ad, +0xf0faf675, +0xd6acba16, +0xbfd70d1a, +0xc9c17928, +0x13ae1e79, +0x1c2ee6f6, +0x8ae4b70d, +0x923619c8, +0xc54b4ac4, +0x1e82efe9, +0x58bcc56c, +0xb15db328, +0xf4f1bbaa, +0x058bd35c, +0xd439515f, +0xe99481e5, +0xb833285b, +0x214ba49c, +0xe3bb3ba5, +0x783ce306, +0x8bd65f3e, +0xf59bfc66, +0xce224b63, +0x879855aa, +0x38467fa7, +0xd3958581, +0x56194ae8, +0x2fad847b, +0xec10ea2e, +0x1d752c4f, +0x56e00502, +0x9614ee55, +0x06c2d9ee, +0xc95093c3, +0xbea76d38, +0xbaa189bb, +0xace42523, +0x00c6a049, +0x013b06cd, +0xcd397574, +0xd9b82f40, +0xf44b5c91, +0x5aaf94dc, +0xf88c962b, +0xc4862718, +0xc9afb4ff, +0x6e74ca65, +0x0b1b14a2, +0x9b3da602, +0x6518ca92, +0xa90aa412, +0xab387f14, +0x47b5962b, +0xb9be944f, +0x89259665, +0x039eb015, +0x189b6200, +0x9e48e975, +0x7481b054, +0x17fd0e56, +0x8437de76, +0x8901dc97, +0x141613f4, +0xb79c43b9, +0x55ec0a03, +0x90bcb95b, +0x6ff9187c, +0xe0a3ace0, +0xe61e998e, +0x4fca4e79, +0xcbf0b457, +0x3f959ace, +0xbaf69044, +0xd9603203, +0xeb58a330, +0x9b0ec1d8, +0x178d5ae5, +0xb716bdaa, +0x75b8f16e, +0xe5c07e40, +0xef214273, +0xda8a0a54, +0x19763d08, +0x6657b2be, +0xd0c75fbd, +0x9c6cc83d, +0xc6b680af, +0xeada68cb, +0x788b0c60, +0x1f9e5afb, +0xc846b255, +0x157b9d6d, +0xf3e58155, +0xeed4048c, +0x17c80c05, +0x31543042, +0xdbbbd9d3, +0xbfebd659, +0xf418a4b4, +0x4db9d9f7, +0x7c3f981e, +0xe60ef273, +0x1cbd6b64, +0xbf395cbb, +0xf34b2618, +0x78b83912, +0x8d23cb5e, +0x7db8dae2, +0x4a0360c6, +0xe6ec8ee2, +0x8e1dcb68, +0x1d16105b, +0x5b4d8b43, +0xea12885e, +0xb26dffd7, +0x16995885, +0x0a654e76, +0x8abbb56f, +0x863c956e, +0x4dc28dcd, +0xa2367f6e, +0xf42fa058, +0xaeed73b2, +0x066e7147, +0x79e09ef5, +0x30e44014, +0x8e4e6607, +0xd89709da, +0xb1e7485d, +0x548d644b, +0x5eaef3c2, +0x80baa3b9, +0xc61b3fa3, +0x9c99b7e0, +0x323ac3d3, +0x4f35d45f, +0x33cca471, +0x1086421a, +0x0a0b6cdb, +0x83af20f6, +0x8bc2c537, +0xea7b72fb, +0x325a8f86, +0xbe3ac450, +0x6dff9d98, +0xad051bfa, +0x56bf739c, +0x57f0cfff, +0xb7091a8e, +0x896ddc6b, +0x9b13ffdb, +0xb569d216, +0x2e5a5aab, +0xcf6e4afb, +0xd2645b45, +0xff1a7dcf, +0x76f153c8, +0x17316ccc, +0x9655f7f3, +0xc8e24e51, +0xf16f7c1c, +0x80008089, +0x052cee4b, +0x86029f09, +0x892ef360, +0x34afa627, +0x9888d44a, +0xb2a59686, +0x061c83dc, +0x5b185df7, +0x03782fde, +0x86e3f968, +0x434cd369, +0x7c5d2b28, +0x47fde40e, +0xb5cc3c6c, +0xc32b183e, +0x4bda159e, +0x169a94d6, +0x4e73d070, +0x46a2c966, +0xd9048d77, +0x154bed19, +0x4ef5760d, +0x2d1bfc98, +0x976ed262, +0x7756b1ed, +0x6c09bf67, +0x7fdc2aab, +0x82b88fed, +0xfbc2063d, +0x046641ac, +0xd9576df1, +0x1e0d28eb, +0x9011cc14, +0x2eec239a, +0x042e2802, +0xcb6dceb7, +0x4da92c91, +0x79e54c85, +0x747487f8, +0x8dbe6b78, +0x8d3ce330, +0x8a24a510, +0x2afe5834, +0x1929fc61, +0x90d710db, +0xd1a00433, +0x3a0b3291, +0x4623bff9, +0xd3218188, +0xb624e960, +0x708de2d3, +0x18c63a3d, +0xafac76fd, +0x5f10ce00, +0x022940c7, +0x90d62e4c, +0xfa1f7c21, +0x8ec6177e, +0xf18c957a, +0x3aa6c297, +0x7d872d5a, +0xba1528a2, +0x3a09311c, +0xe0de67e0, +0xab38433b, +0x03a0f2aa, +0xc15fab30, +0x808c8f49, +0x13eb17d4, +0xec15ca96, +0xd044a3fd, +0xef5692ac, +0x8849b865, +0x141827bd, +0xb598077c, +0xff8b25c5, +0xeed55327, +0xed21baac, +0x36c2174f, +0xacf362a1, +0x255a0bcd, +0xceaf47dd, +0x7fdfcedc, +0xb97f20f0, +0xd11645e7, +0x1cf2b4b9, +0x675cf3a1, +0xab7d5a82, +0x0f3c9271, +0xafc3c241, +0x30f09cde, +0x2f95dec6, +0xb37fc677, +0x671ed76d, +0x2a43cc19, +0x371a7895, +0x868c5ccc, +0x96680c0a, +0x1dc08f94, +0x5e7ae2bb, +0x09d61a0f, +0xc8bcc8de, +0x02e75603, +0x091e2d0e, +0x98c4c7ac, +0x4c3cf8eb, +0x629164fc, +0xd3655506, +0xa00d2b9c, +0x73a01637, +0x40a35cc5, +0xf6fdaf22, +0x6e3be81a, +0x30f68158, +0xb5b329ab, +0xc46ce07d, +0xb0408bae, +0xc2208a00, +0xa6a1c9d9, +0xd7b7754b, +0x96e7d3bc, +0x25feb3dc, +0x307daca9, +0xda854ec0, +0x6ccd33ee, +0xbf2c735c, +0xbfcf7e6f, +0xcbf4d7c3, +0x04f694be, +0xb987b164, +0x0c1fc795, +0xbefa9422, +0x1472bc27, +0x7efab1a0, +0xba0d16f8, +0xfae18b61, +0x18686792, +0x89a65740, +0xa2ff2cdc, +0xe3e94892, +0xcbc3d11e, +0x842a7108, +0x970cdd23, +0xc076a4ab, +0x3fe8e87b, +0xe4b261ea, +0xe3551304, +0x16b9c4e9, +0x3e6801c6, +0x638bbc12, +0x2baf5d48, +0x8dd8b38b, +0x96df2350, +0x2bf1a19c, +0xcd50a39d, +0x29087d9d, +0x288879ad, +0x6c9203c6, +0x1ee468e9, +0x3166b17c, +0x0f06269b, +0xbbb81de2, +0x599b44c6, +0xfe9a9b69, +0x0e92d5b6, +0x7287b03a, +0x094b9478, +0xbac278c3, +0xdc13687c, +0x9328f7bb, +0x95f1d3ee, +0x267d99e0, +0xcf18c53f, +0x98aa0349, +0x961fe18c, +0x2f394359, +0x7b881777, +0x879b4fec, +0xc27c9622, +0xa7c368bc, +0x96961f1c, +0x42ab6b60, +0xb9f560c8, +0x8924959d, +0x67fcdf27, +0x91a9968f, +0x726ad9c9, +0x1f07c790, +0x5cfd7f0c, +0xb7637276, +0x48f44891, +0xd3a0823c, +0x86742f43, +0x336a770d, +0x139774b7, +0xa00ee3e4, +0x29cbf20e, +0xfc3c471e, +0xfb3e078e, +0x8e1eaf8d, +0x0c43ed69, +0x3e03bc76, +0xb83f41e6, +0x03a69001, +0x61e5db68, +0x9e73f370, +0x68be173c, +0xc5a5bb06, +0xacecd9c5, +0x84055b02, +0xe93c5cb4, +0x91ef4efb, +0x8738f606, +0xe0ec523b, +0xc83ce614, +0xa4cf5472, +0x371f15ad, +0x0c6118c8, +0x677b7e80, +0x72dfb44c, +0x9b7fa187, +0x240f9fe9, +0x903c8936, +0xca3d0026, +0x8aeb51de, +0x6eb4f06b, +0x30c3ddf8, +0x1ba781be, +0x6533ca66, +0x318c1299, +0xe7ee831f, +0xc3e3a1d0, +0x195d1e08, +0x99ada44f, +0x1a4e8ff3, +0xe51d14eb, +0x5192fb33, +0x3eff3456, +0xe320b3ba, +0xdae476ae, +0x36471f1a, +0xe6e71779, +0xca50499f, +0x44b7c0cf, +0x579cdd34, +0xf5ca83bd, +0x1d56d433, +0x3588e4ae, +0x0930b409, +0xe2112b29, +0x6e7b1504, +0x8281af41, +0xcfa123ff, +0xfd326caf, +0xaccdcb08, +0x137f406d, +0x1e3f0ed0, +0x3d3ac53b, +0x51542d07, +0x61bfbbc2, +0x98827376, +0x750afc8e, +0xa2cf1ccd, +0x0d3c0aa4, +0x009ef471, +0x72f095cd, +0xf81128c3, +0xb2fdae11, +0x72b4f3ad, +0x192ef44e, +0x9f36835c, +0xd9f8b762, +0xea4ba86f, +0x0216d915, +0xf290f901, +0x38f5e2de, +0xacc8c1b6, +0x04eb557b, +0x347c21de, +0x4bcb11ba, +0xb0ecd6aa, +0x8a3d6590, +0xf0c88b1a, +0x82c4ef64, +0x23bffa71, +0x2e68a684, +0x0ec7ddbf, +0xa2367bb9, +0x2f50e287, +0x7808ed93, +0x57427583, +0xfc3f22f5, +0x889d7b02, +0x6178c900, +0xdd684262, +0x6820112a, +0x36d63aab, +0xc1ba3197, +0xc6da520e, +0x20a4ad9a, +0x0504ec11, +0x18f09700, +0x6b477b06, +0x2b7dfa46, +0x5939ca79, +0xb1e06c8a, +0x20ae69c7, +0xa4b44813, +0x17fd27a9, +0x3fd504a1, +0x68f6a1e3, +0x8d2b2e53, +0x73ef50c2, +0xa7f50807, +0xae3e10e8, +0x163a7a88, +0xd7b82730, +0xff2b6394, +0x4149d027, +0x630f3e7b, +0x85ccbd5e, +0x90e67b88, +0xee5b7d42, +0x0729e301, +0xb676707c, +0x3329a8ac, +0xc98f60d4, +0x2add5060, +0x1d8716a1, +0x2a166bbf, +0xe70a2ba6, +0x3332049e, +0x28f6ecaf, +0xfe7b283c, +0x3fc2fbfb, +0x4525099b, +0x9ed4b6de, +0xf156f9ac, +0xcf876547, +0xdcb20747, +0x30b6b90e, +0x92286f50, +0x4edecc5b, +0xbada3bfd, +0xf40d2581, +0x7c6c83ae, +0x1c38c37f, +0x151fcd9c, +0x63fe5af1, +0xa0d0c821, +0xac47735e, +0x9d64101b, +0xf1551052, +0x353b6499, +0x179e8d89, +0x3595ba4b, +0x79553d59, +0x40d32d82, +0xe6dd2c1f, +0x19a158d1, +0x92fd6941, +0x955d9521, +0x59c060e8, +0x13141bf8, +0xa1b9d359, +0xdbe3651a, +0x7bdc3222, +0xde6c8401, +0x10185234, +0xaeca73a8, +0x9f3f40d0, +0x31f403a7, +0x3f2381f5, +0x11f98a9d, +0x7b2116bb, +0x387136c8, +0xb9f6bdf7, +0x37a4afde, +0xac8f4222, +0x3d3f1cbf, +0x0cd93ca0, +0x1377a4fc, +0x24f2bcc0, +0x93d2687a, +0x88ee41f1, +0x9d35a09f, +0x71a3efce, +0x38e7a7cc, +0x308b68f7, +0x8e4a7383, +0x3c1369e7, +0xc9ee53f0, +0x927c9e1a, +0x826215b0, +0x949e1f2f, +0x69167a1e, +0x25e867c1, +0x7efc26a8, +0x4d182479, +0xdb2205b3, +0x0b90f0d9, +0x89f25cbd, +0x845838f9, +0xcde1dfe0, +0x8e43e8f8, +0xac1fc68a, +0x061b89ef, +0xa37df2aa, +0x42e7fe68, +0xc1810376, +0xe495a3fc, +0x5495f46c, +0x358a3f36, +0xec503131, +0x284a816f, +0x54a8b7a8, +0xc378bc21, +0x6c55a871, +0x29b6dee7, +0x08952daa, +0x8af012cb, +0xee2541d7, +0xa3f8ccba, +0xb6d6c503, +0x90a992ed, +0xbf4764bf, +0x98b632e8, +0x97027a89, +0xf0d2a03a, +0x4f8b5e1e, +0xb81b4487, +0x91a4d4a3, +0x5516f4bb, +0xc51a8dc9, +0x6b4e85a7, +0xdfc45266, +0x18564e5a, +0xade39142, +0xb858cd9b, +0x0455cf91, +0x26b7e0e9, +0x3bc6e4e3, +0x381404cc, +0x078ac564, +0x286a0985, +0xf334ab0b, +0x49951c3f, +0xa23a2eef, +0x1666e8f8, +0x441a4ec2, +0x93ef4e7f, +0xbbdac08c, +0xe1a85b5f, +0xbd5658ce, +0x3ef6ac1c, +0x2ea4758a, +0x61fd3a1c, +0x9e287c6c, +0x7c494e95, +0x0a8ba3f0, +0x1902357e, +0xeb33086d, +0xfe6b73fa, +0x1b3208f5, +0xbf4beacd, +0x9eec5990, +0xd22870e8, +0x17fc2880, +0x06577963, +0xc828f9f6, +0x0422db85, +0xb3e39b31, +0xf02d4d02, +0x6cbbcbba, +0x21aaac13, +0x1239b92e, +0x28f6d204, +0xdbb2aaa4, +0xbd7b02dc, +0xb6ba8725, +0xa7b07c2d, +0x13013b03, +0x0d9a10aa, +0x67ad9e3b, +0xf1891589, +0x55bad3d5, +0xab6fa888, +0xbb895cb6, +0xa4f2a908, +0x07010992, +0x65ecb565, +0x6f085016, +0xef0c9ccd, +0xe9385dbe, +0x65977b88, +0x657be502, +0xdac1ae09, +0xbb05fa99, +0x35a2c874, +0xc2fa3122, +0x493f7375, +0xbf7efc15, +0x47e88b77, +0x11c2935d, +0x8332c977, +0x130b98f4, +0x23fb767d, +0xc0ddf2ef, +0x15b716ba, +0xd614a7df, +0xc7a506c7, +0xcaeefb8d, +0x2e772b2d, +0x79521336, +0x3c6bd07a, +0x3b2b1d06, +0xac54be7b, +0xd66346e3, +0xbff92a0b, +0x484511a5, +0xf06ae9b4, +0x1127760a, +0x2bde0f46, +0x29f24ac7, +0xb64ff9b8, +0xfa3a66ad, +0x4bd93e3d, +0x50f49283, +0x4c20122d, +0x92b36dcc, +0x0ee63101, +0x11385d99, +0xc95f9e12, +0x57fe80b0, +0xe756e94f, +0x2204b2f1, +0x0b68828b, +0xef84382d, +0x62b906e1, +0x74db80e2, +0xb0eb0fa8, +0xc903e452, +0xa44b5682, +0xfe332e24, +0xf1603212, +0x0be29841, +0xb9e35437, +0xda021f63, +0x50f55fcf, +0xb64f2390, +0x029c253f, +0xb91d4510, +0x3b968b14, +0x496a3565, +0x4952e061, +0xb36a0ad7, +0x0a04ffaa, +0x6b8a1e45, +0x43188076, +0x7fb15893, +0x5784445b, +0x2ffd79ed, +0xccbb14c7, +0x82a24590, +0xf0f08a05, +0xd4fc6e11, +0xf3942512, +0xfba77aec, +0x42b3d99e, +0xc0eeb657, +0xf88b86cf, +0x4c3c91f9, +0xcb3348a7, +0x26449d0c, +0xf4c333e4, +0x029096ea, +0x3f74ca74, +0x0b996b9b, +0x16e71651, +0xa6a1bb50, +0xc541ec39, +0x2aed4700, +0x9a52b5b0, +0x96c0be1f, +0xf6351f02, +0x15b9dd38, +0xe66c0cd7, +0x2865f36d, +0x821434e7, +0x2a53fa1f, +0xaec10cd3, +0x19a0906c, +0x1329d6b1, +0x0cd5e897, +0x15ae6abc, +0x029d9d6e, +0xcce67ca0, +0xb37b5da9, +0x5facbebc, +0x79ed8956, +0x51f04832, +0xeaf99e03, +0x19986538, +0x93e10d8f, +0xccb77bd8, +0x13c167b5, +0x02a13fdc, +0xbdbdb93a, +0xd2427294, +0x96c19fe9, +0x618a091b, +0x141fdc3e, +0x03cedf83, +0x09871639, +0xf4dab049, +0x4dbaab65, +0x24a416c6, +0x844f692c, +0x440fd568, +0x941c763e, +0x665832f1, +0xee8e6e26, +0x85e4fde7, +0xd3cda80b, +0xff767e91, +0x7281073b, +0x966b5096, +0xead27ea7, +0x00b9772d, +0xf870a895, +0x93563223, +0xbee9c8a7, +0x42553283, +0xdcdb5b27, +0xc8bad9aa, +0x0381f5cd, +0x6f3df43b, +0xf5be0b3c, +0xa17d1c9d, +0xbe5436d1, +0xecc0ccfc, +0xb3720db7, +0x9c09fb52, +0x3dfdee38, +0xcb2645b3, +0x08c5cf13, +0x6ae1d71e, +0x7ea141df, +0xd86e16bf, +0x3ffa60de, +0x7ddf5302, +0xc36b798f, +0x298ff556, +0x3311ed0d, +0x2f533c45, +0xe32b7ced, +0x47507411, +0xe0b10a3e, +0x8b8b9818, +0x8bd679d5, +0x88473aef, +0x48bf588e, +0xd501ecdd, +0x28f245b1, +0xe90a6ccc, +0x4102a079, +0x18d2fc41, +0x3f49be3e, +0xa9175515, +0x8e5ba5de, +0x81c9414a, +0x11ee66a7, +0xfb3e7611, +0xe2bfd2c4, +0x152d37bc, +0xa6afd72a, +0xb7029eb2, +0xb2de0cd2, +0xfa8690ce, +0xf3bebbda, +0x3661ecca, +0xd77fadaf, +0xd4962764, +0xae8a3134, +0x2f49d3ed, +0x7eac50f6, +0xdedba2b2, +0x9fea4f14, +0x2b77f7ea, +0xb99b4b16, +0xed1826e9, +0x94ce6f1f, +0x63a51a57, +0x2dd5f38d, +0x0054bde4, +0x512578fb, +0xbdb1a5f2, +0xb9a0e9df, +0x1e05b5ff, +0x419b4433, +0xe26fadee, +0xd955830d, +0x46969338, +0x31e6f981, +0x36efd7c6, +0x833bad20, +0x11291102, +0x25ae7db8, +0xcab3ffe5, +0x263e0942, +0x259d3aa3, +0x19e9d6d9, +0x5a2f0c80, +0x0fe63f48, +0x737b71ae, +0xbf808271, +0x9494e032, +0xe31a58bc, +0x860d485f, +0x911bff6f, +0xba150cec, +0x8e470d00, +0xcf6211c1, +0x8470e028, +0xfe43de4e, +0x04b60f78, +0x5f1a275c, +0xf5fde735, +0x92b5d366, +0x6cb10f43, +0xdf7bbc47, +0xd008034a, +0xfd0dc7be, +0xc94615ce, +0xe69596c0, +0xa70ed38e, +0xd620a02c, +0x53190a54, +0xddfb3283, +0x994c36cc, +0x59e75619, +0x4bc3ad73, +0xdb810a25, +0xcb295dae, +0x84d1aa16, +0xcdd56de4, +0x23a724d0, +0x0886f2fe, +0xb37a7cad, +0xbfba3581, +0xd9859d9f, +0xffb96dff, +0x300d2e9e, +0x3fae69c7, +0xf06d5009, +0xfa6a9e87, +0xa67b7011, +0xbc312433, +0x6959b666, +0xd29622cc, +0x7f852907, +0xbe221450, +0xd50d6f7e, +0x04bbc917, +0x44b8bd03, +0x496684c8, +0x65bc3a04, +0x3e8b5175, +0xcfaaa9df, +0xbcc459e6, +0xb27eac47, +0xc4b00f8c, +0x23c79293, +0x92152683, +0xee2d646c, +0x68a4ee2e, +0xa33984da, +0x6eff8542, +0x1c429a58, +0xb8a0284b, +0x8e94f5e9, +0x47f5e742, +0x9d16d65c, +0x2de6f385, +0xdad01e22, +0x5764da70, +0x4cff9d2d, +0x70074947, +0xa422b3ca, +0x58379e5f, +0xd10fde65, +0xce8de7b8, +0x49561ba7, +0xed02c847, +0xccb886a5, +0x1698689e, +0x33134741, +0x73e355c7, +0x1c5e13d2, +0x9a3e7ee6, +0x07a42d04, +0x70423c0d, +0x81288bb1, +0xdbda34bf, +0xff7031c1, +0x408770ac, +0xfac2f954, +0xd166f859, +0x3672390f, +0xf993cd25, +0xfc719ede, +0xe872fc42, +0x09081db8, +0xc6204fd2, +0xfcd29698, +0xb19e86f6, +0x2f183a4e, +0x4677ccab, +0x1a4d58bc, +0x97ad26fe, +0x31d754a5, +0x9bfa0c10, +0x6f5a505f, +0xf25afae4, +0xa75167f3, +0x90d3aed5, +0xd60bf101, +0x8a5b6264, +0xd7ca7f0c, +0xa5e14694, +0x39b3dbee, +0xcc13c88b, +0x158d929d, +0x3ee0e29f, +0x98d4c19b, +0x6f0468ed, +0x77e330ac, +0x951de380, +0x67ec5762, +0xb2dd1a3f, +0x57102f2a, +0xe5461fb0, +0x4c1d3cc6, +0x8d9cb4c7, +0x23cf2dd9, +0xd0ed812f, +0xfbd9a43e, +0xd4ef422a, +0x8eea14dd, +0x63981dac, +0xcb7c2073, +0xa4eb7d14, +0x6c4c86e4, +0xa3414156, +0x24db0596, +0xd3ef550a, +0xb672e78d, +0x39a62bb4, +0x830acdbe, +0x9cc62e45, +0x9c94693f, +0x111bf7a1, +0x17f7d5d9, +0xd96c7a79, +0x229396da, +0x5a13ef0f, +0xbb2439bf, +0xaa32daca, +0x846ab3f2, +0x72e9d8fc, +0x2b9001d1, +0x3adad70f, +0x72031435, +0x2277ca18, +0xf40d3b9f, +0xf06e5966, +0xc13b5888, +0xbe7f2ffd, +0x490928f5, +0x9fda56ef, +0x83d8924b, +0xf99e8cdb, +0x45a5ccd2, +0x78e64a24, +0xb5701cfc, +0x428db501, +0x4d574485, +0x82f358e0, +0x6c41b048, +0xdc8e50e6, +0x81cb41e3, +0x6d721bff, +0x6c93b1c3, +0x1cd094dc, +0x2528675b, +0x0b5c0020, +0x29f2a363, +0xdd5dfb69, +0x90ec72c4, +0x9fdf1556, +0x00d4e81a, +0x1431c949, +0xdf5aff28, +0x91cc7181, +0xb123c261, +0x2df9fa2c, +0x35549c93, +0x414bbf94, +0xd91c83b1, +0xe99dfe91, +0x0799ddca, +0x554cbc90, +0x93c2a98f, +0xda6c6d13, +0x71c6389f, +0xeb276d33, +0x59b0045b, +0x72472364, +0x895e842f, +0xc9a16fef, +0x387a2f42, +0x3019c8a2, +0xb1eac8d5, +0xbbb1b8eb, +0x9c3800c1, +0x2fdc591d, +0xe57fc315, +0xe9239780, +0xb7dacb99, +0x6d762775, +0x210ad44d, +0xd7576752, +0x99ce8f93, +0x256d9b71, +0x52a8191a, +0xb8e51547, +0x7ced7374, +0x35cee29c, +0xee73f681, +0x81fd9f7f, +0x249b288e, +0x5822bb33, +0x0dba5c56, +0xe5508ac8, +0x495af883, +0x0fa8ad9f, +0x68783d8e, +0xe221c173, +0x6c9b946c, +0x060ff249, +0x4689f74b, +0x9afc690c, +0x991b71b8, +0xafd1ea2d, +0xeb5d0acb, +0x56f7fdd2, +0x9d1d79da, +0x1550ec2a, +0x8cf6f64c, +0xb1a20038, +0x567b6f8e, +0xcf5ba24b, +0xe53f98b0, +0xa99e938e, +0xe328f6df, +0x4677939a, +0x67042a44, +0xfed7df61, +0x508fd09f, +0xf90eb16d, +0x40a3d6b7, +0x2c1a8523, +0xfb063656, +0x3fa2cbe8, +0x87c0e632, +0x42d8b2da, +0x0f2e7396, +0x21cc2081, +0x4d6bc29f, +0x01b13ed0, +0xd8343355, +0xfa84d78f, +0xebcee565, +0xb06bb995, +0xcf3e8e03, +0x648f81bc, +0xfcf805ff, +0xcca6c80f, +0x8c31df48, +0xd6575a33, +0x30bbbb64, +0x1f951d4d, +0x1a12fb20, +0x048e1b07, +0x3084015c, +0xdaa1180b, +0x9163c2d0, +0xe42c048e, +0xe2900a51, +0x42c348dd, +0x93a26a2f, +0xd844da27, +0x0057e04b, +0xeaff5e48, +0x804ae313, +0x14d2bafe, +0x8e3ed9c0, +0xb3ce0ddf, +0xe1dfcd2d, +0x8b9cbf83, +0xee338bf9, +0xc9b65b2a, +0x7a629eb7, +0xbad9e243, +0xd4bfe31d, +0xf1da3fca, +0x1c0ba3d3, +0x99a4b0ed, +0x5b99229a, +0x05630bf6, +0x712836ca, +0x3b650385, +0x0278bbc8, +0x4dce3b35, +0xcb18a089, +0x0f9230d9, +0x7bc80fb1, +0xc5e6ea33, +0x6f4883ba, +0xd1930147, +0xbfd49408, +0xb385abba, +0x47598a25, +0x80f1739e, +0x0bd6d92b, +0xd0df5cab, +0xe65e3217, +0xd1a0844a, +0xa7e036cd, +0xc20458b2, +0x1bda2d05, +0x1d03b2c3, +0x18c994ca, +0xf42ed836, +0x77fbfcf1, +0xa7c2bae7, +0xa6bb6686, +0x387b39c1, +0x5987fdd1, +0x64862aa9, +0xf1fbc953, +0xba3128f3, +0x3c8a7c82, +0x7928e208, +0xd1cee01f, +0x319896d1, +0x81feedef, +0x314bbfba, +0xdb61cb26, +0x29ea939a, +0x5c32b037, +0xc0d5f23b, +0x0d61b48a, +0x781a7707, +0x09f8632c, +0x95265f9c, +0x0d388adc, +0x6bbc6c7d, +0x5b3bffcd, +0xfcf38e92, +0xa30965a3, +0xf2e1db7e, +0xfd0f8aa8, +0xf1098f9d, +0x4b3da821, +0xb9b0b556, +0x948ec33d, +0x6a63482a, +0x6b16643e, +0xcd5bdb27, +0xde0b9799, +0x0219d3d1, +0x7e209597, +0x3e239aac, +0x8b05ddbd, +0xf559100d, +0x404a772d, +0x4fcb9bbb, +0x2a8508b8, +0xff4ba6ef, +0xf8d4cbb4, +0xe2614212, +0x33f6b737, +0xf924aeba, +0xe69eb69c, +0xec9b36b3, +0xaa5eba3d, +0x4d799ebf, +0x9c302f11, +0xb9d57b0f, +0xb9e7645d, +0x87ed7e4a, +0xc6a76208, +0x1df9b325, +0x2a3179c9, +0x101923e2, +0x2c7b61fe, +0x1da2fea0, +0xd45c6916, +0x8a1a2fd9, +0x1c706a77, +0x1274e8b6, +0xa92d7cec, +0xfa7cc2d4, +0xf1c2e223, +0x23de5b53, +0x3664e358, +0x220b9bd6, +0x895e829e, +0x6b1209a1, +0xabbe8fc2, +0xab021189, +0x1ae09102, +0xfe249d3f, +0x5f449815, +0xcdbb0f3f, +0xf6af92a4, +0x8dfea125, +0x91c25292, +0xddf8be95, +0xeb321eaf, +0x2ddeea25, +0xc7724eaf, +0x5ae7212e, +0x8cdb9f42, +0x66144f0f, +0xd9ca40e9, +0xf579d025, +0xff2cd495, +0xe6811c44, +0xf7f57ef7, +0xc43a215c, +0x516418a5, +0x0e2b736d, +0x446a2722, +0xa916c378, +0x4ca66c3a, +0x270f0e56, +0xe6ee3218, +0x4ee44cf1, +0x91b635b6, +0x3d012c9d, +0x8257bde1, +0x4b78720d, +0xf274cec8, +0x60cd339c, +0x60963984, +0x196cb610, +0xfedfc695, +0x3ee1b143, +0x3522d928, +0xdf128e53, +0x976aa145, +0x5c86bdd4, +0x527996c9, +0xe84e451a, +0x86a5cc4f, +0xb80d10d4, +0xe59d7668, +0x46405876, +0x12bbee0f, +0x802eace2, +0xa85bf35e, +0x1dbd207a, +0xc7c1d541, +0xfceb0b56, +0x1e5b7772, +0x2f9f5569, +0x181ba125, +0x6f547daf, +0x90170bcd, +0x3756585e, +0xfb6ee748, +0xcc758d68, +0xf8c76718, +0x71cd53f9, +0xe1e0cd10, +0x90cef4d7, +0x3b359caf, +0x23094e49, +0x27096ef0, +0x50a8d08a, +0xcbcf574f, +0x62c64f17, +0xff3f6fee, +0xb16df7ab, +0x547f5e4f, +0xb40138ee, +0x674ad5c6, +0x42610543, +0x77abb8db, +0x693d2635, +0x9f4b412e, +0x97334d68, +0x05937ae6, +0x5fe77a2a, +0x2da20bff, +0xb940f087, +0x5b611d27, +0xe96ea15d, +0x262cd2e1, +0xd86420e6, +0x7dc7c335, +0x6240c282, +0x93b04497, +0x973367bf, +0xde50e8fd, +0xba4f49a1, +0xf9f5cd67, +0x1012ae5d, +0x9dd04ab4, +0xde87f909, +0x980c2060, +0x38579bc5, +0x53426566, +0xc28b488e, +0xd8f3a989, +0xac838937, +0x0fd40d09, +0x14a95b71, +0x41a96efe, +0xb41d8602, +0xb5c9c05c, +0xc00528d1, +0x166b4906, +0x70671a00, +0x09b02bb2, +0xe2127026, +0xa4237f50, +0xbe21f65d, +0xbe6ac6fa, +0x171a28c6, +0xea68a771, +0x586b477a, +0x9cb0512e, +0xbab8893a, +0x4b39bb55, +0xdc731a74, +0x304f0f9b, +0x0e29ecdb, +0x2d109c60, +0x779831ae, +0xfe760f56, +0xc76d1670, +0xecb3b974, +0x995a49fc, +0x7726d83e, +0x10e58778, +0x44981df5, +0x7dfc15f7, +0x8b74622f, +0xd4becef4, +0x10d7251a, +0x6323a116, +0x174da862, +0xb6eb8b84, +0x48164db2, +0xc111485e, +0x76165726, +0x862d7642, +0x6df99823, +0x6aa1dce8, +0x415caeac, +0xcaf2c545, +0xfd0258d5, +0xa90e19ce, +0xdb29fbef, +0x8e3b9155, +0x0465b8aa, +0x58b5f44e, +0x786d2aed, +0xfdf05ea9, +0x06ae6c91, +0xf82020e1, +0xbe783669, +0x6c3914ef, +0x0c8d3044, +0x4d3503da, +0x04fb480e, +0xe7dc9d9e, +0x7eaa938f, +0x8cf597bc, +0x2624f737, +0xb33471db, +0x47b426d2, +0xb4c4b97f, +0x69e16bd7, +0xac739579, +0xa8fad8d2, +0xf730c7ee, +0x2c57c2ec, +0x84931b80, +0xb59bc69d, +0x1d772639, +0x1b71de03, +0x54d1d68f, +0x57b02de7, +0xb7318ee7, +0x3dbefdaf, +0xf5f2a363, +0xf62f80e6, +0x94ef8c63, +0xdcdb9fb0, +0x2c4b0020, +0x56dcfdc0, +0x8b6e6897, +0xa3615879, +0x2c1216d2, +0x432cf5a0, +0x0c97e84b, +0xa33c826a, +0x5f27d1e4, +0x30e0a9da, +0xbf15b6bc, +0x1cf2058e, +0xbe64bd04, +0x09266629, +0x5c738374, +0xd219d248, +0x08c1ed94, +0xf93bed0b, +0xaf3b9784, +0xe32b0765, +0x5870afe7, +0xa2a964be, +0xa6b456ab, +0xe17aa8d0, +0x8f945b86, +0xc4125809, +0x00c6833d, +0xc5f87e56, +0x89fce694, +0xdbb7fbd9, +0x5070e9fa, +0xf8f3fa75, +0xe1e0fe7c, +0xfaff2de4, +0x8d2c0303, +0xf135c95b, +0x963f685a, +0x9c60b23d, +0x54dc9cbf, +0x88cf5a5d, +0x930fd32e, +0x9c6d5f50, +0x49841b71, +0x843a67d0, +0xcf158a40, +0x8bb7f560, +0x69ee85ca, +0xf158f73b, +0xf59ff217, +0xbfb0edad, +0x279e0aeb, +0x433410cc, +0x475e64b5, +0xff6a7c16, +0x49e446fc, +0x8b2d905e, +0x09120079, +0xe420be58, +0xe9f9378d, +0xffb3397a, +0xb0f6c1d0, +0x5adf4f12, +0xa36d6af1, +0x7b063b63, +0x81948486, +0x6f62f6a6, +0xc3d4cf3e, +0x1d37a796, +0x13b66ce0, +0x072929ce, +0xfd65725d, +0x7767e025, +0xead9fa19, +0xfd238230, +0xf475393a, +0x038cc057, +0xf42e6502, +0xa4919ebe, +0x4e753232, +0x25570d27, +0xb27c0f01, +0x9c233bd9, +0xd71a0c39, +0xc52f6a13, +0xce21114d, +0xc35b3bcd, +0xd5bf77b1, +0xa2c49a85, +0x6655f10f, +0x23e2dd96, +0x3432287b, +0x97c60e51, +0x96908b38, +0x0ef5c2cd, +0x84018ed8, +0x01504762, +0xcdad1346, +0xc8a35d9b, +0xf3ec2a41, +0xc5875409, +0xb0c09ef6, +0x8537bdf6, +0xed00864a, +0x66fc75fa, +0x3d509cc4, +0x45aba277, +0xddf5d1af, +0xff05a170, +0x0502ac1e, +0x372d00bc, +0x4a9a417b, +0x1edf8fd1, +0xfcaed6f2, +0xb37b291d, +0x1c3fcf86, +0x2007a7f3, +0x4ff75ae3, +0x75d01780, +0xaeb27878, +0xd5ebc299, +0x2b3cf8f4, +0x8716c457, +0x56f09f2a, +0x563c4b3f, +0x051f3a25, +0xb5b952c0, +0x6fa4d0ac, +0x42a430f0, +0xa3d25ad8, +0x5f5b2e04, +0xe9daaed2, +0x09c2bd74, +0xa37d252e, +0x1393bbfe, +0xe8928e31, +0xd143fa03, +0x630df3fa, +0xe9a65754, +0x46e3d719, +0x1eaed82c, +0x23078bef, +0x6a9a5ed4, +0x487444ba, +0xa3647273, +0xbf2703ef, +0xdbcf9135, +0x83dba87e, +0xcfd2e94a, +0x8e4e9367, +0x0be548d4, +0xdd0aa508, +0x0f9c9e32, +0xe155e03a, +0x9b2b62c4, +0x7e8a9395, +0x04126017, +0x313951e6, +0xe0548879, +0x580f34d0, +0x55b00c49, +0xd02db419, +0xad6dc189, +0x392f4006, +0xe31bf9c7, +0x2811a35f, +0x845b191b, +0xcfa937a3, +0x9dc22ba4, +0x168b6e05, +0x15ae8138, +0x3fbddff5, +0xfdb70b02, +0xdc6fc8f9, +0x9e370881, +0xa1445a98, +0xb4a7c8eb, +0xa25191ff, +0x13db7974, +0x7622c042, +0xfb678ba5, +0xbd10f39b, +0xc5a390bc, +0x01d9e6d2, +0xe3678292, +0xad2474f9, +0x34b3ee18, +0x09f0c135, +0x3c7984d9, +0x476f6a68, +0x422a58ba, +0x7a103f51, +0x8a45bcf2, +0x8b68fdf2, +0xc68ec6f4, +0xc0a0a1ce, +0x5548e732, +0x25a8584c, +0xcbde4888, +0x2e7c72b4, +0xfb3f56d2, +0xa4c85f6d, +0xfe3f40aa, +0xbadebdb3, +0x6c8ce55b, +0x902fb4d7, +0x44798cb7, +0x1a7f28dc, +0xa0720d67, +0xb2b72966, +0x7e0617e5, +0xddad88e1, +0xc464cba3, +0xdbb265de, +0x59aa99a7, +0xcafec606, +0x44166d46, +0x2e65ab78, +0x89bd39c1, +0x882c80ae, +0xdeb88749, +0xc7e711ba, +0x50d01787, +0xacb615ba, +0x79baca73, +0x25b4c1ae, +0x4bd484e0, +0xb995287d, +0xf5938e70, +0xd07b0607, +0xe646b90c, +0x62a96641, +0xd8a02445, +0xfa33c4a2, +0xaa91f55d, +0x4fb3a5db, +0x0b280d4b, +0xfe44e369, +0xc94932a1, +0x7e7d35b3, +0x3787f8d5, +0x56a2e234, +0xe63684d0, +0x63f46053, +0x4072c61d, +0x6e08600a, +0x8c86b8ff, +0xf66c3285, +0x8fce45fd, +0x8085b14b, +0xc21f6549, +0xbe34a1e9, +0x10601487, +0x7bfb372b, +0xae02fc14, +0x08a33a57, +0x330e859a, +0xe2e9127c, +0xe5e1527e, +0xa54d7bcb, +0x67a3b7de, +0x913602cf, +0x1b85c0e1, +0x46a18e3b, +0x68359cbc, +0xc3c53185, +0x75a8b6bc, +0x92b5b96a, +0x08d0c988, +0x91aaad44, +0x3fa37929, +0x6be34382, +0x3cca8604, +0x88c60f5d, +0x7b2eed24, +0x25457db0, +0xa5ff2b24, +0x9b705426, +0x94c8a057, +0x741537ae, +0xc1ba8dba, +0x384db485, +0x52652652, +0x7bbb10a2, +0xd08f61d9, +0x92828a53, +0x0c1034c8, +0x591cb8ce, +0xdae839d5, +0x333eeb9c, +0xb23ea318, +0xa72eb48c, +0xe56e9fb8, +0x01c7e252, +0xd2af99ab, +0x6f25d4ef, +0x28e10c19, +0x812480c6, +0x61af525f, +0x615dd85c, +0xb1b592af, +0x658c3caa, +0xf5b3222d, +0x0ef26e91, +0xfa1bbb27, +0xba85d298, +0xde212b1a, +0x091af081, +0x786a25f6, +0x933bdcb7, +0x1d252a17, +0xf0d95267, +0xb10759d4, +0x474ae90a, +0x18ba4ddf, +0x0f9bc96c, +0x421bd639, +0x7a4243bf, +0x663db111, +0x16dd061f, +0x76114cf8, +0x074c3211, +0x4b482753, +0xb362efef, +0xec13759f, +0xea601ce7, +0x441bfc51, +0xcae8b275, +0xd61876d9, +0xb195fba5, +0xaaa9e776, +0x72dd0352, +0x3ca2c724, +0x251fdecf, +0x739a0374, +0x76767ef2, +0x9d805230, +0x5e9a2439, +0x4e956076, +0xf7fa56b7, +0xa518cc0a, +0xe6ffe307, +0xd3ad6ab7, +0xc3b3c22e, +0xcaf2715b, +0xa8e499f1, +0x7d110d44, +0xcd718786, +0x84bf8b45, +0x0ac0a64f, +0xc881e645, +0x9050ab78, +0x3c376d36, +0x3631177a, +0x35688337, +0xd3f62d5a, +0x952775b7, +0x08562c86, +0x5daffa53, +0x722baf7e, +0x7087c3eb, +0xfd64e268, +0x366391fc, +0x4a496217, +0x0c354eaf, +0xcd71bd20, +0x229ef694, +0x798e7dd1, +0x6b013034, +0x20b5c7b3, +0x81af665c, +0x41f25858, +0x5feea1e7, +0xdc818af6, +0xb277f335, +0x1504c425, +0x4243150d, +0xa2bb4333, +0x374b5a99, +0xba9254a0, +0x34efa0d8, +0x110aa148, +0x798d4989, +0xaa96a881, +0x50b74db3, +0x0a0f4ff1, +0xa8c7e7c1, +0x2e6efef9, +0x984fce06, +0x7953b926, +0x82b19305, +0xd521fa99, +0x6d12fe8c, +0xfd3a9503, +0x8bad9270, +0xa0b50463, +0x083310b1, +0xf1aee8b9, +0x37e05532, +0xffa9bb43, +0xf90e161e, +0x78f8525c, +0x1d8e32ad, +0x9d4a920f, +0xfa07cc47, +0x0be1cff7, +0xa62ec199, +0x38f759a9, +0x68d5ed10, +0x1584973b, +0xc7cafd56, +0x1efa5628, +0x2ce2ccb9, +0x739be188, +0x19c96d61, +0xd37eccf4, +0xfd0b3e81, +0xa6a95a7d, +0x0f67522b, +0x9df2f6d8, +0x597d2a63, +0xda056d85, +0xc11445a5, +0xd87ff32e, +0xba594766, +0x9b6c3b57, +0xfbb0b1e7, +0xc62eacb2, +0x856348f2, +0x10408b00, +0x6f953cd6, +0xd7b4d114, +0xe9c171ed, +0xd7ce04f4, +0xb1110b41, +0x02711735, +0xc31191fb, +0x34586a8e, +0x18af135f, +0x50401307, +0x38f9d4c2, +0xf1a7ebb2, +0x24558f7c, +0x1966a4d9, +0x27d2fb12, +0xc45168bc, +0x82bc8240, +0x2634a039, +0x61578760, +0x0c7d07eb, +0x5e6a1ddb, +0x8b29eff2, +0x2bd8b8b2, +0x38b74d6c, +0x848e95c1, +0x81b88c2f, +0xce525ccd, +0x9016756b, +0x47e35f64, +0x060cad38, +0x6a1ba531, +0x5693296c, +0x594fddc6, +0xddd6082d, +0x31b9f790, +0x6190886c, +0x5dca699f, +0x43b9d24a, +0x72f8c585, +0x37c73563, +0xb06a5e1d, +0x8c338795, +0xc5bb51c3, +0x45132436, +0x0e7e1073, +0x1a1e79f4, +0xb4272b16, +0x7fd92937, +0xe3255ecf, +0xe21cfe14, +0x5c180fcf, +0x1b01e3a7, +0x86cdd161, +0x8d8ea39d, +0xdd07de90, +0x84c377f8, +0x0e771e88, +0x06ed4696, +0xe0cb3386, +0xffb5b2b7, +0x35c24160, +0xdaa6efff, +0x30e05389, +0x98e0994d, +0x860a3829, +0x60c36bfb, +0x152210a6, +0x1ad32213, +0x1c23ee60, +0x1512341b, +0x2c1a661a, +0xe2e6c964, +0x557acc77, +0xdc8acc92, +0x8854a3bd, +0x2b35fda5, +0x3ca8e574, +0x3820fb79, +0x21622357, +0x70fde86a, +0xc4c0c0fd, +0x8e595158, +0x127aac74, +0x1c64ef36, +0xc1e04e94, +0xc62d52a7, +0xb3ccdda4, +0x73df6282, +0x14d5a4fd, +0x672931fb, +0x57102c39, +0x32a93600, +0xaed0cf13, +0x53d97301, +0x52e14dfa, +0xcf174946, +0xe9890d97, +0xfcd8fe9e, +0x13db2a54, +0x9aafbc56, +0x2f43a3ab, +0x9c2228b3, +0x1da6c306, +0x6b4c07c3, +0x158e7a0b, +0xa186e868, +0x414bde56, +0x69bd1442, +0xdccba338, +0xfa430c0b, +0xd1959f35, +0xf7a45a05, +0xbdb41122, +0x474181ce, +0x494ba1fa, +0x5b81242e, +0x8d7f9b0f, +0x666be707, +0xaa89a698, +0x0737711e, +0x085ec8b9, +0xed0d6fa9, diff --git a/src/cpu/intel/haswell/microcode-M7240651_00000006.h b/src/cpu/intel/haswell/microcode-M7240651_00000006.h deleted file mode 100644 index 7df48a9077..0000000000 --- a/src/cpu/intel/haswell/microcode-M7240651_00000006.h +++ /dev/null @@ -1,960 +0,0 @@ -0x00000001, 0x00000006, 0x02222013, 0x00040651, -0xc9c88122, 0x00000001, 0x00000072, 0x00003bd0, -0x00003c00, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x000000a1, 0x00020001, 0x00000006, -0x00000000, 0x00000e41, 0x20130221, 0x00000e41, -0x00000001, 0x00040651, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x28f5c8c7, 0x9e112164, 0xf02f86e8, 0xf6b6111d, -0x3c4e5d43, 0xd650ad15, 0x38aa12f0, 0xa22e6707, -0xa19308a3, 0x5b19c4b7, 0x4a1b425b, 0x7d6a74f6, -0x81624193, 0x3a559605, 0x5475280b, 0xe7319d58, -0x48624ca7, 0x507af030, 0x3b32d96a, 0x30164068, -0x5284d2f5, 0x725b2915, 0xf63c9280, 0x44b7c142, -0xe67ca7b3, 0xd6f163e7, 0xcdf51f3c, 0x41d180a1, -0xcc3931b1, 0xf7a544a9, 0x7f6bf77d, 0xfc45a45f, -0xf0985836, 0x652d7e2e, 0x0324b1f3, 0x24b9548c, -0x7bcae7a5, 0xdcdebf79, 0x27015922, 0x0c83c606, -0x3d2ceeb7, 0x61c5eec8, 0x6b6899c6, 0x3e500531, -0xf08bfa44, 0xb304a8f4, 0xcee8f713, 0x2912c786, -0xfae6c34c, 0xa5292960, 0x7d63e389, 0xaa257a01, -0x1fb25054, 0x963fc676, 0x5bcb9fd3, 0x58f369a4, -0xf6e3beb2, 0xa58b5eb0, 0x33c7eba4, 0x37fe8b66, -0x00714403, 0xf0fd0c4e, 0xaa122996, 0x9a55b184, -0x00201507, 0xc9fb6e3a, 0x11ab60c8, 0x80ff6e84, -0xc37aabdd, 0x0fc23175, 0xb0b18c34, 0xf1ec806c, -0x00000011, 0xb446b9bb, 0x11a39f7e, 0x83a4e800, -0xf403aa18, 0x12d1dc1e, 0x438bea79, 0xd7808b62, -0x51b1b426, 0x7b7d0b59, 0x7ca0d77c, 0x5104e85b, -0xcf72fbb2, 0xde64ad8b, 0x18555138, 0xd1b30f33, -0x51f7abc6, 0xb9f5f98a, 0x63433b31, 0x020fb6ec, -0xc83d63c4, 0x5235d1c1, 0x75f744ca, 0x1a2a203a, -0xd2acee38, 0x0257ee06, 0x743dc8fd, 0x7092432f, -0xd669ef00, 0x406bd83f, 0xbf41491b, 0x97f73536, -0xfd3d1815, 0x197dedcd, 0x619286eb, 0xf463e603, -0xc4a6391f, 0x70b5c1aa, 0xe97b562f, 0xbee42bdc, -0xc5f9161b, 0x19c16776, 0x54677a02, 0x577e4564, -0x3f7f0a9e, 0xf2b94d7d, 0x8a2bee71, 0xe5523125, -0xc48ffd22, 0x7ade387b, 0x5b59c395, 0x3195e214, -0x987839ae, 0xef23b028, 0xe9574b34, 0x084f9aed, -0xb8d14461, 0x92ee473a, 0x5b5fc73d, 0x00460894, -0x0b5967ed, 0x987685ef, 0x50a2550b, 0xd87522c8, -0xbe2ff4a9, 0xe299bc1b, 0x452096bd, 0x5baaecf9, -0xf8f1956e, 0x2d02606f, 0x87fd45e8, 0x5bf097b3, -0x07236f9d, 0xcd6a058d, 0xbf9fa005, 0x8c7cc99a, -0xb89e30ef, 0xad128bcb, 0x4a7e1219, 0xc2481852, -0x19129474, 0x227d9802, 0xdb6047f0, 0x44fb7f7e, -0xa553b7de, 0xd36cf600, 0x50b29f3b, 0xba3798d0, -0xde788331, 0x344dac23, 0x63716887, 0x835d6c94, -0xc1c178e4, 0x68fae96d, 0x5a50782e, 0xb6054e32, -0x3a501249, 0xe2fe62da, 0x778a6b05, 0x7de9f5fa, -0xc0a1a476, 0xf765e134, 0xf9906b29, 0x4c847ede, -0xd721564e, 0x37c16584, 0xfcfa7c80, 0x8b7c405d, -0xe0929d68, 0xc21e8810, 0x96e75c1a, 0xd07a402f, -0x1c42a7c1, 0x97f0146b, 0x8fc5d3f3, 0x3dace643, -0xeba6869d, 0xf67391bd, 0x5f5cb5b5, 0x74fb3b28, -0x7a9e587b, 0x33ca7543, 0x2e0775aa, 0x9e1097be, -0xb019ad1c, 0x79642e86, 0x6ab5e4ba, 0x470d2670, -0x6fd90246, 0x65c3c566, 0x39a298f5, 0x7b779f08, -0x1f4a965f, 0xead217d9, 0x7e538c63, 0xdf71122c, -0x2d8e5893, 0x650a8b5b, 0x07848c67, 0x5a5a9714, -0x8d4884c2, 0xae30cbeb, 0x2a75f5b2, 0x5ad9ef89, -0xe6f968d6, 0x4976db33, 0x2aae8868, 0x54a0f425, -0x938be96c, 0xe4779ace, 0x15f6d58d, 0xd9773d3a, -0x7986c83d, 0x58a8f3b2, 0x3d927e9c, 0xb981d8d6, -0xfc5b69b4, 0x816c556d, 0xb79d4dac, 0x56c72592, -0x30793478, 0x52792616, 0xdd3368bf, 0x8615f67c, -0x9e9ad64e, 0x21986208, 0x52cbf75b, 0x99158bf6, -0x90a4bb94, 0xd101ccdd, 0x7f9893bf, 0x95d654ad, -0x75747d0c, 0x2a0aed08, 0xd51abee7, 0x0b1a1664, -0x44dba341, 0x76435331, 0x1ed332d7, 0x86af2c20, -0x5a14dcf0, 0x720af164, 0xdb03b43d, 0xf0434592, -0xcd374221, 0xbe6cb668, 0xc7fe200d, 0x9024aa11, -0x98973a68, 0x45854fe5, 0x42fbfba1, 0x7ecda23c, -0xd3810753, 0x94a2dfd9, 0xa6d9c615, 0xb01f739c, -0x072672eb, 0x5f71c0d3, 0xbcb5e5b5, 0x4bd6829f, -0x9357c942, 0x7d2dc61c, 0xdc737d79, 0x0e8069b9, -0xa6a8948b, 0x824cb986, 0x8712ca46, 0x88a6e076, -0xf6e4bdd4, 0x125194ba, 0xa6c566b0, 0x21b6ae11, -0xb0e55a44, 0x1c71d4d9, 0xdcb7b53f, 0x8d9aa903, -0x3b2f3e5e, 0xba0a80d2, 0xd81b15c3, 0xf8b69b19, -0xfc4f4ee6, 0x371aff7c, 0xf977d01d, 0x6753eb49, -0xf8c6aba3, 0x52a32da8, 0xf8bc09a9, 0xafaae176, -0xbd1a2509, 0x9c4ba2f7, 0xf2c5117b, 0x408fd867, -0xb417fd42, 0xf7c63c92, 0xd7817632, 0x45820959, -0xe3180104, 0x95f3cf3e, 0xa758b59c, 0x887a8fe2, -0x3dd7a338, 0x5a73b3ca, 0xad7db285, 0x1ccbb377, -0xf7dec7f9, 0x9bbf2b6b, 0xe05ab128, 0x3d92924b, -0x61c63664, 0xd544d18f, 0xba6ddcb4, 0xec691bc4, -0xd5ffea1d, 0x4a06c0a8, 0x6fbc8ca8, 0x75676b0d, -0x0f557867, 0x9fa53efd, 0xc7e736fe, 0x0580f0c1, -0xbceac219, 0x8f8e0bbf, 0x0cc23b6f, 0xb81dc329, -0x7e0b8083, 0x3a80b402, 0x4dd57a81, 0x1026ba1b, -0x63f8d61a, 0x33aa33a8, 0xfbb2388a, 0x2db9444f, -0x1b2337bf, 0x68a9e70b, 0xb0278540, 0x04ca1d3f, -0xdda4cbba, 0x07285957, 0x2bb2ad49, 0xbc3c632e, -0xdb30073a, 0x3485ea61, 0x728c610a, 0x26d911fc, -0xd9079ed1, 0xdb5ed68e, 0xe8015226, 0xc674c819, -0x8245885c, 0x1e78f037, 0xec3f2319, 0x2218c785, -0x5233ddb2, 0x22ad3fe8, 0x627f3680, 0x34be829c, -0x68db8e7e, 0x648fa39b, 0x50be8c93, 0x76e8032a, -0x9d6bc072, 0xe4cb2873, 0xdd4659e3, 0x4ca89b06, -0x68cee095, 0x331b6344, 0x8b42e6bd, 0x189f545f, -0x810656bb, 0xdef5199b, 0xe95eb90a, 0xaa8fa334, -0x9f74279b, 0x7a0cfa6f, 0xaebc1cb6, 0x453573ed, -0x39873714, 0x84ea8dd6, 0xeaa7d8ac, 0x753f045e, -0xed5a38fc, 0xd15b3135, 0x9bcb2a47, 0x3bec4c99, -0xffdce6e3, 0xc172bfc1, 0x5086aee0, 0xf3df0a2e, -0x90efa3b3, 0x29d3bcfd, 0x2feea67c, 0xad1ad1fb, -0xb8a68400, 0xbd7e92e6, 0x0181a4ed, 0x72a0d21c, -0x6ec9cd1e, 0x4470dbcc, 0xcb62bb94, 0x2e9f2616, -0x71f85a2c, 0x4e645795, 0x4c0b3aaa, 0xefc2fd2e, -0x12126c51, 0x5fe0b2bd, 0xa2ea0296, 0x241aab09, -0x3ff9e277, 0xfec1e535, 0xa1862c20, 0x1d388628, -0x15bac0e6, 0x5107fc7f, 0x017c73c4, 0xb45e3354, -0x1e20663b, 0xc155ab92, 0x702600e0, 0xd42bc23e, -0x235caab1, 0xca8e02b0, 0xdfc5efba, 0xb99d7766, -0x709eee81, 0xc0f9742d, 0x3cfbf530, 0xafc0cb77, -0xa1d97cce, 0x1c7e8e9f, 0x99405b33, 0xe17f2274, -0x3270f9b9, 0x2f702761, 0x50c87113, 0xe9fbc2c5, -0x598d7a49, 0x1ebf50e8, 0x69e46dba, 0x45a0e13a, -0x531dea3a, 0x4f167a0f, 0x50301d05, 0x011ec979, -0x046416ac, 0xf8f24e19, 0x52abb228, 0x586163f8, -0x83a4f211, 0xdf42625b, 0x59549ea4, 0x2f1e65e6, -0x9fe42b62, 0xc0d869d1, 0x6615ef68, 0xa2687bce, -0x49a46a7c, 0xe9dd362b, 0x0bb5d2e4, 0x0b19630e, -0xe121854d, 0x0aa9ab28, 0x715231f7, 0xda126b34, -0x4935896d, 0x92d0d59b, 0x2865b221, 0x2d7659a5, -0xcfdaaa5f, 0x4b3df303, 0xdb6ee69a, 0xfd8acc6d, -0xe9f0f278, 0xbe73c6ea, 0x79a6cc3a, 0xd0ec7aa4, -0x6f4f3211, 0xe5ceb325, 0xedcb8bec, 0x3c06567b, -0xfc4020db, 0xe4514d36, 0xa6efdf9a, 0xd1027491, -0x22ac2657, 0x9573ce20, 0xb975b125, 0xc2a43590, -0xf2bd1d69, 0xa65d09fb, 0x791ad65c, 0xb22629c4, -0x00d8f643, 0x10c31e80, 0x59366171, 0x1c5eae00, -0x66fc579e, 0xa9cd3b65, 0x52b251a6, 0x80601bcf, -0x96310f9a, 0x9750dd48, 0x8b893602, 0x38a25b68, -0xdc6a3b4d, 0x627b969c, 0x31a0702b, 0x73c624ca, -0x7fc4eef2, 0x80c81884, 0x117f023f, 0x3e981c1e, -0x873d99ca, 0x9bfc9459, 0x0be5af0b, 0x3c257880, -0xb8cf77b8, 0x11949c50, 0x47114468, 0x80f91bbe, -0x442cd2ab, 0xee976c2e, 0xcefe1a32, 0xef5ebaeb, -0xd573c27e, 0x2978d764, 0x653eddfc, 0x85a6910a, -0x644a1dce, 0xd194a1eb, 0x3103ca3a, 0xddf7c31e, -0x502d1c7b, 0x9ea11aca, 0x8415e1be, 0xc8b5e6b7, -0x737ec3d1, 0x0025a1e8, 0x2d10e23e, 0xe1cf25c9, -0xd93f9834, 0x5f176c76, 0xed90f0eb, 0x5bfd86a7, -0x0572ccd4, 0xd70c8a08, 0x850da421, 0x0daab877, -0x619e62e6, 0x18c6cda2, 0xc6893dfd, 0xa89177db, -0x7f1797fa, 0x949da24a, 0x3243a802, 0xc98709ed, -0x99134653, 0x671a8b96, 0x5fed050f, 0x78425038, -0xf4d43815, 0x114618a8, 0x75a50583, 0xb8ef5853, -0xbcdff144, 0x10b07fca, 0x99ed97bd, 0xe815d87b, -0x948c0a51, 0x8573a114, 0xf28e0f59, 0xc12cb20e, -0x8aa754d1, 0x199dc118, 0x5fdf32ba, 0x57146859, -0xa4941b44, 0xdcc65dad, 0x6bec0038, 0xeadee691, -0x635fc01b, 0x70e7ea43, 0x6f3e679d, 0xb04deb01, -0x96aba9ef, 0x0409473f, 0x6c69818a, 0xd41e74bf, -0x822f563b, 0x6b224567, 0xc9583923, 0x64460243, -0x6fab20e5, 0x20b85a7d, 0x7ff6c610, 0x84ce4172, -0xc2242380, 0xd512c67d, 0x2f1c7df7, 0x55289339, -0x8cfe618e, 0x14ebf8cb, 0x7b562bbc, 0x37b512cd, -0x5c07cce5, 0xb8020aee, 0x9a91c3a0, 0x3be3adf3, -0x50ffc652, 0x76d2ae8c, 0xafc3153d, 0x6ec9e9ca, -0xfc7908f7, 0xdb95584b, 0xe9195fa7, 0xa68ccbfa, -0xfb5c972f, 0x9f8c7d1c, 0x0bf06c92, 0xe1581091, -0x1fe6f263, 0xff2ef660, 0xd3207637, 0x63c75e6c, -0x6e058902, 0xd2b7fc96, 0xe624c80f, 0xd9567175, -0x07a2f14d, 0xea931882, 0xd82b83e6, 0xef0333d2, -0xc9aefaa5, 0x9cc369a9, 0x2f8d3dde, 0xd357d196, -0xbf34448b, 0x568a4927, 0xa011c011, 0x842b8e78, -0x5f713235, 0xfc9635da, 0xe32b8035, 0x993efdc7, -0x662b2e4c, 0x203c2fda, 0x1a637a9d, 0x4ffb9037, -0x8750b84a, 0xc0678521, 0xa409c34e, 0x87beeb49, -0x2b9c74ed, 0xaaaab901, 0xfc00020d, 0x31450438, -0x0115b209, 0x9c6000e3, 0x34fbc4e7, 0xe4904905, -0xb18ba3fd, 0xf59461e7, 0x0cfe1630, 0xc9fdf2a3, -0xe778d88d, 0xac018200, 0xb71fea46, 0xe303e55f, -0xce7e8ed7, 0xb84a943e, 0x6e2cdd1d, 0x6cdba37d, -0x488d4d64, 0xc7956242, 0x1a8056a8, 0xef28092f, -0x205bcdd9, 0xdb000225, 0x60592274, 0xe2b5e6a3, -0x61f0299e, 0x826c08b4, 0x5840da4b, 0x7b38f75a, -0x02435a81, 0x0411fc4e, 0x27d53980, 0xb68be32f, -0x66c7132b, 0xe5095758, 0xb5369c1d, 0xcd36f9e0, -0x4b3cd470, 0x815c94b9, 0x188df989, 0x2ce8d855, -0xaa643e10, 0x79800fbc, 0x3e5b5471, 0x0d894001, -0xbdbb3801, 0x9ff9f719, 0x1cd71921, 0x17ef534b, -0x0c779b3d, 0xcfe872ac, 0x4f810fdd, 0x83017c60, -0xbfec9761, 0xebace400, 0xe2dfb6ee, 0x18d62ca4, -0xae3b101d, 0xacd56190, 0x6fb19c2f, 0xc01a2110, -0x677fefcb, 0x792a248a, 0x83c8d7ff, 0xfd1365ef, -0x64e955b3, 0x61a37834, 0xc4141d09, 0xd85ace5d, -0x67b146dd, 0xdfcb7a9b, 0xcd76894a, 0x0465e1a0, -0x2abd5dd7, 0x832d6077, 0xcff6633e, 0xcf03bd51, -0x524b04d8, 0x98bf7f34, 0xcf495873, 0xeaa6d8b8, -0xaa928eda, 0xd1d364c7, 0x3c93d762, 0x7a64ffc6, -0x0a8037f6, 0x92000ece, 0xf4e3195d, 0x01c4ee4b, -0x9612d484, 0x941bc1eb, 0xac0a1f83, 0x4c8be21d, -0x7800d3b8, 0x61c76ba7, 0x1c2145e0, 0x91a403b5, -0x71315117, 0xacbf80ec, 0x5e42a85d, 0xf215e0f4, -0xc493e5b2, 0x2360435b, 0xf094ce88, 0x324b3e06, -0x659eb9d9, 0xdebb6dd3, 0x248d35e2, 0x7684d9ba, -0xcbd387b1, 0xa6467cb1, 0xb562ee9d, 0x468e53b9, -0x8bd38964, 0x470b2b7a, 0xde131b58, 0xc4c2ba37, -0xb87d47b4, 0x68c86e09, 0xb48567ca, 0xecd6ceb6, -0xf6d4091d, 0x04c6fab5, 0xedd1f977, 0xb4a25d69, -0x37499fdf, 0xb0c02112, 0xd4a927b1, 0x62041ee0, -0x7fc53271, 0x8b66957a, 0x0e21ca06, 0x12154793, -0xf3463d4b, 0x1afe8d79, 0x934b1044, 0x6aca9c9e, -0xbfc1f26e, 0x62352d63, 0x67d8aa9e, 0x9c075ef8, -0x0dfd401b, 0x1928628d, 0x90d1c980, 0x986d1689, -0x4dfecca5, 0x02aa70bf, 0x2fd5010e, 0x6b595451, -0x63767819, 0x82d63750, 0x73dfa2f1, 0x460ce4c5, -0x52113035, 0xe600faea, 0xbb91197e, 0xa9c6a682, -0xd0d3a7f7, 0xce342b0e, 0x1e87f0bf, 0xe800dfea, -0x29b14f0e, 0xbc430364, 0x1e5524f8, 0xc7366dcb, -0x769ea9a3, 0x2a7f71e0, 0xd764e720, 0x9deed5cd, -0xcfe424b0, 0x35816bc3, 0xe05f58ca, 0x4b5e7322, -0x9ff4259e, 0x535f805e, 0xdc6a4590, 0xb4e4f87a, -0x2f414aee, 0x44106f70, 0x462a6abc, 0x8f8424cc, -0x6cd666bb, 0x1bbd9ad3, 0xc8b5895b, 0x1f1a3d04, -0x45f7f5a4, 0x677e959b, 0xf96fbd87, 0x4eda1f8c, -0x9ce7f266, 0x9f89a83e, 0x625b11f6, 0xf8a14ae9, -0xa1b74809, 0x5c0a2767, 0x57041d2e, 0xfc677b51, -0x7f9cadaf, 0x5b973281, 0xff4037d1, 0x731b118b, -0xfb7a03ce, 0x68caba11, 0x0fb4721e, 0x5c35cf30, -0x7c4baf0f, 0xc86dab09, 0x75e4e9af, 0xd8d32796, -0x10b23123, 0xde91d224, 0x4976a748, 0x9c05cfff, -0xa4988e9e, 0x08501676, 0xe67878fb, 0x50a0070e, -0x981049c2, 0x6d7913a8, 0xe2fabd7d, 0xfd182706, -0xe6f94d8e, 0xd6a8bcb1, 0xc6b15c51, 0xf33c8e80, -0x6ecd2ecc, 0xd5a68dcb, 0x9dfc5334, 0xfb5ea241, -0x3a2f72e5, 0xca46e813, 0x431b8b8e, 0x6febccda, -0x49839ce1, 0xf3bb3160, 0xd73a25d8, 0xaf9f28b2, -0x38fc3477, 0xdb4a6323, 0x4033330c, 0xfccce782, -0x89e1de9c, 0xeb1525ba, 0x83f8d0f6, 0x46605021, -0x8935829f, 0x7062d709, 0xfb00a81f, 0x2169c690, -0x281ed324, 0x5cf5e518, 0x035f49de, 0xdaddf93e, -0xbace8d92, 0x44f104f0, 0x1494026c, 0xeca404f3, -0xfc7e17c0, 0x9550ba9c, 0x4b12d482, 0x2879812c, -0x85e9599f, 0x911bdd00, 0xa9eda77e, 0x360e081d, -0x78ca0e8d, 0xb8da0b26, 0x4e9caab5, 0x20fbbd28, -0x45b00578, 0x9be52a42, 0x3b3adfb7, 0x8e63140e, -0xdc12c7d9, 0x8a47baa8, 0x333aa390, 0xe0d660fb, -0x486371b3, 0x285fa010, 0x886d827c, 0x051b9d65, -0xbba94b67, 0x17d84a96, 0xf0a66f79, 0xccf282d5, -0x23ce6a92, 0xae2e0000, 0x48089dd8, 0xe8861ab2, -0xb4bfb958, 0x2bcf25b5, 0x503f269f, 0x1b70d243, -0x5bfe2415, 0xfbd32a52, 0x2f26b1ad, 0x06bbc224, -0xf0f26f1a, 0x2de81fef, 0x50fe8ca4, 0x96ef22b4, -0x47091853, 0x761ee27a, 0x63daadd4, 0xa789f906, -0xcd9c27b2, 0xbf435f5c, 0x566d6231, 0xd42b0e75, -0xfcff2ef1, 0x7a794a7a, 0x5b75e982, 0xefcf56bd, -0x039d19c6, 0xebf156b3, 0xb7e4321b, 0xe21ce160, -0x0c10f33a, 0xeefae4cf, 0x75d84717, 0xef3d258e, -0x726d7b3b, 0xd4b7c671, 0xbaa0d837, 0x85dc8b73, -0x427d805a, 0x98af49ec, 0x5590eaf6, 0x21d347cb, -0x070c912f, 0x3c47624a, 0xa39ce494, 0xc29b7745, -0xed27a280, 0x6a3074cc, 0x22302c0e, 0xb3a597bb, -0x9e2feaa1, 0x165a69db, 0x1c525060, 0x70524264, -0x1b869d99, 0xed1ec4e1, 0x6a2bf925, 0xf1babe28, -0x1fbe4e7e, 0x020cfeeb, 0x95fdf645, 0xd0a74567, -0x2b70274d, 0xcbfdc79c, 0xf057f195, 0xbcc9adfd, -0x52e3bc04, 0x0754f675, 0xce7a72db, 0xd0cd06bd, -0xe40d3511, 0x30bf2517, 0x505df290, 0x2238136f, -0xf45e1246, 0x500eb35d, 0x78668ef3, 0x30da8b8f, -0x6a9181d8, 0x9dd1320a, 0xdf416ea6, 0xb3283c78, -0x61d83cb1, 0x5eb143af, 0xb3125e66, 0xfe1f6b8c, -0xb003cf08, 0x7a6a9f8c, 0x20a514d2, 0x76063b90, -0xd2633f18, 0xd556ae32, 0xc9621dd3, 0x92f56c58, -0x0c148404, 0xde8c6cfa, 0x7aeb8e7c, 0xde8df7b2, -0x44466456, 0x3b680854, 0xc82639c5, 0x7b9721df, -0xcd18a5e5, 0xcccc452d, 0xc5e52e62, 0x93fee698, -0x8283de78, 0xa30a633b, 0x141f50fc, 0xaff73f5a, -0xcc10bbe1, 0xf902c092, 0xa588e45c, 0x670e6d01, -0x81b983a8, 0x0f050d23, 0x5bd740d7, 0x4999abc0, -0x0c57106e, 0x2b52cc23, 0xf45806b3, 0x634bf883, -0x4d2a61ca, 0x824d80f3, 0x4628188e, 0xb4f546a1, -0x6d4e3827, 0x8003f015, 0xbc1b9bce, 0xb39e014b, -0x0c3f3816, 0xb176ba07, 0xaddbf865, 0x7ee1f1b8, -0xe4265881, 0xba7ac132, 0xf1297d80, 0x03657fd0, -0x2fff7cee, 0x5730fb0b, 0xbd82aa45, 0x3b73392d, -0xac7ff8ba, 0x24eb3509, 0xdebf48f7, 0x3f677574, -0xfaebe27c, 0x0fd6057a, 0x2b174c7d, 0x19cc475b, -0x86a24948, 0xf93b486a, 0xec4b3229, 0x5ff55583, -0x15c66f53, 0x4943cf48, 0x78f21980, 0x049dafd4, -0x741e70de, 0x5ddeee61, 0xb447d639, 0x2abea882, -0x27bcb7bd, 0x0d97a7db, 0x24a45573, 0xd3ff84e1, -0xb29edea8, 0xff9d4169, 0x34847315, 0x6f7306a7, -0x82506253, 0x00171a65, 0x35e28463, 0x9508b7a8, -0x75fa250b, 0x065d477b, 0x34249304, 0x9cf82e8d, -0xc49c9c3d, 0x796150ea, 0x02ee27e5, 0xdbe0e114, -0x0ceb7c06, 0x8658b12e, 0xf934a16a, 0x08b6c3d5, -0x789d90f9, 0x3494c445, 0xdde09cc8, 0xf7470770, -0x4f97ded0, 0x3591ff55, 0x49cd8020, 0x5ed34825, -0x1b156b21, 0x8ced7603, 0x4f481da2, 0x5092d16d, -0x2ee6ebe1, 0x17afb1a5, 0xc7b8382e, 0xb1ea3a85, -0xa2ce0013, 0x49a2764b, 0x521d82f4, 0xb4d3281e, -0x5346b8fa, 0xea0d859b, 0x491e5556, 0xa244aa3f, -0x01612757, 0x391098eb, 0xf15611e1, 0xb548c503, -0x93130d80, 0xb822cd1b, 0xaeb8413e, 0x3677716a, -0x5aa1e8e3, 0xd9df3a26, 0xa45d23e1, 0x138cf8d1, -0xd5bb81c5, 0xd5b3a6b6, 0x6450c940, 0xf9dcb5ab, -0x89f42817, 0x6bfa9846, 0xfb599b34, 0x58286624, -0x880b2850, 0xba0bd7d8, 0x23f9b1f5, 0xe634893d, -0xb55626b0, 0xea88afe5, 0xf3317948, 0x45b3c314, -0x12ef60cd, 0x861f0298, 0x9df9b7d9, 0x750bc728, -0x0107a026, 0x92d075e9, 0xa4cb738a, 0x4d80a3bd, -0x2ecbfc2f, 0x2ab8405e, 0x00806d49, 0x54cfd69d, -0x5f627f6e, 0x52adade3, 0x0d43439a, 0x26bd04c1, -0xdec4adaa, 0xd09365b3, 0xb07e6b69, 0xaec00374, -0x872fc813, 0x12d513da, 0x49fc1378, 0xb62fa8b3, -0xecf5b71a, 0xe1b7cb2a, 0xfcfc3cf5, 0x007b80dc, -0x272398c3, 0x2eb19c04, 0xbf3427e2, 0x99bca982, -0xe124481d, 0x08d93963, 0x0533e624, 0xa662297c, -0x0b4787a6, 0xb647b150, 0xec81da7b, 0xa71fa2d8, -0x6a6cdbda, 0x81ac8f38, 0xfb2a6a22, 0xee381b76, -0xdf04c6d4, 0xa7cf9808, 0x922f74c5, 0xcadb536f, -0xe2eb0414, 0x5ef67bc4, 0x4cd7055a, 0x5efb33af, -0x15a6f90a, 0xf374b7d3, 0xdc8e1c81, 0x7d7a1380, -0xe45a11d7, 0x47d86b2f, 0x687fee01, 0x91dcc48f, -0x13a3fb21, 0x0d962225, 0x81d6b2c5, 0xc6f9472c, -0x5e3cd85c, 0xefea9ff4, 0xaf23cdbb, 0x855b6c85, -0xbebe0361, 0x93749508, 0x9d73271d, 0x2ed98ea7, -0x982bad4f, 0x0b7d849a, 0xeb296a70, 0x1ede4d5c, -0xfd456e8b, 0x6e68d5cb, 0xcb05eca8, 0x783d4205, -0xf44a90e1, 0xdf369d1b, 0x6d770e65, 0xf2b3d175, -0x3750a53d, 0xcb41d546, 0xfc090b92, 0x1e793bfb, -0xf95e220c, 0xc9489628, 0x19330ddf, 0xbb3ed7ae, -0x5fcff880, 0xb73467b0, 0x2ffb94e1, 0x3cf4f68e, -0x364132c2, 0x162f0fc3, 0xb6e61410, 0x7d923452, -0x7437d978, 0x3d4e5f87, 0xbccae82b, 0x3f766f7f, -0x01b20414, 0xf938c74b, 0x5b40b872, 0x82265389, -0xeec17bf5, 0x05debd79, 0x233c02a6, 0xda9c6156, -0x5f721f56, 0x411a0b1f, 0xf7ac4162, 0x737685db, -0x59f2d52a, 0x05e789d3, 0xe5f3cb54, 0xf21edfca, -0x1bab963c, 0xf2e1264e, 0xf64b54c4, 0xf2c954ad, -0x500415b6, 0xaf0b4e2b, 0x7efa90b0, 0xd599c9a8, -0x1db78fda, 0xe46f9a0c, 0xfea4711e, 0xb6cf82ee, -0x1bccb9c8, 0x8f1c0d24, 0x4030215f, 0x4650a709, -0x40faa996, 0xe931dbde, 0x69325d9f, 0x3b9eb821, -0x1fe4513a, 0x56cabe26, 0x3a4e0a87, 0x736b4a20, -0xb7518f04, 0x39d42642, 0x9fd7fb23, 0x10c9e73a, -0x636f73f1, 0xc527f2fe, 0xa26a30eb, 0xdf37179d, -0x514c4aa2, 0x35e9c3b7, 0x44a5d905, 0x4beaf2f8, -0xf19f5f94, 0xc2fce14d, 0x84d6d019, 0x5d727a52, -0x89c23872, 0xba4b24d7, 0x56fe9fd0, 0x0a094a06, -0x49032487, 0x20a05f63, 0xc5c41fa5, 0xc2bb20ba, -0x50aded39, 0x87c1acf4, 0xd673ab01, 0xbb675253, -0x4c4a51cc, 0xb81efc6f, 0x761c7a06, 0x70f409c5, -0xb35f2bf7, 0x94b1842e, 0x221c684e, 0x275f3df6, -0x85f13440, 0x5e975c05, 0xcd68aef9, 0x1905171c, -0x83a63d24, 0xda77c1e9, 0xd904745d, 0x7e145218, -0xb6dc967a, 0x160d4c41, 0xa657f9d6, 0x298d1599, -0xeb9e1714, 0x9094b1c2, 0x2b328c96, 0x8ec92de9, -0x65df7282, 0x697e7cc7, 0x5eaf7cfb, 0xf85f2b2c, -0x3a8dfcc7, 0x104d27e4, 0xfdd36c08, 0x0e710d9f, -0xbfa2a9ff, 0x3084621c, 0xa783b3f4, 0xc0a92b67, -0xe0f41153, 0x422ab6e1, 0xcc09e15a, 0x12624d90, -0xe04e68c4, 0x8e7e5fe9, 0x73fc577c, 0xf06d31cc, -0xdc6933a9, 0x7b46ca45, 0x82a1ef8f, 0xfe3f2f93, -0x09133db7, 0x8707ec96, 0x933b15dd, 0x83ee88fa, -0x64329b72, 0xeb83294a, 0x6a1979fd, 0x76e135d0, -0xfb82d0f7, 0x0eb5ab40, 0x3238ddc3, 0x17e1895a, -0xab09fec3, 0x9b01aa2b, 0xe5dffb13, 0xd7b89a51, -0xfd97e2d8, 0x31e8baf8, 0x0a844bd7, 0xe92c2a3f, -0xf723fd28, 0x8d8dcfee, 0x45997de3, 0xf3f66fb8, -0x9c6ed175, 0x9d09a91c, 0xcf687a76, 0xaa0a1bb2, -0x9abc05ac, 0x54da0c6a, 0xb013d20b, 0xb3a60e8d, -0xa4041564, 0x721c69f0, 0xadcbb137, 0xa78da1fd, -0x61eb8f2b, 0x20b80206, 0xa7fef9e3, 0x43e69780, -0x2e7d2105, 0x1fc2c0d4, 0x9e4a035c, 0x1d391a13, -0x7dc62265, 0x1ead5933, 0x496ce97c, 0x3ab8ae44, -0x36c32802, 0x5946844d, 0x0db8cfcd, 0xdf2dc77f, -0xbc99385d, 0x7da63575, 0x60313d5b, 0xa63067bd, -0xbd38b29d, 0xd8499661, 0x70cf216c, 0x27df62f7, -0xc8375fd0, 0xe5860a15, 0x43eae7bc, 0x634b776d, -0xda322f70, 0x4845c62b, 0xd203ddc6, 0x88772a73, -0x4245859c, 0x86c9fe74, 0x6b1fcb93, 0x44d87f32, -0x78b663a5, 0xafe103e7, 0xf37af1ba, 0xc7500cae, -0x732cc784, 0x3ae33be5, 0xc8fc57bc, 0x9f5afb1e, -0x5c08d7ff, 0xb153b9cd, 0x996b8fdd, 0xd9bb40ce, -0x59108156, 0xf53aebb3, 0x08e848c5, 0x533d36e3, -0x30415ad7, 0xe6c795b2, 0xf14f368b, 0xb1c47026, -0xc19d5168, 0x2d1ee985, 0x21ef2cb0, 0x19e33330, -0x2e585ebd, 0xc7c92471, 0xe52bc348, 0x5248d0b7, -0x8f8047f8, 0x7860d087, 0x8d9daac7, 0xe348534d, -0x5cf2542b, 0xf530b329, 0xec9d35cd, 0x22c3211e, -0xd78fa2d9, 0x5ccd4afa, 0x36b43086, 0x41505ff0, -0x6ef8b8b7, 0x8d21e267, 0x8019e2b5, 0x42fb5d92, -0x91e20727, 0x6fe8c69a, 0x1892ee32, 0x67c63f18, -0xbca72002, 0xd7d9ae20, 0x93c2c8a9, 0x187fb44f, -0x4df76754, 0x4a112103, 0x68477de4, 0x00538e8a, -0x84a6f4cb, 0xff74b213, 0xed0d9c8d, 0x307a372f, -0xf23193d7, 0x9df266c0, 0xcd9131bf, 0x4d7884fb, -0x44966696, 0x0323c77d, 0xadfeb668, 0x1fa2dfd9, -0xb7578c63, 0x8a5d9856, 0xc81985f3, 0x023d8dc3, -0x343a277f, 0xa053964a, 0xc8708064, 0x75c88148, -0x1a1bc416, 0x9713a3c8, 0x01a0c6f0, 0x8200f404, -0x8c3d5ac1, 0x0b531f90, 0xdc7e8197, 0x9cde055b, -0x03d0f726, 0x5f8cb39d, 0x40079754, 0xb86cf3ec, -0x95d281e6, 0xcdf73d3a, 0xfd1ca798, 0x47b51ff3, -0x26bd82d2, 0x4f7f628a, 0x42121ddf, 0x0263d3fc, -0x4afbaf1a, 0x0c4dea1e, 0x01b741ae, 0x7a438bd0, -0x8b820fc9, 0x4b9314a1, 0x09ed960d, 0x867ae17f, -0xa7da11e1, 0x4eeaabb0, 0x92b6b767, 0xc46ae3de, -0x1fa58ac6, 0xbc14be04, 0x2c3bcb62, 0x7b8ca13f, -0x55b67258, 0xdb2414ed, 0xf4780715, 0x2da33f59, -0xd70c2321, 0xace0a988, 0x3a74466f, 0xc873c6d0, -0x08837ba9, 0xed33318b, 0x8d97ccce, 0x2dc948c2, -0xd7fab572, 0x6af225b4, 0x16791847, 0x49979d55, -0xc7aa0238, 0x2696b7e4, 0xaf90c8d6, 0x7fbd7b43, -0xd5cb34bb, 0xff46949b, 0x73f931f8, 0x31d8b57b, -0x41fa3917, 0x44e97506, 0x52a469b3, 0xbdd21daa, -0x30488f02, 0x6ee3eb1f, 0x4808aad2, 0x78ff0ca8, -0x826cead2, 0x1e71fc21, 0x1fd81641, 0x714c9f08, -0x71ac1f39, 0x11253412, 0x92a6d60a, 0xb496409e, -0x3e241151, 0x67a8818c, 0xfd00854a, 0x7a70361c, -0x5dda0c1d, 0xdb7887a3, 0x26dcdb04, 0x6a7d588c, -0x81e0c55a, 0x54d2a698, 0x62048e52, 0x7c2ba376, -0xbe2b2b01, 0xa5dd0bac, 0x1b7d4ee5, 0x23e040b8, -0x76c285ef, 0x4c2b01ee, 0x34eabd03, 0x264b6261, -0x99643856, 0x115b4e72, 0x86b5ac49, 0xeb040d41, -0xe343e96b, 0x98e31e88, 0x44de4837, 0x1bb1ef9c, -0xb83c86c5, 0x1a52eeb0, 0x1f90f598, 0xbe7e172c, -0x67cd8bc5, 0xdc130e0f, 0xe2a1c399, 0x690a1f1b, -0xe75f6b88, 0xd4c62760, 0x9db2e144, 0x44a6a42f, -0x01eb64fa, 0x27e5c6a2, 0xd08a423e, 0xf5c24ac1, -0x56a616d4, 0x5d3c11e8, 0x9f452f4f, 0x106efdf6, -0x782a9dd2, 0xe3de8e3e, 0x0d0a1c9c, 0x6f2b937d, -0xf40074f5, 0x49b99d8e, 0x80a94818, 0x7d859cec, -0x62f9deb9, 0xf4b2d5aa, 0x29c9558c, 0x03db82b0, -0x3e151f8d, 0x80f48bdc, 0x13dce759, 0x1e44419a, -0x9fc16b8f, 0xcd11ed93, 0x3b83734b, 0x197d0630, -0x1f0e8c94, 0x3c23d1e6, 0x6cd6588f, 0x61328b1f, -0xda81cee7, 0x0abfb164, 0x6855b84c, 0xa6ce1d24, -0x2b8a9ff5, 0x4358f5b3, 0x3715d36c, 0xf0392717, -0x460873ef, 0xe632b3ac, 0x429a73fc, 0xe6c0d570, -0x778dbce1, 0x45cf770e, 0x932fb6e3, 0x813b228e, -0x89c4c5eb, 0xbfef781c, 0xd92a513b, 0x85fc3596, -0x763ecced, 0x614f36a3, 0x256a64de, 0x273cf78d, -0x835607ee, 0xe12fc92c, 0xcd39cadb, 0x8a57dc40, -0xe9ad11e9, 0x0a838cb7, 0xdfb5bc90, 0x03db53b4, -0x2c8440fd, 0x1883a3d8, 0x52b9faa4, 0x85865cba, -0xe262cfb7, 0x1d4f330c, 0x5cb42da3, 0xa17dbdfe, -0xf70726cb, 0xc85425c6, 0x95b2fd6d, 0x097eb5e4, -0xbadbd483, 0x62f7f615, 0xa31b1f8a, 0x6bdbde11, -0x7cb6d971, 0x683dbe82, 0xcce63573, 0x0684b015, -0x84693d3a, 0xe07cf230, 0xe92029a5, 0xd8b51931, -0x4e25b0c0, 0xee5270c3, 0x1976877f, 0xe86da511, -0x14325478, 0xde8e0ccb, 0x169d0b23, 0x6af61903, -0x66ab7559, 0x4315c203, 0x2cb683ee, 0xe535c8d0, -0x62b24e37, 0x166a8d42, 0x318ab2a1, 0xb2f46067, -0xcc8b522d, 0x99452df0, 0x09748975, 0xfe0ea905, -0x387a852c, 0xbb79dd87, 0x372f06b7, 0x760994eb, -0x72e12cbc, 0x9197fcb7, 0xb55298a6, 0x683aef24, -0x363ca2f8, 0xc9c78276, 0x34b3c182, 0x560ebad2, -0xb470e19f, 0x4c97a0b2, 0xcc9ac3ea, 0x8ce71a62, -0xe51eb203, 0x6ef6bc8e, 0xf3f6ce30, 0x3b897cb5, -0x3ea47192, 0x3568792a, 0x74fd4cf2, 0xf228e7c5, -0xd58b34e9, 0x6a248d54, 0x92cb751b, 0x40c56ee1, -0x2aaa732c, 0xc76e8739, 0x2f5469fe, 0x38b399e2, -0x1f1c773e, 0xff742d40, 0xe0b9893e, 0x49686555, -0xd934f027, 0xace42921, 0x88c3d897, 0x0616afcb, -0x1e93841a, 0xf6e1ea90, 0x7ce80ef4, 0x22ee431a, -0xed0f3142, 0x6e49847d, 0x2f524e8b, 0x75b795ab, -0x95049d5b, 0xf1c5849d, 0xa51dede6, 0xbcc8dc18, -0x1163a676, 0x3b1438e2, 0x76a639d4, 0xee1edd3f, -0x96de87c3, 0x45d63c50, 0xb1114d03, 0xff58e8a4, -0x60b4e173, 0x4364016f, 0x56b76f7d, 0xff1313a9, -0xd53ec4dd, 0xdcb4f982, 0x13592177, 0xd522e87a, -0x0fdbe476, 0x9187b67a, 0xf3d06269, 0x4a9da90b, -0xd9d341a5, 0x73998813, 0xbef2bb9d, 0xa05801b8, -0xf4980344, 0x1bb22261, 0x5d8912d5, 0x5b061137, -0x09cb8a14, 0x8ed7d22c, 0xdd4ce1d4, 0x62b574d5, -0x053c5f6e, 0x855a668b, 0xe8d65e27, 0x35c93fc8, -0xa40dfd35, 0x421230a6, 0x080542c8, 0xe7e5345a, -0xfd4f46c9, 0x7b08e24c, 0x40929d56, 0x3ca573c0, -0x5f4f0b22, 0x42e62596, 0x6c4be7ad, 0xa0d2df6f, -0xddae803a, 0x6c9d8ed5, 0x7ab7ad30, 0x4b21c7ec, -0x3c7f4f91, 0xd8a47ef7, 0x5b9022c9, 0x4d8b5968, -0xc4eb3055, 0x63308a8f, 0x454aceac, 0xca13fdfe, -0xd895c8ef, 0xb07b20c4, 0x2c33e72b, 0xa68baf63, -0x1224f1f8, 0xf575c61f, 0x4fc4fb09, 0xe5df35a8, -0x28a6d14d, 0x7c5c2df0, 0x0c1bf4c6, 0xf915588b, -0x9a153aee, 0x1c729730, 0xb37f5603, 0x2a56f79b, -0x31115753, 0x9320e4ae, 0xfe8a140f, 0x1fcb0de7, -0x99a89003, 0x5d17cb0b, 0x7526b3e4, 0xb1ffcdb3, -0xa244483a, 0xc6cae04b, 0x271a6cb5, 0x3a1a78e7, -0x9123d147, 0x1623164f, 0x50131c22, 0xc71c44ea, -0x9d45c809, 0x319a2d9f, 0x139a396d, 0xf5be1640, -0xec0129d2, 0x6d38ad24, 0xa90d58e4, 0xda465e01, -0xf7f30996, 0x633f98ad, 0x4408de5f, 0x2ecd5e18, -0x26a27917, 0xd392a671, 0xab12a391, 0xe273f8b6, -0xa9dad013, 0x8de4f531, 0xc349364e, 0x49b51ece, -0x6f1930b1, 0x9d042382, 0x9f400049, 0x7a2b169d, -0x00f3219a, 0xd4a4a932, 0x5a71a860, 0x2f119e2e, -0xf77637c0, 0xd56d138e, 0x67c00efa, 0xcab97fbf, -0x56fd87d1, 0x940d3bf7, 0x163ba5b9, 0xdac0c245, -0x21d9f9a7, 0x4b3d80bd, 0xb32c710a, 0x15ed4155, -0x3a399a5b, 0xb9cd0f77, 0x950a06e1, 0xcae6a37c, -0xd574a6bf, 0x5eb9924d, 0x5d9b285d, 0x51211b3a, -0x564da988, 0x2077db05, 0xa73b1fb0, 0xd2613ab7, -0x0b2c73d1, 0x65b52cfb, 0x1cb9ca42, 0x9633b440, -0x14dfe779, 0x5bd8153c, 0xfeacba2d, 0xc0f7be5a, -0x910411a6, 0x4a7bad83, 0xb80584f7, 0x0dfb949e, -0x30d44c70, 0x95dc2448, 0x451ddc9e, 0xec9b9d61, -0xca115af5, 0xaed655e5, 0xe3f6275b, 0xfb7e970c, -0x48acbc47, 0x0528dcd8, 0x792dda40, 0x2acc0c83, -0x5a6c52ce, 0x8987ea8e, 0xd51e0fff, 0x5fd74d93, -0xa2ebcf81, 0xb33982f6, 0xb02d8517, 0x7106b421, -0x8705902b, 0x5554a09c, 0x6cdc274a, 0x518b78d4, -0xc45272d2, 0xf1d20094, 0xbc83023b, 0x7b92e11a, -0x2127e95e, 0xea1c4f94, 0x87685745, 0xf02f8723, -0x0d657815, 0x65281001, 0x0a802809, 0x6c1de0f2, -0x7dfe2907, 0x8314380c, 0x825ef43a, 0x64928f88, -0x29ac56d6, 0x65e7896f, 0x3fe3e098, 0xb891785e, -0xb905a618, 0xfa0b7a5a, 0xb7760ed8, 0x2a09b52c, -0x2f1df687, 0x299a3810, 0x22384521, 0xacbfb85f, -0x769ef0b5, 0xbaf10659, 0xb8867a12, 0x070fc670, -0xbdaee197, 0x3e1d3788, 0x88f6a0f6, 0xe8ced6ce, -0xcd6b2889, 0x2f575b28, 0xde815700, 0xba108211, -0x81bb9106, 0xcb9f3470, 0xc7706cb6, 0x9b97c18f, -0xd965ccb8, 0x8abc2d40, 0x97ba3f98, 0x76e5ad94, -0xa1aa8a91, 0xbc38eb72, 0xdc19830d, 0x1ea6d2d2, -0xf2d44340, 0x14e2981f, 0x14c3da58, 0x56941785, -0xb89bbca2, 0xcdb3a50d, 0x649860cb, 0x73f27c05, -0xf17a7647, 0xd0ec6994, 0x7c1cbbf4, 0xa69d51b3, -0x2e62f6d4, 0xb47c815a, 0x9f38abc8, 0x04d73af6, -0xf295e077, 0x95227fe1, 0x54f76a6d, 0xe29cd090, -0xe8d8c7df, 0x5710353e, 0x003ef58b, 0xb36845ca, -0x49dc02bb, 0xf3ab0691, 0x1fcffc36, 0xb06ab2ae, -0xe447c7df, 0xdb64ac06, 0x6c3cc550, 0x45be8fd6, -0x57d936cd, 0x04a19414, 0xbd7826f4, 0xcd535a8e, -0x83a4f39b, 0xb767c0ff, 0x289274bb, 0x251bb729, -0x770e6068, 0x37499a21, 0x69173b98, 0xc7eb88d6, -0xf7e8e372, 0xe188c165, 0x628fcfce, 0xbe7dfe45, -0x6ddc9969, 0xa1cf2884, 0x0df7ffa8, 0x2f840376, -0x59ac62e2, 0x061a4781, 0x36b65146, 0xa4f96e5c, -0x1d6ac540, 0x42417b41, 0x0d6d203c, 0x27d1ae6d, -0x7c646013, 0x3a7e353d, 0x728d24ca, 0x99c73e22, -0x55aa311d, 0x4c950d8c, 0x981af0c2, 0x31e597b1, -0x1e0c483b, 0x8986725e, 0x193bb7ae, 0xaa4b61e7, -0xb0af3602, 0x24d7633a, 0x5932b068, 0xf5ec2a15, -0x46e00a83, 0xff944061, 0xb8ddc4a1, 0xc1e0ef58, -0xcf6ab52d, 0xb6217e21, 0x77a1c56f, 0xdc64b8f7, -0xecbad078, 0xda412cf2, 0x847e62f1, 0xddca350f, -0x68b4495c, 0x0f490863, 0x2dcf584d, 0x829e7660, -0x0303d884, 0x60465078, 0x29e5e1cc, 0x11f41ab2, -0x968f7872, 0x4660fbc7, 0xc8ea385a, 0xe474dbb8, -0x3b943657, 0xdf2ede56, 0x75667c66, 0xb8a1c4ad, -0x526410a1, 0xb4fd5d70, 0x87eb4dcb, 0x6a18ade1, -0x250cc94c, 0x39922dff, 0x39bdb8a8, 0xe264ed5b, -0x0ecd0891, 0x9d7fa275, 0xd75cace1, 0xfe009cab, -0x94440126, 0x0d2639e2, 0x87bf340a, 0xa1861ace, -0x8bec69d1, 0x964e70b9, 0xbe073561, 0xc3605902, -0xa22bc32f, 0xac6ece3d, 0x60b4e3b0, 0x7add4964, -0x58f5a300, 0x08679784, 0x026a134f, 0x412dd9e7, -0x22d33251, 0x461d6f6c, 0x59140bac, 0x68053736, -0x754dd267, 0x23796fe4, 0x40bd3f71, 0xf762979a, -0xf3960525, 0x913b5690, 0x34137ec4, 0xa08fd1bb, -0x19b9d1d3, 0x64799f17, 0x773451a3, 0xedbee62b, -0xe2aaeae7, 0xa262bca5, 0x67d1c5e3, 0xac9ec514, -0xc55ee660, 0xa21712b4, 0x1bbcc683, 0xce4dc09d, -0x6b277c75, 0x39dcd39c, 0x561eae71, 0xe5fc29b7, -0x53e081ff, 0xe3915c88, 0xe50d6831, 0xe0fa2cb3, -0xa679fefb, 0x1bf47255, 0xf3fca929, 0x53d6ef55, -0x9fdc0bdc, 0xc5019cf8, 0xe93622e4, 0xd4ccae19, -0xec135e5b, 0x3882c02d, 0x7b989295, 0x23866190, -0x1d65d694, 0xc44fd24d, 0x32ac5842, 0x0b7f6ca2, -0xe8567872, 0x5372e0c6, 0x42ad7230, 0x79708c5a, -0x7210aa7e, 0x43b33795, 0x5ebeb3de, 0xa10cc4f3, -0x1db8247e, 0xfd69e44c, 0x90265f7c, 0x64da4062, -0x64600ed8, 0x2be3baf7, 0xc9e5eab8, 0xc71082e1, -0xf916a1b4, 0x037218b2, 0x21f2c5f5, 0xb06f7fc9, -0xac7e85f4, 0x5ffe4990, 0x5fa03cc4, 0x1bda88a6, -0x06c6ecde, 0x6bbdf5b7, 0x3f661b1b, 0x1a752611, -0x0795cd8e, 0xc4912438, 0xcd7dc1c4, 0x20140d24, -0x28b7906d, 0x5c88487b, 0xdb4cb66a, 0x7480e66d, -0x6c3cdafd, 0xf89939fb, 0xda8084bd, 0xb1d004c2, -0x7dce565c, 0x03bca5c1, 0xe4698b06, 0xa4a6a898, -0xce307b03, 0x6ee1d1c7, 0xfadc6fd6, 0x31bc9ba7, -0x068077d4, 0x288c3a53, 0xbbb7bb8c, 0x31bb51cc, -0x6c3ebfc5, 0x528cd18a, 0x42a10ca4, 0xd8536a73, -0xcea79f78, 0xc1e60a2f, 0x1b34cc0d, 0x3b67ba68, -0xa1a5a7f7, 0xcccac432, 0xcce44415, 0xe9f72329, -0xed2b7418, 0x2e132fa3, 0x93c79de7, 0xae5be0c8, -0xe5d8ac4c, 0xe44494ac, 0x37fe2022, 0xb4b6a708, -0x8a64bcbb, 0xb2edad76, 0xdb183255, 0x00b76b3e, -0x08ed65a4, 0xf6cbe4e0, 0x68ad583a, 0xf52301a2, -0xaf2b12bf, 0x733b2cd8, 0x2b96df15, 0xd73694f8, -0x9828ad99, 0x3a0ce96e, 0x758b0926, 0x1a6224a8, -0x82751745, 0x50fb01ed, 0x2263404e, 0x24a8a8e8, -0xcfd357af, 0x841a5214, 0x473a05fe, 0x081b24e0, -0x27450a67, 0x3f544f1e, 0xb0c5d641, 0x96925629, -0xb3f52948, 0x94d1cca1, 0x8452f267, 0x78804a70, -0xd98dd79a, 0x1d618913, 0x514696a1, 0xc1f4673b, -0xbbcfa0d5, 0x47dd2bc2, 0xbb435b52, 0x3f5b7a76, -0x2ef3ebdf, 0x8a4abb6b, 0xf0f2e87c, 0xc10d0512, -0xec9148a3, 0x8c240267, 0x519b3600, 0xe46dfb40, -0xb2fc67dc, 0x47701417, 0x710ba38c, 0x05b578fe, -0x0e3f77f2, 0x43ede712, 0x6575f254, 0xb85e1540, -0xb875d437, 0x43f9e107, 0xfeeb6aa9, 0xf604d027, -0x926d6190, 0xff22770a, 0xbde679c4, 0x13c5f920, -0xc3a8524f, 0x6ada5b52, 0x2dabf693, 0x188338bf, -0x73322d1c, 0xd68babc7, 0xaf61e4d9, 0x2d8f9b52, -0x7180d7c6, 0x17fd14b3, 0x380408e9, 0x5508f09c, -0x50d3dddf, 0x9fbd289f, 0x0ab08840, 0x8696d39a, -0x3940f678, 0xfc6d18a7, 0xe798fc3f, 0xd424718a, -0x8a4fd5d8, 0x5b486672, 0x2ce2f129, 0x0f6a6b82, -0xbc3ba7ad, 0xd6170b7f, 0x41f53ef3, 0xc55130ed, -0x757410b4, 0xca3b3b2e, 0x9c7e7481, 0xd08f1082, -0x167589e7, 0x851a83ee, 0x83f804a8, 0x9a69644c, -0x982ae89f, 0xd423db54, 0xbaad1ff5, 0x4b40b588, -0x53ad20c9, 0x0a970cb2, 0x22bdf3f0, 0x64b4a53e, -0xa09f4dad, 0x612c3f43, 0xb88b2191, 0xf406c182, -0x090da946, 0xea6a775f, 0x0d65ff36, 0xef3ce316, -0x5d755d46, 0x7de78c4d, 0x8f5174d9, 0xafbf7d02, -0x4a4c86cc, 0x88560d24, 0xbe20b642, 0xaabaa5e2, -0xbfb7e1d7, 0x2ec8eae9, 0x2b186dc5, 0x6d309620, -0x3af05061, 0x766df20b, 0x7916052e, 0xfc2dded9, -0xb3d20301, 0xad33df5b, 0x4cee069a, 0xc1a7a81e, -0x5e0d2e35, 0x2805a1a3, 0x5f2cea35, 0x130cf8bb, -0xe79edeb2, 0xaedd8cbe, 0x80efe93c, 0x0d483938, -0x452afcb1, 0xa2b3758f, 0xce4f3a7f, 0x56122d3b, -0x9e168187, 0x8397f609, 0x146ff536, 0x7a7dc4c8, -0x50703042, 0x595cd1ec, 0xba543372, 0xe1b151b5, -0xc46d2c8c, 0x19e12bd1, 0x9282164a, 0x2ed012e9, -0xd9035dcb, 0x7d736af6, 0x2ca9d8ff, 0xfc99f12f, -0xc8ec3a6f, 0x62a4e97c, 0x4e31b465, 0x11e25a96, -0x3160f44f, 0xd9a1d58e, 0x20808031, 0xec00b0fa, -0x3c87eb83, 0x30f94451, 0xe2c3952d, 0xaf0801f7, -0xcac70533, 0x487d6603, 0x0af5250a, 0x63080e46, -0x6cedae0f, 0x701f0981, 0xa3b66541, 0x6b733727, -0x482f441c, 0xd498c452, 0xba40059d, 0x6f85bb3a, -0xbd51e78c, 0x2859c03e, 0xe70d9d99, 0x0fc6c26c, -0x5c078e15, 0x3f7157b2, 0x4d2cde72, 0x8be833f9, -0xabe0af3c, 0xf09058e5, 0x436204b5, 0x1e532c1e, -0x727cff49, 0xc11dd498, 0x7b88b1f1, 0x850b8bed, -0xbd0cc30a, 0x650bb89f, 0x610cdd43, 0xbed699b5, -0x18152f49, 0x8c0a6496, 0x87b0a913, 0x7af59111, -0xe9ce27bf, 0xe6fb006d, 0x6b357612, 0xe0572e24, -0x3045f40f, 0xafd7b93d, 0x6769860b, 0x8c21c3cd, -0xe303ea80, 0xcb18f550, 0x98389f36, 0xd2dcdc4f, -0x7b26eb79, 0xec64f080, 0xe21a0d89, 0x18ae1918, -0x7176e366, 0xe8c4d728, 0xc5cd386e, 0xb616f441, -0xb979bb54, 0x4a61011b, 0x9178034c, 0x4fce8d95, -0x97686376, 0x48f05b11, 0xcf14eda7, 0xe6ff3da4, -0x3162b2af, 0xfe2fd68f, 0x478783fd, 0xe1084210, -0x6f9facd9, 0xc6ccc402, 0x868466f1, 0xa6f47627, -0x39b7af6c, 0x9f91fb32, 0x02b65635, 0xd703f967, -0x6af2e5a8, 0x52c32e81, 0x31dac449, 0xa006713f, -0xdb92d3e0, 0x4506bbb5, 0x25f59244, 0x276d6b08, -0x9ab553cc, 0x37612200, 0xbb5fd352, 0x1e369f70, -0x6f3bec85, 0xa0d99e71, 0x93642918, 0x54c3b57f, -0x39745b49, 0x107f30f6, 0x7225202b, 0x0d32ee6a, -0xc9f8df68, 0x479b96fc, 0x5157d18d, 0x59fae351, -0x96185c52, 0x49dd2e14, 0x6bb9d326, 0x8dc40d3f, -0x8f9fdac9, 0x8d9d47ae, 0x5f32bf3b, 0x3def03fe, -0x6f93cad1, 0xf73d0b0d, 0xdfe00b8e, 0x97e41f69, -0xc9b2c8ef, 0x1de99304, 0x4cebc433, 0xd9e1d3b7, -0xb2b77b24, 0xad5d3803, 0x015cfb06, 0xe73dd973, -0xb0ac2332, 0x59ce79cf, 0x55945d61, 0x6df6434d, -0xc593a4ae, 0xaa34537e, 0x8ed711bc, 0x1c4521b8, -0x578db5f1, 0xc319851d, 0x155e2a08, 0xa5800acd, -0x70a1c445, 0x47aa82bd, 0xf70b6f05, 0x7a635ae6, -0xf8770ac4, 0x1a5ed921, 0x2dedcb10, 0xf636289d, -0x5c7544e3, 0x64db30a0, 0xae13089d, 0x33b2686e, -0x185f96a7, 0x97068958, 0xd7d1389a, 0xe5b44a6b, -0x36112243, 0xefa493cb, 0x9083a640, 0xe68c5c0f, -0x5c0adca0, 0x8d1b147c, 0xbf7f384d, 0xdd8afb98, -0xff4c2a95, 0x25366bcc, 0x3969376b, 0x9ae8c87d, -0x55335aeb, 0xaaed8693, 0xea5b1441, 0xfeb2e4b5, -0xdce1ef6e, 0x5404d8b3, 0xf2571c76, 0x300a8cb6, -0xbac6c865, 0x9af56dca, 0x5e5b7f74, 0xcbf77e48, -0x625a0618, 0xe9082583, 0xb36626c8, 0x8827ee3f, -0x063905ab, 0x516d8fbd, 0xa2841336, 0x400d8539, -0x80b1ce20, 0xc2250673, 0x674b3b7d, 0x5aca5117, -0x72376888, 0xc94395cf, 0xdf49d93e, 0xfa614c96, -0x6ae76787, 0xc2414688, 0xa3d907aa, 0x3f4d6e64, -0x55a0266a, 0xee5c5ee5, 0xf93bd2d4, 0x5d42fb98, -0x3801880e, 0xdb5d8c5e, 0x8199a6b0, 0x7439e4df, -0x3b913581, 0xf60f67ef, 0xffc3209f, 0x98e40217, -0x030aa73a, 0x2f36c2ba, 0x29abd0db, 0xc731f0c1, -0x7eb9df5a, 0x30cb5f3b, 0x3789b186, 0x6d86b5cb, -0x34285488, 0x20da7f81, 0xacbdf893, 0x2c2a002d, -0x9b83203a, 0xf0386c1a, 0x9d3483dc, 0x236c1e17, -0x36932dcc, 0x575da852, 0x026dbcbd, 0x55dc9721, -0x1cfbbb40, 0x6f41ae1f, 0x19291f9b, 0x1e0a9767, -0x122e0463, 0x5d1ffb16, 0xabd5bcba, 0xe995341b, -0xab265d98, 0x572681c4, 0xb2aec7e5, 0x4029fb6d, -0x41020e98, 0x26dc21a7, 0xd9f7c588, 0xeb5cfe4b, -0x58b43f0c, 0x99f4cfca, 0x199b0ab7, 0x0aa040c0, -0x764a034c, 0xc209cd28, 0x21bc4580, 0x6cdcfac3, -0x87a2c27d, 0x9e844f4c, 0xc0a13c4a, 0xfa616765, -0x7322b9c6, 0x61e4963f, 0x04776967, 0x45fff36f, -0xfd8157b7, 0x82e3a974, 0xdb5f3807, 0xb89df834, -0x707b88b2, 0x633991a6, 0x0f2be137, 0xaffa7d22, -0x4f3a5fc1, 0xe02d7929, 0xa0cfc36d, 0x1d2fa776, -0x9dd8cc06, 0xa9af0f7d, 0xa904959e, 0xde9f41c5, -0x67c2f167, 0x5c7bcf08, 0x457bb7e4, 0x59dcb4e0, -0x4a433c8e, 0x570f7e57, 0x6165d55c, 0x67c20286, -0x9eeeff21, 0x93a2573a, 0xad6ca028, 0xa3b6825a, -0xcd56806e, 0x732e6de6, 0x0593c268, 0x5033849c, -0xf63cda8b, 0xe04fe7c7, 0xb7aebd59, 0xedaa70a1, -0xcd6cbab1, 0x36486a78, 0x9fc80222, 0x9515ab73, -0xa5c9c606, 0x8cf5b39a, 0x4134c919, 0x1194230a, -0x36a59cc6, 0xdbfc20b1, 0x57734e76, 0x9748480b, -0xf4cc43ab, 0xa447c5a4, 0xfef930a1, 0xaaee7cf6, -0x9baf4bc9, 0x7ed4b11d, 0xa6d96c25, 0xa23ca74c, -0xaa544043, 0x16818dda, 0x0c1aba69, 0xff3ac26f, -0xfdc7a0d4, 0xc7b308d0, 0xc9abe69b, 0x2f9c52b6, -0x18b82863, 0x79535750, 0xea74f7b1, 0x4f8664fa, -0x9466d84d, 0xb266932b, 0x83926175, 0x9beaf1b1, -0x5a430d93, 0x5409277c, 0xc6657acc, 0x3b94532d, -0x70f91530, 0xd7f1106c, 0x93c01e83, 0xea491ef4, -0xc19a3766, 0x4f44f96d, 0x3505453f, 0xbe4bd0ef, -0x7fa37537, 0x2767aa84, 0x53545e49, 0xea73763c, -0x31165a86, 0x9d782d3c, 0xf5c4bd5a, 0x9bf85499, -0xad998612, 0x0a66ad87, 0xc34240b3, 0x886fb112, -0x25f6cd2a, 0x279d7eb8, 0x649a8506, 0x095702a5, -0xd257e1ba, 0xd2f16855, 0x927fc73d, 0x38b9c1c9, -0x4ff21a76, 0xa49835ba, 0xa5e78f6f, 0xd6a7eff8, -0x4b10ad12, 0xd2d47632, 0x4d69db46, 0xcb6b34ad, -0x9d510095, 0x2b3eaad4, 0x1a284335, 0x446175b2, -0xc7e72fbf, 0x88891af4, 0x0a4bcd9c, 0xf392ee57, -0x4e3b29aa, 0x5c1d5f9c, 0x70ead218, 0x8396bc4d, -0xd70c0ce2, 0x3ef572ea, 0x8884acc0, 0x994df85c, -0x99764347, 0x3e37263c, 0x90935e62, 0x1b3d8ec7, -0x59d3adb1, 0x855449ed, 0x5856989b, 0xbda0552a, -0xe5e2b642, 0x5dd26583, 0xa244fbd6, 0x1b4773f7, -0xa1ed86df, 0xff6e9503, 0x534ef6af, 0x82adbe2b, -0xc019cce0, 0x90b5466d, 0x05c2ff5b, 0x9366755e, -0x95f05f17, 0x9e66b9fa, 0x8df0d260, 0xcca134c6, -0x87ba85b7, 0x20897696, 0x217e2d47, 0x72275294, -0x91129332, 0x61ee3907, 0xdc16a89a, 0x87eeae2a, -0xb909819a, 0x58f2b5be, 0x481784c3, 0x12ed5ee2, -0xe2400550, 0x4f0644d8, 0xb51d41e2, 0x77c83780, -0x1f25d06a, 0x59a06d2c, 0x6d8bd115, 0xda1c2ac1, -0x868e8b5e, 0x071186d0, 0x43c0c312, 0xffe85804, -0xd9496f80, 0x84ce51d8, 0x7956483a, 0xd1405abc, -0x09561de9, 0xea291de7, 0x0dcfd003, 0x38178a17, -0xddf6e3b0, 0xa712cfcd, 0x5df8cd3d, 0xba55da91, -0x7b7269d0, 0xef16cc88, 0xb5878dd8, 0x9ba275f3, -0x0ef6b904, 0x95c36c7f, 0xedb2bb38, 0x5d49294b, -0xe2283613, 0xb8e5b63b, 0x714258e9, 0x0ffc610d, -0x4d3603d6, 0x2d2e428a, 0xb3bf9096, 0x5a72f460, -0x39b6db1d, 0xfc7152ca, 0xe743356e, 0x95b49b6c, -0xe68394d8, 0x09c6766c, 0xa121ea0c, 0x6d2ba336, -0xb2cbd5eb, 0xfd08c8c4, 0xedbcef77, 0x3108cbb0, -0x074d343a, 0x0b82d06f, 0xec4793a7, 0x395c0b37, -0x1dfe63e0, 0xa5f573df, 0xbda29e5a, 0xbe6b91f5, -0xa30334fc, 0x0bd7e798, 0x7c7d22b1, 0xac3f048b, -0xcabfc343, 0xac8e0d8c, 0x54186878, 0x9b09527b, -0x14567ce1, 0x9705ed18, 0x61023a15, 0xd8b762bd, -0x63b4f16c, 0x4c87ea52, 0x704b2865, 0xa5e2685b, -0xaf8d5db2, 0xc6bc0f2a, 0x33afc127, 0xc2561d76, -0x26a2bbbd, 0xcb63aead, 0x9bc5b6df, 0x9e31b4d1, -0x4fb75377, 0x5ec1ecf0, 0x63c5bf52, 0x0a017dd3, -0x1f2a20ca, 0x14cc6ffe, 0x0b3fcc86, 0x8c50a026, -0x3d672373, 0x8b956914, 0x30c8c153, 0xfd534b64, -0x28b0b854, 0x0b5d8e45, 0x567bc73e, 0x20b455de, -0x1829334a, 0xd434bf15, 0xc9619f5c, 0x5da74cce, -0x916401ea, 0xa3bd4486, 0x6823c60d, 0x9c91560c, -0x2117cad4, 0x6c66bcdb, 0x9550340f, 0x550e8d97, -0x5209cd44, 0x0dcb51b2, 0xe6492fc3, 0x0de46cfc, -0x163e5b7b, 0x40146883, 0x80e4a485, 0xb990134e, -0x7851d0f6, 0x5739c514, 0x8f242d6e, 0x36ca258a, -0x16a4cdd6, 0x315b52c2, 0x40eef0ff, 0x9f3a89b5, -0xd28c53c4, 0x3b0bfda1, 0x1c64048d, 0x33c36d3a, -0x99fbc613, 0xae676d5b, 0xdf81d183, 0xa485f8d0, -0x68cf4562, 0x518de339, 0x3eb4f6e0, 0xb4d76bb7, -0x16434ca8, 0xbd70620f, 0x9a5992eb, 0x5c9fa4a9, -0xc11b2c0f, 0x0451774e, 0xb6c3ec7a, 0xfe194a24, -0xa3174684, 0xcc56c062, 0xc574e8f0, 0x90abdcec, -0x31c7c52b, 0xec5de583, 0xfcd5d7a2, 0x426f41d4, -0x2cf1c508, 0xc72a0b51, 0x4fb1f431, 0x6624ef2b, -0x79aa8bfe, 0xbfad4b0c, 0xd77cf3f2, 0x205191b8, -0x4407be23, 0x8b2e5041, 0xd3f962b5, 0xb8d5b6ab, -0x9ab1e89b, 0x87acd401, 0x2f242e5c, 0x0a90d574, -0x61dc7ec2, 0xbdc51df7, 0x5b5ae6c3, 0xd502d4ad, -0x9186b015, 0x1fea30cc, 0xfb3f17ed, 0x4368b8d0, -0x5d16f257, 0x102b9206, 0x3f0f7d44, 0xf885111e, -0x5e2b6df1, 0x577ad1cc, 0xefb8ad88, 0xefd80ed0, -0x51b32eb8, 0xfa776389, 0x69a9f7ee, 0x662fc857, -0xc1ae7765, 0x2d964bd7, 0x675be16d, 0x44ed135d, -0x38c96605, 0xf3650d4f, 0x837ee4cf, 0x1f084ec9, -0x1195b940, 0xe6e0efe3, 0x1bb1ff64, 0x7711bbbc, -0x193c1521, 0x4071d579, 0x7f9cb73f, 0x5ec50212, -0x5fc22225, 0x958271d4, 0xce269d1e, 0x86cee227, -0x57667154, 0x6ee813a8, 0x75c7bbf7, 0x07dcfeab, -0xc0809ae0, 0x27b06249, 0xbae823de, 0xb6a1591a, -0x9d1dfe30, 0x983a41e4, 0x2ed09436, 0x2a635078, -0xd73ff054, 0xac7434ca, 0x6f133aa7, 0x2e2909b6, -0xae5a8d45, 0x30ac8903, 0xf8d64d7c, 0x3dfdefd5, -0xebb0e023, 0xfed8c69e, 0x891ae90d, 0x8e7e5320, -0x2cfb5b3d, 0x5ec75f82, 0x71e29320, 0x5a8cbf26, -0xeff320f4, 0x5812b25f, 0xf0c52517, 0xe622b0dd, -0x0acea14c, 0xbf136a87, 0xf9df1cbe, 0xb31b2ea9, -0x3da9d39f, 0x678326c2, 0x871cd9c1, 0xa9c1acc5, -0x71a6060b, 0xa3493e34, 0x16133a09, 0xfe5d0d43, -0x60e16195, 0xfac4b6dc, 0xb344292d, 0x5456c6d6, -0x7381dfe1, 0x35ba0a55, 0x16081681, 0xe5d6e16f, -0x216d2b46, 0xc9490c1b, 0xbf0a2520, 0xc0d10973, -0xa1d81317, 0x95813b7a, 0x46f0f8cd, 0x7221a626, -0xec8bfc36, 0xdeb10e26, 0xec798ae3, 0xc8ffbe45, -0xfcfa11e9, 0xebdc55a3, 0x736a379e, 0x676e7af0, -0xa2945215, 0xf068e484, 0x89231a34, 0xcedbf2df, -0x7a6311d6, 0x1d678905, 0x1c74cd90, 0x87129c62, -0x40806f69, 0x253b9301, 0x4f008223, 0xd3ff8432, -0x95012970, 0x88656d86, 0x0c0ee02c, 0x787f3587, -0xc42277e3, 0x79e6ef87, 0x5196006c, 0xf2d0cbc2, -0xab71f09a, 0xfb7962ba, 0x9a5ed845, 0x5f475d29, -0xe9e9f194, 0x6caafba5, 0x3f8a6913, 0xbcafaf43, -0xb426d1ba, 0x7ddf1b80, 0x87710a60, 0xd3f65d40, -0x217c5029, 0x6b6c6b5e, 0xdd30c968, 0xe2a8ad5b, -0x2ce40081, 0x0b0326fd, 0x1775f4b9, 0x9984d53b, -0x19c84319, 0x465a38ac, 0x1bd7e712, 0x99a9f93c, -0x67ced20b, 0xd909a91c, 0xcbbbae58, 0x1a56bcae, -0xc9c1c973, 0x2e090318, 0x353dc224, 0xb72fc0ee, -0x0001dc88, 0x52c0aec6, 0xb4a89127, 0xb8740fe8, -0x0141c569, 0x4ec1bf2c, 0x1c9f7cb2, 0xf7d58573, -0xafba44a6, 0x20fcaace, 0xed059923, 0x60d377e0, -0x9cd58a6d, 0xceb64564, 0x39d50927, 0x4f829bf4, -0xd782dd10, 0x7bfeeb5b, 0x2805389a, 0x06ee4e50, -0x45e3e1bf, 0x8b0782d1, 0x55510724, 0xde4340dc, -0x0468d730, 0x20af74ed, 0xdb7ff10b, 0x7977bf6b, -0x2bd02094, 0x1d0a216f, 0x03cfabbc, 0x164b1fcf, -0x534a4437, 0x1915263a, 0x150e93ea, 0xf9d63f34, -0x857af279, 0xf9b826bd, 0x4f9c1631, 0x761b288f, -0xefd930dc, 0x7e21b509, 0xc275ee25, 0x97dccf92, -0x2eb45005, 0xcb303a17, 0x84fcdc5c, 0xa21d3fe8, -0x724124a5, 0x54524483, 0x389170e3, 0x4e1ff7d5, -0x72110258, 0xc0cf6e82, 0x6e1fe12e, 0x65c90371, -0xa99c9462, 0x5b78aa98, 0xbc9436a1, 0xede73575, -0xde169877, 0x720934e4, 0xde3155b7, 0x7ebb2f0e, -0xb2d0e40d, 0x15b597d0, 0xdf082d5e, 0x22ebbbba, -0x68cb42cb, 0x58e6e661, 0xbaefc91f, 0x4e3217cb, -0x52cc18eb, 0x7bc2f199, 0x8e7fdc90, 0x4907f862, -0xd0815fa4, 0x1b7eaad8, 0x90b39c74, 0x2f02f979, -0xd7985fad, 0x82c4d349, 0xb878c5e6, 0xd6d7365f, -0xb360fdc2, 0xaf8ffc5d, 0xb0098ef0, 0x0b41dfc8, -0x24e4e4ea, 0xe17f8877, 0xbcde039d, 0x9b586e03, -0x192b18ce, 0x2a9a1d86, 0xa864f8c8, 0xce6563fd, -0xd9ee2351, 0xdef41347, 0xd21994e2, 0x387c9359, -0xe2d3abc0, 0x4982c680, 0xe3e43f84, 0x67d8fe93, -0xc8cfe469, 0x2095c98a, 0xda2db810, 0x9e5766c7, -0x3c2f4b20, 0x92e67606, 0xe1bac93a, 0xa805c705, -0x4aed9ea0, 0xd1f0c546, 0x807248fd, 0x43b26233, -0x3486434b, 0x4e2d025a, 0x755f498f, 0xb58c5be4, -0xebb5fcfe, 0xb6bc61f2, 0xa7693118, 0xd9df5f82, -0x23c0c360, 0x436d2b4e, 0x717ca75e, 0x6f0fea5e, -0xfe11bed5, 0x1031f3bb, 0x3a8c3570, 0x3c784752, -0x90a3f899, 0x38929e1c, 0x00c554a7, 0xfe083bb7, -0x489b1d2b, 0x81b619ed, 0xe8a7207a, 0xebfcc03f, -0x58265a1c, 0xdb698877, 0xc8da280f, 0xdb60cfd3, -0x0f8ac573, 0x41935f4a, 0x03f574c1, 0xe7084e1a, -0x4f481b4f, 0xccecdfe4, 0x17974d9a, 0x50ef62bc, -0xb28317d6, 0x1118de1e, 0x9f95e190, 0x116d18f5, -0x4d83f4f2, 0xfd2069d3, 0xff4df0c6, 0x1fb97350, -0x738c1695, 0x81218575, 0x049869e2, 0xafd6d853, -0x2eef0331, 0xabe2333d, 0x5f5da74e, 0x2aad7e80, -0x30ef17d8, 0xda18d115, 0x14cf5948, 0x83a8fd0f, -0xe0418383, 0x1051450a, 0xeda7fd61, 0xc1e5636f, -0xba6853ca, 0xd442829f, 0xba5046b0, 0x49ed0cdc, -0x47b45c36, 0x947b6622, 0xb937b3ab, 0xcc56bf60, -0x114b3314, 0x689ee17b, 0xd06cf12e, 0x27d6ede6, -0x6f558857, 0xe04c4418, 0x7b8d2ee6, 0xac511481, -0xa7ffeb98, 0xfcdc240b, 0x2df5364c, 0x76c0a100, -0xadb9fe5d, 0x1c947fba, 0xde6aa412, 0x4a27d690, -0x1b0b912f, 0xfb9e0ef1, 0xccb65c2b, 0xfc951766, -0x6e2517a2, 0x6915a740, 0x5d25a614, 0x6cd7b974, -0xa7ce4d32, 0x3224f657, 0x4282b7a1, 0xec366255, -0x0e47b33e, 0xdcfcc85d, 0xa1664173, 0xf59ba283, -0xee9e56ff, 0x19394206, 0x10c79974, 0xae5dc824, -0x6c0ee811, 0x71e73438, 0x3dbd7096, 0x3067b002, -0xd4dbf4a1, 0xeeadf929, 0xf9fbf969, 0x313828ac, -0xf3098c09, 0x9f4471b4, 0x603db9bc, 0x183e48cb, -0x4fde31ea, 0x1d742894, 0x15925c74, 0x05c76d00, -0x0c4014bc, 0x8740492f, 0x55d13385, 0x26da473b, -0x46073574, 0xe838bddf, 0x05eebc9f, 0x102db9d7, -0x29e40133, 0x25358cec, 0xfc5a1101, 0x3d47e19e, -0xd5d41f36, 0xf0ed93fb, 0xfed93b52, 0xa8eb8c88, -0x8c46e49a, 0x53e1c785, 0x6b16ceb0, 0x7b371456, -0xa002bb76, 0x124fb3fa, 0xcce07630, 0xf7a2b85b, -0xbfc9d8f6, 0xcabd8927, 0xa17a6f95, 0x376f6b76, -0x736e63e6, 0x1817b743, 0xb1065d6a, 0x465c9f0b, -0xa0f2834b, 0xf2a4e312, 0x440c9337, 0xf90a881c, -0x5394b548, 0x39d7270b, 0x34df5a19, 0xef293328, -0x9208a78d, 0xb10047a0, 0x4cdb36e0, 0x956341d2, -0x1172f6a7, 0x0d4dbcd9, 0x150257e5, 0x6fcd2819, -0x58d0fbb0, 0xd0c02e0a, 0xdaa14a11, 0x9916a9cb, -0x1b57cc6a, 0xfcb7d15f, 0x1f53a411, 0x5879f5b8, -0x16b0a08b, 0x682bc794, 0xc7a3b009, 0xe03786c4, -0x0b5a7c63, 0xc8dc0446, 0x193e9316, 0x47d5c30d, -0xa60a3c80, 0xf4a12762, 0xf8793c61, 0x2409a00b, -0x6c6d50f1, 0x7ea3a994, 0x30451730, 0x826e1d45, -0x3976f84e, 0xd23342a7, 0xd4f833df, 0x15fb07a5, -0x44a51f2f, 0xa791f9c7, 0x2ab655ac, 0x330f04ed, -0x7993420d, 0x6c30b008, 0x5605f4a6, 0x0b8f8ab9, -0x6cf1deee, 0x6b60da51, 0xbc1422b1, 0x74e8f1f0, -0x0c2c01f4, 0x88eee820, 0x9f6f60ca, 0xbd4e5376, -0xa2e01d54, 0xbbac9a7e, 0x95ffc15c, 0xf17cbfe7, -0x2f7be37e, 0x65db6739, 0xe75ad573, 0xa9b14b3a, -0x3999e77d, 0x402c7ee2, 0xef122e31, 0x2b82eacc, -0x29085b92, 0xe4ffbf36, 0xf8ed47db, 0xead6e5cf, -0x5de54805, 0x7a1d9515, 0xcb865781, 0x4e60f4ed, -0x98d61f94, 0x3cef4824, 0x6ce64200, 0x7a8e1493, -0xefab6481, 0xf9e0de21, 0x00d68953, 0x8328e844, -0xc5ffa497, 0xcdd2f8e5, 0xe70ed12d, 0x8c8d24f0, -0x95abdfaf, 0xed54a7a8, 0x443150f3, 0xbfd46120, -0xbf5a7bf6, 0x99a5b47f, 0x0c9d7760, 0xd70a3ea5, -0xe4183d93, 0x5af80980, 0xba263b1d, 0xeedf5a94, -0x8f935597, 0x7e84bb8d, 0x24a54001, 0x230a3c64, -0x5ee409a0, 0xbc4a02e8, 0x73487e4b, 0xb8a14b12, -0x4d2c9105, 0x1fdcdc1c, 0x10eb2962, 0xb0217fba, -0xbe8793f2, 0x3c44cfcf, 0x67a95305, 0xdef9c77f, -0xd60b9d0d, 0xa8a1fbc7, 0xc3b7fef7, 0x1a76c5ac, -0xf55092a9, 0xe3a3752a, 0x08a88130, 0x9909eb5a, -0x0e4c37c4, 0x13b66089, 0x7a49ac95, 0xe60b4832, -0xc300cf0c, 0xe1582543, 0x3b3d2c8a, 0xfe882522, -0xa24b794c, 0x81a3b399, 0x48f3fb1e, 0xd2b325a8, -0xf8015b2c, 0x0c35913d, 0x639e9bbf, 0x80c8ec76, -0x81c0705b, 0xa4fe643b, 0xa06100d6, 0x9f8d4894, -0x5d17d490, 0xd7a9007c, 0x5adcc8b3, 0xd7c1c03e, -0xaefa34f6, 0xbf959047, 0xdaafcc99, 0xdd14e71c, -0xd7ac0efc, 0x3c9c4c89, 0x48bbd2ed, 0x907b4da3, -0x817d5b8b, 0x822c5db5, 0x7f3293bc, 0xb712ffb3, -0x7c154824, 0xc354ea89, 0xd6b1252b, 0x39bf78c0, -0x2127a973, 0x9bd70e29, 0x51fd538a, 0x535fac18, -0xf2c5e53f, 0x1b736b26, 0x71255f0f, 0x6c254021, -0x3eb72bda, 0x05da558d, 0x84131772, 0xa276638f, -0xd577fb79, 0xef0d1a08, 0x8bdc53fd, 0x2a71b3fd, -0x4ed41204, 0x592abca3, 0x995154c7, 0xbede8562, -0xe9492455, 0xddc9a5ce, 0x1e9db016, 0x57477a40, -0xcc86ebfa, 0xba7c18a3, 0xd9060d3a, 0x3866c4a7, -0x5ad05ee6, 0xcd1df98e, 0xcf031455, 0x3d31984a, -0x481e2ea1, 0x29e760dc, 0x5e49a8e0, 0xe8354e48, -0x611ffef7, 0xfa9bb0d3, 0x7c8bbad7, 0x65fb7b7b, -0x47971e27, 0x431f6b52, 0x1cf9b8f0, 0x2ab3c24e, -0xecbaeb0e, 0x7d57cf23, 0x23d1f43f, 0x3e607986, -0x3d697fe1, 0xbb3c596e, 0x707a141c, 0x9c3c5974, -0x4789aa5c, 0x2354a40b, 0x4e050f47, 0x430f417f, -0x1ad0b489, 0x291fbd9f, 0x0919fd8c, 0xb5b1cffa, -0xcab90385, 0xd81804ac, 0x818b7b6b, 0xb3fff6b4, -0x42881bda, 0xe562c316, 0x4d374783, 0xe5d9eebd, -0x0f8d2d59, 0x014043c9, 0x68dd37c2, 0x0b1cee46, -0xe0fde299, 0x0ee2e06d, 0x8314a2a2, 0x0492cb97, -0x402bd26a, 0x7e3b9161, 0xa492def0, 0xb3474888, -0xeeeb9bfe, 0x00dbde69, 0x585d8ad8, 0x3cdc19f9, -0x6d5b6885, 0x3809aac8, 0x7da7e149, 0xbca5df24, -0x6379477f, 0xc7953baf, 0x9c6782e7, 0xcab924d8, -0x0e319d11, 0x6e190440, 0xecf1be0c, 0x8b4940fc, -0x5ac3a404, 0x60aa3685, 0x421d8f9f, 0x29d74acf, -0x0ebbd757, 0x2d32d521, 0xacc74cc8, 0xbd2cb4db, -0x35d8f179, 0xd3e00599, 0xfea923b0, 0x921c158e, -0x129411a1, 0x9d7caf7b, 0x49e567e6, 0xc4807bdf, -0xf93181c9, 0x718e08c3, 0x19c6ed21, 0xdef94589, -0xd0768a4c, 0x148e8c3e, 0x68788954, 0xf34fccad, diff --git a/src/cpu/intel/haswell/microcode-M7240651_0000001c.h b/src/cpu/intel/haswell/microcode-M7240651_0000001c.h new file mode 100644 index 0000000000..1f30842af2 --- /dev/null +++ b/src/cpu/intel/haswell/microcode-M7240651_0000001c.h @@ -0,0 +1,5120 @@ +0x00000001, +0x0000001c, +0x07032014, +0x00040651, +0x4f9aa4c4, +0x00000001, +0x00000072, +0x00004fd0, +0x00005000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x000000a1, +0x00020001, +0x0000001c, +0x00000002, +0x00001331, +0x20140702, +0x00001331, +0x00000001, +0x00040651, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x54803536, +0x5b42092a, +0x9f337d90, +0x538e6ae5, +0xee797c87, +0x40b34be7, +0x2058da4a, +0x02665b1f, +0xa19308a3, +0x5b19c4b7, +0x4a1b425b, +0x7d6a74f6, +0x81624193, +0x3a559605, +0x5475280b, +0xe7319d58, +0x48624ca7, +0x507af030, +0x3b32d96a, +0x30164068, +0x5284d2f5, +0x725b2915, +0xf63c9280, +0x44b7c142, +0xe67ca7b3, +0xd6f163e7, +0xcdf51f3c, +0x41d180a1, +0xcc3931b1, +0xf7a544a9, +0x7f6bf77d, +0xfc45a45f, +0xf0985836, +0x652d7e2e, +0x0324b1f3, +0x24b9548c, +0x7bcae7a5, +0xdcdebf79, +0x27015922, +0x0c83c606, +0x3d2ceeb7, +0x61c5eec8, +0x6b6899c6, +0x3e500531, +0xf08bfa44, +0xb304a8f4, +0xcee8f713, +0x2912c786, +0xfae6c34c, +0xa5292960, +0x7d63e389, +0xaa257a01, +0x1fb25054, +0x963fc676, +0x5bcb9fd3, +0x58f369a4, +0xf6e3beb2, +0xa58b5eb0, +0x33c7eba4, +0x37fe8b66, +0x00714403, +0xf0fd0c4e, +0xaa122996, +0x9a55b184, +0x00201507, +0xc9fb6e3a, +0x11ab60c8, +0x80ff6e84, +0xc37aabdd, +0x0fc23175, +0xb0b18c34, +0xf1ec806c, +0x00000011, +0x93ec6a8e, +0xe7e59e0e, +0x8354a863, +0x6532cc70, +0x6b941f6e, +0xe6efb015, +0x813a0672, +0x4bd6a134, +0xe7d2ae2e, +0xb801fd17, +0xc6730db1, +0xffaf70c6, +0x99963a56, +0x552b2448, +0x06da244f, +0xbddb7094, +0xc41bbd43, +0x8566bdda, +0x8730b02b, +0x0ffc1836, +0x57f083f5, +0xbc7eb4f9, +0x93720c90, +0xb948e082, +0x646a29c2, +0xab785ca6, +0x22d6de29, +0xad6632ee, +0xf781c405, +0xab8c189f, +0xe9f84888, +0xdfc91edd, +0x7c42229e, +0x713f0b2e, +0xbfec8862, +0xd7041476, +0x30cdc9df, +0x6a884797, +0x4df51550, +0xe6e3d09a, +0x2b63aff3, +0xbe437a9a, +0x2bbc6a7e, +0x36cd4cac, +0x4c3a5d83, +0x22e35ba1, +0x2602cf9d, +0x90506b16, +0xad5e4dae, +0xfd02e76c, +0x41ecfaf1, +0x5885656a, +0xf1da2947, +0x9a6e02ea, +0x338ab563, +0x73de7a3e, +0x80131004, +0xd82962c5, +0x8e8c88ef, +0x7ae0d2fa, +0x3420c82a, +0x202e795c, +0x3a0d9404, +0x3d337908, +0xc1c8f56d, +0x1a9d5f9a, +0x8d294c4d, +0x054fa4f0, +0x1feb3cba, +0x1fcaf41f, +0x36ce8dfa, +0x15765644, +0x5741c08d, +0xd258e716, +0x67d51f76, +0xe16efcf6, +0x53877ae9, +0x5632053f, +0x3efc3569, +0x21202e38, +0x59367def, +0x73e8c31b, +0x5558b394, +0x3801fe26, +0xa291f1ad, +0xb853571c, +0x43d8845b, +0x919a9ede, +0x5eaf4d90, +0x986cb6b6, +0x822a630b, +0x0904e79e, +0xa20dcab6, +0x05470b25, +0x62dc1169, +0x0de7ce15, +0xd4cafd8a, +0x2216b4fa, +0x3ba658df, +0xf84db879, +0x94365ec0, +0xffd76c6b, +0xcf5003d0, +0x2ab8d6dd, +0xb87ce90c, +0x77b341c4, +0xe9bdd2d1, +0x05343cca, +0x0d0a7813, +0xcc23da22, +0xbbaef3c9, +0x82bb35d0, +0xc8d97e27, +0x062c07f0, +0x31fc6743, +0xa5d7b86e, +0xfb399a4a, +0xea0ca298, +0x45c56f0c, +0x9de334e0, +0x2b808722, +0xdcb90fee, +0x86880439, +0x4bb5520f, +0x2f8ccd3f, +0xb31154f5, +0x76b037c1, +0xc8cf720d, +0x9e53125e, +0x495ab1d6, +0xdc09098f, +0x90ff69e5, +0x4fb52efa, +0xe07dbe04, +0x505dce0e, +0x9930358e, +0xc7243a95, +0xacae76b3, +0x23702ced, +0x36ba2ba8, +0x12f6a4d6, +0x6291a5df, +0x43e09751, +0xd86e8606, +0xe5b8d173, +0x84cf7f38, +0x5a2a732d, +0xea8dec57, +0x075ab4bd, +0x3093ea05, +0x7ddc4623, +0x9eeac07d, +0x0bae6c5e, +0x1170d85f, +0x54585ce5, +0x424b5930, +0x6f962ed0, +0x6291c170, +0xda9a243b, +0x7a1aa460, +0x07fe426b, +0x3e0fbcef, +0xe6f65e2e, +0x16a76698, +0x2ee2c974, +0xd42dd042, +0x60b2d4c2, +0x84ca0de9, +0x1b321482, +0xd80847e7, +0x97cf9fc9, +0xabad4e62, +0x4c5e7534, +0xba474a3d, +0x4b386fe1, +0xb1d3bd4a, +0x66f2e748, +0xff997d29, +0x7f9a5ecb, +0x08b74697, +0xd5ff51e3, +0xf0e80f08, +0xbc8a3750, +0x96c2b150, +0x993ddd82, +0xb1fcad1a, +0x39c457ed, +0x8e7887a9, +0x951385c2, +0x5e192577, +0x5ece4be6, +0xd8aa0cce, +0xda9db0dd, +0xf0a65605, +0xcbe133fb, +0xd62d187c, +0x43d65c21, +0xd9ff512b, +0x2c1e670f, +0x94862f11, +0x2ad5876f, +0x0347f479, +0x837c9d9a, +0xd588cfb5, +0x3184bcbe, +0x4d29209d, +0xb11531fa, +0xcf60605f, +0x8582c22e, +0xf80aec84, +0x56770992, +0xb008270e, +0xe61f0247, +0x5b96ca82, +0xddf6a6d7, +0xa8fd309f, +0x5a37ebf0, +0x89c55922, +0xa1d3e943, +0xc7437f57, +0x8767c3b9, +0x2aace409, +0xd3ffea65, +0x01673382, +0x3062cc4d, +0xdc3ca70e, +0x72ec823f, +0x013dfcf0, +0x3cea3c0f, +0x5c6f9892, +0x0401238b, +0xd0f5c9a9, +0x83d5363a, +0x20594afe, +0xf31625f7, +0x36d9bf4d, +0x979d10e2, +0x82ec9621, +0x1575da7e, +0x1e48b107, +0xcf273476, +0x8f6bc6ce, +0xc468a1f1, +0x19304de2, +0x8a514ade, +0x0da8ed49, +0x89bba358, +0x4fcde67f, +0x1b236a87, +0xbd9c34c4, +0xc31e7624, +0x8d4e1b94, +0xca715a48, +0x57aab513, +0xdc01097a, +0x61536abc, +0x9ab66e22, +0xc3e9acac, +0xf9793dc1, +0x01d27d3e, +0xec783b0a, +0x7f8a7b0a, +0x8952bd32, +0x78f97900, +0xea165074, +0x6a3b9b4f, +0x6994be45, +0x97b278db, +0x2d7a1059, +0x2a9a584d, +0x3102f971, +0x3dd2edfd, +0x75d40781, +0xbd8bb3f7, +0x69c9e2ad, +0x2924453d, +0xf971a611, +0xc44c6a20, +0x6458ddf0, +0x344e948d, +0x99861094, +0xffc216ce, +0x46a544ac, +0xa0e12280, +0x2342bdd0, +0xd264153a, +0xef7c5510, +0x982fdb4b, +0xaa8061e1, +0xeeb4cb06, +0x1c4e24bb, +0x35137ad0, +0xd383e7b0, +0xb3515b98, +0x34ab789c, +0xc6677101, +0x3a179ec6, +0x8e1b7f83, +0xbc952258, +0x528cc506, +0xbb0ee496, +0x041a20c7, +0x435c1764, +0xc5ffbfe5, +0x7aadad66, +0xba7c49b5, +0x16961f55, +0x53a973b0, +0x82b7c322, +0x6108d300, +0x1e465f56, +0xde5b0cdf, +0x1db4c843, +0xdc84068d, +0x746b86a8, +0xe18bb690, +0x9c31e6c3, +0x3fbe45db, +0x9fcd70bc, +0xebf1e3bb, +0xf293ed6a, +0x9acc3c5f, +0xc2d8d4a7, +0xb4f10f0e, +0x8f08aade, +0x7ff658e3, +0x571f87e4, +0x53911020, +0x8eabc16c, +0x66de43e6, +0x86313e1d, +0x091638f2, +0x4fabd2cf, +0xf64a8806, +0x34a9f3c4, +0x342eb98c, +0x6da221f8, +0x5dc9ad3d, +0x3f235ca4, +0xf13aae29, +0xe58aae0d, +0xbb0f06b0, +0x0146ce07, +0xdb82eed1, +0xb8a5b35e, +0x5ad2f1af, +0xc904facd, +0x9cb2684d, +0x664cdcc1, +0x8b83058c, +0x3a144bad, +0xd818e9fb, +0x1a4378e3, +0x087ee2c7, +0xc45812e8, +0xd10705f1, +0x040bdc37, +0x24dcced6, +0x5d917109, +0x6544b517, +0x321bea6d, +0xb4c74b5a, +0x93b11971, +0xdbd04da0, +0x9180fdad, +0x9b5c205b, +0x8e123be0, +0x2752e398, +0x74ab49b4, +0x3b8090ae, +0x8e564f95, +0xae58ebb9, +0x7c2ab771, +0x8d8b4559, +0x4aae59b0, +0x3d57724b, +0x5324f318, +0x3f6b4f5b, +0xa7c2dd69, +0x75cc2f3e, +0x58d81e09, +0x724a5ddd, +0x00373586, +0xfe1bfc27, +0xebeed8c4, +0x9f4df4dd, +0xa3d7150f, +0xd4cf1d99, +0x77663800, +0xba7326ee, +0xf799bb1d, +0x17f711a1, +0x0b683496, +0x16734362, +0x1c1ec0fa, +0xbd7606d5, +0xde0ecfaa, +0x4fa3d7e1, +0x18b5cafe, +0x86ded1cb, +0x84eb26a4, +0xe15ad21b, +0x6222135a, +0x4813612b, +0xf435160d, +0x8bb9cdef, +0xc0febebc, +0x908ea268, +0x6114ec6d, +0xde72772c, +0x2de363f2, +0xac07caff, +0x4d1367d2, +0x5ccb4e20, +0xb8c2480c, +0xd40a88f1, +0x4c8aaf04, +0xec69eadf, +0x08d603d4, +0x1d6b72c2, +0x45cb2279, +0x9c18a457, +0xb1eefcd5, +0x6f5bbe8a, +0x8656da63, +0x5abd01ef, +0xbd3a0fa9, +0x07f8b848, +0x4723e8da, +0x1c8a7404, +0x0ee2c60d, +0xf4d73710, +0x2e98dd50, +0x42265393, +0x607cae51, +0x5ad2d65a, +0x443fae0a, +0x212bdac1, +0x94eff1e7, +0x8fd0d83d, +0xf3f48729, +0xaa613eeb, +0x532716af, +0x22f67b55, +0x197dd562, +0x30bbc619, +0x452ca5b8, +0x69125584, +0xbe8ffd8f, +0xcdc33841, +0x1afadf4f, +0x6c327b0a, +0x1ffee636, +0xbc3e313d, +0x2274f02f, +0x1d4bd1ab, +0xadf7f661, +0xc6ae5dba, +0x65c67cce, +0xd8ba01b4, +0x067ec15e, +0xcdd98197, +0xf63a814d, +0xa63ef3b1, +0x3a0f7ab7, +0x0b141297, +0xbd16dffd, +0x80de07c9, +0x5b855491, +0x775d7917, +0x79039980, +0xc4f0b5a2, +0x7ad189f3, +0x5b808e2c, +0x6e6c48f8, +0xea4b291a, +0x244153fb, +0xd866387a, +0x0fbad87f, +0x37fd2697, +0xe38d68cc, +0xd56bb9be, +0x0fe9183c, +0xfe4286c7, +0xa9238f4e, +0x57c6bafe, +0x7e7c64da, +0xf5f0b3c6, +0xf2174839, +0x9622aabd, +0xbfb9add1, +0x7a9d83f3, +0x22cdc940, +0xd0aed140, +0xb2842a1c, +0x19350ede, +0x844cea83, +0x03f824b6, +0x2d6a80d1, +0xcc7234f5, +0x64e522f9, +0x68463ec1, +0xc22ca25a, +0xf6fb480b, +0x92df3534, +0xcd143a85, +0xcba797d1, +0xab3040eb, +0xaa862cda, +0xeb8dbb5a, +0x72f87be7, +0x0574be93, +0x7967a4e8, +0xc43d5618, +0x95f48b0f, +0x605384f1, +0x49d7bbd0, +0x20e6ff24, +0x8891ad61, +0xbe37fb81, +0xa14cc9ac, +0x1737a15d, +0x0d8c64c8, +0xf31ed8cd, +0xaeba1a38, +0x99b73598, +0xfb58e711, +0xe2cd0a2a, +0xba3ae60f, +0x53874128, +0xca6bd9f6, +0xdaa3865a, +0xdf558d1e, +0x69c074ea, +0xd2d74d88, +0xd7924cfa, +0x9cfbba04, +0x560eb2ac, +0xb58eb3fb, +0xac0f471a, +0x8b9775a6, +0x04f93abd, +0x71830a7b, +0xabece5a2, +0x7d0b9603, +0x447e0437, +0x9b19fdf0, +0x2aeb904f, +0xb6c581ab, +0x69c4a6e6, +0x9e996bf9, +0x28345395, +0x8797c013, +0xab770f48, +0x02414cb3, +0xf1400aa8, +0x77b85d38, +0x6c1519d4, +0x68aa8d18, +0x4ad589f6, +0xde108567, +0x26ce3cc8, +0x855d739d, +0x4123b448, +0x0acfaf11, +0x3d1d706e, +0xcf6dfbc2, +0x02869b0e, +0x8ad4c4b5, +0xb118ed06, +0x19defc29, +0x955de3e2, +0x4246d3bb, +0x20d55907, +0x9263ee1a, +0xe3b1a896, +0x2aa64af6, +0xac652be4, +0xc319f5db, +0x1f87bdbc, +0x5d35a264, +0x915af64d, +0xa63f8b9d, +0x8b596f71, +0xb289a637, +0xbf4df8f4, +0x637223dd, +0x1c7b17aa, +0xb73cff48, +0x490b6e3b, +0xfb9cc770, +0xbdddc085, +0xf61b9342, +0xf632cb9c, +0x7a1273c8, +0xe12e5792, +0xc8874fda, +0xbac1a2cb, +0x2525df42, +0x14735a6b, +0x48b123d4, +0xbf80739f, +0xa5acac23, +0xe509b461, +0xd72e2e2c, +0x94553b2d, +0x61274a8a, +0xbad8722a, +0x9cde98cb, +0x497a8db7, +0x84bca500, +0x85ddf493, +0xcb5717a7, +0xdbada31f, +0x34e9d14e, +0xc23d20d7, +0xf3a32825, +0x688ea606, +0xecbc1379, +0xf7cc7e17, +0x98826691, +0x0a2fc103, +0xfa891b0d, +0x6031f829, +0x3d93a25c, +0x45ebed73, +0xd5e938b5, +0xb3a8e0cb, +0xd271fb09, +0x6c01ec65, +0x26528bfb, +0x358e2521, +0xde0ea304, +0x3aa0e26d, +0x06bbe682, +0x0e141d87, +0x80f84192, +0xd2ca916c, +0x38193f29, +0x1f26fcb8, +0x48b0f72c, +0xa9e5b9d4, +0x757b1925, +0x2171c824, +0x7a5cdb28, +0x67a9cd39, +0x58e682cf, +0xfe773460, +0x54f56488, +0x4fab4a18, +0xd5d62f56, +0xaa1ff73c, +0x663a3adc, +0x5b28b030, +0xcf7c2fae, +0xe86c08aa, +0x675ecdf9, +0x6c54904e, +0x59bac9cd, +0xe830b6b5, +0x9c72f3c8, +0xc2d2dfc2, +0x7eea1860, +0x3e68956e, +0xcabee365, +0x2abecc3f, +0xf5584efd, +0x97494ab2, +0x4547de19, +0x23b75177, +0xf5158de7, +0x8f887368, +0x82aa37f9, +0x45edb6b6, +0x8cd4567e, +0x35a853f1, +0xabdfdde1, +0x126a775d, +0x74971303, +0x92965554, +0x884af013, +0x01678e07, +0x5ce5e949, +0x0e92a0b7, +0xb4ae83b3, +0xb33f17e1, +0xc1eaae2c, +0xf4d8a373, +0x7aaa8222, +0xbdf9d56b, +0x4b34135f, +0x5ec53983, +0xd79506ad, +0x48931578, +0x907b2609, +0x129ca0e3, +0xd1fd7d15, +0xd6cff42e, +0xe91542cc, +0x006dd750, +0xd45db570, +0x0d6787cb, +0x41fac008, +0xa14abb50, +0xe3836ddb, +0xa08d7c2a, +0x0c42081e, +0x99231ac9, +0xc572a6d2, +0xedd8f7c7, +0x299a0245, +0x1dd8dc9d, +0x67f43cff, +0xe59c0063, +0xb53706a5, +0x4779de2e, +0x01d4ae62, +0xf1b3af1f, +0x04fe1683, +0xa6ae95d2, +0xc049f706, +0x35da73f9, +0x786c55fe, +0x45541fe0, +0x0b712835, +0x0ba80808, +0xfbfa8301, +0xf243658e, +0x3fa0a207, +0xf1ad361a, +0x1022cd47, +0x9931194a, +0x458118ba, +0x65b01c42, +0x9eaed094, +0xea3c1c7d, +0x1f54744a, +0x3a93c482, +0xb624d29f, +0x78015089, +0x0a68782b, +0xf5497256, +0x0d9422b2, +0xf79ca89c, +0xd0a62c46, +0xf6bfb279, +0x87639d4f, +0x853431ca, +0x7cbf82ce, +0xb0b8579f, +0x91dbf9ca, +0xa4b41a8d, +0x6cc03669, +0x0a8459aa, +0xa84998ee, +0xb0e5442d, +0xc1206664, +0x1d66b29c, +0x2aa662fe, +0x3ff230f5, +0xb3b9ea5e, +0x28d59572, +0x071a2784, +0x48ad8df4, +0xb672a99d, +0x431837c5, +0x312da9d2, +0x552f1f1e, +0xba76bf31, +0x0fde86fc, +0x3a4b0e5b, +0x27767132, +0x3207cd66, +0x7acd2d75, +0xa04c2b7a, +0xbeb5576e, +0xe69396d7, +0xdb471676, +0xc1155dd9, +0xedeff438, +0xad1fac56, +0x2bdd6c24, +0x1b6a29ed, +0x3150d31f, +0xfef32ddc, +0x4478c8cf, +0xe291fdb3, +0xbff85812, +0x07f945a0, +0x2be5471e, +0xcc38f9f9, +0x2372ce7c, +0x8a9ffc48, +0x4e76ee7a, +0x6f6edd41, +0x192c0cc1, +0xe2edaa52, +0x455a388c, +0x33f1129e, +0x3a0db93d, +0x3182e227, +0xd751be55, +0x8f36e600, +0x3cfdd41f, +0x4b9aef6d, +0x2f7793dc, +0xc53a7f45, +0x8fc9ed8e, +0x515715ae, +0x0fd65cf7, +0xd9a798e8, +0x515ac27f, +0xd45cbc76, +0x8bde099b, +0xff9917b9, +0x8aafd3e3, +0x5fa447d1, +0x7dcff5a9, +0xbba90ca7, +0x306066d0, +0xd8ce22e7, +0x9b82e925, +0x1878501a, +0x3c04683c, +0x8178343c, +0x2bf7e5ee, +0xe9e47825, +0x3b7e90d9, +0x4e702270, +0x66092537, +0x8c499ea6, +0xfa7d1ac9, +0x08ca5fe7, +0xcaf8de79, +0x1fed7575, +0xc0878a9c, +0xe4c7df3b, +0xd1192e90, +0xae1c68d1, +0x8ae43a18, +0x378c02d4, +0xbcfa07c2, +0xc9f916d7, +0x0e219276, +0xf56251a5, +0xfa7a412a, +0x34cf60f7, +0x518c5a65, +0x8bd147a9, +0x51043034, +0xb63867c8, +0x0ef93a61, +0x5913a6ab, +0x5f6fe3d4, +0x2ea3d257, +0x720d761d, +0x4b5c0dff, +0xa9a9067a, +0x3576ccf3, +0x52a971d7, +0xeba0bc8a, +0x609de37d, +0xe6cc6920, +0xf5a5622e, +0xd0c42306, +0xf9d9eca2, +0xc24b0b89, +0x317c001f, +0x99f19460, +0xeab46ee8, +0x14af43e9, +0xa56855a2, +0x335f45cd, +0xfc976335, +0x7fa14450, +0x36a6f269, +0xe6b4a19c, +0xb702c383, +0x3e161b8b, +0xcdf62b5e, +0xc79e2106, +0x11f6c5f3, +0x0528cf91, +0x76c17fda, +0x2092699f, +0xed122ee1, +0xd0442e54, +0xf533a93a, +0xc1dddb81, +0x4c48e8a9, +0x517fba08, +0xc05af246, +0x19ea1e1a, +0x7a53892b, +0xf81e9376, +0xa50e2b38, +0x3f269768, +0xd0d29924, +0x51e6eed6, +0xc4c07b1f, +0x1c5b173e, +0x80cbaab2, +0x8ba8b11e, +0xdc2b9580, +0xa5d279d3, +0xf264d55e, +0x5e0eb0ad, +0xae46c12b, +0xe1dde70b, +0x47f68516, +0x68dab0ba, +0xe978b014, +0xa0e24cc6, +0x961da73d, +0x60662676, +0x185f3c24, +0xd7da33ce, +0xe37e39b2, +0x64ee0f85, +0x53208460, +0x09262285, +0x165ef996, +0x66df340d, +0xd07ad742, +0x10423944, +0x5f72f0b7, +0xbb6389ed, +0xcba698f1, +0xa1b0f049, +0x800dc191, +0xb44316c1, +0x202e479d, +0x6ee045e5, +0x75250bdc, +0x703ca7c5, +0x4995125e, +0x3b14ec5f, +0x6b4ba5f4, +0x98d07673, +0x46098994, +0x6891156b, +0x59d5f5db, +0xc5d2152d, +0x84edbe62, +0x35e66a49, +0xa58b0a83, +0x1ad08594, +0x330f0018, +0x563a7d22, +0xa39da757, +0xa8eefd78, +0xb6d24f9a, +0x0b646c4c, +0x74c16db6, +0x8c91aed5, +0xad4dd608, +0x4e0dc1b5, +0xc8cf6685, +0xa617c47f, +0x9797a48e, +0xa60bdc57, +0x57423988, +0x573924b2, +0xd26d99bd, +0x1ea54b51, +0x4335e39c, +0x5f57c59e, +0xa2026ad0, +0xbe251997, +0xe782f773, +0xe825f32e, +0x23efe8d9, +0xd193811f, +0xb43a94ed, +0x0604c7b6, +0x015a8da6, +0xfde229c1, +0xe4a43b08, +0x404b8388, +0x6dfec830, +0x66eb6b3e, +0x02cd278d, +0x7b2a3b47, +0x53d2f2ec, +0x2d82c0f3, +0xb8156542, +0x8cb4e600, +0xc2b720b3, +0xa16af285, +0xb377d3cd, +0x4abb191b, +0x88c66fa6, +0x4a821c50, +0xb6a4bf28, +0xc09c062d, +0xfb856cf7, +0xa41125f7, +0x219c807f, +0x6f8bd4ac, +0xd6276165, +0x3f9ed781, +0x49ff1c61, +0xe3854da0, +0xba0e472f, +0xeae9f81b, +0xdab793d4, +0x573ad66c, +0x6ba2bf0f, +0x3ee93044, +0x399db579, +0x5626bcac, +0x25baa925, +0xc5ca7ab8, +0x2f630a5f, +0xeacb1efb, +0x435c8db1, +0xd8bb68fa, +0xd41b1fb3, +0x06434a60, +0xba285e40, +0xedab6511, +0xe265b9b0, +0x383fada9, +0xb908e96c, +0x6baaa59f, +0x0b327507, +0x1773282d, +0x4e9fbd60, +0xc701cd31, +0x62896b62, +0xed700f5f, +0x38df9e58, +0x97eaf308, +0xe707fdd1, +0xcc0e1c62, +0x2cdc90d5, +0x6fc314d5, +0x258b7893, +0x303a2879, +0x9559982c, +0xeed7400d, +0xc91c91f5, +0x9a56a47d, +0x27482786, +0x2b7a6e5f, +0xd1a6a9d8, +0xc2349e62, +0xe2f94d62, +0x891135cb, +0x9760ea82, +0xdd2c8d9f, +0x00b4cf61, +0x453b6c9d, +0x6c3619ff, +0x58096979, +0xf3ddd46e, +0xe9e4334b, +0x2f0b3f65, +0xcc91a583, +0xc42c72e1, +0xd8206185, +0x2cc5007b, +0x794967f7, +0x351d7c59, +0xc1836803, +0x96ef084d, +0xf7f2c8a0, +0x06e384f3, +0xf4e50073, +0xf99e8383, +0x511dad20, +0xa3181f7e, +0x76dd9820, +0x9056b6e6, +0x5e2eef9b, +0x1b708db3, +0x61cd4520, +0x21fb54a9, +0x8df6dfc4, +0x66768bc2, +0x84419abb, +0xb57efcaa, +0x666e4545, +0x5474db67, +0x3e25059a, +0x06221228, +0xa7395d62, +0xaa2f5904, +0x402ca4db, +0x93493a9a, +0xbfc2d6d3, +0x2a98403c, +0x7fb63164, +0xdfcea70e, +0xf7c90a2b, +0xd6d4a59e, +0xf0d591e7, +0x2307ddaa, +0x439cfbe4, +0xa81b20c8, +0x012393e1, +0x523ae00c, +0x6e249634, +0x12bc37f1, +0xc523a326, +0xc7580939, +0xab063148, +0xe1c7866b, +0xc9b1667a, +0x2fad1f24, +0xee522d95, +0x2fe92e48, +0x813c9a5c, +0x0b226aaf, +0x009d00e4, +0x42abf72d, +0x44f2133b, +0x3e898e0a, +0x78a512f2, +0x1c105e72, +0x08951b8a, +0x1e5a35de, +0x0e28e856, +0x5dcf985a, +0x63ff27b3, +0x5c0d4a53, +0x7c18da96, +0x11cddd39, +0xb29505c7, +0x41462446, +0x0ef1e2f4, +0x249f8562, +0xd178666d, +0xd98daa34, +0x561ac04f, +0x4de3646a, +0x16d77ee1, +0xc36a9c24, +0xde1f7dd4, +0x8a633eaf, +0x7ae16e67, +0xf1af0e65, +0x25287e88, +0x5c606845, +0x9439fdda, +0x6f5138aa, +0xdf97c6bf, +0x639a9ce9, +0xf41a89bd, +0xcedb500a, +0x3cf37ecf, +0x5bb9d77a, +0x34b8853e, +0x849b1429, +0x54653682, +0x6a020ed3, +0xf3b91a11, +0x6068efd5, +0xddb5289a, +0x02b64c69, +0x1eb2ba97, +0xa6c46e47, +0x2a4c1ecf, +0xa71712b4, +0x40895499, +0x4f37fcf1, +0x5cbc9ced, +0xc662b1cc, +0xac535570, +0x27ed6ca1, +0x2177a3d8, +0x675ce22b, +0xe3095c95, +0x688a52d6, +0x57f1fce6, +0x32ab2e87, +0x45c135b8, +0xf64859e0, +0xbbcdd921, +0x8b4075f5, +0x1b50ec22, +0xbba41e3c, +0x78307f4b, +0xcaafef45, +0xc8645a4b, +0xeb743b8c, +0x326f87d9, +0xe4448780, +0x4da186b4, +0x65e21fe9, +0x7894e394, +0xf9a430b7, +0x216908bc, +0x06856be1, +0xaaee6daa, +0x50c7d590, +0x6e6d448e, +0x0cc8679d, +0xb55a6229, +0x92ad5319, +0x85ad9493, +0x36163b75, +0xa84f841f, +0xa468af85, +0x51788616, +0x437ecc5c, +0x7603fe0a, +0xc94ee734, +0xe610511d, +0x881d2657, +0x620a2f81, +0x69b7c4d7, +0x490af3b2, +0x570d9ec8, +0xed541f39, +0x90573fc4, +0x11e8cb9d, +0xadaf811e, +0x54d4b616, +0xd5fccef5, +0x0b3d7e70, +0x66fe5859, +0xcb3c38ba, +0xe2917270, +0x2f0a5ac6, +0x60957f74, +0xa616db51, +0x492d4689, +0x4ead8e43, +0x26b31363, +0x19a57294, +0x48fc2866, +0xe4d3951f, +0xd959ac06, +0x5d754901, +0xfd996d94, +0x5abee864, +0x78dd567c, +0x9a2dbe1e, +0x7ac44435, +0xa7582eb0, +0x5999cb1f, +0x4206c12e, +0x9859660a, +0x248f194f, +0xa4dac482, +0x6ba3ad4c, +0x5f1cbc3c, +0x5485b5b4, +0xca4030be, +0x71f7e0a5, +0xdb0bf1d6, +0x5bc7b8e8, +0xb2285178, +0xaa4eba2d, +0x201a2ac2, +0x6617ca57, +0xadeb0c95, +0x5a256471, +0xc5bfa51c, +0xfd79f832, +0xc3153463, +0x6aa87186, +0x1e23d197, +0xc7b02eb4, +0xdd4875dc, +0x5c3c0776, +0xd9b6a2ff, +0x6a82f1cc, +0x0a5ee213, +0x72d5f081, +0x56ee7208, +0xb7b7b0d7, +0x28b52266, +0x6deeaf2e, +0x4fe1bd3f, +0xcd4af160, +0x3b31e610, +0x4bc8d92f, +0xd75853e9, +0x04a3662a, +0x50d193de, +0x363a900b, +0x7b04fe66, +0x99072e5e, +0x2daa5fb7, +0x011ab301, +0x565e6ab8, +0xbfa88876, +0x1073ddad, +0x19a942d8, +0xb5a45742, +0x43ce67d3, +0x880d6790, +0x6d09683d, +0x2bba28b3, +0x9e30b5d3, +0xa5e094b5, +0xbffb1f54, +0xda2866cf, +0x170061d2, +0x087bbd9d, +0xe9147714, +0xccf75aad, +0x5980ed14, +0xb9b54e0e, +0xb370cfce, +0xd4477c79, +0x29569a2e, +0xee03c3ff, +0x8db1ad92, +0x6b62fc38, +0x280fd928, +0x93e906e4, +0xc0fc86f7, +0x66ea89b0, +0x9585292b, +0xee3678b5, +0xf57ee940, +0x7113e57e, +0x68c6a0ea, +0x83f0ab09, +0xab5d7d82, +0xaa7c6d28, +0x7fbe8a3b, +0xabec0792, +0x101cfdbc, +0xa0772cf3, +0x9b1179b4, +0x720bb88f, +0x37780004, +0x6c92eada, +0xfaf5450a, +0xfd4c8f89, +0x240857d6, +0x64134ce9, +0xbabddc85, +0x7ccc36a8, +0x00b3fb82, +0xd494018f, +0x4b0c4ecc, +0xc51edeec, +0x7e94fe64, +0xe8071a49, +0x4e27faf2, +0x2acc3b75, +0xddefacf8, +0x5ac7088c, +0x93a44eff, +0x0b95d285, +0x53e5ddf0, +0xbd491bc8, +0xa18d7961, +0x730e2f58, +0x799e89ac, +0x861e1337, +0x94b7b76f, +0xb29b3ea9, +0x2b053a54, +0xd745754f, +0x3e597c54, +0x97b5e51a, +0xdd21897e, +0xcb3877af, +0x35cf2417, +0x1d6b6638, +0x6dd0be45, +0x5ab82db0, +0x2446a5eb, +0x70a6826e, +0xe326b14e, +0xa3658c00, +0x60c39ff8, +0x7c655475, +0x0ca4fdd0, +0x7315b3cd, +0x91ef3632, +0x917dcc35, +0x32dbda46, +0x66583842, +0xb5b5e9c7, +0x07bb1f42, +0xb7e1c698, +0x5b0f6474, +0xa14d16a1, +0xf7c69623, +0x240c07fc, +0x6edac9d1, +0xcb28d545, +0xdbbfa1e7, +0xe5b5ccfc, +0xc1421833, +0x8c06525e, +0x99f00d70, +0x41f1756a, +0x014b6db1, +0x0b0e4c9d, +0x7ba19462, +0x7ed7bdf2, +0x58460b8e, +0xa6ce6448, +0x1a1b2b90, +0xe43ada40, +0x3fc41eb2, +0xcb1faab6, +0x259ec598, +0xf221d105, +0x447ddf12, +0x784fa66e, +0x3896fbbf, +0xd607bd56, +0x5d1e9547, +0x075bffdc, +0xfd39e000, +0x8cd067f3, +0xdc91037f, +0x1cd74bf4, +0xfdae556e, +0xe9e56868, +0x06abe229, +0x72ecaf0d, +0x3dd95d46, +0x50655092, +0x8c6be8b4, +0x5882c6a0, +0x48ca02e6, +0xddd72bed, +0x81efbbc0, +0x50b69a75, +0xb29e4220, +0x3b2bb967, +0xb8600874, +0x7e4d9fa8, +0xf4af1198, +0x230409c5, +0x1dedeade, +0x0eb89456, +0x2dab1b30, +0x670e764e, +0x1b04935f, +0x7c2322f9, +0x1a509a7e, +0x994f97ff, +0x3c49c170, +0x446dde7a, +0x7e4c9251, +0x17663c09, +0x41d6c8cd, +0x928cceaf, +0xb65ddf36, +0x369fec92, +0x21d1bc44, +0x2d3f693c, +0x103fdafd, +0x37f61a5e, +0xd9c957c4, +0xd83f085c, +0x4faeb03f, +0x11d010ed, +0x3e40ddcc, +0x55f637e3, +0xe7a0c55c, +0x19959083, +0x7601f29d, +0x84240811, +0x2664346b, +0xa0ffb322, +0xcb360ff8, +0x9faa514e, +0xc7662f40, +0xc2a7cb3f, +0x56817170, +0xeb0fc302, +0x20b1fae4, +0x8117ef36, +0x160c02c7, +0x68308405, +0x5eb5a567, +0x870effb3, +0xdb0cd956, +0x41fa5f19, +0x6324c713, +0x6e776daf, +0x51e9d794, +0x57d7681a, +0xd6f6a968, +0xe7307598, +0xae05ac2b, +0x53294cfd, +0xdbfa3706, +0xac8d9743, +0x6fbfd6db, +0x3f4ea73a, +0x91c1059b, +0xf66e20d5, +0x8f53988e, +0xa0c4a0e3, +0x3d969b28, +0x7bfa0ff2, +0xe92c21d9, +0xe9537559, +0x539b62f7, +0xc33bd95b, +0x4de2a8bf, +0x85da648d, +0x670148c1, +0x4af7a7e5, +0xc8f69af3, +0x277cba64, +0xc316448a, +0x73e7f8be, +0x1b703345, +0x93c376e0, +0x0f53fd44, +0xe62bf3ba, +0x6f8ec391, +0x3c972ca9, +0x091ca3c6, +0x713e1e60, +0x9646b17a, +0x1c8d733a, +0x476f523a, +0xf78c4236, +0x35a9422d, +0x8a3bc243, +0xed1797a1, +0xc39d0fde, +0x82d4e0e2, +0x1a571aa6, +0xcb37073b, +0x8ce8b583, +0x0e46b21b, +0x8be5edfc, +0xc3264126, +0x6de50885, +0x3154140b, +0xeb03524f, +0x42907386, +0xf28eacbc, +0xd5babd2e, +0xb100d6bd, +0x709f76a3, +0x13b1642b, +0xd4560451, +0x148b14c2, +0xf2b7d130, +0x958baf5b, +0x722fb85f, +0x6ad8c4d7, +0xa050553c, +0x73952ded, +0x02a5cfc9, +0x02d778af, +0x81d56fd7, +0xabd587ee, +0x228e0dd7, +0xbb299ac8, +0x69a11126, +0xcc516bed, +0xe21a4b27, +0xfa888cb4, +0x58623b79, +0x6b408e00, +0xf629abcf, +0x21d9e338, +0x70027401, +0x6a09706e, +0xc3fdaec7, +0xe6450cd8, +0x6b36442e, +0x2604c9e1, +0x77cf42c0, +0x9b1e0522, +0x79340f54, +0xbf357f9f, +0xa7e01d5d, +0x1e998ad9, +0x6b62ec55, +0x2cc8ffd9, +0xca7262f1, +0x29759fc0, +0x3fb1e23f, +0x407b7e8b, +0x395d7b38, +0x7fc7cb0d, +0x4948cdd5, +0xac1cd1d1, +0x4bdb813a, +0x4b718f91, +0xacaa36fd, +0xa7c7997d, +0xcd147af1, +0x76993ad2, +0xd7119077, +0x237b6926, +0x6a8dfc22, +0x17f9ec46, +0x0b00917c, +0x9aae66c1, +0x2da74bca, +0x2f86482a, +0x6b721e26, +0x021553d7, +0x1754bf78, +0x569b3825, +0x5c00e561, +0x703103c8, +0x18e0004e, +0xd4f68c70, +0x96b64cf0, +0x200f3dcb, +0x18e446b0, +0x8f249d20, +0xbb66d4de, +0x8a7f6d01, +0x7ab85979, +0xadea84f7, +0x1d96548d, +0x6121759b, +0x669911e0, +0xdb91abd7, +0x52c1db11, +0x1d58473e, +0x81840d89, +0xb4723b6f, +0x2a6e48be, +0x7957eb22, +0x8bdfe7fd, +0x70e922f3, +0xaaf702c0, +0xfeed26cf, +0xe3cc0244, +0x2507c5b2, +0x7bb59f03, +0x8c3a76b4, +0xa03388da, +0x2f2b627c, +0xe8f29601, +0x20a1dfcf, +0x6c46841d, +0x10487f61, +0xb9e954a5, +0x3e21654a, +0x7a44e6a8, +0x034045dd, +0x8f1f192a, +0xe78808e9, +0x1e1ebb0c, +0x3e4e01c0, +0x1051faf8, +0x9f1ebf14, +0x1dcc581f, +0xdeb51e40, +0x93fc89d3, +0x38415c2e, +0x4d7c8e9f, +0x0042112a, +0x230348a8, +0x3afe6855, +0x7fa8aa29, +0xf11e0de0, +0x80b32965, +0xabda25bb, +0x32ab8cd8, +0x11bb816b, +0x3f8c8a40, +0xb99b9603, +0xe92ee1f4, +0x3d42efe9, +0x5cf83e52, +0xe9aba8fe, +0x5b0d3dd0, +0x162bf5d7, +0x23409250, +0x21df5d9f, +0x282d7c07, +0xbae82d2d, +0x204a34fb, +0x73c8cbda, +0x4ab2d458, +0xd33dc9c5, +0x3104d92f, +0x89e1ad5f, +0xd4ec1ebf, +0xece6e880, +0x2cc54cc3, +0xf50979aa, +0x08ab292b, +0xba7a1ba1, +0x42900cef, +0xb239e70e, +0x75438b52, +0x9fce69a4, +0x7aeac599, +0xc479a7ad, +0x95f4b513, +0xa4ad8fed, +0xe1381482, +0xfdb4f70e, +0xb7ddad0d, +0x6e12b0f7, +0x70aa2201, +0x93035ce8, +0xfe87d943, +0x6a7e80cb, +0xbe0c643d, +0xd3ab55b4, +0x4d3ffb16, +0x0dff6e18, +0xee2e77ed, +0xa3f0244b, +0x590474c7, +0x798d5547, +0x59ffa16a, +0x38df5e5b, +0x7aa158c4, +0x751e5482, +0xaaeba39e, +0x2ccd1221, +0x9bf44535, +0xf936f2fb, +0x34a9de69, +0x33ca175c, +0x0485855e, +0xc6c0aa01, +0xf633ef11, +0xf6c65488, +0xcfd4eb34, +0xe7452351, +0x74e63c2d, +0x43b23730, +0x3e6371ba, +0x16e216d4, +0x1bbd985d, +0x3d479c16, +0x4e8f0427, +0x283e2970, +0x44260f1e, +0x7c45e38e, +0x702bf17a, +0x1e629106, +0xfeeb31fc, +0xfe5a3c3b, +0x727dc41a, +0x3442e1e9, +0xfd3b7735, +0x85b0efd8, +0x250b13e9, +0x4a9766ff, +0x95ce8407, +0xbfb894ea, +0x97a5195e, +0xa6654a73, +0xec4faa90, +0x0b65e10a, +0xfb928cc9, +0x494b456b, +0xe7fa2204, +0x95373d0b, +0xd24b972d, +0x457ddac1, +0x7a747b27, +0xf318eb4b, +0x24e4a65d, +0xa3f0749a, +0xe717abe8, +0xba8c80bd, +0x7d52be30, +0x12c93c4e, +0x126f17ca, +0x905ade24, +0x72fd1b30, +0x86f10948, +0xde05d53a, +0x40c2d9e1, +0x3d29c294, +0x0205e0e1, +0x782e184f, +0x38e19d96, +0xc23e1505, +0xb0a3ee7b, +0xa629fc94, +0x67a0be1d, +0xf19c4cb3, +0x43663bf0, +0xc2d0be9f, +0x5f55643b, +0xdbceb2fe, +0x5dd84fc8, +0x5daa48fb, +0x4cf735b4, +0x0509a91d, +0xf349fff4, +0x5eb0f0ae, +0x4bc02c37, +0x0a7775f2, +0xe82c4183, +0xf3f68ecc, +0x911af63c, +0x4758828f, +0x8449f80f, +0x4c421119, +0x14647f5f, +0x779e2b9d, +0xe4ab1a44, +0x439fa920, +0x4bd8b75b, +0xf94c0001, +0xef2d4d79, +0x786942c2, +0x5e4aee3a, +0x81ce2390, +0xbfc706ba, +0x721c3386, +0xe404ed97, +0x574daa9d, +0x32470dd8, +0x3de30cef, +0xf334b67b, +0x06c3b886, +0xbcc51791, +0x343a49d2, +0x4c2805f7, +0x4bcd1e08, +0xb5ba4c59, +0xa38ad1f1, +0xb265705f, +0x164cf5c9, +0x5597e64c, +0xdbc173d6, +0x34cdc9ba, +0xbceb9e14, +0xc8fa1932, +0x89888990, +0xd8668a04, +0x3838d309, +0x74b87ec7, +0xabf16a63, +0xf2f31139, +0xf6e381b0, +0x1dcfb650, +0x312c061b, +0x63189215, +0x113d4d64, +0x949c8dca, +0x92d49315, +0x9329863d, +0x00dd9240, +0x6a932887, +0x311f620c, +0x76e0c797, +0x982d6768, +0x86c7a327, +0xc6e436c5, +0x0fa88a62, +0xb142307e, +0x313998ba, +0x6f973392, +0xeefee1d3, +0xecda4d45, +0x45beba7c, +0x80566f62, +0x2524d686, +0x3e294737, +0x1c54be7b, +0x12aba319, +0x055a50f2, +0x16df2b2c, +0x3f0197f1, +0x17c9d836, +0x5aa26984, +0x85354a95, +0xc1067d56, +0x59041931, +0x6967cfa9, +0xecd856ee, +0x795da2b2, +0xbe22954e, +0x46b3535c, +0x58f89824, +0xb6563ab5, +0xb5d81dbf, +0x34e0ca07, +0xcf31b877, +0xd225d056, +0x5d1f9423, +0x3046c941, +0x97f9c884, +0x803f7a49, +0xda51486f, +0x221e1ee1, +0xda39cba9, +0x06345732, +0xfe24ddd2, +0x232c7b09, +0x4bf1fc10, +0x3c8b1076, +0xc59a1e79, +0xeee28815, +0xfb516ed7, +0xd9c583ed, +0xa3d02109, +0x4122ede6, +0x0221b118, +0xf161c9ce, +0x98eb8c01, +0x00f25590, +0xb239c1b8, +0xa28e6a0c, +0x983e1180, +0xac518016, +0xb2275327, +0x862b2a0c, +0xebbcda8f, +0xfb3963b9, +0x7a2403ac, +0x696f018d, +0x255c9052, +0xf66330d4, +0xcb9a8503, +0x1928b8b0, +0xc4392666, +0x875bf29d, +0x93845c90, +0xd3ce822f, +0xafa84cdc, +0x34fee83b, +0x2e3704ca, +0x11d3dc2b, +0xe7b1c421, +0xcf6a02a2, +0xb9c16c95, +0xa8e012cb, +0xc1df0e21, +0x60fe0340, +0x91d01576, +0x99dbd24a, +0xc3da782b, +0x4b8ba245, +0x8ec7a2fa, +0x1b85f893, +0x76f719e8, +0xa5a81b30, +0xf411c6e8, +0xa0867ab5, +0xd084ba22, +0x91ca34e5, +0x809a3d35, +0x47b55eba, +0x0d447b76, +0x0105aaa0, +0x511ce927, +0xdb3e8fce, +0xdf281fec, +0x45c3511d, +0x14e70135, +0x3aac5c53, +0xde304341, +0x984e8b79, +0xfb51a149, +0x082abb5d, +0xd7c11288, +0x4706bd6d, +0x6de99f22, +0xcf0e88f8, +0x4869b59f, +0xfb1228a4, +0xeaeabbb3, +0x941c307e, +0x0858cb3f, +0xb0b8aab7, +0x2997fc2c, +0x08dc2ac6, +0xdaee8a9f, +0x009a2879, +0xe09227ee, +0xe760fa27, +0x808c753b, +0xed645a2a, +0xe7b35294, +0x875da6d5, +0x91a7d0f5, +0xa7e27bf9, +0x13d79171, +0xddc7ea8d, +0x871119f8, +0x05782f05, +0x1367dbda, +0x61abcf83, +0x6bf9962b, +0x0855c17a, +0x98d6b65c, +0x8b3e3bc1, +0xcd9f07c0, +0x5a8aacdd, +0x56de51e4, +0x633f7171, +0x618406bc, +0x26ad3679, +0xb78dd7b9, +0x9d6e1a11, +0x90860397, +0x2f778605, +0xa3ae2bbf, +0x77ab097a, +0x259e74e9, +0x49d0697c, +0x34ebe8b4, +0x8af23270, +0xe0cb58a5, +0xf42813a0, +0x2ab40d08, +0x45c38f5b, +0xe40768fc, +0xa00a7e81, +0xcb1622cb, +0x76932bbb, +0x380bbd03, +0x4e888e14, +0x57748f95, +0xebb3a9a2, +0x15268ab0, +0x5f0ca109, +0x197ed3fb, +0xa396cbc7, +0xdd4544d3, +0x72bcad87, +0x9bacf1c5, +0xc29a2586, +0xafff138a, +0x06ae187e, +0xfa09b8a1, +0xce61d82c, +0xe1cf706d, +0xb4b386c8, +0xd1e7a92f, +0xd8cf6f74, +0x8e04c16c, +0xbebc903a, +0x6daa28e1, +0x80609217, +0x566f0132, +0x0ced94da, +0xc578937e, +0xe9aa4250, +0x2b91dca3, +0x97e92316, +0xcd4cb9c4, +0x47e27a30, +0x7c7b2403, +0x08016d6c, +0x0bbe10d4, +0x1ed123b6, +0x06c96396, +0xf8a5bf6b, +0xad1072c2, +0xba941cc4, +0xe037e205, +0x83f168a6, +0xec6560ec, +0xfa40ca26, +0xd65cfc94, +0x1bdc826a, +0x6bd9c11d, +0xff5b007c, +0x266536f8, +0xfdcec273, +0x43f228e5, +0x90b4df14, +0x8a0af815, +0x5b094b39, +0x81557772, +0xa299eab7, +0x36c9f544, +0x20ac0b41, +0x98b35d1f, +0xa9257811, +0x8b139c37, +0xabe02e60, +0x09013c2d, +0x928f431f, +0xdfed27df, +0xf39322b0, +0x7afa38fb, +0x6be0a4a7, +0xd1e29fdd, +0x7d0ae420, +0x03a07c22, +0xcd4fb717, +0xba8dea2c, +0xe5eb6967, +0x4c6749c9, +0x1291af8e, +0xab638bff, +0x30bc3540, +0x4d87aac0, +0x8b05c47a, +0x5eefd021, +0x54f12af6, +0xc2b4058b, +0xf34cc743, +0x32c52d84, +0x5f3e8a3c, +0xbd01d895, +0x103da8b5, +0xa7a8c1ad, +0xda260c67, +0x7e50f04b, +0xfb8b5e03, +0xcce6b146, +0xd3c2c47f, +0x87a122ed, +0x2b993551, +0xfd71137d, +0x8a6053c9, +0x4856a2ea, +0x09c81bc3, +0x0bbc0386, +0x916dadc8, +0x5644c85f, +0x25e0b999, +0x8f9429e8, +0xee3ebc5c, +0xb7598fae, +0xd37bc93e, +0x45e2bc3a, +0x81d68b22, +0xa9adb1b2, +0x11e4d6ea, +0x54e2d2ab, +0xdcdb457e, +0x7eec508a, +0xf08f2924, +0x1d0f9df0, +0x51454db7, +0x877b20ac, +0x2b765a9f, +0x7ce268d6, +0xbc4ee5e7, +0xcf568649, +0xffb05d1e, +0x558af352, +0xca04227d, +0x2dee1df3, +0x78e75939, +0x84cda769, +0x235e7fc3, +0x034cbdc1, +0x4e9ce87e, +0x55bbfcba, +0x32e99c12, +0x8ddc91af, +0xabb90ee0, +0x0991018b, +0xcda3b110, +0x5c817e68, +0x5023abfd, +0x9c812b0a, +0x9b57eb07, +0xa18782db, +0xa0f91c06, +0x9bde0572, +0x3bb6fd14, +0x97e5111e, +0xd5c883fa, +0x8628514a, +0x001e90fc, +0xf3ba4bb8, +0x8e4e01c4, +0xce5afd59, +0x36b26bcb, +0xb7407dc9, +0xd5f49f87, +0x8a0cff32, +0x56505350, +0xb303dcca, +0xc971e593, +0xa4a51ee1, +0xd25f811b, +0x77f138e1, +0x35825a3c, +0x21568e0d, +0xcc6226a0, +0x1874d2c9, +0x164076a4, +0x5fd825a7, +0xcbc3bd4a, +0x4c7eb6b3, +0x67293518, +0x57c68c88, +0x8d3d80b5, +0xfaaf0fa1, +0x6e19db43, +0x0ff03a9e, +0xc90f8c44, +0xea5e4a53, +0xf57612df, +0x64153938, +0xea843b3a, +0xa32e589e, +0x86563c63, +0x0f2d8e96, +0xa9cf8cf5, +0x0c2f9151, +0xc0937d75, +0x5023556a, +0x254369bc, +0x19c8e66a, +0xd6dc36af, +0x508db6bc, +0xa56322f9, +0x3dd77c1e, +0x01137d6b, +0xcf1a44ac, +0x0e031252, +0xd2cd440b, +0x0fc5ef56, +0x59753f8b, +0xbaf85623, +0x85eb6dc3, +0xe5aee9d0, +0x4e0cc6a6, +0x1e68bdb0, +0x6708eec2, +0xc1f18bf9, +0x403cc612, +0x982e78e5, +0xd41a90b9, +0x3f73bacc, +0xf14c5c04, +0x421e5bcb, +0x670feaaa, +0x3f730685, +0x725bc072, +0xb756a547, +0xb4c4e653, +0xa77d83cf, +0x7a76b097, +0x30fc210d, +0x228d2cac, +0x41ee4179, +0x333422dc, +0x058604ee, +0x01138532, +0xbf028a4a, +0x0e9b8bb7, +0x9e4fefbc, +0x389ea6f8, +0x7bbb969d, +0x1a0ea648, +0x94a1378c, +0xf63df085, +0xce5865f9, +0xcde59d20, +0x31394f39, +0x342eeaf4, +0x6922775a, +0x3305a9d0, +0x0d5eda70, +0xc146f9e6, +0x5c5b8eb6, +0xa8ec5a3a, +0xf7271c8b, +0x1da14ba3, +0x12429600, +0x51f9021e, +0x6a64c06b, +0xb7be5176, +0x5c1ea01e, +0xc527a763, +0xd319b4e9, +0x2fdfb539, +0x304f0ab5, +0xab03e3a6, +0x7bdb9eb3, +0x64654823, +0x903577d3, +0xb78d0207, +0x98091543, +0x86a0d06a, +0xb908c1d3, +0x4200d06e, +0xae1d81d3, +0xf84b17a7, +0xfd873b86, +0xd573f9c7, +0x3cbbd2aa, +0xdca2b53c, +0xe4863a75, +0xd671623b, +0x80b5ed85, +0x02df2232, +0x55cb02a4, +0x52d44db3, +0x39bb74e9, +0x9b5f07af, +0x9b59fc4e, +0xe03360b5, +0xbe5a727c, +0x62985b5f, +0xf4054d9b, +0x0ef889dd, +0xeca27a0d, +0xd75e9a4a, +0x8475121e, +0x42969e5b, +0x92fc387b, +0xac5b3eea, +0xbeaecf23, +0xe41c3415, +0x1166550a, +0x91897285, +0x515d78eb, +0xb999b01b, +0x3270e601, +0x9925929f, +0x297a659d, +0x9a7542d8, +0x2fe3c326, +0x90434988, +0x49c09eb3, +0x8d959433, +0x851d5190, +0xb355ae5f, +0xc905b570, +0xdef48766, +0x3e1aef0f, +0xdd2d97b0, +0xda4d88c4, +0xaf4e3984, +0x03d1379a, +0x19d40f8d, +0x9c104c2f, +0x6969fe11, +0x37e274a3, +0xf971a5c5, +0x26ad6b15, +0x9f7f3ed0, +0xb8801c58, +0xc90b8ce5, +0x0e06de8f, +0xb38a51d5, +0x7507741e, +0xa5ca22ff, +0x92a4c7bd, +0xfacf82bf, +0xc8237ea8, +0x274b5ee3, +0xa00a735f, +0xe4b0a18d, +0x1654f1a8, +0x49d72f81, +0x427514c4, +0xd527afbc, +0x2b828199, +0xf2bce884, +0xa3ac6544, +0xef2feee1, +0x8a35a000, +0x76f75d2e, +0x8e9f3c56, +0x836c90dd, +0xe2171aaa, +0xd741bd23, +0xba1dfe6b, +0xe929a3f4, +0x93193cfc, +0xa1780246, +0xe08ebc81, +0xf201a38e, +0xeaa33380, +0xa0ad7bcb, +0xc55f1dbf, +0x3cad3d37, +0x343ef6c2, +0x2aba3d58, +0x8aee352a, +0x4d000028, +0x40aba8d7, +0x9e526b1e, +0xea0ca587, +0x43b5310d, +0x06a180b1, +0x4c7ef4d1, +0x1509e884, +0xbfe7434c, +0xd355a073, +0xc46dfca3, +0x87ae84ec, +0x547254e5, +0x07e76bcb, +0x0ab64ecc, +0x9d1b38d8, +0x2c0d037a, +0x2157e51b, +0x4ff2d37b, +0x82749dce, +0x5ed4035e, +0x10ba9087, +0xfcaf1e32, +0x904c84e0, +0x8f7fa1a4, +0x7c521be0, +0x14638166, +0xe190363e, +0x4406c3b1, +0x70cf4c95, +0xfd6f6d5f, +0xef3a82c6, +0x2b8ad973, +0xa18b8f83, +0x98df1272, +0xddfc2663, +0xccb3d374, +0x50200417, +0x24e5e9cd, +0x8e5bdb29, +0xf0e7d30c, +0x044e2365, +0x5aa3752c, +0x962903fa, +0x08096d80, +0x6ccc5019, +0x980d9276, +0xab06a0aa, +0x2c184dea, +0xd030d051, +0xfa2c286c, +0xc5ee6752, +0x0d01c775, +0x08dc0b9d, +0xe0e80e92, +0x07c3ae5a, +0x0afd83f3, +0xc75a5e13, +0x43aa4abf, +0x4fc573e3, +0xd5fef3f9, +0xc925bed0, +0x3dcd545a, +0x9c38a04a, +0xe76596c2, +0x58417a77, +0x5d41575b, +0xfe22a4e6, +0xf01166db, +0xfdec546f, +0xf68dc228, +0x8d98f2d6, +0xb9df8917, +0xcb77df27, +0xd96ea21f, +0x9ad30fae, +0xc14b4cf9, +0xd042d065, +0x7ef8a588, +0xe1290b57, +0xb63013dc, +0x2d8e3706, +0xc7b8b020, +0x269531ff, +0xf542b017, +0x3bffadbb, +0xf10befb8, +0x83d64aa6, +0xf249db6b, +0x5cb20a76, +0x77b917b4, +0x75b1928d, +0x54f9656b, +0x378d0b22, +0x1fddbaa6, +0x4fdfe289, +0x25d3a70a, +0x742aa440, +0x23d4dac0, +0x09f87b6e, +0x6cae4aac, +0x69cbddd9, +0xdae5c53c, +0xb3334174, +0xb9b286ec, +0xd00a2f16, +0xf85b0415, +0x6d940d46, +0x8dc206a5, +0x7934abfb, +0xff924615, +0x0ab97330, +0x534f3892, +0x5ccc3fb3, +0x8319bc0a, +0xe6aa2d53, +0x0c969180, +0xa8cef536, +0x1d47940c, +0x8f6d6b81, +0xea993c5d, +0x7b62cb80, +0xd3d8afa4, +0x41f69f3a, +0x0105c930, +0x1076a1ae, +0xfc1c513b, +0x934b3023, +0x6038edb9, +0x51547854, +0x70df12db, +0x5f80064e, +0xa3b849a8, +0x816f2ae4, +0x2fbfc976, +0xf9778cfa, +0x0dfcfd6b, +0x5cad2b8a, +0x6dba494e, +0xbcb2d6cb, +0x7411183b, +0x089609b4, +0x1108420d, +0xfb2fff13, +0xffe09b7d, +0x0448553f, +0x66b94fc8, +0xe57662aa, +0x5ae14576, +0x1ac17a3e, +0xda0af6a0, +0xcaad8b23, +0x2c2d5e25, +0xb5b838f2, +0x1c9f7373, +0x16aa1d98, +0x4974fec4, +0xa8f57a26, +0x45cbb8c6, +0x0a384ba3, +0x73c7a5a6, +0x8b7701e3, +0x04e94edc, +0xb23baf28, +0xd72ba468, +0xbd567619, +0x794dd424, +0x715f9d1d, +0x1d5aa5ca, +0xe6d1b5c2, +0xc4454ff9, +0x77a51c7c, +0x4563a2cc, +0x2de4a847, +0x759fbe2d, +0x26582948, +0x7e1f7c85, +0x2c02f945, +0x0cb38f9d, +0x730cc1b9, +0x4381e953, +0xac61b20c, +0xbaecb4ec, +0x2d60afae, +0x9ec1ddc8, +0x1e22d6ca, +0x6db5cdda, +0x389d72d0, +0x2f9f0126, +0x3e628849, +0x09b00e4d, +0x37ce1b77, +0xa45e7e32, +0xf32ece6b, +0xf1295641, +0x4b7f3e8c, +0xb0f32abe, +0x147fe08e, +0xd21d5fe9, +0x5dad1765, +0x68944f69, +0x4ca7b0fd, +0xdec6ed99, +0xce0fd6e5, +0x5a76053e, +0xff52d641, +0x7ba14a03, +0x12e9ac8e, +0x5da27afb, +0x9a178be3, +0x6383c4db, +0xc4997272, +0x14bd9ff5, +0x9a54d4fd, +0x62152ae1, +0xad16f69c, +0x70fca056, +0xdffe7858, +0x17ed0670, +0x94a7b667, +0x25086946, +0xaf8cdf34, +0xf0e2e989, +0x10c4fa9b, +0xcc6be9b9, +0xa7d41319, +0x5153504a, +0x5e60c244, +0x5e2bba45, +0x4f6837a4, +0x0514781c, +0xfb10bec6, +0x58fe9b40, +0x3f01b063, +0x99e20ba9, +0x7a9f08b4, +0x9153ef3f, +0x1c87637a, +0xc768ca0f, +0x6a005b91, +0xd81ec648, +0xa562b4f8, +0xf181de29, +0xed1e009d, +0x5caa39c8, +0x3f081868, +0xb1a7bfe9, +0xd911beb1, +0x6009bd89, +0xb6a6c69b, +0xc2b5b817, +0x57c51571, +0x50c2e0d9, +0x87a3244d, +0x5174f395, +0xe3928633, +0x6b5c7f64, +0x9499e8c4, +0xc42d555f, +0x119a0789, +0xdfbf0c46, +0x472f65d2, +0x68ff57dd, +0xe4ffd20d, +0xaa25a50b, +0x25e2e231, +0x37a2fbc1, +0xc14724ba, +0xee54f5b9, +0x617038d9, +0xa5513954, +0x679608b6, +0xb5011dcb, +0x11da66ec, +0xf9c03956, +0xf40e3d37, +0x5d1b5853, +0x2aa74bc2, +0xd6cd2c0e, +0x6f9e7f5e, +0x071520e0, +0xb859ee8a, +0x685ac308, +0x802cae93, +0x59a7321a, +0x733485eb, +0x72ba637e, +0xb47d7c18, +0x128b696f, +0xd2cebfec, +0xc7158d0d, +0xb4064407, +0xe536dd9d, +0xe9829009, +0x97dfaae4, +0x8c3d7201, +0x99610659, +0xd4718253, +0x9625f17a, +0x43fab7f2, +0x2621ca0e, +0x254319f6, +0x5a02e2b3, +0xddc9f52f, +0x2fe2779a, +0x4f6e0852, +0x4dbde8b7, +0x532cc790, +0x8c92d82b, +0x5d85a58c, +0x1589899f, +0xe9433e17, +0x123dbe9b, +0xeff94e38, +0xb7192345, +0xd10c04bc, +0x0a653c70, +0x27da65cb, +0x724c0366, +0x8660d570, +0x6f752fb1, +0x7a2f4925, +0x7433591c, +0x8698573a, +0x98d882f0, +0x7a03dcf8, +0x9bda5ed4, +0xa2a2a2b1, +0xe43ef0c5, +0x3b1dd256, +0x1761b2b2, +0x6e1e56dc, +0x5dd19888, +0xa2dae55d, +0xc575ee0b, +0x78453bac, +0x7b5da7f3, +0x47830f4e, +0xfd24ebe0, +0x709146a9, +0x5c0cce35, +0x529b2174, +0xf7c8d08b, +0xdd84cdb5, +0xe1c3ba98, +0x4b92ba9a, +0x9eeee319, +0x14f53b0d, +0x28d32f2b, +0x4b08c647, +0x6698fed7, +0xcdb26787, +0xb314b3ab, +0x376efcde, +0x345b5531, +0xb0ea7f68, +0x18ef8315, +0x3320c970, +0x6c75bfe6, +0x0ff165f7, +0x327eb8b7, +0xbe05f679, +0x79e8424c, +0x4dfa8aff, +0x1a29ad36, +0x6db0ff7c, +0x36d6c97e, +0xec2ddfdc, +0x2e43a8d3, +0x8375b77e, +0xbd3dd5ee, +0xd4b978a1, +0xcb0c6885, +0x28b7cb15, +0xb15cd265, +0xc61c5f1e, +0xd3add732, +0x41892c0d, +0x9a9d04b7, +0xb3e4cd6a, +0xfb7ab190, +0x51611b48, +0xe181f9a6, +0xac6b46cd, +0x81a68dd2, +0xade51f0e, +0xafea158c, +0xc66cca82, +0x843a4fd9, +0xcbcfba0a, +0xa06f84d8, +0x09ac26b0, +0x347494fc, +0x23a78093, +0x0a00ab9c, +0xfc305057, +0x194e6310, +0x62ced9c0, +0x03833b0b, +0x8afd5943, +0xbbc1dcf5, +0x0073973e, +0xdbac1e68, +0xb71ec7b6, +0xd91e0971, +0xcc7d4e64, +0x03da7794, +0x13c9636c, +0x032609e0, +0xbcd89537, +0x1eeba1e0, +0x750bb7d2, +0xb7338ac8, +0x947f7f6a, +0x95a8b1b3, +0xcdfd324a, +0x10e658da, +0x172e3dff, +0x93b2d8a7, +0x236a650e, +0x1f1b67ae, +0x224505bb, +0x3a73417e, +0xd74df883, +0x2a6e33a5, +0x9fb954f8, +0xd6ad9566, +0x2ddfa1c9, +0xab12586d, +0x9c6da60b, +0xc3ddbaba, +0x6d41b748, +0xaba9bf16, +0x7c224cc8, +0x4e39e5c0, +0x4aebe559, +0xc26fd2ee, +0x1f811a6e, +0xb73be5f7, +0x004010d3, +0xfceec8de, +0xbfb7f67f, +0x457967d2, +0x59a3b253, +0xec18b1dd, +0xcde0e0cf, +0x6d7bcddc, +0x5d1bd7b3, +0x8b51f8ce, +0x94e19b51, +0x83818da5, +0xa8fe8c7f, +0xf118acc8, +0x90d31135, +0x74576c4c, +0x86c9c5e9, +0xc72a8cdd, +0x59a2d7e6, +0x6806b96e, +0x50265477, +0x0a3d34ba, +0x41854d99, +0x8cf43e3d, +0x2711aed6, +0xe881c39b, +0x41a8830a, +0x6b846bc5, +0x9d5ab0d2, +0xf2149be7, +0x360a1df5, +0x26117995, +0x02b4aa7b, +0xe1950d6b, +0xdb5d271a, +0x9f3bf539, +0x88ffe82c, +0xc4ea1ac0, +0x5f5e53ec, +0xaad42738, +0x8c262ef6, +0xaf9b066a, +0xf0872d1c, +0x178cf011, +0xa18dabdf, +0x4acb6249, +0xaef7af0f, +0x86e1730a, +0x529de70c, +0x94d55aa3, +0xed4ca43c, +0x96d935ad, +0xd1e6904e, +0xc70aaf68, +0x65a666a8, +0xfe2054ba, +0xc8360f44, +0xd15ca0f3, +0xd225d942, +0x164d5a35, +0x9061be3c, +0xd93a0aeb, +0xbe3d28b0, +0xcf876a6e, +0x24ee344f, +0x663df9fd, +0x497cd718, +0x73c5d0ce, +0xaf6a540e, +0x1e517b55, +0xb64c3c08, +0x79ef0d4a, +0xa103f384, +0x6d89d6d8, +0xba9d484f, +0xe7a077bb, +0x374b7b13, +0xf6c34e4d, +0x6797d667, +0x595a49ca, +0x7e4ad667, +0x04c50855, +0x618c7a60, +0x32448985, +0xf6599a67, +0xcdbb0b5e, +0x69ab2030, +0x3cd5825f, +0xa94cdc5e, +0x4d2de10d, +0x8d941061, +0x6525b319, +0x398a6f78, +0xdaa5ee1d, +0xa8c5763c, +0xc6d0eccd, +0x42daa2d4, +0x46195a19, +0xadeb3676, +0x380335c8, +0x25aa588e, +0x7a0b88c1, +0xcb0034cc, +0x0b39d916, +0x4a86bb4e, +0x7466c566, +0xc1216dbe, +0xe0b939a5, +0xc0b27f60, +0x11fac0e9, +0x9d1648fc, +0x6d8ebe7f, +0x3646602a, +0xd75ff20a, +0x8eb4ac6b, +0x06bcb6a1, +0x7c0514fa, +0x76cccdc7, +0x3ecbfc25, +0x1d477a2c, +0x847c167a, +0x55f195a0, +0xe62708e7, +0x36b15203, +0x834b3209, +0xff0232ad, +0xe72e9662, +0x3dfd0370, +0x45f96511, +0x06caef0c, +0x1916d679, +0x48547dce, +0xdd2ac4aa, +0x056b9f0b, +0x025ece56, +0x2bacceb0, +0x16be23e1, +0x5a22b391, +0x69c870b2, +0x6e9612e0, +0x3f6d79ff, +0x2c8842f3, +0x08fe63ed, +0xeef07eac, +0x86fb2b9e, +0xf28000a3, +0x423bf4c2, +0x6dac5f60, +0xa3438d58, +0x221c5f0f, +0x82746b39, +0xe4d02d8a, +0xe1c52284, +0xfc5786b0, +0x16d31e93, +0x91d130cc, +0x05e3c67f, +0xd3851827, +0xfe1282c8, +0x7c3d8e8e, +0x102b79c1, +0x3d30a541, +0xb0f390b6, +0xb6e39ec3, +0x0bdece96, +0xc62e38c1, +0xc77f2649, +0xdf382702, +0x671f70d1, +0x02aad865, +0x1fb88588, +0xab6e9a72, +0x994a53a9, +0x33091d86, +0x00967d27, +0xab055a9a, +0xd10bebb9, +0xe06067ad, +0x2eefc272, +0x507b4f63, +0xa6776dc2, +0xd354b1e9, +0xf5333bde, +0xdc643d21, +0x5837246c, +0xf789b20b, +0x36817b21, +0xdd9500dc, +0xc7ee8e18, +0x318cceb6, +0xce7410f9, +0x80c25e64, +0xfb250ab8, +0x990d6ea8, +0x6a6d28e6, +0xf2b6d65d, +0x86d64352, +0x4a63f9b3, +0xaafdd365, +0xa48a865e, +0x24d13930, +0xa38880bb, +0x960f8796, +0xd37412c6, +0xd317c335, +0x648bc505, +0x2f447276, +0x1b2ac702, +0x318d25ac, +0x8f28a886, +0xb4121e07, +0xeb8b039d, +0x2bbbfbf6, +0xf3b5d76e, +0xdcfcf9c4, +0xeb49eff5, +0xaebe5efc, +0xffc4e443, +0xd383cc5a, +0xedff96fc, +0xc81c6590, +0x03112218, +0xd8f1a3e6, +0x2aa347df, +0xbb357bb2, +0x32ae2a23, +0x2be30bd0, +0x0fab4908, +0x28ca5809, +0x97cab691, +0x43b384f9, +0x5d53faaf, +0xe7773e12, +0xea09e2f7, +0x7e4d1759, +0x175eee68, +0x955f79a8, +0x9a19a259, +0xa01e0918, +0xd506b767, +0xb9edd62b, +0x5f96cc35, +0x23a9f9e0, +0x6c7a5f49, +0x1d11adac, +0x69abc8a0, +0xbb7a0e30, +0x01b98373, +0x4594385f, +0x2dceab59, +0xf0690368, +0x95c44885, +0x14c52e57, +0x9412d71d, +0x6b2eb5af, +0x7e17c99e, +0x443facdb, +0x47a5121a, +0x781825d6, +0xa7773fcf, +0x2bc971a5, +0xad314dbd, +0xda1f792a, +0x1cbe7bb5, +0x78c73ddf, +0xfb1084e6, +0x1520f3bf, +0xcbe64972, +0x6af27ff5, +0x78fa499c, +0x56e78809, +0xf157f62d, +0xd79cd556, +0xb3630d74, +0x0fe193f1, +0x3a525f15, +0xb8360770, +0xb9fc79eb, +0xc119c465, +0x9c4e6cea, +0x796ed2e0, +0x7ea5bf3a, +0xbbc96092, +0x7fab2abb, +0x51db14bb, +0x396fb289, +0x9bb1fe7f, +0xb78bc587, +0xa11e824a, +0x0e7ec7d0, +0x935ea888, +0xcd31816e, +0xe6ffad19, +0x25f4eefa, +0xcd85de99, +0xc4df9cf2, +0x325f2ba4, +0x30e92f74, +0x3228afaf, +0x1db42f19, +0x863d460c, +0x49f01598, +0x394dc72e, +0xf34c8102, +0x9bf324a7, +0x20bae348, +0x8ba1ef96, +0x7f83c9e1, +0xc872d3a2, +0xa2bf5a6b, +0x3ace9565, +0x93c1cfeb, +0x68da7bd0, +0xf66ffcc3, +0x7c615af3, +0x9d4a45f6, +0x7a767a88, +0x831963c6, +0x7da2017f, +0xb26a7c81, +0x763f4ca3, +0x3178f4d8, +0xfa65e5c2, +0xecfcd393, +0xfbe6c388, +0xa343179d, +0xd58f3c83, +0x7e2da10f, +0x53636d18, +0xed27af74, +0x6c576292, +0x374c90b4, +0x3bf07fe9, +0xa6519017, +0xe7e36ae7, +0x23cc0c0c, +0x86f11bb5, +0xe6faec68, +0x066d82d7, +0x0f74f757, +0xf4b15293, +0x80c69421, +0x77efed20, +0xbd25faf8, +0xd20be300, +0x03d66481, +0x99026974, +0x348674b6, +0xe745097e, +0x4cc1948f, +0x3901b58a, +0xba4cbe7b, +0xc7841132, +0x60eaeef6, +0xa21aee74, +0x471f2713, +0x4eedc729, +0xeb940a32, +0x9edb4cd7, +0x6ab917d6, +0x883a3380, +0x0cdaf1b1, +0x17c327b2, +0xed59beb2, +0x2817a78a, +0xad0fb637, +0x8af25604, +0x8377e0c9, +0x8153fcc6, +0x4dd06f5b, +0xc53460f8, +0x4613d1f8, +0x881ecb2b, +0x61635800, +0x3161f625, +0x2a514279, +0x3a979459, +0x80816f2e, +0xa43a2b79, +0xbe0b57d3, +0x88c380b9, +0xd6c1ba6b, +0xbb58c9c2, +0x0015479a, +0xa2d74dbb, +0xf6a12a17, +0x7f026911, +0x1b7b2c6e, +0x872776a2, +0xd229a1d7, +0xa8a18ad4, +0x92d4cae4, +0xed92ce50, +0x89c6940d, +0x532b136e, +0xd1d0a913, +0x768bc2b9, +0xa07c19a1, +0xd0114ab4, +0x3830fb81, +0xeefb1da4, +0xb82e25ff, +0x62dfe06c, +0x15171cd7, +0x3d0f7796, +0x36779b17, +0xec1bac6c, +0xa08ecfc7, +0x2a26390f, +0x11be1de5, +0x388c9834, +0xbb756fd5, +0x28a9ef0a, +0x82c55faf, +0x02106d73, +0xcfba07bc, +0xdfdae27f, +0x5189a7de, +0x1c0ed0b8, +0xb3cca2b2, +0x19054ab5, +0x49a89575, +0x9aeeb656, +0xc31b9b38, +0x954744f4, +0x8fc22bf6, +0xd8f39f19, +0xb7bd824d, +0xfafabb8e, +0x22e4d9b4, +0xdb0b426b, +0x661e1903, +0x36f24730, +0x14e23d23, +0x7d87c8cd, +0x9eb76c23, +0xe539b20f, +0x46ae2013, +0x76a59666, +0xbb2560c2, +0xc594b08b, +0xb050cc85, +0x467690fa, +0xa951958c, +0x1ffa21aa, +0x18c40d61, +0x39434b6c, +0x4b107901, +0x6256e70e, +0x70342211, +0xc552aa46, +0xda90d164, +0x9ca9210d, +0xaa32e33d, +0x211e3d00, +0x4e9b16c7, +0x186f92fa, +0xfd95c0a4, +0xea9bb1a9, +0x1d6288d3, +0x19d9277c, +0x8ee3a02f, +0x39457299, +0x6b8ea5d6, +0xebcc2af8, +0x3f1fb107, +0xf23e3e98, +0xa1c40be5, +0xc9459d51, +0xa48cf93c, +0x3571d2f9, +0x7c4dbf5a, +0xf77757c2, +0xaad01e4a, +0x970db9d9, +0x3ac71c1d, +0x78fad179, +0x4fb8bb3c, +0x70bba938, +0x83ede56f, +0x6161e971, +0x8d7c830d, +0x829bad0d, +0x0a21b8e6, +0x393d7463, +0x2c2076ab, +0xa74dd0e5, +0x94376e60, +0x1cd50531, +0x1aef6c72, +0x449868a7, +0x927ff54f, +0xbd5248f7, +0x32647753, +0xbaaa180c, +0xa2a45164, +0xdade9fd7, +0x6e4f3ee9, +0x42b79f19, +0x3fc2969a, +0x8d7b5000, +0x14fb647d, +0xb1c40e7e, +0x5488b76b, +0x74136e02, +0x351e40e2, +0x8306f650, +0xbdb35e09, +0xe561a0b2, +0xc0f53956, +0xd8d4590e, +0x410aa007, +0xc85562fb, +0x29bc516a, +0xf41ff6cb, +0x2368a2ec, +0x068684d3, +0xdfa5afff, +0x9b9c58df, +0xec1eb8db, +0x3a061b42, +0x8be5890a, +0x41900e66, +0xaa285397, +0xa068ea9c, +0xa193dcbe, +0x9f7ffb2e, +0x80aa5197, +0xe473d1c7, +0x801bccbc, +0xc435ef45, +0x582a76cb, +0x65283821, +0x8d4f1552, +0x4369a4b0, +0x6ffb58b6, +0x9d69709f, +0xc4989d21, +0x3c1ab5ff, +0xebad12db, +0xac330967, +0x3467f89f, +0x264f7e5c, +0x04be69ad, +0x4b3174d8, +0x3746242b, +0xc299d5b7, +0xc134a601, +0x7a9f5294, +0x4aecd319, +0x51154234, +0x0a5a7180, +0xadefbdb2, +0xfb3bf137, +0x55c839ad, +0x333ae081, +0xac7239b8, +0x96de5477, +0x3c562516, +0x819a43f7, +0xf0a93b64, +0x9017c9cf, +0xd90a96be, +0x956abd6b, +0xbe14d92d, +0xbff0b51d, +0x54bc4fbd, +0x7b582d3c, +0xd016ad18, +0xb9ea92e9, +0x404a1825, +0x96ad48c4, +0x01c30b60, +0xb71b764a, +0xc5e83022, +0x6bd6a3df, +0x99d752ed, +0xdba50160, +0x8ae6ae76, +0x974834b9, +0x7b43f985, +0x5930337a, +0x637da8a3, +0x498d3b46, +0xff545989, +0x636e4bbf, +0x36f5bd68, +0xab22e0e8, +0x5ba13795, +0x338b92bb, +0x8bfd201e, +0xd7cf5375, +0xe0f52c6b, +0x27811ca0, +0xa1420d9f, +0x6e594c9e, +0xc5f505a8, +0x08ffc79d, +0xed20c941, +0xb9428101, +0x064b4c52, +0x5eaadb2f, +0x1af0551f, +0x61f8af78, +0xf5e112f4, +0xb9e84b63, +0xcf725bb3, +0xa02a2e65, +0xc07babfa, +0x3f70eb00, +0x06d3f569, +0xc8284125, +0xa6619823, +0x729244b4, +0xd20ffaa6, +0x025af246, +0x2772f59c, +0xed130a74, +0x8d1ad807, +0x602f3466, +0x4c483502, +0xa984517c, +0xaf889784, +0x181f076c, +0xc2e7db4e, +0x21beddd1, +0x4f30741f, +0xf7569779, +0xec6d74bf, +0x8c6f878f, +0x28058e49, +0x3b6ae1fa, +0x016154a4, +0xd89b3eaf, +0x67893386, +0x4948c802, +0x72359f2d, +0xbd586e7c, +0xefade558, +0x66f5ebd7, +0x4d903956, +0xb7c7573a, +0x98bf67f0, +0xa9c6a6b5, +0x31652d15, +0xc71a8f90, +0x747cc66d, +0x0ca883d4, +0xb47a5b85, +0x7b3f7a41, +0x63655254, +0x61b86ffb, +0x85c20b37, +0xe2f8ac44, +0x2a23083e, +0xe611c93d, +0x542036b7, +0x3082a731, +0xdbc5fe01, +0xd7a03fe2, +0xfb351402, +0xaa21517b, +0x958a55b4, +0x868b20b2, +0xa9f4ff87, +0xaafde28e, +0x090917f7, +0x90fc5886, +0x89ffc27c, +0x135846c0, +0x5157ffff, +0xaddfe6e0, +0x420de05f, +0x4c4ff192, +0x501b2d8f, +0xeb0b326b, +0x57ab5ded, +0xdb1086e8, +0xab76fbe9, +0x170991f0, +0x3dbfe9f3, +0x1cc24909, +0xdb2e3aea, +0xff55a932, +0xfb9ea5c5, +0xb5d7ab5b, +0xd1f06c5f, +0x1f190a72, +0xbaa1792d, +0xe96c8d78, +0x575b58e6, +0x06d241bf, +0x8844c3bb, +0x4e3016b2, +0x32fd4d0e, +0x45f69dcd, +0x2d1ac976, +0xca23164a, +0xebf0d020, +0x01b45f50, +0xe387be3b, +0x10851359, +0xb0e532a0, +0xfdd14b4c, +0x06c09ba1, +0x6ff3fa57, +0x7bb3ae24, +0x392efe9d, +0x288291a3, +0x763fed12, +0x6878dc1a, +0x6f4bd552, +0x7eb83b3b, +0x38702104, +0x10a0cc2c, +0x327dfe3d, +0xab265a51, +0xa8ed1d06, +0x31ec5087, +0xdbae25da, +0x30006363, +0x6b3445fc, +0xc5a1ab21, +0x984990b4, +0x6b2e9d74, +0xd309190f, +0x62682a13, +0xceab4e75, +0x18065ca5, +0x7681d95c, +0xff3767b9, +0x7951b0d8, +0xa43d8e9c, +0xe3e2f297, +0xff2914b6, +0x9c93dcbb, +0xd961ec4a, +0x890eaf4f, +0xf4d16c4f, +0x82f4b510, +0x8c669bd9, +0x144fece7, +0xf6814ed7, +0xdef133cd, +0x9d4df9d0, +0x19f610c8, +0x7eccfbd8, +0xa70e28b6, +0x9129380d, +0x15b1c5db, +0xf0f0d86f, +0xe74153f5, +0x5313e291, +0x9bdcf917, +0xb775a537, +0x8850c86f, +0x96790a6d, +0x5e382798, +0x153d624f, +0xbf1211c9, +0xf39ba580, +0x6698bba9, +0x9d0b3816, +0xbcbfb5f8, +0xd4654d05, +0xae53ae6a, +0x409b5cb2, +0x8fbdcb5d, +0x9edbf86f, +0x2f8a1515, +0x0901c1cd, +0xed2de425, +0x68a3de2f, +0xcc3cbeb7, +0x65ca347b, +0x2927ad97, +0x18c232cd, +0x2a3bf2ed, +0x00346946, +0xca3d4eb8, +0xd571e640, +0xe77c0f5e, +0xe67a4ba9, +0xd1d535be, +0x0b210d76, +0x0956d69f, +0xa5da366e, +0x54266ae5, +0xf5411644, +0xfe133067, +0xf67f5fa6, +0xa90f5006, +0x9120820b, +0x1e85d6a1, +0xdf497a0b, +0x820f2b5c, +0xd19fe47e, +0x7a5ee8b4, +0x6f9c999d, +0xac580753, +0xbc7608d4, +0x78c48ee6, +0x7e39844a, +0x21df5f29, +0xea7dcffa, +0x9ce59f50, +0x8baec77b, +0xf758e8e7, +0x7e0a0568, +0x38058ec8, +0x9bcda57d, +0xff4af641, +0xe62cb5c4, +0x94a42d0f, +0x7808c674, +0x914e3f26, +0x9c7f08c6, +0x89b0fae3, +0x61f9152e, +0x36424903, +0xda042fa9, +0x0481c199, +0x06d71286, +0xa4aeac50, +0xc0bd99d4, +0xa6e2cb34, +0xc4e5cfc9, +0xc6ca7c48, +0xb7616475, +0x365449dd, +0x79d9d5ad, +0x24329b9a, +0x65e7095b, +0xaa3e336d, +0x06749e1f, +0x04a5963c, +0xe507cd8f, +0xd278050c, +0x7360cecd, +0x2c4abfa4, +0x0b612f7d, +0xb655108b, +0xdb3bb735, +0xc0fdb880, +0x34b3e5c5, +0xc2952b93, +0xc99b3aa7, +0xe7051d39, +0xe3344f7b, +0x31241fe5, +0x8c958ee5, +0xdde4cc87, +0x880130f3, +0xfd28d5b3, +0xb15d852b, +0x83d7cb4a, +0x7bf26fc0, +0x2d9e3c36, +0xab0304f3, +0x435c930b, +0xc5ebc70d, +0x08416b31, +0x89acdfeb, +0x12c9e83e, +0xaa05968c, +0x9e5a67d8, +0x3bac1b48, +0x5d32c0ab, +0x330309a8, +0x4b99deaa, +0x8f1ecd35, +0x80d1d798, +0x6707bf8f, +0x25bb560c, +0xb9145b28, +0x47e43b2e, +0x9dea75b6, +0x95fe6f30, +0x9fb167b7, +0x7aef02dd, +0xabf4b3d1, +0x98d09d41, +0x62031949, +0x1ed7a5d2, +0x3a9a8588, +0x17f98a61, +0x4709c106, +0x4f176243, +0x38231698, +0x45351109, +0xe1a1fe25, +0xa20ec597, +0xf82f221c, +0xa2bd42c1, +0x774e0012, +0xc33a0a5b, +0xd05da439, +0xdfd64aa2, +0x2f548ef4, +0x56ab9995, +0x2b7a856f, +0xd403cc27, +0x80ccd469, +0x44b4868c, +0x642f9dbd, +0x5ceab8c0, +0xa4066663, +0x6889d201, +0x13df6b3f, +0x483b67e1, +0x5af914cb, +0x136c2bc2, +0x916dbd9a, +0xb510adb8, +0xe2144042, +0xb657206b, +0xd528fb40, +0xa5de9ecf, +0xb72a58d5, +0xff8ddfd2, +0xf5d5192d, +0xabbd5164, +0xf17238ad, +0xda3417df, +0xc76d7271, +0x1eb6138c, +0xfb7bd846, +0xa3b8c4f0, +0x3e91b6e1, +0x4de3ea12, +0x3198bebf, +0xe57471e5, +0x1861ff72, +0x102c0ed3, +0xb303d5fd, +0x6e5e307b, +0x5d90e1e1, +0x3e880a5e, +0xc308cd29, +0x58785225, +0xa706f09a, +0x9954d5f4, +0xb2d05edb, +0x836a8223, +0xf0209294, +0xca8dff3d, +0x663e840e, +0x97a9d7f7, +0x197978c3, +0xb96a6943, +0x47649766, +0x9f3c9f85, +0x4678ed6c, +0xd359a4f7, +0x20d56684, +0xccf6f6ce, +0xa420d806, +0x0203bf82, +0x93d31115, +0x90e9f008, +0xcaa788eb, +0xda2a558c, +0xbe0ded55, +0xc987b6c8, +0x471b16d6, +0x3cec879b, +0xaf4fe676, +0x559afe9b, +0x27e3b79a, +0x5be24aef, +0x8b085772, +0x9e147677, +0x0de2cc8a, +0x23a132f8, +0x31ee16c5, +0x86c707ca, +0x1db85924, +0x0d0c0e14, +0x5db87d36, +0x4cabff3b, +0x6d947820, +0x0ff434c9, +0xc5c5760d, +0x2a88448d, +0xcdf0b1c6, +0xb3d86c54, +0x80ae749c, +0x49410a98, +0x1851caf8, +0x6350e1a0, +0x504c1297, +0x09a88652, +0xf3506173, +0xb85689a4, +0x5a799576, +0xbf0c2ce0, +0xf0d5538a, +0x28f214f7, +0x8643b5df, +0x20819c7d, +0x71cd2bb7, +0xbdb27657, +0x72dd4ed4, +0xc84545c2, +0x9a08eaee, +0x16326fce, +0x2d4342c2, +0xab008c9c, +0x00204ceb, +0xa993c9ef, +0xb7c3c076, +0x75218534, +0xb14eb69d, +0xf718cccf, +0xb81e5e67, +0xff55fc53, +0x970bbbad, +0xda2f1a45, +0x256f333d, +0x1ff0f5a8, +0x2eb661a5, +0x0337ef90, +0x57e1656e, +0x4a9b07ee, +0xacf54f2e, +0x9717abea, +0xb5bb714c, +0x1792f7a6, +0x81cdd7e8, +0x62a12406, +0x761f99f7, +0x072a3a97, +0xe22bd93e, +0xf100ec03, +0xc8e0a791, +0x361145f7, +0x36e15247, +0x2ee9386a, +0x1d439e0d, +0xea8b8df7, +0x674afbe1, +0xe33b5da1, +0x23690868, +0x9fd72a8c, +0xf7dd3c7a, +0xed75f0e8, +0xaf8c3031, +0x198afbff, +0x92010eba, +0x7748e906, +0xdd8844cc, +0x00affff6, +0x24d46ac1, +0x90df95f0, +0xdd0c2aa4, +0xce2104aa, +0xe23e4620, +0x142b9215, +0x769d8186, +0x6ec121a8, +0xdd309c46, +0x7fb0b89b, +0x8016afdc, +0xf3708954, +0xce3d39be, +0x52476650, +0x9e827030, +0x0ca77a29, +0x7df3a31e, +0x4fca9715, +0xc59ad4a2, +0xbb26442d, +0x3f8a3cce, +0x81e09ea3, +0x94919687, +0x958c6a31, +0x06508982, +0x32988dab, +0x3a276ce9, +0x0208f157, +0xcf8367d3, +0x163ba3bf, +0x17159607, +0xf265d581, +0xaad84b54, +0x63a9365d, +0x80af00dc, +0x257f8001, +0x772dfd0d, +0x367eecf1, +0xdaa6aa96, +0x0f6a5c10, +0xd5acf51d, +0x7872c2e5, +0x79708bf6, +0xc40f652b, +0xf62bc7ca, +0x22952a96, +0x5cffcdfa, +0xfab55a3f, +0xcf5256b9, +0x27de0e02, +0xdace9547, +0x92db78cf, +0xfa005e20, +0x3ec98153, +0x1647c3e5, +0xe386397a, +0x039b0510, +0xb02c2fee, +0x0428ecb9, +0x7e889fff, +0xc39d8bf9, +0xadfacddc, +0x64f2ca0b, +0xa82acc83, +0xbacf9264, +0x656e28d5, +0x53014b7b, +0x014a593c, +0x43ae7d08, +0x4e5e660f, +0x6b548f42, +0xbd1c298c, +0xfae46cb0, +0xb2983391, +0x5461c49e, +0xc4d0be21, +0xae949561, +0xe719d444, +0xb9e88874, +0xae19b604, +0xc8df3646, +0x1354ab60, +0xe47f58ab, +0x4f827aac, +0x83344c8c, +0xc0233ae0, +0x2118c6ec, +0x93e3f597, +0x1b5b0281, +0x0ddc480f, +0xfb7c17b6, +0x6fad8d4e, +0x1dae9191, +0x09d78e21, +0x53ca75ee, +0xb9c4f84d, +0x610154ce, +0x7f113f51, +0x33332eff, +0x2e8bf6ed, +0x9a960f02, +0xf4287ef4, +0x494b8b99, +0x8bd01fe5, +0xe0baa3b7, +0x39cd90ff, +0x12fd7ef8, +0xf41687dd, +0x62bff535, +0x7e8b1b36, +0x0bda14b7, +0x7d179fce, +0x9faf161d, +0x03b14666, +0xb356ecb0, +0x3f2b190d, +0x38846643, +0xb9a3442a, +0x4c56f86a, +0x05ad857a, +0x54789c95, +0x3ad47233, +0x392744bc, +0x0b7f7d75, +0x28a7ed56, +0x15a84f5a, +0x1b02dfc6, +0xbc8df094, +0x82690988, +0x7a390885, +0xa1bbe4a9, +0xdc71d353, +0x6d26f0e0, +0x86660dd5, +0x23248a1c, +0xb1517a0c, +0xd9d8d09f, +0x63fc6034, +0x65b2e78c, +0xf9633cf0, +0x97db9ebb, +0x7b9aaafd, +0x351328d8, +0x8c9d13b8, +0x78b7a2b0, +0xfd60f60b, +0xf98e9794, +0x159071ab, +0x85c5654c, +0x9fb0bf2d, +0xf870e501, +0x52474957, +0xe2f03cc7, +0x9f966cc9, +0x390a72a3, +0x5096b069, +0xd616565e, +0xcc98c4cf, +0x84998bed, +0xe76237ef, +0xa7be56ab, +0x8a050904, +0x2eedcd6d, +0x033a7054, +0x95a0eecd, +0xc952457a, +0x490e57ff, +0x0a93414f, +0x7ee5be6b, +0x31b637d6, +0xa4a09d0e, +0x00cd2ed0, +0x9a106b5e, +0xb56d3501, +0xf4fea131, +0xa05f6692, +0x50a4d745, +0x53aefb25, +0xefa92b0d, +0x81513e81, +0x2d1bb9cc, +0x664d4f1e, +0x9a4314a4, +0xeaca641d, +0xa91ad134, +0xadf4747a, +0x143b7cd3, +0x7dad81ce, +0xf5f9e604, +0x79853b12, +0x69789d1e, +0x30428e5e, +0xca324ec5, +0x0fcc78e5, +0xc53e6fca, +0x4d35b7b3, +0x3197723e, +0x6875a6d3, +0xd4e337b0, +0x306810cf, +0xeb665343, +0x7a87f334, +0x54b48e76, +0xbcca9639, +0x97015ef7, +0xf7489ffb, +0x51137556, +0x3a00e23a, +0x1601a20a, +0xa56142e9, +0xcf3f6686, +0xe011d298, +0x12040cce, +0xc35370a9, +0xf0334d1c, +0xf3ad5d2c, +0x0e8b90f9, +0xa3e960c4, +0x4594364c, +0xb2c67fab, +0xb9fde2ea, +0x14c177c0, +0xff37d1d1, +0x9caff287, +0x9ff37fec, +0x65ddd0e0, +0xa3af5640, +0xe58b14af, +0x20eb11f2, +0x92bbee51, +0xea08071f, +0xa7307967, +0x40c64879, +0xcd048a82, +0xc67bcb55, +0x796d61d0, +0x2f64447c, +0x363bfe30, +0x9471cc2d, +0xffc9abdc, +0xadd4ae51, +0x69f84501, +0xa00f2dd8, +0x41ba0692, +0x086ae228, +0x399c227a, +0xf5857bb9, +0x81c407e6, +0xfb89d225, +0xbe135bda, +0x4628c85e, +0x16075b1e, +0xbd4e9bff, +0x10d56cf4, +0x7b8324ad, +0x107bc662, +0x145a6ac4, +0xbb843ce2, +0xc3b2ee37, +0x32e46fdd, +0xebfbff21, +0xf7f879ef, +0xe9120cf8, +0x07a8692b, +0xdb3178f9, +0x252ab16e, +0xa1a18aae, +0x5ffd978c, +0x0c930ad0, +0xb9c5ab5c, +0xf313f14a, +0x0a263adf, +0x4a9e5ce5, +0x200cbf81, +0x51760e33, +0xdc46fc9b, +0xbc4074f8, +0x457c18fe, +0xa4b32e67, +0x6b1ddef7, +0xc7a43160, +0x7401a555, +0x121ff4af, +0xd570ca26, +0x96834b82, +0x22708c95, +0xe03ca738, +0x0dbe1c49, +0x3ddadd32, +0x7ccc33ff, +0xe6901061, +0xb1d60fdc, +0x0da12ead, +0x6b127930, +0xa8a1b7a6, +0x5874d1b0, +0x4dc510a8, +0x10ccdaca, +0xc6261fd7, +0x9a1f640d, +0x0830fb74, +0x88d32e04, +0xa423cb97, +0xab47c146, +0x9622a2aa, +0x645cb863, +0xdee11ddf, +0xa86e42bd, +0xf9abfe02, +0xe90a884e, +0xd8f7c9e3, +0x0e00e7ac, +0x974bd00b, +0x2ae3ae6f, +0xb3769668, +0x12af4a65, +0x8168fcb9, +0xd2347009, +0x6eb7cb98, +0x3d7ded18, +0xa992905b, +0xcc639b5b, +0x070f435c, +0xd7975257, +0x9a14b13d, +0x60a83c28, +0x3f75d649, +0x8e4c0293, +0x36fae022, +0x016f50c6, +0xd1a11a06, +0x37565aec, +0xf013fdf4, +0x573f3c06, +0x6143253c, +0xe476aa9d, +0x5fb1f168, +0xdb947737, +0x8ecb1d59, +0x078034ec, +0x34de29ba, +0xa6355e48, +0x26d200dd, +0x5ed91fa4, +0xfe209ec2, +0xf07f0e96, +0x0c85decd, +0xdc4826aa, +0xbcd6160e, +0x58fae767, +0x3abc4cb7, +0x3e53766c, +0x454f65e6, +0x8e6d022b, +0xcd19b787, +0x290f55af, +0x1fd62d64, +0x8acd2656, +0xca329872, +0xec09529a, +0x532ea97c, +0x83779692, +0x2330688b, +0x83e13072, +0x7da1462b, +0x629bed72, +0xd553318c, +0xa5274b10, +0x5251883a, +0xbca83ba4, +0x66f4380e, +0xc6bf0e55, +0xb4f7af61, +0x2e22487a, +0xf9b51c4b, +0x4edb1462, +0x254d1810, +0x6855fdff, +0xbf652c08, +0xb475e20d, +0x49d2b19d, +0x75869421, +0x342a175a, +0x4911a63b, +0xfecb43c8, +0xa173e5f6, +0x599ea60a, +0xad383364, +0x4b414fd1, +0xc73cd9f0, +0xc1bae2b2, +0xff3421ee, +0x0ef8dcd2, +0x516a1b2f, +0xb35d9270, +0x78fad230, +0x64753c9d, +0x4ee0c049, +0x3efae84f, +0x332a450f, +0x5df8fe97, +0x697565d6, +0x5ef8c9b1, +0xa6fbae64, +0x128ac0e1, +0xf95129a6, +0x1cf53bcd, +0x04435183, +0xb058ca3f, +0x1a3a086e, +0x9562c50f, +0x8c90e9ea, +0xa0df4f23, +0x5334155b, +0x16c62826, +0x680f3213, +0xecd3e8f7, +0xb3836f13, +0xfbb84b82, +0x3e45ca63, +0x39ce4c83, +0x39bc92e7, +0xa1a067a5, +0x9dc60770, +0x9b32e09f, +0x78a7cb2b, +0xcd1f68ef, +0x8cdd261d, +0xa88f0fac, +0xb3ce9949, +0x83471661, +0x33383459, +0x44246d99, +0xcc9c4fcc, +0x1f8d89ed, +0xbc75b0b6, +0xd15b7a15, +0x0516ab7f, +0xecf3553d, +0x64ab1dfb, +0x431ec543, +0x35d4ffdd, +0xbe1d1dce, +0x3cec9a68, +0xc9f5fe6b, +0x48f216ad, +0x21d5458c, +0xb4e89c33, +0xdf6fc2a1, +0x75a82ce8, +0x9772d2b8, +0x50f0ee84, +0xf89dd66c, +0x1af93b95, +0xc82bdb01, +0x4241204a, +0x38a0852a, +0x83a563e2, +0xcc579e3f, +0x64c3ff4a, +0x55a489db, +0x09f3e441, +0x47e6f47c, +0x0ebc9ed3, +0x65a93ed6, +0xbd282038, +0x3a84f7ca, +0xe9aea1cb, +0xba382a96, +0x0b7f4464, +0x82c2da22, +0x08cd24d7, +0x1f7c415b, +0x08592b5b, +0x1fd07e86, +0x866322ef, +0x0c13e720, +0xab129b1f, +0xad307bb0, +0x9dd275dd, +0x4736eb09, +0x56472906, +0xa06de3ef, +0x051f600d, +0x788bf911, +0xe84b13c8, +0xc69eb604, +0x2a7ef36d, +0x35930deb, +0x277db8f7, +0x324b23ff, +0xc99f7ddc, +0x022fb9e0, +0x376faa11, +0x880d3142, +0xe0364be6, +0x3d736920, +0xfe801b4c, +0xc79e26b6, +0xb15bc802, +0x7a203cc6, +0x2e41cee3, +0xaf4ecc90, +0xf00b3388, +0x472e4cba, +0xf5c5fa9e, +0x499282ea, +0xae3c37d4, +0x9c4dc51d, +0x4447b018, +0x96f3c04e, +0xdbf895ad, +0x78277314, +0xc8322681, +0x4799a312, +0xa1f59724, +0xcdbd0a94, +0xaf0e344b, +0xfce052bb, +0xdebb9269, +0x5b708031, +0xa6dd155f, +0x28a8e97e, +0x47a4d35d, +0xbca41db8, +0xd44e8c89, +0x8ea4cfd4, +0x2087643e, +0x5c5361a0, +0x19d5b038, +0xe1a44e71, +0xbaaa5865, +0x32985d2e, +0xb30cb132, +0x8346f712, +0x72122d8a, +0x9da8fe8b, +0x8ad3b0b9, +0xb86020c6, +0x96076c4d, +0xaf15e5dd, +0x4eb7694e, +0xcb66e0f9, +0xc0cc7811, +0x9f62498c, +0xf7628eb1, +0xb40f5782, +0xe3909967, +0x5268c0ea, +0x5ed85a84, +0xeddcfc66, +0x2aab8bcc, +0x67d9cc4c, +0xdad309a9, +0x4fb8f216, +0x87b670ff, +0x8046968e, +0x1005493e, +0x7aff15cc, +0x18a3b0ff, +0x275e0830, +0xe794620c, +0x84ff92f0, +0xefe38a1e, +0x5f13f4d9, +0x5b65eb4e, +0x0e3b130b, +0x28c7a40d, +0xd2e79e8a, +0xa979057b, +0x865238ac, +0x11c29a5c, +0x9c4a67b0, +0x3a4033e5, +0x5cd9ce4d, +0x446f5f03, +0x3eb976ec, +0x0db06dfb, +0x7d91aba4, +0xfe5a51ae, +0xaa1fc1aa, +0x84faba78, +0x74e7675a, +0xb8b6c3d2, +0x2bf10867, +0x372e7c86, +0xe41e6e82, +0xa4a14b4b, +0xccd7934d, +0x9dfd2ab8, +0xf85e71fa, +0x0b03de17, +0xab711a2e, +0x0c3667b5, +0xc1168ffd, +0x8f136051, +0x404a38d9, +0x4b1c5b34, +0xea938905, +0xd7e8ca3f, +0x76e7c24d, +0xd12d7b32, +0x83d3d1e7, +0xcbdf10fa, +0x56c9a35b, +0x487ddb54, +0x2625fb37, +0x58115a05, +0xd7ba9677, +0x32485abd, +0x7f1cf033, +0x1363fcf5, +0x498429a7, +0xcee7b643, +0x4a143dfd, +0xc7277108, +0x540a1db1, +0x8f382d79, +0xe6d57a47, +0x7573ff7c, +0xab24a417, +0x038c794e, +0x3d554bae, +0x7701c302, +0x7503f382, +0xd78eb998, +0x981f748f, +0x8674777e, +0x50d1d36a, +0x720d2a1c, +0x5a73a23e, +0x6c11d5d5, +0x5a50129d, +0xb102a470, +0xa7725c61, +0x50367f63, +0xb40cb199, +0x36e40d6a, +0x351e6215, +0x844a1961, +0xd7e04ed3, +0x840dd7fd, +0x6d1cca8a, +0x8e87c6fa, +0x71577bfa, +0x0f332230, +0xee23eda7, +0x693f76e9, +0x3c8ed3c4, +0x6a72fca5, +0x91bc7dde, +0x8353ad65, +0x7fd77a7f, +0xc9fb1685, +0x63d52396, +0xc58586cf, +0x1513f259, +0xd0b1b6c1, +0x50ccee15, +0x4bf40990, +0xd78a2a7a, +0x4e356a76, +0x9db0a659, +0x8472ca4c, +0xc74eeff6, +0xe5548c38, +0x4ca3343d, +0xa380a749, +0xfcbba8c7, +0xec8b5df2, +0xf290a3f6, +0xda4fc91c, +0x4e037ff3, +0x369ee32b, +0x1e4f0d76, +0xe771cddf, +0x165aed55, +0x28b0b90b, +0x67d033e5, +0xbd763f03, +0x5bd5e38e, +0x4295e5a3, +0xa293db4f, +0x5f607ab4, +0x5322a0d0, +0xc94c8c94, +0xeceded4d, +0x73785c71, +0x17e0bf88, +0x7f5c0911, +0x98d8710f, +0x567d8325, +0x4761278a, +0xb8f49fd0, +0x22ae4f2c, +0x5b913027, +0x31da1fbb, +0xa859ccd5, +0xf628dcd8, +0x0c08f212, +0x757dd74a, +0xa3483622, +0xa4afab73, +0xf85495fc, +0x79aeba4c, +0xf760fedf, +0x37e9980a, +0x70afa8a8, +0x771fccd3, +0xabe409ae, +0xa3caf014, +0xc61bb263, +0xdf6f080a, +0xa1b1a7a1, +0xd4cb1433, +0x772173b1, +0x127e2a84, +0x6078ed37, +0xe9ae0d72, +0x068deb2e, +0x538509b0, +0x3745ca8c, +0x80411c2a, +0xdc0af1f1, +0xbf1bd266, +0xddb1e7da, +0xe58b0f03, +0x8cf24e18, +0xb082104a, +0x3f3bf7f5, +0xbc52c82b, +0x7c289318, +0x91621c7e, +0x61ba7282, +0xe057ef2a, +0x2c7490ec, +0x636ed4f9, +0xef4ee885, +0xc2102cd3, +0x03b096fa, +0xa721a20f, +0xe2e2de9b, +0xdf99ee9c, +0x63e87140, +0x98f04a3b, +0x998a1415, +0x47d425d5, +0x81e18b1e, +0xfd75cd73, +0xda911e2f, +0xa131759c, +0xe609c123, +0x8bcf7251, +0xa062ca69, +0xf1254c75, +0xca0c3afa, +0x2b620162, +0x8f05cdc7, +0xf5e35e5d, +0x694d0ada, +0x9c30edcd, +0x91fcd15b, +0x7c4da71f, +0x8133bb65, +0x60c41108, +0xc8fe6ebe, +0x24baed41, +0x327b23e2, +0x3823edbd, +0x77a223e9, +0xeb2d7390, +0x16068273, +0xe63bfd53, +0x0f29df30, +0x27d62905, +0xf0ac1652, +0xe6f5f20d, +0xfee7aab7, +0x6e6aa877, +0xb61f6c21, +0xca0b9dde, +0x16b8384c, +0x8eab3c80, +0x0de85346, +0x3d3d32e5, +0x58663398, +0x0b0b33e9, +0xd154d1f5, +0x5c747425, +0xe4228b0b, +0x856dcb01, +0xa716d47f, +0x805c4ca7, +0x1d815217, +0xd8a0cf3f, +0x42f34017, +0xba088929, +0x80a2cd8a, +0x517ffe63, +0x20aa7c69, +0xa72d7746, +0x165e2f6a, +0x93e5568d, +0xf8f31ded, +0xd1598f8a, +0x2fda6076, +0xa31b5c80, +0x8d43b7f2, +0x7d2375c1, +0x2a00e4b7, +0x1040cf38, +0x264e88d7, +0xc8abe360, +0xdfe13c3e, +0x3b750fb9, +0x406183c3, +0x78bc2427, +0x334b01d1, +0xc26cad7a, +0x88b72b50, +0x1bc1d63c, +0x32810eca, +0x80f6a523, +0xa141a57f, +0x32ce732c, +0x68556d26, +0x72a0dc26, +0xdd25e4c0, +0xa61f2404, +0xe1592e10, +0x4698acc1, +0x7d80e659, +0x0913ddf7, +0xda82f04b, +0xb788cd43, +0x3de72856, +0x8bc444d2, +0x1d3dc87b, +0x2380fbc0, +0x434fd2d0, +0xa37cc127, +0xa5806f48, +0x2bbd90ae, +0x0c4d4ebe, +0x6a9306ba, +0xac3254d9, +0xd7cefc84, +0xc98c0ca7, +0xea8bb1c6, +0x16851fe0, +0x02c28a65, +0x76324463, +0xac6c62c3, +0x9bb2ce0d, +0xe7f220ba, +0x59a250af, +0xf432731f, +0x555c8843, +0xb0fbdbf5, +0xc4f37431, +0x64d68150, +0xb9da0993, +0x9321efd2, +0x67e301bf, +0xf6c6ea44, +0x3092635a, +0xd1ebed53, +0x02115815, +0x22815a78, +0x74c011ea, +0x303b0004, +0x317bc945, +0x79fffdb5, +0x0f5aed16, +0xaf6eabb2, +0x93624d52, +0x8d9cdf73, +0xd5656d1a, +0xbc7a2d44, +0x880f264f, +0x1db87830, +0x2db5e687, +0x89d6bac3, +0x7d3e0955, +0xb3b5db9f, +0x0d9405b8, +0x22f818be, +0x292e26fd, +0xb461ebc9, +0xa6b5ddab, +0xa6e4f23e, +0x2a088cfb, +0x9fc5b8d6, +0x59b210a7, +0x1498dd36, +0xe4e9feaf, +0x1a47f3b7, +0xfc5693bb, +0x52076044, +0xe2074937, +0x9762fcfa, +0x0700fd20, +0xc324f305, +0x3a7e03a2, +0xc766ab10, +0xa17541e4, +0xbce64eaa, +0xe68c5ae4, +0x5bf60a02, +0xf89f055e, +0xf13ccc98, +0x969b0106, +0x22191c6d, +0x8d2e0add, +0x33738386, +0xd3363e1a, +0xf2e5e217, +0x6bf72eb3, +0xa2159955, +0x322bc2f9, +0xdce59e07, +0x1a403d7a, +0xd40da160, +0xce583705, +0x705b002e, +0x53e38536, +0x0b46b6f4, +0xc889d7c7, +0xf282eac8, +0x864fc78f, +0x2de9689f, +0xed001e5a, +0xdafae8d0, +0xc3407619, +0x2ae6a6ea, +0x69713a02, +0x7bb17fcc, +0xfec1da98, +0xa607c8e6, +0x99e36005, +0x11e5b59f, +0x8ec18208, +0xf067d7f4, +0xe8a608b5, +0x26207dd2, +0xc7cb8146, +0xbaf6d7ad, +0xf47df435, +0xc54522c7, +0x748a8b8e, +0x99e794eb, +0xf2bf9683, +0x52f62b6c, +0x82b46215, +0x572d1d5e, +0x04c0f1df, +0xe6509ba2, +0x970a88ff, +0x152fc27f, +0xb93c6389, +0x0146abd0, +0x871834e7, +0x5eb57bc0, +0xaa0aeb71, +0xa52b0f4c, +0x241780a7, +0x64793af4, +0x5aaf4d43, +0x3cdbee68, +0x3dca4e19, +0xbaeebf0b, +0x320a8567, +0xe11a3bd2, +0x9b1d91a6, +0x810d70ce, +0xd1283978, +0x0d125cae, +0xb013fa71, +0x2bc20620, +0x3d5d2ff7, +0xde44d71c, +0x7fc69f0d, +0x4ad2e8af, +0x2f14b582, +0x6853bf2b, +0x68919517, +0x9d5f6509, +0xd9fab7ca, +0x7a6ce651, +0x8f982024, +0xb5547784, +0xae74490a, +0x714065fa, +0x405372cc, +0x3a58a46f, +0xe78230ca, +0x55cef9c0, +0xdbcad2d7, +0x962ea979, +0x33832922, +0x9673c257, +0xe2a54fc7, +0x758afe4a, +0x697c69cf, +0x1d03764f, +0x3c472146, +0x11bf0aad, +0x07d02cc8, +0x61d2ba2b, +0x1c8b3139, +0xa8e1b0dc, +0x2c90ea31, +0x6103556e, +0xd0e94b78, +0xe3314ab1, +0xd2cf23ca, +0x04763ea4, +0x4cffeb72, +0x25ec80ed, +0x63aaba43, +0xaa340488, +0x85e9a636, +0xfcdd73c1, +0x14ddf111, +0xec29eec7, +0x8acfbdae, +0xd545844c, +0x222077aa, +0xb3914d02, +0xd0828004, +0x3dfbaecb, +0xa9b3094b, +0xef71cf12, +0x553fb47d, +0xc1d0cd93, +0xd7ba76a0, +0xfae66db4, +0x18c47d41, +0x3aa84d32, +0x175836ff, +0xdd3c5f15, +0xe45bc3da, +0x2cc8d22f, +0x33bcf111, +0x1318ceed, +0x859f7c6d, +0x5346115c, +0xae7ac501, +0x7d10961b, +0x6df6c9e1, +0x07a9a3ae, +0x13e284a8, +0x658ef9f8, +0x20245391, +0x9822ef01, +0xc1457049, +0x4cdb8fce, +0xf466eb27, +0xf0e3554f, +0x644780ba, +0x4fa1bd26, +0x82f5f7c9, +0x367fbc36, +0x75aac234, +0x8950f1e4, +0x73eef9b8, +0x106b26d4, +0x154ac50f, +0xc928a55a, +0x8aecdff8, +0x6bea8c50, +0xf819b422, +0x4dde53cf, +0x83e2d7bb, +0x711b4da1, +0x8c63329c, +0x0117361e, +0xbdf6b395, +0x3ce2ad71, +0x13afbd7d, +0xd9363170, +0xc07606b5, +0xb3e57512, +0x34eeef15, +0x9d308933, +0x5d1f96ab, +0x6bdc81f3, +0x74e0ad20, +0x436731ce, +0x924dd479, +0x39e04f1d, +0x15e3fc6c, +0x89c73eb1, +0x56d7a3f1, +0x6d90ae82, +0x1b85ef26, +0x328fcad2, +0x28acd6ad, +0x221ece3b, +0x918ee52d, +0x869de6a0, +0x8e67660a, +0x57a65605, +0xc16e2019, +0x5b1a8b07, +0xbb76a606, +0xb864e189, +0xb42f7ec3, +0xddd14d1a, +0x2d9b60ea, +0x06ab5c4a, +0x3a5f0e8a, +0xd8a2925f, +0x69c60a15, +0x31aacc3d, +0xb696029e, +0xf1db51f3, +0xf5a2fc5c, +0xf865e873, +0x12838c07, +0xac5402f5, +0x4a4d06c9, +0xd376714f, +0x99afff3e, +0x8faa34e1, +0xc41d60b4, +0x9771a02b, +0xf054ae7b, +0xedf372df, +0x825d7c86, +0xe3072c73, +0x0005e224, +0x31c57f28, +0xc16a1696, +0xf53e5497, +0x7ef862ed, +0x7c6aa7fa, +0x78a74bed, +0xf95a114e, +0xaa361ba1, +0xa191f3cf, +0xed1a7af2, +0x2f551a17, diff --git a/src/cpu/intel/haswell/microcode_blob.h b/src/cpu/intel/haswell/microcode_blob.h index ef79cac90e..2bceb7353d 100644 --- a/src/cpu/intel/haswell/microcode_blob.h +++ b/src/cpu/intel/haswell/microcode_blob.h @@ -17,11 +17,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#if CONFIG_INTEL_LYNXPOINT_LP +#include "microcode-M7240650_ffff000a.h" +#include "microcode-M7240651_0000001c.h" +#else #include "microcode-M32306c1_ffff000d.h" #include "microcode-M32306c2_ffff0003.h" +#include "microcode-M32306c3_0000001c.h" #include "microcode-M3240660_ffff000b.h" -#include "microcode-M7240650_ffff000a.h" -#include "microcode-M7240651_00000006.h" +#endif /* Dummy terminator */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, diff --git a/src/cpu/intel/haswell/monotonic_timer.c b/src/cpu/intel/haswell/monotonic_timer.c new file mode 100644 index 0000000000..c51bcbd0c9 --- /dev/null +++ b/src/cpu/intel/haswell/monotonic_timer.c @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include + +#define MSR_COUNTER_24_MHz 0x637 +static struct monotonic_counter { + int initialized; + struct mono_time time; + uint32_t last_value; +} mono_counter; + +static inline uint32_t read_counter_msr(void) +{ + /* Even though the MSR is 64-bit it is assumed that the hardware + * is polled frequently enough to only use the lower 32-bits. */ + msr_t counter_msr; + + counter_msr = rdmsr(MSR_COUNTER_24_MHz); + + return counter_msr.lo; +} + +void timer_monotonic_get(struct mono_time *mt) +{ + uint32_t current_tick; + uint32_t usecs_elapsed; + + if (!mono_counter.initialized) { + mono_counter.last_value = read_counter_msr(); + mono_counter.initialized = 1; + } + + current_tick = read_counter_msr(); + usecs_elapsed = (current_tick - mono_counter.last_value) / 24; + + /* Update current time and tick values only if a full tick occurred. */ + if (usecs_elapsed) { + mono_time_add_usecs(&mono_counter.time, usecs_elapsed); + mono_counter.last_value = current_tick; + } + + /* Save result. */ + *mt = mono_counter.time; +} diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index ff5758471f..fee928dd2d 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -33,10 +33,12 @@ #include #include #include +#include #include #include -#if CONFIG_CHROMEOS #include +#if CONFIG_EC_GOOGLE_CHROMEEC +#include #endif #include "haswell.h" #include "northbridge/intel/haswell/haswell.h" @@ -162,7 +164,7 @@ static void *setup_romstage_stack_after_car(void) return slot; } -void * __attribute__((regparm(0))) romstage_main(unsigned long bist) +void * asmlinkage romstage_main(unsigned long bist) { int i; void *romstage_stack_after_car; @@ -188,11 +190,6 @@ void * __attribute__((regparm(0))) romstage_main(unsigned long bist) /* Get the stack to use after cache-as-ram is torn down. */ romstage_stack_after_car = setup_romstage_stack_after_car(); -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif - return romstage_stack_after_car; } @@ -202,25 +199,22 @@ void romstage_common(const struct romstage_params *params) int wake_from_s3; struct romstage_handoff *handoff; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif - -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + timestamp_early_init(base_time); + timestamp_add_now(TS_START_ROMSTAGE); if (params->bist == 0) enable_lapic(); wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config); +#if CONFIG_EC_GOOGLE_CHROMEEC + /* Ensure the EC is in the right mode for recovery */ + google_chromeec_early_init(); +#endif + /* Halt if there was a built in self test failure */ report_bist_failure(params->bist); @@ -249,17 +243,16 @@ void romstage_common(const struct romstage_params *params) post_code(0x3a); params->pei_data->boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + timestamp_add_now(TS_BEFORE_INITRAM); report_platform_info(); + if (params->copy_spd != NULL) + params->copy_spd(params->pei_data); + sdram_initialize(params->pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + timestamp_add_now(TS_AFTER_INITRAM); post_code(0x3b); intel_early_me_status(); @@ -288,13 +281,7 @@ void romstage_common(const struct romstage_params *params) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS - timestamp_init(base_time); - timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); - timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); - timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif } static inline void prepare_for_resume(struct romstage_handoff *handoff) @@ -321,77 +308,28 @@ void romstage_after_car(void) prepare_for_resume(handoff); -#if CONFIG_VBOOT_VERIFY_FIRMWARE vboot_verify_firmware(handoff); -#endif /* Load the ramstage. */ - copy_and_run(0); + copy_and_run(); } #if CONFIG_RELOCATABLE_RAMSTAGE -void cache_loaded_ramstage(struct romstage_handoff *handoff, - const struct cbmem_entry *ramstage, - void *entry_point) +#include + +struct ramstage_cache *ramstage_cache_location(long *size) { - struct ramstage_cache *cache; - uint32_t total_size; - uint32_t ramstage_size; - void *ramstage_base; - - ramstage_size = cbmem_entry_size(ramstage); - ramstage_base = cbmem_entry_start(ramstage); - /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET. * The top of ram is defined to be the TSEG base address. */ - cache = (void *)(get_top_of_ram() + RESERVED_SMM_OFFSET); - total_size = sizeof(*cache) + ramstage_size; - if (total_size > RESERVED_SMM_SIZE) { - printk(BIOS_DEBUG, "0x%08x > RESERVED_SMM_SIZE (0x%08x)\n", - total_size, RESERVED_SMM_SIZE); - /* Nuke whatever may be there now just in case. */ - cache->magic = ~RAMSTAGE_CACHE_MAGIC; - return; - } - - cache->magic = RAMSTAGE_CACHE_MAGIC; - cache->entry_point = (uint32_t)entry_point; - cache->load_address = (uint32_t)ramstage_base; - cache->size = ramstage_size; - - printk(BIOS_DEBUG, "Saving ramstage to SMM space cache.\n"); - - /* Copy over the program. */ - memcpy(&cache->program[0], ramstage_base, ramstage_size); - - if (handoff == NULL) - return; - - handoff->ramstage_entry_point = (uint32_t)entry_point; + *size = RESERVED_SMM_SIZE; + return (void *)(get_top_of_ram() + RESERVED_SMM_OFFSET); } -void *load_cached_ramstage(struct romstage_handoff *handoff, - const struct cbmem_entry *ramstage) +void ramstage_cache_invalid(struct ramstage_cache *cache) { - struct ramstage_cache *cache; - - /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET. - * The top of ram is defined to be the TSEG base address. */ - cache = (void *)(get_top_of_ram() + RESERVED_SMM_OFFSET); - - if (cache->magic != RAMSTAGE_CACHE_MAGIC) { - printk(BIOS_DEBUG, "Invalid ramstage cache found.\n"); - #if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE - reset_system(); - #endif - return NULL; - } - - printk(BIOS_DEBUG, "Loading ramstage from SMM space cache.\n"); - - memcpy((void *)cache->load_address, &cache->program[0], cache->size); - - return (void *)cache->entry_point; +#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE + reset_system(); +#endif } #endif diff --git a/src/cpu/intel/haswell/sipi_header.c b/src/cpu/intel/haswell/sipi_header.c deleted file mode 100644 index 846a82d7c2..0000000000 --- a/src/cpu/intel/haswell/sipi_header.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - - -extern void *ap_start; - -DEFINE_RMODULE_HEADER(sipi_vector_header, ap_start, RMODULE_TYPE_SIPI_VECTOR); diff --git a/src/cpu/intel/haswell/smmrelocate.c b/src/cpu/intel/haswell/smmrelocate.c index a8ab841492..aeaf1ff574 100644 --- a/src/cpu/intel/haswell/smmrelocate.c +++ b/src/cpu/intel/haswell/smmrelocate.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -164,11 +165,18 @@ static int bsp_setup_msr_save_state(struct smm_relocation_params *relo_params) /* The relocation work is actually performed in SMM context, but the code * resides in the ramstage module. This occurs by trampolining from the default * SMRAM entry point to here. */ -static void __attribute__((cdecl)) -cpu_smm_do_relocation(void *arg, int cpu, const struct smm_runtime *runtime) +static void asmlinkage cpu_smm_do_relocation(void *arg) { msr_t mtrr_cap; - struct smm_relocation_params *relo_params = arg; + struct smm_relocation_params *relo_params; + const struct smm_module_params *p; + const struct smm_runtime *runtime; + int cpu; + + p = arg; + runtime = p->runtime; + relo_params = p->arg; + cpu = p->cpu; if (cpu >= CONFIG_MAX_CPUS) { printk(BIOS_CRIT, @@ -286,6 +294,22 @@ static void fill_in_relocation_params(device_t dev, params->uncore_emrr_mask.hi = (1 << (39 - 32)) - 1; } +static void adjust_apic_id_map(struct smm_loader_params *smm_params) +{ + struct smm_runtime *runtime; + int i; + + /* Adjust the APIC id map if HT is disabled. */ + if (!ht_disabled) + return; + + runtime = smm_params->runtime; + + /* The APIC ids increment by 2 when HT is disabled. */ + for (i = 0; i < CONFIG_MAX_CPUS; i++) + runtime->apic_id_to_cpu[i] = runtime->apic_id_to_cpu[i] * 2; +} + static int install_relocation_handler(int num_cpus, struct smm_relocation_params *relo_params) { @@ -305,7 +329,12 @@ static int install_relocation_handler(int num_cpus, .handler_arg = (void *)relo_params, }; - return smm_setup_relocation_handler(&smm_params); + if (smm_setup_relocation_handler(&smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; } static void setup_ied_area(struct smm_relocation_params *params) @@ -347,8 +376,13 @@ static int install_permanent_handler(int num_cpus, printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", relo_params->smram_base); - return smm_load_module((void *)relo_params->smram_base, - relo_params->smram_size, &smm_params); + if (smm_load_module((void *)relo_params->smram_base, + relo_params->smram_size, &smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; } static int cpu_smm_setup(void) @@ -402,27 +436,27 @@ int smm_initialize(void) /* Run the relocation handler. */ smm_initiate_relocation(); - /* If smm_save_state_in_msrs is non-zero then parallel SMM relocation - * shall take place. Run the relocation handler a second time to do - * the final move. */ if (smm_reloc_params.smm_save_state_in_msrs) { printk(BIOS_DEBUG, "Doing parallel SMM relocation.\n"); - release_aps_for_smm_relocation(1); - smm_initiate_relocation_parallel(); - } else { - release_aps_for_smm_relocation(0); } - /* Now that all APs have been relocated as well as the BSP let SMIs - * start flowing. */ - southbridge_smm_enable_smi(); - - /* Lock down the SMRAM space. */ - smm_lock(); - return 0; } +void smm_relocate(void) +{ + /* + * If smm_save_state_in_msrs is non-zero then parallel SMM relocation + * shall take place. Run the relocation handler a second time on the + * BSP to do * the final move. For APs, a relocation handler always + * needs to be run. + */ + if (smm_reloc_params.smm_save_state_in_msrs) + smm_initiate_relocation_parallel(); + else if (!boot_cpu()) + smm_initiate_relocation(); +} + void smm_init(void) { /* smm_init() is normally called from initialize_cpus() in diff --git a/src/cpu/intel/haswell/tsc_freq.c b/src/cpu/intel/haswell/tsc_freq.c new file mode 100644 index 0000000000..0a7805319d --- /dev/null +++ b/src/cpu/intel/haswell/tsc_freq.c @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "cpu/intel/haswell/haswell.h" + +unsigned long tsc_freq_mhz(void) +{ + msr_t platform_info; + + platform_info = rdmsr(MSR_PLATFORM_INFO); + return HASWELL_BCLK * ((platform_info.lo >> 8) & 0xff); +} diff --git a/src/cpu/intel/model_1067x/Kconfig b/src/cpu/intel/model_1067x/Kconfig index 852c9cdf0c..80d0d64752 100644 --- a/src/cpu/intel/model_1067x/Kconfig +++ b/src/cpu/intel/model_1067x/Kconfig @@ -1,5 +1,8 @@ config CPU_INTEL_MODEL_1067X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 select TSC_SYNC_MFENCE diff --git a/src/cpu/intel/model_106cx/Kconfig b/src/cpu/intel/model_106cx/Kconfig index e26bf1fea5..4dc59c00aa 100644 --- a/src/cpu/intel/model_106cx/Kconfig +++ b/src/cpu/intel/model_106cx/Kconfig @@ -1,5 +1,8 @@ config CPU_INTEL_MODEL_106CX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 select UDELAY_LAPIC @@ -7,7 +10,10 @@ config CPU_INTEL_MODEL_106CX select AP_IN_SIPI_WAIT select TSC_SYNC_MFENCE +if CPU_INTEL_MODEL_106CX + config CPU_ADDR_BITS int default 32 +endif diff --git a/src/cpu/intel/model_206ax/Kconfig b/src/cpu/intel/model_206ax/Kconfig index 5b3f893943..5baf3800e3 100644 --- a/src/cpu/intel/model_206ax/Kconfig +++ b/src/cpu/intel/model_206ax/Kconfig @@ -8,6 +8,9 @@ if CPU_INTEL_MODEL_206AX || CPU_INTEL_MODEL_306AX config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 select UDELAY_LAPIC diff --git a/src/cpu/intel/model_206ax/cache_as_ram.inc b/src/cpu/intel/model_206ax/cache_as_ram.inc index 4202da9800..d147bd3a7d 100644 --- a/src/cpu/intel/model_206ax/cache_as_ram.inc +++ b/src/cpu/intel/model_206ax/cache_as_ram.inc @@ -248,7 +248,7 @@ before_romstage: post_code(0x38) /* Enable Write Back and Speculative Reads for the first MB - * and coreboot_ram. + * and ramstage. */ movl $MTRRphysBase_MSR(0), %ecx movl $(0x00000000 | MTRR_TYPE_WRBACK), %eax @@ -316,17 +316,12 @@ __acpi_resume_backup_done: post_code(0x3d) - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/intel/model_206ax/model_206ax.h b/src/cpu/intel/model_206ax/model_206ax.h index d440c7035f..1773cc88dc 100644 --- a/src/cpu/intel/model_206ax/model_206ax.h +++ b/src/cpu/intel/model_206ax/model_206ax.h @@ -97,7 +97,6 @@ #define PSS_LATENCY_TRANSITION 10 #define PSS_LATENCY_BUSMASTER 10 -#ifndef __ROMCC__ #ifdef __SMM__ /* Lock MSRs */ void intel_model_206ax_finalize_smm(void); @@ -106,6 +105,5 @@ void intel_model_206ax_finalize_smm(void); void set_power_limits(u8 power_limit_1_time); int cpu_config_tdp_levels(void); #endif -#endif #endif diff --git a/src/cpu/intel/model_65x/Kconfig b/src/cpu/intel/model_65x/Kconfig index 1ef48139f6..ac5617c94d 100644 --- a/src/cpu/intel/model_65x/Kconfig +++ b/src/cpu/intel/model_65x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_65X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_67x/Kconfig b/src/cpu/intel/model_67x/Kconfig index b65081c4bc..8a54bf8f15 100644 --- a/src/cpu/intel/model_67x/Kconfig +++ b/src/cpu/intel/model_67x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_67X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_68x/Kconfig b/src/cpu/intel/model_68x/Kconfig index f7f05f6e73..41cdab74eb 100644 --- a/src/cpu/intel/model_68x/Kconfig +++ b/src/cpu/intel/model_68x/Kconfig @@ -20,4 +20,7 @@ config CPU_INTEL_MODEL_68X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_69x/Kconfig b/src/cpu/intel/model_69x/Kconfig index 596763cf35..955619286f 100644 --- a/src/cpu/intel/model_69x/Kconfig +++ b/src/cpu/intel/model_69x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_69X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_6bx/Kconfig b/src/cpu/intel/model_6bx/Kconfig index 10661d0d96..3b89fcd73a 100644 --- a/src/cpu/intel/model_6bx/Kconfig +++ b/src/cpu/intel/model_6bx/Kconfig @@ -1,3 +1,7 @@ config CPU_INTEL_MODEL_6BX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP + diff --git a/src/cpu/intel/model_6dx/Kconfig b/src/cpu/intel/model_6dx/Kconfig index 5e70f59117..8ca134e4ee 100644 --- a/src/cpu/intel/model_6dx/Kconfig +++ b/src/cpu/intel/model_6dx/Kconfig @@ -1,3 +1,7 @@ config CPU_INTEL_MODEL_6DX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP + diff --git a/src/cpu/intel/model_6ex/Kconfig b/src/cpu/intel/model_6ex/Kconfig index e2b1986132..a6a9444ace 100644 --- a/src/cpu/intel/model_6ex/Kconfig +++ b/src/cpu/intel/model_6ex/Kconfig @@ -1,5 +1,8 @@ config CPU_INTEL_MODEL_6EX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 select UDELAY_LAPIC diff --git a/src/cpu/intel/model_6ex/cache_as_ram.inc b/src/cpu/intel/model_6ex/cache_as_ram.inc index b8222e15a2..50fab35ccc 100644 --- a/src/cpu/intel/model_6ex/cache_as_ram.inc +++ b/src/cpu/intel/model_6ex/cache_as_ram.inc @@ -225,17 +225,12 @@ clear_mtrrs: post_code(0x3c) - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/intel/model_6fx/Kconfig b/src/cpu/intel/model_6fx/Kconfig index 4517f17fa6..0acf149eac 100644 --- a/src/cpu/intel/model_6fx/Kconfig +++ b/src/cpu/intel/model_6fx/Kconfig @@ -1,5 +1,8 @@ config CPU_INTEL_MODEL_6FX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP select SSE2 select UDELAY_LAPIC diff --git a/src/cpu/intel/model_6xx/Kconfig b/src/cpu/intel/model_6xx/Kconfig index 96c7040706..ce43f134b7 100644 --- a/src/cpu/intel/model_6xx/Kconfig +++ b/src/cpu/intel/model_6xx/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_6XX bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_f0x/Kconfig b/src/cpu/intel/model_f0x/Kconfig index 9dd7fd0bdc..b2532efbeb 100644 --- a/src/cpu/intel/model_f0x/Kconfig +++ b/src/cpu/intel/model_f0x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_F0X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_f1x/Kconfig b/src/cpu/intel/model_f1x/Kconfig index ea75857949..0ecad7e5ed 100644 --- a/src/cpu/intel/model_f1x/Kconfig +++ b/src/cpu/intel/model_f1x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_F1X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_f2x/Kconfig b/src/cpu/intel/model_f2x/Kconfig index 50cac7937c..95d8979894 100644 --- a/src/cpu/intel/model_f2x/Kconfig +++ b/src/cpu/intel/model_f2x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_F2X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_f3x/Kconfig b/src/cpu/intel/model_f3x/Kconfig index 4cfca83dc6..d9137d562e 100644 --- a/src/cpu/intel/model_f3x/Kconfig +++ b/src/cpu/intel/model_f3x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_F3X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/model_f4x/Kconfig b/src/cpu/intel/model_f4x/Kconfig index 97c909a0ae..a63a5f8c7a 100644 --- a/src/cpu/intel/model_f4x/Kconfig +++ b/src/cpu/intel/model_f4x/Kconfig @@ -1,3 +1,6 @@ config CPU_INTEL_MODEL_F4X bool + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select SMP diff --git a/src/cpu/intel/turbo/Kconfig b/src/cpu/intel/turbo/Kconfig new file mode 100644 index 0000000000..5432c28eb3 --- /dev/null +++ b/src/cpu/intel/turbo/Kconfig @@ -0,0 +1,6 @@ + +config CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED + def_bool n + help + This option indicates that the turbo mode setting is not package + scoped. i.e. enable_turbo() needs to be called on not just the bsp diff --git a/src/cpu/intel/turbo/turbo.c b/src/cpu/intel/turbo/turbo.c index 779550e26b..7599ff1d05 100644 --- a/src/cpu/intel/turbo/turbo.c +++ b/src/cpu/intel/turbo/turbo.c @@ -24,7 +24,28 @@ #include #include -static int turbo_state = TURBO_UNKNOWN; +#if CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED +static inline int get_global_turbo_state(void) +{ + return TURBO_UNKNOWN; +} + +static inline void set_global_turbo_state(int state) +{ +} +#else +static int g_turbo_state = TURBO_UNKNOWN; + +static inline int get_global_turbo_state(void) +{ + return g_turbo_state; +} + +static inline void set_global_turbo_state(int state) +{ + g_turbo_state = state; +} +#endif static const char *turbo_state_desc[] = { [TURBO_UNKNOWN] = "unknown", @@ -43,6 +64,7 @@ int get_turbo_state(void) struct cpuid_result cpuid_regs; int turbo_en, turbo_cap; msr_t msr; + int turbo_state = get_global_turbo_state(); /* Return cached state if available */ if (turbo_state != TURBO_UNKNOWN) @@ -65,6 +87,7 @@ int get_turbo_state(void) turbo_state = TURBO_ENABLED; } + set_global_turbo_state(turbo_state); printk(BIOS_INFO, "Turbo is %s\n", turbo_state_desc[turbo_state]); return turbo_state; } @@ -84,7 +107,7 @@ void enable_turbo(void) wrmsr(MSR_IA32_MISC_ENABLES, msr); /* Update cached turbo state */ - turbo_state = TURBO_ENABLED; + set_global_turbo_state(TURBO_ENABLED); printk(BIOS_INFO, "Turbo has been enabled\n"); } } diff --git a/src/cpu/mips/Kconfig b/src/cpu/mips/Kconfig new file mode 100644 index 0000000000..f3aae85f99 --- /dev/null +++ b/src/cpu/mips/Kconfig @@ -0,0 +1,26 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +config CPU_MIPS + bool + select ARCH_BOOTBLOCK_MIPS + select ARCH_ROMSTAGE_MIPS + select ARCH_RAMSTAGE_MIPS diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig deleted file mode 100644 index 92b6460643..0000000000 --- a/src/cpu/samsung/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config CPU_SAMSUNG_EXYNOS5 - depends on ARCH_ARMV7 - select HAVE_UART_SPECIAL - select DEFAULT_EARLY_CONSOLE - bool - default n - -if CPU_SAMSUNG_EXYNOS5 -source src/cpu/samsung/exynos5250/Kconfig -endif diff --git a/src/cpu/samsung/Makefile.inc b/src/cpu/samsung/Makefile.inc deleted file mode 100644 index 97e9aab148..0000000000 --- a/src/cpu/samsung/Makefile.inc +++ /dev/null @@ -1,2 +0,0 @@ -subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5) += exynos5-common -subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5) += exynos5250 diff --git a/src/cpu/samsung/exynos5-common/Makefile.inc b/src/cpu/samsung/exynos5-common/Makefile.inc deleted file mode 100644 index 6911b70765..0000000000 --- a/src/cpu/samsung/exynos5-common/Makefile.inc +++ /dev/null @@ -1,23 +0,0 @@ -romstage-y += spi.c -ramstage-y += spi.c -bootblock-y += spi.c - -bootblock-y += gpio.c -bootblock-$(CONFIG_EARLY_CONSOLE) += pwm.c -bootblock-$(CONFIG_EARLY_CONSOLE) += timer.c - -romstage-y += pwm.c # needed by timer.c -romstage-y += gpio.c -romstage-y += timer.c -romstage-y += i2c.c - -#romstage-y += wdt.c -#romstage-y += sromc.c - -ramstage-y += cpu_info.c -ramstage-y += pwm.c # needed by timer.c -ramstage-y += timer.c -ramstage-y += gpio.c -ramstage-y += i2c.c -ramstage-y += s5p-dp-reg.c -ramstage-y += exynos-fb.c diff --git a/src/cpu/samsung/exynos5-common/clk.h b/src/cpu/samsung/exynos5-common/clk.h deleted file mode 100644 index 9de4f45516..0000000000 --- a/src/cpu/samsung/exynos5-common/clk.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * (C) Copyright 2012 The Chromium Authors - * (C) Copyright 2010 Samsung Electronics - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef __EXYNOS_COMMON_CLK_H_ -#define __EXYNOS_COMMON_CLK_H_ - -#include -#include - -enum periph_id; - -#define APLL 0 -#define MPLL 1 -#define EPLL 2 -#define HPLL 3 -#define VPLL 4 -#define BPLL 5 - -enum pll_src_bit { - SRC_MPLL = 6, - SRC_EPLL, - SRC_VPLL, -}; - -/* * - * This structure is to store the src bit, div bit and prediv bit - * positions of the peripheral clocks of the src and div registers - */ -struct clk_bit_info { - s8 src_bit; /* offset in register to clock source field */ - s8 n_src_bits; /* number of bits in 'src_bit' field */ - s8 div_bit; - s8 prediv_bit; -}; - -unsigned long get_pll_clk(int pllreg); -unsigned long get_arm_clk(void); -unsigned long get_pwm_clk(void); -unsigned long get_uart_clk(int dev_index); -void set_mmc_clk(int dev_index, unsigned int div); - -/** - * get the clk frequency of the required peripherial - * - * @param peripherial Peripherial id - * - * @return frequency of the peripherial clk - */ -unsigned long clock_get_periph_rate(enum periph_id peripheral); - -#endif diff --git a/src/cpu/samsung/exynos5-common/clock.h b/src/cpu/samsung/exynos5-common/clock.h deleted file mode 100644 index c0cd896b22..0000000000 --- a/src/cpu/samsung/exynos5-common/clock.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang - * Heungjun Kim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef __ASM_ARM_ARCH_CLOCK_H_ -#define __ASM_ARM_ARCH_CLOCK_H_ - -#ifndef __ASSEMBLER__ -struct s5pc100_clock { - unsigned int apll_lock; - unsigned int mpll_lock; - unsigned int epll_lock; - unsigned int hpll_lock; - unsigned char res1[0xf0]; - unsigned int apll_con; - unsigned int mpll_con; - unsigned int epll_con; - unsigned int hpll_con; - unsigned char res2[0xf0]; - unsigned int src0; - unsigned int src1; - unsigned int src2; - unsigned int src3; - unsigned char res3[0xf0]; - unsigned int div0; - unsigned int div1; - unsigned int div2; - unsigned int div3; - unsigned int div4; - unsigned char res4[0x1ec]; - unsigned int gate_d00; - unsigned int gate_d01; - unsigned int gate_d02; - unsigned char res5[0x54]; - unsigned int gate_sclk0; - unsigned int gate_sclk1; -}; - -struct s5pc110_clock { - unsigned int apll_lock; - unsigned char res1[0x4]; - unsigned int mpll_lock; - unsigned char res2[0x4]; - unsigned int epll_lock; - unsigned char res3[0xc]; - unsigned int vpll_lock; - unsigned char res4[0xdc]; - unsigned int apll_con; - unsigned char res5[0x4]; - unsigned int mpll_con; - unsigned char res6[0x4]; - unsigned int epll_con; - unsigned char res7[0xc]; - unsigned int vpll_con; - unsigned char res8[0xdc]; - unsigned int src0; - unsigned int src1; - unsigned int src2; - unsigned int src3; - unsigned char res9[0xf0]; - unsigned int div0; - unsigned int div1; - unsigned int div2; - unsigned int div3; - unsigned int div4; - unsigned char res10[0x1ec]; - unsigned int gate_d00; - unsigned int gate_d01; - unsigned int gate_d02; - unsigned char res11[0x54]; - unsigned int gate_sclk0; - unsigned int gate_sclk1; -}; -#endif - -#endif diff --git a/src/cpu/samsung/exynos5-common/cpu.h b/src/cpu/samsung/exynos5-common/cpu.h deleted file mode 100644 index 3a1df21cd0..0000000000 --- a/src/cpu/samsung/exynos5-common/cpu.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * (C) Copyright 2009-2010 Samsung Electronics - * Minkyu Kang - * Heungjun Kim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef _EXYNOS_COMMON_CPU_H -#define _EXYNOS_COMMON_CPU_H - -#define S5PC1XX_ADDR_BASE 0xE0000000 - -/* S5PC100 */ -#define S5PC100_PRO_ID 0xE0000000 -#define S5PC100_CLOCK_BASE 0xE0100000 -#define S5PC100_GPIO_BASE 0xE0300000 -#define S5PC100_VIC0_BASE 0xE4000000 -#define S5PC100_VIC1_BASE 0xE4100000 -#define S5PC100_VIC2_BASE 0xE4200000 -#define S5PC100_DMC_BASE 0xE6000000 -#define S5PC100_SROMC_BASE 0xE7000000 -#define S5PC100_ONENAND_BASE 0xE7100000 -#define S5PC100_PWMTIMER_BASE 0xEA000000 -#define S5PC100_WATCHDOG_BASE 0xEA200000 -#define S5PC100_UART_BASE 0xEC000000 -#define S5PC100_MMC_BASE 0xED800000 - -/* S5PC110 */ -#define S5PC110_PRO_ID 0xE0000000 -#define S5PC110_CLOCK_BASE 0xE0100000 -#define S5PC110_GPIO_BASE 0xE0200000 -#define S5PC110_PWMTIMER_BASE 0xE2500000 -#define S5PC110_WATCHDOG_BASE 0xE2700000 -#define S5PC110_UART_BASE 0xE2900000 -#define S5PC110_SROMC_BASE 0xE8000000 -#define S5PC110_MMC_BASE 0xEB000000 -#define S5PC110_DMC0_BASE 0xF0000000 -#define S5PC110_DMC1_BASE 0xF1400000 -#define S5PC110_VIC0_BASE 0xF2000000 -#define S5PC110_VIC1_BASE 0xF2100000 -#define S5PC110_VIC2_BASE 0xF2200000 -#define S5PC110_VIC3_BASE 0xF2300000 -#define S5PC110_OTG_BASE 0xEC000000 -#define S5PC110_PHY_BASE 0xEC100000 -#define S5PC110_USB_PHY_CONTROL 0xE010E80C - - -#include -/* CPU detection macros */ -extern unsigned int s5p_cpu_id; - -inline void s5p_set_cpu_id(void); - -#define IS_SAMSUNG_TYPE(type, id) \ -static inline int cpu_is_##type(void) \ -{ \ - return s5p_cpu_id == id ? 1 : 0; \ -} - -IS_SAMSUNG_TYPE(s5pc100, 0xc100) -IS_SAMSUNG_TYPE(s5pc110, 0xc110) - -int s5p_get_cpu_rev(void); -//void s5p_set_cpu_id(void); -int s5p_get_cpu_id(void); - -#define DEVICE_NOT_AVAILABLE 0 - -#define EXYNOS_PRO_ID 0x10000000 - -/* Address of address of function that copys data from SD or MMC */ -#define EXYNOS_COPY_MMC_FNPTR_ADDR 0x02020030 - -/* Address of address of function that copys data from SPI */ -#define EXYNOS_COPY_SPI_FNPTR_ADDR 0x02020058 - -/* Address of address of function that copys data through USB */ -#define EXYNOS_COPY_USB_FNPTR_ADDR 0x02020070 - -/* Boot mode values */ -#define EXYNOS_USB_SECONDARY_BOOT 0xfeed0002 - -#define EXYNOS_IRAM_SECONDARY_BASE 0x02020018 - -#define EXYNOS_I2C_SPACING 0x10000 - -enum boot_mode { - /* - * Assign the OM pin values for respective boot modes. - * Exynos4 does not support spi boot and the mmc boot OM - * pin values are the same across Exynos4 and Exynos5. - */ - BOOT_MODE_MMC = 4, - BOOT_MODE_SERIAL = 20, - /* Boot based on Operating Mode pin settings */ - BOOT_MODE_OM = 32, - BOOT_MODE_USB, /* Boot using USB download */ -}; - -/** - * Get the boot device containing BL1, BL2 (SPL) and U-boot - * - * @return boot device - */ -enum boot_mode exynos_get_boot_device(void); - -/** - * Check if a wakeup is permitted. - * - * On some boards we need to look at a special GPIO to ensure that the wakeup - * from sleep was valid. If the wakeup is not valid we need to go through a - * full reset. - * - * The default implementation of this function allows all wakeups. - * - * @return 1 if wakeup is permitted; 0 otherwise - */ -int board_wakeup_permitted(void); - -#define cpu_is_exynos4() (s5p_get_cpu_id() == 0xc210) -#define cpu_is_exynos5() (s5p_get_cpu_id() == 0xc520) - -/** - * Init subsystems according to the reset status - * - * @return 0 for a normal boot, non-zero for a resume - */ -int lowlevel_init_subsystems(void); - -#endif /* _EXYNOS_COMMON_CPU_H */ diff --git a/src/cpu/samsung/exynos5-common/cpu_info.c b/src/cpu/samsung/exynos5-common/cpu_info.c deleted file mode 100644 index dec3c779aa..0000000000 --- a/src/cpu/samsung/exynos5-common/cpu_info.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Minkyu Kang - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include -#if 0 -#include -#include -#include -#include -#endif -#include - -#include -#include -#include - -#include -#include /* for EXYNOS_PRO_ID */ - -/* FIXME(dhendrix): consolidate samsung ID code/#defines to a common location */ -#include /* cpu_info_init() prototype */ - -/* - * The following CPU infos are initialized in lowlevel_init(). They should be - * put in the .data section. Otherwise, a compile will put them in the .bss - * section since they don't have initial values. The relocation code which - * runs after lowlevel_init() will reset them to zero. - */ -unsigned int s5p_cpu_id __attribute__((section(".data"))); -unsigned int s5p_cpu_rev __attribute__((section(".data"))); - -void cpu_info_init(void) -{ - s5p_set_cpu_id(); -} - -int s5p_get_cpu_id(void) -{ - return s5p_cpu_id; -} - -int s5p_get_cpu_rev(void) -{ - return s5p_cpu_rev; -} - -void s5p_set_cpu_id(void) -{ - s5p_cpu_id = readl(EXYNOS_PRO_ID); - s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12)); - - /* - * 0xC200: EXYNOS4210 EVT0 - * 0xC210: EXYNOS4210 EVT1 - */ - if (s5p_cpu_id == 0xC200) { - s5p_cpu_id |= 0x10; - s5p_cpu_rev = 0; - } else if (s5p_cpu_id == 0xC210) { - s5p_cpu_rev = 1; - } -} - -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) -{ - char buf[32]; - - printf("CPU: S5P%X @ %sMHz\n", - s5p_cpu_id, strmhz(buf, get_arm_clk())); - - return 0; -} -#endif - -#if 0 -void board_show_dram(ulong size) -{ - enum ddr_mode mem_type; - unsigned frequency_mhz; - unsigned arm_freq; - enum mem_manuf mem_manuf; - char buf[32]; - int ret; - - /* Get settings from the fdt */ - ret = clock_get_mem_selection(&mem_type, &frequency_mhz, - &arm_freq, &mem_manuf); - if (ret) - panic("Invalid DRAM information"); - - puts("DRAM: "); - print_size(size, " "); - printf("%s %s @ %sMHz", - clock_get_mem_manuf_name(mem_manuf), - clock_get_mem_type_name(mem_type), - strmhz(buf, frequency_mhz)); - putc('\n'); -} -#endif - -#ifdef CONFIG_ARCH_CPU_INIT -int arch_cpu_init(void) -{ - cpu_info_init(); - - return 0; -} -#endif diff --git a/src/cpu/samsung/exynos5-common/exynos5-common.h b/src/cpu/samsung/exynos5-common/exynos5-common.h deleted file mode 100644 index b510d68ce0..0000000000 --- a/src/cpu/samsung/exynos5-common/exynos5-common.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Common configuration settings for EXYNOS5 based boards. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* TODO(dhendrix): some #defines are commented out here and moved to Kconfig */ - -#ifndef __EXYNOS5_CONFIG_H -#define __EXYNOS5_CONFIG_H - -/* High Level Configuration Options */ -#define CONFIG_SAMSUNG /* in a SAMSUNG core */ -#define CONFIG_S5P /* S5P Family */ -#define CONFIG_EXYNOS5 /* which is in a Exynos5 Family */ -#define BUILD_PART_FS_STUFF 1 /* Disk Partition Support */ - -#define CONFIG_ARCH_CPU_INIT /* Used to check cpu type */ - -#include /* get chip and board defs */ - -/* Align LCD to 1MB boundary */ -#define CONFIG_LCD_ALIGNMENT MMU_SECTION_SIZE - -#define CONFIG_DISPLAY_CPUINFO -#define CONFIG_DISPLAY_BOARDINFO_LATE -#define CONFIG_SYS_CONSOLE_INFO_QUIET -#define CONFIG_BOARD_LATE_INIT - -#define CONFIG_CMD_SHA256 -//#define CONFIG_EXYNOS_ACE_SHA - -//#define CONFIG_SYS_SDRAM_BASE 0x40000000 -//#define CONFIG_SYS_TEXT_BASE 0x43e00000 - -#define CONFIG_SETUP_MEMORY_TAGS -#define CONFIG_CMDLINE_TAG -#define CONFIG_INITRD_TAG -#define CONFIG_CMDLINE_EDITING - -/* Power Down Modes */ -#define S5P_CHECK_SLEEP 0x00000BAD -#define S5P_CHECK_DIDLE 0xBAD00000 -#define S5P_CHECK_LPA 0xABAD0000 - -/* Offset for inform registers */ -#define INFORM0_OFFSET 0x800 -#define INFORM1_OFFSET 0x804 - -/* Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (4 << 20)) - -/* select serial console configuration */ -#define CONFIG_SERIAL_MULTI -//#define CONFIG_BAUDRATE 115200 -#define EXYNOS5_DEFAULT_UART_OFFSET 0x010000 - -#define CONFIG_BOARD_EARLY_INIT_F - -/* PWM */ -#define CONFIG_PWM - -/* allow to overwrite serial and ethaddr */ -#define CONFIG_ENV_OVERWRITE - -/* SPL */ -#define CONFIG_SPL -#define CONFIG_SPL_GPIO_SUPPORT -#define CONFIG_SPL_POWER_SUPPORT -#define CONFIG_SPL_I2C_SUPPORT -#define CONFIG_SPL_SERIAL_SUPPORT -#define CONFIG_SPL_LIBCOMMON_SUPPORT - -/* Number of GPIOS to use for board revision detection */ -#define CONFIG_BOARD_REV_GPIO_COUNT 2 - -/* Miscellaneous configurable options */ -#define CONFIG_SYS_LONGHELP /* undef to save memory */ -#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */ -#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " -#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ -#define CONFIG_SYS_PBSIZE 384 /* Print Buffer Size */ -#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ -/* Boot Argument Buffer Size */ -#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE -/* memtest works on */ -#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE -#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x5E00000) -#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x3E00000) - -#define CONFIG_SYS_HZ 1000 - -/* valid baudrates */ -#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } - -/* Stack sizes */ -#define CONFIG_STACKSIZE (256 << 10) /* 256KB */ - -#define CONFIG_SYS_MONITOR_BASE 0x00000000 - -#ifdef CONFIG_SPI_FLASH -/* Enable SPI H/W Controller Driver support */ -#define CONFIG_EXYNOS_SPI - -/* FIXME(dhendrix): We should be concerned with SPI flash parts here... */ -#if 0 -#define CONFIG_CMD_SF -#define CONFIG_CMD_SPI -#define CONFIG_SPI_FLASH_WINBOND -/* Enable Gigadevice SPI flash support for Snow board */ -#define CONFIG_SPI_FLASH_GIGADEVICE -#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0 -/* Set speed for SPI flash */ -#define CONFIG_SF_DEFAULT_SPEED 50000000 -#endif -#endif - -/* FLASH and environment organization */ -#define CONFIG_SYS_NO_FLASH -#undef CONFIG_CMD_IMLS - -#define CONFIG_SECURE_BL1_ONLY - -/* Secure FW size configuration */ -#ifdef CONFIG_SECURE_BL1_ONLY -#define CONFIG_SEC_FW_SIZE (8 << 10) /* 8KB */ -#else -#define CONFIG_SEC_FW_SIZE 0 -#endif - -/* Configuration of BL1, BL2, ENV Blocks on mmc */ -#define CONFIG_RES_BLOCK_SIZE (512) -#define CONFIG_BL1_SIZE (16 << 10) /*16 K reserved for BL1*/ -#define CONFIG_BL2_SIZE (512UL << 10UL) /* 512 KB */ -#define CONFIG_ENV_SIZE (16 << 10) /* 16 KB */ - -#define CONFIG_BL1_OFFSET (CONFIG_RES_BLOCK_SIZE + CONFIG_SEC_FW_SIZE) -#define CONFIG_BL2_OFFSET (CONFIG_BL1_OFFSET + CONFIG_BL1_SIZE) - -#define SPI_FLASH_UBOOT_POS (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE) - -#ifdef CONFIG_ENV_IS_IN_SPI_FLASH -#define CONFIG_ENV_SPI_MODE SPI_MODE_0 -#define CONFIG_ENV_OFFSET (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE + \ - CONFIG_BL2_SIZE) -#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE -#define CONFIG_ENV_SPI_BUS 1 -#else /* CONFIG_ENV_IS_IN_MMC */ -#define CONFIG_ENV_OFFSET (CONFIG_BL2_OFFSET + CONFIG_BL2_SIZE) -#endif - -/* U-boot copy size from boot Media to DRAM.*/ -#define BL2_START_OFFSET (CONFIG_BL2_OFFSET/512) - -/* Set the emmc bus width to 8 */ -#define CONFIG_MSHCI_BUS_WIDTH 8 -#define CONFIG_MSHCI_PERIPH_ID PERIPH_ID_SDMMC0 - -#if BUILD_PART_FS_STUFF -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#endif - -/* Enable devicetree support */ -#define CONFIG_OF_LIBFDT - -#define CONFIG_SYS_THUMB_BUILD - -/* We spend about 100us getting from reset to SPL */ -#define CONFIG_SPL_TIME_US 100000 - -/* Stringify a token */ -#ifndef STRINGIFY -#define _STRINGIFY(x) #x -#define STRINGIFY(x) _STRINGIFY(x) -#endif - -#endif /* __EXYNOS5_CONFIG_H */ diff --git a/src/cpu/samsung/exynos5-common/gpio.c b/src/cpu/samsung/exynos5-common/gpio.c deleted file mode 100644 index c9c4c26ced..0000000000 --- a/src/cpu/samsung/exynos5-common/gpio.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* FIXME(dhendrix): fix this up so it doesn't require a bunch of #ifdefs... */ -#include -#include -//#include -#include -#include -#include -#include -#include /* FIXME: for gpio_decode_number prototype */ - -#define CON_MASK(x) (0xf << ((x) << 2)) -#define CON_SFR(x, v) ((v) << ((x) << 2)) - -#define DAT_MASK(x) (0x1 << (x)) -#define DAT_SET(x) (0x1 << (x)) - -#define PULL_MASK(x) (0x3 << ((x) << 1)) -#define PULL_MODE(x, v) ((v) << ((x) << 1)) - -#define DRV_MASK(x) (0x3 << ((x) << 1)) -#define DRV_SET(x, m) ((m) << ((x) << 1)) -#define RATE_MASK(x) (0x1 << (x + 16)) -#define RATE_SET(x) (0x1 << (x + 16)) - -struct gpio_info { - unsigned int reg_addr; /* Address of register for this part */ - unsigned int max_gpio; /* Maximum GPIO in this part */ -}; - -#include -static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { - { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, - { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, - { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, - { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 }, - { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 }, - { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT }, -}; - -#define HAVE_GENERIC_GPIO - -/* This macro gets gpio pin offset from 0..7 */ -#define GPIO_BIT(x) ((x) & 0x7) - -//#ifdef HAVE_GENERIC_GPIO -static struct s5p_gpio_bank *gpio_get_bank(unsigned int gpio) -{ - const struct gpio_info *data; - unsigned int upto; - int i; - - for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS; - i++, upto = data->max_gpio, data++) { - if (gpio < data->max_gpio) { - struct s5p_gpio_bank *bank; - - bank = (struct s5p_gpio_bank *)data->reg_addr; - bank += (gpio - upto) / GPIO_PER_BANK; - return bank; - } - } - - assert(gpio < GPIO_MAX_PORT); /* ...which it will not be */ - return NULL; -} -//#endif - -/* TODO: Deprecation this interface in favour of asm-generic/gpio.h */ -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) -{ - unsigned int value; - - value = readl(&bank->con); - value &= ~CON_MASK(gpio); - value |= CON_SFR(gpio, cfg); - writel(value, &bank->con); -} - -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en) -{ - unsigned int value; - - s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_OUTPUT); - - value = readl(&bank->dat); - value &= ~DAT_MASK(gpio); - if (en) - value |= DAT_SET(gpio); - writel(value, &bank->dat); -} - -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) -{ - s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_INPUT); -} - -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) -{ - unsigned int value; - - value = readl(&bank->dat); - value &= ~DAT_MASK(gpio); - if (en) - value |= DAT_SET(gpio); - writel(value, &bank->dat); -} - -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) -{ - unsigned int value; - - value = readl(&bank->dat); - return !!(value & DAT_MASK(gpio)); -} - -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->pull); - value &= ~PULL_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_PULL_DOWN: - case EXYNOS_GPIO_PULL_UP: - value |= PULL_MODE(gpio, mode); - break; - default: - break; - } - - writel(value, &bank->pull); -} - -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->drv); - value &= ~DRV_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_DRV_1X: - case EXYNOS_GPIO_DRV_2X: - case EXYNOS_GPIO_DRV_3X: - case EXYNOS_GPIO_DRV_4X: - value |= DRV_SET(gpio, mode); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->drv); - value &= ~RATE_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_DRV_FAST: - case EXYNOS_GPIO_DRV_SLOW: - value |= RATE_SET(gpio); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -/* Common GPIO API - only available on Exynos5 */ -/* FIXME(dhendrix): If this stuff is really only applicable to exynos5, - move it to a more sensible location. */ -#ifdef HAVE_GENERIC_GPIO - -void gpio_cfg_pin(int gpio, int cfg) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->con); - value &= ~CON_MASK(GPIO_BIT(gpio)); - value |= CON_SFR(GPIO_BIT(gpio), cfg); - writel(value, &bank->con); -} - -static int gpio_get_cfg(int gpio) -{ - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - int shift = GPIO_BIT(gpio) << 2; - - return (readl(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift; -} - -void gpio_set_pull(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->pull); - value &= ~PULL_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_PULL_DOWN: - case EXYNOS_GPIO_PULL_UP: - value |= PULL_MODE(GPIO_BIT(gpio), mode); - break; - default: - break; - } - - writel(value, &bank->pull); -} - -void gpio_set_drv(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->drv); - value &= ~DRV_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_DRV_1X: - case EXYNOS_GPIO_DRV_2X: - case EXYNOS_GPIO_DRV_3X: - case EXYNOS_GPIO_DRV_4X: - value |= DRV_SET(GPIO_BIT(gpio), mode); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -void gpio_set_rate(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->drv); - value &= ~RATE_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_DRV_FAST: - case EXYNOS_GPIO_DRV_SLOW: - value |= RATE_SET(GPIO_BIT(gpio)); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -int gpio_free(unsigned gpio) -{ - return 0; -} - -int gpio_direction_input(unsigned gpio) -{ - gpio_cfg_pin(gpio, EXYNOS_GPIO_INPUT); - - return 0; -} - -int gpio_direction_output(unsigned gpio, int value) -{ - unsigned int val; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - gpio_cfg_pin(gpio, EXYNOS_GPIO_OUTPUT); - - val = readl(&bank->dat); - val &= ~DAT_MASK(GPIO_BIT(gpio)); - if (value) - val |= DAT_SET(GPIO_BIT(gpio)); - writel(val, &bank->dat); - - return 0; -} - -int gpio_get_value(unsigned gpio) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->dat); - return !!(value & DAT_MASK(GPIO_BIT(gpio))); -} - -int gpio_set_value(unsigned gpio, int value) -{ - unsigned int val; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - val = readl(&bank->dat); - val &= ~DAT_MASK(GPIO_BIT(gpio)); - if (value) - val |= DAT_SET(GPIO_BIT(gpio)); - writel(val, &bank->dat); - - return 0; -} -#else - -static int s5p_gpio_get_pin(unsigned gpio) -{ - return gpio % GPIO_PER_BANK; -} - -/* - * If we have the old-style GPIO numbering setup, use these functions - * which don't necessary provide sequentially increasing GPIO numbers. - */ -static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio) -{ - int bank = gpio / GPIO_PER_BANK; - bank *= sizeof(struct s5p_gpio_bank); - - return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank); -} - -int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -int gpio_free(unsigned gpio) -{ - return 0; -} - -int gpio_direction_input(unsigned gpio) -{ - s5p_gpio_direction_input(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio)); - return 0; -} - -int gpio_direction_output(unsigned gpio, int value) -{ - s5p_gpio_direction_output(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio), value); - return 0; -} - -int gpio_get_value(unsigned gpio) -{ - return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio)); -} - -int gpio_set_value(unsigned gpio, int value) -{ - s5p_gpio_set_value(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio), value); - - return 0; -} - -#endif /* HAVE_GENERIC_GPIO */ - -/* - * Add a delay here to give the lines time to settle - * TODO(sjg): 1us does not always work, 2 is stable, so use 5 to be safe - * Come back to this and sort out what the datasheet says - */ -#define GPIO_DELAY_US 5 - -#ifndef __BOOT_BLOCK__ -/* - * FIXME(dhendrix): These functions use udelay, which has dependencies on - * pwm code and timer code. These aren't necessary for the bootblock and - * bloat the image significantly. - */ -int gpio_read_mvl3(unsigned gpio) -{ - int high, low; - enum mvl3 value; - - if (gpio >= GPIO_MAX_PORT) - return -1; - - gpio_direction_input(gpio); - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); - udelay(GPIO_DELAY_US); - high = gpio_get_value(gpio); - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_DOWN); - udelay(GPIO_DELAY_US); - low = gpio_get_value(gpio); - - if (high && low) /* external pullup */ - value = LOGIC_1; - else if (!high && !low) /* external pulldown */ - value = LOGIC_0; - else /* floating */ - value = LOGIC_Z; - - /* - * Check if line is externally pulled high and - * configure the internal pullup to match. For - * floating and pulldowns, the GPIO is already - * configured with an internal pulldown from the - * above test. - */ - if (value == LOGIC_1) - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); - - return value; -} - -int gpio_decode_number(unsigned gpio_list[], int count) -{ - int result = 0; - int multiplier = 1; - int gpio, i, value; - enum mvl3 mvl3; - - for (i = 0; i < count; i++) { - gpio = gpio_list[i]; - - mvl3 = gpio_read_mvl3(gpio); - if (mvl3 == LOGIC_1) - value = 2; - else if (mvl3 == LOGIC_0) - value = 1; - else if (mvl3 == LOGIC_Z) - value = 0; - else - return -1; - - result += value * multiplier; - multiplier *= 3; - } - - return result; -} -#endif /* __BOOT_BLOCK__ */ - -static const char *get_cfg_name(int cfg) -{ - static char name[8]; - - if (cfg == EXYNOS_GPIO_INPUT) - return "input"; - else if (cfg == EXYNOS_GPIO_OUTPUT) - return "output"; - printk(BIOS_INFO, "func %d", cfg); -// sprintf(name, "func %d", cfg); - - return name; -} - -/* - * Display Exynos GPIO information - */ -void gpio_info(void) -{ - unsigned gpio; - - for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) { - int cfg = gpio_get_cfg(gpio); - - printk(BIOS_INFO, "GPIO_%-3d: %s", gpio, get_cfg_name(cfg)); - if (cfg == EXYNOS_GPIO_INPUT || cfg == EXYNOS_GPIO_OUTPUT) - printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio)); - printk(BIOS_INFO, "\n"); - } -} diff --git a/src/cpu/samsung/exynos5-common/gpio.h b/src/cpu/samsung/exynos5-common/gpio.h deleted file mode 100644 index 0e4afc50c8..0000000000 --- a/src/cpu/samsung/exynos5-common/gpio.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * (C) Copyright 2009-2010 Samsung Electronics - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __ASM_ARCH_COMMON_GPIO_H -#define __ASM_ARCH_COMMON_GPIO_H - -#ifndef __ASSEMBLER__ /* FIXME: not needed (i hope)? */ - -#include /* FIXME: for S5PC110_GPIO_BASE */ - -struct s5p_gpio_bank { - unsigned int con; - unsigned int dat; - unsigned int pull; - unsigned int drv; - unsigned int pdn_con; - unsigned int pdn_pull; - unsigned char res1[8]; -}; - -struct s5pc100_gpio { - struct s5p_gpio_bank a0; - struct s5p_gpio_bank a1; - struct s5p_gpio_bank b; - struct s5p_gpio_bank c; - struct s5p_gpio_bank d; - struct s5p_gpio_bank e0; - struct s5p_gpio_bank e1; - struct s5p_gpio_bank f0; - struct s5p_gpio_bank f1; - struct s5p_gpio_bank f2; - struct s5p_gpio_bank f3; - struct s5p_gpio_bank g0; - struct s5p_gpio_bank g1; - struct s5p_gpio_bank g2; - struct s5p_gpio_bank g3; - struct s5p_gpio_bank i; - struct s5p_gpio_bank j0; - struct s5p_gpio_bank j1; - struct s5p_gpio_bank j2; - struct s5p_gpio_bank j3; - struct s5p_gpio_bank j4; - struct s5p_gpio_bank k0; - struct s5p_gpio_bank k1; - struct s5p_gpio_bank k2; - struct s5p_gpio_bank k3; - struct s5p_gpio_bank l0; - struct s5p_gpio_bank l1; - struct s5p_gpio_bank l2; - struct s5p_gpio_bank l3; - struct s5p_gpio_bank l4; - struct s5p_gpio_bank h0; - struct s5p_gpio_bank h1; - struct s5p_gpio_bank h2; - struct s5p_gpio_bank h3; -}; - -struct s5pc110_gpio { - struct s5p_gpio_bank a0; - struct s5p_gpio_bank a1; - struct s5p_gpio_bank b; - struct s5p_gpio_bank c0; - struct s5p_gpio_bank c1; - struct s5p_gpio_bank d0; - struct s5p_gpio_bank d1; - struct s5p_gpio_bank e0; - struct s5p_gpio_bank e1; - struct s5p_gpio_bank f0; - struct s5p_gpio_bank f1; - struct s5p_gpio_bank f2; - struct s5p_gpio_bank f3; - struct s5p_gpio_bank g0; - struct s5p_gpio_bank g1; - struct s5p_gpio_bank g2; - struct s5p_gpio_bank g3; - struct s5p_gpio_bank i; - struct s5p_gpio_bank j0; - struct s5p_gpio_bank j1; - struct s5p_gpio_bank j2; - struct s5p_gpio_bank j3; - struct s5p_gpio_bank j4; - struct s5p_gpio_bank mp0_1; - struct s5p_gpio_bank mp0_2; - struct s5p_gpio_bank mp0_3; - struct s5p_gpio_bank mp0_4; - struct s5p_gpio_bank mp0_5; - struct s5p_gpio_bank mp0_6; - struct s5p_gpio_bank mp0_7; - struct s5p_gpio_bank mp1_0; - struct s5p_gpio_bank mp1_1; - struct s5p_gpio_bank mp1_2; - struct s5p_gpio_bank mp1_3; - struct s5p_gpio_bank mp1_4; - struct s5p_gpio_bank mp1_5; - struct s5p_gpio_bank mp1_6; - struct s5p_gpio_bank mp1_7; - struct s5p_gpio_bank mp1_8; - struct s5p_gpio_bank mp2_0; - struct s5p_gpio_bank mp2_1; - struct s5p_gpio_bank mp2_2; - struct s5p_gpio_bank mp2_3; - struct s5p_gpio_bank mp2_4; - struct s5p_gpio_bank mp2_5; - struct s5p_gpio_bank mp2_6; - struct s5p_gpio_bank mp2_7; - struct s5p_gpio_bank mp2_8; - struct s5p_gpio_bank res1[48]; - struct s5p_gpio_bank h0; - struct s5p_gpio_bank h1; - struct s5p_gpio_bank h2; - struct s5p_gpio_bank h3; -}; - -/* functions */ -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en); -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); - -/* GPIO pins per bank */ -#define GPIO_PER_BANK 8 - -static inline unsigned int s5p_gpio_base(int nr) -{ - return S5PC110_GPIO_BASE; -} - -#define s5pc110_gpio_get_nr(bank, pin) \ - ((((((unsigned int)&(((struct s5pc110_gpio *)S5PC110_GPIO_BASE)->bank))\ - - S5PC110_GPIO_BASE) / sizeof(struct s5p_gpio_bank)) \ - * GPIO_PER_BANK) + pin) -#endif - -/* Pin configurations */ -#define GPIO_INPUT 0x0 -#define GPIO_OUTPUT 0x1 -#define GPIO_IRQ 0xf -#define GPIO_FUNC(x) (x) - -/* Pull mode */ -#define GPIO_PULL_NONE 0x0 -#define GPIO_PULL_DOWN 0x1 -#define GPIO_PULL_UP 0x2 - -/* Drive Strength level */ -#define GPIO_DRV_1X 0x0 -#define GPIO_DRV_3X 0x1 -#define GPIO_DRV_2X 0x2 -#define GPIO_DRV_4X 0x3 -#define GPIO_DRV_FAST 0x0 -#define GPIO_DRV_SLOW 0x1 - -#if 0 -struct s5p_gpio_bank { - unsigned int con; - unsigned int dat; - unsigned int pull; - unsigned int drv; - unsigned int pdn_con; - unsigned int pdn_pull; - unsigned char res1[8]; -}; - -/* functions */ -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en); -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); -#endif - -/* GPIO pins per bank */ -#define GPIO_PER_BANK 8 - -/* Pin configurations */ -#define EXYNOS_GPIO_INPUT 0x0 -#define EXYNOS_GPIO_OUTPUT 0x1 -#define EXYNOS_GPIO_IRQ 0xf -#define EXYNOS_GPIO_FUNC(x) (x) - -/* Pull mode */ -#define EXYNOS_GPIO_PULL_NONE 0x0 -#define EXYNOS_GPIO_PULL_DOWN 0x1 -#define EXYNOS_GPIO_PULL_UP 0x3 - -/* Drive Strength level */ -#define EXYNOS_GPIO_DRV_1X 0x0 -#define EXYNOS_GPIO_DRV_3X 0x1 -#define EXYNOS_GPIO_DRV_2X 0x2 -#define EXYNOS_GPIO_DRV_4X 0x3 -#define EXYNOS_GPIO_DRV_FAST 0x0 -#define EXYNOS_GPIO_DRV_SLOW 0x1 - -#define EXYNOS5_GPIO_BASE0 0x11400000 -#define EXYNOS5_GPIO_BASE1 0x13400000 -#define EXYNOS5_GPIO_BASE2 0x10d10000 -#define EXYNOS5_GPIO_BASE3 0x03860000 - -enum exynos5_gpio_port { - /* - * Ordered by base address + offset. - * ETC registers are special, thus not included. - */ - - /* base == EXYNOS_GPIO_BASE0 */ - EXYNOS5_GPA0 = EXYNOS5_GPIO_BASE0 + 0x0000, - EXYNOS5_GPA1 = EXYNOS5_GPIO_BASE0 + 0x0020, - EXYNOS5_GPA2 = EXYNOS5_GPIO_BASE0 + 0x0040, - - EXYNOS5_GPB0 = EXYNOS5_GPIO_BASE0 + 0x0060, - EXYNOS5_GPB1 = EXYNOS5_GPIO_BASE0 + 0x0080, - EXYNOS5_GPB2 = EXYNOS5_GPIO_BASE0 + 0x00a0, - EXYNOS5_GPB3 = EXYNOS5_GPIO_BASE0 + 0x00c0, - - EXYNOS5_GPC0 = EXYNOS5_GPIO_BASE0 + 0x00e0, - EXYNOS5_GPC1 = EXYNOS5_GPIO_BASE0 + 0x0100, - EXYNOS5_GPC2 = EXYNOS5_GPIO_BASE0 + 0x0120, - EXYNOS5_GPC3 = EXYNOS5_GPIO_BASE0 + 0x0140, - - EXYNOS5_GPD0 = EXYNOS5_GPIO_BASE0 + 0x0160, - EXYNOS5_GPD1 = EXYNOS5_GPIO_BASE0 + 0x0180, - - EXYNOS5_GPY0 = EXYNOS5_GPIO_BASE0 + 0x01a0, - EXYNOS5_GPY1 = EXYNOS5_GPIO_BASE0 + 0x01c0, - EXYNOS5_GPY2 = EXYNOS5_GPIO_BASE0 + 0x01e0, - EXYNOS5_GPY3 = EXYNOS5_GPIO_BASE0 + 0x0200, - EXYNOS5_GPY4 = EXYNOS5_GPIO_BASE0 + 0x0220, - EXYNOS5_GPY5 = EXYNOS5_GPIO_BASE0 + 0x0240, - EXYNOS5_GPY6 = EXYNOS5_GPIO_BASE0 + 0x0260, - - EXYNOS5_GPX0 = EXYNOS5_GPIO_BASE0 + 0x0c00, - EXYNOS5_GPX1 = EXYNOS5_GPIO_BASE0 + 0x0c20, - EXYNOS5_GPX2 = EXYNOS5_GPIO_BASE0 + 0x0c40, - EXYNOS5_GPX3 = EXYNOS5_GPIO_BASE0 + 0x0c60, - - /* base == EXYNOS_GPIO_BASE1 */ - EXYNOS5_GPE0 = EXYNOS5_GPIO_BASE1 + 0x0000, - EXYNOS5_GPE1 = EXYNOS5_GPIO_BASE1 + 0x0020, - - EXYNOS5_GPF0 = EXYNOS5_GPIO_BASE1 + 0x0040, - EXYNOS5_GPF1 = EXYNOS5_GPIO_BASE1 + 0x0060, - - EXYNOS5_GPG0 = EXYNOS5_GPIO_BASE1 + 0x0080, - EXYNOS5_GPG1 = EXYNOS5_GPIO_BASE1 + 0x00a0, - EXYNOS5_GPG2 = EXYNOS5_GPIO_BASE1 + 0x00c0, - - EXYNOS5_GPH0 = EXYNOS5_GPIO_BASE1 + 0x00e0, - EXYNOS5_GPH1 = EXYNOS5_GPIO_BASE1 + 0x0100, - - /* base == EXYNOS_GPIO_BASE2 */ - EXYNOS5_GPV0 = EXYNOS5_GPIO_BASE2 + 0x0000, - EXYNOS5_GPV1 = EXYNOS5_GPIO_BASE2 + 0x0020, - EXYNOS5_GPV2 = EXYNOS5_GPIO_BASE2 + 0x0060, - EXYNOS5_GPV3 = EXYNOS5_GPIO_BASE2 + 0x0080, - EXYNOS5_GPV4 = EXYNOS5_GPIO_BASE2 + 0x00c0, - - /* base == EXYNOS_GPIO_BASE3 */ - EXYNOS5_GPZ = EXYNOS5_GPIO_BASE3 + 0x0000, -}; - -#endif diff --git a/src/cpu/samsung/exynos5-common/i2c.c b/src/cpu/samsung/exynos5-common/i2c.c deleted file mode 100644 index 7384b506df..0000000000 --- a/src/cpu/samsung/exynos5-common/i2c.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * (C) Copyright 2002 - * David Mueller, ELSOFT AG, d.mueller@elsoft.ch - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* This code should work for both the S3C2400 and the S3C2410 - * as they seem to have the same I2C controller inside. - * The different address mapping is handled by the s3c24xx.h files below. - */ - -#include -#include -#include "clk.h" -#include "cpu/samsung/exynos5-common/clk.h" -#include "cpu/samsung/exynos5250/cpu.h" -#include "gpio.h" -#include "cpu/samsung/exynos5250/gpio.h" -#include "cpu/samsung/exynos5250/pinmux.h" - -//#include -#include "device/i2c.h" -#include "i2c.h" - -#define I2C_WRITE 0 -#define I2C_READ 1 - -#define I2C_OK 0 -#define I2C_NOK 1 -#define I2C_NACK 2 -#define I2C_NOK_LA 3 /* Lost arbitration */ -#define I2C_NOK_TOUT 4 /* time out */ - -#define I2CSTAT_BSY 0x20 /* Busy bit */ -#define I2CSTAT_NACK 0x01 /* Nack bit */ -#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ -#define I2CCON_IRPND 0x10 /* Interrupt pending bit */ -#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ -#define I2C_MODE_MR 0x80 /* Master Receive Mode */ -#define I2C_START_STOP 0x20 /* START / STOP */ -#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ - -/* The timeouts we live by */ -enum { - I2C_XFER_TIMEOUT_MS = 35, /* xfer to complete */ - I2C_INIT_TIMEOUT_MS = 1000, /* bus free on init */ - I2C_IDLE_TIMEOUT_MS = 100, /* waiting for bus idle */ - I2C_STOP_TIMEOUT_US = 200, /* waiting for stop events */ -}; - -/* We should not rely on any particular ordering of these IDs */ -#if 0 -#ifndef CONFIG_OF_CONTROL -static enum periph_id periph_for_dev[EXYNOS_I2C_MAX_CONTROLLERS] = { - PERIPH_ID_I2C0, - PERIPH_ID_I2C1, - PERIPH_ID_I2C2, - PERIPH_ID_I2C3, - PERIPH_ID_I2C4, - PERIPH_ID_I2C5, - PERIPH_ID_I2C6, - PERIPH_ID_I2C7, -}; -#endif -#endif - -static unsigned int g_current_bus __attribute__((section(".data"))); -static struct s3c24x0_i2c *g_early_i2c_config __attribute__((section(".data"))); - -static struct s3c24x0_i2c_bus i2c_bus[EXYNOS_I2C_MAX_CONTROLLERS] - __attribute__((section(".data"))); -static int i2c_busses __attribute__((section(".data"))); - -void i2c_set_early_reg(unsigned int base) -{ - g_early_i2c_config = (struct s3c24x0_i2c *)base; -} - -static struct s3c24x0_i2c_bus *get_bus(int bus_idx) -{ - /* If an early i2c config exists we just use that */ - if (g_early_i2c_config) { - /* FIXME: value not retained from i2c_set_early_reg()? (but then, how - * did if (!i2c) check pass earlier on? Corrupt value? */ - i2c_bus[0].regs = g_early_i2c_config; - return &i2c_bus[0]; - } - - if (bus_idx < i2c_busses) - return &i2c_bus[bus_idx]; - debug("Undefined bus: %d\n", bus_idx); - return NULL; -} - -static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void) -{ - return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE); -} - -static int WaitForXfer(struct s3c24x0_i2c *i2c) -{ - int i; - - i = I2C_XFER_TIMEOUT_MS * 20; - while (!(readl(&i2c->iiccon) & I2CCON_IRPND)) { - if (i == 0) { - debug("%s: i2c xfer timeout\n", __func__); - return I2C_NOK_TOUT; - } - udelay(50); - i--; - } - - return I2C_OK; -} - -static int IsACK(struct s3c24x0_i2c *i2c) -{ - return !(readl(&i2c->iicstat) & I2CSTAT_NACK); -} - -static void ReadWriteByte(struct s3c24x0_i2c *i2c) -{ - uint32_t x; - - x = readl(&i2c->iiccon); - writel(x & ~I2CCON_IRPND, &i2c->iiccon); - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ -// writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); -} - -static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) -{ - unsigned long freq, pres = 16, div; - - freq = clock_get_periph_rate(PERIPH_ID_I2C0); - /* calculate prescaler and divisor values */ - if ((freq / pres / (16 + 1)) > speed) - /* set prescaler to 512 */ - pres = 512; - - div = 0; - - while ((freq / pres / (div + 1)) > speed) - div++; - - /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ - writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); - - /* init to SLAVE REVEIVE and set slaveaddr */ - writel(0, &i2c->iicstat); - writel(slaveadd, &i2c->iicadd); - /* program Master Transmit (and implicit STOP) */ - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); -} - -/* TODO: determine if this is necessary to init board using FDT-provided info */ -#if 0 -void board_i2c_init(const void *blob) -{ - /* - * Turn off the early i2c configuration and init the i2c properly, - * this is done here to enable the use of i2c configs from FDT. - */ - i2c_set_early_reg(0); - -#ifdef CONFIG_OF_CONTROL - int node_list[EXYNOS_I2C_MAX_CONTROLLERS]; - int i, count; - - count = fdtdec_find_aliases_for_id(blob, "i2c", - COMPAT_SAMSUNG_S3C2440_I2C, node_list, - EXYNOS_I2C_MAX_CONTROLLERS); - - for (i = 0; i < count; i++) { - struct s3c24x0_i2c_bus *bus; - int node = node_list[i]; - - if (node < 0) - continue; - bus = &i2c_bus[i2c_busses]; - bus->regs = (struct s3c24x0_i2c *) - fdtdec_get_addr(blob, node, "reg"); - bus->id = (enum periph_id) - fdtdec_get_int(blob, node, "samsung,periph-id", -1); - bus->node = node; - bus->bus_num = i2c_busses++; - } -#else - int i; - - for (i = 0; i < EXYNOS_I2C_MAX_CONTROLLERS; i++) { - unsigned intptr_t reg_addr = samsung_get_base_i2c() + - EXYNOS_I2C_SPACING * i; - - i2c_bus[i].regs = (struct s3c24x0_i2c_bus *)reg_addr; - i2c_bus[i].id = periph_for_dev[i]; - } - i2c_busses = EXYNOS_I2C_MAX_CONTROLLERS; -#endif -} -#endif - -/* - * MULTI BUS I2C support - */ -static void i2c_bus_init(struct s3c24x0_i2c_bus *i2c, unsigned int bus) -{ - exynos_pinmux_config(i2c->id, 0); - i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -} - -#ifdef CONFIG_I2C_MULTI_BUS -int i2c_set_bus_num(unsigned int bus) -{ - struct s3c24x0_i2c_bus *i2c; - - i2c = get_bus(bus); - if (!i2c) - return -1; - g_current_bus = bus; - i2c_bus_init(i2c, g_current_bus); - - return 0; -} - -unsigned int i2c_get_bus_num(void) -{ - return g_current_bus; -} -#endif - -#ifdef CONFIG_OF_CONTROL -int i2c_get_bus_num_fdt(const void *blob, int node) -{ - enum fdt_compat_id compat; - fdt_addr_t reg; - int i; - - compat = fdtdec_lookup(blob, node); - if (compat != COMPAT_SAMSUNG_S3C2440_I2C) { - debug("%s: Not a supported I2C node\n", __func__); - return -1; - } - - reg = fdtdec_get_addr(blob, node, "reg"); - for (i = 0; i < i2c_busses; i++) - if (reg == (fdt_addr_t)(unsigned intptr_t)i2c_bus[i].regs) - return i; - - debug("%s: Can't find any matched I2C bus\n", __func__); - return -1; -} - -int i2c_reset_port_fdt(const void *blob, int node) -{ - struct s3c24x0_i2c_bus *i2c; - - int bus; - - bus = i2c_get_bus_num_fdt(blob, node); - if (bus < 0) { - printf("could not get bus for node %d\n", node); - return -1; - } - i2c = get_bus(bus); - if (!i2c) { - printf("get_bus() failed for node node %d\n", node); - return -1; - } - - i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - return 0; -} -#endif - -/* - * Verify the whether I2C ACK was received or not - * - * @param i2c pointer to I2C register base - * @param buf array of data - * @param len length of data - * return I2C_OK when transmission done - * I2C_NACK otherwise - */ -static int i2c_send_verify(struct s3c24x0_i2c *i2c, unsigned char buf[], - unsigned char len) -{ - int i, result = I2C_OK; - - if (IsACK(i2c)) { - for (i = 0; (i < len) && (result == I2C_OK); i++) { - writel(buf[i], &i2c->iicds); - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - if (result == I2C_OK && !IsACK(i2c)) - result = I2C_NACK; - } - } else { - result = I2C_NACK; - } - - return result; -} - -void i2c_init(int speed, int slaveadd) -{ - struct s3c24x0_i2c_bus *i2c; - struct exynos5_gpio_part1 *gpio; - int i; - uint32_t x; - - /* By default i2c channel 0 is the current bus */ - g_current_bus = 0; - - i2c = get_bus(g_current_bus); - if (!i2c) - return; - - i2c_bus_init(i2c, g_current_bus); - - /* wait for some time to give previous transfer a chance to finish */ - i = I2C_INIT_TIMEOUT_MS * 20; - while ((readl(&i2c->regs->iicstat) & I2CSTAT_BSY) && (i > 0)) { - udelay(50); - i--; - } - - gpio = exynos_get_base_gpio1(); - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ -// writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con); - x = readl(&gpio->b3.con); - writel((x & ~0x00FF) | 0x0022, &gpio->b3.con); - - i2c_ch_init(i2c->regs, speed, slaveadd); -} - -/* - * Send a STOP event and wait for it to have completed - * - * @param mode If it is a master transmitter or receiver - * @return I2C_OK if the line became idle before timeout I2C_NOK_TOUT otherwise - */ -static int i2c_send_stop(struct s3c24x0_i2c *i2c, int mode) -{ - int timeout; - - /* Setting the STOP event to fire */ - writel(mode | I2C_TXRX_ENA, &i2c->iicstat); - ReadWriteByte(i2c); - - /* Wait for the STOP to send and the bus to go idle */ - for (timeout = I2C_STOP_TIMEOUT_US; timeout > 0; timeout -= 5) { - if (!(readl(&i2c->iicstat) & I2CSTAT_BSY)) - return I2C_OK; - udelay(5); - } - - return I2C_NOK_TOUT; -} - -/* - * cmd_type is 0 for write, 1 for read. - * - * addr_len can take any value from 0-255, it is only limited - * by the char, we could make it larger if needed. If it is - * 0 we skip the address write cycle. - */ -static int i2c_transfer(struct s3c24x0_i2c *i2c, - unsigned char cmd_type, - unsigned char chip, - unsigned char addr[], - unsigned char addr_len, - unsigned char data[], - unsigned short data_len) -{ - int i, result, stop_bit_result; - uint32_t x; - - if (data == 0 || data_len == 0) { - /* Don't support data transfer of no length or to address 0 */ - debug("i2c_transfer: bad call\n"); - return I2C_NOK; - } - - /* Check I2C bus idle */ - i = I2C_IDLE_TIMEOUT_MS * 20; - while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) { - udelay(50); - i--; - } - - if (readl(&i2c->iicstat) & I2CSTAT_BSY) { - debug("%s: bus busy\n", __func__); - return I2C_NOK_TOUT; - } - - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ - //writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); - x = readl(&i2c->iiccon); - writel(x | I2CCON_ACKGEN, &i2c->iiccon); - - if (addr && addr_len) { - writel(chip, &i2c->iicds); - /* send START */ - writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - if (WaitForXfer(i2c) == I2C_OK) - result = i2c_send_verify(i2c, addr, addr_len); - else - result = I2C_NACK; - } else - result = I2C_NACK; - - switch (cmd_type) { - case I2C_WRITE: - if (result == I2C_OK) - result = i2c_send_verify(i2c, data, data_len); - else { - writel(chip, &i2c->iicds); - /* send START */ - writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - if (WaitForXfer(i2c) == I2C_OK) - result = i2c_send_verify(i2c, data, data_len); - } - - if (result == I2C_OK) - result = WaitForXfer(i2c); - - stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MT); - break; - - case I2C_READ: - { - int was_ok = (result == I2C_OK); - - writel(chip, &i2c->iicds); - /* resend START */ - writel(I2C_MODE_MR | I2C_TXRX_ENA | - I2C_START_STOP, &i2c->iicstat); - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - - if (was_ok || IsACK(i2c)) { - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - /* disable ACK for final READ */ - if (i == data_len - 1) { - /* FIXME(dhendrix): nested macro */ -#if 0 - writel(readl(&i2c->iiccon) & - ~I2CCON_ACKGEN, - &i2c->iiccon); -#endif - x = readl(&i2c->iiccon) & ~I2CCON_ACKGEN; - writel(x, &i2c->iiccon); - } - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - data[i] = readl(&i2c->iicds); - i++; - } - } else { - result = I2C_NACK; - } - - stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MR); - break; - } - - default: - debug("i2c_transfer: bad call\n"); - result = stop_bit_result = I2C_NOK; - break; - } - - /* - * If the transmission went fine, then only the stop bit was left to - * fail. Otherwise, the real failure we're interested in came before - * that, during the actual transmission. - */ - return (result == I2C_OK) ? stop_bit_result : result; -} - -int i2c_probe(unsigned char chip) -{ - struct s3c24x0_i2c_bus *i2c; - unsigned char buf[1]; - int ret; - - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - buf[0] = 0; - - /* - * What is needed is to send the chip address and verify that the - * address was ed (i.e. there was a chip at that address which - * drove the data line low). - */ - ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, 0, 0, buf, 1); - - return ret != I2C_OK; -} - -int i2c_read(unsigned char chip, unsigned int addr, int alen, unsigned char *buffer, int len) -{ - struct s3c24x0_i2c_bus *i2c; - unsigned char xaddr[4]; - int ret; - - if (alen > 4) { - debug("I2C read: addr len %d not supported\n", alen); - return 1; - } - - if (alen > 0) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } - -#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW - /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. - * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. - */ - if (alen > 0) - chip |= ((addr >> (alen * 8)) & - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); -#endif - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, &xaddr[4 - alen], - alen, buffer, len); - if (ret) { - debug("I2c read: failed %d\n", ret); - return 1; - } - return 0; -} - -int i2c_write(unsigned char chip, unsigned int addr, int alen, unsigned char *buffer, int len) -{ - struct s3c24x0_i2c_bus *i2c; - unsigned char xaddr[4]; - int ret; - - if (alen > 4) { - debug("I2C write: addr len %d not supported\n", alen); - return 1; - } - - if (alen > 0) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } -#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW - /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. - * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. - */ - if (alen > 0) - chip |= ((addr >> (alen * 8)) & - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); -#endif - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - - ret = i2c_transfer(i2c->regs, I2C_WRITE, chip << 1, &xaddr[4 - alen], - alen, buffer, len); - - return ret != 0; -} diff --git a/src/cpu/samsung/exynos5-common/power.h b/src/cpu/samsung/exynos5-common/power.h deleted file mode 100644 index 57e2a2ba19..0000000000 --- a/src/cpu/samsung/exynos5-common/power.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2009 Samsung Electronics - * Kyungmin Park - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef __ASM_ARM_ARCH_POWER_H_ -#define __ASM_ARM_ARCH_POWER_H_ - -/* - * Power control - */ -#define S5PC100_OTHERS 0xE0108200 -#define S5PC100_RST_STAT 0xE0108300 -#define S5PC100_SLEEP_WAKEUP (1 << 3) -#define S5PC100_WAKEUP_STAT 0xE0108304 -#define S5PC100_INFORM0 0xE0108400 - -#define S5PC110_RST_STAT 0xE010A000 -#define S5PC110_SLEEP_WAKEUP (1 << 3) -#define S5PC110_WAKEUP_STAT 0xE010C200 -#define S5PC110_OTHERS 0xE010E000 -#define S5PC110_USB_PHY_CON 0xE010E80C -#define S5PC110_INFORM0 0xE010F000 - -#endif diff --git a/src/cpu/samsung/exynos5-common/pwm.c b/src/cpu/samsung/exynos5-common/pwm.c deleted file mode 100644 index 0fc571b220..0000000000 --- a/src/cpu/samsung/exynos5-common/pwm.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * - * Donghwa Lee - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -int pwm_enable(int pwm_id) -{ - const struct s5p_timer *pwm = - samsung_get_base_timer(); - unsigned long tcon; - - tcon = readl(&pwm->tcon); - tcon |= TCON_START(pwm_id); - - writel(tcon, &pwm->tcon); - - return 0; -} - -int pwm_check_enabled(int pwm_id) -{ - const struct s5p_timer *pwm = - samsung_get_base_timer(); - const unsigned long tcon = readl(&pwm->tcon); - - return tcon & TCON_START(pwm_id); -} - -void pwm_disable(int pwm_id) -{ - const struct s5p_timer *pwm = - samsung_get_base_timer(); - unsigned long tcon; - - tcon = readl(&pwm->tcon); - tcon &= ~TCON_START(pwm_id); - - writel(tcon, &pwm->tcon); -} - -static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) -{ - unsigned long tin_parent_rate; - unsigned int div; - - tin_parent_rate = clock_get_periph_rate(PERIPH_ID_PWM0); - - for (div = 2; div <= 16; div *= 2) { - if ((tin_parent_rate / (div << 16)) < freq) - return tin_parent_rate / div; - } - - return tin_parent_rate / 16; -} - -#define NS_IN_SEC 1000000000UL - -int pwm_config(int pwm_id, int duty_ns, int period_ns) -{ - const struct s5p_timer *pwm = - samsung_get_base_timer(); - unsigned int offset; - unsigned long tin_rate; - unsigned long tin_ns; - unsigned long frequency; - unsigned long tcon; - unsigned long tcnt; - unsigned long tcmp; - - /* - * We currently avoid using 64bit arithmetic by using the - * fact that anything faster than 1GHz is easily representable - * by 32bits. - */ - if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0) - return -1; -// return -ERANGE; - - if (duty_ns > period_ns) - return -1; -// return -EINVAL; - - frequency = NS_IN_SEC / period_ns; - - /* Check to see if we are changing the clock rate of the PWM */ - tin_rate = pwm_calc_tin(pwm_id, frequency); - - tin_ns = NS_IN_SEC / tin_rate; - tcnt = period_ns / tin_ns; - - /* Note, counters count down */ - tcmp = duty_ns / tin_ns; - tcmp = tcnt - tcmp; - - /* Update the PWM register block. */ - offset = pwm_id * 3; - if (pwm_id < 4) { - writel(tcnt, &pwm->tcntb0 + offset); - writel(tcmp, &pwm->tcmpb0 + offset); - } - - tcon = readl(&pwm->tcon); - tcon |= TCON_UPDATE(pwm_id); - if (pwm_id < 4) - tcon |= TCON_AUTO_RELOAD(pwm_id); - else - tcon |= TCON4_AUTO_RELOAD; - writel(tcon, &pwm->tcon); - - tcon &= ~TCON_UPDATE(pwm_id); - writel(tcon, &pwm->tcon); - - return 0; -} - -int pwm_init(int pwm_id, int div, int invert) -{ - u32 val; - const struct s5p_timer *pwm = - samsung_get_base_timer(); - unsigned long ticks_per_period; - unsigned int offset, prescaler; - - /* - * Timer Freq(HZ) = - * PWM_CLK / { (prescaler_value + 1) * (divider_value) } - */ - - val = readl(&pwm->tcfg0); - if (pwm_id < 2) { - prescaler = PRESCALER_0; - val &= ~0xff; - val |= (prescaler & 0xff); - } else { - prescaler = PRESCALER_1; - val &= ~(0xff << 8); - val |= (prescaler & 0xff) << 8; - } - writel(val, &pwm->tcfg0); - val = readl(&pwm->tcfg1); - val &= ~(0xf << MUX_DIV_SHIFT(pwm_id)); - val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id); - writel(val, &pwm->tcfg1); - - - if (pwm_id == 4) { - /* - * TODO(sjg): Use this as a countdown timer for now. We count - * down from the maximum value to 0, then reset. - */ - ticks_per_period = -1UL; - } else { - const unsigned long pwm_hz = 1000; - unsigned long timer_rate_hz = clock_get_periph_rate( - PERIPH_ID_PWM0) / ((prescaler + 1) * (1 << div)); - - ticks_per_period = timer_rate_hz / pwm_hz; - } - - /* set count value */ - offset = pwm_id * 3; - - writel(ticks_per_period, &pwm->tcntb0 + offset); - - val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id)); - if (invert && (pwm_id < 4)) - val |= TCON_INVERTER(pwm_id); - writel(val, &pwm->tcon); - - pwm_enable(pwm_id); - - return 0; -} diff --git a/src/cpu/samsung/exynos5-common/pwm.h b/src/cpu/samsung/exynos5-common/pwm.h deleted file mode 100644 index d7aa76fd15..0000000000 --- a/src/cpu/samsung/exynos5-common/pwm.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Kyungmin Park - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __ASM_ARM_ARCH_COMMON_PWM_H_ -#define __ASM_ARM_ARCH_COMMON_PWM_H_ - -#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */ -#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ - -/* Divider MUX */ -#define MUX_DIV_1 0 /* 1/1 period */ -#define MUX_DIV_2 1 /* 1/2 period */ -#define MUX_DIV_4 2 /* 1/4 period */ -#define MUX_DIV_8 3 /* 1/8 period */ -#define MUX_DIV_16 4 /* 1/16 period */ - -#define MUX_DIV_SHIFT(x) (x * 4) - -#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2) - -#define TCON_START(x) (1 << TCON_OFFSET(x)) -#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1)) -#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2)) -#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) -#define TCON4_AUTO_RELOAD (1 << 22) - -#ifndef __ASSEMBLER__ -struct s5p_timer { - unsigned int tcfg0; - unsigned int tcfg1; - unsigned int tcon; - unsigned int tcntb0; - unsigned int tcmpb0; - unsigned int tcnto0; - unsigned int tcntb1; - unsigned int tcmpb1; - unsigned int tcnto1; - unsigned int tcntb2; - unsigned int tcmpb2; - unsigned int tcnto2; - unsigned int tcntb3; - unsigned int tcmpb3; - unsigned int tcnto3; - unsigned int tcntb4; - unsigned int tcnto4; - unsigned int tintcstat; -}; - -int pwm_config(int pwm_id, int duty_ns, int period_ns); -int pwm_check_enabled(int pwm_id); -void pwm_disable(int pwm_id); -int pwm_enable(int pwm_id); -int pwm_init(int pwm_id, int div, int invert); -#endif /* __ASSEMBLER__ */ - -#endif diff --git a/src/cpu/samsung/exynos5-common/sromc.c b/src/cpu/samsung/exynos5-common/sromc.c deleted file mode 100644 index 7bc93e7862..0000000000 --- a/src/cpu/samsung/exynos5-common/sromc.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 Samsung Electronics - * Naveen Krishna Ch - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include - -/* - * s5p_config_sromc() - select the proper SROMC Bank and configure the - * band width control and bank control registers - * srom_bank - SROM - * srom_bw_conf - SMC Band witdh reg configuration value - * srom_bc_conf - SMC Bank Control reg configuration value - */ -void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) -{ - u32 tmp; - struct s5p_sromc *srom = - samsung_get_base_sromc(); - - /* Configure SMC_BW register to handle proper SROMC bank */ - tmp = srom->bw; - tmp &= ~(0xF << (srom_bank * 4)); - tmp |= srom_bw_conf; - srom->bw = tmp; - - /* Configure SMC_BC register */ - srom->bc[srom_bank] = srom_bc_conf; -} diff --git a/src/cpu/samsung/exynos5-common/sromc.h b/src/cpu/samsung/exynos5-common/sromc.h deleted file mode 100644 index d4fdae90e6..0000000000 --- a/src/cpu/samsung/exynos5-common/sromc.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * (C) Copyright 2010 Samsung Electronics - * Naveen Krishna Ch - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * Note: This file contains the register description for SROMC - * - */ - -#ifndef __ASM_ARCH_COMMON_SROMC_H_ -#define __ASM_ARCH_COMMON_SROMC_H_ - -#define SROMC_DATA16_WIDTH(x) (1<<((x*4)+0)) -#define SROMC_BYTE_ADDR_MODE(x) (1<<((x*4)+1)) /* 0-> Half-word base address*/ - /* 1-> Byte base address*/ -#define SROMC_WAIT_ENABLE(x) (1<<((x*4)+2)) -#define SROMC_BYTE_ENABLE(x) (1<<((x*4)+3)) - -#define SROMC_BC_TACS(x) (x << 28) /* address set-up */ -#define SROMC_BC_TCOS(x) (x << 24) /* chip selection set-up */ -#define SROMC_BC_TACC(x) (x << 16) /* access cycle */ -#define SROMC_BC_TCOH(x) (x << 12) /* chip selection hold */ -#define SROMC_BC_TAH(x) (x << 8) /* address holding time */ -#define SROMC_BC_TACP(x) (x << 4) /* page mode access cycle */ -#define SROMC_BC_PMC(x) (x << 0) /* normal(1data)page mode configuration */ - -#ifndef __ASSEMBLER__ -struct s5p_sromc { - unsigned int bw; - unsigned int bc[4]; -}; -#endif /* __ASSEMBLER__ */ - -/* Configure the Band Width and Bank Control Regs for required SROMC Bank */ -void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf); - -enum { - FDT_SROM_PMC, - FDT_SROM_TACP, - FDT_SROM_TAH, - FDT_SROM_TCOH, - FDT_SROM_TACC, - FDT_SROM_TCOS, - FDT_SROM_TACS, - - FDT_SROM_TIMING_COUNT, -}; - -struct fdt_sromc { - u8 bank; /* srom bank number */ - u8 width; /* bus width in bytes */ - unsigned int timing[FDT_SROM_TIMING_COUNT]; /* timing parameters */ -}; - -#endif /* __ASM_ARCH_COMMON_SROMC_H_ */ diff --git a/src/cpu/samsung/exynos5-common/timer.c b/src/cpu/samsung/exynos5-common/timer.c deleted file mode 100644 index 6cd5f5dd35..0000000000 --- a/src/cpu/samsung/exynos5-common/timer.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Heungjun Kim - * Inki Dae - * Minkyu Kang - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -//#include - -//DECLARE_GLOBAL_DATA_PTR; -static unsigned long long timer_reset_value; -static unsigned long lastinc; - -/* macro to read the 16 bit timer */ -static inline struct s5p_timer *s5p_get_base_timer(void) -{ - return samsung_get_base_timer(); -} - -/** - * Read the countdown timer. - * - * This operates at 1MHz and counts downwards. It will wrap about every - * hour (2^32 microseconds). - * - * @return current value of timer - */ -static unsigned long timer_get_us_down(void) -{ - struct s5p_timer *const timer = s5p_get_base_timer(); - - return readl(&timer->tcnto4); -} - -int init_timer(void) -{ - /* Timer may have been enabled in SPL */ - if (!pwm_check_enabled(4)) { - /* PWM Timer 4 */ - pwm_init(4, MUX_DIV_4, 0); - pwm_config(4, 100000, 100000); - pwm_enable(4); - - /* Use this as the current monotonic time in us */ - //gd->timer_reset_value = 0; - timer_reset_value = 0; - - /* Use this as the last timer value we saw */ - //gd->lastinc = timer_get_us_down(); - lastinc = timer_get_us_down(); - } - - return 0; -} - -/* - * timer without interrupts - */ -unsigned long get_timer(unsigned long base) -{ - unsigned long now = timer_get_us_down(); - - /* - * Increment the time by the amount elapsed since the last read. - * The timer may have wrapped around, but it makes no difference to - * our arithmetic here. - */ -#if 0 - gd->timer_reset_value += gd->lastinc - now; - gd->lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - return gd->timer_reset_value / 1000 - base; -#endif - timer_reset_value += lastinc - now; - lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - return timer_reset_value / 1000 - base; -} - -unsigned long timer_get_us(void) -{ - struct s5p_timer *const timer = s5p_get_base_timer(); - unsigned long now_downward_us = readl(&timer->tcnto4); - - /* - * Note that this timer counts downward. The pre-SPL process (BL1) - * takes about 100ms, so add this in here. - */ - return CONFIG_SPL_TIME_US - now_downward_us; -} - -/* delay x useconds */ -void __udelay(unsigned long usec) -{ - unsigned long count_value; - - count_value = timer_get_us_down(); - while ((int)(count_value - timer_get_us_down()) < (int)usec) - ; -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -unsigned long get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} - -unsigned long timer_get_boot_us(void) -{ - return timer_get_us(); -} diff --git a/src/cpu/samsung/exynos5-common/uart.h b/src/cpu/samsung/exynos5-common/uart.h deleted file mode 100644 index 350e224b86..0000000000 --- a/src/cpu/samsung/exynos5-common/uart.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang - * Heungjun Kim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef __EXYNOS_COMMON_UART_H_ -#define __EXYNOS_COMMON_UART_H_ - -/* baudrate rest value */ -union br_rest { - unsigned short slot; /* udivslot */ - unsigned char value; /* ufracval */ -}; - -struct s5p_uart { - unsigned int ulcon; - unsigned int ucon; - unsigned int ufcon; - unsigned int umcon; - unsigned int utrstat; - unsigned int uerstat; - unsigned int ufstat; - unsigned int umstat; - unsigned char utxh; - unsigned char res1[3]; - unsigned char urxh; - unsigned char res2[3]; - unsigned int ubrdiv; - union br_rest rest; - unsigned char res3[0xffd0]; -}; - -static inline int s5p_uart_divslot(void) -{ - return 0; -} - -#endif diff --git a/src/cpu/samsung/exynos5-common/watchdog.h b/src/cpu/samsung/exynos5-common/watchdog.h deleted file mode 100644 index 5b3b651ffa..0000000000 --- a/src/cpu/samsung/exynos5-common/watchdog.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * Heungjun Kim - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ -#define __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ - -#define WTCON_RESET_OFFSET 0 -#define WTCON_INTEN_OFFSET 2 -#define WTCON_CLKSEL_OFFSET 3 -#define WTCON_EN_OFFSET 5 -#define WTCON_PRE_OFFSET 8 - -#define WTCON_CLK_16 0x0 -#define WTCON_CLK_32 0x1 -#define WTCON_CLK_64 0x2 -#define WTCON_CLK_128 0x3 - -#define WTCON_CLK(x) ((x & 0x3) << WTCON_CLKSEL_OFFSET) -#define WTCON_PRESCALER(x) ((x) << WTCON_PRE_OFFSET) -#define WTCON_EN (0x1 << WTCON_EN_OFFSET) -#define WTCON_RESET (0x1 << WTCON_RESET_OFFSET) -#define WTCON_INT (0x1 << WTCON_INTEN_OFFSET) - -#ifndef __ASSEMBLER__ -struct s5p_watchdog { - unsigned int wtcon; - unsigned int wtdat; - unsigned int wtcnt; - unsigned int wtclrint; -}; - -/* functions */ -void wdt_stop(void); -void wdt_start(unsigned int timeout); -#endif /* __ASSEMBLER__ */ - -#endif diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig deleted file mode 100644 index ca306b6de8..0000000000 --- a/src/cpu/samsung/exynos5250/Kconfig +++ /dev/null @@ -1,99 +0,0 @@ -config BOOTBLOCK_CPU_INIT - string - default "cpu/samsung/exynos5250/bootblock.c" - help - CPU/SoC-specific bootblock code. This is useful if the - bootblock must load microcode or copy data from ROM before - searching for the bootblock. - -config EXYNOS_ACE_SHA - bool - default n - -config SATA_AHCI - bool - default n - -config BL1_SIZE_KB - int - default 8 - -# Example SRAM/iRAM map for Exynos5250 platform: -# -# 0x0202_0000: vendor-provided BL1 -# 0x0202_3400: bootblock, assume up to 32KB in size -# 0x0203_0000: romstage, assume up to 128KB in size. -# 0x0207_8000: stack pointer - -config BOOTBLOCK_BASE - hex - default 0x02023400 - -config ROMSTAGE_BASE - hex - default 0x02030000 - -config ROMSTAGE_SIZE - hex - default 0x10000 - -# Stack may reside in either IRAM or DRAM. We will define it to live -# at the top of IRAM for now. -# -# Stack grows downward, push operation stores register contents in -# consecutive memory locations ending just below SP -config STACK_TOP - hex - default 0x02078000 - -config STACK_BOTTOM - hex - default 0x02077000 - -config STACK_SIZE - hex - default 0x1000 - -config CBFS_ROM_OFFSET - # Calculated by BL1 + max bootblock size. - hex "offset of CBFS data in ROM" - default 0x0A000 - -# TODO Change this to some better address not overlapping bootblock when -# cbfstool supports creating header in arbitrary location. -config CBFS_HEADER_ROM_OFFSET - hex "offset of master CBFS header in ROM" - default 0x2040 - -# TODO We may probably move this to board-specific implementation files instead -# of KConfig values. -config CBFS_CACHE_ADDRESS - hex "memory address to put CBFS cache data" - default 0x02060000 - -config CBFS_CACHE_SIZE - hex "size of CBFS cache data" - default 0x000017000 - -# FIXME: This is for copying SPI content into SRAM temporarily and -# will be removed when we have the SPI streaming driver implemented. -config SPI_IMAGE_HACK - hex - default 0x02060000 - -# FIXME: other magic numbers that should probably go away -config XIP_ROM_SIZE - hex - default ROMSTAGE_SIZE - -config SYS_SDRAM_BASE - hex - default 0x40000000 - -config SYS_TEXT_BASE - hex - default 0x43e00000 - -config COREBOOT_TABLES_SIZE - hex - default 0x100000 diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc deleted file mode 100644 index 74bc871f36..0000000000 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ /dev/null @@ -1,36 +0,0 @@ -# Run an intermediate step when producing coreboot.rom -# that adds additional components to the final firmware -# image outside of CBFS -#INTERMEDIATE += exynos5250_add_bl1 - -bootblock-y += pinmux.c -# Clock is required for UART -bootblock-$(CONFIG_EARLY_CONSOLE) += clock_init.c -bootblock-$(CONFIG_EARLY_CONSOLE) += clock.c -bootblock-$(CONFIG_EARLY_CONSOLE) += soc.c -bootblock-$(CONFIG_EARLY_CONSOLE) += uart.c - -romstage-y += clock.c -romstage-y += clock_init.c -romstage-y += pinmux.c # required by s3c24x0_i2c (exynos5-common) and uart. -romstage-y += dmc_common.c -romstage-y += dmc_init_ddr3.c -romstage-y += power.c -romstage-$(CONFIG_EARLY_CONSOLE) += soc.c -romstage-$(CONFIG_EARLY_CONSOLE) += uart.c - -#ramstage-y += tzpc_init.c -ramstage-y += clock.c -ramstage-y += clock_init.c -ramstage-y += pinmux.c -ramstage-y += power.c -ramstage-y += soc.c -ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c -ramstage-y += cpu.c - -#ramstage-$(CONFIG_SATA_AHCI) += sata.c - -exynos5250_add_bl1: $(obj)/coreboot.pre - printf " DD Adding Samsung Exynos5250 BL1\n" - dd if=3rdparty/cpu/samsung/exynos5250/E5250.nbl1.bin \ - of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c deleted file mode 100644 index 618fdb6a86..0000000000 --- a/src/cpu/samsung/exynos5250/clock_init.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Clock setup for SMDK5250 board based on EXYNOS5 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include - -/* FIXME: remove unneeded #includes */ -#include -#include -#include -#include -#include -#include - -#include "setup.h" - -void system_clock_init(struct mem_timings *mem, - struct arm_clk_ratios *arm_clk_ratio) -{ - struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; - struct exynos5_mct_regs *mct_regs = - (struct exynos5_mct_regs *)EXYNOS5_MULTI_CORE_TIMER_BASE; - u32 val, tmp; - - /* Turn on the MCT as early as possible. */ - mct_regs->g_tcon |= (1 << 8); - - clrbits_le32(&clk->src_cpu, MUX_APLL_SEL_MASK); - do { - val = readl(&clk->mux_stat_cpu); - } while ((val | MUX_APLL_SEL_MASK) != val); - - clrbits_le32(&clk->src_core1, MUX_MPLL_SEL_MASK); - do { - val = readl(&clk->mux_stat_core1); - } while ((val | MUX_MPLL_SEL_MASK) != val); - - clrbits_le32(&clk->src_top2, MUX_CPLL_SEL_MASK); - clrbits_le32(&clk->src_top2, MUX_EPLL_SEL_MASK); - clrbits_le32(&clk->src_top2, MUX_VPLL_SEL_MASK); - clrbits_le32(&clk->src_top2, MUX_GPLL_SEL_MASK); - tmp = MUX_CPLL_SEL_MASK | MUX_EPLL_SEL_MASK | MUX_VPLL_SEL_MASK - | MUX_GPLL_SEL_MASK; - do { - val = readl(&clk->mux_stat_top2); - } while ((val | tmp) != val); - - clrbits_le32(&clk->src_cdrex, MUX_BPLL_SEL_MASK); - do { - val = readl(&clk->mux_stat_cdrex); - } while ((val | MUX_BPLL_SEL_MASK) != val); - - /* PLL locktime */ - writel(APLL_LOCK_VAL, &clk->apll_lock); - - writel(MPLL_LOCK_VAL, &clk->mpll_lock); - - writel(BPLL_LOCK_VAL, &clk->bpll_lock); - - writel(CPLL_LOCK_VAL, &clk->cpll_lock); - - writel(GPLL_LOCK_VAL, &clk->gpll_lock); - - writel(EPLL_LOCK_VAL, &clk->epll_lock); - - writel(VPLL_LOCK_VAL, &clk->vpll_lock); - - writel(CLK_REG_DISABLE, &clk->pll_div2_sel); - - writel(MUX_HPM_SEL_MASK, &clk->src_cpu); - do { - val = readl(&clk->mux_stat_cpu); - } while ((val | HPM_SEL_SCLK_MPLL) != val); - - val = arm_clk_ratio->arm2_ratio << 28 - | arm_clk_ratio->apll_ratio << 24 - | arm_clk_ratio->pclk_dbg_ratio << 20 - | arm_clk_ratio->atb_ratio << 16 - | arm_clk_ratio->periph_ratio << 12 - | arm_clk_ratio->acp_ratio << 8 - | arm_clk_ratio->cpud_ratio << 4 - | arm_clk_ratio->arm_ratio; - writel(val, &clk->div_cpu0); - do { - val = readl(&clk->div_stat_cpu0); - } while (0 != val); - - writel(CLK_DIV_CPU1_VAL, &clk->div_cpu1); - do { - val = readl(&clk->div_stat_cpu1); - } while (0 != val); - - /* Set APLL */ - writel(APLL_CON1_VAL, &clk->apll_con1); - val = set_pll(arm_clk_ratio->apll_mdiv, arm_clk_ratio->apll_pdiv, - arm_clk_ratio->apll_sdiv); - writel(val, &clk->apll_con0); - while ((readl(&clk->apll_con0) & APLL_CON0_LOCKED) == 0) - ; - - /* Set MPLL */ - writel(MPLL_CON1_VAL, &clk->mpll_con1); - val = set_pll(mem->mpll_mdiv, mem->mpll_pdiv, mem->mpll_sdiv); - writel(val, &clk->mpll_con0); - while ((readl(&clk->mpll_con0) & MPLL_CON0_LOCKED) == 0) - ; - - /* - * Configure MUX_MPLL_FOUT to choose the direct clock source - * path and avoid the fixed DIV/2 block to save power - */ - setbits_le32(&clk->pll_div2_sel, MUX_MPLL_FOUT_SEL); - - /* Set BPLL */ - if (mem->use_bpll) { - writel(BPLL_CON1_VAL, &clk->bpll_con1); - val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); - writel(val, &clk->bpll_con0); - while ((readl(&clk->bpll_con0) & BPLL_CON0_LOCKED) == 0) - ; - - setbits_le32(&clk->pll_div2_sel, MUX_BPLL_FOUT_SEL); - } - - /* Set CPLL */ - writel(CPLL_CON1_VAL, &clk->cpll_con1); - val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); - writel(val, &clk->cpll_con0); - while ((readl(&clk->cpll_con0) & CPLL_CON0_LOCKED) == 0) - ; - - /* Set GPLL */ - writel(GPLL_CON1_VAL, &clk->gpll_con1); - val = set_pll(mem->gpll_mdiv, mem->gpll_pdiv, mem->gpll_sdiv); - writel(val, &clk->gpll_con0); - while ((readl(&clk->gpll_con0) & GPLL_CON0_LOCKED) == 0) - ; - - /* Set EPLL */ - writel(EPLL_CON2_VAL, &clk->epll_con2); - writel(EPLL_CON1_VAL, &clk->epll_con1); - val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); - writel(val, &clk->epll_con0); - while ((readl(&clk->epll_con0) & EPLL_CON0_LOCKED) == 0) - ; - - /* Set VPLL */ - writel(VPLL_CON2_VAL, &clk->vpll_con2); - writel(VPLL_CON1_VAL, &clk->vpll_con1); - val = set_pll(mem->vpll_mdiv, mem->vpll_pdiv, mem->vpll_sdiv); - writel(val, &clk->vpll_con0); - while ((readl(&clk->vpll_con0) & VPLL_CON0_LOCKED) == 0) - ; - - writel(CLK_SRC_CORE0_VAL, &clk->src_core0); - writel(CLK_DIV_CORE0_VAL, &clk->div_core0); - while (readl(&clk->div_stat_core0) != 0) - ; - - writel(CLK_DIV_CORE1_VAL, &clk->div_core1); - while (readl(&clk->div_stat_core1) != 0) - ; - - writel(CLK_DIV_SYSRGT_VAL, &clk->div_sysrgt); - while (readl(&clk->div_stat_sysrgt) != 0) - ; - - writel(CLK_DIV_ACP_VAL, &clk->div_acp); - while (readl(&clk->div_stat_acp) != 0) - ; - - writel(CLK_DIV_SYSLFT_VAL, &clk->div_syslft); - while (readl(&clk->div_stat_syslft) != 0) - ; - - writel(CLK_SRC_TOP0_VAL, &clk->src_top0); - writel(CLK_SRC_TOP1_VAL, &clk->src_top1); - writel(TOP2_VAL, &clk->src_top2); - writel(CLK_SRC_TOP3_VAL, &clk->src_top3); - - writel(CLK_DIV_TOP0_VAL, &clk->div_top0); - while (readl(&clk->div_stat_top0)) - ; - - writel(CLK_DIV_TOP1_VAL, &clk->div_top1); - while (readl(&clk->div_stat_top1)) - ; - - writel(CLK_SRC_LEX_VAL, &clk->src_lex); - while (1) { - val = readl(&clk->mux_stat_lex); - if (val == (val | 1)) - break; - } - - writel(CLK_DIV_LEX_VAL, &clk->div_lex); - while (readl(&clk->div_stat_lex)) - ; - - writel(CLK_DIV_R0X_VAL, &clk->div_r0x); - while (readl(&clk->div_stat_r0x)) - ; - - writel(CLK_DIV_R0X_VAL, &clk->div_r0x); - while (readl(&clk->div_stat_r0x)) - ; - - writel(CLK_DIV_R1X_VAL, &clk->div_r1x); - while (readl(&clk->div_stat_r1x)) - ; - - if (mem->use_bpll) { - writel(MUX_BPLL_SEL_MASK | MUX_MCLK_CDREX_SEL | - MUX_MCLK_DPHY_SEL, &clk->src_cdrex); - } else { - writel(CLK_REG_DISABLE, &clk->src_cdrex); - } - - writel(CLK_DIV_CDREX_VAL, &clk->div_cdrex); - while (readl(&clk->div_stat_cdrex)) - ; - - val = readl(&clk->src_cpu); - val |= CLK_SRC_CPU_VAL; - writel(val, &clk->src_cpu); - - val = readl(&clk->src_top2); - val |= CLK_SRC_TOP2_VAL; - writel(val, &clk->src_top2); - - val = readl(&clk->src_core1); - val |= CLK_SRC_CORE1_VAL; - writel(val, &clk->src_core1); - - writel(CLK_SRC_FSYS0_VAL, &clk->src_fsys); - writel(CLK_DIV_FSYS0_VAL, &clk->div_fsys0); - while (readl(&clk->div_stat_fsys0)) - ; - - writel(CLK_REG_DISABLE, &clk->clkout_cmu_cpu); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_core); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_acp); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_top); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_lex); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_r0x); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_r1x); - writel(CLK_REG_DISABLE, &clk->clkout_cmu_cdrex); - - writel(CLK_SRC_PERIC0_VAL, &clk->src_peric0); - writel(CLK_DIV_PERIC0_VAL, &clk->div_peric0); - - writel(CLK_SRC_PERIC1_VAL, &clk->src_peric1); - writel(CLK_DIV_PERIC1_VAL, &clk->div_peric1); - writel(CLK_DIV_PERIC2_VAL, &clk->div_peric2); - writel(SCLK_SRC_ISP_VAL, &clk->sclk_src_isp); - writel(SCLK_DIV_ISP_VAL, &clk->sclk_div_isp); - writel(CLK_DIV_ISP0_VAL, &clk->div_isp0); - writel(CLK_DIV_ISP1_VAL, &clk->div_isp1); - writel(CLK_DIV_ISP2_VAL, &clk->div_isp2); - - /* FIMD1 SRC CLK SELECTION */ - writel(CLK_SRC_DISP1_0_VAL, &clk->src_disp1_0); - - val = MMC2_PRE_RATIO_VAL << MMC2_PRE_RATIO_OFFSET - | MMC2_RATIO_VAL << MMC2_RATIO_OFFSET - | MMC3_PRE_RATIO_VAL << MMC3_PRE_RATIO_OFFSET - | MMC3_RATIO_VAL << MMC3_RATIO_OFFSET; - writel(val, &clk->div_fsys2); -} - -void clock_gate(void) -{ - struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; - - /* CLK_GATE_IP_SYSRGT */ - clrbits_le32(&clk->gate_ip_sysrgt, CLK_C2C_MASK); - - /* CLK_GATE_IP_ACP */ - clrbits_le32(&clk->gate_ip_acp, CLK_SMMUG2D_MASK | - CLK_SMMUSSS_MASK | - CLK_SMMUMDMA_MASK | - CLK_ID_REMAPPER_MASK | - CLK_G2D_MASK | - CLK_SSS_MASK | - CLK_MDMA_MASK | - CLK_SECJTAG_MASK); - - /* CLK_GATE_BUS_SYSLFT */ - clrbits_le32(&clk->gate_bus_syslft, CLK_EFCLK_MASK); - - /* CLK_GATE_IP_ISP0 */ - clrbits_le32(&clk->gate_ip_isp0, CLK_UART_ISP_MASK | - CLK_WDT_ISP_MASK | - CLK_PWM_ISP_MASK | - CLK_MTCADC_ISP_MASK | - CLK_I2C1_ISP_MASK | - CLK_I2C0_ISP_MASK | - CLK_MPWM_ISP_MASK | - CLK_MCUCTL_ISP_MASK | - CLK_INT_COMB_ISP_MASK | - CLK_SMMU_MCUISP_MASK | - CLK_SMMU_SCALERP_MASK | - CLK_SMMU_SCALERC_MASK | - CLK_SMMU_FD_MASK | - CLK_SMMU_DRC_MASK | - CLK_SMMU_ISP_MASK | - CLK_GICISP_MASK | - CLK_ARM9S_MASK | - CLK_MCUISP_MASK | - CLK_SCALERP_MASK | - CLK_SCALERC_MASK | - CLK_FD_MASK | - CLK_DRC_MASK | - CLK_ISP_MASK); - - /* CLK_GATE_IP_ISP1 */ - clrbits_le32(&clk->gate_ip_isp1, CLK_SPI1_ISP_MASK | - CLK_SPI0_ISP_MASK | - CLK_SMMU3DNR_MASK | - CLK_SMMUDIS1_MASK | - CLK_SMMUDIS0_MASK | - CLK_SMMUODC_MASK | - CLK_3DNR_MASK | - CLK_DIS_MASK | - CLK_ODC_MASK); - - /* CLK_GATE_SCLK_ISP */ - clrbits_le32(&clk->gate_sclk_isp, SCLK_MPWM_ISP_MASK); - - /* CLK_GATE_IP_GSCL */ - clrbits_le32(&clk->gate_ip_gscl, CLK_SMMUFIMC_LITE2_MASK | - CLK_SMMUFIMC_LITE1_MASK | - CLK_SMMUFIMC_LITE0_MASK | - CLK_SMMUGSCL3_MASK | - CLK_SMMUGSCL2_MASK | - CLK_SMMUGSCL1_MASK | - CLK_SMMUGSCL0_MASK | - CLK_GSCL_WRAP_B_MASK | - CLK_GSCL_WRAP_A_MASK | - CLK_CAMIF_TOP_MASK | - CLK_GSCL3_MASK | - CLK_GSCL2_MASK | - CLK_GSCL1_MASK | - CLK_GSCL0_MASK); - - /* CLK_GATE_IP_DISP1 */ - clrbits_le32(&clk->gate_ip_disp1, CLK_SMMUTVX_MASK | - CLK_ASYNCTVX_MASK | - CLK_HDMI_MASK | - CLK_MIXER_MASK | - CLK_DSIM1_MASK); - - /* CLK_GATE_IP_MFC */ - clrbits_le32(&clk->gate_ip_mfc, CLK_SMMUMFCR_MASK | - CLK_SMMUMFCL_MASK | - CLK_MFC_MASK); - - /* CLK_GATE_IP_GEN */ - clrbits_le32(&clk->gate_ip_gen, CLK_SMMUMDMA1_MASK | - CLK_SMMUJPEG_MASK | - CLK_SMMUROTATOR_MASK | - CLK_MDMA1_MASK | - CLK_JPEG_MASK | - CLK_ROTATOR_MASK); - - /* CLK_GATE_IP_FSYS */ - clrbits_le32(&clk->gate_ip_fsys, CLK_WDT_IOP_MASK | - CLK_SMMUMCU_IOP_MASK | - CLK_SATA_PHY_I2C_MASK | - CLK_SATA_PHY_CTRL_MASK | - CLK_MCUCTL_MASK | - CLK_NFCON_MASK | - CLK_SMMURTIC_MASK | - CLK_RTIC_MASK | - CLK_MIPI_HSI_MASK | - CLK_USBOTG_MASK | - CLK_SATA_MASK | - CLK_PDMA1_MASK | - CLK_PDMA0_MASK | - CLK_MCU_IOP_MASK); - - /* CLK_GATE_IP_PERIC */ - clrbits_le32(&clk->gate_ip_peric, CLK_HS_I2C3_MASK | - CLK_HS_I2C2_MASK | - CLK_HS_I2C1_MASK | - CLK_HS_I2C0_MASK | - CLK_AC97_MASK | - CLK_SPDIF_MASK | - CLK_PCM2_MASK | - CLK_PCM1_MASK | - CLK_I2S2_MASK | - CLK_SPI2_MASK | - CLK_SPI0_MASK); - - /* CLK_GATE_IP_PERIS */ - clrbits_le32(&clk->gate_ip_peris, CLK_RTC_MASK | - CLK_TZPC9_MASK | - CLK_TZPC8_MASK | - CLK_TZPC7_MASK | - CLK_TZPC6_MASK | - CLK_TZPC5_MASK | - CLK_TZPC4_MASK | - CLK_TZPC3_MASK | - CLK_TZPC2_MASK | - CLK_TZPC1_MASK | - CLK_TZPC0_MASK | - CLK_CHIPID_MASK); - - /* CLK_GATE_BLOCK */ - clrbits_le32(&clk->gate_block, CLK_ACP_MASK); - - /* CLK_GATE_IP_CDREX */ - clrbits_le32(&clk->gate_ip_cdrex, CLK_DPHY0_MASK | - CLK_DPHY1_MASK | - CLK_TZASC_DRBXR_MASK); - -} - -void clock_init_dp_clock(void) -{ - struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; - - /* DP clock enable */ - setbits_le32(&clk->gate_ip_disp1, CLK_GATE_DP1_ALLOW); - - /* We run DP at 267 Mhz */ - setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); -} - -/* - * This is a custom implementation for the udelay(), as we do not the timer - * initialise during the SPL boot. We are assuming the cpu takes 3 instruction - * pre cycle. This is based on the implementation of sdelay() function. - */ -void udelay(unsigned usec) -{ - unsigned long count; - - /* TODO(alim.akhtar@samsung.com): Comment on why divided by 30000000 */ - count = usec * (get_pll_clk(APLL) / (3 * 10000000)); - sdelay(count); -} diff --git a/src/cpu/samsung/exynos5250/clock_init.h b/src/cpu/samsung/exynos5250/clock_init.h deleted file mode 100644 index bb7f7e9677..0000000000 --- a/src/cpu/samsung/exynos5250/clock_init.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Clock initialization routines - * - * Copyright (c) 2011 The Chromium OS Authors. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __EXYNOS_CLOCK_INIT_H -#define __EXYNOS_CLOCK_INIT_H -#include "dmc.h" - -/* These are the ratio's for configuring ARM clock */ -struct arm_clk_ratios { - unsigned int arm_freq_mhz; /* Frequency of ARM core in MHz */ - - unsigned int apll_mdiv; - unsigned int apll_pdiv; - unsigned int apll_sdiv; - - unsigned int arm2_ratio; - unsigned int apll_ratio; - unsigned int pclk_dbg_ratio; - unsigned int atb_ratio; - unsigned int periph_ratio; - unsigned int acp_ratio; - unsigned int cpud_ratio; - unsigned int arm_ratio; -}; - -/** - * Get the clock ratios for CPU configuration - * - * @return pointer to the clock ratios that we should use - */ -struct arm_clk_ratios *get_arm_clk_ratios(void); - -/* - * Initialize clock for the device - */ -struct mem_timings; -void system_clock_init(struct mem_timings *mem, - struct arm_clk_ratios *arm_clk_ratio); -#endif diff --git a/src/cpu/samsung/exynos5250/cpu.c b/src/cpu/samsung/exynos5250/cpu.c deleted file mode 100644 index 4bb06e8b4a..0000000000 --- a/src/cpu/samsung/exynos5250/cpu.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include - -#define RAM_BASE_KB (CONFIG_SYS_SDRAM_BASE >> 10) -#define RAM_SIZE_KB (CONFIG_DRAM_SIZE_MB << 10UL) - -static void cpu_init(device_t dev) -{ - ram_resource(dev, 0, RAM_BASE_KB, RAM_SIZE_KB); -} - -static void cpu_noop(device_t dev) -{ -} - -static struct device_operations cpu_ops = { - .read_resources = cpu_noop, - .set_resources = cpu_noop, - .enable_resources = cpu_noop, - .init = cpu_init, - .scan_bus = 0, -}; - -static void enable_dev(device_t dev) -{ - /* Set the operations if it is a special bus type */ - if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { - dev->ops = &cpu_ops; - } -} - -struct chip_operations cpu_samsung_exynos5250_ops = { - CHIP_NAME("CPU Samsung Exynos 5250") - .enable_dev = enable_dev, -}; - -void exynos5250_config_l2_cache(void) -{ - uint32_t val; - - /* - * Bit 9 - L2 tag RAM setup (1 cycle) - * Bits 8:6 - L2 tag RAM latency (3 cycles) - * Bit 5 - L2 data RAM setup (1 cycle) - * Bits 2:0 - L2 data RAM latency (3 cycles) - */ - val = (1 << 9) | (0x2 << 6) | (1 << 5) | (0x2); - write_l2ctlr(val); -} diff --git a/src/cpu/samsung/exynos5250/cpu.h b/src/cpu/samsung/exynos5250/cpu.h deleted file mode 100644 index a356e19990..0000000000 --- a/src/cpu/samsung/exynos5250/cpu.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * (C) Copyright 2010 Samsung Electronics - * Minkyu Kang - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef _EXYNOS5250_CPU_H -#define _EXYNOS5250_CPU_H - -#include - -/* EXYNOS5 */ -#define EXYNOS5_GPIO_PART6_BASE 0x03860000 /* Z<6:0> */ -#define EXYNOS5_PRO_ID 0x10000000 -#define EXYNOS5_CLOCK_BASE 0x10010000 -#define EXYNOS5_POWER_BASE 0x10040000 -#define EXYNOS5_SWRESET 0x10040400 -#define EXYNOS5_SYSREG_BASE 0x10050000 -#define EXYNOS5_TZPC1_DECPROT1SET 0x10110810 -#define EXYNOS5_MULTI_CORE_TIMER_BASE 0x101C0000 -#define EXYNOS5_WATCHDOG_BASE 0x101D0000 -#define EXYNOS5_ACE_SFR_BASE 0x10830000 -#define EXYNOS5_DMC_PHY0_BASE 0x10C00000 -#define EXYNOS5_DMC_PHY1_BASE 0x10C10000 -#define EXYNOS5_GPIO_PART4_BASE 0x10D10000 /* V00..V37 */ -#define EXYNOS5_GPIO_PART5_BASE 0x10D100C0 /* V40..V47 */ -#define EXYNOS5_DMC_CTRL_BASE 0x10DD0000 -#define EXYNOS5_GPIO_PART1_BASE 0x11400000 /* A00..Y67 */ -#define EXYNOS5_GPIO_PART2_BASE 0x11400c00 /* X00..X37 */ -#define EXYNOS5_USB_HOST_EHCI_BASE 0x12110000 -#define EXYNOS5_USBPHY_BASE 0x12130000 -#define EXYNOS5_USBOTG_BASE 0x12140000 - -#ifndef CONFIG_OF_CONTROL -#define EXYNOS5_MMC_BASE 0x12200000 -#define EXYNOS5_MSHC_BASE 0x12240000 -#endif - -#define EXYNOS5_SROMC_BASE 0x12250000 -#define EXYNOS5_UART_BASE 0x12C00000 - -#define EXYNOS5_SPI1_BASE 0x12D30000 -#ifndef CONFIG_OF_CONTROL -#define EXYNOS5_I2C_BASE 0x12C60000 -#define EXYNOS5_SPI_BASE 0x12D20000 -#define EXYNOS5_PWMTIMER_BASE 0x12DD0000 -#define EXYNOS5_SPI_ISP_BASE 0x131A0000 -#endif -#define EXYNOS5_I2S_BASE 0x12D60000 -#define EXYNOS5_GPIO_PART3_BASE 0x13400000 /* E00..H17 */ -#define EXYNOS5_FIMD_BASE 0x14400000 -#define EXYNOS5_DISP1_CTRL_BASE 0x14420000 -#define EXYNOS5_MIPI_DSI1_BASE 0x14500000 - -#define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE -#define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE - -/* Compatibility defines */ -#define EXYNOS_POWER_BASE EXYNOS5_POWER_BASE - -/* Marker values stored at the bottom of IRAM stack by SPL */ -#define EXYNOS5_SPL_MARKER 0xb004f1a9 /* hexspeak word: bootflag */ - -/* Distance between each Trust Zone PC register set */ -#define TZPC_BASE_OFFSET 0x10000 - -#define samsung_get_base_adc() ((struct exynos5_adc *)EXYNOS5_ADC_BASE) -#define samsung_get_base_clock() ((struct exynos5_clock *)EXYNOS5_CLOCK_BASE) -#define samsung_get_base_ace_sfr() ((struct exynos5_ace_sfr *)EXYNOS5_ACE_SFR_BASE) -#define samsung_get_base_dsim() ((struct exynos5_dsim *)EXYNOS5_MIPI_DSI1_BASE) -#define samsung_get_base_disp_ctrl() ((struct exynos5_disp_ctrl *)EXYNOS5_DISP1_CTRL_BASE) -#define samsung_get_base_fimd() ((struct exynos5_fimd *)EXYNOS5_FIMD_BASE) -#define samsung_get_base_gpio_part1() ((struct exynos5_gpio_part1 *)EXYNOS5_GPIO_PART1_BASE) -#define samsung_get_base_gpio_part2() ((struct exynos5_gpio_part2 *)EXYNOS5_GPIO_PART2_BASE) -#define samsung_get_base_gpio_part3() ((struct exynos5_gpio_part3 *)EXYNOS5_GPIO_PART3_BASE) -#define samsung_get_base_gpio_part4() ((struct exynos5_gpio_part4 *)EXYNOS5_GPIO_PART4_BASE) -#define samsung_get_base_gpio_part5() ((struct exynos5_gpio_part5 *)EXYNOS5_GPIO_PART5_BASE) -#define samsung_get_base_gpio_part6() ((struct exynos5_gpio_part6 *)EXYNOS5_GPIO_PART6_BASE) -#define samsung_get_base_pro_id() ((struct exynos5_pro_id *)EXYNOS5_PRO_ID) - -#define samsung_get_base_mmc() ((struct exynos5_mmc *)EXYNOS5_MMC_BASE) -#define samsung_get_base_mshci() ((struct exynos5_mshci *)EXYNOS5_MSHC_BASE) - -#define samsung_get_base_modem() ((struct exynos5_modem *)EXYNOS5_MODEM_BASE) -#define samsung_get_base_sromc() ((struct exynos5_sromc *)EXYNOS5_SROMC_BASE) -#define samsung_get_base_swreset() ((struct exynos5_swreset *)EXYNOS5_SWRESET) -#define samsung_get_base_sysreg() ((struct exynos5_sysreg *)EXYNOS5_SYSREG_BASE) -#define samsung_get_base_timer() ((struct s5p_timer *)EXYNOS5_PWMTIMER_BASE) -#define samsung_get_base_uart() ((struct exynos5_uart *)EXYNOS5_UART_BASE) -#define samsung_get_base_usb_phy() ((struct exynos5_usb_phy *)EXYNOS5_USBPHY_BASE) -#define samsung_get_base_usb_otg() ((struct exynos5_usb_otg *)EXYNOS5_USBOTG_BASE) -#define samsung_get_base_watchdog() ((struct exynos5_watchdog *)EXYNOS5_WATCHDOG_BASE) -#define samsung_get_base_power() ((struct exynos5_power *)EXYNOS5_POWER_BASE) -#define samsung_get_base_i2s() ((struct exynos5_i2s *)EXYNOS5_I2S_BASE) -#define samsung_get_base_spi1() ((struct exynos5_spi1 *)EXYNOS5_SPI1_BASE) -#define samsung_get_base_i2c() ((struct exynos5_i2c *)EXYNOS5_I2C_BASE) -#define samsung_get_base_spi() ((struct exynos5_spi *)EXYNOS5_SPI_BASE) -#define samsung_get_base_spi_isp() ((struct exynos5_spi_isp *)EXYNOS5_SPI_ISP_BASE) - -#define EXYNOS5_SPI_NUM_CONTROLLERS 5 -#define EXYNOS_I2C_MAX_CONTROLLERS 8 - -/* helper function to map mmio address to peripheral id */ -enum periph_id exynos5_get_periph_id(unsigned base_addr); - -void exynos5250_config_l2_cache(void); - -#endif /* _EXYNOS5250_CPU_H */ diff --git a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c deleted file mode 100644 index 9a4ead0583..0000000000 --- a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -//#include "clock.h" -/* FIXME(dhendrix): untangle clock/clk ... */ -#include -#include -#include "clk.h" -#include "cpu.h" -#include "dmc.h" -#include "setup.h" -#include "clock_init.h" - -#define RDLVL_COMPLETE_TIMEOUT 10000 - -static void reset_phy_ctrl(void) -{ - struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; - - writel(LPDDR3PHY_CTRL_PHY_RESET_OFF, &clk->lpddr3phy_ctrl); - writel(LPDDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl); - - /* - * For proper memory initialization there should be a minimum delay of - * 500us after the LPDDR3PHY_CTRL_PHY_RESET signal. - * The below value is an approximate value whose calculation in done - * considering that sdelay takes 2 instruction for every 1 delay cycle. - * And assuming each instruction takes 1 clock cycle i.e 1/(1.7 Ghz)sec - * So for 500 usec, the number of delay cycle should be - * (500 * 10^-6) * (1.7 * 10^9) / 2 = 425000 - * - * TODO(hatim.rv@samsung.com): Implement the delay using timer/counter - */ - sdelay(425000); -} - -int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size) -{ - unsigned int val; - struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl; - struct exynos5_dmc *dmc; - int i; - - phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE; - phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE; - dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE; - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: reset phy: "); - reset_phy_ctrl(); - printk(BIOS_SPEW, "done\n"); - - /* Set Impedance Output Driver */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Set Impedance Output Driver\n"); - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: mem->impedance 0x%x\n", - mem->impedance); - val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) | - (mem->impedance << CA_CKE_DRVR_DS_OFFSET) | - (mem->impedance << CA_CS_DRVR_DS_OFFSET) | - (mem->impedance << CA_ADR_DRVR_DS_OFFSET); - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: val 0x%x\n", val); - writel(val, &phy0_ctrl->phy_con39); - writel(val, &phy1_ctrl->phy_con39); - - /* Set Read Latency and Burst Length for PHY0 and PHY1 */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: " - "Set Read Latency and Burst Length for PHY0 and PHY1\n"); - val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | - (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); - writel(val, &phy0_ctrl->phy_con42); - writel(val, &phy1_ctrl->phy_con42); - - /* ZQ Calibration */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: ZQ Calibration\n"); - if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl)) - return SETUP_ERR_ZQ_CALIBRATION_FAILURE; - - /* DQ Signal */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: DQ Signal\n"); - writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14); - writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14); - - writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) - | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), - &dmc->concontrol); - - update_reset_dll(dmc, DDR_MODE_DDR3); - - /* DQS Signal */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: DQS Signal\n"); - writel(mem->phy0_dqs, &phy0_ctrl->phy_con4); - writel(mem->phy1_dqs, &phy1_ctrl->phy_con4); - - writel(mem->phy0_dq, &phy0_ctrl->phy_con6); - writel(mem->phy1_dq, &phy1_ctrl->phy_con6); - - writel(mem->phy0_tFS, &phy0_ctrl->phy_con10); - writel(mem->phy1_tFS, &phy1_ctrl->phy_con10); - - val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) | - (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | - (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | - (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); - writel(val, &phy0_ctrl->phy_con12); - writel(val, &phy1_ctrl->phy_con12); - - /* Start DLL locking */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Start DLL Locking\n"); - writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), - &phy0_ctrl->phy_con12); - writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), - &phy1_ctrl->phy_con12); - - update_reset_dll(dmc, DDR_MODE_DDR3); - - writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), - &dmc->concontrol); - - /* Memory Channel Inteleaving Size */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: " - "Memory Channel Inteleaving Size\n"); - writel(mem->iv_size, &dmc->ivcontrol); - - /* Set DMC MEMCONTROL register */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Set DMC MEMCONTROL register\n"); - val = mem->memcontrol & ~DMC_MEMCONTROL_DSREF_ENABLE; - writel(val, &dmc->memcontrol); - - writel(mem->memconfig, &dmc->memconfig0); - writel(mem->memconfig, &dmc->memconfig1); - writel(mem->membaseconfig0, &dmc->membaseconfig0); - writel(mem->membaseconfig1, &dmc->membaseconfig1); - - /* Precharge Configuration */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Precharge Configuration\n"); - writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, - &dmc->prechconfig); - - /* Power Down mode Configuration */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: " - "Power Down mode Configuraation\n"); - writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT | - mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT, - &dmc->pwrdnconfig); - - /* TimingRow, TimingData, TimingPower and Timingaref - * values as per Memory AC parameters - */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: " - "TimingRow, TimingData, TimingPower and Timingaref\n"); - writel(mem->timing_ref, &dmc->timingref); - writel(mem->timing_row, &dmc->timingrow); - writel(mem->timing_data, &dmc->timingdata); - writel(mem->timing_power, &dmc->timingpower); - - /* Send PALL command */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send PALL Command\n"); - dmc_config_prech(mem, dmc); - - /* Send NOP, MRS and ZQINIT commands */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send NOP, MRS, and ZQINIT\n"); - dmc_config_mrs(mem, dmc); - - if (mem->gate_leveling_enable) { - val = PHY_CON0_RESET_VAL; - val |= P0_CMD_EN; - writel(val, &phy0_ctrl->phy_con0); - writel(val, &phy1_ctrl->phy_con0); - - val = PHY_CON2_RESET_VAL; - val |= INIT_DESKEW_EN; - writel(val, &phy0_ctrl->phy_con2); - writel(val, &phy1_ctrl->phy_con2); - - val = PHY_CON0_RESET_VAL; - val |= P0_CMD_EN; - val |= BYTE_RDLVL_EN; - writel(val, &phy0_ctrl->phy_con0); - writel(val, &phy1_ctrl->phy_con0); - - val = (mem->ctrl_start_point << - PHY_CON12_CTRL_START_POINT_SHIFT) | - (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | - (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | - (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | - (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); - writel(val, &phy0_ctrl->phy_con12); - writel(val, &phy1_ctrl->phy_con12); - - val = PHY_CON2_RESET_VAL; - val |= INIT_DESKEW_EN; - val |= RDLVL_GATE_EN; - writel(val, &phy0_ctrl->phy_con2); - writel(val, &phy1_ctrl->phy_con2); - - val = PHY_CON0_RESET_VAL; - val |= P0_CMD_EN; - val |= BYTE_RDLVL_EN; - val |= CTRL_SHGATE; - writel(val, &phy0_ctrl->phy_con0); - writel(val, &phy1_ctrl->phy_con0); - - val = PHY_CON1_RESET_VAL; - val &= ~(CTRL_GATEDURADJ_MASK); - writel(val, &phy0_ctrl->phy_con1); - writel(val, &phy1_ctrl->phy_con1); - - writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config); - i = RDLVL_COMPLETE_TIMEOUT; - while ((readl(&dmc->phystatus) & - (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != - (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { - /* - * TODO(waihong): Comment on how long this take to - * timeout - */ - sdelay(100); - i--; - } - if (!i){ - printk(BIOS_SPEW, "Timeout on RDLVL. No DRAM.\n"); - return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; - } - writel(CTRL_RDLVL_GATE_DISABLE, &dmc->rdlvl_config); - - writel(0, &phy0_ctrl->phy_con14); - writel(0, &phy1_ctrl->phy_con14); - - val = (mem->ctrl_start_point << - PHY_CON12_CTRL_START_POINT_SHIFT) | - (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | - (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | - (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | - (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | - (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); - writel(val, &phy0_ctrl->phy_con12); - writel(val, &phy1_ctrl->phy_con12); - - update_reset_dll(dmc, DDR_MODE_DDR3); - } - - /* Send PALL command */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send PALL Command\n"); - dmc_config_prech(mem, dmc); - - writel(mem->memcontrol, &dmc->memcontrol); - - /* Set DMC Concontrol and enable auto-refresh counter */ - printk(BIOS_SPEW, "ddr3_mem_ctrl_init: " - "Set DMC Concontrol and enable auto-refresh counter\n"); - writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) - | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol); - return 0; -} diff --git a/src/cpu/samsung/exynos5250/exynos-cpufreq.h b/src/cpu/samsung/exynos5250/exynos-cpufreq.h deleted file mode 100644 index 1c28e77ea4..0000000000 --- a/src/cpu/samsung/exynos5250/exynos-cpufreq.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS - CPU frequency scaling support - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Define various levels of ARM frequency */ -enum cpufreq_level { - CPU_FREQ_L200, /* 200 MHz */ - CPU_FREQ_L300, /* 300 MHz */ - CPU_FREQ_L400, /* 400 MHz */ - CPU_FREQ_L500, /* 500 MHz */ - CPU_FREQ_L600, /* 600 MHz */ - CPU_FREQ_L700, /* 700 MHz */ - CPU_FREQ_L800, /* 800 MHz */ - CPU_FREQ_L900, /* 900 MHz */ - CPU_FREQ_L1000, /* 1000 MHz */ - CPU_FREQ_L1100, /* 1100 MHz */ - CPU_FREQ_L1200, /* 1200 MHz */ - CPU_FREQ_L1300, /* 1300 MHz */ - CPU_FREQ_L1400, /* 1400 MHz */ - CPU_FREQ_L1500, /* 1500 MHz */ - CPU_FREQ_L1600, /* 1600 MHz */ - CPU_FREQ_L1700, /* 1700 MHz */ - CPU_FREQ_LCOUNT, -}; - -/* - * Initialize ARM frequency scaling - * - * @param blob FDT blob - * @return int value, 0 for success - */ -int exynos5250_cpufreq_init(const void *blob); - -/* - * Switch ARM frequency to new level - * - * @param new_freq_level enum cpufreq_level, states new frequency - * @return int value, 0 for success - */ -int exynos5250_set_frequency(enum cpufreq_level new_freq_level); diff --git a/src/cpu/samsung/exynos5250/exynos-tmu.h b/src/cpu/samsung/exynos5250/exynos-tmu.h deleted file mode 100644 index ad9e394456..0000000000 --- a/src/cpu/samsung/exynos5250/exynos-tmu.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * Akshay Saraswat - * - * EXYNOS - Thermal Management Unit - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __ASM_ARCH_THERMAL_H -#define __ASM_ARCH_THERMAL_H - -struct tmu_reg { - unsigned triminfo; - unsigned rsvd1; - unsigned rsvd2; - unsigned rsvd3; - unsigned rsvd4; - unsigned triminfo_control; - unsigned rsvd5; - unsigned rsvd6; - unsigned tmu_control; - unsigned rsvd7; - unsigned tmu_status; - unsigned sampling_internal; - unsigned counter_value0; - unsigned counter_value1; - unsigned rsvd8; - unsigned rsvd9; - unsigned current_temp; - unsigned rsvd10; - unsigned rsvd11; - unsigned rsvd12; - unsigned threshold_temp_rise; - unsigned threshold_temp_fall; - unsigned rsvd13; - unsigned rsvd14; - unsigned past_temp3_0; - unsigned past_temp7_4; - unsigned past_temp11_8; - unsigned past_temp15_12; - unsigned inten; - unsigned intstat; - unsigned intclear; - unsigned rsvd15; - unsigned emul_con; -}; - -enum tmu_status_t { - TMU_STATUS_INIT = 0, - TMU_STATUS_NORMAL, - TMU_STATUS_WARNING, - TMU_STATUS_TRIPPED, -}; - -/* - * Monitors status of the TMU device and exynos temperature - * - * @param temp pointer to the current temperature value - * @return enum tmu_status_t value, code indicating event to execute - * and -1 on error - */ -enum tmu_status_t tmu_monitor(int *temp); - -/* - * Initialize TMU device - * - * @param blob FDT blob - * @return int value, 0 for success - */ -int tmu_init(const void *blob); -#endif diff --git a/src/cpu/samsung/exynos5250/fet.h b/src/cpu/samsung/exynos5250/fet.h deleted file mode 100644 index e76bcbfc7c..0000000000 --- a/src/cpu/samsung/exynos5250/fet.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - */ - -#ifndef __ASM_ARM_ARCH_EXYNOS5_FET_H -#define __ASM_ARM_ARCH_EXYNOS5_FET_H - -/* The FET IDs for TPS65090 PMU chip. */ -enum { - FET_ID_BL = 1 - FET_ID_VIDEO, - FET_ID_WWAN, - FET_ID_SDCARD, - FET_ID_CAMOUT, - FET_ID_LCD, - FET_ID_TS -}; - -#endif diff --git a/src/cpu/samsung/exynos5250/lowlevel_init_c.c b/src/cpu/samsung/exynos5250/lowlevel_init_c.c deleted file mode 100644 index daa691f19e..0000000000 --- a/src/cpu/samsung/exynos5250/lowlevel_init_c.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Lowlevel setup for SMDK5250 board based on S5PC520 - * - * Copyright (C) 2012 Samsung Electronics - * Copyright (c) 2012 The Chromium OS Authors. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* - * FIXME: This file is essentially the "bootblock" leftover from U-Boot. For - * now it serves as a reference until all the resume-related stuff is added - * to the appropriate bootblock/romstage/ramstage files in coreboot. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "setup.h" - -#include - -void do_barriers(void); /* FIXME: make gcc shut up about "no previous prototype" */ - -void do_barriers(void) -{ - /* - * The reason we don't write out the instructions dsb/isb/sev: - * While ARM Cortex-A8 supports ARM v7 instruction set (-march=armv7a), - * we compile with -march=armv5 to allow more compilers to work. - * For U-Boot code this has no performance impact. - */ - __asm__ __volatile__( -#if defined(__thumb__) - ".hword 0xF3BF, 0x8F4F\n" /* dsb; darn -march=armv5 */ - ".hword 0xF3BF, 0x8F6F\n" /* isb; darn -march=armv5 */ - ".hword 0xBF40\n" /* sev; darn -march=armv5 */ -#else - ".word 0xF57FF04F\n" /* dsb; darn -march=armv5 */ - ".word 0xF57FF06F\n" /* isb; darn -march=armv5 */ - ".word 0xE320F004\n" /* sev; darn -march=armv5 */ -#endif - ); -} - -/* These are the things we can do during low-level init */ -enum { - DO_WAKEUP = 1 << 0, - DO_UART = 1 << 1, - DO_CLOCKS = 1 << 2, - DO_POWER = 1 << 3, -}; - -int lowlevel_init_subsystems(void) -{ -// uint32_t reset_status; - int actions = 0; - -// do_barriers(); - - /* Setup cpu info which is needed to select correct register offsets */ - cpu_info_init(); - -#if 0 - reset_status = power_read_reset_status(); - - switch (reset_status) { - case S5P_CHECK_SLEEP: - actions = DO_CLOCKS | DO_WAKEUP; - break; - case S5P_CHECK_DIDLE: - case S5P_CHECK_LPA: - actions = DO_WAKEUP; - default: - /* This is a normal boot (not a wake from sleep) */ - actions = DO_UART | DO_CLOCKS | DO_POWER; - } -#endif - - actions = DO_UART | DO_CLOCKS | DO_POWER; - if (actions & DO_POWER) - power_init(); - if (actions & DO_CLOCKS) - system_clock_init(); - if (actions & DO_UART) { - - /* Set up serial UART so we can printf() */ - /* FIXME(dhendrix): add a function for mapping - CONFIG_CONSOLE_SERIAL_UART_ADDRESS to PERIPH_ID_UARTn */ -// exynos_pinmux_config(EXYNOS_UART, PINMUX_FLAG_NONE); - exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); - - console_init(); - while (1) { - console_tx_byte('C'); - } - } - init_timer(); /* FIXME(dhendrix): was timer_init() */ - -#if 0 - if (actions & DO_CLOCKS) { - mem_ctrl_init(); - tzpc_init(); - } -#endif - -// return actions & DO_WAKEUP; - return 0; -} diff --git a/src/cpu/samsung/exynos5250/pinmux.c b/src/cpu/samsung/exynos5250/pinmux.c deleted file mode 100644 index becced24d5..0000000000 --- a/src/cpu/samsung/exynos5250/pinmux.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics. - * Abhilash Kesavan - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -int exynos_pinmux_config(enum periph_id peripheral, int flags) -{ - int i, start, count, start_ext, pin_ext, pin, drv; - - switch (peripheral) { - case PERIPH_ID_UART0: - case PERIPH_ID_UART1: - case PERIPH_ID_UART2: - case PERIPH_ID_UART3: - switch (peripheral) { - default: - case PERIPH_ID_UART0: - start = GPIO_A00; count = 4; - break; - case PERIPH_ID_UART1: - start = GPIO_A04; count = 4; - break; - case PERIPH_ID_UART2: - start = GPIO_A10; count = 4; - break; - case PERIPH_ID_UART3: - start = GPIO_A14; count = 2; - break; - } - for (i = start; i < start + count; i++) { - gpio_set_pull(i, EXYNOS_GPIO_PULL_NONE); - gpio_cfg_pin(i, EXYNOS_GPIO_FUNC(0x2)); - } - break; - case PERIPH_ID_SDMMC0: - case PERIPH_ID_SDMMC1: - case PERIPH_ID_SDMMC2: - case PERIPH_ID_SDMMC3: - pin = EXYNOS_GPIO_FUNC(0x2); - pin_ext = EXYNOS_GPIO_FUNC(0x2); - drv = EXYNOS_GPIO_DRV_4X; - switch (peripheral) { - default: - case PERIPH_ID_SDMMC0: - start = GPIO_C00; - start_ext = GPIO_C10; - break; - case PERIPH_ID_SDMMC1: - start = GPIO_C20; - start_ext = 0; - break; - case PERIPH_ID_SDMMC2: - start = GPIO_C30; - /* - * TODO: (alim.akhtar@samsung.com) - * add support for 8 bit mode (needs to be a per-board - * option, so in the FDT). - */ - start_ext = 0; - break; - case PERIPH_ID_SDMMC3: - /* - * TODO: Need to add defintions for GPC4 before - * enabling this. - */ - debug("SDMMC3 not supported yet"); - return -1; - } - if ((flags & PINMUX_FLAG_8BIT_MODE) && !start_ext) { - debug("SDMMC device %d does not support 8bit mode", - peripheral); - return -1; - } - if (flags & PINMUX_FLAG_8BIT_MODE) { - assert(peripheral == PERIPH_ID_SDMMC0); - for (i = 0; i <= 3; i++) { - gpio_cfg_pin(start_ext + i, pin_ext); - gpio_set_pull(start_ext + i, - EXYNOS_GPIO_PULL_UP); - gpio_set_drv(start_ext + i, drv); - } - } - for (i = 0; i < 2; i++) { - gpio_cfg_pin(start + i, pin); - gpio_set_pull(start + i, EXYNOS_GPIO_PULL_NONE); - gpio_set_drv(start + i, drv); - } - for (i = 2; i <= 6; i++) { - gpio_cfg_pin(start + i, pin); - gpio_set_pull(start + i, EXYNOS_GPIO_PULL_UP); - gpio_set_drv(start + i, drv); - } - break; - case PERIPH_ID_SROMC: - /* - * SROM:CS1 and EBI - * - * GPY0[0] SROM_CSn[0] - * GPY0[1] SROM_CSn[1](2) - * GPY0[2] SROM_CSn[2] - * GPY0[3] SROM_CSn[3] - * GPY0[4] EBI_OEn(2) - * GPY0[5] EBI_EEn(2) - * - * GPY1[0] EBI_BEn[0](2) - * GPY1[1] EBI_BEn[1](2) - * GPY1[2] SROM_WAIT(2) - * GPY1[3] EBI_DATA_RDn(2) - */ - gpio_cfg_pin(GPIO_Y00 + (flags & PINMUX_FLAG_BANK), - EXYNOS_GPIO_FUNC(2)); - gpio_cfg_pin(GPIO_Y04, EXYNOS_GPIO_FUNC(2)); - gpio_cfg_pin(GPIO_Y05, EXYNOS_GPIO_FUNC(2)); - - for (i = 2; i < 4; i++) - gpio_cfg_pin(GPIO_Y10 + i, EXYNOS_GPIO_FUNC(2)); - - /* - * EBI: 8 Addrss Lines - * - * GPY3[0] EBI_ADDR[0](2) - * GPY3[1] EBI_ADDR[1](2) - * GPY3[2] EBI_ADDR[2](2) - * GPY3[3] EBI_ADDR[3](2) - * GPY3[4] EBI_ADDR[4](2) - * GPY3[5] EBI_ADDR[5](2) - * GPY3[6] EBI_ADDR[6](2) - * GPY3[7] EBI_ADDR[7](2) - * - * EBI: 16 Data Lines - * - * GPY5[0] EBI_DATA[0](2) - * GPY5[1] EBI_DATA[1](2) - * GPY5[2] EBI_DATA[2](2) - * GPY5[3] EBI_DATA[3](2) - * GPY5[4] EBI_DATA[4](2) - * GPY5[5] EBI_DATA[5](2) - * GPY5[6] EBI_DATA[6](2) - * GPY5[7] EBI_DATA[7](2) - * - * GPY6[0] EBI_DATA[8](2) - * GPY6[1] EBI_DATA[9](2) - * GPY6[2] EBI_DATA[10](2) - * GPY6[3] EBI_DATA[11](2) - * GPY6[4] EBI_DATA[12](2) - * GPY6[5] EBI_DATA[13](2) - * GPY6[6] EBI_DATA[14](2) - * GPY6[7] EBI_DATA[15](2) - */ - for (i = 0; i < 8; i++) { - gpio_cfg_pin(GPIO_Y30 + i, EXYNOS_GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y30 + i, EXYNOS_GPIO_PULL_UP); - - gpio_cfg_pin(GPIO_Y50 + i, EXYNOS_GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y50 + i, EXYNOS_GPIO_PULL_UP); - - if (flags & PINMUX_FLAG_16BIT) { - gpio_cfg_pin(GPIO_Y60 + i, EXYNOS_GPIO_FUNC(2)); - gpio_set_pull(GPIO_Y60 + i, - EXYNOS_GPIO_PULL_UP); - } - } - break; - case PERIPH_ID_SPI0: - case PERIPH_ID_SPI1: - case PERIPH_ID_SPI2: - case PERIPH_ID_SPI3: { - int cfg; - - switch (peripheral) { - default: - case PERIPH_ID_SPI0: - start = GPIO_A20; - cfg = 0x2; - break; - case PERIPH_ID_SPI1: - start = GPIO_A24; - cfg = 0x2; - break; - case PERIPH_ID_SPI2: - start = GPIO_B11; - cfg = 0x5; - break; - case PERIPH_ID_SPI3: - start = GPIO_E00; - cfg = 0x2; - break; - } - - for (i = 0; i < 4; i++) - gpio_cfg_pin(start + i, EXYNOS_GPIO_FUNC(cfg)); - break; - } - case PERIPH_ID_SPI4: - for (i = 0; i < 2; i++) - gpio_cfg_pin(GPIO_F02 + i, EXYNOS_GPIO_FUNC(0x4)); - for (i = 2; i < 4; i++) - gpio_cfg_pin(GPIO_E02 + i, EXYNOS_GPIO_FUNC(0x4)); - break; - case PERIPH_ID_BACKLIGHT: - gpio_cfg_pin(GPIO_B20, EXYNOS_GPIO_OUTPUT); - gpio_set_value(GPIO_B20, 1); - break; - case PERIPH_ID_LCD: - gpio_cfg_pin(GPIO_Y25, EXYNOS_GPIO_OUTPUT); - gpio_set_value(GPIO_Y25, 1); - gpio_cfg_pin(GPIO_X15, EXYNOS_GPIO_OUTPUT); - gpio_set_value(GPIO_X15, 1); - gpio_cfg_pin(GPIO_X30, EXYNOS_GPIO_OUTPUT); - gpio_set_value(GPIO_X30, 1); - break; - case PERIPH_ID_I2C0: - gpio_cfg_pin(GPIO_B30, EXYNOS_GPIO_FUNC(0x2)); - gpio_cfg_pin(GPIO_B31, EXYNOS_GPIO_FUNC(0x2)); - gpio_set_pull(GPIO_B30, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_B31, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C1: - gpio_cfg_pin(GPIO_B32, EXYNOS_GPIO_FUNC(0x2)); - gpio_cfg_pin(GPIO_B33, EXYNOS_GPIO_FUNC(0x2)); - gpio_set_pull(GPIO_B32, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_B33, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C2: - gpio_cfg_pin(GPIO_A06, EXYNOS_GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A07, EXYNOS_GPIO_FUNC(0x3)); - gpio_set_pull(GPIO_A06, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_A07, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C3: - gpio_cfg_pin(GPIO_A12, EXYNOS_GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A13, EXYNOS_GPIO_FUNC(0x3)); - gpio_set_pull(GPIO_A12, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_A13, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C4: - gpio_cfg_pin(GPIO_A20, EXYNOS_GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A21, EXYNOS_GPIO_FUNC(0x3)); - gpio_set_pull(GPIO_A20, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_A21, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C5: - gpio_cfg_pin(GPIO_A22, EXYNOS_GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_A23, EXYNOS_GPIO_FUNC(0x3)); - gpio_set_pull(GPIO_A22, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_A23, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2C6: - gpio_cfg_pin(GPIO_B13, EXYNOS_GPIO_FUNC(0x4)); - gpio_cfg_pin(GPIO_B14, EXYNOS_GPIO_FUNC(0x4)); - break; - case PERIPH_ID_I2C7: - gpio_cfg_pin(GPIO_B22, EXYNOS_GPIO_FUNC(0x3)); - gpio_cfg_pin(GPIO_B23, EXYNOS_GPIO_FUNC(0x3)); - gpio_set_pull(GPIO_B22, EXYNOS_GPIO_PULL_NONE); - gpio_set_pull(GPIO_B23, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_DPHPD: - /* Set Hotplug detect for DP */ - gpio_cfg_pin(GPIO_X07, EXYNOS_GPIO_FUNC(0x3)); - - /* - * Hotplug detect should have an external pullup; disable the - * internal pulldown so they don't fight. - */ - gpio_set_pull(GPIO_X07, EXYNOS_GPIO_PULL_NONE); - break; - case PERIPH_ID_I2S1: - for (i = 0; i < 5; i++) - gpio_cfg_pin(GPIO_B00 + i, EXYNOS_GPIO_FUNC(0x02)); - break; - default: - debug("%s: invalid peripheral %d", __func__, peripheral); - return -1; - } - - return 0; -} diff --git a/src/cpu/samsung/exynos5250/pinmux.h b/src/cpu/samsung/exynos5250/pinmux.h deleted file mode 100644 index 81c00870a6..0000000000 --- a/src/cpu/samsung/exynos5250/pinmux.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef __EXYNOS_PINMUX_H -#define __EXYNOS_PINMUX_H - -//#include -#include "periph.h" - -enum { - PINMUX_FLAG_NONE = 0x00000000, - - /* Flags for eMMC */ - PINMUX_FLAG_8BIT_MODE = 1 << 0, /* SDMMC 8-bit mode */ - - /* - * Flags for SPI. - */ - PINMUX_FLAG_SLAVE_MODE = 1 << 0, /* Slave mode */ - - /* Flags for SROM controller */ - PINMUX_FLAG_BANK = 3 << 0, /* bank number (0-3) */ - PINMUX_FLAG_16BIT = 1 << 2, /* 16-bit width */ -}; - -/** - * Configures the pinmux for a particular peripheral. - * - * Each gpio can be configured in many different ways (4 bits on exynos) - * such as "input", "output", "special function", "external interrupt" - * etc. This function will configure the peripheral pinmux along with - * pull-up/down and drive strength. - * - * @param peripheral peripheral to be configured - * @param flags configure flags - * @return 0 if ok, -1 on error (e.g. unsupported peripheral) - */ -int exynos_pinmux_config(enum periph_id peripheral, int flags); - -#endif diff --git a/src/cpu/samsung/exynos5250/power.c b/src/cpu/samsung/exynos5250/power.c deleted file mode 100644 index ffba8c5f37..0000000000 --- a/src/cpu/samsung/exynos5250/power.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Power setup code for EXYNOS5 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static void ps_hold_setup(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - /* Set PS-Hold high */ - setbits_le32(&power->ps_hold_ctrl, POWER_PS_HOLD_CONTROL_DATA_HIGH); -} - -void power_reset(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - /* Clear inform1 so there's no change we think we've got a wake reset */ - power->inform1 = 0; - - setbits_le32(&power->sw_reset, 1); -} - -/* This function never returns */ -void power_shutdown(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - clrbits_le32(&power->ps_hold_ctrl, POWER_PS_HOLD_CONTROL_DATA_HIGH); - - hlt(); -} - -void power_enable_dp_phy(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - setbits_le32(&power->dptx_phy_control, DPTX_PHY_ENABLE); -} - -void power_enable_usb_phy(void) -{ - struct exynos5_sysreg *sysreg = - samsung_get_base_sysreg(); - struct exynos5_power *power = - samsung_get_base_power(); - unsigned int phy_cfg; - - /* Setting USB20PHY_CONFIG register to USB 2.0 HOST link */ - phy_cfg = readl(&sysreg->usb20_phy_cfg); - if (phy_cfg & USB20_PHY_CFG_EN) { - debug("USB 2.0 HOST link already selected\n"); - } else { - phy_cfg |= USB20_PHY_CFG_EN; - writel(phy_cfg, &sysreg->usb20_phy_cfg); - } - - /* Enabling USBHOST_PHY */ - setbits_le32(&power->usb_host_phy_ctrl, POWER_USB_HOST_PHY_CTRL_EN); -} - -void power_disable_usb_phy(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - /* Disabling USBHost_PHY */ - clrbits_le32(&power->usb_host_phy_ctrl, POWER_USB_HOST_PHY_CTRL_EN); -} - -void power_enable_hw_thermal_trip(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - /* Enable HW thermal trip */ - setbits_le32(&power->ps_hold_ctrl, POWER_ENABLE_HW_TRIP); -} - -uint32_t power_read_reset_status(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - return power->inform1; -} - -void power_exit_wakeup(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - typedef void (*resume_func)(void); - - ((resume_func)power->inform0)(); -} - -int power_init(void) -{ - ps_hold_setup(); - return 0; -} - -void power_enable_xclkout(void) -{ - struct exynos5_power *power = - samsung_get_base_power(); - - /* use xxti for xclk out */ - clrsetbits_le32(&power->pmu_debug, PMU_DEBUG_CLKOUT_SEL_MASK, - PMU_DEBUG_XXTI); -} diff --git a/src/cpu/samsung/exynos5250/sata.c b/src/cpu/samsung/exynos5250/sata.c deleted file mode 100644 index d32c612ed5..0000000000 --- a/src/cpu/samsung/exynos5250/sata.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium OS Authors. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SATA_AHCI_AXI 0x122f0000 -#define SATA_PHCTRL_APB 0x12170000 -#define SATA_PHY_I2C_ABP 0x121d0000 -#define EXYNOS5_SATA_PHY_CONTROL (0x10040000 + 0x724) -#define S5P_PMU_SATA_PHY_CONTROL_EN 0x1 - -void * const phy_ctrl = (void *)SATA_PHCTRL_APB; -void * const phy_i2c_base = (void *)SATA_PHY_I2C_ABP; - -typedef unsigned char bool; -#define true 1 -#define false 0 - - -#define SATA_TIME_LIMIT 10000 -#define SATA_PHY_I2C_SLAVE_ADDRS 0x70 - -#define SATA_RESET 0x4 -#define RESET_CMN_RST_N (1 << 1) -#define LINK_RESET 0xF0000 - -#define SATA_MODE0 0x10 - -#define SATA_CTRL0 0x14 -#define CTRL0_P0_PHY_CALIBRATED_SEL (1 << 9) -#define CTRL0_P0_PHY_CALIBRATED (1 << 8) - -#define SATA_PHSATA_CTRLM 0xE0 -#define PHCTRLM_REF_RATE (1 << 1) -#define PHCTRLM_HIGH_SPEED (1 << 0) - -#define SATA_PHSATA_STATM 0xF0 -#define PHSTATM_PLL_LOCKED (1 << 0) - - -/********************** I2C**************/ -#define SATA_I2C_CON 0x00 -#define SATA_I2C_STAT 0x04 -#define SATA_I2C_ADDR 0x08 -#define SATA_I2C_DS 0x0C -#define SATA_I2C_LC 0x10 - -/* I2CCON reg */ -#define CON_ACKEN (1 << 7) -#define CON_CLK512 (1 << 6) -#define CON_CLK16 (~CON_CLK512) -#define CON_INTEN (1 << 5) -#define CON_INTPND (1 << 4) -#define CON_TXCLK_PS (0xF) - -/* I2CSTAT reg */ -#define STAT_MSTT (0x3 << 6) -#define STAT_BSYST (1 << 5) -#define STAT_RTEN (1 << 4) -#define STAT_LAST (1 << 0) - -#define LC_FLTR_EN (1 << 2) - -#define SATA_PHY_CON_RESET 0xF003F - -#define SCLK_SATA_FREQ (66 * MHZ) - - - -enum { - SATA_GENERATION1, - SATA_GENERATION2, - SATA_GENERATION3, -}; - -static bool sata_is_reg(void __iomem *base, u32 reg, u32 checkbit, u32 Status) -{ - if ((__raw_readl(base + reg) & checkbit) == Status) - return true; - else - return false; -} - -static bool wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit, - u32 Status) -{ - u32 time_limit_cnt = 0; - while (!sata_is_reg(base, reg, checkbit, Status)) { - if (time_limit_cnt == SATA_TIME_LIMIT) { - return false; - } - udelay(1000); - time_limit_cnt++; - } - return true; -} - - -static void sata_set_gen(u8 gen) -{ - __raw_writel(gen, phy_ctrl + SATA_MODE0); -} - -/* Address :I2C Address */ -static void sata_i2c_write_addrs(u8 data) -{ - __raw_writeb((data & 0xFE), phy_i2c_base + SATA_I2C_DS); -} - -static void sata_i2c_write_data(u8 data) -{ - __raw_writeb((data), phy_i2c_base + SATA_I2C_DS); -} - -static void sata_i2c_start(void) -{ - u32 val; - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val |= STAT_BSYST; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); -} - -static void sata_i2c_stop(void) -{ - u32 val; - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val &= ~STAT_BSYST; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); -} - -static bool sata_i2c_get_int_status(void) -{ - if ((__raw_readl(phy_i2c_base + SATA_I2C_CON)) & CON_INTPND) - return true; - else - return false; -} - -static bool sata_i2c_is_tx_ack(void) -{ - if ((__raw_readl(phy_i2c_base + SATA_I2C_STAT)) & STAT_LAST) - return false; - else - return true; -} - -static bool sata_i2c_is_bus_ready(void) -{ - if ((__raw_readl(phy_i2c_base + SATA_I2C_STAT)) & STAT_BSYST) - return false; - else - return true; -} - -static bool sata_i2c_wait_for_busready(u32 time_out) -{ - while (--time_out) { - if (sata_i2c_is_bus_ready()) - return true; - udelay(100); - } - return false; -} - -static bool sata_i2c_wait_for_tx_ack(u32 time_out) -{ - while (--time_out) { - if (sata_i2c_get_int_status()) { - if (sata_i2c_is_tx_ack()) - return true; - } - udelay(100); - } - return false; -} - -static void sata_i2c_clear_int_status(void) -{ - u32 val; - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val &= ~CON_INTPND; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); -} - - -static void sata_i2c_set_ack_gen(bool enable) -{ - u32 val; - if (enable) { - val = (__raw_readl(phy_i2c_base + SATA_I2C_CON)) | CON_ACKEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - } else { - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val &= ~CON_ACKEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - } - -} - -static void sata_i2c_set_master_tx(void) -{ - u32 val; - /* Disable I2C */ - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val &= ~STAT_RTEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); - /* Clear Mode */ - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val &= ~STAT_MSTT; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); - - sata_i2c_clear_int_status(); - /* interrupt disable */ - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val &= ~CON_INTEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - - /* Master, Send mode */ - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val |= STAT_MSTT; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); - - /* interrupt enable */ - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val |= CON_INTEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - - /* Enable I2C */ - val = __raw_readl(phy_i2c_base + SATA_I2C_STAT); - val |= STAT_RTEN; - __raw_writel(val, phy_i2c_base + SATA_I2C_STAT); -} - -static void sata_i2c_init(void) -{ - u32 val; - - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val &= CON_CLK16; - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val &= ~(CON_TXCLK_PS); - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - - val = __raw_readl(phy_i2c_base + SATA_I2C_CON); - val |= (2 & CON_TXCLK_PS); - __raw_writel(val, phy_i2c_base + SATA_I2C_CON); - - val = __raw_readl(phy_i2c_base + SATA_I2C_LC); - val &= ~(LC_FLTR_EN); - __raw_writel(val, phy_i2c_base + SATA_I2C_LC); - - sata_i2c_set_ack_gen(false); -} -static bool sata_i2c_send(u8 slave_addrs, u8 addrs, u8 ucData) -{ - s32 ret = 0; - if (!sata_i2c_wait_for_busready(SATA_TIME_LIMIT)) - return false; - - sata_i2c_init(); - sata_i2c_set_master_tx(); - - __raw_writel(SATA_PHY_CON_RESET, phy_ctrl + SATA_RESET); - sata_i2c_write_addrs(slave_addrs); - sata_i2c_start(); - if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT)) { - ret = false; - goto STOP; - } - sata_i2c_write_data(addrs); - sata_i2c_clear_int_status(); - if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT)) { - ret = false; - goto STOP; - } - sata_i2c_write_data(ucData); - sata_i2c_clear_int_status(); - if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT)) { - ret = false; - goto STOP; - } - ret = true; - -STOP: - sata_i2c_stop(); - sata_i2c_clear_int_status(); - sata_i2c_wait_for_busready(SATA_TIME_LIMIT); - - return ret; -} - -static bool ahci_phy_init(void __iomem *mmio) -{ - u8 uCount, i = 0; - /* 0x3A for 40bit I/F */ - u8 reg_addrs[] = {0x22, 0x21, 0x3A}; - /* 0x0B for 40bit I/F */ - u8 default_setting_value[] = {0x30, 0x4f, 0x0B}; - - uCount = sizeof(reg_addrs)/sizeof(u8); - while (i < uCount) { - if (!sata_i2c_send(SATA_PHY_I2C_SLAVE_ADDRS, reg_addrs[i], - default_setting_value[i])) - return false; - i++; - } - return true; -} - -static int exynos5_ahci_init(void __iomem *mmio) -{ - int val, ret; - - __raw_writel(S5P_PMU_SATA_PHY_CONTROL_EN, EXYNOS5_SATA_PHY_CONTROL); - - val = 0; - __raw_writel(val, phy_ctrl + SATA_RESET); - val = __raw_readl(phy_ctrl + SATA_RESET); - val |= 0x3D; - __raw_writel(val, phy_ctrl + SATA_RESET); - - val = __raw_readl(phy_ctrl + SATA_RESET); - val |= LINK_RESET; - __raw_writel(val, phy_ctrl + SATA_RESET); - - val = __raw_readl(phy_ctrl + SATA_RESET); - val |= RESET_CMN_RST_N; - __raw_writel(val, phy_ctrl + SATA_RESET); - - val = __raw_readl(phy_ctrl + SATA_PHSATA_CTRLM); - val &= ~PHCTRLM_REF_RATE; - __raw_writel(val, phy_ctrl + SATA_PHSATA_CTRLM); - - /* High speed enable for Gen3 */ - val = __raw_readl(phy_ctrl + SATA_PHSATA_CTRLM); - val |= PHCTRLM_HIGH_SPEED; - __raw_writel(val, phy_ctrl + SATA_PHSATA_CTRLM); - - /* Port0 is available */ - __raw_writel(0x1, mmio + HOST_PORTS_IMPL); - - ret = ahci_phy_init(mmio); - - val = __raw_readl(phy_ctrl + SATA_CTRL0); - val |= CTRL0_P0_PHY_CALIBRATED_SEL|CTRL0_P0_PHY_CALIBRATED; - __raw_writel(val, phy_ctrl + SATA_CTRL0); - sata_set_gen(SATA_GENERATION3); - - /* release cmu reset */ - val = __raw_readl(phy_ctrl + SATA_RESET); - val &= ~RESET_CMN_RST_N; - __raw_writel(val, phy_ctrl + SATA_RESET); - - val = __raw_readl(phy_ctrl + SATA_RESET); - val |= RESET_CMN_RST_N; - __raw_writel(val, phy_ctrl + SATA_RESET); - - if (wait_for_reg_status(phy_ctrl, SATA_PHSATA_STATM, - PHSTATM_PLL_LOCKED, 1)) { - return ret; - } - return 0; -} - -static int exynos5_sata_enable_power(const void *blob) -{ - int node; - struct fdt_gpio_state gpio; - - node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_SATA); - if (node >= 0 && - fdtdec_decode_gpio(blob, node, "enable-gpios", &gpio) == 0) { - gpio_cfg_pin(gpio.gpio, EXYNOS_GPIO_OUTPUT); - gpio_set_value(gpio.gpio, 1); - return 0; - } - return -ENODEV; -} - -static void exynos5_enable_clock_gates(void) -{ - /* Turn on all SATA clock gates & DMA gates. */ - const unsigned cmu_toppart = 0x10020000; - const unsigned addr = cmu_toppart + 0x944; - const unsigned sata_clocks = (1 << 25) | (1 << 24) | (1 << 6); - const unsigned dma_clocks = (2 << 1) | (1 << 1); - const unsigned clk_gate_ip_fsys = readl(addr); - writel(clk_gate_ip_fsys | sata_clocks | dma_clocks, addr); -} - -int exynos5_sata_init(const void *blob) -{ - if (exynos5_sata_enable_power(blob) == 0) { - exynos5_enable_clock_gates(); - - if (exynos5_ahci_init((void *)SATA_AHCI_AXI)) { - ahci_init(SATA_AHCI_AXI); - scsi_scan(1); - return 0; - } - } - return -ENODEV; -} diff --git a/src/cpu/samsung/exynos5250/tzpc.h b/src/cpu/samsung/exynos5250/tzpc.h deleted file mode 100644 index b9937b84b5..0000000000 --- a/src/cpu/samsung/exynos5250/tzpc.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * (C) Copyright 2012 Samsung Electronics - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - */ - -#ifndef __TZPC_H_ -#define __TZPC_H_ - -#ifndef __ASSEMBLER__ -struct exynos5_tzpc { - unsigned int r0size; - char res1[0x7FC]; - unsigned int decprot0stat; - unsigned int decprot0set; - unsigned int decprot0clr; - unsigned int decprot1stat; - unsigned int decprot1set; - unsigned int decprot1clr; - unsigned int decprot2stat; - unsigned int decprot2set; - unsigned int decprot2clr; - unsigned int decprot3stat; - unsigned int decprot3set; - unsigned int decprot3clr; - char res2[0x7B0]; - unsigned int periphid0; - unsigned int periphid1; - unsigned int periphid2; - unsigned int periphid3; - unsigned int pcellid0; - unsigned int pcellid1; - unsigned int pcellid2; - unsigned int pcellid3; -}; -#endif - -#endif diff --git a/src/cpu/samsung/exynos5250/tzpc_init.c b/src/cpu/samsung/exynos5250/tzpc_init.c deleted file mode 100644 index 370c2ed9c2..0000000000 --- a/src/cpu/samsung/exynos5250/tzpc_init.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Lowlevel setup for SMDK5250 board based on S5PC520 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include"setup.h" - -/* Setting TZPC[TrustZone Protection Controller] */ -void tzpc_init(void) -{ - struct exynos5_tzpc *tzpc; - unsigned int addr; - - for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) { - tzpc = (struct exynos5_tzpc *)addr; - - if (addr == TZPC0_BASE) - writel(R0SIZE, &tzpc->r0size); - - writel(DECPROTXSET, &tzpc->decprot0set); - writel(DECPROTXSET, &tzpc->decprot1set); - - if (addr == TZPC9_BASE) { - - /* TODO: Add comment here describing the numerical values - * used below. - */ - writel(0xf0, &tzpc->decprot2set); - writel(0x50, &tzpc->decprot3set); - } else { - writel(DECPROTXSET, &tzpc->decprot2set); - writel(DECPROTXSET, &tzpc->decprot3set); - } - } -} diff --git a/src/cpu/samsung/exynos5250/uart.h b/src/cpu/samsung/exynos5250/uart.h deleted file mode 100644 index 1d872d705f..0000000000 --- a/src/cpu/samsung/exynos5250/uart.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) Copyright 2012 The ChromiumOS Authors - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang - * Heungjun Kim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * This file is based off of arch/arm/include/asm/arch-exynos5/uart.h - * from u-boot. - */ - -#ifndef __EXYNOS5250_UART_H_ -#define __EXYNOS5250_UART_H_ - -#define EXYNOS5_UART0_BASE 0x12c00000 -#define EXYNOS5_UART1_BASE 0x12c10000 -#define EXYNOS5_UART2_BASE 0x12c20000 -#define EXYNOS5_UART3_BASE 0x12c30000 -#define EXYNOS5_ISP_UART_BASE 0x13190000 - -#endif diff --git a/src/cpu/via/c3/Kconfig b/src/cpu/via/c3/Kconfig index 259a1f211d..2e4d177d31 100644 --- a/src/cpu/via/c3/Kconfig +++ b/src/cpu/via/c3/Kconfig @@ -5,6 +5,9 @@ if CPU_VIA_C3 config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select UDELAY_TSC select MMX select IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS diff --git a/src/cpu/via/c7/Kconfig b/src/cpu/via/c7/Kconfig index ebbb8f9f02..01fd408a49 100644 --- a/src/cpu/via/c7/Kconfig +++ b/src/cpu/via/c7/Kconfig @@ -5,6 +5,9 @@ if CPU_VIA_C7 config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select UDELAY_TSC select MMX select SSE2 diff --git a/src/cpu/via/car/cache_as_ram.inc b/src/cpu/via/car/cache_as_ram.inc index 1af8eccfe1..17b4b833db 100644 --- a/src/cpu/via/car/cache_as_ram.inc +++ b/src/cpu/via/car/cache_as_ram.inc @@ -264,17 +264,12 @@ testok: movl %eax, %cr0 invd - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/cpu/via/nano/Kconfig b/src/cpu/via/nano/Kconfig index 3b1c2137e8..c998acd55e 100644 --- a/src/cpu/via/nano/Kconfig +++ b/src/cpu/via/nano/Kconfig @@ -24,6 +24,9 @@ if CPU_VIA_NANO config CPU_SPECIFIC_OPTIONS def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select UDELAY_TSC select MMX select SSE2 diff --git a/src/cpu/x86/16bit/entry16.lds b/src/cpu/x86/16bit/entry16.ld similarity index 100% rename from src/cpu/x86/16bit/entry16.lds rename to src/cpu/x86/16bit/entry16.ld diff --git a/src/cpu/x86/16bit/reset16.lds b/src/cpu/x86/16bit/reset16.ld similarity index 100% rename from src/cpu/x86/16bit/reset16.lds rename to src/cpu/x86/16bit/reset16.ld diff --git a/src/cpu/x86/32bit/entry32.lds b/src/cpu/x86/32bit/entry32.ld similarity index 100% rename from src/cpu/x86/32bit/entry32.lds rename to src/cpu/x86/32bit/entry32.ld diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 4c5176b693..c28d00b5a1 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -11,6 +11,13 @@ config UDELAY_LAPIC bool default n +config LAPIC_MONOTONIC_TIMER + def_bool n + depends on UDELAY_LAPIC + select HAVE_MONOTONIC_TIMER + help + Expose monotonic time using the local apic. + config UDELAY_LAPIC_FIXED_FSB int @@ -18,6 +25,20 @@ config UDELAY_TSC bool default n +config TSC_CONSTANT_RATE + def_bool n + depends on UDELAY_TSC + help + This option asserts that the TSC ticks at a known constant rate. + Therefore, no TSC calibration is required. + +config TSC_MONOTONIC_TIMER + def_bool n + depends on UDELAY_TSC + select HAVE_MONOTONIC_TIMER + help + Expose monotonic time using the TSC. + config UDELAY_TIMER2 bool default n @@ -94,3 +115,23 @@ config X86_AMD_FIXED_MTRRS help This option informs the MTRR code to use the RdMem and WrMem fields in the fixed MTRR MSRs. + +config PARALLEL_MP + def_bool n + help + This option uses common MP infrastructure for bringing up APs + in parallel. It additionally provides a more flexible mechanism + for sequencing the steps of bringing up the APs. + +config BACKUP_DEFAULT_SMM_REGION + def_bool n + help + The cpu support will select this option if the default SMM region + needs to be backed up for suspend/resume purposes. + +config BOOT_MEDIA_SPI_BUS + int + default 0 + depends on SPI_FLASH + help + Most x86 systems which boot from SPI flash boot using bus 0. diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc new file mode 100644 index 0000000000..94c1655be1 --- /dev/null +++ b/src/cpu/x86/Makefile.inc @@ -0,0 +1,23 @@ +romstage-$(CONFIG_CAR_MIGRATION) += car.c + +subdirs-$(CONFIG_PARALLEL_MP) += name +ramstage-$(CONFIG_PARALLEL_MP) += mp_init.c + +SIPI_ELF=$(obj)/cpu/x86/sipi_vector.elf +SIPI_RMOD=$(SIPI_ELF).rmod +SIPI_BIN=$(SIPI_ELF:.elf=) +SIPI_DOTO=$(SIPI_ELF:.elf=.o) + +ifeq ($(CONFIG_PARALLEL_MP),y) +ramstage-objs += $(SIPI_BIN).ramstage.o +endif +rmodules_$(ARCH-RAMSTAGE-y)-$(CONFIG_PARALLEL_MP) += sipi_vector.S + +$(eval $(call rmodule_link,$(SIPI_ELF), $(dir $(SIPI_ELF))sipi_vector.rmodules_$(ARCH-RAMSTAGE-y).o, 0,x86_32)) + +$(SIPI_BIN): $(SIPI_RMOD) + $(OBJCOPY_ramstage) -O binary $< $@ + +$(SIPI_BIN).ramstage.o: $(SIPI_BIN) + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + cd $(dir $@); $(OBJCOPY_ramstage) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) diff --git a/src/cpu/x86/car.c b/src/cpu/x86/car.c new file mode 100644 index 0000000000..cdcfec1f40 --- /dev/null +++ b/src/cpu/x86/car.c @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +extern char _car_data_start[]; +extern char _car_data_end[]; + +/* + * The car_migrated global variable determines if the cache-as-ram space has + * been migrated to real RAM. It does this by asumming the following things: + * 1. cache-as-ram space is zero'd out once it is set up. + * 2. Either the cache-as-ram space is memory-backed after getting torn down + * or the space returns 0xff's for each byte read. + * Based on these 2 attributes there is the ability to tell when the + * cache-as-ram region has been migrated. + */ +static int car_migrated CAR_GLOBAL; + + +void *car_get_var_ptr(void *var) +{ + char *migrated_base; + int offset; + void * _car_start = &_car_data_start; + void * _car_end = &_car_data_end; + + /* If the cache-as-ram has not been migrated return the pointer + * passed in. */ + if (!car_migrated) + return var; + + if (var < _car_start || var >= _car_end) { + printk(BIOS_ERR, + "Requesting CAR variable outside of CAR region: %p\n", + var); + return var; + } + + migrated_base = cbmem_find(CBMEM_ID_CAR_GLOBALS); + + if (migrated_base == NULL) { + printk(BIOS_ERR, "CAR: Could not find migration base!\n"); + return var; + } + + offset = (char *)var - (char *)_car_start; + + return &migrated_base[offset]; +} + +void car_migrate_variables(void) +{ + void *migrated_base; + size_t car_data_size = &_car_data_end[0] - &_car_data_start[0]; + + migrated_base = cbmem_add(CBMEM_ID_CAR_GLOBALS, car_data_size); + + if (migrated_base == NULL) { + printk(BIOS_ERR, "Could not migrate CAR data!\n"); + return; + } + + memcpy(migrated_base, &_car_data_start[0], car_data_size); + + /* Mark that the data has been moved. */ + car_migrated = ~0; +} diff --git a/src/cpu/x86/lapic/apic_timer.c b/src/cpu/x86/lapic/apic_timer.c index b60da27256..868fb92716 100644 --- a/src/cpu/x86/lapic/apic_timer.c +++ b/src/cpu/x86/lapic/apic_timer.c @@ -19,10 +19,12 @@ */ #include +#include #include +#include #include #include -#include +#include #include #include #include @@ -94,6 +96,9 @@ void udelay(u32 usecs) { u32 start, value, ticks; + if (!thread_yield_microseconds(usecs)) + return; + if (!timer_fsb || (lapic_read(LAPIC_LVTT) & (LAPIC_LVT_TIMER_PERIODIC | LAPIC_LVT_MASKED)) != (LAPIC_LVT_TIMER_PERIODIC | LAPIC_LVT_MASKED)) @@ -106,3 +111,45 @@ void udelay(u32 usecs) value = lapic_read(LAPIC_TMCCT); } while((start - value) < ticks); } + +#if CONFIG_LAPIC_MONOTONIC_TIMER && !defined(__PRE_RAM__) +#include + +static struct monotonic_counter { + int initialized; + struct mono_time time; + uint32_t last_value; +} mono_counter; + +void timer_monotonic_get(struct mono_time *mt) +{ + uint32_t current_tick; + uint32_t usecs_elapsed; + + if (!mono_counter.initialized) { + init_timer(); + /* An FSB frequency of 200Mhz provides a 20 second polling + * interval between timer_monotonic_get() calls before wrap + * around occurs. */ + if (timer_fsb > 200) + printk(BIOS_WARNING, + "apic timer freq (%d) may be too fast.\n", + timer_fsb); + mono_counter.last_value = lapic_read(LAPIC_TMCCT); + mono_counter.initialized = 1; + } + + current_tick = lapic_read(LAPIC_TMCCT); + /* Note that the APIC timer counts down. */ + usecs_elapsed = (mono_counter.last_value - current_tick) / timer_fsb; + + /* Update current time and tick values only if a full tick occurred. */ + if (usecs_elapsed) { + mono_time_add_usecs(&mono_counter.time, usecs_elapsed); + mono_counter.last_value = current_tick; + } + + /* Save result. */ + *mt = mono_counter.time; +} +#endif diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c index 69430d551f..90b0f8dd7a 100644 --- a/src/cpu/x86/lapic/lapic_cpu_init.c +++ b/src/cpu/x86/lapic/lapic_cpu_init.c @@ -20,10 +20,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include +#include #include #include #include @@ -32,6 +34,7 @@ #include #include #include +#include #if CONFIG_SMP && CONFIG_MAX_CPUS > 1 /* This is a lot more paranoid now, since Linux can NOT handle @@ -292,6 +295,7 @@ int start_cpu(device_t cpu) info = (struct cpu_info *)stack_end; info->index = index; info->cpu = cpu; + thread_init_cpu_info_non_bsp(info); /* Advertise the new stack and index to start_cpu */ secondary_stack = stack_end; @@ -405,26 +409,6 @@ void stop_this_cpu(void) } #endif -#ifdef __SSE3__ -static __inline__ __attribute__((always_inline)) unsigned long readcr4(void) -{ - unsigned long value; - __asm__ __volatile__ ( - "mov %%cr4, %[value]" - : [value] "=a" (value)); - return value; -} - -static __inline__ __attribute__((always_inline)) void writecr4(unsigned long Data) -{ - __asm__ __volatile__ ( - "mov %%eax, %%cr4" - : - : "a" (Data) - ); -} -#endif - /* C entry point of secondary cpus */ void asmlinkage secondary_cpu_init(unsigned int index) { @@ -439,9 +423,9 @@ void asmlinkage secondary_cpu_init(unsigned int index) * Turn on CR4.OSFXSR and CR4.OSXMMEXCPT when SSE options enabled */ u32 cr4_val; - cr4_val = readcr4(); - cr4_val |= (1 << 9 | 1 << 10); - writecr4(cr4_val); + cr4_val = read_cr4(); + cr4_val |= (CR4_OSFXSR | CR4_OSXMMEXCPT); + write_cr4(cr4_val); #endif cpu_initialize(index); #if CONFIG_SERIAL_CPU_INIT diff --git a/src/cpu/intel/haswell/mp_init.c b/src/cpu/x86/mp_init.c similarity index 61% rename from src/cpu/intel/haswell/mp_init.c rename to src/cpu/x86/mp_init.c index ddcff6c834..55fc49aaa6 100644 --- a/src/cpu/intel/haswell/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 ChromeOS Authors + * Copyright (C) 2013 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,38 +27,42 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include #include -#include "haswell.h" +#include +#include +#define MAX_APIC_IDS 256 /* This needs to match the layout in the .module_parametrs section. */ struct sipi_params { - u16 gdtlimit; - u32 gdt; - u16 unused; - u32 idt_ptr; - u32 stack_top; - u32 stack_size; - u32 microcode_ptr; - u32 msr_table_ptr; - u32 msr_count; - u32 c_handler; - u32 c_handler_arg; - u8 apic_to_cpu_num[CONFIG_MAX_CPUS]; + uint16_t gdtlimit; + uint32_t gdt; + uint16_t unused; + uint32_t idt_ptr; + uint32_t stack_top; + uint32_t stack_size; + uint32_t microcode_lock; /* 0xffffffff means parallel loading. */ + uint32_t microcode_ptr; + uint32_t msr_table_ptr; + uint32_t msr_count; + uint32_t c_handler; + atomic_t ap_count; } __attribute__((packed)); /* This also needs to match the assembly code for saved MSR encoding. */ struct saved_msr { - u32 index; - u32 lo; - u32 hi; + uint32_t index; + uint32_t lo; + uint32_t hi; } __attribute__((packed)); @@ -69,44 +73,41 @@ extern char gdt[]; extern char gdt_end[]; extern char idtarg[]; -/* This table keeps track of each CPU's APIC id. */ -static u8 apic_id_table[CONFIG_MAX_CPUS]; -static device_t cpu_devs[CONFIG_MAX_CPUS]; +/* The SIPI vector is loaded at the SMM_DEFAULT_BASE. The reason is at the + * memory range is already reserved so the OS cannot use it. That region is + * free to use for AP bringup before SMM is initialized. */ +static const uint32_t sipi_vector_location = SMM_DEFAULT_BASE; +static const int sipi_vector_location_size = SMM_DEFAULT_SIZE; -/* Number of APs checked that have checked in. */ -static atomic_t num_aps; -/* Number of APs that have relocated their SMM handler. */ -static atomic_t num_aps_relocated_smm; -/* Barrier to stop APs from performing SMM relcoation. */ -static int smm_relocation_barrier_begin __attribute__ ((aligned (64))); +struct mp_flight_plan { + int num_records; + struct mp_flight_record *records; +}; -static inline void mfence(void) +static struct mp_flight_plan mp_info; + +struct cpu_map { + device_t dev; + int apic_id; +}; + +/* Keep track of apic and device structure for each cpu. */ +static struct cpu_map cpus[CONFIG_MAX_CPUS]; + +static inline void barrier_wait(atomic_t *b) { - __asm__ __volatile__("mfence\t\n": : :"memory"); -} - -static inline void wait_for_barrier(volatile int *barrier) -{ - while (*barrier == 0) { + while (atomic_read(b) == 0) { asm ("pause"); } + mfence(); } -static inline void release_barrier(volatile int *barrier) +static inline void release_barrier(atomic_t *b) { - *barrier = 1; + mfence(); + atomic_set(b, 1); } -static void ap_wait_for_smm_relocation_begin(void) -{ - wait_for_barrier(&smm_relocation_barrier_begin); -} - -/* This function pointer is used by the non-BSP CPUs to initiate relocation. It - * points to either a serial or parallel SMM initiation. */ -static void (*ap_initiate_smm_relocation)(void) = &smm_initiate_relocation; - - /* 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) @@ -125,92 +126,63 @@ static int wait_for_aps(atomic_t *val, int target, int total_delay, return timeout; } -void release_aps_for_smm_relocation(int do_parallel) +static void ap_do_flight_plan(void) { - /* Change the AP SMM initiation function, and ensure it is visible - * before releasing the APs. */ - if (do_parallel) { - ap_initiate_smm_relocation = &smm_initiate_relocation_parallel; - mfence(); - } - release_barrier(&smm_relocation_barrier_begin); - /* Wait for CPUs to relocate their SMM handler up to 100ms. */ - if (wait_for_aps(&num_aps_relocated_smm, atomic_read(&num_aps), - 100000 /* 100 ms */, 200 /* us */)) - printk(BIOS_DEBUG, "Timed out waiting for AP SMM relocation\n"); -} + int i; -/* The mtrr code sets up ROM caching on the BSP, but not the others. However, - * the boot loader payload disables this. In order for Linux not to complain - * ensure the caching is disabled for tha APs before going to sleep. */ -static void cleanup_rom_caching(void) -{ - x86_mtrr_disable_rom_caching(); + for (i = 0; i < mp_info.num_records; i++) { + struct mp_flight_record *rec = &mp_info.records[i]; + + atomic_inc(&rec->cpus_entered); + barrier_wait(&rec->barrier); + + if (rec->ap_call != NULL) { + rec->ap_call(rec->ap_arg); + } + } } /* By the time APs call ap_init() caching has been setup, and microcode has * been loaded. */ -static void __attribute__((cdecl)) -ap_init(unsigned int cpu, void *microcode_ptr) +static void asmlinkage ap_init(unsigned int cpu) { struct cpu_info *info; - - /* Signal that the AP has arrived. */ - atomic_inc(&num_aps); + int apic_id; /* Ensure the local apic is enabled */ enable_lapic(); info = cpu_info(); info->index = cpu; - info->cpu = cpu_devs[cpu]; + info->cpu = cpus[cpu].dev; + thread_init_cpu_info_non_bsp(info); - apic_id_table[info->index] = lapicid(); - info->cpu->path.apic.apic_id = apic_id_table[info->index]; + apic_id = lapicid(); + info->cpu->path.apic.apic_id = apic_id; + cpus[cpu].apic_id = apic_id; - /* Call through the cpu driver's initialization. */ - cpu_initialize(info->index); + printk(BIOS_INFO, "AP: slot %d apic_id %x.\n", cpu, apic_id); - ap_wait_for_smm_relocation_begin(); + /* Walk the flight plan */ + ap_do_flight_plan(); - ap_initiate_smm_relocation(); - - /* Indicate that SMM relocation has occured on this thread. */ - atomic_inc(&num_aps_relocated_smm); - - /* After SMM relocation a 2nd microcode load is required. */ - intel_microcode_load_unlocked(microcode_ptr); - - /* The MTRR resources are core scoped. Therefore, there is no need - * to do the same work twice. Additionally, this check keeps the - * ROM cache enabled on the BSP since its hyperthread sibling won't - * call cleanup_rom_caching(). */ - if ((lapicid() & 1) == 0) - cleanup_rom_caching(); - - /* FIXME(adurbin): park CPUs properly -- preferably somewhere in a - * reserved part of memory that the OS cannot get to. */ + /* Park the AP. */ stop_this_cpu(); } static void setup_default_sipi_vector_params(struct sipi_params *sp) { - int i; - - sp->gdt = (u32)&gdt; - sp->gdtlimit = (u32)&gdt_end - (u32)&gdt - 1; - sp->idt_ptr = (u32)&idtarg; + sp->gdt = (uint32_t)&gdt; + sp->gdtlimit = (uint32_t)&gdt_end - (u32)&gdt - 1; + sp->idt_ptr = (uint32_t)&idtarg; sp->stack_size = CONFIG_STACK_SIZE; - sp->stack_top = (u32)&_estack; + sp->stack_top = (uint32_t)&_estack; /* Adjust the stack top to take into account cpu_info. */ sp->stack_top -= sizeof(struct cpu_info); - /* Default to linear APIC id space. */ - for (i = 0; i < CONFIG_MAX_CPUS; i++) - sp->apic_to_cpu_num[i] = i; } #define NUM_FIXED_MTRRS 11 -static unsigned int fixed_mtrrs[NUM_FIXED_MTRRS] = { +static const unsigned int fixed_mtrrs[NUM_FIXED_MTRRS] = { MTRRfix64K_00000_MSR, MTRRfix16K_80000_MSR, MTRRfix16K_A0000_MSR, MTRRfix4K_C0000_MSR, MTRRfix4K_C8000_MSR, MTRRfix4K_D0000_MSR, MTRRfix4K_D8000_MSR, MTRRfix4K_E0000_MSR, MTRRfix4K_E8000_MSR, @@ -266,13 +238,7 @@ static int save_bsp_msrs(char *start, int size) return msr_count; } -/* The SIPI vector is loaded at the SMM_DEFAULT_BASE. The reason is at the - * memory range is already reserved so the OS cannot use it. That region is - * free to use for AP bringup before SMM is initialized. */ -static u32 sipi_vector_location = SMM_DEFAULT_BASE; -static int sipi_vector_location_size = SMM_DEFAULT_SIZE; - -static int load_sipi_vector(const void *microcode_patch) +static atomic_t *load_sipi_vector(struct mp_params *mp_params) { struct rmodule sipi_mod; int module_size; @@ -280,106 +246,101 @@ static int load_sipi_vector(const void *microcode_patch) struct sipi_params *sp; char *mod_loc = (void *)sipi_vector_location; const int loc_size = sipi_vector_location_size; + atomic_t *ap_count = NULL; if (rmodule_parse(&_binary_sipi_vector_start, &sipi_mod)) { printk(BIOS_CRIT, "Unable to parse sipi module.\n"); - return -1; + return ap_count; } if (rmodule_entry_offset(&sipi_mod) != 0) { printk(BIOS_CRIT, "SIPI module entry offset is not 0!\n"); - return -1; + return ap_count; } if (rmodule_load_alignment(&sipi_mod) != 4096) { printk(BIOS_CRIT, "SIPI module load alignment(%d) != 4096.\n", rmodule_load_alignment(&sipi_mod)); - return -1; + return ap_count; } module_size = rmodule_memory_size(&sipi_mod); /* Align to 4 bytes. */ - module_size += 3; - module_size &= ~3; + module_size = ALIGN(module_size, 4); if (module_size > loc_size) { printk(BIOS_CRIT, "SIPI module size (%d) > region size (%d).\n", module_size, loc_size); - return -1; + return ap_count; } num_msrs = save_bsp_msrs(&mod_loc[module_size], loc_size - module_size); if (num_msrs < 0) { printk(BIOS_CRIT, "Error mirroring BSP's msrs.\n"); - return -1; + return ap_count; } if (rmodule_load(mod_loc, &sipi_mod)) { printk(BIOS_CRIT, "Unable to load SIPI module.\n"); - return -1; + return ap_count; } sp = rmodule_parameters(&sipi_mod); if (sp == NULL) { printk(BIOS_CRIT, "SIPI module has no parameters.\n"); - return -1; + return ap_count; } setup_default_sipi_vector_params(sp); /* Setup MSR table. */ - sp->msr_table_ptr = (u32)&mod_loc[module_size]; + sp->msr_table_ptr = (uint32_t)&mod_loc[module_size]; sp->msr_count = num_msrs; /* Provide pointer to microcode patch. */ - sp->microcode_ptr = (u32)microcode_patch; - /* The microcode pointer is passed on through to the c handler so - * that it can be loaded again after SMM relocation. */ - sp->c_handler_arg = (u32)microcode_patch; - sp->c_handler = (u32)&ap_init; + sp->microcode_ptr = (uint32_t)mp_params->microcode_pointer; + /* Pass on abiility to load microcode in parallel. */ + if (mp_params->parallel_microcode_load) { + sp->microcode_lock = 0; + } else { + sp->microcode_lock = ~0; + } + sp->c_handler = (uint32_t)&ap_init; + ap_count = &sp->ap_count; + atomic_set(ap_count, 0); - /* Make sure SIPI vector hits RAM so the APs that come up will see - * the startup code even if the caches are disabled. */ - wbinvd(); - - return 0; + return ap_count; } -static int allocate_cpu_devices(struct bus *cpu_bus, int *total_hw_threads) +static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p) { int i; - int num_threads; - int num_cores; int max_cpus; struct cpu_info *info; - msr_t msr; - info = cpu_info(); - cpu_devs[info->index] = info->cpu; - apic_id_table[info->index] = info->cpu->path.apic.apic_id; - - msr = rdmsr(CORE_THREAD_COUNT_MSR); - num_threads = (msr.lo >> 0) & 0xffff; - num_cores = (msr.lo >> 16) & 0xffff; - printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", - num_cores, num_threads); - - max_cpus = num_threads; - *total_hw_threads = num_threads; - if (num_threads > CONFIG_MAX_CPUS) { + max_cpus = p->num_cpus; + if (max_cpus > CONFIG_MAX_CPUS) { printk(BIOS_CRIT, "CPU count(%d) exceeds CONFIG_MAX_CPUS(%d)\n", - num_threads, CONFIG_MAX_CPUS); + max_cpus, CONFIG_MAX_CPUS); max_cpus = CONFIG_MAX_CPUS; } + info = cpu_info(); for (i = 1; i < max_cpus; i++) { struct device_path cpu_path; device_t new; + int apic_id; /* Build the cpu device path */ cpu_path.type = DEVICE_PATH_APIC; - cpu_path.apic.apic_id = info->cpu->path.apic.apic_id + i; + + /* Assuming linear APIC space allocation. */ + apic_id = info->cpu->path.apic.apic_id + i; + if (p->adjust_apic_id != NULL) { + apic_id = p->adjust_apic_id(i, apic_id); + } + cpu_path.apic.apic_id = apic_id; /* Allocate the new cpu device structure */ new = alloc_find_dev(cpu_bus, &cpu_path); @@ -387,37 +348,12 @@ static int allocate_cpu_devices(struct bus *cpu_bus, int *total_hw_threads) printk(BIOS_CRIT, "Could not allocte cpu device\n"); max_cpus--; } - cpu_devs[i] = new; + cpus[i].dev = new; } return max_cpus; } -int setup_ap_init(struct bus *cpu_bus, int *max_cpus, - const void *microcode_patch) -{ - int num_cpus; - int hw_threads; - - /* Default to currently running CPU. */ - num_cpus = allocate_cpu_devices(cpu_bus, &hw_threads); - - /* Load the SIPI vector. */ - if (load_sipi_vector(microcode_patch)) - return -1; - - *max_cpus = num_cpus; - - if (num_cpus < hw_threads) { - printk(BIOS_CRIT, - "ERROR: More HW threads (%d) than support (%d).\n", - hw_threads, num_cpus); - return -1; - } - - return 0; -} - /* Returns 1 for timeout. 0 on success. */ static int apic_wait_timeout(int total_delay, int delay_step) { @@ -436,9 +372,11 @@ static int apic_wait_timeout(int total_delay, int delay_step) return timeout; } -int start_aps(struct bus *cpu_bus, int ap_count) +static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps) { int sipi_vector; + /* Max location is 4KiB below 1MiB */ + const int max_vector_loc = ((1 << 20) - (1 << 12)) >> 12; if (ap_count == 0) return 0; @@ -446,7 +384,7 @@ int start_aps(struct bus *cpu_bus, int ap_count) /* The vector is sent as a 4k aligned address in one byte. */ sipi_vector = sipi_vector_location >> 12; - if (sipi_vector > 256) { + if (sipi_vector > max_vector_loc) { printk(BIOS_CRIT, "SIPI vector too large! 0x%08x\n", sipi_vector); return -1; @@ -490,8 +428,9 @@ int start_aps(struct bus *cpu_bus, int ap_count) } else { printk(BIOS_DEBUG, "done.\n"); } + /* Wait for CPUs to check in up to 200 us. */ - wait_for_aps(&num_aps, ap_count, 200 /* us */, 15 /* us */); + wait_for_aps(num_aps, ap_count, 200 /* us */, 15 /* us */); /* Send 2nd SIPI */ if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) { @@ -515,15 +454,138 @@ int start_aps(struct bus *cpu_bus, int ap_count) } /* Wait for CPUs to check in. */ - if (wait_for_aps(&num_aps, ap_count, 10000 /* 10 ms */, 50 /* us */)) { + if (wait_for_aps(num_aps, ap_count, 10000 /* 10 ms */, 50 /* us */)) { printk(BIOS_DEBUG, "Not all APs checked in: %d/%d.\n", - atomic_read(&num_aps), ap_count); + atomic_read(num_aps), ap_count); return -1; } return 0; } +static int bsp_do_flight_plan(struct mp_params *mp_params) +{ + int i; + int ret = 0; + const int timeout_us = 100000; + const int step_us = 100; + int num_aps = mp_params->num_cpus - 1; + + for (i = 0; i < mp_params->num_records; i++) { + struct mp_flight_record *rec = &mp_params->flight_plan[i]; + + /* Wait for APs if the record is not released. */ + if (atomic_read(&rec->barrier) == 0) { + /* Wait for the APs to check in. */ + if (wait_for_aps(&rec->cpus_entered, num_aps, + timeout_us, step_us)) { + printk(BIOS_ERR, "MP record %d timeout.\n", i); + ret = -1; + } + } + + if (rec->bsp_call != NULL) { + rec->bsp_call(rec->bsp_arg); + } + + release_barrier(&rec->barrier); + } + return ret; +} + +static void init_bsp(struct bus *cpu_bus) +{ + struct device_path cpu_path; + struct cpu_info *info; + char processor_name[49]; + + /* Print processor name */ + fill_processor_name(processor_name); + printk(BIOS_INFO, "CPU: %s.\n", processor_name); + + /* Ensure the local apic is enabled */ + enable_lapic(); + + /* Set the device path of the boot cpu. */ + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.apic.apic_id = lapicid(); + + /* Find the device structure for the boot cpu. */ + info = cpu_info(); + info->cpu = alloc_find_dev(cpu_bus, &cpu_path); + + if (info->index != 0) + printk(BIOS_CRIT, "BSP index(%d) != 0!\n", info->index); + + /* Track BSP in cpu_map structures. */ + cpus[info->index].dev = info->cpu; + cpus[info->index].apic_id = cpu_path.apic.apic_id; +} + +int mp_init(struct bus *cpu_bus, struct mp_params *p) +{ + int num_cpus; + int num_aps; + atomic_t *ap_count; + + init_bsp(cpu_bus); + + if (p == NULL || p->flight_plan == NULL || p->num_records < 1) { + printk(BIOS_CRIT, "Invalid MP parameters\n"); + return -1; + } + + /* Default to currently running CPU. */ + num_cpus = allocate_cpu_devices(cpu_bus, p); + + if (num_cpus < p->num_cpus) { + printk(BIOS_CRIT, + "ERROR: More cpus requested (%d) than supported (%d).\n", + p->num_cpus, num_cpus); + return -1; + } + + /* Copy needed parameters so that APs have a reference to the plan. */ + mp_info.num_records = p->num_records; + mp_info.records = p->flight_plan; + + /* Load the SIPI vector. */ + ap_count = load_sipi_vector(p); + if (ap_count == NULL) + return -1; + + /* Make sure SIPI data hits RAM so the APs that come up will see + * the startup code even if the caches are disabled. */ + wbinvd(); + + /* Start the APs providing number of APs and the cpus_entered field. */ + num_aps = p->num_cpus - 1; + if (start_aps(cpu_bus, num_aps, ap_count) < 0) { + mdelay(1000); + printk(BIOS_DEBUG, "%d/%d eventually checked in?\n", + atomic_read(ap_count), num_aps); + return -1; + } + + /* Walk the flight plan for the BSP. */ + return bsp_do_flight_plan(p); +} + +void mp_initialize_cpu(void *unused) +{ + /* Call back into driver infrastructure for the AP initialization. */ + struct cpu_info *info = cpu_info(); + cpu_initialize(info->index); +} + +int mp_get_apic_id(int cpu_slot) +{ + if (cpu_slot >= CONFIG_MAX_CPUS || cpu_slot < 0) + return -1; + + return cpus[cpu_slot].apic_id; +} + void smm_initiate_relocation_parallel(void) { if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) { @@ -546,6 +608,7 @@ void smm_initiate_relocation_parallel(void) DECLARE_SPIN_LOCK(smm_relocation_lock); +/* Send SMI to self with single user serialization. */ void smm_initiate_relocation(void) { spin_lock(&smm_relocation_lock); diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 608912754c..6c4721670b 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,12 @@ #define BIOS_MTRRS 6 #define OS_MTRRS 2 #define MTRRS (BIOS_MTRRS + OS_MTRRS) +/* + * Static storage size for variable MTRRs. Its sized sufficiently large to + * handle different types of CPUs. Empiricially, 16 variable MTRRs has not + * yet been observed. + */ +#define NUM_MTRR_STATIC_STORAGE 16 static int total_mtrrs = MTRRS; static int bios_mtrrs = BIOS_MTRRS; @@ -59,6 +66,13 @@ static void detect_var_mtrrs(void) msr = rdmsr(MTRRcap_MSR); total_mtrrs = msr.lo & 0xff; + + if (total_mtrrs > NUM_MTRR_STATIC_STORAGE) { + printk(BIOS_WARNING, + "MTRRs detected (%d) > NUM_MTRR_STATIC_STORAGE (%d)\n", + total_mtrrs, NUM_MTRR_STATIC_STORAGE); + total_mtrrs = NUM_MTRR_STATIC_STORAGE; + } bios_mtrrs = total_mtrrs - OS_MTRRS; } @@ -310,8 +324,6 @@ static void commit_fixed_mtrrs(void) memset(&fixed_msrs, 0, sizeof(fixed_msrs)); - disable_cache(); - msr_num = 0; type_index = 0; for (i = 0; i < ARRAY_SIZE(fixed_mtrr_desc); i++) { @@ -343,12 +355,13 @@ static void commit_fixed_mtrrs(void) } } - for (i = 0; i < ARRAY_SIZE(fixed_msrs); i++) { + for (i = 0; i < ARRAY_SIZE(fixed_msrs); i++) printk(BIOS_DEBUG, "MTRR: Fixed MSR 0x%lx 0x%08x%08x\n", msr_index[i], fixed_msrs[i].hi, fixed_msrs[i].lo); - wrmsr(msr_index[i], fixed_msrs[i]); - } + disable_cache(); + for (i = 0; i < ARRAY_SIZE(fixed_msrs); i++) + wrmsr(msr_index[i], fixed_msrs[i]); enable_cache(); } @@ -408,19 +421,41 @@ void x86_mtrr_disable_rom_caching(void) enable_cache(); } -void disable_cache_rom(void) +static void disable_cache_rom(void *unused) { x86_mtrr_disable_rom_caching(); } + +BOOT_STATE_INIT_ENTRIES(disable_rom_cache_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, + disable_cache_rom, NULL), + BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, + disable_cache_rom, NULL), +}; #endif +struct var_mtrr_regs { + msr_t base; + msr_t mask; +}; + +struct var_mtrr_solution { + int mtrr_default_type; + int num_used; + struct var_mtrr_regs regs[NUM_MTRR_STATIC_STORAGE]; +}; + +/* Global storage for variable MTRR solution. */ +static struct var_mtrr_solution mtrr_global_solution; + struct var_mtrr_state { struct memranges *addr_space; int above4gb; int address_bits; - int commit_mtrrs; + int prepare_msrs; int mtrr_index; int def_mtrr_type; + struct var_mtrr_regs *regs; }; static void clear_var_mtrr(int index) @@ -432,11 +467,10 @@ static void clear_var_mtrr(int index) wrmsr(MTRRphysMask_MSR(index), msr_val); } -static void write_var_mtrr(struct var_mtrr_state *var_state, - uint32_t base, uint32_t size, int mtrr_type) +static void prep_var_mtrr(struct var_mtrr_state *var_state, + uint32_t base, uint32_t size, int mtrr_type) { - msr_t msr_val; - unsigned long msr_index; + struct var_mtrr_regs *regs; resource_t rbase; resource_t rsize; resource_t mask; @@ -475,18 +509,15 @@ static void write_var_mtrr(struct var_mtrr_state *var_state, printk(BIOS_DEBUG, "MTRR: %d base 0x%016llx mask 0x%016llx type %d\n", var_state->mtrr_index, rbase, rsize, mtrr_type); - msr_val.lo = rbase; - msr_val.lo |= mtrr_type; + regs = &var_state->regs[var_state->mtrr_index]; - msr_val.hi = rbase >> 32; - msr_index = MTRRphysBase_MSR(var_state->mtrr_index); - wrmsr(msr_index, msr_val); + regs->base.lo = rbase; + regs->base.lo |= mtrr_type; + regs->base.hi = rbase >> 32; - msr_val.lo = rsize; - msr_val.lo |= MTRRphysMaskValid; - msr_val.hi = rsize >> 32; - msr_index = MTRRphysMask_MSR(var_state->mtrr_index); - wrmsr(msr_index, msr_val); + regs->mask.lo = rsize; + regs->mask.lo |= MTRRphysMaskValid; + regs->mask.hi = rsize >> 32; } static void calc_var_mtrr_range(struct var_mtrr_state *var_state, @@ -508,8 +539,8 @@ static void calc_var_mtrr_range(struct var_mtrr_state *var_state, else mtrr_size = 1 << addr_lsb; - if (var_state->commit_mtrrs) - write_var_mtrr(var_state, base, mtrr_size, mtrr_type); + if (var_state->prepare_msrs) + prep_var_mtrr(var_state, base, mtrr_size, mtrr_type); size -= mtrr_size; base += mtrr_size; @@ -668,7 +699,7 @@ static int calc_var_mtrrs(struct memranges *addr_space, var_state.addr_space = addr_space; var_state.above4gb = above4gb; var_state.address_bits = address_bits; - var_state.commit_mtrrs = 0; + var_state.prepare_msrs = 0; wb_deftype_count = 0; uc_deftype_count = 0; @@ -743,20 +774,21 @@ static int calc_var_mtrrs(struct memranges *addr_space, return MTRR_TYPE_UNCACHEABLE; } -static void commit_var_mtrrs(struct memranges *addr_space, int def_type, - int above4gb, int address_bits) +static void prepare_var_mtrrs(struct memranges *addr_space, int def_type, + int above4gb, int address_bits, + struct var_mtrr_solution *sol) { struct range_entry *r; struct var_mtrr_state var_state; - int i; var_state.addr_space = addr_space; var_state.above4gb = above4gb; var_state.address_bits = address_bits; - /* Write the MSRs. */ - var_state.commit_mtrrs = 1; + /* Prepare the MSRs. */ + var_state.prepare_msrs = 1; var_state.mtrr_index = 0; var_state.def_mtrr_type = def_type; + var_state.regs = &sol->regs[0]; memranges_each_entry(r, var_state.addr_space) { if (range_entry_mtrr_type(r) == def_type) @@ -769,30 +801,46 @@ static void commit_var_mtrrs(struct memranges *addr_space, int def_type, calc_var_mtrrs_without_hole(&var_state, r); } - /* Clear all remaining variable MTTRs. */ - for (i = var_state.mtrr_index; i < total_mtrrs; i++) + /* Update the solution. */ + sol->num_used = var_state.mtrr_index; +} + +static void commit_var_mtrrs(const struct var_mtrr_solution *sol) +{ + int i; + + /* Write out the variable MTTRs. */ + disable_cache(); + for (i = 0; i < sol->num_used; i++) { + wrmsr(MTRRphysBase_MSR(i), sol->regs[i].base); + wrmsr(MTRRphysMask_MSR(i), sol->regs[i].mask); + } + /* Clear the ones that are unused. */ + for (; i < total_mtrrs; i++) clear_var_mtrr(i); + enable_cache(); + } void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb) { - static int mtrr_default_type = -1; + static struct var_mtrr_solution *sol = NULL; struct memranges *addr_space; addr_space = get_physical_address_space(); - if (mtrr_default_type == -1) { + if (sol == NULL) { if (above4gb == 2) detect_var_mtrrs(); - mtrr_default_type = + sol = &mtrr_global_solution; + sol->mtrr_default_type = calc_var_mtrrs(addr_space, !!above4gb, address_bits); + prepare_var_mtrrs(addr_space, sol->mtrr_default_type, + !!above4gb, address_bits, sol); } - disable_cache(); - commit_var_mtrrs(addr_space, mtrr_default_type, !!above4gb, - address_bits); - enable_var_mtrr(mtrr_default_type); - enable_cache(); + commit_var_mtrrs(sol); + enable_var_mtrr(sol->mtrr_default_type); } void x86_setup_mtrrs(void) diff --git a/src/cpu/x86/pae/pgtbl.c b/src/cpu/x86/pae/pgtbl.c index 814c5f161f..935473828c 100644 --- a/src/cpu/x86/pae/pgtbl.c +++ b/src/cpu/x86/pae/pgtbl.c @@ -1,5 +1,5 @@ /* - 2005.12 yhlu add coreboot_ram cross the vga font buffer handling + 2005.12 yhlu add ramstage cross the vga font buffer handling */ #include diff --git a/src/cpu/intel/haswell/sipi_vector.S b/src/cpu/x86/sipi_vector.S similarity index 83% rename from src/cpu/intel/haswell/sipi_vector.S rename to src/cpu/x86/sipi_vector.S index 664a9ee8ee..c08c3911df 100644 --- a/src/cpu/intel/haswell/sipi_vector.S +++ b/src/cpu/x86/sipi_vector.S @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 ChromeOS Authors + * Copyright (C) 2013 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -42,6 +42,8 @@ stack_top: .long 0 stack_size: .long 0 +microcode_lock: +.long 0 microcode_ptr: .long 0 msr_table_ptr: @@ -50,14 +52,14 @@ msr_count: .long 0 c_handler: .long 0 -c_handler_arg: +ap_count: .long 0 -apic_to_cpu_num: -.fill CONFIG_MAX_CPUS,1,0xff .text .code16 .global ap_start +.global __rmodule_entry +__rmodule_entry: ap_start: cli xorl %eax, %eax @@ -98,28 +100,14 @@ ap_start: mov idt_ptr, %ebx lidt (%ebx) - /* The CPU number is calculated by reading the initial APIC id. */ - mov $1, %eax - cpuid - /* Default APIC id in ebx[31:24]. Move it to bl. */ - bswap %ebx - mov $(apic_to_cpu_num), %eax - xor %ecx, %ecx - + /* Obtain cpu number. */ + movl ap_count, %eax 1: - cmp (%eax, %ecx, 1), %bl - je 1f + movl %eax, %ecx inc %ecx - cmp $CONFIG_MAX_CPUS, %ecx - jne 1b + lock cmpxchg %ecx, ap_count + jnz 1b - /* This is bad. No CPU number found. However, the BSP should have setup - * the AP handler properly. Just park the CPU. */ - mov $0x80, %dx - movw $0xdead, %ax - outw %ax, %dx - jmp halt_jump -1: /* Setup stacks for each CPU. */ movl stack_size, %eax mul %ecx @@ -132,7 +120,7 @@ ap_start: /* Determine if one should check microcode versions. */ mov microcode_ptr, %edi test %edi, %edi - jz 1f /* Bypass if no microde exists. */ + jz microcode_done /* Bypass if no microde exists. */ /* Get the Microcode version. */ mov $1, %eax @@ -141,8 +129,18 @@ ap_start: rdmsr /* If something already loaded skip loading again. */ test %edx, %edx - jnz 1f + jnz microcode_done + /* Determine if parallel microcode loading is allowed. */ + cmp $0xffffffff, microcode_lock + je load_microcode + + /* Protect microcode loading. */ +lock_microcode: + lock bts $0, microcode_lock + jc lock_microcode + +load_microcode: /* Load new microcode. */ mov $IA32_UPDT_TRIG, %ecx xor %edx, %edx @@ -154,7 +152,14 @@ ap_start: wrmsr popa -1: + /* Unconditionally unlock microcode loading. */ + cmp $0xffffffff, microcode_lock + je microcode_done + + xor %eax, %eax + mov %eax, microcode_lock + +microcode_done: /* * Load MSRs. Each entry in the table consists of: * 0: index, @@ -180,8 +185,7 @@ load_msr: and $0x9fffffff, %eax /* CD, NW = 0 */ mov %eax, %cr0 - /* c_handler(cpu_num, *c_handler_arg) */ - push c_handler_arg + /* c_handler(cpu_num) */ push %esi /* cpu_num */ mov c_handler, %eax call *%eax diff --git a/src/cpu/x86/smm/Makefile.inc b/src/cpu/x86/smm/Makefile.inc index b595a36924..fdfa8e2011 100644 --- a/src/cpu/x86/smm/Makefile.inc +++ b/src/cpu/x86/smm/Makefile.inc @@ -17,82 +17,88 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## +ramstage-$(CONFIG_BACKUP_DEFAULT_SMM_REGION) += backup_default_smm.c + +$(eval $(call create_class_compiler,smm,x86_32)) +$(eval $(call create_class_compiler,smmstub,x86_32)) + +smmstub-generic-ccopts += -D__SMM__ +smm-generic-ccopts += -D__SMM__ + ifeq ($(CONFIG_SMM_MODULES),y) smmstub-y += smm_stub.S -smmstub-y += smm_module_header.c smm-y += smiutil.c -smm-y += smm_module_header.c smm-y += smm_module_handler.c ramstage-y += smm_module_loader.c -ramstage-srcs += $(obj)/cpu/x86/smm/smm -ramstage-srcs += $(obj)/cpu/x86/smm/smmstub +ramstage-objs += $(obj)/cpu/x86/smm/smm.ramstage.o +ramstage-objs += $(obj)/cpu/x86/smm/smmstub.ramstage.o -# SMM Stub Module. The stub is used as a trampoline for relocation and normal -# SMM handling. -$(obj)/cpu/x86/smm/smmstub.o: $$(smmstub-objs) - $(CC) $(LDFLAGS) -nostdlib -r -o $@ $^ +# SMM Stub Module. The stub is used as a trampoline for relocation and normal SMM handling. +$(eval $(call rmodule_link,$(obj)/cpu/x86/smm/smmstub.elf, $$$$(smmstub-objs), 0,x86_32)) -# Link the SMM stub module with a 0-byte heap. -$(eval $(call rmodule_link,$(obj)/cpu/x86/smm/smmstub.elf, $(obj)/cpu/x86/smm/smmstub.o, 0)) - -$(obj)/cpu/x86/smm/smmstub: $(obj)/cpu/x86/smm/smmstub.elf - $(OBJCOPY) -O binary $< $@ +$(obj)/cpu/x86/smm/smmstub: $(obj)/cpu/x86/smm/smmstub.elf.rmod + $(OBJCOPY_smmstub) -O binary $< $@ $(obj)/cpu/x86/smm/smmstub.ramstage.o: $(obj)/cpu/x86/smm/smmstub @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cd $(dir $@); $(OBJCOPY) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) + cd $(dir $@); $(OBJCOPY_smmstub) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) # C-based SMM handler. -$(obj)/cpu/x86/smm/smm.o: $$(smm-objs) $(LIBGCC_FILE_NAME) - $(CC) $(LDFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(smm-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group +$(obj)/cpu/x86/smm/smm.o: $$(smm-objs) $(LIBGCC_FILE_NAME_smm) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,smm,$(filter %.a %.o,$(^)),-o $(@),-r $(LIBGCC_WRAP_LDFLAGS)) +$(eval $(call rmodule_link,$(obj)/cpu/x86/smm/smm.elf, $(obj)/cpu/x86/smm/smm.o, $(CONFIG_SMM_MODULE_HEAP_SIZE),x86_32)) -$(eval $(call rmodule_link,$(obj)/cpu/x86/smm/smm.elf, $(obj)/cpu/x86/smm/smm.o, $(CONFIG_SMM_MODULE_HEAP_SIZE))) - -$(obj)/cpu/x86/smm/smm: $(obj)/cpu/x86/smm/smm.elf - $(OBJCOPY) -O binary $< $@ +$(obj)/cpu/x86/smm/smm: $(obj)/cpu/x86/smm/smm.elf.rmod + $(OBJCOPY_smm) -O binary $< $@ $(obj)/cpu/x86/smm/smm.ramstage.o: $(obj)/cpu/x86/smm/smm @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cd $(dir $@); $(OBJCOPY) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) + cd $(dir $@); $(OBJCOPY_smm) -I binary $(notdir $<) -O elf32-i386 -B i386 $(notdir $@) else # CONFIG_SMM_MODULES ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.S ifeq ($(CONFIG_HAVE_SMI_HANDLER),y) -ramstage-srcs += $(obj)/cpu/x86/smm/smm_wrap +ramstage-objs += $(obj)/cpu/x86/smm/smm_wrap.ramstage.o endif # Use TSEG specific entry point and linker script ifeq ($(CONFIG_SMM_TSEG),y) smm-y += smmhandler_tseg.S -SMM_LDFLAGS := $(LDFLAGS) -pie -SMM_LDSCRIPT := smm_tseg.ld +smm-c-ccopts += -fpic +SMM_LDFLAGS := -pie +SMM_LDSCRIPT := smm_tseg else smm-y += smmhandler.S -SMM_LDFLAGS := $(LDFLAGFS) -SMM_LDSCRIPT := smm.ld +SMM_LDFLAGS := +SMM_LDSCRIPT := smm endif smm-y += smihandler.c smm-y += smiutil.c -$(obj)/cpu/x86/smm/smm.o: $$(smm-objs) $(LIBGCC_FILE_NAME) - $(CC) $(LDFLAGS) -nostdlib -r -o $@ -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,--start-group $(smm-objs) $(LIBGCC_FILE_NAME) -Wl,--end-group +smm-y += $(SMM_LDSCRIPT).ld -$(obj)/cpu/x86/smm/smm_wrap: $(obj)/cpu/x86/smm/smm.o $(src)/cpu/x86/smm/$(SMM_LDSCRIPT) $(obj)/ldoptions - $(CC) $(SMM_LDFLAGS) -nostdlib -nostartfiles -static -o $(obj)/cpu/x86/smm/smm.elf -T $(src)/cpu/x86/smm/$(SMM_LDSCRIPT) $(obj)/cpu/x86/smm/smm.o - $(NM) -n $(obj)/cpu/x86/smm/smm.elf | sort > $(obj)/cpu/x86/smm/smm.map - $(OBJCOPY) -O binary $(obj)/cpu/x86/smm/smm.elf $(obj)/cpu/x86/smm/smm +$(obj)/cpu/x86/smm/smm.o: $$(smm-objs) $(LIBGCC_FILE_NAME_smm) + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,smm,$(filter %.a %.o,$(^)),-o $(@),-r $(LIBGCC_WRAP_LDFLAGS)) + +$(obj)/cpu/x86/smm/smm_wrap: $(obj)/cpu/x86/smm/smm.o + @printf " LINK $(subst $(obj)/,,$(@))\n" + $(call link,smm,$(<),-o $(obj)/cpu/x86/smm/smm.elf -T $(obj)/cpu/x86/smm/$(SMM_LDSCRIPT).smm.ld,$(SMM_LDFLAGS)) + $(NM_smm) -n $(obj)/cpu/x86/smm/smm.elf | sort > $(obj)/cpu/x86/smm/smm.map + $(OBJCOPY_smm) -O binary $(obj)/cpu/x86/smm/smm.elf $(obj)/cpu/x86/smm/smm # change to the target path because objcopy will use the path name in its # ELF symbol names. $(obj)/cpu/x86/smm/smm_wrap.ramstage.o: $(obj)/cpu/x86/smm/smm_wrap @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" - cd $(obj)/cpu/x86/smm; $(OBJCOPY) -I binary smm -O elf32-i386 -B i386 smm_wrap.ramstage.o + cd $(obj)/cpu/x86/smm; $(OBJCOPY_smm) -I binary smm -O elf32-i386 -B i386 smm_wrap.ramstage.o endif # CONFIG_SMM_MODULES diff --git a/src/cpu/x86/smm/backup_default_smm.c b/src/cpu/x86/smm/backup_default_smm.c new file mode 100644 index 0000000000..ef1d3a9e41 --- /dev/null +++ b/src/cpu/x86/smm/backup_default_smm.c @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void *backup_default_smm_area(void) +{ + void *save_area; + const void *default_smm = (void *)SMM_DEFAULT_BASE; + + if (!IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) + return NULL; + + /* + * The buffer needs to be preallocated regardless. In the non-resume + * path it will be allocated for handling resume. Note that cbmem_add() + * does a find before the addition. + */ + save_area = cbmem_add(CBMEM_ID_SMM_SAVE_SPACE, SMM_DEFAULT_SIZE); + + if (save_area == NULL) { + printk(BIOS_DEBUG, "SMM save area not added.\n"); + return NULL; + } + + /* Only back up the area on S3 resume. */ + if (acpi_slp_type == 3) { + memcpy(save_area, default_smm, SMM_DEFAULT_SIZE); + return save_area; + } + + /* + * Not the S3 resume path. No need to restore memory contents after + * SMM relocation. + */ + return NULL; +} + +void restore_default_smm_area(void *smm_save_area) +{ + void *default_smm = (void *)SMM_DEFAULT_BASE; + + if (smm_save_area == NULL) + return; + + memcpy(default_smm, smm_save_area, SMM_DEFAULT_SIZE); +} diff --git a/src/cpu/x86/smm/smihandler.c b/src/cpu/x86/smm/smihandler.c index fc30909ae8..f6b80dd2c7 100644 --- a/src/cpu/x86/smm/smihandler.c +++ b/src/cpu/x86/smm/smihandler.c @@ -24,6 +24,12 @@ #include #include +#if CONFIG_SPI_FLASH_SMM +#include +#endif + +static int do_driver_init = 1; + #if !CONFIG_SMM_TSEG /* TSEG handler locks in assembly */ typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore; @@ -183,6 +189,14 @@ void smi_handler(u32 smm_revision) return; } + /* Allow drivers to initialize variables in SMM context. */ + if (do_driver_init) { +#if CONFIG_SPI_FLASH_SMM + spi_init(); +#endif + do_driver_init = 0; + } + /* Call chipset specific SMI handlers. */ if (cpu_smi_handler) cpu_smi_handler(node, &state_save); diff --git a/src/cpu/x86/smm/smm.ld b/src/cpu/x86/smm/smm.ld index d5c7127a15..1d337d0069 100644 --- a/src/cpu/x86/smm/smm.ld +++ b/src/cpu/x86/smm/smm.ld @@ -10,6 +10,7 @@ SECTIONS */ . = 0xa0000; .handler (.): { + _program = .; /* Assembler stub */ *(.handler) @@ -31,9 +32,10 @@ SECTIONS *(.bss) *(.sbss) - /* What is this? */ + /* What is this? (Something we don't need with -fno-common.) */ *(COMMON) . = ALIGN(4); + _eprogram = .; } /* We are using the ASEG interleaved to stuff the SMM handlers diff --git a/src/cpu/x86/smm/smm_module_handler.c b/src/cpu/x86/smm/smm_module_handler.c index 116dafa196..8c0e804523 100644 --- a/src/cpu/x86/smm/smm_module_handler.c +++ b/src/cpu/x86/smm/smm_module_handler.c @@ -20,6 +20,13 @@ #include #include #include +#include + +#if CONFIG_SPI_FLASH_SMM +#include +#endif + +static int do_driver_init = 1; typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore; @@ -113,8 +120,16 @@ void *smm_get_save_state(int cpu) return base; } -void smm_handler_start(void *arg, int cpu, const struct smm_runtime *runtime) +void asmlinkage smm_handler_start(void *arg) { + const struct smm_module_params *p; + const struct smm_runtime *runtime; + int cpu; + + p = arg; + runtime = p->runtime; + cpu = p->cpu; + /* Make sure to set the global runtime. It's OK to race as the value * will be the same across CPUs as well as multiple SMIs. */ if (smm_runtime == NULL) @@ -145,6 +160,14 @@ void smm_handler_start(void *arg, int cpu, const struct smm_runtime *runtime) printk(BIOS_SPEW, "\nSMI# #%d\n", cpu); + /* Allow drivers to initialize variables in SMM context. */ + if (do_driver_init) { +#if CONFIG_SPI_FLASH_SMM + spi_init(); +#endif + do_driver_init = 0; + } + cpu_smi_handler(); northbridge_smi_handler(); southbridge_smi_handler(); @@ -157,6 +180,8 @@ void smm_handler_start(void *arg, int cpu, const struct smm_runtime *runtime) smi_set_eos(); } +RMODULE_ENTRY(smm_handler_start); + /* Provide a default implementation for all weak handlers so that relocation * entries in the modules make sense. Without default implementations the * weak relocations w/o a symbol have a 0 address which is where the modules @@ -165,6 +190,6 @@ int __attribute__((weak)) mainboard_io_trap_handler(int smif) { return 0; } void __attribute__((weak)) cpu_smi_handler(void) {} void __attribute__((weak)) northbridge_smi_handler() {} void __attribute__((weak)) southbridge_smi_handler() {} -void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts) {} +void __attribute__((weak)) mainboard_smi_gpi(u32 gpi_sts) {} int __attribute__((weak)) mainboard_smi_apmc(u8 data) { return 0; } void __attribute__((weak)) mainboard_smi_sleep(u8 slp_typ) {} diff --git a/src/cpu/x86/smm/smm_stub.S b/src/cpu/x86/smm/smm_stub.S index 07eb5dcb6d..083cb577b6 100644 --- a/src/cpu/x86/smm/smm_stub.S +++ b/src/cpu/x86/smm/smm_stub.S @@ -61,6 +61,8 @@ fallback_stack_top: .text .code16 .global smm_handler_start +.global __rmodule_entry +__rmodule_entry: smm_handler_start: movl $(smm_relocate_gdt), %ebx data32 lgdt (%ebx) @@ -132,11 +134,13 @@ smm_trampoline32: 2: /* Call into the c-based SMM relocation function with the platform * parameters. Equivalent to: - * c_handler(c_handler_params, cpu_num, smm_runtime); + * struct arg = { c_handler_params, cpu_num, smm_runtime {; + * c_handler(&arg) */ push $(smm_runtime) push %ecx push c_handler_arg + push %esp mov c_handler, %eax call *%eax diff --git a/src/cpu/x86/smm/smm_tseg.ld b/src/cpu/x86/smm/smm_tseg.ld index 6def972949..7b82ff2ee7 100644 --- a/src/cpu/x86/smm/smm_tseg.ld +++ b/src/cpu/x86/smm/smm_tseg.ld @@ -30,6 +30,7 @@ SECTIONS /* 16KB for the heap at 64KB */ . = 0x10000; .heap : { + _program = .; _heap = .; . = 0x4000; _eheap = .; @@ -61,6 +62,7 @@ SECTIONS . = ALIGN(4); _smm_c_handler_end = .; + _eprogram = .; } /DISCARD/ : { diff --git a/src/cpu/x86/tsc/Makefile.inc b/src/cpu/x86/tsc/Makefile.inc index 44bfe85170..3bbae847f8 100644 --- a/src/cpu/x86/tsc/Makefile.inc +++ b/src/cpu/x86/tsc/Makefile.inc @@ -1,2 +1,6 @@ ramstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c +romstage-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c +ifeq ($(CONFIG_HAVE_SMI_HANDLER),y) +smm-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c +endif diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c index 1907a9cfec..b8f250394f 100644 --- a/src/cpu/x86/tsc/delay_tsc.c +++ b/src/cpu/x86/tsc/delay_tsc.c @@ -4,9 +4,18 @@ #include #include #include +#include + +#if !defined(__PRE_RAM__) static unsigned long clocks_per_usec; +#if CONFIG_TSC_CONSTANT_RATE +static unsigned long calibrate_tsc(void) +{ + return tsc_freq_mhz(); +} +#else /* CONFIG_TSC_CONSTANT_RATE */ #if !CONFIG_TSC_CALIBRATE_WITH_IO #define CLOCK_TICK_RATE 1193180U /* Underlying HZ */ @@ -139,6 +148,7 @@ static unsigned long long calibrate_tsc(void) #endif /* CONFIG_TSC_CALIBRATE_WITH_IO */ +#endif /* CONFIG_TSC_CONSTANT_RATE */ void init_timer(void) { @@ -148,19 +158,71 @@ void init_timer(void) } } +static inline unsigned long get_clocks_per_usec(void) +{ + init_timer(); + return clocks_per_usec; +} +#else /* !defined(__PRE_RAM__) */ +/* romstage calls into cpu/board specific function every time. */ +static inline unsigned long get_clocks_per_usec(void) +{ + return tsc_freq_mhz(); +} +#endif /* !defined(__PRE_RAM__) */ + void udelay(unsigned us) { - unsigned long long count; - unsigned long long stop; - unsigned long long clocks; + unsigned long long start; + unsigned long long current; + unsigned long long clocks; - init_timer(); + if (!thread_yield_microseconds(us)) + return; + + start = rdtscll(); clocks = us; - clocks *= clocks_per_usec; - count = rdtscll(); - stop = clocks + count; - while(stop > count) { + clocks *= get_clocks_per_usec(); + current = rdtscll(); + while((current - start) < clocks) { cpu_relax(); - count = rdtscll(); - } + current = rdtscll(); + } } + +#if CONFIG_TSC_MONOTONIC_TIMER && !defined(__PRE_RAM__) && !defined(__SMM__) +#include + +static struct monotonic_counter { + int initialized; + struct mono_time time; + uint64_t last_value; +} mono_counter; + +void timer_monotonic_get(struct mono_time *mt) +{ + uint64_t current_tick; + uint64_t ticks_elapsed; + + if (!mono_counter.initialized) { + init_timer(); + mono_counter.last_value = rdtscll(); + mono_counter.initialized = 1; + } + + current_tick = rdtscll(); + ticks_elapsed = current_tick - mono_counter.last_value; + + /* Update current time and tick values only if a full tick occurred. */ + if (ticks_elapsed >= clocks_per_usec) { + uint64_t usecs_elapsed; + + usecs_elapsed = ticks_elapsed / clocks_per_usec; + mono_time_add_usecs(&mono_counter.time, (long)usecs_elapsed); + mono_counter.last_value = current_tick; + } + + /* Save result. */ + *mt = mono_counter.time; +} +#endif diff --git a/src/device/Kconfig b/src/device/Kconfig index ca2fb33028..659e5e46fe 100644 --- a/src/device/Kconfig +++ b/src/device/Kconfig @@ -83,6 +83,18 @@ config PCI_ROM_RUN If unsure, say N when using SeaBIOS as payload, Y otherwise. +config ALWAYS_LOAD_OPROM + def_bool n + depends on PCI_ROM_RUN || VGA_ROM_RUN + help + Always load option roms if any are found. The decision to run + the rom is still determined at runtime, but the distinction + between loading and not running comes into play for CHROMEOS. + + An example where this is required is that VBT (video bios tables) + are needed for the kernel's display driver to know how a piece of + hardware is configured to be used. + config ON_DEVICE_ROM_RUN bool "Run Option ROMs on PCI devices" default n if PAYLOAD_SEABIOS @@ -242,6 +254,22 @@ config PCIEXP_ASPM help Detect and enable ASPM on PCIe links. +config PCIEXP_CLK_PM + prompt "Enable PCIe Clock Power Management" + bool + depends on PCIEXP_PLUGIN_SUPPORT + default n + help + Detect and enable Clock Power Management on PCIe. + +config PCIEXP_L1_SUB_STATE + prompt "Enable PCIe ASPM L1 SubState" + bool + depends on PCIEXP_PLUGIN_SUPPORT + default n + help + Detect and enable ASPM on PCIe links. + config PCI_BUS_SEGN_BITS int default 0 @@ -498,3 +526,29 @@ config PXE_ROM_ID Under GNU/Linux you can run `lspci -nn` to list the IDs of your PCI devices. endmenu + +config SUBSYSTEM_VENDOR_ID + hex "Override PCI Subsystem Vendor ID" + depends on PCI + default "0x0000" + help + This config option will override the devicetree settings for + PCI Subsystem Vendor ID. + +config SUBSYSTEM_DEVICE_ID + hex "Override PCI Subsystem Device ID" + depends on PCI + default "0x0000" + help + This config option will override the devicetree settings for + PCI Subsystem Device ID. + +config SOFTWARE_I2C + bool "Enable I2C controller emulation in software" + default n + help + This config option will enable code to override the i2c_transfer + routine with a (simple) software emulation of the protocol. This may + be useful for debugging or on platforms where a driver for the real + I2C controller is not (yet) available. The platform code needs to + provide bindings to manually toggle I2C lines. diff --git a/src/device/Makefile.inc b/src/device/Makefile.inc index 9fe156ba8c..0104a0303e 100644 --- a/src/device/Makefile.inc +++ b/src/device/Makefile.inc @@ -8,7 +8,7 @@ ramstage-$(CONFIG_PCIX_PLUGIN_SUPPORT) += pcix_device.c ramstage-$(CONFIG_PCIEXP_PLUGIN_SUPPORT) += pciexp_device.c ramstage-$(CONFIG_AGP_PLUGIN_SUPPORT) += agp_device.c ramstage-$(CONFIG_CARDBUS_PLUGIN_SUPPORT) += cardbus_device.c -ramstage-$(CONFIG_ARCH_X86) += pnp_device.c +ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += pnp_device.c ramstage-$(CONFIG_PCI) += pci_ops.c ramstage-y += smbus_ops.c @@ -22,3 +22,6 @@ else ramstage-$(CONFIG_VGA_ROM_RUN) += pci_rom.c endif +bootblock-$(CONFIG_SOFTWARE_I2C) += software_i2c.c +romstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c +ramstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c diff --git a/src/device/device.c b/src/device/device.c index e0c8bf0523..52edda270f 100644 --- a/src/device/device.c +++ b/src/device/device.c @@ -43,6 +43,7 @@ #if CONFIG_ARCH_X86 #include #endif +#include /** Linked list of ALL devices */ struct device *all_devices = &dev_root; @@ -65,10 +66,32 @@ void dev_initialize_chips(void) /* Initialize chip if we haven't yet. */ if (dev->chip_ops && dev->chip_ops->init && !dev->chip_ops->initialized) { + post_log_path(dev); dev->chip_ops->init(dev->chip_info); dev->chip_ops->initialized = 1; } } + post_log_clear(); +} + +/** + * Finalize all chips of statically known devices. + * + * This is the last call before calling the payload. This is a good place + * to lock registers or other final cleanup. + */ +void dev_finalize_chips(void) +{ + struct device *dev; + + for (dev = all_devices; dev; dev = dev->next) { + /* Initialize chip if we haven't yet. */ + if (dev->chip_ops && dev->chip_ops->final && + !dev->chip_ops->finalized) { + dev->chip_ops->final(dev->chip_info); + dev->chip_ops->finalized = 1; + } + } } DECLARE_SPIN_LOCK(dev_lock) @@ -192,12 +215,14 @@ static void read_resources(struct bus *bus) dev_path(curdev)); continue; } + post_log_path(curdev); curdev->ops->read_resources(curdev); /* Read in the resources behind the current device's links. */ for (link = curdev->link_list; link; link = link->next) read_resources(link); } + post_log_clear(); printk(BIOS_SPEW, "%s read_resources bus %d link: %d done\n", dev_path(bus->dev), bus->secondary, bus->link_num); } @@ -820,8 +845,10 @@ void assign_resources(struct bus *bus) dev_path(curdev)); continue; } + post_log_path(curdev); curdev->ops->set_resources(curdev); } + post_log_clear(); printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n", dev_path(bus->dev), bus->secondary, bus->link_num); } @@ -844,14 +871,17 @@ static void enable_resources(struct bus *link) struct bus *c_link; for (dev = link->children; dev; dev = dev->sibling) { - if (dev->enabled && dev->ops && dev->ops->enable_resources) + if (dev->enabled && dev->ops && dev->ops->enable_resources) { + post_log_path(dev); dev->ops->enable_resources(dev); + } } for (dev = link->children; dev; dev = dev->sibling) { for (c_link = dev->link_list; c_link; c_link = c_link->next) enable_resources(c_link); } + post_log_clear(); } /** @@ -891,6 +921,8 @@ unsigned int scan_bus(struct device *busdev, unsigned int max) return max; } + post_log_path(busdev); + do_scan_bus = 1; while (do_scan_bus) { struct bus *link; @@ -950,6 +982,7 @@ void dev_enumerate(void) return; } scan_bus(root, 0); + post_log_clear(); printk(BIOS_INFO, "done\n"); } @@ -996,6 +1029,7 @@ void dev_configure(void) for (child = root->link_list->children; child; child = child->sibling) { if (!(child->path.type == DEVICE_PATH_DOMAIN)) continue; + post_log_path(child); for (res = child->resource_list; res; res = res->next) { if (res->flags & IORESOURCE_FIXED) continue; @@ -1042,6 +1076,7 @@ void dev_configure(void) for (child = root->link_list->children; child; child = child->sibling) { if (!(child->path.type == DEVICE_PATH_DOMAIN)) continue; + post_log_path(child); for (res = child->resource_list; res; res = res->next) { if (res->flags & IORESOURCE_FIXED) continue; @@ -1103,6 +1138,10 @@ static void init_dev(struct device *dev) return; if (!dev->initialized && dev->ops && dev->ops->init) { +#if CONFIG_HAVE_MONOTONIC_TIMER + struct stopwatch sw; + stopwatch_init(&sw); +#endif if (dev->path.type == DEVICE_PATH_I2C) { printk(BIOS_DEBUG, "smbus: %s[%d]->", dev_path(dev->bus->dev), dev->bus->link_num); @@ -1111,6 +1150,10 @@ static void init_dev(struct device *dev) printk(BIOS_DEBUG, "%s init\n", dev_path(dev)); dev->initialized = 1; dev->ops->init(dev); +#if CONFIG_HAVE_MONOTONIC_TIMER + printk(BIOS_DEBUG, "%s init %ld usecs\n", dev_path(dev), + stopwatch_duration_usecs(&sw)); +#endif } } @@ -1119,8 +1162,11 @@ static void init_link(struct bus *link) struct device *dev; struct bus *c_link; - for (dev = link->children; dev; dev = dev->sibling) + for (dev = link->children; dev; dev = dev->sibling) { + post_code(POST_BS_DEV_INIT); + post_log_path(dev); init_dev(dev); + } for (dev = link->children; dev; dev = dev->sibling) { for (c_link = dev->link_list; c_link; c_link = c_link->next) @@ -1151,7 +1197,63 @@ void dev_initialize(void) /* Now initialize everything. */ for (link = dev_root.link_list; link; link = link->next) init_link(link); + post_log_clear(); printk(BIOS_INFO, "Devices initialized\n"); show_all_devs(BIOS_SPEW, "After init."); } + +/** + * Finalize a specific device. + * + * The parent should be finalized first to avoid having an ordering problem. + * This is done by calling the parent's final() method before its childrens' + * final() methods. + * + * @param dev The device to be initialized. + */ +static void final_dev(struct device *dev) +{ + if (!dev->enabled) + return; + + if (dev->ops && dev->ops->final) { + printk(BIOS_DEBUG, "%s final\n", dev_path(dev)); + dev->ops->final(dev); + } +} + +static void final_link(struct bus *link) +{ + struct device *dev; + struct bus *c_link; + + for (dev = link->children; dev; dev = dev->sibling) + final_dev(dev); + + for (dev = link->children; dev; dev = dev->sibling) { + for (c_link = dev->link_list; c_link; c_link = c_link->next) + final_link(c_link); + } +} +/** + * Finalize all devices in the global device tree. + * + * Starting at the root device, call the device's final() method to do + * device-specific cleanup, then call each child's final() method. + */ +void dev_finalize(void) +{ + struct bus *link; + + printk(BIOS_INFO, "Finalize devices...\n"); + + /* First call the mainboard finalize. */ + final_dev(&dev_root); + + /* Now finalize everything. */ + for (link = dev_root.link_list; link; link = link->next) + final_link(link); + + printk(BIOS_INFO, "Devices finalized\n"); +} diff --git a/src/device/device_util.c b/src/device/device_util.c index 180169da85..efefa88ed1 100644 --- a/src/device/device_util.c +++ b/src/device/device_util.c @@ -113,6 +113,29 @@ device_t dev_find_lapic(unsigned apic_id) return result; } +/** + * Find a PNP device of given port and device ID. + * + * @param port A PNP port ID. + * @param device A PNP device ID. + * @return Pointer to the device struct. + */ +struct device *dev_find_pnp(unsigned int port, unsigned int device) +{ + struct device *dev, *result; + + result = NULL; + for (dev = all_devices; dev; dev = dev->next) { + if ((dev->path.type == DEVICE_PATH_PNP) && + (dev->path.pnp.port == port) && + (dev->path.pnp.device == device)) { + result = dev; + break; + } + } + return result; +} + /** * Find a device of a given vendor and type. * @@ -158,6 +181,61 @@ struct device *dev_find_class(unsigned int class, struct device *from) return from; } +/** + * Encode the device path into 3 bytes for logging to CMOS. + * + * @param dev The device path to encode. + * @return Device path encoded into lower 3 bytes of dword. + */ +u32 dev_path_encode(device_t dev) +{ + u32 ret; + + if (!dev) + return 0; + + /* Store the device type in 3rd byte. */ + ret = dev->path.type << 16; + + /* Encode the device specific path in the low word. */ + switch (dev->path.type) { + case DEVICE_PATH_ROOT: + break; + case DEVICE_PATH_PCI: + ret |= dev->bus->secondary << 8 | dev->path.pci.devfn; + break; + case DEVICE_PATH_PNP: + ret |= dev->path.pnp.port << 8 | dev->path.pnp.device; + break; + case DEVICE_PATH_I2C: + ret |= dev->bus->secondary << 8 | dev->path.pnp.device; + break; + case DEVICE_PATH_APIC: + ret |= dev->path.apic.apic_id; + break; + case DEVICE_PATH_DOMAIN: + ret |= dev->path.domain.domain; + break; + case DEVICE_PATH_CPU_CLUSTER: + ret |= dev->path.cpu_cluster.cluster; + break; + case DEVICE_PATH_CPU: + ret |= dev->path.cpu.id; + break; + case DEVICE_PATH_CPU_BUS: + ret |= dev->path.cpu_bus.id; + break; + case DEVICE_PATH_IOAPIC: + ret |= dev->path.ioapic.ioapic_id; + break; + case DEVICE_PATH_NONE: + default: + break; + } + + return ret; +} + /* * Warning: This function uses a static buffer. Don't call it more than once * from the same print statement! @@ -713,7 +791,7 @@ void print_resource_tree(struct device *root, int debug_level, const char *msg) void show_devs_tree(struct device *dev, int debug_level, int depth, int linknum) { - char depth_str[20] = ""; + char depth_str[20]; int i; struct device *sibling; struct bus *link; diff --git a/src/device/oprom/realmode/x86.c b/src/device/oprom/realmode/x86.c index 94b65e1abc..4385c03074 100644 --- a/src/device/oprom/realmode/x86.c +++ b/src/device/oprom/realmode/x86.c @@ -29,7 +29,7 @@ #include #include #include "x86.h" -#include "vbe.h" +#include #include /* we use x86emu's register file representation */ #include @@ -118,7 +118,7 @@ static int intXX_unknown_handler(void) } /* setup interrupt handlers for mainboard */ -void mainboard_interrupt_handlers(int intXX, void *intXX_func) +void mainboard_interrupt_handlers(int intXX, int (*intXX_func)(void)) { intXX_handler[intXX] = intXX_func; } diff --git a/src/device/oprom/yabel/compat/functions.c b/src/device/oprom/yabel/compat/functions.c index f693d7bae9..f0160ed52a 100644 --- a/src/device/oprom/yabel/compat/functions.c +++ b/src/device/oprom/yabel/compat/functions.c @@ -18,7 +18,7 @@ #include #include "../debug.h" #include "../biosemu.h" -#include "../vbe.h" +#include #include "../compat/time.h" #define VMEM_SIZE (1024 * 1024) /* 1 MB */ diff --git a/src/device/oprom/yabel/device.h b/src/device/oprom/yabel/device.h index 017aab9384..63f1d8e50e 100644 --- a/src/device/oprom/yabel/device.h +++ b/src/device/oprom/yabel/device.h @@ -128,7 +128,7 @@ u8 biosemu_dev_translate_address(int type, unsigned long * addr); static inline void out32le(void *addr, u32 val) { -#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARMV7 +#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM *((u32*) addr) = cpu_to_le32(val); #else asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr)); @@ -139,7 +139,7 @@ static inline u32 in32le(void *addr) { u32 val; -#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARMV7 +#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM val = cpu_to_le32(*((u32 *) addr)); #else asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr)); @@ -150,7 +150,7 @@ in32le(void *addr) static inline void out16le(void *addr, u16 val) { -#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARMV7 +#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM *((u16*) addr) = cpu_to_le16(val); #else asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr)); @@ -161,7 +161,7 @@ static inline u16 in16le(void *addr) { u16 val; -#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARMV7 +#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM val = cpu_to_le16(*((u16*) addr)); #else asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr)); diff --git a/src/device/oprom/yabel/vbe.h b/src/device/oprom/yabel/vbe.h deleted file mode 100644 index bf286bc12c..0000000000 --- a/src/device/oprom/yabel/vbe.h +++ /dev/null @@ -1,23 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2004, 2008 IBM Corporation - * All rights reserved. - * This program and the accompanying materials - * are made available under the terms of the BSD License - * which accompanies this distribution, and is available at - * http://www.opensource.org/licenses/bsd-license.php - * - * Contributors: - * IBM Corporation - initial implementation - *****************************************************************************/ - -#ifndef _BIOSEMU_VBE_H_ -#define _BIOSEMU_VBE_H_ - -struct lb_framebuffer; - -void vbe_set_graphics(void); -int vbe_mode_info_valid(void); -void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); -void vbe_textmode_console(void); - -#endif diff --git a/src/device/pci_device.c b/src/device/pci_device.c index 4c5a81451c..026fc79554 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -599,6 +599,10 @@ void pci_dev_enable_resources(struct device *dev) /* Set the subsystem vendor and device ID for mainboard devices. */ ops = ops_pci(dev); if (dev->on_mainboard && ops && ops->set_subsystem) { + if (CONFIG_SUBSYSTEM_VENDOR_ID) + dev->subsystem_vendor = CONFIG_SUBSYSTEM_VENDOR_ID; + if (CONFIG_SUBSYSTEM_DEVICE_ID) + dev->subsystem_device = CONFIG_SUBSYSTEM_DEVICE_ID; printk(BIOS_DEBUG, "%s subsystem <- %04x/%04x\n", dev_path(dev), dev->subsystem_vendor, dev->subsystem_device); @@ -659,6 +663,50 @@ void pci_dev_set_subsystem(struct device *dev, unsigned vendor, unsigned device) int oprom_is_loaded = 0; #endif +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int should_run_oprom(struct device *dev) +{ + static int should_run = -1; + + if (should_run >= 0) + return should_run; + +#if CONFIG_CHROMEOS + /* In ChromeOS we want to boot blazingly fast. Therefore + * we don't run (VGA) option ROMs, unless we have to print + * something on the screen before the kernel is loaded. + */ + if (!developer_mode_enabled() && !recovery_mode_enabled() && + !vboot_wants_oprom()) { + printk(BIOS_DEBUG, "Not running VGA Option ROM\n"); + should_run = 0; + return should_run; + } +#endif + should_run = 1; + + return should_run; +} + +static int should_load_oprom(struct device *dev) +{ +#if CONFIG_HAVE_ACPI_RESUME && !CONFIG_S3_VGA_ROM_RUN + /* If S3_VGA_ROM_RUN is disabled, skip running VGA option + * ROMs when coming out of an S3 resume. + */ + if ((acpi_slp_type == 3) && + ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) + return 0; +#endif + if (IS_ENABLED(CONFIG_ALWAYS_LOAD_OPROM)) + return 1; + if (should_run_oprom(dev)) + return 1; + + return 0; +} +#endif /* CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN */ + /** Default handler: only runs the relevant PCI BIOS. */ void pci_dev_init(struct device *dev) { @@ -673,26 +721,8 @@ void pci_dev_init(struct device *dev) ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) return; -#if CONFIG_CHROMEOS - /* In ChromeOS we want to boot blazingly fast. Therefore - * we don't run (VGA) option ROMs, unless we have to print - * something on the screen before the kernel is loaded. - */ - if (!developer_mode_enabled() && !recovery_mode_enabled() && - !vboot_wants_oprom()) { - printk(BIOS_DEBUG, "Not loading VGA Option ROM\n"); + if (!should_load_oprom(dev)) return; - } -#endif - -#if CONFIG_HAVE_ACPI_RESUME && !CONFIG_S3_VGA_ROM_RUN - /* If S3_VGA_ROM_RUN is disabled, skip running VGA option - * ROMs when coming out of an S3 resume. - */ - if ((acpi_slp_type == 3) && - ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) - return; -#endif rom = pci_rom_probe(dev); if (rom == NULL) @@ -702,6 +732,9 @@ void pci_dev_init(struct device *dev) if (ram == NULL) return; + if (!should_run_oprom(dev)) + return; + run_bios(dev, (unsigned long)ram); #if CONFIG_CHROMEOS oprom_is_loaded = 1; diff --git a/src/device/pciexp_device.c b/src/device/pciexp_device.c index 87aea672db..002a89798c 100644 --- a/src/device/pciexp_device.c +++ b/src/device/pciexp_device.c @@ -25,6 +25,29 @@ #include #include +unsigned int pciexp_find_extended_cap(device_t dev, unsigned int cap) +{ + unsigned int this_cap_offset, next_cap_offset; + unsigned int this_cap, cafe; + + this_cap_offset = PCIE_EXT_CAP_OFFSET; + do { + this_cap = pci_mmio_read_config32(dev, this_cap_offset); + next_cap_offset = this_cap >> 20; + this_cap &= 0xffff; + cafe = pci_mmio_read_config32(dev, this_cap_offset + 4); + cafe &= 0xffff; + if (this_cap == cap) + return this_cap_offset; + else if (cafe == cap) + return this_cap_offset + 4; + else + this_cap_offset = next_cap_offset; + } while (next_cap_offset != 0); + + return 0; +} + #if CONFIG_PCIEXP_COMMON_CLOCK /* * Re-train a PCIe link @@ -90,6 +113,177 @@ static void pciexp_enable_common_clock(device_t root, unsigned root_cap, } #endif /* CONFIG_PCIEXP_COMMON_CLOCK */ +#if CONFIG_PCIEXP_CLK_PM +static void pciexp_enable_clock_power_pm(device_t endp, unsigned endp_cap) +{ + /* check if per port clk req is supported in device */ + u32 endp_ca; + u16 lnkctl; + endp_ca = pci_read_config32(endp, endp_cap + PCI_EXP_LNKCAP); + if ((endp_ca & PCI_EXP_CLK_PM) == 0) { + printk(BIOS_INFO, "PCIE CLK PM is not supported by endpoint"); + return; + } + lnkctl = pci_read_config16(endp, endp_cap + PCI_EXP_LNKCTL); + lnkctl = lnkctl | PCI_EXP_EN_CLK_PM; + pci_write_config16(endp, endp_cap + PCI_EXP_LNKCTL, lnkctl); +} +#endif /* CONFIG_PCIEXP_CLK_PM */ + +#if CONFIG_PCIEXP_L1_SUB_STATE +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or) +{ + u32 reg32; + + reg32 = pci_mmio_read_config32(dev, reg); + reg32 &= mask; + reg32 |= or; + pci_mmio_write_config32(dev, reg, reg32); +} + +static void pciexp_config_max_latency(device_t root, device_t dev) +{ + unsigned int cap; + cap = pciexp_find_extended_cap(dev, PCIE_EXT_CAP_LTR_ID); + if (root->ops->ops_pci->set_L1_ss_latency != NULL) + root->ops->ops_pci->set_L1_ss_latency(dev, cap + 4); +} + +static void pciexp_enable_ltr(device_t dev) +{ + unsigned int cap; + cap = pci_find_capability(dev, PCI_CAP_ID_PCIE); + + pcie_update_cfg(dev, cap + 0x28, ~(1 << 10), 1 << 10); +} + +static unsigned char pciexp_L1_substate_cal(device_t dev, unsigned int endp_cap, + unsigned int *data) +{ + unsigned char mult[4] = {2, 10, 100, 0}; + + unsigned int L1SubStateSupport = *data & 0xf; + unsigned int comm_mode_rst_time = (*data >> 8) & 0xff; + unsigned int power_on_scale = (*data >> 16) & 0x3; + unsigned int power_on_value = (*data >> 19) & 0x1f; + + unsigned int endp_data = pci_mmio_read_config32(dev, endp_cap + 4); + unsigned int endp_L1SubStateSupport = endp_data & 0xf; + unsigned int endp_comm_mode_restore_time = (endp_data >> 8) & 0xff; + unsigned int endp_power_on_scale = (endp_data >> 16) & 0x3; + unsigned int endp_power_on_value = (endp_data >> 19) & 0x1f; + + L1SubStateSupport &= endp_L1SubStateSupport; + + if (L1SubStateSupport == 0) + return 0; + + if (power_on_value * mult[power_on_scale] < + endp_power_on_value * mult[endp_power_on_scale]) { + power_on_value = endp_power_on_value; + power_on_scale = endp_power_on_scale; + } + if (comm_mode_rst_time < endp_comm_mode_restore_time) + comm_mode_rst_time = endp_comm_mode_restore_time; + + *data = (comm_mode_rst_time << 8) | (power_on_scale << 16) + | (power_on_value << 19) | L1SubStateSupport; + + return 1; +} + +static void pciexp_L1_substate_commit(device_t root, device_t dev, + unsigned int root_cap, unsigned int end_cap) +{ + device_t dev_t; + unsigned char L1_ss_ok; + unsigned int rp_L1_support = pci_mmio_read_config32(root, root_cap + 4); + unsigned int L1SubStateSupport; + unsigned int comm_mode_rst_time; + unsigned int power_on_scale; + unsigned int endp_power_on_value; + + for (dev_t = dev; dev_t; dev_t = dev_t->sibling) { + /* + * rp_L1_support is init'd above from root port. + * it needs coordination with endpoints to reach in common. + * if certain endpoint doesn't support L1 Sub-State, abort + * this feature enabling. + */ + L1_ss_ok = pciexp_L1_substate_cal(dev_t, end_cap, + &rp_L1_support); + if (!L1_ss_ok) + return; + } + + L1SubStateSupport = rp_L1_support & 0xf; + comm_mode_rst_time = (rp_L1_support >> 8) & 0xff; + power_on_scale = (rp_L1_support >> 16) & 0x3; + endp_power_on_value = (rp_L1_support >> 19) & 0x1f; + + printk(BIOS_INFO, "L1 Sub-State supported from root port %d\n", + root->path.pci.devfn >> 3); + printk(BIOS_INFO, "L1 Sub-State Support = 0x%x\n", L1SubStateSupport); + printk(BIOS_INFO, "CommonModeRestoreTime = 0x%x\n", comm_mode_rst_time); + printk(BIOS_INFO, "Power On Value = 0x%x, Power On Scale = 0x%x\n", + endp_power_on_value, power_on_scale); + + pciexp_enable_ltr(root); + + pcie_update_cfg(root, root_cap + 0x08, ~0xff00, + (comm_mode_rst_time << 8)); + + pcie_update_cfg(root, root_cap + 0x0c , 0xffffff04, + (endp_power_on_value << 3) | (power_on_scale)); + + pcie_update_cfg(root, root_cap + 0x08, ~0xe3ff0000, + (1 << 21) | (1 << 23) | (1 << 30)); + + pcie_update_cfg(root, root_cap + 0x08, ~0xf, + L1SubStateSupport); + + for (dev_t = dev; dev_t; dev_t = dev_t->sibling) { + pcie_update_cfg(dev_t, end_cap + 0x08, ~0xff00, + (comm_mode_rst_time << 8)); + + pcie_update_cfg(dev_t, end_cap + 0x0c , 0xffffff04, + (endp_power_on_value << 3) | (power_on_scale)); + + pcie_update_cfg(dev_t, end_cap + 0x08, ~0xe3ff0000, + (1 << 21) | (1 << 23) | (1 << 30)); + + pcie_update_cfg(dev_t, end_cap + 0x08, ~0xf, + L1SubStateSupport); + + pciexp_enable_ltr(dev_t); + + pciexp_config_max_latency(root, dev_t); + } +} + +static void pciexp_config_L1_sub_state(device_t root, device_t dev) +{ + unsigned int root_cap, end_cap; + + /* Do it for function 0 only */ + if (dev->path.pci.devfn & 0x7) + return; + + root_cap = pciexp_find_extended_cap(root, PCIE_EXT_CAP_L1SS_ID); + if (!root_cap) + return; + + end_cap = pciexp_find_extended_cap(dev, PCIE_EXT_CAP_L1SS_ID); + if (!end_cap) { + end_cap = pciexp_find_extended_cap(dev, 0xcafe); + if (!end_cap) + return; + } + + pciexp_L1_substate_commit(root, dev, root_cap, end_cap); +} +#endif /* CONFIG_PCIEXP_L1_SUB_STATE */ + #if CONFIG_PCIEXP_ASPM /* * Determine the ASPM L0s or L1 exit latency for a link @@ -200,6 +394,16 @@ static void pciexp_tune_dev(device_t dev) pciexp_enable_common_clock(root, root_cap, dev, cap); #endif +#if CONFIG_PCIEXP_CLK_PM + /* Check if per port CLK req is supported by endpoint*/ + pciexp_enable_clock_power_pm(dev, cap); +#endif + +#if CONFIG_PCIEXP_L1_SUB_STATE + /* Enable L1 Sub-State when both root port and endpoint support */ + pciexp_config_L1_sub_state(root, dev); +#endif /* CONFIG_PCIEXP_L1_SUB_STATE */ + #if CONFIG_PCIEXP_ASPM /* Check for and enable ASPM */ enum aspm_type apmc = pciexp_enable_aspm(root, root_cap, dev, cap); diff --git a/src/device/pnp_device.c b/src/device/pnp_device.c index da691f8efe..2cbc0fa2e1 100644 --- a/src/device/pnp_device.c +++ b/src/device/pnp_device.c @@ -269,6 +269,16 @@ static void get_resources(device_t dev, struct pnp_info *info) resource->size = 1; resource->flags |= IORESOURCE_IRQ; } + if (info->flags & PNP_MSC4) { + resource = new_resource(dev, PNP_IDX_MSC4); + resource->size = 1; + resource->flags |= IORESOURCE_IRQ; + } + if (info->flags & PNP_MSC10) { + resource = new_resource(dev, PNP_IDX_MSC10); + resource->size = 1; + resource->flags |= IORESOURCE_IRQ; + } } void pnp_enable_devices(device_t base_dev, struct device_operations *ops, diff --git a/src/device/software_i2c.c b/src/device/software_i2c.c new file mode 100644 index 0000000000..518aa5faf7 --- /dev/null +++ b/src/device/software_i2c.c @@ -0,0 +1,346 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include + +/* + * The implementation is based on Wikipedia. + */ + +#define DEBUG 0 /* Set to 1 for per-byte output */ +#define SPEW 0 /* Set to 1 for verbose bitwise/line-state output */ +#define DELAY_US 5 /* Default setup delay: 4us (+1 for timer inaccuracy) */ +#define TIMEOUT_US 50000 /* Maximum clock stretching time we want to allow */ + +#define spew(...) do { if (SPEW) printk(BIOS_SPEW, ##__VA_ARGS__); } while (0) + +struct software_i2c_ops *software_i2c[SOFTWARE_I2C_MAX_BUS]; + +/* + * Waits until either timeout_us have passed or (iff for_scl is set) until SCL + * goes high. Will report random line changes during the wait and return SCL. + */ +static int __wait(unsigned bus, int timeout_us, int for_scl) +{ + int us; + int sda = software_i2c[bus]->get_sda(bus); + int scl = software_i2c[bus]->get_scl(bus); + struct stopwatch sw; + + stopwatch_init_usecs_expire(&sw, timeout_us); + + do { + int old_sda = sda; + int old_scl = scl; + + us = stopwatch_duration_usecs(&sw); + + if (old_sda != (sda = software_i2c[bus]->get_sda(bus))) + spew("[SDA transitioned to %d after %dus] ", sda, us); + if (old_scl != (scl = software_i2c[bus]->get_scl(bus))) + spew("[SCL transitioned to %d after %dus] ", scl, us); + } while (!stopwatch_expired(&sw) && (!for_scl || !scl)); + + return scl; +} + +/* Waits the default DELAY_US to allow line state to stabilize. */ +static void wait(unsigned bus) +{ + __wait(bus, DELAY_US, 0); +} + +/* Waits until SCL goes high. Prints a contextual error message on timeout. */ +static int wait_for_scl(unsigned bus, const char *error_context) +{ + if (!__wait(bus, TIMEOUT_US, 1)) { + printk(BIOS_ERR, "software_i2c(%d): ERROR: Clock stretching " + "timeout %s!\n", bus, error_context); + return -1; + } + + return 0; +} + +static int start_cond(unsigned bus) +{ + spew("software_i2c(%d): Sending start condition... ", bus); + + /* SDA might not yet be high if repeated start. */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + + /* Might need to wait for clock stretching if repeated start. */ + software_i2c[bus]->set_scl(bus, 1); + if (wait_for_scl(bus, "before start condition")) + return -1; + wait(bus); /* Repeated start setup time, minimum 4.7us */ + + if (!software_i2c[bus]->get_sda(bus)) { + printk(BIOS_ERR, "software_i2c(%d): Arbitration lost trying " + "to send start condition!\n", bus); + return -1; + } + + /* SCL is high, transition SDA low as first part of start condition. */ + software_i2c[bus]->set_sda(bus, 0); + wait(bus); + assert(software_i2c[bus]->get_scl(bus)); + + /* Pull SCL low to finish start condition (next pulse will be data). */ + software_i2c[bus]->set_scl(bus, 0); + + spew("Start condition transmitted!\n"); + return 0; +} + +static int stop_cond(unsigned bus) +{ + spew("software_i2c(%d): Sending stop condition... ", bus); + + /* SDA is unknown, set it to low. SCL must be low. */ + software_i2c[bus]->set_sda(bus, 0); + wait(bus); + + /* Clock stretching */ + assert(!software_i2c[bus]->get_scl(bus)); + software_i2c[bus]->set_scl(bus, 1); + if (wait_for_scl(bus, "before stop condition")) + return -1; + wait(bus); /* Stop bit setup time, minimum 4us */ + + /* SCL is high, transition SDA high to signal stop condition. */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + if (!software_i2c[bus]->get_sda(bus)) { + printk(BIOS_WARNING, "software_i2c(%d): WARNING: SDA low after " + "stop condition... access by another master or line " + "stuck from faulty slave?\n", bus); + /* Could theoretically happen with multi-master, so no -1. */ + } + + spew("Stop condition transmitted\n"); + return 0; +} + +static int out_bit(unsigned bus, int bit) +{ + spew("software_i2c(%d): Sending a %d bit... ", bus, bit); + + software_i2c[bus]->set_sda(bus, bit); + wait(bus); + + if (bit && !software_i2c[bus]->get_sda(bus)) { + printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low " + "by slave before clock pulse on transmit!\n", bus); + return -1; + } + + /* Clock stretching */ + assert(!software_i2c[bus]->get_scl(bus)); + software_i2c[bus]->set_scl(bus, 1); + if (wait_for_scl(bus, "on transmit")) + return -1; + wait(bus); + + if (bit && !software_i2c[bus]->get_sda(bus)) { + printk(BIOS_ERR, "software_i2c(%d): ERROR: SDA wedged low " + "by slave after clock pulse on transmit!\n", bus); + return -1; + } + + assert(software_i2c[bus]->get_scl(bus)); + software_i2c[bus]->set_scl(bus, 0); + + spew("%d bit sent!\n", bit); + return 0; +} + +static int in_bit(unsigned bus) +{ + int bit; + + spew("software_i2c(%d): Receiving a bit... ", bus); + + /* Let the slave drive data */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + + /* Clock stretching */ + assert(!software_i2c[bus]->get_scl(bus)); + software_i2c[bus]->set_scl(bus, 1); + if (wait_for_scl(bus, "on receive")) + return -1; + + /* SCL is high, now data is valid */ + bit = software_i2c[bus]->get_sda(bus); + wait(bus); + assert(software_i2c[bus]->get_scl(bus)); + software_i2c[bus]->set_scl(bus, 0); + + spew("Received a %d!\n", bit); + + return bit; +} + +/* Write a byte to I2C bus. Return 0 if ack by the slave. */ +static int out_byte(unsigned bus, u8 byte) +{ + unsigned bit; + int nack; + + for (bit = 0; bit < 8; bit++) + if (out_bit(bus, (byte >> (7 - bit)) & 0x1) < 0) + return -1; + + nack = in_bit(bus); + + if (DEBUG && nack >= 0) + printk(BIOS_DEBUG, "software_i2c(%d): wrote byte 0x%02x, " + "received %s\n", bus, byte, nack ? "NAK" : "ACK"); + + return nack; +} + +static int in_byte(unsigned bus, int ack) +{ + u8 byte = 0; + int i; + for (i = 0; i < 8; ++i) { + int bit = in_bit(bus); + if (bit < 0) + return -1; + byte = (byte << 1) | bit; + } + + if (out_bit(bus, !ack) < 0) + return -1; + + if (DEBUG) + printk(BIOS_DEBUG, "software_i2c(%d): read byte 0x%02x, " + "sent %s\n", bus, byte, ack ? "ACK" : "NAK"); + + return byte; +} + +int software_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) +{ + int i; + struct i2c_seg *seg; + + for (seg = segments; seg - segments < count; seg++) { + if (start_cond(bus) < 0) + return -1; + if (out_byte(bus, seg->chip << 1 | !!seg->read) < 0) + return -1; + for (i = 0; i < seg->len; i++) { + int ret; + if (seg->read) { + ret = in_byte(bus, i < seg->len - 1); + seg->buf[i] = (u8)ret; + } else { + ret = out_byte(bus, seg->buf[i]); + } + if (ret < 0) + return -1; + } + } + if (stop_cond(bus) < 0) + return -1; + + return 0; +} + +void software_i2c_wedge_ack(unsigned bus, u8 chip) +{ + int i; + + /* Start a command to 'chip'... */ + start_cond(bus); + + /* Send the address bits but don't yet read the ACK. */ + chip <<= 1; + for (i = 0; i < 8; ++i) + out_bit(bus, (chip >> (7 - i)) & 0x1); + + /* Let the slave drive it's ACK but keep the clock high forever. */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + software_i2c[bus]->set_scl(bus, 1); + wait_for_scl(bus, "on wedge_ack()"); + + printk(BIOS_INFO, "software_i2c(%d): wedged address write on slave " + "ACK. SDA %d, SCL %d\n", bus, software_i2c[bus]->get_sda(bus), + software_i2c[bus]->get_scl(bus)); +} + +void software_i2c_wedge_read(unsigned bus, u8 chip, u8 reg, int bits) +{ + int i; + + /* Start a command to 'chip'... */ + start_cond(bus); + out_byte(bus, chip << 1); + /* ...for register 'reg'. */ + out_byte(bus, reg); + + /* Start a read command... */ + start_cond(bus); + out_byte(bus, chip << 1 | 1); + + /* Read bit_count bits and stop */ + for (i = 0; i < bits; ++i) + in_bit(bus); + + /* Let the slave drive SDA but keep the clock high forever. */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + software_i2c[bus]->set_scl(bus, 1); + wait_for_scl(bus, "on wedge_read()"); + + printk(BIOS_INFO, "software_i2c(%d): wedged data read after %d bits. " + "SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus), + software_i2c[bus]->get_scl(bus)); +} + +void software_i2c_wedge_write(unsigned bus, u8 chip, u8 reg, int bits) +{ + int i; + + /* Start a command to 'chip'... */ + start_cond(bus); + out_byte(bus, chip << 1); + + /* Write bit_count register bits and stop */ + for (i = 0; i < bits; ++i) + out_bit(bus, (reg >> (7 - i)) & 0x1); + + /* Pretend to write another 1 bit but keep the clock high forever. */ + software_i2c[bus]->set_sda(bus, 1); + wait(bus); + software_i2c[bus]->set_scl(bus, 1); + wait_for_scl(bus, "on wedge_write()"); + + printk(BIOS_INFO, "software_i2c(%d): wedged data write after %d bits. " + "SDA %d, SCL %d\n", bus, bits, software_i2c[bus]->get_sda(bus), + software_i2c[bus]->get_scl(bus)); +} diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig index 315d291bcb..c8734906e2 100644 --- a/src/drivers/Kconfig +++ b/src/drivers/Kconfig @@ -17,20 +17,25 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## +source src/drivers/ams/Kconfig source src/drivers/ati/Kconfig source src/drivers/dec/Kconfig source src/drivers/elog/Kconfig source src/drivers/emulation/Kconfig source src/drivers/generic/Kconfig +source src/drivers/gic/Kconfig source src/drivers/i2c/Kconfig source src/drivers/ics/Kconfig +source src/drivers/intel/Kconfig source src/drivers/ipmi/Kconfig source src/drivers/maxim/Kconfig source src/drivers/oxford/Kconfig +source src/drivers/parade/Kconfig if PC80_SYSTEM source src/drivers/pc80/Kconfig endif source src/drivers/realtek/Kconfig source src/drivers/sil/Kconfig source src/drivers/spi/Kconfig +source src/drivers/ti/Kconfig source src/drivers/trident/Kconfig diff --git a/src/drivers/Makefile.inc b/src/drivers/Makefile.inc index 16d60019f1..4063759229 100644 --- a/src/drivers/Makefile.inc +++ b/src/drivers/Makefile.inc @@ -17,18 +17,23 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## +subdirs-y += ams subdirs-y += ati subdirs-y += dec subdirs-y += emulation subdirs-y += generic +subdirs-y += gic subdirs-y += i2c +subdirs-y += intel subdirs-y += maxim subdirs-y += oxford +subdirs-y += parade subdirs-y += realtek subdirs-y += sil subdirs-y += trident subdirs-y += ics subdirs-y += spi +subdirs-y += ti subdirs-y += ipmi subdirs-y += elog subdirs-$(CONFIG_ARCH_X86) += pc80 diff --git a/src/drivers/ams/Kconfig b/src/drivers/ams/Kconfig new file mode 100644 index 0000000000..44b89c5f0c --- /dev/null +++ b/src/drivers/ams/Kconfig @@ -0,0 +1,11 @@ +config DRIVERS_AS3722_RTC + bool "AS3722 RTC support" + default n + +config DRIVERS_AS3722_RTC_BUS + int "AS3722 RTC bus" + depends on DRIVERS_AS3722_RTC + +config DRIVERS_AS3722_RTC_ADDR + hex "AS3722 RTC chip address" + depends on DRIVERS_AS3722_RTC diff --git a/src/drivers/ams/Makefile.inc b/src/drivers/ams/Makefile.inc new file mode 100644 index 0000000000..cf5183196c --- /dev/null +++ b/src/drivers/ams/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_DRIVERS_AS3722_RTC) += as3722rtc.c diff --git a/src/drivers/ams/as3722rtc.c b/src/drivers/ams/as3722rtc.c new file mode 100644 index 0000000000..8fe5748e16 --- /dev/null +++ b/src/drivers/ams/as3722rtc.c @@ -0,0 +1,91 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +enum AS3722_RTC_REG +{ + AS3722_RTC_CONTROL = 0x60, + AS3722_RTC_SECOND = 0x61, + AS3722_RTC_MINUTE = 0x62, + AS3722_RTC_HOUR = 0x63, + AS3722_RTC_DAY = 0x64, + AS3722_RTC_MONTH = 0x65, + AS3722_RTC_YEAR = 0x66 +}; + +enum { + AS3722_RTC_CONTROL_ON = 0x1 << 2 +}; + +static uint8_t as3722_read(enum AS3722_RTC_REG reg) +{ + uint8_t val; + i2c_readb(CONFIG_DRIVERS_AS3722_RTC_BUS, + CONFIG_DRIVERS_AS3722_RTC_ADDR, reg, &val); + return val; +} + +static void as3722_write(enum AS3722_RTC_REG reg, uint8_t val) +{ + i2c_writeb(CONFIG_DRIVERS_AS3722_RTC_BUS, + CONFIG_DRIVERS_AS3722_RTC_ADDR, reg, val); +} + +static void as3722rtc_init(void) +{ + static int initialized; + if (initialized) + return; + + uint8_t control = as3722_read(AS3722_RTC_CONTROL); + as3722_write(AS3722_RTC_CONTROL, control | AS3722_RTC_CONTROL_ON); + + initialized = 1; +} + +int rtc_set(const struct rtc_time *time) +{ + as3722rtc_init(); + + as3722_write(AS3722_RTC_SECOND, bin2bcd(time->sec)); + as3722_write(AS3722_RTC_MINUTE, bin2bcd(time->min)); + as3722_write(AS3722_RTC_HOUR, bin2bcd(time->hour)); + as3722_write(AS3722_RTC_DAY, bin2bcd(time->mday)); + as3722_write(AS3722_RTC_MONTH, bin2bcd(time->mon + 1)); + as3722_write(AS3722_RTC_YEAR, bin2bcd(time->year)); + return 0; +} + +int rtc_get(struct rtc_time *time) +{ + as3722rtc_init(); + + time->sec = bcd2bin(as3722_read(AS3722_RTC_SECOND) & 0x7f); + time->min = bcd2bin(as3722_read(AS3722_RTC_MINUTE) & 0x7f); + time->hour = bcd2bin(as3722_read(AS3722_RTC_HOUR) & 0x3f); + time->mday = bcd2bin(as3722_read(AS3722_RTC_DAY) & 0x3f); + time->mon = bcd2bin(as3722_read(AS3722_RTC_MONTH) & 0x1f) - 1; + time->year = bcd2bin(as3722_read(AS3722_RTC_YEAR) & 0x7f); + return 0; +} diff --git a/src/drivers/elog/elog.c b/src/drivers/elog/elog.c index 1a794d90ab..4331409916 100644 --- a/src/drivers/elog/elog.c +++ b/src/drivers/elog/elog.c @@ -17,10 +17,16 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ +#if CONFIG_HAVE_ACPI_RESUME == 1 #include +#endif #include #include +#if CONFIG_ARCH_X86 #include +#endif +#include +#include #include #include #include @@ -57,19 +63,33 @@ /* * Static variables for ELOG state */ +static struct elog_area *elog_area; +static u16 total_size; +static u16 log_size; +static u32 flash_base; + +static elog_area_state area_state; +static elog_header_state header_state; +static elog_event_buffer_state event_buffer_state; + +static u16 next_event_offset; +static u16 event_count; + static int elog_initialized; static struct spi_flash *elog_spi; -static struct elog_descriptor elog_flash_area; -static struct elog_descriptor elog_mem_area; -static inline struct elog_descriptor* elog_get_mem(void) -{ - return &elog_mem_area; -} -static inline struct elog_descriptor* elog_get_flash(void) +static inline u32 get_rom_size(void) { - return &elog_flash_area; + u32 rom_size; + + /* Assume the used space of the ROM image starts from 0. The + * physical size of the device may not be completely used. */ + rom_size = elog_spi->size; + if (rom_size > CONFIG_ROM_SIZE) + rom_size = CONFIG_ROM_SIZE; + + return rom_size; } /* @@ -77,55 +97,28 @@ static inline struct elog_descriptor* elog_get_flash(void) */ static inline u32 elog_flash_address_to_offset(u8 *address) { +#if CONFIG_ARCH_X86 + /* For x86, assume address is memory-mapped near 4GB */ + u32 rom_size; + if (!elog_spi) return 0; - return (u32)address - ((u32)~0UL - elog_spi->size + 1); -} -/* - * Convert a flash offset into a memory mapped flash address - */ -static inline u8* elog_flash_offset_to_address(u32 offset) -{ - if (!elog_spi) - return NULL; - return (u8*)((u32)~0UL - elog_spi->size + 1 + offset); -} + rom_size = get_rom_size(); -/* - * The ELOG header is at the very beginning of the area - */ -static inline struct elog_header* -elog_get_header(struct elog_descriptor *elog) -{ - return elog->backing_store; + return (u32)address - ((u32)~0UL - rom_size + 1); +#else + return (u32)(uintptr_t)address; +#endif } /* * Pointer to an event log header in the event data area */ static inline struct event_header* -elog_get_event_base(struct elog_descriptor *elog, u32 offset) +elog_get_event_base(u32 offset) { - return (struct event_header *)&elog->data[offset]; -} - -/* - * Pointer to where the next event should be stored - */ -static inline struct event_header* -elog_get_next_event_base(struct elog_descriptor *elog) -{ - return elog_get_event_base(elog, elog->next_event_offset); -} - -/* - * Pointer to the last logged event - */ -static inline struct event_header* -elog_get_last_event_base(struct elog_descriptor *elog) -{ - return elog_get_event_base(elog, elog->last_event_offset); + return (struct event_header *)&elog_area->data[offset]; } /* @@ -153,7 +146,7 @@ static u8 elog_checksum_event(struct event_header *event) /* * Check if a raw buffer is filled with ELOG_TYPE_EOL byte */ -static int elog_is_buffer_clear(u8 *base, u32 size) +static int elog_is_buffer_clear(void *base, u32 size) { u8 *current = base; u8 *end = current + size; @@ -167,26 +160,18 @@ static int elog_is_buffer_clear(u8 *base, u32 size) return 1; } -/* - * Verify whether ELOG area is filled with ELOG_TYPE_EOL byte - */ -static int elog_is_area_clear(struct elog_descriptor *elog) -{ - return elog_is_buffer_clear(elog->backing_store, elog->total_size); -} - /* * Check that the ELOG area has been initialized and is valid. */ -static int elog_is_area_valid(struct elog_descriptor *elog) +static int elog_is_area_valid(void) { elog_debug("elog_is_area_valid()\n"); - if (elog->area_state != ELOG_AREA_HAS_CONTENT) + if (area_state != ELOG_AREA_HAS_CONTENT) return 0; - if (elog->header_state != ELOG_HEADER_VALID) + if (header_state != ELOG_HEADER_VALID) return 0; - if (elog->event_buffer_state != ELOG_EVENT_BUFFER_OK) + if (event_buffer_state != ELOG_EVENT_BUFFER_OK) return 0; return 1; } @@ -210,7 +195,7 @@ static int elog_is_header_valid(struct elog_header *header) return 0; } if (header->header_size != sizeof(*header)) { - printk(BIOS_ERR, "ELOG: header size mismatch %u != %u\n", + printk(BIOS_ERR, "ELOG: header size mismatch %u != %zu\n", header->header_size, sizeof(*header)); return 0; } @@ -220,17 +205,17 @@ static int elog_is_header_valid(struct elog_header *header) /* * Validate the event header and data. */ -static int elog_is_event_valid(struct elog_descriptor *elog, u32 offset) +static int elog_is_event_valid(u32 offset) { struct event_header *event; - event = elog_get_event_base(elog, offset); + event = elog_get_event_base(offset); if (!event) return 0; /* Validate event length */ if ((offsetof(struct event_header, type) + - sizeof(event->type) - 1 + offset) >= elog->data_size) + sizeof(event->type) - 1 + offset) >= log_size) return 0; /* End of event marker has been found */ @@ -239,14 +224,14 @@ static int elog_is_event_valid(struct elog_descriptor *elog, u32 offset) /* Check if event fits in area */ if ((offsetof(struct event_header, length) + - sizeof(event->length) - 1 + offset) >= elog->data_size) + sizeof(event->length) - 1 + offset) >= log_size) return 0; /* * If the current event length + the current offset exceeds * the area size then the event area is corrupt. */ - if ((event->length + offset) >= elog->data_size) + if ((event->length + offset) >= log_size) return 0; /* Event length must be at least header size + checksum */ @@ -262,45 +247,40 @@ static int elog_is_event_valid(struct elog_descriptor *elog, u32 offset) } /* - * Write 'size' bytes of data provided in 'buffer' into flash - * device at offset 'offset'. This will not erase the flash and - * it assumes the flash area is erased appropriately. + * Write 'size' bytes of data pointed to by 'address' in the flash backing + * store into flash. This will not erase the flash and it assumes the flash + * area has been erased appropriately. */ -static void elog_flash_write(u8 *address, u8 *buffer, u32 size) +static void elog_flash_write(void *address, u32 size) { - struct elog_descriptor *flash = elog_get_flash(); u32 offset; - if (!address || !buffer || !size || !elog_spi) + if (!address || !size || !elog_spi) return; - offset = flash->flash_base; - offset += address - (u8*)flash->backing_store; + offset = flash_base; + offset += (u8 *)address - (u8 *)elog_area; - elog_debug("elog_flash_write(address=0x%p offset=0x%08x buffer=0x%p " - "size=%u)\n", address, offset, buffer, size); + elog_debug("elog_flash_write(address=0x%p offset=0x%08x size=%u)\n", + address, offset, size); /* Write the data to flash */ - elog_spi->write(elog_spi, offset, size, buffer); - - /* Update the copy in memory */ - memcpy(address, buffer, size); + elog_spi->write(elog_spi, offset, size, address); } /* * Erase the first block specified in the address. * Only handles flash area within a single flash block. */ -static void elog_flash_erase(u8 *address, u32 size) +static void elog_flash_erase(void *address, u32 size) { - struct elog_descriptor *flash = elog_get_flash(); u32 offset; if (!address || !size || !elog_spi) return; - offset = flash->flash_base; - offset += address - (u8*)flash->backing_store; + offset = flash_base; + offset += (u8 *)address - (u8*)elog_area; elog_debug("elog_flash_erase(address=0x%p offset=0x%08x size=%u)\n", address, offset, size); @@ -310,27 +290,24 @@ static void elog_flash_erase(u8 *address, u32 size) } /* - * Scan the event area and validate each entry and - * update the ELOG descriptor state. + * Scan the event area and validate each entry and update the ELOG state. */ -static void elog_update_event_buffer_state(struct elog_descriptor *elog) +static void elog_update_event_buffer_state(void) { u32 count = 0; u32 offset = 0; - u32 last_offset = 0; - u32 last_event_size = 0; struct event_header *event; elog_debug("elog_update_event_buffer_state()\n"); /* Go through each event and validate it */ while (1) { - event = elog_get_event_base(elog, offset); + event = elog_get_event_base(offset); /* Do not de-reference anything past the area length */ if ((offsetof(struct event_header, type) + - sizeof(event->type) - 1 + offset) >= elog->data_size) { - elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; + sizeof(event->type) - 1 + offset) >= log_size) { + event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; break; } @@ -339,292 +316,73 @@ static void elog_update_event_buffer_state(struct elog_descriptor *elog) break; /* Validate the event */ - if (!elog_is_event_valid(elog, offset)) { - elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; + if (!elog_is_event_valid(offset)) { + event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; break; } /* Move to the next event */ count++; - last_offset = offset; - last_event_size = event->length; offset += event->length; } /* Ensure the remaining buffer is empty */ - if (!elog_is_buffer_clear(&elog->data[offset], - elog->data_size - offset)) - elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; + if (!elog_is_buffer_clear(&elog_area->data[offset], log_size - offset)) + event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED; - /* Update data into elog descriptor */ - elog->event_count = count; - elog->next_event_offset = offset; - elog->last_event_offset = last_offset; - elog->last_event_size = last_event_size; + /* Update ELOG state */ + event_count = count; + next_event_offset = offset; } -static void elog_validate_and_fill(struct elog_descriptor *elog) +static void elog_scan_flash(void) { - elog_debug("elog_validate_and_fill()\n"); + elog_debug("elog_scan_flash()\n"); - /* Check if the area is empty or not */ - if (elog_is_area_clear(elog)) { - elog->area_state = ELOG_AREA_EMPTY; - return; - } - - elog->area_state = ELOG_AREA_HAS_CONTENT; - - /* Validate the header */ - if (!elog_is_header_valid(elog->staging_header)) { - elog->header_state = ELOG_HEADER_INVALID; - return; - } - - elog->header_state = ELOG_HEADER_VALID; - elog_update_event_buffer_state(elog); -} - -/* - * Initialize a new ELOG descriptor - */ -static void elog_init_descriptor(struct elog_descriptor *elog, - elog_descriptor_type type, - u8 *buffer, u32 size, - struct elog_header *header) -{ - elog_debug("elog_init_descriptor(type=%u buffer=0x%p size=%u)\n", - type, buffer, size); - - elog->type = type; - elog->area_state = ELOG_AREA_UNDEFINED; - elog->header_state = ELOG_HEADER_INVALID; - elog->event_buffer_state = ELOG_EVENT_BUFFER_OK; - elog->backing_store = buffer; - elog->total_size = size; + area_state = ELOG_AREA_UNDEFINED; + header_state = ELOG_HEADER_INVALID; + event_buffer_state = ELOG_EVENT_BUFFER_OK; /* Fill memory buffer by reading from SPI */ - if (type == ELOG_DESCRIPTOR_FLASH) - elog_spi->read(elog_spi, elog->flash_base, size, buffer); + elog_spi->read(elog_spi, flash_base, total_size, elog_area); - /* Get staging header from backing store */ - elog->staging_header = header; - memcpy(header, buffer, sizeof(struct elog_header)); + next_event_offset = 0; + event_count = 0; - /* Data starts immediately after header */ - elog->data = &buffer[sizeof(struct elog_header)]; - elog->data_size = size - sizeof(struct elog_header); - - elog->next_event_offset = 0; - elog->last_event_offset = 0; - elog->last_event_size = 0; - elog->event_count = 0; - - elog_validate_and_fill(elog); -} - -/* - * Re-initialize an existing ELOG descriptor - */ -static void elog_reinit_descriptor(struct elog_descriptor *elog) -{ - elog_debug("elog_reinit_descriptor()\n"); - elog_init_descriptor(elog, elog->type, elog->backing_store, - elog->total_size, elog->staging_header); -} - -/* - * Create ELOG descriptor data structures for all ELOG areas. - */ -static int elog_setup_descriptors(u32 flash_base, u32 area_size) -{ - struct elog_header *staging_header; - u8 *area; - - elog_debug("elog_setup_descriptors(base=0x%08x size=%u)\n", - flash_base, area_size); - - /* Prepare flash descriptors */ - if (flash_base == 0) { - printk(BIOS_ERR, "ELOG: Invalid flash base\n"); - return -1; + /* Check if the area is empty or not */ + if (elog_is_buffer_clear(elog_area, total_size)) { + area_state = ELOG_AREA_EMPTY; + return; } - staging_header = malloc(sizeof(struct elog_header)); - if (!staging_header) { - printk(BIOS_ERR, "ELOG: Unable to allocate header\n"); - return -1; + area_state = ELOG_AREA_HAS_CONTENT; + + /* Validate the header */ + if (!elog_is_header_valid(&elog_area->header)) { + header_state = ELOG_HEADER_INVALID; + return; } - area = malloc(area_size); - if (!area) { - printk(BIOS_ERR, "ELOG: Unable to determine flash address\n"); - return -1; - } - elog_get_flash()->flash_base = flash_base; - elog_init_descriptor(elog_get_flash(), ELOG_DESCRIPTOR_FLASH, - area, area_size, staging_header); - - /* Initialize the memory area to look like a cleared flash area */ - area = malloc(area_size); - if (!area) { - printk(BIOS_ERR, "ELOG: Unable to allocate mem area\n"); - return -1; - } - memset(area, ELOG_TYPE_EOL, area_size); - elog_init_descriptor(elog_get_mem(), ELOG_DESCRIPTOR_MEMORY, - area, area_size, (struct elog_header *)area); - - return 0; + header_state = ELOG_HEADER_VALID; + elog_update_event_buffer_state(); } -static void elog_flash_erase_area(void) -{ - struct elog_descriptor *elog = elog_get_flash(); - - elog_debug("elog_flash_erase_area()\n"); - - elog_flash_erase(elog->backing_store, elog->total_size); - memset(elog->backing_store, ELOG_TYPE_EOL, elog->total_size); - elog_reinit_descriptor(elog); -} - -static void elog_prepare_empty(struct elog_descriptor *elog, - u8 *data, u32 data_size) +static void elog_prepare_empty(void) { struct elog_header *header; - elog_debug("elog_prepare_empty(%u bytes)\n", data_size); - - if (!elog_is_area_clear(elog)) - return; + elog_debug("elog_prepare_empty()\n"); /* Write out the header */ - header = elog->staging_header; + header = &elog_area->header; header->magic = ELOG_SIGNATURE; header->version = ELOG_VERSION; header->header_size = sizeof(struct elog_header); header->reserved[0] = ELOG_TYPE_EOL; header->reserved[1] = ELOG_TYPE_EOL; - elog_flash_write(elog->backing_store, (u8*)header, - header->header_size); + elog_flash_write(elog_area, header->header_size); - /* Write out the data */ - if (data) - elog_flash_write(elog->data, data, data_size); - - elog_reinit_descriptor(elog); - - /* Clear the log if corrupt */ - if (!elog_is_area_valid(elog)) - elog_flash_erase_area(); -} - -static int elog_sync_flash_to_mem(void) -{ - struct elog_descriptor *mem = elog_get_mem(); - struct elog_descriptor *flash = elog_get_flash(); - - elog_debug("elog_sync_flash_to_mem()\n"); - - /* Fill with empty pattern first */ - memset(mem->backing_store, ELOG_TYPE_EOL, mem->total_size); - - /* Read the header from SPI to memory */ - elog_spi->read(elog_spi, flash->flash_base, - sizeof(struct elog_header), mem->backing_store); - - /* Read the valid flash contents from SPI to memory */ - elog_spi->read(elog_spi, flash->flash_base + sizeof(struct elog_header), - flash->next_event_offset, mem->data); - - elog_reinit_descriptor(mem); - - return elog_is_area_valid(mem) ? 0 : -1; -} - -static int elog_sync_mem_to_flash(void) -{ - struct elog_descriptor *mem = elog_get_mem(); - struct elog_descriptor *flash = elog_get_flash(); - u8 *src, *dest; - u32 size; - - elog_debug("elog_sync_mem_to_flash()\n"); - - /* - * In the case of a BIOS flash the active area will be cleared. - * One can catch this case and log the proper shutdown event by - * checking if the active flash elog is empty. Note that if the - * header size changes we will have corrupted the flash area. - * However that will be corrected on the next boot. - */ - if (elog_is_area_clear(flash)) { - elog_prepare_empty(flash, - (u8*)elog_get_last_event_base(mem), - mem->last_event_size); - elog_sync_flash_to_mem(); - return 0; - } - - /* Calculate the destination and source bases */ - dest = (u8*)elog_get_next_event_base(flash); - src = (u8*)elog_get_event_base(mem, flash->next_event_offset); - - /* Calculate how much data to sync */ - size = mem->next_event_offset - flash->next_event_offset; - - /* Write the log data */ - elog_flash_write(dest, src, size); - - /* Update descriptor */ - flash->event_count = mem->event_count; - flash->next_event_offset = mem->next_event_offset; - flash->last_event_offset = mem->last_event_offset; - flash->last_event_size = mem->last_event_size; - - return 0; -} - -/* - * Called during ELOG entry handler to prepare state for flash. - */ -static int elog_flash_area_bootstrap(void) -{ - struct elog_descriptor *elog = elog_get_flash(); - - elog_debug("elog_flash_area_bootstrap()\n"); - - switch (elog->area_state) { - case ELOG_AREA_UNDEFINED: - printk(BIOS_ERR, "ELOG: flash area undefined\n"); - return -1; - - case ELOG_AREA_EMPTY: - /* Write a new header with no data */ - elog_prepare_empty(elog, NULL, 0); - break; - - case ELOG_AREA_HAS_CONTENT: - break; - } - - if (elog->header_state == ELOG_HEADER_INVALID) { - /* If the header is invalid no events can be salvaged - * so erase the entire area. */ - printk(BIOS_ERR, "ELOG: flash area header invalid\n"); - elog_flash_erase_area(); - elog_prepare_empty(elog, NULL, 0); - } - - if (elog->event_buffer_state == ELOG_EVENT_BUFFER_CORRUPTED) { - /* Wipe the source flash area */ - elog_flash_erase_area(); - elog_prepare_empty(elog, elog_get_mem()->data, - elog_get_mem()->next_event_offset); - } - - return 0; + elog_scan_flash(); } /* @@ -633,14 +391,14 @@ static int elog_flash_area_bootstrap(void) */ static int elog_shrink(void) { - struct elog_descriptor *mem = elog_get_mem(); struct event_header *event; u16 discard_count = 0; u16 offset = 0; + u16 new_size = 0; elog_debug("elog_shrink()\n"); - if (mem->next_event_offset < CONFIG_ELOG_SHRINK_SIZE) + if (next_event_offset < CONFIG_ELOG_SHRINK_SIZE) return 0; while (1) { @@ -648,7 +406,7 @@ static int elog_shrink(void) if (offset > CONFIG_ELOG_SHRINK_SIZE) break; - event = elog_get_event_base(mem, offset); + event = elog_get_event_base(offset); /* Reached the end of the area */ if (!event || event->type == ELOG_TYPE_EOL) @@ -658,17 +416,17 @@ static int elog_shrink(void) discard_count++; } - /* Erase flash area */ - elog_flash_erase_area(); + new_size = next_event_offset - offset; + memmove(&elog_area->data[0], &elog_area->data[offset], new_size); + memset(&elog_area->data[new_size], ELOG_TYPE_EOL, log_size - new_size); - /* Write new flash area */ - elog_prepare_empty(elog_get_flash(), - (u8*)elog_get_event_base(mem, offset), - mem->next_event_offset - offset); + elog_flash_erase(elog_area, total_size); + elog_flash_write(elog_area, total_size); + elog_scan_flash(); - /* Update memory area from flash */ - if (elog_sync_flash_to_mem() < 0) { - printk(BIOS_ERR, "Unable to update memory area from flash\n"); + /* Ensure the area was successfully erased */ + if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) { + printk(BIOS_ERR, "ELOG: Flash area was not erased!\n"); return -1; } @@ -678,46 +436,46 @@ static int elog_shrink(void) return 0; } +#ifndef __SMM__ +#if IS_ENABLED(CONFIG_ARCH_X86) + /* - * Initialize the SPI bus and probe for a flash chip + * Convert a flash offset into a memory mapped flash address */ -static int elog_spi_init(void) +static inline u8 *elog_flash_offset_to_address(u32 offset) { - elog_debug("elog_spi_init()\n"); + u32 rom_size; - /* Prepare SPI subsystem */ - spi_init(); + if (!elog_spi) + return NULL; - /* Look for flash chip */ - elog_spi = spi_flash_probe(0, 0, 0, 0); + rom_size = get_rom_size(); - return elog_spi ? 0 : -1; + return (u8 *)((u32)~0UL - rom_size + 1 + offset); } -#ifndef __SMM__ /* * Fill out SMBIOS Type 15 table entry so the * event log can be discovered at runtime. */ int elog_smbios_write_type15(unsigned long *current, int handle) { - struct elog_descriptor *flash = elog_get_flash(); struct smbios_type15 *t = (struct smbios_type15 *)*current; int len = sizeof(struct smbios_type15); #if CONFIG_ELOG_CBMEM /* Save event log buffer into CBMEM for the OS to read */ - void *cbmem = cbmem_add(CBMEM_ID_ELOG, flash->total_size); + void *cbmem = cbmem_add(CBMEM_ID_ELOG, total_size); if (!cbmem) return 0; - memcpy(cbmem, flash->backing_store, flash->total_size); + memcpy(cbmem, elog_area, total_size); #endif memset(t, 0, len); t->type = SMBIOS_EVENT_LOG; t->length = len - 2; t->handle = handle; - t->area_length = flash->total_size - 1; + t->area_length = total_size - 1; t->header_offset = 0; t->data_offset = sizeof(struct elog_header); t->access_method = SMBIOS_EVENTLOG_ACCESS_METHOD_MMIO32; @@ -726,7 +484,7 @@ int elog_smbios_write_type15(unsigned long *current, int handle) #if CONFIG_ELOG_CBMEM t->address = (u32)cbmem; #else - t->address = (u32)elog_flash_offset_to_address(flash->flash_base); + t->address = (u32)elog_flash_offset_to_address(flash_base); #endif t->header_format = ELOG_HEADER_TYPE_OEM; t->log_type_descriptors = 0; @@ -736,116 +494,147 @@ int elog_smbios_write_type15(unsigned long *current, int handle) return len; } #endif +#endif /* * Clear the entire event log */ int elog_clear(void) { - struct elog_descriptor *flash = elog_get_flash(); - elog_debug("elog_clear()\n"); + /* Make sure ELOG structures are initialized */ + if (elog_init() < 0) + return -1; + /* Erase flash area */ - elog_flash_erase_area(); + elog_flash_erase(elog_area, total_size); + elog_prepare_empty(); - /* Prepare new empty area */ - elog_prepare_empty(flash, NULL, 0); - - /* Update memory area from flash */ - if (elog_sync_flash_to_mem() < 0) + if (!elog_is_area_valid()) return -1; /* Log the clear event */ - elog_add_event_word(ELOG_TYPE_LOG_CLEAR, flash->total_size); + elog_add_event_word(ELOG_TYPE_LOG_CLEAR, total_size); return 0; } +static void elog_find_flash(void) +{ +#if CONFIG_CHROMEOS + u8 *flash_base_ptr; +#endif + + elog_debug("elog_find_flash()\n"); + +#if CONFIG_CHROMEOS + /* Find the ELOG base and size in FMAP */ + total_size = find_fmap_entry("RW_ELOG", (void **)&flash_base_ptr); + if (total_size < 0) { + printk(BIOS_WARNING, "ELOG: Unable to find RW_ELOG in FMAP, " + "using CONFIG_ELOG_FLASH_BASE instead\n"); + total_size = CONFIG_ELOG_AREA_SIZE; + } else { + flash_base = elog_flash_address_to_offset(flash_base_ptr); + + /* Use configured size if smaller than FMAP size */ + if (total_size > CONFIG_ELOG_AREA_SIZE) + total_size = CONFIG_ELOG_AREA_SIZE; + } +#else + flash_base = CONFIG_ELOG_FLASH_BASE; + total_size = CONFIG_ELOG_AREA_SIZE; +#endif + log_size = total_size - sizeof(struct elog_header); +} + /* * Event log main entry point */ int elog_init(void) { - u32 flash_base = CONFIG_ELOG_FLASH_BASE; - int flash_size = CONFIG_ELOG_AREA_SIZE; -#if CONFIG_CHROMEOS - u8 *flash_base_ptr; -#endif - if (elog_initialized) return 0; elog_debug("elog_init()\n"); - /* Find SPI flash chip for backing store */ - if (elog_spi_init() < 0) { + /* Probe SPI chip. SPI controller must already be initialized. */ + elog_spi = spi_flash_probe(CONFIG_BOOT_MEDIA_SPI_BUS, 0); + if (!elog_spi) { printk(BIOS_ERR, "ELOG: Unable to find SPI flash\n"); return -1; } -#if CONFIG_CHROMEOS - /* Find the ELOG base and size in FMAP */ - flash_size = find_fmap_entry("RW_ELOG", (void **)&flash_base_ptr); - if (flash_size < 0) { - printk(BIOS_WARNING, "ELOG: Unable to find RW_ELOG in FMAP, " - "using CONFIG_ELOG_FLASH_BASE instead\n"); - flash_size = CONFIG_ELOG_AREA_SIZE; - } else { - flash_base = elog_flash_address_to_offset(flash_base_ptr); - - /* Use configured size if smaller than FMAP size */ - if (flash_size > CONFIG_ELOG_AREA_SIZE) - flash_size = CONFIG_ELOG_AREA_SIZE; - } -#endif - - /* Setup descriptors for flash and memory areas */ - if (elog_setup_descriptors(flash_base, flash_size) < 0) { - printk(BIOS_ERR, "ELOG: Unable to initialize descriptors\n"); + /* Set up the backing store */ + elog_find_flash(); + if (flash_base == 0) { + printk(BIOS_ERR, "ELOG: Invalid flash base\n"); return -1; } - /* Bootstrap the flash area */ - if (elog_flash_area_bootstrap() < 0) { - printk(BIOS_ERR, "ELOG: Unable to bootstrap flash area\n"); + elog_area = malloc(total_size); + if (!elog_area) { + printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n"); return -1; } - /* Initialize the memory area */ - if (elog_sync_flash_to_mem() < 0) { - printk(BIOS_ERR, "ELOG: Unable to initialize memory area\n"); + /* Load the log from flash */ + elog_scan_flash(); + + /* Prepare the flash if necessary */ + if (header_state == ELOG_HEADER_INVALID || + event_buffer_state == ELOG_EVENT_BUFFER_CORRUPTED) { + /* If the header is invalid or the events are corrupted, + * no events can be salvaged so erase the entire area. */ + printk(BIOS_ERR, "ELOG: flash area invalid\n"); + elog_flash_erase(elog_area, total_size); + elog_prepare_empty(); + } + + if (area_state == ELOG_AREA_EMPTY) + elog_prepare_empty(); + + if (!elog_is_area_valid()) { + printk(BIOS_ERR, "ELOG: Unable to prepare flash\n"); return -1; } elog_initialized = 1; - printk(BIOS_INFO, "ELOG: MEM @0x%p FLASH @0x%p [SPI 0x%08x]\n", - elog_get_mem()->backing_store, - elog_get_flash()->backing_store, elog_get_flash()->flash_base); + printk(BIOS_INFO, "ELOG: FLASH @0x%p [SPI 0x%08x]\n", + elog_area, flash_base); - printk(BIOS_INFO, "ELOG: areas are %d bytes, full threshold %d," - " shrink size %d\n", CONFIG_ELOG_AREA_SIZE, + printk(BIOS_INFO, "ELOG: area is %d bytes, full threshold %d," + " shrink size %d\n", total_size, CONFIG_ELOG_FULL_THRESHOLD, CONFIG_ELOG_SHRINK_SIZE); /* Log a clear event if necessary */ - if (elog_get_flash()->event_count == 0) - elog_add_event_word(ELOG_TYPE_LOG_CLEAR, - elog_get_flash()->total_size); + if (event_count == 0) + elog_add_event_word(ELOG_TYPE_LOG_CLEAR, total_size); /* Shrink the log if we are getting too full */ - if (elog_get_mem()->next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) - elog_shrink(); + if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) + if (elog_shrink() < 0) + return -1; -#if CONFIG_ELOG_BOOT_COUNT && !defined(__SMM__) +#if !defined(__SMM__) /* Log boot count event except in S3 resume */ - if (acpi_slp_type != 3) +#if CONFIG_ELOG_BOOT_COUNT == 1 +#if CONFIG_HAVE_ACPI_RESUME == 1 + if (acpi_slp_type != 3) +#endif elog_add_event_dword(ELOG_TYPE_BOOT, boot_count_read()); +#else + /* If boot count is not implemented, fake it. */ + elog_add_event_dword(ELOG_TYPE_BOOT, 0); #endif -#if CONFIG_CMOS_POST && !defined(__SMM__) +#if CONFIG_ARCH_X86 /* Check and log POST codes from previous boot */ - cmos_post_log(); + if (CONFIG_CMOS_POST) + cmos_post_log(); +#endif #endif return 0; @@ -856,12 +645,15 @@ int elog_init(void) */ static void elog_fill_timestamp(struct event_header *event) { - event->second = cmos_read(RTC_CLK_SECOND); - event->minute = cmos_read(RTC_CLK_MINUTE); - event->hour = cmos_read(RTC_CLK_HOUR); - event->day = cmos_read(RTC_CLK_DAYOFMONTH); - event->month = cmos_read(RTC_CLK_MONTH); - event->year = cmos_read(RTC_CLK_YEAR); + struct rtc_time time; + + rtc_get(&time); + event->second = bin2bcd(time.sec); + event->minute = bin2bcd(time.min); + event->hour = bin2bcd(time.hour); + event->day = bin2bcd(time.mday); + event->month = bin2bcd(time.mon); + event->year = bin2bcd(time.year % 100); /* Basic sanity check of expected ranges */ if (event->month > 0x12 || event->day > 0x31 || event->hour > 0x23 || @@ -876,37 +668,36 @@ static void elog_fill_timestamp(struct event_header *event) } /* - * Add an event to the memory area + * Add an event to the log */ -static int elog_add_event_mem(u8 event_type, void *data, u8 data_size) +void elog_add_event_raw(u8 event_type, void *data, u8 data_size) { struct event_header *event; - struct elog_descriptor *mem = elog_get_mem(); u8 event_size; - elog_debug("elog_add_event_mem(type=%X)\n", event_type); + elog_debug("elog_add_event_raw(type=%X)\n", event_type); /* Make sure ELOG structures are initialized */ if (elog_init() < 0) - return -1; + return; /* Header + Data + Checksum */ event_size = sizeof(*event) + data_size + 1; if (event_size > MAX_EVENT_SIZE) { printk(BIOS_ERR, "ELOG: Event(%X) data size too " "big (%d)\n", event_type, event_size); - return -1; + return; } /* Make sure event data can fit */ - if ((mem->next_event_offset + event_size) >= mem->data_size) { + if ((next_event_offset + event_size) >= log_size) { printk(BIOS_ERR, "ELOG: Event(%X) does not fit\n", event_type); - return -1; + return; } /* Fill out event data */ - event = elog_get_next_event_base(mem); + event = elog_get_event_base(next_event_offset); event->type = event_type; event->length = event_size; elog_fill_timestamp(event); @@ -918,32 +709,18 @@ static int elog_add_event_mem(u8 event_type, void *data, u8 data_size) elog_update_checksum(event, 0); elog_update_checksum(event, -(elog_checksum_event(event))); - /* Update memory descriptor parameters */ - mem->event_count++; - mem->last_event_offset = mem->next_event_offset; - mem->last_event_size = event_size; - mem->next_event_offset += event_size; + /* Update the ELOG state */ + event_count++; + + elog_flash_write((void *)event, event_size); + + next_event_offset += event_size; printk(BIOS_INFO, "ELOG: Event(%X) added with size %d\n", event_type, event_size); - return 0; -} - -void elog_add_event_raw(u8 event_type, void *data, u8 data_size) -{ - elog_debug("elog_add_event_raw(type=%X)\n", event_type); - - /* Add event to the memory area */ - if (elog_add_event_mem(event_type, data, data_size) < 0) { - printk(BIOS_ERR, "Unable to add event to memory area\n"); - return; - } - - /* Sync the memory buffer to flash */ - elog_sync_mem_to_flash(); /* Shrink the log if we are getting too full */ - if (elog_get_mem()->next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) + if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) elog_shrink(); } diff --git a/src/drivers/elog/elog_internal.h b/src/drivers/elog/elog_internal.h index f6aa051007..dd282311a6 100644 --- a/src/drivers/elog/elog_internal.h +++ b/src/drivers/elog/elog_internal.h @@ -47,12 +47,6 @@ struct event_header { /* SMBIOS Type 15 related constants */ #define ELOG_HEADER_TYPE_OEM 0x88 -typedef enum elog_descriptor_type { - ELOG_DESCRIPTOR_UNKNOWN, - ELOG_DESCRIPTOR_MEMORY, - ELOG_DESCRIPTOR_FLASH, -} elog_descriptor_type; - typedef enum elog_area_state { ELOG_AREA_UNDEFINED, /* Initial boot strap state */ ELOG_AREA_EMPTY, /* Entire area is empty */ @@ -69,24 +63,9 @@ typedef enum elog_event_buffer_state { ELOG_EVENT_BUFFER_CORRUPTED, } elog_event_buffer_state; -/* - * Internal handler for event log buffers - */ -struct elog_descriptor { - elog_descriptor_type type; - elog_area_state area_state; - elog_header_state header_state; - elog_event_buffer_state event_buffer_state; - struct elog_header *staging_header; - void *backing_store; - u8 *data; - u32 flash_base; - u16 total_size; - u16 data_size; - u16 next_event_offset; - u16 last_event_offset; - u16 last_event_size; - u16 event_count; -}; +struct elog_area { + struct elog_header header; + u8 data[0]; +} __attribute__((packed)); #endif /* ELOG_INTERNAL_H_ */ diff --git a/src/drivers/generic/ioapic/ioapic.c b/src/drivers/generic/ioapic/ioapic.c index 9a93c78336..42b2f071f3 100644 --- a/src/drivers/generic/ioapic/ioapic.c +++ b/src/drivers/generic/ioapic/ioapic.c @@ -12,18 +12,6 @@ #include #include -static u32 io_apic_read(u32 ioapic_base, u32 reg) -{ - write32(ioapic_base, reg); - return read32(ioapic_base + 0x10); -} - -static void io_apic_write(u32 ioapic_base, u32 reg, u32 value) -{ - write32(ioapic_base, reg); - write32(ioapic_base + 0x10, value); -} - static void ioapic_init(device_t dev) { struct drivers_generic_ioapic_config *config = dev->chip_info; diff --git a/src/drivers/gic/Kconfig b/src/drivers/gic/Kconfig new file mode 100644 index 0000000000..193311fc05 --- /dev/null +++ b/src/drivers/gic/Kconfig @@ -0,0 +1,4 @@ +config GIC + def_bool n + help + This option enables GIC support, the ARM generic interrupt controller. diff --git a/src/drivers/gic/Makefile.inc b/src/drivers/gic/Makefile.inc new file mode 100644 index 0000000000..51e3e199e2 --- /dev/null +++ b/src/drivers/gic/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_GIC) += gic.c diff --git a/src/drivers/gic/gic.c b/src/drivers/gic/gic.c new file mode 100644 index 0000000000..885d2216be --- /dev/null +++ b/src/drivers/gic/gic.c @@ -0,0 +1,120 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include "gic.h" + +enum { + ENABLE_GRP0 = 0x1 << 0, + ENABLE_GRP1 = 0x1 << 1, +}; + +struct gic { + struct gicd_mmio *gicd; + struct gicc_mmio *gicc; + size_t num_interrupts; + unsigned int version; + unsigned int security_extensions; +}; + +static struct gic *gic_get(void) +{ + static struct gic gic; + + if (gic.gicd == NULL) { + uint32_t typer; + + gic.gicd = gicd_base(); + gic.gicc = gicc_base(); + typer = read32(&gic.gicd->typer); + gic.num_interrupts = 32 * ((typer & 0x1f) + 1); + gic.security_extensions = !!(typer & (1 << 10)); + gic.version = (read32(&gic.gicd->icpidr2) & 0xf0) >> 4; + + printk(BIOS_DEBUG, "GICv%d - %zu ints %s GICD=%p GICC=%p\n", + gic.version, gic.num_interrupts, + gic.security_extensions ? "SecExtn" : "", + gic.gicd, gic.gicc); + } + + return &gic; +} + +static inline void gic_write(uint32_t *base, uint32_t val) +{ + write32(val, base); +} + +static void gic_write_regs(uint32_t *base, size_t num_regs, uint32_t val) +{ + size_t i; + + for (i = 0; i < num_regs; i++) + gic_write(base++, val); +} + +static void gic_write_banked_regs(uint32_t *base, size_t interrupts_per_reg, + uint32_t val) +{ + /* 1st 32 interrupts are banked per CPU. */ + gic_write_regs(base, 32 / interrupts_per_reg, val); +} + +void gic_init(void) +{ + struct gic *gic; + struct gicd_mmio *gicd; + struct gicc_mmio *gicc; + uint32_t cpu_mask; + + gic = gic_get(); + gicd = gic->gicd; + gicc = gic->gicc; + + /* Enable Group 0 and Group 1 in GICD -- banked regs. */ + gic_write(&gicd->ctlr, ENABLE_GRP0 | ENABLE_GRP1); + + /* Enable Group 0 and Group 1 in GICC and enable all priroity levels. */ + gic_write(&gicc->ctlr, ENABLE_GRP0 | ENABLE_GRP1); + gic_write(&gicc->pmr, 1 << 7); + + cpu_mask = 1 << smp_processor_id(); + cpu_mask |= cpu_mask << 8; + cpu_mask |= cpu_mask << 16; + + /* Only write banked registers for secondary CPUs. */ + if (smp_processor_id()) { + gic_write_banked_regs(&gicd->itargetsr[0], 4, cpu_mask); + /* Put interrupts into Group 1. */ + gic_write_banked_regs(&gicd->igroupr[0], 32, ~0x0); + /* Allow Non-secure access to everything. */ + gic_write_banked_regs(&gicd->nsacr[0], 16, ~0x0); + return; + } + + /* All interrupts routed to processors that execute this function. */ + gic_write_regs(&gicd->itargetsr[0], gic->num_interrupts / 4, cpu_mask); + /* Put all interrupts into Gropup 1. */ + gic_write_regs(&gicd->igroupr[0], gic->num_interrupts / 32, ~0x0); + /* Allow Non-secure access to everything. */ + gic_write_regs(&gicd->nsacr[0], gic->num_interrupts / 16, ~0x0); +} diff --git a/src/drivers/gic/gic.h b/src/drivers/gic/gic.h new file mode 100644 index 0000000000..d6f8d097cb --- /dev/null +++ b/src/drivers/gic/gic.h @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DRIVERS_GIC_H +#define DRIVERS_GIC_H + +#include + +#define NR(start, end) (((end) - (start)) / sizeof(uint32_t)) + +struct gicd_mmio { + uint32_t ctlr; /* 0x000 - 0x003 */ + uint32_t typer; /* 0x004 - 0x007 */ + uint32_t iidr; /* 0x008 - 0x00b */ + uint32_t reserved_1[NR(0xc, 0x80)]; /* 0x00c - 0x07f */ + uint32_t igroupr[NR(0x80, 0x100)]; /* 0x080 - 0x0ff */ + uint32_t isenabler[NR(0x100, 0x180)]; /* 0x100 - 0x17f */ + uint32_t icenabler[NR(0x180, 0x200)]; /* 0x180 - 0x1ff */ + uint32_t ispendr[NR(0x200, 0x280)]; /* 0x200 - 0x27f */ + uint32_t icpendr[NR(0x280, 0x300)]; /* 0x280 - 0x2ff */ + uint32_t isactiver[NR(0x300, 0x380)]; /* 0x300 - 0x37f */ + uint32_t icactiver[NR(0x380, 0x400)]; /* 0x380 - 0x3ff */ + uint32_t ipriorityr[NR(0x400, 0x7fc)]; /* 0x400 - 0x7fb */ + uint32_t reserved_2[NR(0x7fc, 0x800)]; /* 0x7fc - 0x7ff */ + uint32_t itargetsr[NR(0x800, 0xbfc)]; /* 0x800 - 0xbfb */ + uint32_t reserved_3[NR(0xbfc, 0xc00)]; /* 0xbfc - 0x2ff */ + uint32_t icfgr[NR(0xc00, 0xd00)]; /* 0xc00 - 0xcff */ + uint32_t reserved_4[NR(0xd00, 0xe00)]; /* 0xd00 - 0xdff */ + uint32_t nsacr[NR(0xe00, 0xf00)]; /* 0xe00 - 0xeff */ + uint32_t sgir; /* 0xf00 - 0xf03 */ + uint32_t reserved_5[NR(0xf04, 0xf10)]; /* 0xf04 - 0xf0f */ + uint32_t cpendsgir[NR(0xf10, 0xf20)]; /* 0xf10 - 0xf1f */ + uint32_t spendsgir[NR(0xf20, 0xf30)]; /* 0xf20 - 0xf2f */ + uint32_t reserved_6[NR(0xf30, 0xfe8)]; /* 0xf30 - 0xfe7 */ + uint32_t icpidr2; /* 0xfe8 - 0xfeb */ + uint32_t reserved_7[NR(0xfec, 0x1000)]; /* 0xfec - 0xfff */ +}; + +struct gicc_mmio { + uint32_t ctlr; /* 0x000 - 0x003 */ + uint32_t pmr; /* 0x004 - 0x007 */ + uint32_t bpr; /* 0x008 - 0x00b */ + uint32_t iar; /* 0x00c - 0x00f */ + uint32_t eoir; /* 0x010 - 0x013 */ + uint32_t rpr; /* 0x014 - 0x017 */ + uint32_t hppir; /* 0x018 - 0x01b */ + uint32_t apbr; /* 0x01c - 0x01f */ + uint32_t aiar; /* 0x020 - 0x023 */ + uint32_t aeoir; /* 0x024 - 0x027 */ + uint32_t ahppir; /* 0x028 - 0x02b */ + uint32_t resered_1[NR(0x2c, 0xd0)]; /* 0x02c - 0x0cf */ + uint32_t apr[NR(0xd0, 0xe0)]; /* 0x0d0 - 0x0df */ + uint32_t nsapr[NR(0xe0, 0xf0)]; /* 0x0e0 - 0x0ef */ + uint32_t resered_2[NR(0xf0, 0xfc)]; /* 0x0f0 - 0x0fb */ + uint32_t iidr; /* 0x0fc - 0x0ff */ + uint32_t reserved_3[NR(0x100, 0x1000)]; /* 0x100 - 0xfff */ + uint32_t dir; /* 0x1000 - 0x1003 */ +}; + +#undef NR + +#endif /* DRIVERS_GIC_H */ diff --git a/src/drivers/i2c/Kconfig b/src/drivers/i2c/Kconfig index 4eb3f3f1f3..5c55c44d07 100644 --- a/src/drivers/i2c/Kconfig +++ b/src/drivers/i2c/Kconfig @@ -4,5 +4,7 @@ source src/drivers/i2c/adt7463/Kconfig source src/drivers/i2c/i2cmux/Kconfig source src/drivers/i2c/i2cmux2/Kconfig source src/drivers/i2c/lm63/Kconfig +source src/drivers/i2c/rtd2132/Kconfig +source src/drivers/i2c/tpm/Kconfig source src/drivers/i2c/w83795/Kconfig source src/drivers/i2c/w83793/Kconfig diff --git a/src/drivers/i2c/Makefile.inc b/src/drivers/i2c/Makefile.inc index 331b26c135..26d68d8244 100644 --- a/src/drivers/i2c/Makefile.inc +++ b/src/drivers/i2c/Makefile.inc @@ -4,5 +4,7 @@ subdirs-y += adt7463 subdirs-y += i2cmux subdirs-y += i2cmux2 subdirs-y += lm63 +subdirs-y += rtd2132 +subdirs-y += tpm subdirs-y += w83795 subdirs-y += w83793 diff --git a/src/drivers/i2c/rtd2132/Kconfig b/src/drivers/i2c/rtd2132/Kconfig new file mode 100644 index 0000000000..f76b14ff23 --- /dev/null +++ b/src/drivers/i2c/rtd2132/Kconfig @@ -0,0 +1,5 @@ +config DRIVERS_I2C_RTD2132 + bool + default n + help + Enable support for Realtek RTD2132 DisplayPort to LVDS bridge chip. diff --git a/src/drivers/i2c/rtd2132/Makefile.inc b/src/drivers/i2c/rtd2132/Makefile.inc new file mode 100644 index 0000000000..4974a479ce --- /dev/null +++ b/src/drivers/i2c/rtd2132/Makefile.inc @@ -0,0 +1 @@ +ramstage-$(CONFIG_DRIVERS_I2C_RTD2132) += rtd2132.c diff --git a/src/drivers/i2c/rtd2132/chip.h b/src/drivers/i2c/rtd2132/chip.h new file mode 100644 index 0000000000..2cf08270d3 --- /dev/null +++ b/src/drivers/i2c/rtd2132/chip.h @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +struct drivers_i2c_rtd2132_config { + /* Panel Power Sequencing. All units in ms. */ + u16 t1; /* Delay from panel Vcc enable to LVDS output enable. */ + u16 t2; /* Delay from LVDS output enable to PWM output enable. */ + u16 t3; /* Delay from PWM output enable to backlight output enable. */ + u16 t4; /* Delay from backlight output disable to PWM output disable. */ + u16 t5; /* Delay from PWM output disable to LVDS output disable. */ + u16 t6; /* Delay from LVDS output disable to panel Vcc disable. */ + u16 t7; /* Delay between tweo panel power on/off sequence. */ + + /* + * LVDS swap. + * 0x00 - Normal + * 0x01 - Mirror + * 0x02 - P/N + * 0x03 - Mirror + P/N + * 0x04 - R/L + * + * Dual Support or in bit 7: + * 0x80 - Dual Swap + */ + u8 lvds_swap; + + /* + * LVDS Spread Spectrum Clock + * 0x00 = DISABLED + * 0x05 = 0.5% + * 0x10 = 1.0% + * 0x15 = 1.5% + */ + u8 sscg_percent; +}; diff --git a/src/drivers/i2c/rtd2132/rtd2132.c b/src/drivers/i2c/rtd2132/rtd2132.c new file mode 100644 index 0000000000..22a9f03108 --- /dev/null +++ b/src/drivers/i2c/rtd2132/rtd2132.c @@ -0,0 +1,263 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "chip.h" + +/* Chip commands */ +#define RTD2132_COMMAND 0x01 +#define RTD2132_DATA 0x00 +#define RTD2132_FIRMWARE 0x80 +#define RTD2132_FIRMWARE_START 0x00 +#define RTD2132_FIRMWARE_STOP 0x01 + +/* Panel Power Sequence Timing Registers. */ +#define RTD2132_COMMAND_PWR_SEQ_T1 0x32 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T2 0x33 /* 4ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T3 0x34 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T4 0x35 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T5 0x36 /* 4ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T6 0x37 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T7 0x38 /* 4ms units. */ + +/* Spread spectrum configuration */ +#define RTD2132_COMMAND_SSCG_CONFIG_0 0x39 +#define RTD2132_SSCG_ENABLE 0xa0 +#define RTD2132_SSCG_DISABLE 0x20 +#define RTD2132_COMMAND_SSCG_CONFIG_1 0x3a +#define RTD2132_SSCG_CONFIG_DISABLED 0x01 /* DISABLED */ +#define RTD2132_SSCG_CONFIG_0_5 0x07 /* 0.5% */ +#define RTD2132_SSCG_CONFIG_1_0 0x0f /* 1.0% */ +#define RTD2132_SSCG_CONFIG_1_5 0x16 /* 1.5% */ + +/* LVDS Swap */ +#define RTD2132_COMMAND_LVDS_SWAP 0x3b +#define RTD2132_LVDS_SWAP_DUAL 0x80 +#define RTD2132_LVDS_SWAP_NORMAL 0x04 +#define RTD2132_LVDS_SWAP_MIRROR 0x14 +#define RTD2132_LVDS_SWAP_P_N 0x24 +#define RTD2132_LVDS_SWAP_MIRROR_P_N 0x34 +#define RTD2132_LVDS_SWAP_R_L 0x0c + +/* Configuration values from devicetree */ +#define RTD2132_SSCG_PERCENT_0_0 0x00 /* DISABLED */ +#define RTD2132_SSCG_PERCENT_0_5 0x05 /* 0.5% */ +#define RTD2132_SSCG_PERCENT_1_0 0x10 /* 1.0% */ +#define RTD2132_SSCG_PERCENT_1_5 0x15 /* 1.5% */ + +#define RTD2132_LVDS_SWAP_CFG_DUAL 0x80 +#define RTD2132_LVDS_SWAP_CFG_NORMAL 0x00 +#define RTD2132_LVDS_SWAP_CFG_MIRROR 0x01 +#define RTD2132_LVDS_SWAP_CFG_P_N 0x02 +#define RTD2132_LVDS_SWAP_CFG_MIRROR_P_N 0x03 +#define RTD2132_LVDS_SWAP_CFG_R_L 0x04 + +#define RTD2132_DEBUG_REG 0 + +static void rtd2132_write_reg(device_t dev, u8 reg, u8 value) +{ + if (RTD2132_DEBUG_REG) + printk(BIOS_DEBUG, "RTD2132 0x%02x <- 0x%02x\n", reg, value); + smbus_write_byte(dev, RTD2132_COMMAND, reg); + smbus_write_byte(dev, RTD2132_DATA, value); +} + +static void rtd2132_firmware_stop(device_t dev) +{ + smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_STOP); + mdelay(60); +} + +static void rtd2132_firmware_start(device_t dev) +{ + smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_START); +} + +static void rtd2132_pps(device_t dev, struct drivers_i2c_rtd2132_config *cfg) +{ + /* T2, T5, and T7 register values are in units of 4ms. */ + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T1, cfg->t1); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T2, cfg->t2 / 4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T3, cfg->t3); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T4, cfg->t4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T5, cfg->t5 / 4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T6, cfg->t6); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T7, cfg->t7 / 4); +} + +static void rtd2132_sscg_enable(device_t dev, u8 sscg_percent) +{ + /* SSCG_Config_0 */ + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0, + RTD2132_SSCG_ENABLE); + + /* SSCG_Config_1 */ + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1, sscg_percent); +} + +static void rtd2132_sscg_disable(device_t dev) +{ + /* SSCG_Config_0 */ + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0, + RTD2132_SSCG_DISABLE); + + /* SSCG_Config_1 */ + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1, + RTD2132_SSCG_CONFIG_DISABLED); +} + +static void rtd2132_sscg(device_t dev, struct drivers_i2c_rtd2132_config *cfg) +{ + switch (cfg->sscg_percent) { + case RTD2132_SSCG_PERCENT_0_0: + printk(BIOS_INFO, "RTD2132: Disable Spread Spectrum\n"); + rtd2132_sscg_disable(dev); + break; + case RTD2132_SSCG_PERCENT_0_5: + printk(BIOS_INFO, "RTD2132: Enable 0.5%% Spread Spectrum\n"); + rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_0_5); + break; + case RTD2132_SSCG_PERCENT_1_0: + printk(BIOS_INFO, "RTD2132: Enable 1.0%% Spread Spectrum\n"); + rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_1_0); + break; + case RTD2132_SSCG_PERCENT_1_5: + printk(BIOS_INFO, "RTD2132: Enable 1.5%% Spread Spectrum\n"); + rtd2132_sscg_enable(dev, RTD2132_SSCG_CONFIG_1_5); + break; + default: + printk(BIOS_ERR, "RTD2132: Invalid Spread Spectrum 0x%02x\n", + cfg->sscg_percent); + } +} + +static void rtd2132_lvds_swap(device_t dev, + struct drivers_i2c_rtd2132_config *cfg) +{ + u8 swap_value = RTD2132_LVDS_SWAP_NORMAL; + + switch (cfg->lvds_swap & ~RTD2132_LVDS_SWAP_CFG_DUAL) { + case RTD2132_LVDS_SWAP_CFG_NORMAL: + swap_value = RTD2132_LVDS_SWAP_NORMAL; + break; + case RTD2132_LVDS_SWAP_CFG_MIRROR: + swap_value = RTD2132_LVDS_SWAP_MIRROR; + break; + case RTD2132_LVDS_SWAP_CFG_P_N: + swap_value = RTD2132_LVDS_SWAP_P_N; + break; + case RTD2132_LVDS_SWAP_CFG_MIRROR_P_N: + swap_value = RTD2132_LVDS_SWAP_MIRROR_P_N; + break; + case RTD2132_LVDS_SWAP_CFG_R_L: + swap_value = RTD2132_LVDS_SWAP_R_L; + break; + default: + printk(BIOS_ERR, "RTD2132: Invalid LVDS swap value 0x%02x\n", + cfg->lvds_swap); + } + + if (cfg->lvds_swap & RTD2132_LVDS_SWAP_CFG_DUAL) + swap_value |= RTD2132_LVDS_SWAP_DUAL; + + printk(BIOS_INFO, "RTD2132: LVDS Swap 0x%02x\n", swap_value);; + + rtd2132_write_reg(dev, RTD2132_COMMAND_LVDS_SWAP, swap_value); +} + +static void rtd2132_defaults(device_t dev) +{ + static const struct def_setting { + u8 reg; + u8 value; + } def_settings[] = { + { 0x3c, 0x06 }, + { 0x3d, 0x38 }, + { 0x3e, 0x73 }, + { 0x3f, 0x33 }, + { 0x06, 0x90 }, + { 0x06, 0xb0 }, + { 0x06, 0x80 }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(def_settings); i++) + rtd2132_write_reg(dev, def_settings[i].reg, + def_settings[i].value); +} + +static void rtd2132_setup(device_t dev) +{ + struct drivers_i2c_rtd2132_config *config = dev->chip_info; + + if (!config) + return; + + /* Stop running firmware */ + rtd2132_firmware_stop(dev); + + /* Panel Power Sequencing Settings. */ + rtd2132_pps(dev, config); + + /* Spread spectrum configuration */ + rtd2132_sscg(dev, config); + + /* LVDS Swap Setting. */ + rtd2132_lvds_swap(dev, config); + + /* Default settings. */ + rtd2132_defaults(dev); + + /* Start firmware */ + rtd2132_firmware_start(dev); +} + +static void rtd2132_init(device_t dev) +{ + if (dev->enabled && dev->path.type == DEVICE_PATH_I2C && + ops_smbus_bus(get_pbus_smbus(dev))) { + rtd2132_setup(dev); + } +} + +static void rtd2132_noop(device_t dummy) +{ +} + +static struct device_operations rtd2132_operations = { + .read_resources = rtd2132_noop, + .set_resources = rtd2132_noop, + .enable_resources = rtd2132_noop, + .init = rtd2132_init, +}; + +static void enable_dev(struct device *dev) +{ + dev->ops = &rtd2132_operations; +} + +struct chip_operations drivers_i2c_rtd2132_ops = { + CHIP_NAME("Realtek RTD2132 LVDS Bridge") + .enable_dev = enable_dev, +}; diff --git a/src/drivers/i2c/tpm/Kconfig b/src/drivers/i2c/tpm/Kconfig new file mode 100644 index 0000000000..cb754bd212 --- /dev/null +++ b/src/drivers/i2c/tpm/Kconfig @@ -0,0 +1,14 @@ +config I2C_TPM + bool "I2C TPM" + depends on !PC80 # for now + +config DRIVER_TPM_I2C_BUS + hex "I2C TPM chip bus" + default 9 # FIXME, workaround for Kconfig BS + depends on I2C_TPM + +config DRIVER_TPM_I2C_ADDR + hex "I2C TPM chip address" + default 2 # FIXME, workaround for Kconfig BS + depends on I2C_TPM + diff --git a/src/drivers/i2c/tpm/Makefile.inc b/src/drivers/i2c/tpm/Makefile.inc new file mode 100644 index 0000000000..55c01def17 --- /dev/null +++ b/src/drivers/i2c/tpm/Makefile.inc @@ -0,0 +1,3 @@ +ramstage-$(CONFIG_I2C_TPM) += tis.c tpm.c +romstage-$(CONFIG_I2C_TPM) += tis.c tpm.c +verstage-$(CONFIG_I2C_TPM) += tis.c tpm.c \ No newline at end of file diff --git a/src/drivers/i2c/tpm/tis.c b/src/drivers/i2c/tpm/tis.c new file mode 100644 index 0000000000..696634d9d7 --- /dev/null +++ b/src/drivers/i2c/tpm/tis.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2011 Infineon Technologies + * Copyright 2013 Google Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "tpm.h" + +#include + +/* global structure for tpm chip data */ +struct tpm_chip g_chip; + +#define TPM_CMD_COUNT_BYTE 2 +#define TPM_CMD_ORDINAL_BYTE 6 + +int tis_open(void) +{ + int rc; + + if (g_chip.is_open) { + printk(BIOS_DEBUG, "tis_open() called twice.\n"); + return -1; + } + + rc = tpm_vendor_init(CONFIG_DRIVER_TPM_I2C_BUS, + CONFIG_DRIVER_TPM_I2C_ADDR); + + if (rc < 0) + g_chip.is_open = 0; + + if (rc) { + return -1; + } + + return 0; +} + +int tis_close(void) +{ + if (g_chip.is_open) { + tpm_vendor_cleanup(&g_chip); + g_chip.is_open = 0; + } + + return 0; +} + +int tis_init(void) +{ + int bus = CONFIG_DRIVER_TPM_I2C_BUS; + int chip = CONFIG_DRIVER_TPM_I2C_ADDR; + + /* + * Probe TPM twice; the first probing might fail because TPM is asleep, + * and the probing can wake up TPM. + */ + if (i2c_writeb(bus, chip, 0, 0) && i2c_writeb(bus, chip, 0, 0)) + return -1; + + return 0; +} + +static ssize_t tpm_transmit(const uint8_t *buf, size_t bufsiz) +{ + int rc; + uint32_t count, ordinal; + + struct tpm_chip *chip = &g_chip; + + memcpy(&count, buf + TPM_CMD_COUNT_BYTE, sizeof(count)); + count = be32_to_cpu(count); + memcpy(&ordinal, buf + TPM_CMD_ORDINAL_BYTE, sizeof(ordinal)); + ordinal = be32_to_cpu(ordinal); + + if (count == 0) { + printk(BIOS_DEBUG, "tpm_transmit: no data\n"); + return -1; + } + if (count > bufsiz) { + printk(BIOS_DEBUG, "tpm_transmit: invalid count value %x %zx\n", + count, bufsiz); + return -1; + } + + ASSERT(chip->vendor.send); + rc = chip->vendor.send(chip, (uint8_t *) buf, count); + if (rc < 0) { + printk(BIOS_DEBUG, "tpm_transmit: tpm_send error\n"); + goto out; + } + + if (chip->vendor.irq) + goto out_recv; + + int timeout = 2 * 60 * 1000; /* two minutes timeout */ + while (timeout) { + ASSERT(chip->vendor.status); + uint8_t status = chip->vendor.status(chip); + if ((status & chip->vendor.req_complete_mask) == + chip->vendor.req_complete_val) { + goto out_recv; + } + + if ((status == chip->vendor.req_canceled)) { + printk(BIOS_DEBUG, "tpm_transmit: Operation Canceled\n"); + rc = -1; + goto out; + } + mdelay(TPM_TIMEOUT); + timeout--; + } + + ASSERT(chip->vendor.cancel); + chip->vendor.cancel(chip); + printk(BIOS_DEBUG, "tpm_transmit: Operation Timed out\n"); + rc = -1; //ETIME; + goto out; + +out_recv: + + rc = chip->vendor.recv(chip, (uint8_t *) buf, TPM_BUFSIZE); + if (rc < 0) + printk(BIOS_DEBUG, "tpm_transmit: tpm_recv: error %d\n", rc); +out: + return rc; +} + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + uint8_t buf[TPM_BUFSIZE]; + + if (sizeof(buf) < sbuf_size) + return -1; + + memcpy(buf, sendbuf, sbuf_size); + + int len = tpm_transmit(buf, sbuf_size); + + if (len < 10) { + *rbuf_len = 0; + return -1; + } + + if (len > *rbuf_len) { + *rbuf_len = len; + return -1; + } + + memcpy(recvbuf, buf, len); + *rbuf_len = len; + + return 0; +} diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c new file mode 100644 index 0000000000..63ef29547f --- /dev/null +++ b/src/drivers/i2c/tpm/tpm.c @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2011 Infineon Technologies + * + * Authors: + * Peter Huewe + * + * Description: + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.2, revision 1.0 and the + * Infineon I2C Protocol Stack Specification v0.20. + * + * It is based on the Linux kernel driver tpm.c from Leendert van + * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. + * + * Version: 2.1.1 + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "tpm.h" + +/* Address of the TPM on the I2C bus */ +#define TPM_I2C_ADDR 0x20 + +/* max. number of iterations after I2C NAK */ +#define MAX_COUNT 3 + +#define SLEEP_DURATION 60 /* in usec */ + +/* max. number of iterations after I2C NAK for 'long' commands + * we need this especially for sending TPM_READY, since the cleanup after the + * transtion to the ready state may take some time, but it is unpredictable + * how long it will take. + */ +#define MAX_COUNT_LONG 50 + +#define SLEEP_DURATION_LONG 210 /* in usec */ + +/* expected value for DIDVID register */ +#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L + +enum i2c_chip_type { + SLB9635, + SLB9645, + UNKNOWN, +}; + +static const char * const chip_name[] = { + [SLB9635] = "slb9635tt", + [SLB9645] = "slb9645tt", + [UNKNOWN] = "unknown/fallback to slb9635", +}; + +/* Structure to store I2C TPM specific stuff */ +struct tpm_inf_dev { + int bus; + unsigned int addr; + uint8_t buf[TPM_BUFSIZE + sizeof(uint8_t)]; // max. buffer size + addr + enum i2c_chip_type chip_type; +}; + +static struct tpm_inf_dev tpm_dev = { + .bus = -1, + .addr = TPM_I2C_ADDR +}; + +/* + * iic_tpm_read() - read from TPM register + * @addr: register address to read from + * @buffer: provided by caller + * @len: number of bytes to read + * + * Read len bytes from TPM register and put them into + * buffer (little-endian format, i.e. first byte is put into buffer[0]). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * Return -1 on error, 0 on success. + */ +static int iic_tpm_read(uint8_t addr, uint8_t *buffer, size_t len) +{ + int rc; + int count; + + if (tpm_dev.bus < 0) + return -1; + if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { + /* slb9635 protocol should work in both cases */ + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_write_raw(tpm_dev.bus, tpm_dev.addr, &addr, 1); + if (rc == 0) + break; /* success, break to skip sleep */ + + udelay(SLEEP_DURATION); + } + + if (rc) + return -1; + + /* After the TPM has successfully received the register address + * it needs some time, thus we're sleeping here again, before + * retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + udelay(SLEEP_DURATION); + rc = i2c_read_raw(tpm_dev.bus, tpm_dev.addr, + buffer, len); + if (rc == 0) + break; /* success, break to skip sleep */ + + } + } else { + /* use a combined read for newer chips + * unfortunately the smbus functions are not suitable due to + * the 32 byte limit of the smbus. + * retries should usually not be needed, but are kept just to + * be safe on the safe side. + */ + struct i2c_seg aseg = { .read = 0, .chip = tpm_dev.addr, + .buf = &addr, .len = 1 }; + struct i2c_seg dseg = { .read = 1, .chip = tpm_dev.addr, + .buf = buffer, .len = len }; + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_transfer(tpm_dev.bus, &aseg, 1) || + i2c_transfer(tpm_dev.bus, &dseg, 1); + if (rc == 0) + break; /* break here to skip sleep */ + udelay(SLEEP_DURATION); + } + } + + /* take care of 'guard time' */ + udelay(SLEEP_DURATION); + if (rc) + return -1; + + return 0; +} + +static int iic_tpm_write_generic(uint8_t addr, uint8_t *buffer, size_t len, + unsigned int sleep_time, + uint8_t max_count) +{ + int rc = 0; + int count; + + if (len > TPM_BUFSIZE) { + printk(BIOS_DEBUG, "%s: Length %zd is too large\n", __func__, len); + return -1; + } + + /* prepare send buffer */ + tpm_dev.buf[0] = addr; + memcpy(&(tpm_dev.buf[1]), buffer, len); + + if (tpm_dev.bus < 0) + return -1; + for (count = 0; count < max_count; count++) { + rc = i2c_write_raw(tpm_dev.bus, tpm_dev.addr, + tpm_dev.buf, len + 1); + if (rc == 0) + break; /* success, break to skip sleep */ + + udelay(sleep_time); + } + + /* take care of 'guard time' */ + udelay(SLEEP_DURATION); + if (rc) + return -1; + + return 0; +} + +/* + * iic_tpm_write() - write to TPM register + * @addr: register address to write to + * @buffer: containing data to be written + * @len: number of bytes to write + * + * Write len bytes from provided buffer to TPM register (little + * endian format, i.e. buffer[0] is written as first byte). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * NOTE: use this function instead of the iic_tpm_write_generic function. + * + * Return -EIO on error, 0 on success + */ +static int iic_tpm_write(uint8_t addr, uint8_t *buffer, size_t len) +{ + return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION, + MAX_COUNT); +} + +/* + * This function is needed especially for the cleanup situation after + * sending TPM_READY + * */ +static int iic_tpm_write_long(uint8_t addr, uint8_t *buffer, size_t len) +{ + return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, + MAX_COUNT_LONG); +} + +#define TPM_HEADER_SIZE 10 + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) +#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) + +static int check_locality(struct tpm_chip *chip, int loc) +{ + uint8_t buf; + + if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) + return -1; + + if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { + chip->vendor.locality = loc; + return loc; + } + + return -1; +} + +static void release_locality(struct tpm_chip *chip, int loc, int force) +{ + uint8_t buf; + if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) + return; + + if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { + buf = TPM_ACCESS_ACTIVE_LOCALITY; + iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + } +} + +static int request_locality(struct tpm_chip *chip, int loc) +{ + uint8_t buf = TPM_ACCESS_REQUEST_USE; + + if (check_locality(chip, loc) >= 0) + return loc; /* we already have the locality */ + + iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + + /* wait for burstcount */ + int timeout = 2 * 1000; /* 2s timeout */ + while (timeout) { + if (check_locality(chip, loc) >= 0) + return loc; + mdelay(TPM_TIMEOUT); + timeout--; + } + + return -1; +} + +static uint8_t tpm_tis_i2c_status(struct tpm_chip *chip) +{ + /* NOTE: Since I2C read may fail, return 0 in this case --> time-out */ + uint8_t buf; + if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) + return 0; + else + return buf; +} + +static void tpm_tis_i2c_ready(struct tpm_chip *chip) +{ + /* this causes the current command to be aborted */ + uint8_t buf = TPM_STS_COMMAND_READY; + iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); +} + +static ssize_t get_burstcount(struct tpm_chip *chip) +{ + ssize_t burstcnt; + uint8_t buf[3]; + + /* wait for burstcount */ + int timeout = 2 * 1000; /* 2s timeout */ + while (timeout) { + /* Note: STS is little endian */ + if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) < 0) + burstcnt = 0; + else + burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; + + if (burstcnt) + return burstcnt; + mdelay(TPM_TIMEOUT); + timeout--; + } + return -1; +} + +static int wait_for_stat(struct tpm_chip *chip, uint8_t mask, int *status) +{ + unsigned long timeout = 2 * 1024; + while (timeout) { + *status = tpm_tis_i2c_status(chip); + if ((*status & mask) == mask) + return 0; + mdelay(TPM_TIMEOUT); + timeout--; + } + + return -1; +} + +static int recv_data(struct tpm_chip *chip, uint8_t *buf, size_t count) +{ + size_t size = 0; + + while (size < count) { + ssize_t burstcnt = get_burstcount(chip); + int rc; + + /* burstcount < 0 = TPM is busy */ + if (burstcnt < 0) + return burstcnt; + + /* limit received data to max. left */ + if (burstcnt > (count - size)) + burstcnt = count - size; + + rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), + &(buf[size]), + burstcnt); + if (rc == 0) + size += burstcnt; + + } + return size; +} + +static int tpm_tis_i2c_recv(struct tpm_chip *chip, uint8_t *buf, size_t count) +{ + int size = 0; + uint32_t expected; + int status; + + if (count < TPM_HEADER_SIZE) { + size = -1; + goto out; + } + + /* read first 10 bytes, including tag, paramsize, and result */ + size = recv_data(chip, buf, TPM_HEADER_SIZE); + if (size < TPM_HEADER_SIZE) { + printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Unable to read header\n"); + goto out; + } + + memcpy(&expected, buf + TPM_RSP_SIZE_BYTE, sizeof(expected)); + expected = be32_to_cpu(expected); + if ((size_t)expected > count) { + size = -1; + goto out; + } + + size += recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Unable to " + "read remainder of result\n"); + size = -1; + goto out; + } + + wait_for_stat(chip, TPM_STS_VALID, &status); + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + printk(BIOS_DEBUG, "tpm_tis_i2c_recv: Error left over data\n"); + size = -1; + goto out; + } + +out: + tpm_tis_i2c_ready(chip); + + return size; +} + +static int tpm_tis_i2c_send(struct tpm_chip *chip, uint8_t *buf, size_t len) +{ + int status; + size_t count = 0; + uint8_t sts = TPM_STS_GO; + + if (len > TPM_BUFSIZE) + return -1; /* command is too long for our TPM, sorry */ + + status = tpm_tis_i2c_status(chip); + if ((status & TPM_STS_COMMAND_READY) == 0) { + tpm_tis_i2c_ready(chip); + if (wait_for_stat(chip, TPM_STS_COMMAND_READY, &status) < 0) + goto out_err; + } + + while (count < len - 1) { + ssize_t burstcnt = get_burstcount(chip); + + /* burstcount < 0 = TPM is busy */ + if (burstcnt < 0) + return burstcnt; + + if (burstcnt > (len-1-count)) + burstcnt = len-1-count; + +#ifdef CONFIG_TPM_I2C_BURST_LIMITATION + if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION) + burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION; +#endif /* CONFIG_TPM_I2C_BURST_LIMITATION */ + + if (iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), + &(buf[count]), burstcnt) == 0) + count += burstcnt; + + wait_for_stat(chip, TPM_STS_VALID, &status); + if ((status & TPM_STS_DATA_EXPECT) == 0) + goto out_err; + } + + /* write last byte */ + iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); + + wait_for_stat(chip, TPM_STS_VALID, &status); + if ((status & TPM_STS_DATA_EXPECT) != 0) + goto out_err; + + /* go and do it */ + iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); + + return len; + +out_err: + tpm_tis_i2c_ready(chip); + + return -1; +} + +static struct tpm_vendor_specific tpm_tis_i2c = { + .status = tpm_tis_i2c_status, + .recv = tpm_tis_i2c_recv, + .send = tpm_tis_i2c_send, + .cancel = tpm_tis_i2c_ready, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = TPM_STS_COMMAND_READY, +}; + +/* Initialization of I2C TPM */ + +int tpm_vendor_init(unsigned bus, uint32_t dev_addr) +{ + uint32_t vendor; + unsigned int old_addr; + struct tpm_chip *chip; + extern struct tpm_chip g_chip; + + old_addr = tpm_dev.addr; + if (dev_addr != 0) + tpm_dev.addr = dev_addr; + tpm_dev.bus = bus; + + chip = &g_chip; + memcpy(&chip->vendor, &tpm_tis_i2c, sizeof(struct tpm_vendor_specific)); + chip->is_open = 1; + + /* Disable interrupts (not supported) */ + chip->vendor.irq = 0; + + if (request_locality(chip, 0) != 0) + goto out_err; + + /* Read four bytes from DID_VID register */ + if (iic_tpm_read(TPM_DID_VID(0), (uint8_t *)&vendor, 4) < 0) + goto out_release; + + if (vendor == TPM_TIS_I2C_DID_VID_9645) { + tpm_dev.chip_type = SLB9645; + } else if (be32_to_cpu(vendor) == TPM_TIS_I2C_DID_VID_9635) { + tpm_dev.chip_type = SLB9635; + } else { + printk(BIOS_DEBUG, "Vendor ID 0x%08x not recognized.\n", vendor); + goto out_release; + } + + printk(BIOS_DEBUG, "1.2 TPM (chip type %s device-id 0x%X)\n", + chip_name[tpm_dev.chip_type], vendor >> 16); + + /* + * A timeout query to TPM can be placed here. + * Standard timeout values are used so far + */ + + return 0; + +out_release: + release_locality(chip, 0, 1); + +out_err: + tpm_dev.addr = old_addr; + return -1; +} + +void tpm_vendor_cleanup(struct tpm_chip *chip) +{ + release_locality(chip, chip->vendor.locality, 1); +} diff --git a/src/drivers/i2c/tpm/tpm.h b/src/drivers/i2c/tpm/tpm.h new file mode 100644 index 0000000000..de88a661a3 --- /dev/null +++ b/src/drivers/i2c/tpm/tpm.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2011 Infineon Technologies + * + * Authors: + * Peter Huewe + * + * Version: 2.1.1 + * + * Description: + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * It is based on the Linux kernel driver tpm.c from Leendert van + * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. + * + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __DRIVERS_TPM_SLB9635_I2C_TPM_H__ +#define __DRIVERS_TPM_SLB9635_I2C_TPM_H__ + +#include + +enum tpm_timeout { + TPM_TIMEOUT = 1, /* msecs */ +}; + +/* Size of external transmit buffer (used for stack buffer in tpm_sendrecv) */ +#define TPM_BUFSIZE 1260 + +/* Index of fields in TPM command buffer */ +#define TPM_CMD_SIZE_BYTE 2 +#define TPM_CMD_ORDINAL_BYTE 6 + +/* Index of Count field in TPM response buffer */ +#define TPM_RSP_SIZE_BYTE 2 +#define TPM_RSP_RC_BYTE 6 + +struct tpm_chip; + +struct tpm_vendor_specific { + const uint8_t req_complete_mask; + const uint8_t req_complete_val; + const uint8_t req_canceled; + int irq; + int (*recv)(struct tpm_chip *, uint8_t *, size_t); + int (*send)(struct tpm_chip *, uint8_t *, size_t); + void (*cancel)(struct tpm_chip *); + uint8_t(*status)(struct tpm_chip *); + int locality; +}; + +struct tpm_chip { + int is_open; + struct tpm_vendor_specific vendor; +}; + +struct tpm_input_header { + uint16_t tag; + uint32_t length; + uint32_t ordinal; +} __attribute__ ((packed)); + +struct tpm_output_header { + uint16_t tag; + uint32_t length; + uint32_t return_code; +} __attribute__ ((packed)); + +struct timeout_t { + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; +} __attribute__ ((packed)); + +struct duration_t { + uint32_t tpm_short; + uint32_t tpm_medium; + uint32_t tpm_long; +} __attribute__ ((packed)); + +typedef union { + struct timeout_t timeout; + struct duration_t duration; +} cap_t; + +struct tpm_getcap_params_in { + uint32_t cap; + uint32_t subcap_size; + uint32_t subcap; +} __attribute__ ((packed)); + +struct tpm_getcap_params_out { + uint32_t cap_size; + cap_t cap; +} __attribute__ ((packed)); + +typedef union { + struct tpm_input_header in; + struct tpm_output_header out; +} tpm_cmd_header; + +typedef union { + struct tpm_getcap_params_out getcap_out; + struct tpm_getcap_params_in getcap_in; +} tpm_cmd_params; + +struct tpm_cmd_t { + tpm_cmd_header header; + tpm_cmd_params params; +} __attribute__ ((packed)); + +/* ---------- Interface for TPM vendor ------------ */ + +int tpm_vendor_init(unsigned bus, uint32_t dev_addr); + +void tpm_vendor_cleanup(struct tpm_chip *chip); + +#endif /* __DRIVERS_TPM_SLB9635_I2C_TPM_H__ */ diff --git a/src/drivers/intel/Kconfig b/src/drivers/intel/Kconfig new file mode 100644 index 0000000000..a94e06e4d0 --- /dev/null +++ b/src/drivers/intel/Kconfig @@ -0,0 +1,21 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +source src/drivers/intel/gma/Kconfig +source src/drivers/intel/fsp/Kconfig diff --git a/src/drivers/intel/Makefile.inc b/src/drivers/intel/Makefile.inc new file mode 100644 index 0000000000..e9e12ec0eb --- /dev/null +++ b/src/drivers/intel/Makefile.inc @@ -0,0 +1,2 @@ +subdirs-$(CONFIG_INTEL_DP) += gma +subdirs-$(CONFIG_PLATFORM_USES_FSP) += fsp diff --git a/src/drivers/intel/fsp/Kconfig b/src/drivers/intel/fsp/Kconfig new file mode 100644 index 0000000000..19147cdd18 --- /dev/null +++ b/src/drivers/intel/fsp/Kconfig @@ -0,0 +1,207 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Sage Electronic Engineering, LLC. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +comment "Intel FSP" + +config PLATFORM_USES_FSP + bool "Use Intel Firmware Support Package" + help + Does the code require the Intel Firmware Support Package? + +if PLATFORM_USES_FSP + +config HAVE_FSP_BIN + bool "Should the Intel FSP binary be added to the flash image" + help + Select this option to add an Intel FSP binary to + the resulting coreboot image. + + Note: Without this binary, coreboot builds relying on the FSP + will not boot + +config USING_FSP_1_0 + bool "Code uses FSP 1.0 API" + default n + help + Select this option to use the FSP 1.0 API. + +config DCACHE_RAM_BASE + hex + default 0xfef00000 + +config DCACHE_RAM_SIZE + hex + default 0x4000 + +if HAVE_FSP_BIN + +config FSP_FILE + string "Intel FSP binary path and filename" + help + The path and filename of the Intel FSP binary for this platform. + +config FSP_INCLUDE_PATH + string "Path for FSP specific include files" + help + The path and filename of the Intel FSP binary for this platform. + +config FSP_IMAGE_ID_DWORD0 + hex "First 4 bytes of 8 byte platform string" + help + The first four bytes of the eight byte platform specific string + used to identify the FSP binary that should be used. + +config FSP_IMAGE_ID_DWORD1 + hex "Second 4 bytes of 8 byte platform string" + help + The second four bytes of the eight byte platform specific string + used to identify the FSP binary that should be used. + +config FSP_LOC + hex "Intel FSP Binary location in CBFS" + help + The location in CBFS that the FSP is located. This must match the + value that is set in the FSP binary. If the FSP needs to be moved, + rebase the FSP with Intel's BCT (tool). + +config FSP_RESERVED_MEM_SIZE + hex "FSP Reserved Memory" + default 0x00100000 + help + Memory size in bytes reserved by FSP between PEI Memory and the + base of TSEG. + +config ENABLE_FSP_FAST_BOOT + bool "Enable Fast Boot" + select ENABLE_MRC_CACHE + default n + help + Enabling this feature will force the MRC data to be cached in NV + storage to be used for speeding up boot time on future reboots + and/or power cycles. + +config ENABLE_MRC_CACHE + bool + default y if HAVE_ACPI_RESUME + default n + help + Enabling this feature will cause MRC data to be cached in NV storage. + This can either be used for fast boot, or just because the FSP wants + it to be saved. + +config MRC_CACHE_FILE + string "File containing the cached MRC values" + help + The path and filename of the cached MRC values. + +config MRC_CACHE_SIZE + hex "Fast Boot Data Cache Size" + default 0x10000 + depends on ENABLE_MRC_CACHE + help + This is the amount of space in NV storage that is reserved for the + fast boot data cache storage. + + WARNING: Because this area will be erased and re-written, the size + should be a full sector of the flash ROM chip and nothing else should + be included in CBFS in any sector that the fast boot cache data is in. + +config OVERRIDE_CACHE_CACHE_LOC + bool + help + Selected by the platform to set a new default location for the + MRC/fast boot cache. + +config MRC_CACHE_LOC_OVERRIDE + hex + help + Sets the override CBFS location of the MRC/fast boot cache. + +config MRC_CACHE_LOC + hex "Fast Boot Data Cache location in CBFS" + default MRC_CACHE_LOC_OVERRIDE if OVERRIDE_CACHE_CACHE_LOC + default 0xfff50000 + depends on ENABLE_MRC_CACHE + help + The location in CBFS for the MRC data to be cached. + + WARNING: This should be on a sector boundary of the BIOS ROM chip + and nothing else should be included in that sector, or IT WILL BE + ERASED. + +config VIRTUAL_ROM_SIZE + hex "Virtual ROM Size" + default ROM_SIZE + depends on ENABLE_MRC_CACHE + help + This is used to calculate the offset of the MRC data cache in NV + Storage for fast boot. If in doubt, leave this set to the default + which sets the virtual size equal to the ROM size. + + Example: Cougar Canyon 2 has two 8 MB SPI ROMs. When the SPI ROMs are + loaded with a 4 MB coreboot image, the virtual ROM size is 8 MB. When + the SPI ROMs are loaded with an 8 MB coreboot image, the virtual ROM + size is 16 MB. + +config CPU_MICROCODE_CBFS_LEN + hex "Microcode update region length in bytes" + default 0 + help + The length in bytes of the microcode update region. + +config CPU_MICROCODE_CBFS_LOC + hex "Microcode update base address in CBFS" + default 0 + help + The location (base address) in CBFS that contains the microcode update + binary. + +endif #HAVE_FSP_BIN + +config CACHE_ROM_SIZE_OVERRIDE + hex "Cache ROM Size" + default CBFS_SIZE + help + This is the size of the cachable area that is passed into the FSP in + the early initialization. Typically this should be the size of the CBFS + area, but the size must be a power of 2 whereas the CBFS size does not + have this limitation. + +config USE_GENERIC_FSP_CAR_INC + bool + default n + help + The chipset can select this to use a generic cache_as_ram.inc file + that should be good for all FSP based platforms. + +config FSP_USES_UPD + bool + default n + help + If this FSP uses UPD/VPD data regions, select this in the chipset Kconfig. + +config POST_IO + bool + default y + +config POST_IO_PORT + hex + default 0x80 + +endif #PLATFORM_USES_FSP diff --git a/src/drivers/intel/fsp/Makefile.inc b/src/drivers/intel/fsp/Makefile.inc new file mode 100644 index 0000000000..e1bf7d9adb --- /dev/null +++ b/src/drivers/intel/fsp/Makefile.inc @@ -0,0 +1,51 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Sage Electronic Engineering, LLC. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +ramstage-y += fsp_util.c +romstage-y += fsp_util.c +romstage-$(CONFIG_USING_FSP_1_0) += fsp_util_1_0.c +ramstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c +romstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c +romstage-y += fsp_hob.c +ramstage-y += fsp_hob.c + +CPPFLAGS_common += -Isrc/drivers/intel/fsp + +ifeq ($(CONFIG_USE_GENERIC_FSP_CAR_INC),y) +cpu_incs += $(src)/drivers/intel/fsp/cache_as_ram.inc +endif + +ifeq ($(CONFIG_HAVE_FSP_BIN),y) +cbfs-files-y += fsp.bin +fsp.bin-file := $(call strip_quotes,$(CONFIG_FSP_FILE)) +fsp.bin-position := $(CONFIG_FSP_LOC) +fsp.bin-type := 0xab +endif + +ifeq ($(CONFIG_ENABLE_MRC_CACHE_FILE),y) +$(obj)/mrc.cache: + dd if=/dev/zero count=1 \ + bs=$(shell printf "%d" $(CONFIG_MRC_CACHE_SIZE) ) | \ + tr '\000' '\377' > $@ + +cbfs-files-y += mrc.cache +mrc.cache-file := $(call strip_quotes,$(CONFIG_MRC_CACHE_FILE)) +mrc.cache-position := $(CONFIG_MRC_CACHE_LOC) +mrc.cache-type := 0xac +endif diff --git a/src/drivers/intel/fsp/cache_as_ram.inc b/src/drivers/intel/fsp/cache_as_ram.inc new file mode 100644 index 0000000000..40787b5cec --- /dev/null +++ b/src/drivers/intel/fsp/cache_as_ram.inc @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#ifndef CONFIG_FSP_LOC +# error "CONFIG_FSP_LOC must be set." +#endif + +#ifndef CONFIG_POST_IO +# error "CONFIG_POST_IO must be set." +#endif + +#if CONFIG_POST_IO +# ifndef CONFIG_POST_IO_PORT +# error "CONFIG_POST_IO_PORT must be set." +# endif +#endif + +#ifndef CONFIG_CPU_MICROCODE_CBFS_LOC +# error "CONFIG_CPU_MICROCODE_CBFS_LOC must be set." +#endif + +#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */ + + cmp $0, %eax + jne bisthalt + +cache_as_ram: + post_code(0x20) + + /* + * Find the FSP binary in cbfs. + * Make a fake stack that has the return value back to this code. + */ + lea fake_fsp_stack, %esp + jmp find_fsp +find_fsp_ret: + /* Save the FSP location */ + mov %eax, %ebp + cmp $CONFIG_FSP_LOC, %eax + jb halt1 + + post_code(0x22) + + /* Calculate entry into FSP */ + mov 0x30(%ebp), %eax /* Load TempRamInitEntry */ + add 0x1c(%ebp), %eax /* add in the offset for the FSP base address */ + + /* + * Pass early init variables on a fake stack (no memory yet) + * as well as the return location + */ + lea CAR_init_stack, %esp + + /* call FSP binary to setup temporary stack */ + jmp *%eax + +CAR_init_done: + addl $4, %esp + cmp $0, %eax + jne halt2 + + /* Save FSP_INFO_HEADER location in ebx */ + mov %ebp, %ebx + + /* + * set up bootloader stack + * ecx: stack base + * edx: stack top + */ + lea -4(%edx), %esp + movl %esp, %ebp + pushl %ebx + +before_romstage: + post_code(0x23) + + /* Call romstage.c main function. */ + call main /* does not return */ + movb $0xB8, %ah + jmp .Lhlt + +bisthalt: + movb $0xB9, %ah + jmp .Lhlt + +halt1: + /* + * Failures for postcode 0xBA - failed in find_fsp() + * + * Values are: + * 0x01 - FV signature, "_FVH" not present + * 0x02 - FFS GUID not present + * 0x03 - FSP INFO Header not found + * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased to + * a different location, or does it need to be? + * 0x05 - FSP INFO Header signature "FSPH" not found + * 0x06 - FSP Image ID is not the expected ID. + */ + movb $0xBA, %ah + jmp .Lhlt + +halt2: + /* + * Failures for postcode 0xBB - failed in the FSP: + * + * 0x00 - FSP_SUCCESS: Temp RAM was initialized successfully. + * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid. + * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode region. + * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met. + * 0x07 - FSP_DEVICE_ERROR: Temp RAM initialization failed + * 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked + */ + movb $0xBB, %ah + +.Lhlt: + xchg %al, %ah +#if CONFIG_POST_IO + outb %al, $CONFIG_POST_IO_PORT +#else + post_code(POST_DEAD_CODE) +#endif + movl $LHLT_DELAY, %ecx +.Lhlt_Delay: + outb %al, $0xED + loop .Lhlt_Delay + jmp .Lhlt + +/* + * esp is set to this location so that the call into and return from the FSP + * in find_fsp will work. + */ + .align 4 +fake_fsp_stack: + .long find_fsp_ret + +CAR_init_params: + .long CONFIG_CPU_MICROCODE_CBFS_LOC + .long CONFIG_CPU_MICROCODE_CBFS_LEN + .long 0xFFFFFFFF - CACHE_ROM_SIZE + 1 /* Firmware Location */ + .long CACHE_ROM_SIZE /* Total Firmware Length */ + +CAR_init_stack: + .long CAR_init_done + .long CAR_init_params + diff --git a/src/drivers/intel/fsp/fastboot_cache.c b/src/drivers/intel/fsp/fastboot_cache.c new file mode 100644 index 0000000000..91796c6e78 --- /dev/null +++ b/src/drivers/intel/fsp/fastboot_cache.c @@ -0,0 +1,271 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // hexdump +#include "fsp_util.h" + +#ifndef CONFIG_VIRTUAL_ROM_SIZE +#error "CONFIG_VIRTUAL_ROM_SIZE must be set." +#endif + +/* convert a pointer to flash area into the offset inside the flash */ +static inline u32 to_flash_offset(void *p) +{ + return (u32)p + CONFIG_VIRTUAL_ROM_SIZE; +} + +static struct mrc_data_container *next_mrc_block( + struct mrc_data_container *mrc_cache) +{ + /* MRC data blocks are aligned within the region */ + u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->mrc_data_size; + if (mrc_size & (MRC_DATA_ALIGN - 1UL)) { + mrc_size &= ~(MRC_DATA_ALIGN - 1UL); + mrc_size += MRC_DATA_ALIGN; + } + + u8 *region_ptr = (u8 *)mrc_cache; + region_ptr += mrc_size; + return (struct mrc_data_container *)region_ptr; +} + +static int is_mrc_cache(struct mrc_data_container *mrc_cache) +{ + return (!!mrc_cache) + && (mrc_cache->mrc_signature == MRC_DATA_SIGNATURE); +} + +static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) +{ + const char *name = "mrc.cache"; + int type = 0xac; + struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, name); + + if (file == NULL) { + printk(BIOS_ERR, "Could not find file '%s'.\n", name); + return 0; + } + + if (ntohl(file->type) != type) { + printk(BIOS_ERR, "File '%s' is of type %x, but we requested %x.\n", + name, ntohl(file->type), type); + return 0; + } + + return ntohl(file->len); +} + +/* + * Find the largest index block in the MRC cache. Return NULL if none is + * found. + */ +static struct mrc_data_container *find_current_mrc_cache_local + (struct mrc_data_container *mrc_cache, u32 region_size) +{ + u32 region_end; + u32 entry_id = 0; + struct mrc_data_container *mrc_next = mrc_cache; + + region_end = (u32) mrc_cache + region_size; + + /* Search for the last filled entry in the region */ + while (is_mrc_cache(mrc_next)) { + entry_id++; + mrc_cache = mrc_next; + mrc_next = next_mrc_block(mrc_next); + if ((u32)mrc_next >= region_end) { + /* Stay in the MRC data region */ + break; + } + } + + if (entry_id == 0) { + printk(BIOS_ERR, "%s: No valid fast boot cache found.\n", + __func__); + return NULL; + } + + /* Verify checksum */ + if (mrc_cache->mrc_checksum != + compute_ip_checksum(mrc_cache->mrc_data, + mrc_cache->mrc_data_size)) { + printk(BIOS_ERR, "%s: fast boot cache checksum mismatch\n", + __func__); + return NULL; + } + + printk(BIOS_DEBUG, "%s: picked entry %u from cache block\n", __func__, + entry_id - 1); + + return mrc_cache; +} + +/* SPI code needs malloc/free. + * Also unknown if writing flash from XIP-flash code is a good idea + */ +#if !defined(__PRE_RAM__) +/* find the first empty block in the MRC cache area. + * If there's none, return NULL. + * + * @mrc_cache_base - base address of the MRC cache area + * @mrc_cache - current entry (for which we need to find next) + * @region_size - total size of the MRC cache area + */ +static struct mrc_data_container *find_next_mrc_cache + (struct mrc_data_container *mrc_cache_base, + struct mrc_data_container *mrc_cache, + u32 region_size) +{ + u32 region_end = (u32) mrc_cache_base + region_size; + u32 mrc_data_size = mrc_cache->mrc_data_size; + + mrc_cache = next_mrc_block(mrc_cache); + if (((u32)mrc_cache + mrc_data_size) >= region_end) { + /* Crossed the boundary */ + mrc_cache = NULL; + printk(BIOS_DEBUG, "%s: no available entries found\n", + __func__); + } else { + printk(BIOS_DEBUG, + "%s: picked next entry from cache block at %p\n", + __func__, mrc_cache); + } + + return mrc_cache; +} + +void update_mrc_cache(void *unused) +{ + printk(BIOS_DEBUG, "Updating fast boot cache data.\n"); + struct mrc_data_container *current = cbmem_find(CBMEM_ID_MRCDATA); + struct mrc_data_container *cache, *cache_base; + u32 cache_size; + + if (!current) { + printk(BIOS_ERR, "No fast boot cache in cbmem. Can't update flash.\n"); + return; + } + if (current->mrc_data_size == -1) { + printk(BIOS_ERR, "Fast boot cache data in cbmem invalid.\n"); + return; + } + + cache_base = NULL; + cache_size = get_mrc_cache_region(&cache_base); + if (cache_base == NULL) { + printk(BIOS_ERR, "%s: could not find fast boot cache area\n", + __func__); + return; + } + + /* + * we need to: + * 0. compare MRC data to last mrc-cache block (exit if same) + */ + cache = find_current_mrc_cache_local(cache_base, cache_size); + + if (cache && (cache->mrc_data_size == current->mrc_data_size) && + (memcmp(cache, current, cache->mrc_data_size) == 0)) { + printk(BIOS_DEBUG, + "MRC data in flash is up to date. No update.\n"); + return; + } + + /* 1. use spi_flash_probe() to find the flash, then... */ + spi_init(); + struct spi_flash *flash = spi_flash_probe(0, 0); + if (!flash) { + printk(BIOS_DEBUG, "Could not find SPI device\n"); + return; + } + + /* 2. look up the first unused block */ + if (cache) + cache = find_next_mrc_cache(cache_base, cache, cache_size); + + /* + * 3. if no such place exists, erase entire mrc-cache range & use + * block 0. First time around the erase is not needed, but this is a + * small overhead for simpler code. + */ + if (!cache) { + printk(BIOS_DEBUG, + "Need to erase the MRC cache region of %d bytes at %p\n", + cache_size, cache_base); + + flash->erase(flash, to_flash_offset(cache_base), cache_size); + + /* we will start at the beginning again */ + cache = cache_base; + } + /* 4. write mrc data with flash->write() */ + printk(BIOS_DEBUG, "Write MRC cache update to flash at %p\n", + cache); + flash->write(flash, to_flash_offset(cache), + current->mrc_data_size + sizeof(*current), current); +} + +#endif /* !defined(__PRE_RAM__) */ + +void *find_and_set_fastboot_cache(void) +{ + struct mrc_data_container *mrc_cache = NULL; + mrc_cache = find_current_mrc_cache(); + if ((mrc_cache == NULL) || + (mrc_cache->mrc_data_size == -1UL)) { + printk(BIOS_DEBUG, "FSP MRC cache not present.\n"); + return NULL; + } + printk(BIOS_DEBUG, "FSP MRC cache present at %x.\n", (u32)mrc_cache); + printk(BIOS_SPEW, "Saved MRC data:\n"); + hexdump32(BIOS_SPEW, (void *)mrc_cache->mrc_data, + mrc_cache->mrc_data_size); + return (void *) mrc_cache->mrc_data; +} + +struct mrc_data_container *find_current_mrc_cache(void) +{ + struct mrc_data_container *cache_base; + u32 cache_size; + + cache_base = NULL; + cache_size = get_mrc_cache_region(&cache_base); + if (cache_base == NULL) { + printk(BIOS_ERR, "%s: could not find fast boot cache area\n", + __func__); + return NULL; + } + + /* + * we need to: + * 0. compare MRC data to last mrc-cache block (exit if same) + */ + return find_current_mrc_cache_local(cache_base, cache_size); +} diff --git a/src/drivers/intel/fsp/fsp_hob.c b/src/drivers/intel/fsp/fsp_hob.c new file mode 100644 index 0000000000..54df2497b3 --- /dev/null +++ b/src/drivers/intel/fsp/fsp_hob.c @@ -0,0 +1,488 @@ +/****************************************************************************** + +Copyright (C) 2013, Intel Corporation + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + ******************************************************************************/ + +/*********************************************************************** + * + * fsp_hob.c + * + * HOB infrastructure code. + * + **********************************************************************/ + +#include +#include +#include +#include +#include "fsp_util.h" +#include +#include // hexdump +#include + +void *fsp_hob_list_ptr CAR_GLOBAL; + +/* + * Reads a 64-bit value from memory that may be unaligned. + * + * This function returns the 64-bit value pointed to by buffer. The + * function guarantees that the read operation does not produce an + * alignment fault. + * + * If buffer is NULL, then ASSERT(). + * + * buffer: Pointer to a 64-bit value that may be unaligned. + * + * Returns the 64-bit value read from buffer. + * + */ +static +uint64_t +read_unaligned_64( + const uint64_t *buffer + ) +{ + ASSERT(buffer != NULL); + + return *buffer; +} + +/* + * Compares two GUIDs. + * + * This function compares guid1 to guid2. If the GUIDs are identical then + * TRUE is returned. If there are any bit differences in the two GUIDs, + * then FALSE is returned. + * + * If guid1 is NULL, then ASSERT(). + * If guid2 is NULL, then ASSERT(). + * + * guid1: A pointer to a 128 bit GUID. + * guid2: A pointer to a 128 bit GUID. + * + * Returns non-zero if guid1 and guid2 are identical, otherwise returns 0. + * + */ +static +long +compare_guid( + const EFI_GUID * guid1, + const EFI_GUID * guid2 + ) +{ + uint64_t low_part_of_guid1; + uint64_t low_part_of_guid2; + uint64_t high_part_of_guid1; + uint64_t high_part_of_guid2; + + low_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1); + low_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2); + high_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1 + 1); + high_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2 + 1); + + return ((low_part_of_guid1 == low_part_of_guid2) + && (high_part_of_guid1 == high_part_of_guid2)); +} + +/* Returns the pointer to the HOB list. */ +void +set_hob_list( + void *hob_list_ptr + ) +{ + void **hob_ptr; + + fsp_hob_list_ptr = hob_list_ptr; + printk(BIOS_SPEW, "0x%p: fsp_hob_list_ptr\n", hob_list_ptr); + hob_ptr = cbmem_add(CBMEM_ID_HOB_LIST, sizeof(hob_list_ptr)); + if (hob_ptr == NULL) + die("ERROR - cbmem_add failed in set_hob_list!\n"); + *hob_ptr = hob_list_ptr; +} + +/* Returns the pointer to the HOB list. */ +VOID * +EFIAPI +get_hob_list( + VOID + ) +{ + void **hob_ptr; + + if (fsp_hob_list_ptr == NULL) { + hob_ptr = cbmem_find(CBMEM_ID_HOB_LIST); + if (hob_ptr == NULL) + die("Call set_hob_list before this call!\n"); + fsp_hob_list_ptr = *hob_ptr; + } + return fsp_hob_list_ptr; +} + +/* Returns the next instance of a HOB type from the starting HOB. */ +VOID * +EFIAPI +get_next_hob( + UINT16 type, + CONST VOID *hob_start + ) +{ + EFI_PEI_HOB_POINTERS hob; + + ASSERT(hob_start != NULL); + + hob.Raw = (UINT8 *)hob_start; + + /* Parse the HOB list until end of list or matching type is found. */ + while (!END_OF_HOB_LIST(hob.Raw)) { + if (hob.Header->HobType == type) + return hob.Raw; + if (GET_HOB_LENGTH(hob.Raw) < sizeof(*hob.Header)) + break; + hob.Raw = GET_NEXT_HOB(hob.Raw); + } + return NULL; +} + +/* Returns the first instance of a HOB type among the whole HOB list. */ +VOID * +EFIAPI +get_first_hob( + UINT16 type + ) +{ + VOID *hob_list; + + hob_list = get_hob_list(); + return get_next_hob(type, hob_list); +} + +/* Returns the next instance of the matched GUID HOB from the starting HOB. */ +VOID * +EFIAPI +get_next_guid_hob( + CONST EFI_GUID * guid, + CONST VOID *hob_start + ) +{ + EFI_PEI_HOB_POINTERS guid_hob; + + guid_hob.Raw = (UINT8 *)hob_start; + while ((guid_hob.Raw = get_next_hob(EFI_HOB_TYPE_GUID_EXTENSION, + guid_hob.Raw)) != NULL) { + if (compare_guid(guid, &guid_hob.Guid->Name)) + break; + guid_hob.Raw = GET_NEXT_HOB(guid_hob.Raw); + } + return guid_hob.Raw; +} + +/* + * Returns the first instance of the matched GUID HOB among the whole HOB list. + */ +VOID * +EFIAPI +get_first_guid_hob( + CONST EFI_GUID * guid + ) +{ + VOID *hob_list; + + hob_list = get_hob_list(); + return get_next_guid_hob(guid, hob_list); +} + +static void print_hob_mem_attributes(void *hob_ptr) +{ + EFI_HOB_MEMORY_ALLOCATION *hob_memory_ptr = + (EFI_HOB_MEMORY_ALLOCATION *)hob_ptr; + EFI_MEMORY_TYPE hob_mem_type = + hob_memory_ptr->AllocDescriptor.MemoryType; + u64 hob_mem_addr = hob_memory_ptr->AllocDescriptor.MemoryBaseAddress; + u64 hob_mem_length = hob_memory_ptr->AllocDescriptor.MemoryLength; + const char *hob_mem_type_names[15]; + + hob_mem_type_names[0] = "EfiReservedMemoryType"; + hob_mem_type_names[1] = "EfiLoaderCode"; + hob_mem_type_names[2] = "EfiLoaderData"; + hob_mem_type_names[3] = "EfiBootServicesCode"; + hob_mem_type_names[4] = "EfiBootServicesData"; + hob_mem_type_names[5] = "EfiRuntimeServicesCode"; + hob_mem_type_names[6] = "EfiRuntimeServicesData"; + hob_mem_type_names[7] = "EfiConventionalMemory"; + hob_mem_type_names[8] = "EfiUnusableMemory"; + hob_mem_type_names[9] = "EfiACPIReclaimMemory"; + hob_mem_type_names[10] = "EfiACPIMemoryNVS"; + hob_mem_type_names[11] = "EfiMemoryMappedIO"; + hob_mem_type_names[12] = "EfiMemoryMappedIOPortSpace"; + hob_mem_type_names[13] = "EfiPalCode"; + hob_mem_type_names[14] = "EfiMaxMemoryType"; + + printk(BIOS_SPEW, " Memory type %s (0x%x)\n", + hob_mem_type_names[(u32)hob_mem_type], + (u32)hob_mem_type); + printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n", + (unsigned long)hob_mem_addr, + (unsigned long)hob_mem_length); +} + +static void print_hob_resource_attributes(void *hob_ptr) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *hob_resource_ptr = + (EFI_HOB_RESOURCE_DESCRIPTOR *)hob_ptr; + u32 hob_res_type = hob_resource_ptr->ResourceType; + u32 hob_res_attr = hob_resource_ptr->ResourceAttribute; + u64 hob_res_addr = hob_resource_ptr->PhysicalStart; + u64 hob_res_length = hob_resource_ptr->ResourceLength; + const char *hob_res_type_str = NULL; + + /* HOB Resource Types */ + switch (hob_res_type) { + case EFI_RESOURCE_SYSTEM_MEMORY: + hob_res_type_str = "EFI_RESOURCE_SYSTEM_MEMORY"; + break; + case EFI_RESOURCE_MEMORY_MAPPED_IO: + hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO"; + break; + case EFI_RESOURCE_IO: + hob_res_type_str = "EFI_RESOURCE_IO"; + break; + case EFI_RESOURCE_FIRMWARE_DEVICE: + hob_res_type_str = "EFI_RESOURCE_FIRMWARE_DEVICE"; + break; + case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT: + hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT"; + break; + case EFI_RESOURCE_MEMORY_RESERVED: + hob_res_type_str = "EFI_RESOURCE_MEMORY_RESERVED"; + break; + case EFI_RESOURCE_IO_RESERVED: + hob_res_type_str = "EFI_RESOURCE_IO_RESERVED"; + break; + case EFI_RESOURCE_MAX_MEMORY_TYPE: + hob_res_type_str = "EFI_RESOURCE_MAX_MEMORY_TYPE"; + break; + default: + hob_res_type_str = "EFI_RESOURCE_UNKNOWN"; + break; + } + + printk(BIOS_SPEW, " Resource %s (0x%0x) has attributes 0x%0x\n", + hob_res_type_str, hob_res_type, hob_res_attr); + printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n", + (unsigned long)hob_res_addr, + (unsigned long)hob_res_length); +} + +static const char *get_hob_type_string(void *hob_ptr) +{ + EFI_HOB_GENERIC_HEADER *hob_header_ptr = + (EFI_HOB_GENERIC_HEADER *)hob_ptr; + u16 hob_type = hob_header_ptr->HobType; + const char *hob_type_string = NULL; + + switch (hob_type) { + case EFI_HOB_TYPE_HANDOFF: + hob_type_string = "EFI_HOB_TYPE_HANDOFF"; + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + hob_type_string = "EFI_HOB_TYPE_MEMORY_ALLOCATION"; + break; + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + hob_type_string = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR"; + break; + case EFI_HOB_TYPE_GUID_EXTENSION: + hob_type_string = "EFI_HOB_TYPE_GUID_EXTENSION"; + break; + case EFI_HOB_TYPE_MEMORY_POOL: + hob_type_string = "EFI_HOB_TYPE_MEMORY_POOL"; + break; + case EFI_HOB_TYPE_UNUSED: + hob_type_string = "EFI_HOB_TYPE_UNUSED"; + break; + case EFI_HOB_TYPE_END_OF_HOB_LIST: + hob_type_string = "EFI_HOB_TYPE_END_OF_HOB_LIST"; + break; + default: + hob_type_string = "EFI_HOB_TYPE_UNRECOGNIZED"; + break; + } + + return hob_type_string; +} + +/* + * Print out a structure of all the HOBs + * that match a certain type: + * Print all types (0x0000) + * EFI_HOB_TYPE_HANDOFF (0x0001) + * EFI_HOB_TYPE_MEMORY_ALLOCATION (0x0002) + * EFI_HOB_TYPE_RESOURCE_DESCRIPTOR (0x0003) + * EFI_HOB_TYPE_GUID_EXTENSION (0x0004) + * EFI_HOB_TYPE_MEMORY_POOL (0x0007) + * EFI_HOB_TYPE_UNUSED (0xFFFE) + * EFI_HOB_TYPE_END_OF_HOB_LIST (0xFFFF) + */ +void print_hob_type_structure(u16 hob_type, void *hob_list_ptr) +{ + u32 *current_hob; + u32 *next_hob = 0; + u8 last_hob = 0; + u32 current_type; + const char *current_type_str; + + current_hob = hob_list_ptr; + + /* + * Print out HOBs of our desired type until + * the end of the HOB list + */ + printk(BIOS_DEBUG, "\n=== FSP HOB Data Structure ===\n"); + printk(BIOS_DEBUG, "0x%p: hob_list_ptr\n", hob_list_ptr); + do { + EFI_HOB_GENERIC_HEADER *current_header_ptr = + (EFI_HOB_GENERIC_HEADER *)current_hob; + + /* Get the type of this HOB */ + current_type = current_header_ptr->HobType; + current_type_str = get_hob_type_string(current_hob); + + if (current_type == hob_type || hob_type == 0x0000) { + printk(BIOS_DEBUG, "HOB 0x%0x is an %s (type 0x%0x)\n", + (u32)current_hob, current_type_str, + current_type); + switch (current_type) { + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + print_hob_mem_attributes(current_hob); + break; + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + print_hob_resource_attributes(current_hob); + break; + } + } + + /* Check for end of HOB list */ + last_hob = END_OF_HOB_LIST(current_hob); + if (!last_hob) { + /* Get next HOB pointer */ + next_hob = GET_NEXT_HOB(current_hob); + + /* Start on next HOB */ + current_hob = next_hob; + } + } while (!last_hob); + printk(BIOS_DEBUG, "=== End of FSP HOB Data Structure ===\n\n"); +} + +#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE) +/* + * Save the FSP memory HOB (mrc data) to the MRC area in CBMEM + */ +int save_mrc_data(void *hob_start) +{ + u32 *mrc_hob; + u32 *mrc_hob_data; + u32 mrc_hob_size; + struct mrc_data_container *mrc_data; + int output_len; + const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID; + + mrc_hob = get_next_guid_hob(&mrc_guid, hob_start); + if (mrc_hob == NULL) { + printk(BIOS_DEBUG, + "Memory Configure Data Hob is not present\n"); + return 0; + } + + mrc_hob_data = GET_GUID_HOB_DATA(mrc_hob); + mrc_hob_size = (u32) GET_HOB_LENGTH(mrc_hob); + + printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n", + (void *)mrc_hob_data, mrc_hob_size); + + output_len = ALIGN(mrc_hob_size, 16); + + /* Save the MRC S3/fast boot/ADR restore data to cbmem */ + mrc_data = cbmem_add(CBMEM_ID_MRCDATA, + output_len + sizeof(struct mrc_data_container)); + + /* Just return if there was a problem with getting CBMEM */ + if (mrc_data == NULL) { + printk(BIOS_WARNING, + "CBMEM was not available to save the fast boot cache data.\n"); + return 0; + } + + printk(BIOS_DEBUG, + "Copy FSP MRC DATA to HOB (source addr %p, dest addr %p, %u bytes)\n", + (void *)mrc_hob_data, mrc_data, output_len); + + mrc_data->mrc_signature = MRC_DATA_SIGNATURE; + mrc_data->mrc_data_size = output_len; + mrc_data->reserved = 0; + memcpy(mrc_data->mrc_data, (const void *)mrc_hob_data, mrc_hob_size); + + /* Zero the unused space in aligned buffer. */ + if (output_len > mrc_hob_size) + memset((mrc_data->mrc_data + mrc_hob_size), 0, + output_len - mrc_hob_size); + + mrc_data->mrc_checksum = compute_ip_checksum(mrc_data->mrc_data, + mrc_data->mrc_data_size); + + printk(BIOS_SPEW, "Fast boot data (includes align and checksum):\n"); + hexdump32(BIOS_SPEW, (void *)mrc_data->mrc_data, output_len); + return 1; +} +#endif /* CONFIG_ENABLE_MRC_CACHE */ + +static void find_fsp_hob_update_mrc(void *unused) +{ + void *hob_list_ptr; + + /* 0x0000: Print all types */ + hob_list_ptr = get_hob_list(); + print_hob_type_structure(0x000, hob_list_ptr); + + #if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE) + if (save_mrc_data(hob_list_ptr)) + update_mrc_cache(NULL); + else + printk(BIOS_DEBUG, "Not updating MRC data in flash.\n"); + #endif +} + +void __attribute__ ((weak)) update_mrc_cache(void *unused) +{ + printk(BIOS_ERR, "Add routine %s to save the MRC data.\n", __func__); +} + +/* Update the MRC/fast boot cache as part of the late table writing stage */ +BOOT_STATE_INIT_ENTRIES(fsp_hob_find) = { + BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, + find_fsp_hob_update_mrc, NULL), +}; diff --git a/src/drivers/intel/fsp/fsp_util.c b/src/drivers/intel/fsp/fsp_util.c new file mode 100644 index 0000000000..d0f9ef4a01 --- /dev/null +++ b/src/drivers/intel/fsp/fsp_util.c @@ -0,0 +1,173 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "fsp_util.h" +#include + +/* Locate the FSP binary in the coreboot filesystem */ +FSP_INFO_HEADER *find_fsp(void) +{ + union { + EFI_FFS_FILE_HEADER *ffh; + FSP_INFO_HEADER *fih; + EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh; + EFI_FIRMWARE_VOLUME_HEADER *fvh; + EFI_RAW_SECTION *rs; + u8 *u8; + u32 u32; + } fsp_ptr; + u32 *image_id; + +#ifndef CONFIG_FSP_LOC +#error "CONFIG_FSP_LOC must be set." +#endif + + for (;;) { + /* Get the FSP binary base address in CBFS */ + fsp_ptr.u8 = (u8 *)CONFIG_FSP_LOC; + + /* Check the FV signature, _FVH */ + if (fsp_ptr.fvh->Signature != 0x4856465F) { + fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG; + break; + } + + /* Locate the file header which follows the FV header. */ + fsp_ptr.u8 += fsp_ptr.fvh->ExtHeaderOffset; + fsp_ptr.u8 += fsp_ptr.fveh->ExtHeaderSize; + fsp_ptr.u8 = (u8 *)((fsp_ptr.u32 + 7) & 0xFFFFFFF8); + + /* Check the FFS GUID */ + if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE) + || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284) + || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9) + || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) { + fsp_ptr.u8 = (u8 *)ERROR_NO_FFS_GUID; + break; + } + + /* Locate the Raw Section Header */ + fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER); + + if (fsp_ptr.rs->Type != EFI_SECTION_RAW) { + fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER; + break; + } + + /* Locate the FSP INFO Header which follows the Raw Header. */ + fsp_ptr.u8 += sizeof(EFI_RAW_SECTION); + + /* Verify that the FSP base address.*/ + if (fsp_ptr.fih->ImageBase != CONFIG_FSP_LOC) { + fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH; + break; + } + + /* Verify the FSP Signature */ + if (fsp_ptr.fih->Signature != FSP_SIG) { + fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH; + break; + } + + /* Verify the FSP ID */ + image_id = (u32 *)&fsp_ptr.fih->ImageId[0]; + if ((image_id[0] != CONFIG_FSP_IMAGE_ID_DWORD0) + || (image_id[1] != CONFIG_FSP_IMAGE_ID_DWORD1)) + fsp_ptr.u8 = (u8 *)ERROR_FSP_SIG_MISMATCH; + break; + } + + return fsp_ptr.fih; +} + +void print_fsp_info(FSP_INFO_HEADER *fsp_header) +{ + u8 *fsp_base; + + fsp_base = (u8 *)fsp_header->ImageBase; + printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header); + printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n", + fsp_header->ImageId[0], fsp_header->ImageId[1], + fsp_header->ImageId[2], fsp_header->ImageId[3], + fsp_header->ImageId[4], fsp_header->ImageId[5], + fsp_header->ImageId[6], fsp_header->ImageId[7]); + printk(BIOS_INFO, "FSP Header Version: %d\n", + fsp_header->HeaderRevision); + printk(BIOS_INFO, "FSP Revision: %d.%d\n", + (u8)((fsp_header->ImageRevision >> 8) & 0xff), + (u8)(fsp_header->ImageRevision & 0xff)); + printk(BIOS_SPEW, "FSP Entry Points:\n"); + printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base); + printk(BIOS_SPEW, " 0x%p: TempRamInit\n", + &fsp_base[fsp_header->TempRamInitEntryOffset]); + printk(BIOS_SPEW, " 0x%p: FspInit\n", + &fsp_base[fsp_header->FspInitEntryOffset]); + if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_1_1) { + printk(BIOS_SPEW, " 0x%p: MemoryInit\n", + &fsp_base[fsp_header->FspMemoryInitEntryOffset]); + printk(BIOS_SPEW, " 0x%p: TempRamExit\n", + &fsp_base[fsp_header->TempRamExitEntryOffset]); + printk(BIOS_SPEW, " 0x%p: SiliconInit\n", + &fsp_base[fsp_header->FspSiliconInitEntryOffset]); + } + printk(BIOS_SPEW, " 0x%p: NotifyPhase\n", + &fsp_base[fsp_header->NotifyPhaseEntryOffset]); + printk(BIOS_SPEW, " 0x%p: Image End\n", + &fsp_base[fsp_header->ImageSize]); +} + +#ifndef __PRE_RAM__ + +FSP_INFO_HEADER *fsp_header_ptr = NULL; + +void fsp_notify(u32 phase) +{ + FSP_NOTIFY_PHASE notify_phase_proc; + NOTIFY_PHASE_PARAMS notify_phase_params; + EFI_STATUS status; + + if (fsp_header_ptr == NULL) { + fsp_header_ptr = (void *)find_fsp(); + if ((u32)fsp_header_ptr < 0xff) { + /* output something in case there is no serial */ + post_code(0x4F); + die("Can't find the FSP!\n"); + } + } + + /* call FSP PEI to Notify PostPciEnumeration */ + notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase + + fsp_header_ptr->NotifyPhaseEntryOffset); + notify_phase_params.Phase = phase; + + timestamp_add_now(phase == EnumInitPhaseReadyToBoot ? + TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE); + + status = notify_phase_proc(¬ify_phase_params); + + timestamp_add_now(phase == EnumInitPhaseReadyToBoot ? + TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE); + + if (status != 0) + printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n", + phase, status); +} + +#endif /* #ifndef __PRE_RAM__ */ diff --git a/src/drivers/intel/fsp/fsp_util.h b/src/drivers/intel/fsp/fsp_util.h new file mode 100644 index 0000000000..6ef478874c --- /dev/null +++ b/src/drivers/intel/fsp/fsp_util.h @@ -0,0 +1,117 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FSP_UTIL_H +#define FSP_UTIL_H + +#include +#include + +/* + * The following are functions with prototypes defined in the EDK2 headers. The + * EDK2 headers are included with chipset_fsp_util.h. Define the following + * names to reduce the use of CamelCase in the other source files. + */ +#define GetHobList get_hob_list +#define GetNextHob get_next_hob +#define GetFirstHob get_first_hob +#define GetNextGuidHob get_next_guid_hob +#define GetFirstGuidHob get_first_guid_hob + +/* Include the EDK2 headers */ +#include + +#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE) +int save_mrc_data(void *hob_start); +void * find_and_set_fastboot_cache(void); +#endif + +FSP_INFO_HEADER *find_fsp(void); +void fsp_early_init(FSP_INFO_HEADER *fsp_info); +void fsp_notify(u32 phase); +void print_hob_type_structure(u16 hob_type, void *hob_list_ptr); +void print_fsp_info(FSP_INFO_HEADER *fsp_header); +void set_hob_list(void *hob_list_ptr); + +/* The following are chipset support routines */ +#if IS_ENABLED(CONFIG_USING_FSP_1_0) +void chipset_fsp_early_init(FSP_INIT_PARAMS * fsp_init_params, + FSP_INFO_HEADER *fsp_ptr); +void chipset_fsp_return_point(EFI_STATUS status, VOID *hob_list_ptr); +#endif + +/* The following are board support routines */ +#if IS_ENABLED(CONFIG_USING_FSP_1_0) +void romstage_fsp_rt_buffer_callback( + FSP_INIT_RT_COMMON_BUFFER * fsp_rt_common_buffer); +#endif + + +/* Additional HOB types not included in the FSP: + * #define EFI_HOB_TYPE_HANDOFF 0x0001 + * #define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 + * #define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 + * #define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 + * #define EFI_HOB_TYPE_FV 0x0005 + * #define EFI_HOB_TYPE_CPU 0x0006 + * #define EFI_HOB_TYPE_MEMORY_POOL 0x0007 + * #define EFI_HOB_TYPE_CV 0x0008 + * #define EFI_HOB_TYPE_UNUSED 0xFFFE + * #define EFI_HOB_TYPE_END_OF_HOB_LIST 0xffff + */ +#define EFI_HOB_TYPE_HANDOFF 0x0001 +#define EFI_HOB_TYPE_MEMORY_POOL 0x0007 + +#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE) +#define MRC_DATA_ALIGN 0x1000 +#define MRC_DATA_SIGNATURE (('M'<<0)|('R'<<8)|('C'<<16)|('D'<<24)) + +struct mrc_data_container { + u32 mrc_signature; // "MRCD" + u32 mrc_data_size; // Actual total size of this structure + u32 mrc_checksum; // IP style checksum + u32 reserved; // For header alignment + u8 mrc_data[0]; // Variable size, platform/run time dependent. +} __attribute__ ((packed)); + +struct mrc_data_container *find_current_mrc_cache(void); + +void update_mrc_cache(void *unused); + +#endif /* CONFIG_ENABLE_MRC_CACHE */ + +/* The offset in bytes from the start of the info structure */ +#define FSP_IMAGE_SIG_LOC 0 +#define FSP_IMAGE_ID_LOC 16 +#define FSP_IMAGE_BASE_LOC 28 + +#define FSP_SIG 0x48505346 /* 'FSPH' */ + +#define ERROR_NO_FV_SIG 1 +#define ERROR_NO_FFS_GUID 2 +#define ERROR_NO_INFO_HEADER 3 +#define ERROR_IMAGEBASE_MISMATCH 4 +#define ERROR_INFO_HEAD_SIG_MISMATCH 5 +#define ERROR_FSP_SIG_MISMATCH 6 + +#ifndef __PRE_RAM__ +extern void *FspHobListPtr; +#endif + +#endif /* FSP_UTIL_H */ diff --git a/src/drivers/intel/fsp/fsp_util_1_0.c b/src/drivers/intel/fsp/fsp_util_1_0.c new file mode 100644 index 0000000000..a4bbdbac19 --- /dev/null +++ b/src/drivers/intel/fsp/fsp_util_1_0.c @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "fsp_util.h" +#include + +#ifdef __PRE_RAM__ + +/* + * Call the FSP to do memory init. The FSP doesn't return to this function. + * The FSP returns to the romstage_main_continue(). + */ +void __attribute__ ((noreturn)) fsp_early_init(FSP_INFO_HEADER *fsp_ptr) +{ + FSP_FSP_INIT fsp_init_api; + FSP_INIT_PARAMS fsp_init_params; + FSP_INIT_RT_BUFFER fsp_rt_buffer; +#if IS_ENABLED(CONFIG_FSP_USES_UPD) + UPD_DATA_REGION fsp_upd_data; +#endif + + memset((void *)&fsp_rt_buffer, 0, sizeof(FSP_INIT_RT_BUFFER)); + fsp_rt_buffer.Common.StackTop = (u32 *)ROMSTAGE_STACK; + fsp_init_params.NvsBufferPtr = NULL; + +#if IS_ENABLED(CONFIG_FSP_USES_UPD) + fsp_rt_buffer.Common.UpdDataRgnPtr = &fsp_upd_data; +#endif + fsp_init_params.RtBufferPtr = (FSP_INIT_RT_BUFFER *)&fsp_rt_buffer; + fsp_init_params.ContinuationFunc = + (CONTINUATION_PROC)chipset_fsp_return_point; + fsp_init_api = (FSP_FSP_INIT)(fsp_ptr->ImageBase + + fsp_ptr->FspInitEntryOffset); + + /* Call the chipset code to fill in the chipset specific structures */ + chipset_fsp_early_init(&fsp_init_params, fsp_ptr); + + /* Call back to romstage for board specific changes */ + romstage_fsp_rt_buffer_callback(&fsp_rt_buffer); + + fsp_init_api(&fsp_init_params); + + /* Should never return. Control will continue from ContinuationFunc */ + die("Uh Oh! FspInit returned"); +} +#endif /* __PRE_RAM__ */ diff --git a/src/drivers/intel/gma/Kconfig b/src/drivers/intel/gma/Kconfig new file mode 100644 index 0000000000..073f70819b --- /dev/null +++ b/src/drivers/intel/gma/Kconfig @@ -0,0 +1,30 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config INTEL_DP + bool + default n + help + helper functions for intel display port operations + +config INTEL_DDI + bool + default n + help + helper functions for intel DDI operations diff --git a/src/drivers/intel/gma/Makefile.inc b/src/drivers/intel/gma/Makefile.inc new file mode 100644 index 0000000000..7766f333e3 --- /dev/null +++ b/src/drivers/intel/gma/Makefile.inc @@ -0,0 +1,22 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_INTEL_DP) += intel_dp.c drm_dp_helper.c display.c +ramstage-$(CONFIG_INTEL_DDI) += intel_ddi.c + diff --git a/src/drivers/intel/gma/display.c b/src/drivers/intel/gma/display.c new file mode 100644 index 0000000000..afcec91d4c --- /dev/null +++ b/src/drivers/intel/gma/display.c @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Google Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Keith Packard + * + */ + +/* This code was created by the coccinnelle filters in the i915tool, + * with some final hand filtering. + */ + +#include +#include +#include +#include +#include + +void compute_display_params(struct intel_dp *dp) +{ + struct edid *edid = &(dp->edid); + struct edid_mode *mode = &edid->mode; + + /* step 1: get the constants in the dp struct set up. */ + dp->lane_count = dp->dpcd[DP_MAX_LANE_COUNT]&DP_LANE_COUNT_MASK; + + dp->link_bw = dp->dpcd[DP_MAX_LINK_RATE]; + dp->clock = intel_dp_bw_code_to_link_rate(dp->link_bw); + dp->edid.link_clock = intel_dp_bw_code_to_link_rate(dp->link_bw); + + /* step 2. Do some computation of other stuff. */ + dp->bytes_per_pixel = dp->pipe_bits_per_pixel/8; + + dp->stride = edid->bytes_per_line; + + dp->htotal = (mode->ha - 1) | ((mode->ha + mode->hbl - 1) << 16); + + dp->hblank = (mode->ha - 1) | ((mode->ha + mode->hbl - 1) << 16); + + dp->hsync = (mode->ha + mode->hso - 1) | + ((mode->ha + mode->hso + mode->hspw - 1) << 16); + + dp->vtotal = (mode->va - 1) | ((mode->va + mode->vbl - 1) << 16); + + dp->vblank = (mode->va - 1) | ((mode->va + mode->vbl - 1) << 16); + + dp->vsync = (mode->va + mode->vso - 1) | + ((mode->va + mode->vso + mode->vspw - 1) << 16); + + /* PIPEASRC is wid-1 x ht-1 */ + dp->pipesrc = (mode->ha-1)<<16 | (mode->va-1); + + dp->pfa_pos = 0; + + dp->pfa_ctl = PF_ENABLE | PF_FILTER_MED_3x3; + /* IVB hack */ + if (dp->gen == 6) + dp->pfa_ctl |= PF_PIPE_SEL_IVB(dp->pipe); + + dp->pfa_sz = (mode->ha << 16) | (mode->va); + + /* step 3. Call the linux code we pulled in. */ + dp->flags = intel_ddi_calc_transcoder_flags(edid->panel_bits_per_pixel, + dp->port, + dp->pipe, + dp->type, + dp->lane_count, + dp->pfa_sz, + mode->phsync == '+'?1:0, + mode->pvsync == '+'?1:0); + + dp->transcoder = intel_ddi_get_transcoder(dp->port, + dp->pipe); + + intel_dp_compute_m_n(edid->panel_bits_per_pixel, + dp->lane_count, + dp->edid.mode.pixel_clock, + dp->edid.link_clock, + &dp->m_n); + + printk(BIOS_SPEW, "dp->lane_count = 0x%08x\n",dp->lane_count); + printk(BIOS_SPEW, "dp->stride = 0x%08x\n",dp->stride); + printk(BIOS_SPEW, "dp->htotal = 0x%08x\n", dp->htotal); + printk(BIOS_SPEW, "dp->hblank = 0x%08x\n", dp->hblank); + printk(BIOS_SPEW, "dp->hsync = 0x%08x\n", dp->hsync); + printk(BIOS_SPEW, "dp->vtotal = 0x%08x\n", dp->vtotal); + printk(BIOS_SPEW, "dp->vblank = 0x%08x\n", dp->vblank); + printk(BIOS_SPEW, "dp->vsync = 0x%08x\n", dp->vsync); + printk(BIOS_SPEW, "dp->pipesrc = 0x%08x\n", dp->pipesrc); + printk(BIOS_SPEW, "dp->pfa_pos = 0x%08x\n", dp->pfa_pos); + printk(BIOS_SPEW, "dp->pfa_ctl = 0x%08x\n", dp->pfa_ctl); + printk(BIOS_SPEW, "dp->pfa_sz = 0x%08x\n", dp->pfa_sz); + printk(BIOS_SPEW, "dp->link_m = 0x%08x\n", dp->m_n.link_m); + printk(BIOS_SPEW, "dp->link_n = 0x%08x\n", dp->m_n.link_n); + printk(BIOS_SPEW, "0x6f030 = 0x%08x\n", + TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m); + printk(BIOS_SPEW, "0x6f030 = 0x%08x\n", dp->m_n.gmch_m); + printk(BIOS_SPEW, "0x6f034 = 0x%08x\n", dp->m_n.gmch_n); + printk(BIOS_SPEW, "dp->flags = 0x%08x\n", dp->flags); +} diff --git a/src/drivers/intel/gma/drm_dp_helper.c b/src/drivers/intel/gma/drm_dp_helper.c new file mode 100644 index 0000000000..66072263f4 --- /dev/null +++ b/src/drivers/intel/gma/drm_dp_helper.c @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2009 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +/* reduced a lot for coreboot. */ +/** + * DOC: dp helpers + * + * These functions contain some common logic and helpers at various + * abstraction levels to deal with Display Port sink devices and + * related things like DP aux channel transfers, EDID reading over DP + * aux channels, decoding certain DPCD blocks, ... + */ + + +/* Helpers for DP link training */ +static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) +{ + printk(BIOS_SPEW, "%s: %d, %d, %d\n", __func__, + r, r - DP_LANE0_1_STATUS, + link_status[r - DP_LANE0_1_STATUS]); + return link_status[r - DP_LANE0_1_STATUS]; +} + +static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_LANE0_1_STATUS + (lane >> 1); + int s = (lane & 1) * 4; + u8 l = dp_link_status(link_status, i); + return (l >> s) & 0xf; +} + +int drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count) +{ + u8 lane_align; + u8 lane_status; + int lane; + + lane_align = dp_link_status(link_status, + DP_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return 0; + for (lane = 0; lane < lane_count; lane++) { + lane_status = dp_get_lane_status(link_status, lane); + if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) + return 0; + } + return 1; +} + +int drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count) +{ + int lane; + u8 lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = dp_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return 0; + } + return 1; +} + +u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + u8 l = dp_link_status(link_status, i); + + printk(BIOS_SPEW, "%s: i %d s %d l %d return %d\n", + __func__, i, s, l, + ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT); + return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; +} + +u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + u8 l = dp_link_status(link_status, i); + + return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; +} diff --git a/src/drivers/intel/gma/drm_dp_helper.h b/src/drivers/intel/gma/drm_dp_helper.h new file mode 100644 index 0000000000..f2e06c33f3 --- /dev/null +++ b/src/drivers/intel/gma/drm_dp_helper.h @@ -0,0 +1,239 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2008 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _DRM_DP_HELPER_H_ +#define _DRM_DP_HELPER_H_ + +/* From the VESA DisplayPort spec */ + +#define AUX_NATIVE_WRITE 0x8 +#define AUX_NATIVE_READ 0x9 +#define AUX_I2C_WRITE 0x0 +#define AUX_I2C_READ 0x1 +#define AUX_I2C_STATUS 0x2 +#define AUX_I2C_MOT 0x4 + +#define AUX_NATIVE_REPLY_ACK (0x0 << 4) +#define AUX_NATIVE_REPLY_NACK (0x1 << 4) +#define AUX_NATIVE_REPLY_DEFER (0x2 << 4) +#define AUX_NATIVE_REPLY_MASK (0x3 << 4) + +#define AUX_I2C_REPLY_ACK (0x0 << 6) +#define AUX_I2C_REPLY_NACK (0x1 << 6) +#define AUX_I2C_REPLY_DEFER (0x2 << 6) +#define AUX_I2C_REPLY_MASK (0x3 << 6) + +/* AUX CH addresses */ +/* DPCD */ +#define DP_DPCD_REV 0x000 + +#define DP_MAX_LINK_RATE 0x001 + +#define DP_MAX_LANE_COUNT 0x002 +# define DP_MAX_LANE_COUNT_MASK 0x1f +# define DP_TPS3_SUPPORTED (1 << 6) +# define DP_ENHANCED_FRAME_CAP (1 << 7) + +#define DP_MAX_DOWNSPREAD 0x003 +# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6) + +#define DP_NORP 0x004 + +#define DP_DOWNSTREAMPORT_PRESENT 0x005 +# define DP_DWN_STRM_PORT_PRESENT (1 << 0) +# define DP_DWN_STRM_PORT_TYPE_MASK 0x06 +/* 00b = DisplayPort */ +/* 01b = Analog */ +/* 10b = TMDS or HDMI */ +/* 11b = Other */ +# define DP_FORMAT_CONVERSION (1 << 3) + +#define DP_MAIN_LINK_CHANNEL_CODING 0x006 + +#define DP_EDP_CONFIGURATION_CAP 0x00d +#define DP_TRAINING_AUX_RD_INTERVAL 0x00e + +#define DP_PSR_SUPPORT 0x070 +# define DP_PSR_IS_SUPPORTED 1 +#define DP_PSR_CAPS 0x071 +# define DP_PSR_NO_TRAIN_ON_EXIT 1 +# define DP_PSR_SETUP_TIME_330 (0 << 1) +# define DP_PSR_SETUP_TIME_275 (1 << 1) +# define DP_PSR_SETUP_TIME_220 (2 << 1) +# define DP_PSR_SETUP_TIME_165 (3 << 1) +# define DP_PSR_SETUP_TIME_110 (4 << 1) +# define DP_PSR_SETUP_TIME_55 (5 << 1) +# define DP_PSR_SETUP_TIME_0 (6 << 1) +# define DP_PSR_SETUP_TIME_MASK (7 << 1) +# define DP_PSR_SETUP_TIME_SHIFT 1 + +/* link configuration */ +#define DP_LINK_BW_SET 0x100 +# define DP_LINK_BW_1_62 0x06 +# define DP_LINK_BW_2_7 0x0a +# define DP_LINK_BW_5_4 0x14 + +#define DP_LANE_COUNT_SET 0x101 +# define DP_LANE_COUNT_MASK 0x0f +# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) + +#define DP_TRAINING_PATTERN_SET 0x102 +# define DP_TRAINING_PATTERN_DISABLE 0 +# define DP_TRAINING_PATTERN_1 1 +# define DP_TRAINING_PATTERN_2 2 +# define DP_TRAINING_PATTERN_3 3 +# define DP_TRAINING_PATTERN_MASK 0x3 + +# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) +# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) +# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) +# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) +# define DP_LINK_QUAL_PATTERN_MASK (3 << 2) + +# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) +# define DP_LINK_SCRAMBLING_DISABLE (1 << 5) + +# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) +# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) +# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) +# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) + +#define DP_TRAINING_LANE0_SET 0x103 +#define DP_TRAINING_LANE1_SET 0x104 +#define DP_TRAINING_LANE2_SET 0x105 +#define DP_TRAINING_LANE3_SET 0x106 + +# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 +# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 +# define DP_TRAIN_MAX_SWING_REACHED (1 << 2) +# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) +# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) +# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) +# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) + +# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) +# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) +# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) +# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) +# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) + +# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 +# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) + +#define DP_DOWNSPREAD_CTRL 0x107 +# define DP_SPREAD_AMP_0_5 (1 << 4) + +#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 +# define DP_SET_ANSI_8B10B (1 << 0) + +#define DP_PSR_EN_CFG 0x170 +# define DP_PSR_ENABLE (1 << 0) +# define DP_PSR_MAIN_LINK_ACTIVE (1 << 1) +# define DP_PSR_CRC_VERIFICATION (1 << 2) +# define DP_PSR_FRAME_CAPTURE (1 << 3) + +#define DP_DEVICE_SERVICE_IRQ_VECTOR 0x201 +# define DP_REMOTE_CONTROL_COMMAND_PENDING (1 << 0) +# define DP_AUTOMATED_TEST_REQUEST (1 << 1) +# define DP_CP_IRQ (1 << 2) +# define DP_SINK_SPECIFIC_IRQ (1 << 6) + +#define DP_EDP_CONFIGURATION_SET 0x10a + +#define DP_LANE0_1_STATUS 0x202 +#define DP_LANE2_3_STATUS 0x203 +# define DP_LANE_CR_DONE (1 << 0) +# define DP_LANE_CHANNEL_EQ_DONE (1 << 1) +# define DP_LANE_SYMBOL_LOCKED (1 << 2) + +#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \ + DP_LANE_CHANNEL_EQ_DONE | \ + DP_LANE_SYMBOL_LOCKED) + +#define DP_LANE_ALIGN_STATUS_UPDATED 0x204 + +#define DP_INTERLANE_ALIGN_DONE (1 << 0) +#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) +#define DP_LINK_STATUS_UPDATED (1 << 7) + +#define DP_SINK_STATUS 0x205 + +#define DP_RECEIVE_PORT_0_STATUS (1 << 0) +#define DP_RECEIVE_PORT_1_STATUS (1 << 1) + +#define DP_ADJUST_REQUEST_LANE0_1 0x206 +#define DP_ADJUST_REQUEST_LANE2_3 0x207 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 +# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 + +#define DP_TEST_REQUEST 0x218 +# define DP_TEST_LINK_TRAINING (1 << 0) +# define DP_TEST_LINK_PATTERN (1 << 1) +# define DP_TEST_LINK_EDID_READ (1 << 2) +# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */ + +#define DP_TEST_LINK_RATE 0x219 +# define DP_LINK_RATE_162 (0x6) +# define DP_LINK_RATE_27 (0xa) + +#define DP_TEST_LANE_COUNT 0x220 + +#define DP_TEST_PATTERN 0x221 + +#define DP_TEST_RESPONSE 0x260 +# define DP_TEST_ACK (1 << 0) +# define DP_TEST_NAK (1 << 1) +# define DP_TEST_EDID_CHECKSUM_WRITE (1 << 2) + +#define DP_SET_POWER 0x600 +# define DP_SET_POWER_D0 0x1 +# define DP_SET_POWER_D3 0x2 + +#define DP_PSR_ERROR_STATUS 0x2006 +# define DP_PSR_LINK_CRC_ERROR (1 << 0) +# define DP_PSR_RFB_STORAGE_ERROR (1 << 1) + +#define DP_PSR_ESI 0x2007 +# define DP_PSR_CAPS_CHANGE (1 << 0) + +#define DP_PSR_STATUS 0x2008 +# define DP_PSR_SINK_INACTIVE 0 +# define DP_PSR_SINK_ACTIVE_SRC_SYNCED 1 +# define DP_PSR_SINK_ACTIVE_RFB 2 +# define DP_PSR_SINK_ACTIVE_SINK_SYNCED 3 +# define DP_PSR_SINK_ACTIVE_RESYNC 4 +# define DP_PSR_SINK_INTERNAL_ERROR 7 +# define DP_PSR_SINK_STATE_MASK 0x07 + +#define MODE_I2C_START 1 +#define MODE_I2C_WRITE 2 +#define MODE_I2C_READ 4 +#define MODE_I2C_STOP 8 + +#endif /* _DRM_DP_HELPER_H_ */ diff --git a/src/drivers/intel/gma/i915.h b/src/drivers/intel/gma/i915.h new file mode 100644 index 0000000000..d87bbcc715 --- /dev/null +++ b/src/drivers/intel/gma/i915.h @@ -0,0 +1,290 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +/* port types. We stick with the same defines as the kernel */ +#define INTEL_OUTPUT_UNUSED 0 +#define INTEL_OUTPUT_ANALOG 1 +#define INTEL_OUTPUT_DVO 2 +#define INTEL_OUTPUT_SDVO 3 +#define INTEL_OUTPUT_LVDS 4 +#define INTEL_OUTPUT_TVOUT 5 +#define INTEL_OUTPUT_HDMI 6 +#define INTEL_OUTPUT_DISPLAYPORT 7 +#define INTEL_OUTPUT_EDP 8 + +/* things that are, strangely, not defined anywhere? */ +#define PCH_PP_UNLOCK 0xabcd0000 +#define WMx_LP_SR_EN (1<<31) +#define PRB0_TAIL 0x02030 +#define PRB0_HEAD 0x02034 +#define PRB0_START 0x02038 +#define PRB0_CTL 0x0203c + +enum port { + PORT_A = 0, + PORT_B, + PORT_C, + PORT_D, + PORT_E, + I915_NUM_PORTS +}; + +enum pipe { + PIPE_A = 0, + PIPE_B, + PIPE_C, + I915_NUM_PIPES +}; + +enum transcoder { + TRANSCODER_A = 0, + TRANSCODER_B, + TRANSCODER_C, + TRANSCODER_EDP = 0xF, +}; + +enum plane { + PLANE_A = 0, + PLANE_B, + PLANE_C, +}; + +/* debug enums. These are for printks that, due to their place in the + * middle of graphics device IO, might change timing. Use with care + * or not at all. + */ +enum { + vio = 2, /* dump every IO */ + vspin = 4, /* print # of times we spun on a register value */ +}; + +/* The mainboard must provide these functions. */ +unsigned long io_i915_read32(unsigned long addr); +void io_i915_write32(unsigned long val, unsigned long addr); + +/* + * To communicate to and control the extracted-from-kernel code, + * we need this struct. It has a counterpart in the ARM code, so + * there is a precedent. + */ + +#define DP_RECEIVER_CAP_SIZE 0xf +#define DP_LINK_STATUS_SIZE 6 +#define DP_LINK_CHECK_TIMEOUT (10 * 1000) + +#define DP_LINK_CONFIGURATION_SIZE 9 + +struct intel_dp_m_n { + uint32_t tu; + uint32_t gmch_m; + uint32_t gmch_n; + uint32_t link_m; + uint32_t link_n; +}; + +struct intel_dp { + int gen; // 6 for link, 7 for wtm2 + int has_pch_split; // 1 for link and wtm2 + int has_pch_cpt; // 1 for everything we know about. + int is_haswell; + /* output register offset in MMIO space. Usually DP_A */ + u32 output_reg; + /* The initial value of the DP register. + * Mainboards can set this to a non-zero + * value in the case that there are undetectable + * but essential parameters. + */ + u32 DP; + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; + u32 color_range; + /* these paramaters are determined after reading the DPCD */ + int dpms_mode; + uint8_t link_bw; + uint8_t lane_count; + /* This data is read from the panel via the AUX channel.*/ + uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; + int type; + int edp; + int is_pch_edp; + /* state related to training. */ + uint8_t train_set[4]; + /* Determined from EDID or coreboot hard-sets. */ + int panel_power_up_delay; + int panel_power_down_delay; + int panel_power_cycle_delay; + int backlight_on_delay; + int backlight_off_delay; + int want_panel_vdd; + u32 clock; + int port; + int pipe; + int plane; + int pipe_bits_per_pixel; + /* i2c on aux is ... interesting. + * Before you do an i2c cycle, you need to set the address. + * This requires we remember it from one moment to the next. + * Remember it here. + */ + u16 address; + /* timing parameters for aux channel IO. They used to compute these on + * each and every entry to the functions, which is kind of stupid, and it had + * errors anyway. + * note: you can get these from watching YABEL output. E.g.: + * you see an outb of 0x802300e1 to 64010. the 3 is the precharge + * and the e1 is the clock divider. + */ + u32 aux_clock_divider; + u32 precharge; + /* EDID, raw and processed */ + u8 rawedid[256]; + int edidlen; + struct edid edid; + /* computed values needed for "i915" registers */ + int bytes_per_pixel; + u32 htotal; + u32 hblank; + u32 hsync; + u32 vtotal; + u32 vblank; + u32 vsync; + u32 pfa_sz; + u32 pfa_pos; + u32 pfa_ctl; + u32 pipesrc; + u32 stride; + struct intel_dp_m_n m_n; + u32 flags; + u32 transcoder; + /* parameters computed by the early startup, to be used + * in the GMA code. + */ + u8 *graphics; + /* physical address, not to be used directly. */ + u64 physbase; +}; + +/* we may yet need these. */ +void intel_dp_mode_set(struct intel_dp *intel_dp); +void intel_dp_start_link_train(struct intel_dp *intel_dp); + +int intel_dp_i2c_init(struct intel_dp *intel_dp); +int intel_dp_i2c_aux_ch(struct intel_dp *intel_dp, + int mode, uint8_t write_byte, uint8_t *read_byte); + +int intel_dp_get_dpcd(struct intel_dp *intel_dp); +struct edid *intel_dp_get_edid(struct intel_dp *intel_dp); + +void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); +void ironlake_edp_pll_on(void); +void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp); +void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, int sync); +int intel_dp_get_max_downspread(struct intel_dp *intel_dp, u8 *max_downspread); +void ironlake_edp_panel_on(struct intel_dp *intel_dp); +void ironlake_edp_backlight_on(struct intel_dp *intel_dp); +/* needed only on haswell. */ +void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port); +int intel_dp_aux_ch(struct intel_dp *intel_dp, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_size); +void unpack_aux(u32 src, uint8_t *dst, int dst_bytes); +int intel_channel_eq_ok(struct intel_dp *intel_dp, + uint8_t link_status[DP_LINK_STATUS_SIZE]); +void ironlake_edp_panel_off(struct intel_dp *intel_dp); +void ironlake_edp_backlight_off(struct intel_dp *intel_dp); + +/* drm_dp_helper.c */ +int drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count); +int drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], + int lane_count); +u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], + int lane); +u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], + int lane); + + +void intel_dp_wait_reg(unsigned long addr, + unsigned long val); + +void intel_dp_wait_panel_power_control(unsigned long val); + +void intel_dp_compute_m_n(unsigned int bits_per_pixel, + unsigned int nlanes, + unsigned int pixel_clock, + unsigned int link_clock, + struct intel_dp_m_n *m_n); + +u32 intel_ddi_calc_transcoder_flags(u32 pipe_bpp, + enum port port, + enum pipe pipe, + int type, + int lane_count, + int pf_sz, + u8 phsync, + u8 pvsync); + +enum transcoder intel_ddi_get_transcoder(enum port port, + enum pipe pipe); + +void intel_dp_set_m_n_regs(struct intel_dp *intel_dp); +int intel_dp_bw_code_to_link_rate(u8 link_bw); +void intel_dp_set_resolution(struct intel_dp *intel_dp); + +int intel_dp_i2c_write(struct intel_dp *intel_dp, + u8 val); + +int intel_dp_i2c_read(struct intel_dp *intel_dp, + u8 *val); + +int intel_dp_set_bw(struct intel_dp *intel_dp); +int intel_dp_set_lane_count(struct intel_dp *intel_dp); +int intel_dp_set_training_lane0(struct intel_dp *intel_dp, + u8 val); +int intel_dp_set_training_pattern(struct intel_dp *intel_dp, + u8 pat); + +int intel_dp_get_link_status(struct intel_dp *intel_dp, + uint8_t link_status[DP_LINK_STATUS_SIZE]); + +int intel_dp_get_training_pattern(struct intel_dp *intel_dp, + u8 *recv); + +int intel_dp_get_lane_count(struct intel_dp *intel_dp, + u8 *recv); + +int intel_dp_get_lane_align_status(struct intel_dp *intel_dp, + u8 *recv); + +void intel_prepare_ddi(void); +void intel_ddi_set_pipe_settings(struct intel_dp *intel_dp); + +int gtt_poll(u32 reg, u32 mask, u32 value); +void gtt_write(unsigned long reg, unsigned long data); +unsigned long gtt_read(unsigned long reg); + +int i915lightup(unsigned int physbase, unsigned int mmio, + unsigned int gfx, unsigned int init_fb); +int panel_lightup(struct intel_dp *dp, unsigned int init_fb); + +/* display.c */ +void compute_display_params(struct intel_dp *dp); diff --git a/src/drivers/intel/gma/i915_reg.h b/src/drivers/intel/gma/i915_reg.h new file mode 100644 index 0000000000..e413371fe9 --- /dev/null +++ b/src/drivers/intel/gma/i915_reg.h @@ -0,0 +1,4698 @@ +/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _I915_REG_H_ +#define _I915_REG_H_ + +#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a))) + +#define _PORT(port, a, b) ((a) + (port)*((b)-(a))) + +#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a)) +#define _MASKED_BIT_DISABLE(a) ((a) << 16) + +/* + * The Bridge device's PCI config space has information about the + * fb aperture size and the amount of pre-reserved memory. + * This is all handled in the intel-gtt.ko module. i915.ko only + * cares about the vga bit for the vga rbiter. + */ +#define INTEL_GMCH_CTRL 0x52 +#define INTEL_GMCH_VGA_DISABLE (1 << 1) +#define SNB_GMCH_CTRL 0x50 +#define SNB_GMCH_GGMS_SHIFT 8 /* GTT Graphics Memory Size */ +#define SNB_GMCH_GGMS_MASK 0x3 +#define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */ +#define SNB_GMCH_GMS_MASK 0x1f +#define IVB_GMCH_GMS_SHIFT 4 +#define IVB_GMCH_GMS_MASK 0xf + + +/* PCI config space */ + +#define HPLLCC 0xc0 /* 855 only */ +#define GC_CLOCK_CONTROL_MASK (0xf << 0) +#define GC_CLOCK_133_200 (0 << 0) +#define GC_CLOCK_100_200 (1 << 0) +#define GC_CLOCK_100_133 (2 << 0) +#define GC_CLOCK_166_250 (3 << 0) +#define GCFGC2 0xda +#define GCFGC 0xf0 /* 915+ only */ +#define GC_LOW_FREQUENCY_ENABLE (1 << 7) +#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4) +#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4) +#define GC_DISPLAY_CLOCK_MASK (7 << 4) +#define GM45_GC_RENDER_CLOCK_MASK (0xf << 0) +#define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0) +#define GM45_GC_RENDER_CLOCK_320_MHZ (9 << 0) +#define GM45_GC_RENDER_CLOCK_400_MHZ (0xb << 0) +#define GM45_GC_RENDER_CLOCK_533_MHZ (0xc << 0) +#define I965_GC_RENDER_CLOCK_MASK (0xf << 0) +#define I965_GC_RENDER_CLOCK_267_MHZ (2 << 0) +#define I965_GC_RENDER_CLOCK_333_MHZ (3 << 0) +#define I965_GC_RENDER_CLOCK_444_MHZ (4 << 0) +#define I965_GC_RENDER_CLOCK_533_MHZ (5 << 0) +#define I945_GC_RENDER_CLOCK_MASK (7 << 0) +#define I945_GC_RENDER_CLOCK_166_MHZ (0 << 0) +#define I945_GC_RENDER_CLOCK_200_MHZ (1 << 0) +#define I945_GC_RENDER_CLOCK_250_MHZ (3 << 0) +#define I945_GC_RENDER_CLOCK_400_MHZ (5 << 0) +#define I915_GC_RENDER_CLOCK_MASK (7 << 0) +#define I915_GC_RENDER_CLOCK_166_MHZ (0 << 0) +#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) +#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) +#define LBB 0xf4 + +/* Graphics reset regs */ +#define I965_GDRST 0xc0 /* PCI config register */ +#define ILK_GDSR 0x2ca4 /* MCHBAR offset */ +#define GRDOM_FULL (0<<2) +#define GRDOM_RENDER (1<<2) +#define GRDOM_MEDIA (3<<2) +#define GRDOM_RESET_ENABLE (1<<0) + +#define GEN6_MBCUNIT_SNPCR 0x900c /* for LLC config */ +#define GEN6_MBC_SNPCR_SHIFT 21 +#define GEN6_MBC_SNPCR_MASK (3<<21) +#define GEN6_MBC_SNPCR_MAX (0<<21) +#define GEN6_MBC_SNPCR_MED (1<<21) +#define GEN6_MBC_SNPCR_LOW (2<<21) +#define GEN6_MBC_SNPCR_MIN (3<<21) /* only 1/16th of the cache is shared */ + +#define GEN6_MBCTL 0x0907c +#define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4) +#define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3) +#define GEN6_MBCTL_BME_UPDATE_ENABLE (1 << 2) +#define GEN6_MBCTL_MAE_UPDATE_ENABLE (1 << 1) +#define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0) + +#define GEN6_GDRST 0x941c +#define GEN6_GRDOM_FULL (1 << 0) +#define GEN6_GRDOM_RENDER (1 << 1) +#define GEN6_GRDOM_MEDIA (1 << 2) +#define GEN6_GRDOM_BLT (1 << 3) + +#define RING_PP_DIR_BASE(ring) ((ring)->mmio_base+0x228) +#define RING_PP_DIR_BASE_READ(ring) ((ring)->mmio_base+0x518) +#define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220) +#define PP_DIR_DCLV_2G 0xffffffff + +#define GAM_ECOCHK 0x4090 +#define ECOCHK_SNB_BIT (1<<10) +#define ECOCHK_PPGTT_CACHE64B (0x3<<3) +#define ECOCHK_PPGTT_CACHE4B (0x0<<3) + +#define GAC_ECO_BITS 0x14090 +#define ECOBITS_PPGTT_CACHE64B (3<<8) +#define ECOBITS_PPGTT_CACHE4B (0<<8) + +#define GAB_CTL 0x24000 +#define GAB_CTL_CONT_AFTER_PAGEFAULT (1<<8) + +/* VGA stuff */ + +#define VGA_ST01_MDA 0x3ba +#define VGA_ST01_CGA 0x3da + +#define VGA_MSR_WRITE 0x3c2 +#define VGA_MSR_READ 0x3cc +#define VGA_MSR_MEM_EN (1<<1) +#define VGA_MSR_CGA_MODE (1<<0) + +#define VGA_SR_INDEX 0x3c4 +#define VGA_SR_DATA 0x3c5 + +#define VGA_AR_INDEX 0x3c0 +#define VGA_AR_VID_EN (1<<5) +#define VGA_AR_DATA_WRITE 0x3c0 +#define VGA_AR_DATA_READ 0x3c1 + +#define VGA_GR_INDEX 0x3ce +#define VGA_GR_DATA 0x3cf +/* GR05 */ +#define VGA_GR_MEM_READ_MODE_SHIFT 3 +#define VGA_GR_MEM_READ_MODE_PLANE 1 +/* GR06 */ +#define VGA_GR_MEM_MODE_MASK 0xc +#define VGA_GR_MEM_MODE_SHIFT 2 +#define VGA_GR_MEM_A0000_AFFFF 0 +#define VGA_GR_MEM_A0000_BFFFF 1 +#define VGA_GR_MEM_B0000_B7FFF 2 +#define VGA_GR_MEM_B0000_BFFFF 3 + +#define VGA_DACMASK 0x3c6 +#define VGA_DACRX 0x3c7 +#define VGA_DACWX 0x3c8 +#define VGA_DACDATA 0x3c9 + +#define VGA_CR_INDEX_MDA 0x3b4 +#define VGA_CR_DATA_MDA 0x3b5 +#define VGA_CR_INDEX_CGA 0x3d4 +#define VGA_CR_DATA_CGA 0x3d5 + +/* + * Memory interface instructions used by the kernel + */ +#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags)) + +#define MI_NOOP MI_INSTR(0, 0) +#define MI_USER_INTERRUPT MI_INSTR(0x02, 0) +#define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) +#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) +#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) +#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) +#define MI_FLUSH MI_INSTR(0x04, 0) +#define MI_READ_FLUSH (1 << 0) +#define MI_EXE_FLUSH (1 << 1) +#define MI_NO_WRITE_FLUSH (1 << 2) +#define MI_SCENE_COUNT (1 << 3) /* just increment scene count */ +#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ +#define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */ +#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) +#define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) +#define MI_SUSPEND_FLUSH_EN (1<<0) +#define MI_REPORT_HEAD MI_INSTR(0x07, 0) +#define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) +#define MI_OVERLAY_CONTINUE (0x0<<21) +#define MI_OVERLAY_ON (0x1<<21) +#define MI_OVERLAY_OFF (0x2<<21) +#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) +#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) +#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) +/* IVB has funny definitions for which plane to flip. */ +#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) +#define MI_ARB_ON_OFF MI_INSTR(0x08, 0) +#define MI_ARB_ENABLE (1<<0) +#define MI_ARB_DISABLE (0<<0) + +#define MI_SET_CONTEXT MI_INSTR(0x18, 0) +#define MI_MM_SPACE_GTT (1<<8) +#define MI_MM_SPACE_PHYSICAL (0<<8) +#define MI_SAVE_EXT_STATE_EN (1<<3) +#define MI_RESTORE_EXT_STATE_EN (1<<2) +#define MI_FORCE_RESTORE (1<<1) +#define MI_RESTORE_INHIBIT (1<<0) +#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) +#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ +#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) +#define MI_STORE_DWORD_INDEX_SHIFT 2 +/* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: + * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw + * simply ignores the register load under certain conditions. + * - One can actually load arbitrary many arbitrary registers: Simply issue x + * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! + */ +#define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) +#define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ +#define MI_FLUSH_DW_STORE_INDEX (1<<21) +#define MI_INVALIDATE_TLB (1<<18) +#define MI_FLUSH_DW_OP_STOREDW (1<<14) +#define MI_INVALIDATE_BSD (1<<7) +#define MI_FLUSH_DW_USE_GTT (1<<2) +#define MI_FLUSH_DW_USE_PPGTT (0<<2) +#define MI_BATCH_BUFFER MI_INSTR(0x30, 1) +#define MI_BATCH_NON_SECURE (1) +/* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */ +#define MI_BATCH_NON_SECURE_I965 (1<<8) +#define MI_BATCH_PPGTT_HSW (1<<8) +#define MI_BATCH_NON_SECURE_HSW (1<<13) +#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) +#define MI_BATCH_GTT (2<<6) /* aliased with (1<<7) on gen4 */ +#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ +#define MI_SEMAPHORE_GLOBAL_GTT (1<<22) +#define MI_SEMAPHORE_UPDATE (1<<21) +#define MI_SEMAPHORE_COMPARE (1<<20) +#define MI_SEMAPHORE_REGISTER (1<<18) +#define MI_SEMAPHORE_SYNC_RV (2<<16) +#define MI_SEMAPHORE_SYNC_RB (0<<16) +#define MI_SEMAPHORE_SYNC_VR (0<<16) +#define MI_SEMAPHORE_SYNC_VB (2<<16) +#define MI_SEMAPHORE_SYNC_BR (2<<16) +#define MI_SEMAPHORE_SYNC_BV (0<<16) +#define MI_SEMAPHORE_SYNC_INVALID (1<<0) +/* + * 3D instructions used by the kernel + */ +#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags)) + +#define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24)) +#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define SC_UPDATE_SCISSOR (0x1<<1) +#define SC_ENABLE_MASK (0x1<<0) +#define SC_ENABLE (0x1<<0) +#define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16)) +#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) +#define SCI_YMIN_MASK (0xffff<<16) +#define SCI_XMIN_MASK (0xffff<<0) +#define SCI_YMAX_MASK (0xffff<<16) +#define SCI_XMAX_MASK (0xffff<<0) +#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) +#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) +#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) +#define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) +#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) +#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) +#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) +#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) +#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define BLT_DEPTH_8 (0<<24) +#define BLT_DEPTH_16_565 (1<<24) +#define BLT_DEPTH_16_1555 (2<<24) +#define BLT_DEPTH_32 (3<<24) +#define BLT_ROP_GXCOPY (0xcc<<16) +#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */ +#define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */ +#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) +#define ASYNC_FLIP (1<<22) +#define DISPLAY_PLANE_A (0<<20) +#define DISPLAY_PLANE_B (1<<20) +#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) +#define PIPE_CONTROL_CS_STALL (1<<20) +#define PIPE_CONTROL_TLB_INVALIDATE (1<<18) +#define PIPE_CONTROL_QW_WRITE (1<<14) +#define PIPE_CONTROL_DEPTH_STALL (1<<13) +#define PIPE_CONTROL_WRITE_FLUSH (1<<12) +#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ +#define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */ +#define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */ +#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9) +#define PIPE_CONTROL_NOTIFY (1<<8) +#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4) +#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3) +#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2) +#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1) +#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0) +#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ + + +/* + * Reset registers + */ +#define DEBUG_RESET_I830 0x6070 +#define DEBUG_RESET_FULL (1<<7) +#define DEBUG_RESET_RENDER (1<<8) +#define DEBUG_RESET_DISPLAY (1<<9) + +/* + * DPIO - a special bus for various display related registers to hide behind: + * 0x800c: m1, m2, n, p1, p2, k dividers + * 0x8014: REF and SFR select + * 0x8014: N divider, VCO select + * 0x801c/3c: core clock bits + * 0x8048/68: low pass filter coefficients + * 0x8100: fast clock controls + */ +#define DPIO_PKT 0x2100 +#define DPIO_RID (0<<24) +#define DPIO_OP_WRITE (1<<16) +#define DPIO_OP_READ (0<<16) +#define DPIO_PORTID (0x12<<8) +#define DPIO_BYTE (0xf<<4) +#define DPIO_BUSY (1<<0) /* status only */ +#define DPIO_DATA 0x2104 +#define DPIO_REG 0x2108 +#define DPIO_CTL 0x2110 +#define DPIO_MODSEL1 (1<<3) /* if ref clk b == 27 */ +#define DPIO_MODSEL0 (1<<2) /* if ref clk a == 27 */ +#define DPIO_SFR_BYPASS (1<<1) +#define DPIO_RESET (1<<0) + +#define _DPIO_DIV_A 0x800c +#define DPIO_POST_DIV_SHIFT (28) /* 3 bits */ +#define DPIO_K_SHIFT (24) /* 4 bits */ +#define DPIO_P1_SHIFT (21) /* 3 bits */ +#define DPIO_P2_SHIFT (16) /* 5 bits */ +#define DPIO_N_SHIFT (12) /* 4 bits */ +#define DPIO_ENABLE_CALIBRATION (1<<11) +#define DPIO_M1DIV_SHIFT (8) /* 3 bits */ +#define DPIO_M2DIV_MASK 0xff +#define _DPIO_DIV_B 0x802c +#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B) + +#define _DPIO_REFSFR_A 0x8014 +#define DPIO_REFSEL_OVERRIDE 27 +#define DPIO_PLL_MODESEL_SHIFT 24 /* 3 bits */ +#define DPIO_BIAS_CURRENT_CTL_SHIFT 21 /* 3 bits, always 0x7 */ +#define DPIO_PLL_REFCLK_SEL_SHIFT 16 /* 2 bits */ +#define DPIO_PLL_REFCLK_SEL_MASK 3 +#define DPIO_DRIVER_CTL_SHIFT 12 /* always set to 0x8 */ +#define DPIO_CLK_BIAS_CTL_SHIFT 8 /* always set to 0x5 */ +#define _DPIO_REFSFR_B 0x8034 +#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B) + +#define _DPIO_CORE_CLK_A 0x801c +#define _DPIO_CORE_CLK_B 0x803c +#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) + +#define _DPIO_LFP_COEFF_A 0x8048 +#define _DPIO_LFP_COEFF_B 0x8068 +#define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B) + +#define DPIO_FASTCLK_DISABLE 0x8100 + +#define DPIO_DATA_CHANNEL1 0x8220 +#define DPIO_DATA_CHANNEL2 0x8420 + +/* + * Fence registers + */ +#define FENCE_REG_830_0 0x2000 +#define FENCE_REG_945_8 0x3000 +#define I830_FENCE_START_MASK 0x07f80000 +#define I830_FENCE_TILING_Y_SHIFT 12 +#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) +#define I830_FENCE_PITCH_SHIFT 4 +#define I830_FENCE_REG_VALID (1<<0) +#define I915_FENCE_MAX_PITCH_VAL 4 +#define I830_FENCE_MAX_PITCH_VAL 6 +#define I830_FENCE_MAX_SIZE_VAL (1<<8) + +#define I915_FENCE_START_MASK 0x0ff00000 +#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) + +#define FENCE_REG_965_0 0x03000 +#define I965_FENCE_PITCH_SHIFT 2 +#define I965_FENCE_TILING_Y_SHIFT 1 +#define I965_FENCE_REG_VALID (1<<0) +#define I965_FENCE_MAX_PITCH_VAL 0x0400 + +#define FENCE_REG_SANDYBRIDGE_0 0x100000 +#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32 + +/* control register for cpu gtt access */ +#define TILECTL 0x101000 +#define TILECTL_SWZCTL (1 << 0) +#define TILECTL_TLB_PREFETCH_DIS (1 << 2) +#define TILECTL_BACKSNOOP_DIS (1 << 3) + +/* + * Instruction and interrupt control regs + */ +#define PGTBL_ER 0x02024 +#define RENDER_RING_BASE 0x02000 +#define BSD_RING_BASE 0x04000 +#define GEN6_BSD_RING_BASE 0x12000 +#define BLT_RING_BASE 0x22000 +#define RING_TAIL(base) ((base)+0x30) +#define RING_HEAD(base) ((base)+0x34) +#define RING_START(base) ((base)+0x38) +#define RING_CTL(base) ((base)+0x3c) +#define RING_SYNC_0(base) ((base)+0x40) +#define RING_SYNC_1(base) ((base)+0x44) +#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) +#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) +#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) +#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) +#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) +#define RING_MAX_IDLE(base) ((base)+0x54) +#define RING_HWS_PGA(base) ((base)+0x80) +#define RING_HWS_PGA_GEN6(base) ((base)+0x2080) +#define ARB_MODE 0x04030 +#define ARB_MODE_SWIZZLE_SNB (1<<4) +#define ARB_MODE_SWIZZLE_IVB (1<<5) +#define RENDER_HWS_PGA_GEN7 (0x04080) +#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) +#define DONE_REG 0x40b0 +#define BSD_HWS_PGA_GEN7 (0x04180) +#define BLT_HWS_PGA_GEN7 (0x04280) +#define RING_ACTHD(base) ((base)+0x74) +#define RING_NOPID(base) ((base)+0x94) +#define RING_IMR(base) ((base)+0xa8) +#define RING_TIMESTAMP(base) ((base)+0x358) +#define TAIL_ADDR 0x001FFFF8 +#define HEAD_WRAP_COUNT 0xFFE00000 +#define HEAD_WRAP_ONE 0x00200000 +#define HEAD_ADDR 0x001FFFFC +#define RING_NR_PAGES 0x001FF000 +#define RING_REPORT_MASK 0x00000006 +#define RING_REPORT_64K 0x00000002 +#define RING_REPORT_128K 0x00000004 +#define RING_NO_REPORT 0x00000000 +#define RING_VALID_MASK 0x00000001 +#define RING_VALID 0x00000001 +#define RING_INVALID 0x00000000 +#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */ +#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ +#define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */ +#if 0 +#define PRB0_TAIL 0x02030 +#define PRB0_HEAD 0x02034 +#define PRB0_START 0x02038 +#define PRB0_CTL 0x0203c +#define PRB1_TAIL 0x02040 /* 915+ only */ +#define PRB1_HEAD 0x02044 /* 915+ only */ +#define PRB1_START 0x02048 /* 915+ only */ +#define PRB1_CTL 0x0204c /* 915+ only */ +#endif +#define IPEIR_I965 0x02064 +#define IPEHR_I965 0x02068 +#define INSTDONE_I965 0x0206c +#define GEN7_INSTDONE_1 0x0206c +#define GEN7_SC_INSTDONE 0x07100 +#define GEN7_SAMPLER_INSTDONE 0x0e160 +#define GEN7_ROW_INSTDONE 0x0e164 +#define I915_NUM_INSTDONE_REG 4 +#define RING_IPEIR(base) ((base)+0x64) +#define RING_IPEHR(base) ((base)+0x68) +#define RING_INSTDONE(base) ((base)+0x6c) +#define RING_INSTPS(base) ((base)+0x70) +#define RING_DMA_FADD(base) ((base)+0x78) +#define RING_INSTPM(base) ((base)+0xc0) +#define INSTPS 0x02070 /* 965+ only */ +#define INSTDONE1 0x0207c /* 965+ only */ +#define ACTHD_I965 0x02074 +#define HWS_PGA 0x02080 +#define HWS_ADDRESS_MASK 0xfffff000 +#define HWS_START_ADDRESS_SHIFT 4 +#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTX_EN (1<<0) +#define IPEIR 0x02088 +#define IPEHR 0x0208c +#define INSTDONE 0x02090 +#define NOPID 0x02094 +#define HWSTAM 0x02098 +#define DMA_FADD_I8XX 0x020d0 + +#define ERROR_GEN6 0x040a0 +#define GEN7_ERR_INT 0x44040 +#define ERR_INT_MMIO_UNCLAIMED (1<<13) + +#define DERRMR 0x44050 + +/* GM45+ chicken bits -- debug workaround bits that may be required + * for various sorts of correct behavior. The top 16 bits of each are + * the enables for writing to the corresponding low bit. + */ +#define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10) +#define _3D_CHICKEN2 0x0208c +/* Disables pipelining of read flushes past the SF-WIZ interface. + * Required on all Ironlake steppings according to the B-Spec, but the + * particular danger of not doing so is not specified. + */ +# define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) +#define _3D_CHICKEN3 0x02090 +#define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10) +#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) + +#define MI_MODE 0x0209c +# define VS_TIMER_DISPATCH (1 << 6) +# define MI_FLUSH_ENABLE (1 << 12) +# define ASYNC_FLIP_PERF_DISABLE (1 << 14) + +#define GEN6_GT_MODE 0x20d0 +#define GEN6_GT_MODE_HI (1 << 9) +#define GEN6_TD_FOUR_ROW_DISPATCH_DISABLE (1 << 5) + +#define GFX_MODE 0x02520 +#define GFX_MODE_GEN7 0x0229c +#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) +#define GFX_RUN_LIST_ENABLE (1<<15) +#define GFX_TLB_INVALIDATE_ALWAYS (1<<13) +#define GFX_SURFACE_FAULT_ENABLE (1<<12) +#define GFX_REPLAY_MODE (1<<11) +#define GFX_PSMI_GRANULARITY (1<<10) +#define GFX_PPGTT_ENABLE (1<<9) + +#define VLV_DISPLAY_BASE 0x180000 + +#define SCPD0 0x0209c /* 915+ only */ +#define IER 0x020a0 +#define IIR 0x020a4 +#define IMR 0x020a8 +#define ISR 0x020ac +#define VLV_GUNIT_CLOCK_GATE 0x182060 +#define GCFG_DIS (1<<8) +#define VLV_IIR_RW 0x182084 +#define VLV_IER 0x1820a0 +#define VLV_IIR 0x1820a4 +#define VLV_IMR 0x1820a8 +#define VLV_ISR 0x1820ac +#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) +#define I915_DISPLAY_PORT_INTERRUPT (1<<17) +#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) +#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */ +#define I915_HWB_OOM_INTERRUPT (1<<13) +#define I915_SYNC_STATUS_INTERRUPT (1<<12) +#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) +#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) +#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) +#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) +#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) +#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) +#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) +#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) +#define I915_DEBUG_INTERRUPT (1<<2) +#define I915_USER_INTERRUPT (1<<1) +#define I915_ASLE_INTERRUPT (1<<0) +#define I915_BSD_USER_INTERRUPT (1<<25) +#define EIR 0x020b0 +#define EMR 0x020b4 +#define ESR 0x020b8 +#define GM45_ERROR_PAGE_TABLE (1<<5) +#define GM45_ERROR_MEM_PRIV (1<<4) +#define I915_ERROR_PAGE_TABLE (1<<4) +#define GM45_ERROR_CP_PRIV (1<<3) +#define I915_ERROR_MEMORY_REFRESH (1<<1) +#define I915_ERROR_INSTRUCTION (1<<0) +#define INSTPM 0x020c0 +#define INSTPM_SELF_EN (1<<12) /* 915GM only */ +#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts + will not assert AGPBUSY# and will only + be delivered when out of C3. */ +#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ +#define ACTHD 0x020c8 +#define FW_BLC 0x020d8 +#define FW_BLC2 0x020dc +#define FW_BLC_SELF 0x020e0 /* 915+ only */ +#define FW_BLC_SELF_EN_MASK (1<<31) +#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ +#define FW_BLC_SELF_EN (1<<15) /* 945 only */ +#define MM_BURST_LENGTH 0x00700000 +#define MM_FIFO_WATERMARK 0x0001F000 +#define LM_BURST_LENGTH 0x00000700 +#define LM_FIFO_WATERMARK 0x0000001F +#define MI_ARB_STATE 0x020e4 /* 915+ only */ + +/* Make render/texture TLB fetches lower priorty than associated data + * fetches. This is not turned on by default + */ +#define MI_ARB_RENDER_TLB_LOW_PRIORITY (1 << 15) + +/* Isoch request wait on GTT enable (Display A/B/C streams). + * Make isoch requests stall on the TLB update. May cause + * display underruns (test mode only) + */ +#define MI_ARB_ISOCH_WAIT_GTT (1 << 14) + +/* Block grant count for isoch requests when block count is + * set to a finite value. + */ +#define MI_ARB_BLOCK_GRANT_MASK (3 << 12) +#define MI_ARB_BLOCK_GRANT_8 (0 << 12) /* for 3 display planes */ +#define MI_ARB_BLOCK_GRANT_4 (1 << 12) /* for 2 display planes */ +#define MI_ARB_BLOCK_GRANT_2 (2 << 12) /* for 1 display plane */ +#define MI_ARB_BLOCK_GRANT_0 (3 << 12) /* don't use */ + +/* Enable render writes to complete in C2/C3/C4 power states. + * If this isn't enabled, render writes are prevented in low + * power states. That seems bad to me. + */ +#define MI_ARB_C3_LP_WRITE_ENABLE (1 << 11) + +/* This acknowledges an async flip immediately instead + * of waiting for 2TLB fetches. + */ +#define MI_ARB_ASYNC_FLIP_ACK_IMMEDIATE (1 << 10) + +/* Enables non-sequential data reads through arbiter + */ +#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9) + +/* Disable FSB snooping of cacheable write cycles from binner/render + * command stream + */ +#define MI_ARB_CACHE_SNOOP_DISABLE (1 << 8) + +/* Arbiter time slice for non-isoch streams */ +#define MI_ARB_TIME_SLICE_MASK (7 << 5) +#define MI_ARB_TIME_SLICE_1 (0 << 5) +#define MI_ARB_TIME_SLICE_2 (1 << 5) +#define MI_ARB_TIME_SLICE_4 (2 << 5) +#define MI_ARB_TIME_SLICE_6 (3 << 5) +#define MI_ARB_TIME_SLICE_8 (4 << 5) +#define MI_ARB_TIME_SLICE_10 (5 << 5) +#define MI_ARB_TIME_SLICE_14 (6 << 5) +#define MI_ARB_TIME_SLICE_16 (7 << 5) + +/* Low priority grace period page size */ +#define MI_ARB_LOW_PRIORITY_GRACE_4KB (0 << 4) /* default */ +#define MI_ARB_LOW_PRIORITY_GRACE_8KB (1 << 4) + +/* Disable display A/B trickle feed */ +#define MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE (1 << 2) + +/* Set display plane priority */ +#define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */ +#define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */ + +#define CACHE_MODE_0 0x02120 /* 915+ only */ +#define CM0_PIPELINED_RENDER_FLUSH_DISABLE (1<<8) +#define CM0_IZ_OPT_DISABLE (1<<6) +#define CM0_ZR_OPT_DISABLE (1<<5) +#define CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5) +#define CM0_DEPTH_EVICT_DISABLE (1<<4) +#define CM0_COLOR_EVICT_DISABLE (1<<3) +#define CM0_DEPTH_WRITE_DISABLE (1<<1) +#define CM0_RC_OP_FLUSH_DISABLE (1<<0) +#define BB_ADDR 0x02140 /* 8 bytes */ +#define GFX_FLSH_CNTL 0x02170 /* 915+ only */ +#define GFX_FLSH_CNTL_GEN6 0x101008 +#define GFX_FLSH_CNTL_EN (1<<0) +#define ECOSKPD 0x021d0 +#define ECO_GATING_CX_ONLY (1<<3) +#define ECO_FLIP_DONE (1<<0) + +#define CACHE_MODE_1 0x7004 /* IVB+ */ +#define PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6) + +/* GEN6 interrupt control + * Note that the per-ring interrupt bits do alias with the global interrupt bits + * in GTIMR. */ +#define GEN6_RENDER_HWSTAM 0x2098 +#define GEN6_RENDER_IMR 0x20a8 +#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8) +#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7) +#define GEN6_RENDER_TIMEOUT_COUNTER_EXPIRED (1 << 6) +#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5) +#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4) +#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3) +#define GEN6_RENDER_SYNC_STATUS (1 << 2) +#define GEN6_RENDER_DEBUG_INTERRUPT (1 << 1) +#define GEN6_RENDER_USER_INTERRUPT (1 << 0) + +#define GEN6_BLITTER_HWSTAM 0x22098 +#define GEN6_BLITTER_IMR 0x220a8 +#define GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT (1 << 26) +#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) +#define GEN6_BLITTER_SYNC_STATUS (1 << 24) +#define GEN6_BLITTER_USER_INTERRUPT (1 << 22) + +#define GEN6_BLITTER_ECOSKPD 0x221d0 +#define GEN6_BLITTER_LOCK_SHIFT 16 +#define GEN6_BLITTER_FBC_NOTIFY (1<<3) + +#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 +#define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) +#define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) +#define GEN6_BSD_SLEEP_INDICATOR (1 << 3) +#define GEN6_BSD_GO_INDICATOR (1 << 4) + +#define GEN6_BSD_HWSTAM 0x12098 +#define GEN6_BSD_IMR 0x120a8 +#define GEN6_BSD_USER_INTERRUPT (1 << 12) + +#define GEN6_BSD_RNCID 0x12198 + +#define GEN7_FF_THREAD_MODE 0x20a0 +#define GEN7_FF_SCHED_MASK 0x0077070 +#define GEN7_FF_TS_SCHED_HS1 (0x5<<16) +#define GEN7_FF_TS_SCHED_HS0 (0x3<<16) +#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16) +#define GEN7_FF_TS_SCHED_HW (0x0<<16) /* Default */ +#define GEN7_FF_VS_SCHED_HS1 (0x5<<12) +#define GEN7_FF_VS_SCHED_HS0 (0x3<<12) +#define GEN7_FF_VS_SCHED_LOAD_BALANCE (0x1<<12) /* Default */ +#define GEN7_FF_VS_SCHED_HW (0x0<<12) +#define GEN7_FF_DS_SCHED_HS1 (0x5<<4) +#define GEN7_FF_DS_SCHED_HS0 (0x3<<4) +#define GEN7_FF_DS_SCHED_LOAD_BALANCE (0x1<<4) /* Default */ +#define GEN7_FF_DS_SCHED_HW (0x0<<4) + +/* + * Framebuffer compression (915+ only) + */ + +#define FBC_CFB_BASE 0x03200 /* 4k page aligned */ +#define FBC_LL_BASE 0x03204 /* 4k page aligned */ +#define FBC_CONTROL 0x03208 +#define FBC_CTL_EN (1<<31) +#define FBC_CTL_PERIODIC (1<<30) +#define FBC_CTL_INTERVAL_SHIFT (16) +#define FBC_CTL_UNCOMPRESSIBLE (1<<14) +#define FBC_CTL_C3_IDLE (1<<13) +#define FBC_CTL_STRIDE_SHIFT (5) +#define FBC_CTL_FENCENO (1<<0) +#define FBC_COMMAND 0x0320c +#define FBC_CMD_COMPRESS (1<<0) +#define FBC_STATUS 0x03210 +#define FBC_STAT_COMPRESSING (1<<31) +#define FBC_STAT_COMPRESSED (1<<30) +#define FBC_STAT_MODIFIED (1<<29) +#define FBC_STAT_CURRENT_LINE (1<<0) +#define FBC_CONTROL2 0x03214 +#define FBC_CTL_FENCE_DBL (0<<4) +#define FBC_CTL_IDLE_IMM (0<<2) +#define FBC_CTL_IDLE_FULL (1<<2) +#define FBC_CTL_IDLE_LINE (2<<2) +#define FBC_CTL_IDLE_DEBUG (3<<2) +#define FBC_CTL_CPU_FENCE (1<<1) +#define FBC_CTL_PLANEA (0<<0) +#define FBC_CTL_PLANEB (1<<0) +#define FBC_FENCE_OFF 0x0321b +#define FBC_TAG 0x03300 + +#define FBC_LL_SIZE (1536) + +/* Framebuffer compression for GM45+ */ +#define DPFC_CB_BASE 0x3200 +#define DPFC_CONTROL 0x3208 +#define DPFC_CTL_EN (1<<31) +#define DPFC_CTL_PLANEA (0<<30) +#define DPFC_CTL_PLANEB (1<<30) +#define DPFC_CTL_FENCE_EN (1<<29) +#define DPFC_CTL_PERSISTENT_MODE (1<<25) +#define DPFC_SR_EN (1<<10) +#define DPFC_CTL_LIMIT_1X (0<<6) +#define DPFC_CTL_LIMIT_2X (1<<6) +#define DPFC_CTL_LIMIT_4X (2<<6) +#define DPFC_RECOMP_CTL 0x320c +#define DPFC_RECOMP_STALL_EN (1<<27) +#define DPFC_RECOMP_STALL_WM_SHIFT (16) +#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) +#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) +#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) +#define DPFC_STATUS 0x3210 +#define DPFC_INVAL_SEG_SHIFT (16) +#define DPFC_INVAL_SEG_MASK (0x07ff0000) +#define DPFC_COMP_SEG_SHIFT (0) +#define DPFC_COMP_SEG_MASK (0x000003ff) +#define DPFC_STATUS2 0x3214 +#define DPFC_FENCE_YOFF 0x3218 +#define DPFC_CHICKEN 0x3224 +#define DPFC_HT_MODIFY (1<<31) + +/* Framebuffer compression for Ironlake */ +#define ILK_DPFC_CB_BASE 0x43200 +#define ILK_DPFC_CONTROL 0x43208 +/* The bit 28-8 is reserved */ +#define DPFC_RESERVED (0x1FFFFF00) +#define ILK_DPFC_RECOMP_CTL 0x4320c +#define ILK_DPFC_STATUS 0x43210 +#define ILK_DPFC_FENCE_YOFF 0x43218 +#define ILK_DPFC_CHICKEN 0x43224 +#define ILK_FBC_RT_BASE 0x2128 +#define ILK_FBC_RT_VALID (1<<0) + +#define ILK_DISPLAY_CHICKEN1 0x42000 +#define ILK_FBCQ_DIS (1<<22) +#define ILK_PABSTRETCH_DIS (1<<21) + + +/* + * Framebuffer compression for Sandybridge + * + * The following two registers are of type GTTMMADR + */ +#define SNB_DPFC_CTL_SA 0x100100 +#define SNB_CPU_FENCE_ENABLE (1<<29) +#define DPFC_CPU_FENCE_OFFSET 0x100104 + + +/* + * GPIO regs + */ +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 +#define GPIOD 0x501c +#define GPIOE 0x5020 +#define GPIOF 0x5024 +#define GPIOG 0x5028 +#define GPIOH 0x502c +# define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR_IN (0 << 1) +# define GPIO_CLOCK_DIR_OUT (1 << 1) +# define GPIO_CLOCK_VAL_MASK (1 << 2) +# define GPIO_CLOCK_VAL_OUT (1 << 3) +# define GPIO_CLOCK_VAL_IN (1 << 4) +# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) +# define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR_IN (0 << 9) +# define GPIO_DATA_DIR_OUT (1 << 9) +# define GPIO_DATA_VAL_MASK (1 << 10) +# define GPIO_DATA_VAL_OUT (1 << 11) +# define GPIO_DATA_VAL_IN (1 << 12) +# define GPIO_DATA_PULLUP_DISABLE (1 << 13) + +#define GMBUS0 0x5100 /* clock/port select */ +#define GMBUS_RATE_100KHZ (0<<8) +#define GMBUS_RATE_50KHZ (1<<8) +#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ +#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ +#define GMBUS_RATE_MASK (3<<8) +#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ +#define GMBUS_PORT_DISABLED 0 +#define GMBUS_PORT_SSC 1 +#define GMBUS_PORT_VGADDC 2 +#define GMBUS_PORT_PANEL 3 +#define GMBUS_PORT_DPC 4 /* HDMIC */ +#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ +#define GMBUS_PORT_DPD 6 /* HDMID */ +#define GMBUS_PORT_RESERVED 7 /* 7 reserved */ +#define GMBUS_NUM_PORTS (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1) +#define GMBUS_PORT_MASK 7 +#define GMBUS1 0x5104 /* command/status */ +#define GMBUS_SW_CLR_INT (1<<31) +#define GMBUS_SW_RDY (1<<30) +#define GMBUS_ENT (1<<29) /* enable timeout */ +#define GMBUS_CYCLE_NONE (0<<25) +#define GMBUS_CYCLE_WAIT (1<<25) +#define GMBUS_CYCLE_INDEX (2<<25) +#define GMBUS_CYCLE_STOP (4<<25) +#define GMBUS_BYTE_COUNT_SHIFT 16 +#define GMBUS_SLAVE_INDEX_SHIFT 8 +#define GMBUS_SLAVE_ADDR_SHIFT 1 +#define GMBUS_SLAVE_READ (1<<0) +#define GMBUS_SLAVE_WRITE (0<<0) +#define GMBUS2 0x5108 /* status */ +#define GMBUS_INUSE (1<<15) +#define GMBUS_HW_WAIT_PHASE (1<<14) +#define GMBUS_STALL_TIMEOUT (1<<13) +#define GMBUS_INT (1<<12) +#define GMBUS_HW_RDY (1<<11) +#define GMBUS_SATOER (1<<10) +#define GMBUS_ACTIVE (1<<9) +#define GMBUS3 0x510c /* data buffer bytes 3-0 */ +#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ +#define GMBUS_SLAVE_TIMEOUT_EN (1<<4) +#define GMBUS_NAK_EN (1<<3) +#define GMBUS_IDLE_EN (1<<2) +#define GMBUS_HW_WAIT_EN (1<<1) +#define GMBUS_HW_RDY_EN (1<<0) +#define GMBUS5 0x5120 /* byte index */ +#define GMBUS_2BYTE_INDEX_EN (1<<31) + +/* + * Clock control & power management + */ + +#define VGA0 0x6000 +#define VGA1 0x6004 +#define VGA_PD 0x6010 +#define VGA0_PD_P2_DIV_4 (1 << 7) +#define VGA0_PD_P1_DIV_2 (1 << 5) +#define VGA0_PD_P1_SHIFT 0 +#define VGA0_PD_P1_MASK (0x1f << 0) +#define VGA1_PD_P2_DIV_4 (1 << 15) +#define VGA1_PD_P1_DIV_2 (1 << 13) +#define VGA1_PD_P1_SHIFT 8 +#define VGA1_PD_P1_MASK (0x1f << 8) +#define _DPLL_A 0x06014 +#define _DPLL_B 0x06018 +#define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B) +#define DPLL_VCO_ENABLE (1 << 31) +#define DPLL_DVO_HIGH_SPEED (1 << 30) +#define DPLL_EXT_BUFFER_ENABLE_VLV (1 << 30) +#define DPLL_SYNCLOCK_ENABLE (1 << 29) +#define DPLL_REFA_CLK_ENABLE_VLV (1 << 29) +#define DPLL_VGA_MODE_DIS (1 << 28) +#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +#define DPLL_MODE_MASK (3 << 26) +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ +#define DPLL_LOCK_VLV (1<<15) +#define DPLL_INTEGRATED_CLOCK_VLV (1<<13) + +#define SRX_INDEX 0x3c4 +#define SRX_DATA 0x3c5 +#define SR01 1 +#define SR01_SCREEN_OFF (1<<5) + +#define PPCR 0x61204 +#define PPCR_ON (1<<0) + +#define DVOB 0x61140 +#define DVOB_ON (1<<31) +#define DVOC 0x61160 +#define DVOC_ON (1<<31) +#define LVDS 0x61180 +#define LVDS_ON (1<<31) + +/* Scratch pad debug 0 reg: + */ +#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 +/* + * The i830 generation, in LVDS mode, defines P1 as the bit number set within + * this field (only one bit may be set). + */ +#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15 +/* i830, required in DVO non-gang */ +#define PLL_P2_DIVIDE_BY_4 (1 << 23) +#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +#define PLL_REF_INPUT_DREFCLK (0 << 13) +#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ +#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +#define PLL_REF_INPUT_MASK (3 << 13) +#define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* Ironlake */ +# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 +# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) +# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9) +# define DPLL_FPA1_P1_POST_DIV_SHIFT 0 +# define DPLL_FPA1_P1_POST_DIV_MASK 0xff + +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +/* + * SDVO multiplier for 945G/GM. Not used on 965. + */ +#define SDVO_MULTIPLIER_MASK 0x000000ff +#define SDVO_MULTIPLIER_SHIFT_HIRES 4 +#define SDVO_MULTIPLIER_SHIFT_VGA 0 +#define _DPLL_A_MD 0x0601c /* 965+ only */ +/* + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +#define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/* + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/* + * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ +#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +#define _DPLL_B_MD 0x06020 /* 965+ only */ +#define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD) + +#define _FPA0 0x06040 +#define _FPA1 0x06044 +#define _FPB0 0x06048 +#define _FPB1 0x0604c +#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0) +#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1) +#define FP_N_DIV_MASK 0x003f0000 +#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 +#define FP_N_DIV_SHIFT 16 +#define FP_M1_DIV_MASK 0x00003f00 +#define FP_M1_DIV_SHIFT 8 +#define FP_M2_DIV_MASK 0x0000003f +#define FP_M2_PINEVIEW_DIV_MASK 0x000000ff +#define FP_M2_DIV_SHIFT 0 +#define DPLL_TEST 0x606c +#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +#define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +#define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +#define DPLLB_TEST_N_BYPASS (1 << 19) +#define DPLLB_TEST_M_BYPASS (1 << 18) +#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +#define DPLLA_TEST_N_BYPASS (1 << 3) +#define DPLLA_TEST_M_BYPASS (1 << 2) +#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) +#define D_STATE 0x6104 +#define DSTATE_GFX_RESET_I830 (1<<6) +#define DSTATE_PLL_D3_OFF (1<<3) +#define DSTATE_GFX_CLOCK_GATING (1<<1) +#define DSTATE_DOT_CLOCK_GATING (1<<0) +#define DSPCLK_GATE_D 0x6200 +# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */ +# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */ +# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */ +# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */ +# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */ +# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */ +# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */ +# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */ +# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */ +# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */ +# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */ +# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */ +# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */ +# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */ +# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */ +# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */ +# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */ +# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */ +# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */ +# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) +# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10) +# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9) +# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8) +# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */ +# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */ +# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */ +# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5) +# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4) +/** + * This bit must be set on the 830 to prevent hangs when turning off the + * overlay scaler. + */ +# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3) +# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2) +# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1) +# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */ +# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */ + +#define RENCLK_GATE_D1 0x6204 +# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */ +# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */ +# define PC_FE_CLOCK_GATE_DISABLE (1 << 11) +# define PC_BE_CLOCK_GATE_DISABLE (1 << 10) +# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9) +# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8) +# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7) +# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6) +# define MAG_CLOCK_GATE_DISABLE (1 << 5) +/** This bit must be unset on 855,865 */ +# define MECI_CLOCK_GATE_DISABLE (1 << 4) +# define DCMP_CLOCK_GATE_DISABLE (1 << 3) +# define MEC_CLOCK_GATE_DISABLE (1 << 2) +# define MECO_CLOCK_GATE_DISABLE (1 << 1) +/** This bit must be set on 855,865. */ +# define SV_CLOCK_GATE_DISABLE (1 << 0) +# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16) +# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15) +# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14) +# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13) +# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12) +# define I915_WM_CLOCK_GATE_DISABLE (1 << 11) +# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10) +# define I915_PI_CLOCK_GATE_DISABLE (1 << 9) +# define I915_DI_CLOCK_GATE_DISABLE (1 << 8) +# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7) +# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6) +# define I915_SC_CLOCK_GATE_DISABLE (1 << 5) +# define I915_FL_CLOCK_GATE_DISABLE (1 << 4) +# define I915_DM_CLOCK_GATE_DISABLE (1 << 3) +# define I915_PS_CLOCK_GATE_DISABLE (1 << 2) +# define I915_CC_CLOCK_GATE_DISABLE (1 << 1) +# define I915_BY_CLOCK_GATE_DISABLE (1 << 0) + +# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30) +/** This bit must always be set on 965G/965GM */ +# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29) +# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28) +# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27) +# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26) +# define I965_GW_CLOCK_GATE_DISABLE (1 << 25) +# define I965_TD_CLOCK_GATE_DISABLE (1 << 24) +/** This bit must always be set on 965G */ +# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23) +# define I965_IC_CLOCK_GATE_DISABLE (1 << 22) +# define I965_EU_CLOCK_GATE_DISABLE (1 << 21) +# define I965_IF_CLOCK_GATE_DISABLE (1 << 20) +# define I965_TC_CLOCK_GATE_DISABLE (1 << 19) +# define I965_SO_CLOCK_GATE_DISABLE (1 << 17) +# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16) +# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15) +# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14) +# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13) +# define I965_EM_CLOCK_GATE_DISABLE (1 << 12) +# define I965_UC_CLOCK_GATE_DISABLE (1 << 11) +# define I965_SI_CLOCK_GATE_DISABLE (1 << 6) +# define I965_MT_CLOCK_GATE_DISABLE (1 << 5) +# define I965_PL_CLOCK_GATE_DISABLE (1 << 4) +# define I965_DG_CLOCK_GATE_DISABLE (1 << 3) +# define I965_QC_CLOCK_GATE_DISABLE (1 << 2) +# define I965_FT_CLOCK_GATE_DISABLE (1 << 1) +# define I965_DM_CLOCK_GATE_DISABLE (1 << 0) + +#define RENCLK_GATE_D2 0x6208 +#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9) +#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7) +#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6) +#define RAMCLK_GATE_D 0x6210 /* CRL only */ +#define DEUC 0x6214 /* CRL only */ + +#define FW_BLC_SELF_VLV 0x6500 +#define FW_CSPWRDWNEN (1<<15) + +/* + * Palette regs + */ + +#define _PALETTE_A 0x0a000 +#define _PALETTE_B 0x0a800 +#define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B) + +/* MCH MMIO space */ + +/* + * MCHBAR mirror. + * + * This mirrors the MCHBAR MMIO space whose location is determined by + * device 0 function 0's pci config register 0x44 or 0x48 and matches it in + * every way. It is not accessible from the CP register read instructions. + * + */ +#define MCHBAR_MIRROR_BASE 0x10000 + +#define MCHBAR_MIRROR_BASE_SNB 0x140000 + +/** 915-945 and GM965 MCH register controlling DRAM channel access */ +#define DCC 0x10200 +#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0) +#define DCC_ADDRESSING_MODE_MASK (3 << 0) +#define DCC_CHANNEL_XOR_DISABLE (1 << 10) +#define DCC_CHANNEL_XOR_BIT_17 (1 << 9) + +/** Pineview MCH register contains DDR3 setting */ +#define CSHRDDR3CTL 0x101a8 +#define CSHRDDR3CTL_DDR3 (1 << 2) + +/** 965 MCH register controlling DRAM channel configuration */ +#define C0DRB3 0x10206 +#define C1DRB3 0x10606 + +/** snb MCH registers for reading the DRAM channel configuration */ +#define MAD_DIMM_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5004) +#define MAD_DIMM_C1 (MCHBAR_MIRROR_BASE_SNB + 0x5008) +#define MAD_DIMM_C2 (MCHBAR_MIRROR_BASE_SNB + 0x500C) +#define MAD_DIMM_ECC_MASK (0x3 << 24) +#define MAD_DIMM_ECC_OFF (0x0 << 24) +#define MAD_DIMM_ECC_IO_ON_LOGIC_OFF (0x1 << 24) +#define MAD_DIMM_ECC_IO_OFF_LOGIC_ON (0x2 << 24) +#define MAD_DIMM_ECC_ON (0x3 << 24) +#define MAD_DIMM_ENH_INTERLEAVE (0x1 << 22) +#define MAD_DIMM_RANK_INTERLEAVE (0x1 << 21) +#define MAD_DIMM_B_WIDTH_X16 (0x1 << 20) /* X8 chips if unset */ +#define MAD_DIMM_A_WIDTH_X16 (0x1 << 19) /* X8 chips if unset */ +#define MAD_DIMM_B_DUAL_RANK (0x1 << 18) +#define MAD_DIMM_A_DUAL_RANK (0x1 << 17) +#define MAD_DIMM_A_SELECT (0x1 << 16) +/* DIMM sizes are in multiples of 256mb. */ +#define MAD_DIMM_B_SIZE_SHIFT 8 +#define MAD_DIMM_B_SIZE_MASK (0xff << MAD_DIMM_B_SIZE_SHIFT) +#define MAD_DIMM_A_SIZE_SHIFT 0 +#define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT) + + +/* Clocking configuration register */ +#define CLKCFG 0x10c00 +#define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ +#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ +#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ +#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ +#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ +#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ +/* Note, below two are guess */ +#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_MASK (7 << 0) +#define CLKCFG_MEM_533 (1 << 4) +#define CLKCFG_MEM_667 (2 << 4) +#define CLKCFG_MEM_800 (3 << 4) +#define CLKCFG_MEM_MASK (7 << 4) + +#define TSC1 0x11001 +#define TSE (1<<0) +#define TR1 0x11006 +#define TSFS 0x11020 +#define TSFS_SLOPE_MASK 0x0000ff00 +#define TSFS_SLOPE_SHIFT 8 +#define TSFS_INTR_MASK 0x000000ff + +#define CRSTANDVID 0x11100 +#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ +#define PXVFREQ_PX_MASK 0x7f000000 +#define PXVFREQ_PX_SHIFT 24 +#define VIDFREQ_BASE 0x11110 +#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */ +#define VIDFREQ2 0x11114 +#define VIDFREQ3 0x11118 +#define VIDFREQ4 0x1111c +#define VIDFREQ_P0_MASK 0x1f000000 +#define VIDFREQ_P0_SHIFT 24 +#define VIDFREQ_P0_CSCLK_MASK 0x00f00000 +#define VIDFREQ_P0_CSCLK_SHIFT 20 +#define VIDFREQ_P0_CRCLK_MASK 0x000f0000 +#define VIDFREQ_P0_CRCLK_SHIFT 16 +#define VIDFREQ_P1_MASK 0x00001f00 +#define VIDFREQ_P1_SHIFT 8 +#define VIDFREQ_P1_CSCLK_MASK 0x000000f0 +#define VIDFREQ_P1_CSCLK_SHIFT 4 +#define VIDFREQ_P1_CRCLK_MASK 0x0000000f +#define INTTOEXT_BASE_ILK 0x11300 +#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */ +#define INTTOEXT_MAP3_SHIFT 24 +#define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT) +#define INTTOEXT_MAP2_SHIFT 16 +#define INTTOEXT_MAP2_MASK (0x1f << INTTOEXT_MAP2_SHIFT) +#define INTTOEXT_MAP1_SHIFT 8 +#define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT) +#define INTTOEXT_MAP0_SHIFT 0 +#define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT) +#define MEMSWCTL 0x11170 /* Ironlake only */ +#define MEMCTL_CMD_MASK 0xe000 +#define MEMCTL_CMD_SHIFT 13 +#define MEMCTL_CMD_RCLK_OFF 0 +#define MEMCTL_CMD_RCLK_ON 1 +#define MEMCTL_CMD_CHFREQ 2 +#define MEMCTL_CMD_CHVID 3 +#define MEMCTL_CMD_VMMOFF 4 +#define MEMCTL_CMD_VMMON 5 +#define MEMCTL_CMD_STS (1<<12) /* write 1 triggers command, clears + when command complete */ +#define MEMCTL_FREQ_MASK 0x0f00 /* jitter, from 0-15 */ +#define MEMCTL_FREQ_SHIFT 8 +#define MEMCTL_SFCAVM (1<<7) +#define MEMCTL_TGT_VID_MASK 0x007f +#define MEMIHYST 0x1117c +#define MEMINTREN 0x11180 /* 16 bits */ +#define MEMINT_RSEXIT_EN (1<<8) +#define MEMINT_CX_SUPR_EN (1<<7) +#define MEMINT_CONT_BUSY_EN (1<<6) +#define MEMINT_AVG_BUSY_EN (1<<5) +#define MEMINT_EVAL_CHG_EN (1<<4) +#define MEMINT_MON_IDLE_EN (1<<3) +#define MEMINT_UP_EVAL_EN (1<<2) +#define MEMINT_DOWN_EVAL_EN (1<<1) +#define MEMINT_SW_CMD_EN (1<<0) +#define MEMINTRSTR 0x11182 /* 16 bits */ +#define MEM_RSEXIT_MASK 0xc000 +#define MEM_RSEXIT_SHIFT 14 +#define MEM_CONT_BUSY_MASK 0x3000 +#define MEM_CONT_BUSY_SHIFT 12 +#define MEM_AVG_BUSY_MASK 0x0c00 +#define MEM_AVG_BUSY_SHIFT 10 +#define MEM_EVAL_CHG_MASK 0x0300 +#define MEM_EVAL_BUSY_SHIFT 8 +#define MEM_MON_IDLE_MASK 0x00c0 +#define MEM_MON_IDLE_SHIFT 6 +#define MEM_UP_EVAL_MASK 0x0030 +#define MEM_UP_EVAL_SHIFT 4 +#define MEM_DOWN_EVAL_MASK 0x000c +#define MEM_DOWN_EVAL_SHIFT 2 +#define MEM_SW_CMD_MASK 0x0003 +#define MEM_INT_STEER_GFX 0 +#define MEM_INT_STEER_CMR 1 +#define MEM_INT_STEER_SMI 2 +#define MEM_INT_STEER_SCI 3 +#define MEMINTRSTS 0x11184 +#define MEMINT_RSEXIT (1<<7) +#define MEMINT_CONT_BUSY (1<<6) +#define MEMINT_AVG_BUSY (1<<5) +#define MEMINT_EVAL_CHG (1<<4) +#define MEMINT_MON_IDLE (1<<3) +#define MEMINT_UP_EVAL (1<<2) +#define MEMINT_DOWN_EVAL (1<<1) +#define MEMINT_SW_CMD (1<<0) +#define MEMMODECTL 0x11190 +#define MEMMODE_BOOST_EN (1<<31) +#define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */ +#define MEMMODE_BOOST_FREQ_SHIFT 24 +#define MEMMODE_IDLE_MODE_MASK 0x00030000 +#define MEMMODE_IDLE_MODE_SHIFT 16 +#define MEMMODE_IDLE_MODE_EVAL 0 +#define MEMMODE_IDLE_MODE_CONT 1 +#define MEMMODE_HWIDLE_EN (1<<15) +#define MEMMODE_SWMODE_EN (1<<14) +#define MEMMODE_RCLK_GATE (1<<13) +#define MEMMODE_HW_UPDATE (1<<12) +#define MEMMODE_FSTART_MASK 0x00000f00 /* starting jitter, 0-15 */ +#define MEMMODE_FSTART_SHIFT 8 +#define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */ +#define MEMMODE_FMAX_SHIFT 4 +#define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */ +#define RCBMAXAVG 0x1119c +#define MEMSWCTL2 0x1119e /* Cantiga only */ +#define SWMEMCMD_RENDER_OFF (0 << 13) +#define SWMEMCMD_RENDER_ON (1 << 13) +#define SWMEMCMD_SWFREQ (2 << 13) +#define SWMEMCMD_TARVID (3 << 13) +#define SWMEMCMD_VRM_OFF (4 << 13) +#define SWMEMCMD_VRM_ON (5 << 13) +#define CMDSTS (1<<12) +#define SFCAVM (1<<11) +#define SWFREQ_MASK 0x0380 /* P0-7 */ +#define SWFREQ_SHIFT 7 +#define TARVID_MASK 0x001f +#define MEMSTAT_CTG 0x111a0 +#define RCBMINAVG 0x111a0 +#define RCUPEI 0x111b0 +#define RCDNEI 0x111b4 +#define RSTDBYCTL 0x111b8 +#define RS1EN (1<<31) +#define RS2EN (1<<30) +#define RS3EN (1<<29) +#define D3RS3EN (1<<28) /* Display D3 imlies RS3 */ +#define SWPROMORSX (1<<27) /* RSx promotion timers ignored */ +#define RCWAKERW (1<<26) /* Resetwarn from PCH causes wakeup */ +#define DPRSLPVREN (1<<25) /* Fast voltage ramp enable */ +#define GFXTGHYST (1<<24) /* Hysteresis to allow trunk gating */ +#define RCX_SW_EXIT (1<<23) /* Leave RSx and prevent re-entry */ +#define RSX_STATUS_MASK (7<<20) +#define RSX_STATUS_ON (0<<20) +#define RSX_STATUS_RC1 (1<<20) +#define RSX_STATUS_RC1E (2<<20) +#define RSX_STATUS_RS1 (3<<20) +#define RSX_STATUS_RS2 (4<<20) /* aka rc6 */ +#define RSX_STATUS_RSVD (5<<20) /* deep rc6 unsupported on ilk */ +#define RSX_STATUS_RS3 (6<<20) /* rs3 unsupported on ilk */ +#define RSX_STATUS_RSVD2 (7<<20) +#define UWRCRSXE (1<<19) /* wake counter limit prevents rsx */ +#define RSCRP (1<<18) /* rs requests control on rs1/2 reqs */ +#define JRSC (1<<17) /* rsx coupled to cpu c-state */ +#define RS2INC0 (1<<16) /* allow rs2 in cpu c0 */ +#define RS1CONTSAV_MASK (3<<14) +#define RS1CONTSAV_NO_RS1 (0<<14) /* rs1 doesn't save/restore context */ +#define RS1CONTSAV_RSVD (1<<14) +#define RS1CONTSAV_SAVE_RS1 (2<<14) /* rs1 saves context */ +#define RS1CONTSAV_FULL_RS1 (3<<14) /* rs1 saves and restores context */ +#define NORMSLEXLAT_MASK (3<<12) +#define SLOW_RS123 (0<<12) +#define SLOW_RS23 (1<<12) +#define SLOW_RS3 (2<<12) +#define NORMAL_RS123 (3<<12) +#define RCMODE_TIMEOUT (1<<11) /* 0 is eval interval method */ +#define IMPROMOEN (1<<10) /* promo is immediate or delayed until next idle interval (only for timeout method above) */ +#define RCENTSYNC (1<<9) /* rs coupled to cpu c-state (3/6/7) */ +#define STATELOCK (1<<7) /* locked to rs_cstate if 0 */ +#define RS_CSTATE_MASK (3<<4) +#define RS_CSTATE_C367_RS1 (0<<4) +#define RS_CSTATE_C36_RS1_C7_RS2 (1<<4) +#define RS_CSTATE_RSVD (2<<4) +#define RS_CSTATE_C367_RS2 (3<<4) +#define REDSAVES (1<<3) /* no context save if was idle during rs0 */ +#define REDRESTORES (1<<2) /* no restore if was idle during rs0 */ +#define VIDCTL 0x111c0 +#define VIDSTS 0x111c8 +#define VIDSTART 0x111cc /* 8 bits */ +#define MEMSTAT_ILK 0x111f8 +#define MEMSTAT_VID_MASK 0x7f00 +#define MEMSTAT_VID_SHIFT 8 +#define MEMSTAT_PSTATE_MASK 0x00f8 +#define MEMSTAT_PSTATE_SHIFT 3 +#define MEMSTAT_MON_ACTV (1<<2) +#define MEMSTAT_SRC_CTL_MASK 0x0003 +#define MEMSTAT_SRC_CTL_CORE 0 +#define MEMSTAT_SRC_CTL_TRB 1 +#define MEMSTAT_SRC_CTL_THM 2 +#define MEMSTAT_SRC_CTL_STDBY 3 +#define RCPREVBSYTUPAVG 0x113b8 +#define RCPREVBSYTDNAVG 0x113bc +#define PMMISC 0x11214 +#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */ +#define SDEW 0x1124c +#define CSIEW0 0x11250 +#define CSIEW1 0x11254 +#define CSIEW2 0x11258 +#define PEW 0x1125c +#define DEW 0x11270 +#define MCHAFE 0x112c0 +#define CSIEC 0x112e0 +#define DMIEC 0x112e4 +#define DDREC 0x112e8 +#define PEG0EC 0x112ec +#define PEG1EC 0x112f0 +#define GFXEC 0x112f4 +#define RPPREVBSYTUPAVG 0x113b8 +#define RPPREVBSYTDNAVG 0x113bc +#define ECR 0x11600 +#define ECR_GPFE (1<<31) +#define ECR_IMONE (1<<30) +#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */ +#define OGW0 0x11608 +#define OGW1 0x1160c +#define EG0 0x11610 +#define EG1 0x11614 +#define EG2 0x11618 +#define EG3 0x1161c +#define EG4 0x11620 +#define EG5 0x11624 +#define EG6 0x11628 +#define EG7 0x1162c +#define PXW 0x11664 +#define PXWL 0x11680 +#define LCFUSE02 0x116c0 +#define LCFUSE_HIV_MASK 0x000000ff +#define CSIPLL0 0x12c10 +#define DDRMPLL1 0X12c20 +#define PEG_BAND_GAP_DATA 0x14d68 + +#define GEN6_GT_THREAD_STATUS_REG 0x13805c +#define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 +#define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) + +#define GEN6_GT_PERF_STATUS 0x145948 +#define GEN6_RP_STATE_LIMITS 0x145994 +#define GEN6_RP_STATE_CAP 0x145998 + +/* + * Logical Context regs + */ +#define CCID 0x2180 +#define CCID_EN (1<<0) +#define CXT_SIZE 0x21a0 +#define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f) +#define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f) +#define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f) +#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f) +#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f) +#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_POWER_SIZE(cxt_reg) + \ + GEN6_CXT_RING_SIZE(cxt_reg) + \ + GEN6_CXT_RENDER_SIZE(cxt_reg) + \ + GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ + GEN6_CXT_PIPELINE_SIZE(cxt_reg)) +#define GEN7_CXT_SIZE 0x21a8 +#define GEN7_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 25) & 0x7f) +#define GEN7_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 22) & 0x7) +#define GEN7_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f) +#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f) +#define GEN7_CXT_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7) +#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f) +#define GEN7_CXT_TOTAL_SIZE(ctx_reg) (GEN7_CXT_POWER_SIZE(ctx_reg) + \ + GEN7_CXT_RING_SIZE(ctx_reg) + \ + GEN7_CXT_RENDER_SIZE(ctx_reg) + \ + GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \ + GEN7_CXT_GT1_SIZE(ctx_reg) + \ + GEN7_CXT_VFSTATE_SIZE(ctx_reg)) +#define HSW_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 26) & 0x3f) +#define HSW_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 23) & 0x7) +#define HSW_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 15) & 0xff) +#define HSW_CXT_TOTAL_SIZE(ctx_reg) (HSW_CXT_POWER_SIZE(ctx_reg) + \ + HSW_CXT_RING_SIZE(ctx_reg) + \ + HSW_CXT_RENDER_SIZE(ctx_reg) + \ + GEN7_CXT_VFSTATE_SIZE(ctx_reg)) + + +/* + * Overlay regs + */ + +#define OVADD 0x30000 +#define DOVSTA 0x30008 +#define OC_BUF (0x3<<20) +#define OGAMC5 0x30010 +#define OGAMC4 0x30014 +#define OGAMC3 0x30018 +#define OGAMC2 0x3001c +#define OGAMC1 0x30020 +#define OGAMC0 0x30024 + +/* + * Display engine regs + */ + +/* Pipe A timing regs */ +#define _HTOTAL_A 0x60000 +#define _HBLANK_A 0x60004 +#define _HSYNC_A 0x60008 +#define _VTOTAL_A 0x6000c +#define _VBLANK_A 0x60010 +#define _VSYNC_A 0x60014 +#define _PIPEASRC 0x6001c +#define _BCLRPAT_A 0x60020 +#define _VSYNCSHIFT_A 0x60028 + +/* Pipe B timing regs */ +#define _HTOTAL_B 0x61000 +#define _HBLANK_B 0x61004 +#define _HSYNC_B 0x61008 +#define _VTOTAL_B 0x6100c +#define _VBLANK_B 0x61010 +#define _VSYNC_B 0x61014 +#define _PIPEBSRC 0x6101c +#define _BCLRPAT_B 0x61020 +#define _VSYNCSHIFT_B 0x61028 + + +#define HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B) +#define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B) +#define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B) +#define VTOTAL(trans) _TRANSCODER(trans, _VTOTAL_A, _VTOTAL_B) +#define VBLANK(trans) _TRANSCODER(trans, _VBLANK_A, _VBLANK_B) +#define VSYNC(trans) _TRANSCODER(trans, _VSYNC_A, _VSYNC_B) +#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B) +#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B) + +/* VGA port control */ +#define ADPA 0x61100 +#define PCH_ADPA 0xe1100 +#define VLV_ADPA (VLV_DISPLAY_BASE + ADPA) + +#define ADPA_DAC_ENABLE (1<<31) +#define ADPA_DAC_DISABLE 0 +#define ADPA_PIPE_SELECT_MASK (1<<30) +#define ADPA_PIPE_A_SELECT 0 +#define ADPA_PIPE_B_SELECT (1<<30) +#define ADPA_PIPE_SELECT(pipe) ((pipe) << 30) +/* CPT uses bits 29:30 for pch transcoder select */ +#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */ +#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2<<24) +#define ADPA_CRT_HOTPLUG_ENABLE (1<<23) +#define ADPA_CRT_HOTPLUG_PERIOD_64 (0<<22) +#define ADPA_CRT_HOTPLUG_PERIOD_128 (1<<22) +#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0<<21) +#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1<<21) +#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0<<20) +#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1<<20) +#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3<<18) +#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0<<17) +#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) +#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) +#define ADPA_USE_VGA_HVPOLARITY (1<<15) +#define ADPA_SETS_HVPOLARITY 0 +#define ADPA_VSYNC_CNTL_DISABLE (1<<11) +#define ADPA_VSYNC_CNTL_ENABLE 0 +#define ADPA_HSYNC_CNTL_DISABLE (1<<10) +#define ADPA_HSYNC_CNTL_ENABLE 0 +#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) +#define ADPA_VSYNC_ACTIVE_LOW 0 +#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) +#define ADPA_HSYNC_ACTIVE_LOW 0 +#define ADPA_DPMS_MASK (~(3<<10)) +#define ADPA_DPMS_ON (0<<10) +#define ADPA_DPMS_SUSPEND (1<<10) +#define ADPA_DPMS_STANDBY (2<<10) +#define ADPA_DPMS_OFF (3<<10) + + +/* Hotplug control (945+ only) */ +#define PORT_HOTPLUG_EN 0x61110 +#define HDMIB_HOTPLUG_INT_EN (1 << 29) +#define DPB_HOTPLUG_INT_EN (1 << 29) +#define HDMIC_HOTPLUG_INT_EN (1 << 28) +#define DPC_HOTPLUG_INT_EN (1 << 28) +#define HDMID_HOTPLUG_INT_EN (1 << 27) +#define DPD_HOTPLUG_INT_EN (1 << 27) +#define SDVOB_HOTPLUG_INT_EN (1 << 26) +#define SDVOC_HOTPLUG_INT_EN (1 << 25) +#define TV_HOTPLUG_INT_EN (1 << 18) +#define CRT_HOTPLUG_INT_EN (1 << 9) +#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) + +#define PORT_HOTPLUG_STAT 0x61114 +/* HDMI/DP bits are gen4+ */ +#define DPB_HOTPLUG_LIVE_STATUS (1 << 29) +#define DPC_HOTPLUG_LIVE_STATUS (1 << 28) +#define DPD_HOTPLUG_LIVE_STATUS (1 << 27) +#define DPD_HOTPLUG_INT_STATUS (3 << 21) +#define DPC_HOTPLUG_INT_STATUS (3 << 19) +#define DPB_HOTPLUG_INT_STATUS (3 << 17) +/* HDMI bits are shared with the DP bits */ +#define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29) +#define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28) +#define HDMID_HOTPLUG_LIVE_STATUS (1 << 27) +#define HDMID_HOTPLUG_INT_STATUS (3 << 21) +#define HDMIC_HOTPLUG_INT_STATUS (3 << 19) +#define HDMIB_HOTPLUG_INT_STATUS (3 << 17) +/* CRT/TV common between gen3+ */ +#define CRT_HOTPLUG_INT_STATUS (1 << 11) +#define TV_HOTPLUG_INT_STATUS (1 << 10) +#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +/* SDVO is different across gen3/4 */ +#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) +#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) +#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) + +/* SDVO port control */ +#define SDVOB 0x61140 +#define SDVOC 0x61160 +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_B_SELECT (1 << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/** + * 915G/GM SDVO pixel multiplier. + * + * Programmed value is multiplier - 1, up to 5x. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) +#define SDVO_ENCODING_SDVO (0x0 << 10) +#define SDVO_ENCODING_HDMI (0x2 << 10) +/** Requird for HDMI operation */ +#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) +#define SDVO_COLOR_RANGE_16_235 (1 << 8) +#define SDVO_BORDER_ENABLE (1 << 7) +#define SDVO_AUDIO_ENABLE (1 << 6) +/** New with 965, default is to be set */ +#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +/** New with 965, default is to be set */ +#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define SDVOB_PCIE_CONCURRENCY (1 << 3) +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26)) +#define SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26)) + +/* DVO port control */ +#define DVOA 0x61120 +#define DVOB 0x61140 +#define DVOC 0x61160 +#define DVO_ENABLE (1 << 31) +#define DVO_PIPE_B_SELECT (1 << 30) +#define DVO_PIPE_STALL_UNUSED (0 << 28) +#define DVO_PIPE_STALL (1 << 28) +#define DVO_PIPE_STALL_TV (2 << 28) +#define DVO_PIPE_STALL_MASK (3 << 28) +#define DVO_USE_VGA_SYNC (1 << 15) +#define DVO_DATA_ORDER_I740 (0 << 14) +#define DVO_DATA_ORDER_FP (1 << 14) +#define DVO_VSYNC_DISABLE (1 << 11) +#define DVO_HSYNC_DISABLE (1 << 10) +#define DVO_VSYNC_TRISTATE (1 << 9) +#define DVO_HSYNC_TRISTATE (1 << 8) +#define DVO_BORDER_ENABLE (1 << 7) +#define DVO_DATA_ORDER_GBRG (1 << 6) +#define DVO_DATA_ORDER_RGGB (0 << 6) +#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) +#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) +#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) +#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define DVO_BLANK_ACTIVE_HIGH (1 << 2) +#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ +#define DVO_PRESERVE_MASK (0x7<<24) +#define DVOA_SRCDIM 0x61124 +#define DVOB_SRCDIM 0x61144 +#define DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 +#define DVO_SRCDIM_VERTICAL_SHIFT 0 + +/* LVDS port control */ +#define LVDS 0x61180 +/* + * Enables the LVDS port. This bit must be set before DPLLs are enabled, as + * the DPLL semantics change when the LVDS is assigned to that pipe. + */ +#define LVDS_PORT_EN (1 << 31) +/* Selects pipe B for LVDS data. Must be set on pre-965. */ +#define LVDS_PIPEB_SELECT (1 << 30) +#define LVDS_PIPE_MASK (1 << 30) +#define LVDS_PIPE(pipe) ((pipe) << 30) +/* LVDS dithering flag on 965/g4x platform */ +#define LVDS_ENABLE_DITHER (1 << 25) +/* LVDS sync polarity flags. Set to invert (i.e. negative) */ +#define LVDS_VSYNC_POLARITY (1 << 21) +#define LVDS_HSYNC_POLARITY (1 << 20) + +/* Enable border for unscaled (or aspect-scaled) display */ +#define LVDS_BORDER_ENABLE (1 << 15) +/* + * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per + * pixel. + */ +#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) +#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) +#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) +/* + * Controls the A3 data pair, which contains the additional LSBs for 24 bit + * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be + * on. + */ +#define LVDS_A3_POWER_MASK (3 << 6) +#define LVDS_A3_POWER_DOWN (0 << 6) +#define LVDS_A3_POWER_UP (3 << 6) +/* + * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP + * is set. + */ +#define LVDS_CLKB_POWER_MASK (3 << 4) +#define LVDS_CLKB_POWER_DOWN (0 << 4) +#define LVDS_CLKB_POWER_UP (3 << 4) +/* + * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 + * setting for whether we are in dual-channel mode. The B3 pair will + * additionally only be powered up when LVDS_A3_POWER_UP is set. + */ +#define LVDS_B0B3_POWER_MASK (3 << 2) +#define LVDS_B0B3_POWER_DOWN (0 << 2) +#define LVDS_B0B3_POWER_UP (3 << 2) + +/* Video Data Island Packet control */ +#define VIDEO_DIP_DATA 0x61178 +/* Read the description of VIDEO_DIP_DATA (before Haswel) or VIDEO_DIP_ECC + * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte + * of the infoframe structure specified by CEA-861. */ +#define VIDEO_DIP_DATA_SIZE 32 +#define VIDEO_DIP_CTL 0x61170 +/* Pre HSW: */ +#define VIDEO_DIP_ENABLE (1 << 31) +#define VIDEO_DIP_PORT_B (1 << 29) +#define VIDEO_DIP_PORT_C (2 << 29) +#define VIDEO_DIP_PORT_D (3 << 29) +#define VIDEO_DIP_PORT_MASK (3 << 29) +#define VIDEO_DIP_ENABLE_GCP (1 << 25) +#define VIDEO_DIP_ENABLE_AVI (1 << 21) +#define VIDEO_DIP_ENABLE_VENDOR (2 << 21) +#define VIDEO_DIP_ENABLE_GAMUT (4 << 21) +#define VIDEO_DIP_ENABLE_SPD (8 << 21) +#define VIDEO_DIP_SELECT_AVI (0 << 19) +#define VIDEO_DIP_SELECT_VENDOR (1 << 19) +#define VIDEO_DIP_SELECT_SPD (3 << 19) +#define VIDEO_DIP_SELECT_MASK (3 << 19) +#define VIDEO_DIP_FREQ_ONCE (0 << 16) +#define VIDEO_DIP_FREQ_VSYNC (1 << 16) +#define VIDEO_DIP_FREQ_2VSYNC (2 << 16) +#define VIDEO_DIP_FREQ_MASK (3 << 16) +/* HSW and later: */ +#define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) +#define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) +#define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) +#define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) +#define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) +#define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) + +/* Panel power sequencing */ +#define PP_STATUS 0x61200 +#define PP_ON (1 << 31) +/* + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +#define PP_READY (1 << 30) +#define PP_SEQUENCE_NONE (0 << 28) +#define PP_SEQUENCE_POWER_UP (1 << 28) +#define PP_SEQUENCE_POWER_DOWN (2 << 28) +#define PP_SEQUENCE_MASK (3 << 28) +#define PP_SEQUENCE_SHIFT 28 +#define PP_CYCLE_DELAY_ACTIVE (1 << 27) +#define PP_SEQUENCE_STATE_MASK 0x0000000f +#define PP_SEQUENCE_STATE_OFF_IDLE (0x0 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_1 (0x1 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_2 (0x2 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_3 (0x3 << 0) +#define PP_SEQUENCE_STATE_ON_IDLE (0x8 << 0) +#define PP_SEQUENCE_STATE_ON_S1_0 (0x9 << 0) +#define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0) +#define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0) +#define PP_SEQUENCE_STATE_RESET (0xf << 0) +#define PP_CONTROL 0x61204 +#define POWER_TARGET_ON (1 << 0) +#define PP_ON_DELAYS 0x61208 +#define PP_OFF_DELAYS 0x6120c +#define PP_DIVISOR 0x61210 + +/* Panel fitting */ +#define PFIT_CONTROL 0x61230 +#define PFIT_ENABLE (1 << 31) +#define PFIT_PIPE_MASK (3 << 29) +#define PFIT_PIPE_SHIFT 29 +#define VERT_INTERP_DISABLE (0 << 10) +#define VERT_INTERP_BILINEAR (1 << 10) +#define VERT_INTERP_MASK (3 << 10) +#define VERT_AUTO_SCALE (1 << 9) +#define HORIZ_INTERP_DISABLE (0 << 6) +#define HORIZ_INTERP_BILINEAR (1 << 6) +#define HORIZ_INTERP_MASK (3 << 6) +#define HORIZ_AUTO_SCALE (1 << 5) +#define PANEL_8TO6_DITHER_ENABLE (1 << 3) +#define PFIT_FILTER_FUZZY (0 << 24) +#define PFIT_SCALING_AUTO (0 << 26) +#define PFIT_SCALING_PROGRAMMED (1 << 26) +#define PFIT_SCALING_PILLAR (2 << 26) +#define PFIT_SCALING_LETTER (3 << 26) +#define PFIT_PGM_RATIOS 0x61234 +#define PFIT_VERT_SCALE_MASK 0xfff00000 +#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* Pre-965 */ +#define PFIT_VERT_SCALE_SHIFT 20 +#define PFIT_VERT_SCALE_MASK 0xfff00000 +#define PFIT_HORIZ_SCALE_SHIFT 4 +#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* 965+ */ +#define PFIT_VERT_SCALE_SHIFT_965 16 +#define PFIT_VERT_SCALE_MASK_965 0x1fff0000 +#define PFIT_HORIZ_SCALE_SHIFT_965 0 +#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff + +#define PFIT_AUTO_RATIOS 0x61238 + +/* Backlight control */ +#define BLC_PWM_CTL2 0x61250 /* 965+ only */ +#define BLM_PWM_ENABLE (1 << 31) +#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ +#define BLM_PIPE_SELECT (1 << 29) +#define BLM_PIPE_SELECT_IVB (3 << 29) +#define BLM_PIPE_A (0 << 29) +#define BLM_PIPE_B (1 << 29) +#define BLM_PIPE_C (2 << 29) /* ivb + */ +#define BLM_PIPE(pipe) ((pipe) << 29) +#define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ +#define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) +#define BLM_PHASE_IN_ENABLE (1 << 25) +#define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) +#define BLM_PHASE_IN_TIME_BASE_SHIFT (16) +#define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) +#define BLM_PHASE_IN_COUNT_SHIFT (8) +#define BLM_PHASE_IN_COUNT_MASK (0xff << 8) +#define BLM_PHASE_IN_INCR_SHIFT (0) +#define BLM_PHASE_IN_INCR_MASK (0xff << 0) +#define BLC_PWM_CTL 0x61254 +/* + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ +/* + * This is the number of cycles out of the backlight modulation cycle for which + * the backlight is on. + * + * This field must be no greater than the number of cycles in the complete + * backlight modulation cycle. + */ +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) +#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) +#define BLM_POLARITY_PNV (1 << 0) /* pnv only */ + +#define BLC_HIST_CTL 0x61260 + +/* New registers for PCH-split platforms. Safe where new bits show up, the + * register layout machtes with gen4 BLC_PWM_CTL[12]. */ +#define BLC_PWM_CPU_CTL2 0x48250 +#define BLC_PWM2_ENABLE (1<<31) +#define BLC_PWM_CPU_CTL 0x48254 + +#define BLM_HIST_CTL 0x48260 +#define ENH_HIST_ENABLE (1<<31) +#define ENH_MODIF_TBL_ENABLE (1<<30) +#define ENH_PIPE_A_SELECT (0<<29) +#define ENH_PIPE_B_SELECT (1<<29) +#define ENH_PIPE(pipe) _PIPE(pipe, ENH_PIPE_A_SELECT, ENH_PIPE_B_SELECT) +#define HIST_MODE_YUV (0<<24) +#define HIST_MODE_HSV (1<<24) +#define ENH_MODE_DIRECT (0<<13) +#define ENH_MODE_ADDITIVE (1<<13) +#define ENH_MODE_MULTIPLICATIVE (2<<13) +#define BIN_REGISTER_SET (1<<11) +#define ENH_NUM_BINS 32 + +#define BLM_HIST_ENH 0x48264 + +#define BLM_HIST_GUARD_BAND 0x48268 +#define BLM_HIST_INTR_ENABLE (1<<31) +#define BLM_HIST_EVENT_STATUS (1<<30) +#define BLM_HIST_INTR_DELAY_MASK (0xFF<<22) +#define BLM_HIST_INTR_DELAY_SHIFT 22 + +/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is + * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ +#define BLC_PWM_PCH_CTL1 0xc8250 +#define BLM_PCH_PWM_ENABLE (1 << 31) +#define BLM_PCH_OVERRIDE_ENABLE (1 << 30) +#define BLM_PCH_POLARITY (1 << 29) +#define BLC_PWM_PCH_CTL2 0xc8254 + +/* TV port control */ +#define TV_CTL 0x68000 +/** Enables the TV encoder */ +# define TV_ENC_ENABLE (1 << 31) +/** Sources the TV encoder input from pipe B instead of A. */ +# define TV_ENC_PIPEB_SELECT (1 << 30) +/** Outputs composite video (DAC A only) */ +# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) +/** Outputs SVideo video (DAC B/C) */ +# define TV_ENC_OUTPUT_SVIDEO (1 << 28) +/** Outputs Component video (DAC A/B/C) */ +# define TV_ENC_OUTPUT_COMPONENT (2 << 28) +/** Outputs Composite and SVideo (DAC A/B/C) */ +# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28) +# define TV_TRILEVEL_SYNC (1 << 21) +/** Enables slow sync generation (945GM only) */ +# define TV_SLOW_SYNC (1 << 20) +/** Selects 4x oversampling for 480i and 576p */ +# define TV_OVERSAMPLE_4X (0 << 18) +/** Selects 2x oversampling for 720p and 1080i */ +# define TV_OVERSAMPLE_2X (1 << 18) +/** Selects no oversampling for 1080p */ +# define TV_OVERSAMPLE_NONE (2 << 18) +/** Selects 8x oversampling */ +# define TV_OVERSAMPLE_8X (3 << 18) +/** Selects progressive mode rather than interlaced */ +# define TV_PROGRESSIVE (1 << 17) +/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */ +# define TV_PAL_BURST (1 << 16) +/** Field for setting delay of Y compared to C */ +# define TV_YC_SKEW_MASK (7 << 12) +/** Enables a fix for 480p/576p standard definition modes on the 915GM only */ +# define TV_ENC_SDP_FIX (1 << 11) +/** + * Enables a fix for the 915GM only. + * + * Not sure what it does. + */ +# define TV_ENC_C0_FIX (1 << 10) +/** Bits that must be preserved by software */ +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) +# define TV_FUSE_STATE_MASK (3 << 4) +/** Read-only state that reports all features enabled */ +# define TV_FUSE_STATE_ENABLED (0 << 4) +/** Read-only state that reports that Macrovision is disabled in hardware*/ +# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) +/** Read-only state that reports that TV-out is disabled in hardware. */ +# define TV_FUSE_STATE_DISABLED (2 << 4) +/** Normal operation */ +# define TV_TEST_MODE_NORMAL (0 << 0) +/** Encoder test pattern 1 - combo pattern */ +# define TV_TEST_MODE_PATTERN_1 (1 << 0) +/** Encoder test pattern 2 - full screen vertical 75% color bars */ +# define TV_TEST_MODE_PATTERN_2 (2 << 0) +/** Encoder test pattern 3 - full screen horizontal 75% color bars */ +# define TV_TEST_MODE_PATTERN_3 (3 << 0) +/** Encoder test pattern 4 - random noise */ +# define TV_TEST_MODE_PATTERN_4 (4 << 0) +/** Encoder test pattern 5 - linear color ramps */ +# define TV_TEST_MODE_PATTERN_5 (5 << 0) +/** + * This test mode forces the DACs to 50% of full output. + * + * This is used for load detection in combination with TVDAC_SENSE_MASK + */ +# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) +# define TV_TEST_MODE_MASK (7 << 0) + +#define TV_DAC 0x68004 +# define TV_DAC_SAVE 0x00ffff00 +/** + * Reports that DAC state change logic has reported change (RO). + * + * This gets cleared when TV_DAC_STATE_EN is cleared +*/ +# define TVDAC_STATE_CHG (1 << 31) +# define TVDAC_SENSE_MASK (7 << 28) +/** Reports that DAC A voltage is above the detect threshold */ +# define TVDAC_A_SENSE (1 << 30) +/** Reports that DAC B voltage is above the detect threshold */ +# define TVDAC_B_SENSE (1 << 29) +/** Reports that DAC C voltage is above the detect threshold */ +# define TVDAC_C_SENSE (1 << 28) +/** + * Enables DAC state detection logic, for load-based TV detection. + * + * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set + * to off, for load detection to work. + */ +# define TVDAC_STATE_CHG_EN (1 << 27) +/** Sets the DAC A sense value to high */ +# define TVDAC_A_SENSE_CTL (1 << 26) +/** Sets the DAC B sense value to high */ +# define TVDAC_B_SENSE_CTL (1 << 25) +/** Sets the DAC C sense value to high */ +# define TVDAC_C_SENSE_CTL (1 << 24) +/** Overrides the ENC_ENABLE and DAC voltage levels */ +# define DAC_CTL_OVERRIDE (1 << 7) +/** Sets the slew rate. Must be preserved in software */ +# define ENC_TVDAC_SLEW_FAST (1 << 6) +# define DAC_A_1_3_V (0 << 4) +# define DAC_A_1_1_V (1 << 4) +# define DAC_A_0_7_V (2 << 4) +# define DAC_A_MASK (3 << 4) +# define DAC_B_1_3_V (0 << 2) +# define DAC_B_1_1_V (1 << 2) +# define DAC_B_0_7_V (2 << 2) +# define DAC_B_MASK (3 << 2) +# define DAC_C_1_3_V (0 << 0) +# define DAC_C_1_1_V (1 << 0) +# define DAC_C_0_7_V (2 << 0) +# define DAC_C_MASK (3 << 0) + +/** + * CSC coefficients are stored in a floating point format with 9 bits of + * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, + * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with + * -1 (0x3) being the only legal negative value. + */ +#define TV_CSC_Y 0x68010 +# define TV_RY_MASK 0x07ff0000 +# define TV_RY_SHIFT 16 +# define TV_GY_MASK 0x00000fff +# define TV_GY_SHIFT 0 + +#define TV_CSC_Y2 0x68014 +# define TV_BY_MASK 0x07ff0000 +# define TV_BY_SHIFT 16 +/** + * Y attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AY_MASK 0x000003ff +# define TV_AY_SHIFT 0 + +#define TV_CSC_U 0x68018 +# define TV_RU_MASK 0x07ff0000 +# define TV_RU_SHIFT 16 +# define TV_GU_MASK 0x000007ff +# define TV_GU_SHIFT 0 + +#define TV_CSC_U2 0x6801c +# define TV_BU_MASK 0x07ff0000 +# define TV_BU_SHIFT 16 +/** + * U attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AU_MASK 0x000003ff +# define TV_AU_SHIFT 0 + +#define TV_CSC_V 0x68020 +# define TV_RV_MASK 0x0fff0000 +# define TV_RV_SHIFT 16 +# define TV_GV_MASK 0x000007ff +# define TV_GV_SHIFT 0 + +#define TV_CSC_V2 0x68024 +# define TV_BV_MASK 0x07ff0000 +# define TV_BV_SHIFT 16 +/** + * V attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AV_MASK 0x000007ff +# define TV_AV_SHIFT 0 + +#define TV_CLR_KNOBS 0x68028 +/** 2s-complement brightness adjustment */ +# define TV_BRIGHTNESS_MASK 0xff000000 +# define TV_BRIGHTNESS_SHIFT 24 +/** Contrast adjustment, as a 2.6 unsigned floating point number */ +# define TV_CONTRAST_MASK 0x00ff0000 +# define TV_CONTRAST_SHIFT 16 +/** Saturation adjustment, as a 2.6 unsigned floating point number */ +# define TV_SATURATION_MASK 0x0000ff00 +# define TV_SATURATION_SHIFT 8 +/** Hue adjustment, as an integer phase angle in degrees */ +# define TV_HUE_MASK 0x000000ff +# define TV_HUE_SHIFT 0 + +#define TV_CLR_LEVEL 0x6802c +/** Controls the DAC level for black */ +# define TV_BLACK_LEVEL_MASK 0x01ff0000 +# define TV_BLACK_LEVEL_SHIFT 16 +/** Controls the DAC level for blanking */ +# define TV_BLANK_LEVEL_MASK 0x000001ff +# define TV_BLANK_LEVEL_SHIFT 0 + +#define TV_H_CTL_1 0x68030 +/** Number of pixels in the hsync. */ +# define TV_HSYNC_END_MASK 0x1fff0000 +# define TV_HSYNC_END_SHIFT 16 +/** Total number of pixels minus one in the line (display and blanking). */ +# define TV_HTOTAL_MASK 0x00001fff +# define TV_HTOTAL_SHIFT 0 + +#define TV_H_CTL_2 0x68034 +/** Enables the colorburst (needed for non-component color) */ +# define TV_BURST_ENA (1 << 31) +/** Offset of the colorburst from the start of hsync, in pixels minus one. */ +# define TV_HBURST_START_SHIFT 16 +# define TV_HBURST_START_MASK 0x1fff0000 +/** Length of the colorburst */ +# define TV_HBURST_LEN_SHIFT 0 +# define TV_HBURST_LEN_MASK 0x0001fff + +#define TV_H_CTL_3 0x68038 +/** End of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_END_SHIFT 16 +# define TV_HBLANK_END_MASK 0x1fff0000 +/** Start of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_START_SHIFT 0 +# define TV_HBLANK_START_MASK 0x0001fff + +#define TV_V_CTL_1 0x6803c +/** XXX */ +# define TV_NBR_END_SHIFT 16 +# define TV_NBR_END_MASK 0x07ff0000 +/** XXX */ +# define TV_VI_END_F1_SHIFT 8 +# define TV_VI_END_F1_MASK 0x00003f00 +/** XXX */ +# define TV_VI_END_F2_SHIFT 0 +# define TV_VI_END_F2_MASK 0x0000003f + +#define TV_V_CTL_2 0x68040 +/** Length of vsync, in half lines */ +# define TV_VSYNC_LEN_MASK 0x07ff0000 +# define TV_VSYNC_LEN_SHIFT 16 +/** Offset of the start of vsync in field 1, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F1_MASK 0x00007f00 +# define TV_VSYNC_START_F1_SHIFT 8 +/** + * Offset of the start of vsync in field 2, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F2_MASK 0x0000007f +# define TV_VSYNC_START_F2_SHIFT 0 + +#define TV_V_CTL_3 0x68044 +/** Enables generation of the equalization signal */ +# define TV_EQUAL_ENA (1 << 31) +/** Length of vsync, in half lines */ +# define TV_VEQ_LEN_MASK 0x007f0000 +# define TV_VEQ_LEN_SHIFT 16 +/** Offset of the start of equalization in field 1, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F1_MASK 0x0007f00 +# define TV_VEQ_START_F1_SHIFT 8 +/** + * Offset of the start of equalization in field 2, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F2_MASK 0x000007f +# define TV_VEQ_START_F2_SHIFT 0 + +#define TV_V_CTL_4 0x68048 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F1_MASK 0x003f0000 +# define TV_VBURST_START_F1_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F1_MASK 0x000000ff +# define TV_VBURST_END_F1_SHIFT 0 + +#define TV_V_CTL_5 0x6804c +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F2_MASK 0x003f0000 +# define TV_VBURST_START_F2_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F2_MASK 0x000000ff +# define TV_VBURST_END_F2_SHIFT 0 + +#define TV_V_CTL_6 0x68050 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F3_MASK 0x003f0000 +# define TV_VBURST_START_F3_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F3_MASK 0x000000ff +# define TV_VBURST_END_F3_SHIFT 0 + +#define TV_V_CTL_7 0x68054 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F4_MASK 0x003f0000 +# define TV_VBURST_START_F4_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F4_MASK 0x000000ff +# define TV_VBURST_END_F4_SHIFT 0 + +#define TV_SC_CTL_1 0x68060 +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA1_EN (1 << 31) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA2_EN (1 << 30) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA3_EN (1 << 29) +/** Sets the subcarrier DDA to reset frequency every other field */ +# define TV_SC_RESET_EVERY_2 (0 << 24) +/** Sets the subcarrier DDA to reset frequency every fourth field */ +# define TV_SC_RESET_EVERY_4 (1 << 24) +/** Sets the subcarrier DDA to reset frequency every eighth field */ +# define TV_SC_RESET_EVERY_8 (2 << 24) +/** Sets the subcarrier DDA to never reset the frequency */ +# define TV_SC_RESET_NEVER (3 << 24) +/** Sets the peak amplitude of the colorburst.*/ +# define TV_BURST_LEVEL_MASK 0x00ff0000 +# define TV_BURST_LEVEL_SHIFT 16 +/** Sets the increment of the first subcarrier phase generation DDA */ +# define TV_SCDDA1_INC_MASK 0x00000fff +# define TV_SCDDA1_INC_SHIFT 0 + +#define TV_SC_CTL_2 0x68064 +/** Sets the rollover for the second subcarrier phase generation DDA */ +# define TV_SCDDA2_SIZE_MASK 0x7fff0000 +# define TV_SCDDA2_SIZE_SHIFT 16 +/** Sets the increent of the second subcarrier phase generation DDA */ +# define TV_SCDDA2_INC_MASK 0x00007fff +# define TV_SCDDA2_INC_SHIFT 0 + +#define TV_SC_CTL_3 0x68068 +/** Sets the rollover for the third subcarrier phase generation DDA */ +# define TV_SCDDA3_SIZE_MASK 0x7fff0000 +# define TV_SCDDA3_SIZE_SHIFT 16 +/** Sets the increent of the third subcarrier phase generation DDA */ +# define TV_SCDDA3_INC_MASK 0x00007fff +# define TV_SCDDA3_INC_SHIFT 0 + +#define TV_WIN_POS 0x68070 +/** X coordinate of the display from the start of horizontal active */ +# define TV_XPOS_MASK 0x1fff0000 +# define TV_XPOS_SHIFT 16 +/** Y coordinate of the display from the start of vertical active (NBR) */ +# define TV_YPOS_MASK 0x00000fff +# define TV_YPOS_SHIFT 0 + +#define TV_WIN_SIZE 0x68074 +/** Horizontal size of the display window, measured in pixels*/ +# define TV_XSIZE_MASK 0x1fff0000 +# define TV_XSIZE_SHIFT 16 +/** + * Vertical size of the display window, measured in pixels. + * + * Must be even for interlaced modes. + */ +# define TV_YSIZE_MASK 0x00000fff +# define TV_YSIZE_SHIFT 0 + +#define TV_FILTER_CTL_1 0x68080 +/** + * Enables automatic scaling calculation. + * + * If set, the rest of the registers are ignored, and the calculated values can + * be read back from the register. + */ +# define TV_AUTO_SCALE (1 << 31) +/** + * Disables the vertical filter. + * + * This is required on modes more than 1024 pixels wide */ +# define TV_V_FILTER_BYPASS (1 << 29) +/** Enables adaptive vertical filtering */ +# define TV_VADAPT (1 << 28) +# define TV_VADAPT_MODE_MASK (3 << 26) +/** Selects the least adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_LEAST (0 << 26) +/** Selects the moderately adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MODERATE (1 << 26) +/** Selects the most adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MOST (3 << 26) +/** + * Sets the horizontal scaling factor. + * + * This should be the fractional part of the horizontal scaling factor divided + * by the oversampling rate. TV_HSCALE should be less than 1, and set to: + * + * (src width - 1) / ((oversample * dest width) - 1) + */ +# define TV_HSCALE_FRAC_MASK 0x00003fff +# define TV_HSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_2 0x68084 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) + */ +# define TV_VSCALE_INT_MASK 0x00038000 +# define TV_VSCALE_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * \sa TV_VSCALE_INT_MASK + */ +# define TV_VSCALE_FRAC_MASK 0x00007fff +# define TV_VSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_3 0x68088 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + */ +# define TV_VSCALE_IP_INT_MASK 0x00038000 +# define TV_VSCALE_IP_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + * + * \sa TV_VSCALE_IP_INT_MASK + */ +# define TV_VSCALE_IP_FRAC_MASK 0x00007fff +# define TV_VSCALE_IP_FRAC_SHIFT 0 + +#define TV_CC_CONTROL 0x68090 +# define TV_CC_ENABLE (1 << 31) +/** + * Specifies which field to send the CC data in. + * + * CC data is usually sent in field 0. + */ +# define TV_CC_FID_MASK (1 << 27) +# define TV_CC_FID_SHIFT 27 +/** Sets the horizontal position of the CC data. Usually 135. */ +# define TV_CC_HOFF_MASK 0x03ff0000 +# define TV_CC_HOFF_SHIFT 16 +/** Sets the vertical position of the CC data. Usually 21 */ +# define TV_CC_LINE_MASK 0x0000003f +# define TV_CC_LINE_SHIFT 0 + +#define TV_CC_DATA 0x68094 +# define TV_CC_RDY (1 << 31) +/** Second word of CC data to be transmitted. */ +# define TV_CC_DATA_2_MASK 0x007f0000 +# define TV_CC_DATA_2_SHIFT 16 +/** First word of CC data to be transmitted. */ +# define TV_CC_DATA_1_MASK 0x0000007f +# define TV_CC_DATA_1_SHIFT 0 + +#define TV_H_LUMA_0 0x68100 +#define TV_H_LUMA_59 0x681ec +#define TV_H_CHROMA_0 0x68200 +#define TV_H_CHROMA_59 0x682ec +#define TV_V_LUMA_0 0x68300 +#define TV_V_LUMA_42 0x683a8 +#define TV_V_CHROMA_0 0x68400 +#define TV_V_CHROMA_42 0x684a8 + +/* Display Port */ +#define DP_A 0x64000 /* eDP */ +#define DP_B 0x64100 +#define DP_C 0x64200 +#define DP_D 0x64300 + +#define DP_PORT_EN (1 << 31) +#define DP_PIPEB_SELECT (1 << 30) +#define DP_PIPE_MASK (1 << 30) + +/* Link training mode - select a suitable mode for each stage */ +#define DP_LINK_TRAIN_PAT_1 (0 << 28) +#define DP_LINK_TRAIN_PAT_2 (1 << 28) +#define DP_LINK_TRAIN_PAT_IDLE (2 << 28) +#define DP_LINK_TRAIN_OFF (3 << 28) +#define DP_LINK_TRAIN_MASK (3 << 28) +#define DP_LINK_TRAIN_SHIFT 28 + +/* CPT Link training mode */ +#define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) +#define DP_LINK_TRAIN_PAT_2_CPT (1 << 8) +#define DP_LINK_TRAIN_PAT_IDLE_CPT (2 << 8) +#define DP_LINK_TRAIN_OFF_CPT (3 << 8) +#define DP_LINK_TRAIN_MASK_CPT (7 << 8) +#define DP_LINK_TRAIN_SHIFT_CPT 8 + +/* Signal voltages. These are mostly controlled by the other end */ +#define DP_VOLTAGE_0_4 (0 << 25) +#define DP_VOLTAGE_0_6 (1 << 25) +#define DP_VOLTAGE_0_8 (2 << 25) +#define DP_VOLTAGE_1_2 (3 << 25) +#define DP_VOLTAGE_MASK (7 << 25) +#define DP_VOLTAGE_SHIFT 25 + +/* Signal pre-emphasis levels, like voltages, the other end tells us what + * they want + */ +#define DP_PRE_EMPHASIS_0 (0 << 22) +#define DP_PRE_EMPHASIS_3_5 (1 << 22) +#define DP_PRE_EMPHASIS_6 (2 << 22) +#define DP_PRE_EMPHASIS_9_5 (3 << 22) +#define DP_PRE_EMPHASIS_MASK (7 << 22) +#define DP_PRE_EMPHASIS_SHIFT 22 + +/* How many wires to use. I guess 3 was too hard */ +#define DP_PORT_WIDTH_1 (0 << 19) +#define DP_PORT_WIDTH_2 (1 << 19) +#define DP_PORT_WIDTH_4 (3 << 19) +#define DP_PORT_WIDTH_MASK (7 << 19) + +/* Mystic DPCD version 1.1 special mode */ +#define DP_ENHANCED_FRAMING (1 << 18) + +/* eDP */ +#define DP_PLL_FREQ_270MHZ (0 << 16) +#define DP_PLL_FREQ_160MHZ (1 << 16) +#define DP_PLL_FREQ_MASK (3 << 16) + +/** locked once port is enabled */ +#define DP_PORT_REVERSAL (1 << 15) + +/* eDP */ +#define DP_PLL_ENABLE (1 << 14) + +/** sends the clock on lane 15 of the PEG for debug */ +#define DP_CLOCK_OUTPUT_ENABLE (1 << 13) + +#define DP_SCRAMBLING_DISABLE (1 << 12) +#define DP_SCRAMBLING_DISABLE_IRONLAKE (1 << 7) + +/** limit RGB values to avoid confusing TVs */ +#define DP_COLOR_RANGE_16_235 (1 << 8) + +/** Turn on the audio link */ +#define DP_AUDIO_OUTPUT_ENABLE (1 << 6) + +/** vs and hs sync polarity */ +#define DP_SYNC_VS_HIGH (1 << 4) +#define DP_SYNC_HS_HIGH (1 << 3) + +/** A fantasy */ +#define DP_DETECTED (1 << 2) + +/** The aux channel provides a way to talk to the + * signal sink for DDC etc. Max packet size supported + * is 20 bytes in each direction, hence the 5 fixed + * data registers + */ +#define DPA_AUX_CH_CTL 0x64010 +#define DPA_AUX_CH_DATA1 0x64014 +#define DPA_AUX_CH_DATA2 0x64018 +#define DPA_AUX_CH_DATA3 0x6401c +#define DPA_AUX_CH_DATA4 0x64020 +#define DPA_AUX_CH_DATA5 0x64024 + +#define DPB_AUX_CH_CTL 0x64110 +#define DPB_AUX_CH_DATA1 0x64114 +#define DPB_AUX_CH_DATA2 0x64118 +#define DPB_AUX_CH_DATA3 0x6411c +#define DPB_AUX_CH_DATA4 0x64120 +#define DPB_AUX_CH_DATA5 0x64124 + +#define DPC_AUX_CH_CTL 0x64210 +#define DPC_AUX_CH_DATA1 0x64214 +#define DPC_AUX_CH_DATA2 0x64218 +#define DPC_AUX_CH_DATA3 0x6421c +#define DPC_AUX_CH_DATA4 0x64220 +#define DPC_AUX_CH_DATA5 0x64224 + +#define DPD_AUX_CH_CTL 0x64310 +#define DPD_AUX_CH_DATA1 0x64314 +#define DPD_AUX_CH_DATA2 0x64318 +#define DPD_AUX_CH_DATA3 0x6431c +#define DPD_AUX_CH_DATA4 0x64320 +#define DPD_AUX_CH_DATA5 0x64324 + +#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) +#define DP_AUX_CH_CTL_DONE (1 << 30) +#define DP_AUX_CH_CTL_INTERRUPT (1 << 29) +#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28) +#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_1600us (3 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) +#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20 +#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16) +#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16 +#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15) +#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14) +#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13) +#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12) +#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0 + +/* + * Computing GMCH M and N values for the Display Port link + * + * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes + * + * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz) + * + * The GMCH value is used internally + * + * bytes_per_pixel is the number of bytes coming out of the plane, + * which is after the LUTs, so we want the bytes for our color format. + * For our current usage, this is always 3, one byte for R, G and B. + */ +#define _PIPEA_GMCH_DATA_M 0x70050 +#define _PIPEB_GMCH_DATA_M 0x71050 + +/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ +#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) +#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25 + +#define PIPE_GMCH_DATA_M_MASK (0xffffff) + +#define _PIPEA_GMCH_DATA_N 0x70054 +#define _PIPEB_GMCH_DATA_N 0x71054 +#define PIPE_GMCH_DATA_N_MASK (0xffffff) + +/* + * Computing Link M and N values for the Display Port link + * + * Link M / N = pixel_clock / ls_clk + * + * (the DP spec calls pixel_clock the 'strm_clk') + * + * The Link value is transmitted in the Main Stream + * Attributes and VB-ID. + */ + +#define _PIPEA_DP_LINK_M 0x70060 +#define _PIPEB_DP_LINK_M 0x71060 +#define PIPEA_DP_LINK_M_MASK (0xffffff) + +#define _PIPEA_DP_LINK_N 0x70064 +#define _PIPEB_DP_LINK_N 0x71064 +#define PIPEA_DP_LINK_N_MASK (0xffffff) + +#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M) +#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N) +#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) +#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) + +/* Display & cursor control */ + +/* Pipe A */ +#define _PIPEADSL 0x70000 +#define DSL_LINEMASK_GEN2 0x00000fff +#define DSL_LINEMASK_GEN3 0x00001fff +#define _PIPEACONF 0x70008 +#define PIPECONF_ENABLE (1<<31) +#define PIPECONF_DISABLE 0 +#define PIPECONF_DOUBLE_WIDE (1<<30) +#define I965_PIPECONF_ACTIVE (1<<30) +#define PIPECONF_FRAME_START_DELAY_MASK (3<<27) +#define PIPECONF_SINGLE_WIDE 0 +#define PIPECONF_PIPE_UNLOCKED 0 +#define PIPECONF_PIPE_LOCKED (1<<25) +#define PIPECONF_PALETTE 0 +#define PIPECONF_GAMMA (1<<24) +#define PIPECONF_FORCE_BORDER (1<<25) +#define PIPECONF_INTERLACE_MASK (7 << 21) +#define PIPECONF_INTERLACE_MASK_HSW (3 << 21) +/* Note that pre-gen3 does not support interlaced display directly. Panel + * fitting must be disabled on pre-ilk for interlaced. */ +#define PIPECONF_PROGRESSIVE (0 << 21) +#define PIPECONF_INTERLACE_W_SYNC_SHIFT_PANEL (4 << 21) /* gen4 only */ +#define PIPECONF_INTERLACE_W_SYNC_SHIFT (5 << 21) /* gen4 only */ +#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) /* gen3 only */ +/* Ironlake and later have a complete new set of values for interlaced. PFIT + * means panel fitter required, PF means progressive fetch, DBL means power + * saving pixel doubling. */ +#define PIPECONF_PFIT_PF_INTERLACED_ILK (1 << 21) +#define PIPECONF_INTERLACED_ILK (3 << 21) +#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ +#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ +#define PIPECONF_CXSR_DOWNCLOCK (1<<16) +#define PIPECONF_BPP_MASK (0x000000e0) +#define PIPECONF_BPP_8 (0<<5) +#define PIPECONF_BPP_10 (1<<5) +#define PIPECONF_BPP_6 (2<<5) +#define PIPECONF_BPP_12 (3<<5) +#define PIPECONF_DITHER_EN (1<<4) +#define PIPECONF_DITHER_TYPE_MASK (0x0000000c) +#define PIPECONF_DITHER_TYPE_SP (0<<2) +#define PIPECONF_DITHER_TYPE_ST1 (1<<2) +#define PIPECONF_DITHER_TYPE_ST2 (2<<2) +#define PIPECONF_DITHER_TYPE_TEMP (3<<2) +#define _PIPEASTAT 0x70024 +#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) +#define SPRITE1_FLIPDONE_INT_EN_VLV (1UL<<30) +#define PIPE_CRC_ERROR_ENABLE (1UL<<29) +#define PIPE_CRC_DONE_ENABLE (1UL<<28) +#define PIPE_GMBUS_EVENT_ENABLE (1UL<<27) +#define PLANE_FLIP_DONE_INT_EN_VLV (1UL<<26) +#define PIPE_HOTPLUG_INTERRUPT_ENABLE (1UL<<26) +#define PIPE_VSYNC_INTERRUPT_ENABLE (1UL<<25) +#define PIPE_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24) +#define PIPE_DPST_EVENT_ENABLE (1UL<<23) +#define SPRITE0_FLIP_DONE_INT_EN_VLV (1UL<<26) +#define PIPE_LEGACY_BLC_EVENT_ENABLE (1UL<<22) +#define PIPE_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21) +#define PIPE_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20) +#define PIPE_HOTPLUG_TV_INTERRUPT_ENABLE (1UL<<18) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */ +#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL<<17) +#define PIPEA_HBLANK_INT_EN_VLV (1UL<<16) +#define PIPE_OVERLAY_UPDATED_ENABLE (1UL<<16) +#define SPRITE1_FLIPDONE_INT_STATUS_VLV (1UL<<15) +#define SPRITE0_FLIPDONE_INT_STATUS_VLV (1UL<<15) +#define PIPE_CRC_ERROR_INTERRUPT_STATUS (1UL<<13) +#define PIPE_CRC_DONE_INTERRUPT_STATUS (1UL<<12) +#define PIPE_GMBUS_INTERRUPT_STATUS (1UL<<11) +#define PLANE_FLIPDONE_INT_STATUS_VLV (1UL<<10) +#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL<<10) +#define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9) +#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) +#define PIPE_DPST_EVENT_STATUS (1UL<<7) +#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6) +#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) +#define PIPE_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4) +#define PIPE_HOTPLUG_TV_INTERRUPT_STATUS (1UL<<2) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ +#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) +#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) +#define PIPE_BPC_MASK (7 << 5) /* Ironlake */ +#define PIPE_8BPC (0 << 5) +#define PIPE_10BPC (1 << 5) +#define PIPE_6BPC (2 << 5) +#define PIPE_12BPC (3 << 5) + +#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC) +#define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF) +#define PIPEDSL(pipe) _PIPE(pipe, _PIPEADSL, _PIPEBDSL) +#define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH) +#define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) +#define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) + +#define VLV_DPFLIPSTAT 0x70028 +#define PIPEB_LINE_COMPARE_INT_EN (1<<29) +#define PIPEB_HLINE_INT_EN (1<<28) +#define PIPEB_VBLANK_INT_EN (1<<27) +#define SPRITED_FLIPDONE_INT_EN (1<<26) +#define SPRITEC_FLIPDONE_INT_EN (1<<25) +#define PLANEB_FLIPDONE_INT_EN (1<<24) +#define PIPEA_LINE_COMPARE_INT_EN (1<<21) +#define PIPEA_HLINE_INT_EN (1<<20) +#define PIPEA_VBLANK_INT_EN (1<<19) +#define SPRITEB_FLIPDONE_INT_EN (1<<18) +#define SPRITEA_FLIPDONE_INT_EN (1<<17) +#define PLANEA_FLIPDONE_INT_EN (1<<16) + +#define DPINVGTT 0x7002c /* VLV only */ +#define CURSORB_INVALID_GTT_INT_EN (1<<23) +#define CURSORA_INVALID_GTT_INT_EN (1<<22) +#define SPRITED_INVALID_GTT_INT_EN (1<<21) +#define SPRITEC_INVALID_GTT_INT_EN (1<<20) +#define PLANEB_INVALID_GTT_INT_EN (1<<19) +#define SPRITEB_INVALID_GTT_INT_EN (1<<18) +#define SPRITEA_INVALID_GTT_INT_EN (1<<17) +#define PLANEA_INVALID_GTT_INT_EN (1<<16) +#define DPINVGTT_EN_MASK 0xff0000 +#define CURSORB_INVALID_GTT_STATUS (1<<7) +#define CURSORA_INVALID_GTT_STATUS (1<<6) +#define SPRITED_INVALID_GTT_STATUS (1<<5) +#define SPRITEC_INVALID_GTT_STATUS (1<<4) +#define PLANEB_INVALID_GTT_STATUS (1<<3) +#define SPRITEB_INVALID_GTT_STATUS (1<<2) +#define SPRITEA_INVALID_GTT_STATUS (1<<1) +#define PLANEA_INVALID_GTT_STATUS (1<<0) +#define DPINVGTT_STATUS_MASK 0xff + +#define DSPARB 0x70030 +#define DSPARB_CSTART_MASK (0x7f << 7) +#define DSPARB_CSTART_SHIFT 7 +#define DSPARB_BSTART_MASK (0x7f) +#define DSPARB_BSTART_SHIFT 0 +#define DSPARB_BEND_SHIFT 9 /* on 855 */ +#define DSPARB_AEND_SHIFT 0 + +#define DSPFW1 0x70034 +#define DSPFW_SR_SHIFT 23 +#define DSPFW_SR_MASK (0x1ff<<23) +#define DSPFW_CURSORB_SHIFT 16 +#define DSPFW_CURSORB_MASK (0x3f<<16) +#define DSPFW_PLANEB_SHIFT 8 +#define DSPFW_PLANEB_MASK (0x7f<<8) +#define DSPFW_PLANEA_MASK (0x7f) +#define DSPFW2 0x70038 +#define DSPFW_CURSORA_MASK 0x00003f00 +#define DSPFW_CURSORA_SHIFT 8 +#define DSPFW_PLANEC_MASK (0x7f) +#define DSPFW3 0x7003c +#define DSPFW_HPLL_SR_EN (1<<31) +#define DSPFW_CURSOR_SR_SHIFT 24 +#define PINEVIEW_SELF_REFRESH_EN (1<<30) +#define DSPFW_CURSOR_SR_MASK (0x3f<<24) +#define DSPFW_HPLL_CURSOR_SHIFT 16 +#define DSPFW_HPLL_CURSOR_MASK (0x3f<<16) +#define DSPFW_HPLL_SR_MASK (0x1ff) + +/* drain latency register values*/ +#define DRAIN_LATENCY_PRECISION_32 32 +#define DRAIN_LATENCY_PRECISION_16 16 +#define VLV_DDL1 0x70050 +#define DDL_CURSORA_PRECISION_32 (1<<31) +#define DDL_CURSORA_PRECISION_16 (0<<31) +#define DDL_CURSORA_SHIFT 24 +#define DDL_PLANEA_PRECISION_32 (1<<7) +#define DDL_PLANEA_PRECISION_16 (0<<7) +#define VLV_DDL2 0x70054 +#define DDL_CURSORB_PRECISION_32 (1<<31) +#define DDL_CURSORB_PRECISION_16 (0<<31) +#define DDL_CURSORB_SHIFT 24 +#define DDL_PLANEB_PRECISION_32 (1<<7) +#define DDL_PLANEB_PRECISION_16 (0<<7) + +/* FIFO watermark sizes etc */ +#define G4X_FIFO_LINE_SIZE 64 +#define I915_FIFO_LINE_SIZE 64 +#define I830_FIFO_LINE_SIZE 32 + +#define VALLEYVIEW_FIFO_SIZE 255 +#define G4X_FIFO_SIZE 127 +#define I965_FIFO_SIZE 512 +#define I945_FIFO_SIZE 127 +#define I915_FIFO_SIZE 95 +#define I855GM_FIFO_SIZE 127 /* In cachelines */ +#define I830_FIFO_SIZE 95 + +#define VALLEYVIEW_MAX_WM 0xff +#define G4X_MAX_WM 0x3f +#define I915_MAX_WM 0x3f + +#define PINEVIEW_DISPLAY_FIFO 512 /* in 64byte unit */ +#define PINEVIEW_FIFO_LINE_SIZE 64 +#define PINEVIEW_MAX_WM 0x1ff +#define PINEVIEW_DFT_WM 0x3f +#define PINEVIEW_DFT_HPLLOFF_WM 0 +#define PINEVIEW_GUARD_WM 10 +#define PINEVIEW_CURSOR_FIFO 64 +#define PINEVIEW_CURSOR_MAX_WM 0x3f +#define PINEVIEW_CURSOR_DFT_WM 0 +#define PINEVIEW_CURSOR_GUARD_WM 5 + +#define VALLEYVIEW_CURSOR_MAX_WM 64 +#define I965_CURSOR_FIFO 64 +#define I965_CURSOR_MAX_WM 32 +#define I965_CURSOR_DFT_WM 8 + +/* define the Watermark register on Ironlake */ +#define WM0_PIPEA_ILK 0x45100 +#define WM0_PIPE_PLANE_MASK (0x7f<<16) +#define WM0_PIPE_PLANE_SHIFT 16 +#define WM0_PIPE_SPRITE_MASK (0x3f<<8) +#define WM0_PIPE_SPRITE_SHIFT 8 +#define WM0_PIPE_CURSOR_MASK (0x1f) + +#define WM0_PIPEB_ILK 0x45104 +#define WM0_PIPEC_IVB 0x45200 +#define WM1_LP_ILK 0x45108 +#define WM1_LP_SR_EN (1<<31) +#define WM1_LP_LATENCY_SHIFT 24 +#define WM1_LP_LATENCY_MASK (0x7f<<24) +#define WM1_LP_FBC_MASK (0xf<<20) +#define WM1_LP_FBC_SHIFT 20 +#define WM1_LP_SR_MASK (0x1ff<<8) +#define WM1_LP_SR_SHIFT 8 +#define WM1_LP_CURSOR_MASK (0x3f) +#define WM2_LP_ILK 0x4510c +#define WM2_LP_EN (1<<31) +#define WM3_LP_ILK 0x45110 +#define WM3_LP_EN (1<<31) +#define WM1S_LP_ILK 0x45120 +#define WM2S_LP_IVB 0x45124 +#define WM3S_LP_IVB 0x45128 +#define WM1S_LP_EN (1<<31) + +/* Memory latency timer register */ +#define MLTR_ILK 0x11222 +#define MLTR_WM1_SHIFT 0 +#define MLTR_WM2_SHIFT 8 +/* the unit of memory self-refresh latency time is 0.5us */ +#define ILK_SRLT_MASK 0x3f +#define ILK_LATENCY(shift) (I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK) +#define ILK_READ_WM1_LATENCY() ILK_LATENCY(MLTR_WM1_SHIFT) +#define ILK_READ_WM2_LATENCY() ILK_LATENCY(MLTR_WM2_SHIFT) + +/* define the fifo size on Ironlake */ +#define ILK_DISPLAY_FIFO 128 +#define ILK_DISPLAY_MAXWM 64 +#define ILK_DISPLAY_DFTWM 8 +#define ILK_CURSOR_FIFO 32 +#define ILK_CURSOR_MAXWM 16 +#define ILK_CURSOR_DFTWM 8 + +#define ILK_DISPLAY_SR_FIFO 512 +#define ILK_DISPLAY_MAX_SRWM 0x1ff +#define ILK_DISPLAY_DFT_SRWM 0x3f +#define ILK_CURSOR_SR_FIFO 64 +#define ILK_CURSOR_MAX_SRWM 0x3f +#define ILK_CURSOR_DFT_SRWM 8 + +#define ILK_FIFO_LINE_SIZE 64 + +/* define the WM info on Sandybridge */ +#define SNB_DISPLAY_FIFO 128 +#define SNB_DISPLAY_MAXWM 0x7f /* bit 16:22 */ +#define SNB_DISPLAY_DFTWM 8 +#define SNB_CURSOR_FIFO 32 +#define SNB_CURSOR_MAXWM 0x1f /* bit 4:0 */ +#define SNB_CURSOR_DFTWM 8 + +#define SNB_DISPLAY_SR_FIFO 512 +#define SNB_DISPLAY_MAX_SRWM 0x1ff /* bit 16:8 */ +#define SNB_DISPLAY_DFT_SRWM 0x3f +#define SNB_CURSOR_SR_FIFO 64 +#define SNB_CURSOR_MAX_SRWM 0x3f /* bit 5:0 */ +#define SNB_CURSOR_DFT_SRWM 8 + +#define SNB_FBC_MAX_SRWM 0xf /* bit 23:20 */ + +#define SNB_FIFO_LINE_SIZE 64 + + +/* the address where we get all kinds of latency value */ +#define SSKPD 0x5d10 +#define SSKPD_WM_MASK 0x3f +#define SSKPD_WM0_SHIFT 0 +#define SSKPD_WM1_SHIFT 8 +#define SSKPD_WM2_SHIFT 16 +#define SSKPD_WM3_SHIFT 24 + +#define SNB_LATENCY(shift) (I915_READ(MCHBAR_MIRROR_BASE_SNB + SSKPD) >> (shift) & SSKPD_WM_MASK) +#define SNB_READ_WM0_LATENCY() SNB_LATENCY(SSKPD_WM0_SHIFT) +#define SNB_READ_WM1_LATENCY() SNB_LATENCY(SSKPD_WM1_SHIFT) +#define SNB_READ_WM2_LATENCY() SNB_LATENCY(SSKPD_WM2_SHIFT) +#define SNB_READ_WM3_LATENCY() SNB_LATENCY(SSKPD_WM3_SHIFT) + +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> + * PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define _PIPEAFRAMEHIGH 0x70040 +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 +#define _PIPEAFRAMEPIXEL 0x70044 +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 +/* GM45+ just has to be different */ +#define _PIPEA_FRMCOUNT_GM45 0x70040 +#define _PIPEA_FLIPCOUNT_GM45 0x70044 +#define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45) + +/* Cursor A & B regs */ +#define _CURACNTR 0x70080 +/* Old style CUR*CNTR flags (desktop 8xx) */ +#define CURSOR_ENABLE 0x80000000 +#define CURSOR_GAMMA_ENABLE 0x40000000 +#define CURSOR_STRIDE_MASK 0x30000000 +#define CURSOR_FORMAT_SHIFT 24 +#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT) +/* New style CUR*CNTR flags */ +#define CURSOR_MODE 0x27 +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_64_32B_AX 0x07 +#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) +#define MCURSOR_PIPE_SELECT (1 << 28) +#define MCURSOR_PIPE_A 0x00 +#define MCURSOR_PIPE_B (1 << 28) +#define MCURSOR_GAMMA_ENABLE (1 << 26) +#define _CURABASE 0x70084 +#define _CURAPOS 0x70088 +#define CURSOR_POS_MASK 0x007FF +#define CURSOR_POS_SIGN 0x8000 +#define CURSOR_X_SHIFT 0 +#define CURSOR_Y_SHIFT 16 +#define CURSIZE 0x700a0 +#define _CURBCNTR 0x700c0 +#define _CURBBASE 0x700c4 +#define _CURBPOS 0x700c8 + +#define _CURBCNTR_IVB 0x71080 +#define _CURBBASE_IVB 0x71084 +#define _CURBPOS_IVB 0x71088 + +#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) +#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) +#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) + +#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB) +#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB) +#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB) + +/* Display A control */ +#define _DSPACNTR 0x70180 +#define DISPLAY_PLANE_ENABLE (1<<31) +#define DISPLAY_PLANE_DISABLE 0 +#define DISPPLANE_GAMMA_ENABLE (1<<30) +#define DISPPLANE_GAMMA_DISABLE 0 +#define DISPPLANE_PIXFORMAT_MASK (0xf<<26) +#define DISPPLANE_YUV422 (0x0<<26) +#define DISPPLANE_8BPP (0x2<<26) +#define DISPPLANE_BGRA555 (0x3<<26) +#define DISPPLANE_BGRX555 (0x4<<26) +#define DISPPLANE_BGRX565 (0x5<<26) +#define DISPPLANE_BGRX888 (0x6<<26) +#define DISPPLANE_BGRA888 (0x7<<26) +#define DISPPLANE_RGBX101010 (0x8<<26) +#define DISPPLANE_RGBA101010 (0x9<<26) +#define DISPPLANE_BGRX101010 (0xa<<26) +#define DISPPLANE_RGBX161616 (0xc<<26) +#define DISPPLANE_RGBX888 (0xe<<26) +#define DISPPLANE_RGBA888 (0xf<<26) +#define DISPPLANE_STEREO_ENABLE (1<<25) +#define DISPPLANE_STEREO_DISABLE 0 +#define DISPPLANE_SEL_PIPE_SHIFT 24 +#define DISPPLANE_SEL_PIPE_MASK (3<> 30) +#define PORT_TO_PIPE_CPT(val) (((val) & PORT_TRANS_SEL_MASK) >> 29) + +#define TRANS_DP_CTL_A 0xe0300 +#define TRANS_DP_CTL_B 0xe1300 +#define TRANS_DP_CTL_C 0xe2300 +#define TRANS_DP_CTL(pipe) _PIPE(pipe, TRANS_DP_CTL_A, TRANS_DP_CTL_B) +#define TRANS_DP_OUTPUT_ENABLE (1<<31) +#define TRANS_DP_PORT_SEL_B (0<<29) +#define TRANS_DP_PORT_SEL_C (1<<29) +#define TRANS_DP_PORT_SEL_D (2<<29) +#define TRANS_DP_PORT_SEL_NONE (3<<29) +#define TRANS_DP_PORT_SEL_MASK (3<<29) +#define TRANS_DP_AUDIO_ONLY (1<<26) +#define TRANS_DP_ENH_FRAMING (1<<18) +#define TRANS_DP_8BPC (0<<9) +#define TRANS_DP_10BPC (1<<9) +#define TRANS_DP_6BPC (2<<9) +#define TRANS_DP_12BPC (3<<9) +#define TRANS_DP_BPC_MASK (3<<9) +#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4) +#define TRANS_DP_VSYNC_ACTIVE_LOW 0 +#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3) +#define TRANS_DP_HSYNC_ACTIVE_LOW 0 +#define TRANS_DP_SYNC_MASK (3<<3) + +/* SNB eDP training params */ +/* SNB A-stepping */ +#define EDP_LINK_TRAIN_400MV_0DB_SNB_A (0x38<<22) +#define EDP_LINK_TRAIN_400MV_6DB_SNB_A (0x02<<22) +#define EDP_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01<<22) +#define EDP_LINK_TRAIN_800MV_0DB_SNB_A (0x0<<22) +/* SNB B-stepping */ +#define EDP_LINK_TRAIN_400_600MV_0DB_SNB_B (0x0<<22) +#define EDP_LINK_TRAIN_400MV_3_5DB_SNB_B (0x1<<22) +#define EDP_LINK_TRAIN_400_600MV_6DB_SNB_B (0x3a<<22) +#define EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B (0x39<<22) +#define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22) +#define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) + +/* IVB */ +#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 <<22) +#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a <<22) +#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f <<22) +#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22) +#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22) +#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22) +#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22) + +/* legacy values */ +#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22) +#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 <<22) +#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 <<22) +#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 <<22) +#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 <<22) + +#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22) + +#define FORCEWAKE 0xA18C +#define FORCEWAKE_VLV 0x1300b0 +#define FORCEWAKE_ACK_VLV 0x1300b4 +#define FORCEWAKE_ACK_HSW 0x130044 +#define FORCEWAKE_ACK 0x130090 +#define FORCEWAKE_MT 0xa188 /* multi-threaded */ +#define FORCEWAKE_KERNEL 0x1 +#define FORCEWAKE_USER 0x2 +#define FORCEWAKE_MT_ACK 0x130040 +#define ECOBUS 0xa180 +#define FORCEWAKE_MT_ENABLE (1<<5) + +#define GTFIFODBG 0x120000 +#define GT_FIFO_CPU_ERROR_MASK 7 +#define GT_FIFO_OVFERR (1<<2) +#define GT_FIFO_IAWRERR (1<<1) +#define GT_FIFO_IARDERR (1<<0) + +#define GT_FIFO_FREE_ENTRIES 0x120008 +#define GT_FIFO_NUM_RESERVED_ENTRIES 20 + +#define GEN6_UCGCTL1 0x9400 +# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5) +# define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) + +#define GEN6_UCGCTL2 0x9404 +# define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) +# define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) +# define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) +# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) +# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) + +#define GEN7_UCGCTL4 0x940c +#define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) + +#define GEN6_RPNSWREQ 0xA008 +#define GEN6_TURBO_DISABLE (1<<31) +#define GEN6_FREQUENCY(x) ((x)<<25) +#define GEN6_OFFSET(x) ((x)<<19) +#define GEN6_AGGRESSIVE_TURBO (0<<15) +#define GEN6_RC_VIDEO_FREQ 0xA00C +#define GEN6_RC_CONTROL 0xA090 +#define GEN6_RC_CTL_RC6pp_ENABLE (1<<16) +#define GEN6_RC_CTL_RC6p_ENABLE (1<<17) +#define GEN6_RC_CTL_RC6_ENABLE (1<<18) +#define GEN6_RC_CTL_RC1e_ENABLE (1<<20) +#define GEN6_RC_CTL_RC7_ENABLE (1<<22) +#define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) +#define GEN6_RC_CTL_HW_ENABLE (1<<31) +#define GEN6_RP_DOWN_TIMEOUT 0xA010 +#define GEN6_RP_INTERRUPT_LIMITS 0xA014 +#define GEN6_RPSTAT1 0xA01C +#define GEN6_CAGF_SHIFT 8 +#define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT) +#define GEN6_RP_CONTROL 0xA024 +#define GEN6_RP_MEDIA_TURBO (1<<11) +#define GEN6_RP_MEDIA_MODE_MASK (3<<9) +#define GEN6_RP_MEDIA_HW_TURBO_MODE (3<<9) +#define GEN6_RP_MEDIA_HW_NORMAL_MODE (2<<9) +#define GEN6_RP_MEDIA_HW_MODE (1<<9) +#define GEN6_RP_MEDIA_SW_MODE (0<<9) +#define GEN6_RP_MEDIA_IS_GFX (1<<8) +#define GEN6_RP_ENABLE (1<<7) +#define GEN6_RP_UP_IDLE_MIN (0x1<<3) +#define GEN6_RP_UP_BUSY_AVG (0x2<<3) +#define GEN6_RP_UP_BUSY_CONT (0x4<<3) +#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) +#define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) +#define GEN6_RP_UP_THRESHOLD 0xA02C +#define GEN6_RP_DOWN_THRESHOLD 0xA030 +#define GEN6_RP_CUR_UP_EI 0xA050 +#define GEN6_CURICONT_MASK 0xffffff +#define GEN6_RP_CUR_UP 0xA054 +#define GEN6_CURBSYTAVG_MASK 0xffffff +#define GEN6_RP_PREV_UP 0xA058 +#define GEN6_RP_CUR_DOWN_EI 0xA05C +#define GEN6_CURIAVG_MASK 0xffffff +#define GEN6_RP_CUR_DOWN 0xA060 +#define GEN6_RP_PREV_DOWN 0xA064 +#define GEN6_RP_UP_EI 0xA068 +#define GEN6_RP_DOWN_EI 0xA06C +#define GEN6_RP_IDLE_HYSTERSIS 0xA070 +#define GEN6_RC_STATE 0xA094 +#define GEN6_RC1_WAKE_RATE_LIMIT 0xA098 +#define GEN6_RC6_WAKE_RATE_LIMIT 0xA09C +#define GEN6_RC6pp_WAKE_RATE_LIMIT 0xA0A0 +#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8 +#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC +#define GEN6_RC_SLEEP 0xA0B0 +#define GEN6_RC1e_THRESHOLD 0xA0B4 +#define GEN6_RC6_THRESHOLD 0xA0B8 +#define GEN6_RC6p_THRESHOLD 0xA0BC +#define GEN6_RC6pp_THRESHOLD 0xA0C0 +#define GEN6_PMINTRMSK 0xA168 + +#define GEN6_PMISR 0x44020 +#define GEN6_PMIMR 0x44024 /* rps_lock */ +#define GEN6_PMIIR 0x44028 +#define GEN6_PMIER 0x4402C +#define GEN6_PM_MBOX_EVENT (1<<25) +#define GEN6_PM_THERMAL_EVENT (1<<24) +#define GEN6_PM_RP_DOWN_TIMEOUT (1<<6) +#define GEN6_PM_RP_UP_THRESHOLD (1<<5) +#define GEN6_PM_RP_DOWN_THRESHOLD (1<<4) +#define GEN6_PM_RP_UP_EI_EXPIRED (1<<2) +#define GEN6_PM_RP_DOWN_EI_EXPIRED (1<<1) +#define GEN6_PM_DEFERRED_EVENTS (GEN6_PM_RP_UP_THRESHOLD | \ + GEN6_PM_RP_DOWN_THRESHOLD | \ + GEN6_PM_RP_DOWN_TIMEOUT) + +#define GEN6_GT_GFX_RC6_LOCKED 0x138104 +#define GEN6_GT_GFX_RC6 0x138108 +#define GEN6_GT_GFX_RC6p 0x13810C +#define GEN6_GT_GFX_RC6pp 0x138110 + +#define GEN6_PCODE_MAILBOX 0x138124 +#define GEN6_PCODE_READY (1<<31) +#define GEN6_READ_OC_PARAMS 0xc +#define GEN6_PCODE_WRITE_MIN_FREQ_TABLE 0x8 +#define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9 +#define GEN6_PCODE_WRITE_RC6VIDS 0x4 +#define GEN6_PCODE_READ_RC6VIDS 0x5 +#define GEN6_ENCODE_RC6_VID(mv) (((mv) / 5) - 245) < 0 ?: 0 +#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) > 0 ? ((vids) * 5) + 245 : 0) +#define GEN6_PCODE_DATA 0x138128 +#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 + +#define GEN6_GT_CORE_STATUS 0x138060 +#define GEN6_CORE_CPD_STATE_MASK (7<<4) +#define GEN6_RCn_MASK 7 +#define GEN6_RC0 0 +#define GEN6_RC3 2 +#define GEN6_RC6 3 +#define GEN6_RC7 4 + +#define GEN7_MISCCPCTL (0x9424) +#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) + +/* IVYBRIDGE DPF */ +#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ +#define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) +#define GEN7_PARITY_ERROR_VALID (1<<13) +#define GEN7_L3CDERRST1_BANK_MASK (3<<11) +#define GEN7_L3CDERRST1_SUBBANK_MASK (7<<8) +#define GEN7_PARITY_ERROR_ROW(reg) \ + ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14) +#define GEN7_PARITY_ERROR_BANK(reg) \ + ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11) +#define GEN7_PARITY_ERROR_SUBBANK(reg) \ + ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) +#define GEN7_L3CDERRST1_ENABLE (1<<7) + +#define GEN7_L3LOG_BASE 0xB070 +#define GEN7_L3LOG_SIZE 0x80 + +#define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ +#define GEN7_HALF_SLICE_CHICKEN1_GT2 0xf100 +#define GEN7_MAX_PS_THREAD_DEP (8<<12) +#define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1<<3) + +#define GEN7_ROW_CHICKEN2 0xe4f4 +#define GEN7_ROW_CHICKEN2_GT2 0xf4f4 +#define DOP_CLOCK_GATING_DISABLE (1<<0) + +#define G4X_AUD_VID_DID 0x62020 +#define INTEL_AUDIO_DEVCL 0x808629FB +#define INTEL_AUDIO_DEVBLC 0x80862801 +#define INTEL_AUDIO_DEVCTG 0x80862802 + +#define G4X_AUD_CNTL_ST 0x620B4 +#define G4X_ELDV_DEVCL_DEVBLC (1 << 13) +#define G4X_ELDV_DEVCTG (1 << 14) +#define G4X_ELD_ADDR (0xf << 5) +#define G4X_ELD_ACK (1 << 4) +#define G4X_HDMIW_HDMIEDID 0x6210C + +#define IBX_HDMIW_HDMIEDID_A 0xE2050 +#define IBX_HDMIW_HDMIEDID_B 0xE2150 +#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ + IBX_HDMIW_HDMIEDID_A, \ + IBX_HDMIW_HDMIEDID_B) +#define IBX_AUD_CNTL_ST_A 0xE20B4 +#define IBX_AUD_CNTL_ST_B 0xE21B4 +#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \ + IBX_AUD_CNTL_ST_A, \ + IBX_AUD_CNTL_ST_B) +#define IBX_ELD_BUFFER_SIZE (0x1f << 10) +#define IBX_ELD_ADDRESS (0x1f << 5) +#define IBX_ELD_ACK (1 << 4) +#define IBX_AUD_CNTL_ST2 0xE20C0 +#define IBX_ELD_VALIDB (1 << 0) +#define IBX_CP_READYB (1 << 1) + +#define CPT_HDMIW_HDMIEDID_A 0xE5050 +#define CPT_HDMIW_HDMIEDID_B 0xE5150 +#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ + CPT_HDMIW_HDMIEDID_A, \ + CPT_HDMIW_HDMIEDID_B) +#define CPT_AUD_CNTL_ST_A 0xE50B4 +#define CPT_AUD_CNTL_ST_B 0xE51B4 +#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \ + CPT_AUD_CNTL_ST_A, \ + CPT_AUD_CNTL_ST_B) +#define CPT_AUD_CNTRL_ST2 0xE50C0 + +/* These are the 4 32-bit write offset registers for each stream + * output buffer. It determines the offset from the + * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. + */ +#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4) + +#define IBX_AUD_CONFIG_A 0xe2000 +#define IBX_AUD_CONFIG_B 0xe2100 +#define IBX_AUD_CFG(pipe) _PIPE(pipe, \ + IBX_AUD_CONFIG_A, \ + IBX_AUD_CONFIG_B) +#define CPT_AUD_CONFIG_A 0xe5000 +#define CPT_AUD_CONFIG_B 0xe5100 +#define CPT_AUD_CFG(pipe) _PIPE(pipe, \ + CPT_AUD_CONFIG_A, \ + CPT_AUD_CONFIG_B) +#define AUD_CONFIG_N_VALUE_INDEX (1 << 29) +#define AUD_CONFIG_N_PROG_ENABLE (1 << 28) +#define AUD_CONFIG_UPPER_N_SHIFT 20 +#define AUD_CONFIG_UPPER_N_VALUE (0xff << 20) +#define AUD_CONFIG_LOWER_N_SHIFT 4 +#define AUD_CONFIG_LOWER_N_VALUE (0xfff << 4) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 +#define AUD_CONFIG_PIXEL_CLOCK_HDMI (0xf << 16) +#define AUD_CONFIG_DISABLE_NCTS (1 << 3) + +/* HSW Audio */ +#define HSW_AUD_CONFIG_A 0x65000 /* Audio Configuration Transcoder A */ +#define HSW_AUD_CONFIG_B 0x65100 /* Audio Configuration Transcoder B */ +#define HSW_AUD_CFG(pipe) _PIPE(pipe, \ + HSW_AUD_CONFIG_A, \ + HSW_AUD_CONFIG_B) + +#define HSW_AUD_MISC_CTRL_A 0x65010 /* Audio Misc Control Convert 1 */ +#define HSW_AUD_MISC_CTRL_B 0x65110 /* Audio Misc Control Convert 2 */ +#define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \ + HSW_AUD_MISC_CTRL_A, \ + HSW_AUD_MISC_CTRL_B) + +#define HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4 /* Audio DIP and ELD Control State Transcoder A */ +#define HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4 /* Audio DIP and ELD Control State Transcoder B */ +#define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \ + HSW_AUD_DIP_ELD_CTRL_ST_A, \ + HSW_AUD_DIP_ELD_CTRL_ST_B) + +/* Audio Digital Converter */ +#define HSW_AUD_DIG_CNVT_1 0x65080 /* Audio Converter 1 */ +#define HSW_AUD_DIG_CNVT_2 0x65180 /* Audio Converter 1 */ +#define AUD_DIG_CNVT(pipe) _PIPE(pipe, \ + HSW_AUD_DIG_CNVT_1, \ + HSW_AUD_DIG_CNVT_2) +#define DIP_PORT_SEL_MASK 0x3 + +#define HSW_AUD_EDID_DATA_A 0x65050 +#define HSW_AUD_EDID_DATA_B 0x65150 +#define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \ + HSW_AUD_EDID_DATA_A, \ + HSW_AUD_EDID_DATA_B) + +#define HSW_AUD_PIPE_CONV_CFG 0x6507c /* Audio pipe and converter configs */ +#define HSW_AUD_PIN_ELD_CP_VLD 0x650c0 /* Audio ELD and CP Ready Status */ +#define AUDIO_INACTIVE_C (1<<11) +#define AUDIO_INACTIVE_B (1<<7) +#define AUDIO_INACTIVE_A (1<<3) +#define AUDIO_OUTPUT_ENABLE_A (1<<2) +#define AUDIO_OUTPUT_ENABLE_B (1<<6) +#define AUDIO_OUTPUT_ENABLE_C (1<<10) +#define AUDIO_ELD_VALID_A (1<<0) +#define AUDIO_ELD_VALID_B (1<<4) +#define AUDIO_ELD_VALID_C (1<<8) +#define AUDIO_CP_READY_A (1<<1) +#define AUDIO_CP_READY_B (1<<5) +#define AUDIO_CP_READY_C (1<<9) + +/* HSW Power Wells */ +#define HSW_PWR_WELL_CTL1 0x45400 /* BIOS */ +#define HSW_PWR_WELL_CTL2 0x45404 /* Driver */ +#define HSW_PWR_WELL_CTL3 0x45408 /* KVMR */ +#define HSW_PWR_WELL_CTL4 0x4540C /* Debug */ +#define HSW_PWR_WELL_ENABLE (1<<31) +#define HSW_PWR_WELL_STATE (1<<30) +#define HSW_PWR_WELL_CTL5 0x45410 +#define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1<<31) +#define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1<<20) +#define HSW_PWR_WELL_FORCE_ON (1<<19) +#define HSW_PWR_WELL_CTL6 0x45414 + +/* Per-pipe DDI Function Control */ +#define TRANS_DDI_FUNC_CTL_A 0x60400 +#define TRANS_DDI_FUNC_CTL_B 0x61400 +#define TRANS_DDI_FUNC_CTL_C 0x62400 +#define TRANS_DDI_FUNC_CTL_EDP 0x6F400 +#define TRANS_DDI_FUNC_CTL(tran) _TRANSCODER(tran, TRANS_DDI_FUNC_CTL_A, \ + TRANS_DDI_FUNC_CTL_B) +#define TRANS_DDI_FUNC_ENABLE (1<<31) +/* Those bits are ignored by pipe EDP since it can only connect to DDI A */ +#define TRANS_DDI_PORT_MASK (7<<28) +#define TRANS_DDI_SELECT_PORT(x) ((x)<<28) +#define TRANS_DDI_PORT_NONE (0<<28) +#define TRANS_DDI_MODE_SELECT_MASK (7<<24) +#define TRANS_DDI_MODE_SELECT_HDMI (0<<24) +#define TRANS_DDI_MODE_SELECT_DVI (1<<24) +#define TRANS_DDI_MODE_SELECT_DP_SST (2<<24) +#define TRANS_DDI_MODE_SELECT_DP_MST (3<<24) +#define TRANS_DDI_MODE_SELECT_FDI (4<<24) +#define TRANS_DDI_BPC_MASK (7<<20) +#define TRANS_DDI_BPC_8 (0<<20) +#define TRANS_DDI_BPC_10 (1<<20) +#define TRANS_DDI_BPC_6 (2<<20) +#define TRANS_DDI_BPC_12 (3<<20) +#define TRANS_DDI_PVSYNC (1<<17) +#define TRANS_DDI_PHSYNC (1<<16) +#define TRANS_DDI_EDP_INPUT_MASK (7<<12) +#define TRANS_DDI_EDP_INPUT_A_ON (0<<12) +#define TRANS_DDI_EDP_INPUT_A_ONOFF (4<<12) +#define TRANS_DDI_EDP_INPUT_B_ONOFF (5<<12) +#define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12) +#define TRANS_DDI_BFI_ENABLE (1<<4) +#define TRANS_DDI_PORT_WIDTH_X1 (0<<1) +#define TRANS_DDI_PORT_WIDTH_X2 (1<<1) +#define TRANS_DDI_PORT_WIDTH_X4 (3<<1) + +/* DisplayPort Transport Control */ +#define DP_TP_CTL_A 0x64040 +#define DP_TP_CTL_B 0x64140 +#define DP_TP_CTL(port) _PORT(port, DP_TP_CTL_A, DP_TP_CTL_B) +#define DP_TP_CTL_ENABLE (1<<31) +#define DP_TP_CTL_MODE_SST (0<<27) +#define DP_TP_CTL_MODE_MST (1<<27) +#define DP_TP_CTL_ENHANCED_FRAME_ENABLE (1<<18) +#define DP_TP_CTL_FDI_AUTOTRAIN (1<<15) +#define DP_TP_CTL_LINK_TRAIN_MASK (7<<8) +#define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8) +#define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8) +#define DP_TP_CTL_LINK_TRAIN_PAT3 (4<<8) +#define DP_TP_CTL_LINK_TRAIN_IDLE (2<<8) +#define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8) +#define DP_TP_CTL_SCRAMBLE_DISABLE (1<<7) + +/* DisplayPort Transport Status */ +#define DP_TP_STATUS_A 0x64044 +#define DP_TP_STATUS_B 0x64144 +#define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B) +#define DP_TP_STATUS_IDLE_DONE (1<<25) +#define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12) + +/* DDI Buffer Control */ +#define DDI_BUF_CTL_A 0x64000 +#define DDI_BUF_CTL_B 0x64100 +#define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B) +#define DDI_BUF_CTL_ENABLE (1<<31) +#define DDI_BUF_EMP_400MV_0DB_HSW (0<<24) /* Sel0 */ +#define DDI_BUF_EMP_400MV_3_5DB_HSW (1<<24) /* Sel1 */ +#define DDI_BUF_EMP_400MV_6DB_HSW (2<<24) /* Sel2 */ +#define DDI_BUF_EMP_400MV_9_5DB_HSW (3<<24) /* Sel3 */ +#define DDI_BUF_EMP_600MV_0DB_HSW (4<<24) /* Sel4 */ +#define DDI_BUF_EMP_600MV_3_5DB_HSW (5<<24) /* Sel5 */ +#define DDI_BUF_EMP_600MV_6DB_HSW (6<<24) /* Sel6 */ +#define DDI_BUF_EMP_800MV_0DB_HSW (7<<24) /* Sel7 */ +#define DDI_BUF_EMP_800MV_3_5DB_HSW (8<<24) /* Sel8 */ +#define DDI_BUF_EMP_MASK (0xf<<24) +#define DDI_BUF_IS_IDLE (1<<7) +#define DDI_A_4_LANES (1<<4) +#define DDI_PORT_WIDTH(width) (((width) - 1) << 1) +#define DDI_PORT_WIDTH_X1 (0<<1) +#define DDI_PORT_WIDTH_X2 (1<<1) +#define DDI_PORT_WIDTH_X4 (3<<1) +#define DDI_INIT_DISPLAY_DETECTED (1<<0) + +/* DDI Buffer Translations */ +#define DDI_BUF_TRANS_A 0x64E00 +#define DDI_BUF_TRANS_B 0x64E60 +#define DDI_BUF_TRANS(port) _PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + +/* Sideband Interface (SBI) is programmed indirectly, via + * SBI_ADDR, which contains the register offset; and SBI_DATA, + * which contains the payload */ +#define SBI_ADDR 0xC6000 +#define SBI_DATA 0xC6004 +#define SBI_CTL_STAT 0xC6008 +#define SBI_CTL_DEST_ICLK (0x0<<16) +#define SBI_CTL_DEST_MPHY (0x1<<16) +#define SBI_CTL_OP_IORD (0x2<<8) +#define SBI_CTL_OP_IOWR (0x3<<8) +#define SBI_CTL_OP_CRRD (0x6<<8) +#define SBI_CTL_OP_CRWR (0x7<<8) +#define SBI_RESPONSE_FAIL (0x1<<1) +#define SBI_RESPONSE_SUCCESS (0x0<<1) +#define SBI_BUSY (0x1<<0) +#define SBI_READY (0x0<<0) + +/* SBI offsets */ +#define SBI_SSCDIVINTPHASE6 0x0600 +#define SBI_SSCDIVINTPHASE_DIVSEL_MASK ((0x7f)<<1) +#define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x)<<1) +#define SBI_SSCDIVINTPHASE_INCVAL_MASK ((0x7f)<<8) +#define SBI_SSCDIVINTPHASE_INCVAL(x) ((x)<<8) +#define SBI_SSCDIVINTPHASE_DIR(x) ((x)<<15) +#define SBI_SSCDIVINTPHASE_PROPAGATE (1<<0) +#define SBI_SSCCTL 0x020c +#define SBI_SSCCTL6 0x060C +#define SBI_SSCCTL_PATHALT (1<<3) +#define SBI_SSCCTL_DISABLE (1<<0) +#define SBI_SSCAUXDIV6 0x0610 +#define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x)<<4) +#define SBI_DBUFF0 0x2a00 +#define SBI_DBUFF0_ENABLE (1<<0) + +/* LPT PIXCLK_GATE */ +#define PIXCLK_GATE 0xC6020 +#define PIXCLK_GATE_UNGATE (1<<0) +#define PIXCLK_GATE_GATE (0<<0) + +/* SPLL */ +#define SPLL_CTL 0x46020 +#define SPLL_PLL_ENABLE (1<<31) +#define SPLL_PLL_SSC (1<<28) +#define SPLL_PLL_NON_SSC (2<<28) +#define SPLL_PLL_FREQ_810MHz (0<<26) +#define SPLL_PLL_FREQ_1350MHz (1<<26) + +/* WRPLL */ +#define WRPLL_CTL1 0x46040 +#define WRPLL_CTL2 0x46060 +#define WRPLL_PLL_ENABLE (1<<31) +#define WRPLL_PLL_SELECT_SSC (0x01<<28) +#define WRPLL_PLL_SELECT_NON_SSC (0x02<<28) +#define WRPLL_PLL_SELECT_LCPLL_2700 (0x03<<28) +/* WRPLL divider programming */ +#define WRPLL_DIVIDER_REFERENCE(x) ((x)<<0) +#define WRPLL_DIVIDER_POST(x) ((x)<<8) +#define WRPLL_DIVIDER_FEEDBACK(x) ((x)<<16) + +/* Port clock selection */ +#define PORT_CLK_SEL_A 0x46100 +#define PORT_CLK_SEL_B 0x46104 +#define PORT_CLK_SEL(port) _PORT(port, PORT_CLK_SEL_A, PORT_CLK_SEL_B) +#define PORT_CLK_SEL_LCPLL_2700 (0<<29) +#define PORT_CLK_SEL_LCPLL_1350 (1<<29) +#define PORT_CLK_SEL_LCPLL_810 (2<<29) +#define PORT_CLK_SEL_SPLL (3<<29) +#define PORT_CLK_SEL_WRPLL1 (4<<29) +#define PORT_CLK_SEL_WRPLL2 (5<<29) +#define PORT_CLK_SEL_NONE (7<<29) + +/* Transcoder clock selection */ +#define TRANS_CLK_SEL_A 0x46140 +#define TRANS_CLK_SEL_B 0x46144 +#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B) +/* For each transcoder, we need to select the corresponding port clock */ +#define TRANS_CLK_SEL_DISABLED (0x0<<29) +#define TRANS_CLK_SEL_PORT(x) ((x+1)<<29) + +#define _TRANSA_MSA_MISC 0x60410 +#define _TRANSB_MSA_MISC 0x61410 +#define TRANS_MSA_MISC(tran) _TRANSCODER(tran, _TRANSA_MSA_MISC, \ + _TRANSB_MSA_MISC) +#define TRANS_MSA_SYNC_CLK (1<<0) +#define TRANS_MSA_6_BPC (0<<5) +#define TRANS_MSA_8_BPC (1<<5) +#define TRANS_MSA_10_BPC (2<<5) +#define TRANS_MSA_12_BPC (3<<5) +#define TRANS_MSA_16_BPC (4<<5) + +/* LCPLL Control */ +#define LCPLL_CTL 0x130040 +#define LCPLL_PLL_DISABLE (1<<31) +#define LCPLL_PLL_LOCK (1<<30) +#define LCPLL_CLK_FREQ_MASK (3<<26) +#define LCPLL_CLK_FREQ_450 (0<<26) +#define LCPLL_CD_CLOCK_DISABLE (1<<25) +#define LCPLL_CD2X_CLOCK_DISABLE (1<<23) +#define LCPLL_CD_SOURCE_FCLK (1<<21) + +/* Pipe WM_LINETIME - watermark line time */ +#define PIPE_WM_LINETIME_A 0x45270 +#define PIPE_WM_LINETIME_B 0x45274 +#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, PIPE_WM_LINETIME_A, \ + PIPE_WM_LINETIME_B) +#define PIPE_WM_LINETIME_MASK (0x1ff) +#define PIPE_WM_LINETIME_TIME(x) ((x)) +#define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) +#define PIPE_WM_LINETIME_IPS_LINETIME(x) ((x)<<16) + +/* SFUSE_STRAP */ +#define SFUSE_STRAP 0xc2014 +#define SFUSE_STRAP_DDIB_DETECTED (1<<2) +#define SFUSE_STRAP_DDIC_DETECTED (1<<1) +#define SFUSE_STRAP_DDID_DETECTED (1<<0) + +#define WM_DBG 0x45280 +#define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0) +#define WM_DBG_DISALLOW_MAXFIFO (1<<1) +#define WM_DBG_DISALLOW_SPRITE (1<<2) + +/* North Display Engine Reset Warn Options */ +#define NDE_RSTWRN_OPT 0x46408 +#define RST_PCH_HNDSHK_EN (1<<4) + +#endif /* _I915_REG_H_ */ diff --git a/src/drivers/intel/gma/intel_ddi.c b/src/drivers/intel/gma/intel_ddi.c new file mode 100644 index 0000000000..50f5ca2d31 --- /dev/null +++ b/src/drivers/intel/gma/intel_ddi.c @@ -0,0 +1,273 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eugeni Dodonov + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* HDMI/DVI modes ignore everything but the last 2 items. So we share + * them for both DP and FDI transports, allowing those ports to + * automatically adapt to HDMI connections as well. + */ +static u32 hsw_ddi_translations_dp[] = { + 0x00FFFFFF, 0x0006000E, /* DP parameters */ + 0x00D75FFF, 0x0005000A, + 0x00C30FFF, 0x00040006, + 0x80AAAFFF, 0x000B0000, + 0x00FFFFFF, 0x0005000A, + 0x00D75FFF, 0x000C0004, + 0x80C30FFF, 0x000B0000, + 0x00FFFFFF, 0x00040006, + 0x80D75FFF, 0x000B0000, + 0x00FFFFFF, 0x00040006 /* HDMI parameters */ +}; + +static u32 hsw_ddi_translations_fdi[] = { + 0x00FFFFFF, 0x0007000E, /* FDI parameters */ + 0x00D75FFF, 0x000F000A, + 0x00C30FFF, 0x00060006, + 0x00AAAFFF, 0x001E0000, + 0x00FFFFFF, 0x000F000A, + 0x00D75FFF, 0x00160004, + 0x00C30FFF, 0x001E0000, + 0x00FFFFFF, 0x00060006, + 0x00D75FFF, 0x001E0000, + 0x00FFFFFF, 0x00040006 /* HDMI parameters */ +}; + +/* On Haswell, DDI port buffers must be programmed with correct values + * in advance. The buffer values are different for FDI and DP modes, + * but the HDMI/DVI fields are shared among those. So we program the DDI + * in either FDI or DP modes only, as HDMI connections will work with both + * of those. + */ +static void intel_prepare_ddi_buffers(int port, int use_fdi_mode) +{ + u32 reg; + int i; + u32 *ddi_translations = ((use_fdi_mode) ? + hsw_ddi_translations_fdi : + hsw_ddi_translations_dp); + + printk(BIOS_SPEW, "Initializing DDI buffers for port %d in %s mode\n", + port, + use_fdi_mode ? "FDI" : "DP"); + + for (i=0,reg=DDI_BUF_TRANS(port);i < ARRAY_SIZE(hsw_ddi_translations_fdi);i++) { + gtt_write(reg,ddi_translations[i]); + reg += 4; + } +} + +void intel_prepare_ddi(void) +{ + int port; + u32 use_fdi = 1; + + for (port = PORT_A; port < PORT_E; port++) + intel_prepare_ddi_buffers(port, !use_fdi); + + intel_prepare_ddi_buffers(PORT_E, use_fdi); +} + +static void intel_wait_ddi_buf_idle(int port) +{ + uint32_t reg = DDI_BUF_CTL(port); + int i; + + for (i = 0; i < 8; i++) { + udelay(1); + if (gtt_read(reg) & DDI_BUF_IS_IDLE){ + printk(BIOS_SPEW, "%s: buf is idle (success)\n", __func__); + return; + } + } + printk(BIOS_ERR, "Timeout waiting for DDI BUF %d idle bit\n", port); +} + + +void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, int port) +{ + int wait; + uint32_t val; + + if (gtt_read(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { + val = gtt_read(DDI_BUF_CTL(port)); + if (val & DDI_BUF_CTL_ENABLE) { + val &= ~DDI_BUF_CTL_ENABLE; + gtt_write(val,DDI_BUF_CTL(port)); + wait = 1; + } + + val = gtt_read(DP_TP_CTL(port)); + val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); + val |= DP_TP_CTL_LINK_TRAIN_PAT1; + gtt_write(val,DP_TP_CTL(port)); + //POSTING_READ(DP_TP_CTL(port)); + + if (wait) + intel_wait_ddi_buf_idle(port); + } + + val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | + DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; + gtt_write(val,DP_TP_CTL(port)); + //POSTING_READ(DP_TP_CTL(port)); + + intel_dp->DP |= DDI_BUF_CTL_ENABLE; + gtt_write(intel_dp->DP,DDI_BUF_CTL(port)); + //POSTING_READ(DDI_BUF_CTL(port)); + + udelay(600); +} + +u32 intel_ddi_calc_transcoder_flags(u32 pipe_bpp, + enum port port, + enum pipe pipe, + int type, + int lane_count, + int pf_sz, + u8 phsync, + u8 pvsync) +{ + u32 temp; + + temp = TRANS_DDI_FUNC_ENABLE; + temp |= TRANS_DDI_SELECT_PORT(port); + + switch (pipe_bpp) { + case 18: + temp |= TRANS_DDI_BPC_6; + break; + case 24: + temp |= TRANS_DDI_BPC_8; + break; + case 30: + temp |= TRANS_DDI_BPC_10; + break; + case 36: + temp |= TRANS_DDI_BPC_12; + break; + default: + printk(BIOS_ERR, "Invalid pipe_bpp: %d, *** Initialization will not succeed *** \n", pipe_bpp); + } + + if (port == PORT_A) { + switch (pipe) { + case PIPE_A: + if (pf_sz) + temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; + else + temp |= TRANS_DDI_EDP_INPUT_A_ON; + break; + case PIPE_B: + temp |= TRANS_DDI_EDP_INPUT_B_ONOFF; + break; + case PIPE_C: + temp |= TRANS_DDI_EDP_INPUT_C_ONOFF; + break; + default: + printk(BIOS_ERR, "Invalid pipe %d\n", pipe); + } + } + + if (phsync) + temp |= TRANS_DDI_PHSYNC; + + if (pvsync) + temp |= TRANS_DDI_PVSYNC; + + if (type == INTEL_OUTPUT_HDMI) { + /* Need to understand when to set TRANS_DDI_MODE_SELECT_HDMI / TRANS_DDI_MODE_SELECT_DVI */ + } else if (type == INTEL_OUTPUT_ANALOG) { + /* Set TRANS_DDI_MODE_SELECT_FDI with lane_count */ + } else if (type == INTEL_OUTPUT_DISPLAYPORT || + type == INTEL_OUTPUT_EDP) { + temp |= TRANS_DDI_MODE_SELECT_DP_SST; + + temp |= DDI_PORT_WIDTH(lane_count); + } else { + printk(BIOS_ERR, "Invalid type %d for pipe\n", type); + } + + return temp; +} + +enum transcoder intel_ddi_get_transcoder(enum port port, + enum pipe pipe) +{ + if (port == PORT_A) + return TRANSCODER_EDP; + return (enum transcoder)pipe; +} + +void intel_ddi_set_pipe_settings(struct intel_dp *intel_dp) +{ + u32 val = TRANS_MSA_SYNC_CLK; + + switch (intel_dp->pipe_bits_per_pixel) { + case 18: + val |= TRANS_MSA_6_BPC; + break; + case 24: + val |= TRANS_MSA_8_BPC; + break; + case 30: + val |= TRANS_MSA_10_BPC; + break; + case 36: + val |= TRANS_MSA_12_BPC; + break; + default: + printk(BIOS_ERR, "Invalid bpp settings %d\n", intel_dp->pipe_bits_per_pixel); + } + gtt_write(TRANS_MSA_MISC(intel_dp->transcoder),val); +} diff --git a/src/drivers/intel/gma/intel_dp.c b/src/drivers/intel/gma/intel_dp.c new file mode 100644 index 0000000000..7c43bbf24a --- /dev/null +++ b/src/drivers/intel/gma/intel_dp.c @@ -0,0 +1,1616 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Keith Packard + * + */ + +/* This code was created by the coccinnelle filters in the i915tool, + * with some final hand filtering. + */ + +#include +#include +#include +#include +#include + +/** + * is_edp - is the given port attached to an eDP panel (either CPU or PCH) + * @intel_dp: DP struct + * + * If a CPU or PCH DP output is attached to an eDP panel, this function + * will return 1, and 0 otherwise. + */ +static int is_edp(struct intel_dp *intel_dp) +{ + return intel_dp->type == INTEL_OUTPUT_EDP; +} + +/** + * is_pch_edp - is the port on the PCH and attached to an eDP panel? + * @intel_dp: DP struct + * + * Returns 1 if the given DP struct corresponds to a PCH DP port attached + * to an eDP panel, 0 otherwise. Helpful for determining whether we + * may need FDI resources for a given DP output or not. + */ +static int is_pch_edp(struct intel_dp *intel_dp) +{ + return intel_dp->is_pch_edp; +} + +/** + * is_cpu_edp - is the port on the CPU and attached to an eDP panel? + * @intel_dp: DP struct + * + * Returns 1 if the given DP struct corresponds to a CPU eDP port. + */ +static int is_cpu_edp(struct intel_dp *intel_dp) +{ + return is_edp(intel_dp) && !is_pch_edp(intel_dp); +} + +static uint32_t +pack_aux(uint8_t *src, int src_bytes) +{ + int i; + uint32_t v = 0; + + if (src_bytes > 4) + src_bytes = 4; + for (i = 0; i < src_bytes; i++) + v |= ((uint32_t) src[i]) << ((3-i) * 8); + return v; +} + +void +unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) +{ + int i; + if (dst_bytes > 4) + dst_bytes = 4; + for (i = 0; i < dst_bytes; i++) + dst[i] = src >> ((3-i) * 8); +} + +static int ironlake_edp_have_panel_power(struct intel_dp *intel_dp) +{ + + return (gtt_read(PCH_PP_STATUS) & PP_ON) != 0; +} + +static int ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp) +{ + return (gtt_read(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0; +} + +int +intel_dp_aux_ch(struct intel_dp *intel_dp, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_size) +{ + uint32_t output_reg = intel_dp->output_reg; + uint32_t ch_ctl = output_reg + 0x10; + uint32_t ch_data = ch_ctl + 4; + int i; + int recv_bytes; + uint32_t status; + int try; + + /* Try to wait for any previous AUX channel activity */ + for (try = 0; try < 3; try++) { + status = gtt_read(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + mdelay(1); + } + + if (try == 3) { + if (1) { + status = gtt_read(ch_ctl); + printk(BIOS_ERR, + "dp_aux_ch not started status 0x%08x\n", + status); + } + return -1; + } + + /* Must try at least 3 times according to DP spec */ + for (try = 0; try < 5; try++) { + /* Load the send data into the aux channel data registers */ + for (i = 0; i < send_bytes; i += 4){ + u32 val, addr; + val = pack_aux(send + i, send_bytes - i); + addr = ch_data + i; + gtt_write(addr,val); + } + + /* Send the command and wait for it to complete */ + gtt_write(ch_ctl, DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (intel_dp->precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (intel_dp->aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + for (;;) { + status = gtt_read(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + udelay(100); + } + + /* Clear done status and any errors */ + gtt_write(ch_ctl, status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR)) + continue; + if (status & DP_AUX_CH_CTL_DONE) + break; + } + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { + printk(BIOS_ERR, "dp_aux_ch not done status 0x%08x\n", status); + return -1; + } + + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ + if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { + printk(BIOS_ERR, + "dp_aux_ch receive error status 0x%08x\n", status); + return -1; + } + + /* Timeouts occur when the device isn't connected, so they're + * "normal" -- don't fill the kernel log with these */ + if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { + printk(BIOS_ERR, "dp_aux_ch timeout status 0x%08x\n", status); + return -1; + } + + /* Unload any bytes sent back from the other side */ + recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> + DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(gtt_read(ch_data + i), + recv + i, recv_bytes - i); + + return recv_bytes; +} + +/* Write data to the aux channel in native mode */ +static int +intel_dp_aux_native_write(struct intel_dp *intel_dp, + uint16_t address, uint8_t *send, int send_bytes) +{ + int ret; + uint8_t msg[20]; + int msg_bytes; + uint8_t ack; + + if (send_bytes > 16) + return -1; + msg[0] = AUX_NATIVE_WRITE << 4; + msg[1] = address >> 8; + msg[2] = address & 0xff; + msg[3] = send_bytes - 1; + memcpy(&msg[4], send, send_bytes); + msg_bytes = send_bytes + 4; + for (;;) { + ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1); + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + break; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -1; + } + return send_bytes; +} + +/* Write a single byte to the aux channel in native mode */ +static int +intel_dp_aux_native_write_1(struct intel_dp *intel_dp, + uint16_t address, uint8_t byte) +{ + return intel_dp_aux_native_write(intel_dp, address, &byte, 1); +} + +int intel_dp_set_bw(struct intel_dp *intel_dp) +{ + printk(BIOS_SPEW, "DP_LINK_BW_SET"); + return intel_dp_aux_native_write_1(intel_dp, + DP_LINK_BW_SET, + intel_dp->link_bw); +} + +int intel_dp_set_lane_count(struct intel_dp *intel_dp) +{ + printk(BIOS_SPEW, "DP_LANE_COUNT_SET %d ", intel_dp->lane_count); + return intel_dp_aux_native_write_1(intel_dp, + DP_LANE_COUNT_SET, + intel_dp->lane_count); +} + +int intel_dp_set_training_pattern(struct intel_dp *intel_dp, + u8 pat) +{ + printk(BIOS_SPEW, "DP_TRAINING_PATTERN_SET"); + return intel_dp_aux_native_write_1(intel_dp, + DP_TRAINING_PATTERN_SET, + pat); +} + +int intel_dp_set_training_lane0(struct intel_dp *intel_dp, + u8 val) +{ + printk(BIOS_SPEW, "DP_TRAINING_LANE0_SET"); + return intel_dp_aux_native_write_1(intel_dp, + DP_TRAINING_LANE0_SET, + val); +} + +/* read bytes from a native aux channel */ +static int +intel_dp_aux_native_read(struct intel_dp *intel_dp, + uint16_t address, uint8_t *recv, int recv_bytes) +{ + uint8_t msg[4]; + int msg_bytes; + uint8_t reply[20]; + int reply_bytes; + uint8_t ack; + int ret; + + msg[0] = AUX_NATIVE_READ << 4; + msg[1] = address >> 8; + msg[2] = address & 0xff; + msg[3] = recv_bytes - 1; + + msg_bytes = 4; + reply_bytes = recv_bytes + 1; + + for (;;) { + ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, + reply, reply_bytes); + if (ret == 0) + return -1; + if (ret < 0) + return ret; + ack = reply[0]; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { + memcpy(recv, reply + 1, ret - 1); + return ret - 1; + } + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -1; + } +} + +int +intel_dp_i2c_aux_ch(struct intel_dp *intel_dp, + int mode, uint8_t write_byte, uint8_t *read_byte) +{ + uint8_t msg[5]; + uint8_t reply[2]; + unsigned retry; + int msg_bytes; + int reply_bytes; + int ret; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[0] = AUX_I2C_READ << 4; + else + msg[0] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[0] |= AUX_I2C_MOT << 4; + + msg[1] = intel_dp->address >> 8; + msg[2] = intel_dp->address; + + switch (mode) { + case MODE_I2C_WRITE: + msg[3] = 0; + msg[4] = write_byte; + msg_bytes = 5; + reply_bytes = 1; + break; + case MODE_I2C_READ: + msg[3] = 0; + msg_bytes = 4; + reply_bytes = 2; + break; + default: + msg_bytes = 3; + reply_bytes = 1; + break; + } + + for (retry = 0; retry < 5; retry++) { + ret = intel_dp_aux_ch(intel_dp, + msg, msg_bytes, + reply, reply_bytes); + if (ret < 0) { + printk(BIOS_ERR, "aux_ch failed %d\n", ret); + return ret; + } + + switch (reply[0] & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + /* I2C-over-AUX Reply field is only valid + * when paired with AUX ACK. + */ + break; + case AUX_NATIVE_REPLY_NACK: + printk(BIOS_ERR, "aux_ch native nack\n"); + return -1; + case AUX_NATIVE_REPLY_DEFER: + udelay(100); + continue; + default: + printk(BIOS_ERR, "aux_ch invalid native reply 0x%02x\n", + reply[0]); + return -1; + } + + switch (reply[0] & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) { + *read_byte = reply[1]; + } + return reply_bytes - 1; + case AUX_I2C_REPLY_NACK: + printk(BIOS_ERR, "aux_i2c nack\n"); + return -1; + case AUX_I2C_REPLY_DEFER: + printk(BIOS_ERR, "aux_i2c defer\n"); + udelay(100); + break; + default: + printk(BIOS_ERR, + "aux_i2c invalid reply 0x%02x\n", reply[0]); + return -1; + } + } + + printk(BIOS_ERR, "too many retries, giving up\n"); + return -1; +} + +int intel_dp_i2c_write(struct intel_dp *intel_dp, + u8 val) +{ + return intel_dp_i2c_aux_ch(intel_dp, + MODE_I2C_WRITE, + val, + NULL); +} + +int intel_dp_i2c_read(struct intel_dp *intel_dp, + u8 *val) +{ + return intel_dp_i2c_aux_ch(intel_dp, + MODE_I2C_READ, + 0, + val); +} + +int +intel_dp_i2c_init(struct intel_dp *intel_dp) +{ + int ret = 0; + + /* not clear what we need to do here, if anything. + * this function was more about setting up the kernel. + * it's a handy placeholder, so we leave it in for now. + */ + return ret; +} + +static void +intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) +{ + while (*num > DATA_LINK_M_N_MASK || *den > DATA_LINK_M_N_MASK) { + *num >>= 1; + *den >>= 1; + } +} + +unsigned int roundup_power_of_two(unsigned int n); + +unsigned int roundup_power_of_two(unsigned int n) +{ + n--; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n++; + return n; +} + +static void compute_m_n(unsigned int m, unsigned int n, + unsigned int *ret_m, unsigned int *ret_n) +{ + /* We noticed in the IO operations that + * the VBIOS was setting N to DATA_LINK_N_MAX. + * This makes sense, actually: the bigger N is, i.e. + * the bigger the denominator is, the bigger + * the numerator can be, and the more + * bits of numerator you get, the better the result. + * So, first pick the max of the two powers of two. + * And, in the (unlikely) event that you end up with + * something bigger than DATA_LINK_N_MAX, catch that + * case with a MIN. Note the second case is unlikely, + * but we are best off being careful. + */ + *ret_n = MAX(roundup_power_of_two(n), DATA_LINK_N_MAX); + *ret_n = MIN(*ret_n, DATA_LINK_N_MAX); + *ret_m = ( (unsigned long long)m * *ret_n) / n; + intel_reduce_m_n_ratio(ret_m, ret_n); +} + +void intel_dp_compute_m_n(unsigned int bits_per_pixel, + unsigned int nlanes, + unsigned int pixel_clock, + unsigned int link_clock, + struct intel_dp_m_n *m_n) +{ + m_n->tu = 64; + compute_m_n(bits_per_pixel * pixel_clock, + link_clock * nlanes * 8, + &m_n->gmch_m, &m_n->gmch_n); + + compute_m_n(pixel_clock, link_clock, + &m_n->link_m, &m_n->link_n); +} + +static void ironlake_edp_pll_off(void); + +void +intel_dp_mode_set(struct intel_dp *intel_dp) +{ + /* Turn on the eDP PLL if needed */ + if (is_edp(intel_dp)) { + if (!is_pch_edp(intel_dp)) + ironlake_edp_pll_on(); + else + ironlake_edp_pll_off(); + } + + /* + * There are four kinds of DP registers: + * + * IBX PCH + * SNB CPU + * IVB CPU + * CPT PCH + * + * IBX PCH and CPU are the same for almost everything, + * except that the CPU DP PLL is configured in this + * register + * + * CPT PCH is quite different, having many bits moved + * to the TRANS_DP_CTL register instead. That + * configuration happens (oddly) in ironlake_pch_enable + */ + + /* Preserve the BIOS-computed detected bit. This is + * supposed to be read-only. + */ + intel_dp->DP = gtt_read(intel_dp->output_reg) & DP_DETECTED; + printk(BIOS_SPEW, "%s: initial value is %08lx\n", __func__, + (unsigned long)intel_dp->DP); + /* | 0 essentially */ + intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; + + /* Handle DP bits in common between all three register formats */ + + switch (intel_dp->lane_count) { + case 1: + intel_dp->DP |= DP_PORT_WIDTH_1; + break; + case 2: + intel_dp->DP |= DP_PORT_WIDTH_2; + break; + case 4: + intel_dp->DP |= DP_PORT_WIDTH_4; + break; + } + memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); + intel_dp->link_configuration[0] = intel_dp->link_bw; + intel_dp->link_configuration[1] = intel_dp->lane_count; + intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B; + /* + * Check for DPCD version > 1.1 and enhanced framing support + */ + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { + intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + } + + /* Split out the IBX/CPU vs CPT settings */ + + if (is_cpu_edp(intel_dp) && (intel_dp->gen == 7)) { + /* what are these? We're not sure. + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + intel_dp->DP |= DP_SYNC_HS_HIGH; + + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + */ + intel_dp->DP |= DP_SYNC_VS_HIGH; + /* */ + intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; + + if (intel_dp->link_configuration[1] & + DP_LANE_COUNT_ENHANCED_FRAME_EN) + intel_dp->DP |= DP_ENHANCED_FRAMING; + + intel_dp->DP |= intel_dp->pipe << 29; + + /* don't miss out required setting for eDP */ + intel_dp->DP |= DP_PLL_ENABLE; + if (intel_dp->clock < 200000) + intel_dp->DP |= DP_PLL_FREQ_160MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + } else if (!intel_dp->has_pch_cpt || is_cpu_edp(intel_dp)) { + intel_dp->DP |= intel_dp->color_range; + intel_dp->DP |= DP_LINK_TRAIN_OFF; + + if (intel_dp->link_configuration[1] & + DP_LANE_COUNT_ENHANCED_FRAME_EN) + intel_dp->DP |= DP_ENHANCED_FRAMING; + + if (intel_dp->pipe == 1) + intel_dp->DP |= DP_PIPEB_SELECT; + + if (is_cpu_edp(intel_dp)) { + /* don't miss out required setting for eDP */ + intel_dp->DP |= DP_PLL_ENABLE; + if (intel_dp->clock < 200000) + intel_dp->DP |= DP_PLL_FREQ_160MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + } + } else { + intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; + } +} + +#define IDLE_ON_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) +#define IDLE_ON_VALUE (PP_ON | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE) + +#define IDLE_OFF_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK) +#define IDLE_OFF_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE) + +#define IDLE_CYCLE_MASK (PP_ON | 0 | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK) +#define IDLE_CYCLE_VALUE (0 | 0 | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_OFF_IDLE) + +static void ironlake_wait_panel_status(struct intel_dp *intel_dp, + u32 mask, + u32 value) +{ + int i; + u32 status; + printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_ERR, "mask %08lx value %08lx status %08lx control %08lx\n", + (unsigned long) mask, (unsigned long) value, + (unsigned long)gtt_read(PCH_PP_STATUS), + (unsigned long)gtt_read(PCH_PP_CONTROL)); + + for(i = 0, status = gtt_read(PCH_PP_STATUS); ((status & mask) != value) && (i < 5000); + status = gtt_read(PCH_PP_STATUS)){ + udelay(10); + } + if (i > 5000){ + printk(BIOS_ERR, + "Panel status timeout: status %08lx control %08lx\n", + (unsigned long)gtt_read(PCH_PP_STATUS), + (unsigned long)gtt_read(PCH_PP_CONTROL)); + } +} + +static void ironlake_wait_panel_on(struct intel_dp *intel_dp) +{ + printk(BIOS_ERR, "Wait for panel power on\n"); + ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE); +} + +static void ironlake_wait_panel_off(struct intel_dp *intel_dp) +{ + printk(BIOS_ERR, "Wait for panel power off time\n"); + ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE); +} + +static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp) +{ + printk(BIOS_ERR, "Wait for panel power cycle\n"); + ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE); +} + +void intel_dp_wait_reg(unsigned long addr, + unsigned long val) +{ + unsigned long newval; + int tries = 0; + + while ((newval = gtt_read(addr)) != val) { + udelay(1); + if (tries++ > 1000) { + printk(BIOS_ERR, "%s: Waiting on %08lx to be %08lx, got %08lx\n", + __func__, addr, val, newval); + break; + } + } +} + +void intel_dp_wait_panel_power_control(unsigned long val) +{ + intel_dp_wait_reg(PCH_PP_CONTROL, val); +} + +/* Read the current pp_control value, unlocking the register if it + * is locked + */ + +static u32 ironlake_get_pp_control(void) +{ + u32 control = gtt_read(PCH_PP_CONTROL); + + control &= ~PANEL_UNLOCK_MASK; + control |= PANEL_UNLOCK_REGS; + return control; +} + +void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!is_edp(intel_dp)) + return; + printk(BIOS_ERR, "Turn eDP VDD on\n"); + + if (intel_dp->want_panel_vdd) { + printk(BIOS_ERR, "eDP VDD already requested on\n"); + } + + intel_dp->want_panel_vdd = 1; + + if (ironlake_edp_have_panel_vdd(intel_dp)) { + printk(BIOS_ERR, "eDP VDD already on\n"); + return; + } + + if (!ironlake_edp_have_panel_power(intel_dp)) + ironlake_wait_panel_power_cycle(intel_dp); + + pp = ironlake_get_pp_control(); + pp |= EDP_FORCE_VDD; + gtt_write(PCH_PP_CONTROL,pp); + // remember this if we need it later. Not sure yet. + ////POSTING_READ(PCH_PP_CONTROL); + printk(BIOS_ERR, "PCH_PP_STATUS: 0x%08lx PCH_PP_CONTROL: 0x%08lx\n", + gtt_read(PCH_PP_STATUS), gtt_read(PCH_PP_CONTROL)); + + /* + * If the panel wasn't on, delay before accessing aux channel + */ + if (!ironlake_edp_have_panel_power(intel_dp)) { + printk(BIOS_ERR, "eDP was not running\n"); + mdelay(intel_dp->panel_power_up_delay); + } +} + +static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { + pp = ironlake_get_pp_control(); + pp &= ~EDP_FORCE_VDD; + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + + /* Make sure sequencer is idle before allowing subsequent activity */ + printk(BIOS_ERR, "PCH_PP_STATUS: 0x%08lx PCH_PP_CONTROL: 0x%08lx\n", + gtt_read(PCH_PP_STATUS), gtt_read(PCH_PP_CONTROL)); + + mdelay(intel_dp->panel_power_down_delay); + } +} + +void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, int sync) +{ + if (!is_edp(intel_dp)) + return; + + printk(BIOS_ERR, "Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); + if (!intel_dp->want_panel_vdd) { + printk(BIOS_ERR, "eDP VDD not forced on"); + } + + intel_dp->want_panel_vdd = 0; + + if (sync) + ironlake_panel_vdd_off_sync(intel_dp); +} + +void ironlake_edp_panel_on(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!is_edp(intel_dp)) + return; + + printk(BIOS_ERR, "Turn eDP power on\n"); + + if (ironlake_edp_have_panel_power(intel_dp)) { + printk(BIOS_ERR, "eDP power already on\n"); + return; + } + + ironlake_wait_panel_power_cycle(intel_dp); + + pp = ironlake_get_pp_control(); + if ((intel_dp->gen == 5)) { + /* ILK workaround: disable reset around power sequence */ + pp &= ~PANEL_POWER_RESET; + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + } + + pp |= POWER_TARGET_ON; + if (!(intel_dp->gen == 5)) + pp |= PANEL_POWER_RESET; + + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + + ironlake_wait_panel_on(intel_dp); + + if ((intel_dp->gen == 5)) { + pp |= PANEL_POWER_RESET; /* restore panel reset bit */ + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + } +} + +void ironlake_edp_panel_off(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!is_edp(intel_dp)) + return; + + printk(BIOS_ERR, "Turn eDP power off\n"); + + if (intel_dp->want_panel_vdd) { + printk(BIOS_ERR, "Cannot turn power off while VDD is on\n"); + } + + pp = ironlake_get_pp_control(); + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | + PANEL_POWER_RESET | EDP_BLC_ENABLE); + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + + ironlake_wait_panel_off(intel_dp); +} + +void ironlake_edp_backlight_on(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!is_edp(intel_dp)) + return; + + /* + * If we enable the backlight right away following a panel power + * on, we may see slight flicker as the panel syncs with the eDP + * link. So delay a bit to make sure the image is solid before + * allowing it to appear. + */ + mdelay(intel_dp->backlight_on_delay); + pp = ironlake_get_pp_control(); + pp |= EDP_BLC_ENABLE; + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); +} + +void ironlake_edp_backlight_off(struct intel_dp *intel_dp) +{ + u32 pp; + + if (!is_edp(intel_dp)) + return; + + pp = ironlake_get_pp_control(); + pp &= ~EDP_BLC_ENABLE; + gtt_write(PCH_PP_CONTROL,pp); + ////POSTING_READ(PCH_PP_CONTROL); + mdelay(intel_dp->backlight_off_delay); +} + +void ironlake_edp_pll_on(void) +{ + u32 dpa_ctl; + + dpa_ctl = gtt_read(DP_A); + dpa_ctl |= DP_PLL_ENABLE; + gtt_write(DP_A,dpa_ctl); + ////POSTING_READ(DP_A); + udelay(200); +} + +static void ironlake_edp_pll_off(void) +{ + u32 dpa_ctl; + + dpa_ctl = gtt_read(DP_A); + dpa_ctl &= ~DP_PLL_ENABLE; + gtt_write(DP_A,dpa_ctl); + ////POSTING_READ(DP_A); + udelay(200); +} + +/* If the sink supports it, try to set the power state appropriately */ +void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) +{ + int ret, i; + + /* Should have a valid DPCD by this point */ + if (intel_dp->dpcd[DP_DPCD_REV] < 0x11) + return; + + /* the convention, for whatever reason, is that mode > 0 means 'off' */ + if (mode) { + ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER, + DP_SET_POWER_D3); + if (ret != 1) { + printk(BIOS_ERR, "failed to write sink power state\n"); + } + } else { + /* + * When turning on, we need to retry for 1ms to give the sink + * time to wake up. + */ + for (i = 0; i < 3; i++) { + ret = intel_dp_aux_native_write_1(intel_dp, + DP_SET_POWER, + DP_SET_POWER_D0); + if (ret == 1) + break; + mdelay(1); + } + } +} + +/* + * Native read with retry for link status and receiver capability reads for + * cases where the sink may still be asleep. + */ +static int +intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address, + uint8_t *recv, int recv_bytes) +{ + int ret, i; + + /* + * Sinks are *supposed* to come up within 1ms from an off state, + * but we're also supposed to retry 3 times per the spec. + */ + for (i = 0; i < 3; i++) { + ret = intel_dp_aux_native_read(intel_dp, address, recv, + recv_bytes); + if (ret == recv_bytes) + return ret; + mdelay(1); + } + + return ret; +} + +/* + * Fetch AUX CH registers 0x202 - 0x207 which contain + * link status information + */ +int +intel_dp_get_link_status(struct intel_dp *intel_dp, + uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + int ret, i; + + ret = intel_dp_aux_native_read_retry(intel_dp, + DP_LANE0_1_STATUS, + link_status, + DP_LINK_STATUS_SIZE); + + printk(BIOS_SPEW, "%s:", __func__); + for(i = 0; i < /* !!sizeof(link_status) == 4*/ + DP_LINK_STATUS_SIZE; i++) + printk(BIOS_SPEW, " %02x", link_status[i]); + printk(BIOS_SPEW, "\n"); + return ret; +} + +static uint8_t +intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int r) +{ + return link_status[r - DP_LANE0_1_STATUS]; +} + +const char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +const char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; +const char *link_train_names[] = { + "pattern 1", "pattern 2", "idle", "off" +}; + +/* + * These are source-specific values; current Intel hardware supports + * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB + */ + +static uint8_t +intel_dp_voltage_max(struct intel_dp *intel_dp) +{ + + if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_800; + else if (intel_dp->has_pch_cpt && !is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_1200; + else + return DP_TRAIN_VOLTAGE_SWING_800; +} + +static uint8_t +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) +{ + + if (intel_dp->is_haswell){ + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_9_5; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } else if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp)) { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } else { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } +} + +static void +intel_get_adjust_train(struct intel_dp *intel_dp, + uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + uint8_t v = 0; + uint8_t p = 0; + int lane; + uint8_t voltage_max; + uint8_t preemph_max; + + for (lane = 0; lane < intel_dp->lane_count; lane++) { + uint8_t this_v = drm_dp_get_adjust_request_voltage( + link_status, lane); + uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis( + link_status, lane); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + voltage_max = intel_dp_voltage_max(intel_dp); + if (v >= voltage_max) + v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; + + preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); + if (p >= preemph_max) + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + printk(BIOS_SPEW, "%s: set to %s %s%s %s\n", + __func__, + voltage_names[v&3], pre_emph_names[p&3], + v & DP_TRAIN_MAX_SWING_REACHED ? ",max volt swing reached":"", + p & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ? + ", max pre emph reached" : ""); + for (lane = 0; lane < 4; lane++) + intel_dp->train_set[lane] = v | p; +} + +static uint32_t +intel_dp_signal_levels(uint8_t train_set) +{ + uint32_t signal_levels = 0; + + switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + default: + signal_levels |= DP_VOLTAGE_0_4; + break; + case DP_TRAIN_VOLTAGE_SWING_600: + signal_levels |= DP_VOLTAGE_0_6; + break; + case DP_TRAIN_VOLTAGE_SWING_800: + signal_levels |= DP_VOLTAGE_0_8; + break; + case DP_TRAIN_VOLTAGE_SWING_1200: + signal_levels |= DP_VOLTAGE_1_2; + break; + } + switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { + case DP_TRAIN_PRE_EMPHASIS_0: + default: + signal_levels |= DP_PRE_EMPHASIS_0; + break; + case DP_TRAIN_PRE_EMPHASIS_3_5: + signal_levels |= DP_PRE_EMPHASIS_3_5; + break; + case DP_TRAIN_PRE_EMPHASIS_6: + signal_levels |= DP_PRE_EMPHASIS_6; + break; + case DP_TRAIN_PRE_EMPHASIS_9_5: + signal_levels |= DP_PRE_EMPHASIS_9_5; + break; + } + return signal_levels; +} + +/* Gen6's DP voltage swing and pre-emphasis control */ +static uint32_t +intel_gen6_edp_signal_levels(uint8_t train_set) +{ + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_400MV_3_5DB_SNB_B; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: + return EDP_LINK_TRAIN_400_600MV_6DB_SNB_B; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_600_800MV_3_5DB_SNB_B; + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: + case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B; + default: + printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_ERR, "Unsupported voltage swing/pre-emphasis level:" + "0x%x\n", signal_levels); + return EDP_LINK_TRAIN_400_600MV_0DB_SNB_B; + } +} + +/* Gen7's DP voltage swing and pre-emphasis control */ +static uint32_t +intel_gen7_edp_signal_levels(uint8_t train_set) +{ + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_400MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_400MV_3_5DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: + return EDP_LINK_TRAIN_400MV_6DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_600MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_600MV_3_5DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_800MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_800MV_3_5DB_IVB; + + default: + printk(BIOS_ERR, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_ERR, "Unsupported voltage swing/pre-emphasis level:" + "0x%x\n", signal_levels); + return EDP_LINK_TRAIN_500MV_0DB_IVB; + } +} + +/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ +static uint32_t +intel_dp_signal_levels_hsw(uint8_t train_set) +{ + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: + return DDI_BUF_EMP_400MV_0DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: + return DDI_BUF_EMP_400MV_3_5DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: + return DDI_BUF_EMP_400MV_6DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5: + return DDI_BUF_EMP_400MV_9_5DB_HSW; + + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: + return DDI_BUF_EMP_600MV_0DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: + return DDI_BUF_EMP_600MV_3_5DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6: + return DDI_BUF_EMP_600MV_6DB_HSW; + + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: + return DDI_BUF_EMP_800MV_0DB_HSW; + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: + return DDI_BUF_EMP_800MV_3_5DB_HSW; + default: + printk(BIOS_SPEW, + "Unsupported voltage swing/pre-emphasis level:" + "0x%x\n", signal_levels); + return DDI_BUF_EMP_400MV_0DB_HSW; + } +} + + +static uint8_t +intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int s = (lane & 1) * 4; + uint8_t l = link_status[lane>>1]; + + return (l >> s) & 0xf; +} + +/* Check for clock recovery is done on all channels */ +static int +intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane_count) +{ + int lane; + uint8_t lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = intel_get_lane_status(link_status, lane); + printk(BIOS_SPEW, + "%s: Lane %d, status %02x\n", __func__, + lane, lane_status); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return 0; + } + return 1; +} + +/* Check to see if channel eq is done on all channels */ +#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE| \ + DP_LANE_CHANNEL_EQ_DONE| \ + DP_LANE_SYMBOL_LOCKED) +int +intel_channel_eq_ok(struct intel_dp *intel_dp, + uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + uint8_t lane_align; + uint8_t lane_status; + int lane; + + lane_align = intel_dp_link_status(link_status, + DP_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return 0; + for (lane = 0; lane < intel_dp->lane_count; lane++) { + lane_status = intel_get_lane_status(link_status, lane); + if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) + return 0; + } + return 1; +} + +static int +intel_dp_set_link_train(struct intel_dp *intel_dp, + uint32_t dp_reg_value, + uint8_t dp_train_pat) +{ + int ret; + u32 temp; + int port = intel_dp->port; + int i; + + printk(BIOS_SPEW, "%s: dp_reg_value %08lx dp_train_pat %02x\n", + __func__, (unsigned long) dp_reg_value, dp_train_pat); + if (intel_dp->is_haswell){ + temp = gtt_read(DP_TP_CTL(port)); + + if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) + temp |= DP_TP_CTL_SCRAMBLE_DISABLE; + else + temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; + + temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; + switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { + case DP_TRAINING_PATTERN_DISABLE: + temp |= DP_TP_CTL_LINK_TRAIN_IDLE; + gtt_write(DP_TP_CTL(port), temp); + + for(i = 0; i < 10; i++){ + u32 status; + status = gtt_read(DP_TP_STATUS(port)); + if (status & DP_TP_STATUS_IDLE_DONE) + break; + } + + if (i == 10) + printk(BIOS_ERR, + "Timed out waiting for DP idle patterns\n"); + + temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; + temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; + + break; + case DP_TRAINING_PATTERN_1: + temp |= DP_TP_CTL_LINK_TRAIN_PAT1; + break; + case DP_TRAINING_PATTERN_2: + temp |= DP_TP_CTL_LINK_TRAIN_PAT2; + break; + case DP_TRAINING_PATTERN_3: + temp |= DP_TP_CTL_LINK_TRAIN_PAT3; + break; + } + gtt_write(DP_TP_CTL(port), temp); + + } else if (intel_dp->has_pch_cpt && + (intel_dp->gen != 7 || !is_cpu_edp(intel_dp))) { + dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT; + + switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { + case DP_TRAINING_PATTERN_DISABLE: + dp_reg_value |= DP_LINK_TRAIN_OFF_CPT; + break; + case DP_TRAINING_PATTERN_1: + dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT; + break; + case DP_TRAINING_PATTERN_2: + dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; + break; + case DP_TRAINING_PATTERN_3: + printk(BIOS_ERR, + "DP training pattern 3 not supported\n"); + dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT; + break; + } + + } else { + dp_reg_value &= ~DP_LINK_TRAIN_MASK; + + switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { + case DP_TRAINING_PATTERN_DISABLE: + dp_reg_value |= DP_LINK_TRAIN_OFF; + break; + case DP_TRAINING_PATTERN_1: + dp_reg_value |= DP_LINK_TRAIN_PAT_1; + break; + case DP_TRAINING_PATTERN_2: + dp_reg_value |= DP_LINK_TRAIN_PAT_2; + break; + case DP_TRAINING_PATTERN_3: + printk(BIOS_ERR,"DP training pattern 3 not supported\n"); + dp_reg_value |= DP_LINK_TRAIN_PAT_2; + break; + } + } + + gtt_write(intel_dp->output_reg, dp_reg_value); + //POSTING_READ(intel_dp->output_reg); + + intel_dp_aux_native_write_1(intel_dp, + DP_TRAINING_PATTERN_SET, + dp_train_pat); + + if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) != + DP_TRAINING_PATTERN_DISABLE) { + ret = intel_dp_aux_native_write(intel_dp, + DP_TRAINING_LANE0_SET, + intel_dp->train_set, + intel_dp->lane_count); + if (ret != intel_dp->lane_count){ + printk(BIOS_ERR, "%s: wanted %d, got %d\n", __func__, + intel_dp->lane_count, ret); + return 0; + } + } + + printk(BIOS_SPEW, "%s: success\n", __func__); + return 1; +} + +/* Enable corresponding port and start training pattern 1 */ +void +intel_dp_start_link_train(struct intel_dp *intel_dp) +{ + int i; + uint8_t voltage; + int clock_recovery = 0; + int voltage_tries, loop_tries; + u32 reg; + uint32_t DP = intel_dp->DP; + + if (intel_dp->is_haswell) + intel_ddi_prepare_link_retrain(intel_dp, intel_dp->port); + + /* Write the link configuration data */ + printk(BIOS_SPEW, "Write the link configuration data\n"); + intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, + intel_dp->link_configuration, + DP_LINK_CONFIGURATION_SIZE); + printk(BIOS_SPEW, "Written\n"); + + DP |= DP_PORT_EN; + + memset(intel_dp->train_set, 0, 4); + voltage = 0xff; + voltage_tries = 0; + loop_tries = 0; + clock_recovery = 0; + + for (;;) { + /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + uint8_t link_status[DP_LINK_STATUS_SIZE]; + uint32_t signal_levels; + + if (intel_dp->is_haswell){ + signal_levels = + intel_dp_signal_levels_hsw(intel_dp->train_set[0]); + DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; + printk(BIOS_SPEW, "Haswell: levels %08x DP %08x\n", signal_levels, DP); + } else if ((intel_dp->gen == 7) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; + } else if ((intel_dp->gen == 6) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; + } else { + signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; + } + printk(BIOS_ERR, "training pattern 1 signal levels %08x\n", signal_levels); + + if (intel_dp->has_pch_cpt && ((intel_dp->gen == 7) || !is_cpu_edp(intel_dp))) + reg = DP | DP_LINK_TRAIN_PAT_1_CPT; + else + reg = DP | DP_LINK_TRAIN_PAT_1; + + if (!intel_dp_set_link_train(intel_dp, reg, + DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE)) + break; + /* Set training pattern 1 */ + + udelay(100); + if (!intel_dp_get_link_status(intel_dp, link_status)) { + printk(BIOS_ERR, "failed to get link status\n"); + break; + } + + if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) { + printk(BIOS_ERR, "clock recovery OK\n"); + clock_recovery = 1; + break; + } + + /* Check to see if we've tried the max voltage */ + for (i = 0; i < intel_dp->lane_count; i++) + if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + if (i == intel_dp->lane_count) { + ++loop_tries; + if (loop_tries == 5) { + printk(BIOS_ERR, "too many full retries, give up\n"); + break; + } + printk(BIOS_SPEW, "%s: reset train set\n", __func__); + memset(intel_dp->train_set, 0, 4); + voltage_tries = 0; + continue; + } + + /* Check to see if we've tried the same voltage 5 times */ + if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++voltage_tries; + if (voltage_tries == 5) { + printk(BIOS_ERR, "too many voltage retries, give up\n"); + break; + } + } else + voltage_tries = 0; + voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + printk(BIOS_SPEW, "%s: voltage now %s\n", __func__, + voltage_names[voltage]); + + /* Compute new intel_dp->train_set as requested by target */ + intel_get_adjust_train(intel_dp, link_status); + printk(BIOS_SPEW, "%s: new intel train set is " + "%02x%02x%02x%02x", + __func__, + intel_dp->train_set[0], intel_dp->train_set[1], + intel_dp->train_set[2], intel_dp->train_set[3]); + } + + intel_dp->DP = DP; +} + +int +intel_dp_get_dpcd(struct intel_dp *intel_dp) +{ + int got = 0, want = sizeof(intel_dp->dpcd), rev; + got = intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, + want); + if (got < want) { + printk(BIOS_SPEW, "%s: got %d, wanted %d\n", __func__, got, want); + return 0; + } + + rev = intel_dp->dpcd[DP_DPCD_REV]; + if (!rev){ + printk(BIOS_SPEW, "%s: intel->dp[DP_DPCD_REV] is 0\n", + __func__); + return 0; + } + + printk(BIOS_SPEW, "DPCD: %02hx%02hx%02hx%02hx%02hx%02hx%02hx%02hx\n", + intel_dp->dpcd[0], intel_dp->dpcd[1], intel_dp->dpcd[2], + intel_dp->dpcd[3], intel_dp->dpcd[4], intel_dp->dpcd[5], + intel_dp->dpcd[6], intel_dp->dpcd[7]); + return 1; +} + +/* I have no idea how big max downspread is. 1 byte? Hard as hell to find. */ +int +intel_dp_get_max_downspread(struct intel_dp *intel_dp, u8 *max_downspread) +{ + int got, want = 1; + got = intel_dp_aux_native_read_retry(intel_dp, DP_MAX_DOWNSPREAD, max_downspread, + want); + if (got < want) { + printk(BIOS_SPEW, "%s: got %d, wanted %d\n", __func__, got, want); + return 0; + } + + printk(BIOS_SPEW, "%s: max_downspread is %02x\n", __func__, *max_downspread); + return 1; +} + +void intel_dp_set_m_n_regs(struct intel_dp *dp) +{ + gtt_write(PIPE_DATA_M1(dp->transcoder), + TU_SIZE(dp->m_n.tu) | dp->m_n.gmch_m); + gtt_write(PIPE_DATA_N1(dp->transcoder),dp->m_n.gmch_n); + gtt_write(PIPE_LINK_M1(dp->transcoder),dp->m_n.link_m); + gtt_write(PIPE_LINK_N1(dp->transcoder),dp->m_n.link_n); +} + +int intel_dp_bw_code_to_link_rate(u8 link_bw) +{ + switch (link_bw) { + default: + printk(BIOS_ERR, + "ERROR: link_bw(%d) is bogus; must be one of 6, 0xa, or 0x14\n", + link_bw); + case DP_LINK_BW_1_62: + return 162000; + case DP_LINK_BW_2_7: + return 270000; + case DP_LINK_BW_5_4: + return 540000; + } +} + +void intel_dp_set_resolution(struct intel_dp *intel_dp) +{ + gtt_write(HTOTAL(intel_dp->transcoder),intel_dp->htotal); + gtt_write(HBLANK(intel_dp->transcoder),intel_dp->hblank); + gtt_write(HSYNC(intel_dp->transcoder),intel_dp->hsync); + gtt_write(VTOTAL(intel_dp->transcoder),intel_dp->vtotal); + gtt_write(VBLANK(intel_dp->transcoder),intel_dp->vblank); + gtt_write(VSYNC(intel_dp->transcoder),intel_dp->vsync); +} + +int intel_dp_get_training_pattern(struct intel_dp *intel_dp, + u8 *recv) +{ + return intel_dp_aux_native_read_retry(intel_dp, + DP_TRAINING_PATTERN_SET, + recv, + 0); +} + +int intel_dp_get_lane_count(struct intel_dp *intel_dp, + u8 *recv) +{ + int val = intel_dp_aux_native_read_retry(intel_dp, + DP_LANE_COUNT_SET, + recv, + 0); + *recv &= DP_LANE_COUNT_MASK; + printk(BIOS_SPEW, "Lane count %s:%d\n", val < 0 ? "fail" : "ok", *recv); + return val; +} + +int intel_dp_get_lane_align_status(struct intel_dp *intel_dp, + u8 *recv) +{ + return intel_dp_aux_native_read_retry(intel_dp, + DP_LANE_ALIGN_STATUS_UPDATED, + recv, + 0); +} diff --git a/src/drivers/maxim/max77686/max77686.c b/src/drivers/maxim/max77686/max77686.c index 16fa7f50bb..e971dc504d 100644 --- a/src/drivers/maxim/max77686/max77686.c +++ b/src/drivers/maxim/max77686/max77686.c @@ -21,9 +21,8 @@ * MA 02111-1307 USA */ +#include #include -#include -//#include #include #include "max77686.h" @@ -91,10 +90,10 @@ struct max77686_para max77686_param[] = {/*{vol_addr, vol_bitpos, * @param val value to be written * */ -static inline int max77686_i2c_write(unsigned char chip_addr, +static inline int max77686_i2c_write(unsigned int bus, unsigned char chip_addr, unsigned int reg, unsigned char val) { - return i2c_write(chip_addr, reg, 1, &val, 1); + return i2c_writeb(bus, chip_addr, reg, val); } /* @@ -105,10 +104,10 @@ static inline int max77686_i2c_write(unsigned char chip_addr, * @param val value to be written * */ -static inline int max77686_i2c_read(unsigned char chip_addr, +static inline int max77686_i2c_read(unsigned int bus, unsigned char chip_addr, unsigned int reg, unsigned char *val) { - return i2c_read(chip_addr, reg, 1, val, 1); + return i2c_readb(bus, chip_addr, reg, (uint8_t *)val); } /* @@ -121,7 +120,7 @@ static inline int max77686_i2c_read(unsigned char chip_addr, needed to set the buck/ldo enable bit OFF * @return Return 0 if ok, else -1 */ -static int max77686_enablereg(enum max77686_regnum reg, int enable) +static int max77686_enablereg(unsigned int bus, enum max77686_regnum reg, int enable) { struct max77686_para *pmic; unsigned char read_data; @@ -129,10 +128,10 @@ static int max77686_enablereg(enum max77686_regnum reg, int enable) pmic = &max77686_param[reg]; - ret = max77686_i2c_read(MAX77686_I2C_ADDR, pmic->reg_enaddr, + ret = max77686_i2c_read(bus, MAX77686_I2C_ADDR, pmic->reg_enaddr, &read_data); if (ret != 0) { - debug("max77686 i2c read failed.\n"); + printk(BIOS_DEBUG, "max77686 i2c read failed.\n"); return -1; } @@ -145,18 +144,18 @@ static int max77686_enablereg(enum max77686_regnum reg, int enable) pmic->reg_enbiton << pmic->reg_enbitpos); } - ret = max77686_i2c_write(MAX77686_I2C_ADDR, + ret = max77686_i2c_write(bus, MAX77686_I2C_ADDR, pmic->reg_enaddr, read_data); if (ret != 0) { - debug("max77686 i2c write failed.\n"); + printk(BIOS_DEBUG, "max77686 i2c write failed.\n"); return -1; } return 0; } -static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, - int enable, int volt_units) +int max77686_volsetting(unsigned int bus, enum max77686_regnum reg, + unsigned int volt, int enable, int volt_units) { struct max77686_para *pmic; unsigned char read_data; @@ -166,13 +165,13 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, pmic = &max77686_param[reg]; if (pmic->vol_addr == 0) { - debug("not a voltage register.\n"); + printk(BIOS_DEBUG, "not a voltage register.\n"); return -1; } - ret = max77686_i2c_read(MAX77686_I2C_ADDR, pmic->vol_addr, &read_data); + ret = max77686_i2c_read(bus, MAX77686_I2C_ADDR, pmic->vol_addr, &read_data); if (ret != 0) { - debug("max77686 i2c read failed.\n"); + printk(BIOS_DEBUG, "max77686 i2c read failed.\n"); return -1; } @@ -182,7 +181,7 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, vol_level = (volt - (u32)pmic->vol_min) * 1000; if (vol_level < 0) { - debug("Not a valid voltage level to set\n"); + printk(BIOS_DEBUG, "Not a valid voltage level to set\n"); return -1; } vol_level /= (u32)pmic->vol_div; @@ -190,47 +189,33 @@ static int max77686_do_volsetting(enum max77686_regnum reg, unsigned int volt, clrsetbits_8(&read_data, pmic->vol_bitmask << pmic->vol_bitpos, vol_level << pmic->vol_bitpos); - ret = max77686_i2c_write(MAX77686_I2C_ADDR, pmic->vol_addr, read_data); + ret = max77686_i2c_write(bus, MAX77686_I2C_ADDR, pmic->vol_addr, read_data); if (ret != 0) { - debug("max77686 i2c write failed.\n"); + printk(BIOS_DEBUG, "max77686 i2c write failed.\n"); return -1; } - ret = max77686_enablereg(reg, enable); + ret = max77686_enablereg(bus, reg, enable); if (ret != 0) { - debug("Failed to enable buck/ldo.\n"); + printk(BIOS_DEBUG, "Failed to enable buck/ldo.\n"); return -1; } return 0; } -int max77686_volsetting(enum max77686_regnum reg, unsigned int volt, - int enable, int volt_units) +int max77686_enable_32khz_cp(unsigned int bus) { - int old_bus = i2c_get_bus_num(); - int ret; - - i2c_set_bus_num(0); - ret = max77686_do_volsetting(reg, volt, enable, volt_units); - i2c_set_bus_num(old_bus); - return ret; + return max77686_enablereg(bus, PMIC_EN32KHZ_CP, REG_ENABLE); } -int max77686_enable_32khz_cp(void) -{ - i2c_set_bus_num(0); - return max77686_enablereg(PMIC_EN32KHZ_CP, REG_ENABLE); -} - -int max77686_disable_backup_batt(void) +int max77686_disable_backup_batt(unsigned int bus) { unsigned char val; int ret; - i2c_set_bus_num(0); - ret = max77686_i2c_read(MAX77686_I2C_ADDR, REG_BBAT, &val); + ret = max77686_i2c_read(bus, MAX77686_I2C_ADDR, REG_BBAT, &val); if (ret) { - debug("max77686 i2c read failed\n"); + printk(BIOS_DEBUG, "max77686 i2c read failed\n"); return ret; } @@ -241,17 +226,17 @@ int max77686_disable_backup_batt(void) /* First disable charging */ val &= ~BBAT_BBCHOSTEN_MASK; - ret = max77686_i2c_write(MAX77686_I2C_ADDR, REG_BBAT, val); + ret = max77686_i2c_write(bus, MAX77686_I2C_ADDR, REG_BBAT, val); if (ret) { - debug("max77686 i2c write failed\n"); + printk(BIOS_DEBUG, "max77686 i2c write failed\n"); return -1; } /* Finally select 3.5V to minimize power consumption */ val |= BBAT_BBCVS_MASK; - ret = max77686_i2c_write(MAX77686_I2C_ADDR, REG_BBAT, val); + ret = max77686_i2c_write(bus, MAX77686_I2C_ADDR, REG_BBAT, val); if (ret) { - debug("max77686 i2c write failed\n"); + printk(BIOS_DEBUG, "max77686 i2c write failed\n"); return -1; } diff --git a/src/drivers/maxim/max77686/max77686.h b/src/drivers/maxim/max77686/max77686.h index ee53e27a81..cebd2d9a1c 100644 --- a/src/drivers/maxim/max77686/max77686.h +++ b/src/drivers/maxim/max77686/max77686.h @@ -105,13 +105,16 @@ enum { /** * This function enables the 32KHz coprocessor clock. * + * @param bus i2c bus + * * Return 0 if ok, else -1 */ -int max77686_enable_32khz_cp(void); +int max77686_enable_32khz_cp(unsigned int bus); /** * Set the required voltage level of pmic * + * @param bus i2c bus * @param reg register number of buck/ldo to be set * @param volt voltage level to be set * @param enable enable or disable bit @@ -120,14 +123,16 @@ int max77686_enable_32khz_cp(void); * * @return Return 0 if ok, else -1 */ -int max77686_volsetting(enum max77686_regnum reg, unsigned int volt, - int enable, int volt_units); +int max77686_volsetting(unsigned int bus, enum max77686_regnum reg, + unsigned int volt, int enable, int volt_units); /** * Disable charging of the RTC backup battery * + * @param bus i2c bus + * * @return Return 0 if ok, else -1 */ -int max77686_disable_backup_batt(void); +int max77686_disable_backup_batt(unsigned int bus); #endif /* __MAX77686_PMIC_H_ */ diff --git a/src/drivers/maxim/max77802/max77802.h b/src/drivers/maxim/max77802/max77802.h new file mode 100644 index 0000000000..beb7195dfb --- /dev/null +++ b/src/drivers/maxim/max77802/max77802.h @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Rajeshwari Shinde + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __MAX77802_H_ +#define __MAX77802_H_ + +enum { + MAX77802_REG_PMIC_ID = 0x0, + MAX77802_REG_PMIC_INTSRC, + MAX77802_REG_PMIC_INT1, + MAX77802_REG_PMIC_INT2, + MAX77802_REG_PMIC_INT1MSK, + MAX77802_REG_PMIC_INT2MSK, + + MAX77802_REG_PMIC_STATUS1, + MAX77802_REG_PMIC_STATUS2, + + MAX77802_REG_PMIC_PWRON, + MAX77802_REG_PMIC_MRSTB = 0xA, + MAX77802_REG_PMIC_EPWRHOLD, + MAX77802_REG_PMIC_BOOSTCTRL = 0xE, + MAX77802_REG_PMIC_BOOSTOUT, + + MAX77802_REG_PMIC_BUCK1CTRL = 0x10, + MAX77802_REG_PMIC_BUCK1DVS1, + MAX77802_REG_PMIC_BUCK1DVS2, + MAX77802_REG_PMIC_BUCK1DVS3, + MAX77802_REG_PMIC_BUCK1DVS4, + MAX77802_REG_PMIC_BUCK1DVS5, + MAX77802_REG_PMIC_BUCK1DVS6, + MAX77802_REG_PMIC_BUCK1DVS7, + MAX77802_REG_PMIC_BUCK1DVS8, + + MAX77802_REG_PMIC_BUCK234FREQ, + MAX77802_REG_PMIC_BUCK2CTRL1, + MAX77802_REG_PMIC_BUCK2CTRL2, + MAX77802_REG_PMIC_BUCK2PHTRAN, + + MAX77802_REG_PMIC_BUCK2DVS1, + MAX77802_REG_PMIC_BUCK2DVS2, + MAX77802_REG_PMIC_BUCK2DVS3, + MAX77802_REG_PMIC_BUCK2DVS4, + MAX77802_REG_PMIC_BUCK2DVS5, + MAX77802_REG_PMIC_BUCK2DVS6, + MAX77802_REG_PMIC_BUCK2DVS7, + MAX77802_REG_PMIC_BUCK2DVS8, + MAX77802_REG_PMIC_BUCK3CTRL1 = 0x27, + MAX77802_REG_PMIC_BUCK3DVS1, + MAX77802_REG_PMIC_BUCK3DVS2, + MAX77802_REG_PMIC_BUCK3DVS3, + MAX77802_REG_PMIC_BUCK3DVS4, + MAX77802_REG_PMIC_BUCK3DVS5, + MAX77802_REG_PMIC_BUCK3DVS6, + MAX77802_REG_PMIC_BUCK3DVS7, + MAX77802_REG_PMIC_BUCK3DVS8, + MAX77802_REG_PMIC_BUCK4CTRL1 = 0x37, + MAX77802_REG_PMIC_BUCK4DVS1, + MAX77802_REG_PMIC_BUCK4DVS2, + MAX77802_REG_PMIC_BUCK4DVS3, + MAX77802_REG_PMIC_BUCK4DVS4, + MAX77802_REG_PMIC_BUCK4DVS5, + MAX77802_REG_PMIC_BUCK4DVS6, + MAX77802_REG_PMIC_BUCK4DVS7, + MAX77802_REG_PMIC_BUCK4DVS8, + MAX77802_REG_PMIC_BUCK5CTRL1 = 0x40, + MAX77802_REG_PMIC_BUCK5CTRL, + MAX77802_REG_PMIC_BUCK5OUT, + + MAX77802_REG_PMIC_BUCK6CTRL = 0x44, + MAX77802_REG_PMIC_BUCK6DVS1, + MAX77802_REG_PMIC_BUCK6DVS2, + MAX77802_REG_PMIC_BUCK6DVS3, + MAX77802_REG_PMIC_BUCK6DVS4, + MAX77802_REG_PMIC_BUCK6DVS5, + MAX77802_REG_PMIC_BUCK6DVS6, + MAX77802_REG_PMIC_BUCK6DVS7, + MAX77802_REG_PMIC_BUCK6DVS8, + + MAX77802_REG_PMIC_BUCK7CTRL = 0x4E, + MAX77802_REG_PMIC_BUCK7OUT, + + MAX77802_REG_PMIC_BUCK8CTRL = 0x51, + MAX77802_REG_PMIC_BUCK8OUT, + + MAX77802_REG_PMIC_BUCK9CTRL = 0x54, + MAX77802_REG_PMIC_BUCK9OUT, + + MAX77802_REG_PMIC_BUCK10CTRL = 0x57, + MAX77802_REG_PMIC_BUCK10OUT, + + MAX77802_REG_PMIC_LDO1CTRL1 = 0x60, + MAX77802_REG_PMIC_LDO2CTRL1, + MAX77802_REG_PMIC_LDO3CTRL1, + MAX77802_REG_PMIC_LDO4CTRL1, + MAX77802_REG_PMIC_LDO5CTRL1, + MAX77802_REG_PMIC_LDO6CTRL1, + MAX77802_REG_PMIC_LDO7CTRL1, + MAX77802_REG_PMIC_LDO8CTRL1, + MAX77802_REG_PMIC_LDO9CTRL1, + MAX77802_REG_PMIC_LDO10CTRL1, + MAX77802_REG_PMIC_LDO11CTRL1, + MAX77802_REG_PMIC_LDO12CTRL1, + MAX77802_REG_PMIC_LDO13CTRL1, + MAX77802_REG_PMIC_LDO14CTRL1, + MAX77802_REG_PMIC_LDO15CTRL1, + + MAX77802_REG_PMIC_LDO17CTRL1 = 0x70, + MAX77802_REG_PMIC_LDO18CTRL1, + MAX77802_REG_PMIC_LDO19CTRL1, + MAX77802_REG_PMIC_LDO20CTRL1, + MAX77802_REG_PMIC_LDO21CTRL1, + + MAX77802_REG_PMIC_LDO23CTRL1 = 0x76, + MAX77802_REG_PMIC_LDO24CTRL1, + MAX77802_REG_PMIC_LDO25CTRL1, + MAX77802_REG_PMIC_LDO26CTRL1, + MAX77802_REG_PMIC_LDO27CTRL1 = 0x7A, + MAX77802_REG_PMIC_LDO28CTRL1, + MAX77802_REG_PMIC_LDO29CTRL1, + MAX77802_REG_PMIC_LDO30CTRL1, + MAX77802_REG_PMIC_LDO32CTRL1 = 0x7F, + MAX77802_REG_PMIC_LDO33CTRL1, + MAX77802_REG_PMIC_LDO34CTRL1, + MAX77802_REG_PMIC_LDO35CTRL1, + + MAX77802_REG_PMIC_LDO1CTRL2 = 0x90, + MAX77802_REG_PMIC_LDO2CTRL2, + MAX77802_REG_PMIC_LDO3CTRL2, + MAX77802_REG_PMIC_LDO4CTRL2, + MAX77802_REG_PMIC_LDO5CTRL2, + MAX77802_REG_PMIC_LDO6CTRL2 = 0x95, + MAX77802_REG_PMIC_LDO7CTRL2, + MAX77802_REG_PMIC_LDO8CTRL2, + MAX77802_REG_PMIC_LDO9CTRL2, + MAX77802_REG_PMIC_LDO10CTRL2, + MAX77802_REG_PMIC_LDO11CTRL2, + MAX77802_REG_PMIC_LDO12CTRL2, + MAX77802_REG_PMIC_LDO13CTRL2, + MAX77802_REG_PMIC_LDO14CTRL2, + MAX77802_REG_PMIC_LDO15CTRL2, + + MAX77802_REG_PMIC_LDO17CTRL2 = 0xA0, + MAX77802_REG_PMIC_LDO18CTRL2, + MAX77802_REG_PMIC_LDO19CTRL2, + MAX77802_REG_PMIC_LDO20CTRL2, + MAX77802_REG_PMIC_LDO21CTRL2, + MAX77802_REG_PMIC_LDO22CTRL2, + MAX77802_REG_PMIC_LDO23CTRL2, + MAX77802_REG_PMIC_LDO24CTRL2, + MAX77802_REG_PMIC_LDO25CTRL2, + MAX77802_REG_PMIC_LDO26CTRL2, + MAX77802_REG_PMIC_LDO27CTRL2 = 0xAA, + MAX77802_REG_PMIC_LDO28CTRL2, + MAX77802_REG_PMIC_LDO29CTRL2, + MAX77802_REG_PMIC_LDO30CTRL2, + MAX77802_REG_PMIC_LDO32CTRL2 = 0xAF, + MAX77802_REG_PMIC_LDO33CTRL2 = 0xB0, + MAX77802_REG_PMIC_LDO34CTRL2, + MAX77802_REG_PMIC_LDO35CTRL2, + + MAX77802_REG_PMIC_BBAT = 0xB4, + MAX77802_REG_PMIC_32KHZ, + + MAX77802_NUM_OF_REGS, +}; + +/* I2C device address for pmic max77686 */ +#define MAX77802_I2C_ADDR (0x12 >> 1) + +enum { + LDO_OFF = 0, + LDO_ON, + + DIS_LDO = (0x00 << 6), + EN_LDO = (0x3 << 6), +}; + +/* Buck1 1.0 volt value (P1.0V_AP_MIF) */ +#define MAX77802_BUCK1DVS1_1V 0x3E +/* Buck2 1.0 volt value (P1.0V_VDD_ARM) */ +#define MAX77802_BUCK2DVS1_1V 0x40 +/* Buck2 1.2625 volt value (P1.2625V_VDD_ARM) */ +#define MAX77802_BUCK2DVS1_1_2625V 0x6A +/* Buck3 1.0 volt value (P1.0V_VDD_INT) */ +#define MAX77802_BUCK3DVS1_1V 0x40 +/* Buck4 1.0 volt value (P1.0V_VDD_G3D) */ +#define MAX77802_BUCK4DVS1_1V 0x40 +/* Buck6 1.0 volt value (P1.0V_AP_KFC) */ +#define MAX77802_BUCK6DVS1_1V 0x3E + +/* + * Different Bucks use different bits to control power. There are two types, + * defined below. + */ +/* Type 1, works for BUCKs 1, 5, 6...10 */ +#define MAX77802_BUCK_TYPE1_ON (1 << 0) +#define MAX77802_BUCK_TYPE1_IGNORE_PWRREQ (1 << 1) + +/* Type 2, works for BUCKs 2...4 */ +#define MAX77802_BUCK_TYPE2_ON (1 << 4) +#define MAX77802_BUCK_TYPE2_IGNORE_PWRREQ (1 << 5) + +/* LDO35 1.2 volt value for bridge ic */ +#define MAX77802_LDO35CTRL1_1_2V (1 << 4) +#define MAX77802_LOD35CTRL1_ON (1 << 6) + +/* Disable Boost Mode*/ +#define MAX77802_BOOSTCTRL_OFF 0x09 + +/* + * MAX77802_REG_PMIC_32KHZ set to 32KH CP + * output is activated + */ +#define MAX77802_32KHCP_EN (1 << 1) + +/* + * MAX77802_REG_PMIC_BBAT set to + * Back up batery charger on and + * limit voltage setting to 3.5v + */ +#define MAX77802_BBCHOSTEN (1 << 0) +#define MAX77802_BBCVS_3_5V (3 << 3) + +#endif /* __MAX77802_H_ */ diff --git a/src/drivers/oxford/oxpcie/oxpcie_early.c b/src/drivers/oxford/oxpcie/oxpcie_early.c index 98996197e7..2c7b4e86cd 100644 --- a/src/drivers/oxford/oxpcie/oxpcie_early.c +++ b/src/drivers/oxford/oxpcie/oxpcie_early.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/drivers/parade/Kconfig b/src/drivers/parade/Kconfig new file mode 100644 index 0000000000..b4b2ac2fbc --- /dev/null +++ b/src/drivers/parade/Kconfig @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +source src/drivers/parade/ps8625/Kconfig diff --git a/src/drivers/parade/Makefile.inc b/src/drivers/parade/Makefile.inc new file mode 100644 index 0000000000..efbd11de0f --- /dev/null +++ b/src/drivers/parade/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-$(CONFIG_DRIVER_PARADE_PS8625) += ps8625/ diff --git a/src/drivers/parade/ps8625/Kconfig b/src/drivers/parade/ps8625/Kconfig new file mode 100644 index 0000000000..41aa92b983 --- /dev/null +++ b/src/drivers/parade/ps8625/Kconfig @@ -0,0 +1,24 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config DRIVER_PARADE_PS8625 + bool + default n + help + Parade ps8625 display port to lvds bridge diff --git a/src/drivers/parade/ps8625/Makefile.inc b/src/drivers/parade/ps8625/Makefile.inc new file mode 100644 index 0000000000..ef546bae3b --- /dev/null +++ b/src/drivers/parade/ps8625/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_DRIVER_PARADE_PS8625) += ps8625.c diff --git a/src/drivers/parade/ps8625/ps8625.c b/src/drivers/parade/ps8625/ps8625.c new file mode 100644 index 0000000000..c673d3a3a5 --- /dev/null +++ b/src/drivers/parade/ps8625/ps8625.c @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "ps8625.h" + +void parade_ps8625_bridge_setup(unsigned bus, unsigned chip_base, + const struct parade_write *parade_writes, + int parade_write_count) +{ + int i; + + for (i = 0; i < parade_write_count; i++) { + const struct parade_write *w = ¶de_writes[i]; + i2c_writeb(bus, chip_base + w->offset, w->reg, w->val); + } +} diff --git a/src/drivers/parade/ps8625/ps8625.h b/src/drivers/parade/ps8625/ps8625.h new file mode 100644 index 0000000000..82f2499545 --- /dev/null +++ b/src/drivers/parade/ps8625/ps8625.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __PS8625_H__ +#define __PS8625_H__ + +struct parade_write { + uint8_t offset; + uint8_t reg; + uint8_t val; +}; + +void parade_ps8625_bridge_setup(unsigned bus, unsigned chip_base, + const struct parade_write *, + int parade_write_count); + +#endif diff --git a/src/drivers/pc80/Kconfig b/src/drivers/pc80/Kconfig index 3c8fd8c6cd..2e406b3715 100644 --- a/src/drivers/pc80/Kconfig +++ b/src/drivers/pc80/Kconfig @@ -15,10 +15,19 @@ config DRIVERS_PS2_KEYBOARD this option, then you can say N here to speed up boot time. Otherwise say Y. -config TPM +config DRIVERS_MC146818_RTC bool - default n - help - Enable this option to enable TPM support in coreboot. + default y if ARCH_X86 + default n if !ARCH_X86 - If unsure, say N. +config DRIVERS_MC146818_CMOS + bool + default y if ARCH_X86 + default n if !ARCH_X86 + +config DRIVERS_RTC_HAS_ALTCENTURY + bool "The RTC supports alt century" + depends on DRIVERS_MC146818_RTC + default y + +source src/drivers/pc80/tpm/Kconfig diff --git a/src/drivers/pc80/Makefile.inc b/src/drivers/pc80/Makefile.inc index 23e986a515..61b3853b61 100644 --- a/src/drivers/pc80/Makefile.inc +++ b/src/drivers/pc80/Makefile.inc @@ -1,19 +1,20 @@ -ramstage-y += mc146818rtc.c +ramstage-$(CONFIG_DRIVERS_MC146818_RTC) += mc146818rtc.c +ramstage-$(CONFIG_DRIVERS_MC146818_CMOS) += mc146818.c ramstage-y += isa-dma.c ramstage-y += i8254.c ramstage-y += i8259.c ramstage-$(CONFIG_UDELAY_IO) += udelay_io.c ramstage-y += keyboard.c -romstage-$(CONFIG_TPM) += tpm.c +ifeq ($(CONFIG_DRIVERS_MC146818_CMOS),y) romstage-$(CONFIG_USE_OPTION_TABLE) += mc146818rtc_early.c -subdirs-y += vga +endif + +subdirs-y += tpm vga cbfs-files-$(CONFIG_HAVE_CMOS_DEFAULT) += cmos.default cmos.default-file = $(CONFIG_CMOS_DEFAULT_FILE):nvramtool cmos.default-type = 0xaa +smm-y += mc146818.c smm-y += mc146818rtc.c - -$(obj)/drivers/pc80/mc146818rtc.ramstage.o : $(obj)/build.h -$(obj)/drivers/pc80/mc146818rtc.smm.o : $(obj)/build.h diff --git a/src/drivers/pc80/keyboard.c b/src/drivers/pc80/keyboard.c index 2888bcf295..e389329710 100644 --- a/src/drivers/pc80/keyboard.c +++ b/src/drivers/pc80/keyboard.c @@ -25,6 +25,9 @@ #include #include #include +#if CONFIG_HAVE_ACPI_RESUME +#include +#endif #define KBD_DATA 0x60 #define KBD_COMMAND 0x64 @@ -194,6 +197,12 @@ void pc_keyboard_init(struct pc_keyboard *keyboard) u8 regval; if (!CONFIG_DRIVERS_PS2_KEYBOARD) return; + +#if CONFIG_HAVE_ACPI_RESUME + if (acpi_slp_type == 3) + return; +#endif + printk(BIOS_DEBUG, "Keyboard init...\n"); /* Run a keyboard controller self-test */ diff --git a/src/drivers/pc80/mc146818.c b/src/drivers/pc80/mc146818.c new file mode 100644 index 0000000000..1500191509 --- /dev/null +++ b/src/drivers/pc80/mc146818.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_USE_OPTION_TABLE +#include "option_table.h" +#include +#endif +#if CONFIG_HAVE_ACPI_RESUME +#include +#endif + + +static void cmos_reset_date(void) +{ + /* Now setup a default date equals to the build date */ + struct rtc_time time = { + .sec = 0, + .min = 0, + .hour = 1, + .mday = bcd2bin(COREBOOT_BUILD_DAY_BCD), + .mon = bcd2bin(COREBOOT_BUILD_MONTH_BCD), + .year = 2000 + bcd2bin(COREBOOT_BUILD_YEAR_BCD), + .wday = bcd2bin(COREBOOT_BUILD_WEEKDAY_BCD) + }; + rtc_set(&time); +} + +#if CONFIG_USE_OPTION_TABLE +static int cmos_checksum_valid(int range_start, int range_end, int cks_loc) +{ + int i; + u16 sum, old_sum; + sum = 0; + for (i = range_start; i <= range_end; i++) + sum += cmos_read(i); + old_sum = ((cmos_read(cks_loc) << 8) | cmos_read(cks_loc + 1)) & + 0x0ffff; + return sum == old_sum; +} + +static void cmos_set_checksum(int range_start, int range_end, int cks_loc) +{ + int i; + u16 sum; + sum = 0; + for (i = range_start; i <= range_end; i++) + sum += cmos_read(i); + cmos_write(((sum >> 8) & 0x0ff), cks_loc); + cmos_write(((sum >> 0) & 0x0ff), cks_loc + 1); +} +#endif + +#define RTC_CONTROL_DEFAULT (RTC_24H) +#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) + +#ifndef __SMM__ +void cmos_init(int invalid) +{ + int cmos_invalid = 0; + int checksum_invalid = 0; +#if CONFIG_USE_OPTION_TABLE + unsigned char x; +#endif + +#if CONFIG_HAVE_ACPI_RESUME + /* Avoid clearing pending interrupts and resetting the RTC control + * register in the resume path because the Linux kernel relies on + * this to know if it should restart the RTC timerqueue if the wake + * was due to the RTC alarm. + */ + if (acpi_slp_type == 3) + return; +#endif + + printk(BIOS_DEBUG, "RTC Init\n"); + +#if CONFIG_USE_OPTION_TABLE + /* See if there has been a CMOS power problem. */ + x = cmos_read(RTC_VALID); + cmos_invalid = !(x & RTC_VRT); + + /* See if there is a CMOS checksum error */ + checksum_invalid = !cmos_checksum_valid(PC_CKS_RANGE_START, + PC_CKS_RANGE_END,PC_CKS_LOC); + +#define CLEAR_CMOS 0 +#else +#define CLEAR_CMOS 1 +#endif + + if (invalid || cmos_invalid || checksum_invalid) { +#if CLEAR_CMOS + int i; + + cmos_write(0, 0x01); + cmos_write(0, 0x03); + cmos_write(0, 0x05); + for (i = 10; i < 128; i++) + cmos_write(0, i); +#endif + if (cmos_invalid) + cmos_reset_date(); + + printk(BIOS_WARNING, "RTC:%s%s%s%s\n", + invalid?" Clear requested":"", + cmos_invalid?" Power Problem":"", + checksum_invalid?" Checksum invalid":"", + CLEAR_CMOS?" zeroing cmos":""); + } + + /* Setup the real time clock */ + cmos_write(RTC_CONTROL_DEFAULT, RTC_CONTROL); + /* Setup the frequency it operates at */ + cmos_write(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT); + /* Ensure all reserved bits are 0 in register D */ + cmos_write(RTC_VRT, RTC_VALID); + +#if CONFIG_USE_OPTION_TABLE + /* See if there is a LB CMOS checksum error */ + checksum_invalid = !cmos_checksum_valid(LB_CKS_RANGE_START, + LB_CKS_RANGE_END,LB_CKS_LOC); + if (checksum_invalid) + printk(BIOS_DEBUG, "RTC: coreboot checksum invalid\n"); + + /* Make certain we have a valid checksum */ + cmos_set_checksum(PC_CKS_RANGE_START, PC_CKS_RANGE_END, PC_CKS_LOC); +#endif + + /* Clear any pending interrupts */ + cmos_read(RTC_INTR_FLAGS); +} +#endif + + +#if CONFIG_USE_OPTION_TABLE +/* + * This routine returns the value of the requested bits + * input bit = bit count from the beginning of the cmos image + * length = number of bits to include in the value + * vret = a character pointer to where the value is to be returned + * returns 0 = successful, -1 = an error occurred + */ +static int get_cmos_value(unsigned long bit, unsigned long length, void *vret) +{ + unsigned char *ret; + unsigned long byte,byte_bit; + unsigned long i; + unsigned char uchar; + + /* + * The table is checked when it is built to ensure all + * values are valid. + */ + ret = vret; + byte = bit / 8; /* find the byte where the data starts */ + byte_bit = bit % 8; /* find the bit in the byte where the data starts */ + if (length < 9) { /* one byte or less */ + uchar = cmos_read(byte); /* load the byte */ + uchar >>= byte_bit; /* shift the bits to byte align */ + /* clear unspecified bits */ + ret[0] = uchar & ((1 << length) - 1); + } else { /* more that one byte so transfer the whole bytes */ + for (i = 0; length; i++, length -= 8, byte++) { + /* load the byte */ + ret[i] = cmos_read(byte); + } + } + return 0; +} + +int get_option(void *dest, const char *name) +{ + struct cmos_option_table *ct; + struct cmos_entries *ce; + size_t namelen; + int found = 0; + + /* Figure out how long name is */ + namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); + + /* find the requested entry record */ + ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); + if (!ct) { + printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " + "Options are disabled\n"); + return -2; + } + ce = (struct cmos_entries*)((unsigned char *)ct + ct->header_length); + for(; ce->tag == LB_TAG_OPTION; + ce = (struct cmos_entries*)((unsigned char *)ce + ce->size)) { + if (memcmp(ce->name, name, namelen) == 0) { + found = 1; + break; + } + } + if (!found) { + printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); + return -2; + } + + if (get_cmos_value(ce->bit, ce->length, dest)) + return -3; + if (!cmos_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END, + LB_CKS_LOC)) + return -4; + return 0 ; +} + +static int set_cmos_value(unsigned long bit, unsigned long length, void *vret) +{ + unsigned char *ret; + unsigned long byte,byte_bit; + unsigned long i; + unsigned char uchar, mask; + unsigned int chksum_update_needed = 0; + + ret = vret; + byte = bit / 8; /* find the byte where the data starts */ + byte_bit = bit % 8; /* find the bit where the data starts */ + if (length <= 8) { /* one byte or less */ + mask = (1 << length) - 1; + mask <<= byte_bit; + + uchar = cmos_read(byte); + uchar &= ~mask; + uchar |= (ret[0] << byte_bit); + cmos_write(uchar, byte); + if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END) + chksum_update_needed = 1; + } else { /* more that one byte so transfer the whole bytes */ + if (byte_bit || length % 8) + return -1; + + for (i = 0; length; i++, length -= 8, byte++) + cmos_write(ret[i], byte); + if (byte >= LB_CKS_RANGE_START && + byte <= LB_CKS_RANGE_END) + chksum_update_needed = 1; + } + + if (chksum_update_needed) { + cmos_set_checksum(LB_CKS_RANGE_START, LB_CKS_RANGE_END, + LB_CKS_LOC); + } + return 0; +} + + +int set_option(const char *name, void *value) +{ + struct cmos_option_table *ct; + struct cmos_entries *ce; + unsigned long length; + size_t namelen; + int found = 0; + + /* Figure out how long name is */ + namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); + + /* find the requested entry record */ + ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); + if (!ct) { + printk(BIOS_ERR, "cmos_layout.bin could not be found. " + "Options are disabled\n"); + return -2; + } + ce = (struct cmos_entries*)((unsigned char *)ct + ct->header_length); + for(; ce->tag == LB_TAG_OPTION; + ce = (struct cmos_entries*)((unsigned char *)ce + ce->size)) { + if (memcmp(ce->name, name, namelen) == 0) { + found = 1; + break; + } + } + if (!found) { + printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); + return -2; + } + + length = ce->length; + if (ce->config == 's') { + length = MAX(strlen((const char *)value) * 8, ce->length - 8); + /* make sure the string is null terminated */ + if ((set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0}))) + return -3; + } + + if ((set_cmos_value(ce->bit, length, value))) + return -3; + + return 0; +} +#endif /* CONFIG_USE_OPTION_TABLE */ + +/* + * If the CMOS is cleared, the rtc_reg has the invalid date. That + * hurts some OSes. Even if we don't set USE_OPTION_TABLE, we need + * to make sure the date is valid. + */ +void cmos_check_update_date(void) +{ + u8 year, century; + + /* Note: Need to check if the hardware supports RTC_CLK_ALTCENTURY. */ + century = CONFIG_DRIVERS_RTC_HAS_ALTCENTURY ? + cmos_read(RTC_CLK_ALTCENTURY) : 0; + year = cmos_read(RTC_CLK_YEAR); + + /* + * TODO: If century is 0xFF, 100% that the cmos is cleared. + * Other than that, so far rtc_year is the only entry to check + * if the date is valid. + */ + if (century > 0x99 || year > 0x99) /* Invalid date */ + cmos_reset_date(); +} diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c index d91f207427..7954af41ba 100644 --- a/src/drivers/pc80/mc146818rtc.c +++ b/src/drivers/pc80/mc146818rtc.c @@ -1,324 +1,53 @@ -#include -#include -#include -#include -#include -#include -#if CONFIG_USE_OPTION_TABLE -#include "option_table.h" -#include -#endif -#if CONFIG_HAVE_ACPI_RESUME -#include -#endif - - -static void rtc_update_cmos_date(u8 has_century) -{ - /* Now setup a default date equals to the build date */ - cmos_write(0, RTC_CLK_SECOND); - cmos_write(0, RTC_CLK_MINUTE); - cmos_write(1, RTC_CLK_HOUR); - cmos_write(COREBOOT_BUILD_WEEKDAY_BCD + 1, RTC_CLK_DAYOFWEEK); - cmos_write(COREBOOT_BUILD_DAY_BCD, RTC_CLK_DAYOFMONTH); - cmos_write(COREBOOT_BUILD_MONTH_BCD, RTC_CLK_MONTH); - cmos_write(COREBOOT_BUILD_YEAR_BCD, RTC_CLK_YEAR); - if (has_century) cmos_write(0x20, RTC_CLK_ALTCENTURY); -} - -#if CONFIG_USE_OPTION_TABLE -static int rtc_checksum_valid(int range_start, int range_end, int cks_loc) -{ - int i; - u16 sum, old_sum; - sum = 0; - for(i = range_start; i <= range_end; i++) { - sum += cmos_read(i); - } - old_sum = ((cmos_read(cks_loc)<<8) | cmos_read(cks_loc+1))&0x0ffff; - return sum == old_sum; -} - -static void rtc_set_checksum(int range_start, int range_end, int cks_loc) -{ - int i; - u16 sum; - sum = 0; - for(i = range_start; i <= range_end; i++) { - sum += cmos_read(i); - } - cmos_write(((sum >> 8) & 0x0ff), cks_loc); - cmos_write(((sum >> 0) & 0x0ff), cks_loc+1); -} -#endif - -#if CONFIG_ARCH_X86 -#define RTC_CONTROL_DEFAULT (RTC_24H) -#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) -#else -#if CONFIG_ARCH_ALPHA -#define RTC_CONTROL_DEFAULT (RTC_SQWE | RTC_24H) -#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) -#endif -#endif - -#ifndef __SMM__ -void rtc_init(int invalid) -{ - int cmos_invalid = 0; - int checksum_invalid = 0; -#if CONFIG_USE_OPTION_TABLE - unsigned char x; -#endif - - printk(BIOS_DEBUG, "RTC Init\n"); - -#if CONFIG_USE_OPTION_TABLE - /* See if there has been a CMOS power problem. */ - x = cmos_read(RTC_VALID); - cmos_invalid = !(x & RTC_VRT); - - /* See if there is a CMOS checksum error */ - checksum_invalid = !rtc_checksum_valid(PC_CKS_RANGE_START, - PC_CKS_RANGE_END,PC_CKS_LOC); - -#define CLEAR_CMOS 0 -#else -#define CLEAR_CMOS 1 -#endif - - if (invalid || cmos_invalid || checksum_invalid) { -#if CLEAR_CMOS - int i; - - cmos_write(0, 0x01); - cmos_write(0, 0x03); - cmos_write(0, 0x05); - for(i = 10; i < 128; i++) { - cmos_write(0, i); - } -#endif - if (cmos_invalid) { - rtc_update_cmos_date(RTC_HAS_NO_ALTCENTURY); - } - - printk(BIOS_WARNING, "RTC:%s%s%s%s\n", - invalid?" Clear requested":"", - cmos_invalid?" Power Problem":"", - checksum_invalid?" Checksum invalid":"", - CLEAR_CMOS?" zeroing cmos":""); - } - - /* Setup the real time clock */ - cmos_write(RTC_CONTROL_DEFAULT, RTC_CONTROL); - /* Setup the frequency it operates at */ - cmos_write(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT); - /* Ensure all reserved bits are 0 in register D */ - cmos_write(RTC_VRT, RTC_VALID); - -#if CONFIG_USE_OPTION_TABLE - /* See if there is a LB CMOS checksum error */ - checksum_invalid = !rtc_checksum_valid(LB_CKS_RANGE_START, - LB_CKS_RANGE_END,LB_CKS_LOC); - if(checksum_invalid) - printk(BIOS_DEBUG, "RTC: coreboot checksum invalid\n"); - - /* Make certain we have a valid checksum */ - rtc_set_checksum(PC_CKS_RANGE_START, - PC_CKS_RANGE_END,PC_CKS_LOC); -#endif - -#if CONFIG_HAVE_ACPI_RESUME - /* - * Avoid clearing pending interrupts in the resume path because - * the Linux kernel relies on this to know if it should restart - * the RTC timerqueue if the wake was due to the RTC alarm. - */ - if (acpi_slp_type == 3) - return; -#endif - - /* Clear any pending interrupts */ - (void) cmos_read(RTC_INTR_FLAGS); -} -#endif - - -#if CONFIG_USE_OPTION_TABLE -/* This routine returns the value of the requested bits - input bit = bit count from the beginning of the cmos image - length = number of bits to include in the value - ret = a character pointer to where the value is to be returned - output the value placed in ret - returns 0 = successful, -1 = an error occurred -*/ -static int get_cmos_value(unsigned long bit, unsigned long length, void *vret) -{ - unsigned char *ret; - unsigned long byte,byte_bit; - unsigned long i; - unsigned char uchar; - - /* The table is checked when it is built to ensure all - values are valid. */ - ret = vret; - byte=bit/8; /* find the byte where the data starts */ - byte_bit=bit%8; /* find the bit in the byte where the data starts */ - if(length<9) { /* one byte or less */ - uchar = cmos_read(byte); /* load the byte */ - uchar >>= byte_bit; /* shift the bits to byte align */ - /* clear unspecified bits */ - ret[0] = uchar & ((1 << length) -1); - } - else { /* more that one byte so transfer the whole bytes */ - for(i=0;length;i++,length-=8,byte++) { - /* load the byte */ - ret[i]=cmos_read(byte); - } - } - return 0; -} - -int get_option(void *dest, const char *name) -{ - struct cmos_option_table *ct; - struct cmos_entries *ce; - size_t namelen; - int found=0; - - /* Figure out how long name is */ - namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); - - /* find the requested entry record */ - ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT); - if (!ct) { - printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " - "Options are disabled\n"); - return(-2); - } - ce=(struct cmos_entries*)((unsigned char *)ct + ct->header_length); - for(;ce->tag==LB_TAG_OPTION; - ce=(struct cmos_entries*)((unsigned char *)ce + ce->size)) { - if (memcmp(ce->name, name, namelen) == 0) { - found=1; - break; - } - } - if(!found) { - printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); - return(-2); - } - - if(get_cmos_value(ce->bit, ce->length, dest)) - return(-3); - if(!rtc_checksum_valid(LB_CKS_RANGE_START, - LB_CKS_RANGE_END,LB_CKS_LOC)) - return(-4); - return(0); -} - -static int set_cmos_value(unsigned long bit, unsigned long length, void *vret) -{ - unsigned char *ret; - unsigned long byte,byte_bit; - unsigned long i; - unsigned char uchar, mask; - unsigned int chksum_update_needed = 0; - - ret = vret; - byte = bit / 8; /* find the byte where the data starts */ - byte_bit = bit % 8; /* find the bit in the byte where the data starts */ - if(length <= 8) { /* one byte or less */ - mask = (1 << length) - 1; - mask <<= byte_bit; - - uchar = cmos_read(byte); - uchar &= ~mask; - uchar |= (ret[0] << byte_bit); - cmos_write(uchar, byte); - if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END) - chksum_update_needed = 1; - } else { /* more that one byte so transfer the whole bytes */ - if (byte_bit || length % 8) - return -1; - - for(i=0; length; i++, length-=8, byte++) - cmos_write(ret[i], byte); - if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END) - chksum_update_needed = 1; - } - - if (chksum_update_needed) { - rtc_set_checksum(LB_CKS_RANGE_START, - LB_CKS_RANGE_END,LB_CKS_LOC); - } - return 0; -} - - -int set_option(const char *name, void *value) -{ - struct cmos_option_table *ct; - struct cmos_entries *ce; - unsigned long length; - size_t namelen; - int found=0; - - /* Figure out how long name is */ - namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); - - /* find the requested entry record */ - ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT); - if (!ct) { - printk(BIOS_ERR, "cmos_layout.bin could not be found. Options are disabled\n"); - return(-2); - } - ce=(struct cmos_entries*)((unsigned char *)ct + ct->header_length); - for(;ce->tag==LB_TAG_OPTION; - ce=(struct cmos_entries*)((unsigned char *)ce + ce->size)) { - if (memcmp(ce->name, name, namelen) == 0) { - found=1; - break; - } - } - if(!found) { - printk(BIOS_DEBUG, "WARNING: No CMOS option '%s'.\n", name); - return(-2); - } - - length = ce->length; - if (ce->config == 's') { - length = MAX(strlen((const char *)value) * 8, ce->length - 8); - /* make sure the string is null terminated */ - if ((set_cmos_value(ce->bit + ce->length - 8, 8, &(u8[]){0}))) - return (-3); - } - - if ((set_cmos_value(ce->bit, length, value))) - return (-3); - - return 0; -} -#endif /* CONFIG_USE_OPTION_TABLE */ - /* - * If the CMOS is cleared, the rtc_reg has the invalid date. That - * hurts some OSes. Even if we don't set USE_OPTION_TABLE, we need - * to make sure the date is valid. + * This file is part of the coreboot project. + * + * Copyright 2014 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -void rtc_check_update_cmos_date(u8 has_century) + +#include +#include +#include + +int rtc_set(const struct rtc_time *time) { - u8 year, century; - - /* Note: We need to check if the hardware supports RTC_CLK_ALTCENTURY. */ - century = has_century ? cmos_read(RTC_CLK_ALTCENTURY) : 0; - year = cmos_read(RTC_CLK_YEAR); - - /* TODO: If century is 0xFF, 100% that the cmos is cleared. - * Other than that, so far rtc_year is the only entry to check if the date is valid. */ - if (century > 0x99 || year > 0x99) { /* Invalid date */ - rtc_update_cmos_date(has_century); - } + cmos_write(bin2bcd(time->sec), RTC_CLK_SECOND); + cmos_write(bin2bcd(time->min), RTC_CLK_MINUTE); + cmos_write(bin2bcd(time->hour), RTC_CLK_HOUR); + cmos_write(bin2bcd(time->mday), RTC_CLK_DAYOFMONTH); + cmos_write(bin2bcd(time->mon), RTC_CLK_MONTH); + cmos_write(bin2bcd(time->year % 100), RTC_CLK_YEAR); + if (CONFIG_DRIVERS_RTC_HAS_ALTCENTURY) + cmos_write(bin2bcd(time->year / 100), + RTC_CLK_ALTCENTURY); + cmos_write(bin2bcd(time->wday + 1), RTC_CLK_DAYOFWEEK); + return 0; +} + +int rtc_get(struct rtc_time *time) +{ + time->sec = bcd2bin(cmos_read(RTC_CLK_SECOND)); + time->min = bcd2bin(cmos_read(RTC_CLK_MINUTE)); + time->hour = bcd2bin(cmos_read(RTC_CLK_HOUR)); + time->mday = bcd2bin(cmos_read(RTC_CLK_DAYOFMONTH)); + time->mon = bcd2bin(cmos_read(RTC_CLK_MONTH)); + time->year = bcd2bin(cmos_read(RTC_CLK_YEAR)); + if (CONFIG_DRIVERS_RTC_HAS_ALTCENTURY) + time->year += bcd2bin(cmos_read(RTC_CLK_ALTCENTURY)) * 100; + else + time->year += 2000; + time->wday = bcd2bin(cmos_read(RTC_CLK_DAYOFWEEK)) - 1; + return 0; } diff --git a/src/drivers/pc80/tpm/Kconfig b/src/drivers/pc80/tpm/Kconfig new file mode 100644 index 0000000000..9630de2ac1 --- /dev/null +++ b/src/drivers/pc80/tpm/Kconfig @@ -0,0 +1,16 @@ +config LPC_TPM + bool + default n + help + Enable this option to enable LPC TPM support in coreboot. + + If unsure, say N. + +config TPM_TIS_BASE_ADDRESS + hex "TPM Base Address" + default 0xfed40000 + help + This can be used to adjust the TPM memory base address. + The default is specified by the TCG PC Client Specific TPM + Interface Specification 1.2 and should not be changed unless + the TPM being used does not conform to TPM TIS 1.2. diff --git a/src/drivers/pc80/tpm/Makefile.inc b/src/drivers/pc80/tpm/Makefile.inc new file mode 100644 index 0000000000..c900fe8c1d --- /dev/null +++ b/src/drivers/pc80/tpm/Makefile.inc @@ -0,0 +1,2 @@ +romstage-$(CONFIG_LPC_TPM) += tpm.c +ramstage-$(CONFIG_LPC_TPM) += tpm.c diff --git a/src/drivers/pc80/tpm/acpi/tpm.asl b/src/drivers/pc80/tpm/acpi/tpm.asl new file mode 100644 index 0000000000..7500211570 --- /dev/null +++ b/src/drivers/pc80/tpm/acpi/tpm.asl @@ -0,0 +1,104 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Trusted Platform Module */ + +Device (TPM) +{ + Name (_HID, EISAID ("PNP0C31")) + Name (_CID, 0x310cd041) + Name (_UID, 1) + + Method (_STA, 0) + { + If (CONFIG_LPC_TPM) { + Return (0xf) + } Else { + Return (0x0) + } + } + + Name (IBUF, ResourceTemplate () + { + /* Updated based on TPM interrupt for Locality 0 */ + Interrupt (ResourceConsumer, Edge, ActiveHigh, + Exclusive, , , TIRQ) { 0 } + }) + + Name (RBUF, ResourceTemplate () + { + IO (Decode16, 0x2e, 0x2e, 0x01, 0x02) + Memory32Fixed (ReadWrite, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000) + }) + + Method (_CRS, 0, NotSerialized) + { + OperationRegion (TREG, SystemMemory, + CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000) + Field (TREG, ByteAcc, NoLock, Preserve) + { + /* TPM_INT_ENABLE_0 */ + Offset (0x0008), + , 3, + ITPL, 2, /* Interrupt type and polarity */ + + /* TPM_INT_VECTOR_0 */ + Offset (0x000C), + IVEC, 4, /* SERIRQ vector */ + } + + If (LGreater (IVEC, 0)) { + /* Update interrupt vector */ + CreateField (^IBUF, ^TIRQ._INT, 32, TVEC) + Store (IVEC, TVEC) + + /* Update interrupt type and polarity */ + CreateBitField (^IBUF, ^TIRQ._HE, TTYP) + CreateBitField (^IBUF, ^TIRQ._LL, TPOL) + CreateBitField (^IBUF, ^TIRQ._SHR, TSHR) + + If (LEqual (ITPL, 0x0)) { + /* Active-High Level-Triggered Shared */ + Store (Zero, TPOL) + Store (Zero, TTYP) + Store (One, TSHR) + } ElseIf (LEqual (ITPL, 0x1)) { + /* Active-Low Level-Triggered Shared */ + Store (One, TPOL) + Store (Zero, TTYP) + Store (One, TSHR) + } ElseIf (LEqual (ITPL, 0x2)) { + /* Active-High Edge-Triggered Exclusive */ + Store (Zero, TPOL) + Store (One, TTYP) + Store (Zero, TSHR) + } ElseIf (LEqual (ITPL, 0x3)) { + /* Active-Low Edge-Triggered Exclusive */ + Store (One, TPOL) + Store (One, TTYP) + Store (Zero, TSHR) + } + + /* Merge IRQ with base address */ + Return (ConcatenateResTemplate (RBUF, IBUF)) + } Else { + Return (RBUF) + } + } +} diff --git a/src/drivers/pc80/tpm/chip.h b/src/drivers/pc80/tpm/chip.h new file mode 100644 index 0000000000..bcfb877dfa --- /dev/null +++ b/src/drivers/pc80/tpm/chip.h @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef DRIVERS_PC80_TPM_CHIP_H +#define DRIVERS_PC80_TPM_CHIP_H + +typedef struct drivers_pc80_tpm_config { + /* + * TPM Interrupt polarity: + * + * High Level 0 + * Low Level 1 + * Rising Edge 2 + * Falling Edge 3 + */ + u8 irq_polarity; +} tpm_config_t; + +#endif /* DRIVERS_PC80_TPM_CHIP_H */ diff --git a/src/drivers/pc80/tpm.c b/src/drivers/pc80/tpm/tpm.c similarity index 62% rename from src/drivers/pc80/tpm.c rename to src/drivers/pc80/tpm/tpm.c index c7b50816be..95db1620c5 100644 --- a/src/drivers/pc80/tpm.c +++ b/src/drivers/pc80/tpm/tpm.c @@ -33,8 +33,10 @@ #include #include #include -#include -#include +#include +#include +#include +#include "chip.h" #define PREFIX "lpc_tpm: " @@ -44,6 +46,10 @@ printk(BIOS_DEBUG, PREFIX); \ printk(BIOS_DEBUG, fmt , ##args); \ } +#define TPM_DEBUG_IO_READ(reg_, val_) \ + TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_)) +#define TPM_DEBUG_IO_WRITE(reg_, val_) \ + TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_)) #define printf(x...) printk(BIOS_ERR, x) #define min(a,b) MIN(a,b) @@ -70,6 +76,7 @@ #define TIS_REG_INT_STATUS 0x10 #define TIS_REG_INTF_CAPABILITY 0x14 #define TIS_REG_STS 0x18 +#define TIS_REG_BURST_COUNT 0x19 #define TIS_REG_DATA_FIFO 0x24 #define TIS_REG_DID_VID 0xf00 #define TIS_REG_RID 0xf04 @@ -90,9 +97,6 @@ #define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ #define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ -#define TIS_STS_BURST_COUNT_MASK (0xffff) -#define TIS_STS_BURST_COUNT_SHIFT (8) - /* * Error value returned if a tpm register does not enter the expected state * after continuous polling. No actual TPM register reading ever returns ~0, @@ -107,10 +111,6 @@ /* 1 second is plenty for anything TPM does.*/ #define MAX_DELAY_US (1000 * 1000) -/* Retrieve burst count value out of the status register contents. */ -#define BURST_COUNT(status) ((u16)(((status) >> TIS_STS_BURST_COUNT_SHIFT) & \ - TIS_STS_BURST_COUNT_MASK)) - /* * Structures defined below allow creating descriptions of TPM vendor/device * ID information for run time discovery. The only device the system knows @@ -160,71 +160,179 @@ static const struct vendor_name vendor_names[] = { */ static u32 vendor_dev_id CAR_GLOBAL; -static int is_byte_reg(u32 reg) +static inline u8 tpm_read_status(int locality) { - /* - * These TPM registers are 8 bits wide and as such require byte access - * on writes and truncated value on reads. - */ - return ((reg == TIS_REG_ACCESS) || - (reg == TIS_REG_INT_VECTOR) || - (reg == TIS_REG_DATA_FIFO)); -} - -/* TPM access functions are carved out to make tracing easier. */ -static u32 tpm_read(int locality, u32 reg) -{ - u32 value; - /* - * Data FIFO register must be read and written in byte access mode, - * otherwise the FIFO values are returned 4 bytes at a time. - */ - if (is_byte_reg(reg)) - value = readb(TIS_REG(locality, reg)); - else - value = readl(TIS_REG(locality, reg)); - - TPM_DEBUG("Read reg 0x%x returns 0x%x\n", reg, value); + u8 value = readb(TIS_REG(locality, TIS_REG_STS)); + TPM_DEBUG_IO_READ(TIS_REG_STS, value); return value; } -static void tpm_write(u32 value, int locality, u32 reg) +static inline void tpm_write_status(u8 sts, int locality) { - TPM_DEBUG("Write reg 0x%x with 0x%x\n", reg, value); + TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts); + writeb(sts, TIS_REG(locality, TIS_REG_STS)); +} - if (is_byte_reg(reg)) - writeb(value & 0xff, TIS_REG(locality, reg)); - else - writel(value, TIS_REG(locality, reg)); +static inline u8 tpm_read_data(int locality) +{ + u8 value = readb(TIS_REG(locality, TIS_REG_DATA_FIFO)); + TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value); + return value; +} + +static inline void tpm_write_data(u8 data, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_STS, data); + writeb(data, TIS_REG(locality, TIS_REG_DATA_FIFO)); +} + +static inline u16 tpm_read_burst_count(int locality) +{ + u16 count; + count = readb(TIS_REG(locality, TIS_REG_BURST_COUNT)); + count |= readb(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8; + TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count); + return count; +} + +static inline u8 tpm_read_access(int locality) +{ + u8 value = readb(TIS_REG(locality, TIS_REG_ACCESS)); + TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value); + return value; +} + +static inline void tpm_write_access(u8 data, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data); + writeb(data, TIS_REG(locality, TIS_REG_ACCESS)); +} + +static inline u32 tpm_read_did_vid(int locality) +{ + u32 value = readl(TIS_REG(locality, TIS_REG_DID_VID)); + TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value); + return value; +} + +static inline void tpm_write_int_vector(int vector, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector); + writeb(vector & 0xf, TIS_REG(locality, TIS_REG_INT_VECTOR)); +} + +static inline void tpm_write_int_polarity(int polarity, int locality) +{ + /* Set polarity and leave all other bits at 0 */ + u32 value = (polarity & 0x3) << 3; + TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value); + writel(value, TIS_REG(locality, TIS_REG_INT_ENABLE)); } /* - * tis_wait_reg() + * tis_wait_sts() * - * Wait for at least a second for a register to change its state to match the + * Wait for at least a second for a status to change its state to match the * expected state. Normally the transition happens within microseconds. * - * @reg - the TPM register offset * @locality - locality * @mask - bitmask for the bitfield(s) to watch * @expected - value the field(s) are supposed to be set to * - * Returns the register contents in case the expected value was found in the - * appropriate register bits, or TPM_TIMEOUT_ERR on timeout. + * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. */ -static u32 tis_wait_reg(u8 reg, u8 locality, u8 mask, u8 expected) +static int tis_wait_sts(int locality, u8 mask, u8 expected) { u32 time_us = MAX_DELAY_US; while (time_us > 0) { - u32 value = tpm_read(locality, reg); + u8 value = tpm_read_status(locality); if ((value & mask) == expected) - return value; + return 0; udelay(1); /* 1 us */ time_us--; } return TPM_TIMEOUT_ERR; } +static inline int tis_wait_ready(int locality) +{ + return tis_wait_sts(locality, TIS_STS_COMMAND_READY, + TIS_STS_COMMAND_READY); +} + +static inline int tis_wait_valid(int locality) +{ + return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID); +} + +static inline int tis_wait_valid_data(int locality) +{ + const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; + return tis_wait_sts(locality, has_data, has_data); +} + +static inline int tis_has_valid_data(int locality) +{ + const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; + return (tpm_read_status(locality) & has_data) == has_data; +} + +static inline int tis_expect_data(int locality) +{ + return !!(tpm_read_status(locality) & TIS_STS_EXPECT); +} + +/* + * tis_wait_access() + * + * Wait for at least a second for a access to change its state to match the + * expected state. Normally the transition happens within microseconds. + * + * @locality - locality + * @mask - bitmask for the bitfield(s) to watch + * @expected - value the field(s) are supposed to be set to + * + * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. + */ +static int tis_wait_access(int locality, u8 mask, u8 expected) +{ + u32 time_us = MAX_DELAY_US; + while (time_us > 0) { + u8 value = tpm_read_access(locality); + if ((value & mask) == expected) + return 0; + udelay(1); /* 1 us */ + time_us--; + } + return TPM_TIMEOUT_ERR; +} + +static inline int tis_wait_dropped_access(int locality) +{ + return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0); +} + +static inline int tis_wait_received_access(int locality) +{ + return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, + TIS_ACCESS_ACTIVE_LOCALITY); +} + +static inline int tis_has_access(int locality) +{ + return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY); +} + +static inline void tis_request_access(int locality) +{ + tpm_write_access(TIS_ACCESS_REQUEST_USE, locality); +} + +static inline void tis_drop_access(int locality) +{ + tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality); +} + /* * PC Client Specific TPM Interface Specification section 11.2.12: * @@ -244,23 +352,19 @@ static int tis_command_ready(u8 locality) u32 status; /* 1st attempt to set command ready */ - tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS); + tpm_write_status(TIS_STS_COMMAND_READY, locality); /* Wait for response */ - status = tpm_read(locality, TIS_REG_STS); + status = tpm_read_status(locality); /* Check if command ready is set yet */ if (status & TIS_STS_COMMAND_READY) return 0; /* 2nd attempt to set command ready */ - tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS); + tpm_write_status(TIS_STS_COMMAND_READY, locality); - /* Wait for command ready to get set */ - status = tis_wait_reg(TIS_REG_STS, locality, - TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); - - return (status == TPM_TIMEOUT_ERR) ? TPM_TIMEOUT_ERR : 0; + return tis_wait_ready(locality); } /* @@ -278,16 +382,16 @@ static u32 tis_probe(void) u16 vid, did; int i; - if (vendor_dev_id) + if (car_get_var(vendor_dev_id)) return 0; /* Already probed. */ - didvid = tpm_read(0, TIS_REG_DID_VID); + didvid = tpm_read_did_vid(0); if (!didvid || (didvid == 0xffffffff)) { printf("%s: No TPM device found\n", __FUNCTION__); return TPM_DRIVER_ERR; } - vendor_dev_id = didvid; + car_set_var(vendor_dev_id, didvid); vid = didvid & 0xffff; did = (didvid >> 16) & 0xffff; @@ -331,16 +435,13 @@ static u32 tis_senddata(const u8 * const data, u32 len) u16 burst = 0; u32 max_cycles = 0; u8 locality = 0; - u32 value; - value = tis_wait_reg(TIS_REG_STS, locality, TIS_STS_COMMAND_READY, - TIS_STS_COMMAND_READY); - if (value == TPM_TIMEOUT_ERR) { + if (tis_wait_ready(locality)) { printf("%s:%d - failed to get 'command_ready' status\n", __FILE__, __LINE__); return TPM_DRIVER_ERR; } - burst = BURST_COUNT(value); + burst = tpm_read_burst_count(locality); while (1) { unsigned count; @@ -353,7 +454,7 @@ static u32 tis_senddata(const u8 * const data, u32 len) return TPM_DRIVER_ERR; } udelay(1); - burst = BURST_COUNT(tpm_read(locality, TIS_REG_STS)); + burst = tpm_read_burst_count(locality); } max_cycles = 0; @@ -369,18 +470,15 @@ static u32 tis_senddata(const u8 * const data, u32 len) */ count = min(burst, len - offset - 1); while (count--) - tpm_write(data[offset++], locality, TIS_REG_DATA_FIFO); + tpm_write_data(data[offset++], locality); - value = tis_wait_reg(TIS_REG_STS, locality, - TIS_STS_VALID, TIS_STS_VALID); - - if ((value == TPM_TIMEOUT_ERR) || !(value & TIS_STS_EXPECT)) { + if (tis_wait_valid(locality) || !tis_expect_data(locality)) { printf("%s:%d TPM command feed overflow\n", __FILE__, __LINE__); return TPM_DRIVER_ERR; } - burst = BURST_COUNT(value); + burst = tpm_read_burst_count(locality); if ((offset == (len - 1)) && burst) /* * We need to be able to send the last byte to the @@ -391,22 +489,20 @@ static u32 tis_senddata(const u8 * const data, u32 len) } /* Send the last byte. */ - tpm_write(data[offset++], locality, TIS_REG_DATA_FIFO); + tpm_write_data(data[offset++], locality); /* * Verify that TPM does not expect any more data as part of this * command. */ - value = tis_wait_reg(TIS_REG_STS, locality, - TIS_STS_VALID, TIS_STS_VALID); - if ((value == TPM_TIMEOUT_ERR) || (value & TIS_STS_EXPECT)) { + if (tis_wait_valid(locality) || tis_expect_data(locality)) { printf("%s:%d unexpected TPM status 0x%x\n", - __FILE__, __LINE__, value); + __FILE__, __LINE__, tpm_read_status(locality)); return TPM_DRIVER_ERR; } /* OK, sitting pretty, let's start the command execution. */ - tpm_write(TIS_STS_TPM_GO, locality, TIS_REG_STS); + tpm_write_status(TIS_STS_TPM_GO, locality); return 0; } @@ -426,37 +522,31 @@ static u32 tis_senddata(const u8 * const data, u32 len) static u32 tis_readresponse(u8 *buffer, size_t *len) { u16 burst_count; - u32 status; u32 offset = 0; u8 locality = 0; - const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; u32 expected_count = *len; int max_cycles = 0; /* Wait for the TPM to process the command */ - status = tis_wait_reg(TIS_REG_STS, locality, has_data, has_data); - if (status == TPM_TIMEOUT_ERR) { - printf("%s:%d failed processing command\n", - __FILE__, __LINE__); + if (tis_wait_valid_data(locality)) { + printf("%s:%d failed processing command\n", __FILE__, __LINE__); return TPM_DRIVER_ERR; } do { - while ((burst_count = BURST_COUNT(status)) == 0) { + while ((burst_count = tpm_read_burst_count(locality)) == 0) { if (max_cycles++ == MAX_DELAY_US) { printf("%s:%d TPM stuck on read\n", __FILE__, __LINE__); return TPM_DRIVER_ERR; } udelay(1); - status = tpm_read(locality, TIS_REG_STS); } max_cycles = 0; while (burst_count-- && (offset < expected_count)) { - buffer[offset++] = (u8) tpm_read(locality, - TIS_REG_DATA_FIFO); + buffer[offset++] = tpm_read_data(locality); if (offset == 6) { /* * We got the first six bytes of the reply, @@ -482,9 +572,7 @@ static u32 tis_readresponse(u8 *buffer, size_t *len) } /* Wait for the next portion */ - status = tis_wait_reg(TIS_REG_STS, locality, - TIS_STS_VALID, TIS_STS_VALID); - if (status == TPM_TIMEOUT_ERR) { + if (tis_wait_valid(locality)) { printf("%s:%d failed to read response\n", __FILE__, __LINE__); return TPM_DRIVER_ERR; @@ -493,15 +581,13 @@ static u32 tis_readresponse(u8 *buffer, size_t *len) if (offset == expected_count) break; /* We got all we need */ - } while ((status & has_data) == has_data); + } while (tis_has_valid_data(locality)); - /* - * Make sure we indeed read all there was. The TIS_STS_VALID bit is - * known to be set. - */ - if (status & TIS_STS_DATA_AVAILABLE) { - printf("%s:%d wrong receive status %x\n", - __FILE__, __LINE__, status); + /* * Make sure we indeed read all there was. */ + if (tis_has_valid_data(locality)) { + printf("%s:%d wrong receive status: %x %d bytes left\n", + __FILE__, __LINE__, tpm_read_status(locality), + tpm_read_burst_count(locality)); return TPM_DRIVER_ERR; } @@ -542,12 +628,10 @@ int tis_open(void) return TPM_DRIVER_ERR; /* now request access to locality */ - tpm_write(TIS_ACCESS_REQUEST_USE, locality, TIS_REG_ACCESS); + tis_request_access(locality); /* did we get a lock? */ - if (tis_wait_reg(TIS_REG_ACCESS, locality, - TIS_ACCESS_ACTIVE_LOCALITY, - TIS_ACCESS_ACTIVE_LOCALITY) == TPM_TIMEOUT_ERR) { + if (tis_wait_received_access(locality)) { printf("%s:%d - failed to lock locality %d\n", __FILE__, __LINE__, locality); return TPM_DRIVER_ERR; @@ -572,13 +656,9 @@ int tis_open(void) int tis_close(void) { u8 locality = 0; - if (tpm_read(locality, TIS_REG_ACCESS) & - TIS_ACCESS_ACTIVE_LOCALITY) { - tpm_write(TIS_ACCESS_ACTIVE_LOCALITY, locality, TIS_REG_ACCESS); - - if (tis_wait_reg(TIS_REG_ACCESS, locality, - TIS_ACCESS_ACTIVE_LOCALITY, 0) == - TPM_TIMEOUT_ERR) { + if (tis_has_access(locality)) { + tis_drop_access(locality); + if (tis_wait_dropped_access(locality)) { printf("%s:%d - failed to release locality %d\n", __FILE__, __LINE__, locality); return TPM_DRIVER_ERR; @@ -611,3 +691,92 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, return tis_readresponse(recvbuf, recv_len); } + +#ifdef __RAMSTAGE__ + +/* + * tis_setup_interrupt() + * + * Set up the interrupt vector and polarity for locality 0 and + * disable all interrupts so they are unused in firmware but can + * be enabled by the OS. + * + * The values used here must match what is passed in the TPM ACPI + * device if ACPI is used on the platform. + * + * @vector - TPM interrupt vector + * @polarity - TPM interrupt polarity + * + * Returns 0 on success, TPM_DRIVER_ERR on failure. + */ +static int tis_setup_interrupt(int vector, int polarity) +{ + u8 locality = 0; + int has_access = tis_has_access(locality); + + /* Open connection and request access if not already granted */ + if (!has_access && tis_open() < 0) + return TPM_DRIVER_ERR; + + /* Set TPM interrupt vector */ + tpm_write_int_vector(vector, locality); + + /* Set TPM interupt polarity and disable interrupts */ + tpm_write_int_polarity(polarity, locality); + + /* Close connection if it was opened */ + if (!has_access && tis_close() < 0) + return TPM_DRIVER_ERR; + + return 0; +} + +static void lpc_tpm_read_resources(struct device *dev) +{ + /* Static 5K memory region specified in Kconfig */ + mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10); +} + +static void lpc_tpm_set_resources(struct device *dev) +{ + tpm_config_t *config = (tpm_config_t *)dev->chip_info; + struct resource *res; + + for (res = dev->resource_list; res; res = res->next) { + if (!(res->flags & IORESOURCE_ASSIGNED)) + continue; + + if (res->flags & IORESOURCE_IRQ) { + /* Set interrupt vector */ + tis_setup_interrupt((int)res->base, + config->irq_polarity); + } else { + continue; + } + + res->flags |= IORESOURCE_STORED; + report_resource_stored(dev, res, " "); + } +} + +static struct device_operations lpc_tpm_ops = { + .read_resources = &lpc_tpm_read_resources, + .set_resources = &lpc_tpm_set_resources, +}; + +static struct pnp_info pnp_dev_info[] = { + { .flags = PNP_IRQ0 } +}; + +static void enable_dev(struct device *dev) +{ + pnp_enable_devices(dev, &lpc_tpm_ops, + ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations drivers_pc80_tpm_ops = { + CHIP_NAME("LPC TPM") + .enable_dev = enable_dev +}; + +#endif /* __RAMSTAGE__ */ diff --git a/src/drivers/pc80/udelay_io.c b/src/drivers/pc80/udelay_io.c index 37f3f73186..48ff32c944 100644 --- a/src/drivers/pc80/udelay_io.c +++ b/src/drivers/pc80/udelay_io.c @@ -1,6 +1,10 @@ #include #include +void init_timer(void) +{ +} + void udelay(unsigned usecs) { int i; diff --git a/src/drivers/spi/Kconfig b/src/drivers/spi/Kconfig index a99199ab76..2032319ebc 100644 --- a/src/drivers/spi/Kconfig +++ b/src/drivers/spi/Kconfig @@ -24,6 +24,23 @@ config SPI_FLASH Select this option if your chipset driver needs to store certain data in the SPI flash. +config SPI_ATOMIC_SEQUENCING + bool + default y if ARCH_X86 + default n if !ARCH_X86 + help + Select this option if the SPI controller uses "atomic sequencing." + Atomic sequencing is when the sequence of commands is pre-programmed + in the SPI controller. Hardware manages the transaction instead of + software. This is common on x86 platforms. + +config SPI_FLASH_MEMORY_MAPPED + bool + default y if ARCH_X86 + default n if !ARCH_X86 + help + Inform system if SPI is memory-mapped or not. + config SPI_FLASH_SMM bool "SPI flash driver support in SMM" default n @@ -33,7 +50,7 @@ config SPI_FLASH_SMM config SPI_FLASH_EON bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -41,7 +58,7 @@ config SPI_FLASH_EON config SPI_FLASH_MACRONIX bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -49,7 +66,7 @@ config SPI_FLASH_MACRONIX config SPI_FLASH_SPANSION bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -57,7 +74,7 @@ config SPI_FLASH_SPANSION config SPI_FLASH_SST bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -65,7 +82,7 @@ config SPI_FLASH_SST config SPI_FLASH_STMICRO bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -73,7 +90,7 @@ config SPI_FLASH_STMICRO config SPI_FLASH_WINBOND bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain @@ -89,8 +106,17 @@ config SPI_FLASH_NO_FAST_READ config SPI_FLASH_GIGADEVICE bool - default y + default y if !COMMON_CBFS_SPI_WRAPPER depends on SPI_FLASH help Select this option if your chipset driver needs to store certain data in the SPI flash and your SPI flash is made by Gigadevice. + +config SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B + bool + default n + depends on SPI_FLASH + help + Select this option if your SPI flash supports the fast read dual- + output command (opcode 0x3b) where the opcode and address are sent + to the chip on MOSI and data is received on both MOSI and MISO. diff --git a/src/drivers/spi/Makefile.inc b/src/drivers/spi/Makefile.inc index 1a34ab54cf..1319ae27ea 100644 --- a/src/drivers/spi/Makefile.inc +++ b/src/drivers/spi/Makefile.inc @@ -1,4 +1,38 @@ # SPI flash driver interface + +ifeq ($(CONFIG_COMMON_CBFS_SPI_WRAPPER),y) +bootblock-y += spi_flash.c +bootblock-$(CONFIG_SPI_FLASH_EON) += eon.c +bootblock-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c +bootblock-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c +bootblock-$(CONFIG_SPI_FLASH_SPANSION) += spansion.c +bootblock-$(CONFIG_SPI_FLASH_SST) += sst.c +bootblock-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c +bootblock-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c +bootblock-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c + +romstage-$(CONFIG_SPI_FLASH) += spi_flash.c +romstage-$(CONFIG_SPI_FLASH_EON) += eon.c +romstage-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c +romstage-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c +romstage-$(CONFIG_SPI_FLASH_SPANSION) += spansion.c +romstage-$(CONFIG_SPI_FLASH_SST) += sst.c +romstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c +romstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c +romstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c + +verstage-$(CONFIG_SPI_FLASH) += spi_flash.c +verstage-$(CONFIG_SPI_FLASH_EON) += eon.c +verstage-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c +verstage-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c +verstage-$(CONFIG_SPI_FLASH_SPANSION) += spansion.c +verstage-$(CONFIG_SPI_FLASH_SST) += sst.c +verstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c +verstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c +verstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c + +endif + ramstage-$(CONFIG_SPI_FLASH) += spi_flash.c # drivers diff --git a/src/drivers/spi/eon.c b/src/drivers/spi/eon.c index 21103ae221..4fa093aafa 100644 --- a/src/drivers/spi/eon.c +++ b/src/drivers/spi/eon.c @@ -1,5 +1,7 @@ /* * (C) Copyright 2010, ucRobotics Inc. + * Copyright (c) 2014, Sage Electronic Engineering, LLC + * . * Author: Chong Huang * Licensed under the GPL-2 or later. */ @@ -8,23 +10,24 @@ #include #include "spi_flash_internal.h" -/* EN25Q128-specific commands */ -#define CMD_EN25Q128_WREN 0x06 /* Write Enable */ -#define CMD_EN25Q128_WRDI 0x04 /* Write Disable */ -#define CMD_EN25Q128_RDSR 0x05 /* Read Status Register */ -#define CMD_EN25Q128_WRSR 0x01 /* Write Status Register */ -#define CMD_EN25Q128_READ 0x03 /* Read Data Bytes */ -#define CMD_EN25Q128_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ -#define CMD_EN25Q128_PP 0x02 /* Page Program */ -#define CMD_EN25Q128_SE 0x20 /* Sector Erase */ -#define CMD_EN25Q128_BE 0xd8 /* Block Erase */ -#define CMD_EN25Q128_DP 0xb9 /* Deep Power-down */ -#define CMD_EN25Q128_RES 0xab /* Release from DP, and Read Signature */ +/* EN25*-specific commands */ +#define CMD_EN25_WREN 0x06 /* Write Enable */ +#define CMD_EN25_WRDI 0x04 /* Write Disable */ +#define CMD_EN25_RDSR 0x05 /* Read Status Register */ +#define CMD_EN25_WRSR 0x01 /* Write Status Register */ +#define CMD_EN25_READ 0x03 /* Read Data Bytes */ +#define CMD_EN25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define CMD_EN25_PP 0x02 /* Page Program */ +#define CMD_EN25_SE 0x20 /* Sector Erase */ +#define CMD_EN25_BE 0xd8 /* Block Erase */ +#define CMD_EN25_DP 0xb9 /* Deep Power-down */ +#define CMD_EN25_RES 0xab /* Release from DP, and Read Signature */ -#define EON_ID_EN25Q128 0x18 +#define EON_ID_EN25Q128 0x3018 +#define EON_ID_EN25S64 0x3817 struct eon_spi_flash_params { - u8 idcode1; + u16 id; u16 page_size; u16 pages_per_sector; u16 sectors_per_block; @@ -45,46 +48,51 @@ static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash) static const struct eon_spi_flash_params eon_spi_flash_table[] = { { - .idcode1 = EON_ID_EN25Q128, + .id = EON_ID_EN25Q128, .page_size = 256, .pages_per_sector = 16, .sectors_per_block = 16, .nr_sectors = 4096, .name = "EN25Q128", }, + { + .id = EON_ID_EN25S64, + .page_size = 256, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_sectors = 2048, + .name = "EN25S64", + }, }; static int eon_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { struct eon_spi_flash *eon = to_eon_spi_flash(flash); - unsigned long page_addr; unsigned long byte_addr; unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; - page_size = eon->params->page_size; - page_addr = offset / page_size; + page_size = min(eon->params->page_size, CONTROLLER_PAGE_LIMIT); byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } - ret = 0; for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); + ret = spi_flash_cmd(flash->spi, CMD_EN25_WREN, NULL, 0); + if (ret < 0) { + printk(BIOS_WARNING, "SF: Enabling Write failed\n"); + goto out; + } - cmd[0] = CMD_EN25Q128_PP; - cmd[1] = page_addr >> 8; - cmd[2] = page_addr; - cmd[3] = byte_addr; + cmd[0] = CMD_EN25_PP; + cmd[1] = (offset >> 16) & 0xff; + cmd[2] = (offset >> 8) & 0xff; + cmd[3] = offset & 0xff; #if CONFIG_DEBUG_SPI_FLASH printk(BIOS_SPEW, @@ -92,39 +100,35 @@ static int eon_write(struct spi_flash *flash, buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); #endif - ret = spi_flash_cmd(flash->spi, CMD_EN25Q128_WREN, NULL, 0); - if (ret < 0) { - printk(BIOS_WARNING, "SF: Enabling Write failed\n"); - break; - } - ret = spi_flash_cmd_write(flash->spi, cmd, 4, buf + actual, chunk_len); if (ret < 0) { printk(BIOS_WARNING, "SF: EON Page Program failed\n"); - break; + goto out; } ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); - if (ret) - break; + if (ret) { + printk(BIOS_WARNING, "SF: EON Page Program timeout\n"); + goto out; + } - page_addr++; + offset += chunk_len; byte_addr = 0; } #if CONFIG_DEBUG_SPI_FLASH - printk(BIOS_SPEW, "SF: EON: Successfully programmed %zu bytes @ 0x%x\n", - len, offset); + printk(BIOS_SPEW, "SF: EON: Successfully programmed %zu bytes @ %#x\n", + len, (unsigned int)(offset - len)); #endif - spi_release_bus(flash->spi); +out: return ret; } static int eon_erase(struct spi_flash *flash, u32 offset, size_t len) { - return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len); + return spi_flash_cmd_erase(flash, CMD_EN25_SE, offset, len); } struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) @@ -135,12 +139,13 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) { params = &eon_spi_flash_table[i]; - if (params->idcode1 == idcode[2]) + if (params->id == ((idcode[1] << 8) | idcode[2])) break; } if (i == ARRAY_SIZE(eon_spi_flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported EON ID %02x\n", idcode[1]); + printk(BIOS_WARNING, "SF: Unsupported EON ID %#02x%02x\n", + idcode[1], idcode[2]); return NULL; } @@ -157,8 +162,7 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) eon->flash.write = eon_write; eon->flash.erase = eon_erase; eon->flash.read = spi_flash_cmd_read_fast; - eon->flash.sector_size = params->page_size * params->pages_per_sector - * params->sectors_per_block; + eon->flash.sector_size = params->page_size * params->pages_per_sector; eon->flash.size = params->page_size * params->pages_per_sector * params->nr_sectors; diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c index 5a8f82f053..ad5d470e91 100644 --- a/src/drivers/spi/gigadevice.c +++ b/src/drivers/spi/gigadevice.c @@ -105,7 +105,15 @@ static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = { .pages_per_sector = 16, .sectors_per_block = 16, .nr_blocks = 128, - .name = "GD25Q64(B)", + .name = "GD25Q64B/GD25B64C", + }, + { + .id = 0x6017, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "GD25LQ64C/GD25LB64C", }, { .id = 0x4018, @@ -125,19 +133,13 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset, unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; page_size = min(1 << stm->params->l2_page_size, CONTROLLER_PAGE_LIMIT); byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, - "SF gigadevice.c: Unable to claim SPI bus\n"); - return ret; - } for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); @@ -185,7 +187,6 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset, ret = 0; out: - spi_release_bus(flash->spi); return ret; } @@ -194,11 +195,12 @@ static int gigadevice_erase(struct spi_flash *flash, u32 offset, size_t len) return spi_flash_cmd_erase(flash, CMD_GD25_SE, offset, len); } +static struct gigadevice_spi_flash stm; + struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) { const struct gigadevice_spi_flash_params *params; unsigned page_size; - struct gigadevice_spi_flash *stm; unsigned int i; for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) { @@ -214,32 +216,25 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) return NULL; } - stm = malloc(sizeof(struct gigadevice_spi_flash)); - if (!stm) { - printk(BIOS_WARNING, - "SF gigadevice.c: Failed to allocate memory\n"); - return NULL; - } - - stm->params = params; - stm->flash.spi = spi; - stm->flash.name = params->name; + stm.params = params; + stm.flash.spi = spi; + stm.flash.name = params->name; /* Assuming power-of-two page size initially. */ page_size = 1 << params->l2_page_size; - stm->flash.write = gigadevice_write; - stm->flash.erase = gigadevice_erase; + stm.flash.write = gigadevice_write; + stm.flash.erase = gigadevice_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ - stm->flash.read = spi_flash_cmd_read_slow; + stm.flash.read = spi_flash_cmd_read_slow; #else - stm->flash.read = spi_flash_cmd_read_fast; + stm.flash.read = spi_flash_cmd_read_fast; #endif - stm->flash.sector_size = (1 << stm->params->l2_page_size) * - stm->params->pages_per_sector; - stm->flash.size = page_size * params->pages_per_sector + stm.flash.sector_size = (1 << stm.params->l2_page_size) * + stm.params->pages_per_sector; + stm.flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; - return &stm->flash; + return &stm.flash; } diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c index bbc3704656..de8bb946a3 100644 --- a/src/drivers/spi/macronix.c +++ b/src/drivers/spi/macronix.c @@ -118,6 +118,14 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = { .nr_blocks = 256, .name = "MX25L12855E", }, + { + .idcode = 0x2537, + .page_size = 256, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "MX25U6435F", + }, }; static int macronix_write(struct spi_flash *flash, @@ -128,20 +136,14 @@ static int macronix_write(struct spi_flash *flash, unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; page_size = min(mcx->params->page_size, CONTROLLER_PAGE_LIMIT); byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } - ret = 0; for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); @@ -182,7 +184,6 @@ static int macronix_write(struct spi_flash *flash, " 0x%lx\n", len, (unsigned long)(offset - len)); #endif - spi_release_bus(flash->spi); return ret; } diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c index 6dd6df921a..23b62c98d3 100644 --- a/src/drivers/spi/spansion.c +++ b/src/drivers/spi/spansion.c @@ -43,18 +43,25 @@ #define CMD_S25FLXX_DP 0xb9 /* Deep Power-down */ #define CMD_S25FLXX_RES 0xab /* Release from DP, and Read Signature */ +#define SPSN_MANUFACTURER_ID_S25FL116K 0x01 #define SPSN_ID_S25FL008A 0x0213 #define SPSN_ID_S25FL016A 0x0214 #define SPSN_ID_S25FL032A 0x0215 #define SPSN_ID_S25FL064A 0x0216 +#define SPSN_ID_S25FL128S 0x0219 #define SPSN_ID_S25FL128P 0x2018 +#define SPSN_ID_S25FL116K 0x4015 #define SPSN_EXT_ID_S25FL128P_256KB 0x0300 #define SPSN_EXT_ID_S25FL128P_64KB 0x0301 #define SPSN_EXT_ID_S25FL032P 0x4d00 +#define SPSN_EXT_ID_S25FLXXS_64KB 0x4d01 struct spansion_spi_flash_params { + u8 idcode0; u16 idcode1; u16 idcode2; + int (*identify) (const struct spansion_spi_flash_params *params, + u8 *idcode); u16 page_size; u16 pages_per_sector; u16 nr_sectors; @@ -72,63 +79,130 @@ static inline struct spansion_spi_flash *to_spansion_spi_flash(struct spi_flash return container_of(flash, struct spansion_spi_flash, flash); } +/* + * returns non-zero if the given idcode matches the ID of the chip. this is for + * chips which use 2nd, 3rd, 4th, and 5th byte. + */ +static int identify_2345(const struct spansion_spi_flash_params *params, + u8 *idcode) +{ + u16 jedec = idcode[1] << 8 | idcode[2]; + u16 ext_jedec = idcode[3] << 8 | idcode[4]; + return (params->idcode1 == jedec) && (params->idcode2 == ext_jedec); +} + +/* + * returns non-zero if the given idcode matches the ID of the chip. this is for + * chips which use 1st, 2nd, and 3rd byte. + */ +static int identify_123(const struct spansion_spi_flash_params *params, + u8 *idcode) +{ + u16 jedec = idcode[1] << 8 | idcode[2]; + return (params->idcode0 == idcode[0]) && (params->idcode1 == jedec); +} + static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL008A, .idcode2 = 0, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 16, .name = "S25FL008A", }, { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL016A, .idcode2 = 0, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 32, .name = "S25FL016A", }, { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL032A, .idcode2 = 0, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 64, .name = "S25FL032A", }, { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL064A, .idcode2 = 0, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 128, .name = "S25FL064A", }, { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL128P, .idcode2 = SPSN_EXT_ID_S25FL128P_64KB, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 256, .name = "S25FL128P_64K", }, { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL128P, .idcode2 = SPSN_EXT_ID_S25FL128P_256KB, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 1024, .nr_sectors = 64, .name = "S25FL128P_256K", }, { + .idcode0 = 0, + .idcode1 = SPSN_ID_S25FL128S, + .idcode2 = SPSN_EXT_ID_S25FLXXS_64KB, + .identify = identify_2345, + .page_size = 256, + .pages_per_sector = 256, + .nr_sectors = 512, + .name = "S25FL128S_256K", + }, + { + .idcode0 = 0, .idcode1 = SPSN_ID_S25FL032A, .idcode2 = SPSN_EXT_ID_S25FL032P, + .identify = identify_2345, .page_size = 256, .pages_per_sector = 256, .nr_sectors = 64, .name = "S25FL032P", }, + { + .idcode0 = 0, + .idcode1 = SPSN_ID_S25FL128P, + .idcode2 = SPSN_EXT_ID_S25FLXXS_64KB, + .identify = identify_2345, + .page_size = 256, + .pages_per_sector = 256, + .nr_sectors = 256, + .name = "25FS128S", + }, + { + .idcode0 = SPSN_MANUFACTURER_ID_S25FL116K, + .idcode1 = SPSN_ID_S25FL116K, + .idcode2 = 0, + .identify = identify_123, + .page_size = 256, + .pages_per_sector = 256, + .nr_sectors = 32, + .name = "S25FL116K_16M", + }, }; static int spansion_write(struct spi_flash *flash, @@ -140,7 +214,7 @@ static int spansion_write(struct spi_flash *flash, unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; page_size = spsn->params->page_size; @@ -148,13 +222,7 @@ static int spansion_write(struct spi_flash *flash, byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } - ret = 0; for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); @@ -195,7 +263,6 @@ static int spansion_write(struct spi_flash *flash, len, offset); #endif - spi_release_bus(flash->spi); return ret; } @@ -204,34 +271,28 @@ static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len); } +static struct spansion_spi_flash spsn_flash; + struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) { const struct spansion_spi_flash_params *params; struct spansion_spi_flash *spsn; unsigned int i; - unsigned short jedec, ext_jedec; - - jedec = idcode[1] << 8 | idcode[2]; - ext_jedec = idcode[3] << 8 | idcode[4]; for (i = 0; i < ARRAY_SIZE(spansion_spi_flash_table); i++) { params = &spansion_spi_flash_table[i]; - if (params->idcode1 == jedec) { - if (params->idcode2 == ext_jedec) - break; - } + if (params->identify(params, idcode)) + break; } if (i == ARRAY_SIZE(spansion_spi_flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported SPANSION ID %04x %04x\n", jedec, ext_jedec); + printk(BIOS_WARNING, + "SF: Unsupported SPANSION ID %02x %02x %02x %02x %02x\n", + idcode[0], idcode[1], idcode[2], idcode[3], idcode[4]); return NULL; } - spsn = malloc(sizeof(struct spansion_spi_flash)); - if (!spsn) { - printk(BIOS_WARNING, "SF: Failed to allocate memory\n"); - return NULL; - } + spsn = &spsn_flash; spsn->params = params; spsn->flash.spi = spi; @@ -239,7 +300,7 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) spsn->flash.write = spansion_write; spsn->flash.erase = spansion_erase; - spsn->flash.read = spi_flash_cmd_read_fast; + spsn->flash.read = spi_flash_cmd_read_slow; spsn->flash.sector_size = params->page_size * params->pages_per_sector; spsn->flash.size = spsn->flash.sector_size * params->nr_sectors; diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index d1a95046db..1bcad9bf29 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -25,19 +25,64 @@ static void spi_flash_addr(u32 addr, u8 *cmd) cmd[3] = addr >> 0; } +/* + * If atomic sequencing is used, the cycle type is known to the SPI + * controller so that it can perform consecutive transfers and arbitrate + * automatically. Otherwise the SPI controller transfers whatever the + * user requests immediately, without regard to sequence. Atomic + * sequencing is commonly used on x86 platforms. + * + * SPI flash commands are simple two-step sequences. The command byte is + * always written first and may be followed by an address. Then data is + * either read or written. For atomic sequencing we'll pass everything into + * spi_xfer() at once and let the controller handle the details. Otherwise + * we will write all output bytes first and then read if necessary. + * + * FIXME: This really should be abstracted better, but that will + * require overhauling the entire SPI infrastructure. + */ +static int do_spi_flash_cmd(struct spi_slave *spi, const void *dout, + unsigned int bytes_out, void *din, unsigned int bytes_in) +{ + int ret = 1; + + if (spi_claim_bus(spi)) + return ret; + +#if CONFIG_SPI_ATOMIC_SEQUENCING == 1 + if (spi_xfer(spi, dout, bytes_out, din, bytes_in) < 0) + goto done; +#else + if (dout && bytes_out) { + if (spi_xfer(spi, dout, bytes_out, NULL, 0) < 0) + goto done; + } + + if (din && bytes_in) { + if (spi_xfer(spi, NULL, 0, din, bytes_in) < 0) + goto done; + } +#endif + + ret = 0; +done: + spi_release_bus(spi); + return ret; +} + int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len) { - int ret = spi_xfer(spi, &cmd, 8, response, len * 8); + int ret = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len); if (ret) printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret); return ret; } -int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len) +static int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, + size_t cmd_len, void *data, size_t data_len) { - int ret = spi_xfer(spi, cmd, cmd_len * 8, data, data_len * 8); + int ret = do_spi_flash_cmd(spi, cmd, cmd_len, data, data_len); if (ret) { printk(BIOS_WARNING, "SF: Failed to send read command (%zu bytes): %d\n", data_len, ret); @@ -46,6 +91,9 @@ int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, return ret; } +/* TODO: This code is quite possibly broken and overflowing stacks. Fix ASAP! */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstack-usage=" int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len) { @@ -54,7 +102,7 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, memcpy(buff, cmd, cmd_len); memcpy(buff + cmd_len, data, data_len); - ret = spi_xfer(spi, buff, (cmd_len + data_len) * 8, NULL, 0); + ret = do_spi_flash_cmd(spi, buff, cmd_len + data_len, NULL, 0); if (ret) { printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n", data_len, ret); @@ -62,44 +110,53 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, return ret; } +#pragma GCC diagnostic pop -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len) +static int spi_flash_cmd_read_array(struct spi_slave *spi, u8 *cmd, + size_t cmd_len, u32 offset, + size_t len, void *data) { - struct spi_slave *spi = flash->spi; - int ret; + while (len) { + size_t transfer_size; - spi->rw = SPI_READ_FLAG; - spi_claim_bus(spi); - ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); - spi_release_bus(spi); + if (spi->max_transfer_size) + transfer_size = min(len, spi->max_transfer_size); + else + transfer_size = len; - return ret; + spi_flash_addr(offset, cmd); + + if (spi_flash_cmd_read(spi, cmd, cmd_len, data, transfer_size)) + break; + + offset += transfer_size; + data = (void *)((uintptr_t)data + transfer_size); + len -= transfer_size; + } + + return len != 0; } int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *data) { - struct spi_slave *spi = flash->spi; u8 cmd[5]; cmd[0] = CMD_READ_ARRAY_FAST; - spi_flash_addr(offset, cmd); cmd[4] = 0x00; - return spi_flash_cmd_read(spi, cmd, sizeof(cmd), data, len); + return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd), + offset, len, data); } int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset, - size_t len, void *data) + size_t len, void *data) { - struct spi_slave *spi = flash->spi; u8 cmd[4]; cmd[0] = CMD_READ_ARRAY_SLOW; - spi_flash_addr(offset, cmd); - - return spi_flash_cmd_read(spi, cmd, sizeof(cmd), data, len); + return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd), + offset, len, data); } int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, @@ -150,11 +207,6 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, } flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } cmd[0] = erase_cmd; start = offset; @@ -184,7 +236,6 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, printk(BIOS_DEBUG, "SF: Successfully erased %zu bytes @ %#x\n", len, start); out: - spi_release_bus(flash->spi); return ret; } @@ -246,26 +297,20 @@ static struct { }; #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN) -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode) +struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs) { struct spi_slave *spi; struct spi_flash *flash = NULL; int ret, i, shift; u8 idcode[IDCODE_LEN], *idp; - spi = spi_setup_slave(bus, cs, max_hz, spi_mode); + spi = spi_setup_slave(bus, cs); if (!spi) { printk(BIOS_WARNING, "SF: Failed to set up slave\n"); return NULL; } spi->rw = SPI_READ_FLAG; - ret = spi_claim_bus(spi); - if (ret) { - printk(BIOS_WARNING, "SF: Failed to claim SPI bus: %d\n", ret); - goto err_claim_bus; - } /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); @@ -273,7 +318,10 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_read_id; #if CONFIG_DEBUG_SPI_FLASH - printk(BIOS_SPEW, "SF: Got idcodes\n"); + printk(BIOS_SPEW, "SF: Got idcode: "); + for (i = 0; i < sizeof(idcode); i++) + printk(BIOS_SPEW, "%02x ", idcode[i]); + printk(BIOS_SPEW, "\n"); #endif /* count the number of continuation bytes */ @@ -311,13 +359,9 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, printk(BIOS_INFO, "SF: Detected %s with page size %x, total %x\n", flash->name, flash->sector_size, flash->size); - spi_release_bus(spi); - return flash; err_manufacturer_probe: err_read_id: - spi_release_bus(spi); -err_claim_bus: return NULL; } diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h index 37ffee64f8..94b66a60e7 100644 --- a/src/drivers/spi/spi_flash_internal.h +++ b/src/drivers/spi/spi_flash_internal.h @@ -29,13 +29,6 @@ /* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); -/* - * Send a multi-byte command to the device and read the response. Used - * for flash array reads, etc. - */ -int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len); - int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *data); @@ -49,13 +42,6 @@ int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset, int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len); -/* - * Same as spi_flash_cmd_read() except it also claims/releases the SPI - * bus. Used as common part of the ->read() operation. - */ -int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, - size_t cmd_len, void *data, size_t data_len); - /* Send a command to the device and wait for some bit to clear itself. */ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, u8 cmd, u8 poll_bit); diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c index 8cf3f964fd..a09f4e9c4e 100644 --- a/src/drivers/spi/sst.c +++ b/src/drivers/spi/sst.c @@ -150,15 +150,10 @@ static int sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { size_t actual, cmd_len; - int ret; + int ret = 0; u8 cmd[4]; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } /* If the data is not word aligned, write out leading single byte */ actual = offset % 2; @@ -213,7 +208,6 @@ done: printk(BIOS_SPEW, "SF: SST: program %s %zu bytes @ 0x%lx\n", ret ? "failure" : "success", len, (unsigned long)offset - actual); #endif - spi_release_bus(flash->spi); return ret; } diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c index 9aa31cf402..bc4d581e2f 100644 --- a/src/drivers/spi/stmicro.c +++ b/src/drivers/spi/stmicro.c @@ -141,7 +141,7 @@ static int stmicro_write(struct spi_flash *flash, unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; page_size = stm->params->page_size; @@ -149,13 +149,7 @@ static int stmicro_write(struct spi_flash *flash, byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } - ret = 0; for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); @@ -196,7 +190,6 @@ static int stmicro_write(struct spi_flash *flash, len, offset); #endif - spi_release_bus(flash->spi); return ret; } diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index c44afea832..a0abeb4ef0 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -85,6 +85,14 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .nr_blocks = 64, .name = "W25Q32", }, + { + .id = 0x6016, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 64, + .name = "W25Q32DW", + }, { .id = 0x4017, .l2_page_size = 8, @@ -93,6 +101,14 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .nr_blocks = 128, .name = "W25Q64", }, + { + .id = 0x6017, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "W25Q64DW", + }, { .id = 0x4018, .l2_page_size = 8, @@ -111,18 +127,13 @@ static int winbond_write(struct spi_flash *flash, unsigned long page_size; size_t chunk_len; size_t actual; - int ret; + int ret = 0; u8 cmd[4]; page_size = min(1 << stm->params->l2_page_size, CONTROLLER_PAGE_LIMIT); byte_addr = offset % page_size; flash->spi->rw = SPI_WRITE_FLAG; - ret = spi_claim_bus(flash->spi); - if (ret) { - printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n"); - return ret; - } for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); @@ -165,7 +176,6 @@ static int winbond_write(struct spi_flash *flash, ret = 0; out: - spi_release_bus(flash->spi); return ret; } @@ -174,11 +184,12 @@ static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len); } +static struct winbond_spi_flash stm; + struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) { const struct winbond_spi_flash_params *params; unsigned page_size; - struct winbond_spi_flash *stm; unsigned int i; for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { @@ -193,31 +204,25 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) return NULL; } - stm = malloc(sizeof(struct winbond_spi_flash)); - if (!stm) { - printk(BIOS_WARNING, "SF: Failed to allocate memory\n"); - return NULL; - } - - stm->params = params; - stm->flash.spi = spi; - stm->flash.name = params->name; + stm.params = params; + stm.flash.spi = spi; + stm.flash.name = params->name; /* Assuming power-of-two page size initially. */ page_size = 1 << params->l2_page_size; - stm->flash.write = winbond_write; - stm->flash.erase = winbond_erase; + stm.flash.write = winbond_write; + stm.flash.erase = winbond_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ - stm->flash.read = spi_flash_cmd_read_slow; + stm.flash.read = spi_flash_cmd_read_slow; #else - stm->flash.read = spi_flash_cmd_read_fast; + stm.flash.read = spi_flash_cmd_read_fast; #endif - stm->flash.sector_size = (1 << stm->params->l2_page_size) * - stm->params->pages_per_sector; - stm->flash.size = page_size * params->pages_per_sector + stm.flash.sector_size = (1 << stm.params->l2_page_size) * + stm.params->pages_per_sector; + stm.flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; - return &stm->flash; + return &stm.flash; } diff --git a/src/drivers/ti/Kconfig b/src/drivers/ti/Kconfig new file mode 100644 index 0000000000..42ead039be --- /dev/null +++ b/src/drivers/ti/Kconfig @@ -0,0 +1,21 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 The Chromium OS Authors. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +source src/drivers/ti/tps65090/Kconfig +source src/drivers/ti/tps65913/Kconfig diff --git a/src/drivers/ti/Makefile.inc b/src/drivers/ti/Makefile.inc new file mode 100644 index 0000000000..037da94f58 --- /dev/null +++ b/src/drivers/ti/Makefile.inc @@ -0,0 +1,22 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 The Chromium OS Authors. +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-$(CONFIG_DRIVER_TI_TPS65090) += tps65090/ +subdirs-$(CONFIG_DRIVERS_TI_TPS65913) += tps65913/ diff --git a/src/drivers/ti/tps65090/Kconfig b/src/drivers/ti/tps65090/Kconfig new file mode 100644 index 0000000000..feae160635 --- /dev/null +++ b/src/drivers/ti/tps65090/Kconfig @@ -0,0 +1,24 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config DRIVER_TI_TPS65090 + bool + default n + help + TI TPS65090 diff --git a/src/drivers/ti/tps65090/Makefile.inc b/src/drivers/ti/tps65090/Makefile.inc new file mode 100644 index 0000000000..10b4dd964a --- /dev/null +++ b/src/drivers/ti/tps65090/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 The ChromiumOS Authors +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_DRIVER_TI_TPS65090) += tps65090.c diff --git a/src/drivers/ti/tps65090/tps65090.c b/src/drivers/ti/tps65090/tps65090.c new file mode 100644 index 0000000000..35a050f36f --- /dev/null +++ b/src/drivers/ti/tps65090/tps65090.c @@ -0,0 +1,262 @@ +/* + * Copyright 2012, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#include +#include +#include +#include +#include "tps65090.h" + +/* TPS65090 register addresses */ +enum { + REG_CG_CTRL0 = 4, + REG_CG_STATUS1 = 0xa, +}; + +enum { + CG_CTRL0_ENC_MASK = 0x01, + + MAX_FET_NUM = 7, + MAX_CTRL_READ_TRIES = 5, + + /* TPS65090 FET_CTRL register values */ + FET_CTRL_TOFET = 1 << 7, /* Timeout, startup, overload */ + FET_CTRL_PGFET = 1 << 4, /* Power good for FET status */ + FET_CTRL_WAIT = 3 << 2, /* Overcurrent timeout max */ + FET_CTRL_ADENFET = 1 << 1, /* Enable output auto discharge */ + FET_CTRL_ENFET = 1 << 0, /* Enable FET */ +}; + +static int tps65090_i2c_write(unsigned int bus, + unsigned int reg_addr, unsigned char value) +{ + int ret; + + ret = i2c_writeb(bus, TPS65090_I2C_ADDR, reg_addr, value); + printk(BIOS_DEBUG, "%s: reg=%#x, value=%#x, ret=%d\n", + __func__, reg_addr, value, ret); + return ret; +} + +static int tps65090_i2c_read(unsigned int bus, + unsigned int reg_addr, unsigned char *value) +{ + int ret; + + printk(BIOS_DEBUG, "%s: reg=%#x, ", __func__, reg_addr); + ret = i2c_readb(bus, TPS65090_I2C_ADDR, reg_addr, value); + if (ret) + printk(BIOS_DEBUG, "fail, ret=%d\n", ret); + else + printk(BIOS_DEBUG, "value=%#x, ret=%d\n", *value, ret); + return ret; +} + +/** + * Set the power state for a FET + * + * @fet_id Fet number to set (1..MAX_FET_NUM) + * @set 1 to power on FET, 0 to power off + * @return FET_ERR_COMMS if we got a comms error, FET_ERR_NOT_READY if the + * FET failed to change state. If all is ok, returns 0. + */ +static int tps65090_fet_set(unsigned int bus, enum fet_id fet_id, int set) +{ + int retry, value; + uint8_t reg; + + value = FET_CTRL_ADENFET | FET_CTRL_WAIT; + if (set) + value |= FET_CTRL_ENFET; + + if (tps65090_i2c_write(bus, fet_id, value)) + return FET_ERR_COMMS; + /* Try reading until we get a result */ + for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) { + if (tps65090_i2c_read(bus, fet_id, ®)) + return FET_ERR_COMMS; + + /* Check that the fet went into the expected state */ + if (!!(reg & FET_CTRL_PGFET) == set) + return 0; + + /* If we got a timeout, there is no point in waiting longer */ + if (reg & FET_CTRL_TOFET) + break; + + udelay(1000); + } + + printk(BIOS_DEBUG, "FET %d: Power good should have set to %d but " + "reg=%#02x\n", fet_id, set, reg); + return FET_ERR_NOT_READY; +} + +/* FIXME(dhendrix): add timer API */ +#if 0 +int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id) +{ + int loops; + unsigned long start; + int ret = 0; + + start = get_timer(0); + for (loops = 0; ; loops++) { + ret = tps65090_fet_set(bus, fet_id, 1); + if (!ret) + break; + + if (get_timer(start) > 100) + break; + + /* Turn it off and try again until we time out */ + tps65090_fet_set(bus, fet_id, 0); + } + + if (ret) { + printk(BIOS_DEBUG, "%s: FET%d failed to power on: time=%lums, " + "loops=%d\n", __func__, fet_id, + get_timer(start), loops); + } else if (loops) { + printk(BIOS_DEBUG, "%s: FET%d powered on after %lums, " + "loops=%d\n", __func__, fet_id, + get_timer(start), loops); + } + /* + * Unfortunately, there are some conditions where the power + * good bit will be 0, but the fet still comes up. One such + * case occurs with the lcd backlight. We'll just return 0 here + * and assume that the fet will eventually come up. + */ + if (ret == FET_ERR_NOT_READY) + ret = 0; + + return ret; +} +#endif +int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id) +{ + int loops; + int ret = 0; + + for (loops = 0; loops < 100; loops++) { + ret = tps65090_fet_set(bus, fet_id, 1); + if (!ret) + break; + + /* Turn it off and try again until we time out */ + tps65090_fet_set(bus, fet_id, 0); + udelay(1000); + } + + if (ret) { + printk(BIOS_DEBUG, "%s: FET%d failed to power on\n", + __func__, fet_id); + } else if (loops) { + printk(BIOS_DEBUG, "%s: FET%d powered on\n", + __func__, fet_id); + } + /* + * Unfortunately, there are some conditions where the power + * good bit will be 0, but the fet still comes up. One such + * case occurs with the lcd backlight. We'll just return 0 here + * and assume that the fet will eventually come up. + */ + if (ret == FET_ERR_NOT_READY) + ret = 0; + + return ret; +} + +int tps65090_fet_disable(unsigned int bus, enum fet_id fet_id) +{ + return tps65090_fet_set(bus, fet_id, 0); +} + +int tps65090_fet_is_enabled(unsigned int bus, enum fet_id fet_id) +{ + unsigned char reg; + int ret; + + ret = tps65090_i2c_read(bus, fet_id, ®); + if (ret) { + printk(BIOS_DEBUG, "fail to read FET%u_CTRL", fet_id); + return -2; + } + + return reg & FET_CTRL_ENFET; +} + +int tps65090_is_charging(unsigned int bus) +{ + unsigned char val; + int ret; + + ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val); + if (ret) + return ret; + return val & CG_CTRL0_ENC_MASK ? 1 : 0; +} + +int tps65090_set_charge_enable(unsigned int bus, int enable) +{ + unsigned char val; + int ret; + + ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val); + if (!ret) { + if (enable) + val |= CG_CTRL0_ENC_MASK; + else + val &= ~CG_CTRL0_ENC_MASK; + ret = tps65090_i2c_write(bus, REG_CG_CTRL0, val); + } + if (ret) { + printk(BIOS_DEBUG, "%s: Failed to enable\n", __func__); + return ret; + } + return 0; +} + +int tps65090_get_status(unsigned int bus) +{ + unsigned char val; + int ret; + + ret = tps65090_i2c_read(bus, REG_CG_STATUS1, &val); + if (ret) + return ret; + return val; +} diff --git a/src/drivers/ti/tps65090/tps65090.h b/src/drivers/ti/tps65090/tps65090.h new file mode 100644 index 0000000000..b38db59892 --- /dev/null +++ b/src/drivers/ti/tps65090/tps65090.h @@ -0,0 +1,118 @@ +/* + * Copyright 2012, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#ifndef __TPS65090_H_ +#define __TPS65090_H_ + +/* I2C device address for TPS65090 PMU */ +#define TPS65090_I2C_ADDR 0x48 + +/* TPS65090 FET control registers */ +enum fet_id { + FET1_CTRL = 0x0f, + FET2_CTRL, + FET3_CTRL, + FET4_CTRL, + FET5_CTRL, + FET6_CTRL, + FET7_CTRL, +}; + +enum { + /* Status register fields */ + TPS65090_ST1_OTC = 1 << 0, + TPS65090_ST1_OCC = 1 << 1, + TPS65090_ST1_STATE_SHIFT = 4, + TPS65090_ST1_STATE_MASK = 0xf << TPS65090_ST1_STATE_SHIFT, +}; + +/* FET errors */ +enum { + FET_ERR_COMMS = -1, /* FET comms error */ + FET_ERR_NOT_READY = -2, /* FET is not yet ready - retry */ +}; + +/** + * Enable FET + * + * @bus I2C bus number the TPS65090 is on + * @fet_id FET ID, value between 1 and 7 + * return 0 on success, non-0 on failure + */ +int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id); + +/** + * Disable FET + * + * @bus I2C bus number the TPS65090 is on + * @fet_id FET ID, value between 1 and 7 + * @return 0 on success, non-0 on failure + */ +int tps65090_fet_disable(unsigned int bus, enum fet_id fet_id); + +/** + * Is FET enabled? + * + * @bus I2C bus number the TPS65090 is on + * @fet_id FET ID, value between 1 and 7 + * @return 1 enabled, 0 disabled, negative value on failure + */ +int tps65090_fet_is_enabled(unsigned int bus, enum fet_id fet_id); + +/** + * Enable / disable the battery charger + * + * @bus I2C bus number the TPS65090 is on + * @enable 0 to disable charging, non-zero to enable + */ +int tps65090_set_charge_enable(unsigned int bus, int enable); + +/** + * Check whether we have enabled battery charging + * + * @bus I2C bus number the TPS65090 is on + * @return 1 if enabled, 0 if disabled + */ +int tps65090_is_charging(unsigned int bus); + +/** + * Return the value of the status register + * + * @bus I2C bus number the TPS65090 is on + * @return status register value, or -1 on error + */ +int tps65090_get_status(unsigned int bus); + +#endif /* __TPS65090_H_ */ diff --git a/src/drivers/ti/tps65913/Kconfig b/src/drivers/ti/tps65913/Kconfig new file mode 100644 index 0000000000..bd24baeeba --- /dev/null +++ b/src/drivers/ti/tps65913/Kconfig @@ -0,0 +1,35 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config DRIVERS_TI_TPS65913 + bool "TI TPS65913 support" + default n + +config DRIVERS_TI_TPS65913_RTC + bool "TI TPS65913 RTC support" + default n + select DRIVERS_TI_TPS65913 + +config DRIVERS_TI_TPS65913_RTC_BUS + int "TI TPS65913 RTC bus" + depends on DRIVERS_TI_TPS65913_RTC + +config DRIVERS_TI_TPS65913_RTC_ADDR + hex "TI TPS65913 RTC chip address" + depends on DRIVERS_TI_TPS65913_RTC diff --git a/src/drivers/ti/tps65913/Makefile.inc b/src/drivers/ti/tps65913/Makefile.inc new file mode 100644 index 0000000000..272b026383 --- /dev/null +++ b/src/drivers/ti/tps65913/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_DRIVERS_TI_TPS65913_RTC) += tps65913rtc.c diff --git a/src/drivers/ti/tps65913/tps65913rtc.c b/src/drivers/ti/tps65913/tps65913rtc.c new file mode 100644 index 0000000000..46dd4f9dd0 --- /dev/null +++ b/src/drivers/ti/tps65913/tps65913rtc.c @@ -0,0 +1,155 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +enum TPS65913_RTC_REG { + TPS65913_SECONDS_REG = 0x00, + TPS65913_MINUTES_REG = 0x01, + TPS65913_HOURS_REG = 0x02, + TPS65913_DAYS_REG = 0x03, + TPS65913_MONTHS_REG = 0x04, + TPS65913_YEARS_REG = 0x05, + TPS65913_WEEKS_REG = 0x06, + TPS65913_RTC_CTRL_REG = 0x10, + TPS65913_RTC_STATUS_REG = 0x11, + TPS65913_RTC_INTERRUPS_REG = 0x12, +}; + +enum { + TPS65913_RTC_CTRL_STOP = (1 << 0), + TPS65913_RTC_CTRL_GET_TIME = (1 << 6), + + TPS65913_RTC_STATUS_RUN = (1 << 1), + TPS65913_RTC_RUNNING = (1 << 1), + TPS65913_RTC_FROZEN = (0 << 1), +}; + +static inline uint8_t tps65913_read(enum TPS65913_RTC_REG reg) +{ + uint8_t val; + i2c_readb(CONFIG_DRIVERS_TI_TPS65913_RTC_BUS, + CONFIG_DRIVERS_TI_TPS65913_RTC_ADDR, reg, &val); + return val; +} + +static inline void tps65913_write(enum TPS65913_RTC_REG reg, uint8_t val) +{ + i2c_writeb(CONFIG_DRIVERS_TI_TPS65913_RTC_BUS, + CONFIG_DRIVERS_TI_TPS65913_RTC_ADDR, reg, val); +} + +static void tps65913_rtc_ctrl_clear(uint8_t bit) +{ + uint8_t control = tps65913_read(TPS65913_RTC_CTRL_REG); + + control &= ~bit; + tps65913_write(TPS65913_RTC_CTRL_REG, control); +} + +static void tps65913_rtc_ctrl_set(uint8_t bit) +{ + uint8_t control = tps65913_read(TPS65913_RTC_CTRL_REG); + + control |= TPS65913_RTC_CTRL_GET_TIME; + tps65913_write(TPS65913_RTC_CTRL_REG, control); +} + +static int tps65913_is_rtc_running(void) +{ + uint8_t status = tps65913_read(TPS65913_RTC_STATUS_REG); + return ((status & TPS65913_RTC_STATUS_RUN) == TPS65913_RTC_RUNNING); +} + +/* + * This function ensures that current time is copied to shadow registers. Then a + * normal read on TC registers reads from the shadow instead of current TC + * registers. This helps prevent the accidental change in counters while + * reading. In order to ensure that the current TC registers are copied into + * shadow registers, GET_TIME bit needs to be set to 0 and then to 1. + */ +static void tps65913_rtc_shadow(void) +{ + tps65913_rtc_ctrl_clear(TPS65913_RTC_CTRL_GET_TIME); + tps65913_rtc_ctrl_set(TPS65913_RTC_CTRL_GET_TIME); +} + +static int tps65913_rtc_stop(void) +{ + /* Clearing stop bit freezes RTC */ + tps65913_rtc_ctrl_clear(TPS65913_RTC_CTRL_STOP); + + if (tps65913_is_rtc_running()) { + printk(BIOS_ERR, "Could not stop RTC\n"); + return 1; + } + + return 0; +} + +static int tps65913_rtc_start(void) +{ + /* Setting stop bit starts RTC */ + tps65913_rtc_ctrl_set(TPS65913_RTC_CTRL_STOP); + + if (!tps65913_is_rtc_running()) { + printk(BIOS_ERR, "Could not start RTC\n"); + return 1; + } + + return 0; +} + +int rtc_set(const struct rtc_time *time) +{ + /* Before setting the time, ensure that rtc is stopped */ + if (tps65913_rtc_stop()) + return 1; + + tps65913_write(TPS65913_SECONDS_REG, bin2bcd(time->sec)); + tps65913_write(TPS65913_MINUTES_REG, bin2bcd(time->min)); + tps65913_write(TPS65913_HOURS_REG, bin2bcd(time->hour)); + tps65913_write(TPS65913_DAYS_REG, bin2bcd(time->mday)); + tps65913_write(TPS65913_MONTHS_REG, bin2bcd(time->mon)); + tps65913_write(TPS65913_YEARS_REG, bin2bcd(time->year)); + + /* Re-start rtc */ + if (tps65913_rtc_start()) + return 1; + + return 0; +} + +int rtc_get(struct rtc_time *time) +{ + tps65913_rtc_shadow(); + + time->sec = bcd2bin(tps65913_read(TPS65913_SECONDS_REG) & 0x7f); + time->min = bcd2bin(tps65913_read(TPS65913_MINUTES_REG) & 0x7f); + time->hour = bcd2bin(tps65913_read(TPS65913_HOURS_REG) & 0x3f); + time->mday = bcd2bin(tps65913_read(TPS65913_DAYS_REG) & 0x3f); + time->mon = bcd2bin(tps65913_read(TPS65913_MONTHS_REG) & 0x1f); + time->year = bcd2bin(tps65913_read(TPS65913_YEARS_REG) & 0xff); + + return 0; +} diff --git a/src/ec/google/chromeec/Kconfig b/src/ec/google/chromeec/Kconfig index b8d34443f4..49d0789a52 100644 --- a/src/ec/google/chromeec/Kconfig +++ b/src/ec/google/chromeec/Kconfig @@ -1,11 +1,55 @@ config EC_GOOGLE_CHROMEEC bool + select SERIRQ_CONTINUOUS_MODE help Google's Chrome EC -config EC_GOOGLE_API_ROOT - depends on EC_GOOGLE_CHROMEEC - string "Path to the EC API include file" - default "/usr/include" - help - Path to the ec API file (ec/ec_commands.h). +config EC_GOOGLE_CHROMEEC_I2C + depends on EC_GOOGLE_CHROMEEC + def_bool n + help + Google's Chrome EC via I2C bus. + +config EC_GOOGLE_CHROMEEC_I2C_BUS + depends on EC_GOOGLE_CHROMEEC_I2C + hex "I2C bus for Google's Chrome EC" + +config EC_GOOGLE_CHROMEEC_I2C_CHIP + depends on EC_GOOGLE_CHROMEEC_I2C + hex + default 0x1e + +config EC_GOOGLE_CHROMEEC_I2C_PROTO3 + depends on EC_GOOGLE_CHROMEEC_I2C + bool + default n + help + Use only proto3 for i2c EC communication. + +config EC_GOOGLE_CHROMEEC_LPC + depends on EC_GOOGLE_CHROMEEC && ARCH_X86 # Needs Plug-and-play. + def_bool y + help + Google Chrome EC via LPC bus. + +config EC_GOOGLE_CHROMEEC_SPI + depends on EC_GOOGLE_CHROMEEC + def_bool n + help + Google's Chrome EC via SPI bus. + +config EC_GOOGLE_CHROMEEC_SPI_BUS + depends on EC_GOOGLE_CHROMEEC_SPI + hex "SPI bus for Google's Chrome EC" + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + depends on EC_GOOGLE_CHROMEEC_SPI + int + default 0 + help + Force delay after asserting /CS to allow EC to wakeup. + +config EC_GOOGLE_CHROMEEC_SPI_CHIP + depends on EC_GOOGLE_CHROMEEC_SPI + hex + default 0 diff --git a/src/ec/google/chromeec/Makefile.inc b/src/ec/google/chromeec/Makefile.inc index 93ad333bb4..0df6e8b1c5 100644 --- a/src/ec/google/chromeec/Makefile.inc +++ b/src/ec/google/chromeec/Makefile.inc @@ -1,5 +1,19 @@ -ramstage-y += ec.c -smm-y += ec.c -romstage-y += ec.c +ramstage-y += ec.c crosec_proto.c +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +smm-y += ec.c crosec_proto.c +smm-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c +smm-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c +smm-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +romstage-y += ec.c crosec_proto.c +romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c +romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c +romstage-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +ifeq ($(CONFIG_VBOOT2_VERIFY_FIRMWARE),y) +verstage-y += ec.c crosec_proto.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_I2C) += ec_i2c.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_LPC) += ec_lpc.c +verstage-$(CONFIG_EC_GOOGLE_CHROMEEC_SPI) += ec_spi.c +endif -CFLAGS += -I $(call strip_quotes,$(CONFIG_EC_GOOGLE_API_ROOT)) diff --git a/src/ec/google/chromeec/acpi/als.asl b/src/ec/google/chromeec/acpi/als.asl new file mode 100644 index 0000000000..8bc68bf1d1 --- /dev/null +++ b/src/ec/google/chromeec/acpi/als.asl @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device (ALS) +{ + Name (_HID, "ACPI0008") + Name (_UID, 1) + + Method (_STA, 0, NotSerialized) + { + Return (0xF) + } + + /* + * Returns the current ambient light illuminance reading in lux + * + * 0: Reading is below the range of sensitivity of the sensor + * -1: Reading is above the range or sensitivity of the sensor + */ + Method (_ALI, 0, NotSerialized) + { + Return (^^ALS0) + } + + /* + * Returns a recommended polling frequency in tenths of seconds + * + * 0: No need to poll, async notifications will indicate changes + */ + Name (_ALP, 10) + + /* + * Returns a package of packages where each tuple consists of a pair + * of integers mapping ambient light illuminance to display brightness. + * + * {, } + * + * Ambient light illuminance values are specified in lux. + * + * Display luminance adjustment values are relative percentages where + * 100 is no (0%) display brightness adjustment. Values <100 indicate + * negative adjustment (dimming) and values >100 indicate positive + * adjustment (brightening). + * + * This is currently unused by the Linux kernel ACPI ALS driver but + * is required by the ACPI specification so just define a basic two + * point response curve. + */ + Name (_ALR, Package () + { + Package () { 70, 30 }, // Min { -30% adjust at 30 lux } + Package () { 150, 1000 } // Max { +50% adjust at 1000 lux } + }) +} diff --git a/src/ec/google/chromeec/acpi/battery.asl b/src/ec/google/chromeec/acpi/battery.asl index 341911c372..5591b334e0 100644 --- a/src/ec/google/chromeec/acpi/battery.asl +++ b/src/ec/google/chromeec/acpi/battery.asl @@ -126,9 +126,7 @@ Device (BAT0) Return (PBIF) } - // Extended Battery info method is disabled for now due to - // a bug in the Linux kernel: http://crosbug.com/28747 - Method (XBIX, 0, Serialized) + Method (_BIX, 0, Serialized) { // Last Full Charge Capacity Store (BTDF, Index (PBIX, 3)) @@ -210,8 +208,8 @@ Device (BAT0) // https://bugzilla.kernel.org/show_bug.cgi?id=12632 Store (BTDF, Local2) - // See if within ~3% of full - ShiftRight (Local2, 5, Local3) + // See if within ~6% of full + ShiftRight (Local2, 4, Local3) If (LAnd (LGreater (Local1, Subtract (Local2, Local3)), LLess (Local1, Add (Local2, Local3)))) { diff --git a/src/ec/google/chromeec/acpi/ec.asl b/src/ec/google/chromeec/acpi/ec.asl index 2fb8e7961c..7cd8f75dbf 100644 --- a/src/ec/google/chromeec/acpi/ec.asl +++ b/src/ec/google/chromeec/acpi/ec.asl @@ -23,15 +23,21 @@ * re-evaluate their _PPC and _CST tables. */ +// Mainboard specific throttle handler +External (\_TZ.THRT, MethodObj) +External (\_SB.DPTF.TEVT, MethodObj) +External (\_SB.DPTF.TCHG, DeviceObj) + Device (EC0) { Name (_HID, EISAID ("PNP0C09")) Name (_UID, 1) - Name (_GPE, Add(EC_SCI_GPI, 16)) + Name (_GPE, EC_SCI_GPI) Name (TOFS, EC_TEMP_SENSOR_OFFSET) - Name (TNOP, 0xFD) // Thermal sensor has no power - Name (TBAD, 0xFE) // Thermal sensor bad reading - Name (TNPR, 0xFF) // Thermal sensor not present + Name (TNCA, EC_TEMP_SENSOR_NOT_CALIBRATED) + Name (TNOP, EC_TEMP_SENSOR_NOT_POWERED) + Name (TBAD, EC_TEMP_SENSOR_ERROR) + Name (TNPR, EC_TEMP_SENSOR_NOT_PRESENT) Name (DWRN, 15) // Battery capacity warning at 15% Name (DLOW, 10) // Battery capacity low at 10% @@ -43,6 +49,11 @@ Device (EC0) TSTB, 8, // Test Byte TSTC, 8, // Complement of Test Byte KBLV, 8, // Keyboard Backlight + FAND, 8, // Set Fan Duty Cycle + PATI, 8, // Programmable Auxiliary Trip Sensor ID + PATT, 8, // Programmable Auxiliary Trip Threshold + PATC, 8, // Programmable Auxiliary Trip Commit + CHGL, 8, // Charger Current Limit } OperationRegion (EMEM, SystemIO, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE) @@ -85,6 +96,8 @@ Device (EC0) BMOD, 64, // Battery Model String BSER, 64, // Battery Serial String BTYP, 64, // Battery Type String + Offset (0x80), + ALS0, 16, // ALS reading 0 in lux } Method (TINS, 1, Serialized) @@ -130,6 +143,40 @@ Device (EC0) Store (LIDS, \LIDS) } + /* Read requested temperature and check against EC error values */ + Method (TSRD, 1, Serialized) + { + Store (\_SB.PCI0.LPCB.EC0.TINS (Arg0), Local0) + + /* Check for sensor not calibrated */ + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (Zero) + } + + /* Check for sensor not present */ + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (Zero) + } + + /* Check for sensor not powered */ + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (Zero) + } + + /* Check for sensor bad reading */ + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (Zero) + } + + /* Adjust by offset to get Kelvin */ + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + /* Convert to 1/10 Kelvin */ + Multiply (Local0, 10, Local0) + + Return (Local0) + } + // Lid Closed Event Method (_Q01, 0, NotSerialized) { @@ -159,6 +206,9 @@ Device (EC0) Store ("EC: AC CONNECTED", Debug) Store (ACEX, \PWRS) Notify (AC, 0x80) + If (CondRefOf (\_SB.DPTF.TCHG)) { + Notify (\_SB.DPTF.TCHG, 0x80) + } \PNOT () } @@ -168,6 +218,9 @@ Device (EC0) Store ("EC: AC DISCONNECTED", Debug) Store (ACEX, \PWRS) Notify (AC, 0x80) + If (CondRefOf (\_SB.DPTF.TCHG)) { + Notify (\_SB.DPTF.TCHG, 0x80) + } \PNOT () } @@ -192,13 +245,6 @@ Device (EC0) Notify (BAT0, 0x81) } - // Thermal Treshold Event - Method (_Q09, 0, NotSerialized) - { - Store ("EC: THERMAL THRESHOLD", Debug) - Notify (\_TZ, 0x80) - } - // Thermal Overload Event Method (_Q0A, 0, NotSerialized) { @@ -225,6 +271,188 @@ Device (EC0) Store ("EC: KEY PRESSED", Debug) } + // Thermal Shutdown Imminent + Method (_Q10, 0, NotSerialized) + { + Store ("EC: THERMAL SHUTDOWN", Debug) + Notify (\_TZ, 0x80) + } + + // Battery Shutdown Imminent + Method (_Q11, 0, NotSerialized) + { + Store ("EC: BATTERY SHUTDOWN", Debug) + Notify (BAT0, 0x80) + } + + // Throttle Start + Method (_Q12, 0, NotSerialized) + { + Store ("EC: THROTTLE START", Debug) + If (CondRefOf (\_TZ.THRT, Local0)) { + \_TZ.THRT (1) + } + } + + // Throttle Stop + Method (_Q13, 0, NotSerialized) + { + Store ("EC: THROTTLE STOP", Debug) + If (CondRefOf (\_TZ.THRT, Local0)) { + \_TZ.THRT (0) + } + } + +#ifdef EC_ENABLE_PD_MCU_DEVICE + // PD event + Method (_Q16, 0, NotSerialized) + { + Store ("EC: GOT PD EVENT", Debug) + Notify (ECPD, 0x80) + } +#endif + + // Battery Status + Method (_Q17, 0, NotSerialized) + { + Store ("EC: BATTERY STATUS", Debug) + Notify (BAT0, 0x80) + } + + /* + * Dynamic Platform Thermal Framework support + */ + + /* Mutex for EC PAT interface */ + Mutex (PATM, 1) + + /* + * Set Aux Trip Point 0 + * Arg0 = Temp Sensor ID + * Arg1 = Value to set + */ + Method (PAT0, 2, Serialized) + { + If (Acquire (^PATM, 1000)) { + Return (0) + } + + /* Set sensor ID */ + Store (ToInteger (Arg0), ^PATI) + + /* Temperature is passed in 1/10 Kelvin */ + Divide (ToInteger (Arg1), 10, Local0, Local1) + + /* Adjust by EC temperature offset */ + Subtract (Local1, ^TOFS, ^PATT) + + /* Set commit value with SELECT=0 and ENABLE=1 */ + Store (0x02, ^PATC) + + Release (^PATM) + Return (1) + } + + /* + * Set Aux Trip Point 1 + * Arg0 = Temp Sensor ID + * Arg1 = Value to set + */ + Method (PAT1, 2, Serialized) + { + If (Acquire (^PATM, 1000)) { + Return (0) + } + + /* Set sensor ID */ + Store (ToInteger (Arg0), ^PATI) + + /* Temperature is passed in 1/10 Kelvin */ + Divide (ToInteger (Arg1), 10, Local0, Local1) + + /* Adjust by EC temperature offset */ + Subtract (Local1, ^TOFS, ^PATT) + + /* Set commit value with SELECT=1 and ENABLE=1 */ + Store (0x03, ^PATC) + + Release (^PATM) + Return (1) + } + + /* Disable Aux Trip Points + * Arg0 = Temp Sensor ID + */ + Method (PATD, 1, Serialized) + { + If (Acquire (^PATM, 1000)) { + Return (0) + } + + Store (ToInteger (Arg0), ^PATI) + Store (0x00, ^PATT) + + /* Disable PAT0 */ + Store (0x00, ^PATC) + + /* Disable PAT1 */ + Store (0x01, ^PATC) + + Release (^PATM) + Return (1) + } + + /* + * Thermal Threshold Event + */ + Method (_Q09, 0, NotSerialized) + { + If (Acquire (^PATM, 1000)) { + Return () + } + + /* Read sensor ID for event */ + Store (^PATI, Local0) + + /* When sensor ID returns 0xFF then no more events */ + While (LNotEqual (Local0, EC_TEMP_SENSOR_NOT_PRESENT)) + { + If (CondRefOf (\_SB.DPTF.TEVT, Local1)) { + \_SB.DPTF.TEVT (Local0) + } + + /* Keep reaading sensor ID for event */ + Store (^PATI, Local0) + } + + Release (^PATM) + } + + /* + * Set Charger Current Limit + * Arg0 = Current Limit in 64mA steps + */ + Method (CHGS, 1, Serialized) + { + Store (ToInteger (Arg0), ^CHGL) + } + + /* + * Disable Charger Current Limit + */ + Method (CHGD, 0, Serialized) + { + Store (0xFF, ^CHGL) + } + #include "ac.asl" #include "battery.asl" + +#ifdef EC_ENABLE_ALS_DEVICE + #include "als.asl" +#endif + +#ifdef EC_ENABLE_PD_MCU_DEVICE + #include "pd.asl" +#endif } diff --git a/src/ec/google/chromeec/acpi/pd.asl b/src/ec/google/chromeec/acpi/pd.asl new file mode 100644 index 0000000000..a1acc2c40f --- /dev/null +++ b/src/ec/google/chromeec/acpi/pd.asl @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device (ECPD) +{ + Name (_HID, "GOOG0003") + Name (_UID, 1) + Name (_DDN, "EC PD Device") +} diff --git a/src/ec/google/chromeec/acpi/superio.asl b/src/ec/google/chromeec/acpi/superio.asl index 56f0f185c6..a02286405c 100644 --- a/src/ec/google/chromeec/acpi/superio.asl +++ b/src/ec/google/chromeec/acpi/superio.asl @@ -29,8 +29,9 @@ * SIO_EC_HOST_ENABLE : Enable EC host command interface resources * EC_LPC_ADDR_HOST_DATA : EC host command interface data port * EC_LPC_ADDR_HOST_CMD : EC host command interface command port - * EC_LPC_ADDR_OLD_PARAM : EC host command parameter range base (old) - * EC_OLD_PARAM_SIZE : Parameter buffer size (old) + * EC_HOST_CMD_REGION0 : EC host command buffer + * EC_HOST_CMD_REGION1 : EC host command buffer + * EC_HOST_CMD_REGION_SIZE : EC host command buffer size */ // Scope is \_SB.PCI0.LPCB @@ -51,12 +52,14 @@ Device (SIO) { Name (_CRS, ResourceTemplate () { - FixedIO (EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE) + IO (Decode16, EC_LPC_ADDR_MEMMAP, EC_LPC_ADDR_MEMMAP, + 0x08, EC_MEMMAP_SIZE) }) Name (_PRS, ResourceTemplate () { - FixedIO (EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE) + IO (Decode16, EC_LPC_ADDR_MEMMAP, EC_LPC_ADDR_MEMMAP, + 0x08, EC_MEMMAP_SIZE) }) } #endif @@ -73,19 +76,33 @@ Device (SIO) { Name (_CRS, ResourceTemplate () { - FixedIO (EC_LPC_ADDR_HOST_DATA, 1) - FixedIO (EC_LPC_ADDR_HOST_CMD, 1) - FixedIO (EC_LPC_ADDR_OLD_PARAM, - EC_OLD_PARAM_SIZE) + IO (Decode16, + EC_LPC_ADDR_HOST_DATA, EC_LPC_ADDR_HOST_DATA, + 0x01, 0x01) + IO (Decode16, + EC_LPC_ADDR_HOST_CMD, EC_LPC_ADDR_HOST_CMD, + 0x01, 0x01) + IO (Decode16, + EC_HOST_CMD_REGION0, EC_HOST_CMD_REGION0, 0x08, + EC_HOST_CMD_REGION_SIZE) + IO (Decode16, + EC_HOST_CMD_REGION1, EC_HOST_CMD_REGION0, 0x08, + EC_HOST_CMD_REGION_SIZE) }) Name (_PRS, ResourceTemplate () { StartDependentFn (0, 0) { - FixedIO (EC_LPC_ADDR_HOST_DATA, 1) - FixedIO (EC_LPC_ADDR_HOST_CMD, 1) - FixedIO (EC_LPC_ADDR_OLD_PARAM, - EC_OLD_PARAM_SIZE) + IO (Decode16, EC_LPC_ADDR_HOST_DATA, + EC_LPC_ADDR_HOST_DATA, 0x01, 0x01) + IO (Decode16, EC_LPC_ADDR_HOST_CMD, + EC_LPC_ADDR_HOST_CMD, 0x01, 0x01) + IO (Decode16, + EC_HOST_CMD_REGION0, EC_HOST_CMD_REGION0, + 0x08, EC_HOST_CMD_REGION_SIZE) + IO (Decode16, + EC_HOST_CMD_REGION1, EC_HOST_CMD_REGION1, + 0x08, EC_HOST_CMD_REGION_SIZE) } EndDependentFn () }) @@ -104,14 +121,14 @@ Device (SIO) { Name (_CRS, ResourceTemplate () { - FixedIO (0x03F8, 0x08) + IO (Decode16, 0x03F8, 0x3F8, 0x08, 0x08) IRQNoFlags () {4} }) Name (_PRS, ResourceTemplate () { StartDependentFn (0, 0) { - FixedIO (0x03F8, 0x08) + IO (Decode16, 0x03F8, 0x3F8, 0x08, 0x08) IRQNoFlags () {4} } EndDependentFn () @@ -133,17 +150,25 @@ Device (SIO) { Name (_CRS, ResourceTemplate() { - FixedIO (0x60, 0x01) - FixedIO (0x64, 0x01) + IO (Decode16, 0x60, 0x60, 0x01, 0x01) + IO (Decode16, 0x64, 0x64, 0x01, 0x01) +#ifdef SIO_EC_PS2K_IRQ + SIO_EC_PS2K_IRQ +#else IRQNoFlags () {1} +#endif }) Name (_PRS, ResourceTemplate() { StartDependentFn (0, 0) { - FixedIO (0x60, 0x01) - FixedIO (0x64, 0x01) + IO (Decode16, 0x60, 0x60, 0x01, 0x01) + IO (Decode16, 0x64, 0x64, 0x01, 0x01) +#ifdef SIO_EC_PS2K_IRQ + SIO_EC_PS2K_IRQ +#else IRQNoFlags () {1} +#endif } EndDependentFn () }) diff --git a/src/ec/google/chromeec/crosec_proto.c b/src/ec/google/chromeec/crosec_proto.c new file mode 100644 index 0000000000..1183e827f1 --- /dev/null +++ b/src/ec/google/chromeec/crosec_proto.c @@ -0,0 +1,263 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" +#include "ec_commands.h" +#include "ec_message.h" + +/* Common utilities */ +void * __attribute__((weak)) crosec_get_buffer(size_t size, int req) +{ + printk(BIOS_DEBUG, "crosec_get_buffer() implementation required.\n"); + return NULL; +} + +/* Dumps EC command / response data into debug output. + * + * @param name Message prefix name. + * @param cmd Command code, or -1 to ignore cmd message. + * @param data Data buffer to print. + * @param len Length of data. + */ +static void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, + int len) +{ + int i; + + printk(BIOS_DEBUG, "%s: ", name); + if (cmd != -1) + printk(BIOS_DEBUG, "cmd=%#x: ", cmd); + for (i = 0; i < len; i++) + printk(BIOS_DEBUG, "%02x ", data[i]); + printk(BIOS_DEBUG, "\n"); +} + +/* Calculate a simple 8-bit checksum of a data block + * + * @param data Data block to checksum + * @param size Size of data block in bytes + * @return checksum value (0 to 255) + */ +static int cros_ec_calc_checksum(const uint8_t *data, int size) +{ + int csum, i; + + for (i = csum = 0; i < size; i++) + csum += data[i]; + return csum & 0xff; +} + +/* Standard Chrome EC protocol, version 3 */ + +struct ec_command_v3 { + struct ec_host_request header; + uint8_t data[MSG_BYTES]; +}; + +struct ec_response_v3 { + struct ec_host_response header; + uint8_t data[MSG_BYTES]; +}; + +/** + * Create a request packet for protocol version 3. + * + * @param cec_command Command description. + * @param cmd Packed command bit stream. + * @return packet size in bytes, or <0 if error. + */ +static int create_proto3_request(const struct chromeec_command *cec_command, + struct ec_command_v3 *cmd) +{ + struct ec_host_request *rq = &cmd->header; + int out_bytes = cec_command->cmd_size_in + sizeof(*rq); + + /* Fail if output size is too big */ + if (out_bytes > sizeof(*cmd)) { + printk(BIOS_ERR, "%s: Cannot send %d bytes\n", __func__, + cec_command->cmd_size_in); + return -EC_RES_REQUEST_TRUNCATED; + } + + /* Fill in request packet */ + rq->struct_version = EC_HOST_REQUEST_VERSION; + rq->checksum = 0; + rq->command = cec_command->cmd_code; + rq->command_version = cec_command->cmd_version; + rq->reserved = 0; + rq->data_len = cec_command->cmd_size_in; + + /* Copy data after header */ + memcpy(cmd->data, cec_command->cmd_data_in, cec_command->cmd_size_in); + + /* Write checksum field so the entire packet sums to 0 */ + rq->checksum = (uint8_t)(-cros_ec_calc_checksum( + (const uint8_t*)cmd, out_bytes)); + + cros_ec_dump_data("out", rq->command, (const uint8_t *)cmd, out_bytes); + + /* Return size of request packet */ + return out_bytes; +} + +/** + * Prepare the device to receive a protocol version 3 response. + * + * @param cec_command Command description. + * @param resp Response buffer. + * @return maximum expected number of bytes in response, or <0 if error. + */ +static int prepare_proto3_response_buffer( + const struct chromeec_command *cec_command, + struct ec_response_v3 *resp) +{ + int in_bytes = cec_command->cmd_size_out + sizeof(resp->header); + + /* Fail if input size is too big */ + if (in_bytes > sizeof(*resp)) { + printk(BIOS_ERR, "%s: Cannot receive %d bytes\n", __func__, + cec_command->cmd_size_out); + return -EC_RES_RESPONSE_TOO_BIG; + } + + /* Return expected size of response packet */ + return in_bytes; +} + +/** + * Handle a protocol version 3 response packet. + * + * The packet must already be stored in the response buffer. + * + * @param resp Response buffer. + * @param cec_command Command structure to receive valid response. + * @return number of bytes of response data, or <0 if error + */ +static int handle_proto3_response(struct ec_response_v3 *resp, + struct chromeec_command *cec_command) +{ + struct ec_host_response *rs = &resp->header; + int in_bytes; + int csum; + + cros_ec_dump_data("in-header", -1, (const uint8_t*)rs, sizeof(*rs)); + + /* Check input data */ + if (rs->struct_version != EC_HOST_RESPONSE_VERSION) { + printk(BIOS_ERR, "%s: EC response version mismatch\n", __func__); + return -EC_RES_INVALID_RESPONSE; + } + + if (rs->reserved) { + printk(BIOS_ERR, "%s: EC response reserved != 0\n", __func__); + return -EC_RES_INVALID_RESPONSE; + } + + if (rs->data_len > sizeof(resp->data) || + rs->data_len > cec_command->cmd_size_out) { + printk(BIOS_ERR, "%s: EC returned too much data\n", __func__); + return -EC_RES_RESPONSE_TOO_BIG; + } + + cros_ec_dump_data("in-data", -1, resp->data, rs->data_len); + + /* Update in_bytes to actual data size */ + in_bytes = sizeof(*rs) + rs->data_len; + + /* Verify checksum */ + csum = cros_ec_calc_checksum((const uint8_t *)resp, in_bytes); + if (csum) { + printk(BIOS_ERR, "%s: EC response checksum invalid: 0x%02x\n", + __func__, csum); + return -EC_RES_INVALID_CHECKSUM; + } + + /* Return raw response. */ + cec_command->cmd_code = rs->result; + cec_command->cmd_size_out = rs->data_len; + memcpy(cec_command->cmd_data_out, resp->data, rs->data_len); + + /* Return error result, if any */ + if (rs->result) { + printk(BIOS_ERR, "%s: EC response with error code: %d\n", + __func__, rs->result); + return -(int)rs->result; + } + + return rs->data_len; +} + +static int send_command_proto3(struct chromeec_command *cec_command, + crosec_io_t crosec_io, void *context) +{ + int out_bytes, in_bytes; + int rv; + struct ec_command_v3 *cmd; + struct ec_response_v3 *resp; + + if ((cmd = crosec_get_buffer(sizeof(*cmd), 1)) == NULL) + return -EC_RES_ERROR; + if ((resp = crosec_get_buffer(sizeof(*resp), 0)) == NULL) + return -EC_RES_ERROR; + + /* Create request packet */ + out_bytes = create_proto3_request(cec_command, cmd); + if (out_bytes < 0) { + return out_bytes; + } + + /* Prepare response buffer */ + in_bytes = prepare_proto3_response_buffer(cec_command, resp); + if (in_bytes < 0) { + return in_bytes; + } + + rv = crosec_io(out_bytes, in_bytes, context); + if (rv != 0) { + printk(BIOS_ERR, "%s: failed to complete I/O: Err = %#x.\n", + __func__, rv >= 0 ? rv : -rv); + return -EC_RES_ERROR; + } + + /* Process the response */ + return handle_proto3_response(resp, cec_command); +} + +static int crosec_command_proto_v3(struct chromeec_command *cec_command, + crosec_io_t crosec_io, void *context) +{ + int rv = send_command_proto3(cec_command, crosec_io, context); + if (rv < 0) { + cec_command->cmd_code = rv; + return 1; + } + return 0; +} + +int crosec_command_proto(struct chromeec_command *cec_command, + crosec_io_t crosec_io, void *context) +{ + // TODO(hungte) Detect and fallback to v2 if we need. + return crosec_command_proto_v3(cec_command, crosec_io, context); +} diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c index 5ae0178ebf..9fe6e4740d 100644 --- a/src/ec/google/chromeec/ec.c +++ b/src/ec/google/chromeec/ec.c @@ -18,187 +18,28 @@ */ #include +#include #include #include #include -#include -#include +#include +#include #ifndef __PRE_RAM__ #include #include -#include -#include -#include #include "chip.h" #endif #include "ec.h" #include "ec_commands.h" #include -/* an internal API to send a command to the EC and wait for response. */ -struct chromeec_command { - u8 cmd_code; /* command code in, status out */ - u8 cmd_version; /* command version */ - const void* cmd_data_in; /* command data, if any */ - void* cmd_data_out; /* command response, if any */ - u16 cmd_size_in; /* size of command data */ - u16 cmd_size_out; /* expected size of command response in, - * actual received size out */ -}; - -static int google_chromeec_wait_ready(u16 port) +uint8_t google_chromeec_calc_checksum(const uint8_t *data, int size) { - u8 ec_status = inb(port); - u32 time_count = 0; - - /* - * One second is more than plenty for any EC operation to complete - * (and the bus accessing/code execution) overhead will make the - * timeout even longer. - */ -#define MAX_EC_TIMEOUT_US 1000000 - - while (ec_status & - (EC_LPC_CMDR_PENDING | EC_LPC_CMDR_BUSY)) { - udelay(1); - if (time_count++ == MAX_EC_TIMEOUT_US) - return -1; - ec_status = inb(port); - } - return 0; -} - -static int google_chromeec_cmd_args_supported(void) -{ - if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) == 'E' && - inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) == 'C' && - (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS) & - EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED)) - return 1; - - return 0; -} - -static int google_chromeec_command_old(struct chromeec_command *cec_command) -{ - int i; - - if (cec_command->cmd_version) { - printk(BIOS_ERR, "Invalid version for command protocol!\n"); - return 1; - } - - if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { - printk(BIOS_ERR, "Timeout waiting for EC ready!\n"); - return 1; - } - - /* Copy command data, if any. */ - for (i = 0; i < cec_command->cmd_size_in; i++) - outb(((char*)cec_command->cmd_data_in)[i], - EC_LPC_ADDR_OLD_PARAM + i); - - /* Issue the command. */ - outb(cec_command->cmd_code, EC_LPC_ADDR_HOST_CMD); - - if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { - printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", - cec_command->cmd_code); - return 1; - } - - for (i = 0; i < cec_command->cmd_size_out; i++) - ((char*)cec_command->cmd_data_out)[i] = - inb(EC_LPC_ADDR_OLD_PARAM + i); - cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); - return 0; -} - -static int google_chromeec_command(struct chromeec_command *cec_command) -{ - struct ec_lpc_host_args args; - const u8 *d; - u8 *dout; - u8 cmd_code = cec_command->cmd_code; int csum; - int i; - /* Fall back to old command protocol if necessary */ - if (!google_chromeec_cmd_args_supported()) - return google_chromeec_command_old(cec_command); - - /* Fill in args */ - args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; - args.command_version = cec_command->cmd_version; - args.data_size = cec_command->cmd_size_in; - - /* Initialize checksum */ - csum = cmd_code + args.flags + args.command_version + args.data_size; - - /* Write data and update checksum */ - for (i = 0, d = (const u8 *)cec_command->cmd_data_in; - i < cec_command->cmd_size_in; i++, d++) { - outb(*d, EC_LPC_ADDR_HOST_PARAM + i); - csum += *d; - } - - /* Finalize checksum and write args */ - args.checksum = (u8)csum; - for (i = 0, d = (const u8 *)&args; i < sizeof(args); i++, d++) - outb(*d, EC_LPC_ADDR_HOST_ARGS + i); - - - /* Issue the command */ - outb(cmd_code, EC_LPC_ADDR_HOST_CMD); - - if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { - printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", - cec_command->cmd_code); - return 1; - } - - /* Check result */ - cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); - if (cec_command->cmd_code) - return 1; - - /* Read back args */ - for (i = 0, dout = (u8 *)&args; i < sizeof(args); i++, dout++) - *dout = inb(EC_LPC_ADDR_HOST_ARGS + i); - - /* - * If EC didn't modify args flags, then somehow we sent a new-style - * command to an old EC, which means it would have read its params - * from the wrong place. - */ - if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) { - printk(BIOS_ERR, "EC protocol mismatch\n"); - return 1; - } - - if (args.data_size > cec_command->cmd_size_out) { - printk(BIOS_ERR, "EC returned too much data\n"); - return 1; - } - cec_command->cmd_size_out = args.data_size; - - /* Start calculating response checksum */ - csum = cmd_code + args.flags + args.command_version + args.data_size; - - /* Read data, if any */ - for (i = 0, dout = (u8 *)cec_command->cmd_data_out; - i < args.data_size; i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PARAM + i); - csum += *dout; - } - - /* Verify checksum */ - if (args.checksum != (u8)csum) { - printk(BIOS_ERR, "EC response has invalid checksum\n"); - return 1; - } - - return 0; + for (csum = 0; size > 0; data++, size--) + csum += *data; + return (uint8_t)(csum & 0xff); } int google_chromeec_kbbacklight(int percent) @@ -215,6 +56,7 @@ int google_chromeec_kbbacklight(int percent) cec_cmd.cmd_data_out = &rsp_backlight; cec_cmd.cmd_size_in = sizeof(cmd_backlight); cec_cmd.cmd_size_out = sizeof(rsp_backlight); + cec_cmd.cmd_dev_index = 0; google_chromeec_command(&cec_cmd); printk(BIOS_DEBUG, "Google Chrome set keyboard backlight: %x status (%x)\n", rsp_backlight.percent, cec_cmd.cmd_code); @@ -247,19 +89,13 @@ static u32 google_chromeec_get_mask(u8 type) cmd.cmd_size_in = sizeof(req); cmd.cmd_data_out = &rsp; cmd.cmd_size_out = sizeof(rsp); + cmd.cmd_dev_index = 0; if (google_chromeec_command(&cmd) == 0) return rsp.mask; return 0; } -u32 google_chromeec_get_events_b(void) -{ - return google_chromeec_get_mask(EC_CMD_HOST_EVENT_GET_B); -} - -#ifndef __PRE_RAM__ - static int google_chromeec_set_mask(u8 type, u32 mask) { struct ec_params_host_event_mask req; @@ -273,10 +109,257 @@ static int google_chromeec_set_mask(u8 type, u32 mask) cmd.cmd_size_in = sizeof(req); cmd.cmd_data_out = &rsp; cmd.cmd_size_out = sizeof(rsp); + cmd.cmd_dev_index = 0; return google_chromeec_command(&cmd); } +u32 google_chromeec_get_events_b(void) +{ + return google_chromeec_get_mask(EC_CMD_HOST_EVENT_GET_B); +} + +int google_chromeec_clear_events_b(u32 mask) +{ + printk(BIOS_DEBUG, "Chrome EC: clear events_b mask to 0x%08x\n", mask); + return google_chromeec_set_mask( + EC_CMD_HOST_EVENT_CLEAR_B, mask); +} + +#ifndef __SMM__ +#ifdef __PRE_RAM__ +void google_chromeec_check_ec_image(int expected_type) +{ + struct chromeec_command cec_cmd; + struct ec_response_get_version cec_resp = { { 0 } }; + + cec_cmd.cmd_code = EC_CMD_GET_VERSION; + cec_cmd.cmd_version = 0; + cec_cmd.cmd_data_out = &cec_resp; + cec_cmd.cmd_size_in = 0; + cec_cmd.cmd_size_out = sizeof(cec_resp); + cec_cmd.cmd_dev_index = 0; + google_chromeec_command(&cec_cmd); + + if (cec_cmd.cmd_code || cec_resp.current_image != expected_type) { + struct ec_params_reboot_ec reboot_ec; + /* Reboot the EC and make it come back in RO mode */ + reboot_ec.cmd = EC_REBOOT_COLD; + reboot_ec.flags = 0; + cec_cmd.cmd_code = EC_CMD_REBOOT_EC; + cec_cmd.cmd_version = 0; + cec_cmd.cmd_data_in = &reboot_ec; + cec_cmd.cmd_size_in = sizeof(reboot_ec); + cec_cmd.cmd_size_out = 0; /* ignore response, if any */ + cec_cmd.cmd_dev_index = 0; + printk(BIOS_DEBUG, "Rebooting with EC in RO mode:\n"); + post_code(0); /* clear current post code */ + google_chromeec_command(&cec_cmd); + udelay(1000); + hard_reset(); + hlt(); + } +} + +/* Check for recovery mode and ensure EC is in RO */ +void google_chromeec_early_init(void) +{ + /* If in recovery ensure EC is running RO firmware. */ + if (recovery_mode_enabled()) { + google_chromeec_check_ec_image(EC_IMAGE_RO); + } +} + +void google_chromeec_check_pd_image(int expected_type) +{ + struct chromeec_command cec_cmd; + struct ec_response_get_version cec_resp = { { 0 } }; + + cec_cmd.cmd_code = EC_CMD_GET_VERSION; + cec_cmd.cmd_version = 0; + cec_cmd.cmd_data_out = &cec_resp; + cec_cmd.cmd_size_in = 0; + cec_cmd.cmd_size_out = sizeof(cec_resp); + cec_cmd.cmd_dev_index = 1; /* PD */ + google_chromeec_command(&cec_cmd); + + if (cec_cmd.cmd_code || cec_resp.current_image != expected_type) { + struct ec_params_reboot_ec reboot_ec; + /* Reboot the PD and make it come back in RO mode */ + reboot_ec.cmd = EC_REBOOT_COLD; + reboot_ec.flags = 0; + cec_cmd.cmd_code = EC_CMD_REBOOT_EC; + cec_cmd.cmd_version = 0; + cec_cmd.cmd_data_in = &reboot_ec; + cec_cmd.cmd_size_in = sizeof(reboot_ec); + cec_cmd.cmd_size_out = 0; /* ignore response, if any */ + cec_cmd.cmd_dev_index = 1; /* PD */ + printk(BIOS_DEBUG, "Rebooting PD to RO mode\n"); + google_chromeec_command(&cec_cmd); + udelay(1000); + } +} + +/* Check for recovery mode and ensure PD is in RO */ +void google_chromeec_early_pd_init(void) +{ + /* If in recovery ensure PD is running RO firmware. */ + if (recovery_mode_enabled()) { + google_chromeec_check_pd_image(EC_IMAGE_RO); + } +} +#endif + +u16 google_chromeec_get_board_version(void) +{ + struct chromeec_command cmd; + struct ec_response_board_version board_v; + + cmd.cmd_code = EC_CMD_GET_BOARD_VERSION; + cmd.cmd_version = 0; + cmd.cmd_size_in = 0; + cmd.cmd_size_out = sizeof(board_v); + cmd.cmd_data_out = &board_v; + cmd.cmd_dev_index = 0; + + if (google_chromeec_command(&cmd) != 0) + return 0; + + return board_v.board_version; +} + +int google_chromeec_vbnv_context(int is_read, uint8_t *data, int len) +{ + struct chromeec_command cec_cmd; + struct ec_params_vbnvcontext cmd_vbnvcontext; + struct ec_response_vbnvcontext rsp_vbnvcontext; + int retries = 3; + + if (len != EC_VBNV_BLOCK_SIZE) + return -1; + + retry: + cec_cmd.cmd_code = EC_CMD_VBNV_CONTEXT; + cec_cmd.cmd_version = EC_VER_VBNV_CONTEXT; + cec_cmd.cmd_data_in = &cmd_vbnvcontext; + cec_cmd.cmd_data_out = &rsp_vbnvcontext; + cec_cmd.cmd_size_in = sizeof(cmd_vbnvcontext); + cec_cmd.cmd_size_out = is_read ? sizeof(rsp_vbnvcontext) : 0; + cec_cmd.cmd_dev_index = 0; + + cmd_vbnvcontext.op = is_read ? EC_VBNV_CONTEXT_OP_READ : + EC_VBNV_CONTEXT_OP_WRITE; + + if (!is_read) + memcpy(&cmd_vbnvcontext.block, data, EC_VBNV_BLOCK_SIZE); + + if (google_chromeec_command(&cec_cmd)) { + printk(BIOS_ERR, "ERROR: failed to %s vbnv_ec context: %d\n", + is_read ? "read" : "write", (int)cec_cmd.cmd_code); + mdelay(10); /* just in case */ + if (--retries) + goto retry; + } + + if (is_read) + memcpy(data, &rsp_vbnvcontext.block, EC_VBNV_BLOCK_SIZE); + + return cec_cmd.cmd_code; +} + +#endif /* ! __SMM__ */ + +#ifndef __PRE_RAM__ + +int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen, + uint8_t *buffer, int len, int is_read) +{ + union { + struct ec_params_i2c_passthru p; + uint8_t outbuf[EC_HOST_PARAM_SIZE]; + } params; + union { + struct ec_response_i2c_passthru r; + uint8_t inbuf[EC_HOST_PARAM_SIZE]; + } response; + struct ec_params_i2c_passthru *p = ¶ms.p; + struct ec_response_i2c_passthru *r = &response.r; + struct ec_params_i2c_passthru_msg *msg = p->msg; + struct chromeec_command cmd; + uint8_t *pdata; + int read_len, write_len; + int size; + int rv; + + p->port = 0; + + if (alen != 1) { + printk(BIOS_ERR, "Unsupported address length %d\n", alen); + return -1; + } + if (is_read) { + read_len = len; + write_len = alen; + p->num_msgs = 2; + } else { + read_len = 0; + write_len = alen + len; + p->num_msgs = 1; + } + + size = sizeof(*p) + p->num_msgs * sizeof(*msg); + if (size + write_len > sizeof(params)) { + printk(BIOS_ERR, "Params too large for buffer\n"); + return -1; + } + if (sizeof(*r) + read_len > sizeof(response)) { + printk(BIOS_ERR, "Read length too big for buffer\n"); + return -1; + } + + /* Create a message to write the register address and optional data */ + pdata = (uint8_t *)p + size; + msg->addr_flags = chip; + msg->len = write_len; + pdata[0] = addr; + if (!is_read) + memcpy(pdata + 1, buffer, len); + msg++; + + if (read_len) { + msg->addr_flags = chip | EC_I2C_FLAG_READ; + msg->len = read_len; + } + + cmd.cmd_code = EC_CMD_I2C_PASSTHRU; + cmd.cmd_version = 0; + cmd.cmd_data_in = p; + cmd.cmd_size_in = size + write_len; + cmd.cmd_data_out = r; + cmd.cmd_size_out = sizeof(*r) + read_len; + cmd.cmd_dev_index = 0; + rv = google_chromeec_command(&cmd); + if (rv != 0) + return rv; + + /* Parse response */ + if (r->i2c_status & EC_I2C_STATUS_ERROR) { + printk(BIOS_ERR, "Transfer failed with status=0x%x\n", + r->i2c_status); + return -1; + } + + if (cmd.cmd_size_out < sizeof(*r) + read_len) { + printk(BIOS_ERR, "Truncated read response\n"); + return -1; + } + + if (read_len) + memcpy(buffer, r->data, read_len); + + return 0; +} + int google_chromeec_set_sci_mask(u32 mask) { printk(BIOS_DEBUG, "Chrome EC: Set SCI mask to 0x%08x\n", mask); @@ -304,82 +387,25 @@ u32 google_chromeec_get_wake_mask(void) EC_CMD_HOST_EVENT_GET_WAKE_MASK); } -#if CONFIG_ELOG -/* Find the last port80 code from the previous boot */ -static u16 google_chromeec_get_port80_last_boot(void) -{ - struct ec_response_port80_last_boot rsp; - struct chromeec_command cmd = { - .cmd_code = EC_CMD_PORT80_LAST_BOOT, - .cmd_data_out = &rsp, - .cmd_size_out = sizeof(rsp), - }; - - /* Get last port80 code */ - if (google_chromeec_command(&cmd) == 0) - return rsp.code; - - return 0; -} -#endif - void google_chromeec_log_events(u32 mask) { #if CONFIG_ELOG u8 event; - u16 code; + u32 wake_mask; - /* Find the last port80 code */ - code = google_chromeec_get_port80_last_boot(); - - /* Log the last post code only if it is abornmal */ - if (code > 0 && code != POST_OS_BOOT && code != POST_OS_RESUME) - printk(BIOS_DEBUG, "Chrome EC: Last POST code was 0x%02x\n", - code); + /* Set wake mask so events will be read from ACPI interface */ + wake_mask = google_chromeec_get_wake_mask(); + google_chromeec_set_wake_mask(mask); while ((event = google_chromeec_get_event()) != 0) { if (EC_HOST_EVENT_MASK(event) & mask) elog_add_event_byte(ELOG_TYPE_EC_EVENT, event); } + + google_chromeec_set_wake_mask(wake_mask); #endif } -u8 google_chromeec_get_event(void) -{ - if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { - printk(BIOS_ERR, "Timeout waiting for EC ready!\n"); - return 1; - } - - /* Issue the ACPI query-event command */ - outb(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD); - - if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { - printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n"); - return 0; - } - - /* Event (or 0 if none) is returned directly in the data byte */ - return inb(EC_LPC_ADDR_ACPI_DATA); -} - -u16 google_chromeec_get_board_version(void) -{ - struct chromeec_command cmd; - struct ec_response_board_version board_v; - - cmd.cmd_code = EC_CMD_GET_BOARD_VERSION; - cmd.cmd_version = 0; - cmd.cmd_size_in = 0; - cmd.cmd_size_out = sizeof(board_v); - cmd.cmd_data_out = &board_v; - - if (google_chromeec_command(&cmd) != 0) - return 0; - - return board_v.board_version; -} - int google_chromeec_set_usb_charge_mode(u8 port_id, enum usb_charge_mode mode) { struct chromeec_command cmd; @@ -394,6 +420,7 @@ int google_chromeec_set_usb_charge_mode(u8 port_id, enum usb_charge_mode mode) cmd.cmd_data_in = &set_mode; cmd.cmd_size_out = 0; cmd.cmd_data_out = NULL; + cmd.cmd_dev_index = 0; return google_chromeec_command(&cmd); } @@ -413,6 +440,7 @@ int google_chromeec_hello(void) cec_cmd.cmd_data_out = &rsp_hello.out_data; cec_cmd.cmd_size_in = sizeof(cmd_hello.in_data); cec_cmd.cmd_size_out = sizeof(rsp_hello.out_data); + cec_cmd.cmd_dev_index = 0; google_chromeec_command(&cec_cmd); printk(BIOS_DEBUG, "Google Chrome EC: Hello got back %x status (%x)\n", rsp_hello.out_data, cec_cmd.cmd_code); @@ -421,26 +449,21 @@ int google_chromeec_hello(void) static int ec_image_type; /* Cached EC image type (ro or rw). */ -static void google_chromeec_init(device_t dev) +void google_chromeec_init(void) { struct chromeec_command cec_cmd; - struct ec_google_chromeec_config *conf = dev->chip_info; - struct ec_response_get_version lpcv_cmd; - - if (!dev->enabled) - return; + struct ec_response_get_version cec_resp = {{0}}; printk(BIOS_DEBUG, "Google Chrome EC: Initializing keyboard.\n"); - pc_keyboard_init(&conf->keyboard); google_chromeec_hello(); - memset(&lpcv_cmd, 0, sizeof(lpcv_cmd)); cec_cmd.cmd_code = EC_CMD_GET_VERSION; cec_cmd.cmd_version = 0; - cec_cmd.cmd_data_out = &lpcv_cmd; + cec_cmd.cmd_data_out = &cec_resp; cec_cmd.cmd_size_in = 0; - cec_cmd.cmd_size_out = sizeof(lpcv_cmd); + cec_cmd.cmd_size_out = sizeof(cec_resp); + cec_cmd.cmd_dev_index = 0; google_chromeec_command(&cec_cmd); if (cec_cmd.cmd_code) { @@ -448,16 +471,16 @@ static void google_chromeec_init(device_t dev) "Google Chrome EC: version command failed!\n"); } else { printk(BIOS_DEBUG, "Google Chrome EC: version:\n"); - printk(BIOS_DEBUG, " ro: %s\n", lpcv_cmd.version_string_ro); - printk(BIOS_DEBUG, " rw: %s\n", lpcv_cmd.version_string_rw); + printk(BIOS_DEBUG, " ro: %s\n", cec_resp.version_string_ro); + printk(BIOS_DEBUG, " rw: %s\n", cec_resp.version_string_rw); printk(BIOS_DEBUG, " running image: %d\n", - lpcv_cmd.current_image); - ec_image_type = lpcv_cmd.current_image; + cec_resp.current_image); + ec_image_type = cec_resp.current_image; } if (cec_cmd.cmd_code || (recovery_mode_enabled() && - (lpcv_cmd.current_image != EC_IMAGE_RO))) { + (cec_resp.current_image != EC_IMAGE_RO))) { struct ec_params_reboot_ec reboot_ec; /* Reboot the EC and make it come back in RO mode */ reboot_ec.cmd = EC_REBOOT_COLD; @@ -467,7 +490,9 @@ static void google_chromeec_init(device_t dev) cec_cmd.cmd_data_in = &reboot_ec; cec_cmd.cmd_size_in = sizeof(reboot_ec); cec_cmd.cmd_size_out = 0; /* ignore response, if any */ + cec_cmd.cmd_dev_index = 0; printk(BIOS_DEBUG, "Rebooting with EC in RO mode:\n"); + post_code(0); /* clear current post code */ google_chromeec_command(&cec_cmd); udelay(1000); hard_reset(); @@ -476,37 +501,6 @@ static void google_chromeec_init(device_t dev) } -static void google_chromeec_read_resources(device_t dev) -{ - /* Nothing, but this function avoids an error on serial console. */ -} - -static void google_chromeec_enable_resources(device_t dev) -{ - /* Nothing, but this function avoids an error on serial console. */ -} - -static struct device_operations ops = { - .init = google_chromeec_init, - .read_resources = google_chromeec_read_resources, - .enable_resources = google_chromeec_enable_resources -}; - -static struct pnp_info pnp_dev_info[] = { - { &ops, 0, 0, { 0, 0 }, } -}; - -static void enable_dev(device_t dev) -{ - pnp_enable_devices(dev, &pnp_ops, ARRAY_SIZE(pnp_dev_info), - pnp_dev_info); -} - -struct chip_operations ec_google_chromeec_ops = { - CHIP_NAME("Google Chrome EC") - .enable_dev = enable_dev, -}; - int google_ec_running_ro(void) { return (ec_image_type == EC_IMAGE_RO); diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h index f056d266e6..cdf94dae16 100644 --- a/src/ec/google/chromeec/ec.h +++ b/src/ec/google/chromeec/ec.h @@ -21,21 +21,38 @@ #ifndef _EC_GOOGLE_CHROMEEC_EC_H #define _EC_GOOGLE_CHROMEEC_EC_H +#include +#include #ifndef __PRE_RAM__ +int google_chromeec_i2c_xfer(uint8_t chip, uint8_t addr, int alen, + uint8_t *buffer, int len, int is_read); u32 google_chromeec_get_wake_mask(void); int google_chromeec_set_sci_mask(u32 mask); int google_chromeec_set_smi_mask(u32 mask); int google_chromeec_set_wake_mask(u32 mask); u8 google_chromeec_get_event(void); int google_ec_running_ro(void); -u16 google_chromeec_get_board_version(void); +void google_chromeec_init(void); #endif +#ifdef __PRE_RAM__ +/* If recovery mode is enabled and EC is not running RO firmware reboot. */ +void google_chromeec_early_init(void); +void google_chromeec_early_pd_init(void); +/* Reboot if EC firmware is not expected type. */ +void google_chromeec_check_ec_image(int expected_type); +void google_chromeec_check_pd_image(int expected_type); +#endif + +uint8_t google_chromeec_calc_checksum(const uint8_t *data, int size); +u16 google_chromeec_get_board_version(void); u32 google_chromeec_get_events_b(void); +int google_chromeec_clear_events_b(u32 mask); int google_chromeec_kbbacklight(int percent); void google_chromeec_post(u8 postcode); void google_chromeec_log_events(u32 mask); +int google_chromeec_vbnv_context(int is_read, uint8_t *data, int len); enum usb_charge_mode { USB_CHARGE_MODE_DISABLED, @@ -46,4 +63,38 @@ enum usb_charge_mode { }; int google_chromeec_set_usb_charge_mode(u8 port_id, enum usb_charge_mode mode); +/* internal structure to send a command to the EC and wait for response. */ +struct chromeec_command { + uint16_t cmd_code; /* command code in, status out */ + uint8_t cmd_version; /* command version */ + const void* cmd_data_in; /* command data, if any */ + void* cmd_data_out; /* command response, if any */ + uint16_t cmd_size_in; /* size of command data */ + uint16_t cmd_size_out; /* expected size of command response in, + * actual received size out */ + int cmd_dev_index;/* device index for passthru */ +}; + +/* + * There are transport level constraints for sending protov3 packets. Because + * of this provide a way for the generic protocol layer to request buffers + * so that there is zero copying being done through the layers. + * + * Request the buffer provided the size. If 'req' is non-zero then the + * buffer requested is for EC requests. Otherwise it's for responses. Return + * non-NULL on success, NULL on error. + */ +void *crosec_get_buffer(size_t size, int req); + +/* + * The lower level transport works on the buffers handed out to the + * upper level. Therefore, only the size of the request and response + * are required. + */ +typedef int (*crosec_io_t)(size_t req_size, size_t resp_size, void *context); +int crosec_command_proto(struct chromeec_command *cec_command, + crosec_io_t crosec_io, void *context); + +int google_chromeec_command(struct chromeec_command *cec_command); + #endif /* _EC_GOOGLE_CHROMEEC_EC_H */ diff --git a/src/ec/google/chromeec/ec_commands.h b/src/ec/google/chromeec/ec_commands.h index c1b19bcf1a..1339d328eb 100644 --- a/src/ec/google/chromeec/ec_commands.h +++ b/src/ec/google/chromeec/ec_commands.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,25 +9,12 @@ #define __CROS_EC_COMMANDS_H /* - * Protocol overview + * Current version of this protocol * - * request: CMD [ P0 P1 P2 ... Pn S ] - * response: ERR [ P0 P1 P2 ... Pn S ] - * - * where the bytes are defined as follow : - * - CMD is the command code. (defined by EC_CMD_ constants) - * - ERR is the error code. (defined by EC_RES_ constants) - * - Px is the optional payload. - * it is not sent if the error code is not success. - * (defined by ec_params_ and ec_response_ structures) - * - S is the checksum which is the sum of all payload bytes. - * - * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD - * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM. - * On I2C, all bytes are sent serially in the same message. + * TODO(crosbug.com/p/11223): This is effectively useless; protocol is + * determined in other ways. Remove this once the kernel code no longer + * depends on it. */ - -/* Current version of this protocol */ #define EC_PROTO_VERSION 0x00000002 /* Command version mask */ @@ -42,13 +29,19 @@ #define EC_LPC_ADDR_HOST_CMD 0x204 /* I/O addresses for host command args and params */ -#define EC_LPC_ADDR_HOST_ARGS 0x800 -#define EC_LPC_ADDR_HOST_PARAM 0x804 -#define EC_HOST_PARAM_SIZE 0x0fc /* Size of param area in bytes */ +/* Protocol version 2 */ +#define EC_LPC_ADDR_HOST_ARGS 0x800 /* And 0x801, 0x802, 0x803 */ +#define EC_LPC_ADDR_HOST_PARAM 0x804 /* For version 2 params; size is + * EC_PROTO2_MAX_PARAM_SIZE */ +/* Protocol version 3 */ +#define EC_LPC_ADDR_HOST_PACKET 0x800 /* Offset of version 3 packet */ +#define EC_LPC_HOST_PACKET_SIZE 0x100 /* Max size of version 3 packet */ -/* I/O addresses for host command params, old interface */ -#define EC_LPC_ADDR_OLD_PARAM 0x880 -#define EC_OLD_PARAM_SIZE 0x080 /* Size of param area in bytes */ +/* The actual block is 0x800-0x8ff, but some BIOSes think it's 0x880-0x8ff + * and they tell the kernel that so we have to think of it as two parts. */ +#define EC_HOST_CMD_REGION0 0x800 +#define EC_HOST_CMD_REGION1 0x880 +#define EC_HOST_CMD_REGION_SIZE 0x80 /* EC command register bit functions */ #define EC_LPC_CMDR_DATA (1 << 0) /* Data ready for host to read */ @@ -64,18 +57,22 @@ #define EC_MEMMAP_TEXT_MAX 8 /* Size of a string in the memory map */ /* The offset address of each type of data in mapped memory. */ -#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors */ -#define EC_MEMMAP_FAN 0x10 /* Fan speeds */ -#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* Temp sensors (second set) */ -#define EC_MEMMAP_ID 0x20 /* 'E' 'C' */ +#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors 0x00 - 0x0f */ +#define EC_MEMMAP_FAN 0x10 /* Fan speeds 0x10 - 0x17 */ +#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* More temp sensors 0x18 - 0x1f */ +#define EC_MEMMAP_ID 0x20 /* 0x20 == 'E', 0x21 == 'C' */ #define EC_MEMMAP_ID_VERSION 0x22 /* Version of data in 0x20 - 0x2f */ #define EC_MEMMAP_THERMAL_VERSION 0x23 /* Version of data in 0x00 - 0x1f */ #define EC_MEMMAP_BATTERY_VERSION 0x24 /* Version of data in 0x40 - 0x7f */ #define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */ #define EC_MEMMAP_EVENTS_VERSION 0x26 /* Version of data in 0x34 - 0x3f */ -#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host command interface flags */ -#define EC_MEMMAP_SWITCHES 0x30 -#define EC_MEMMAP_HOST_EVENTS 0x34 +#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host cmd interface flags (8 bits) */ +/* Unused 0x28 - 0x2f */ +#define EC_MEMMAP_SWITCHES 0x30 /* 8 bits */ +/* Unused 0x31 - 0x33 */ +#define EC_MEMMAP_HOST_EVENTS 0x34 /* 32 bits */ +/* Reserve 0x38 - 0x3f for additional host event-related stuff */ +/* Battery values are all 32 bits */ #define EC_MEMMAP_BATT_VOLT 0x40 /* Battery Present Voltage */ #define EC_MEMMAP_BATT_RATE 0x44 /* Battery Present Rate */ #define EC_MEMMAP_BATT_CAP 0x48 /* Battery Remaining Capacity */ @@ -84,10 +81,24 @@ #define EC_MEMMAP_BATT_DVLT 0x54 /* Battery Design Voltage */ #define EC_MEMMAP_BATT_LFCC 0x58 /* Battery Last Full Charge Capacity */ #define EC_MEMMAP_BATT_CCNT 0x5c /* Battery Cycle Count */ +/* Strings are all 8 bytes (EC_MEMMAP_TEXT_MAX) */ #define EC_MEMMAP_BATT_MFGR 0x60 /* Battery Manufacturer String */ #define EC_MEMMAP_BATT_MODEL 0x68 /* Battery Model Number String */ #define EC_MEMMAP_BATT_SERIAL 0x70 /* Battery Serial Number String */ #define EC_MEMMAP_BATT_TYPE 0x78 /* Battery Type String */ +#define EC_MEMMAP_ALS 0x80 /* ALS readings in lux (2 X 16 bits) */ +/* Unused 0x84 - 0x8f */ +#define EC_MEMMAP_ACC_STATUS 0x90 /* Accelerometer status (8 bits )*/ +/* Unused 0x91 */ +#define EC_MEMMAP_ACC_DATA 0x92 /* Accelerometer data 0x92 - 0x9f */ +#define EC_MEMMAP_GYRO_DATA 0xa0 /* Gyroscope data 0xa0 - 0xa5 */ +/* Unused 0xa6 - 0xfe (remember, 0xff is NOT part of the memmap region) */ + + +/* Define the format of the accelerometer mapped memory status byte. */ +#define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f +#define EC_MEMMAP_ACC_STATUS_BUSY_BIT (1 << 4) +#define EC_MEMMAP_ACC_STATUS_PRESENCE_BIT (1 << 7) /* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */ #define EC_TEMP_SENSOR_ENTRIES 16 @@ -96,16 +107,31 @@ * * Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2. */ -#define EC_TEMP_SENSOR_B_ENTRIES 8 -#define EC_TEMP_SENSOR_NOT_PRESENT 0xff -#define EC_TEMP_SENSOR_ERROR 0xfe -#define EC_TEMP_SENSOR_NOT_POWERED 0xfd +#define EC_TEMP_SENSOR_B_ENTRIES 8 + +/* Special values for mapped temperature sensors */ +#define EC_TEMP_SENSOR_NOT_PRESENT 0xff +#define EC_TEMP_SENSOR_ERROR 0xfe +#define EC_TEMP_SENSOR_NOT_POWERED 0xfd +#define EC_TEMP_SENSOR_NOT_CALIBRATED 0xfc /* * The offset of temperature value stored in mapped memory. This allows * reporting a temperature range of 200K to 454K = -73C to 181C. */ #define EC_TEMP_SENSOR_OFFSET 200 +/* + * Number of ALS readings at EC_MEMMAP_ALS + */ +#define EC_ALS_ENTRIES 2 + +/* + * The default value a temperature sensor will return when it is present but + * has not been read this boot. This is a reasonable number to avoid + * triggering alarms on the host. + */ +#define EC_TEMP_SENSOR_DEFAULT (296 - EC_TEMP_SENSOR_OFFSET) + #define EC_FAN_SPEED_ENTRIES 4 /* Number of fans at EC_MEMMAP_FAN */ #define EC_FAN_SPEED_NOT_PRESENT 0xffff /* Entry not present */ #define EC_FAN_SPEED_STALLED 0xfffe /* Fan stalled */ @@ -121,8 +147,8 @@ #define EC_SWITCH_LID_OPEN 0x01 #define EC_SWITCH_POWER_BUTTON_PRESSED 0x02 #define EC_SWITCH_WRITE_PROTECT_DISABLED 0x04 -/* Recovery requested via keyboard */ -#define EC_SWITCH_KEYBOARD_RECOVERY 0x08 +/* Was recovery requested via keyboard; now unused. */ +#define EC_SWITCH_IGNORE1 0x08 /* Recovery requested via dedicated signal (from servo board) */ #define EC_SWITCH_DEDICATED_RECOVERY 0x10 /* Was fake developer mode switch; now unused. Remove in next refactor. */ @@ -131,10 +157,15 @@ /* Host command interface flags */ /* Host command interface supports LPC args (LPC interface only) */ #define EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED 0x01 +/* Host command interface supports version 3 protocol */ +#define EC_HOST_CMD_FLAG_VERSION_3 0x02 /* Wireless switch flags */ -#define EC_WIRELESS_SWITCH_WLAN 0x01 -#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02 +#define EC_WIRELESS_SWITCH_ALL ~0x00 /* All flags */ +#define EC_WIRELESS_SWITCH_WLAN 0x01 /* WLAN radio */ +#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02 /* Bluetooth radio */ +#define EC_WIRELESS_SWITCH_WWAN 0x04 /* WWAN power */ +#define EC_WIRELESS_SWITCH_WLAN_POWER 0x08 /* WLAN power */ /* * This header file is used in coreboot both in C and ACPI code. The ACPI code @@ -186,6 +217,14 @@ enum ec_status { EC_RES_INVALID_RESPONSE = 5, EC_RES_INVALID_VERSION = 6, EC_RES_INVALID_CHECKSUM = 7, + EC_RES_IN_PROGRESS = 8, /* Accepted, command in progress */ + EC_RES_UNAVAILABLE = 9, /* No response available */ + EC_RES_TIMEOUT = 10, /* We got a timeout */ + EC_RES_OVERFLOW = 11, /* Table / data overflow */ + EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */ + EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */ + EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */ + EC_RES_BUS_ERROR = 15 /* Communications bus error */ }; /* @@ -223,6 +262,22 @@ enum host_event_code { /* Shutdown due to battery level too low */ EC_HOST_EVENT_BATTERY_SHUTDOWN = 17, + /* Suggest that the AP throttle itself */ + EC_HOST_EVENT_THROTTLE_START = 18, + /* Suggest that the AP resume normal speed */ + EC_HOST_EVENT_THROTTLE_STOP = 19, + + /* Hang detect logic detected a hang and host event timeout expired */ + EC_HOST_EVENT_HANG_DETECT = 20, + /* Hang detect logic detected a hang and warm rebooted the AP */ + EC_HOST_EVENT_HANG_REBOOT = 21, + + /* PD MCU triggering host event */ + EC_HOST_EVENT_PD_MCU = 22, + + /* Battery Status flags have changed */ + EC_HOST_EVENT_BATTERY_STATUS = 23, + /* * The high bit of the event mask is not used as a host event code. If * it reads back as set, then the entire event mask should be @@ -267,10 +322,192 @@ struct ec_lpc_host_args { */ #define EC_HOST_ARGS_FLAG_TO_HOST 0x02 +/*****************************************************************************/ +/* + * Byte codes returned by EC over SPI interface. + * + * These can be used by the AP to debug the EC interface, and to determine + * when the EC is not in a state where it will ever get around to responding + * to the AP. + * + * Example of sequence of bytes read from EC for a current good transfer: + * 1. - - AP asserts chip select (CS#) + * 2. EC_SPI_OLD_READY - AP sends first byte(s) of request + * 3. - - EC starts handling CS# interrupt + * 4. EC_SPI_RECEIVING - AP sends remaining byte(s) of request + * 5. EC_SPI_PROCESSING - EC starts processing request; AP is clocking in + * bytes looking for EC_SPI_FRAME_START + * 6. - - EC finishes processing and sets up response + * 7. EC_SPI_FRAME_START - AP reads frame byte + * 8. (response packet) - AP reads response packet + * 9. EC_SPI_PAST_END - Any additional bytes read by AP + * 10 - - AP deasserts chip select + * 11 - - EC processes CS# interrupt and sets up DMA for + * next request + * + * If the AP is waiting for EC_SPI_FRAME_START and sees any value other than + * the following byte values: + * EC_SPI_OLD_READY + * EC_SPI_RX_READY + * EC_SPI_RECEIVING + * EC_SPI_PROCESSING + * + * Then the EC found an error in the request, or was not ready for the request + * and lost data. The AP should give up waiting for EC_SPI_FRAME_START, + * because the EC is unable to tell when the AP is done sending its request. + */ + +/* + * Framing byte which precedes a response packet from the EC. After sending a + * request, the AP will clock in bytes until it sees the framing byte, then + * clock in the response packet. + */ +#define EC_SPI_FRAME_START 0xec + +/* + * Padding bytes which are clocked out after the end of a response packet. + */ +#define EC_SPI_PAST_END 0xed + +/* + * EC is ready to receive, and has ignored the byte sent by the AP. EC expects + * that the AP will send a valid packet header (starting with + * EC_COMMAND_PROTOCOL_3) in the next 32 bytes. + */ +#define EC_SPI_RX_READY 0xf8 + +/* + * EC has started receiving the request from the AP, but hasn't started + * processing it yet. + */ +#define EC_SPI_RECEIVING 0xf9 + +/* EC has received the entire request from the AP and is processing it. */ +#define EC_SPI_PROCESSING 0xfa + +/* + * EC received bad data from the AP, such as a packet header with an invalid + * length. EC will ignore all data until chip select deasserts. + */ +#define EC_SPI_RX_BAD_DATA 0xfb + +/* + * EC received data from the AP before it was ready. That is, the AP asserted + * chip select and started clocking data before the EC was ready to receive it. + * EC will ignore all data until chip select deasserts. + */ +#define EC_SPI_NOT_READY 0xfc + +/* + * EC was ready to receive a request from the AP. EC has treated the byte sent + * by the AP as part of a request packet, or (for old-style ECs) is processing + * a fully received packet but is not ready to respond yet. + */ +#define EC_SPI_OLD_READY 0xfd + +/*****************************************************************************/ + +/* + * Protocol version 2 for I2C and SPI send a request this way: + * + * 0 EC_CMD_VERSION0 + (command version) + * 1 Command number + * 2 Length of params = N + * 3..N+2 Params, if any + * N+3 8-bit checksum of bytes 0..N+2 + * + * The corresponding response is: + * + * 0 Result code (EC_RES_*) + * 1 Length of params = M + * 2..M+1 Params, if any + * M+2 8-bit checksum of bytes 0..M+1 + */ +#define EC_PROTO2_REQUEST_HEADER_BYTES 3 +#define EC_PROTO2_REQUEST_TRAILER_BYTES 1 +#define EC_PROTO2_REQUEST_OVERHEAD (EC_PROTO2_REQUEST_HEADER_BYTES + \ + EC_PROTO2_REQUEST_TRAILER_BYTES) + +#define EC_PROTO2_RESPONSE_HEADER_BYTES 2 +#define EC_PROTO2_RESPONSE_TRAILER_BYTES 1 +#define EC_PROTO2_RESPONSE_OVERHEAD (EC_PROTO2_RESPONSE_HEADER_BYTES + \ + EC_PROTO2_RESPONSE_TRAILER_BYTES) + +/* Parameter length was limited by the LPC interface */ +#define EC_PROTO2_MAX_PARAM_SIZE 0xfc + +/* Maximum request and response packet sizes for protocol version 2 */ +#define EC_PROTO2_MAX_REQUEST_SIZE (EC_PROTO2_REQUEST_OVERHEAD + \ + EC_PROTO2_MAX_PARAM_SIZE) +#define EC_PROTO2_MAX_RESPONSE_SIZE (EC_PROTO2_RESPONSE_OVERHEAD + \ + EC_PROTO2_MAX_PARAM_SIZE) + +/*****************************************************************************/ + +/* + * Value written to legacy command port / prefix byte to indicate protocol + * 3+ structs are being used. Usage is bus-dependent. + */ +#define EC_COMMAND_PROTOCOL_3 0xda + +#define EC_HOST_REQUEST_VERSION 3 + +/* Version 3 request from host */ +struct ec_host_request { + /* Struct version (=3) + * + * EC will return EC_RES_INVALID_HEADER if it receives a header with a + * version it doesn't know how to parse. + */ + uint8_t struct_version; + + /* + * Checksum of request and data; sum of all bytes including checksum + * should total to 0. + */ + uint8_t checksum; + + /* Command code */ + uint16_t command; + + /* Command version */ + uint8_t command_version; + + /* Unused byte in current protocol version; set to 0 */ + uint8_t reserved; + + /* Length of data which follows this header */ + uint16_t data_len; +} __packed; + +#define EC_HOST_RESPONSE_VERSION 3 + +/* Version 3 response from EC */ +struct ec_host_response { + /* Struct version (=3) */ + uint8_t struct_version; + + /* + * Checksum of response and data; sum of all bytes including checksum + * should total to 0. + */ + uint8_t checksum; + + /* Result code (EC_RES_*) */ + uint16_t result; + + /* Length of data which follows this header */ + uint16_t data_len; + + /* Unused bytes in current protocol version; set to 0 */ + uint16_t reserved; +} __packed; + +/*****************************************************************************/ /* * Notes on commands: * - * Each command is an 8-byte command value. Commands which take params or + * Each command is an 16-bit command value. Commands which take params or * return response data specify structs for that data. If no struct is * specified, the command does not input or output data, respectively. * Parameter/response length is implicit in the structs. Some underlying @@ -388,12 +625,94 @@ struct ec_response_get_cmd_versions { uint32_t version_mask; } __packed; +/* + * Check EC communcations status (busy). This is needed on i2c/spi but not + * on lpc since it has its own out-of-band busy indicator. + * + * lpc must read the status from the command register. Attempting this on + * lpc will overwrite the args/parameter space and corrupt its data. + */ +#define EC_CMD_GET_COMMS_STATUS 0x09 + +/* Avoid using ec_status which is for return values */ +enum ec_comms_status { + EC_COMMS_STATUS_PROCESSING = 1 << 0, /* Processing cmd */ +}; + +struct ec_response_get_comms_status { + uint32_t flags; /* Mask of enum ec_comms_status */ +} __packed; + +/* Fake a variety of responses, purely for testing purposes. */ +#define EC_CMD_TEST_PROTOCOL 0x0a + +/* Tell the EC what to send back to us. */ +struct ec_params_test_protocol { + uint32_t ec_result; + uint32_t ret_len; + uint8_t buf[32]; +} __packed; + +/* Here it comes... */ +struct ec_response_test_protocol { + uint8_t buf[32]; +} __packed; + +/* Get prococol information */ +#define EC_CMD_GET_PROTOCOL_INFO 0x0b + +/* Flags for ec_response_get_protocol_info.flags */ +/* EC_RES_IN_PROGRESS may be returned if a command is slow */ +#define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0) + +struct ec_response_get_protocol_info { + /* Fields which exist if at least protocol version 3 supported */ + + /* Bitmask of protocol versions supported (1 << n means version n)*/ + uint32_t protocol_versions; + + /* Maximum request packet size, in bytes */ + uint16_t max_request_packet_size; + + /* Maximum response packet size, in bytes */ + uint16_t max_response_packet_size; + + /* Flags; see EC_PROTOCOL_INFO_* */ + uint32_t flags; +} __packed; + + +/*****************************************************************************/ +/* Get/Set miscellaneous values */ + +/* The upper byte of .flags tells what to do (nothing means "get") */ +#define EC_GSV_SET 0x80000000 + +/* The lower three bytes of .flags identifies the parameter, if that has + meaning for an individual command. */ +#define EC_GSV_PARAM_MASK 0x00ffffff + +struct ec_params_get_set_value { + uint32_t flags; + uint32_t value; +} __packed; + +struct ec_response_get_set_value { + uint32_t flags; + uint32_t value; +} __packed; + +/* More than one command can use these structs to get/set paramters. */ +#define EC_CMD_GSV_PAUSE_IN_S5 0x0c + + /*****************************************************************************/ /* Flash commands */ /* Get flash info */ #define EC_CMD_FLASH_INFO 0x10 +/* Version 0 returns these fields */ struct ec_response_flash_info { /* Usable flash size, in bytes */ uint32_t flash_size; @@ -414,6 +733,37 @@ struct ec_response_flash_info { uint32_t protect_block_size; } __packed; +/* Flags for version 1+ flash info command */ +/* EC flash erases bits to 0 instead of 1 */ +#define EC_FLASH_INFO_ERASE_TO_0 (1 << 0) + +/* + * Version 1 returns the same initial fields as version 0, with additional + * fields following. + * + * gcc anonymous structs don't seem to get along with the __packed directive; + * if they did we'd define the version 0 struct as a sub-struct of this one. + */ +struct ec_response_flash_info_1 { + /* Version 0 fields; see above for description */ + uint32_t flash_size; + uint32_t write_block_size; + uint32_t erase_block_size; + uint32_t protect_block_size; + + /* Version 1 adds these fields: */ + /* + * Ideal write size in bytes. Writes will be fastest if size is + * exactly this and offset is a multiple of this. For example, an EC + * may have a write buffer which can do half-page operations if data is + * aligned, and a slower word-at-a-time write mode. + */ + uint32_t write_ideal_size; + + /* Flags; see EC_FLASH_INFO_* */ + uint32_t flags; +} __packed; + /* * Read flash * @@ -428,15 +778,15 @@ struct ec_params_flash_read { /* Write flash */ #define EC_CMD_FLASH_WRITE 0x12 +#define EC_VER_FLASH_WRITE 1 + +/* Version 0 of the flash command supported only 64 bytes of data */ +#define EC_FLASH_WRITE_VER0_SIZE 64 struct ec_params_flash_write { uint32_t offset; /* Byte offset to write */ uint32_t size; /* Size to write in bytes */ - /* - * Data to write. Could really use EC_PARAM_SIZE - 8, but tidiest to - * use a power of 2 so writes stay aligned. - */ - uint8_t data[64]; + /* Followed by data to write */ } __packed; /* Erase flash */ @@ -468,8 +818,8 @@ struct ec_params_flash_erase { * be changed. */ #define EC_FLASH_PROTECT_RO_NOW (1 << 1) -/* RW flash code protected now, until reboot. */ -#define EC_FLASH_PROTECT_RW_NOW (1 << 2) +/* Entire flash code protected now, until reboot. */ +#define EC_FLASH_PROTECT_ALL_NOW (1 << 2) /* Flash write protect GPIO is asserted now */ #define EC_FLASH_PROTECT_GPIO_ASSERTED (1 << 3) /* Error - at least one bank of flash is stuck locked, and cannot be unlocked */ @@ -480,8 +830,8 @@ struct ec_params_flash_erase { * re-requesting the desired flags, or by a hard reset if that fails. */ #define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5) -/* RW flash code protected when the EC boots */ -#define EC_FLASH_PROTECT_RW_AT_BOOT (1 << 6) +/* Entile flash code protected when the EC boots */ +#define EC_FLASH_PROTECT_ALL_AT_BOOT (1 << 6) struct ec_params_flash_protect { uint32_t mask; /* Bits in flags to apply */ @@ -512,7 +862,7 @@ struct ec_response_flash_protect { enum ec_flash_region { /* Region which holds read-only EC image */ - EC_FLASH_REGION_RO, + EC_FLASH_REGION_RO = 0, /* Region which holds rewritable EC image */ EC_FLASH_REGION_RW, /* @@ -520,6 +870,8 @@ enum ec_flash_region { * EC_FLASH_REGION_RO) */ EC_FLASH_REGION_WP_RO, + /* Number of regions */ + EC_FLASH_REGION_COUNT, }; struct ec_params_flash_region_info { @@ -531,6 +883,24 @@ struct ec_response_flash_region_info { uint32_t size; } __packed; +/* Read/write VbNvContext */ +#define EC_CMD_VBNV_CONTEXT 0x17 +#define EC_VER_VBNV_CONTEXT 1 +#define EC_VBNV_BLOCK_SIZE 16 + +enum ec_vbnvcontext_op { + EC_VBNV_CONTEXT_OP_READ, + EC_VBNV_CONTEXT_OP_WRITE, +}; + +struct ec_params_vbnvcontext { + uint32_t op; + uint8_t block[EC_VBNV_BLOCK_SIZE]; +} __packed; + +struct ec_response_vbnvcontext { + uint8_t block[EC_VBNV_BLOCK_SIZE]; +} __packed; /*****************************************************************************/ /* PWM commands */ @@ -573,52 +943,244 @@ struct ec_params_pwm_set_fan_duty { /*****************************************************************************/ /* - * Lightbar commands. This looks worse than it is. Since we only use one LPC + * Lightbar commands. This looks worse than it is. Since we only use one HOST * command to say "talk to the lightbar", we put the "and tell it to do X" part * into a subcommand. We'll make separate structs for subcommands with * different input args, so that we know how much to expect. */ #define EC_CMD_LIGHTBAR_CMD 0x28 -struct ec_params_lightbar_cmd { - union { - union { - uint8_t cmd; - struct { - uint8_t cmd; - } dump, off, on, init, get_seq; - struct num { - uint8_t cmd; - uint8_t num; - } brightness, seq; +struct rgb_s { + uint8_t r, g, b; +}; - struct reg { - uint8_t cmd; - uint8_t ctrl, reg, value; - } reg; - struct rgb { - uint8_t cmd; - uint8_t led, red, green, blue; - } rgb; - } in; - union { - struct dump { - struct { - uint8_t reg; - uint8_t ic0; - uint8_t ic1; - } vals[23]; - } dump; - struct get_seq { - uint8_t num; - } get_seq; - struct { - /* no return params */ - } off, on, init, brightness, seq, reg, rgb; - } out; +#define LB_BATTERY_LEVELS 4 +/* List of tweakable parameters. NOTE: It's __packed so it can be sent in a + * host command, but the alignment is the same regardless. Keep it that way. + */ +struct lightbar_params_v0 { + /* Timing */ + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; + + /* Oscillation */ + uint8_t new_s0; + uint8_t osc_min[2]; /* AC=0/1 */ + uint8_t osc_max[2]; /* AC=0/1 */ + uint8_t w_ofs[2]; /* AC=0/1 */ + + /* Brightness limits based on the backlight and AC. */ + uint8_t bright_bl_off_fixed[2]; /* AC=0/1 */ + uint8_t bright_bl_on_min[2]; /* AC=0/1 */ + uint8_t bright_bl_on_max[2]; /* AC=0/1 */ + + /* Battery level thresholds */ + uint8_t battery_threshold[LB_BATTERY_LEVELS - 1]; + + /* Map [AC][battery_level] to color index */ + uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ + uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + + /* Color palette */ + struct rgb_s color[8]; /* 0-3 are Google colors */ +} __packed; + +struct lightbar_params_v1 { + /* Timing */ + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; + int32_t tap_tick_delay; + int32_t tap_display_time; + + /* Tap-for-battery params */ + uint8_t tap_pct_red; + uint8_t tap_pct_green; + uint8_t tap_seg_min_on; + uint8_t tap_seg_max_on; + uint8_t tap_seg_osc; + uint8_t tap_idx[3]; + + /* Oscillation */ + uint8_t osc_min[2]; /* AC=0/1 */ + uint8_t osc_max[2]; /* AC=0/1 */ + uint8_t w_ofs[2]; /* AC=0/1 */ + + /* Brightness limits based on the backlight and AC. */ + uint8_t bright_bl_off_fixed[2]; /* AC=0/1 */ + uint8_t bright_bl_on_min[2]; /* AC=0/1 */ + uint8_t bright_bl_on_max[2]; /* AC=0/1 */ + + /* Battery level thresholds */ + uint8_t battery_threshold[LB_BATTERY_LEVELS - 1]; + + /* Map [AC][battery_level] to color index */ + uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ + uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + + /* Color palette */ + struct rgb_s color[8]; /* 0-3 are Google colors */ +} __packed; + +/* Lightbyte program. */ +#define LB_PROG_LEN 192 +struct lb_program { + uint8_t size; + uint8_t data[LB_PROG_LEN]; +}; + +struct ec_params_lightbar { + uint8_t cmd; /* Command (see enum lightbar_command) */ + union { + struct { + /* no args */ + } dump, off, on, init, get_seq, get_params_v0, get_params_v1, + version, get_brightness, get_demo; + + struct { + uint8_t num; + } set_brightness, seq, demo; + + struct { + uint8_t ctrl, reg, value; + } reg; + + struct { + uint8_t led, red, green, blue; + } set_rgb; + + struct { + uint8_t led; + } get_rgb; + + struct lightbar_params_v0 set_params_v0; + struct lightbar_params_v1 set_params_v1; + struct lb_program set_program; }; } __packed; +struct ec_response_lightbar { + union { + struct { + struct { + uint8_t reg; + uint8_t ic0; + uint8_t ic1; + } vals[23]; + } dump; + + struct { + uint8_t num; + } get_seq, get_brightness, get_demo; + + struct lightbar_params_v0 get_params_v0; + struct lightbar_params_v1 get_params_v1; + + struct { + uint32_t num; + uint32_t flags; + } version; + + struct { + uint8_t red, green, blue; + } get_rgb; + + struct { + /* no return params */ + } off, on, init, set_brightness, seq, reg, set_rgb, + demo, set_params_v0, set_params_v1, + set_program; + }; +} __packed; + +/* Lightbar commands */ +enum lightbar_command { + LIGHTBAR_CMD_DUMP = 0, + LIGHTBAR_CMD_OFF = 1, + LIGHTBAR_CMD_ON = 2, + LIGHTBAR_CMD_INIT = 3, + LIGHTBAR_CMD_SET_BRIGHTNESS = 4, + LIGHTBAR_CMD_SEQ = 5, + LIGHTBAR_CMD_REG = 6, + LIGHTBAR_CMD_SET_RGB = 7, + LIGHTBAR_CMD_GET_SEQ = 8, + LIGHTBAR_CMD_DEMO = 9, + LIGHTBAR_CMD_GET_PARAMS_V0 = 10, + LIGHTBAR_CMD_SET_PARAMS_V0 = 11, + LIGHTBAR_CMD_VERSION = 12, + LIGHTBAR_CMD_GET_BRIGHTNESS = 13, + LIGHTBAR_CMD_GET_RGB = 14, + LIGHTBAR_CMD_GET_DEMO = 15, + LIGHTBAR_CMD_GET_PARAMS_V1 = 16, + LIGHTBAR_CMD_SET_PARAMS_V1 = 17, + LIGHTBAR_CMD_SET_PROGRAM = 18, + LIGHTBAR_NUM_CMDS +}; + +/*****************************************************************************/ +/* LED control commands */ + +#define EC_CMD_LED_CONTROL 0x29 + +enum ec_led_id { + /* LED to indicate battery state of charge */ + EC_LED_ID_BATTERY_LED = 0, + /* + * LED to indicate system power state (on or in suspend). + * May be on power button or on C-panel. + */ + EC_LED_ID_POWER_LED, + /* LED on power adapter or its plug */ + EC_LED_ID_ADAPTER_LED, + + EC_LED_ID_COUNT +}; + +/* LED control flags */ +#define EC_LED_FLAGS_QUERY (1 << 0) /* Query LED capability only */ +#define EC_LED_FLAGS_AUTO (1 << 1) /* Switch LED back to automatic control */ + +enum ec_led_colors { + EC_LED_COLOR_RED = 0, + EC_LED_COLOR_GREEN, + EC_LED_COLOR_BLUE, + EC_LED_COLOR_YELLOW, + EC_LED_COLOR_WHITE, + + EC_LED_COLOR_COUNT +}; + +struct ec_params_led_control { + uint8_t led_id; /* Which LED to control */ + uint8_t flags; /* Control flags */ + + uint8_t brightness[EC_LED_COLOR_COUNT]; +} __packed; + +struct ec_response_led_control { + /* + * Available brightness value range. + * + * Range 0 means color channel not present. + * Range 1 means on/off control. + * Other values means the LED is control by PWM. + */ + uint8_t brightness_range[EC_LED_COLOR_COUNT]; +} __packed; + /*****************************************************************************/ /* Verified boot commands */ @@ -651,22 +1213,206 @@ struct ec_response_vboot_hash { } __packed; enum ec_vboot_hash_cmd { - EC_VBOOT_HASH_GET, /* Get current hash status */ - EC_VBOOT_HASH_ABORT, /* Abort calculating current hash */ - EC_VBOOT_HASH_START, /* Start computing a new hash */ - EC_VBOOT_HASH_RECALC, /* Synchronously compute a new hash */ + EC_VBOOT_HASH_GET = 0, /* Get current hash status */ + EC_VBOOT_HASH_ABORT = 1, /* Abort calculating current hash */ + EC_VBOOT_HASH_START = 2, /* Start computing a new hash */ + EC_VBOOT_HASH_RECALC = 3, /* Synchronously compute a new hash */ }; enum ec_vboot_hash_type { - EC_VBOOT_HASH_TYPE_SHA256, /* SHA-256 */ + EC_VBOOT_HASH_TYPE_SHA256 = 0, /* SHA-256 */ }; enum ec_vboot_hash_status { - EC_VBOOT_HASH_STATUS_NONE, /* No hash (not started, or aborted) */ - EC_VBOOT_HASH_STATUS_DONE, /* Finished computing a hash */ - EC_VBOOT_HASH_STATUS_BUSY, /* Busy computing a hash */ + EC_VBOOT_HASH_STATUS_NONE = 0, /* No hash (not started, or aborted) */ + EC_VBOOT_HASH_STATUS_DONE = 1, /* Finished computing a hash */ + EC_VBOOT_HASH_STATUS_BUSY = 2, /* Busy computing a hash */ }; +/* + * Special values for offset for EC_VBOOT_HASH_START and EC_VBOOT_HASH_RECALC. + * If one of these is specified, the EC will automatically update offset and + * size to the correct values for the specified image (RO or RW). + */ +#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe +#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd + +/*****************************************************************************/ +/* + * Motion sense commands. We'll make separate structs for sub-commands with + * different input args, so that we know how much to expect. + */ +#define EC_CMD_MOTION_SENSE_CMD 0x2B + +/* Motion sense commands */ +enum motionsense_command { + /* + * Dump command returns all motion sensor data including motion sense + * module flags and individual sensor flags. + */ + MOTIONSENSE_CMD_DUMP = 0, + + /* + * Info command returns data describing the details of a given sensor, + * including enum motionsensor_type, enum motionsensor_location, and + * enum motionsensor_chip. + */ + MOTIONSENSE_CMD_INFO = 1, + + /* + * EC Rate command is a setter/getter command for the EC sampling rate + * of all motion sensors in milliseconds. + */ + MOTIONSENSE_CMD_EC_RATE = 2, + + /* + * Sensor ODR command is a setter/getter command for the output data + * rate of a specific motion sensor in millihertz. + */ + MOTIONSENSE_CMD_SENSOR_ODR = 3, + + /* + * Sensor range command is a setter/getter command for the range of + * a specified motion sensor in +/-G's or +/- deg/s. + */ + MOTIONSENSE_CMD_SENSOR_RANGE = 4, + + /* + * Setter/getter command for the keyboard wake angle. When the lid + * angle is greater than this value, keyboard wake is disabled in S3, + * and when the lid angle goes less than this value, keyboard wake is + * enabled. Note, the lid angle measurement is an approximate, + * un-calibrated value, hence the wake angle isn't exact. + */ + MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5, + + /* Number of motionsense sub-commands. */ + MOTIONSENSE_NUM_CMDS +}; + +enum motionsensor_id { + EC_MOTION_SENSOR_ACCEL_BASE = 0, + EC_MOTION_SENSOR_ACCEL_LID = 1, + EC_MOTION_SENSOR_GYRO = 2, + + /* + * Note, if more sensors are added and this count changes, the padding + * in ec_response_motion_sense dump command must be modified. + */ + EC_MOTION_SENSOR_COUNT = 3 +}; + +/* List of motion sensor types. */ +enum motionsensor_type { + MOTIONSENSE_TYPE_ACCEL = 0, + MOTIONSENSE_TYPE_GYRO = 1, +}; + +/* List of motion sensor locations. */ +enum motionsensor_location { + MOTIONSENSE_LOC_BASE = 0, + MOTIONSENSE_LOC_LID = 1, +}; + +/* List of motion sensor chips. */ +enum motionsensor_chip { + MOTIONSENSE_CHIP_KXCJ9 = 0, + MOTIONSENSE_CHIP_LSM6DS0 = 1, +}; + +/* Module flag masks used for the dump sub-command. */ +#define MOTIONSENSE_MODULE_FLAG_ACTIVE (1<<0) + +/* Sensor flag masks used for the dump sub-command. */ +#define MOTIONSENSE_SENSOR_FLAG_PRESENT (1<<0) + +/* + * Send this value for the data element to only perform a read. If you + * send any other value, the EC will interpret it as data to set and will + * return the actual value set. + */ +#define EC_MOTION_SENSE_NO_VALUE -1 + +struct ec_params_motion_sense { + uint8_t cmd; + union { + /* Used for MOTIONSENSE_CMD_DUMP. */ + struct { + /* no args */ + } dump; + + /* + * Used for MOTIONSENSE_CMD_EC_RATE and + * MOTIONSENSE_CMD_KB_WAKE_ANGLE. + */ + struct { + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ + int16_t data; + } ec_rate, kb_wake_angle; + + /* Used for MOTIONSENSE_CMD_INFO. */ + struct { + /* Should be element of enum motionsensor_id. */ + uint8_t sensor_num; + } info; + + /* + * Used for MOTIONSENSE_CMD_SENSOR_ODR and + * MOTIONSENSE_CMD_SENSOR_RANGE. + */ + struct { + /* Should be element of enum motionsensor_id. */ + uint8_t sensor_num; + + /* Rounding flag, true for round-up, false for down. */ + uint8_t roundup; + + uint16_t reserved; + + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ + int32_t data; + } sensor_odr, sensor_range; + }; +} __packed; + +struct ec_response_motion_sense { + union { + /* Used for MOTIONSENSE_CMD_DUMP. */ + struct { + /* Flags representing the motion sensor module. */ + uint8_t module_flags; + + /* Flags for each sensor in enum motionsensor_id. */ + uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT]; + + /* Array of all sensor data. Each sensor is 3-axis. */ + int16_t data[3*EC_MOTION_SENSOR_COUNT]; + } dump; + + /* Used for MOTIONSENSE_CMD_INFO. */ + struct { + /* Should be element of enum motionsensor_type. */ + uint8_t type; + + /* Should be element of enum motionsensor_location. */ + uint8_t location; + + /* Should be element of enum motionsensor_chip. */ + uint8_t chip; + } info; + + /* + * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR, + * MOTIONSENSE_CMD_SENSOR_RANGE, and + * MOTIONSENSE_CMD_KB_WAKE_ANGLE. + */ + struct { + /* Current value of the parameter queried. */ + int32_t ret; + } ec_rate, sensor_odr, sensor_range, kb_wake_angle; + }; +} __packed; + /*****************************************************************************/ /* USB charging control commands */ @@ -738,28 +1484,67 @@ struct ec_response_rtc { /*****************************************************************************/ /* Port80 log access */ +/* Maximum entries that can be read/written in a single command */ +#define EC_PORT80_SIZE_MAX 32 + /* Get last port80 code from previous boot */ #define EC_CMD_PORT80_LAST_BOOT 0x48 +#define EC_CMD_PORT80_READ 0x48 + +enum ec_port80_subcmd { + EC_PORT80_GET_INFO = 0, + EC_PORT80_READ_BUFFER, +}; + +struct ec_params_port80_read { + uint16_t subcmd; + union { + struct { + uint32_t offset; + uint32_t num_entries; + } read_buffer; + }; +} __packed; + +struct ec_response_port80_read { + union { + struct { + uint32_t writes; + uint32_t history_size; + uint32_t last_boot; + } get_info; + struct { + uint16_t codes[EC_PORT80_SIZE_MAX]; + } data; + }; +} __packed; struct ec_response_port80_last_boot { uint16_t code; } __packed; /*****************************************************************************/ -/* Thermal engine commands */ +/* Thermal engine commands. Note that there are two implementations. We'll + * reuse the command number, but the data and behavior is incompatible. + * Version 0 is what originally shipped on Link. + * Version 1 separates the CPU thermal limits from the fan control. + */ -/* Set thershold value */ #define EC_CMD_THERMAL_SET_THRESHOLD 0x50 +#define EC_CMD_THERMAL_GET_THRESHOLD 0x51 +/* The version 0 structs are opaque. You have to know what they are for + * the get/set commands to make any sense. + */ + +/* Version 0 - set */ struct ec_params_thermal_set_threshold { uint8_t sensor_type; uint8_t threshold_id; uint16_t value; } __packed; -/* Get threshold value */ -#define EC_CMD_THERMAL_GET_THRESHOLD 0x51 - +/* Version 0 - get */ struct ec_params_thermal_get_threshold { uint8_t sensor_type; uint8_t threshold_id; @@ -769,9 +1554,82 @@ struct ec_response_thermal_get_threshold { uint16_t value; } __packed; + +/* The version 1 structs are visible. */ +enum ec_temp_thresholds { + EC_TEMP_THRESH_WARN = 0, + EC_TEMP_THRESH_HIGH, + EC_TEMP_THRESH_HALT, + + EC_TEMP_THRESH_COUNT +}; + +/* Thermal configuration for one temperature sensor. Temps are in degrees K. + * Zero values will be silently ignored by the thermal task. + */ +struct ec_thermal_config { + uint32_t temp_host[EC_TEMP_THRESH_COUNT]; /* levels of hotness */ + uint32_t temp_fan_off; /* no active cooling needed */ + uint32_t temp_fan_max; /* max active cooling needed */ +} __packed; + +/* Version 1 - get config for one sensor. */ +struct ec_params_thermal_get_threshold_v1 { + uint32_t sensor_num; +} __packed; +/* This returns a struct ec_thermal_config */ + +/* Version 1 - set config for one sensor. + * Use read-modify-write for best results! */ +struct ec_params_thermal_set_threshold_v1 { + uint32_t sensor_num; + struct ec_thermal_config cfg; +} __packed; +/* This returns no data */ + +/****************************************************************************/ + /* Toggle automatic fan control */ #define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52 +/* Get TMP006 calibration data */ +#define EC_CMD_TMP006_GET_CALIBRATION 0x53 + +struct ec_params_tmp006_get_calibration { + uint8_t index; +} __packed; + +struct ec_response_tmp006_get_calibration { + float s0; + float b0; + float b1; + float b2; +} __packed; + +/* Set TMP006 calibration data */ +#define EC_CMD_TMP006_SET_CALIBRATION 0x54 + +struct ec_params_tmp006_set_calibration { + uint8_t index; + uint8_t reserved[3]; /* Reserved; set 0 */ + float s0; + float b0; + float b1; + float b2; +} __packed; + +/* Read raw TMP006 data */ +#define EC_CMD_TMP006_GET_RAW 0x55 + +struct ec_params_tmp006_get_raw { + uint8_t index; +} __packed; + +struct ec_response_tmp006_get_raw { + int32_t t; /* In 1/100 K */ + int32_t v; /* In nV */ +}; + /*****************************************************************************/ /* MKBP - Matrix KeyBoard Protocol */ @@ -801,6 +1659,112 @@ struct ec_params_mkbp_simulate_key { uint8_t pressed; } __packed; +/* Configure keyboard scanning */ +#define EC_CMD_MKBP_SET_CONFIG 0x64 +#define EC_CMD_MKBP_GET_CONFIG 0x65 + +/* flags */ +enum mkbp_config_flags { + EC_MKBP_FLAGS_ENABLE = 1, /* Enable keyboard scanning */ +}; + +enum mkbp_config_valid { + EC_MKBP_VALID_SCAN_PERIOD = 1 << 0, + EC_MKBP_VALID_POLL_TIMEOUT = 1 << 1, + EC_MKBP_VALID_MIN_POST_SCAN_DELAY = 1 << 3, + EC_MKBP_VALID_OUTPUT_SETTLE = 1 << 4, + EC_MKBP_VALID_DEBOUNCE_DOWN = 1 << 5, + EC_MKBP_VALID_DEBOUNCE_UP = 1 << 6, + EC_MKBP_VALID_FIFO_MAX_DEPTH = 1 << 7, +}; + +/* Configuration for our key scanning algorithm */ +struct ec_mkbp_config { + uint32_t valid_mask; /* valid fields */ + uint8_t flags; /* some flags (enum mkbp_config_flags) */ + uint8_t valid_flags; /* which flags are valid */ + uint16_t scan_period_us; /* period between start of scans */ + /* revert to interrupt mode after no activity for this long */ + uint32_t poll_timeout_us; + /* + * minimum post-scan relax time. Once we finish a scan we check + * the time until we are due to start the next one. If this time is + * shorter this field, we use this instead. + */ + uint16_t min_post_scan_delay_us; + /* delay between setting up output and waiting for it to settle */ + uint16_t output_settle_us; + uint16_t debounce_down_us; /* time for debounce on key down */ + uint16_t debounce_up_us; /* time for debounce on key up */ + /* maximum depth to allow for fifo (0 = no keyscan output) */ + uint8_t fifo_max_depth; +} __packed; + +struct ec_params_mkbp_set_config { + struct ec_mkbp_config config; +} __packed; + +struct ec_response_mkbp_get_config { + struct ec_mkbp_config config; +} __packed; + +/* Run the key scan emulation */ +#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66 + +enum ec_keyscan_seq_cmd { + EC_KEYSCAN_SEQ_STATUS = 0, /* Get status information */ + EC_KEYSCAN_SEQ_CLEAR = 1, /* Clear sequence */ + EC_KEYSCAN_SEQ_ADD = 2, /* Add item to sequence */ + EC_KEYSCAN_SEQ_START = 3, /* Start running sequence */ + EC_KEYSCAN_SEQ_COLLECT = 4, /* Collect sequence summary data */ +}; + +enum ec_collect_flags { + /* + * Indicates this scan was processed by the EC. Due to timing, some + * scans may be skipped. + */ + EC_KEYSCAN_SEQ_FLAG_DONE = 1 << 0, +}; + +struct ec_collect_item { + uint8_t flags; /* some flags (enum ec_collect_flags) */ +}; + +struct ec_params_keyscan_seq_ctrl { + uint8_t cmd; /* Command to send (enum ec_keyscan_seq_cmd) */ + union { + struct { + uint8_t active; /* still active */ + uint8_t num_items; /* number of items */ + /* Current item being presented */ + uint8_t cur_item; + } status; + struct { + /* + * Absolute time for this scan, measured from the + * start of the sequence. + */ + uint32_t time_us; + uint8_t scan[0]; /* keyscan data */ + } add; + struct { + uint8_t start_item; /* First item to return */ + uint8_t num_items; /* Number of items to return */ + } collect; + }; +} __packed; + +struct ec_result_keyscan_seq_ctrl { + union { + struct { + uint8_t num_items; /* Number of items */ + /* Data for each item */ + struct ec_collect_item item[0]; + } collect; + }; +} __packed; + /*****************************************************************************/ /* Temperature sensor commands */ @@ -864,11 +1828,41 @@ struct ec_params_switch_enable_backlight { /* Enable/disable WLAN/Bluetooth */ #define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91 +#define EC_VER_SWITCH_ENABLE_WIRELESS 1 -struct ec_params_switch_enable_wireless { +/* Version 0 params; no response */ +struct ec_params_switch_enable_wireless_v0 { uint8_t enabled; } __packed; +/* Version 1 params */ +struct ec_params_switch_enable_wireless_v1 { + /* Flags to enable now */ + uint8_t now_flags; + + /* Which flags to copy from now_flags */ + uint8_t now_mask; + + /* + * Flags to leave enabled in S3, if they're on at the S0->S3 + * transition. (Other flags will be disabled by the S0->S3 + * transition.) + */ + uint8_t suspend_flags; + + /* Which flags to copy from suspend_flags */ + uint8_t suspend_mask; +} __packed; + +/* Version 1 response */ +struct ec_response_switch_enable_wireless_v1 { + /* Flags to enable now */ + uint8_t now_flags; + + /* Flags to leave enabled in S3 */ + uint8_t suspend_flags; +} __packed; + /*****************************************************************************/ /* GPIO commands. Only available on EC if write protect has been disabled. */ @@ -883,6 +1877,7 @@ struct ec_params_gpio_set { /* Get GPIO value */ #define EC_CMD_GPIO_GET 0x93 +/* Version 0 of input params and response */ struct ec_params_gpio_get { char name[32]; } __packed; @@ -890,14 +1885,51 @@ struct ec_response_gpio_get { uint8_t val; } __packed; +/* Version 1 of input params and response */ +struct ec_params_gpio_get_v1 { + uint8_t subcmd; + union { + struct { + char name[32]; + } get_value_by_name; + struct { + uint8_t index; + } get_info; + }; +} __packed; + +struct ec_response_gpio_get_v1 { + union { + struct { + uint8_t val; + } get_value_by_name, get_count; + struct { + uint8_t val; + char name[32]; + uint32_t flags; + } get_info; + }; +} __packed; + +enum gpio_get_subcmd { + EC_GPIO_GET_BY_NAME = 0, + EC_GPIO_GET_COUNT = 1, + EC_GPIO_GET_INFO = 2, +}; + /*****************************************************************************/ /* I2C commands. Only available when flash write protect is unlocked. */ +/* + * TODO(crosbug.com/p/23570): These commands are deprecated, and will be + * removed soon. Use EC_CMD_I2C_XFER instead. + */ + /* Read I2C bus */ #define EC_CMD_I2C_READ 0x94 struct ec_params_i2c_read { - uint16_t addr; + uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ uint8_t read_size; /* Either 8 or 16. */ uint8_t port; uint8_t offset; @@ -911,7 +1943,7 @@ struct ec_response_i2c_read { struct ec_params_i2c_write { uint16_t data; - uint16_t addr; + uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ uint8_t write_size; /* Either 8 or 16. */ uint8_t port; uint8_t offset; @@ -920,11 +1952,20 @@ struct ec_params_i2c_write { /*****************************************************************************/ /* Charge state commands. Only available when flash write protect unlocked. */ -/* Force charge state machine to stop in idle mode */ -#define EC_CMD_CHARGE_FORCE_IDLE 0x96 +/* Force charge state machine to stop charging the battery or force it to + * discharge the battery. + */ +#define EC_CMD_CHARGE_CONTROL 0x96 +#define EC_VER_CHARGE_CONTROL 1 -struct ec_params_force_idle { - uint8_t enabled; +enum ec_charge_control_mode { + CHARGE_CONTROL_NORMAL = 0, + CHARGE_CONTROL_IDLE, + CHARGE_CONTROL_DISCHARGE, +}; + +struct ec_params_charge_control { + uint32_t mode; /* enum charge_control_mode */ } __packed; /*****************************************************************************/ @@ -941,35 +1982,439 @@ struct ec_params_force_idle { */ #define EC_CMD_CONSOLE_READ 0x98 +/*****************************************************************************/ + +/* + * Cut off battery power immediately or after the host has shut down. + * + * return EC_RES_INVALID_COMMAND if unsupported by a board/battery. + * EC_RES_SUCCESS if the command was successful. + * EC_RES_ERROR if the cut off command failed. + */ +#define EC_CMD_BATTERY_CUT_OFF 0x99 + +#define EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN (1 << 0) + +struct ec_params_battery_cutoff { + uint8_t flags; +} __packed; + +/*****************************************************************************/ +/* USB port mux control. */ + +/* + * Switch USB mux or return to automatic switching. + */ +#define EC_CMD_USB_MUX 0x9a + +struct ec_params_usb_mux { + uint8_t mux; +} __packed; + +/*****************************************************************************/ +/* LDOs / FETs control. */ + +enum ec_ldo_state { + EC_LDO_STATE_OFF = 0, /* the LDO / FET is shut down */ + EC_LDO_STATE_ON = 1, /* the LDO / FET is ON / providing power */ +}; + +/* + * Switch on/off a LDO. + */ +#define EC_CMD_LDO_SET 0x9b + +struct ec_params_ldo_set { + uint8_t index; + uint8_t state; +} __packed; + +/* + * Get LDO state. + */ +#define EC_CMD_LDO_GET 0x9c + +struct ec_params_ldo_get { + uint8_t index; +} __packed; + +struct ec_response_ldo_get { + uint8_t state; +} __packed; + +/*****************************************************************************/ +/* Power info. */ + +/* + * Get power info. + */ +#define EC_CMD_POWER_INFO 0x9d + +struct ec_response_power_info { + uint32_t usb_dev_type; + uint16_t voltage_ac; + uint16_t voltage_system; + uint16_t current_system; + uint16_t usb_current_limit; +} __packed; + +/*****************************************************************************/ +/* I2C passthru command */ + +#define EC_CMD_I2C_PASSTHRU 0x9e + +/* Read data; if not present, message is a write */ +#define EC_I2C_FLAG_READ (1 << 15) + +/* Mask for address */ +#define EC_I2C_ADDR_MASK 0x3ff + +#define EC_I2C_STATUS_NAK (1 << 0) /* Transfer was not acknowledged */ +#define EC_I2C_STATUS_TIMEOUT (1 << 1) /* Timeout during transfer */ + +/* Any error */ +#define EC_I2C_STATUS_ERROR (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT) + +struct ec_params_i2c_passthru_msg { + uint16_t addr_flags; /* I2C slave address (7 or 10 bits) and flags */ + uint16_t len; /* Number of bytes to read or write */ +} __packed; + +struct ec_params_i2c_passthru { + uint8_t port; /* I2C port number */ + uint8_t num_msgs; /* Number of messages */ + struct ec_params_i2c_passthru_msg msg[]; + /* Data to write for all messages is concatenated here */ +} __packed; + +struct ec_response_i2c_passthru { + uint8_t i2c_status; /* Status flags (EC_I2C_STATUS_...) */ + uint8_t num_msgs; /* Number of messages processed */ + uint8_t data[]; /* Data read by messages concatenated here */ +} __packed; + +/*****************************************************************************/ +/* Power button hang detect */ + +#define EC_CMD_HANG_DETECT 0x9f + +/* Reasons to start hang detection timer */ +/* Power button pressed */ +#define EC_HANG_START_ON_POWER_PRESS (1 << 0) + +/* Lid closed */ +#define EC_HANG_START_ON_LID_CLOSE (1 << 1) + + /* Lid opened */ +#define EC_HANG_START_ON_LID_OPEN (1 << 2) + +/* Start of AP S3->S0 transition (booting or resuming from suspend) */ +#define EC_HANG_START_ON_RESUME (1 << 3) + +/* Reasons to cancel hang detection */ + +/* Power button released */ +#define EC_HANG_STOP_ON_POWER_RELEASE (1 << 8) + +/* Any host command from AP received */ +#define EC_HANG_STOP_ON_HOST_COMMAND (1 << 9) + +/* Stop on end of AP S0->S3 transition (suspending or shutting down) */ +#define EC_HANG_STOP_ON_SUSPEND (1 << 10) + +/* + * If this flag is set, all the other fields are ignored, and the hang detect + * timer is started. This provides the AP a way to start the hang timer + * without reconfiguring any of the other hang detect settings. Note that + * you must previously have configured the timeouts. + */ +#define EC_HANG_START_NOW (1 << 30) + +/* + * If this flag is set, all the other fields are ignored (including + * EC_HANG_START_NOW). This provides the AP a way to stop the hang timer + * without reconfiguring any of the other hang detect settings. + */ +#define EC_HANG_STOP_NOW (1 << 31) + +struct ec_params_hang_detect { + /* Flags; see EC_HANG_* */ + uint32_t flags; + + /* Timeout in msec before generating host event, if enabled */ + uint16_t host_event_timeout_msec; + + /* Timeout in msec before generating warm reboot, if enabled */ + uint16_t warm_reboot_timeout_msec; +} __packed; + +/*****************************************************************************/ +/* Commands for battery charging */ + +/* + * This is the single catch-all host command to exchange data regarding the + * charge state machine (v2 and up). + */ +#define EC_CMD_CHARGE_STATE 0xa0 + +/* Subcommands for this host command */ +enum charge_state_command { + CHARGE_STATE_CMD_GET_STATE, + CHARGE_STATE_CMD_GET_PARAM, + CHARGE_STATE_CMD_SET_PARAM, + CHARGE_STATE_NUM_CMDS +}; + +/* + * Known param numbers are defined here. Ranges are reserved for board-specific + * params, which are handled by the particular implementations. + */ +enum charge_state_params { + CS_PARAM_CHG_VOLTAGE, /* charger voltage limit */ + CS_PARAM_CHG_CURRENT, /* charger current limit */ + CS_PARAM_CHG_INPUT_CURRENT, /* charger input current limit */ + CS_PARAM_CHG_STATUS, /* charger-specific status */ + CS_PARAM_CHG_OPTION, /* charger-specific options */ + /* How many so far? */ + CS_NUM_BASE_PARAMS, + + /* Range for CONFIG_CHARGER_PROFILE_OVERRIDE params */ + CS_PARAM_CUSTOM_PROFILE_MIN = 0x10000, + CS_PARAM_CUSTOM_PROFILE_MAX = 0x1ffff, + + /* Other custom param ranges go here... */ +}; + +struct ec_params_charge_state { + uint8_t cmd; /* enum charge_state_command */ + union { + struct { + /* no args */ + } get_state; + + struct { + uint32_t param; /* enum charge_state_param */ + } get_param; + + struct { + uint32_t param; /* param to set */ + uint32_t value; /* value to set */ + } set_param; + }; +} __packed; + +struct ec_response_charge_state { + union { + struct { + int ac; + int chg_voltage; + int chg_current; + int chg_input_current; + int batt_state_of_charge; + } get_state; + + struct { + uint32_t value; + } get_param; + struct { + /* no return values */ + } set_param; + }; +} __packed; + + +/* + * Set maximum battery charging current. + */ +#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1 + +struct ec_params_current_limit { + uint32_t limit; /* in mA */ +} __packed; + +/* + * Set maximum external power current. + */ +#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2 + +struct ec_params_ext_power_current_limit { + uint32_t limit; /* in mA */ +} __packed; + +/*****************************************************************************/ +/* Smart battery pass-through */ + +/* Get / Set 16-bit smart battery registers */ +#define EC_CMD_SB_READ_WORD 0xb0 +#define EC_CMD_SB_WRITE_WORD 0xb1 + +/* Get / Set string smart battery parameters + * formatted as SMBUS "block". + */ +#define EC_CMD_SB_READ_BLOCK 0xb2 +#define EC_CMD_SB_WRITE_BLOCK 0xb3 + +struct ec_params_sb_rd { + uint8_t reg; +} __packed; + +struct ec_response_sb_rd_word { + uint16_t value; +} __packed; + +struct ec_params_sb_wr_word { + uint8_t reg; + uint16_t value; +} __packed; + +struct ec_response_sb_rd_block { + uint8_t data[32]; +} __packed; + +struct ec_params_sb_wr_block { + uint8_t reg; + uint16_t data[32]; +} __packed; + + +/*****************************************************************************/ +/* Battery vendor parameters + * + * Get or set vendor-specific parameters in the battery. Implementations may + * differ between boards or batteries. On a set operation, the response + * contains the actual value set, which may be rounded or clipped from the + * requested value. + */ + +#define EC_CMD_BATTERY_VENDOR_PARAM 0xb4 + +enum ec_battery_vendor_param_mode { + BATTERY_VENDOR_PARAM_MODE_GET = 0, + BATTERY_VENDOR_PARAM_MODE_SET, +}; + +struct ec_params_battery_vendor_param { + uint32_t param; + uint32_t value; + uint8_t mode; +} __packed; + +struct ec_response_battery_vendor_param { + uint32_t value; +} __packed; + +/*****************************************************************************/ +/* + * Smart Battery Firmware Update Commands + */ +#define EC_CMD_SB_FW_UPDATE 0xb5 + +enum ec_sb_fw_update_subcmd { + EC_SB_FW_UPDATE_PREPARE = 0x0, + EC_SB_FW_UPDATE_INFO = 0x1, /*query sb info */ + EC_SB_FW_UPDATE_BEGIN = 0x2, /*check if protected */ + EC_SB_FW_UPDATE_WRITE = 0x3, /*check if protected */ + EC_SB_FW_UPDATE_END = 0x4, + EC_SB_FW_UPDATE_STATUS = 0x5, + EC_SB_FW_UPDATE_PROTECT = 0x6, + EC_SB_FW_UPDATE_MAX = 0x7, +}; + +#define SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE 32 +#define SB_FW_UPDATE_CMD_STATUS_SIZE 2 +#define SB_FW_UPDATE_CMD_INFO_SIZE 8 + +struct ec_sb_fw_update_header { + uint16_t subcmd; /* enum ec_sb_fw_update_subcmd */ + uint16_t fw_id; /* firmware id */ +} __packed; + +struct ec_params_sb_fw_update { + struct ec_sb_fw_update_header hdr; + union { + /* EC_SB_FW_UPDATE_PREPARE = 0x0 */ + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + /* EC_SB_FW_UPDATE_BEGIN = 0x2 */ + /* EC_SB_FW_UPDATE_END = 0x4 */ + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + /* EC_SB_FW_UPDATE_PROTECT = 0x6 */ + struct { + /* no args */ + } dummy; + + /* EC_SB_FW_UPDATE_WRITE = 0x3 */ + struct { + uint8_t data[SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE]; + } write; + }; +} __packed; + +struct ec_response_sb_fw_update { + union { + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + struct { + uint8_t data[SB_FW_UPDATE_CMD_INFO_SIZE]; + } info; + + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + struct { + uint8_t data[SB_FW_UPDATE_CMD_STATUS_SIZE]; + } status; + }; +} __packed; + +/* + * Entering Verified Boot Mode Command + * Default mode is VBOOT_MODE_NORMAL if EC did not receive this command. + * Valid Modes are: normal, developer, and recovery. + */ +#define EC_CMD_ENTERING_MODE 0xb6 + +struct ec_params_entering_mode { + int vboot_mode; +} __packed; + +#define VBOOT_MODE_NORMAL 0 +#define VBOOT_MODE_DEVELOPER 1 +#define VBOOT_MODE_RECOVERY 2 + /*****************************************************************************/ /* System commands */ /* - * TODO: this is a confusing name, since it doesn't necessarily reboot the EC. - * Rename to "set image" or something similar. + * TODO(crosbug.com/p/23747): This is a confusing name, since it doesn't + * necessarily reboot the EC. Rename to "image" or something similar? */ #define EC_CMD_REBOOT_EC 0xd2 /* Command */ enum ec_reboot_cmd { EC_REBOOT_CANCEL = 0, /* Cancel a pending reboot */ - EC_REBOOT_JUMP_RO, /* Jump to RO without rebooting */ - EC_REBOOT_JUMP_RW, /* Jump to RW without rebooting */ + EC_REBOOT_JUMP_RO = 1, /* Jump to RO without rebooting */ + EC_REBOOT_JUMP_RW = 2, /* Jump to RW without rebooting */ /* (command 3 was jump to RW-B) */ EC_REBOOT_COLD = 4, /* Cold-reboot */ - EC_REBOOT_DISABLE_JUMP, /* Disable jump until next reboot */ + EC_REBOOT_DISABLE_JUMP = 5, /* Disable jump until next reboot */ + EC_REBOOT_HIBERNATE = 6 /* Hibernate EC */ }; /* Flags for ec_params_reboot_ec.reboot_flags */ #define EC_REBOOT_FLAG_RESERVED0 (1 << 0) /* Was recovery request */ -#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) -#define EC_REBOOT_FLAG_POWER_ON (1 << 2) +#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) /* Reboot after AP shutdown */ struct ec_params_reboot_ec { uint8_t cmd; /* enum ec_reboot_cmd */ uint8_t flags; /* See EC_REBOOT_FLAG_* */ } __packed; +/* + * Get information on last EC panic. + * + * Returns variable-length platform-dependent panic information. See panic.h + * for details. + */ +#define EC_CMD_GET_PANIC_INFO 0xd3 + /*****************************************************************************/ /* * ACPI commands @@ -1017,6 +2462,7 @@ struct ec_params_reboot_ec { #define EC_CMD_ACPI_QUERY_EVENT 0x84 /* Valid addresses in ACPI memory space, for read/write commands */ + /* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */ #define EC_ACPI_MEM_VERSION 0x00 /* @@ -1026,8 +2472,60 @@ struct ec_params_reboot_ec { #define EC_ACPI_MEM_TEST 0x01 /* Test compliment; writes here are ignored. */ #define EC_ACPI_MEM_TEST_COMPLIMENT 0x02 + /* Keyboard backlight brightness percent (0 - 100) */ #define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03 +/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */ +#define EC_ACPI_MEM_FAN_DUTY 0x04 + +/* + * DPTF temp thresholds. Any of the EC's temp sensors can have up to two + * independent thresholds attached to them. The current value of the ID + * register determines which sensor is affected by the THRESHOLD and COMMIT + * registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme + * as the memory-mapped sensors. The COMMIT register applies those settings. + * + * The spec does not mandate any way to read back the threshold settings + * themselves, but when a threshold is crossed the AP needs a way to determine + * which sensor(s) are responsible. Each reading of the ID register clears and + * returns one sensor ID that has crossed one of its threshold (in either + * direction) since the last read. A value of 0xFF means "no new thresholds + * have tripped". Setting or enabling the thresholds for a sensor will clear + * the unread event count for that sensor. + */ +#define EC_ACPI_MEM_TEMP_ID 0x05 +#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06 +#define EC_ACPI_MEM_TEMP_COMMIT 0x07 +/* + * Here are the bits for the COMMIT register: + * bit 0 selects the threshold index for the chosen sensor (0/1) + * bit 1 enables/disables the selected threshold (0 = off, 1 = on) + * Each write to the commit register affects one threshold. + */ +#define EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK (1 << 0) +#define EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK (1 << 1) +/* + * Example: + * + * Set the thresholds for sensor 2 to 50 C and 60 C: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x7b to [0x06] -- C_TO_K(50) - EC_TEMP_SENSOR_OFFSET + * write 0x2 to [0x07] -- enable threshold 0 with this value + * write 0x85 to [0x06] -- C_TO_K(60) - EC_TEMP_SENSOR_OFFSET + * write 0x3 to [0x07] -- enable threshold 1 with this value + * + * Disable the 60 C threshold, leaving the 50 C threshold unchanged: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x1 to [0x07] -- disable threshold 1 + */ + +/* DPTF battery charging current limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT 0x08 + +/* Charging limit is specified in 64 mA steps */ +#define EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA 64 +/* Value to disable DPTF battery charging limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT_DISABLED 0xff /* Current version of ACPI memory address space */ #define EC_ACPI_MEM_VERSION_CURRENT 1 @@ -1052,6 +2550,15 @@ struct ec_params_reboot_ec { */ #define EC_CMD_REBOOT 0xd1 /* Think "die" */ +/* + * Resend last response (not supported on LPC). + * + * Returns EC_RES_UNAVAILABLE if there is no response available - for example, + * there was no previous command, or the previous command's response was too + * big to save. + */ +#define EC_CMD_RESEND_RESPONSE 0xdb + /* * This header byte on a command indicate version 0. Any header byte less * than this means that we are talking to an old EC which doesn't support @@ -1060,10 +2567,142 @@ struct ec_params_reboot_ec { * Header bytes greater than this indicate a later version. For example, * EC_CMD_VERSION0 + 1 means we are using version 1. * - * The old EC interface must not use commands 0dc or higher. + * The old EC interface must not use commands 0xdc or higher. */ #define EC_CMD_VERSION0 0xdc +/*****************************************************************************/ +/* + * PD commands + * + * These commands are for PD MCU communication. + */ + +/* EC to PD MCU exchange status command */ +#define EC_CMD_PD_EXCHANGE_STATUS 0x100 + +/* Status of EC being sent to PD */ +struct ec_params_pd_status { + int8_t batt_soc; /* battery state of charge */ +} __packed; + +/* Status of PD being sent back to EC */ +#define PD_STATUS_HOST_EVENT (1 << 0) +struct ec_response_pd_status { + uint32_t status; /* PD MCU status */ + uint32_t curr_lim_ma; /* input current limit */ +} __packed; + +/* Set USB type-C port role and muxes */ +#define EC_CMD_USB_PD_CONTROL 0x101 + +enum usb_pd_control_role { + USB_PD_CTRL_ROLE_NO_CHANGE = 0, + USB_PD_CTRL_ROLE_TOGGLE_ON = 1, /* == AUTO */ + USB_PD_CTRL_ROLE_TOGGLE_OFF = 2, + USB_PD_CTRL_ROLE_FORCE_SINK = 3, + USB_PD_CTRL_ROLE_FORCE_SOURCE = 4, + USB_PD_CTRL_ROLE_COUNT +}; + +enum usb_pd_control_mux { + USB_PD_CTRL_MUX_NO_CHANGE = 0, + USB_PD_CTRL_MUX_NONE = 1, + USB_PD_CTRL_MUX_USB = 2, + USB_PD_CTRL_MUX_DP = 3, + USB_PD_CTRL_MUX_DOCK = 4, + USB_PD_CTRL_MUX_AUTO = 5, + USB_PD_CTRL_MUX_COUNT +}; + +struct ec_params_usb_pd_control { + uint8_t port; + uint8_t role; + uint8_t mux; +} __packed; + +struct ec_response_usb_pd_control { + uint8_t enabled; + uint8_t role; + uint8_t polarity; + uint8_t state; +} __packed; + +/* Write USB-PD device FW */ +#define EC_CMD_USB_PD_FW_UPDATE 0x110 + +enum usb_pd_fw_update_cmds { + USB_PD_FW_REBOOT, + USB_PD_FW_FLASH_ERASE, + USB_PD_FW_FLASH_WRITE, + USB_PD_FW_FLASH_HASH, +}; + +struct ec_params_usb_pd_fw_update { + uint8_t cmd; + uint8_t dev_id; + uint8_t port; + uint8_t reserved; /* reserved */ + uint32_t size; /* Size to write in bytes */ + /* Followed by data to write */ +} __packed; + +/* Write USB-PD Accessory RW_HASH table entry */ +#define EC_CMD_USB_PD_RW_HASH_ENTRY 0x111 +#define SHA1_DIGEST_SIZE 20 +struct ec_params_usb_pd_rw_hash_entry { + uint8_t dev_id; + union { + uint8_t b[SHA1_DIGEST_SIZE]; + uint32_t w[SHA1_DIGEST_SIZE/4]; + } dev_rw_hash; +} __packed; + +/* Read USB-PD Accessory info */ +#define EC_CMD_USB_PD_DEV_INFO 0x112 + +struct ec_params_usb_pd_info_request { + uint8_t port; +} __packed; + #endif /* !__ACPI__ */ +/*****************************************************************************/ +/* + * Passthru commands + * + * Some platforms have sub-processors chained to each other. For example. + * + * AP <--> EC <--> PD MCU + * + * The top 2 bits of the command number are used to indicate which device the + * command is intended for. Device 0 is always the device receiving the + * command; other device mapping is board-specific. + * + * When a device receives a command to be passed to a sub-processor, it passes + * it on with the device number set back to 0. This allows the sub-processor + * to remain blissfully unaware of whether the command originated on the next + * device up the chain, or was passed through from the AP. + * + * In the above example, if the AP wants to send command 0x0002 to the PD MCU, + * AP sends command 0x4002 to the EC + * EC sends command 0x0002 to the PD MCU + * EC forwards PD MCU response back to the AP + */ + +/* Offset and max command number for sub-device n */ +#define EC_CMD_PASSTHRU_OFFSET(n) (0x4000 * (n)) +#define EC_CMD_PASSTHRU_MAX(n) (EC_CMD_PASSTHRU_OFFSET(n) + 0x3fff) + +/*****************************************************************************/ +/* + * Deprecated constants. These constants have been renamed for clarity. The + * meaning and size has not changed. Programs that use the old names should + * switch to the new names soon, as the old names may not be carried forward + * forever. + */ +#define EC_HOST_PARAM_SIZE EC_PROTO2_MAX_PARAM_SIZE +#define EC_LPC_ADDR_OLD_PARAM EC_HOST_CMD_REGION1 +#define EC_OLD_PARAM_SIZE EC_HOST_CMD_REGION_SIZE + #endif /* __CROS_EC_COMMANDS_H */ diff --git a/src/ec/google/chromeec/ec_i2c.c b/src/ec/google/chromeec/ec_i2c.c new file mode 100644 index 0000000000..f5613f739f --- /dev/null +++ b/src/ec/google/chromeec/ec_i2c.c @@ -0,0 +1,266 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "ec.h" +#include "ec_commands.h" + +#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_I2C_PROTO3) + +#define PROTO3_FRAMING_BYTES sizeof(uint32_t) +/* Just use the LPC host packet size to size the buffer. */ +#define PROTO3_MAX_PACKET_SIZE 268 + +struct proto3_i2c_buf { + uint8_t framing_bytes[PROTO3_FRAMING_BYTES]; + uint8_t data[PROTO3_MAX_PACKET_SIZE]; +} __attribute__((aligned(sizeof(uint32_t)))); + +static struct proto3_i2c_buf req_buf; +static struct proto3_i2c_buf resp_buf; + +enum { + CMD_INDEX, + RESP_INDEX, + SEGS_PER_CMD, +}; + +struct i2c_ec { + int bus; + struct i2c_seg segs[SEGS_PER_CMD]; +}; + +static struct i2c_ec ec_dev = { + .bus = CONFIG_EC_GOOGLE_CHROMEEC_I2C_BUS, + .segs[CMD_INDEX] = { + .read = 0, + .chip = CONFIG_EC_GOOGLE_CHROMEEC_I2C_CHIP, + /* Framing byte to be transferred prior to request. */ + .buf = &req_buf.framing_bytes[3], + }, + .segs[RESP_INDEX] = { + .read = 1, + .chip = CONFIG_EC_GOOGLE_CHROMEEC_I2C_CHIP, + /* return code and total length before full response. */ + .buf = &resp_buf.framing_bytes[2], + }, +}; + +void *crosec_get_buffer(size_t size, int req) +{ + struct proto3_i2c_buf *ib; + + if (size > PROTO3_MAX_PACKET_SIZE) { + printk(BIOS_DEBUG, "Proto v3 buffer request too large: %zu!\n", + size); + return NULL; + } + + if (req) + ib = &req_buf; + else + ib = &resp_buf; + + return &ib->data[0]; +} + +static int crosec_i2c_io(size_t req_size, size_t resp_size, void *context) +{ + struct i2c_ec *ec = context; + uint8_t ret_code; + size_t resp_len; + + if (req_size > PROTO3_MAX_PACKET_SIZE || + resp_size > PROTO3_MAX_PACKET_SIZE) + return -1; + + /* Place the framing byte and set size accordingly. */ + ec->segs[CMD_INDEX].len = req_size + 1; + ec->segs[CMD_INDEX].buf[0] = EC_COMMAND_PROTOCOL_3; + /* Return code and length returned prior to packet data. */ + ec->segs[RESP_INDEX].len = resp_size + 2; + + if (i2c_transfer(ec->bus, ec->segs, ARRAY_SIZE(ec->segs)) != 0) { + printk(BIOS_ERR, "%s: Cannot complete read from i2c-%d:%#x\n", + __func__, ec->bus, ec->segs[0].chip); + return -1; + } + + ret_code = ec->segs[RESP_INDEX].buf[0]; + resp_len = ec->segs[RESP_INDEX].buf[1]; + + if (ret_code != 0) { + printk(BIOS_ERR, "EC command returned 0x%x\n", ret_code); + return -1; + } + + if (resp_len > resp_size) { + printk(BIOS_ERR, "Response length mismatch %zu vs %zu\n", + resp_len, resp_size); + return -1; + } + + return 0; +} + +int google_chromeec_command(struct chromeec_command *cec_command) +{ + return crosec_command_proto(cec_command, crosec_i2c_io, &ec_dev); +} + +#else /* CONFIG_EC_GOOGLE_CHROMEEC_I2C_PROTO3 */ + +/* Command (host->device) format for I2C: + * uint8_t version, cmd, len, data[len], checksum; + * + * Response (device->host) format for I2C: + * uint8_t response, len, data[len], checksum; + * + * Note the location of checksum is different from LPC protocol. + * + * The length is 8 bit so maximum data size is 0xff. + * Any I2C command should fit in 0xff + 4 bytes, and max response length + * is 0xff + 3 bytes. + */ +#define MAX_I2C_DATA_SIZE (0xff) + +typedef struct { + uint8_t version; + uint8_t command; + uint8_t length; + uint8_t data[MAX_I2C_DATA_SIZE + 1]; +} EcCommandI2c; + +typedef struct { + uint8_t response; + uint8_t length; + uint8_t data[MAX_I2C_DATA_SIZE + 1]; +} EcResponseI2c; + +static inline void i2c_dump(int bus, int chip, const uint8_t *data, size_t size) +{ +#ifdef TRACE_CHROMEEC + printk(BIOS_INFO, "i2c: bus=%d, chip=%#x, size=%d, data: ", bus, chip, + size); + while (size-- > 0) { + printk(BIOS_INFO, "%02X ", *data++); + } + printk(BIOS_INFO, "\n"); +#endif +} + +static int ec_verify_checksum(const EcResponseI2c *resp) +{ + size_t size = sizeof(*resp) - sizeof(resp->data) + resp->length; + uint8_t calculated = google_chromeec_calc_checksum( + (const uint8_t *)resp, size); + uint8_t received = resp->data[resp->length]; + if (calculated != received) { + printk(BIOS_ERR, "%s: Unmatch (rx: %#02x, calc: %#02x)\n", + __func__, received, calculated); + return 0; + } + return 1; +} + +static void ec_fill_checksum(EcCommandI2c *cmd) +{ + size_t size = sizeof(*cmd) - sizeof(cmd->data) + cmd->length; + cmd->data[cmd->length] = google_chromeec_calc_checksum( + (const uint8_t *)cmd, size); +} + +int google_chromeec_command(struct chromeec_command *cec_command) +{ + EcCommandI2c cmd; + EcResponseI2c resp; + int bus = CONFIG_EC_GOOGLE_CHROMEEC_I2C_BUS; + int chip = CONFIG_EC_GOOGLE_CHROMEEC_I2C_CHIP; + size_t size_i2c_cmd = (sizeof(cmd) - sizeof(cmd.data) + + cec_command->cmd_size_in + 1), + size_i2c_resp = (sizeof(resp) - sizeof(resp.data) + + cec_command->cmd_size_out + 1); + + if (cec_command->cmd_size_in > MAX_I2C_DATA_SIZE || + cec_command->cmd_size_out > MAX_I2C_DATA_SIZE) { + printk(BIOS_ERR, "%s: Command data size too large (%d,%d)\n", + __func__, cec_command->cmd_size_in, + cec_command->cmd_size_out); + cec_command->cmd_code = EC_RES_INVALID_PARAM; + return 1; + } + + /* Construct command. */ + cmd.version = EC_CMD_VERSION0 + cec_command->cmd_version; + cmd.command = cec_command->cmd_code; + cmd.length = cec_command->cmd_size_in; + memcpy(cmd.data, cec_command->cmd_data_in, cmd.length); + ec_fill_checksum(&cmd); + + /* Start I2C communication */ + i2c_dump(bus, chip, (const uint8_t *)&cmd, size_i2c_cmd); + if (i2c_write_raw(bus, chip, (uint8_t *)&cmd, size_i2c_cmd) != 0) { + printk(BIOS_ERR, "%s: Cannot complete write to i2c-%d:%#x\n", + __func__, bus, chip); + cec_command->cmd_code = EC_RES_ERROR; + return 1; + } + if (i2c_read_raw(bus, chip, (uint8_t *)&resp, size_i2c_resp) != 0) { + printk(BIOS_ERR, "%s: Cannot complete read from i2c-%d:%#x\n", + __func__, bus, chip); + cec_command->cmd_code = EC_RES_ERROR; + return 1; + } + + /* Verify and return response */ + cec_command->cmd_code = resp.response; + if (resp.response != EC_RES_SUCCESS) { + printk(BIOS_DEBUG, "%s: Received bad result code %d\n", + __func__, (int)resp.response); + return 1; + } + if (resp.length > cec_command->cmd_size_out) { + printk(BIOS_ERR, "%s: Received len %#02x too large\n", + __func__, (int)resp.length); + cec_command->cmd_code = EC_RES_INVALID_RESPONSE; + return 1; + } + if (!ec_verify_checksum(&resp)) { + cec_command->cmd_code = EC_RES_INVALID_CHECKSUM; + return 1; + } + cec_command->cmd_size_out = resp.length; + memcpy(cec_command->cmd_data_out, resp.data, resp.length); + return 0; +} + +#endif /* CONFIG_EC_GOOGLE_CHROMEEC_I2C_PROTO3 */ + +#ifndef __PRE_RAM__ +u8 google_chromeec_get_event(void) +{ + printk(BIOS_ERR, "%s: Not supported.\n", __func__); + return 0; +} +#endif diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c new file mode 100644 index 0000000000..1675d72aa1 --- /dev/null +++ b/src/ec/google/chromeec/ec_lpc.c @@ -0,0 +1,365 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include +#include +#include +#include +#include "chip.h" +#include "ec.h" +#include "ec_commands.h" + +static int google_chromeec_command_version(void) +{ + u8 id1, id2, flags; + + id1 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID); + id2 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1); + flags = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS); + + if (id1 != 'E' || id2 != 'C') { + printk(BIOS_ERR, "Missing Chromium EC memory map.\n"); + return -1; + } + + if (flags & EC_HOST_CMD_FLAG_VERSION_3) { + return EC_HOST_CMD_FLAG_VERSION_3; + } else if (flags & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) { + return EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED; + } else { + printk(BIOS_ERR, + "Chromium EC command version unsupported\n"); + return -1; + } +} + +static int google_chromeec_wait_ready(u16 port) +{ + u8 ec_status = inb(port); + u32 time_count = 0; + + /* + * One second is more than plenty for any EC operation to complete + * (and the bus accessing/code execution) overhead will make the + * timeout even longer. + */ +#define MAX_EC_TIMEOUT_US 1000000 + + while (ec_status & + (EC_LPC_CMDR_PENDING | EC_LPC_CMDR_BUSY)) { + udelay(1); + if (time_count++ == MAX_EC_TIMEOUT_US) + return -1; + ec_status = inb(port); + } + return 0; +} + +static int google_chromeec_command_v3(struct chromeec_command *cec_command) +{ + struct ec_host_request rq; + struct ec_host_response rs; + const u8 *d; + u8 *dout; + int csum = 0; + int i; + + if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) { + printk(BIOS_ERR, "EC cannot send %d bytes\n", + cec_command->cmd_size_in + sizeof(rq)); + return -1; + } + + if (cec_command->cmd_size_out > EC_LPC_HOST_PACKET_SIZE) { + printk(BIOS_ERR, "EC cannot receive %d bytes\n", + cec_command->cmd_size_out); + return -1; + } + + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + printk(BIOS_ERR, "Timeout waiting for EC start command %d!\n", + cec_command->cmd_code); + return -1; + } + + /* Fill in request packet */ + rq.struct_version = EC_HOST_REQUEST_VERSION; + rq.checksum = 0; + rq.command = cec_command->cmd_code | + EC_CMD_PASSTHRU_OFFSET(cec_command->cmd_dev_index); + rq.command_version = cec_command->cmd_version; + rq.reserved = 0; + rq.data_len = cec_command->cmd_size_in; + + /* Copy data and start checksum */ + for (i = 0, d = (const u8 *)cec_command->cmd_data_in; + i < cec_command->cmd_size_in; i++, d++) { + outb(*d, EC_LPC_ADDR_HOST_PACKET + sizeof(rq) + i); + csum += *d; + } + + /* Finish checksum */ + for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++) + csum += *d; + + /* Write checksum field so the entire packet sums to 0 */ + rq.checksum = (u8)(-csum); + + /* Copy header */ + for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++) + outb(*d, EC_LPC_ADDR_HOST_PACKET + i); + + /* Start the command */ + outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); + + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", + cec_command->cmd_code); + return -1; + } + + /* Check result */ + cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); + if (cec_command->cmd_code) { + printk(BIOS_ERR, "EC returned error result code %d\n", + cec_command->cmd_code); + return -i; + } + + /* Read back response header and start checksum */ + csum = 0; + for (i = 0, dout = (u8 *)&rs; i < sizeof(rs); i++, dout++) { + *dout = inb(EC_LPC_ADDR_HOST_PACKET + i); + csum += *dout; + } + + if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { + printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n", + rs.struct_version, EC_HOST_RESPONSE_VERSION); + return -1; + } + + if (rs.reserved) { + printk(BIOS_ERR, "EC response reserved is %d, should be 0\n", + rs.reserved); + return -1; + } + + if (rs.data_len > cec_command->cmd_size_out) { + printk(BIOS_ERR, "EC returned too much data (%d > %d)\n", + rs.data_len, cec_command->cmd_size_out); + return -1; + } + + /* Read back data and update checksum */ + for (i = 0, dout = (uint8_t *)cec_command->cmd_data_out; + i < rs.data_len; i++, dout++) { + *dout = inb(EC_LPC_ADDR_HOST_PACKET + sizeof(rs) + i); + csum += *dout; + } + + /* Verify checksum */ + if ((u8)csum) { + printk(BIOS_ERR, "EC response has invalid checksum\n"); + return -1; + } + + return 0; +} + +static int google_chromeec_command_v1(struct chromeec_command *cec_command) +{ + struct ec_lpc_host_args args; + const u8 *d; + u8 *dout; + u8 cmd_code = cec_command->cmd_code; + int csum; + int i; + + /* Fill in args */ + args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; + args.command_version = cec_command->cmd_version; + args.data_size = cec_command->cmd_size_in; + + /* Initialize checksum */ + csum = cmd_code + args.flags + args.command_version + args.data_size; + + /* Write data and update checksum */ + for (i = 0, d = (const u8 *)cec_command->cmd_data_in; + i < cec_command->cmd_size_in; i++, d++) { + outb(*d, EC_LPC_ADDR_HOST_PARAM + i); + csum += *d; + } + + /* Finalize checksum and write args */ + args.checksum = (u8)csum; + for (i = 0, d = (const u8 *)&args; i < sizeof(args); i++, d++) + outb(*d, EC_LPC_ADDR_HOST_ARGS + i); + + + /* Issue the command */ + outb(cmd_code, EC_LPC_ADDR_HOST_CMD); + + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", + cec_command->cmd_code); + return 1; + } + + /* Check result */ + cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); + if (cec_command->cmd_code) + return 1; + + /* Read back args */ + for (i = 0, dout = (u8 *)&args; i < sizeof(args); i++, dout++) + *dout = inb(EC_LPC_ADDR_HOST_ARGS + i); + + /* + * If EC didn't modify args flags, then somehow we sent a new-style + * command to an old EC, which means it would have read its params + * from the wrong place. + */ + if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) { + printk(BIOS_ERR, "EC protocol mismatch\n"); + return 1; + } + + if (args.data_size > cec_command->cmd_size_out) { + printk(BIOS_ERR, "EC returned too much data\n"); + return 1; + } + cec_command->cmd_size_out = args.data_size; + + /* Start calculating response checksum */ + csum = cmd_code + args.flags + args.command_version + args.data_size; + + /* Read data, if any */ + for (i = 0, dout = (u8 *)cec_command->cmd_data_out; + i < args.data_size; i++, dout++) { + *dout = inb(EC_LPC_ADDR_HOST_PARAM + i); + csum += *dout; + } + + /* Verify checksum */ + if (args.checksum != (u8)csum) { + printk(BIOS_ERR, "EC response has invalid checksum\n"); + return 1; + } + + return 0; +} + +#ifdef __PRE_RAM__ + +int google_chromeec_command(struct chromeec_command *cec_command) +{ + switch (google_chromeec_command_version()) { + case EC_HOST_CMD_FLAG_VERSION_3: + return google_chromeec_command_v3(cec_command); + case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED: + return google_chromeec_command_v1(cec_command); + } + return -1; +} + +#else /* !__PRE_RAM__ */ + +int google_chromeec_command(struct chromeec_command *cec_command) +{ + static int command_version = 0; + + if (command_version <= 0) + command_version = google_chromeec_command_version(); + + switch (command_version) { + case EC_HOST_CMD_FLAG_VERSION_3: + return google_chromeec_command_v3(cec_command); + case EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED: + return google_chromeec_command_v1(cec_command); + } + return -1; +} + +#ifndef __SMM__ +static void lpc_ec_init(device_t dev) +{ + struct ec_google_chromeec_config *conf = dev->chip_info; + + if (!dev->enabled) + return; + pc_keyboard_init(&conf->keyboard); + google_chromeec_init(); +} + +static void lpc_ec_read_resources(device_t dev) +{ + /* Nothing, but this function avoids an error on serial console. */ +} + +static void lpc_ec_enable_resources(device_t dev) +{ + /* Nothing, but this function avoids an error on serial console. */ +} + +static struct device_operations ops = { + .init = lpc_ec_init, + .read_resources = lpc_ec_read_resources, + .enable_resources = lpc_ec_enable_resources +}; + +static struct pnp_info pnp_dev_info[] = { + { &ops, 0, 0, { 0, 0 }, } +}; + +static void enable_dev(device_t dev) +{ + pnp_enable_devices(dev, &pnp_ops, ARRAY_SIZE(pnp_dev_info), + pnp_dev_info); +} + +struct chip_operations ec_google_chromeec_ops = { + CHIP_NAME("Google Chrome EC") + .enable_dev = enable_dev, +}; + +#endif /* __SMM__ */ + +u8 google_chromeec_get_event(void) +{ + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + printk(BIOS_ERR, "Timeout waiting for EC ready!\n"); + return 1; + } + + /* Issue the ACPI query-event command */ + outb(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD); + + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n"); + return 0; + } + + /* Event (or 0 if none) is returned directly in the data byte */ + return inb(EC_LPC_ADDR_ACPI_DATA); +} +#endif diff --git a/src/ec/google/chromeec/ec_message.h b/src/ec/google/chromeec/ec_message.h new file mode 100644 index 0000000000..a2421c7ba4 --- /dev/null +++ b/src/ec/google/chromeec/ec_message.h @@ -0,0 +1,44 @@ +/* + * Chromium OS Matrix Keyboard Message Protocol definitions + * + * Copyright (c) 2012 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _CROS_MESSAGE_H +#define _CROS_MESSAGE_H + +/* + * Command interface between EC and AP, for LPC, I2C and SPI interfaces. + * + * This is copied from the Chromium OS Open Source Embedded Controller code. + */ +enum { + /* The header byte, which follows the preamble */ + MSG_HEADER = 0xec, + + MSG_HEADER_BYTES = 3, + MSG_TRAILER_BYTES = 2, + MSG_PROTO_BYTES = MSG_HEADER_BYTES + MSG_TRAILER_BYTES, + + /* Max length of messages */ + MSG_BYTES = EC_HOST_PARAM_SIZE + MSG_PROTO_BYTES, +}; + +#endif diff --git a/src/ec/google/chromeec/ec_spi.c b/src/ec/google/chromeec/ec_spi.c new file mode 100644 index 0000000000..d11348cff7 --- /dev/null +++ b/src/ec/google/chromeec/ec_spi.c @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "ec.h" +#include "ec_commands.h" +#include +#include + +static const uint8_t EcFramingByte = 0xec; + +#define PROTO3_MAX_PACKET_SIZE 268 + +static uint8_t req_buf[PROTO3_MAX_PACKET_SIZE]; +static uint8_t resp_buf[PROTO3_MAX_PACKET_SIZE]; + +void *crosec_get_buffer(size_t size, int req) +{ + if (size > PROTO3_MAX_PACKET_SIZE) { + printk(BIOS_DEBUG, "Proto v3 buffer request too large: %zu!\n", + size); + return NULL; + } + + if (req) + return req_buf; + else + return resp_buf; +} + +static int crosec_spi_io(size_t req_size, size_t resp_size, void *context) +{ + struct spi_slave *slave = (struct spi_slave *)context; + + spi_claim_bus(slave); + + /* Allow EC to ramp up clock after being awaken. + * See chrome-os-partner:32223 for more details. */ + udelay(CONFIG_EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US); + + if (spi_xfer(slave, req_buf, req_size, NULL, 0)) { + printk(BIOS_ERR, "%s: Failed to send request.\n", __func__); + spi_release_bus(slave); + return -1; + } + + uint8_t byte; + struct stopwatch sw; + // Wait 1s for a framing byte. + stopwatch_init_usecs_expire(&sw, USECS_PER_SEC); + while (1) { + if (spi_xfer(slave, NULL, 0, &byte, sizeof(byte))) { + printk(BIOS_ERR, "%s: Failed to receive byte.\n", + __func__); + spi_release_bus(slave); + return -1; + } + if (byte == EcFramingByte) + break; + + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, + "%s: Timeout waiting for framing byte.\n", + __func__); + spi_release_bus(slave); + return -1; + } + } + + if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) { + printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__); + spi_release_bus(slave); + return -1; + } + + spi_release_bus(slave); + + return 0; +} + +int google_chromeec_command(struct chromeec_command *cec_command) +{ + static struct spi_slave *slave = NULL; + if (!slave) + slave = spi_setup_slave(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, + CONFIG_EC_GOOGLE_CHROMEEC_SPI_CHIP); + return crosec_command_proto(cec_command, crosec_spi_io, slave); +} + +#ifndef __PRE_RAM__ +u8 google_chromeec_get_event(void) +{ + printk(BIOS_ERR, "%s: Not supported.\n", __func__); + return 0; +} +#endif diff --git a/src/include/antirollback.h b/src/include/antirollback.h new file mode 100644 index 0000000000..5ba36f7e65 --- /dev/null +++ b/src/include/antirollback.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Functions for querying, manipulating and locking rollback indices + * stored in the TPM NVRAM. + */ + +#ifndef ANTIROLLBACK_H_ +#define ANTIROLLBACK_H_ + +#include "tpm_lite/tss_constants.h" + +struct vb2_context; +enum vb2_pcr_digest; + +/* TPM NVRAM location indices. */ +#define FIRMWARE_NV_INDEX 0x1007 +#define KERNEL_NV_INDEX 0x1008 +/* This is just an opaque space for backup purposes */ +#define BACKUP_NV_INDEX 0x1009 + +/* Structure definitions for TPM spaces */ + +/* Flags for firmware space */ + +/* + * Last boot was developer mode. TPM ownership is cleared when transitioning + * to/from developer mode. + */ +#define FLAG_LAST_BOOT_DEVELOPER 0x01 + +/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ + +uint32_t antirollback_read_space_firmware(struct vb2_context *ctx); + +/** + * Write may be called if the versions change. + */ +uint32_t antirollback_write_space_firmware(struct vb2_context *ctx); + +/** + * Lock must be called. + */ +uint32_t antirollback_lock_space_firmware(void); + +/****************************************************************************/ + +/* + * The following functions are internal apis, listed here for use by unit tests + * only. + */ + +/** + * Ask vboot for a digest and extend a TPM PCR with it. + */ +uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, + enum vb2_pcr_digest which_digest); + +/** + * Issue a TPM_Clear and reenable/reactivate the TPM. + */ +uint32_t tpm_clear_and_reenable(void); + +/** + * Like tlcl_write(), but checks for write errors due to hitting the 64-write + * limit and clears the TPM when that happens. This can only happen when the + * TPM is unowned, so it is OK to clear it (and we really have no choice). + * This is not expected to happen frequently, but it could happen. + */ +uint32_t safe_write(uint32_t index, const void *data, uint32_t length); + +/** + * Similarly to safe_write(), this ensures we don't fail a DefineSpace because + * we hit the TPM write limit. This is even less likely to happen than with + * writes because we only define spaces once at initialization, but we'd rather + * be paranoid about this. + */ +uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size); + +/** + * Perform one-time initializations. + * + * Create the NVRAM spaces, and set their initial values as needed. Sets the + * nvLocked bit and ensures the physical presence command is enabled and + * locked. + */ +uint32_t factory_initialize_tpm(struct vb2_context *ctx); + +/** + * Start the TPM and establish the root of trust for the antirollback mechanism. + */ +uint32_t setup_tpm(struct vb2_context *ctx); + +#endif /* ANTIROLLBACK_H_ */ diff --git a/src/include/assert.h b/src/include/assert.h index 346e76961e..9f624a931f 100644 --- a/src/include/assert.h +++ b/src/include/assert.h @@ -20,6 +20,8 @@ #ifndef __ASSERT_H__ #define __ASSERT_H__ +#include + #if defined(__PRE_RAM__) && !CONFIG_CACHE_AS_RAM /* ROMCC versions */ @@ -59,6 +61,8 @@ /* die(""); */ \ } -#endif +#endif /* defined(__PRE_RAM__) && !CONFIG_CACHE_AS_RAM */ + +#define assert(statement) ASSERT(statement) #endif // __ASSERT_H__ diff --git a/src/include/base3.h b/src/include/base3.h new file mode 100644 index 0000000000..e92cc8bae7 --- /dev/null +++ b/src/include/base3.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SRC_INCLUDE_BASE3_H__ +#define __SRC_INCLUDE_BASE3_H__ + +/* We translate a floating pin (Z) as the ternary digit 2. */ +#define Z 2 + +/* + * This provides a variadic macro BASE3() that can be used to translate a set of + * pin states into its base-3 integer representation, even in the context of a + * static initializer. You can call it with any number of up to 6 arguments, + * e.g. BASE3(1, Z) -> 5 or BASE3(0, Z, 1, 0) -> 21. Just don't look too closely + * at how the sausage is made. (Pay extra attention to typos when expanding it!) + */ +#define _BASE3_IMPL_1(arg0, arg1, arg2, arg3, arg4, arg5) arg0 +#define _BASE3_IMPL_2(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg1 + (3 * _BASE3_IMPL_1(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_3(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg2 + (3 * _BASE3_IMPL_2(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_4(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg3 + (3 * _BASE3_IMPL_3(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_5(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg4 + (3 * _BASE3_IMPL_4(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_6(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg5 + (3 * _BASE3_IMPL_5(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL(arg0, arg1, arg2, arg3, arg4, arg5, NARGS, ...) \ + _BASE3_IMPL##NARGS(arg0, arg1, arg2, arg3, arg4, arg5) +#define BASE3(...) _BASE3_IMPL(__VA_ARGS__, _6, _5, _4, _3, _2, _1) + +#endif /* __SRC_INCLUDE_BASE3_H__ */ diff --git a/src/include/bcd.h b/src/include/bcd.h new file mode 100644 index 0000000000..a0850271b8 --- /dev/null +++ b/src/include/bcd.h @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef _BCD_H_ +#define _BCD_H_ + +#include + +static inline uint8_t bcd2bin(uint8_t val) +{ + return ((val >> 4) & 0xf) * 10 + (val & 0xf); +} + +static inline uint8_t bin2bcd(uint8_t val) +{ + return ((val / 10) << 4) | (val % 10); +} + +#endif /* _BCD_H_ */ diff --git a/src/include/boardid.h b/src/include/boardid.h new file mode 100644 index 0000000000..41c21d6e31 --- /dev/null +++ b/src/include/boardid.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __INCLUDE_BOARDID_H__ +#define __INCLUDE_BOARDID_H__ + +#include + +uint8_t board_id(void); +uint32_t ram_code(void); + +#endif /* __INCLUDE_BOARDID_H__ */ diff --git a/src/include/boot/coreboot_tables.h b/src/include/boot/coreboot_tables.h index a7e4ab0500..5340549404 100644 --- a/src/include/boot/coreboot_tables.h +++ b/src/include/boot/coreboot_tables.h @@ -163,7 +163,7 @@ struct lb_console { #define LB_TAG_CONSOLE_SERIAL8250 0 #define LB_TAG_CONSOLE_VGA 1 // OBSOLETE #define LB_TAG_CONSOLE_BTEXT 2 // OBSOLETE -#define LB_TAG_CONSOLE_LOGBUF 3 +#define LB_TAG_CONSOLE_LOGBUF 3 // OBSOLETE #define LB_TAG_CONSOLE_SROM 4 // OBSOLETE #define LB_TAG_CONSOLE_EHCI 5 #define LB_TAG_CONSOLE_SERIAL8250MEM 6 @@ -197,6 +197,10 @@ struct lb_framebuffer { #define LB_TAG_GPIO 0x0013 +/* Values for the polarity field below. */ +#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1 + struct lb_gpio { uint32_t port; uint32_t polarity; @@ -213,18 +217,26 @@ struct lb_gpios { struct lb_gpio gpios[0]; }; -#define LB_TAG_VDAT 0x0015 -struct lb_vdat { +#define LB_TAG_VDAT 0x0015 +#define LB_TAG_VBNV 0x0019 +#define LB_TAB_VBOOT_HANDOFF 0x0020 +#define LB_TAB_DMA 0x0022 +#define LB_TAG_RAM_OOPS 0x0023 +struct lb_range { uint32_t tag; uint32_t size; - void *vdat_addr; - uint32_t vdat_size; + uint64_t range_start; + uint32_t range_size; }; +void lb_ramoops(struct lb_header *header); + #define LB_TAG_TIMESTAMPS 0x0016 #define LB_TAG_CBMEM_CONSOLE 0x0017 #define LB_TAG_MRC_CACHE 0x0018 +#define LB_TAG_ACPI_GNVS 0x0024 +#define LB_TAG_WIFI_CALIBRATION 0x0027 struct lb_cbmem_ref { uint32_t tag; uint32_t size; @@ -232,24 +244,6 @@ struct lb_cbmem_ref { uint64_t cbmem_addr; }; -#define LB_TAG_VBNV 0x0019 -struct lb_vbnv { - uint32_t tag; - uint32_t size; - - uint32_t vbnv_start; - uint32_t vbnv_size; -}; - -#define LB_TAB_VBOOT_HANDOFF 0x0020 -struct lb_vboot_handoff { - uint32_t tag; - uint32_t size; - - void *vboot_handoff_addr; - uint32_t vboot_handoff_size; -}; - #define LB_TAG_X86_ROM_MTRR 0x0021 struct lb_x86_rom_mtrr { uint32_t tag; @@ -258,6 +252,34 @@ struct lb_x86_rom_mtrr { uint32_t index; }; +#define LB_TAG_BOARD_ID 0x0025 +struct lb_board_id { + uint32_t tag; + uint32_t size; + /* Board ID as retrieved from the board revision GPIOs. */ + uint32_t board_id; +}; + +#define LB_TAG_MAC_ADDRS 0x0026 +struct mac_address { + uint8_t mac_addr[6]; + uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ +}; + +struct lb_macs { + uint32_t tag; + uint32_t size; + uint32_t count; + struct mac_address mac_addrs[0]; +}; + +#define LB_TAG_RAM_CODE 0x0028 +struct lb_ram_code { + uint32_t tag; + uint32_t size; + uint32_t ram_code; +}; + /* The following structures are for the cmos definitions table */ #define LB_TAG_CMOS_OPTION_TABLE 200 /* cmos header record */ @@ -347,4 +369,15 @@ struct lb_memory *get_lb_mem(void); void fill_lb_gpios(struct lb_gpios *gpios); +/* Define this in mainboard.c to add board-specific table entries. */ +void lb_board(struct lb_header *header); + +/* + * Function to retrieve MAC address(es) from the VPD and store them in the + * coreboot table. + */ +void lb_table_add_macs_from_vpd(struct lb_header *header); + +struct lb_record *lb_new_record(struct lb_header *header); + #endif /* COREBOOT_TABLES_H */ diff --git a/src/include/boot/elf.h b/src/include/boot/elf.h deleted file mode 100644 index 5be96be103..0000000000 --- a/src/include/boot/elf.h +++ /dev/null @@ -1,403 +0,0 @@ -#ifndef ELF_H -#define ELF_H - -/* Standard ELF types. */ - -#include -#include -#include - -/* Type for a 16-bit quantity. */ -typedef uint16_t Elf32_Half; -typedef uint16_t Elf64_Half; - -/* Types for signed and unsigned 32-bit quantities. */ -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; - -/* Types for signed and unsigned 64-bit quantities. */ -typedef uint64_t Elf32_Xword; -typedef int64_t Elf32_Sxword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* Type of addresses. */ -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf64_Addr; - -/* Type of file offsets. */ -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Off; - -/* Type for section indices, which are 16-bit quantities. */ -typedef uint16_t Elf32_Section; -typedef uint16_t Elf64_Section; - -/* Type of symbol indices. */ -typedef uint32_t Elf32_Symndx; -typedef uint64_t Elf64_Symndx; - - -/* The ELF file header. This appears at the start of every ELF file. */ - -#define EI_NIDENT (16) - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -} Elf32_Ehdr; - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -/* Fields in the e_ident array. The EI_* macros are indices into the - array. The macros under each EI_* macro are the values the byte - may have. */ - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7f /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -/* Conglomeration of the identification bytes, for easy testing as a word. */ -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ -#define ELFCLASSNUM 3 - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ -#define ELFDATANUM 3 - -#define EI_VERSION 6 /* File version byte index */ - /* Value must be EV_CURRENT */ - -#define EI_OSABI 7 /* OS ABI identification */ -#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ -#define ELFOSABI_HPUX 1 /* HP-UX */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* Byte index of padding bytes */ - -/* Legal values for e_type (object file type). */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_NUM 5 /* Number of defined types */ -#define ET_LOPROC 0xff00 /* Processor-specific */ -#define ET_HIPROC 0xffff /* Processor-specific */ - -/* Legal values for e_machine (architecture). */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_486 6 /* Intel 80486 */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_S370 9 /* Amdahl */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ -#define EM_RS6000 11 /* RS6000 */ - -#define EM_PARISC 15 /* HPPA */ -#define EM_nCUBE 16 /* nCUBE */ -#define EM_VPP500 17 /* Fujitsu VPP500 */ -#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ -#define EM_960 19 /* Intel 80960 */ -#define EM_PPC 20 /* PowerPC */ - -#define EM_V800 36 /* NEC V800 series */ -#define EM_FR20 37 /* Fujitsu FR20 */ -#define EM_RH32 38 /* TRW RH32 */ -#define EM_MMA 39 /* Fujitsu MMA */ -#define EM_ARM 40 /* ARM */ -#define EM_FAKE_ALPHA 41 /* Digital Alpha */ -#define EM_SH 42 /* Hitachi SH */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit */ -#define EM_TRICORE 44 /* Siemens Tricore */ -#define EM_ARC 45 /* Argonaut RISC Core */ -#define EM_H8_300 46 /* Hitachi H8/300 */ -#define EM_H8_300H 47 /* Hitachi H8/300H */ -#define EM_H8S 48 /* Hitachi H8S */ -#define EM_H8_500 49 /* Hitachi H8/500 */ -#define EM_IA_64 50 /* Intel Merced */ -#define EM_MIPS_X 51 /* Stanford MIPS-X */ -#define EM_COLDFIRE 52 /* Motorola Coldfire */ -#define EM_68HC12 53 /* Motorola M68HC12 */ -#define EM_NUM 54 - -/* If it is necessary to assign new unofficial EM_* values, please - pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the - chances of collision with official or non-GNU unofficial values. */ - -#define EM_ALPHA 0x9026 - -/* Legal values for e_version (version). */ - -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ -#define EV_NUM 2 - - -/* Program segment header. */ - -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -} Elf32_Phdr; - -typedef struct -{ - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment */ -} Elf64_Phdr; - -/* Legal values for p_type (segment type). */ - -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_NUM 7 /* Number of defined types. */ -#define PT_LOOS 0x60000000 /* Start of OS-specific */ -#define PT_HIOS 0x6fffffff /* End of OS-specific */ -#define PT_LOPROC 0x70000000 /* Start of processor-specific */ -#define PT_HIPROC 0x7fffffff /* End of processor-specific */ - -/* Legal values for p_flags (segment flags). */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific */ - - -/* Note section contents. Each entry in the note section begins with - a header of a fixed form. */ - -typedef struct -{ - Elf32_Word n_namesz; /* Length of the note's name. */ - Elf32_Word n_descsz; /* Length of the note's descriptor. */ - Elf32_Word n_type; /* Type of the note. */ -} Elf32_Nhdr; - -typedef struct -{ - Elf64_Word n_namesz; /* Length of the note's name. */ - Elf64_Word n_descsz; /* Length of the note's descriptor. */ - Elf64_Word n_type; /* Type of the note. */ -} Elf64_Nhdr; - -/* Known names of notes. */ - -/* Solaris entries in the note section have this name. */ -#define ELF_NOTE_SOLARIS "SUNW Solaris" - -/* Note entries for GNU systems have this name. */ -#define ELF_NOTE_GNU "GNU" - - -/* Defined types of notes for Solaris. */ - -/* Value of descriptor (one word) is desired pagesize for the binary. */ -#define ELF_NOTE_PAGESIZE_HINT 1 - - -/* Defined note types for GNU systems. */ - -/* ABI information. The descriptor consists of words: - word 0: OS descriptor - word 1: major version of the ABI - word 2: minor version of the ABI - word 3: subminor version of the ABI -*/ -#define ELF_NOTE_ABI 1 - -/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI - note section entry. */ -#define ELF_NOTE_OS_LINUX 0 -#define ELF_NOTE_OS_GNU 1 -#define ELF_NOTE_OS_SOLARIS2 2 - - -/* Motorola 68k specific definitions. */ - -/* Intel 80386 specific definitions. */ - -/* SUN SPARC specific definitions. */ - -/* Values for Elf64_Ehdr.e_flags. */ - -#define EF_SPARCV9_MM 3 -#define EF_SPARCV9_TSO 0 -#define EF_SPARCV9_PSO 1 -#define EF_SPARCV9_RMO 2 -#define EF_SPARC_EXT_MASK 0xFFFF00 -#define EF_SPARC_SUN_US1 0x000200 -#define EF_SPARC_HAL_R1 0x000400 - -/* MIPS R3000 specific definitions. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ -#define EF_MIPS_PIC 2 /* Contains PIC code */ -#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ -#define EF_MIPS_XGOT 8 -#define EF_MIPS_64BIT_WHIRL 16 -#define EF_MIPS_ABI2 32 -#define EF_MIPS_ABI_ON32 64 -#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ - -/* Legal values for MIPS architecture level. */ - -#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ -#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ -#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ -#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ -#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ - -/* Legal values for p_type field of Elf32_Phdr. */ - -#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ -#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ -#define PT_MIPS_OPTIONS 0x70000002 - -/* Special program header types. */ - -#define PF_MIPS_LOCAL 0x10000000 - - -/* HPPA specific definitions. */ - -/* Legal values for e_flags field of Elf32_Ehdr. */ - -#define EF_PARISC_TRAPNL 1 /* Trap nil pointer dereference. */ -#define EF_PARISC_EXT 2 /* Program uses arch. extensions. */ -#define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */ -/* Defined values are: - 0x020b PA-RISC 1.0 big-endian - 0x0210 PA-RISC 1.1 big-endian - 0x028b PA-RISC 1.0 little-endian - 0x0290 PA-RISC 1.1 little-endian -*/ - - -/* Alpha specific definitions. */ - -/* Legal values for e_flags field of Elf64_Ehdr. */ - -#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ -#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ - - -/* PowerPC specific declarations */ - -/* ARM specific declarations */ - -/* Processor specific flags for the ELF header e_flags field. */ -#define EF_ARM_RELEXEC 0x01 -#define EF_ARM_HASENTRY 0x02 -#define EF_ARM_INTERWORK 0x04 -#define EF_ARM_APCS_26 0x08 -#define EF_ARM_APCS_FLOAT 0x10 -#define EF_ARM_PIC 0x20 -#define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */ -#define EF_NEW_ABI 0x80 -#define EF_OLD_ABI 0x100 - -/* ARM-specific program header flags */ -#define PF_ARM_SB 0x10000000 /* Segment contains the location - addressed by the static base */ - -#if ELF_CLASS == ELFCLASS32 -typedef Elf32_Ehdr Elf_ehdr; -typedef Elf32_Phdr Elf_phdr; -#endif - -#if ELF_CLASS == ELFCLASS64 -typedef Elf64_Ehdr Elf_ehdr; -typedef Elf64_Phdr Elf_phdr; -#endif - -int elf_check_arch(Elf_ehdr *ehdr); -void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long bounce_size); -struct lb_memory; -int elfboot(struct lb_memory *mem); -/* Temporary compile fix, FILO should be dropped from coreboot */ -int filo(struct lb_memory *mem); - -#define FIRMWARE_TYPE "coreboot" -#define BOOTLOADER "elfboot" -#define BOOTLOADER_VERSION "1.3" - -#endif /* elf.h */ diff --git a/src/include/boot/elf_boot.h b/src/include/boot/elf_boot.h deleted file mode 100644 index b119babc00..0000000000 --- a/src/include/boot/elf_boot.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef ELF_BOOT_H -#define ELF_BOOT_H - -#include - -/* This defines the structure of a table of parameters useful for ELF - * bootable images. These parameters are all passed and generated - * by the bootloader to the booted image. For simplicity and - * consistency the Elf Note format is reused. - * - * All of the information must be Position Independent Data. - * That is it must be safe to relocate the whole ELF boot parameter - * block without changing the meaning or correctnes of the data. - * Additionally it must be safe to permute the order of the ELF notes - * to any possible permutation without changing the meaning or correctness - * of the data. - * - */ - -#define ELF_HEAD_SIZE (8*1024) -#define ELF_BOOT_MAGIC 0x0E1FB007 - -typedef uint16_t Elf_Half; -typedef uint32_t Elf_Word; -typedef uint64_t Elf_Xword; - -typedef struct -{ - Elf_Word b_signature; /* "0x0E1FB007" */ - Elf_Word b_size; - Elf_Half b_checksum; - Elf_Half b_records; -} Elf_Bhdr; - -typedef struct -{ - Elf_Word n_namesz; /* Length of the note's name. */ - Elf_Word n_descsz; /* Length of the note's descriptor. */ - Elf_Word n_type; /* Type of the note. */ -} Elf_Nhdr; - - -/* For standard notes n_namesz must be zero */ -/* All of the following standard note types provide a single null - * terminated string in the descriptor. - */ -#define EBN_FIRMWARE_TYPE 0x00000001 -/* On platforms that support multiple classes of firmware this field - * specifies the class of firmware you are loaded under. - */ -#define EBN_BOOTLOADER_NAME 0x00000002 -/* This specifies just the name of the bootloader for easy comparison */ -#define EBN_BOOTLOADER_VERSION 0x00000003 -/* This specifies the version of the bootlader */ -#define EBN_COMMAND_LINE 0x00000004 -/* This specifies a command line that can be set by user interaction, - * and is provided as a free form string to the loaded image. - */ - - -/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */ - -#define ELF_NOTE_BOOT "ELFBoot" - -#define EIN_PROGRAM_NAME 0x00000001 -/* The program in this ELF file */ -#define EIN_PROGRAM_VERSION 0x00000002 -/* The version of the program in this ELF file */ -#define EIN_PROGRAM_CHECKSUM 0x00000003 -/* ip style checksum of the memory image. */ - - -/* Linux image notes for booting... The name for all of these is Linux */ - -#define LINUX_NOTE_BOOT "Linux" - -#define LIN_COMMAND_LINE 0x00000001 -/* The command line to pass to the loaded kernel. */ -#define LIN_ROOT_DEV 0x00000002 -/* The root dev to pass to the loaded kernel. */ -#define LIN_RAMDISK_FLAGS 0x00000003 -/* Various old ramdisk flags */ -#define LIN_INITRD_START 0x00000004 -/* Start of the ramdisk in bytes */ -#define LIN_INITRD_SIZE 0x00000005 -/* Size of the ramdisk in bytes */ - - -#endif /* ELF_BOOT_H */ diff --git a/src/include/bootstate.h b/src/include/bootstate.h new file mode 100644 index 0000000000..cd753042ab --- /dev/null +++ b/src/include/bootstate.h @@ -0,0 +1,192 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef BOOTSTATE_H +#define BOOTSTATE_H + +#include + +/* Control debugging of the boot state machine. */ +#define BOOT_STATE_DEBUG 0 + +/* + * The boot state machine provides a mechanism for calls to be made through- + * out the main boot process. The boot process is separated into discrete + * states. Upon a state's entry and exit and callbacks can be made. For + * example: + * + * Enter State + * + + * | + * V + * +-----------------+ + * | Entry callbacks | + * +-----------------+ + * | State Actions | + * +-----------------+ + * | Exit callbacks | + * +-------+---------+ + * | + * V + * Next State + * + * Below is the current flow from top to bottom: + * + * start + * | + * BS_PRE_DEVICE + * | + * BS_DEV_INIT_CHIPS + * | + * BS_DEV_ENUMERATE + * | + * BS_DEV_RESOURCES + * | + * BS_DEV_ENABLE + * | + * BS_DEV_INIT + * | + * BS_POST_DEVICE + * | + * BS_OS_RESUME_CHECK -------- BS_OS_RESUME + * | | + * BS_WRITE_TABLES os handoff + * | + * BS_PAYLOAD_LOAD + * | + * BS_PAYLOAD_BOOT + * | + * payload run + * + * Brief description of states: + * BS_PRE_DEVICE - before any device tree actions take place + * BS_DEV_INIT_CHIPS - init all chips in device tree + * BS_DEV_ENUMERATE - device tree probing + * BS_DEV_RESOURCES - device tree resource allocation and assignment + * BS_DEV_ENABLE - device tree enabling/disabling of devices + * BS_DEV_INIT - device tree device initialization + * BS_POST_DEVICE - all device tree actions performed + * BS_OS_RESUME_CHECK - check for OS resume + * BS_OS_RESUME - resume to OS + * BS_WRITE_TABLES - write coreboot tables + * BS_PAYLOAD_LOAD - Load payload into memory + * BS_PAYLOAD_BOOT - Boot to payload + */ + +typedef enum { + BS_PRE_DEVICE, + BS_DEV_INIT_CHIPS, + BS_DEV_ENUMERATE, + BS_DEV_RESOURCES, + BS_DEV_ENABLE, + BS_DEV_INIT, + BS_POST_DEVICE, + BS_OS_RESUME_CHECK, + BS_OS_RESUME, + BS_WRITE_TABLES, + BS_PAYLOAD_LOAD, + BS_PAYLOAD_BOOT, +} boot_state_t; + +/* The boot_state_sequence_t describes when a callback is to be made. It is + * called either before a state is entered or when a state is exited. */ +typedef enum { + BS_ON_ENTRY, + BS_ON_EXIT +} boot_state_sequence_t; + +struct boot_state_callback { + void *arg; + void (*callback)(void *arg); + /* For use internal to the boot state machine. */ + struct boot_state_callback *next; +#if BOOT_STATE_DEBUG + const char *location; +#endif +}; + +#if BOOT_STATE_DEBUG +#define BOOT_STATE_CALLBACK_LOC __FILE__ ":" STRINGIFY(__LINE__) +#define BOOT_STATE_CALLBACK_INIT_DEBUG .location = BOOT_STATE_CALLBACK_LOC, +#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \ + bscb_->location = BOOT_STATE_CALLBACK_LOC; +#else +#define BOOT_STATE_CALLBACK_INIT_DEBUG +#define INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) +#endif + +#define BOOT_STATE_CALLBACK_INIT(func_, arg_) \ + { \ + .arg = arg_, \ + .callback = func_, \ + .next = NULL, \ + BOOT_STATE_CALLBACK_INIT_DEBUG \ + } + +#define BOOT_STATE_CALLBACK(name_, func_, arg_) \ + struct boot_state_callback name_ = BOOT_STATE_CALLBACK_INIT(func_, arg_) + +/* Initialize an allocated boot_state_callback. */ +#define INIT_BOOT_STATE_CALLBACK(bscb_, func_, arg_) \ + INIT_BOOT_STATE_CALLBACK_DEBUG(bscb_) \ + bscb_->callback = func_; \ + bscb_->arg = arg_ + +/* The following 2 functions schedule a callback to be called on entry/exit + * to a given state. Note that thare are no ordering guarantees between the + * individual callbacks on a given state. 0 is returned on success < 0 on + * error. */ +int boot_state_sched_on_entry(struct boot_state_callback *bscb, + boot_state_t state); +int boot_state_sched_on_exit(struct boot_state_callback *bscb, + boot_state_t state); + +/* Block/Unblock the (state, seq) pair from transitioning. Returns 0 on + * success < 0 when the phase of the (state,seq) has already ran. */ +int boot_state_block(boot_state_t state, boot_state_sequence_t seq); +int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq); +/* Block/Unblock current state phase from transitioning. */ +void boot_state_current_block(void); +void boot_state_current_unblock(void); + +/* Entry into the boot state machine. */ +void main(void); + +/* In order to schedule boot state callbacks at compile-time specify the + * entries in an array using the BOOT_STATE_INIT_ENTRIES and + * BOOT_STATE_INIT_ENTRY macros below. */ +struct boot_state_init_entry { + boot_state_t state; + boot_state_sequence_t when; + struct boot_state_callback bscb; +}; + +#define BOOT_STATE_INIT_ATTR \ + __attribute__ ((used, aligned(4), section(".bs_init"))) + +#define BOOT_STATE_INIT_ENTRIES(name_) \ + static struct boot_state_init_entry name_[] BOOT_STATE_INIT_ATTR + +#define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_) \ + { \ + .state = state_, \ + .when = when_, \ + .bscb = BOOT_STATE_CALLBACK_INIT(func_, arg_), \ + } + +#endif /* BOOTSTATE_H */ diff --git a/src/include/cbfs.h b/src/include/cbfs.h index ac249aabf5..01117e016e 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -52,11 +52,14 @@ #include +#define CBFS_LOAD_ERROR ((void *)-1) + int cbfs_execute_stage(struct cbfs_media *media, const char *name); void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, uint16_t device, void * dest); void *cbfs_load_payload(struct cbfs_media *media, const char *name); void *cbfs_load_stage(struct cbfs_media *media, const char *name); +void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset); /* Simple buffer for streaming media. */ struct cbfs_simple_buffer { @@ -78,12 +81,17 @@ int run_address(void *f); /* Defined in src/lib/selfboot.c */ struct lb_memory; -int selfboot(struct lb_memory *mem, struct cbfs_payload *payload); +void *selfload(struct lb_memory *mem, struct cbfs_payload *payload); +void selfboot(void *entry); -/* Defined in individual arch / board implementation. */ +/* + * Defined in individual arch / board implementation. + * + * it returns 0 on success and non-zero on error. + */ int init_default_cbfs_media(struct cbfs_media *media); -#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__) +#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__ROMSTAGE__) /* The cache_loaded_ramstage() and load_cached_ramstage() functions are defined * to be weak so that board and chipset code may override them. Their job is to * cache and load the ramstage for quick S3 resume. By default a copy of the diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h index 20636e244a..aaf5c67eb6 100644 --- a/src/include/cbfs_core.h +++ b/src/include/cbfs_core.h @@ -86,10 +86,9 @@ #define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff)) -/** this is the master cbfs header - it need to be located somewhere available - to bootblock (to load romstage). Where it actually lives is up to coreboot. - On x86, a pointer to this header will live at 0xFFFFFFFC. - For other platforms, you need to define CONFIG_CBFS_HEADER_ROM_OFFSET */ +/* this is the master cbfs header - it must be located somewhere available + * to bootblock (to load romstage). The last 4 bytes in the image contain its + * relative offset from the end of the image (as a 32-bit signed integer). */ struct cbfs_header { uint32_t magic; @@ -107,7 +106,7 @@ struct cbfs_header { */ #define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF #define CBFS_ARCHITECTURE_X86 0x00000001 -#define CBFS_ARCHITECTURE_ARMV7 0x00000010 +#define CBFS_ARCHITECTURE_ARM 0x00000010 /** This is a component header - every entry in the CBFS will have this header. @@ -150,8 +149,10 @@ struct cbfs_stage { uint32_t memlen; /** total length of object in memory */ } __attribute__((packed)); -/** this is the sub-header for payload components. Payloads - are loaded by coreboot at the end of the boot process */ +/** this is the sub-header for payload components. Payloads are + * loaded by coreboot or other payloads at the end of the boot + * process + */ struct cbfs_payload_segment { uint32_t type; @@ -166,6 +167,19 @@ struct cbfs_payload { struct cbfs_payload_segment segments; }; +/* for returning payload info to (e.g.) bayou. + * Return the file header, payload header, and name. + * It must be done this way because we can't + * assume file headers and names are contiguous. + * Walking the headers can be expensive, so we get all + * the information we can. + */ +struct cbfs_payload_info { + struct cbfs_file file; + struct cbfs_payload payload; + const char *name; +}; + #define PAYLOAD_SEGMENT_CODE 0x45444F43 #define PAYLOAD_SEGMENT_DATA 0x41544144 #define PAYLOAD_SEGMENT_BSS 0x20535342 @@ -211,9 +225,28 @@ struct cbfs_media { int (*close)(struct cbfs_media *media); }; +/* + * Locate file by name and fill in cbfs_file in host byte order. Returns + * < 0 on error, else the offset of the file data. + */ +ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file, + const char *name); + +/* Read count bytes at offset into dest. Return number of bytes read. */ +size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset, + size_t count); + /* returns pointer to a file entry inside CBFS or NULL */ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name); +/* Fills the pointer info with an array of payload file info structs. + * Reads at most maxentries items. + * Returns number we found. + */ +int cbfs_payload_headers(struct cbfs_media *media, + struct cbfs_payload_info *info, + int maxentries); + /* returns pointer to file content inside CBFS after if type is correct */ void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type); diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 219dbfc53e..ae6a4a9953 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -47,33 +47,83 @@ #define HIGH_MEMORY_SIZE HIGH_MEMORY_DEF_SIZE #endif /* CONFIG_HAVE_ACPI_RESUME */ -#define CBMEM_ID_FREESPACE 0x46524545 -#define CBMEM_ID_GDT 0x4c474454 #define CBMEM_ID_ACPI 0x41435049 #define CBMEM_ID_ACPI_GNVS 0x474e5653 #define CBMEM_ID_ACPI_GNVS_PTR 0x474e5650 +#define CBMEM_ID_WIFI_CALIBRATION 0x57494649 +#define CBMEM_ID_CAR_GLOBALS 0xcac4e6a3 #define CBMEM_ID_CBTABLE 0x43425442 -#define CBMEM_ID_PIRQ 0x49525154 -#define CBMEM_ID_MPTABLE 0x534d5054 -#define CBMEM_ID_RESUME 0x5245534d -#define CBMEM_ID_RESUME_SCRATCH 0x52455343 -#define CBMEM_ID_SMBIOS 0x534d4254 -#define CBMEM_ID_TIMESTAMP 0x54494d45 -#define CBMEM_ID_MRCDATA 0x4d524344 #define CBMEM_ID_CONSOLE 0x434f4e53 -#define CBMEM_ID_ELOG 0x454c4f47 #define CBMEM_ID_COVERAGE 0x47434f56 -#define CBMEM_ID_ROMSTAGE_INFO 0x47545352 -#define CBMEM_ID_ROMSTAGE_RAM_STACK 0x90357ac4 +#define CBMEM_ID_ELOG 0x454c4f47 +#define CBMEM_ID_FREESPACE 0x46524545 +#define CBMEM_ID_GDT 0x4c474454 +#define CBMEM_ID_HOB_LIST 0x486f624c +#define CBMEM_ID_MEMINFO 0x494D454D +#define CBMEM_ID_MPTABLE 0x534d5054 +#define CBMEM_ID_MRCDATA 0x4d524344 +#define CBMEM_ID_PIRQ 0x49525154 +#define CBMEM_ID_POWER_STATE 0x50535454 #define CBMEM_ID_RAMSTAGE 0x9a357a9e #define CBMEM_ID_RAMSTAGE_CACHE 0x9a3ca54e +#define CBMEM_ID_RAM_OOPS 0x05430095 +#define CBMEM_ID_REFCODE 0x04efc0de +#define CBMEM_ID_REFCODE_CACHE 0x4efc0de5 +#define CBMEM_ID_RESUME 0x5245534d +#define CBMEM_ID_RESUME_SCRATCH 0x52455343 +#define CBMEM_ID_ROMSTAGE_INFO 0x47545352 +#define CBMEM_ID_ROMSTAGE_RAM_STACK 0x90357ac4 #define CBMEM_ID_ROOT 0xff4007ff +#define CBMEM_ID_SMBIOS 0x534d4254 +#define CBMEM_ID_SMM_SAVE_SPACE 0x07e9acee +#define CBMEM_ID_SPINTABLE 0x59175917 +#define CBMEM_ID_TIMESTAMP 0x54494d45 #define CBMEM_ID_VBOOT_HANDOFF 0x780074f0 #define CBMEM_ID_NONE 0x00000000 +#define CBMEM_ID_HOB_POINTER 0x484f4221 #ifndef __ASSEMBLER__ #include +struct cbmem_id_to_name { + u32 id; + const char *name; +}; + +#define CBMEM_ID_TO_NAME_TABLE \ + { CBMEM_ID_ACPI, "ACPI " }, \ + { CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, \ + { CBMEM_ID_ACPI_GNVS_PTR, "GNVS PTR " }, \ + { CBMEM_ID_WIFI_CALIBRATION, "WIFI CLBR " }, \ + { CBMEM_ID_CAR_GLOBALS, "CAR GLOBALS" }, \ + { CBMEM_ID_CBTABLE, "COREBOOT " }, \ + { CBMEM_ID_CONSOLE, "CONSOLE " }, \ + { CBMEM_ID_COVERAGE, "COVERAGE " }, \ + { CBMEM_ID_ELOG, "ELOG " }, \ + { CBMEM_ID_FREESPACE, "FREE SPACE " }, \ + { CBMEM_ID_GDT, "GDT " }, \ + { CBMEM_ID_HOB_LIST, "FSP HOB PTR" }, \ + { CBMEM_ID_MEMINFO, "MEM INFO " }, \ + { CBMEM_ID_MPTABLE, "SMP TABLE " }, \ + { CBMEM_ID_MRCDATA, "MRC DATA " }, \ + { CBMEM_ID_PIRQ, "IRQ TABLE " }, \ + { CBMEM_ID_POWER_STATE, "POWER STATE" }, \ + { CBMEM_ID_RAMSTAGE, "RAMSTAGE " }, \ + { CBMEM_ID_RAMSTAGE_CACHE, "RAMSTAGE $ " }, \ + { CBMEM_ID_RAM_OOPS, "RAMOOPS " }, \ + { CBMEM_ID_REFCODE, "REFCODE " }, \ + { CBMEM_ID_REFCODE_CACHE, "REFCODE $ " }, \ + { CBMEM_ID_RESUME, "ACPI RESUME" }, \ + { CBMEM_ID_RESUME_SCRATCH, "ACPISCRATCH" }, \ + { CBMEM_ID_ROMSTAGE_INFO, "ROMSTAGE " }, \ + { CBMEM_ID_ROMSTAGE_RAM_STACK, "ROMSTG STCK" }, \ + { CBMEM_ID_ROOT, "CBMEM ROOT " }, \ + { CBMEM_ID_SMBIOS, "SMBIOS " }, \ + { CBMEM_ID_SMM_SAVE_SPACE, "SMM BACKUP " }, \ + { CBMEM_ID_SPINTABLE, "SPIN TABLE " }, \ + { CBMEM_ID_TIMESTAMP, "TIME STAMP " }, \ + { CBMEM_ID_VBOOT_HANDOFF, "VBOOT " }, + struct cbmem_entry; #if CONFIG_DYNAMIC_CBMEM @@ -155,20 +205,25 @@ void *cbmem_add(u32 id, u64 size); /* Find a cbmem entry of a given id. These return NULL on failure. */ void *cbmem_find(u32 id); +typedef void (* const cbmem_init_hook_t)(void); +void cbmem_run_init_hooks(void); + #ifndef __PRE_RAM__ /* Ramstage only functions. */ void cbmem_list(void); -void cbmem_arch_init(void); -void __attribute__((weak)) cbmem_post_handling(void); void cbmem_print_entry(int n, u32 id, u64 start, u64 size); -/* The pre|post device cbmem initialization functions are for the - * ramstage main to call. When cbmem is actually initialized depends on - * the cbmem implementation. */ -void init_cbmem_pre_device(void); -void init_cbmem_post_device(void); -#else -static inline void cbmem_arch_init(void) {} -#endif /* __PRE_RAM__ */ +#define ROMSTAGE_CBMEM_INIT_HOOK(init_fn_) static cbmem_init_hook_t \ + init_fn_ ## _unused_ __attribute__((unused)) = init_fn_; +#define RAMSTAGE_CBMEM_INIT_HOOK(init_fn_) \ + static cbmem_init_hook_t init_fn_ ## _ptr_ __attribute__((used, \ + section(".rodata.cbmem_init_hooks"))) = init_fn_; +#else /* __PRE_RAM__ */ +#define ROMSTAGE_CBMEM_INIT_HOOK(init_fn_) \ + static cbmem_init_hook_t init_fn_ ## _ptr_ __attribute__((used, \ + section(".rodata.cbmem_init_hooks"))) = init_fn_; +#define RAMSTAGE_CBMEM_INIT_HOOK(init_fn_) static cbmem_init_hook_t \ + init_fn_ ## _unused_ __attribute__((unused)) = init_fn_; +#endif /* !__PRE_RAM__ */ #endif /* __ASSEMBLER__ */ diff --git a/src/include/console/cbmem_console.h b/src/include/console/cbmem_console.h index 37ea4d8e89..1c1da63cdd 100644 --- a/src/include/console/cbmem_console.h +++ b/src/include/console/cbmem_console.h @@ -19,8 +19,13 @@ #ifndef _CONSOLE_CBMEM_CONSOLE_H_ #define _CONSOLE_CBMEM_CONSOLE_H_ +#if IS_ENABLED(CONFIG_CONSOLE_CBMEM) void cbmemc_init(void); void cbmemc_reinit(void); void cbmemc_tx_byte(unsigned char data); +#else +static inline void cbmemc_init(void) {} +static inline void cbmemc_reinit(void) {} +#endif #endif diff --git a/src/include/console/console.h b/src/include/console/console.h index 0b636447be..ffe3a5137a 100644 --- a/src/include/console/console.h +++ b/src/include/console/console.h @@ -23,6 +23,7 @@ #include #include #include +#include #if CONFIG_CONSOLE_SERIAL #include @@ -33,9 +34,7 @@ #if CONFIG_CONSOLE_NE2K #include #endif -#if CONFIG_CONSOLE_CBMEM #include -#endif #ifndef __PRE_RAM__ unsigned char console_rx_byte(void); @@ -69,12 +68,24 @@ void console_init(void); void console_tx_byte(unsigned char byte); void console_tx_flush(void); void post_code(u8 value); +#if CONFIG_CMOS_POST_EXTRA +void post_log_extra(u32 value); +struct device; +void post_log_path(struct device *dev); +void post_log_clear(void); +#else +#define post_log_extra(x) do {} while (0) +#define post_log_path(x) do {} while (0) +#define post_log_clear() do {} while (0) +#endif /* this function is weak and can be overridden by a mainboard function. */ void mainboard_post(u8 value); void __attribute__ ((noreturn)) die(const char *msg); int do_printk(int msg_level, const char *fmt, ...) __attribute__((format(printf, 2, 3))); +int vprintk(int msg_level, const char *fmt, va_list args); -#if defined(__PRE_RAM__) && !CONFIG_EARLY_CONSOLE +#if defined(__BOOTBLOCK__) && !CONFIG_BOOTBLOCK_CONSOLE || \ + (defined(__PRE_RAM__) && !defined(__BOOTBLOCK__)) && !CONFIG_EARLY_CONSOLE static inline void printk(int LEVEL, const char *fmt, ...); static inline void printk(int LEVEL, const char *fmt, ...) { diff --git a/src/include/console/ne2k.h b/src/include/console/ne2k.h index 630252bd21..62424f14fd 100644 --- a/src/include/console/ne2k.h +++ b/src/include/console/ne2k.h @@ -1,5 +1,3 @@ -#ifndef _NE2K_H__ -#define _NE2K_H__ /* * This file is part of the coreboot project. * @@ -19,9 +17,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __ROMCC__ +#ifndef _NE2K_H__ +#define _NE2K_H__ void ne2k_append_data(unsigned char *d, int len, unsigned int base); int ne2k_init(unsigned int eth_nic_base); void ne2k_transmit(unsigned int eth_nic_base); -#endif #endif /* _NE2K_H */ diff --git a/src/include/console/post_codes.h b/src/include/console/post_codes.h index f66d276cdf..a10ea94a8e 100644 --- a/src/include/console/post_codes.h +++ b/src/include/console/post_codes.h @@ -83,16 +83,16 @@ #define POST_ENTRY_C_START 0x13 /** - * \brief Pre call to hardwaremain() + * \brief Pre call to ram stage main() * - * POSTed right before hardwaremain is called from c_start.S + * POSTed right before ram stage main() is called from c_start.S */ #define POST_PRE_HARDWAREMAIN 0x79 /** - * \brief Entry into coreboot in hardwaremain (RAM) + * \brief Entry into coreboot in ram stage main() * - * This is the first call in hardwaremain.c. If this code is POSTed, then + * This is the first call in ram stage main(). If this code is POSTed, then * ramstage has succesfully loaded and started executing. */ #define POST_ENTRY_RAMSTAGE 0x80 @@ -120,32 +120,88 @@ #define POST_ENABLING_CACHE 0x60 /** - * \brief Devices have been enumerated + * \brief Before Device Probe * - * Bus scan, and device enumeration has completed. + * Boot State Machine: bs_pre_device() */ -#define POST_DEVICE_ENUMERATION_COMPLETE 0x66 +#define POST_BS_PRE_DEVICE 0x70 /** - * \brief Devices have been configured + * \brief Initializing Chips * - * Device confgration has completed. + * Boot State Machine: bs_dev_init_chips() */ -#define POST_DEVICE_CONFIGURATION_COMPLETE 0x88 +#define POST_BS_DEV_INIT_CHIPS 0x71 /** - * \brief Devices have been enabled + * \brief Starting Device Enumeration * - * Devices have been enabled. + * Boot State Machine: bs_dev_enumerate() */ -#define POST_DEVICES_ENABLED 0x89 +#define POST_BS_DEV_ENUMERATE 0x72 /** - * \brief Devices have been initialized + * \brief Device Resource Allocatio * - * Devices have been initialized. + * Boot State Machine: bs_dev_resources() */ -#define POST_DEVICES_INITIALIZED 0x8a +#define POST_BS_DEV_RESOURCES 0x73 + +/** + * \brief Device Enable + * + * Boot State Machine: bs_dev_enable() + */ +#define POST_BS_DEV_ENABLE 0x74 + +/** + * \brief Device Initialization + * + * Boot State Machine: bs_dev_init() + */ +#define POST_BS_DEV_INIT 0x75 + +/** + * \brief After Device Probe + * + * Boot State Machine: bs_post_device() + */ +#define POST_BS_POST_DEVICE 0x76 + +/** + * \brief OS Resume Check + * + * Boot State Machine: bs_os_resume_check() + */ +#define POST_BS_OS_RESUME_CHECK 0x77 + +/** + * \brief OS Resume + * + * Boot State Machine: bs_os_resume() + */ +#define POST_BS_OS_RESUME 0x78 + +/** + * \brief Write Tables + * + * Boot State Machine: bs_write_tables() + */ +#define POST_BS_WRITE_TABLES 0x79 + +/** + * \brief Load Payload + * + * Boot State Machine: bs_payload_load() + */ +#define POST_BS_PAYLOAD_LOAD 0x7a + +/** + * \brief Boot Payload + * + * Boot State Machine: bs_payload_boot() + */ +#define POST_BS_PAYLOAD_BOOT 0x7b /** * \brief Entry into elf boot @@ -163,6 +219,13 @@ */ #define POST_JUMPING_TO_PAYLOAD 0xf3 +/** + * \brief TPM failure + * + * An error with the TPM, either unexepcted state or communications failure. + */ +#define POST_TPM_FAILURE 0xed + /** * \brief Not supposed to get here * @@ -172,6 +235,14 @@ */ #define POST_DEAD_CODE 0xee +/** + * \brief Resume from suspend failed + * + * This post code is sent when the firmware is expected to resume it is + * unable to do so. + */ +#define POST_RESUME_FAILURE 0xef + /** * \brief Final code before OS resumes * diff --git a/src/include/cpu/amd/gx2def.h b/src/include/cpu/amd/gx2def.h index c0467beccb..ee55c2f85e 100644 --- a/src/include/cpu/amd/gx2def.h +++ b/src/include/cpu/amd/gx2def.h @@ -511,7 +511,7 @@ #define PMLogic_BASE (0x9D00) -#if !defined(__ROMCC__) && !defined(__ASSEMBLER__) +#if !defined(__ASSEMBLER__) #if defined(__PRE_RAM__) void cpuRegInit(void); void SystemPreInit(void); diff --git a/src/include/cpu/amd/lxdef.h b/src/include/cpu/amd/lxdef.h index 632bfe2217..4eee1568fb 100644 --- a/src/include/cpu/amd/lxdef.h +++ b/src/include/cpu/amd/lxdef.h @@ -630,7 +630,7 @@ #define DELAY_UPPER_DISABLE_CLK135 (1 << 23) #define DELAY_LOWER_STATUS_MASK 0x7C0 -#if !defined(__ROMCC__) && !defined(__ASSEMBLER__) +#if !defined(__ASSEMBLER__) #if defined(__PRE_RAM__) void cpuRegInit(int debug_clock_disable, u8 dimm0, u8 dimm1, int terminated); void SystemPreInit(void); diff --git a/src/include/cpu/cpu.h b/src/include/cpu/cpu.h index a2272f3e84..bed77de017 100644 --- a/src/include/cpu/cpu.h +++ b/src/include/cpu/cpu.h @@ -9,9 +9,6 @@ struct bus; void initialize_cpus(struct bus *cpu_bus); void asmlinkage secondary_cpu_init(unsigned int cpu_index); -/* If a ROM cache was set up disable it before jumping to the payload or OS. */ -void __attribute__((weak)) disable_cache_rom(void); - #if CONFIG_HAVE_SMI_HANDLER void smm_init(void); void smm_lock(void); diff --git a/src/include/cpu/intel/speedstep.h b/src/include/cpu/intel/speedstep.h index f4c4d7283b..8bfae60c1f 100644 --- a/src/include/cpu/intel/speedstep.h +++ b/src/include/cpu/intel/speedstep.h @@ -105,9 +105,7 @@ typedef struct { int num_states; } sst_table_t; -#ifndef __ROMCC__ void speedstep_gen_pstates(sst_table_t *); -#endif #define SPEEDSTEP_MAX_POWER_YONAH 31000 #define SPEEDSTEP_MIN_POWER_YONAH 13100 diff --git a/src/include/cpu/x86/cache.h b/src/include/cpu/x86/cache.h index a448228776..a4d976f156 100644 --- a/src/include/cpu/x86/cache.h +++ b/src/include/cpu/x86/cache.h @@ -20,8 +20,10 @@ #ifndef CPU_X86_CACHE #define CPU_X86_CACHE -#define CR0_CacheDisable (1 << 30) -#define CR0_NoWriteThrough (1 << 29) +#include + +#define CR0_CacheDisable (CR0_CD) +#define CR0_NoWriteThrough (CR0_NW) #if !defined(__ASSEMBLER__) @@ -33,21 +35,6 @@ #if defined(__GNUC__) -/* The memory clobber prevents the GCC from reordering the read/write order - * of CR0 - */ -static inline unsigned long read_cr0(void) -{ - unsigned long cr0; - asm volatile ("movl %%cr0, %0" : "=r" (cr0) :: "memory"); - return cr0; -} - -static inline void write_cr0(unsigned long cr0) -{ - asm volatile ("movl %0, %%cr0" : : "r" (cr0) : "memory"); -} - static inline void wbinvd(void) { asm volatile ("wbinvd" ::: "memory"); @@ -55,18 +42,6 @@ static inline void wbinvd(void) #else -static inline unsigned long read_cr0(void) -{ - unsigned long cr0; - asm volatile ("movl %%cr0, %0" : "=r" (cr0)); - return cr0; -} - -static inline void write_cr0(unsigned long cr0) -{ - asm volatile ("movl %0, %%cr0" : : "r" (cr0)); -} - static inline void wbinvd(void) { asm volatile ("wbinvd"); @@ -93,7 +68,7 @@ static inline __attribute__((always_inline)) void enable_cache(void) { unsigned long cr0; cr0 = read_cr0(); - cr0 &= 0x9fffffff; + cr0 &= ~(CR0_CD | CR0_NW); write_cr0(cr0); } @@ -102,7 +77,7 @@ static inline __attribute__((always_inline)) void disable_cache(void) /* Disable and write back the cache */ unsigned long cr0; cr0 = read_cr0(); - cr0 |= 0x40000000; + cr0 |= CR0_CD; wbinvd(); write_cr0(cr0); wbinvd(); diff --git a/src/include/cpu/x86/cr.h b/src/include/cpu/x86/cr.h new file mode 100644 index 0000000000..1e31adf554 --- /dev/null +++ b/src/include/cpu/x86/cr.h @@ -0,0 +1,112 @@ + +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef CPU_X86_CR_H +#define CPU_X86_CR_H + +#if !defined(__ASSEMBLER__) + +#include + +/* ROMCC apparently chokes certain clobber registers. */ +#if defined(__ROMCC__) +#define COMPILER_BARRIER +#else +#define COMPILER_BARRIER "memory" +#endif + +static alwaysinline unsigned long read_cr0(void) +{ + unsigned long value; + __asm__ __volatile__ ( + "mov %%cr0, %0" + : "=r" (value) + : + : COMPILER_BARRIER + ); + return value; +} + +static alwaysinline void write_cr0(unsigned long data) +{ + __asm__ __volatile__ ( + "mov %0, %%cr0" + : + : "r" (data) + : COMPILER_BARRIER + ); +} + +static alwaysinline unsigned long read_cr4(void) +{ + unsigned long value; + __asm__ __volatile__ ( + "mov %%cr4, %0" + : "=r" (value) + : + : COMPILER_BARRIER + ); + return value; +} + +static alwaysinline void write_cr4(unsigned long data) +{ + __asm__ __volatile__ ( + "mov %0, %%cr4" + : + : "r" (data) + : COMPILER_BARRIER + ); +} + +#endif /* !defined(__ASSEMBLER__) */ + +/* CR0 flags */ +#define CR0_PE (1 << 0) +#define CR0_MP (1 << 1) +#define CR0_EM (1 << 2) +#define CR0_TS (1 << 3) +#define CR0_ET (1 << 4) +#define CR0_NE (1 << 5) +#define CR0_WP (1 << 16) +#define CR0_AM (1 << 18) +#define CR0_NW (1 << 29) +#define CR0_CD (1 << 30) +#define CR0_PG (1 << 31) + +/* CR4 flags */ +#define CR4_VME (1 << 0) +#define CR4_PVI (1 << 1) +#define CR4_TSD (1 << 2) +#define CR4_DE (1 << 3) +#define CR4_PSE (1 << 4) +#define CR4_PAE (1 << 5) +#define CR4_MCE (1 << 6) +#define CR4_PGE (1 << 7) +#define CR4_PCE (1 << 8) +#define CR4_OSFXSR (1 << 9) +#define CR4_OSXMMEXCPT (1 << 10) +#define CR4_VMXE (1 << 13) +#define CR4_SMXE (1 << 14) +#define CR4_FSGSBASE (1 << 16) +#define CR4_PCIDE (1 << 17) +#define CR4_OSXSAVE (1 << 18) +#define CR4_SMEP (1 << 20) + +#endif /* CPU_X86_CR_H */ diff --git a/src/include/cpu/x86/lapic.h b/src/include/cpu/x86/lapic.h index 54b2f5488f..d4f323208b 100644 --- a/src/include/cpu/x86/lapic.h +++ b/src/include/cpu/x86/lapic.h @@ -51,7 +51,6 @@ static inline __attribute__((always_inline)) unsigned long lapicid(void) return lapic_read(LAPIC_ID) >> 24; } -#ifndef __ROMCC__ #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 @@ -155,6 +154,5 @@ int start_cpu(struct device *cpu); #endif /* !__PRE_RAM__ */ int boot_cpu(void); -#endif #endif /* CPU_X86_LAPIC_H */ diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h new file mode 100644 index 0000000000..7e90ee43c7 --- /dev/null +++ b/src/include/cpu/x86/mp.h @@ -0,0 +1,129 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _X86_MP_H_ +#define _X86_MP_H_ + +#include + +#define CACHELINE_SIZE 64 + +struct cpu_info; +struct bus; + +static inline void mfence(void) +{ + __asm__ __volatile__("mfence\t\n": : :"memory"); +} + +typedef void (*mp_callback_t)(void *arg); + +/* + * A mp_flight_record details a sequence of calls for the APs to perform + * along with the BSP to coordinate sequencing. Each flight record either + * provides a barrier for each AP before calling the callback or the APs + * are allowed to perform the callback without waiting. Regardless, each + * record has the cpus_entered field incremented for each record. When + * the BSP observes that the cpus_entered matches the number of APs + * the bsp_call is called with bsp_arg and upon returning releases the + * barrier allowing the APs to make further progress. + * + * Note that ap_call() and bsp_call() can be NULL. In the NULL case the + * callback will just not be called. + */ +struct mp_flight_record { + atomic_t barrier; + atomic_t cpus_entered; + mp_callback_t ap_call; + void *ap_arg; + mp_callback_t bsp_call; + void *bsp_arg; +} __attribute__((aligned(CACHELINE_SIZE))); + +#define _MP_FLIGHT_RECORD(barrier_, ap_func_, ap_arg_, bsp_func_, bsp_arg_) \ + { \ + .barrier = ATOMIC_INIT(barrier_), \ + .cpus_entered = ATOMIC_INIT(0), \ + .ap_call = ap_func_, \ + .ap_arg = ap_arg_, \ + .bsp_call = bsp_func_, \ + .bsp_arg = bsp_arg_, \ + } + +#define MP_FR_BLOCK_APS(ap_func_, ap_arg_, bsp_func_, bsp_arg_) \ + _MP_FLIGHT_RECORD(0, ap_func_, ap_arg_, bsp_func_, bsp_arg_) + +#define MP_FR_NOBLOCK_APS(ap_func_, ap_arg_, bsp_func_, bsp_arg_) \ + _MP_FLIGHT_RECORD(1, ap_func_, ap_arg_, bsp_func_, bsp_arg_) + +/* The mp_params structure provides the arguments to the mp subsystem + * for bringing up APs. */ +struct mp_params { + int num_cpus; /* Total cpus include BSP */ + int parallel_microcode_load; + const void *microcode_pointer; + /* adjust_apic_id() is called for every potential apic id in the + * system up from 0 to CONFIG_MAX_CPUS. Return adjusted apic_id. */ + int (*adjust_apic_id)(int index, int apic_id); + /* Flight plan for APs and BSP. */ + struct mp_flight_record *flight_plan; + int num_records; +}; + +/* + * mp_init() will set up the SIPI vector and bring up the APs according to + * mp_params. Each flight record will be executed according to the plan. Note + * that the MP infrastructure uses SMM default area without saving it. It's + * up to the chipset or mainboard to either e820 reserve this area or save this + * region prior to calling mp_init() and restoring it after mp_init returns. + * + * At the time mp_init() is called the MTRR MSRs are mirrored into APs then + * caching is enabled before running the flight plan. + * + * The MP initialization has the following properties: + * 1. APs are brought up in parallel. + * 2. The ordering of coreboot cpu number and APIC ids is not deterministic. + * Therefore, one cannot rely on this property or the order of devices in + * the device tree unless the chipset or mainboard know the APIC ids + * a priori. + * + * mp_init() returns < 0 on error, 0 on success. + */ +int mp_init(struct bus *cpu_bus, struct mp_params *params); + +/* + * Useful functions to use in flight records when sequencing APs. + */ + +/* Calls cpu_initialize(info->index) which calls the coreboot CPU drivers. */ +void mp_initialize_cpu(void *unused); + +/* Returns apic id for coreboot cpu number or < 0 on failure. */ +int mp_get_apic_id(int cpu_slot); + +/* + * SMM helpers to use with initializing CPUs. + */ + +/* Send SMI to self without any serialization. */ +void smm_initiate_relocation_parallel(void); +/* Send SMI to self with single execution. */ +void smm_initiate_relocation(void); + +#endif /* _X86_MP_H_ */ diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index 62494a9f97..135eb14de4 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -33,6 +33,7 @@ #define SMM_ENTRY_OFFSET 0x8000 #define SMM_SAVE_STATE_BEGIN(x) (SMM_ENTRY_OFFSET + (x)) +#include #include typedef struct { u16 es_selector; @@ -207,6 +208,92 @@ typedef struct { } __attribute__((packed)) em64t_smm_state_save_area_t; +/* Intel Revision 30100 SMM State-Save Area + * The following processor architectures use this: + * - Bay Trail + */ +#define SMM_EM64T100_ARCH_OFFSET 0x7c00 +#define SMM_EM64T100_SAVE_STATE_OFFSET \ + SMM_SAVE_STATE_BEGIN(SMM_EM64T100_ARCH_OFFSET) +typedef struct { + u8 reserved0[256]; + u8 reserved1[208]; + + u32 gdtr_upper_base; + u32 ldtr_upper_base; + u32 idtr_upper_base; + + u8 reserved2[4]; + + u64 io_rdi; + u64 io_rip; + u64 io_rcx; + u64 io_rsi; + + u8 reserved3[64]; + u32 cr4; + + u8 reserved4[72]; + + u32 gdtr_base; + u8 reserved5[4]; + u32 idtr_base; + u8 reserved6[4]; + u32 ldtr_base; + + u8 reserved7[88]; + + u32 smbase; + u32 smm_revision; + + u16 io_restart; + u16 autohalt_restart; + + u8 reserved8[24]; + + u64 r15; + u64 r14; + u64 r13; + u64 r12; + u64 r11; + u64 r10; + u64 r9; + u64 r8; + + u64 rax; + u64 rcx; + u64 rdx; + u64 rbx; + + u64 rsp; + u64 rbp; + u64 rsi; + u64 rdi; + + + u64 io_mem_addr; + u32 io_misc_info; + + u32 es_sel; + u32 cs_sel; + u32 ss_sel; + u32 ds_sel; + u32 fs_sel; + u32 gs_sel; + + u32 ldtr_sel; + u32 tr_sel; + + u64 dr7; + u64 dr6; + u64 rip; + u64 efer; + u64 rflags; + + u64 cr3; + u64 cr0; +} __attribute__((packed)) em64t100_smm_state_save_area_t; + /* Intel Revision 30101 SMM State-Save Area * The following processor architectures use this: * - SandyBridge @@ -371,6 +458,8 @@ typedef struct { #define APM_CNT_ACPI_ENABLE 0xe1 #define APM_CNT_MBI_UPDATE 0xeb #define APM_CNT_GNVS_UPDATE 0xea +#define APM_CNT_FINALIZE 0xcb +#define APM_CNT_LEGACY 0xcc #define APM_STS 0xb3 /* SMI handler function prototypes */ @@ -386,7 +475,7 @@ void southbridge_smi_set_eos(void); void cpu_smi_handler(void); void northbridge_smi_handler(void); void southbridge_smi_handler(void); -void mainboard_smi_gpi(u16 gpi_sts); +void mainboard_smi_gpi(u32 gpi_sts); int mainboard_smi_apmc(u8 data); void mainboard_smi_sleep(u8 slp_typ); #else @@ -394,7 +483,7 @@ void __attribute__((weak)) cpu_smi_handler(unsigned int node, smm_state_save_are void __attribute__((weak)) northbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save); void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save); -void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts); +void __attribute__((weak)) mainboard_smi_gpi(u32 gpi_sts); int __attribute__((weak)) mainboard_smi_apmc(u8 data); void __attribute__((weak)) mainboard_smi_sleep(u8 slp_typ); #endif /* CONFIG_SMM_MODULES */ @@ -429,14 +518,20 @@ struct smm_runtime { u8 apic_id_to_cpu[CONFIG_MAX_CPUS]; } __attribute__ ((packed)); -typedef void __attribute__((cdecl)) (*smm_handler_t)(void *arg, int cpu, - const struct smm_runtime *runtime); +struct smm_module_params { + void *arg; + int cpu; + const struct smm_runtime *runtime; +}; + +/* smm_handler_t is called with arg of smm_module_params pointer. */ +typedef void asmlinkage (*smm_handler_t)(void *); #ifdef __SMM__ /* SMM Runtime helpers. */ /* Entry point for SMM modules. */ -void smm_handler_start(void *arg, int cpu, const struct smm_runtime *runtime); +void asmlinkage smm_handler_start(void *params); /* Retrieve SMM save state for a given CPU. WARNING: This does not take into * account CPUs which are configured to not save their state to RAM. */ @@ -483,4 +578,8 @@ int smm_load_module(void *smram, int size, struct smm_loader_params *params); #endif /* __SMM__ */ #endif /* CONFIG_SMM_MODULES */ +/* Backup and restore default SMM region. */ +void *backup_default_smm_area(void); +void restore_default_smm_area(void *smm_save_area); + #endif diff --git a/src/include/cpu/x86/tsc.h b/src/include/cpu/x86/tsc.h index 6ce7f5fc7d..8e49a669eb 100644 --- a/src/include/cpu/x86/tsc.h +++ b/src/include/cpu/x86/tsc.h @@ -40,4 +40,8 @@ static inline unsigned long long rdtscll(void) } #endif +#if CONFIG_TSC_CONSTANT_RATE +unsigned long tsc_freq_mhz(void); +#endif + #endif /* CPU_X86_TSC_H */ diff --git a/src/include/delay.h b/src/include/delay.h index 0333879c34..b3d8ed95da 100644 --- a/src/include/delay.h +++ b/src/include/delay.h @@ -1,17 +1,9 @@ #ifndef DELAY_H #define DELAY_H -#if !defined( __ROMCC__) - -#if CONFIG_HAVE_INIT_TIMER void init_timer(void); -#else -#define init_timer() do{} while(0) -#endif void udelay(unsigned usecs); void mdelay(unsigned msecs); void delay(unsigned secs); - -#endif #endif /* DELAY_H */ diff --git a/src/include/device/device.h b/src/include/device/device.h index 44a9742ab8..0d8d719045 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -18,7 +18,9 @@ struct smbus_bus_operations; struct chip_operations { void (*enable_dev)(struct device *dev); void (*init)(void *chip_info); + void (*final)(void *chip_info); unsigned int initialized : 1; + unsigned int finalized : 1; const char *name; }; @@ -31,6 +33,7 @@ struct device_operations { void (*set_resources)(device_t dev); void (*enable_resources)(device_t dev); void (*init)(device_t dev); + void (*final)(device_t dev); unsigned int (*scan_bus)(device_t bus, unsigned int max); void (*enable)(device_t dev); void (*disable)(device_t dev); @@ -134,6 +137,8 @@ void dev_configure(void); void dev_enable(void); void dev_initialize(void); void dev_optimize(void); +void dev_finalize(void); +void dev_finalize_chips(void); /* Generic device helper functions */ int reset_bus(struct bus *bus); @@ -143,6 +148,7 @@ void enumerate_static_device(void); void enumerate_static_devices(void); const char *dev_name(device_t dev); const char *dev_path(device_t dev); +u32 dev_path_encode(device_t dev); const char *bus_path(struct bus *bus); void dev_set_enabled(device_t dev, int enable); void disable_children(struct bus *bus); @@ -158,6 +164,7 @@ device_t dev_find_class (unsigned int class, device_t from); device_t dev_find_slot (unsigned int bus, unsigned int devfn); device_t dev_find_slot_on_smbus (unsigned int bus, unsigned int addr); device_t dev_find_lapic(unsigned apic_id); +device_t dev_find_pnp(unsigned int port, unsigned int device); int dev_count_cpu(void); void remap_bsp_lapic(struct bus *cpu_bus); diff --git a/src/include/device/drm_dp_helper.h b/src/include/device/drm_dp_helper.h new file mode 100644 index 0000000000..f2e06c33f3 --- /dev/null +++ b/src/include/device/drm_dp_helper.h @@ -0,0 +1,239 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2008 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _DRM_DP_HELPER_H_ +#define _DRM_DP_HELPER_H_ + +/* From the VESA DisplayPort spec */ + +#define AUX_NATIVE_WRITE 0x8 +#define AUX_NATIVE_READ 0x9 +#define AUX_I2C_WRITE 0x0 +#define AUX_I2C_READ 0x1 +#define AUX_I2C_STATUS 0x2 +#define AUX_I2C_MOT 0x4 + +#define AUX_NATIVE_REPLY_ACK (0x0 << 4) +#define AUX_NATIVE_REPLY_NACK (0x1 << 4) +#define AUX_NATIVE_REPLY_DEFER (0x2 << 4) +#define AUX_NATIVE_REPLY_MASK (0x3 << 4) + +#define AUX_I2C_REPLY_ACK (0x0 << 6) +#define AUX_I2C_REPLY_NACK (0x1 << 6) +#define AUX_I2C_REPLY_DEFER (0x2 << 6) +#define AUX_I2C_REPLY_MASK (0x3 << 6) + +/* AUX CH addresses */ +/* DPCD */ +#define DP_DPCD_REV 0x000 + +#define DP_MAX_LINK_RATE 0x001 + +#define DP_MAX_LANE_COUNT 0x002 +# define DP_MAX_LANE_COUNT_MASK 0x1f +# define DP_TPS3_SUPPORTED (1 << 6) +# define DP_ENHANCED_FRAME_CAP (1 << 7) + +#define DP_MAX_DOWNSPREAD 0x003 +# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6) + +#define DP_NORP 0x004 + +#define DP_DOWNSTREAMPORT_PRESENT 0x005 +# define DP_DWN_STRM_PORT_PRESENT (1 << 0) +# define DP_DWN_STRM_PORT_TYPE_MASK 0x06 +/* 00b = DisplayPort */ +/* 01b = Analog */ +/* 10b = TMDS or HDMI */ +/* 11b = Other */ +# define DP_FORMAT_CONVERSION (1 << 3) + +#define DP_MAIN_LINK_CHANNEL_CODING 0x006 + +#define DP_EDP_CONFIGURATION_CAP 0x00d +#define DP_TRAINING_AUX_RD_INTERVAL 0x00e + +#define DP_PSR_SUPPORT 0x070 +# define DP_PSR_IS_SUPPORTED 1 +#define DP_PSR_CAPS 0x071 +# define DP_PSR_NO_TRAIN_ON_EXIT 1 +# define DP_PSR_SETUP_TIME_330 (0 << 1) +# define DP_PSR_SETUP_TIME_275 (1 << 1) +# define DP_PSR_SETUP_TIME_220 (2 << 1) +# define DP_PSR_SETUP_TIME_165 (3 << 1) +# define DP_PSR_SETUP_TIME_110 (4 << 1) +# define DP_PSR_SETUP_TIME_55 (5 << 1) +# define DP_PSR_SETUP_TIME_0 (6 << 1) +# define DP_PSR_SETUP_TIME_MASK (7 << 1) +# define DP_PSR_SETUP_TIME_SHIFT 1 + +/* link configuration */ +#define DP_LINK_BW_SET 0x100 +# define DP_LINK_BW_1_62 0x06 +# define DP_LINK_BW_2_7 0x0a +# define DP_LINK_BW_5_4 0x14 + +#define DP_LANE_COUNT_SET 0x101 +# define DP_LANE_COUNT_MASK 0x0f +# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) + +#define DP_TRAINING_PATTERN_SET 0x102 +# define DP_TRAINING_PATTERN_DISABLE 0 +# define DP_TRAINING_PATTERN_1 1 +# define DP_TRAINING_PATTERN_2 2 +# define DP_TRAINING_PATTERN_3 3 +# define DP_TRAINING_PATTERN_MASK 0x3 + +# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) +# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) +# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) +# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) +# define DP_LINK_QUAL_PATTERN_MASK (3 << 2) + +# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) +# define DP_LINK_SCRAMBLING_DISABLE (1 << 5) + +# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) +# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) +# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) +# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) + +#define DP_TRAINING_LANE0_SET 0x103 +#define DP_TRAINING_LANE1_SET 0x104 +#define DP_TRAINING_LANE2_SET 0x105 +#define DP_TRAINING_LANE3_SET 0x106 + +# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 +# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 +# define DP_TRAIN_MAX_SWING_REACHED (1 << 2) +# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) +# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) +# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) +# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) + +# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) +# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) +# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) +# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) +# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) + +# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 +# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) + +#define DP_DOWNSPREAD_CTRL 0x107 +# define DP_SPREAD_AMP_0_5 (1 << 4) + +#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 +# define DP_SET_ANSI_8B10B (1 << 0) + +#define DP_PSR_EN_CFG 0x170 +# define DP_PSR_ENABLE (1 << 0) +# define DP_PSR_MAIN_LINK_ACTIVE (1 << 1) +# define DP_PSR_CRC_VERIFICATION (1 << 2) +# define DP_PSR_FRAME_CAPTURE (1 << 3) + +#define DP_DEVICE_SERVICE_IRQ_VECTOR 0x201 +# define DP_REMOTE_CONTROL_COMMAND_PENDING (1 << 0) +# define DP_AUTOMATED_TEST_REQUEST (1 << 1) +# define DP_CP_IRQ (1 << 2) +# define DP_SINK_SPECIFIC_IRQ (1 << 6) + +#define DP_EDP_CONFIGURATION_SET 0x10a + +#define DP_LANE0_1_STATUS 0x202 +#define DP_LANE2_3_STATUS 0x203 +# define DP_LANE_CR_DONE (1 << 0) +# define DP_LANE_CHANNEL_EQ_DONE (1 << 1) +# define DP_LANE_SYMBOL_LOCKED (1 << 2) + +#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \ + DP_LANE_CHANNEL_EQ_DONE | \ + DP_LANE_SYMBOL_LOCKED) + +#define DP_LANE_ALIGN_STATUS_UPDATED 0x204 + +#define DP_INTERLANE_ALIGN_DONE (1 << 0) +#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) +#define DP_LINK_STATUS_UPDATED (1 << 7) + +#define DP_SINK_STATUS 0x205 + +#define DP_RECEIVE_PORT_0_STATUS (1 << 0) +#define DP_RECEIVE_PORT_1_STATUS (1 << 1) + +#define DP_ADJUST_REQUEST_LANE0_1 0x206 +#define DP_ADJUST_REQUEST_LANE2_3 0x207 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 +# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 +# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 +# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 + +#define DP_TEST_REQUEST 0x218 +# define DP_TEST_LINK_TRAINING (1 << 0) +# define DP_TEST_LINK_PATTERN (1 << 1) +# define DP_TEST_LINK_EDID_READ (1 << 2) +# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */ + +#define DP_TEST_LINK_RATE 0x219 +# define DP_LINK_RATE_162 (0x6) +# define DP_LINK_RATE_27 (0xa) + +#define DP_TEST_LANE_COUNT 0x220 + +#define DP_TEST_PATTERN 0x221 + +#define DP_TEST_RESPONSE 0x260 +# define DP_TEST_ACK (1 << 0) +# define DP_TEST_NAK (1 << 1) +# define DP_TEST_EDID_CHECKSUM_WRITE (1 << 2) + +#define DP_SET_POWER 0x600 +# define DP_SET_POWER_D0 0x1 +# define DP_SET_POWER_D3 0x2 + +#define DP_PSR_ERROR_STATUS 0x2006 +# define DP_PSR_LINK_CRC_ERROR (1 << 0) +# define DP_PSR_RFB_STORAGE_ERROR (1 << 1) + +#define DP_PSR_ESI 0x2007 +# define DP_PSR_CAPS_CHANGE (1 << 0) + +#define DP_PSR_STATUS 0x2008 +# define DP_PSR_SINK_INACTIVE 0 +# define DP_PSR_SINK_ACTIVE_SRC_SYNCED 1 +# define DP_PSR_SINK_ACTIVE_RFB 2 +# define DP_PSR_SINK_ACTIVE_SINK_SYNCED 3 +# define DP_PSR_SINK_ACTIVE_RESYNC 4 +# define DP_PSR_SINK_INTERNAL_ERROR 7 +# define DP_PSR_SINK_STATE_MASK 0x07 + +#define MODE_I2C_START 1 +#define MODE_I2C_WRITE 2 +#define MODE_I2C_READ 4 +#define MODE_I2C_STOP 8 + +#endif /* _DRM_DP_HELPER_H_ */ diff --git a/src/include/device/i2c.h b/src/include/device/i2c.h index bd6dd0c231..c1f2a2103a 100644 --- a/src/include/device/i2c.h +++ b/src/include/device/i2c.h @@ -1,14 +1,11 @@ /* - * (C) Copyright 2001 - * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. + * This file is part of the coreboot project. * - * See file CREDITS for list of people who contributed to this - * project. + * Copyright (C) 2014 Google, Inc. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,265 +14,122 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * The original I2C interface was - * (C) 2000 by Paolo Scaffardi (arsenio@tin.it) - * AIRVENT SAM s.p.a - RIMINI(ITALY) - * but has been changed substantially. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -#ifndef _I2C_H_ -#define _I2C_H_ +#ifndef _DEVICE_I2C_H_ +#define _DEVICE_I2C_H_ -/* - * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - * - * The implementation MUST NOT use static or global variables if the - * I2C routines are used to read SDRAM configuration information - * because this is done before the memories are initialized. Limited - * use of stack-based variables are OK (the initial stack size is - * limited). - * - * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING - */ +#include +#include -/* - * Configuration items. - */ -#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */ - -#ifdef CONFIG_I2C_MULTI_BUS -#define MAX_I2C_BUS 2 -#define I2C_MULTI_BUS 1 -#else -#define MAX_I2C_BUS 1 -#define I2C_MULTI_BUS 0 -#endif - -#if !defined(CONFIG_SYS_MAX_I2C_BUS) -#define CONFIG_SYS_MAX_I2C_BUS MAX_I2C_BUS -#endif - -/* define the I2C bus number for RTC and DTT if not already done */ -#if !defined(CONFIG_SYS_RTC_BUS_NUM) -#define CONFIG_SYS_RTC_BUS_NUM 0 -#endif -#if !defined(CONFIG_SYS_DTT_BUS_NUM) -#define CONFIG_SYS_DTT_BUS_NUM 0 -#endif -#if !defined(CONFIG_SYS_SPD_BUS_NUM) -#define CONFIG_SYS_SPD_BUS_NUM 0 -#endif - -#ifndef I2C_SOFT_DECLARATIONS -# if defined(CONFIG_MPC8260) -# define I2C_SOFT_DECLARATIONS volatile ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, I2C_PORT); -# elif defined(CONFIG_8xx) -# define I2C_SOFT_DECLARATIONS volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; - -# elif (defined(CONFIG_AT91RM9200) || \ - defined(CONFIG_AT91SAM9260) || defined(CONFIG_AT91SAM9261) || \ - defined(CONFIG_AT91SAM9263)) && !defined(CONFIG_AT91_LEGACY) -# define I2C_SOFT_DECLARATIONS at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; -# else -# define I2C_SOFT_DECLARATIONS -# endif -#endif - -#ifdef CONFIG_8xx -/* Set default value for the I2C bus speed on 8xx. In the - * future, we'll define these in all 8xx board config files. - */ -#ifndef CONFIG_SYS_I2C_SPEED -#define CONFIG_SYS_I2C_SPEED 50000 -#endif -#endif - -/* - * Many boards/controllers/drivers don't support an I2C slave interface so - * provide a default slave address for them for use in common code. A real - * value for CONFIG_SYS_I2C_SLAVE should be defined for any board which does - * support a slave interface. - */ -#ifndef CONFIG_SYS_I2C_SLAVE -#define CONFIG_SYS_I2C_SLAVE 0xfe -#endif - -/* - * Initialization, must be called once on start up, may be called - * repeatedly to change the speed and slave addresses. - */ -void i2c_init(int speed, int slaveaddr); -void i2c_init_board(void); -#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT -void i2c_board_late_init(void); -#endif - -#if defined(CONFIG_I2C_MUX) - -typedef struct _mux { - unsigned char chip; - unsigned char channel; - char *name; - struct _mux *next; -} I2C_MUX; - -typedef struct _mux_device { - int busid; - I2C_MUX *mux; /* List of muxes, to reach the device */ - struct _mux_device *next; -} I2C_MUX_DEVICE; - -I2C_MUX_DEVICE *i2c_mux_search_device(int id); -I2C_MUX_DEVICE *i2c_mux_ident_muxstring (unsigned char *buf); -int i2x_mux_select_mux(int bus); -int i2c_mux_ident_muxstring_f (unsigned char *buf); -#endif - -/* - * Probe the given I2C chip address. Returns 0 if a chip responded, - * not 0 on failure. - */ -int i2c_probe(unsigned char chip); - -/* - * Read/Write interface: - * chip: I2C chip address, range 0..127 - * addr: Memory (register) address within the chip - * alen: Number of bytes to use for addr (typically 1, 2 for larger - * memories, 0 for register type devices with only one - * register) - * buffer: Where to read/write the data - * len: How many bytes to read/write - * - * Returns: 0 on success, not 0 on failure - */ -int i2c_read(unsigned char chip, unsigned int addr, int alen, - unsigned char *buffer, int len); -int i2c_write(unsigned char chip, unsigned int addr, int alen, - unsigned char *buffer, int len); - -/* - * Utility routines to read/write registers. - */ -static inline u8 i2c_reg_read(u8 addr, u8 reg) +struct i2c_seg { - u8 buf; + int read; + uint8_t chip; + uint8_t *buf; + int len; +}; -#ifdef CONFIG_8xx - /* MPC8xx needs this. Maybe one day we can get rid of it. */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -#endif +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count); -#ifdef DEBUG - printf("%s: addr=0x%02x, reg=0x%02x\n", __func__, addr, reg); -#endif +#define SOFTWARE_I2C_MAX_BUS 10 /* increase as necessary */ - i2c_read(addr, reg, 1, &buf, 1); +struct software_i2c_ops { + void (*set_sda)(unsigned bus, int high); + void (*set_scl)(unsigned bus, int high); + int (*get_sda)(unsigned bus); + int (*get_scl)(unsigned bus); +}; - return buf; -} +extern struct software_i2c_ops *software_i2c[]; -static inline void i2c_reg_write(u8 addr, u8 reg, u8 val) +int software_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count); +void software_i2c_wedge_ack(unsigned bus, u8 chip); +void software_i2c_wedge_read(unsigned bus, u8 chip, u8 reg, int bit_count); +void software_i2c_wedge_write(unsigned bus, u8 chip, u8 reg, int bit_count); + +/* + * software_i2c is supposed to be a debug feature. It's usually not compiled in, + * but when it is it can be dynamically enabled at runtime for certain busses. + * Need this ugly stub to arbitrate since I2C device drivers hardcode + * 'i2c_transfer()' as their entry point. + */ +static inline int i2c_transfer(unsigned bus, struct i2c_seg *segments, + int count) { -#ifdef CONFIG_8xx - /* MPC8xx needs this. Maybe one day we can get rid of it. */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -#endif + if (CONFIG_SOFTWARE_I2C) + if (bus < SOFTWARE_I2C_MAX_BUS && software_i2c[bus]) + return software_i2c_transfer(bus, segments, count); -#ifdef DEBUG - printf("%s: addr=0x%02x, reg=0x%02x, val=0x%02x\n", - __func__, addr, reg, val); -#endif - - i2c_write(addr, reg, 1, &val, 1); + return platform_i2c_transfer(bus, segments, count); } /* - * Functions for setting the current I2C bus and its speed + * Read a raw chunk of data in one segment and one frame. + * + * [start][slave addr][r][data][stop] */ - -/* - * i2c_set_bus_num: - * - * Change the active I2C bus. Subsequent read/write calls will - * go to this one. - * - * bus - bus index, zero based - * - * Returns: 0 on success, not 0 on failure - * - */ -int i2c_set_bus_num(unsigned int bus); - -/* - * i2c_get_bus_num: - * - * Returns index of currently active I2C bus. Zero-based. - */ - -unsigned int i2c_get_bus_num(void); - -/* - * i2c_set_bus_speed: - * - * Change the speed of the active I2C bus - * - * speed - bus speed in Hz - * - * Returns: 0 on success, not 0 on failure - * - */ -int i2c_set_bus_speed(unsigned int); - -/* - * i2c_get_bus_speed: - * - * Returns speed of currently active I2C bus in Hz - */ - -unsigned int i2c_get_bus_speed(void); - -/* NOTE: These two functions MUST be always_inline to avoid code growth! */ -static inline unsigned int I2C_GET_BUS(void) __attribute__((always_inline)); -static inline unsigned int I2C_GET_BUS(void) +static inline int i2c_read_raw(unsigned bus, uint8_t chip, uint8_t *data, + int len) { - return I2C_MULTI_BUS ? i2c_get_bus_num() : 0; -} - -static inline void I2C_SET_BUS(unsigned int bus) __attribute__((always_inline)); -static inline void I2C_SET_BUS(unsigned int bus) -{ - if (I2C_MULTI_BUS) - i2c_set_bus_num(bus); + struct i2c_seg seg = + { .read = 1, .chip = chip, .buf = data, .len = len }; + return i2c_transfer(bus, &seg, 1); } /* - * Set an early register base for a given i2c peripheral. - * This is used to access a single i2c bus early on in the boot sequence. + * Write a raw chunk of data in one segment and one frame. * - * @param base: The base address of the i2c peripheral's register map + * [start][slave addr][w][data][stop] */ -void i2c_set_early_reg(unsigned int base); +static inline int i2c_write_raw(unsigned bus, uint8_t chip, uint8_t *data, + int len) +{ + struct i2c_seg seg = + { .read = 0, .chip = chip, .buf = data, .len = len }; + return i2c_transfer(bus, &seg, 1); +} /** - * Find the I2C bus number by given a FDT I2C node. + * Read a byte with two segments in one frame * - * @param blob Device tree blbo - * @param node FDT I2C node to find - * @return the number of I2C bus (zero based), or -1 on error + * [start][slave addr][w][register addr][start][slave addr][r][data][stop] */ -int i2c_get_bus_num_fdt(const void *blob, int node); +static inline int i2c_readb(unsigned bus, uint8_t chip, uint8_t reg, + uint8_t *data) +{ + struct i2c_seg seg[2]; + + seg[0].read = 0; + seg[0].chip = chip; + seg[0].buf = ® + seg[0].len = 1; + seg[1].read = 1; + seg[1].chip = chip; + seg[1].buf = data; + seg[1].len = 1; + + return i2c_transfer(bus, seg, ARRAY_SIZE(seg)); +} /** - * Reset the I2C bus represented by the given a FDT I2C node. + * Write a byte with one segment in one frame. * - * @param blob Device tree blbo - * @param node FDT I2C node to find - * @return 0 if port was reset, -1 if not found + * [start][slave addr][w][register addr][data][stop] */ -int i2c_reset_port_fdt(const void *blob, int node); +static inline int i2c_writeb(unsigned bus, uint8_t chip, uint8_t reg, + uint8_t data) +{ + struct i2c_seg seg; + uint8_t buf[] = {reg, data}; -#endif /* _I2C_H_ */ + seg.read = 0; + seg.chip = chip; + seg.buf = buf; + seg.len = ARRAY_SIZE(buf); + + return i2c_transfer(bus, &seg, 1); +} + +#endif /* _DEVICE_I2C_H_ */ diff --git a/src/include/device/i915.h b/src/include/device/i915.h new file mode 100644 index 0000000000..34f6d0d51a --- /dev/null +++ b/src/include/device/i915.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +/* things that are, strangely, not defined anywhere? */ +#define PCH_PP_UNLOCK 0xabcd0000 +#define WMx_LP_SR_EN (1<<31) +#define PRB0_TAIL 0x02030 +#define PRB0_HEAD 0x02034 +#define PRB0_START 0x02038 +#define PRB0_CTL 0x0203c + +/* debug enums. These are for printks that, due to their place in the + * middle of graphics device IO, might change timing. Use with care + * or not at all. + */ +enum { + vio = 2, /* dump every IO */ + vspin = 4, /* print # of times we spun on a register value */ +}; + +/* The mainboard must provide these functions. */ +unsigned long io_i915_read32(unsigned long addr); +void io_i915_write32(unsigned long val, unsigned long addr); +void graphics_register_reset(u32 aux_ctl, u32 aux_data, int verbose); + +/* intel_dp.c */ +u32 pack_aux(u32 *src, int src_bytes); +void unpack_aux(u32 src, u8 *dst, int dst_bytes); +int intel_dp_aux_ch(u32 ch_ctl, u32 ch_data, u32 *send, int send_bytes, + u8 *recv, int recv_size); + + diff --git a/src/include/device/i915_reg.h b/src/include/device/i915_reg.h new file mode 100644 index 0000000000..8bdf2cb14c --- /dev/null +++ b/src/include/device/i915_reg.h @@ -0,0 +1,3878 @@ +/* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _I915_REG_H_ +#define _I915_REG_H_ + +#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) + +/* + * The Bridge device's PCI config space has information about the + * fb aperture size and the amount of pre-reserved memory. + * This is all handled in the intel-gtt.ko module. i915.ko only + * cares about the vga bit for the vga rbiter. + */ +#define INTEL_GMCH_CTRL 0x52 +#define INTEL_GMCH_VGA_DISABLE (1 << 1) + +/* PCI config space */ + +#define HPLLCC 0xc0 /* 855 only */ +#define GC_CLOCK_CONTROL_MASK (0xf << 0) +#define GC_CLOCK_133_200 (0 << 0) +#define GC_CLOCK_100_200 (1 << 0) +#define GC_CLOCK_100_133 (2 << 0) +#define GC_CLOCK_166_250 (3 << 0) +#define GCFGC2 0xda +#define GCFGC 0xf0 /* 915+ only */ +#define GC_LOW_FREQUENCY_ENABLE (1 << 7) +#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4) +#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4) +#define GC_DISPLAY_CLOCK_MASK (7 << 4) +#define GM45_GC_RENDER_CLOCK_MASK (0xf << 0) +#define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0) +#define GM45_GC_RENDER_CLOCK_320_MHZ (9 << 0) +#define GM45_GC_RENDER_CLOCK_400_MHZ (0xb << 0) +#define GM45_GC_RENDER_CLOCK_533_MHZ (0xc << 0) +#define I965_GC_RENDER_CLOCK_MASK (0xf << 0) +#define I965_GC_RENDER_CLOCK_267_MHZ (2 << 0) +#define I965_GC_RENDER_CLOCK_333_MHZ (3 << 0) +#define I965_GC_RENDER_CLOCK_444_MHZ (4 << 0) +#define I965_GC_RENDER_CLOCK_533_MHZ (5 << 0) +#define I945_GC_RENDER_CLOCK_MASK (7 << 0) +#define I945_GC_RENDER_CLOCK_166_MHZ (0 << 0) +#define I945_GC_RENDER_CLOCK_200_MHZ (1 << 0) +#define I945_GC_RENDER_CLOCK_250_MHZ (3 << 0) +#define I945_GC_RENDER_CLOCK_400_MHZ (5 << 0) +#define I915_GC_RENDER_CLOCK_MASK (7 << 0) +#define I915_GC_RENDER_CLOCK_166_MHZ (0 << 0) +#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0) +#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0) +#define LBB 0xf4 + +/* Graphics reset regs */ +#define I965_GDRST 0xc0 /* PCI config register */ +#define ILK_GDSR 0x2ca4 /* MCHBAR offset */ +#define GRDOM_FULL (0<<2) +#define GRDOM_RENDER (1<<2) +#define GRDOM_MEDIA (3<<2) + +#define GEN6_MBCUNIT_SNPCR 0x900c /* for LLC config */ +#define GEN6_MBC_SNPCR_SHIFT 21 +#define GEN6_MBC_SNPCR_MASK (3<<21) +#define GEN6_MBC_SNPCR_MAX (0<<21) +#define GEN6_MBC_SNPCR_MED (1<<21) +#define GEN6_MBC_SNPCR_LOW (2<<21) +#define GEN6_MBC_SNPCR_MIN (3<<21) /* only 1/16th of the cache is shared */ + +#define GEN6_MBCTL 0x0907c +#define GEN6_MBCTL_ENABLE_BOOT_FETCH (1 << 4) +#define GEN6_MBCTL_CTX_FETCH_NEEDED (1 << 3) +#define GEN6_MBCTL_BME_UPDATE_ENABLE (1 << 2) +#define GEN6_MBCTL_MAE_UPDATE_ENABLE (1 << 1) +#define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0) + +#define GEN6_GDRST 0x941c +#define GEN6_GRDOM_FULL (1 << 0) +#define GEN6_GRDOM_RENDER (1 << 1) +#define GEN6_GRDOM_MEDIA (1 << 2) +#define GEN6_GRDOM_BLT (1 << 3) + +/* PPGTT stuff */ +#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) + +#define GEN6_PDE_VALID (1 << 0) +#define GEN6_PDE_LARGE_PAGE (2 << 0) /* use 32kb pages */ +/* gen6+ has bit 11-4 for physical addr bit 39-32 */ +#define GEN6_PDE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) + +#define GEN6_PTE_VALID (1 << 0) +#define GEN6_PTE_UNCACHED (1 << 1) +#define GEN6_PTE_CACHE_LLC (2 << 1) +#define GEN6_PTE_CACHE_LLC_MLC (3 << 1) +#define GEN6_PTE_CACHE_BITS (3 << 1) +#define GEN6_PTE_GFDT (1 << 3) +#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr) + +#define RING_PP_DIR_BASE(ring) ((ring)->mmio_base+0x228) +#define RING_PP_DIR_BASE_READ(ring) ((ring)->mmio_base+0x518) +#define RING_PP_DIR_DCLV(ring) ((ring)->mmio_base+0x220) +#define PP_DIR_DCLV_2G 0xffffffff + +#define GAM_ECOCHK 0x4090 +#define ECOCHK_SNB_BIT (1<<10) +#define ECOCHK_PPGTT_CACHE64B (0x3<<3) +#define ECOCHK_PPGTT_CACHE4B (0x0<<3) + +/* VGA stuff */ + +#define VGA_ST01_MDA 0x3ba +#define VGA_ST01_CGA 0x3da + +#define VGA_MSR_WRITE 0x3c2 +#define VGA_MSR_READ 0x3cc +#define VGA_MSR_MEM_EN (1<<1) +#define VGA_MSR_CGA_MODE (1<<0) + +#define VGA_SR_INDEX 0x3c4 +#define VGA_SR_DATA 0x3c5 + +#define VGA_AR_INDEX 0x3c0 +#define VGA_AR_VID_EN (1<<5) +#define VGA_AR_DATA_WRITE 0x3c0 +#define VGA_AR_DATA_READ 0x3c1 + +#define VGA_GR_INDEX 0x3ce +#define VGA_GR_DATA 0x3cf +/* GR05 */ +#define VGA_GR_MEM_READ_MODE_SHIFT 3 +#define VGA_GR_MEM_READ_MODE_PLANE 1 +/* GR06 */ +#define VGA_GR_MEM_MODE_MASK 0xc +#define VGA_GR_MEM_MODE_SHIFT 2 +#define VGA_GR_MEM_A0000_AFFFF 0 +#define VGA_GR_MEM_A0000_BFFFF 1 +#define VGA_GR_MEM_B0000_B7FFF 2 +#define VGA_GR_MEM_B0000_BFFFF 3 + +#define VGA_DACMASK 0x3c6 +#define VGA_DACRX 0x3c7 +#define VGA_DACWX 0x3c8 +#define VGA_DACDATA 0x3c9 + +#define VGA_CR_INDEX_MDA 0x3b4 +#define VGA_CR_DATA_MDA 0x3b5 +#define VGA_CR_INDEX_CGA 0x3d4 +#define VGA_CR_DATA_CGA 0x3d5 + +/* + * Memory interface instructions used by the kernel + */ +#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags)) + +#define MI_NOOP MI_INSTR(0, 0) +#define MI_USER_INTERRUPT MI_INSTR(0x02, 0) +#define MI_WAIT_FOR_EVENT MI_INSTR(0x03, 0) +#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) +#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) +#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) +#define MI_FLUSH MI_INSTR(0x04, 0) +#define MI_READ_FLUSH (1 << 0) +#define MI_EXE_FLUSH (1 << 1) +#define MI_NO_WRITE_FLUSH (1 << 2) +#define MI_SCENE_COUNT (1 << 3) /* just increment scene count */ +#define MI_END_SCENE (1 << 4) /* flush binner and incr scene count */ +#define MI_INVALIDATE_ISP (1 << 5) /* invalidate indirect state pointers */ +#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) +#define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) +#define MI_SUSPEND_FLUSH_EN (1<<0) +#define MI_REPORT_HEAD MI_INSTR(0x07, 0) +#define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) +#define MI_OVERLAY_CONTINUE (0x0<<21) +#define MI_OVERLAY_ON (0x1<<21) +#define MI_OVERLAY_OFF (0x2<<21) +#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) +#define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) +#define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) +#define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) +#define MI_SET_CONTEXT MI_INSTR(0x18, 0) +#define MI_MM_SPACE_GTT (1<<8) +#define MI_MM_SPACE_PHYSICAL (0<<8) +#define MI_SAVE_EXT_STATE_EN (1<<3) +#define MI_RESTORE_EXT_STATE_EN (1<<2) +#define MI_FORCE_RESTORE (1<<1) +#define MI_RESTORE_INHIBIT (1<<0) +#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) +#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ +#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) +#define MI_STORE_DWORD_INDEX_SHIFT 2 +/* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: + * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw + * simply ignores the register load under certain conditions. + * - One can actually load arbitrary many arbitrary registers: Simply issue x + * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! + */ +#define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) +#define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ +#define MI_INVALIDATE_TLB (1<<18) +#define MI_INVALIDATE_BSD (1<<7) +#define MI_BATCH_BUFFER MI_INSTR(0x30, 1) +#define MI_BATCH_NON_SECURE (1) +#define MI_BATCH_NON_SECURE_I965 (1<<8) +#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) +#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ +#define MI_SEMAPHORE_GLOBAL_GTT (1<<22) +#define MI_SEMAPHORE_UPDATE (1<<21) +#define MI_SEMAPHORE_COMPARE (1<<20) +#define MI_SEMAPHORE_REGISTER (1<<18) +#define MI_SEMAPHORE_SYNC_RV (2<<16) +#define MI_SEMAPHORE_SYNC_RB (0<<16) +#define MI_SEMAPHORE_SYNC_VR (0<<16) +#define MI_SEMAPHORE_SYNC_VB (2<<16) +#define MI_SEMAPHORE_SYNC_BR (2<<16) +#define MI_SEMAPHORE_SYNC_BV (0<<16) +#define MI_SEMAPHORE_SYNC_INVALID (1<<0) +/* + * 3D instructions used by the kernel + */ +#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags)) + +#define GFX_OP_RASTER_RULES ((0x3<<29)|(0x7<<24)) +#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define SC_UPDATE_SCISSOR (0x1<<1) +#define SC_ENABLE_MASK (0x1<<0) +#define SC_ENABLE (0x1<<0) +#define GFX_OP_LOAD_INDIRECT ((0x3<<29)|(0x1d<<24)|(0x7<<16)) +#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) +#define SCI_YMIN_MASK (0xffff<<16) +#define SCI_XMIN_MASK (0xffff<<0) +#define SCI_YMAX_MASK (0xffff<<16) +#define SCI_XMAX_MASK (0xffff<<0) +#define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) +#define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) +#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) +#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) +#define GFX_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) +#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) +#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) +#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|4) +#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_MONO_SRC_COPY_IMM_BLT ((2<<29)|(0x71<<22)|5) +#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define BLT_DEPTH_8 (0<<24) +#define BLT_DEPTH_16_565 (1<<24) +#define BLT_DEPTH_16_1555 (2<<24) +#define BLT_DEPTH_32 (3<<24) +#define BLT_ROP_GXCOPY (0xcc<<16) +#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) /* 965+ only */ +#define XY_SRC_COPY_BLT_DST_TILED (1<<11) /* 965+ only */ +#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) +#define ASYNC_FLIP (1<<22) +#define DISPLAY_PLANE_A (0<<20) +#define DISPLAY_PLANE_B (1<<20) +#define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) +#define PIPE_CONTROL_CS_STALL (1<<20) +#define PIPE_CONTROL_QW_WRITE (1<<14) +#define PIPE_CONTROL_DEPTH_STALL (1<<13) +#define PIPE_CONTROL_WRITE_FLUSH (1<<12) +#define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ +#define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on Ironlake */ +#define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */ +#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9) +#define PIPE_CONTROL_NOTIFY (1<<8) +#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4) +#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3) +#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2) +#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1) +#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1<<0) +#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */ + + +/* + * Reset registers + */ +#define DEBUG_RESET_I830 0x6070 +#define DEBUG_RESET_FULL (1<<7) +#define DEBUG_RESET_RENDER (1<<8) +#define DEBUG_RESET_DISPLAY (1<<9) + + +/* + * Fence registers + */ +#define FENCE_REG_830_0 0x2000 +#define FENCE_REG_945_8 0x3000 +#define I830_FENCE_START_MASK 0x07f80000 +#define I830_FENCE_TILING_Y_SHIFT 12 +#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) +#define I830_FENCE_PITCH_SHIFT 4 +#define I830_FENCE_REG_VALID (1<<0) +#define I915_FENCE_MAX_PITCH_VAL 4 +#define I830_FENCE_MAX_PITCH_VAL 6 +#define I830_FENCE_MAX_SIZE_VAL (1<<8) + +#define I915_FENCE_START_MASK 0x0ff00000 +#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) + +#define FENCE_REG_965_0 0x03000 +#define I965_FENCE_PITCH_SHIFT 2 +#define I965_FENCE_TILING_Y_SHIFT 1 +#define I965_FENCE_REG_VALID (1<<0) +#define I965_FENCE_MAX_PITCH_VAL 0x0400 + +#define FENCE_REG_SANDYBRIDGE_0 0x100000 +#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32 + +/* control register for cpu gtt access */ +#define TILECTL 0x101000 +#define TILECTL_SWZCTL (1 << 0) +#define TILECTL_TLB_PREFETCH_DIS (1 << 2) +#define TILECTL_BACKSNOOP_DIS (1 << 3) + +/* + * Instruction and interrupt control regs + */ +#define PGTBL_ER 0x02024 +#define RENDER_RING_BASE 0x02000 +#define BSD_RING_BASE 0x04000 +#define GEN6_BSD_RING_BASE 0x12000 +#define BLT_RING_BASE 0x22000 +#define RING_TAIL(base) ((base)+0x30) +#define RING_HEAD(base) ((base)+0x34) +#define RING_START(base) ((base)+0x38) +#define RING_CTL(base) ((base)+0x3c) +#define RING_SYNC_0(base) ((base)+0x40) +#define RING_SYNC_1(base) ((base)+0x44) +#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) +#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) +#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) +#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) +#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) +#define RING_MAX_IDLE(base) ((base)+0x54) +#define RING_HWS_PGA(base) ((base)+0x80) +#define RING_HWS_PGA_GEN6(base) ((base)+0x2080) +#define ARB_MODE 0x04030 +#define ARB_MODE_SWIZZLE_SNB (1<<4) +#define ARB_MODE_SWIZZLE_IVB (1<<5) +#define ARB_MODE_ENABLE(x) GFX_MODE_ENABLE(x) +#define ARB_MODE_DISABLE(x) GFX_MODE_DISABLE(x) +#define RENDER_HWS_PGA_GEN7 (0x04080) +#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) +#define DONE_REG 0x40b0 +#define BSD_HWS_PGA_GEN7 (0x04180) +#define BLT_HWS_PGA_GEN7 (0x04280) +#define RING_ACTHD(base) ((base)+0x74) +#define RING_NOPID(base) ((base)+0x94) +#define RING_IMR(base) ((base)+0xa8) +#define TAIL_ADDR 0x001FFFF8 +#define HEAD_WRAP_COUNT 0xFFE00000 +#define HEAD_WRAP_ONE 0x00200000 +#define HEAD_ADDR 0x001FFFFC +#define RING_NR_PAGES 0x001FF000 +#define RING_REPORT_MASK 0x00000006 +#define RING_REPORT_64K 0x00000002 +#define RING_REPORT_128K 0x00000004 +#define RING_NO_REPORT 0x00000000 +#define RING_VALID_MASK 0x00000001 +#define RING_VALID 0x00000001 +#define RING_INVALID 0x00000000 +#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */ +#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ +#define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */ +#if 0 +#define PRB0_TAIL 0x02030 +#define PRB0_HEAD 0x02034 +#define PRB0_START 0x02038 +#define PRB0_CTL 0x0203c +#define PRB1_TAIL 0x02040 /* 915+ only */ +#define PRB1_HEAD 0x02044 /* 915+ only */ +#define PRB1_START 0x02048 /* 915+ only */ +#define PRB1_CTL 0x0204c /* 915+ only */ +#endif +#define IPEIR_I965 0x02064 +#define IPEHR_I965 0x02068 +#define INSTDONE_I965 0x0206c +#define RING_IPEIR(base) ((base)+0x64) +#define RING_IPEHR(base) ((base)+0x68) +#define RING_INSTDONE(base) ((base)+0x6c) +#define RING_INSTPS(base) ((base)+0x70) +#define RING_DMA_FADD(base) ((base)+0x78) +#define RING_INSTPM(base) ((base)+0xc0) +#define INSTPS 0x02070 /* 965+ only */ +#define INSTDONE1 0x0207c /* 965+ only */ +#define ACTHD_I965 0x02074 +#define HWS_PGA 0x02080 +#define HWS_ADDRESS_MASK 0xfffff000 +#define HWS_START_ADDRESS_SHIFT 4 +#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTX_EN (1<<0) +#define IPEIR 0x02088 +#define IPEHR 0x0208c +#define INSTDONE 0x02090 +#define NOPID 0x02094 +#define HWSTAM 0x02098 + +#define ERROR_GEN6 0x040a0 + +/* GM45+ chicken bits -- debug workaround bits that may be required + * for various sorts of correct behavior. The top 16 bits of each are + * the enables for writing to the corresponding low bit. + */ +#define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN2 0x0208c +/* Disables pipelining of read flushes past the SF-WIZ interface. + * Required on all Ironlake steppings according to the B-Spec, but the + * particular danger of not doing so is not specified. + */ +# define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) +#define _3D_CHICKEN3 0x02090 + +#define MI_MODE 0x0209c +# define VS_TIMER_DISPATCH (1 << 6) +# define MI_FLUSH_ENABLE (1 << 12) + +#define GFX_MODE 0x02520 +#define GFX_MODE_GEN7 0x0229c +#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) +#define GFX_RUN_LIST_ENABLE (1<<15) +#define GFX_TLB_INVALIDATE_ALWAYS (1<<13) +#define GFX_SURFACE_FAULT_ENABLE (1<<12) +#define GFX_REPLAY_MODE (1<<11) +#define GFX_PSMI_GRANULARITY (1<<10) +#define GFX_PPGTT_ENABLE (1<<9) + +#define GFX_MODE_ENABLE(bit) (((bit) << 16) | (bit)) +#define GFX_MODE_DISABLE(bit) (((bit) << 16) | (0)) + +#define SCPD0 0x0209c /* 915+ only */ +#define IER 0x020a0 +#define IIR 0x020a4 +#define IMR 0x020a8 +#define ISR 0x020ac +#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) +#define I915_DISPLAY_PORT_INTERRUPT (1<<17) +#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) +#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */ +#define I915_HWB_OOM_INTERRUPT (1<<13) +#define I915_SYNC_STATUS_INTERRUPT (1<<12) +#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) +#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) +#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) +#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) +#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) +#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) +#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) +#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) +#define I915_DEBUG_INTERRUPT (1<<2) +#define I915_USER_INTERRUPT (1<<1) +#define I915_ASLE_INTERRUPT (1<<0) +#define I915_BSD_USER_INTERRUPT (1<<25) +#define EIR 0x020b0 +#define EMR 0x020b4 +#define ESR 0x020b8 +#define GM45_ERROR_PAGE_TABLE (1<<5) +#define GM45_ERROR_MEM_PRIV (1<<4) +#define I915_ERROR_PAGE_TABLE (1<<4) +#define GM45_ERROR_CP_PRIV (1<<3) +#define I915_ERROR_MEMORY_REFRESH (1<<1) +#define I915_ERROR_INSTRUCTION (1<<0) +#define INSTPM 0x020c0 +#define INSTPM_SELF_EN (1<<12) /* 915GM only */ +#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts + will not assert AGPBUSY# and will only + be delivered when out of C3. */ +#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ +#define ACTHD 0x020c8 +#define FW_BLC 0x020d8 +#define FW_BLC2 0x020dc +#define FW_BLC_SELF 0x020e0 /* 915+ only */ +#define FW_BLC_SELF_EN_MASK (1<<31) +#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ +#define FW_BLC_SELF_EN (1<<15) /* 945 only */ +#define MM_BURST_LENGTH 0x00700000 +#define MM_FIFO_WATERMARK 0x0001F000 +#define LM_BURST_LENGTH 0x00000700 +#define LM_FIFO_WATERMARK 0x0000001F +#define MI_ARB_STATE 0x020e4 /* 915+ only */ +#define MI_ARB_MASK_SHIFT 16 /* shift for enable bits */ + +/* Make render/texture TLB fetches lower priorty than associated data + * fetches. This is not turned on by default + */ +#define MI_ARB_RENDER_TLB_LOW_PRIORITY (1 << 15) + +/* Isoch request wait on GTT enable (Display A/B/C streams). + * Make isoch requests stall on the TLB update. May cause + * display underruns (test mode only) + */ +#define MI_ARB_ISOCH_WAIT_GTT (1 << 14) + +/* Block grant count for isoch requests when block count is + * set to a finite value. + */ +#define MI_ARB_BLOCK_GRANT_MASK (3 << 12) +#define MI_ARB_BLOCK_GRANT_8 (0 << 12) /* for 3 display planes */ +#define MI_ARB_BLOCK_GRANT_4 (1 << 12) /* for 2 display planes */ +#define MI_ARB_BLOCK_GRANT_2 (2 << 12) /* for 1 display plane */ +#define MI_ARB_BLOCK_GRANT_0 (3 << 12) /* don't use */ + +/* Enable render writes to complete in C2/C3/C4 power states. + * If this isn't enabled, render writes are prevented in low + * power states. That seems bad to me. + */ +#define MI_ARB_C3_LP_WRITE_ENABLE (1 << 11) + +/* This acknowledges an async flip immediately instead + * of waiting for 2TLB fetches. + */ +#define MI_ARB_ASYNC_FLIP_ACK_IMMEDIATE (1 << 10) + +/* Enables non-sequential data reads through arbiter + */ +#define MI_ARB_DUAL_DATA_PHASE_DISABLE (1 << 9) + +/* Disable FSB snooping of cacheable write cycles from binner/render + * command stream + */ +#define MI_ARB_CACHE_SNOOP_DISABLE (1 << 8) + +/* Arbiter time slice for non-isoch streams */ +#define MI_ARB_TIME_SLICE_MASK (7 << 5) +#define MI_ARB_TIME_SLICE_1 (0 << 5) +#define MI_ARB_TIME_SLICE_2 (1 << 5) +#define MI_ARB_TIME_SLICE_4 (2 << 5) +#define MI_ARB_TIME_SLICE_6 (3 << 5) +#define MI_ARB_TIME_SLICE_8 (4 << 5) +#define MI_ARB_TIME_SLICE_10 (5 << 5) +#define MI_ARB_TIME_SLICE_14 (6 << 5) +#define MI_ARB_TIME_SLICE_16 (7 << 5) + +/* Low priority grace period page size */ +#define MI_ARB_LOW_PRIORITY_GRACE_4KB (0 << 4) /* default */ +#define MI_ARB_LOW_PRIORITY_GRACE_8KB (1 << 4) + +/* Disable display A/B trickle feed */ +#define MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE (1 << 2) + +/* Set display plane priority */ +#define MI_ARB_DISPLAY_PRIORITY_A_B (0 << 0) /* display A > display B */ +#define MI_ARB_DISPLAY_PRIORITY_B_A (1 << 0) /* display B > display A */ + +#define CACHE_MODE_0 0x02120 /* 915+ only */ +#define CM0_MASK_SHIFT 16 +#define CM0_IZ_OPT_DISABLE (1<<6) +#define CM0_ZR_OPT_DISABLE (1<<5) +#define CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5) +#define CM0_DEPTH_EVICT_DISABLE (1<<4) +#define CM0_COLOR_EVICT_DISABLE (1<<3) +#define CM0_DEPTH_WRITE_DISABLE (1<<1) +#define CM0_RC_OP_FLUSH_DISABLE (1<<0) +#define BB_ADDR 0x02140 /* 8 bytes */ +#define GFX_FLSH_CNTL 0x02170 /* 915+ only */ +#define ECOSKPD 0x021d0 +#define ECO_GATING_CX_ONLY (1<<3) +#define ECO_FLIP_DONE (1<<0) + +/* GEN6 interrupt control */ +#define GEN6_RENDER_HWSTAM 0x2098 +#define GEN6_RENDER_IMR 0x20a8 +#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8) +#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7) +#define GEN6_RENDER_TIMEOUT_COUNTER_EXPIRED (1 << 6) +#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5) +#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4) +#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3) +#define GEN6_RENDER_SYNC_STATUS (1 << 2) +#define GEN6_RENDER_DEBUG_INTERRUPT (1 << 1) +#define GEN6_RENDER_USER_INTERRUPT (1 << 0) + +#define GEN6_BLITTER_HWSTAM 0x22098 +#define GEN6_BLITTER_IMR 0x220a8 +#define GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT (1 << 26) +#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) +#define GEN6_BLITTER_SYNC_STATUS (1 << 24) +#define GEN6_BLITTER_USER_INTERRUPT (1 << 22) + +#define GEN6_BLITTER_ECOSKPD 0x221d0 +#define GEN6_BLITTER_LOCK_SHIFT 16 +#define GEN6_BLITTER_FBC_NOTIFY (1<<3) + +#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 +#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) +#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) +#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 +#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) + +#define GEN6_BSD_HWSTAM 0x12098 +#define GEN6_BSD_IMR 0x120a8 +#define GEN6_BSD_USER_INTERRUPT (1 << 12) + +#define GEN6_BSD_RNCID 0x12198 + +/* + * Framebuffer compression (915+ only) + */ + +#define FBC_CFB_BASE 0x03200 /* 4k page aligned */ +#define FBC_LL_BASE 0x03204 /* 4k page aligned */ +#define FBC_CONTROL 0x03208 +#define FBC_CTL_EN (1<<31) +#define FBC_CTL_PERIODIC (1<<30) +#define FBC_CTL_INTERVAL_SHIFT (16) +#define FBC_CTL_UNCOMPRESSIBLE (1<<14) +#define FBC_CTL_C3_IDLE (1<<13) +#define FBC_CTL_STRIDE_SHIFT (5) +#define FBC_CTL_FENCENO (1<<0) +#define FBC_COMMAND 0x0320c +#define FBC_CMD_COMPRESS (1<<0) +#define FBC_STATUS 0x03210 +#define FBC_STAT_COMPRESSING (1<<31) +#define FBC_STAT_COMPRESSED (1<<30) +#define FBC_STAT_MODIFIED (1<<29) +#define FBC_STAT_CURRENT_LINE (1<<0) +#define FBC_CONTROL2 0x03214 +#define FBC_CTL_FENCE_DBL (0<<4) +#define FBC_CTL_IDLE_IMM (0<<2) +#define FBC_CTL_IDLE_FULL (1<<2) +#define FBC_CTL_IDLE_LINE (2<<2) +#define FBC_CTL_IDLE_DEBUG (3<<2) +#define FBC_CTL_CPU_FENCE (1<<1) +#define FBC_CTL_PLANEA (0<<0) +#define FBC_CTL_PLANEB (1<<0) +#define FBC_FENCE_OFF 0x0321b +#define FBC_TAG 0x03300 + +#define FBC_LL_SIZE (1536) + +/* Framebuffer compression for GM45+ */ +#define DPFC_CB_BASE 0x3200 +#define DPFC_CONTROL 0x3208 +#define DPFC_CTL_EN (1<<31) +#define DPFC_CTL_PLANEA (0<<30) +#define DPFC_CTL_PLANEB (1<<30) +#define DPFC_CTL_FENCE_EN (1<<29) +#define DPFC_CTL_PERSISTENT_MODE (1<<25) +#define DPFC_SR_EN (1<<10) +#define DPFC_CTL_LIMIT_1X (0<<6) +#define DPFC_CTL_LIMIT_2X (1<<6) +#define DPFC_CTL_LIMIT_4X (2<<6) +#define DPFC_RECOMP_CTL 0x320c +#define DPFC_RECOMP_STALL_EN (1<<27) +#define DPFC_RECOMP_STALL_WM_SHIFT (16) +#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) +#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) +#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) +#define DPFC_STATUS 0x3210 +#define DPFC_INVAL_SEG_SHIFT (16) +#define DPFC_INVAL_SEG_MASK (0x07ff0000) +#define DPFC_COMP_SEG_SHIFT (0) +#define DPFC_COMP_SEG_MASK (0x000003ff) +#define DPFC_STATUS2 0x3214 +#define DPFC_FENCE_YOFF 0x3218 +#define DPFC_CHICKEN 0x3224 +#define DPFC_HT_MODIFY (1<<31) + +/* Framebuffer compression for Ironlake */ +#define ILK_DPFC_CB_BASE 0x43200 +#define ILK_DPFC_CONTROL 0x43208 +/* The bit 28-8 is reserved */ +#define DPFC_RESERVED (0x1FFFFF00) +#define ILK_DPFC_RECOMP_CTL 0x4320c +#define ILK_DPFC_STATUS 0x43210 +#define ILK_DPFC_FENCE_YOFF 0x43218 +#define ILK_DPFC_CHICKEN 0x43224 +#define ILK_FBC_RT_BASE 0x2128 +#define ILK_FBC_RT_VALID (1<<0) + +#define ILK_DISPLAY_CHICKEN1 0x42000 +#define ILK_FBCQ_DIS (1<<22) +#define ILK_PABSTRETCH_DIS (1<<21) + + +/* + * Framebuffer compression for Sandybridge + * + * The following two registers are of type GTTMMADR + */ +#define SNB_DPFC_CTL_SA 0x100100 +#define SNB_CPU_FENCE_ENABLE (1<<29) +#define DPFC_CPU_FENCE_OFFSET 0x100104 + + +/* + * GPIO regs + */ +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 +#define GPIOD 0x501c +#define GPIOE 0x5020 +#define GPIOF 0x5024 +#define GPIOG 0x5028 +#define GPIOH 0x502c +# define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR_IN (0 << 1) +# define GPIO_CLOCK_DIR_OUT (1 << 1) +# define GPIO_CLOCK_VAL_MASK (1 << 2) +# define GPIO_CLOCK_VAL_OUT (1 << 3) +# define GPIO_CLOCK_VAL_IN (1 << 4) +# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) +# define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR_IN (0 << 9) +# define GPIO_DATA_DIR_OUT (1 << 9) +# define GPIO_DATA_VAL_MASK (1 << 10) +# define GPIO_DATA_VAL_OUT (1 << 11) +# define GPIO_DATA_VAL_IN (1 << 12) +# define GPIO_DATA_PULLUP_DISABLE (1 << 13) + +#define GMBUS0 0x5100 /* clock/port select */ +#define GMBUS_RATE_100KHZ (0<<8) +#define GMBUS_RATE_50KHZ (1<<8) +#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ +#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ +#define GMBUS_RATE_MASK (3<<8) +#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ +#define GMBUS_PORT_DISABLED 0 +#define GMBUS_PORT_SSC 1 +#define GMBUS_PORT_VGADDC 2 +#define GMBUS_PORT_PANEL 3 +#define GMBUS_PORT_DPC 4 /* HDMIC */ +#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ +#define GMBUS_PORT_DPD 6 /* HDMID */ +#define GMBUS_PORT_RESERVED 7 /* 7 reserved */ +#define GMBUS_NUM_PORTS (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1) +#define GMBUS_PORT_MASK 7 +#define GMBUS1 0x5104 /* command/status */ +#define GMBUS_SW_CLR_INT (1<<31) +#define GMBUS_SW_RDY (1<<30) +#define GMBUS_ENT (1<<29) /* enable timeout */ +#define GMBUS_CYCLE_NONE (0<<25) +#define GMBUS_CYCLE_WAIT (1<<25) +#define GMBUS_CYCLE_INDEX (2<<25) +#define GMBUS_CYCLE_STOP (4<<25) +#define GMBUS_BYTE_COUNT_SHIFT 16 +#define GMBUS_SLAVE_INDEX_SHIFT 8 +#define GMBUS_SLAVE_ADDR_SHIFT 1 +#define GMBUS_SLAVE_READ (1<<0) +#define GMBUS_SLAVE_WRITE (0<<0) +#define GMBUS2 0x5108 /* status */ +#define GMBUS_INUSE (1<<15) +#define GMBUS_HW_WAIT_PHASE (1<<14) +#define GMBUS_STALL_TIMEOUT (1<<13) +#define GMBUS_INT (1<<12) +#define GMBUS_HW_RDY (1<<11) +#define GMBUS_SATOER (1<<10) +#define GMBUS_ACTIVE (1<<9) +#define GMBUS3 0x510c /* data buffer bytes 3-0 */ +#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ +#define GMBUS_SLAVE_TIMEOUT_EN (1<<4) +#define GMBUS_NAK_EN (1<<3) +#define GMBUS_IDLE_EN (1<<2) +#define GMBUS_HW_WAIT_EN (1<<1) +#define GMBUS_HW_RDY_EN (1<<0) +#define GMBUS5 0x5120 /* byte index */ +#define GMBUS_2BYTE_INDEX_EN (1<<31) + +/* + * Clock control & power management + */ + +#define VGA0 0x6000 +#define VGA1 0x6004 +#define VGA_PD 0x6010 +#define VGA0_PD_P2_DIV_4 (1 << 7) +#define VGA0_PD_P1_DIV_2 (1 << 5) +#define VGA0_PD_P1_SHIFT 0 +#define VGA0_PD_P1_MASK (0x1f << 0) +#define VGA1_PD_P2_DIV_4 (1 << 15) +#define VGA1_PD_P1_DIV_2 (1 << 13) +#define VGA1_PD_P1_SHIFT 8 +#define VGA1_PD_P1_MASK (0x1f << 8) +#define _DPLL_A 0x06014 +#define _DPLL_B 0x06018 +#define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B) +#define DPLL_VCO_ENABLE (1 << 31) +#define DPLL_DVO_HIGH_SPEED (1 << 30) +#define DPLL_SYNCLOCK_ENABLE (1 << 29) +#define DPLL_VGA_MODE_DIS (1 << 28) +#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +#define DPLL_MODE_MASK (3 << 26) +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +#define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ + +#define SRX_INDEX 0x3c4 +#define SRX_DATA 0x3c5 +#define SR01 1 +#define SR01_SCREEN_OFF (1<<5) + +#define PPCR 0x61204 +#define PPCR_ON (1<<0) + +#define DVOB 0x61140 +#define DVOB_ON (1<<31) +#define DVOC 0x61160 +#define DVOC_ON (1<<31) +#define LVDS 0x61180 +#define LVDS_ON (1<<31) + +/* Scratch pad debug 0 reg: + */ +#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 +/* + * The i830 generation, in LVDS mode, defines P1 as the bit number set within + * this field (only one bit may be set). + */ +#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +#define DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15 +/* i830, required in DVO non-gang */ +#define PLL_P2_DIVIDE_BY_4 (1 << 23) +#define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +#define PLL_REF_INPUT_DREFCLK (0 << 13) +#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ +#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +#define PLL_REF_INPUT_MASK (3 << 13) +#define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* Ironlake */ +# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 +# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) +# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1) << 9) +# define DPLL_FPA1_P1_POST_DIV_SHIFT 0 +# define DPLL_FPA1_P1_POST_DIV_MASK 0xff + +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +/* + * SDVO multiplier for 945G/GM. Not used on 965. + */ +#define SDVO_MULTIPLIER_MASK 0x000000ff +#define SDVO_MULTIPLIER_SHIFT_HIRES 4 +#define SDVO_MULTIPLIER_SHIFT_VGA 0 +#define _DPLL_A_MD 0x0601c /* 965+ only */ +/* + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +#define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/* + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/* + * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ +#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +#define _DPLL_B_MD 0x06020 /* 965+ only */ +#define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD) +#define _FPA0 0x06040 +#define _FPA1 0x06044 +#define _FPB0 0x06048 +#define _FPB1 0x0604c +#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0) +#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1) +#define FP_N_DIV_MASK 0x003f0000 +#define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 +#define FP_N_DIV_SHIFT 16 +#define FP_M1_DIV_MASK 0x00003f00 +#define FP_M1_DIV_SHIFT 8 +#define FP_M2_DIV_MASK 0x0000003f +#define FP_M2_PINEVIEW_DIV_MASK 0x000000ff +#define FP_M2_DIV_SHIFT 0 +#define DPLL_TEST 0x606c +#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +#define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +#define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +#define DPLLB_TEST_N_BYPASS (1 << 19) +#define DPLLB_TEST_M_BYPASS (1 << 18) +#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +#define DPLLA_TEST_N_BYPASS (1 << 3) +#define DPLLA_TEST_M_BYPASS (1 << 2) +#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) +#define D_STATE 0x6104 +#define DSTATE_GFX_RESET_I830 (1<<6) +#define DSTATE_PLL_D3_OFF (1<<3) +#define DSTATE_GFX_CLOCK_GATING (1<<1) +#define DSTATE_DOT_CLOCK_GATING (1<<0) +#define DSPCLK_GATE_D 0x6200 +# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */ +# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */ +# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */ +# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */ +# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */ +# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */ +# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */ +# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */ +# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */ +# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */ +# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */ +# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */ +# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */ +# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */ +# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */ +# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */ +# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */ +# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */ +# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */ +# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) +# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10) +# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9) +# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8) +# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */ +# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */ +# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */ +# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5) +# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4) +/** + * This bit must be set on the 830 to prevent hangs when turning off the + * overlay scaler. + */ +# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3) +# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2) +# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1) +# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */ +# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */ + +#define RENCLK_GATE_D1 0x6204 +# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */ +# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */ +# define PC_FE_CLOCK_GATE_DISABLE (1 << 11) +# define PC_BE_CLOCK_GATE_DISABLE (1 << 10) +# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9) +# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8) +# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7) +# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6) +# define MAG_CLOCK_GATE_DISABLE (1 << 5) +/** This bit must be unset on 855,865 */ +# define MECI_CLOCK_GATE_DISABLE (1 << 4) +# define DCMP_CLOCK_GATE_DISABLE (1 << 3) +# define MEC_CLOCK_GATE_DISABLE (1 << 2) +# define MECO_CLOCK_GATE_DISABLE (1 << 1) +/** This bit must be set on 855,865. */ +# define SV_CLOCK_GATE_DISABLE (1 << 0) +# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16) +# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15) +# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14) +# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13) +# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12) +# define I915_WM_CLOCK_GATE_DISABLE (1 << 11) +# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10) +# define I915_PI_CLOCK_GATE_DISABLE (1 << 9) +# define I915_DI_CLOCK_GATE_DISABLE (1 << 8) +# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7) +# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6) +# define I915_SC_CLOCK_GATE_DISABLE (1 << 5) +# define I915_FL_CLOCK_GATE_DISABLE (1 << 4) +# define I915_DM_CLOCK_GATE_DISABLE (1 << 3) +# define I915_PS_CLOCK_GATE_DISABLE (1 << 2) +# define I915_CC_CLOCK_GATE_DISABLE (1 << 1) +# define I915_BY_CLOCK_GATE_DISABLE (1 << 0) + +# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30) +/** This bit must always be set on 965G/965GM */ +# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29) +# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28) +# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27) +# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26) +# define I965_GW_CLOCK_GATE_DISABLE (1 << 25) +# define I965_TD_CLOCK_GATE_DISABLE (1 << 24) +/** This bit must always be set on 965G */ +# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23) +# define I965_IC_CLOCK_GATE_DISABLE (1 << 22) +# define I965_EU_CLOCK_GATE_DISABLE (1 << 21) +# define I965_IF_CLOCK_GATE_DISABLE (1 << 20) +# define I965_TC_CLOCK_GATE_DISABLE (1 << 19) +# define I965_SO_CLOCK_GATE_DISABLE (1 << 17) +# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16) +# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15) +# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14) +# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13) +# define I965_EM_CLOCK_GATE_DISABLE (1 << 12) +# define I965_UC_CLOCK_GATE_DISABLE (1 << 11) +# define I965_SI_CLOCK_GATE_DISABLE (1 << 6) +# define I965_MT_CLOCK_GATE_DISABLE (1 << 5) +# define I965_PL_CLOCK_GATE_DISABLE (1 << 4) +# define I965_DG_CLOCK_GATE_DISABLE (1 << 3) +# define I965_QC_CLOCK_GATE_DISABLE (1 << 2) +# define I965_FT_CLOCK_GATE_DISABLE (1 << 1) +# define I965_DM_CLOCK_GATE_DISABLE (1 << 0) + +#define RENCLK_GATE_D2 0x6208 +#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9) +#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7) +#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6) +#define RAMCLK_GATE_D 0x6210 /* CRL only */ +#define DEUC 0x6214 /* CRL only */ + +/* + * Palette regs + */ + +#define _PALETTE_A 0x0a000 +#define _PALETTE_B 0x0a800 +#define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B) + +/* MCH MMIO space */ + +/* + * MCHBAR mirror. + * + * This mirrors the MCHBAR MMIO space whose location is determined by + * device 0 function 0's pci config register 0x44 or 0x48 and matches it in + * every way. It is not accessible from the CP register read instructions. + * + */ +#define MCHBAR_MIRROR_BASE 0x10000 + +#define MCHBAR_MIRROR_BASE_SNB 0x140000 + +/** 915-945 and GM965 MCH register controlling DRAM channel access */ +#define DCC 0x10200 +#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC (1 << 0) +#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0) +#define DCC_ADDRESSING_MODE_MASK (3 << 0) +#define DCC_CHANNEL_XOR_DISABLE (1 << 10) +#define DCC_CHANNEL_XOR_BIT_17 (1 << 9) + +/** Pineview MCH register contains DDR3 setting */ +#define CSHRDDR3CTL 0x101a8 +#define CSHRDDR3CTL_DDR3 (1 << 2) + +/** 965 MCH register controlling DRAM channel configuration */ +#define C0DRB3 0x10206 +#define C1DRB3 0x10606 + +/** snb MCH registers for reading the DRAM channel configuration */ +#define MAD_DIMM_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5004) +#define MAD_DIMM_C1 (MCHBAR_MIRROR_BASE_SNB + 0x5008) +#define MAD_DIMM_C2 (MCHBAR_MIRROR_BASE_SNB + 0x500C) +#define MAD_DIMM_ECC_MASK (0x3 << 24) +#define MAD_DIMM_ECC_OFF (0x0 << 24) +#define MAD_DIMM_ECC_IO_ON_LOGIC_OFF (0x1 << 24) +#define MAD_DIMM_ECC_IO_OFF_LOGIC_ON (0x2 << 24) +#define MAD_DIMM_ECC_ON (0x3 << 24) +#define MAD_DIMM_ENH_INTERLEAVE (0x1 << 22) +#define MAD_DIMM_RANK_INTERLEAVE (0x1 << 21) +#define MAD_DIMM_B_WIDTH_X16 (0x1 << 20) /* X8 chips if unset */ +#define MAD_DIMM_A_WIDTH_X16 (0x1 << 19) /* X8 chips if unset */ +#define MAD_DIMM_B_DUAL_RANK (0x1 << 18) +#define MAD_DIMM_A_DUAL_RANK (0x1 << 17) +#define MAD_DIMM_A_SELECT (0x1 << 16) +/* DIMM sizes are in multiples of 256mb. */ +#define MAD_DIMM_B_SIZE_SHIFT 8 +#define MAD_DIMM_B_SIZE_MASK (0xff << MAD_DIMM_B_SIZE_SHIFT) +#define MAD_DIMM_A_SIZE_SHIFT 0 +#define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT) + + +/* Clocking configuration register */ +#define CLKCFG 0x10c00 +#define CLKCFG_FSB_400 (5 << 0) /* hrawclk 100 */ +#define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ +#define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ +#define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ +#define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ +#define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ +/* Note, below two are guess */ +#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ +#define CLKCFG_FSB_MASK (7 << 0) +#define CLKCFG_MEM_533 (1 << 4) +#define CLKCFG_MEM_667 (2 << 4) +#define CLKCFG_MEM_800 (3 << 4) +#define CLKCFG_MEM_MASK (7 << 4) + +#define TSC1 0x11001 +#define TSE (1<<0) +#define TR1 0x11006 +#define TSFS 0x11020 +#define TSFS_SLOPE_MASK 0x0000ff00 +#define TSFS_SLOPE_SHIFT 8 +#define TSFS_INTR_MASK 0x000000ff + +#define CRSTANDVID 0x11100 +#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ +#define PXVFREQ_PX_MASK 0x7f000000 +#define PXVFREQ_PX_SHIFT 24 +#define VIDFREQ_BASE 0x11110 +#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */ +#define VIDFREQ2 0x11114 +#define VIDFREQ3 0x11118 +#define VIDFREQ4 0x1111c +#define VIDFREQ_P0_MASK 0x1f000000 +#define VIDFREQ_P0_SHIFT 24 +#define VIDFREQ_P0_CSCLK_MASK 0x00f00000 +#define VIDFREQ_P0_CSCLK_SHIFT 20 +#define VIDFREQ_P0_CRCLK_MASK 0x000f0000 +#define VIDFREQ_P0_CRCLK_SHIFT 16 +#define VIDFREQ_P1_MASK 0x00001f00 +#define VIDFREQ_P1_SHIFT 8 +#define VIDFREQ_P1_CSCLK_MASK 0x000000f0 +#define VIDFREQ_P1_CSCLK_SHIFT 4 +#define VIDFREQ_P1_CRCLK_MASK 0x0000000f +#define INTTOEXT_BASE_ILK 0x11300 +#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */ +#define INTTOEXT_MAP3_SHIFT 24 +#define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT) +#define INTTOEXT_MAP2_SHIFT 16 +#define INTTOEXT_MAP2_MASK (0x1f << INTTOEXT_MAP2_SHIFT) +#define INTTOEXT_MAP1_SHIFT 8 +#define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT) +#define INTTOEXT_MAP0_SHIFT 0 +#define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT) +#define MEMSWCTL 0x11170 /* Ironlake only */ +#define MEMCTL_CMD_MASK 0xe000 +#define MEMCTL_CMD_SHIFT 13 +#define MEMCTL_CMD_RCLK_OFF 0 +#define MEMCTL_CMD_RCLK_ON 1 +#define MEMCTL_CMD_CHFREQ 2 +#define MEMCTL_CMD_CHVID 3 +#define MEMCTL_CMD_VMMOFF 4 +#define MEMCTL_CMD_VMMON 5 +#define MEMCTL_CMD_STS (1<<12) /* write 1 triggers command, clears + when command complete */ +#define MEMCTL_FREQ_MASK 0x0f00 /* jitter, from 0-15 */ +#define MEMCTL_FREQ_SHIFT 8 +#define MEMCTL_SFCAVM (1<<7) +#define MEMCTL_TGT_VID_MASK 0x007f +#define MEMIHYST 0x1117c +#define MEMINTREN 0x11180 /* 16 bits */ +#define MEMINT_RSEXIT_EN (1<<8) +#define MEMINT_CX_SUPR_EN (1<<7) +#define MEMINT_CONT_BUSY_EN (1<<6) +#define MEMINT_AVG_BUSY_EN (1<<5) +#define MEMINT_EVAL_CHG_EN (1<<4) +#define MEMINT_MON_IDLE_EN (1<<3) +#define MEMINT_UP_EVAL_EN (1<<2) +#define MEMINT_DOWN_EVAL_EN (1<<1) +#define MEMINT_SW_CMD_EN (1<<0) +#define MEMINTRSTR 0x11182 /* 16 bits */ +#define MEM_RSEXIT_MASK 0xc000 +#define MEM_RSEXIT_SHIFT 14 +#define MEM_CONT_BUSY_MASK 0x3000 +#define MEM_CONT_BUSY_SHIFT 12 +#define MEM_AVG_BUSY_MASK 0x0c00 +#define MEM_AVG_BUSY_SHIFT 10 +#define MEM_EVAL_CHG_MASK 0x0300 +#define MEM_EVAL_BUSY_SHIFT 8 +#define MEM_MON_IDLE_MASK 0x00c0 +#define MEM_MON_IDLE_SHIFT 6 +#define MEM_UP_EVAL_MASK 0x0030 +#define MEM_UP_EVAL_SHIFT 4 +#define MEM_DOWN_EVAL_MASK 0x000c +#define MEM_DOWN_EVAL_SHIFT 2 +#define MEM_SW_CMD_MASK 0x0003 +#define MEM_INT_STEER_GFX 0 +#define MEM_INT_STEER_CMR 1 +#define MEM_INT_STEER_SMI 2 +#define MEM_INT_STEER_SCI 3 +#define MEMINTRSTS 0x11184 +#define MEMINT_RSEXIT (1<<7) +#define MEMINT_CONT_BUSY (1<<6) +#define MEMINT_AVG_BUSY (1<<5) +#define MEMINT_EVAL_CHG (1<<4) +#define MEMINT_MON_IDLE (1<<3) +#define MEMINT_UP_EVAL (1<<2) +#define MEMINT_DOWN_EVAL (1<<1) +#define MEMINT_SW_CMD (1<<0) +#define MEMMODECTL 0x11190 +#define MEMMODE_BOOST_EN (1<<31) +#define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */ +#define MEMMODE_BOOST_FREQ_SHIFT 24 +#define MEMMODE_IDLE_MODE_MASK 0x00030000 +#define MEMMODE_IDLE_MODE_SHIFT 16 +#define MEMMODE_IDLE_MODE_EVAL 0 +#define MEMMODE_IDLE_MODE_CONT 1 +#define MEMMODE_HWIDLE_EN (1<<15) +#define MEMMODE_SWMODE_EN (1<<14) +#define MEMMODE_RCLK_GATE (1<<13) +#define MEMMODE_HW_UPDATE (1<<12) +#define MEMMODE_FSTART_MASK 0x00000f00 /* starting jitter, 0-15 */ +#define MEMMODE_FSTART_SHIFT 8 +#define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */ +#define MEMMODE_FMAX_SHIFT 4 +#define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */ +#define RCBMAXAVG 0x1119c +#define MEMSWCTL2 0x1119e /* Cantiga only */ +#define SWMEMCMD_RENDER_OFF (0 << 13) +#define SWMEMCMD_RENDER_ON (1 << 13) +#define SWMEMCMD_SWFREQ (2 << 13) +#define SWMEMCMD_TARVID (3 << 13) +#define SWMEMCMD_VRM_OFF (4 << 13) +#define SWMEMCMD_VRM_ON (5 << 13) +#define CMDSTS (1<<12) +#define SFCAVM (1<<11) +#define SWFREQ_MASK 0x0380 /* P0-7 */ +#define SWFREQ_SHIFT 7 +#define TARVID_MASK 0x001f +#define MEMSTAT_CTG 0x111a0 +#define RCBMINAVG 0x111a0 +#define RCUPEI 0x111b0 +#define RCDNEI 0x111b4 +#define RSTDBYCTL 0x111b8 +#define RS1EN (1<<31) +#define RS2EN (1<<30) +#define RS3EN (1<<29) +#define D3RS3EN (1<<28) /* Display D3 imlies RS3 */ +#define SWPROMORSX (1<<27) /* RSx promotion timers ignored */ +#define RCWAKERW (1<<26) /* Resetwarn from PCH causes wakeup */ +#define DPRSLPVREN (1<<25) /* Fast voltage ramp enable */ +#define GFXTGHYST (1<<24) /* Hysteresis to allow trunk gating */ +#define RCX_SW_EXIT (1<<23) /* Leave RSx and prevent re-entry */ +#define RSX_STATUS_MASK (7<<20) +#define RSX_STATUS_ON (0<<20) +#define RSX_STATUS_RC1 (1<<20) +#define RSX_STATUS_RC1E (2<<20) +#define RSX_STATUS_RS1 (3<<20) +#define RSX_STATUS_RS2 (4<<20) /* aka rc6 */ +#define RSX_STATUS_RSVD (5<<20) /* deep rc6 unsupported on ilk */ +#define RSX_STATUS_RS3 (6<<20) /* rs3 unsupported on ilk */ +#define RSX_STATUS_RSVD2 (7<<20) +#define UWRCRSXE (1<<19) /* wake counter limit prevents rsx */ +#define RSCRP (1<<18) /* rs requests control on rs1/2 reqs */ +#define JRSC (1<<17) /* rsx coupled to cpu c-state */ +#define RS2INC0 (1<<16) /* allow rs2 in cpu c0 */ +#define RS1CONTSAV_MASK (3<<14) +#define RS1CONTSAV_NO_RS1 (0<<14) /* rs1 doesn't save/restore context */ +#define RS1CONTSAV_RSVD (1<<14) +#define RS1CONTSAV_SAVE_RS1 (2<<14) /* rs1 saves context */ +#define RS1CONTSAV_FULL_RS1 (3<<14) /* rs1 saves and restores context */ +#define NORMSLEXLAT_MASK (3<<12) +#define SLOW_RS123 (0<<12) +#define SLOW_RS23 (1<<12) +#define SLOW_RS3 (2<<12) +#define NORMAL_RS123 (3<<12) +#define RCMODE_TIMEOUT (1<<11) /* 0 is eval interval method */ +#define IMPROMOEN (1<<10) /* promo is immediate or delayed until next idle interval (only for timeout method above) */ +#define RCENTSYNC (1<<9) /* rs coupled to cpu c-state (3/6/7) */ +#define STATELOCK (1<<7) /* locked to rs_cstate if 0 */ +#define RS_CSTATE_MASK (3<<4) +#define RS_CSTATE_C367_RS1 (0<<4) +#define RS_CSTATE_C36_RS1_C7_RS2 (1<<4) +#define RS_CSTATE_RSVD (2<<4) +#define RS_CSTATE_C367_RS2 (3<<4) +#define REDSAVES (1<<3) /* no context save if was idle during rs0 */ +#define REDRESTORES (1<<2) /* no restore if was idle during rs0 */ +#define VIDCTL 0x111c0 +#define VIDSTS 0x111c8 +#define VIDSTART 0x111cc /* 8 bits */ +#define MEMSTAT_ILK 0x111f8 +#define MEMSTAT_VID_MASK 0x7f00 +#define MEMSTAT_VID_SHIFT 8 +#define MEMSTAT_PSTATE_MASK 0x00f8 +#define MEMSTAT_PSTATE_SHIFT 3 +#define MEMSTAT_MON_ACTV (1<<2) +#define MEMSTAT_SRC_CTL_MASK 0x0003 +#define MEMSTAT_SRC_CTL_CORE 0 +#define MEMSTAT_SRC_CTL_TRB 1 +#define MEMSTAT_SRC_CTL_THM 2 +#define MEMSTAT_SRC_CTL_STDBY 3 +#define RCPREVBSYTUPAVG 0x113b8 +#define RCPREVBSYTDNAVG 0x113bc +#define PMMISC 0x11214 +#define MCPPCE_EN (1<<0) /* enable PM_MSG from PCH->MPC */ +#define SDEW 0x1124c +#define CSIEW0 0x11250 +#define CSIEW1 0x11254 +#define CSIEW2 0x11258 +#define PEW 0x1125c +#define DEW 0x11270 +#define MCHAFE 0x112c0 +#define CSIEC 0x112e0 +#define DMIEC 0x112e4 +#define DDREC 0x112e8 +#define PEG0EC 0x112ec +#define PEG1EC 0x112f0 +#define GFXEC 0x112f4 +#define RPPREVBSYTUPAVG 0x113b8 +#define RPPREVBSYTDNAVG 0x113bc +#define ECR 0x11600 +#define ECR_GPFE (1<<31) +#define ECR_IMONE (1<<30) +#define ECR_CAP_MASK 0x0000001f /* Event range, 0-31 */ +#define OGW0 0x11608 +#define OGW1 0x1160c +#define EG0 0x11610 +#define EG1 0x11614 +#define EG2 0x11618 +#define EG3 0x1161c +#define EG4 0x11620 +#define EG5 0x11624 +#define EG6 0x11628 +#define EG7 0x1162c +#define PXW 0x11664 +#define PXWL 0x11680 +#define LCFUSE02 0x116c0 +#define LCFUSE_HIV_MASK 0x000000ff +#define CSIPLL0 0x12c10 +#define DDRMPLL1 0X12c20 +#define PEG_BAND_GAP_DATA 0x14d68 + +#define GEN6_GT_THREAD_STATUS_REG 0x13805c +#define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 + +#define GEN6_GT_PERF_STATUS 0x145948 +#define GEN6_RP_STATE_LIMITS 0x145994 +#define GEN6_RP_STATE_CAP 0x145998 + +/* + * Logical Context regs + */ +#define CCID 0x2180 +#define CCID_EN (1<<0) +/* + * Overlay regs + */ + +#define OVADD 0x30000 +#define DOVSTA 0x30008 +#define OC_BUF (0x3<<20) +#define OGAMC5 0x30010 +#define OGAMC4 0x30014 +#define OGAMC3 0x30018 +#define OGAMC2 0x3001c +#define OGAMC1 0x30020 +#define OGAMC0 0x30024 + +/* + * Display engine regs + */ + +/* Pipe A timing regs */ +#define _HTOTAL_A 0x60000 +#define _HBLANK_A 0x60004 +#define _HSYNC_A 0x60008 +#define _VTOTAL_A 0x6000c +#define _VBLANK_A 0x60010 +#define _VSYNC_A 0x60014 +#define _PIPEASRC 0x6001c +#define _BCLRPAT_A 0x60020 +#define _VSYNCSHIFT_A 0x60028 + +/* Pipe B timing regs */ +#define _HTOTAL_B 0x61000 +#define _HBLANK_B 0x61004 +#define _HSYNC_B 0x61008 +#define _VTOTAL_B 0x6100c +#define _VBLANK_B 0x61010 +#define _VSYNC_B 0x61014 +#define _PIPEBSRC 0x6101c +#define _BCLRPAT_B 0x61020 +#define _VSYNCSHIFT_B 0x61028 + + +#define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B) +#define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B) +#define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B) +#define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B) +#define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B) +#define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B) +#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B) +#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B) + +/* VGA port control */ +#define ADPA 0x61100 +#define ADPA_DAC_ENABLE (1<<31) +#define ADPA_DAC_DISABLE 0 +#define ADPA_PIPE_SELECT_MASK (1<<30) +#define ADPA_PIPE_A_SELECT 0 +#define ADPA_PIPE_B_SELECT (1<<30) +#define ADPA_PIPE_SELECT(pipe) ((pipe) << 30) +#define ADPA_USE_VGA_HVPOLARITY (1<<15) +#define ADPA_SETS_HVPOLARITY 0 +#define ADPA_VSYNC_CNTL_DISABLE (1<<11) +#define ADPA_VSYNC_CNTL_ENABLE 0 +#define ADPA_HSYNC_CNTL_DISABLE (1<<10) +#define ADPA_HSYNC_CNTL_ENABLE 0 +#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) +#define ADPA_VSYNC_ACTIVE_LOW 0 +#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) +#define ADPA_HSYNC_ACTIVE_LOW 0 +#define ADPA_DPMS_MASK (~(3<<10)) +#define ADPA_DPMS_ON (0<<10) +#define ADPA_DPMS_SUSPEND (1<<10) +#define ADPA_DPMS_STANDBY (2<<10) +#define ADPA_DPMS_OFF (3<<10) + + +/* Hotplug control (945+ only) */ +#define PORT_HOTPLUG_EN 0x61110 +#define HDMIB_HOTPLUG_INT_EN (1 << 29) +#define DPB_HOTPLUG_INT_EN (1 << 29) +#define HDMIC_HOTPLUG_INT_EN (1 << 28) +#define DPC_HOTPLUG_INT_EN (1 << 28) +#define HDMID_HOTPLUG_INT_EN (1 << 27) +#define DPD_HOTPLUG_INT_EN (1 << 27) +#define SDVOB_HOTPLUG_INT_EN (1 << 26) +#define SDVOC_HOTPLUG_INT_EN (1 << 25) +#define TV_HOTPLUG_INT_EN (1 << 18) +#define CRT_HOTPLUG_INT_EN (1 << 9) +#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) + +#define PORT_HOTPLUG_STAT 0x61114 +#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) +#define DPB_HOTPLUG_INT_STATUS (1 << 29) +#define HDMIC_HOTPLUG_INT_STATUS (1 << 28) +#define DPC_HOTPLUG_INT_STATUS (1 << 28) +#define HDMID_HOTPLUG_INT_STATUS (1 << 27) +#define DPD_HOTPLUG_INT_STATUS (1 << 27) +#define CRT_HOTPLUG_INT_STATUS (1 << 11) +#define TV_HOTPLUG_INT_STATUS (1 << 10) +#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) + +/* SDVO port control */ +#define SDVOB 0x61140 +#define SDVOC 0x61160 +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_B_SELECT (1 << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/** + * 915G/GM SDVO pixel multiplier. + * + * Programmed value is multiplier - 1, up to 5x. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) +#define SDVO_ENCODING_SDVO (0x0 << 10) +#define SDVO_ENCODING_HDMI (0x2 << 10) +/** Requird for HDMI operation */ +#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) +#define SDVO_COLOR_RANGE_16_235 (1 << 8) +#define SDVO_BORDER_ENABLE (1 << 7) +#define SDVO_AUDIO_ENABLE (1 << 6) +/** New with 965, default is to be set */ +#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +/** New with 965, default is to be set */ +#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define SDVOB_PCIE_CONCURRENCY (1 << 3) +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26)) +#define SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26)) + +/* DVO port control */ +#define DVOA 0x61120 +#define DVOB 0x61140 +#define DVOC 0x61160 +#define DVO_ENABLE (1 << 31) +#define DVO_PIPE_B_SELECT (1 << 30) +#define DVO_PIPE_STALL_UNUSED (0 << 28) +#define DVO_PIPE_STALL (1 << 28) +#define DVO_PIPE_STALL_TV (2 << 28) +#define DVO_PIPE_STALL_MASK (3 << 28) +#define DVO_USE_VGA_SYNC (1 << 15) +#define DVO_DATA_ORDER_I740 (0 << 14) +#define DVO_DATA_ORDER_FP (1 << 14) +#define DVO_VSYNC_DISABLE (1 << 11) +#define DVO_HSYNC_DISABLE (1 << 10) +#define DVO_VSYNC_TRISTATE (1 << 9) +#define DVO_HSYNC_TRISTATE (1 << 8) +#define DVO_BORDER_ENABLE (1 << 7) +#define DVO_DATA_ORDER_GBRG (1 << 6) +#define DVO_DATA_ORDER_RGGB (0 << 6) +#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) +#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) +#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) +#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define DVO_BLANK_ACTIVE_HIGH (1 << 2) +#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ +#define DVO_PRESERVE_MASK (0x7<<24) +#define DVOA_SRCDIM 0x61124 +#define DVOB_SRCDIM 0x61144 +#define DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 +#define DVO_SRCDIM_VERTICAL_SHIFT 0 + +/* LVDS port control */ +#define LVDS 0x61180 +/* + * Enables the LVDS port. This bit must be set before DPLLs are enabled, as + * the DPLL semantics change when the LVDS is assigned to that pipe. + */ +#define LVDS_PORT_EN (1 << 31) +/* Selects pipe B for LVDS data. Must be set on pre-965. */ +#define LVDS_PIPEB_SELECT (1 << 30) +#define LVDS_PIPE_MASK (1 << 30) +#define LVDS_PIPE(pipe) ((pipe) << 30) +/* LVDS dithering flag on 965/g4x platform */ +#define LVDS_ENABLE_DITHER (1 << 25) +/* LVDS sync polarity flags. Set to invert (i.e. negative) */ +#define LVDS_VSYNC_POLARITY (1 << 21) +#define LVDS_HSYNC_POLARITY (1 << 20) + +/* Enable border for unscaled (or aspect-scaled) display */ +#define LVDS_BORDER_ENABLE (1 << 15) +/* + * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per + * pixel. + */ +#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) +#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) +#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) +/* + * Controls the A3 data pair, which contains the additional LSBs for 24 bit + * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be + * on. + */ +#define LVDS_A3_POWER_MASK (3 << 6) +#define LVDS_A3_POWER_DOWN (0 << 6) +#define LVDS_A3_POWER_UP (3 << 6) +/* + * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP + * is set. + */ +#define LVDS_CLKB_POWER_MASK (3 << 4) +#define LVDS_CLKB_POWER_DOWN (0 << 4) +#define LVDS_CLKB_POWER_UP (3 << 4) +/* + * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 + * setting for whether we are in dual-channel mode. The B3 pair will + * additionally only be powered up when LVDS_A3_POWER_UP is set. + */ +#define LVDS_B0B3_POWER_MASK (3 << 2) +#define LVDS_B0B3_POWER_DOWN (0 << 2) +#define LVDS_B0B3_POWER_UP (3 << 2) + +/* Video Data Island Packet control */ +#define VIDEO_DIP_DATA 0x61178 +#define VIDEO_DIP_CTL 0x61170 +#define VIDEO_DIP_ENABLE (1 << 31) +#define VIDEO_DIP_PORT_B (1 << 29) +#define VIDEO_DIP_PORT_C (2 << 29) +#define VIDEO_DIP_ENABLE_AVI (1 << 21) +#define VIDEO_DIP_ENABLE_VENDOR (2 << 21) +#define VIDEO_DIP_ENABLE_SPD (8 << 21) +#define VIDEO_DIP_SELECT_AVI (0 << 19) +#define VIDEO_DIP_SELECT_VENDOR (1 << 19) +#define VIDEO_DIP_SELECT_SPD (3 << 19) +#define VIDEO_DIP_SELECT_MASK (3 << 19) +#define VIDEO_DIP_FREQ_ONCE (0 << 16) +#define VIDEO_DIP_FREQ_VSYNC (1 << 16) +#define VIDEO_DIP_FREQ_2VSYNC (2 << 16) + +/* Panel power sequencing */ +#define PP_STATUS 0x61200 +#define PP_ON (1 << 31) +/* + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +#define PP_READY (1 << 30) +#define PP_SEQUENCE_NONE (0 << 28) +#define PP_SEQUENCE_POWER_UP (1 << 28) +#define PP_SEQUENCE_POWER_DOWN (2 << 28) +#define PP_SEQUENCE_MASK (3 << 28) +#define PP_SEQUENCE_SHIFT 28 +#define PP_CYCLE_DELAY_ACTIVE (1 << 27) +#define PP_SEQUENCE_STATE_MASK 0x0000000f +#define PP_SEQUENCE_STATE_OFF_IDLE (0x0 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_1 (0x1 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_2 (0x2 << 0) +#define PP_SEQUENCE_STATE_OFF_S0_3 (0x3 << 0) +#define PP_SEQUENCE_STATE_ON_IDLE (0x8 << 0) +#define PP_SEQUENCE_STATE_ON_S1_0 (0x9 << 0) +#define PP_SEQUENCE_STATE_ON_S1_2 (0xa << 0) +#define PP_SEQUENCE_STATE_ON_S1_3 (0xb << 0) +#define PP_SEQUENCE_STATE_RESET (0xf << 0) +#define PP_CONTROL 0x61204 +#define POWER_TARGET_ON (1 << 0) +#define PP_ON_DELAYS 0x61208 +#define PP_OFF_DELAYS 0x6120c +#define PP_DIVISOR 0x61210 + +/* Panel fitting */ +#define PFIT_CONTROL 0x61230 +#define PFIT_ENABLE (1 << 31) +#define PFIT_PIPE_MASK (3 << 29) +#define PFIT_PIPE_SHIFT 29 +#define VERT_INTERP_DISABLE (0 << 10) +#define VERT_INTERP_BILINEAR (1 << 10) +#define VERT_INTERP_MASK (3 << 10) +#define VERT_AUTO_SCALE (1 << 9) +#define HORIZ_INTERP_DISABLE (0 << 6) +#define HORIZ_INTERP_BILINEAR (1 << 6) +#define HORIZ_INTERP_MASK (3 << 6) +#define HORIZ_AUTO_SCALE (1 << 5) +#define PANEL_8TO6_DITHER_ENABLE (1 << 3) +#define PFIT_FILTER_FUZZY (0 << 24) +#define PFIT_SCALING_AUTO (0 << 26) +#define PFIT_SCALING_PROGRAMMED (1 << 26) +#define PFIT_SCALING_PILLAR (2 << 26) +#define PFIT_SCALING_LETTER (3 << 26) +#define PFIT_PGM_RATIOS 0x61234 +#define PFIT_VERT_SCALE_MASK 0xfff00000 +#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* Pre-965 */ +#define PFIT_VERT_SCALE_SHIFT 20 +#define PFIT_VERT_SCALE_MASK 0xfff00000 +#define PFIT_HORIZ_SCALE_SHIFT 4 +#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* 965+ */ +#define PFIT_VERT_SCALE_SHIFT_965 16 +#define PFIT_VERT_SCALE_MASK_965 0x1fff0000 +#define PFIT_HORIZ_SCALE_SHIFT_965 0 +#define PFIT_HORIZ_SCALE_MASK_965 0x00001fff + +#define PFIT_AUTO_RATIOS 0x61238 + +/* Backlight control */ +#define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BLC_PWM_CTL2 0x61250 /* 965+ only */ +#define BLM_COMBINATION_MODE (1 << 30) +/* + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) +/* + * This is the number of cycles out of the backlight modulation cycle for which + * the backlight is on. + * + * This field must be no greater than the number of cycles in the complete + * backlight modulation cycle. + */ +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) + +#define BLC_HIST_CTL 0x61260 + +/* TV port control */ +#define TV_CTL 0x68000 +/** Enables the TV encoder */ +# define TV_ENC_ENABLE (1 << 31) +/** Sources the TV encoder input from pipe B instead of A. */ +# define TV_ENC_PIPEB_SELECT (1 << 30) +/** Outputs composite video (DAC A only) */ +# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) +/** Outputs SVideo video (DAC B/C) */ +# define TV_ENC_OUTPUT_SVIDEO (1 << 28) +/** Outputs Component video (DAC A/B/C) */ +# define TV_ENC_OUTPUT_COMPONENT (2 << 28) +/** Outputs Composite and SVideo (DAC A/B/C) */ +# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28) +# define TV_TRILEVEL_SYNC (1 << 21) +/** Enables slow sync generation (945GM only) */ +# define TV_SLOW_SYNC (1 << 20) +/** Selects 4x oversampling for 480i and 576p */ +# define TV_OVERSAMPLE_4X (0 << 18) +/** Selects 2x oversampling for 720p and 1080i */ +# define TV_OVERSAMPLE_2X (1 << 18) +/** Selects no oversampling for 1080p */ +# define TV_OVERSAMPLE_NONE (2 << 18) +/** Selects 8x oversampling */ +# define TV_OVERSAMPLE_8X (3 << 18) +/** Selects progressive mode rather than interlaced */ +# define TV_PROGRESSIVE (1 << 17) +/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */ +# define TV_PAL_BURST (1 << 16) +/** Field for setting delay of Y compared to C */ +# define TV_YC_SKEW_MASK (7 << 12) +/** Enables a fix for 480p/576p standard definition modes on the 915GM only */ +# define TV_ENC_SDP_FIX (1 << 11) +/** + * Enables a fix for the 915GM only. + * + * Not sure what it does. + */ +# define TV_ENC_C0_FIX (1 << 10) +/** Bits that must be preserved by software */ +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) +# define TV_FUSE_STATE_MASK (3 << 4) +/** Read-only state that reports all features enabled */ +# define TV_FUSE_STATE_ENABLED (0 << 4) +/** Read-only state that reports that Macrovision is disabled in hardware*/ +# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) +/** Read-only state that reports that TV-out is disabled in hardware. */ +# define TV_FUSE_STATE_DISABLED (2 << 4) +/** Normal operation */ +# define TV_TEST_MODE_NORMAL (0 << 0) +/** Encoder test pattern 1 - combo pattern */ +# define TV_TEST_MODE_PATTERN_1 (1 << 0) +/** Encoder test pattern 2 - full screen vertical 75% color bars */ +# define TV_TEST_MODE_PATTERN_2 (2 << 0) +/** Encoder test pattern 3 - full screen horizontal 75% color bars */ +# define TV_TEST_MODE_PATTERN_3 (3 << 0) +/** Encoder test pattern 4 - random noise */ +# define TV_TEST_MODE_PATTERN_4 (4 << 0) +/** Encoder test pattern 5 - linear color ramps */ +# define TV_TEST_MODE_PATTERN_5 (5 << 0) +/** + * This test mode forces the DACs to 50% of full output. + * + * This is used for load detection in combination with TVDAC_SENSE_MASK + */ +# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) +# define TV_TEST_MODE_MASK (7 << 0) + +#define TV_DAC 0x68004 +# define TV_DAC_SAVE 0x00ffff00 +/** + * Reports that DAC state change logic has reported change (RO). + * + * This gets cleared when TV_DAC_STATE_EN is cleared +*/ +# define TVDAC_STATE_CHG (1 << 31) +# define TVDAC_SENSE_MASK (7 << 28) +/** Reports that DAC A voltage is above the detect threshold */ +# define TVDAC_A_SENSE (1 << 30) +/** Reports that DAC B voltage is above the detect threshold */ +# define TVDAC_B_SENSE (1 << 29) +/** Reports that DAC C voltage is above the detect threshold */ +# define TVDAC_C_SENSE (1 << 28) +/** + * Enables DAC state detection logic, for load-based TV detection. + * + * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set + * to off, for load detection to work. + */ +# define TVDAC_STATE_CHG_EN (1 << 27) +/** Sets the DAC A sense value to high */ +# define TVDAC_A_SENSE_CTL (1 << 26) +/** Sets the DAC B sense value to high */ +# define TVDAC_B_SENSE_CTL (1 << 25) +/** Sets the DAC C sense value to high */ +# define TVDAC_C_SENSE_CTL (1 << 24) +/** Overrides the ENC_ENABLE and DAC voltage levels */ +# define DAC_CTL_OVERRIDE (1 << 7) +/** Sets the slew rate. Must be preserved in software */ +# define ENC_TVDAC_SLEW_FAST (1 << 6) +# define DAC_A_1_3_V (0 << 4) +# define DAC_A_1_1_V (1 << 4) +# define DAC_A_0_7_V (2 << 4) +# define DAC_A_MASK (3 << 4) +# define DAC_B_1_3_V (0 << 2) +# define DAC_B_1_1_V (1 << 2) +# define DAC_B_0_7_V (2 << 2) +# define DAC_B_MASK (3 << 2) +# define DAC_C_1_3_V (0 << 0) +# define DAC_C_1_1_V (1 << 0) +# define DAC_C_0_7_V (2 << 0) +# define DAC_C_MASK (3 << 0) + +/** + * CSC coefficients are stored in a floating point format with 9 bits of + * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, + * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with + * -1 (0x3) being the only legal negative value. + */ +#define TV_CSC_Y 0x68010 +# define TV_RY_MASK 0x07ff0000 +# define TV_RY_SHIFT 16 +# define TV_GY_MASK 0x00000fff +# define TV_GY_SHIFT 0 + +#define TV_CSC_Y2 0x68014 +# define TV_BY_MASK 0x07ff0000 +# define TV_BY_SHIFT 16 +/** + * Y attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AY_MASK 0x000003ff +# define TV_AY_SHIFT 0 + +#define TV_CSC_U 0x68018 +# define TV_RU_MASK 0x07ff0000 +# define TV_RU_SHIFT 16 +# define TV_GU_MASK 0x000007ff +# define TV_GU_SHIFT 0 + +#define TV_CSC_U2 0x6801c +# define TV_BU_MASK 0x07ff0000 +# define TV_BU_SHIFT 16 +/** + * U attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AU_MASK 0x000003ff +# define TV_AU_SHIFT 0 + +#define TV_CSC_V 0x68020 +# define TV_RV_MASK 0x0fff0000 +# define TV_RV_SHIFT 16 +# define TV_GV_MASK 0x000007ff +# define TV_GV_SHIFT 0 + +#define TV_CSC_V2 0x68024 +# define TV_BV_MASK 0x07ff0000 +# define TV_BV_SHIFT 16 +/** + * V attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AV_MASK 0x000007ff +# define TV_AV_SHIFT 0 + +#define TV_CLR_KNOBS 0x68028 +/** 2s-complement brightness adjustment */ +# define TV_BRIGHTNESS_MASK 0xff000000 +# define TV_BRIGHTNESS_SHIFT 24 +/** Contrast adjustment, as a 2.6 unsigned floating point number */ +# define TV_CONTRAST_MASK 0x00ff0000 +# define TV_CONTRAST_SHIFT 16 +/** Saturation adjustment, as a 2.6 unsigned floating point number */ +# define TV_SATURATION_MASK 0x0000ff00 +# define TV_SATURATION_SHIFT 8 +/** Hue adjustment, as an integer phase angle in degrees */ +# define TV_HUE_MASK 0x000000ff +# define TV_HUE_SHIFT 0 + +#define TV_CLR_LEVEL 0x6802c +/** Controls the DAC level for black */ +# define TV_BLACK_LEVEL_MASK 0x01ff0000 +# define TV_BLACK_LEVEL_SHIFT 16 +/** Controls the DAC level for blanking */ +# define TV_BLANK_LEVEL_MASK 0x000001ff +# define TV_BLANK_LEVEL_SHIFT 0 + +#define TV_H_CTL_1 0x68030 +/** Number of pixels in the hsync. */ +# define TV_HSYNC_END_MASK 0x1fff0000 +# define TV_HSYNC_END_SHIFT 16 +/** Total number of pixels minus one in the line (display and blanking). */ +# define TV_HTOTAL_MASK 0x00001fff +# define TV_HTOTAL_SHIFT 0 + +#define TV_H_CTL_2 0x68034 +/** Enables the colorburst (needed for non-component color) */ +# define TV_BURST_ENA (1 << 31) +/** Offset of the colorburst from the start of hsync, in pixels minus one. */ +# define TV_HBURST_START_SHIFT 16 +# define TV_HBURST_START_MASK 0x1fff0000 +/** Length of the colorburst */ +# define TV_HBURST_LEN_SHIFT 0 +# define TV_HBURST_LEN_MASK 0x0001fff + +#define TV_H_CTL_3 0x68038 +/** End of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_END_SHIFT 16 +# define TV_HBLANK_END_MASK 0x1fff0000 +/** Start of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_START_SHIFT 0 +# define TV_HBLANK_START_MASK 0x0001fff + +#define TV_V_CTL_1 0x6803c +/** XXX */ +# define TV_NBR_END_SHIFT 16 +# define TV_NBR_END_MASK 0x07ff0000 +/** XXX */ +# define TV_VI_END_F1_SHIFT 8 +# define TV_VI_END_F1_MASK 0x00003f00 +/** XXX */ +# define TV_VI_END_F2_SHIFT 0 +# define TV_VI_END_F2_MASK 0x0000003f + +#define TV_V_CTL_2 0x68040 +/** Length of vsync, in half lines */ +# define TV_VSYNC_LEN_MASK 0x07ff0000 +# define TV_VSYNC_LEN_SHIFT 16 +/** Offset of the start of vsync in field 1, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F1_MASK 0x00007f00 +# define TV_VSYNC_START_F1_SHIFT 8 +/** + * Offset of the start of vsync in field 2, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F2_MASK 0x0000007f +# define TV_VSYNC_START_F2_SHIFT 0 + +#define TV_V_CTL_3 0x68044 +/** Enables generation of the equalization signal */ +# define TV_EQUAL_ENA (1 << 31) +/** Length of vsync, in half lines */ +# define TV_VEQ_LEN_MASK 0x007f0000 +# define TV_VEQ_LEN_SHIFT 16 +/** Offset of the start of equalization in field 1, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F1_MASK 0x0007f00 +# define TV_VEQ_START_F1_SHIFT 8 +/** + * Offset of the start of equalization in field 2, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F2_MASK 0x000007f +# define TV_VEQ_START_F2_SHIFT 0 + +#define TV_V_CTL_4 0x68048 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F1_MASK 0x003f0000 +# define TV_VBURST_START_F1_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F1_MASK 0x000000ff +# define TV_VBURST_END_F1_SHIFT 0 + +#define TV_V_CTL_5 0x6804c +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F2_MASK 0x003f0000 +# define TV_VBURST_START_F2_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F2_MASK 0x000000ff +# define TV_VBURST_END_F2_SHIFT 0 + +#define TV_V_CTL_6 0x68050 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F3_MASK 0x003f0000 +# define TV_VBURST_START_F3_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F3_MASK 0x000000ff +# define TV_VBURST_END_F3_SHIFT 0 + +#define TV_V_CTL_7 0x68054 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F4_MASK 0x003f0000 +# define TV_VBURST_START_F4_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F4_MASK 0x000000ff +# define TV_VBURST_END_F4_SHIFT 0 + +#define TV_SC_CTL_1 0x68060 +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA1_EN (1 << 31) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA2_EN (1 << 30) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA3_EN (1 << 29) +/** Sets the subcarrier DDA to reset frequency every other field */ +# define TV_SC_RESET_EVERY_2 (0 << 24) +/** Sets the subcarrier DDA to reset frequency every fourth field */ +# define TV_SC_RESET_EVERY_4 (1 << 24) +/** Sets the subcarrier DDA to reset frequency every eighth field */ +# define TV_SC_RESET_EVERY_8 (2 << 24) +/** Sets the subcarrier DDA to never reset the frequency */ +# define TV_SC_RESET_NEVER (3 << 24) +/** Sets the peak amplitude of the colorburst.*/ +# define TV_BURST_LEVEL_MASK 0x00ff0000 +# define TV_BURST_LEVEL_SHIFT 16 +/** Sets the increment of the first subcarrier phase generation DDA */ +# define TV_SCDDA1_INC_MASK 0x00000fff +# define TV_SCDDA1_INC_SHIFT 0 + +#define TV_SC_CTL_2 0x68064 +/** Sets the rollover for the second subcarrier phase generation DDA */ +# define TV_SCDDA2_SIZE_MASK 0x7fff0000 +# define TV_SCDDA2_SIZE_SHIFT 16 +/** Sets the increent of the second subcarrier phase generation DDA */ +# define TV_SCDDA2_INC_MASK 0x00007fff +# define TV_SCDDA2_INC_SHIFT 0 + +#define TV_SC_CTL_3 0x68068 +/** Sets the rollover for the third subcarrier phase generation DDA */ +# define TV_SCDDA3_SIZE_MASK 0x7fff0000 +# define TV_SCDDA3_SIZE_SHIFT 16 +/** Sets the increent of the third subcarrier phase generation DDA */ +# define TV_SCDDA3_INC_MASK 0x00007fff +# define TV_SCDDA3_INC_SHIFT 0 + +#define TV_WIN_POS 0x68070 +/** X coordinate of the display from the start of horizontal active */ +# define TV_XPOS_MASK 0x1fff0000 +# define TV_XPOS_SHIFT 16 +/** Y coordinate of the display from the start of vertical active (NBR) */ +# define TV_YPOS_MASK 0x00000fff +# define TV_YPOS_SHIFT 0 + +#define TV_WIN_SIZE 0x68074 +/** Horizontal size of the display window, measured in pixels*/ +# define TV_XSIZE_MASK 0x1fff0000 +# define TV_XSIZE_SHIFT 16 +/** + * Vertical size of the display window, measured in pixels. + * + * Must be even for interlaced modes. + */ +# define TV_YSIZE_MASK 0x00000fff +# define TV_YSIZE_SHIFT 0 + +#define TV_FILTER_CTL_1 0x68080 +/** + * Enables automatic scaling calculation. + * + * If set, the rest of the registers are ignored, and the calculated values can + * be read back from the register. + */ +# define TV_AUTO_SCALE (1 << 31) +/** + * Disables the vertical filter. + * + * This is required on modes more than 1024 pixels wide */ +# define TV_V_FILTER_BYPASS (1 << 29) +/** Enables adaptive vertical filtering */ +# define TV_VADAPT (1 << 28) +# define TV_VADAPT_MODE_MASK (3 << 26) +/** Selects the least adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_LEAST (0 << 26) +/** Selects the moderately adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MODERATE (1 << 26) +/** Selects the most adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MOST (3 << 26) +/** + * Sets the horizontal scaling factor. + * + * This should be the fractional part of the horizontal scaling factor divided + * by the oversampling rate. TV_HSCALE should be less than 1, and set to: + * + * (src width - 1) / ((oversample * dest width) - 1) + */ +# define TV_HSCALE_FRAC_MASK 0x00003fff +# define TV_HSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_2 0x68084 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) + */ +# define TV_VSCALE_INT_MASK 0x00038000 +# define TV_VSCALE_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * \sa TV_VSCALE_INT_MASK + */ +# define TV_VSCALE_FRAC_MASK 0x00007fff +# define TV_VSCALE_FRAC_SHIFT 0 + +#define TV_FILTER_CTL_3 0x68088 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + */ +# define TV_VSCALE_IP_INT_MASK 0x00038000 +# define TV_VSCALE_IP_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + * + * \sa TV_VSCALE_IP_INT_MASK + */ +# define TV_VSCALE_IP_FRAC_MASK 0x00007fff +# define TV_VSCALE_IP_FRAC_SHIFT 0 + +#define TV_CC_CONTROL 0x68090 +# define TV_CC_ENABLE (1 << 31) +/** + * Specifies which field to send the CC data in. + * + * CC data is usually sent in field 0. + */ +# define TV_CC_FID_MASK (1 << 27) +# define TV_CC_FID_SHIFT 27 +/** Sets the horizontal position of the CC data. Usually 135. */ +# define TV_CC_HOFF_MASK 0x03ff0000 +# define TV_CC_HOFF_SHIFT 16 +/** Sets the vertical position of the CC data. Usually 21 */ +# define TV_CC_LINE_MASK 0x0000003f +# define TV_CC_LINE_SHIFT 0 + +#define TV_CC_DATA 0x68094 +# define TV_CC_RDY (1 << 31) +/** Second word of CC data to be transmitted. */ +# define TV_CC_DATA_2_MASK 0x007f0000 +# define TV_CC_DATA_2_SHIFT 16 +/** First word of CC data to be transmitted. */ +# define TV_CC_DATA_1_MASK 0x0000007f +# define TV_CC_DATA_1_SHIFT 0 + +#define TV_H_LUMA_0 0x68100 +#define TV_H_LUMA_59 0x681ec +#define TV_H_CHROMA_0 0x68200 +#define TV_H_CHROMA_59 0x682ec +#define TV_V_LUMA_0 0x68300 +#define TV_V_LUMA_42 0x683a8 +#define TV_V_CHROMA_0 0x68400 +#define TV_V_CHROMA_42 0x684a8 + +/* Display Port */ +#define DP_A 0x64000 /* eDP */ +#define DP_B 0x64100 +#define DP_C 0x64200 +#define DP_D 0x64300 + +#define DP_PORT_EN (1 << 31) +#define DP_PIPEB_SELECT (1 << 30) +#define DP_PIPE_MASK (1 << 30) + +/* Link training mode - select a suitable mode for each stage */ +#define DP_LINK_TRAIN_PAT_1 (0 << 28) +#define DP_LINK_TRAIN_PAT_2 (1 << 28) +#define DP_LINK_TRAIN_PAT_IDLE (2 << 28) +#define DP_LINK_TRAIN_OFF (3 << 28) +#define DP_LINK_TRAIN_MASK (3 << 28) +#define DP_LINK_TRAIN_SHIFT 28 + +/* CPT Link training mode */ +#define DP_LINK_TRAIN_PAT_1_CPT (0 << 8) +#define DP_LINK_TRAIN_PAT_2_CPT (1 << 8) +#define DP_LINK_TRAIN_PAT_IDLE_CPT (2 << 8) +#define DP_LINK_TRAIN_OFF_CPT (3 << 8) +#define DP_LINK_TRAIN_MASK_CPT (7 << 8) +#define DP_LINK_TRAIN_SHIFT_CPT 8 + +/* Signal voltages. These are mostly controlled by the other end */ +#define DP_VOLTAGE_0_4 (0 << 25) +#define DP_VOLTAGE_0_6 (1 << 25) +#define DP_VOLTAGE_0_8 (2 << 25) +#define DP_VOLTAGE_1_2 (3 << 25) +#define DP_VOLTAGE_MASK (7 << 25) +#define DP_VOLTAGE_SHIFT 25 + +/* Signal pre-emphasis levels, like voltages, the other end tells us what + * they want + */ +#define DP_PRE_EMPHASIS_0 (0 << 22) +#define DP_PRE_EMPHASIS_3_5 (1 << 22) +#define DP_PRE_EMPHASIS_6 (2 << 22) +#define DP_PRE_EMPHASIS_9_5 (3 << 22) +#define DP_PRE_EMPHASIS_MASK (7 << 22) +#define DP_PRE_EMPHASIS_SHIFT 22 + +/* How many wires to use. I guess 3 was too hard */ +#define DP_PORT_WIDTH_1 (0 << 19) +#define DP_PORT_WIDTH_2 (1 << 19) +#define DP_PORT_WIDTH_4 (3 << 19) +#define DP_PORT_WIDTH_MASK (7 << 19) + +/* Mystic DPCD version 1.1 special mode */ +#define DP_ENHANCED_FRAMING (1 << 18) + +/* eDP */ +#define DP_PLL_FREQ_270MHZ (0 << 16) +#define DP_PLL_FREQ_160MHZ (1 << 16) +#define DP_PLL_FREQ_MASK (3 << 16) + +/** locked once port is enabled */ +#define DP_PORT_REVERSAL (1 << 15) + +/* eDP */ +#define DP_PLL_ENABLE (1 << 14) + +/** sends the clock on lane 15 of the PEG for debug */ +#define DP_CLOCK_OUTPUT_ENABLE (1 << 13) + +#define DP_SCRAMBLING_DISABLE (1 << 12) +#define DP_SCRAMBLING_DISABLE_IRONLAKE (1 << 7) + +/** limit RGB values to avoid confusing TVs */ +#define DP_COLOR_RANGE_16_235 (1 << 8) + +/** Turn on the audio link */ +#define DP_AUDIO_OUTPUT_ENABLE (1 << 6) + +/** vs and hs sync polarity */ +#define DP_SYNC_VS_HIGH (1 << 4) +#define DP_SYNC_HS_HIGH (1 << 3) + +/** A fantasy */ +#define DP_DETECTED (1 << 2) + +/** The aux channel provides a way to talk to the + * signal sink for DDC etc. Max packet size supported + * is 20 bytes in each direction, hence the 5 fixed + * data registers + */ +#define DPA_AUX_CH_CTL 0x64010 +#define DPA_AUX_CH_DATA1 0x64014 +#define DPA_AUX_CH_DATA2 0x64018 +#define DPA_AUX_CH_DATA3 0x6401c +#define DPA_AUX_CH_DATA4 0x64020 +#define DPA_AUX_CH_DATA5 0x64024 + +#define DPB_AUX_CH_CTL 0x64110 +#define DPB_AUX_CH_DATA1 0x64114 +#define DPB_AUX_CH_DATA2 0x64118 +#define DPB_AUX_CH_DATA3 0x6411c +#define DPB_AUX_CH_DATA4 0x64120 +#define DPB_AUX_CH_DATA5 0x64124 + +#define DPC_AUX_CH_CTL 0x64210 +#define DPC_AUX_CH_DATA1 0x64214 +#define DPC_AUX_CH_DATA2 0x64218 +#define DPC_AUX_CH_DATA3 0x6421c +#define DPC_AUX_CH_DATA4 0x64220 +#define DPC_AUX_CH_DATA5 0x64224 + +#define DPD_AUX_CH_CTL 0x64310 +#define DPD_AUX_CH_DATA1 0x64314 +#define DPD_AUX_CH_DATA2 0x64318 +#define DPD_AUX_CH_DATA3 0x6431c +#define DPD_AUX_CH_DATA4 0x64320 +#define DPD_AUX_CH_DATA5 0x64324 + +#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) +#define DP_AUX_CH_CTL_DONE (1 << 30) +#define DP_AUX_CH_CTL_INTERRUPT (1 << 29) +#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28) +#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_1600us (3 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) +#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20 +#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16) +#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16 +#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15) +#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14) +#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13) +#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12) +#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0 + +/* + * Computing GMCH M and N values for the Display Port link + * + * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes + * + * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz) + * + * The GMCH value is used internally + * + * bytes_per_pixel is the number of bytes coming out of the plane, + * which is after the LUTs, so we want the bytes for our color format. + * For our current usage, this is always 3, one byte for R, G and B. + */ +#define _PIPEA_GMCH_DATA_M 0x70050 +#define _PIPEB_GMCH_DATA_M 0x71050 + +/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ +#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) +#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25 + +#define PIPE_GMCH_DATA_M_MASK (0xffffff) + +#define _PIPEA_GMCH_DATA_N 0x70054 +#define _PIPEB_GMCH_DATA_N 0x71054 +#define PIPE_GMCH_DATA_N_MASK (0xffffff) + +/* + * Computing Link M and N values for the Display Port link + * + * Link M / N = pixel_clock / ls_clk + * + * (the DP spec calls pixel_clock the 'strm_clk') + * + * The Link value is transmitted in the Main Stream + * Attributes and VB-ID. + */ + +#define _PIPEA_DP_LINK_M 0x70060 +#define _PIPEB_DP_LINK_M 0x71060 +#define PIPEA_DP_LINK_M_MASK (0xffffff) + +#define _PIPEA_DP_LINK_N 0x70064 +#define _PIPEB_DP_LINK_N 0x71064 +#define PIPEA_DP_LINK_N_MASK (0xffffff) + +#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M) +#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N) +#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) +#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) + +/* Display & cursor control */ + +/* Pipe A */ +#define _PIPEADSL 0x70000 +#define DSL_LINEMASK 0x00000fff +#define _PIPEACONF 0x70008 +#define PIPECONF_ENABLE (1<<31) +#define PIPECONF_DISABLE 0 +#define PIPECONF_DOUBLE_WIDE (1<<30) +#define I965_PIPECONF_ACTIVE (1<<30) +#define PIPECONF_FRAME_START_DELAY_MASK (3<<27) +#define PIPECONF_SINGLE_WIDE 0 +#define PIPECONF_PIPE_UNLOCKED 0 +#define PIPECONF_PIPE_LOCKED (1<<25) +#define PIPECONF_PALETTE 0 +#define PIPECONF_GAMMA (1<<24) +#define PIPECONF_FORCE_BORDER (1<<25) +#define PIPECONF_INTERLACE_MASK (7 << 21) +/* Note that pre-gen3 does not support interlaced display directly. Panel + * fitting must be disabled on pre-ilk for interlaced. */ +#define PIPECONF_PROGRESSIVE (0 << 21) +#define PIPECONF_INTERLACE_W_SYNC_SHIFT_PANEL (4 << 21) /* gen4 only */ +#define PIPECONF_INTERLACE_W_SYNC_SHIFT (5 << 21) /* gen4 only */ +#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) /* gen3 only */ +/* Ironlake and later have a complete new set of values for interlaced. PFIT + * means panel fitter required, PF means progressive fetch, DBL means power + * saving pixel doubling. */ +#define PIPECONF_PFIT_PF_INTERLACED_ILK (1 << 21) +#define PIPECONF_INTERLACED_ILK (3 << 21) +#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */ +#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */ +#define PIPECONF_CXSR_DOWNCLOCK (1<<16) +#define PIPECONF_BPP_MASK (0x000000e0) +#define PIPECONF_BPP_8 (0<<5) +#define PIPECONF_BPP_10 (1<<5) +#define PIPECONF_BPP_6 (2<<5) +#define PIPECONF_BPP_12 (3<<5) +#define PIPECONF_DITHER_EN (1<<4) +#define PIPECONF_DITHER_TYPE_MASK (0x0000000c) +#define PIPECONF_DITHER_TYPE_SP (0<<2) +#define PIPECONF_DITHER_TYPE_ST1 (1<<2) +#define PIPECONF_DITHER_TYPE_ST2 (2<<2) +#define PIPECONF_DITHER_TYPE_TEMP (3<<2) +#define _PIPEASTAT 0x70024 +#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) +#define PIPE_CRC_ERROR_ENABLE (1UL<<29) +#define PIPE_CRC_DONE_ENABLE (1UL<<28) +#define PIPE_GMBUS_EVENT_ENABLE (1UL<<27) +#define PIPE_HOTPLUG_INTERRUPT_ENABLE (1UL<<26) +#define PIPE_VSYNC_INTERRUPT_ENABLE (1UL<<25) +#define PIPE_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24) +#define PIPE_DPST_EVENT_ENABLE (1UL<<23) +#define PIPE_LEGACY_BLC_EVENT_ENABLE (1UL<<22) +#define PIPE_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21) +#define PIPE_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20) +#define PIPE_HOTPLUG_TV_INTERRUPT_ENABLE (1UL<<18) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */ +#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL<<17) +#define PIPE_OVERLAY_UPDATED_ENABLE (1UL<<16) +#define PIPE_CRC_ERROR_INTERRUPT_STATUS (1UL<<13) +#define PIPE_CRC_DONE_INTERRUPT_STATUS (1UL<<12) +#define PIPE_GMBUS_INTERRUPT_STATUS (1UL<<11) +#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL<<10) +#define PIPE_VSYNC_INTERRUPT_STATUS (1UL<<9) +#define PIPE_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) +#define PIPE_DPST_EVENT_STATUS (1UL<<7) +#define PIPE_LEGACY_BLC_EVENT_STATUS (1UL<<6) +#define PIPE_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) +#define PIPE_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4) +#define PIPE_HOTPLUG_TV_INTERRUPT_STATUS (1UL<<2) /* pre-965 */ +#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ +#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1) +#define PIPE_OVERLAY_UPDATED_STATUS (1UL<<0) +#define PIPE_BPC_MASK (7 << 5) /* Ironlake */ +#define PIPE_8BPC (0 << 5) +#define PIPE_10BPC (1 << 5) +#define PIPE_6BPC (2 << 5) +#define PIPE_12BPC (3 << 5) + +#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC) +#define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF) +#define PIPEDSL(pipe) _PIPE(pipe, _PIPEADSL, _PIPEBDSL) +#define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH) +#define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) +#define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) + +#define DSPARB 0x70030 +#define DSPARB_CSTART_MASK (0x7f << 7) +#define DSPARB_CSTART_SHIFT 7 +#define DSPARB_BSTART_MASK (0x7f) +#define DSPARB_BSTART_SHIFT 0 +#define DSPARB_BEND_SHIFT 9 /* on 855 */ +#define DSPARB_AEND_SHIFT 0 + +#define DSPFW1 0x70034 +#define DSPFW_SR_SHIFT 23 +#define DSPFW_SR_MASK (0x1ff<<23) +#define DSPFW_CURSORB_SHIFT 16 +#define DSPFW_CURSORB_MASK (0x3f<<16) +#define DSPFW_PLANEB_SHIFT 8 +#define DSPFW_PLANEB_MASK (0x7f<<8) +#define DSPFW_PLANEA_MASK (0x7f) +#define DSPFW2 0x70038 +#define DSPFW_CURSORA_MASK 0x00003f00 +#define DSPFW_CURSORA_SHIFT 8 +#define DSPFW_PLANEC_MASK (0x7f) +#define DSPFW3 0x7003c +#define DSPFW_HPLL_SR_EN (1<<31) +#define DSPFW_CURSOR_SR_SHIFT 24 +#define PINEVIEW_SELF_REFRESH_EN (1<<30) +#define DSPFW_CURSOR_SR_MASK (0x3f<<24) +#define DSPFW_HPLL_CURSOR_SHIFT 16 +#define DSPFW_HPLL_CURSOR_MASK (0x3f<<16) +#define DSPFW_HPLL_SR_MASK (0x1ff) + +/* FIFO watermark sizes etc */ +#define G4X_FIFO_LINE_SIZE 64 +#define I915_FIFO_LINE_SIZE 64 +#define I830_FIFO_LINE_SIZE 32 + +#define G4X_FIFO_SIZE 127 +#define I965_FIFO_SIZE 512 +#define I945_FIFO_SIZE 127 +#define I915_FIFO_SIZE 95 +#define I855GM_FIFO_SIZE 127 /* In cachelines */ +#define I830_FIFO_SIZE 95 + +#define G4X_MAX_WM 0x3f +#define I915_MAX_WM 0x3f + +#define PINEVIEW_DISPLAY_FIFO 512 /* in 64byte unit */ +#define PINEVIEW_FIFO_LINE_SIZE 64 +#define PINEVIEW_MAX_WM 0x1ff +#define PINEVIEW_DFT_WM 0x3f +#define PINEVIEW_DFT_HPLLOFF_WM 0 +#define PINEVIEW_GUARD_WM 10 +#define PINEVIEW_CURSOR_FIFO 64 +#define PINEVIEW_CURSOR_MAX_WM 0x3f +#define PINEVIEW_CURSOR_DFT_WM 0 +#define PINEVIEW_CURSOR_GUARD_WM 5 + +#define I965_CURSOR_FIFO 64 +#define I965_CURSOR_MAX_WM 32 +#define I965_CURSOR_DFT_WM 8 + +/* define the Watermark register on Ironlake */ +#define WM0_PIPEA_ILK 0x45100 +#define WM0_PIPE_PLANE_MASK (0x7f<<16) +#define WM0_PIPE_PLANE_SHIFT 16 +#define WM0_PIPE_SPRITE_MASK (0x3f<<8) +#define WM0_PIPE_SPRITE_SHIFT 8 +#define WM0_PIPE_CURSOR_MASK (0x1f) + +#define WM0_PIPEB_ILK 0x45104 +#define WM0_PIPEC_IVB 0x45200 +#define WM1_LP_ILK 0x45108 +#define WM1_LP_SR_EN (1<<31) +#define WM1_LP_LATENCY_SHIFT 24 +#define WM1_LP_LATENCY_MASK (0x7f<<24) +#define WM1_LP_FBC_MASK (0xf<<20) +#define WM1_LP_FBC_SHIFT 20 +#define WM1_LP_SR_MASK (0x1ff<<8) +#define WM1_LP_SR_SHIFT 8 +#define WM1_LP_CURSOR_MASK (0x3f) +#define WM2_LP_ILK 0x4510c +#define WM2_LP_EN (1<<31) +#define WM3_LP_ILK 0x45110 +#define WM3_LP_EN (1<<31) +#define WM1S_LP_ILK 0x45120 +#define WM2S_LP_IVB 0x45124 +#define WM3S_LP_IVB 0x45128 +#define WM1S_LP_EN (1<<31) + +/* Memory latency timer register */ +#define MLTR_ILK 0x11222 +#define MLTR_WM1_SHIFT 0 +#define MLTR_WM2_SHIFT 8 +/* the unit of memory self-refresh latency time is 0.5us */ +#define ILK_SRLT_MASK 0x3f +#define ILK_LATENCY(shift) (I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK) +#define ILK_READ_WM1_LATENCY() ILK_LATENCY(MLTR_WM1_SHIFT) +#define ILK_READ_WM2_LATENCY() ILK_LATENCY(MLTR_WM2_SHIFT) + +/* define the fifo size on Ironlake */ +#define ILK_DISPLAY_FIFO 128 +#define ILK_DISPLAY_MAXWM 64 +#define ILK_DISPLAY_DFTWM 8 +#define ILK_CURSOR_FIFO 32 +#define ILK_CURSOR_MAXWM 16 +#define ILK_CURSOR_DFTWM 8 + +#define ILK_DISPLAY_SR_FIFO 512 +#define ILK_DISPLAY_MAX_SRWM 0x1ff +#define ILK_DISPLAY_DFT_SRWM 0x3f +#define ILK_CURSOR_SR_FIFO 64 +#define ILK_CURSOR_MAX_SRWM 0x3f +#define ILK_CURSOR_DFT_SRWM 8 + +#define ILK_FIFO_LINE_SIZE 64 + +/* define the WM info on Sandybridge */ +#define SNB_DISPLAY_FIFO 128 +#define SNB_DISPLAY_MAXWM 0x7f /* bit 16:22 */ +#define SNB_DISPLAY_DFTWM 8 +#define SNB_CURSOR_FIFO 32 +#define SNB_CURSOR_MAXWM 0x1f /* bit 4:0 */ +#define SNB_CURSOR_DFTWM 8 + +#define SNB_DISPLAY_SR_FIFO 512 +#define SNB_DISPLAY_MAX_SRWM 0x1ff /* bit 16:8 */ +#define SNB_DISPLAY_DFT_SRWM 0x3f +#define SNB_CURSOR_SR_FIFO 64 +#define SNB_CURSOR_MAX_SRWM 0x3f /* bit 5:0 */ +#define SNB_CURSOR_DFT_SRWM 8 + +#define SNB_FBC_MAX_SRWM 0xf /* bit 23:20 */ + +#define SNB_FIFO_LINE_SIZE 64 + + +/* the address where we get all kinds of latency value */ +#define SSKPD 0x5d10 +#define SSKPD_WM_MASK 0x3f +#define SSKPD_WM0_SHIFT 0 +#define SSKPD_WM1_SHIFT 8 +#define SSKPD_WM2_SHIFT 16 +#define SSKPD_WM3_SHIFT 24 + +#define SNB_LATENCY(shift) (I915_READ(MCHBAR_MIRROR_BASE_SNB + SSKPD) >> (shift) & SSKPD_WM_MASK) +#define SNB_READ_WM0_LATENCY() SNB_LATENCY(SSKPD_WM0_SHIFT) +#define SNB_READ_WM1_LATENCY() SNB_LATENCY(SSKPD_WM1_SHIFT) +#define SNB_READ_WM2_LATENCY() SNB_LATENCY(SSKPD_WM2_SHIFT) +#define SNB_READ_WM3_LATENCY() SNB_LATENCY(SSKPD_WM3_SHIFT) + +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> + * PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define _PIPEAFRAMEHIGH 0x70040 +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 +#define _PIPEAFRAMEPIXEL 0x70044 +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 +/* GM45+ just has to be different */ +#define _PIPEA_FRMCOUNT_GM45 0x70040 +#define _PIPEA_FLIPCOUNT_GM45 0x70044 +#define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45) + +/* Cursor A & B regs */ +#define _CURACNTR 0x70080 +/* Old style CUR*CNTR flags (desktop 8xx) */ +#define CURSOR_ENABLE 0x80000000 +#define CURSOR_GAMMA_ENABLE 0x40000000 +#define CURSOR_STRIDE_MASK 0x30000000 +#define CURSOR_FORMAT_SHIFT 24 +#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT) +/* New style CUR*CNTR flags */ +#define CURSOR_MODE 0x27 +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_64_32B_AX 0x07 +#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) +#define MCURSOR_PIPE_SELECT (1 << 28) +#define MCURSOR_PIPE_A 0x00 +#define MCURSOR_PIPE_B (1 << 28) +#define MCURSOR_GAMMA_ENABLE (1 << 26) +#define _CURABASE 0x70084 +#define _CURAPOS 0x70088 +#define CURSOR_POS_MASK 0x007FF +#define CURSOR_POS_SIGN 0x8000 +#define CURSOR_X_SHIFT 0 +#define CURSOR_Y_SHIFT 16 +#define CURSIZE 0x700a0 +#define _CURBCNTR 0x700c0 +#define _CURBBASE 0x700c4 +#define _CURBPOS 0x700c8 + +#define _CURBCNTR_IVB 0x71080 +#define _CURBBASE_IVB 0x71084 +#define _CURBPOS_IVB 0x71088 + +#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) +#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) +#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) + +#define CURCNTR_IVB(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR_IVB) +#define CURBASE_IVB(pipe) _PIPE(pipe, _CURABASE, _CURBBASE_IVB) +#define CURPOS_IVB(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS_IVB) + +/* Display A control */ +#define _DSPACNTR 0x70180 +#define DISPLAY_PLANE_ENABLE (1<<31) +#define DISPLAY_PLANE_DISABLE 0 +#define DISPPLANE_GAMMA_ENABLE (1<<30) +#define DISPPLANE_GAMMA_DISABLE 0 +#define DISPPLANE_PIXFORMAT_MASK (0xf<<26) +#define DISPPLANE_8BPP (0x2<<26) +#define DISPPLANE_15_16BPP (0x4<<26) +#define DISPPLANE_16BPP (0x5<<26) +#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) +#define DISPPLANE_32BPP (0x7<<26) +#define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) +#define DISPPLANE_STEREO_ENABLE (1<<25) +#define DISPPLANE_STEREO_DISABLE 0 +#define DISPPLANE_SEL_PIPE_SHIFT 24 +#define DISPPLANE_SEL_PIPE_MASK (3< +#include + +/* must typedef a gpio_t that fits in 32 bits. */ +_Static_assert(sizeof(gpio_t) <= sizeof(u32), "gpio_t doesn't fit in lb_gpio"); + +/* The following functions must be implemented by SoC/board code. */ +int gpio_get(gpio_t gpio); +void gpio_set(gpio_t gpio, int value); +void gpio_input_pulldown(gpio_t gpio); +void gpio_input_pullup(gpio_t gpio); +void gpio_input(gpio_t gpio); +void gpio_output(gpio_t gpio, int value); +int _gpio_base3_value(gpio_t gpio[], int num_gpio, int binary_first); /* - * Many-value logic (3 states). This can be used for inputs whereby presence - * of external pull-up or pull-down resistors can be added to overcome internal - * pull-ups/pull-downs and force a single value. + * Read the value presented by the set of GPIOs, when each pin is interpreted + * as a base-2 digit (LOW = 0, HIGH = 1). * - * Thus, external pull resistors can force a 0 or 1 and if the value changes - * along with internal pull-up/down enable then the input is floating. - * - * Vpd | Vpu | MVL - * ----------------- - * 0 | 0 | 0 - * ----------------- - * 0 | 1 | Z <-- floating input will follow internal pull up/down - * ----------------- - * 1 | 1 | 1 + * gpio[]: pin positions to read. gpio[0] is less significant than gpio[1]. + * num_gpio: number of pins to read. */ -enum mvl3 { - LOGIC_0, - LOGIC_1, - LOGIC_Z, /* high impedence / tri-stated / floating */ -}; +int gpio_base2_value(gpio_t gpio[], int num_gpio); -#endif /* GPIO_H */ +/* + * Read the value presented by the set of GPIOs, when each pin is interpreted + * as a base-3 digit (LOW = 0, HIGH = 1, Z/floating = 2). + * Example: X1 = Z, X2 = 1 -> gpio_base3_value({GPIO(X1), GPIO(X2)}) = 5 + * BASE3() from can generate numbers to compare the result to. + * + * gpio[]: pin positions to read. gpio[0] is less significant than gpio[1]. + * num_gpio: number of pins to read. + */ +static inline int gpio_base3_value(gpio_t gpio[], int num_gpio) +{ + return _gpio_base3_value(gpio, num_gpio, 0); +} + +/* + * Read the value presented by the set of GPIOs, when each pin is interpreted + * as a base-3 digit (LOW = 0, HIGH = 1, Z/floating = 2) in a non-standard + * ternary number system where the first 2^n natural numbers are represented + * as they would be in a binary system (without any Z digits), and the following + * 3^n-2^n numbers use the remaining ternary representations in the normal + * ternary system order (skipping the values that were already used up). + * This is useful for boards which initially used a binary board ID and later + * decided to switch to tri-state after some revisions have already been built. + * Example: For num_gpio = 2 we get the following representation: + * + * Number X1 X0 + * 0 0 0 + * 1 0 1 + * 2 1 0 + * 3 1 1 // Start counting ternaries back at 0 after this + * 4 0 2 // Skipping 00 and 01 which are already used up + * 5 1 2 // Skipping 10 and 11 which are already used up + * 6 2 0 + * 7 2 1 + * 8 2 2 + * + * gpio[]: pin positions to read. gpio[0] is less significant than gpio[1]. + * num_gpio: number of pins to read. + */ +static inline int gpio_binary_first_base3_value(gpio_t gpio[], int num_gpio) +{ + return _gpio_base3_value(gpio, num_gpio, 1); +} + +#endif /* __SRC_INCLUDE_GPIO_H__ */ diff --git a/src/include/ip_checksum.h b/src/include/ip_checksum.h index de26fa06cc..a1e0ffabd1 100644 --- a/src/include/ip_checksum.h +++ b/src/include/ip_checksum.h @@ -1,8 +1,5 @@ #ifndef IP_CHECKSUM_H #define IP_CHECKSUM_H - -#ifndef __ROMCC__ unsigned long compute_ip_checksum(void *addr, unsigned long length); unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new); -#endif #endif /* IP_CHECKSUM_H */ diff --git a/src/include/lib.h b/src/include/lib.h index 40c76f2db0..be66024f27 100644 --- a/src/include/lib.h +++ b/src/include/lib.h @@ -21,8 +21,8 @@ #ifndef __LIB_H__ #define __LIB_H__ +#include #include -#ifndef __ROMCC__ /* romcc doesn't support prototypes. */ #ifndef __PRE_RAM__ /* Conflicts with inline function in arch/io.h */ /* Defined in src/lib/clog2.c */ @@ -40,12 +40,12 @@ void ram_check(unsigned long start, unsigned long stop); int ram_check_nodie(unsigned long start, unsigned long stop); void quick_ram_check(void); +/* Defined in primitive_memtest.c */ +int primitive_memtest(uintptr_t base, uintptr_t size); + /* Defined in src/lib/stack.c */ int checkstack(void *top_of_stack, int core); -/* currently defined by a ldscript */ -extern unsigned char _estack[]; - /* Defined in romstage.c */ #if CONFIG_CPU_AMD_GEODE_LX void cache_as_ram_main(void); @@ -53,5 +53,8 @@ void cache_as_ram_main(void); void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx); #endif -#endif /* __ROMCC__ */ +/* Defined in src/lib/hexdump.c */ +void hexdump(const void *memory, size_t length); +void hexdump32(char LEVEL, const void *d, size_t len); + #endif /* __LIB_H__ */ diff --git a/src/include/memlayout.h b/src/include/memlayout.h new file mode 100644 index 0000000000..b8cafb4e84 --- /dev/null +++ b/src/include/memlayout.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file contains macro definitions for memlayout.ld linker scripts. */ + +#ifndef __MEMLAYOUT_H +#define __MEMLAYOUT_H + +#include + +#define STR(x) #x + +#define SET_COUNTER(name, addr) \ + _ = ASSERT(. <= addr, STR(name overlaps the previous region!)); \ + . = addr; + +#define SYMBOL(name, addr) \ + SET_COUNTER(name, addr) \ + _##name = .; + +#define REGION(name, addr, size, expected_align) \ + SYMBOL(name, addr) \ + _ = ASSERT(. == ALIGN(expected_align), \ + STR(name must be aligned to expected_align!)); \ + SYMBOL(e##name, addr + size) + +/* Declare according to SRAM/DRAM ranges in SoC hardware-defined address map. */ +#define SRAM_START(addr) SYMBOL(sram, addr) + +#define SRAM_END(addr) SYMBOL(esram, addr) + +#define DRAM_START(addr) SYMBOL(dram, addr) + +/* Coordinate asserted minimum size with timestamp.c and x86 romstage.ld! */ +#define TIMESTAMP(addr, size) \ + REGION(timestamp, addr, size, 8) \ + _ = ASSERT(size >= 0x180, "Timestamp region must fit timestamp_cache!"); + +#define PRERAM_CBMEM_CONSOLE(addr, size) \ + REGION(preram_cbmem_console, addr, size, 4) \ + _ = ASSERT(size <= CONFIG_CONSOLE_CBMEM_BUFFER_SIZE, \ + "pre-RAM CBMEM console size must not be larger than post-RAM!"); + +/* Use either CBFS_CACHE (unified) or both (PRERAM|POSTRAM)_CBFS_CACHE */ +#define CBFS_CACHE(addr, size) REGION(cbfs_cache, addr, size, 4) + +/* TODO: This only works if you never access CBFS in romstage before RAM is up! + * If you need to change that assumption, you have some work ahead of you... */ +#if defined(__PRE_RAM__) && !defined(__ROMSTAGE__) + #define PRERAM_CBFS_CACHE(addr, size) CBFS_CACHE(addr, size) + #define POSTRAM_CBFS_CACHE(addr, size) \ + REGION(unused_cbfs_cache, addr, size, 4) +#else + #define PRERAM_CBFS_CACHE(addr, size) \ + REGION(unused_cbfs_cache, addr, size, 4) + #define POSTRAM_CBFS_CACHE(addr, size) CBFS_CACHE(addr, size) +#endif + +/* Careful: 'INCLUDE ' must always be at the end of the output line */ +#ifdef __BOOTBLOCK__ + #define BOOTBLOCK(addr, sz) \ + SET_COUNTER(bootblock, addr) \ + _ = ASSERT(_ebootblock - _bootblock <= sz, \ + STR(Bootblock exceeded its allotted size! (sz))); \ + INCLUDE "lib/bootblock.bootblock.ld" +#else + #define BOOTBLOCK(addr, sz) \ + SET_COUNTER(bootblock, addr) \ + . += sz; +#endif + +#ifdef __ROMSTAGE__ + #define ROMSTAGE(addr, sz) \ + SET_COUNTER(romstage, addr) \ + _ = ASSERT(_eromstage - _romstage <= sz, \ + STR(Romstage exceeded its allotted size! (sz))); \ + INCLUDE "lib/romstage.romstage.ld" +#else + #define ROMSTAGE(addr, sz) \ + SET_COUNTER(romstage, addr) \ + . += sz; +#endif + +#ifdef __RAMSTAGE__ + #define RAMSTAGE(addr, sz) \ + SET_COUNTER(ramstage, addr) \ + _ = ASSERT(_eramstage - _ramstage <= sz, \ + STR(Ramstage exceeded its allotted size! (sz))); \ + INCLUDE "lib/ramstage.ramstage.ld" +#else + #define RAMSTAGE(addr, sz) \ + SET_COUNTER(ramstage, addr) \ + . += sz; +#endif + +#endif /* __MEMLAYOUT_H */ diff --git a/src/include/memory_info.h b/src/include/memory_info.h new file mode 100644 index 0000000000..7e65f7a891 --- /dev/null +++ b/src/include/memory_info.h @@ -0,0 +1,45 @@ +/* + * Memory information + * + * Copyright (C) 2014, Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _MEMORY_INFO_H_ +#define _MEMORY_INFO_H_ + +/* If this table is filled and put in CBMEM, */ +/* then these info in CBMEM will be used to generate smbios type 17 table */ +struct dimm_info { + uint32_t dimm_size; + uint16_t ddr_type; + uint16_t ddr_frequency; + uint8_t rank_per_dimm; + uint8_t channel_num; + uint8_t dimm_num; + uint8_t bank_locator; + /* The 5th byte is '\0' for the end of string */ + uint8_t serial[5]; + /* The 19th byte is '\0' for the end of string */ + uint8_t module_part_number[19]; + uint16_t mod_id; + uint8_t mod_type; + uint8_t bus_width; +} __attribute__((packed)); + +struct memory_info { + uint8_t dimm_cnt; + /* Maximum num of dimm is 8 */ + struct dimm_info dimm[8]; +} __attribute__((packed)); + +#endif diff --git a/src/include/memrange.h b/src/include/memrange.h index 0e69b2ffeb..7806cc6b64 100644 --- a/src/include/memrange.h +++ b/src/include/memrange.h @@ -75,6 +75,9 @@ static inline void range_entry_update_tag(struct range_entry *r, #define memranges_each_entry(r, ranges) \ for (r = (ranges)->entries; r != NULL; r = r->next) +/* Initialize memranges structure */ +void memranges_init_empty(struct memranges *ranges); + /* Initialize and fill a memranges structure according to the * mask and match type for all memory resources. Tag each entry with the * specified type. */ diff --git a/src/include/pc80/i8254.h b/src/include/pc80/i8254.h index f8e2b489ed..f4f0dcaab0 100644 --- a/src/include/pc80/i8254.h +++ b/src/include/pc80/i8254.h @@ -58,7 +58,5 @@ #define PPCB_SPKR 0x02 /* Bit 1 */ #define PPCB_T2GATE 0x01 /* Bit 0 */ -#ifndef __ROMCC__ void setup_i8254(void); #endif -#endif diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h index ee1473b71a..549368a604 100644 --- a/src/include/pc80/mc146818rtc.h +++ b/src/include/pc80/mc146818rtc.h @@ -1,6 +1,8 @@ #ifndef PC80_MC146818RTC_H #define PC80_MC146818RTC_H +#include + #ifndef RTC_BASE_PORT #define RTC_BASE_PORT 0x70 #endif @@ -89,9 +91,6 @@ #define RTC_CLK_YEAR 9 #define RTC_CLK_ALTCENTURY 0x32 -#define RTC_HAS_ALTCENTURY 1 -#define RTC_HAS_NO_ALTCENTURY 0 - /* On PCs, the checksum is built only over bytes 16..45 */ #define PC_CKS_RANGE_START 16 #define PC_CKS_RANGE_END 45 @@ -168,8 +167,8 @@ static inline void cmos_write32(u8 offset, u32 value) #endif #if !defined(__ROMCC__) -void rtc_init(int invalid); -void rtc_check_update_cmos_date(u8 has_century); +void cmos_init(int invalid); +void cmos_check_update_date(void); #if CONFIG_USE_OPTION_TABLE int set_option(const char *name, void *val); int get_option(void *dest, const char *name); @@ -197,15 +196,24 @@ static inline int get_option(void *dest __attribute__((unused)), # endif #endif +/* + * 0 = Bank Select Magic + * 1 = Bank 0 POST + * 2 = Bank 1 POST + * 3-6 = BANK 0 Extra log + * 7-10 = BANK 1 Extra log + */ #define CMOS_POST_BANK_OFFSET (CMOS_POST_OFFSET) #define CMOS_POST_BANK_0_MAGIC 0x80 #define CMOS_POST_BANK_0_OFFSET (CMOS_POST_OFFSET + 1) +#define CMOS_POST_BANK_0_EXTRA (CMOS_POST_OFFSET + 3) #define CMOS_POST_BANK_1_MAGIC 0x81 #define CMOS_POST_BANK_1_OFFSET (CMOS_POST_OFFSET + 2) +#define CMOS_POST_BANK_1_EXTRA (CMOS_POST_OFFSET + 7) + +#define CMOS_POST_EXTRA_DEV_PATH 0x01 -#if !defined(__ROMCC__) void cmos_post_log(void); -#endif #endif /* CONFIG_CMOS_POST */ #endif /* PC80_MC146818RTC_H */ diff --git a/src/include/ramstage_cache.h b/src/include/ramstage_cache.h new file mode 100644 index 0000000000..8d9b095177 --- /dev/null +++ b/src/include/ramstage_cache.h @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _RAMSTAGE_CACHE_ +#define _RAMSTAGE_CACHE_ + +#include +#include + +/* This structure is saved along with the relocated ramstage program when + * CONFIG_RELOCATED_RAMSTAGE is employed. For x86, it can used to protect + * the integrity of the ramstage program on S3 resume by saving a copy of + * the relocated ramstage in SMM space with the assumption that the SMM region + * cannot be altered from the OS. The magic value just serves as a quick sanity + * check. */ + +#define RAMSTAGE_CACHE_MAGIC 0xf3c3a02a + +struct ramstage_cache { + uint32_t magic; + uint32_t entry_point; + uint32_t load_address; + uint32_t size; + char program[0]; +} __attribute__((packed)); + +/* Chipset/Board function for obtaining cache location and size. */ +struct ramstage_cache *ramstage_cache_location(long *size); +/* Chipset/Board function called when cache is invalid on resume. */ +void ramstage_cache_invalid(struct ramstage_cache *cache); + +static inline int ramstage_cache_is_valid(const struct ramstage_cache *c) +{ + return (c != NULL && c->magic == RAMSTAGE_CACHE_MAGIC); +} + +#endif /* _RAMSTAGE_CACHE_ */ diff --git a/src/include/reg_script.h b/src/include/reg_script.h new file mode 100644 index 0000000000..0c0ea01ce5 --- /dev/null +++ b/src/include/reg_script.h @@ -0,0 +1,364 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef REG_SCRIPT_H +#define REG_SCRIPT_H + +#include +#include +#include +#include + +/* + * The reg script library is a way to provide data-driven I/O accesses for + * initializing devices. It currently supports PCI, legacy I/O, + * memory-mapped I/O, and IOSF accesses. + * + * In order to simplify things for the developer the following features + * are employed: + * - Chaining of tables that allow runtime tables to chain to compile-time + * tables. + * - Notion of current device (device_t) being worked on. This allows for + * PCI config, io, and mmio on a particular device's resources. + * + * Note that when using REG_SCRIPT_COMMAND_NEXT there is an implicit push + * and pop of the context. A chained reg_script inherits the previous + * context (such as current device), but it does not impact the previous + * context in any way. + */ + +enum { + REG_SCRIPT_COMMAND_READ, + REG_SCRIPT_COMMAND_WRITE, + REG_SCRIPT_COMMAND_RMW, + REG_SCRIPT_COMMAND_POLL, + REG_SCRIPT_COMMAND_SET_DEV, + REG_SCRIPT_COMMAND_NEXT, + REG_SCRIPT_COMMAND_END, +}; + +enum { + REG_SCRIPT_TYPE_PCI, + REG_SCRIPT_TYPE_IO, + REG_SCRIPT_TYPE_MMIO, + REG_SCRIPT_TYPE_RES, + REG_SCRIPT_TYPE_IOSF, + REG_SCRIPT_TYPE_MSR, + + /* Insert other platform independent values above this comment */ + + REG_SCRIPT_TYPE_PLATFORM_BASE = 0x10000 +}; + +enum { + REG_SCRIPT_SIZE_8, + REG_SCRIPT_SIZE_16, + REG_SCRIPT_SIZE_32, + REG_SCRIPT_SIZE_64, +}; + +struct reg_script { + uint32_t command; + uint32_t type; + uint32_t size; + uint32_t reg; + uint64_t mask; + uint64_t value; + uint32_t timeout; + union { + uint32_t id; + const struct reg_script *next; + device_t dev; + unsigned int res_index; + }; +}; + +struct reg_script_context { + device_t dev; + struct resource *res; + const struct reg_script *step; +}; + +#ifndef __PRE_RAM__ +struct reg_script_bus_entry { + int type; + uint64_t (*reg_script_read)(struct reg_script_context *ctx); + void (*reg_script_write)(struct reg_script_context *ctx); +}; + +/* Get the address and length of the platform bus table */ +const struct reg_script_bus_entry *platform_bus_table(size_t *table_entries); + +#endif /* __PRE_RAM */ + +/* Internal helper Macros. */ + +#define _REG_SCRIPT_ENCODE_RAW(cmd_, type_, size_, reg_, \ + mask_, value_, timeout_, id_) \ + { .command = cmd_, \ + .type = type_, \ + .size = size_, \ + .reg = reg_, \ + .mask = mask_, \ + .value = value_, \ + .timeout = timeout_, \ + .id = id_, \ + } + +#define _REG_SCRIPT_ENCODE_RES(cmd_, type_, res_index_, size_, reg_, \ + mask_, value_, timeout_) \ + { .command = cmd_, \ + .type = type_, \ + .size = size_, \ + .reg = reg_, \ + .mask = mask_, \ + .value = value_, \ + .timeout = timeout_, \ + .res_index = res_index_, \ + } + +/* + * PCI + */ + +#define REG_SCRIPT_PCI(cmd_, bits_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_PCI, \ + REG_SCRIPT_SIZE_##bits_, \ + reg_, mask_, value_, timeout_, 0) +#define REG_PCI_READ8(reg_) \ + REG_SCRIPT_PCI(READ, 8, reg_, 0, 0, 0) +#define REG_PCI_READ16(reg_) \ + REG_SCRIPT_PCI(READ, 16, reg_, 0, 0, 0) +#define REG_PCI_READ32(reg_) \ + REG_SCRIPT_PCI(READ, 32, reg_, 0, 0, 0) +#define REG_PCI_WRITE8(reg_, value_) \ + REG_SCRIPT_PCI(WRITE, 8, reg_, 0, value_, 0) +#define REG_PCI_WRITE16(reg_, value_) \ + REG_SCRIPT_PCI(WRITE, 16, reg_, 0, value_, 0) +#define REG_PCI_WRITE32(reg_, value_) \ + REG_SCRIPT_PCI(WRITE, 32, reg_, 0, value_, 0) +#define REG_PCI_RMW8(reg_, mask_, value_) \ + REG_SCRIPT_PCI(RMW, 8, reg_, mask_, value_, 0) +#define REG_PCI_RMW16(reg_, mask_, value_) \ + REG_SCRIPT_PCI(RMW, 16, reg_, mask_, value_, 0) +#define REG_PCI_RMW32(reg_, mask_, value_) \ + REG_SCRIPT_PCI(RMW, 32, reg_, mask_, value_, 0) +#define REG_PCI_OR8(reg_, value_) \ + REG_SCRIPT_PCI(RMW, 8, reg_, 0xff, value_, 0) +#define REG_PCI_OR16(reg_, value_) \ + REG_SCRIPT_PCI(RMW, 16, reg_, 0xffff, value_, 0) +#define REG_PCI_OR32(reg_, value_) \ + REG_SCRIPT_PCI(RMW, 32, reg_, 0xffffffff, value_, 0) +#define REG_PCI_POLL8(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_PCI(POLL, 8, reg_, mask_, value_, timeout_) +#define REG_PCI_POLL16(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_PCI(POLL, 16, reg_, mask_, value_, timeout_) +#define REG_PCI_POLL32(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_PCI(POLL, 32, reg_, mask_, value_, timeout_) + +/* + * Legacy IO + */ + +#define REG_SCRIPT_IO(cmd_, bits_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_IO, \ + REG_SCRIPT_SIZE_##bits_, \ + reg_, mask_, value_, timeout_, 0) +#define REG_IO_READ8(reg_) \ + REG_SCRIPT_IO(READ, 8, reg_, 0, 0, 0) +#define REG_IO_READ16(reg_) \ + REG_SCRIPT_IO(READ, 16, reg_, 0, 0, 0) +#define REG_IO_READ32(reg_) \ + REG_SCRIPT_IO(READ, 32, reg_, 0, 0, 0) +#define REG_IO_WRITE8(reg_, value_) \ + REG_SCRIPT_IO(WRITE, 8, reg_, 0, value_, 0) +#define REG_IO_WRITE16(reg_, value_) \ + REG_SCRIPT_IO(WRITE, 16, reg_, 0, value_, 0) +#define REG_IO_WRITE32(reg_, value_) \ + REG_SCRIPT_IO(WRITE, 32, reg_, 0, value_, 0) +#define REG_IO_RMW8(reg_, mask_, value_) \ + REG_SCRIPT_IO(RMW, 8, reg_, mask_, value_, 0) +#define REG_IO_RMW16(reg_, mask_, value_) \ + REG_SCRIPT_IO(RMW, 16, reg_, mask_, value_, 0) +#define REG_IO_RMW32(reg_, mask_, value_) \ + REG_SCRIPT_IO(RMW, 32, reg_, mask_, value_, 0) +#define REG_IO_OR8(reg_, value_) \ + REG_IO_RMW8(reg_, 0xff, value_) +#define REG_IO_OR16(reg_, value_) \ + REG_IO_RMW16(reg_, 0xffff, value_) +#define REG_IO_OR32(reg_, value_) \ + REG_IO_RMW32(reg_, 0xffffffff, value_) +#define REG_IO_POLL8(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_IO(POLL, 8, reg_, mask_, value_, timeout_) +#define REG_IO_POLL16(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_IO(POLL, 16, reg_, mask_, value_, timeout_) +#define REG_IO_POLL32(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_IO(POLL, 32, reg_, mask_, value_, timeout_) + +/* + * Memory Mapped IO + */ + +#define REG_SCRIPT_MMIO(cmd_, bits_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_MMIO, \ + REG_SCRIPT_SIZE_##bits_, \ + reg_, mask_, value_, timeout_, 0) +#define REG_MMIO_READ8(reg_) \ + REG_SCRIPT_MMIO(READ, 8, reg_, 0, 0, 0) +#define REG_MMIO_READ16(reg_) \ + REG_SCRIPT_MMIO(READ, 16, reg_, 0, 0, 0) +#define REG_MMIO_READ32(reg_) \ + REG_SCRIPT_MMIO(READ, 32, reg_, 0, 0, 0) +#define REG_MMIO_WRITE8(reg_, value_) \ + REG_SCRIPT_MMIO(WRITE, 8, reg_, 0, value_, 0) +#define REG_MMIO_WRITE16(reg_, value_) \ + REG_SCRIPT_MMIO(WRITE, 16, reg_, 0, value_, 0) +#define REG_MMIO_WRITE32(reg_, value_) \ + REG_SCRIPT_MMIO(WRITE, 32, reg_, 0, value_, 0) +#define REG_MMIO_RMW8(reg_, mask_, value_) \ + REG_SCRIPT_MMIO(RMW, 8, reg_, mask_, value_, 0) +#define REG_MMIO_RMW16(reg_, mask_, value_) \ + REG_SCRIPT_MMIO(RMW, 16, reg_, mask_, value_, 0) +#define REG_MMIO_RMW32(reg_, mask_, value_) \ + REG_SCRIPT_MMIO(RMW, 32, reg_, mask_, value_, 0) +#define REG_MMIO_OR8(reg_, value_) \ + REG_MMIO_RMW8(reg_, 0xff, value_) +#define REG_MMIO_OR16(reg_, value_) \ + REG_MMIO_RMW16(reg_, 0xffff, value_) +#define REG_MMIO_OR32(reg_, value_) \ + REG_MMIO_RMW32(reg_, 0xffffffff, value_) +#define REG_MMIO_POLL8(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_MMIO(POLL, 8, reg_, mask_, value_, timeout_) +#define REG_MMIO_POLL16(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_MMIO(POLL, 16, reg_, mask_, value_, timeout_) +#define REG_MMIO_POLL32(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_MMIO(POLL, 32, reg_, mask_, value_, timeout_) + +/* + * Access through a device's resource such as a Base Address Register (BAR) + */ + +#define REG_SCRIPT_RES(cmd_, bits_, bar_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RES(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_RES, bar_, \ + REG_SCRIPT_SIZE_##bits_, \ + reg_, mask_, value_, timeout_) +#define REG_RES_READ8(bar_, reg_) \ + REG_SCRIPT_RES(READ, 8, bar_, reg_, 0, 0, 0) +#define REG_RES_READ16(bar_, reg_) \ + REG_SCRIPT_RES(READ, 16, bar_, reg_, 0, 0, 0) +#define REG_RES_READ32(bar_, reg_) \ + REG_SCRIPT_RES(READ, 32, bar_, reg_, 0, 0, 0) +#define REG_RES_WRITE8(bar_, reg_, value_) \ + REG_SCRIPT_RES(WRITE, 8, bar_, reg_, 0, value_, 0) +#define REG_RES_WRITE16(bar_, reg_, value_) \ + REG_SCRIPT_RES(WRITE, 16, bar_, reg_, 0, value_, 0) +#define REG_RES_WRITE32(bar_, reg_, value_) \ + REG_SCRIPT_RES(WRITE, 32, bar_, reg_, 0, value_, 0) +#define REG_RES_RMW8(bar_, reg_, mask_, value_) \ + REG_SCRIPT_RES(RMW, 8, bar_, reg_, mask_, value_, 0) +#define REG_RES_RMW16(bar_, reg_, mask_, value_) \ + REG_SCRIPT_RES(RMW, 16, bar_, reg_, mask_, value_, 0) +#define REG_RES_RMW32(bar_, reg_, mask_, value_) \ + REG_SCRIPT_RES(RMW, 32, bar_, reg_, mask_, value_, 0) +#define REG_RES_OR8(bar_, reg_, value_) \ + REG_RES_RMW8(bar_, reg_, 0xff, value_) +#define REG_RES_OR16(bar_, reg_, value_) \ + REG_RES_RMW16(bar_, reg_, 0xffff, value_) +#define REG_RES_OR32(bar_, reg_, value_) \ + REG_RES_RMW32(bar_, reg_, 0xffffffff, value_) +#define REG_RES_POLL8(bar_, reg_, mask_, value_, timeout_) \ + REG_SCRIPT_RES(POLL, 8, bar_, reg_, mask_, value_, timeout_) +#define REG_RES_POLL16(bar_, reg_, mask_, value_, timeout_) \ + REG_SCRIPT_RES(POLL, 16, bar_, reg_, mask_, value_, timeout_) +#define REG_RES_POLL32(bar_, reg_, mask_, value_, timeout_) \ + REG_SCRIPT_RES(POLL, 32, bar_, reg_, mask_, value_, timeout_) + + +#if CONFIG_SOC_INTEL_BAYTRAIL +/* + * IO Sideband Function + */ + +#define REG_SCRIPT_IOSF(cmd_, unit_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_IOSF, \ + REG_SCRIPT_SIZE_32, \ + reg_, mask_, value_, timeout_, unit_) +#define REG_IOSF_READ(unit_, reg_) \ + REG_SCRIPT_IOSF(READ, unit_, reg_, 0, 0, 0) +#define REG_IOSF_WRITE(unit_, reg_, value_) \ + REG_SCRIPT_IOSF(WRITE, unit_, reg_, 0, value_, 0) +#define REG_IOSF_RMW(unit_, reg_, mask_, value_) \ + REG_SCRIPT_IOSF(RMW, unit_, reg_, mask_, value_, 0) +#define REG_IOSF_OR(unit_, reg_, value_) \ + REG_IOSF_RMW(unit_, reg_, 0xffffffff, value_) +#define REG_IOSF_POLL(unit_, reg_, mask_, value_, timeout_) \ + REG_SCRIPT_IOSF(POLL, unit_, reg_, mask_, value_, timeout_) +#endif /* CONFIG_SOC_INTEL_BAYTRAIL */ + +/* + * CPU Model Specific Register + */ + +#define REG_SCRIPT_MSR(cmd_, reg_, mask_, value_, timeout_) \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, \ + REG_SCRIPT_TYPE_MSR, \ + REG_SCRIPT_SIZE_64, \ + reg_, mask_, value_, timeout_, 0) +#define REG_MSR_READ(reg_) \ + REG_SCRIPT_MSR(READ, reg_, 0, 0, 0) +#define REG_MSR_WRITE(reg_, value_) \ + REG_SCRIPT_MSR(WRITE, reg_, 0, value_, 0) +#define REG_MSR_RMW(reg_, mask_, value_) \ + REG_SCRIPT_MSR(RMW, reg_, mask_, value_, 0) +#define REG_MSR_OR(reg_, value_) \ + REG_MSR_RMW(reg_, -1ULL, value_) +#define REG_MSR_POLL(reg_, mask_, value_, timeout_) \ + REG_SCRIPT_MSR(POLL, reg_, mask_, value_, timeout_) + +/* + * Chain to another table. + */ +#define REG_SCRIPT_NEXT(next_) \ + { .command = REG_SCRIPT_COMMAND_NEXT, \ + .next = next_, \ + } + +/* + * Set current device + */ +#define REG_SCRIPT_SET_DEV(dev_) \ + { .command = REG_SCRIPT_COMMAND_SET_DEV, \ + .dev = dev_, \ + } + +/* + * Last script entry. All tables need to end with REG_SCRIPT_END. + */ +#define REG_SCRIPT_END \ + _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_END, 0, 0, 0, 0, 0, 0, 0) + +void reg_script_run(const struct reg_script *script); +void reg_script_run_on_dev(device_t dev, const struct reg_script *step); + +#endif /* REG_SCRIPT_H */ diff --git a/src/include/reset.h b/src/include/reset.h index 79bf6d5b20..9430ffef56 100644 --- a/src/include/reset.h +++ b/src/include/reset.h @@ -1,15 +1,12 @@ #ifndef RESET_H #define RESET_H -#if !defined( __ROMCC__ ) -/* ROMCC can't do function prototypes... */ - #if CONFIG_HAVE_HARD_RESET void hard_reset(void); #else #define hard_reset() do {} while(0) #endif void soft_reset(void); +void cpu_reset(void); #endif -#endif diff --git a/src/include/rmodule-defs.h b/src/include/rmodule-defs.h new file mode 100644 index 0000000000..4139ef3d41 --- /dev/null +++ b/src/include/rmodule-defs.h @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef RMODULE_DEFS_H +#define RMODULE_DEFS_H + +#include +#include + +#define RMODULE_MAGIC 0xf8fe +#define RMODULE_VERSION_1 1 + +/* All fields with '_offset' in the name are byte offsets into the flat blob. + * The linker and the linker script takes are of assigning the values. */ +struct rmodule_header { + uint16_t magic; + uint8_t version; + uint8_t type; + /* The payload represents the program's loadable code and data. */ + uint32_t payload_begin_offset; + uint32_t payload_end_offset; + /* Begin and of relocation information about the program module. */ + uint32_t relocations_begin_offset; + uint32_t relocations_end_offset; + /* The starting address of the linked program. This address is vital + * for determining relocation offsets as the relocation info and other + * symbols (bss, entry point) need this value as a basis to calculate + * the offsets. + */ + uint32_t module_link_start_address; + /* The module_program_size is the size of memory used while running + * the program. The program is assumed to consume a contiguous amount + * of memory. */ + uint32_t module_program_size; + /* This is program's execution entry point. */ + uint32_t module_entry_point; + /* Optional parameter structure that can be used to pass data into + * the module. */ + uint32_t parameters_begin; + uint32_t parameters_end; + /* BSS section information so the loader can clear the bss. */ + uint32_t bss_begin; + uint32_t bss_end; + /* Add some room for growth. */ + uint32_t padding[4]; +} __attribute__ ((packed)); + +#endif /* RMODULE_DEFS_H */ diff --git a/src/include/rmodule.h b/src/include/rmodule.h index 35a82c159d..d229cf816a 100644 --- a/src/include/rmodule.h +++ b/src/include/rmodule.h @@ -21,9 +21,8 @@ #include #include - -#define RMODULE_MAGIC 0xf8fe -#define RMODULE_VERSION_1 1 +#include +#include enum { RMODULE_TYPE_SMM, @@ -52,70 +51,26 @@ int rmodule_load_alignment(const struct rmodule *m); int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size, size_t *region_size, int *load_offset); -#define FIELD_ENTRY(x_) ((u32)&x_) -#define RMODULE_HEADER(entry_, type_) \ -{ \ - .magic = RMODULE_MAGIC, \ - .version = RMODULE_VERSION_1, \ - .type = type_, \ - .payload_begin_offset = FIELD_ENTRY(_payload_begin_offset), \ - .payload_end_offset = FIELD_ENTRY(_payload_end_offset), \ - .relocations_begin_offset = \ - FIELD_ENTRY(_relocations_begin_offset), \ - .relocations_end_offset = \ - FIELD_ENTRY(_relocations_end_offset), \ - .module_link_start_address = \ - FIELD_ENTRY(_module_link_start_addr), \ - .module_program_size = FIELD_ENTRY(_module_program_size), \ - .module_entry_point = FIELD_ENTRY(entry_), \ - .parameters_begin = FIELD_ENTRY(_module_params_begin), \ - .parameters_end = FIELD_ENTRY(_module_params_end), \ - .bss_begin = FIELD_ENTRY(_bss), \ - .bss_end = FIELD_ENTRY(_ebss), \ -} +/* Support for loading rmodule stages. This API is only available when + * using dynamic cbmem because it uses the dynamic cbmem API to obtain + * the backing store region for the stage. */ +#if CONFIG_DYNAMIC_CBMEM +struct cbfs_stage; +struct cbmem_entry; -#define DEFINE_RMODULE_HEADER(name_, entry_, type_) \ - struct rmodule_header name_ \ - __attribute__ ((section (".module_header"))) = \ - RMODULE_HEADER(entry_, type_) +struct rmod_stage_load { + /* Inputs */ + uint32_t cbmem_id; + const char *name; + /* Outputs */ + const struct cbmem_entry *cbmem_entry; + void *entry; +}; - -/* Private data structures below should not be used directly. */ - -/* All fields with '_offset' in the name are byte offsets into the flat blob. - * The linker and the linker script takes are of assigning the values. */ -struct rmodule_header { - u16 magic; - u8 version; - u8 type; - /* The payload represents the program's loadable code and data. */ - u32 payload_begin_offset; - u32 payload_end_offset; - /* Begin and of relocation information about the program module. */ - u32 relocations_begin_offset; - u32 relocations_end_offset; - /* The starting address of the linked program. This address is vital - * for determining relocation offsets as the reloction info and other - * symbols (bss, entry point) need this value as a basis to calculate - * the offsets. - */ - u32 module_link_start_address; - /* The module_program_size is the size of memory used while running - * the program. The program is assumed to consume a contiguos amount - * of memory. */ - u32 module_program_size; - /* This is program's execution entry point. */ - u32 module_entry_point; - /* Optional paramter structure that can be used to pass data into - * the module. */ - u32 parameters_begin; - u32 parameters_end; - /* BSS section information so the loader can clear the bss. */ - u32 bss_begin; - u32 bss_end; - /* Add some room for growth. */ - u32 padding[4]; -} __attribute__ ((packed)); +/* Both of the following functions return 0 on success, -1 on error. */ +int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage); +int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl); +#endif struct rmodule { void *location; @@ -125,17 +80,12 @@ struct rmodule { void *relocations; }; -/* These are the symbols assumed that every module contains. The linker script - * provides these symbols. */ -extern char _relocations_begin_offset[]; -extern char _relocations_end_offset[]; -extern char _payload_end_offset[]; -extern char _payload_begin_offset[]; -extern char _bss[]; -extern char _ebss[]; -extern char _module_program_size[]; -extern char _module_link_start_addr[]; -extern char _module_params_begin[]; -extern char _module_params_end[]; +#if IS_ENABLED(CONFIG_RELOCATABLE_MODULES) +/* Rmodules have an entry point of named __rmodule_entry. */ +#define RMODULE_ENTRY(entry_) \ + void __rmodule_entry(void *) __attribute__((alias (STRINGIFY(entry_)))) +#else +#define RMODULE_ENTRY(entry_) +#endif #endif /* RMODULE_H */ diff --git a/src/include/romstage_handoff.h b/src/include/romstage_handoff.h index 3152fb2e9d..3d981e45c0 100644 --- a/src/include/romstage_handoff.h +++ b/src/include/romstage_handoff.h @@ -40,7 +40,7 @@ struct romstage_handoff { uint32_t ramstage_entry_point; }; -#if defined(__PRE_RAM__) +#if defined(__ROMSTAGE__) /* The romstage_handoff_find_or_add() function provides the necessary logic * for initializng the romstage_handoff structure in cbmem. Different components * of the romstage may be responsible for setting up different fields. Therefore diff --git a/src/include/rtc.h b/src/include/rtc.h new file mode 100644 index 0000000000..21094e7804 --- /dev/null +++ b/src/include/rtc.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef _RTC_H_ +#define _RTC_H_ + +struct rtc_time +{ + int sec; + int min; + int hour; + int mday; + int mon; + int year; + int wday; +}; + +/* Implemented by the RTC driver (there can be only one) */ +int rtc_set(const struct rtc_time *time); +int rtc_get(struct rtc_time *time); + +/* Common functions */ +int rtc_to_tm(int tim, struct rtc_time *tm); +unsigned long rtc_mktime(const struct rtc_time *tm); +void rtc_display(const struct rtc_time *tm); + +#endif /* _RTC_H_ */ diff --git a/src/include/smbios.h b/src/include/smbios.h index 50bce2a7c6..2b7710ff12 100644 --- a/src/include/smbios.h +++ b/src/include/smbios.h @@ -7,8 +7,16 @@ unsigned long smbios_write_tables(unsigned long start); int smbios_add_string(char *start, const char *str); int smbios_string_table_len(char *start); +/* Used by mainboard to add an on-board device */ +int smbios_write_type41(unsigned long *current, int *handle, + const char *name, u8 instance, u16 segment, + u8 bus, u8 device, u8 function); + const char *smbios_mainboard_serial_number(void); const char *smbios_mainboard_version(void); +#ifdef CONFIG_MAINBOARD_FAMILY +const char *smbios_mainboard_family(void); +#endif #define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7) #define BIOS_CHARACTERISTICS_PC_CARD (1 << 8) @@ -23,6 +31,24 @@ const char *smbios_mainboard_version(void); #define BIOS_EXT1_CHARACTERISTICS_ACPI (1 << 0) #define BIOS_EXT2_CHARACTERISTICS_TARGET (1 << 2) +typedef enum { + MEMORY_FORMFACTOR_OTHER = 0x01, + MEMORY_FORMFACTOR_UNKNOWN = 0x02, + MEMORY_FORMFACTOR_SIMM = 0x03, + MEMORY_FORMFACTOR_SIP = 0x04, + MEMORY_FORMFACTOR_CHIP = 0x05, + MEMORY_FORMFACTOR_DIP = 0x06, + MEMORY_FORMFACTOR_ZIP = 0x07, + MEMORY_FORMFACTOR_PROPRIETARY_CARD = 0x08, + MEMORY_FORMFACTOR_DIMM = 0x09, + MEMORY_FORMFACTOR_TSOP = 0x0a, + MEMORY_FORMFACTOR_ROC = 0x0b, + MEMORY_FORMFACTOR_RIMM = 0x0c, + MEMORY_FORMFACTOR_SODIMM = 0x0d, + MEMORY_FORMFACTOR_SRIMM = 0x0e, + MEMORY_FORMFACTOR_FBDIMM = 0x0f, +} smbios_memory_form_factor; + #define SMBIOS_STATE_SAFE 3 typedef enum { SMBIOS_BIOS_INFORMATION=0, diff --git a/src/include/spd.h b/src/include/spd.h index e8d35cf073..93ec00ccf1 100644 --- a/src/include/spd.h +++ b/src/include/spd.h @@ -232,4 +232,12 @@ #define RC62 62 #define RC63 63 +#define SPD_UNDEFINED 0 +#define SPD_RDIMM 1 +#define SPD_UDIMM 2 +#define SPD_SODIMM 3 +#define SPD_MICRO_DIMM 4 +#define SPD_MINI_RDIMM 5 +#define SPD_MINI_UDIMM 6 + #endif diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h index d252c32ab0..2a2cf1737f 100644 --- a/src/include/spi-generic.h +++ b/src/include/spi-generic.h @@ -28,22 +28,6 @@ /* Controller-specific definitions: */ -/* SPI mode flags */ -#define SPI_CPHA 0x01 /* clock phase */ -#define SPI_CPOL 0x02 /* clock polarity */ -#define SPI_MODE_0 (0|0) /* (original MicroWire) */ -#define SPI_MODE_1 (0|SPI_CPHA) -#define SPI_MODE_2 (SPI_CPOL|0) -#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) -#define SPI_CS_HIGH 0x04 /* CS active high */ -#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ -#define SPI_3WIRE 0x10 /* SI/SO signals shared */ -#define SPI_LOOP 0x20 /* loopback mode */ - -/* SPI transfer flags */ -#define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ -#define SPI_XFER_END 0x02 /* Deassert CS after transfer */ - /* SPI opcodes */ #define SPI_OPCODE_WREN 0x06 #define SPI_OPCODE_FAST_READ 0x0b @@ -59,11 +43,16 @@ * bus: ID of the bus that the slave is attached to. * cs: ID of the chip select connected to the slave. * rw: Read or Write flag + * max_transfer_size: maximum amount of bytes which can be sent in a single + * read or write transaction, usually this is a controller + * property, kept in the slave structure for convenience. Zero in + * this field means 'unlimited'. */ struct spi_slave { - unsigned int bus; - unsigned int cs; - unsigned int rw; + unsigned bus; + unsigned cs; + unsigned rw; + unsigned max_transfer_size; }; /*----------------------------------------------------------------------- @@ -82,14 +71,11 @@ void spi_init(void); * * bus: Bus ID of the slave chip. * cs: Chip select ID of the slave chip on the specified bus. - * max_hz: Maximum SCK rate in Hz. - * mode: Clock polarity, clock phase and other parameters. * * Returns: A spi_slave reference that can be used in subsequent SPI * calls, or NULL if one or more of the parameters are not supported. */ -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode); +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs); /*----------------------------------------------------------------------- * Claim the bus and prepare it for communication with a given slave. @@ -121,63 +107,17 @@ void spi_release_bus(struct spi_slave *slave); /*----------------------------------------------------------------------- * SPI transfer * - * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks - * "bitlen" bits in the SPI MISO port. That's just the way SPI works. - * - * The source of the outgoing bits is the "dout" parameter and the - * destination of the input bits is the "din" parameter. Note that "dout" - * and "din" can point to the same memory location, in which case the - * input data overwrites the output data (since both are buffered by - * temporary variables, this is OK). - * * spi_xfer() interface: * slave: The SPI slave which will be sending/receiving the data. - * dout: Pointer to a string of bits to send out. The bits are - * held in a byte array and are sent MSB first. - * bitsout: How many bits to write. - * din: Pointer to a string of bits that will be filled in. - * bitsin: How many bits to read. + * dout: Pointer to a string of bytes to send out. + * bytesout: How many bytes to write. + * din: Pointer to a string of bytes that will be filled in. + * bytesin: How many bytes to read. * * Returns: 0 on success, not 0 on failure */ -int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout, - void *din, unsigned int bitsin); - -/*----------------------------------------------------------------------- - * Determine if a SPI chipselect is valid. - * This function is provided by the board if the low-level SPI driver - * needs it to determine if a given chipselect is actually valid. - * - * Returns: 1 if bus:cs identifies a valid chip on this board, 0 - * otherwise. - */ -int spi_cs_is_valid(unsigned int bus, unsigned int cs); - -/*----------------------------------------------------------------------- - * Activate a SPI chipselect. - * This function is provided by the board code when using a driver - * that can't control its chipselects automatically (e.g. - * common/soft_spi.c). When called, it should activate the chip select - * to the device identified by "slave". - */ -void spi_cs_activate(struct spi_slave *slave); - -/*----------------------------------------------------------------------- - * Deactivate a SPI chipselect. - * This function is provided by the board code when using a driver - * that can't control its chipselects automatically (e.g. - * common/soft_spi.c). When called, it should deactivate the chip - * select to the device identified by "slave". - */ -void spi_cs_deactivate(struct spi_slave *slave); - -/*----------------------------------------------------------------------- - * Set transfer speed. - * This sets a new speed to be applied for next spi_xfer(). - * slave: The SPI slave - * hz: The transfer speed - */ -void spi_set_speed(struct spi_slave *slave, uint32_t hz); +int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, + void *din, unsigned int bytesin); /*----------------------------------------------------------------------- * Write 8 bits, then read 8 bits. @@ -197,7 +137,7 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) dout[0] = byte; dout[1] = 0; - ret = spi_xfer(slave, dout, 16, din, 16); + ret = spi_xfer(slave, dout, 2, din, 2); return ret < 0 ? ret : din[1]; } diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index fe48d3b757..2c92d6971a 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -66,8 +66,7 @@ struct spi_flash { size_t len); }; -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode); +struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs); static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) diff --git a/src/include/stddef.h b/src/include/stddef.h index 5b51c00635..43b287639e 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -6,7 +6,13 @@ typedef long ptrdiff_t; #define __SIZE_TYPE__ unsigned long #endif typedef __SIZE_TYPE__ size_t; -typedef long ssize_t; +/* There is a GCC macro for a size_t type, but not + * for a ssize_t type. Below construct tricks GCC + * into making __SIZE_TYPE__ signed. + */ +#define unsigned signed +typedef __SIZE_TYPE__ ssize_t; +#undef unsigned typedef int wchar_t; typedef unsigned int wint_t; @@ -20,12 +26,27 @@ typedef unsigned int wint_t; /* Could we ever run into this one? I hope we get this much memory! */ #define TiB (1<<40) +#define KHz (1000) +#define MHz (1000*KHz) +#define GHz (1000*MHz) + #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define check_member(structure, member, offset) _Static_assert( \ + offsetof(struct structure, member) == offset, \ + "`struct " #structure "` offset for `" #member "` is not " #offset ) + #ifdef __PRE_RAM__ #define ROMSTAGE_CONST const #else #define ROMSTAGE_CONST #endif +/* Work around non-writable data segment in execute-in-place romstage on x86. */ +#if defined(__PRE_RAM__) && CONFIG_ARCH_X86 +#define MAYBE_STATIC +#else +#define MAYBE_STATIC static +#endif + #endif /* STDDEF_H */ diff --git a/src/include/stdlib.h b/src/include/stdlib.h index cb5a6ca703..91d4c814bb 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -20,4 +20,12 @@ void *malloc(size_t size); static inline void free(void *ptr) {} #endif +/* not sure romcc will know how to handle this. */ +#ifndef __ROMCC__ +static inline unsigned long div_round_up(unsigned int n, unsigned int d) +{ + return (n + d - 1) / d; +} +#endif + #endif /* STDLIB_H */ diff --git a/src/include/string.h b/src/include/string.h index 44f244c733..77985e1325 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -4,6 +4,12 @@ #include #include +/* Stringify a token */ +#ifndef STRINGIFY +#define _STRINGIFY(x) #x +#define STRINGIFY(x) _STRINGIFY(x) +#endif + void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); diff --git a/src/include/symbols.h b/src/include/symbols.h new file mode 100644 index 0000000000..041f8c1d9c --- /dev/null +++ b/src/include/symbols.h @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __SYMBOLS_H +#define __SYMBOLS_H + +#include + +extern u8 _sram[]; +extern u8 _esram[]; +#define _sram_size (_esram - _sram) + +extern u8 _dram[]; + +extern u8 _timestamp[]; +extern u8 _etimestamp[]; +#define _timestamp_size (_etimestamp - _timestamp) + +extern u8 _preram_cbmem_console[]; +extern u8 _epreram_cbmem_console[]; +#define _preram_cbmem_console_size \ + (_epreram_cbmem_console - _preram_cbmem_console) + +extern u8 _stack[]; +extern u8 _estack[]; +#define _stack_size (_estack - _stack) + +extern u8 _cbfs_cache[]; +extern u8 _ecbfs_cache[]; +#define _cbfs_cache_size (_ecbfs_cache - _cbfs_cache) + +extern u8 _payload[]; +extern u8 _epayload[]; +#define _payload_size (_epayload - _payload) + +/* Careful: _e and __size only defined for the current stage! */ +extern u8 _bootblock[]; +extern u8 _ebootblock[]; +#define _bootblock_size (_ebootblock - _bootblock) + +extern u8 _romstage[]; +extern u8 _eromstage[]; +#define _romstage_size (_eromstage - _romstage) + +extern u8 _ramstage[]; +extern u8 _eramstage[]; +#define _ramstage_size (_eramstage - _ramstage) + +/* "program" always refers to the current execution unit, except for x86 ROM. */ +extern u8 _program[]; +extern u8 _eprogram[]; +#define _program_size (_eprogram - _program) + +/* Arch-specific, move to if they become too many. */ + +extern u8 _ttb[]; +extern u8 _ettb[]; +#define _ttb_size (_ettb - _ttb) + +extern u8 _ttb_subtables[]; +extern u8 _ettb_subtables[]; +#define _ttb_subtables_size (_ettb_subtables - _ttb_subtables) + +extern u8 _dma_coherent[]; +extern u8 _edma_coherent[]; +#define _dma_coherent_size (_edma_coherent - _dma_coherent) + +extern u8 _framebuffer[]; +extern u8 _eframebuffer[]; +#define _framebuffer_size (_eframebuffer - _framebuffer) + +#endif /* __SYMBOLS_H */ diff --git a/src/include/thread.h b/src/include/thread.h new file mode 100644 index 0000000000..a8784ab9fd --- /dev/null +++ b/src/include/thread.h @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef THREAD_H_ +#define THREAD_H_ + +#include +#include +#include +#include +#include + +#if CONFIG_COOP_MULTITASKING && !defined(__SMM__) && !defined(__PRE_RAM__) + +struct thread { + int id; + uintptr_t stack_current; + uintptr_t stack_orig; + struct thread *next; + void (*entry)(void *); + void *entry_arg; + int can_yield; +}; + +void threads_initialize(void); +/* Get the base of the thread stacks. + * Returns pointer to CONFIG_NUM_THREADS*CONFIG_STACK_SIZE contiguous bytes + * aligned to CONFIG_STACK_SIZE, or NULL. + */ +void *arch_get_thread_stackbase(void); +/* Run func(arrg) on a new thread. Return 0 on successful start of thread, < 0 + * when thread could not be started. Note that the thread will block the + * current state in the boot state machine until it is complete. */ +int thread_run(void (*func)(void *), void *arg); +/* thread_run_until is the same as thread_run() except that it blocks state + * transitions from occuring in the (state, seq) pair of the boot state + * machine. */ +int thread_run_until(void (*func)(void *), void *arg, + boot_state_t state, boot_state_sequence_t seq); +/* Return 0 on successful yield for the given amount of time, < 0 when thread + * did not yield. */ +int thread_yield_microseconds(unsigned microsecs); + +/* Allow and prevent thread cooperation on current running thread. By default + * all threads are marked to be cooperative. That means a thread can yeild + * to another thread at a pre-determined switch point. Current there is + * only a single place where switching may occur: a call to udelay(). */ +void thread_cooperate(void); +void thread_prevent_coop(void); + +static inline void thread_init_cpu_info_non_bsp(struct cpu_info *ci) +{ + ci->thread = NULL; +} + +/* Architecture specific thread functions. */ +void asmlinkage switch_to_thread(uintptr_t new_stack, uintptr_t *saved_stack); +/* Set up the stack frame for a new thread so that a switch_to_thread() call + * will enter the thread_entry() function with arg as a parameter. The + * saved_stack field in the struct thread needs to be updated accordingly. */ +void arch_prepare_thread(struct thread *t, + void asmlinkage (*thread_entry)(void *), void *arg); +#else +static inline void threads_initialize(void) {} +static inline int thread_run(void (*func)(void *), void *arg) { return -1; } +static inline int thread_yield_microseconds(unsigned microsecs) { return -1; } +static inline void thread_cooperate(void) {} +static inline void thread_prevent_coop(void) {} +struct cpu_info; +static inline void thread_init_cpu_info_non_bsp(struct cpu_info *ci) { } +#endif + +#endif /* THREAD_H_ */ diff --git a/src/include/timer.h b/src/include/timer.h new file mode 100644 index 0000000000..e30fed782f --- /dev/null +++ b/src/include/timer.h @@ -0,0 +1,185 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef TIMER_H +#define TIMER_H + +#define USECS_PER_SEC 1000000 +#define MSECS_PER_SEC 1000 +#define USECS_PER_MSEC (USECS_PER_SEC / MSECS_PER_SEC) + +/* The time structures are defined to be a representation of the time since + * coreboot started executing one of its stages. The reason for using structures + * is to allow for changes in the future. The structures' details are exposed + * so that the compiler can allocate space on the stack and use in other + * structures. In other words, accessing any field within this structure + * outside of the core timer code is not supported. */ + +struct mono_time { + long microseconds; +}; + +/* A timeout_callback structure is used for the book keeping for scheduling + * work in the future. When a callback is called the structure can be + * re-used for scheduling as it is not being tracked by the core timer + * library any more. */ +struct timeout_callback { + void *priv; + void (*callback)(struct timeout_callback *tocb); + /* Not for public use. The timer library uses the fields below. */ + struct mono_time expiration; +}; + +/* Obtain the current monotonic time. The assumption is that the time counts + * up from the value 0 with value 0 being the point when the timer was + * initialized. Additionally, the timer is assumed to only be valid for the + * duration of the boot. + * + * Note that any implementations of timer_monotonic_get() + * need to ensure its timesource does not roll over within 10 secs. The reason + * is that the time between calls to timer_monotonic_get() may be on order + * of 10 seconds. */ +void timer_monotonic_get(struct mono_time *mt); + +/* Returns 1 if callbacks still present in the queue. 0 if no timers left. */ +int timers_run(void); + +/* Schedule a callback to be ran microseconds from time of invocation. + * 0 returned on success, < 0 on error. */ +int timer_sched_callback(struct timeout_callback *tocb, unsigned long us); + +/* Set an absolute time to a number of microseconds. */ +static inline void mono_time_set_usecs(struct mono_time *mt, long us) +{ + mt->microseconds = us; +} + +/* Set an absolute time to a number of milliseconds. */ +static inline void mono_time_set_msecs(struct mono_time *mt, long ms) +{ + mt->microseconds = ms * USECS_PER_MSEC; +} + +/* Add microseconds to an absoute time. */ +static inline void mono_time_add_usecs(struct mono_time *mt, long us) +{ + mt->microseconds += us; +} + +/* Add milliseconds to an absoute time. */ +static inline void mono_time_add_msecs(struct mono_time *mt, long ms) +{ + mono_time_add_usecs(mt, ms * USECS_PER_MSEC); +} + +/* Compare two absoluted times: Return -1, 0, or 1 if t1 is <, =, or > t2, + * respectively. */ +static inline int mono_time_cmp(const struct mono_time *t1, + const struct mono_time *t2) +{ + if (t1->microseconds == t2->microseconds) + return 0; + + if (t1->microseconds < t2->microseconds) + return -1; + + return 1; +} + +/* Return true if t1 after t2 */ +static inline int mono_time_after(const struct mono_time *t1, + const struct mono_time *t2) +{ + return mono_time_cmp(t1, t2) > 0; +} + +/* Return true if t1 before t2. */ +static inline int mono_time_before(const struct mono_time *t1, + const struct mono_time *t2) +{ + return mono_time_cmp(t1, t2) < 0; +} + +/* Return time difference between t1 and t2. i.e. t2 - t1. */ +static inline long mono_time_diff_microseconds(const struct mono_time *t1, + const struct mono_time *t2) +{ + return t2->microseconds - t1->microseconds; +} + +struct stopwatch { + struct mono_time start; + struct mono_time current; + struct mono_time expires; +}; + +static inline void stopwatch_init(struct stopwatch *sw) +{ + timer_monotonic_get(&sw->start); + sw->current = sw->expires = sw->start; +} + +static inline void stopwatch_init_usecs_expire(struct stopwatch *sw, long us) +{ + stopwatch_init(sw); + mono_time_add_usecs(&sw->expires, us); +} + +static inline void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms) +{ + stopwatch_init_usecs_expire(sw, USECS_PER_MSEC * ms); +} + +/* + * Tick the stopwatch to collect the current time. + */ +static inline void stopwatch_tick(struct stopwatch *sw) +{ + timer_monotonic_get(&sw->current); +} + +/* + * Tick and check the stopwatch for expiration. Returns non-zero on exipration. + */ +static inline int stopwatch_expired(struct stopwatch *sw) +{ + stopwatch_tick(sw); + return !mono_time_before(&sw->current, &sw->expires); +} + +/* + * Return number of microseconds since starting the stopwatch. + */ +static inline long stopwatch_duration_usecs(struct stopwatch *sw) +{ + /* + * If the stopwatch hasn't been ticked (current == start) tick + * the stopwatch to gather the accumulated time. + */ + if (!mono_time_cmp(&sw->start, &sw->current)) + stopwatch_tick(sw); + + return mono_time_diff_microseconds(&sw->start, &sw->current); +} + +static inline long stopwatch_duration_msecs(struct stopwatch *sw) +{ + return stopwatch_duration_usecs(sw) / USECS_PER_MSEC; +} + +#endif /* TIMER_H */ diff --git a/src/include/timestamp.h b/src/include/timestamp.h index 9dd0d0f521..fdfe60cd07 100644 --- a/src/include/timestamp.h +++ b/src/include/timestamp.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright 2011 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,8 @@ #ifndef __TIMESTAMP_H__ #define __TIMESTAMP_H__ +#include + struct timestamp_entry { uint32_t entry_id; uint64_t entry_stamp; @@ -42,31 +44,79 @@ enum timestamp_id { TS_START_COPYRAM = 8, TS_END_COPYRAM = 9, TS_START_RAMSTAGE = 10, + TS_START_BOOTBLOCK = 11, + TS_END_BOOTBLOCK = 12, + TS_START_COPYROM = 13, + TS_END_COPYROM = 14, + TS_START_ULZMA = 15, + TS_END_ULZMA = 16, TS_DEVICE_ENUMERATE = 30, + TS_FSP_BEFORE_ENUMERATE, + TS_FSP_AFTER_ENUMERATE, TS_DEVICE_CONFIGURE = 40, TS_DEVICE_ENABLE = 50, TS_DEVICE_INITIALIZE = 60, TS_DEVICE_DONE = 70, TS_CBMEM_POST = 75, TS_WRITE_TABLES = 80, + TS_FSP_BEFORE_FINALIZE, + TS_FSP_AFTER_FINALIZE, TS_LOAD_PAYLOAD = 90, TS_ACPI_WAKE_JUMP = 98, TS_SELFBOOT_JUMP = 99, + + /* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */ + TS_START_COPYVER = 501, + TS_END_COPYVER = 502, + TS_START_TPMINIT = 503, + TS_END_TPMINIT = 504, + TS_START_VERIFY_SLOT = 505, + TS_END_VERIFY_SLOT = 506, + TS_START_HASH_BODY = 507, + TS_DONE_LOADING = 508, + TS_DONE_HASHING = 509, + TS_END_HASH_BODY = 510, + + /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */ }; #if CONFIG_COLLECT_TIMESTAMPS -#include -void timestamp_init(tsc_t base); -void timestamp_add(enum timestamp_id id, tsc_t ts_time); +/* + * Order of usage of timestamp library is: + * Call timestamp_early_init / timestamp_init to set base time before any + * timestamp_add function is called. timestamp_early_init also ensures that the + * cache is valid in _timestamp region. + * After this, timestamp_add / timestamp_add_now can be used to record + * timestamps. Sync will be automatically taken care of by cbmem_initialize + */ +/* + * Initialize the cache to a valid state and set the base time. + * This function is used before DRAM is setup so that the timestamp cache can + * be initialized in _timestamp region. + * Both, timestamp_init and timestamp_early_init reset the cbmem state to + * timestamp table reset required. Thus, whenever a timestamp_add or + * timestamp_sync is done to add new entries into the cbmem timestamp table, it + * first resets the table to 0 entries. + */ +void timestamp_early_init(uint64_t base); +/* Initialize the base time for timestamps and mark cache as valid */ +void timestamp_init(uint64_t base); +/* + * Add a new timestamp. Depending on cbmem is available or not, this timestamp + * will be stored to cbmem / timestamp cache. + */ +void timestamp_add(enum timestamp_id id, uint64_t ts_time); +/* Calls timestamp_add with current timestamp. */ void timestamp_add_now(enum timestamp_id id); -void timestamp_stash(enum timestamp_id id); -void timestamp_sync(void); +/* Implemented by the architecture code */ +uint64_t timestamp_get(void); #else -#define timestamp_init(base) -#define timestamp_add(id, time) -#define timestamp_add_now(id) -#define timestamp_stash(id) -#define timestamp_sync() +static inline void timestamp_early_init(uint64_t base) { } +static inline void timestamp_init(uint64_t base) { } +static inline void timestamp_add(enum timestamp_id id, uint64_t ts_time) { } +static inline void timestamp_add_now(enum timestamp_id id) { } +static inline void timestamp_sync(void) { } +static inline uint64_t timestamp_get(void) { return 0; } #endif #endif diff --git a/src/include/tpm.h b/src/include/tpm.h new file mode 100644 index 0000000000..e25ad6ab26 --- /dev/null +++ b/src/include/tpm.h @@ -0,0 +1,69 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TPM_H_ +#define TPM_H_ + +#include +#include + +/* + * tis_init() + * + * Initialize the TPM device. Returns 0 on success or -1 on + * failure (in case device probing did not succeed). + */ +int tis_init(void); + +/* + * tis_open() + * + * Requests access to locality 0 for the caller. After all commands have been + * completed the caller is supposed to call tis_close(). + * + * Returns 0 on success, -1 on failure. + */ +int tis_open(void); + +/* + * tis_close() + * + * terminate the currect session with the TPM by releasing the locked + * locality. Returns 0 on success of -1 on failure (in case lock + * removal did not succeed). + */ +int tis_close(void); + +/* + * tis_sendrecv() + * + * Send the requested data to the TPM and then try to get its response + * + * @sendbuf - buffer of the data to send + * @send_size size of the data to send + * @recvbuf - memory to save the response to + * @recv_len - pointer to the size of the response buffer + * + * Returns 0 on success (and places the number of response bytes at recv_len) + * or -1 on failure. + */ +int tis_sendrecv(const u8 *sendbuf, size_t send_size, u8 *recvbuf, + size_t *recv_len); + +#endif /* TPM_H_ */ diff --git a/src/include/tpm_lite/tlcl.h b/src/include/tpm_lite/tlcl.h new file mode 100644 index 0000000000..77245922c9 --- /dev/null +++ b/src/include/tpm_lite/tlcl.h @@ -0,0 +1,137 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * TPM Lightweight Command Library. + * + * A low-level library for interfacing to TPM hardware or an emulator. + */ + +#ifndef TPM_LITE_TLCL_H_ +#define TPM_LITE_TLCL_H_ +#include + +#include "tss_constants.h" + +/*****************************************************************************/ +/* Functions implemented in tlcl.c */ + +/** + * Call this first. Returns 0 if success, nonzero if error. + */ +uint32_t tlcl_lib_init(void); + +/** + * Perform a raw TPM request/response transaction. + */ +uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, + int max_length); + +/* Commands */ + +/** + * Send a TPM_Startup(ST_CLEAR). The TPM error code is returned (0 for + * success). + */ +uint32_t tlcl_startup(void); + +/** + * Resume by sending a TPM_Startup(ST_STATE). The TPM error code is returned + * (0 for success). + */ +uint32_t tlcl_resume(void); + +/** + * Run the self test. + * + * Note---this is synchronous. To run this in parallel with other firmware, + * use ContinueSelfTest(). The TPM error code is returned. + */ +uint32_t tlcl_self_test_full(void); + +/** + * Run the self test in the background. + */ +uint32_t tlcl_continue_self_test(void); + +/** + * Define a space with permission [perm]. [index] is the index for the space, + * [size] the usable data size. The TPM error code is returned. + */ +uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size); + +/** + * Write [length] bytes of [data] to space at [index]. The TPM error code is + * returned. + */ +uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length); + +/** + * Read [length] bytes from space at [index] into [data]. The TPM error code + * is returned. + */ +uint32_t tlcl_read(uint32_t index, void *data, uint32_t length); + +/** + * Assert physical presence in software. The TPM error code is returned. + */ +uint32_t tlcl_assert_physical_presence(void); + +/** + * Enable the physical presence command. The TPM error code is returned. + */ +uint32_t tlcl_physical_presence_cmd_enable(void); + +/** + * Finalize the physical presence settings: sofware PP is enabled, hardware PP + * is disabled, and the lifetime lock is set. The TPM error code is returned. + */ +uint32_t tlcl_finalize_physical_presence(void); + +/** + * Set the nvLocked bit. The TPM error code is returned. + */ +uint32_t tlcl_set_nv_locked(void); + +/** + * Issue a ForceClear. The TPM error code is returned. + */ +uint32_t tlcl_force_clear(void); + +/** + * Issue a PhysicalEnable. The TPM error code is returned. + */ +uint32_t tlcl_set_enable(void); + +/** + * Issue a SetDeactivated. Pass 0 to activate. Returns result code. + */ +uint32_t tlcl_set_deactivated(uint8_t flag); + +/** + * Get flags of interest. Pointers for flags you aren't interested in may + * be NULL. The TPM error code is returned. + */ +uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked); + +/** + * Set the bGlobalLock flag, which only a reboot can clear. The TPM error + * code is returned. + */ +uint32_t tlcl_set_global_lock(void); + +/** + * Perform a TPM_Extend. + */ +uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, + uint8_t *out_digest); + +/** + * Get the entire set of permanent flags. + */ +uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); + +#endif /* TPM_LITE_TLCL_H_ */ diff --git a/src/include/tpm_lite/tss_constants.h b/src/include/tpm_lite/tss_constants.h new file mode 100644 index 0000000000..883a5ad85e --- /dev/null +++ b/src/include/tpm_lite/tss_constants.h @@ -0,0 +1,96 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Some TPM constants and type definitions for standalone compilation for use + * in the firmware + */ +#ifndef VBOOT_REFERENCE_TSS_CONSTANTS_H_ +#define VBOOT_REFERENCE_TSS_CONSTANTS_H_ +#include + +#define TPM_MAX_COMMAND_SIZE 4096 +#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ +#define TPM_PUBEK_SIZE 256 +#define TPM_PCR_DIGEST 20 + +#define TPM_E_NON_FATAL 0x800 + +#define TPM_SUCCESS ((uint32_t)0x00000000) + +#define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) +#define TPM_E_BADINDEX ((uint32_t)0x00000002) +#define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) +#define TPM_E_IOERROR ((uint32_t)0x0000001f) +#define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) +#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) +#define TPM_E_OWNER_SET ((uint32_t)0x00000014) + +#define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) +#define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) + +#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ +#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ +#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ +#define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ +#define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ +#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ +#define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ +#define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ +#define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ +#define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ +#define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ + +#define TPM_NV_INDEX0 ((uint32_t)0x00000000) +#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) +#define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) +#define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) +#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) +#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) + +#define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) +#define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) +#define TPM_TAG_RQU_AUTH2_COMMAND ((uint16_t) 0xc3) + +#define TPM_TAG_RSP_COMMAND ((uint16_t) 0xc4) +#define TPM_TAG_RSP_AUTH1_COMMAND ((uint16_t) 0xc5) +#define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6) + +typedef uint8_t TSS_BOOL; +typedef uint16_t TPM_STRUCTURE_TAG; + +typedef struct tdTPM_PERMANENT_FLAGS +{ + TPM_STRUCTURE_TAG tag; + TSS_BOOL disable; + TSS_BOOL ownership; + TSS_BOOL deactivated; + TSS_BOOL readPubek; + TSS_BOOL disableOwnerClear; + TSS_BOOL allowMaintenance; + TSS_BOOL physicalPresenceLifetimeLock; + TSS_BOOL physicalPresenceHWEnable; + TSS_BOOL physicalPresenceCMDEnable; + TSS_BOOL CEKPUsed; + TSS_BOOL TPMpost; + TSS_BOOL TPMpostLock; + TSS_BOOL FIPS; + TSS_BOOL Operator; + TSS_BOOL enableRevokeEK; + TSS_BOOL nvLocked; + TSS_BOOL readSRKPub; + TSS_BOOL tpmEstablished; + TSS_BOOL maintenanceDone; + TSS_BOOL disableFullDALogicInfo; +} TPM_PERMANENT_FLAGS; + +typedef struct tdTPM_STCLEAR_FLAGS{ + TPM_STRUCTURE_TAG tag; + TSS_BOOL deactivated; + TSS_BOOL disableForceClear; + TSS_BOOL physicalPresence; + TSS_BOOL physicalPresenceLock; + TSS_BOOL bGlobalLock; +} TPM_STCLEAR_FLAGS; + +#endif /* VBOOT_REFERENCE_TSS_CONSTANTS_H_ */ diff --git a/src/include/uart.h b/src/include/uart.h index 6b8d8e844c..b1747e6481 100644 --- a/src/include/uart.h +++ b/src/include/uart.h @@ -26,15 +26,18 @@ #ifndef UART_H #define UART_H +#include + #if CONFIG_CONSOLE_SERIAL8250 || CONFIG_CONSOLE_SERIAL8250MEM #include #endif -#if !defined(__ROMCC__) && CONFIG_CONSOLE_SERIAL_UART +#if CONFIG_CONSOLE_SERIAL_UART unsigned char uart_rx_byte(void); void uart_tx_byte(unsigned char data); void uart_tx_flush(void); void uart_init(void); +int uart_can_rx_byte(void); #endif #if CONFIG_HAVE_UART_MEMORY_MAPPED diff --git a/src/include/uart8250.h b/src/include/uart8250.h index d1164c586c..4b42ef3df2 100644 --- a/src/include/uart8250.h +++ b/src/include/uart8250.h @@ -17,104 +17,103 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef UART8250_H -#define UART8250_H - -#if CONFIG_CONSOLE_SERIAL8250 || CONFIG_CONSOLE_SERIAL8250MEM +#ifndef __UART8250_H__ +#define __UART8250_H__ /* Data */ -#define UART_RBR 0x00 -#define UART_TBR 0x00 +#define UART8250_RBR 0x00 +#define UART8250_TBR 0x00 /* Control */ -#define UART_IER 0x01 -#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ -#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ -#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ -#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ +#define UART8250_IER 0x01 +#define UART8250_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART8250_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART8250_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART8250_IER_RDI 0x01 /* Enable receiver data interrupt */ -#define UART_IIR 0x02 -#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ -#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ +#define UART8250_IIR 0x02 +#define UART8250_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART8250_IIR_ID 0x06 /* Mask for the interrupt ID */ -#define UART_IIR_MSI 0x00 /* Modem status interrupt */ -#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ -#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ -#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ +#define UART8250_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART8250_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART8250_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART8250_IIR_RLSI 0x06 /* Receiver line status interrupt */ -#define UART_FCR 0x02 -#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */ -#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ -#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ -#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ -#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ -#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ -#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ -#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ -#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ +#define UART8250_FCR 0x02 +#define UART8250_FCR_FIFO_EN 0x01 /* Fifo enable */ +#define UART8250_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define UART8250_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ +#define UART8250_FCR_DMA_SELECT 0x08 /* For DMA applications */ +#define UART8250_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ +#define UART8250_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ +#define UART8250_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ +#define UART8250_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ +#define UART8250_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ -#define UART_FCR_RXSR 0x02 /* Receiver soft reset */ -#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */ +#define UART8250_FCR_RXSR 0x02 /* Receiver soft reset */ +#define UART8250_FCR_TXSR 0x04 /* Transmitter soft reset */ -#define UART_LCR 0x03 -#define UART_LCR_WLS_MSK 0x03 /* character length select mask */ -#define UART_LCR_WLS_5 0x00 /* 5 bit character length */ -#define UART_LCR_WLS_6 0x01 /* 6 bit character length */ -#define UART_LCR_WLS_7 0x02 /* 7 bit character length */ -#define UART_LCR_WLS_8 0x03 /* 8 bit character length */ -#define UART_LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ -#define UART_LCR_PEN 0x08 /* Parity eneble */ -#define UART_LCR_EPS 0x10 /* Even Parity Select */ -#define UART_LCR_STKP 0x20 /* Stick Parity */ -#define UART_LCR_SBRK 0x40 /* Set Break */ -#define UART_LCR_BKSE 0x80 /* Bank select enable */ -#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ +#define UART8250_LCR 0x03 +#define UART8250_LCR_WLS_MSK 0x03 /* character length select mask */ +#define UART8250_LCR_WLS_5 0x00 /* 5 bit character length */ +#define UART8250_LCR_WLS_6 0x01 /* 6 bit character length */ +#define UART8250_LCR_WLS_7 0x02 /* 7 bit character length */ +#define UART8250_LCR_WLS_8 0x03 /* 8 bit character length */ +#define UART8250_LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ +#define UART8250_LCR_PEN 0x08 /* Parity eneble */ +#define UART8250_LCR_EPS 0x10 /* Even Parity Select */ +#define UART8250_LCR_STKP 0x20 /* Stick Parity */ +#define UART8250_LCR_SBRK 0x40 /* Set Break */ +#define UART8250_LCR_BKSE 0x80 /* Bank select enable */ +#define UART8250_LCR_DLAB 0x80 /* Divisor latch access bit */ -#define UART_MCR 0x04 -#define UART_MCR_DTR 0x01 /* DTR */ -#define UART_MCR_RTS 0x02 /* RTS */ -#define UART_MCR_OUT1 0x04 /* Out 1 */ -#define UART_MCR_OUT2 0x08 /* Out 2 */ -#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART8250_MCR 0x04 +#define UART8250_MCR_DTR 0x01 /* DTR */ +#define UART8250_MCR_RTS 0x02 /* RTS */ +#define UART8250_MCR_OUT1 0x04 /* Out 1 */ +#define UART8250_MCR_OUT2 0x08 /* Out 2 */ +#define UART8250_MCR_LOOP 0x10 /* Enable loopback test mode */ -#define UART_MCR_DMA_EN 0x04 -#define UART_MCR_TX_DFR 0x08 +#define UART8250_MCR_DMA_EN 0x04 +#define UART8250_MCR_TX_DFR 0x08 -#define UART_DLL 0x00 -#define UART_DLM 0x01 +#define UART8250_DLL 0x00 +#define UART8250_DLM 0x01 /* Status */ -#define UART_LSR 0x05 -#define UART_LSR_DR 0x01 /* Data ready */ -#define UART_LSR_OE 0x02 /* Overrun */ -#define UART_LSR_PE 0x04 /* Parity error */ -#define UART_LSR_FE 0x08 /* Framing error */ -#define UART_LSR_BI 0x10 /* Break */ -#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ -#define UART_LSR_TEMT 0x40 /* Xmitter empty */ -#define UART_LSR_ERR 0x80 /* Error */ +#define UART8250_LSR 0x05 +#define UART8250_LSR_DR 0x01 /* Data ready */ +#define UART8250_LSR_OE 0x02 /* Overrun */ +#define UART8250_LSR_PE 0x04 /* Parity error */ +#define UART8250_LSR_FE 0x08 /* Framing error */ +#define UART8250_LSR_BI 0x10 /* Break */ +#define UART8250_LSR_THRE 0x20 /* Xmit holding register empty */ +#define UART8250_LSR_TEMT 0x40 /* Xmitter empty */ +#define UART8250_LSR_ERR 0x80 /* Error */ -#define UART_MSR 0x06 -#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ -#define UART_MSR_RI 0x40 /* Ring Indicator */ -#define UART_MSR_DSR 0x20 /* Data Set Ready */ -#define UART_MSR_CTS 0x10 /* Clear to Send */ -#define UART_MSR_DDCD 0x08 /* Delta DCD */ -#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ -#define UART_MSR_DDSR 0x02 /* Delta DSR */ -#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART8250_MSR 0x06 +#define UART8250_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART8250_MSR_RI 0x40 /* Ring Indicator */ +#define UART8250_MSR_DSR 0x20 /* Data Set Ready */ +#define UART8250_MSR_CTS 0x10 /* Clear to Send */ +#define UART8250_MSR_DDCD 0x08 /* Delta DCD */ +#define UART8250_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART8250_MSR_DDSR 0x02 /* Delta DSR */ +#define UART8250_MSR_DCTS 0x01 /* Delta CTS */ -#define UART_SCR 0x07 -#define UART_SPR 0x07 +#define UART8250_SCR 0x07 +#define UART8250_SPR 0x07 +#if CONFIG_CONSOLE_SERIAL #if ((115200 % CONFIG_TTYS0_BAUD) != 0) #error Bad ttyS0 baud rate #endif +#endif /* Line Control Settings */ -#define UART_LCS CONFIG_TTYS0_LCS +#define UART8250_LCS CONFIG_TTYS0_LCS -#ifndef __ROMCC__ #if CONFIG_CONSOLE_SERIAL8250 unsigned char uart8250_rx_byte(unsigned base_port); int uart8250_can_rx_byte(unsigned base_port); @@ -145,8 +144,4 @@ void oxford_init(void); #endif #endif -#endif /* __ROMCC__ */ - -#endif /* CONFIG_CONSOLE_SERIAL8250 || CONFIG_CONSOLE_SERIAL8250MEM */ - -#endif /* UART8250_H */ +#endif /* __UART8250_H__ */ diff --git a/src/include/usbdebug.h b/src/include/usbdebug.h index 8caf361f90..c3b34377fa 100644 --- a/src/include/usbdebug.h +++ b/src/include/usbdebug.h @@ -34,7 +34,6 @@ struct ehci_debug_info { u8 bufidx; }; -#ifndef __ROMCC__ void enable_usbdebug(unsigned int port); int dbgp_bulk_write_x(struct ehci_debug_info *dbg_info, const char *bytes, int size); int dbgp_bulk_read_x(struct ehci_debug_info *dbg_info, void *data, int size); @@ -47,4 +46,3 @@ void usbdebug_tx_byte(struct ehci_debug_info *info, unsigned char data); void usbdebug_tx_flush(struct ehci_debug_info *info); int usbdebug_init(unsigned ehci_bar, unsigned offset, struct ehci_debug_info *info); #endif -#endif diff --git a/src/device/oprom/include/vbe.h b/src/include/vbe.h similarity index 93% rename from src/device/oprom/include/vbe.h rename to src/include/vbe.h index ab26d59bf6..009dabd531 100644 --- a/src/device/oprom/include/vbe.h +++ b/src/include/vbe.h @@ -10,14 +10,17 @@ * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ +#ifndef VBE_H +#define VBE_H +#include // these structs are for input from and output to OF typedef struct { u8 display_type; // 0=NONE, 1= analog, 2=digital u16 screen_width; u16 screen_height; u16 screen_linebytes; // bytes per line in framebuffer, may be more than screen_width - u8 color_depth; // color depth in bpp + u8 color_depth; // color depth in bits per pixel u32 framebuffer_address; u8 edid_block_zero[128]; } __attribute__ ((__packed__)) screen_info_t; @@ -102,16 +105,13 @@ typedef struct { u8 edid_block_zero[128]; } vbe_ddc_info_t; -struct lb_framebuffer; - -void vbe_set_graphics(void); -// A way to check if mode information collected by vbe_set_graphics is valid -// and fill_lb_framebuffer will have real information to use. -int vbe_mode_info_valid(void); -void vbe_textmode_console(void); -void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); - #define VESA_GET_INFO 0x4f00 #define VESA_GET_MODE_INFO 0x4f01 #define VESA_SET_MODE 0x4f02 +int vbe_mode_info_valid(void); +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); +void vbe_set_graphics(void); +void vbe_textmode_console(void); + +#endif // VBE_H diff --git a/src/include/version.h b/src/include/version.h index af838b68ad..729026139d 100644 --- a/src/include/version.h +++ b/src/include/version.h @@ -15,8 +15,5 @@ extern const char coreboot_compile_time[]; extern const char coreboot_compile_by[]; extern const char coreboot_compile_host[]; extern const char coreboot_compile_domain[]; -extern const char coreboot_compiler[]; -extern const char coreboot_linker[]; -extern const char coreboot_assembler[]; #endif /* VERSION_H */ diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 9d3588ea60..1b413e41eb 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -18,29 +18,44 @@ # bootblock-y += cbfs.c -ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y) -bootblock-y += memset.c -endif +bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c +bootblock-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c bootblock-y += memchr.c -ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y) -bootblock-y += memcpy.c -endif bootblock-y += memcmp.c +bootblock-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +bootblock-$(CONFIG_GENERIC_UDELAY) += timer.c -ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y) -romstage-y += memset.c -rmodules-y += memset.c +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_CONSOLE_SERIAL8250) += uart8250.c +bootblock-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c +bootblock-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c +bootblock-$(CONFIG_CONSOLE_NE2K) += ne2k.c endif + romstage-y += memchr.c -ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y) -romstage-y += memcpy.c -rmodules-y += memcpy.c -endif romstage-y += memcmp.c -rmodules-y += memcmp.c + +$(foreach arch,$(ARCH_SUPPORTED),\ + $(eval rmodules_$(ARCH_TO_TOOLCHAIN_$(arch))-y += memcmp.c) \ + $(eval rmodules_$(ARCH_TO_TOOLCHAIN_$(arch))-y += rmodule.ld)) + +verstage-y += delay.c +verstage-y += cbfs.c +verstage-y += memcmp.c +verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c +verstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c +verstage-y += tlcl.c +verstage-$(CONFIG_GENERIC_UDELAY) += timer.c +verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c +verstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c + +romstage-y += delay.c romstage-y += cbfs.c -romstage-y += lzma.c +romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c +romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c #romstage-y += lzmadecode.c +romstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c +ramstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c romstage-$(CONFIG_CACHE_AS_RAM) += ramtest.c romstage-$(CONFIG_CONSOLE_SERIAL8250) += uart8250.c romstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c @@ -50,21 +65,16 @@ romstage-$(CONFIG_USBDEBUG) += usbdebug.c romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c romstage-$(CONFIG_EARLY_CBMEM_INIT) += cbmem.c romstage-y += compute_ip_checksum.c -romstage-y += memmove.c -romstage-$(CONFIG_ARCH_X86) += gcc.c +romstage-$(CONFIG_ARCH_ROMSTAGE_X86_32) += gcc.c +romstage-$(CONFIG_GENERIC_UDELAY) += timer.c +romstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c +ramstage-y += rtc.c ramstage-y += hardwaremain.c ramstage-y += selfboot.c ramstage-y += coreboot_table.c -ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y) -ramstage-y += memset.c -endif ramstage-y += memchr.c -ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y) -ramstage-y += memcpy.c -endif ramstage-y += memcmp.c -ramstage-y += memmove.c ramstage-y += malloc.c smm-$(CONFIG_SMM_TSEG) += malloc.c ramstage-y += delay.c @@ -72,10 +82,11 @@ ramstage-y += fallback_boot.c ramstage-y += compute_ip_checksum.c ramstage-y += version.c ramstage-y += cbfs.c +ramstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c ramstage-y += lzma.c #ramstage-y += lzmadecode.c ramstage-y += stack.c -ramstage-$(CONFIG_ARCH_X86) += gcc.c +ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += gcc.c ramstage-y += clog2.c ramstage-$(CONFIG_CONSOLE_SERIAL8250) += uart8250.c ramstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c @@ -87,6 +98,10 @@ ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c ramstage-$(CONFIG_COVERAGE) += libgcov.c ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += edid.c ramstage-y += memrange.c +ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c +ramstage-$(CONFIG_TIMER_QUEUE) += timer_queue.c +ramstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c +ramstage-$(CONFIG_GENERIC_UDELAY) += timer.c # The CBMEM implementations are chosen based on CONFIG_DYNAMIC_CBMEM. ifeq ($(CONFIG_DYNAMIC_CBMEM),y) @@ -96,48 +111,53 @@ else ramstage-y += cbmem.c romstage-$(CONFIG_HAVE_ACPI_RESUME) += cbmem.c endif # CONFIG_DYNAMIC_CBMEM -ramstage-y += cbmem_info.c +romstage-y += cbmem_common.c +ramstage-y += cbmem_common.c + +ramstage-y += hexdump.c +romstage-y += hexdump.c + +ramstage-$(CONFIG_REG_SCRIPT) += reg_script.c +romstage-$(CONFIG_REG_SCRIPT) += reg_script.c ramstage-$(CONFIG_CONSOLE_NE2K) += ne2k.c -ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y) -smm-y += memset.c -endif -ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y) -smm-y += memcpy.c +romstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += ramstage_cache.c + +ifneq ($(CONFIG_ARCH_X86),y) +# X86 bootblock and romstage use custom ldscripts that are all glued together, +# so we need to exclude it here or it would pick these up as well +bootblock-y += bootblock.ld +romstage-y += romstage.ld endif +ramstage-y += ramstage.ld + smm-y += cbfs.c memcmp.c smm-$(CONFIG_CONSOLE_SERIAL8250) += uart8250.c smm-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart8250mem.c smm-$(CONFIG_USBDEBUG) += usbdebug.c smm-y += gcc.c -$(obj)/lib/version.ramstage.o : $(obj)/build.h - -OPTION_TABLE_H:= -ifeq ($(CONFIG_HAVE_OPTION_TABLE),y) -OPTION_TABLE_H:=$(obj)/option_table.h -endif - -$(obj)/lib/uart8250mem.smm.o : $(OPTION_TABLE_H) -$(obj)/lib/uart8250.smm.o : $(OPTION_TABLE_H) - ifeq ($(CONFIG_RELOCATABLE_MODULES),y) ramstage-y += rmodule.c -romstage-$(CONFIG_RELOCATABLE_RAMSTAGE) += rmodule.c - -RMODULE_LDSCRIPT := $(src)/lib/rmodule.ld -RMODULE_LDFLAGS := -nostartfiles -shared -z defs -nostdlib -Bsymbolic -T $(RMODULE_LDSCRIPT) +# Include rmodule.c in romstage if vboot verification is selected. +romstage-$(CONFIG_VBOOT_VERIFY_FIRMWARE) += rmodule.c # rmodule_link_rules is a function that should be called with: # (1) the object name to link # (2) the dependencies # (3) heap size of the relocatable module -# It will create the necessary Make rules. +# (4) arch for which the rmodules are to be linked +# It will create the necessary Make rules to create a rmodule. The resulting +# rmdoule is named $(1).rmod define rmodule_link -$(strip $(1)): $(strip $(2)) $$(RMODULE_LDSCRIPT) $$(obj)/ldoptions - $$(LD) $$(RMODULE_LDFLAGS) --defsym=__heap_size=$(strip $(3)) -o $$@ $(strip $(2)) - $$(NM) -n $$@ > $$(basename $$@).map +$(strip $(1)): $(strip $(2)) $$(LIBGCC_FILE_NAME_rmodules_$(4)) $(obj)/lib/rmodule.rmodules_$(4).ld $$(RMODTOOL) + $$(call link,rmodules_$(4),$$(filter %.a %.o,$$(^)),-o $$(@) -T $(obj)/lib/rmodule.rmodules_$(4).ld,--emit-relocs -z defs -Bsymbolic --defsym=__heap_size=$(strip $(3))) + $$(NM_rmodules_$(4)) -n $$@ > $$(basename $$@).map + +$(strip $(1)).rmod: $(strip $(1)) + $$(RMODTOOL) -i $$^ -o $$@ + endef endif diff --git a/src/lib/bootblock.ld b/src/lib/bootblock.ld new file mode 100644 index 0000000000..a1c2e71011 --- /dev/null +++ b/src/lib/bootblock.ld @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file is included inside a SECTIONS block */ + +.bootblock . : { + _program = .; + _bootblock = .; + *(.text._start); + *(.text.stage_entry); + KEEP(*(.id)); + *(.text); + *(.text.*); + *(.rodata); + *(.rodata.*); + *(.data); + *(.data.*); + *(.bss); + *(.bss.*); + *(.sbss); + *(.sbss.*); + _ebootblock = .; + _eprogram = .; +} : to_load = 0xff + +/DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.ARM.*) +} diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index aba1bcccf0..244ecffa25 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -27,8 +27,9 @@ # define CBFS_MINI_BUILD #elif defined(__SMM__) # define CBFS_MINI_BUILD -#elif defined(__BOOT_BLOCK__) - /* No LZMA in boot block. */ +#elif defined(__PRE_RAM__) && \ + (!defined(__ROMSTAGE__) || !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE)) + /* No LZMA before romstage, and not even there without ramstage compression */ #else # define CBFS_CORE_WITH_LZMA # include @@ -54,20 +55,9 @@ # endif #endif -#if defined(CONFIG_CBFS_HEADER_ROM_OFFSET) && (CONFIG_CBFS_HEADER_ROM_OFFSET) -# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET) -#else -// Indirect address: only works on 32bit top-aligned systems. -# define CBFS_HEADER_ROM_ADDRESS (*(uint32_t *)0xfffffffc) -#endif - #include "cbfs_core.c" -#if CONFIG_VBOOT_VERIFY_FIRMWARE #include -#else -static inline void *vboot_get_payload(int *len) { return NULL; } -#endif #ifndef __SMM__ static inline int tohex4(unsigned int c) @@ -121,105 +111,26 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, return dest; } -#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__) +#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__ROMSTAGE__) #include #include -/* When CONFIG_RELOCATABLE_RAMSTAGE is enabled and this file is being compiled - * for the romstage, the rmodule loader is used. */ -void __attribute__((weak)) -cache_loaded_ramstage(struct romstage_handoff *handoff, - const struct cbmem_entry *ramstage, void *entry_point) -{ - uint32_t ramstage_size; - const struct cbmem_entry *entry; - - if (handoff == NULL) - return; - - ramstage_size = cbmem_entry_size(ramstage); - /* cbmem_entry_add() does a find() before add(). */ - entry = cbmem_entry_add(CBMEM_ID_RAMSTAGE_CACHE, ramstage_size); - - if (entry == NULL) - return; - - /* Keep track of the entry point in the handoff structure. */ - handoff->ramstage_entry_point = (uint32_t)entry_point; - - memcpy(cbmem_entry_start(entry), cbmem_entry_start(ramstage), - ramstage_size); -} - -void * __attribute__((weak)) -load_cached_ramstage(struct romstage_handoff *handoff, - const struct cbmem_entry *ramstage) -{ - const struct cbmem_entry *entry_cache; - - if (handoff == NULL) - return NULL; - - entry_cache = cbmem_entry_find(CBMEM_ID_RAMSTAGE_CACHE); - - if (entry_cache == NULL) - return NULL; - - /* Load the cached ramstage copy into the to-be-run region. */ - memcpy(cbmem_entry_start(ramstage), cbmem_entry_start(entry_cache), - cbmem_entry_size(ramstage)); - - return (void *)handoff->ramstage_entry_point; -} - static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name, struct romstage_handoff *handoff) { - struct cbfs_stage *stage; - struct rmodule ramstage; - void *entry_point; - size_t region_size; - char *ramstage_region; - int rmodule_offset; - int load_offset; - const struct cbmem_entry *ramstage_entry; + struct rmod_stage_load rmod_ram = { + .cbmem_id = CBMEM_ID_RAMSTAGE, + .name = name, + }; - stage = (struct cbfs_stage *) - cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); - - if (stage == NULL) + if (rmodule_stage_load_from_cbfs(&rmod_ram)) { + printk(BIOS_DEBUG, "Could not load ramstage.\n"); return (void *) -1; + } - rmodule_offset = - rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE, - stage->memlen, ®ion_size, &load_offset); + cache_loaded_ramstage(handoff, rmod_ram.cbmem_entry, rmod_ram.entry); - ramstage_entry = cbmem_entry_add(CBMEM_ID_RAMSTAGE, region_size); - - if (ramstage_entry == NULL) - return (void *) -1; - - ramstage_region = cbmem_entry_start(ramstage_entry); - - LOG("Decompressing stage %s @ 0x%p (%d bytes)\n", - name, &ramstage_region[rmodule_offset], stage->memlen); - - if (cbfs_decompress(stage->compression, &stage[1], - &ramstage_region[rmodule_offset], stage->len)) - return (void *) -1; - - if (rmodule_parse(&ramstage_region[rmodule_offset], &ramstage)) - return (void *) -1; - - /* The ramstage is responsible for clearing its own bss. */ - if (rmodule_load(&ramstage_region[load_offset], &ramstage)) - return (void *) -1; - - entry_point = rmodule_entry(&ramstage); - - cache_loaded_ramstage(handoff, ramstage_entry, entry_point); - - return entry_point; + return rmod_ram.entry; } void * cbfs_load_stage(struct cbfs_media *media, const char *name) @@ -252,37 +163,59 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name) #else -void * cbfs_load_stage(struct cbfs_media *media, const char *name) +void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset) { - struct cbfs_stage *stage = (struct cbfs_stage *) - cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); - /* this is a mess. There is no ntohll. */ - /* for now, assume compatible byte order until we solve this. */ - uint32_t entry; + struct cbfs_stage stage; - if (stage == NULL) - return (void *) -1; + DEBUG("reading stage header: offset=0x%x\n", offset); + if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage)) { + ERROR("ERROR: failed to read stage header\n"); + return CBFS_LOAD_ERROR; + } + + LOG("loading stage @ 0x%llx (%d bytes), entry @ 0x%llx\n", + stage.load, stage.memlen, stage.entry); - LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", - name, - (uint32_t) stage->load, stage->memlen, - stage->entry); /* Stages rely the below clearing so that the bss is initialized. */ - memset((void *) (uint32_t) stage->load, 0, stage->memlen); + memset((void *)(uintptr_t)stage.load, 0, stage.memlen); - if (cbfs_decompress(stage->compression, - ((unsigned char *) stage) + - sizeof(struct cbfs_stage), - (void *) (uint32_t) stage->load, - stage->len)) - return (void *) -1; + if (stage.compression == CBFS_COMPRESS_NONE) { + if (cbfs_read(media, (void *)(uintptr_t)stage.load, + offset + sizeof(stage), stage.len) != stage.len) { + ERROR("ERROR: Reading stage failed.\n"); + return CBFS_LOAD_ERROR; + } + } else { + void *data = media->map(media, offset + sizeof(stage), + stage.len); + if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + ERROR("ERROR: Mapping stage failed.\n"); + return CBFS_LOAD_ERROR; + } + if (cbfs_decompress(stage.compression, data, + (void *)(uintptr_t)stage.load, stage.len)) + return CBFS_LOAD_ERROR; + media->unmap(media, data); + } - DEBUG("stage loaded.\n"); + DEBUG("stage loaded\n"); - entry = stage->entry; - // entry = ntohll(stage->entry); + return (void *)(uintptr_t)stage.entry; +} - return (void *) entry; +void *cbfs_load_stage(struct cbfs_media *media, const char *name) +{ + struct cbfs_media default_media; + struct cbfs_file file; + ssize_t offset; + + init_media(&media, &default_media); + + offset = cbfs_locate_file(media, &file, name); + if (offset < 0 || file.type != CBFS_TYPE_STAGE) + return CBFS_LOAD_ERROR; + + return cbfs_load_stage_by_offset(media, offset); } #endif /* CONFIG_RELOCATABLE_RAMSTAGE */ @@ -300,11 +233,112 @@ int cbfs_execute_stage(struct cbfs_media *media, const char *name) return 1; } - /* FIXME: This isn't right */ - LOG("run @ %p\n", (void *) ntohl((uint32_t) stage->entry)); + LOG("run @ %p\n", (void *) (uintptr_t) ntohll(stage->entry)); return run_address((void *)(uintptr_t)ntohll(stage->entry)); } +/* Get all the payload headers. + * One might be tempted to implement cbfs operations as + * - get all headers into memory + * - scan the headers we got for a [payload, stage, file name] + * + * But: FLASH IO can be a very expensive operation on some systems. + * For that reason, we keep this operation separate from anything else. + * In other words, it is not intended to be a building block; in fact + * the only current use is for the payload choose (Bayou) which does need + * to scan all payloads. In future, we might decide we want to return all + * the headers, but realistically we only need this for payloads right now + * and it makes the bayou code less complex to just return payloads. + * Return a count of the payloads found, up to maxentries payloads. + */ +int cbfs_payload_headers(struct cbfs_media *media, + struct cbfs_payload_info *info, + int maxentries) +{ + int cur; + const char *file_name; + uint32_t offset, align, romsize, name_len; + const struct cbfs_header *header; + struct cbfs_file file; + struct cbfs_media default_media; + + cur = 0; + + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initialize default media.\n"); + return 0; + } + } + if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) + return 0; + + // Logical offset (for source media) of first file. + offset = ntohl(header->offset); + align = ntohl(header->align); + romsize = ntohl(header->romsize); + + // TODO Add a "size" in CBFS header for a platform independent way to + // determine the end of CBFS data. + + DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); + + media->open(media); + while (cur < maxentries && offset < romsize && + media->read(media, &file, offset, sizeof(file)) + == sizeof(file)) { + DEBUG("cur %d offset %08x\n", cur, offset); + if (memcmp(CBFS_FILE_MAGIC, file.magic, + sizeof(file.magic))) { + uint32_t new_align = align; + if (offset % align) + new_align += align - (offset % align); + ERROR("ERROR: No file header found at 0x%xx - " + "try next aligned address: 0x%x.\n", offset, + offset + new_align); + offset += new_align; + continue; + } + + // load file name (arbitrary length). + // Do it here so we can debug if we want. It's not expensive. + name_len = ntohl(file.offset) - sizeof(file); + file_name = (const char*)media->map( + media, offset + sizeof(file), name_len); + if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + DEBUG("ERROR: Failed to get filename: 0x%x.\n", offset); + continue; + } + DEBUG("Check :%s: type %x\n", file_name, ntohl(file.type)); + if (ntohl(file.type) == CBFS_TYPE_PAYLOAD){ + DEBUG(" - add entry 0x%x file name (%d bytes)...\n", + offset, name_len); + + info[cur].file = file; + info[cur].name = file_name; + /* we need the metadata too. */ + if (media->read(media, &info[cur].payload, offset, + sizeof(info[cur].payload)) != + sizeof(info[cur].payload)){ + ERROR("ERROR: Failed to get payload" + "info for %s@0x%x.\n", + file_name, offset); + continue; + } + cur++; + } + // Move to next file. + offset += ntohl(file.len) + ntohl(file.offset); + DEBUG("offset moves to %08x\n", offset); + if (offset % align) + offset += align - (offset % align); + } + media->close(media); + + return cur; +} + #if !CONFIG_ALT_CBFS_LOAD_PAYLOAD void *cbfs_load_payload(struct cbfs_media *media, const char *name) { @@ -316,6 +350,8 @@ void *cbfs_load_payload(struct cbfs_media *media, const char *name) payload = (struct cbfs_payload *)cbfs_get_file_content( media, name, CBFS_TYPE_PAYLOAD); + if (payload) + printk(BIOS_DEBUG, "Booting payload %s from cbfs\n", name); return payload; } #endif @@ -330,8 +366,11 @@ void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer, "allocated=%zd, size=%zd, last_allocate=%zd\n", offset, count, buffer->allocated, buffer->size, buffer->last_allocate); - if (buffer->allocated + count >= buffer->size) + if (buffer->allocated + count > buffer->size) { + ERROR("simple_buffer: no room to map %zd bytes from %#zx\n", + count, offset); return CBFS_MEDIA_INVALID_MAP_ADDRESS; + } if (media->read(media, address, offset, count) != count) { ERROR("simple_buffer: fail to read %zd bytes from 0x%zx\n", count, offset); diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c index 9732b829b3..c28afda263 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -34,10 +34,6 @@ * CBFS_CORE_WITH_LZMA (must be #define) * if defined, ulzma() must exist for decompression of data streams * - * CBFS_HEADER_ROM_ADDRESS - * ROM address (offset) of CBFS header. Underlying CBFS media may interpret - * it in other way so we call this "address". - * * ERROR(x...) * print an error message x (in printf format) * @@ -56,6 +52,7 @@ * on failure */ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) { + size_t offset; const struct cbfs_header *header; struct cbfs_media default_media; @@ -66,22 +63,34 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) return CBFS_HEADER_INVALID_ADDRESS; } } - media->open(media); - DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS, - CONFIG_ROM_SIZE); - header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header)); + + /* TODO: allow negative offsets from the end of the CBFS image at media + * layer (like libpayload) so we can combine these two cases. */ + if (IS_ENABLED(CONFIG_ARCH_X86)) { + offset = *(int32_t *)(uintptr_t)0xfffffffc; + header = media->map(media, offset, sizeof(*header)); + } else { + int32_t rel_offset; + if (!media->read(media, &rel_offset, CONFIG_CBFS_SIZE - + sizeof(int32_t), sizeof(int32_t))) { + ERROR("Could not read CBFS master header offset!\n"); + return CBFS_HEADER_INVALID_ADDRESS; + } + offset = CONFIG_CBFS_SIZE + rel_offset; + header = media->map(media, offset, sizeof(*header)); + } + DEBUG("CBFS header offset: 0x%zx/0x%x\n", offset, CONFIG_ROM_SIZE); media->close(media); if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("Failed to load CBFS header from 0x%x\n", - CBFS_HEADER_ROM_ADDRESS); + ERROR("Failed to load CBFS header from 0x%zx\n", offset); return CBFS_HEADER_INVALID_ADDRESS; } if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { - ERROR("Could not find valid CBFS master header at %x: " - "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC, + ERROR("Could not find valid CBFS master header at %#zx: " + "magic %#.8x vs %#.8x.\n", offset, CBFS_HEADER_MAGIC, ntohl(header->magic)); if (header->magic == 0xffffffff) { ERROR("Maybe ROM is not mapped properly?\n"); @@ -91,25 +100,33 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) return header; } + +static int init_media(struct cbfs_media **media, struct cbfs_media *backing) +{ + if (*media == CBFS_DEFAULT_MEDIA) { + *media = backing; + if (init_default_cbfs_media(*media) != 0) { + ERROR("Failed to initialize default media.\n"); + return -1; + } + } + return 0; +} + /* public API starts here*/ -struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) +ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file, + const char *name) { const char *file_name; uint32_t offset, align, romsize, name_len; const struct cbfs_header *header; - struct cbfs_file file, *file_ptr; struct cbfs_media default_media; - if (media == CBFS_DEFAULT_MEDIA) { - media = &default_media; - if (init_default_cbfs_media(media) != 0) { - ERROR("Failed to initialize default media.\n"); - return NULL; - } - } + if (init_media(&media, &default_media)) + return -1; if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) - return NULL; + return -1; // Logical offset (for source media) of first file. offset = ntohl(header->offset); @@ -119,57 +136,112 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) // TODO Add a "size" in CBFS header for a platform independent way to // determine the end of CBFS data. #if defined(CONFIG_ARCH_X86) && CONFIG_ARCH_X86 - romsize -= htonl(header->bootblocksize); -#endif - DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); + // resolve actual length of ROM used for CBFS components + // the bootblock size was not taken into account + romsize -= ntohl(header->bootblocksize); + + // fine tune the length to handle alignment positioning. + // using (bootblock size) % align, to derive the + // number of bytes the bootblock is off from the alignment size. + if ((ntohl(header->bootblocksize) % align)) + romsize -= (align - (ntohl(header->bootblocksize) % align)); + else + romsize -= 1; +#endif + + DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); + DEBUG("Looking for '%s' starting from 0x%x.\n", name, offset); - LOG("Looking for '%s' starting from 0x%x.\n", name, offset); media->open(media); while (offset < romsize && - media->read(media, &file, offset, sizeof(file)) == sizeof(file)) { - if (memcmp(CBFS_FILE_MAGIC, file.magic, - sizeof(file.magic)) != 0) { + media->read(media, file, offset, sizeof(*file)) == sizeof(*file)) { + if (memcmp(CBFS_FILE_MAGIC, file->magic, + sizeof(file->magic)) != 0) { uint32_t new_align = align; if (offset % align) new_align += align - (offset % align); - ERROR("ERROR: No file header found at 0x%x - " + LOG("WARNING: No file header found at 0x%x - " "try next aligned address: 0x%x.\n", offset, offset + new_align); offset += new_align; continue; } - name_len = ntohl(file.offset) - sizeof(file); + + file->len = ntohl(file->len); + file->type= ntohl(file->type); + file->offset = ntohl(file->offset); + + name_len = file->offset - sizeof(*file); DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset, name_len); // load file name (arbitrary length). file_name = (const char *)media->map( - media, offset + sizeof(file), name_len); + media, offset + sizeof(*file), name_len); if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) { ERROR("ERROR: Failed to get filename: 0x%x.\n", offset); } else if (strcmp(file_name, name) == 0) { - int file_offset = ntohl(file.offset), - file_len = ntohl(file.len); - LOG("Found file (offset=0x%x, len=%d).\n", - offset + file_offset, file_len); + DEBUG("Found file (offset=0x%x, len=%d).\n", + offset + file->offset, file->len); media->unmap(media, file_name); - file_ptr = media->map(media, offset, - file_offset + file_len); - media->close(media); - return file_ptr; + return offset + file->offset; } else { - LOG(" (unmatched file @0x%x: %s)\n", offset, file_name); + DEBUG(" (unmatched file @0x%x: %s)\n", offset, + file_name); media->unmap(media, file_name); } // Move to next file. - offset += ntohl(file.len) + ntohl(file.offset); + offset += file->len + file->offset; if (offset % align) offset += align - (offset % align); } media->close(media); - LOG("WARNING: Not found.\n"); - return NULL; + LOG("WARNING: '%s' not found.\n", name); + return -1; +} + +size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset, + size_t count) +{ + struct cbfs_media default_media; + size_t nread; + + if (init_media(&media, &default_media)) + return 0; + + media->open(media); + nread = media->read(media, dest, offset, count); + media->close(media); + + return nread; +} + +struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) +{ + struct cbfs_media default_media; + struct cbfs_file file, *file_ptr; + ssize_t offset; + + if (init_media(&media, &default_media)) + return NULL; + + offset = cbfs_locate_file(media, &file, name); + if (offset < 0) + return NULL; + + /* Map both the metadata and the file contents. */ + media->open(media); + offset -= file.offset; + file_ptr = media->map(media, offset, file.offset + file.len); + media->close(media); + + if (file_ptr == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + ERROR("ERROR: Mapping %s failed.\n", name); + return NULL; + } + + return file_ptr; } void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type) diff --git a/src/lib/cbfs_spi.c b/src/lib/cbfs_spi.c new file mode 100644 index 0000000000..7de0bb76ef --- /dev/null +++ b/src/lib/cbfs_spi.c @@ -0,0 +1,101 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This file provides a common CBFS wrapper for SPI storage. SPI driver + * context is expanded with the buffer descriptor used to store data read from + * SPI. + */ + +#include +#include +#include + +/* SPI flash as CBFS media. */ +struct cbfs_spi_context { + struct spi_flash *spi_flash_info; + struct cbfs_simple_buffer buffer; +}; + +static struct cbfs_spi_context spi_context; + +static int cbfs_media_open(struct cbfs_media *media) +{ + return 0; +} + +static int cbfs_media_close(struct cbfs_media *media) +{ + return 0; +} + +static size_t cbfs_media_read(struct cbfs_media *media, + void *dest, size_t offset, + size_t count) +{ + struct cbfs_spi_context *context = media->context; + + return context->spi_flash_info->read + (context->spi_flash_info, offset, count, dest) ? 0 : count; +} + +static void *cbfs_media_map(struct cbfs_media *media, + size_t offset, size_t count) +{ + struct cbfs_spi_context *context = media->context; + + return cbfs_simple_buffer_map(&context->buffer, media, offset, count); +} + +static void *cbfs_media_unmap(struct cbfs_media *media, + const void *address) +{ + struct cbfs_spi_context *context = media->context; + + return cbfs_simple_buffer_unmap(&context->buffer, address); +} + +static int init_cbfs_media_context(void) +{ + if (!spi_context.spi_flash_info) { + + spi_context.spi_flash_info = spi_flash_probe + (CONFIG_BOOT_MEDIA_SPI_BUS, 0); + + if (!spi_context.spi_flash_info) + return -1; + + spi_context.buffer.buffer = (void *)_cbfs_cache; + spi_context.buffer.size = _cbfs_cache_size; + } + return 0; + +} +int init_default_cbfs_media(struct cbfs_media *media) +{ + media->context = &spi_context; + media->open = cbfs_media_open; + media->close = cbfs_media_close; + media->read = cbfs_media_read; + media->map = cbfs_media_map; + media->unmap = cbfs_media_unmap; + + return init_cbfs_media_context(); +} + diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c index ad98082861..0759d9ed89 100644 --- a/src/lib/cbmem.c +++ b/src/lib/cbmem.c @@ -19,11 +19,14 @@ #include #include +#include #include #include +#include #if CONFIG_HAVE_ACPI_RESUME && !defined(__PRE_RAM__) #include #endif +#include // The CBMEM TOC reserves 512 bytes to keep // the other entries somewhat aligned. @@ -182,7 +185,7 @@ void *cbmem_add(u32 id, u64 size) cbmem_toc[0].base += size; cbmem_toc[0].size -= size; - return (void *)(u32)cbmem_toc[i].base; + return (void *)(uintptr_t)cbmem_toc[i].base; } void *cbmem_find(u32 id) @@ -224,26 +227,26 @@ int cbmem_initialize(void) cbmem_init(high_tables_base, high_tables_size); rv = 1; } -#ifndef __PRE_RAM__ - cbmem_arch_init(); -#endif + cbmem_run_init_hooks(); + + /* Migrate cache-as-ram variables. */ + car_migrate_variables(); + return rv; } #endif #ifndef __PRE_RAM__ -/* cbmem cannot be initialized before device drivers, but it can be initialized - * after the drivers have run. */ -void init_cbmem_pre_device(void) {} - -void init_cbmem_post_device(void) +static void init_cbmem_post_device(void *unused) { cbmem_initialize(); -#if CONFIG_CONSOLE_CBMEM - cbmemc_reinit(); -#endif } +BOOT_STATE_INIT_ENTRIES(cbmem_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_ENTRY, + init_cbmem_post_device, NULL), +}; + void cbmem_list(void) { struct cbmem_entry *cbmem_toc; @@ -261,6 +264,6 @@ void cbmem_list(void) cbmem_toc[i].size); } } -#endif +#endif /* ! __PRE_RAM__ */ diff --git a/src/lib/cbmem_info.c b/src/lib/cbmem_common.c similarity index 56% rename from src/lib/cbmem_info.c rename to src/lib/cbmem_common.c index ad8c890666..2c03aae325 100644 --- a/src/lib/cbmem_info.c +++ b/src/lib/cbmem_common.c @@ -20,33 +20,9 @@ #include #include -static struct cbmem_id_to_name { - u32 id; - const char *name; -} cbmem_ids[] = { - { CBMEM_ID_FREESPACE, "FREE SPACE " }, - { CBMEM_ID_GDT, "GDT " }, - { CBMEM_ID_ACPI, "ACPI " }, - { CBMEM_ID_CBTABLE, "COREBOOT " }, - { CBMEM_ID_PIRQ, "IRQ TABLE " }, - { CBMEM_ID_MPTABLE, "SMP TABLE " }, - { CBMEM_ID_RESUME, "ACPI RESUME" }, - { CBMEM_ID_RESUME_SCRATCH, "ACPISCRATCH" }, - { CBMEM_ID_ACPI_GNVS, "ACPI GNVS " }, - { CBMEM_ID_ACPI_GNVS_PTR, "GNVS PTR " }, - { CBMEM_ID_SMBIOS, "SMBIOS " }, - { CBMEM_ID_TIMESTAMP, "TIME STAMP " }, - { CBMEM_ID_MRCDATA, "MRC DATA " }, - { CBMEM_ID_CONSOLE, "CONSOLE " }, - { CBMEM_ID_ELOG, "ELOG " }, - { CBMEM_ID_COVERAGE, "COVERAGE " }, - { CBMEM_ID_ROMSTAGE_INFO, "ROMSTAGE " }, - { CBMEM_ID_ROMSTAGE_RAM_STACK, "ROMSTG STCK" }, - { CBMEM_ID_RAMSTAGE, "RAMSTAGE " }, - { CBMEM_ID_RAMSTAGE_CACHE, "RAMSTAGE $ " }, - { CBMEM_ID_ROOT, "CBMEM ROOT " }, - { CBMEM_ID_VBOOT_HANDOFF, "VBOOT " }, -}; +#ifndef __PRE_RAM__ /* TODO clean up ifdefs after x86 has --gc-sections */ + +static const struct cbmem_id_to_name cbmem_ids[] = { CBMEM_ID_TO_NAME_TABLE }; void cbmem_print_entry(int n, u32 id, u64 base, u64 size) { @@ -69,3 +45,17 @@ void cbmem_print_entry(int n, u32 id, u64 base, u64 size) printk(BIOS_DEBUG, "%08llx ", base); printk(BIOS_DEBUG, "%08llx\n", size); } + +#endif /* !__PRE_RAM__ */ + +extern cbmem_init_hook_t _cbmem_init_hooks; +extern cbmem_init_hook_t _ecbmem_init_hooks; + +void cbmem_run_init_hooks(void) +{ + cbmem_init_hook_t *init_hook_ptr = &_cbmem_init_hooks; + while (init_hook_ptr != &_ecbmem_init_hooks) { + (*init_hook_ptr)(); + init_hook_ptr++; + } +} diff --git a/src/lib/cbmem_console.c b/src/lib/cbmem_console.c index 2e22decd68..30cb132cab 100644 --- a/src/lib/cbmem_console.c +++ b/src/lib/cbmem_console.c @@ -19,7 +19,8 @@ #include #include -#include +#include +#include #include /* @@ -34,16 +35,15 @@ struct cbmem_console { u8 buffer_body[0]; } __attribute__ ((__packed__)); +static struct cbmem_console *cbmem_console_p CAR_GLOBAL; + #ifdef __PRE_RAM__ /* * While running from ROM, before DRAM is initialized, some area in cache as * ram space is used for the console buffer storage. The size and location of - * the area are defined in the config. + * the area are defined by the linker script with _(e)preram_cbmem_console. */ -static struct cbmem_console car_cbmem_console CAR_CBMEM; -#define cbmem_console_p (&car_cbmem_console) - /* * Once DRAM is initialized and the cache as ram mode is disabled, while still * running from ROM, the console buffer in the cache as RAM area becomes @@ -54,6 +54,7 @@ static struct cbmem_console car_cbmem_console CAR_CBMEM; * find out where the actual console log buffer is. */ #define CBMEM_CONSOLE_REDIRECT (*((struct cbmem_console **)0x600)) + #else /* @@ -62,32 +63,21 @@ static struct cbmem_console car_cbmem_console CAR_CBMEM; * to be concatenated with the CBMEM console buffer contents accumulated * during the ROM stage, once CBMEM becomes available at RAM stage. */ -static u8 static_console[40000]; -static struct cbmem_console *cbmem_console_p; -#endif -void cbmemc_init(void) -{ -#ifdef __PRE_RAM__ - cbmem_console_p->buffer_size = CONFIG_CONSOLE_CAR_BUFFER_SIZE - - sizeof(struct cbmem_console); +#if CONFIG_DYNAMIC_CBMEM +#define STATIC_CONSOLE_SIZE 1024 #else - /* - * Initializing before CBMEM is available, use static buffer to store - * the log. - */ - cbmem_console_p = (struct cbmem_console *) static_console; - cbmem_console_p->buffer_size = sizeof(static_console) - - sizeof(struct cbmem_console); +#define STATIC_CONSOLE_SIZE 40000 +#endif +static u8 static_console[STATIC_CONSOLE_SIZE]; #endif - cbmem_console_p->buffer_cursor = 0; -} -void cbmemc_tx_byte(unsigned char data) +static inline struct cbmem_console *current_console(void) { - struct cbmem_console *cbm_cons_p = cbmem_console_p; - u32 cursor; -#ifdef __PRE_RAM__ +#if CONFIG_CAR_MIGRATION || !defined(__PRE_RAM__) || \ + CONFIG_CONSOLE_FIXED_PRERAM_CBMEM_BUFFER + return car_get_var(cbmem_console_p); +#else /* * This check allows to tell if the cache as RAM mode has been exited * or not. If it has been exited, the real memory is being used @@ -95,9 +85,56 @@ void cbmemc_tx_byte(unsigned char data) * DCACHE_RAM_BASE), use the redirect pointer to find out where the * actual console buffer is. */ - if ((uintptr_t)&cursor < (uintptr_t)&car_cbmem_console) - cbm_cons_p = CBMEM_CONSOLE_REDIRECT; + if ((uintptr_t)__builtin_frame_address(0) < + (uintptr_t)CONFIG_DCACHE_RAM_BASE) + return CBMEM_CONSOLE_REDIRECT; + return car_get_var(cbmem_console_p); +#endif /* CONFIG_CAR_MIGRATION */ +} + +static inline void current_console_set(struct cbmem_console *new_console_p) +{ +#if CONFIG_CAR_MIGRATION || !defined(__PRE_RAM__) || \ + CONFIG_CONSOLE_FIXED_PRERAM_CBMEM_BUFFER + car_set_var(cbmem_console_p, new_console_p); +#else + CBMEM_CONSOLE_REDIRECT = new_console_p; #endif +} + +static inline void init_console_ptr(void *storage, u32 total_space) +{ + struct cbmem_console *cbm_cons_p = storage; + + /* Initialize the cache-as-ram pointer and underlying structure. */ + car_set_var(cbmem_console_p, cbm_cons_p); + cbm_cons_p->buffer_size = total_space - sizeof(struct cbmem_console); +#if !CONFIG_CONSOLE_FIXED_PRERAM_CBMEM_BUFFER || \ + ((defined __BOOTBLOCK__ && CONFIG_BOOTBLOCK_CONSOLE) || \ + (defined __PRE_RAM__ && !defined __BOOTBLOCK__ && \ + CONFIG_EARLY_CONSOLE && !CONFIG_BOOTBLOCK_CONSOLE)) + cbm_cons_p->buffer_cursor = 0; +#endif +} + +void cbmemc_init(void) +{ +#ifdef __PRE_RAM__ + init_console_ptr(_preram_cbmem_console, _preram_cbmem_console_size); +#else + /* + * Initializing before CBMEM is available, use static buffer to store + * the log. + */ + init_console_ptr(static_console, sizeof(static_console)); +#endif +} + +void cbmemc_tx_byte(unsigned char data) +{ + struct cbmem_console *cbm_cons_p = current_console(); + u32 cursor; + if (!cbm_cons_p) return; @@ -119,14 +156,17 @@ static void copy_console_buffer(struct cbmem_console *new_cons_p) { u32 copy_size; u32 cursor = new_cons_p->buffer_cursor; - int overflow = cbmem_console_p->buffer_cursor > - cbmem_console_p->buffer_size; + struct cbmem_console *old_cons_p; + int overflow; + + old_cons_p = current_console(); + + overflow = old_cons_p->buffer_cursor > old_cons_p->buffer_size; copy_size = overflow ? - cbmem_console_p->buffer_size : cbmem_console_p->buffer_cursor; + old_cons_p->buffer_size : old_cons_p->buffer_cursor; - memcpy(new_cons_p->buffer_body + cursor, - cbmem_console_p->buffer_body, + memcpy(new_cons_p->buffer_body + cursor, old_cons_p->buffer_body, copy_size); cursor += copy_size; @@ -134,7 +174,7 @@ static void copy_console_buffer(struct cbmem_console *new_cons_p) if (overflow) { const char loss_str1[] = "\n\n*** Log truncated, "; const char loss_str2[] = " characters dropped. ***\n\n"; - u32 dropped_chars = cbmem_console_p->buffer_cursor - copy_size; + u32 dropped_chars = old_cons_p->buffer_cursor - copy_size; /* * When running from ROM sprintf is not available, a simple @@ -173,7 +213,7 @@ void cbmemc_reinit(void) cbm_cons_p = cbmem_add(CBMEM_ID_CONSOLE, CONFIG_CONSOLE_CBMEM_BUFFER_SIZE); if (!cbm_cons_p) { - CBMEM_CONSOLE_REDIRECT = NULL; + current_console_set(NULL); return; } @@ -181,18 +221,18 @@ void cbmemc_reinit(void) sizeof(struct cbmem_console); cbm_cons_p->buffer_cursor = 0; - - copy_console_buffer(cbm_cons_p); - - CBMEM_CONSOLE_REDIRECT = cbm_cons_p; #else cbm_cons_p = cbmem_find(CBMEM_ID_CONSOLE); if (!cbm_cons_p) return; +#endif copy_console_buffer(cbm_cons_p); - cbmem_console_p = cbm_cons_p; -#endif + current_console_set(cbm_cons_p); } + +/* Call cbmemc_reinit() at cbmem_initialize() time. */ +ROMSTAGE_CBMEM_INIT_HOOK(cbmemc_reinit) +RAMSTAGE_CBMEM_INIT_HOOK(cbmemc_reinit) diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index 765c51001e..1507b15d3e 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,7 @@ static struct lb_record *lb_last_record(struct lb_header *header) return rec; } -static struct lb_record *lb_new_record(struct lb_header *header) +struct lb_record *lb_new_record(struct lb_header *header) { struct lb_record *rec; rec = lb_last_record(header); @@ -137,7 +138,8 @@ static struct lb_serial *lb_serial(struct lb_header *header) #endif } -#if CONFIG_CONSOLE_SERIAL || CONFIG_CONSOLE_LOGBUF || CONFIG_USBDEBUG +#if CONFIG_CONSOLE_SERIAL8250 || CONFIG_CONSOLE_SERIAL8250MEM || \ + CONFIG_CONSOLE_SERIAL_UART || CONFIG_USBDEBUG static void add_console(struct lb_header *header, u16 consoletype) { struct lb_console *console; @@ -157,9 +159,6 @@ static void lb_console(struct lb_header *header) #if CONFIG_CONSOLE_SERIAL8250MEM || CONFIG_CONSOLE_SERIAL_UART add_console(header, LB_TAG_CONSOLE_SERIAL8250MEM); #endif -#if CONFIG_CONSOLE_LOGBUF - add_console(header, LB_TAG_CONSOLE_LOGBUF); -#endif #if CONFIG_USBDEBUG add_console(header, LB_TAG_CONSOLE_EHCI); #endif @@ -177,9 +176,9 @@ static void lb_framebuffer(struct lb_header *header) return; struct lb_framebuffer *framebuffer; framebuffer = (struct lb_framebuffer *)lb_new_record(header); + fill_lb_framebuffer(framebuffer); framebuffer->tag = LB_TAG_FRAMEBUFFER; framebuffer->size = sizeof(*framebuffer); - fill_lb_framebuffer(framebuffer); #endif } @@ -187,6 +186,7 @@ static void lb_framebuffer(struct lb_header *header) static void lb_gpios(struct lb_header *header) { struct lb_gpios *gpios; + gpios = (struct lb_gpios *)lb_new_record(header); gpios->tag = LB_TAG_GPIO; gpios->size = sizeof(*gpios); @@ -197,49 +197,73 @@ static void lb_gpios(struct lb_header *header) static void lb_vdat(struct lb_header *header) { #if CONFIG_GENERATE_ACPI_TABLES - struct lb_vdat* vdat; + struct lb_range *vdat; - vdat = (struct lb_vdat *)lb_new_record(header); + vdat = (struct lb_range *)lb_new_record(header); vdat->tag = LB_TAG_VDAT; vdat->size = sizeof(*vdat); - acpi_get_vdat_info(&vdat->vdat_addr, &vdat->vdat_size); + acpi_get_vdat_info(&vdat->range_start, &vdat->range_size); #endif } static void lb_vbnv(struct lb_header *header) { #if CONFIG_PC80_SYSTEM - struct lb_vbnv* vbnv; + struct lb_range *vbnv; - vbnv = (struct lb_vbnv *)lb_new_record(header); + vbnv = (struct lb_range *)lb_new_record(header); vbnv->tag = LB_TAG_VBNV; vbnv->size = sizeof(*vbnv); - vbnv->vbnv_start = CONFIG_VBNV_OFFSET + 14; - vbnv->vbnv_size = CONFIG_VBNV_SIZE; + vbnv->range_start = CONFIG_VBNV_OFFSET + 14; + vbnv->range_size = CONFIG_VBNV_SIZE; #endif } -#if CONFIG_VBOOT_VERIFY_FIRMWARE static void lb_vboot_handoff(struct lb_header *header) { +#if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE void *addr; uint32_t size; - struct lb_vboot_handoff* vbho; + struct lb_range *vbho; if (vboot_get_handoff_info(&addr, &size)) return; - vbho = (struct lb_vboot_handoff *)lb_new_record(header); + vbho = (struct lb_range *)lb_new_record(header); vbho->tag = LB_TAB_VBOOT_HANDOFF; vbho->size = sizeof(*vbho); - vbho->vboot_handoff_addr = addr; - vbho->vboot_handoff_size = size; -} -#else -static inline void lb_vboot_handoff(struct lb_header *header) {} + vbho->range_start = (intptr_t)addr; + vbho->range_size = size; #endif /* CONFIG_VBOOT_VERIFY_FIRMWARE */ +} #endif /* CONFIG_CHROMEOS */ +static void lb_board_id(struct lb_header *header) +{ +#if CONFIG_BOARD_ID_SUPPORT + struct lb_board_id *bid; + + bid = (struct lb_board_id *)lb_new_record(header); + + bid->tag = LB_TAG_BOARD_ID; + bid->size = sizeof(*bid); + bid->board_id = board_id(); +#endif +} + +static void lb_ram_code(struct lb_header *header) +{ +#if CONFIG_RAM_CODE_SUPPORT + struct lb_ram_code *code; + + code = (struct lb_ram_code *)lb_new_record(header); + + code->tag = LB_TAG_RAM_CODE; + code->size = sizeof(*code); + code->ram_code = ram_code(); +#endif +} + static void lb_x86_rom_cache(struct lb_header *header) { #if CONFIG_ARCH_X86 @@ -269,7 +293,9 @@ static void add_cbmem_pointers(struct lb_header *header) int table_tag; } section_ids[] = { {CBMEM_ID_TIMESTAMP, LB_TAG_TIMESTAMPS}, - {CBMEM_ID_CONSOLE, LB_TAG_CBMEM_CONSOLE} + {CBMEM_ID_CONSOLE, LB_TAG_CBMEM_CONSOLE}, + {CBMEM_ID_ACPI_GNVS, LB_TAG_ACPI_GNVS}, + {CBMEM_ID_WIFI_CALIBRATION, LB_TAG_WIFI_CALIBRATION} }; int i; @@ -349,9 +375,6 @@ static void lb_strings(struct lb_header *header) { LB_TAG_COMPILE_BY, coreboot_compile_by, }, { LB_TAG_COMPILE_HOST, coreboot_compile_host, }, { LB_TAG_COMPILE_DOMAIN, coreboot_compile_domain, }, - { LB_TAG_COMPILER, coreboot_compiler, }, - { LB_TAG_LINKER, coreboot_linker, }, - { LB_TAG_ASSEMBLER, coreboot_assembler, }, }; unsigned int i; for(i = 0; i < ARRAY_SIZE(strings); i++) { @@ -366,6 +389,8 @@ static void lb_strings(struct lb_header *header) } +void __attribute__((weak)) lb_board(struct lb_header *header) { /* NOOP */ } + static struct lb_forward *lb_forward(struct lb_header *header, struct lb_header *next_header) { struct lb_record *rec; @@ -576,8 +601,22 @@ unsigned long write_coreboot_table( /* pass along the vboot_handoff address. */ lb_vboot_handoff(head); #endif + + /* Add board ID if available */ + lb_board_id(head); + + /* Add RAM config if available */ + lb_ram_code(head); + add_cbmem_pointers(head); + /* Add board-specific table entries, if any. */ + lb_board(head); + +#if IS_ENABLED(CONFIG_CHROMEOS_RAMOOPS) + lb_ramoops(head); +#endif + /* Remember where my valid memory ranges are */ return lb_table_fini(head); } diff --git a/src/lib/dynamic_cbmem.c b/src/lib/dynamic_cbmem.c index ae6c87ac87..081ee20b21 100644 --- a/src/lib/dynamic_cbmem.c +++ b/src/lib/dynamic_cbmem.c @@ -17,14 +17,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include #include +#include #if CONFIG_HAVE_ACPI_RESUME && !defined(__PRE_RAM__) #include #endif +#include #ifndef UINT_MAX #define UINT_MAX 4294967295U @@ -117,7 +120,7 @@ static inline void *get_root(void) if (pointer->magic != CBMEM_POINTER_MAGIC) return NULL; - return (void *)pointer->root; + return (void *)(uintptr_t)pointer->root; } static inline void cbmem_entry_assign(struct cbmem_entry *entry, @@ -180,7 +183,10 @@ void cbmem_initialize_empty(void) printk(BIOS_DEBUG, "CBMEM: root @ %p %d entries.\n", root, root->max_entries); - cbmem_arch_init(); + cbmem_run_init_hooks(); + + /* Migrate cache-as-ram variables. */ + car_migrate_variables(); } static inline int cbmem_fail_recovery(void) @@ -193,9 +199,9 @@ static inline int cbmem_fail_recovery(void) static int validate_entries(struct cbmem_root *root) { unsigned int i; - u32 current_end; + uintptr_t current_end; - current_end = (u32)get_top_aligned(); + current_end = (uintptr_t)get_top_aligned(); printk(BIOS_DEBUG, "CBMEM: recovering %d/%d entries from root @ %p\n", root->num_entries, root->max_entries, root); @@ -253,7 +259,10 @@ int cbmem_initialize(void) root->locked = 1; #endif - cbmem_arch_init(); + cbmem_run_init_hooks(); + + /* Migrate cache-as-ram variables. */ + car_migrate_variables(); /* Recovery successful. */ return 0; @@ -262,14 +271,14 @@ int cbmem_initialize(void) static void *cbmem_base(void) { struct cbmem_root *root; - u32 low_addr; + uintptr_t low_addr; root = get_root(); if (root == NULL) return NULL; - low_addr = (u32)root; + low_addr = (uintptr_t)root; /* Assume the lowest address is the last one added. */ if (root->num_entries > 0) { @@ -403,7 +412,7 @@ u64 cbmem_entry_size(const struct cbmem_entry *entry) void *cbmem_entry_start(const struct cbmem_entry *entry) { - return (void *)entry->start; + return (void *)(uintptr_t)entry->start; } @@ -411,15 +420,15 @@ void *cbmem_entry_start(const struct cbmem_entry *entry) /* selected cbmem can be initialized early in ramstage. Additionally, that * means cbmem console can be reinitialized early as well. The post_device * function is empty since cbmem was initialized early in ramstage. */ -void init_cbmem_pre_device(void) +static void init_cbmem_pre_device(void *unused) { cbmem_initialize(); -#if CONFIG_CONSOLE_CBMEM - cbmemc_reinit(); -#endif /* CONFIG_CONSOLE_CBMEM */ } -void init_cbmem_post_device(void) {} +BOOT_STATE_INIT_ENTRIES(cbmem_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, + init_cbmem_pre_device, NULL), +}; void cbmem_add_lb_mem(struct lb_memory *mem) { diff --git a/src/lib/edid.c b/src/lib/edid.c index 460d68dcb2..910a990a8d 100644 --- a/src/lib/edid.c +++ b/src/lib/edid.c @@ -36,55 +36,85 @@ #include #include #include +#include +#include -static int claims_one_point_oh = 0; -static int claims_one_point_two = 0; -static int claims_one_point_three = 0; -static int claims_one_point_four = 0; -static int nonconformant_digital_display = 0; -static int nonconformant_extension = 0; -static int did_detailed_timing = 0; -static int has_name_descriptor = 0; -static int name_descriptor_terminated = 0; -static int has_range_descriptor = 0; -static int has_preferred_timing = 0; -static int has_valid_checksum = 0; -static int has_valid_cvt = 1; -static int has_valid_dummy_block = 1; -static int has_valid_week = 0; -static int has_valid_year = 0; -static int has_valid_detailed_blocks = 0; -static int has_valid_extension_count = 0; -static int has_valid_descriptor_ordering = 1; -static int has_valid_descriptor_pad = 1; -static int has_valid_range_descriptor = 1; -static int has_valid_max_dotclock = 1; -static int has_valid_string_termination = 1; -static int manufacturer_name_well_formed = 0; -static int seen_non_detailed_descriptor = 0; +struct edid_context { + int claims_one_point_oh; + int claims_one_point_two; + int claims_one_point_three; + int claims_one_point_four; + int nonconformant_digital_display; + int nonconformant_extension; + int did_detailed_timing; + int has_name_descriptor; + int has_range_descriptor; + int has_preferred_timing; + int has_valid_checksum; + int has_valid_cvt; + int has_valid_dummy_block; + int has_valid_week; + int has_valid_year; + int has_valid_detailed_blocks; + int has_valid_extension_count; + int has_valid_descriptor_ordering; + int has_valid_descriptor_pad; + int has_valid_range_descriptor; + int has_valid_max_dotclock; + int has_valid_string_termination; + int manufacturer_name_well_formed; + int seen_non_detailed_descriptor; + int warning_excessive_dotclock_correction; + int warning_zero_preferred_refresh; + int conformant; + int max_khz; +}; -static int warning_excessive_dotclock_correction = 0; -static int warning_zero_preferred_refresh = 0; +/* Stuff that isn't used anywhere but is nice to pretty-print while + we're decoding everything else. */ +static struct { + char manuf_name[4]; + unsigned int model; + unsigned int serial; + unsigned int year; + unsigned int week; + unsigned int version[2]; + unsigned int nonconformant; + unsigned int type; -static int conformant = 1; + unsigned int x_mm; + unsigned int y_mm; -static char *manufacturer_name(struct edid *out, unsigned char *x) + unsigned int voltage; + unsigned int sync; + + const char *syncmethod; + const char *range_class; + const char *stereo; +} extra_info; + +static struct edid tmp_edid; + +static int vbe_valid; +static struct lb_framebuffer edid_fb; + +static char *manufacturer_name(unsigned char *x) { - out->manuf_name[0] = ((x[0] & 0x7C) >> 2) + '@'; - out->manuf_name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@'; - out->manuf_name[2] = (x[1] & 0x1F) + '@'; - out->manuf_name[3] = 0; + extra_info.manuf_name[0] = ((x[0] & 0x7C) >> 2) + '@'; + extra_info.manuf_name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@'; + extra_info.manuf_name[2] = (x[1] & 0x1F) + '@'; + extra_info.manuf_name[3] = 0; - if (isupper(out->manuf_name[0]) && - isupper(out->manuf_name[1]) && - isupper(out->manuf_name[2])) - manufacturer_name_well_formed = 1; + if (isupper(extra_info.manuf_name[0]) && + isupper(extra_info.manuf_name[1]) && + isupper(extra_info.manuf_name[2])) + return extra_info.manuf_name; - return out->manuf_name; + return NULL; } static int -detailed_cvt_descriptor(struct edid *out, unsigned char *x, int first) +detailed_cvt_descriptor(unsigned char *x, int first) { const unsigned char empty[3] = { 0, 0, 0 }; const char *names[] = { "50", "60", "75", "85" }; @@ -141,18 +171,9 @@ detailed_cvt_descriptor(struct edid *out, unsigned char *x, int first) return valid; } -static int isalnum(char x) -{ - if (x >= 'a' && x <= 'z') - return 1; - if (x >= 'A' && x <= 'Z') - return 1; - if (x >= '0' && x <= '9') - return 1; - return 0; - -} -/* extract a string from a detailed subblock, checking for termination */ +/* extract a CP437 string from a detailed subblock, checking for termination (if + * less than len of bytes) with LF and padded with SP. + */ static char * extract_string(unsigned char *x, int *valid_termination, int len) { @@ -162,20 +183,16 @@ extract_string(unsigned char *x, int *valid_termination, int len) memset(ret, 0, sizeof(ret)); for (i = 0; i < len; i++) { - if (isalnum(x[i])) { - ret[i] = x[i]; - } else if (!seen_newline) { - if (x[i] == 0x0a) { - seen_newline = 1; - } else { - *valid_termination = 0; - return ret; - } - } else { + if (seen_newline) { if (x[i] != 0x20) { *valid_termination = 0; return ret; } + } else if (x[i] == 0x0a) { + seen_newline = 1; + } else { + /* normal characters */ + ret[i] = x[i]; } } @@ -184,9 +201,10 @@ extract_string(unsigned char *x, int *valid_termination, int len) /* 1 means valid data */ static int -detailed_block(struct edid *out, unsigned char *x, int in_extension) +detailed_block(struct edid *result_edid, unsigned char *x, int in_extension, + struct edid_context *c) { - static unsigned char name[53]; + struct edid *out = &tmp_edid; int i; #if 1 printk(BIOS_SPEW, "Hex of detail: "); @@ -195,22 +213,25 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) printk(BIOS_SPEW, "\n"); #endif + /* Result might already have some valid fields like mode_is_supported */ + *out = *result_edid; + if (x[0] == 0 && x[1] == 0) { /* Monitor descriptor block, not detailed timing descriptor. */ if (x[2] != 0) { /* 1.3, 3.10.3 */ printk(BIOS_SPEW, "Monitor descriptor block has byte 2 nonzero (0x%02x)\n", x[2]); - has_valid_descriptor_pad = 0; + c->has_valid_descriptor_pad = 0; } if (x[3] != 0xfd && x[4] != 0x00) { /* 1.3, 3.10.3 */ printk(BIOS_SPEW, "Monitor descriptor block has byte 4 nonzero (0x%02x)\n", x[4]); - has_valid_descriptor_pad = 0; + c->has_valid_descriptor_pad = 0; } - seen_non_detailed_descriptor = 1; + c->seen_non_detailed_descriptor = 1; if (x[3] <= 0xF) { /* * in principle we can decode these, if we know what they are. @@ -218,73 +239,62 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) * 0x0e is used by EPI: http://www.epi-standard.org/ */ printk(BIOS_SPEW, "Manufacturer-specified data, tag %d\n", x[3]); - return 0; + return 1; } switch (x[3]) { case 0x10: printk(BIOS_SPEW, "Dummy block\n"); for (i = 5; i < 18; i++) if (x[i] != 0x00) - has_valid_dummy_block = 0; - return 0; + c->has_valid_dummy_block = 0; + return 1; case 0xF7: /* TODO */ printk(BIOS_SPEW, "Established timings III\n"); - return 0; + return 1; case 0xF8: { int valid_cvt = 1; /* just this block */ printk(BIOS_SPEW, "CVT 3-byte code descriptor:\n"); if (x[5] != 0x01) { - has_valid_cvt = 0; + c->has_valid_cvt = 0; return 0; } for (i = 0; i < 4; i++) - valid_cvt &= detailed_cvt_descriptor(out, x + 6 + (i * 3), (i == 0)); - has_valid_cvt &= valid_cvt; - return 0; + valid_cvt &= detailed_cvt_descriptor(x + 6 + (i * 3), (i == 0)); + c->has_valid_cvt &= valid_cvt; + return 1; } case 0xF9: /* TODO */ printk(BIOS_SPEW, "Color management data\n"); - return 0; + return 1; case 0xFA: /* TODO */ printk(BIOS_SPEW, "More standard timings\n"); - return 0; + return 1; case 0xFB: /* TODO */ printk(BIOS_SPEW, "Color point\n"); - return 0; + return 1; case 0xFC: - /* XXX should check for spaces after the \n */ - /* XXX check: terminated with 0x0A, padded with 0x20 */ - has_name_descriptor = 1; - if (strchr((char *)name, '\n')) return 0; - /* avoid strncat - strncat((char *)name, (char *)x + 5, 13); - */ - if (strchr((char *)name, '\n') || strchr((char *)x+5, '\n')) { - name_descriptor_terminated = 1; - /* later. - printk(BIOS_SPEW, "Monitor name: %s\n", - extract_string(name, &has_valid_string_termination, - strlen((char *)name))); - */ - } - return 0; + printk(BIOS_SPEW, "Monitor name: %s\n", + extract_string(x + 5, + &c->has_valid_string_termination, + 13)); + return 1; case 0xFD: { int h_max_offset = 0, h_min_offset = 0; int v_max_offset = 0, v_min_offset = 0; int is_cvt = 0; - has_range_descriptor = 1; - out->range_class = ""; + c->has_range_descriptor = 1; + extra_info.range_class = ""; /* * XXX todo: implement feature flags, vtd blocks * XXX check: ranges are well-formed; block termination if no vtd */ - if (claims_one_point_four) { + if (c->claims_one_point_four) { if (x[4] & 0x02) { v_max_offset = 255; if (x[4] & 0x01) { @@ -298,7 +308,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) } } } else if (x[4]) { - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; } /* @@ -306,41 +316,41 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) */ switch (x[10]) { case 0x00: /* default gtf */ - out->range_class = "GTF"; + extra_info.range_class = "GTF"; break; case 0x01: /* range limits only */ - out->range_class = "bare limits"; - if (!claims_one_point_four) - has_valid_range_descriptor = 0; + extra_info.range_class = "bare limits"; + if (!c->claims_one_point_four) + c->has_valid_range_descriptor = 0; break; case 0x02: /* secondary gtf curve */ - out->range_class = "GTF with icing"; + extra_info.range_class = "GTF with icing"; break; case 0x04: /* cvt */ - out->range_class = "CVT"; + extra_info.range_class = "CVT"; is_cvt = 1; - if (!claims_one_point_four) - has_valid_range_descriptor = 0; + if (!c->claims_one_point_four) + c->has_valid_range_descriptor = 0; break; default: /* invalid */ - has_valid_range_descriptor = 0; - out->range_class = "invalid"; + c->has_valid_range_descriptor = 0; + extra_info.range_class = "invalid"; break; } if (x[5] + v_min_offset > x[6] + v_max_offset) - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; if (x[7] + h_min_offset > x[8] + h_max_offset) - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; printk(BIOS_SPEW, "Monitor ranges (%s): %d-%dHz V, %d-%dkHz H", - out->range_class, + extra_info.range_class, x[5] + v_min_offset, x[6] + v_max_offset, x[7] + h_min_offset, x[8] + h_max_offset); if (x[9]) printk(BIOS_SPEW, ", max dotclock %dMHz\n", x[9] * 10); else { - if (claims_one_point_four) - has_valid_max_dotclock = 0; + if (c->claims_one_point_four) + c->has_valid_max_dotclock = 0; printk(BIOS_SPEW, "\n"); } @@ -354,7 +364,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) printk(BIOS_SPEW, "Real max dotclock: %.2fMHz\n", (x[9] * 10) - (raw_offset * 0.25)); if (raw_offset >= 40) - warning_excessive_dotclock_correction = 1; + c->warning_excessive_dotclock_correction = 1; } max_h_pixels = x[12] & 0x03; @@ -371,7 +381,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) x[14] & 0x10 ? "5:4" : "", x[14] & 0x08 ? "15:9" : ""); if (x[14] & 0x07) - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; printk(BIOS_SPEW, "Preferred aspect ratio: "); switch((x[15] & 0xe0) >> 5) { @@ -390,7 +400,7 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) printk(BIOS_SPEW, "Supports CVT reduced blanking\n"); if (x[15] & 0x07) - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; if (x[16] & 0xf0) { printk(BIOS_SPEW, "Supported display scaling:\n"); @@ -405,19 +415,19 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) } if (x[16] & 0x0f) - has_valid_range_descriptor = 0; + c->has_valid_range_descriptor = 0; if (x[17]) printk(BIOS_SPEW, "Preferred vertical refresh: %d Hz\n", x[17]); else - warning_zero_preferred_refresh = 1; + c->warning_zero_preferred_refresh = 1; } /* * Slightly weird to return a global, but I've never seen any * EDID block wth two range descriptors, so it's harmless. */ - return 0; + return 1; } case 0xFE: /* @@ -425,97 +435,135 @@ detailed_block(struct edid *out, unsigned char *x, int in_extension) * seems to be specified by SPWG: http://www.spwg.org/ */ printk(BIOS_SPEW, "ASCII string: %s\n", - extract_string(x + 5, &has_valid_string_termination, 13)); - return 0; + extract_string(x + 5, &c->has_valid_string_termination, 13)); + return 1; case 0xFF: printk(BIOS_SPEW, "Serial number: %s\n", - extract_string(x + 5, &has_valid_string_termination, 13)); - return 0; + extract_string(x + 5, &c->has_valid_string_termination, 13)); + return 1; default: printk(BIOS_SPEW, "Unknown monitor description type %d\n", x[3]); return 0; } } - if (seen_non_detailed_descriptor && !in_extension) { - has_valid_descriptor_ordering = 0; + if (c->seen_non_detailed_descriptor && !in_extension) { + c->has_valid_descriptor_ordering = 0; } - if (! did_detailed_timing){ - out->ha = (x[2] + ((x[4] & 0xF0) << 4)); - out->hbl = (x[3] + ((x[4] & 0x0F) << 8)); - out->hso = (x[8] + ((x[11] & 0xC0) << 2)); - out->hspw = (x[9] + ((x[11] & 0x30) << 4)); - out->hborder = x[15]; - out->va = (x[5] + ((x[7] & 0xF0) << 4)); - out->vbl = (x[6] + ((x[7] & 0x0F) << 8)); - out->vso = ((x[10] >> 4) + ((x[11] & 0x0C) << 2)); - out->vspw = ((x[10] & 0x0F) + ((x[11] & 0x03) << 4)); - out->vborder = x[16]; - printk(BIOS_SPEW, "Did detailed timing\n"); - } - did_detailed_timing = 1; + /* Edid contains pixel clock in terms of 10KHz */ + out->mode.pixel_clock = (x[0] + (x[1] << 8)) * 10; + extra_info.x_mm = (x[12] + ((x[14] & 0xF0) << 4)); + extra_info.y_mm = (x[13] + ((x[14] & 0x0F) << 8)); + out->mode.ha = (x[2] + ((x[4] & 0xF0) << 4)); + out->mode.hbl = (x[3] + ((x[4] & 0x0F) << 8)); + out->mode.hso = (x[8] + ((x[11] & 0xC0) << 2)); + out->mode.hspw = (x[9] + ((x[11] & 0x30) << 4)); + out->mode.hborder = x[15]; + out->mode.va = (x[5] + ((x[7] & 0xF0) << 4)); + out->mode.vbl = (x[6] + ((x[7] & 0x0F) << 8)); + out->mode.vso = ((x[10] >> 4) + ((x[11] & 0x0C) << 2)); + out->mode.vspw = ((x[10] & 0x0F) + ((x[11] & 0x03) << 4)); + out->mode.vborder = x[16]; + /* set up some reasonable defaults for payloads. + * We observe that most modern chipsets we work with + * tend to support rgb888 without regard to the + * panel bits per color or other settings. The rgb888 + * is a convenient layout for software because + * it avoids the messy bit stuffing of rgb565 or rgb444. + * It makes a reasonable trade of memory for speed. + * So, set up the default for + * 32 bits per pixel + * rgb888 (i.e. no alpha, but pixels on 32-bit boundaries) + * The mainboard can modify these if needed, though + * we have yet to see a case where that will happen. + * The existing ARM mainboards don't even call this function + * so this will not affect them. + */ + out->framebuffer_bits_per_pixel = 32; + + out->x_resolution = ALIGN(out->mode.ha * + ((out->framebuffer_bits_per_pixel + 7) / 8), + 64) / (out->framebuffer_bits_per_pixel/8); + out->y_resolution = out->mode.va; + out->bytes_per_line = ALIGN(out->mode.ha * + ((out->framebuffer_bits_per_pixel + 7)/8), + 64); switch ((x[17] & 0x18) >> 3) { case 0x00: - out->syncmethod = " analog composite"; + extra_info.syncmethod = " analog composite"; break; case 0x01: - out->syncmethod = " bipolar analog composite"; + extra_info.syncmethod = " bipolar analog composite"; break; case 0x02: - out->syncmethod = " digital composite"; + extra_info.syncmethod = " digital composite"; break; case 0x03: - out->syncmethod = ""; + extra_info.syncmethod = ""; break; } - out->pvsync = (x[17] & (1 << 2)) ? '+' : '-'; - out->phsync = (x[17] & (1 << 1)) ? '+' : '-'; + out->mode.pvsync = (x[17] & (1 << 2)) ? '+' : '-'; + out->mode.phsync = (x[17] & (1 << 1)) ? '+' : '-'; switch (x[17] & 0x61) { case 0x20: - out->stereo = "field sequential L/R"; + extra_info.stereo = "field sequential L/R"; break; case 0x40: - out->stereo = "field sequential R/L"; + extra_info.stereo = "field sequential R/L"; break; case 0x21: - out->stereo = "interleaved right even"; + extra_info.stereo = "interleaved right even"; break; case 0x41: - out->stereo = "interleaved left even"; + extra_info.stereo = "interleaved left even"; break; case 0x60: - out->stereo = "four way interleaved"; + extra_info.stereo = "four way interleaved"; break; case 0x61: - out->stereo = "side by side interleaved"; + extra_info.stereo = "side by side interleaved"; break; default: - out->stereo = ""; + extra_info.stereo = ""; break; } - printk(BIOS_SPEW, "Detailed mode (IN HEX): Clock %d0 KHz, %x mm x %x mm\n" + printk(BIOS_SPEW, "Detailed mode (IN HEX): Clock %d KHz, %x mm x %x mm\n" " %04x %04x %04x %04x hborder %x\n" " %04x %04x %04x %04x vborder %x\n" " %chsync %cvsync%s%s %s\n", - (x[0] + (x[1] << 8)), - (x[12] + ((x[14] & 0xF0) << 4)), - (x[13] + ((x[14] & 0x0F) << 8)), - out->ha, out->ha + out->hso, out->ha + out->hso + out->hspw, - out->ha + out->hbl, out->hborder, - out->va, out->va + out->vso, out->va + out->vso + out->vspw, - out->va + out->vbl, out->vborder, - out->phsync, out->pvsync, - out->syncmethod, x[17] & 0x80 ?" interlaced" : "", - out->stereo - ); + out->mode.pixel_clock, + extra_info.x_mm, + extra_info.y_mm, + out->mode.ha, out->mode.ha + out->mode.hso, + out->mode.ha + out->mode.hso + out->mode.hspw, + out->mode.ha + out->mode.hbl, out->mode.hborder, + out->mode.va, out->mode.va + out->mode.vso, + out->mode.va + out->mode.vso + out->mode.vspw, + out->mode.va + out->mode.vbl, out->mode.vborder, + out->mode.phsync, out->mode.pvsync, + extra_info.syncmethod, x[17] & 0x80 ?" interlaced" : "", + extra_info.stereo); + + if (c->max_khz && out->mode.pixel_clock > c->max_khz) { + printk(BIOS_SPEW, "Skipping %d\n", out->mode.pixel_clock); + return 1; + } + + if (! c->did_detailed_timing) { + printk(BIOS_SPEW, "Did detailed timing\n"); + c->did_detailed_timing = 1; + *result_edid = *out; + } + return 1; } static int do_checksum(unsigned char *x) { + int valid = 0; printk(BIOS_SPEW, "Checksum: 0x%hx", x[0x7f]); { unsigned char sum = 0; @@ -524,14 +572,13 @@ do_checksum(unsigned char *x) sum += x[i]; if (sum) { printk(BIOS_SPEW, " (should be 0x%hx)", (unsigned char)(x[0x7f] - sum)); - has_valid_checksum = 0; } else { - has_valid_checksum = 1; + valid = 1; printk(BIOS_SPEW, " (valid)"); } } printk(BIOS_SPEW, "\n"); - return has_valid_checksum; + return valid; } /* CEA extension */ @@ -611,6 +658,8 @@ cea_hdmi_block(struct edid *out, unsigned char *x) { int length = x[0] & 0x1f; + out->hdmi_monitor_detected = 1; + printk(BIOS_SPEW, " (HDMI)\n"); printk(BIOS_SPEW, " Source physical address %d.%d.%d.%d\n", @@ -805,7 +854,7 @@ cea_block(struct edid *out, unsigned char *x) } static int -parse_cea(struct edid *out, unsigned char *x) +parse_cea(struct edid *out, unsigned char *x, struct edid_context *c) { int ret = 0; int version = x[1]; @@ -845,11 +894,10 @@ parse_cea(struct edid *out, unsigned char *x) for (detailed = x + offset; detailed + 18 < x + 127; detailed += 18) if (detailed[0]) - detailed_block(out, detailed, 1); + detailed_block(out, detailed, 1, c); } while (0); - do_checksum(x); - + c->has_valid_checksum &= do_checksum(x); return ret; } @@ -862,7 +910,7 @@ extension_version(struct edid *out, unsigned char *x) } static int -parse_extension(struct edid *out, unsigned char *x) +parse_extension(struct edid *out, unsigned char *x, struct edid_context *c) { int conformant_extension = 0; printk(BIOS_SPEW, "\n"); @@ -871,7 +919,7 @@ parse_extension(struct edid *out, unsigned char *x) case 0x02: printk(BIOS_SPEW, "CEA extension block\n"); extension_version(out, x); - conformant_extension = parse_cea(out, x); + conformant_extension = parse_cea(out, x, c); break; case 0x10: printk(BIOS_SPEW, "VTB extension block\n"); break; case 0x40: printk(BIOS_SPEW, "DI extension block\n"); break; @@ -946,6 +994,52 @@ static void dump_breakdown(unsigned char *edid) printk(BIOS_SPEW, "\n"); } +/* + * Lookup table of some well-known modes that can be useful in case the + * auto-detected mode is unsuitable. + * ha = hdisplay; va = vdisplay; + * hbl = htotal - hdisplay; vbl = vtotal - vdisplay; + * hso = hsync_start - hdsiplay; vso = vsync_start - vdisplay; + * hspw = hsync_end - hsync_start; vspw = vsync_end - vsync_start; + */ +static struct edid_mode known_modes[NUM_KNOWN_MODES] = { + [EDID_MODE_640x480_60Hz] = { + .name = "640x480@60Hz", .pixel_clock = 25200, .refresh = 60, + .ha = 640, .hbl = 160, .hso = 16, .hspw = 96, + .va = 480, .vbl = 45, .vso = 10, .vspw = 2, + .phsync = '-', .pvsync = '-' }, + [EDID_MODE_720x480_60Hz] = { + .name = "720x480@60Hz", .pixel_clock = 27000, .refresh = 60, + .ha = 720, .hbl = 138, .hso = 16, .hspw = 62, + .va = 480, .vbl = 45, .vso = 9, .vspw = 6, + .phsync = '-', .pvsync = '-' }, + [EDID_MODE_1280x720_60Hz] = { + .name = "1280x720@60Hz", .pixel_clock = 74250, .refresh = 60, + .ha = 1280, .hbl = 370, .hso = 110, .hspw = 40, + .va = 720, .vbl = 30, .vso = 5, .vspw = 20, + .phsync = '+', .pvsync = '+' }, + [EDID_MODE_1920x1080_60Hz] = { + .name = "1920x1080@60Hz", .pixel_clock = 148500, .refresh = 60, + .ha = 1920, .hbl = 280, .hso = 88, .hspw = 44, + .va = 1080, .vbl = 45, .vso = 4, .vspw = 5, + .phsync = '+', .pvsync = '+' }, +}; + +int set_display_mode(struct edid *edid, enum edid_modes mode) +{ + if (mode == EDID_MODE_AUTO) + return 0; + + if (edid->mode_is_supported[mode]) { + printk(BIOS_DEBUG, "Forcing mode %s\n", known_modes[mode].name); + edid->mode = known_modes[mode]; + return 0; + } + + printk(BIOS_ERR, "Requested display mode not supported.\n"); + return -1; +} + /* * Given a raw edid bloc, decode it into a form * that other parts of coreboot can use -- mainly @@ -953,56 +1047,73 @@ static void dump_breakdown(unsigned char *edid) * required to be 128 bytes long, per the standard, * but we have no way of checking this minimum length. * We accept what we are given. + * + * We'll filter out modes > max_khz; 0 for no filter */ -int decode_edid(unsigned char *edid, int size, struct edid *out) +int decode_edid(unsigned char *edid, int size, struct edid *out, int max_khz) { - int analog, i; + int analog, i, j; + struct edid_context c = { + .has_valid_cvt = 1, + .has_valid_dummy_block = 1, + .has_valid_descriptor_ordering = 1, + .has_valid_detailed_blocks = 1, + .has_valid_descriptor_pad = 1, + .has_valid_range_descriptor = 1, + .has_valid_max_dotclock = 1, + .has_valid_string_termination = 1, + .conformant = 1, + .max_khz = max_khz, + }; dump_breakdown(edid); + memset(out, 0, sizeof(*out)); + if (!edid || memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) { printk(BIOS_SPEW, "No header found\n"); return 1; } - memset(out, 0, sizeof(*out)); - manufacturer_name(out, edid + 0x08); - out->model = (unsigned short)(edid[0x0A] + (edid[0x0B] << 8)); - out->serial = (unsigned int)(edid[0x0C] + (edid[0x0D] << 8) + + if (manufacturer_name(edid + 0x08)) + c.manufacturer_name_well_formed = 1; + + extra_info.model = (unsigned short)(edid[0x0A] + (edid[0x0B] << 8)); + extra_info.serial = (unsigned int)(edid[0x0C] + (edid[0x0D] << 8) + (edid[0x0E] << 16) + (edid[0x0F] << 24)); printk(BIOS_SPEW, "Manufacturer: %s Model %x Serial Number %u\n", - out->manuf_name, + extra_info.manuf_name, (unsigned short)(edid[0x0A] + (edid[0x0B] << 8)), (unsigned int)(edid[0x0C] + (edid[0x0D] << 8) + (edid[0x0E] << 16) + (edid[0x0F] << 24))); - /* XXX need manufacturer ID table */ + /* XXX need manufacturer ID table */ - if (edid[0x10] < 55 || edid[0x10] == 0xff) { - has_valid_week = 1; - if (edid[0x11] > 0x0f) { - if (edid[0x10] == 0xff) { - has_valid_year = 1; - printk(BIOS_SPEW, "Made week %hd of model year %hd\n", edid[0x10], - edid[0x11]); - out->week = edid[0x10]; - out->year = edid[0x11]; - } else { - /* we know it's at least 2013, when this code was written */ - if (edid[0x11] + 90 <= 2013) { - has_valid_year = 1; - printk(BIOS_SPEW, "Made week %hd of %hd\n", - edid[0x10], edid[0x11] + 1990); - out->week = edid[0x10]; - out->year = edid[0x11] + 1990; - } + if (edid[0x10] < 55 || edid[0x10] == 0xff) { + c.has_valid_week = 1; + if (edid[0x11] > 0x0f) { + if (edid[0x10] == 0xff) { + c.has_valid_year = 1; + printk(BIOS_SPEW, "Made week %hd of model year %hd\n", edid[0x10], + edid[0x11]); + extra_info.week = edid[0x10]; + extra_info.year = edid[0x11]; + } else { + /* we know it's at least 2013, when this code was written */ + if (edid[0x11] + 90 <= 2013) { + c.has_valid_year = 1; + printk(BIOS_SPEW, "Made week %hd of %hd\n", + edid[0x10], edid[0x11] + 1990); + extra_info.week = edid[0x10]; + extra_info.year = edid[0x11] + 1990; } } } - + } printk(BIOS_SPEW, "EDID version: %hd.%hd\n", edid[0x12], edid[0x13]); - out->version[0] = edid[0x12]; - out->version[1] = edid[0x13]; + extra_info.version[0] = edid[0x12]; + extra_info.version[1] = edid[0x13]; if (edid[0x12] == 1) { if (edid[0x13] > 4) { @@ -1011,33 +1122,33 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) } switch (edid[0x13]) { case 4: - claims_one_point_four = 1; + c.claims_one_point_four = 1; case 3: - claims_one_point_three = 1; + c.claims_one_point_three = 1; case 2: - claims_one_point_two = 1; + c.claims_one_point_two = 1; default: break; } - claims_one_point_oh = 1; + c.claims_one_point_oh = 1; } /* display section */ - if (edid[0x14] & 0x80) { int conformance_mask; analog = 0; printk(BIOS_SPEW, "Digital display\n"); - if (claims_one_point_four) { + if (c.claims_one_point_four) { conformance_mask = 0; if ((edid[0x14] & 0x70) == 0x00) printk(BIOS_SPEW, "Color depth is undefined\n"); else if ((edid[0x14] & 0x70) == 0x70) - nonconformant_digital_display = 1; + c.nonconformant_digital_display = 1; else printk(BIOS_SPEW, "%d bits per primary color channel\n", ((edid[0x14] & 0x70) >> 3) + 4); - out->bpp = ((edid[0x14] & 0x70) >> 3) + 4; + out->panel_bits_per_color = ((edid[0x14] & 0x70) >> 3) + 4; + out->panel_bits_per_pixel = 3*out->panel_bits_per_color; switch (edid[0x14] & 0x0f) { case 0x00: printk(BIOS_SPEW, "Digital interface is not defined\n"); break; @@ -1047,10 +1158,10 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) case 0x04: printk(BIOS_SPEW, "MDDI interface\n"); break; case 0x05: printk(BIOS_SPEW, "DisplayPort interface\n"); break; default: - nonconformant_digital_display = 1; + c.nonconformant_digital_display = 1; } - out->type = edid[0x14] & 0x0f; - } else if (claims_one_point_two) { + extra_info.type = edid[0x14] & 0x0f; + } else if (c.claims_one_point_two) { conformance_mask = 0x7E; if (edid[0x14] & 0x01) { printk(BIOS_SPEW, "DFP 1.x compatible TMDS\n"); @@ -1058,15 +1169,15 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) } else conformance_mask = 0x7F; - if (!nonconformant_digital_display) - nonconformant_digital_display = edid[0x14] & conformance_mask; - out->nonconformant = nonconformant_digital_display; + if (!c.nonconformant_digital_display) + c.nonconformant_digital_display = edid[0x14] & conformance_mask; + extra_info.nonconformant = c.nonconformant_digital_display; } else { analog = 1; int voltage = (edid[0x14] & 0x60) >> 5; int sync = (edid[0x14] & 0x0F); - out->voltage = voltage; - out->sync = sync; + extra_info.voltage = voltage; + extra_info.sync = sync; printk(BIOS_SPEW, "Analog display, Input voltage level: %s V\n", voltage == 3 ? "0.7/0.7" : @@ -1074,7 +1185,7 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) voltage == 1 ? "0.714/0.286" : "0.7/0.3"); - if (claims_one_point_four) { + if (c.claims_one_point_four) { if (edid[0x14] & 0x10) printk(BIOS_SPEW, "Blank-to-black setup/pedestal\n"); else @@ -1095,243 +1206,280 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) } - if (edid[0x15] && edid[0x16]) { - printk(BIOS_SPEW, "Maximum image size: %d cm x %d cm\n", - edid[0x15], edid[0x16]); - out->xsize_cm = edid[0x15]; - out->ysize_cm = edid[0x16]; - } else if (claims_one_point_four && (edid[0x15] || edid[0x16])) { - if (edid[0x15]) { - printk(BIOS_SPEW, "Aspect ratio is %f (landscape)\n", - 100.0/(edid[0x16] + 99)); - /* truncated to integer %. We try to avoid floating point */ - out->aspect_landscape = 10000 /(edid[0x16] + 99); - } else { - printk(BIOS_SPEW, "Aspect ratio is %f (portrait)\n", - 100.0/(edid[0x15] + 99)); - out->aspect_portrait = 10000 /(edid[0x16] + 99); - } - } else { - /* Either or both can be zero for 1.3 and before */ - printk(BIOS_SPEW, "Image size is variable\n"); + if (edid[0x15] && edid[0x16]) { + printk(BIOS_SPEW, "Maximum image size: %d cm x %d cm\n", + edid[0x15], edid[0x16]); + } else if (c.claims_one_point_four && (edid[0x15] || edid[0x16])) { + if (edid[0x15]) { /* edid[0x15] != 0 && edid[0x16] == 0 */ + unsigned int ratio = 100000/(edid[0x15] + 99); + printk(BIOS_SPEW, "Aspect ratio is %u.%03u (landscape)\n", + ratio / 1000, ratio % 1000); + } else { /* edid[0x15] == 0 && edid[0x16] != 0 */ + unsigned int ratio = 100000/(edid[0x16] + 99); + printk(BIOS_SPEW, "Aspect ratio is %u.%03u (portrait)\n", + ratio / 1000, ratio % 1000); } + } else { + /* Either or both can be zero for 1.3 and before */ + printk(BIOS_SPEW, "Image size is variable\n"); + } - if (edid[0x17] == 0xff) { - if (claims_one_point_four) - printk(BIOS_SPEW, "Gamma is defined in an extension block\n"); - else - /* XXX Technically 1.3 doesn't say this... */ - printk(BIOS_SPEW, "Gamma: 1.0\n"); - } else printk(BIOS_SPEW, "Gamma: %d%%\n", ((edid[0x17] + 100))); - printk(BIOS_SPEW, "Check DPMS levels\n"); - if (edid[0x18] & 0xE0) { - printk(BIOS_SPEW, "DPMS levels:"); - if (edid[0x18] & 0x80) printk(BIOS_SPEW, " Standby"); - if (edid[0x18] & 0x40) printk(BIOS_SPEW, " Suspend"); - if (edid[0x18] & 0x20) printk(BIOS_SPEW, " Off"); - printk(BIOS_SPEW, "\n"); - } + if (edid[0x17] == 0xff) { + if (c.claims_one_point_four) + printk(BIOS_SPEW, "Gamma is defined in an extension block\n"); + else + /* XXX Technically 1.3 doesn't say this... */ + printk(BIOS_SPEW, "Gamma: 1.0\n"); + } else printk(BIOS_SPEW, "Gamma: %d%%\n", ((edid[0x17] + 100))); + printk(BIOS_SPEW, "Check DPMS levels\n"); + if (edid[0x18] & 0xE0) { + printk(BIOS_SPEW, "DPMS levels:"); + if (edid[0x18] & 0x80) printk(BIOS_SPEW, " Standby"); + if (edid[0x18] & 0x40) printk(BIOS_SPEW, " Suspend"); + if (edid[0x18] & 0x20) printk(BIOS_SPEW, " Off"); + printk(BIOS_SPEW, "\n"); + } -/* FIXME: this is from 1.4 spec, check earlier */ - if (analog) { - switch (edid[0x18] & 0x18) { + /* FIXME: this is from 1.4 spec, check earlier */ + if (analog) { + switch (edid[0x18] & 0x18) { case 0x00: printk(BIOS_SPEW, "Monochrome or grayscale display\n"); break; case 0x08: printk(BIOS_SPEW, "RGB color display\n"); break; case 0x10: printk(BIOS_SPEW, "Non-RGB color display\n"); break; case 0x18: printk(BIOS_SPEW, "Undefined display color type\n"); - } - } else { - printk(BIOS_SPEW, "Supported color formats: RGB 4:4:4"); - if (edid[0x18] & 0x10) - printk(BIOS_SPEW, ", YCrCb 4:4:4"); - if (edid[0x18] & 0x08) - printk(BIOS_SPEW, ", YCrCb 4:2:2"); - printk(BIOS_SPEW, "\n"); } - - if (edid[0x18] & 0x04) - printk(BIOS_SPEW, "Default (sRGB) color space is primary color space\n"); - if (edid[0x18] & 0x02) { - printk(BIOS_SPEW, "First detailed timing is preferred timing\n"); - has_preferred_timing = 1; - } - if (edid[0x18] & 0x01) - printk(BIOS_SPEW, "Supports GTF timings within operating range\n"); - - /* XXX color section */ - - printk(BIOS_SPEW, "Established timings supported:\n"); - /* it's not yet clear we want all this stuff in the edid struct. - * Let's wait. - */ - for (i = 0; i < 17; i++) { - if (edid[0x23 + i / 8] & (1 << (7 - i % 8))) { - printk(BIOS_SPEW, " %dx%d@%dHz\n", established_timings[i].x, - established_timings[i].y, established_timings[i].refresh); - } - } - - printk(BIOS_SPEW, "Standard timings supported:\n"); - for (i = 0; i < 8; i++) { - uint8_t b1 = edid[0x26 + i * 2], b2 = edid[0x26 + i * 2 + 1]; - unsigned int x, y, refresh; - - if (b1 == 0x01 && b2 == 0x01) - continue; - - if (b1 == 0) { - printk(BIOS_SPEW, "non-conformant standard timing (0 horiz)\n"); - continue; - } - x = (b1 + 31) * 8; - switch ((b2 >> 6) & 0x3) { - case 0x00: - if (claims_one_point_three) - y = x * 10 / 16; - else - y = x; - break; - case 0x01: - y = x * 3 / 4; - break; - case 0x02: - y = x * 4 / 5; - break; - case 0x03: - y = x * 9 / 16; - break; - } - refresh = 60 + (b2 & 0x3f); - - printk(BIOS_SPEW, " %dx%d@%dHz\n", x, y, refresh); - } - - /* detailed timings */ - printk(BIOS_SPEW, "Detailed timings\n"); - has_valid_detailed_blocks = detailed_block(out, edid + 0x36, 0); - if (has_preferred_timing && !did_detailed_timing) - has_preferred_timing = 0; /* not really accurate... */ - has_valid_detailed_blocks &= detailed_block(out, edid + 0x48, 0); - has_valid_detailed_blocks &= detailed_block(out, edid + 0x5A, 0); - has_valid_detailed_blocks &= detailed_block(out, edid + 0x6C, 0); - - /* check this, 1.4 verification guide says otherwise */ - if (edid[0x7e]) { - printk(BIOS_SPEW, "Has %d extension blocks\n", edid[0x7e]); - /* 2 is impossible because of the block map */ - if (edid[0x7e] != 2) - has_valid_extension_count = 1; - } else { - has_valid_extension_count = 1; - } - - printk(BIOS_SPEW, "Checksum\n"); - do_checksum(edid); - for(i = 0; i < size; i += 128) - nonconformant_extension = parse_extension(out, &edid[i]); -/* - x = edid; - for (edid_lines /= 8; edid_lines > 1; edid_lines--) { - x += 128; - nonconformant_extension += parse_extension(x); - } -*/ - - if (claims_one_point_three) { - if (nonconformant_digital_display || - !has_valid_string_termination || - !has_valid_descriptor_pad || - !has_name_descriptor || - !name_descriptor_terminated || - !has_preferred_timing || - !has_range_descriptor) - conformant = 0; - if (!conformant) - printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.3!\n"); - if (nonconformant_digital_display) - printk(BIOS_ERR, "\tDigital display field contains garbage: %x\n", - nonconformant_digital_display); - if (!has_name_descriptor) - printk(BIOS_ERR, "\tMissing name descriptor\n"); - else if (!name_descriptor_terminated) - printk(BIOS_ERR, "\tName descriptor not terminated with a newline\n"); - if (!has_preferred_timing) - printk(BIOS_ERR, "\tMissing preferred timing\n"); - if (!has_range_descriptor) - printk(BIOS_ERR, "\tMissing monitor ranges\n"); - if (!has_valid_descriptor_pad) /* Might be more than just 1.3 */ - printk(BIOS_ERR, "\tInvalid descriptor block padding\n"); - if (!has_valid_string_termination) /* Likewise */ - printk(BIOS_ERR, "\tDetailed block string not properly terminated\n"); - } else if (claims_one_point_two) { - if (nonconformant_digital_display || - (has_name_descriptor && !name_descriptor_terminated)) - conformant = 0; - if (!conformant) - printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.2!\n"); - if (nonconformant_digital_display) - printk(BIOS_ERR, "\tDigital display field contains garbage: %x\n", - nonconformant_digital_display); - if (has_name_descriptor && !name_descriptor_terminated) - printk(BIOS_ERR, "\tName descriptor not terminated with a newline\n"); - } else if (claims_one_point_oh) { - if (seen_non_detailed_descriptor) - conformant = 0; - if (!conformant) - printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.0!\n"); - if (seen_non_detailed_descriptor) - printk(BIOS_ERR, "\tHas descriptor blocks other than detailed timings\n"); - } - - if (nonconformant_extension || - !has_valid_checksum || - !has_valid_cvt || - !has_valid_year || - !has_valid_week || - !has_valid_detailed_blocks || - !has_valid_dummy_block || - !has_valid_extension_count || - !has_valid_descriptor_ordering || - !has_valid_range_descriptor || - !manufacturer_name_well_formed) { - conformant = 0; - printk(BIOS_ERR, "EDID block does not conform at all!\n"); - if (nonconformant_extension) - printk(BIOS_ERR, "\tHas %d nonconformant extension block(s)\n", - nonconformant_extension); - if (!has_valid_checksum) - printk(BIOS_ERR, "\tBlock has broken checksum\n"); - if (!has_valid_cvt) - printk(BIOS_ERR, "\tBroken 3-byte CVT blocks\n"); - if (!has_valid_year) - printk(BIOS_ERR, "\tBad year of manufacture\n"); - if (!has_valid_week) - printk(BIOS_ERR, "\tBad week of manufacture\n"); - if (!has_valid_detailed_blocks) - printk(BIOS_ERR, "\tDetailed blocks filled with garbage\n"); - if (!has_valid_dummy_block) - printk(BIOS_ERR, "\tDummy block filled with garbage\n"); - if (!has_valid_extension_count) - printk(BIOS_ERR, "\tImpossible extension block count\n"); - if (!manufacturer_name_well_formed) - printk(BIOS_ERR, "\tManufacturer name field contains garbage\n"); - if (!has_valid_descriptor_ordering) - printk(BIOS_ERR, "\tInvalid detailed timing descriptor ordering\n"); - if (!has_valid_range_descriptor) - printk(BIOS_ERR, "\tRange descriptor contains garbage\n"); - if (!has_valid_max_dotclock) - printk(BIOS_ERR, "\tEDID 1.4 block does not set max dotclock\n"); - } - - if (warning_excessive_dotclock_correction) - printk(BIOS_ERR, - "Warning: CVT block corrects dotclock by more than 9.75MHz\n"); - if (warning_zero_preferred_refresh) - printk(BIOS_ERR, - "Warning: CVT block does not set preferred refresh rate\n"); - return !conformant; + } else { + printk(BIOS_SPEW, "Supported color formats: RGB 4:4:4"); + if (edid[0x18] & 0x10) + printk(BIOS_SPEW, ", YCrCb 4:4:4"); + if (edid[0x18] & 0x08) + printk(BIOS_SPEW, ", YCrCb 4:2:2"); + printk(BIOS_SPEW, "\n"); } + if (edid[0x18] & 0x04) + printk(BIOS_SPEW, "Default (sRGB) color space is primary color space\n"); + if (edid[0x18] & 0x02) { + printk(BIOS_SPEW, "First detailed timing is preferred timing\n"); + c.has_preferred_timing = 1; + } + if (edid[0x18] & 0x01) + printk(BIOS_SPEW, "Supports GTF timings within operating range\n"); + + /* XXX color section */ + + printk(BIOS_SPEW, "Established timings supported:\n"); + /* it's not yet clear we want all this stuff in the edid struct. + * Let's wait. + */ + for (i = 0; i < 17; i++) { + if (edid[0x23 + i / 8] & (1 << (7 - i % 8))) { + printk(BIOS_SPEW, " %dx%d@%dHz\n", established_timings[i].x, + established_timings[i].y, established_timings[i].refresh); + + for (j = 0; j < NUM_KNOWN_MODES; j++) { + if (known_modes[j].ha == established_timings[i].x && + known_modes[j].va == established_timings[i].y && + known_modes[j].refresh == established_timings[i].refresh) + out->mode_is_supported[j] = 1; + } + } + + } + + printk(BIOS_SPEW, "Standard timings supported:\n"); + for (i = 0; i < 8; i++) { + uint8_t b1 = edid[0x26 + i * 2], b2 = edid[0x26 + i * 2 + 1]; + unsigned int x, y = 0, refresh; + + if (b1 == 0x01 && b2 == 0x01) + continue; + + if (b1 == 0) { + printk(BIOS_SPEW, "non-conformant standard timing (0 horiz)\n"); + continue; + } + x = (b1 + 31) * 8; + switch ((b2 >> 6) & 0x3) { + case 0x00: + if (c.claims_one_point_three) + y = x * 10 / 16; + else + y = x; + break; + case 0x01: + y = x * 3 / 4; + break; + case 0x02: + y = x * 4 / 5; + break; + case 0x03: + y = x * 9 / 16; + break; + } + refresh = 60 + (b2 & 0x3f); + + printk(BIOS_SPEW, " %dx%d@%dHz\n", x, y, refresh); + for (j = 0; j < NUM_KNOWN_MODES; j++) { + if (known_modes[j].ha == x && known_modes[j].va == y && + known_modes[j].refresh == refresh) + out->mode_is_supported[j] = 1; + } + } + + /* detailed timings */ + printk(BIOS_SPEW, "Detailed timings\n"); + for (i = 0; i < 4; i++) { + c.has_valid_detailed_blocks &= detailed_block( + out, edid + 0x36 + i * 18, 0, &c); + if (i == 0 && c.has_preferred_timing && !c.did_detailed_timing) + { + /* not really accurate... */ + c.has_preferred_timing = 0; + } + } + + /* check this, 1.4 verification guide says otherwise */ + if (edid[0x7e]) { + printk(BIOS_SPEW, "Has %d extension blocks\n", edid[0x7e]); + /* 2 is impossible because of the block map */ + if (edid[0x7e] != 2) + c.has_valid_extension_count = 1; + } else { + c.has_valid_extension_count = 1; + } + + printk(BIOS_SPEW, "Checksum\n"); + c.has_valid_checksum = do_checksum(edid); + + /* EDID v2.0 has a larger blob (256 bytes) and may have some problem in + * the extension parsing loop below. Since v2.0 was quickly deprecated + * by v1.3 and we are unlikely to use any EDID 2.0 panels, we ignore + * that case now and can fix it when we need to use a real 2.0 panel. + */ + for(i = 128; i < size; i += 128) + c.nonconformant_extension += + parse_extension(out, &edid[i], &c); + + if (c.claims_one_point_four) { + if (c.nonconformant_digital_display || + !c.has_valid_string_termination || + !c.has_valid_descriptor_pad || + !c.has_preferred_timing) + c.conformant = 0; + if (!c.conformant) + printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.4!\n"); + if (c.nonconformant_digital_display) + printk(BIOS_ERR, "\tDigital display field contains garbage: %x\n", + c.nonconformant_digital_display); + if (!c.has_valid_string_termination) + printk(BIOS_ERR, "\tDetailed block string not properly terminated\n"); + if (!c.has_valid_descriptor_pad) + printk(BIOS_ERR, "\tInvalid descriptor block padding\n"); + if (!c.has_preferred_timing) + printk(BIOS_ERR, "\tMissing preferred timing\n"); + } else if (c.claims_one_point_three) { + if (c.nonconformant_digital_display || + !c.has_valid_string_termination || + !c.has_valid_descriptor_pad || + !c.has_preferred_timing) { + c.conformant = 0; + } + /** + * According to E-EDID (EDIDv1.3), has_name_descriptor and + * has_range_descriptor are both required. These fields are + * optional in v1.4. However some v1.3 panels (Ex, B133XTN01.3) + * don't have them. As a workaround, we only print warning + * messages. + */ + if (!c.conformant) + printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.3!\n"); + else if (!c.has_name_descriptor || !c.has_range_descriptor) + printk(BIOS_WARNING, "WARNING: EDID block does NOT " + "fully conform to EDID 1.3.\n"); + + if (c.nonconformant_digital_display) + printk(BIOS_ERR, "\tDigital display field contains garbage: %x\n", + c.nonconformant_digital_display); + if (!c.has_name_descriptor) + printk(BIOS_ERR, "\tMissing name descriptor\n"); + if (!c.has_preferred_timing) + printk(BIOS_ERR, "\tMissing preferred timing\n"); + if (!c.has_range_descriptor) + printk(BIOS_ERR, "\tMissing monitor ranges\n"); + if (!c.has_valid_descriptor_pad) /* Might be more than just 1.3 */ + printk(BIOS_ERR, "\tInvalid descriptor block padding\n"); + if (!c.has_valid_string_termination) /* Likewise */ + printk(BIOS_ERR, "\tDetailed block string not properly terminated\n"); + } else if (c.claims_one_point_two) { + if (c.nonconformant_digital_display || + !c.has_valid_string_termination) + c.conformant = 0; + if (!c.conformant) + printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.2!\n"); + if (c.nonconformant_digital_display) + printk(BIOS_ERR, "\tDigital display field contains garbage: %x\n", + c.nonconformant_digital_display); + if (!c.has_valid_string_termination) + printk(BIOS_ERR, "\tDetailed block string not properly terminated\n"); + } else if (c.claims_one_point_oh) { + if (c.seen_non_detailed_descriptor) + c.conformant = 0; + if (!c.conformant) + printk(BIOS_ERR, "EDID block does NOT conform to EDID 1.0!\n"); + if (c.seen_non_detailed_descriptor) + printk(BIOS_ERR, "\tHas descriptor blocks other than detailed timings\n"); + } + + if (c.nonconformant_extension || + !c.has_valid_checksum || + !c.has_valid_cvt || + !c.has_valid_year || + !c.has_valid_week || + !c.has_valid_detailed_blocks || + !c.has_valid_dummy_block || + !c.has_valid_extension_count || + !c.has_valid_descriptor_ordering || + !c.has_valid_range_descriptor || + !c.manufacturer_name_well_formed) { + c.conformant = 0; + printk(BIOS_ERR, "EDID block does not conform at all!\n"); + if (c.nonconformant_extension) + printk(BIOS_ERR, "\tHas %d nonconformant extension block(s)\n", + c.nonconformant_extension); + if (!c.has_valid_checksum) + printk(BIOS_ERR, "\tBlock has broken checksum\n"); + if (!c.has_valid_cvt) + printk(BIOS_ERR, "\tBroken 3-byte CVT blocks\n"); + if (!c.has_valid_year) + printk(BIOS_ERR, "\tBad year of manufacture\n"); + if (!c.has_valid_week) + printk(BIOS_ERR, "\tBad week of manufacture\n"); + if (!c.has_valid_detailed_blocks) + printk(BIOS_ERR, "\tDetailed blocks filled with garbage\n"); + if (!c.has_valid_dummy_block) + printk(BIOS_ERR, "\tDummy block filled with garbage\n"); + if (!c.has_valid_extension_count) + printk(BIOS_ERR, "\tImpossible extension block count\n"); + if (!c.manufacturer_name_well_formed) + printk(BIOS_ERR, "\tManufacturer name field contains garbage\n"); + if (!c.has_valid_descriptor_ordering) + printk(BIOS_ERR, "\tInvalid detailed timing descriptor ordering\n"); + if (!c.has_valid_range_descriptor) + printk(BIOS_ERR, "\tRange descriptor contains garbage\n"); + if (!c.has_valid_max_dotclock) + printk(BIOS_ERR, "\tEDID 1.4 block does not set max dotclock\n"); + } + + if (c.warning_excessive_dotclock_correction) + printk(BIOS_ERR, + "Warning: CVT block corrects dotclock by more than 9.75MHz\n"); + if (c.warning_zero_preferred_refresh) + printk(BIOS_ERR, + "Warning: CVT block does not set preferred refresh rate\n"); + return !c.conformant; +} + /* * Notes on panel extensions: (TODO, implement me in the code) * @@ -1386,3 +1534,65 @@ int decode_edid(unsigned char *edid, int size, struct edid *out) * SPWG also says something strange about the LSB of detailed descriptor 1: * "LSB is set to "1" if panel is DE-timing only. H/V can be ignored." */ +/* + * Take an edid, and create a framebuffer. Set vbe_valid to 1. + */ + +void set_vbe_mode_info_valid(struct edid *edid, uintptr_t fb_addr) +{ + edid_fb.physical_address = fb_addr; + edid_fb.x_resolution = edid->x_resolution; + edid_fb.y_resolution = edid->y_resolution; + edid_fb.bytes_per_line = edid->bytes_per_line; + /* In the case of (e.g.) 24 framebuffer bits per pixel, the convention nowadays + * seems to be to round it up to the nearest reasonable + * boundary, because otherwise the byte-packing is hideous. + * So, for example, in RGB with no alpha, the bytes are still + * packed into 32-bit words, the so-called 32bpp-no-alpha mode. + * Or, in 5:6:5 mode, the bytes are also packed into 32-bit words, + * and in 4:4:4 mode, they are packed into 16-bit words. + * Good call on the hardware guys part. + * It's not clear we're covering all cases here, but + * I'm not sure with grahpics you ever can. + */ + edid_fb.bits_per_pixel = edid->framebuffer_bits_per_pixel; + switch(edid->framebuffer_bits_per_pixel){ + case 32: + case 24: + /* packed into 4-byte words */ + edid_fb.red_mask_pos = 16; + edid_fb.red_mask_size = 8; + edid_fb.green_mask_pos = 8; + edid_fb.green_mask_size = 8; + edid_fb.blue_mask_pos = 0; + edid_fb.blue_mask_size = 8; + break; + case 16: + /* packed into 2-byte words */ + edid_fb.red_mask_pos = 11; + edid_fb.red_mask_size = 5; + edid_fb.green_mask_pos = 5; + edid_fb.green_mask_size = 6; + edid_fb.blue_mask_pos = 0; + edid_fb.blue_mask_size = 5; + break; + default: + printk(BIOS_SPEW, "%s: unsupported BPP %d\n", __func__, + edid->framebuffer_bits_per_pixel); + return; + } + + edid_fb.reserved_mask_pos = 0; + edid_fb.reserved_mask_size = 0; + vbe_valid = 1; +} + +int vbe_mode_info_valid(void) +{ + return vbe_valid; +} + +void fill_lb_framebuffer(struct lb_framebuffer *framebuffer) +{ + *framebuffer = edid_fb; +} diff --git a/src/lib/gcov-glue.c b/src/lib/gcov-glue.c index 4e2b2908b3..ab9062b497 100644 --- a/src/lib/gcov-glue.c +++ b/src/lib/gcov-glue.c @@ -18,8 +18,8 @@ */ #include +#include #include -#include typedef struct file { uint32_t magic; @@ -128,7 +128,7 @@ static void setbuf(FILE *stream, char *buf) gcc_assert(buf == 0); } -void coverage_init(void) +static void coverage_init(void *unused) { extern long __CTOR_LIST__; typedef void (*func_ptr)(void) ; @@ -142,7 +142,7 @@ void coverage_init(void) } void __gcov_flush(void); -void coverage_exit(void) +static void coverage_exit(void *unused) { #if CONFIG_DEBUG_COVERAGE printk(BIOS_DEBUG, "Syncing coverage data.\n"); @@ -150,4 +150,8 @@ void coverage_exit(void) __gcov_flush(); } - +BOOT_STATE_INIT_ENTRIES(gcov_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, coverage_init, NULL), + BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, coverage_exit, NULL), + BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, coverage_exit, NULL), +}; diff --git a/src/lib/gpio.c b/src/lib/gpio.c new file mode 100644 index 0000000000..e77f4a57e4 --- /dev/null +++ b/src/lib/gpio.c @@ -0,0 +1,145 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +int gpio_base2_value(gpio_t gpio[], int num_gpio) +{ + int i, result = 0; + + for (i = 0; i < num_gpio; i++) + gpio_input(gpio[i]); + + /* Wait until signals become stable */ + udelay(10); + + for (i = 0; i < num_gpio; i++) + result |= gpio_get(gpio[i]) << i; + + return result; +} + +int _gpio_base3_value(gpio_t gpio[], int num_gpio, int binary_first) +{ + /* + * GPIOs which are tied to stronger external pull up or pull down + * will stay there regardless of the internal pull up or pull + * down setting. + * + * GPIOs which are floating will go to whatever level they're + * internally pulled to. + */ + + static const char tristate_char[] = {[0] = '0', [1] = '1', [Z] = 'Z'}; + int temp; + int index; + int result = 0; + int has_z = 0; + int binary_below = 0; + char value[32]; + assert(num_gpio <= 32); + + /* Enable internal pull up */ + for (index = 0; index < num_gpio; ++index) + gpio_input_pullup(gpio[index]); + + /* Wait until signals become stable */ + udelay(10); + + /* Get gpio values at internal pull up */ + for (index = 0; index < num_gpio; ++index) + value[index] = gpio_get(gpio[index]); + + /* Enable internal pull down */ + for (index = 0; index < num_gpio; ++index) + gpio_input_pulldown(gpio[index]); + + /* Wait until signals become stable */ + udelay(10); + + /* + * Get gpio values at internal pull down. + * Compare with gpio pull up value and then + * determine a gpio final value/state: + * 0: pull down + * 1: pull up + * 2: floating + */ + printk(BIOS_DEBUG, "Reading tristate GPIOs: "); + for (index = num_gpio - 1; index >= 0; --index) { + temp = gpio_get(gpio[index]); + temp |= ((value[index] ^ temp) << 1); + printk(BIOS_DEBUG, "%c ", tristate_char[temp]); + result = (result * 3) + temp; + + /* + * For binary_first we keep track of the normal ternary result + * and whether we found any pin that was a Z. We also determine + * the amount of numbers that can be represented with only + * binary digits (no Z) whose value in the normal ternary system + * is lower than the one we are parsing. Counting from the left, + * we add 2^i for any '1' digit to account for the binary + * numbers whose values would be below it if all following + * digits we parsed would be '0'. As soon as we find a '2' digit + * we can total the remaining binary numbers below as 2^(i+1) + * because we know that all binary representations counting only + * this and following digits must have values below our number + * (since 1xxx is always smaller than 2xxx). + * + * Example: 1 0 2 1 (counting from the left / most significant) + * '1' at 3^3: Add 2^3 = 8 to account for binaries 0000-0111 + * '0' at 3^2: Ignore (not all binaries 1000-1100 are below us) + * '2' at 3^1: Add 2^(1+1) = 4 to account for binaries 1000-1011 + * Stop adding for lower digits (3^0), all already accounted + * now. We know that there can be no binary numbers 1020-102X. + */ + if (binary_first && !has_z) { + switch(temp) { + case 0: /* Ignore '0' digits. */ + break; + case 1: /* Account for binaries 0 to 2^index - 1. */ + binary_below += 1 << index; + break; + case 2: /* Account for binaries 0 to 2^(index+1) - 1. */ + binary_below += 1 << (index + 1); + has_z = 1; + } + } + } + + if (binary_first) { + if (has_z) + result = result + (1 << num_gpio) - binary_below; + else /* binary_below is normal binary system value if !has_z. */ + result = binary_below; + } + + printk(BIOS_DEBUG, "= %d (%s base3 number system)\n", result, + binary_first ? "binary_first" : "standard"); + + /* Disable pull up / pull down to conserve power */ + for (index = 0; index < num_gpio; ++index) + gpio_input(gpio[index]); + + return result; +} diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index a3ee10bef2..394a4d71bc 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -1,23 +1,20 @@ /* -This software and ancillary information (herein called SOFTWARE ) -called LinuxBIOS is made available under the terms described -here. The SOFTWARE has been approved for release with associated -LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has -been authored by an employee or employees of the University of -California, operator of the Los Alamos National Laboratory under -Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The -U.S. Government has rights to use, reproduce, and distribute this -SOFTWARE. The public may copy, distribute, prepare derivative works -and publicly display this SOFTWARE without charge, provided that this -Notice and any statement of authorship are reproduced on all copies. -Neither the Government nor the University makes any warranty, express -or implied, or assumes any liability or responsibility for the use of -this SOFTWARE. If SOFTWARE is modified to produce derivative works, -such modified SOFTWARE should be clearly marked, so as not to confuse -it with the version available from LANL. - */ -/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL - * rminnich@lanl.gov + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,7 +22,10 @@ it with the version available from LANL. * C Bootstrap code for the coreboot */ +#include +#include #include +#include #include #include #include @@ -33,115 +33,539 @@ it with the version available from LANL. #include #include #include -#include #include #include #if CONFIG_HAVE_ACPI_RESUME #include #endif -#include -#include +#include #include +#include -/** - * @brief Main function of the RAM part of coreboot. - * - * Coreboot is divided into Pre-RAM part and RAM part. - * - * Device Enumeration: - * In the dev_enumerate() phase, - */ - -void hardwaremain(int boot_complete); - -void hardwaremain(int boot_complete) -{ - struct lb_memory *lb_mem; - void *payload; - - timestamp_stash(TS_START_RAMSTAGE); - post_code(POST_ENTRY_RAMSTAGE); - -#if CONFIG_COVERAGE - coverage_init(); +#if BOOT_STATE_DEBUG +#define BS_DEBUG_LVL BIOS_DEBUG +#else +#define BS_DEBUG_LVL BIOS_NEVER #endif +static boot_state_t bs_pre_device(void *arg); +static boot_state_t bs_dev_init_chips(void *arg); +static boot_state_t bs_dev_enumerate(void *arg); +static boot_state_t bs_dev_resources(void *arg); +static boot_state_t bs_dev_eanble(void *arg); +static boot_state_t bs_dev_init(void *arg); +static boot_state_t bs_post_device(void *arg); +static boot_state_t bs_os_resume_check(void *arg); +static boot_state_t bs_os_resume(void *arg); +static boot_state_t bs_write_tables(void *arg); +static boot_state_t bs_payload_load(void *arg); +static boot_state_t bs_payload_boot(void *arg); + +/* + * Typically a state will take 4 time samples: + * 1. Before state entry callbacks + * 2. After state entry callbacks / Before state function. + * 3. After state function / Before state exit callbacks. + * 4. After state exit callbacks. + */ +#define MAX_TIME_SAMPLES 4 +struct boot_state_times { + int num_samples; + struct mono_time samples[MAX_TIME_SAMPLES]; +}; + +/* The prologue (BS_ON_ENTRY) and epilogue (BS_ON_EXIT) of a state can be + * blocked from transitioning to the next (state,seq) pair. When the blockers + * field is 0 a transition may occur. */ +struct boot_phase { + struct boot_state_callback *callbacks; + int blockers; +}; + +struct boot_state { + const char *name; + boot_state_t id; + u8 post_code; + struct boot_phase phases[2]; + boot_state_t (*run_state)(void *arg); + void *arg; + int complete : 1; +#if CONFIG_HAVE_MONOTONIC_TIMER + struct boot_state_times times; +#endif +}; + +#define BS_INIT(state_, run_func_) \ + { \ + .name = #state_, \ + .id = state_, \ + .post_code = POST_ ## state_, \ + .phases = { { NULL, 0 }, { NULL, 0 } }, \ + .run_state = run_func_, \ + .arg = NULL, \ + .complete = 0, \ + } +#define BS_INIT_ENTRY(state_, run_func_) \ + [state_] = BS_INIT(state_, run_func_) + +static struct boot_state boot_states[] = { + BS_INIT_ENTRY(BS_PRE_DEVICE, bs_pre_device), + BS_INIT_ENTRY(BS_DEV_INIT_CHIPS, bs_dev_init_chips), + BS_INIT_ENTRY(BS_DEV_ENUMERATE, bs_dev_enumerate), + BS_INIT_ENTRY(BS_DEV_RESOURCES, bs_dev_resources), + BS_INIT_ENTRY(BS_DEV_ENABLE, bs_dev_eanble), + BS_INIT_ENTRY(BS_DEV_INIT, bs_dev_init), + BS_INIT_ENTRY(BS_POST_DEVICE, bs_post_device), + BS_INIT_ENTRY(BS_OS_RESUME_CHECK, bs_os_resume_check), + BS_INIT_ENTRY(BS_OS_RESUME, bs_os_resume), + BS_INIT_ENTRY(BS_WRITE_TABLES, bs_write_tables), + BS_INIT_ENTRY(BS_PAYLOAD_LOAD, bs_payload_load), + BS_INIT_ENTRY(BS_PAYLOAD_BOOT, bs_payload_boot), +}; + +static boot_state_t bs_pre_device(void *arg) +{ + return BS_DEV_INIT_CHIPS; +} + +static boot_state_t bs_dev_init_chips(void *arg) +{ + timestamp_add_now(TS_DEVICE_ENUMERATE); + + /* Initialize chips early, they might disable unused devices. */ + dev_initialize_chips(); + + return BS_DEV_ENUMERATE; +} + +static boot_state_t bs_dev_enumerate(void *arg) +{ + /* Find the devices we don't have hard coded knowledge about. */ + dev_enumerate(); + + return BS_DEV_RESOURCES; +} + +static boot_state_t bs_dev_resources(void *arg) +{ + timestamp_add_now(TS_DEVICE_CONFIGURE); + + /* Now compute and assign the bus resources. */ + dev_configure(); + + return BS_DEV_ENABLE; +} + +static boot_state_t bs_dev_eanble(void *arg) +{ + timestamp_add_now(TS_DEVICE_ENABLE); + + /* Now actually enable devices on the bus */ + dev_enable(); + + return BS_DEV_INIT; +} + +static boot_state_t bs_dev_init(void *arg) +{ + timestamp_add_now(TS_DEVICE_INITIALIZE); + + /* And of course initialize devices on the bus */ + dev_initialize(); + + return BS_POST_DEVICE; +} + +static boot_state_t bs_post_device(void *arg) +{ + dev_finalize(); + timestamp_add_now(TS_DEVICE_DONE); + + return BS_OS_RESUME_CHECK; +} + +static boot_state_t bs_os_resume_check(void *arg) +{ +#if CONFIG_HAVE_ACPI_RESUME + void *wake_vector; + + wake_vector = acpi_find_wakeup_vector(); + + if (wake_vector != NULL) { + boot_states[BS_OS_RESUME].arg = wake_vector; + return BS_OS_RESUME; + } +#endif + timestamp_add_now(TS_CBMEM_POST); + + return BS_WRITE_TABLES; +} + +static boot_state_t bs_os_resume(void *wake_vector) +{ +#if CONFIG_HAVE_ACPI_RESUME + acpi_resume(wake_vector); +#endif + return BS_WRITE_TABLES; +} + +static boot_state_t bs_write_tables(void *arg) +{ + timestamp_add_now(TS_WRITE_TABLES); + + /* Now that we have collected all of our information + * write our configuration tables. + */ + write_tables(); + + dev_finalize_chips(); + + return BS_PAYLOAD_LOAD; +} + +/* This is something we don't want to use most of the time. + * It is for debug only. Hence, it is not a config variable. + * It is done this way so people can control it from + * build or at runtime via gdb/jtag. The amount of code it + * adds is insignificant. + */ +static int chooser = 0; + +static boot_state_t bs_payload_load(void *arg) +{ + void *payload = NULL; + void *entry; + const char *payload_name = CONFIG_CBFS_PREFIX "/payload"; + + timestamp_add_now(TS_LOAD_PAYLOAD); + + if (chooser) { + static char chosen[128]; + static struct cbfs_payload_info info[16]; + int i; + int npayloads; + + printk(BIOS_SPEW, "Payloads:\n"); + npayloads = cbfs_payload_headers(CBFS_DEFAULT_MEDIA, + info, ARRAY_SIZE(info)); + for(i = 0; i < npayloads; i++) + printk(BIOS_INFO, "%s\n", info[i].name); + while (! payload) { + printk(BIOS_SPEW, "Pick one>"); + for(i = 0; i < sizeof(chosen); i++) { + chosen[i] = console_rx_byte(); + console_tx_byte(chosen[i]); + if ((chosen[i] == '\n') || (chosen[i] == '\r')) { + chosen[i] = 0; + break; + } + } + printk(BIOS_SPEW, "Try to get :%s:\n", chosen); + payload_name = chosen; + payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA, + payload_name); + } + } + + if (! payload) + payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA, + payload_name); + if (! payload) + die("Could not find a payload\n"); + + entry = selfload(get_lb_mem(), payload); + + if (! entry) + die("Could not load payload\n"); + + /* Pass the payload to the next state. */ + boot_states[BS_PAYLOAD_BOOT].arg = entry; + + return BS_PAYLOAD_BOOT; +} + +static boot_state_t bs_payload_boot(void *entry) +{ + selfboot(entry); + + printk(BIOS_EMERG, "Boot failed"); + /* Returning from this state will fail because the following signals + * return to a completed state. */ + return BS_PAYLOAD_BOOT; +} + +#if CONFIG_HAVE_MONOTONIC_TIMER +static void bs_sample_time(struct boot_state *state) +{ + struct mono_time *mt; + + mt = &state->times.samples[state->times.num_samples]; + timer_monotonic_get(mt); + state->times.num_samples++; +} + +static void bs_report_time(struct boot_state *state) +{ + long entry_time; + long run_time; + long exit_time; + struct mono_time *samples = &state->times.samples[0]; + + entry_time = mono_time_diff_microseconds(&samples[0], &samples[1]); + run_time = mono_time_diff_microseconds(&samples[1], &samples[2]); + exit_time = mono_time_diff_microseconds(&samples[2], &samples[3]); + + printk(BIOS_DEBUG, "BS: %s times (us): entry %ld run %ld exit %ld\n", + state->name, entry_time, run_time, exit_time); +} +#else +static inline void bs_sample_time(struct boot_state *state) {} +static inline void bs_report_time(struct boot_state *state) {} +#endif + +#if CONFIG_TIMER_QUEUE +static void bs_run_timers(int drain) +{ + /* Drain all timer callbacks until none are left, if directed. + * Otherwise run the timers only once. */ + do { + if (!timers_run()) + break; + } while (drain); +} +#else +static void bs_run_timers(int drain) {} +#endif + +static void bs_call_callbacks(struct boot_state *state, + boot_state_sequence_t seq) +{ + struct boot_phase *phase = &state->phases[seq]; + + while (1) { + if (phase->callbacks != NULL) { + struct boot_state_callback *bscb; + + /* Remove the first callback. */ + bscb = phase->callbacks; + phase->callbacks = bscb->next; + bscb->next = NULL; + +#if BOOT_STATE_DEBUG + printk(BS_DEBUG_LVL, "BS: callback (%p) @ %s.\n", + bscb, bscb->location); +#endif + bscb->callback(bscb->arg); + + continue; + } + + /* All callbacks are complete and there are no blockers for + * this state. Therefore, this part of the state is complete. */ + if (!phase->blockers) + break; + + /* Something is blocking this state from transitioning. As + * there are no more callbacks a pending timer needs to be + * ran to unblock the state. */ + bs_run_timers(0); + } +} + +/* Keep track of the current state. */ +static struct state_tracker { + boot_state_t state_id; + boot_state_sequence_t seq; +} current_phase = { + .state_id = BS_PRE_DEVICE, + .seq = BS_ON_ENTRY, +}; + +static void bs_walk_state_machine(void) +{ + + while (1) { + struct boot_state *state; + boot_state_t next_id; + + state = &boot_states[current_phase.state_id]; + + if (state->complete) { + printk(BIOS_EMERG, "BS: %s state already executed.\n", + state->name); + break; + } + + printk(BS_DEBUG_LVL, "BS: Entering %s state.\n", state->name); + + bs_run_timers(0); + + bs_sample_time(state); + + bs_call_callbacks(state, current_phase.seq); + /* Update the current sequence so that any calls to block the + * current state from the run_state() function will place a + * block on the correct phase. */ + current_phase.seq = BS_ON_EXIT; + + bs_sample_time(state); + + post_code(state->post_code); + + next_id = state->run_state(state->arg); + + printk(BS_DEBUG_LVL, "BS: Exiting %s state.\n", state->name); + + bs_sample_time(state); + + bs_call_callbacks(state, current_phase.seq); + + /* Update the current phase with new state id and sequence. */ + current_phase.state_id = next_id; + current_phase.seq = BS_ON_ENTRY; + + bs_sample_time(state); + + bs_report_time(state); + + state->complete = 1; + } +} + +static int boot_state_sched_callback(struct boot_state *state, + struct boot_state_callback *bscb, + boot_state_sequence_t seq) +{ + if (state->complete) { + printk(BIOS_WARNING, + "Tried to schedule callback on completed state %s.\n", + state->name); + + return -1; + } + + bscb->next = state->phases[seq].callbacks; + state->phases[seq].callbacks = bscb; + + return 0; +} + +int boot_state_sched_on_entry(struct boot_state_callback *bscb, + boot_state_t state_id) +{ + struct boot_state *state = &boot_states[state_id]; + + return boot_state_sched_callback(state, bscb, BS_ON_ENTRY); +} + +int boot_state_sched_on_exit(struct boot_state_callback *bscb, + boot_state_t state_id) +{ + struct boot_state *state = &boot_states[state_id]; + + return boot_state_sched_callback(state, bscb, BS_ON_EXIT); +} + +static void boot_state_schedule_static_entries(void) +{ + extern struct boot_state_init_entry _bs_init_begin; + extern struct boot_state_init_entry _bs_init_end; + struct boot_state_init_entry *cur; + + cur = &_bs_init_begin; + + while (cur != &_bs_init_end) { + if (cur->when == BS_ON_ENTRY) + boot_state_sched_on_entry(&cur->bscb, cur->state); + else + boot_state_sched_on_exit(&cur->bscb, cur->state); + cur++; + } +} + +void main(void) +{ + timestamp_add_now(TS_START_RAMSTAGE); + post_code(POST_ENTRY_RAMSTAGE); + /* console_init() MUST PRECEDE ALL printk()! */ console_init(); post_code(POST_CONSOLE_READY); - printk(BIOS_NOTICE, "coreboot-%s%s %s %s...\n", - coreboot_version, coreboot_extra_version, coreboot_build, - (boot_complete)?"rebooting":"booting"); + printk(BIOS_NOTICE, "coreboot-%s%s %s booting...\n", + coreboot_version, coreboot_extra_version, coreboot_build); post_code(POST_CONSOLE_BOOT_MSG); - /* If we have already booted attempt a hard reboot */ - if (boot_complete) { - hard_reset(); - } + exception_init(); + threads_initialize(); - /* FIXME: Is there a better way to handle this? */ - init_timer(); + /* Schedule the static boot state entries. */ + boot_state_schedule_static_entries(); - init_cbmem_pre_device(); + /* TODO: Understand why this is here and move to arch/platform code. */ + if (IS_ENABLED(CONFIG_ARCH_X86)) + init_timer(); - timestamp_stash(TS_DEVICE_ENUMERATE); + bs_walk_state_machine(); - /* Initialize chips early, they might disable unused devices. */ - dev_initialize_chips(); - - /* Find the devices we don't have hard coded knowledge about. */ - dev_enumerate(); - post_code(POST_DEVICE_ENUMERATION_COMPLETE); - - timestamp_stash(TS_DEVICE_CONFIGURE); - /* Now compute and assign the bus resources. */ - dev_configure(); - post_code(POST_DEVICE_CONFIGURATION_COMPLETE); - - timestamp_stash(TS_DEVICE_ENABLE); - /* Now actually enable devices on the bus */ - dev_enable(); - post_code(POST_DEVICES_ENABLED); - - timestamp_stash(TS_DEVICE_INITIALIZE); - /* And of course initialize devices on the bus */ - dev_initialize(); - post_code(POST_DEVICES_INITIALIZED); - - timestamp_stash(TS_DEVICE_DONE); - - init_cbmem_post_device(); - - timestamp_sync(); - -#if CONFIG_HAVE_ACPI_RESUME - suspend_resume(); - post_code(0x8a); -#endif - - timestamp_add_now(TS_CBMEM_POST); - - if (cbmem_post_handling) - cbmem_post_handling(); - - timestamp_add_now(TS_WRITE_TABLES); - - /* Now that we have collected all of our information - * write our configuration tables. - */ - lb_mem = write_tables(); - - timestamp_add_now(TS_LOAD_PAYLOAD); - - payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA, - CONFIG_CBFS_PREFIX "/payload"); - if (! payload) - die("Could not find a payload\n"); - - selfboot(lb_mem, payload); - printk(BIOS_EMERG, "Boot failed"); + die("Boot state machine failure.\n"); } + +int boot_state_block(boot_state_t state, boot_state_sequence_t seq) +{ + struct boot_phase *bp; + + /* Blocking a previously ran state is not appropriate. */ + if (current_phase.state_id > state || + (current_phase.state_id == state && current_phase.seq > seq) ) { + printk(BIOS_WARNING, + "BS: Completed state (%d, %d) block attempted.\n", + state, seq); + return -1; + } + + bp = &boot_states[state].phases[seq]; + bp->blockers++; + + return 0; +} + +int boot_state_unblock(boot_state_t state, boot_state_sequence_t seq) +{ + struct boot_phase *bp; + + /* Blocking a previously ran state is not appropriate. */ + if (current_phase.state_id > state || + (current_phase.state_id == state && current_phase.seq > seq) ) { + printk(BIOS_WARNING, + "BS: Completed state (%d, %d) unblock attempted.\n", + state, seq); + return -1; + } + + bp = &boot_states[state].phases[seq]; + + if (bp->blockers == 0) { + printk(BIOS_WARNING, + "BS: Unblock attempted on non-blocked state (%d, %d).\n", + state, seq); + return -1; + } + + bp->blockers--; + + return 0; +} + +void boot_state_current_block(void) +{ + boot_state_block(current_phase.state_id, current_phase.seq); +} + +void boot_state_current_unblock(void) +{ + boot_state_unblock(current_phase.state_id, current_phase.seq); +} diff --git a/src/lib/hexdump.c b/src/lib/hexdump.c new file mode 100644 index 0000000000..a15c5cdb11 --- /dev/null +++ b/src/lib/hexdump.c @@ -0,0 +1,81 @@ +/* + * Copyright 2013 Google Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +static int isprint(int c) +{ + return (c >= 32 && c <= 126); +} + +void hexdump(const void *memory, size_t length) +{ + int i; + uint8_t *m; + int all_zero = 0; + + m = (uint8_t *) memory; + + for (i = 0; i < length; i += 16) { + int j; + + all_zero++; + for (j = 0; j < 16; j++) { + if (m[i + j] != 0) { + all_zero = 0; + break; + } + } + + if (all_zero < 2) { + printk(BIOS_DEBUG, "%p:", memory + i); + for (j = 0; j < 16; j++) + printk(BIOS_DEBUG, " %02x", m[i + j]); + printk(BIOS_DEBUG, " "); + for (j = 0; j < 16; j++) + printk(BIOS_DEBUG, "%c", + isprint(m[i + j]) ? m[i + j] : '.'); + printk(BIOS_DEBUG, "\n"); + } else if (all_zero == 2) { + printk(BIOS_DEBUG, "...\n"); + } + } +} + +void hexdump32(char LEVEL, const void *d, size_t len) +{ + int count = 0; + + while (len > 0) { + if (count % 8 == 0) { + printk(LEVEL, "\n"); + printk(LEVEL, "%p:", d); + } + printk(LEVEL, " 0x%08lx", *(unsigned long *)d); + count++; + len--; + d += 4; + } + + printk(LEVEL, "\n\n"); +} diff --git a/src/lib/lzma.c b/src/lib/lzma.c index cd60b3f3b2..8ba9037454 100644 --- a/src/lib/lzma.c +++ b/src/lib/lzma.c @@ -13,6 +13,7 @@ #include #include #include +#include unsigned long ulzma(unsigned char * src, unsigned char * dst) { @@ -23,14 +24,11 @@ unsigned long ulzma(unsigned char * src, unsigned char * dst) int res; CLzmaDecoderState state; SizeT mallocneeds; -#if !defined(__PRE_RAM__) - /* in ramstage, this can go in BSS */ - static -#endif - /* in pre-ram, it must go on the stack */ - unsigned char scratchpad[15980]; + MAYBE_STATIC unsigned char scratchpad[15980]; unsigned char *cp; + /* Note: these timestamps aren't useful for memory-mapped media (x86) */ + timestamp_add_now(TS_START_ULZMA); memcpy(properties, src, LZMA_PROPERTIES_SIZE); /* The outSize in LZMA stream is a 64bit integer stored in little-endian * (ref: lzma.cc@LZMACompress: put_64). To prevent accessing by @@ -54,5 +52,6 @@ unsigned long ulzma(unsigned char * src, unsigned char * dst) printk(BIOS_WARNING, "lzma: Decoding error = %d\n", res); return 0; } + timestamp_add_now(TS_END_ULZMA); return outSize; } diff --git a/src/lib/memrange.c b/src/lib/memrange.c index 1a16ef73ab..910c07c1f4 100644 --- a/src/lib/memrange.c +++ b/src/lib/memrange.c @@ -215,6 +215,9 @@ static void do_action(struct memranges *ranges, resource_t end; resource_t begin; + if (size == 0) + return; + /* The addresses are aligned to 4096 bytes: the begin address is * aligned down while the end address is aligned up to be conservative * about the full range covered. */ @@ -263,11 +266,16 @@ void memranges_add_resources(struct memranges *ranges, search_global_resources(mask, match, collect_ranges, &context); } +void memranges_init_empty(struct memranges *ranges) +{ + ranges->entries = NULL; +} + void memranges_init(struct memranges *ranges, unsigned long mask, unsigned long match, unsigned long tag) { - ranges->entries = NULL; + memranges_init_empty(ranges); memranges_add_resources(ranges, mask, match, tag); } diff --git a/src/lib/primitive_memtest.c b/src/lib/primitive_memtest.c new file mode 100644 index 0000000000..d59d25fd92 --- /dev/null +++ b/src/lib/primitive_memtest.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +int primitive_memtest(uintptr_t base, uintptr_t size) +{ + uintptr_t *p; + uintptr_t i; + int bad = 0; + + printk(BIOS_SPEW, "Performing primitive memory test.\n"); + printk(BIOS_SPEW, "DRAM start: 0x%08x, DRAM size: 0x%08x", base, size); + for(i = base; i < base + (size - 1) - sizeof(p); i += sizeof(p)) { + if (i % 0x100000 == 0) { + if ((i % 0x800000) == 0) + printk(BIOS_SPEW, "\n"); + else if (i != 0) + printk(BIOS_SPEW, " "); + printk(BIOS_SPEW, "0x%08x", i); + } + p = (uintptr_t *)i; + *p = i; + } + + printk(BIOS_SPEW, "\n\nReading back DRAM content"); + for(i = base; i < base + (size - 1) - sizeof(p); i += sizeof(p)) { + if (i % 0x100000 == 0) { + if ((i % 0x800000) == 0) + printk(BIOS_SPEW, "\n"); + else if (i != 0) + printk(BIOS_SPEW, " "); + printk(BIOS_SPEW, "0x%08x", i); + } + + p = (uintptr_t *)i; + if (*p != i) { + printk(BIOS_SPEW, "\n0x%08zx: got 0x%zx\n", i, *p); + bad++; + } + } + + printk(BIOS_SPEW, "\n"); + printk(BIOS_SPEW, "%d errors\n", bad); + + return bad; +} diff --git a/src/lib/ramstage.ld b/src/lib/ramstage.ld new file mode 100644 index 0000000000..732c8e903c --- /dev/null +++ b/src/lib/ramstage.ld @@ -0,0 +1,117 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file is included inside a SECTIONS block */ + +/* First we place the code and read only data (typically const declared). + * This could theoretically be placed in rom. + */ +.text : { + _program = .; + _ramstage = .; + _text = .; + *(.text._start); + *(.text.stage_entry); + *(.text); + *(.text.*); + . = ALIGN(16); + _etext = .; +} : to_load + +#ifdef CONFIG_COVERAGE +.ctors : { + . = ALIGN(0x100); + __CTOR_LIST__ = .; + KEEP(*(.ctors)); + LONG(0); + LONG(0); + __CTOR_END__ = .; +} +#endif + +/* TODO: align data sections to cache lines? (is that really useful?) */ +.rodata : { + _rodata = .; + . = ALIGN(8); + + /* If any changes are made to the driver start/symbols or the + * section names the equivalent changes need to made to + * rmodule.ld. */ + console_drivers = .; + KEEP(*(.rodata.console_drivers)); + econsole_drivers = . ; + . = ALIGN(8); + pci_drivers = . ; + KEEP(*(.rodata.pci_driver)); + epci_drivers = . ; + cpu_drivers = . ; + KEEP(*(.rodata.cpu_driver)); + ecpu_drivers = . ; + _bs_init_begin = .; + KEEP(*(.bs_init)); + _bs_init_end = .; + _cbmem_init_hooks = .; + KEEP(*(.rodata.cbmem_init_hooks)); + _ecbmem_init_hooks = .; + + *(.rodata) + *(.rodata.*) + /* kevinh/Ispiri - Added an align, because the objcopy tool + * incorrectly converts sections that are not long word aligned. + */ + . = ALIGN(8); + + _erodata = .; +} + +.data : { + /* Move to different cache line to avoid false sharing with .rodata. */ + . = ALIGN(64); /* May not be actual line size, not that important. */ + _data = .; + *(.data) + *(.data.*) + _edata = .; +} + +.bss . : { + _bss = .; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + _ebss = .; +} + +.heap . : { + _heap = .; + /* Reserve CONFIG_HEAP_SIZE bytes for the heap */ + . += CONFIG_HEAP_SIZE ; + . = ALIGN(4); + _eheap = .; + _eramstage = .; + _eprogram = .; +} + +/* Discard the sections we don't need/want */ + +/DISCARD/ : { + *(.comment) + *(.note) + *(.note.*) +} diff --git a/src/lib/ramstage_cache.c b/src/lib/ramstage_cache.c new file mode 100644 index 0000000000..0f7273a961 --- /dev/null +++ b/src/lib/ramstage_cache.c @@ -0,0 +1,144 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM + +void cache_loaded_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage, + void *entry_point) +{ + struct ramstage_cache *cache; + uint32_t total_size; + uint32_t ramstage_size; + void *ramstage_base; + long cache_size = 0; + + ramstage_size = cbmem_entry_size(ramstage); + ramstage_base = cbmem_entry_start(ramstage); + + cache = ramstage_cache_location(&cache_size); + + if (cache == NULL) { + printk(BIOS_DEBUG, "No ramstage cache location provided.\n"); + return; + } + + total_size = sizeof(*cache) + ramstage_size; + if (total_size > cache_size) { + printk(BIOS_DEBUG, "cache size too small: 0x%08x > 0x%08lx\n", + total_size, cache_size); + /* Nuke whatever may be there now just in case. */ + cache->magic = ~RAMSTAGE_CACHE_MAGIC; + return; + } + + cache->magic = RAMSTAGE_CACHE_MAGIC; + cache->entry_point = (uint32_t)entry_point; + cache->load_address = (uint32_t)ramstage_base; + cache->size = ramstage_size; + + printk(BIOS_DEBUG, "Saving ramstage to %p.\n", cache); + + /* Copy over the program. */ + memcpy(&cache->program[0], ramstage_base, ramstage_size); + + if (handoff == NULL) + return; + + handoff->ramstage_entry_point = (uint32_t)entry_point; +} + +void *load_cached_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage) +{ + struct ramstage_cache *cache; + long size = 0; + + cache = ramstage_cache_location(&size); + + if (!ramstage_cache_is_valid(cache)) { + printk(BIOS_DEBUG, "Invalid ramstage cache found.\n"); + ramstage_cache_invalid(cache); + return NULL; + } + + printk(BIOS_DEBUG, "Loading ramstage from %p.\n", cache); + + memcpy((void *)cache->load_address, &cache->program[0], cache->size); + + return (void *)cache->entry_point; +} + +#else + +/* Cache relocated ramstage in CBMEM. */ + +void __attribute__((weak)) +cache_loaded_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage, void *entry_point) +{ + uint32_t ramstage_size; + const struct cbmem_entry *entry; + + if (handoff == NULL) + return; + + ramstage_size = cbmem_entry_size(ramstage); + /* cbmem_entry_add() does a find() before add(). */ + entry = cbmem_entry_add(CBMEM_ID_RAMSTAGE_CACHE, ramstage_size); + + if (entry == NULL) + return; + + /* Keep track of the entry point in the handoff structure. */ + handoff->ramstage_entry_point = (uint32_t)entry_point; + + memcpy(cbmem_entry_start(entry), cbmem_entry_start(ramstage), + ramstage_size); +} + +void * __attribute__((weak)) +load_cached_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage) +{ + const struct cbmem_entry *entry_cache; + + if (handoff == NULL) + return NULL; + + entry_cache = cbmem_entry_find(CBMEM_ID_RAMSTAGE_CACHE); + + if (entry_cache == NULL) + return NULL; + + /* Load the cached ramstage copy into the to-be-run region. */ + memcpy(cbmem_entry_start(ramstage), cbmem_entry_start(entry_cache), + cbmem_entry_size(ramstage)); + + return (void *)handoff->ramstage_entry_point; +} + +#endif diff --git a/src/lib/reg_script.c b/src/lib/reg_script.c new file mode 100644 index 0000000000..9c72024b9b --- /dev/null +++ b/src/lib/reg_script.c @@ -0,0 +1,610 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_ARCH_X86 +#include +#endif + +#if CONFIG_SOC_INTEL_BAYTRAIL +#include /* TODO: wrap in dev = dev; + ctx->res = NULL; +} + +static inline void reg_script_set_step(struct reg_script_context *ctx, + const struct reg_script *step) +{ + ctx->step = step; +} + +static inline const struct reg_script * +reg_script_get_step(struct reg_script_context *ctx) +{ + return ctx->step; +} + +static struct resource *reg_script_get_resource(struct reg_script_context *ctx) +{ +#if defined(__PRE_RAM__) + return NULL; +#else + struct resource *res; + const struct reg_script *step = reg_script_get_step(ctx); + + res = ctx->res; + + if (res != NULL && res->index == step->res_index) + return res; + + res = find_resource(ctx->dev, step->res_index); + ctx->res = res; + return res; +#endif +} + +static uint32_t reg_script_read_pci(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + return pci_read_config8(ctx->dev, step->reg); + case REG_SCRIPT_SIZE_16: + return pci_read_config16(ctx->dev, step->reg); + case REG_SCRIPT_SIZE_32: + return pci_read_config32(ctx->dev, step->reg); + } + return 0; +} + +static void reg_script_write_pci(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + pci_write_config8(ctx->dev, step->reg, step->value); + break; + case REG_SCRIPT_SIZE_16: + pci_write_config16(ctx->dev, step->reg, step->value); + break; + case REG_SCRIPT_SIZE_32: + pci_write_config32(ctx->dev, step->reg, step->value); + break; + } +} + +static uint32_t reg_script_read_io(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + return inb(step->reg); + case REG_SCRIPT_SIZE_16: + return inw(step->reg); + case REG_SCRIPT_SIZE_32: + return inl(step->reg); + } + return 0; +} + +static void reg_script_write_io(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + outb(step->value, step->reg); + break; + case REG_SCRIPT_SIZE_16: + outw(step->value, step->reg); + break; + case REG_SCRIPT_SIZE_32: + outl(step->value, step->reg); + break; + } +} + +static uint32_t reg_script_read_mmio(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + return read8(step->reg); + case REG_SCRIPT_SIZE_16: + return read16(step->reg); + case REG_SCRIPT_SIZE_32: + return read32(step->reg); + } + return 0; +} + +static void reg_script_write_mmio(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->size) { + case REG_SCRIPT_SIZE_8: + write8(step->reg, step->value); + break; + case REG_SCRIPT_SIZE_16: + write16(step->reg, step->value); + break; + case REG_SCRIPT_SIZE_32: + write32(step->reg, step->value); + break; + } +} + +static uint32_t reg_script_read_res(struct reg_script_context *ctx) +{ + struct resource *res; + uint32_t val = 0; + const struct reg_script *step = reg_script_get_step(ctx); + + res = reg_script_get_resource(ctx); + + if (res == NULL) + return val; + + if (res->flags & IORESOURCE_IO) { + const struct reg_script io_step = { + .size = step->size, + .reg = res->base + step->reg, + }; + reg_script_set_step(ctx, &io_step); + val = reg_script_read_io(ctx); + } + else if (res->flags & IORESOURCE_MEM) { + const struct reg_script mmio_step = { + .size = step->size, + .reg = res->base + step->reg, + }; + reg_script_set_step(ctx, &mmio_step); + val = reg_script_read_mmio(ctx); + } + reg_script_set_step(ctx, step); + return val; +} + +static void reg_script_write_res(struct reg_script_context *ctx) +{ + struct resource *res; + const struct reg_script *step = reg_script_get_step(ctx); + + res = reg_script_get_resource(ctx); + + if (res == NULL) + return; + + if (res->flags & IORESOURCE_IO) { + const struct reg_script io_step = { + .size = step->size, + .reg = res->base + step->reg, + .value = step->value, + }; + reg_script_set_step(ctx, &io_step); + reg_script_write_io(ctx); + } + else if (res->flags & IORESOURCE_MEM) { + const struct reg_script mmio_step = { + .size = step->size, + .reg = res->base + step->reg, + .value = step->value, + }; + reg_script_set_step(ctx, &mmio_step); + reg_script_write_mmio(ctx); + } + reg_script_set_step(ctx, step); +} + +#if CONFIG_SOC_INTEL_BAYTRAIL +static uint32_t reg_script_read_iosf(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->id) { + case IOSF_PORT_AUNIT: + return iosf_aunit_read(step->reg); + case IOSF_PORT_CPU_BUS: + return iosf_cpu_bus_read(step->reg); + case IOSF_PORT_BUNIT: + return iosf_bunit_read(step->reg); + case IOSF_PORT_DUNIT_CH0: + return iosf_dunit_ch0_read(step->reg); + case IOSF_PORT_PMC: + return iosf_punit_read(step->reg); + case IOSF_PORT_USBPHY: + return iosf_usbphy_read(step->reg); + case IOSF_PORT_SEC: + return iosf_sec_read(step->reg); + case IOSF_PORT_0x45: + return iosf_port45_read(step->reg); + case IOSF_PORT_0x46: + return iosf_port46_read(step->reg); + case IOSF_PORT_0x47: + return iosf_port47_read(step->reg); + case IOSF_PORT_SCORE: + return iosf_score_read(step->reg); + case IOSF_PORT_0x55: + return iosf_port55_read(step->reg); + case IOSF_PORT_0x58: + return iosf_port58_read(step->reg); + case IOSF_PORT_0x59: + return iosf_port59_read(step->reg); + case IOSF_PORT_0x5a: + return iosf_port5a_read(step->reg); + case IOSF_PORT_USHPHY: + return iosf_ushphy_read(step->reg); + case IOSF_PORT_SCC: + return iosf_scc_read(step->reg); + case IOSF_PORT_LPSS: + return iosf_lpss_read(step->reg); + case IOSF_PORT_0xa2: + return iosf_porta2_read(step->reg); + case IOSF_PORT_CCU: + return iosf_ccu_read(step->reg); + case IOSF_PORT_SSUS: + return iosf_ssus_read(step->reg); + default: + printk(BIOS_DEBUG, "No read support for IOSF port 0x%x.\n", + step->id); + break; + } + return 0; +} + +static void reg_script_write_iosf(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->id) { + case IOSF_PORT_AUNIT: + iosf_aunit_write(step->reg, step->value); + break; + case IOSF_PORT_CPU_BUS: + iosf_cpu_bus_write(step->reg, step->value); + break; + case IOSF_PORT_BUNIT: + iosf_bunit_write(step->reg, step->value); + break; + case IOSF_PORT_DUNIT_CH0: + iosf_dunit_write(step->reg, step->value); + break; + case IOSF_PORT_PMC: + iosf_punit_write(step->reg, step->value); + break; + case IOSF_PORT_USBPHY: + iosf_usbphy_write(step->reg, step->value); + break; + case IOSF_PORT_SEC: + iosf_sec_write(step->reg, step->value); + break; + case IOSF_PORT_0x45: + iosf_port45_write(step->reg, step->value); + break; + case IOSF_PORT_0x46: + iosf_port46_write(step->reg, step->value); + break; + case IOSF_PORT_0x47: + iosf_port47_write(step->reg, step->value); + break; + case IOSF_PORT_SCORE: + iosf_score_write(step->reg, step->value); + break; + case IOSF_PORT_0x55: + iosf_port55_write(step->reg, step->value); + break; + case IOSF_PORT_0x58: + iosf_port58_write(step->reg, step->value); + break; + case IOSF_PORT_0x59: + iosf_port59_write(step->reg, step->value); + break; + case IOSF_PORT_0x5a: + iosf_port5a_write(step->reg, step->value); + break; + case IOSF_PORT_USHPHY: + iosf_ushphy_write(step->reg, step->value); + break; + case IOSF_PORT_SCC: + iosf_scc_write(step->reg, step->value); + break; + case IOSF_PORT_LPSS: + iosf_lpss_write(step->reg, step->value); + break; + case IOSF_PORT_0xa2: + iosf_porta2_write(step->reg, step->value); + break; + case IOSF_PORT_CCU: + iosf_ccu_write(step->reg, step->value); + break; + case IOSF_PORT_SSUS: + iosf_ssus_write(step->reg, step->value); + break; + default: + printk(BIOS_DEBUG, "No write support for IOSF port 0x%x.\n", + step->id); + break; + } +} +#endif + + +static uint64_t reg_script_read_msr(struct reg_script_context *ctx) +{ +#if CONFIG_ARCH_X86 + const struct reg_script *step = reg_script_get_step(ctx); + msr_t msr = rdmsr(step->reg); + uint64_t value = msr.hi; + value = msr.hi; + value <<= 32; + value |= msr.lo; + return value; +#endif +} + +static void reg_script_write_msr(struct reg_script_context *ctx) +{ +#if CONFIG_ARCH_X86 + const struct reg_script *step = reg_script_get_step(ctx); + msr_t msr; + msr.hi = step->value >> 32; + msr.lo = step->value & 0xffffffff; + wrmsr(step->reg, msr); +#endif +} + +#ifndef __PRE_RAM__ +/* Default routine provided for systems without platform specific busses */ +const struct reg_script_bus_entry *__attribute__((weak)) + platform_bus_table(size_t *table_entries) +{ + /* No platform bus type table supplied */ + *table_entries = 0; + return NULL; +} + +/* Locate the structure containing the platform specific bus access routines */ +static const struct reg_script_bus_entry + *find_bus(const struct reg_script *step) +{ + const struct reg_script_bus_entry *bus; + size_t table_entries; + size_t i; + + /* Locate the platform specific bus */ + bus = platform_bus_table(&table_entries); + for (i = 0; i < table_entries; i++) { + if (bus[i].type == step->type) + return &bus[i]; + } + + /* Bus not found */ + return NULL; +} +#endif + +static uint64_t reg_script_read(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->type) { + case REG_SCRIPT_TYPE_PCI: + return reg_script_read_pci(ctx); + case REG_SCRIPT_TYPE_IO: + return reg_script_read_io(ctx); + case REG_SCRIPT_TYPE_MMIO: + return reg_script_read_mmio(ctx); + case REG_SCRIPT_TYPE_RES: + return reg_script_read_res(ctx); + case REG_SCRIPT_TYPE_MSR: + return reg_script_read_msr(ctx); +#if CONFIG_SOC_INTEL_BAYTRAIL + case REG_SCRIPT_TYPE_IOSF: + return reg_script_read_iosf(ctx); +#endif + default: +#ifndef __PRE_RAM__ + { + const struct reg_script_bus_entry *bus; + + /* Read from the platform specific bus */ + bus = find_bus(step); + if (NULL != bus) + return bus->reg_script_read(ctx); + } +#endif + printk(BIOS_ERR, + "Unsupported read type (0x%x) for this device!\n", + step->type); + break; + } + return 0; +} + +static void reg_script_write(struct reg_script_context *ctx) +{ + const struct reg_script *step = reg_script_get_step(ctx); + + switch (step->type) { + case REG_SCRIPT_TYPE_PCI: + reg_script_write_pci(ctx); + break; + case REG_SCRIPT_TYPE_IO: + reg_script_write_io(ctx); + break; + case REG_SCRIPT_TYPE_MMIO: + reg_script_write_mmio(ctx); + break; + case REG_SCRIPT_TYPE_RES: + reg_script_write_res(ctx); + break; + case REG_SCRIPT_TYPE_MSR: + reg_script_write_msr(ctx); + break; +#if CONFIG_SOC_INTEL_BAYTRAIL + case REG_SCRIPT_TYPE_IOSF: + reg_script_write_iosf(ctx); + break; +#endif + default: +#ifndef __PRE_RAM__ + { + const struct reg_script_bus_entry *bus; + + /* Write to the platform specific bus */ + bus = find_bus(step); + if (NULL != bus) { + bus->reg_script_write(ctx); + return; + } + } +#endif + printk(BIOS_ERR, + "Unsupported write type (0x%x) for this device!\n", + step->type); + break; + } +} + +static void reg_script_rmw(struct reg_script_context *ctx) +{ + uint32_t value; + const struct reg_script *step = reg_script_get_step(ctx); + struct reg_script write_step = *step; + + value = reg_script_read(ctx); + value &= step->mask; + value |= step->value; + write_step.value = value; + reg_script_set_step(ctx, &write_step); + reg_script_write(ctx); + reg_script_set_step(ctx, step); +} + +/* In order to easily chain scripts together handle the REG_SCRIPT_COMMAND_NEXT + * as recursive call with a new context that has the same dev and resource + * as the previous one. That will run to completion and then move on to the + * next step of the previous context. */ +static void reg_script_run_next(struct reg_script_context *ctx, + const struct reg_script *step); + + +static void reg_script_run_step(struct reg_script_context *ctx, + const struct reg_script *step) +{ + uint64_t value = 0, try; + + switch (step->command) { + case REG_SCRIPT_COMMAND_READ: + (void)reg_script_read(ctx); + break; + case REG_SCRIPT_COMMAND_WRITE: + reg_script_write(ctx); + break; + case REG_SCRIPT_COMMAND_RMW: + reg_script_rmw(ctx); + break; + case REG_SCRIPT_COMMAND_POLL: + for (try = 0; try < step->timeout; try += POLL_DELAY) { + value = reg_script_read(ctx) & step->mask; + if (value == step->value) + break; + udelay(POLL_DELAY); + } + if (try >= step->timeout) + printk(BIOS_WARNING, "%s: POLL timeout waiting for " + "0x%x to be 0x%lx, got 0x%lx\n", __func__, + step->reg, (unsigned long)step->value, + (unsigned long)value); + break; + case REG_SCRIPT_COMMAND_SET_DEV: + reg_script_set_dev(ctx, step->dev); + break; + case REG_SCRIPT_COMMAND_NEXT: + reg_script_run_next(ctx, step->next); + break; + default: + printk(BIOS_WARNING, "Invalid command: %08x\n", + step->command); + break; + } +} + +static void reg_script_run_with_context(struct reg_script_context *ctx) +{ + while (1) { + const struct reg_script *step = reg_script_get_step(ctx); + + if (step->command == REG_SCRIPT_COMMAND_END) + break; + + reg_script_run_step(ctx, step); + reg_script_set_step(ctx, step + 1); + } +} + +static void reg_script_run_next(struct reg_script_context *prev_ctx, + const struct reg_script *step) +{ + struct reg_script_context ctx; + + /* Use prev context as a basis but start at a new step. */ + ctx = *prev_ctx; + reg_script_set_step(&ctx, step); + reg_script_run_with_context(&ctx); +} + +void reg_script_run_on_dev(device_t dev, const struct reg_script *step) +{ + struct reg_script_context ctx; + + reg_script_set_dev(&ctx, dev); + reg_script_set_step(&ctx, step); + reg_script_run_with_context(&ctx); +} + +void reg_script_run(const struct reg_script *step) +{ + reg_script_run_on_dev(EMPTY_DEV, step); +} diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c index b56ec322be..f3fc38107d 100644 --- a/src/lib/rmodule.c +++ b/src/lib/rmodule.c @@ -20,50 +20,13 @@ #include #include #include +#include #include #include /* Change this define to get more verbose debugging for module loading. */ #define PK_ADJ_LEVEL BIOS_NEVER -#if CONFIG_ARCH_X86 -/* - * On X86, the only relocations currently allowed are R_386_RELATIVE which - * have '0' for the symbol info in the relocation metadata (in r_info). - * The reason is that the module is fully linked and just has the relocations' - * locations. - */ -typedef struct { - u32 r_offset; - u32 r_info; -} Elf32_Rel; - -#define R_386_RELATIVE 8 - -#define RELOCTION_ENTRY_SIZE sizeof(Elf32_Rel) -static inline int rmodule_reloc_offset(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - return rel->r_offset; -} - -static inline int rmodule_reloc_valid(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - return (rel->r_info == R_386_RELATIVE); -} - -static inline void *remodule_next_reloc(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - rel++; - return (void *)rel; -} - -#else -#error Arch needs to add relocation information support for RMODULE -#endif - static inline int rmodule_is_loaded(const struct rmodule *module) { return module->location != NULL; @@ -71,7 +34,7 @@ static inline int rmodule_is_loaded(const struct rmodule *module) /* Calculate a loaded program address based on the blob address. */ static inline void *rmodule_load_addr(const struct rmodule *module, - u32 blob_addr) + uintptr_t blob_addr) { char *loc = module->location; return &loc[blob_addr - module->header->module_link_start_address]; @@ -151,13 +114,13 @@ static void rmodule_clear_bss(struct rmodule *module) memset(begin, 0, size); } -static inline int rmodule_number_relocations(const struct rmodule *module) +static inline size_t rmodule_number_relocations(const struct rmodule *module) { - int r; + size_t r; r = module->header->relocations_end_offset; r -= module->header->relocations_begin_offset; - r /= RELOCTION_ENTRY_SIZE; + r /= sizeof(uintptr_t); return r; } @@ -176,51 +139,33 @@ static void rmodule_copy_payload(const struct rmodule *module) memcpy(module->location, module->payload, module->payload_size); } -static inline u32 *rmodule_adjustment_location(const struct rmodule *module, - const void *reloc) -{ - int reloc_offset; - - /* Don't relocate header field entries -- only program relocations. */ - reloc_offset = rmodule_reloc_offset(reloc); - if (reloc_offset < module->header->module_link_start_address) - return NULL; - - return rmodule_load_addr(module, reloc_offset); -} - static int rmodule_relocate(const struct rmodule *module) { - int num_relocations; - const void *reloc; - u32 adjustment; + size_t num_relocations; + const uintptr_t *reloc; + uintptr_t adjustment; /* Each relocation needs to be adjusted relative to the beginning of * the loaded program. */ - adjustment = (u32)rmodule_load_addr(module, 0); + adjustment = (uintptr_t)rmodule_load_addr(module, 0); reloc = module->relocations; num_relocations = rmodule_number_relocations(module); - printk(BIOS_DEBUG, "Processing %d relocs with adjust value of 0x%08x\n", - num_relocations, adjustment); + printk(BIOS_DEBUG, "Processing %zu relocs. Offset value of 0x%08lx\n", + num_relocations, (unsigned long)adjustment); while (num_relocations > 0) { - u32 *adjust_loc; - - if (!rmodule_reloc_valid(reloc)) - return -1; + uintptr_t *adjust_loc; /* If the adjustment location is non-NULL adjust it. */ - adjust_loc = rmodule_adjustment_location(module, reloc); - if (adjust_loc != NULL) { - printk(PK_ADJ_LEVEL, "Adjusting %p: 0x%08x -> 0x%08x\n", - adjust_loc, *adjust_loc, - *adjust_loc + adjustment); + adjust_loc = rmodule_load_addr(module, *reloc); + printk(PK_ADJ_LEVEL, "Adjusting %p: 0x%08lx -> 0x%08lx\n", + adjust_loc, (unsigned long) *adjust_loc, + (unsigned long) (*adjust_loc + adjustment)); *adjust_loc += adjustment; - } - reloc = remodule_next_reloc(reloc); + reloc++; num_relocations--; } @@ -232,8 +177,8 @@ int rmodule_load_alignment(const struct rmodule *module) /* The load alignment is the start of the program's linked address. * The base address where the program is loaded needs to be a multiple * of the program's starting link address. That way all data alignment - * in the program is presered. */ - return module->header->module_link_start_address; + * in the program is preserved. Default to 4KiB. */ + return 4096; } int rmodule_load(void *base, struct rmodule *module) @@ -252,6 +197,9 @@ int rmodule_load(void *base, struct rmodule *module) if (rmodule_relocate(module)) return -1; rmodule_clear_bss(module); + + cache_sync_instructions(); + return 0; } @@ -300,3 +248,64 @@ int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size, return region_alignment - sizeof(struct rmodule_header); } + +#if CONFIG_DYNAMIC_CBMEM +#include +#include + +int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage) +{ + struct rmodule rmod_stage; + size_t region_size; + char *stage_region; + int rmodule_offset; + int load_offset; + const struct cbmem_entry *cbmem_entry; + + if (stage == NULL || rsl->name == NULL) + return -1; + + rmodule_offset = + rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE, + stage->memlen, ®ion_size, &load_offset); + + cbmem_entry = cbmem_entry_add(rsl->cbmem_id, region_size); + + if (cbmem_entry == NULL) + return -1; + + stage_region = cbmem_entry_start(cbmem_entry); + + printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n", + rsl->name, &stage_region[rmodule_offset], stage->memlen); + + if (cbfs_decompress(stage->compression, &stage[1], + &stage_region[rmodule_offset], stage->len)) + return -1; + + if (rmodule_parse(&stage_region[rmodule_offset], &rmod_stage)) + return -1; + + if (rmodule_load(&stage_region[load_offset], &rmod_stage)) + return -1; + + rsl->cbmem_entry = cbmem_entry; + rsl->entry = rmodule_entry(&rmod_stage); + + return 0; +} + +int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl) +{ + struct cbfs_stage *stage; + + stage =cbfs_get_file_content(CBFS_DEFAULT_MEDIA, + rsl->name, CBFS_TYPE_STAGE); + + if (stage == NULL) + return -1; + + return rmodule_stage_load(rsl, stage); +} + +#endif /* DYNAMIC_CBMEM */ diff --git a/src/lib/rmodule.ld b/src/lib/rmodule.ld index 41d6357fe1..44704dc6e4 100644 --- a/src/lib/rmodule.ld +++ b/src/lib/rmodule.ld @@ -1,19 +1,15 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) - /* * This linker script is used to link rmodules (relocatable modules). It * links at zero so that relocation fixups are easy when placing the binaries * anywhere in the address space. * * NOTE: The program's loadable sections (text, module_params, and data) are - * packed into the flat blob using the AT directive. The rmodule loader assumes - * the entire program resides in one contiguous address space. Therefore, - * alignment for a given section (if required) needs to be done at the end of - * the preceeding section. e.g. if the data section should be aligned to an 8 - * byte address the text section should have ALIGN(8) at the end of its section. - * Otherwise there won't be a consistent mapping between the flat blob and the - * loaded program. + * packed into the flat blob. The rmodule loader assumes the entire program + * resides in one contiguous address space. Therefore, alignment for a given + * section (if required) needs to be done at the end of the preceeding section. + * e.g. if the data section should be aligned to an 8 byte address the text + * section should have ALIGN(8) at the end of its section. Otherwise there + * won't be a consistent mapping between the flat blob and the loaded program. */ BASE_ADDRESS = 0x00000; @@ -22,77 +18,79 @@ SECTIONS { . = BASE_ADDRESS; - .header : AT (0) { - *(.module_header); - . = ALIGN(8); - } - - /* Align the start of the module program to a large enough alignment - * so that any data in the program with an alignement property is met. - * Essentially, this alignment is the maximum possible data alignment - * property a program can have. */ - . = ALIGN(4096); - _module_link_start_addr = .; - _payload_begin_offset = LOADADDR(.header) + SIZEOF(.header); - - .text : AT (_payload_begin_offset) { + .payload : { /* C code of the module. */ - *(.textfirst); + _program = .; + *(.text._start); + *(.text.stage_entry); *(.text); *(.text.*); /* C read-only data. */ . = ALIGN(16); +#ifdef CONFIG_COVERAGE __CTOR_LIST__ = .; *(.ctors); LONG(0); + LONG(0); __CTOR_END__ = .; +#endif /* The driver sections are to allow linking coreboot's * ramstage with the rmodule linker. Any changes made in - * coreboot_ram.ld should be made here as well. */ + * ramstage.ld should be made here as well. */ + . = ALIGN(8); console_drivers = .; *(.rodata.console_drivers) econsole_drivers = . ; - . = ALIGN(4); + . = ALIGN(8); pci_drivers = . ; *(.rodata.pci_driver) epci_drivers = . ; + . = ALIGN(8); cpu_drivers = . ; *(.rodata.cpu_driver) ecpu_drivers = . ; - . = ALIGN(4); + . = ALIGN(8); + _bs_init_begin = .; + *(.bs_init) + _bs_init_end = .; + _cbmem_init_hooks = .; + KEEP(*(.rodata.cbmem_init_hooks)); + _ecbmem_init_hooks = .; + + . = ALIGN(8); *(.rodata); *(.rodata.*); - . = ALIGN(4); - } + . = ALIGN(8); - .module_params : AT (LOADADDR(.text) + SIZEOF(.text)) { /* The parameters section can be used to pass parameters * to a module, however there has to be an prior agreement * on how to interpret the parameters. */ _module_params_begin = .; *(.module_parameters); _module_params_end = .; - . = ALIGN(4); - } + . = ALIGN(8); - .data : AT (LOADADDR(.module_params) + SIZEOF(.module_params)) { + /* Data section. */ + . = ALIGN(64); /* Mirror cache line alignment from ramstage. */ _sdata = .; *(.data); - . = ALIGN(4); + *(.data.*); + . = ALIGN(8); _edata = .; - } - /* _payload_end marks the end of the module's code and data. */ - _payload_end_offset = LOADADDR(.data) + SIZEOF(.data); + . = ALIGN(8); + } .bss (NOLOAD) : { /* C uninitialized data of the module. */ _bss = .; *(.bss); - *(.sbss); + *(.bss.*) + *(.sbss) + *(.sbss.*) *(COMMON); . = ALIGN(8); _ebss = .; @@ -104,38 +102,11 @@ SECTIONS _heap = .; . = . + __heap_size; _eheap = .; + _eprogram = .; } - /* _module_program_size is the total memory used by the program. */ - _module_program_size = _eheap - _module_link_start_addr; - - /* coreboot's ramstage uses the _ram_seg and _eram_seg symbols - * for determining its load location. Provide those to help it out. - * It's a nop for any non-ramstage rmodule. */ - _ram_seg = _module_link_start_addr; - _eram_seg = _module_link_start_addr + _module_program_size; - - /* The relocation information is linked on top of the BSS section - * because the BSS section takes no space on disk. The relocation data - * resides directly after the data section in the flat binary. */ - .relocations ADDR(.bss) : AT (_payload_end_offset) { - *(.rel.*); - } - _relocations_begin_offset = LOADADDR(.relocations); - _relocations_end_offset = _relocations_begin_offset + - SIZEOF(.relocations); - /DISCARD/ : { - /* Drop unnecessary sections. Since these modules are linked - * as shared objects there are dynamic sections. These sections - * aren't needed so drop them. */ - *(.comment); - *(.note); - *(.note.*); - *(.dynamic); - *(.dynsym); - *(.dynstr); - *(.gnu.hash); + /* Drop unnecessary sections. */ *(.eh_frame); } } diff --git a/src/lib/romstage.ld b/src/lib/romstage.ld new file mode 100644 index 0000000000..bbad333adf --- /dev/null +++ b/src/lib/romstage.ld @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file is included inside a SECTIONS block */ + +.text . : { + _program = .; + _romstage = .; + *(.text._start); + *(.text.stage_entry); + *(.text); + *(.text.*); +} : to_load + +.data . : { + . = ALIGN(8); + _cbmem_init_hooks = .; + KEEP(*(.rodata.cbmem_init_hooks)); + _ecbmem_init_hooks = .; + *(.rodata); + *(.rodata.*); + *(.data); + *(.data.*); + . = ALIGN(8); +} + +.bss . : { + . = ALIGN(8); + _bss = .; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + _ebss = .; + _eromstage = .; + _eprogram = .; +} + +/* Discard the sections we don't need/want */ +/DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.eh_frame); +} diff --git a/src/lib/rtc.c b/src/lib/rtc.c new file mode 100644 index 0000000000..bd98590d96 --- /dev/null +++ b/src/lib/rtc.c @@ -0,0 +1,154 @@ +/* + * This file is part of the coreboot project. + * + * (C) Copyright 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * From U-Boot 2016.05 + */ + +#include +#include + +#define FEBRUARY 2 +#define STARTOFTIME 1970 +#define SECDAY 86400L +#define SECYR (SECDAY * 365) +#define LEAP_YEAR(year) ((year) % 4 == 0) +#define DAYS_IN_YEAR(a) (LEAP_YEAR(a) ? 366 : 365) +#define DAYS_IN_MONTH(a) (month_days[(a) - 1]) + +static const int month_offset[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +static const char * const weekdays[] = { + "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", +}; + +static int leaps_to_year(int year) +{ + return year / 4 - year / 100 + year / 400; +} + +/* This only works for the Gregorian calendar after Jan 1 1971. */ +static int rtc_calc_weekday(struct rtc_time *tm) +{ + int leaps_to_date; + int day; + + if (tm->year < 1971) + return -1; + + day = 4; /* Jan 1 1970 was a Thursday. */ + + /* Number of leap corrections to apply up to end of last year */ + leaps_to_date = leaps_to_year(tm->year - 1) - leaps_to_year(1970); + + /* + * This year is a leap year if it is divisible by 4 except when it is + * divisible by 100 unless it is divisible by 400 + * + * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is. + */ + if ((tm->year % 4) && + ((tm->year % 100 != 0) || (tm->year % 400 == 0)) && + (tm->mon > 2)) { + /* We are past Feb. 29 in a leap year */ + day++; + } + + day += (tm->year - 1970) * 365 + leaps_to_date + + month_offset[tm->mon-1] + tm->mday; + tm->wday = day % 7; + + return 0; +} + +int rtc_to_tm(int tim, struct rtc_time *tm) +{ + int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + register int i; + register long hms, day; + + day = tim / SECDAY; + hms = tim % SECDAY; + + /* Hours, minutes, seconds are easy */ + tm->hour = hms / 3600; + tm->min = (hms % 3600) / 60; + tm->sec = (hms % 3600) % 60; + + /* Number of years in days */ + for (i = STARTOFTIME; day >= DAYS_IN_YEAR(i); i++) + day -= DAYS_IN_YEAR(i); + tm->year = i; + + /* Number of months in days left */ + if (LEAP_YEAR(tm->year)) + DAYS_IN_MONTH(FEBRUARY) = 29; + for (i = 1; day >= DAYS_IN_MONTH(i); i++) + day -= DAYS_IN_MONTH(i); + DAYS_IN_MONTH(FEBRUARY) = 28; + tm->mon = i; + + /* Days are what is left over (+1) from all that */ + tm->mday = day + 1; + + /* Determine the day of week */ + return rtc_calc_weekday(tm); +} + +/* + * Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year / 100 + year / 400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines where long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +unsigned long rtc_mktime(const struct rtc_time *tm) +{ + int mon = tm->mon; + int year = tm->year; + int days, hours; + + mon -= 2; + if (0 >= (int)mon) { /* 1..12 -> 11, 12, 1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + days = (unsigned long)(year / 4 - year / 100 + year / 400 + + 367 * mon / 12 + tm->mday) + + year * 365 - 719499; + hours = days * 24 + tm->hour; + return (hours * 60 + tm->min) * 60 + tm->sec; +} + +void rtc_display(const struct rtc_time *tm) +{ + printk(BIOS_INFO, "Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n", + tm->year, tm->mon, tm->mday, + (tm->wday < 0 || tm->wday > 6) ? "unknown " : weekdays[tm->wday], + tm->hour, tm->min, tm->sec); +} diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index be03b853a6..995f1ca180 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -19,33 +19,26 @@ */ #include +#include #include #include #include -#include -#include #include #include #include #include +#include #include #include -#if CONFIG_COLLECT_TIMESTAMPS #include -#endif -#include /* Maximum physical address we can use for the coreboot bounce buffer. */ #ifndef MAX_ADDR #define MAX_ADDR -1UL #endif -/* from coreboot_ram.ld: */ -extern unsigned char _ram_seg; -extern unsigned char _eram_seg; - -static const unsigned long lb_start = (unsigned long)&_ram_seg; -static const unsigned long lb_end = (unsigned long)&_eram_seg; +static const unsigned long lb_start = (unsigned long)&_program; +static const unsigned long lb_end = (unsigned long)&_eprogram; struct segment { struct segment *next; @@ -334,7 +327,7 @@ static int build_self_segment_list( new->s_memsz = ntohl(segment->mem_len); new->compression = ntohl(segment->compression); - new->s_srcaddr = (u32) ((unsigned char *)first_segment) + new->s_srcaddr = (uintptr_t) ((unsigned char *)first_segment) + ntohl(segment->offset); new->s_filesz = ntohl(segment->len); printk(BIOS_DEBUG, " New segment dstaddr 0x%lx memsize 0x%lx srcaddr 0x%lx filesize 0x%lx\n", @@ -342,9 +335,10 @@ static int build_self_segment_list( /* Clean up the values */ if (new->s_filesz > new->s_memsz) { new->s_filesz = new->s_memsz; + printk(BIOS_DEBUG, + " cleaned up filesize 0x%lx\n", + new->s_filesz); } - printk(BIOS_DEBUG, " (cleaned up) New segment addr 0x%lx size 0x%lx offset 0x%lx filesize 0x%lx\n", - new->s_dstaddr, new->s_memsz, new->s_srcaddr, new->s_filesz); break; case PAYLOAD_SEGMENT_BSS: @@ -490,7 +484,7 @@ static int load_self_segments( /* Zero the extra bytes */ memset(middle, 0, end - middle); } - /* Copy the data that's outside the area that shadows coreboot_ram */ + /* Copy the data that's outside the area that shadows ramstage */ printk(BIOS_DEBUG, "dest %p, end %p, bouncebuffer %lx\n", dest, end, bounce_buffer); if ((unsigned long)end > bounce_buffer) { if ((unsigned long)dest < bounce_buffer) { @@ -513,7 +507,7 @@ static int load_self_segments( return 1; } -int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) +void *selfload(struct lb_memory *mem, struct cbfs_payload *payload) { u32 entry=0; struct segment head; @@ -528,22 +522,21 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) printk(BIOS_SPEW, "Loaded segments\n"); + return (void *)(uintptr_t)entry; + +out: + return NULL; +} + +void selfboot(void *entry) +{ /* Reset to booting from this image as late as possible */ boot_successful(); - printk(BIOS_DEBUG, "Jumping to boot code at %x\n", entry); + printk(BIOS_DEBUG, "Jumping to boot code at %p\n", entry); post_code(POST_ENTER_ELF_BOOT); -#if CONFIG_COLLECT_TIMESTAMPS timestamp_add_now(TS_SELFBOOT_JUMP); -#endif -#if CONFIG_COVERAGE - coverage_exit(); -#endif - - /* Tear down the caching of the ROM. */ - if (disable_cache_rom) - disable_cache_rom(); /* Before we go off to run the payload, see if * we stayed within our bounds. @@ -551,9 +544,5 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload) checkstack(_estack, 0); /* Jump to kernel */ - jmp_to_elf_entry((void*)entry, bounce_buffer, bounce_size); - return 1; - -out: - return 0; + jmp_to_elf_entry(entry, bounce_buffer, bounce_size); } diff --git a/src/lib/stack.c b/src/lib/stack.c index 1f9e009944..52dd723e38 100644 --- a/src/lib/stack.c +++ b/src/lib/stack.c @@ -20,31 +20,35 @@ it with the version available from LANL. * rminnich@lanl.gov */ +#include #include #include +#include int checkstack(void *top_of_stack, int core) { + /* Not all archs use CONFIG_STACK_SIZE, those who don't set it to 0. */ + size_t stack_size = CONFIG_STACK_SIZE ? CONFIG_STACK_SIZE : _stack_size; int i; - u32 *stack = (u32 *) (top_of_stack - CONFIG_STACK_SIZE); + u32 *stack = (u32 *) (top_of_stack - stack_size); if (stack[0] != 0xDEADBEEF){ - printk(BIOS_ERR, "Stack overrun on CPU%d." - "Increase stack from current %d bytes\n", - core, CONFIG_STACK_SIZE); + printk(BIOS_ERR, "Stack overrun on CPU%d. " + "Increase stack from current %zu bytes\n", + core, stack_size); + BUG(); return -1; } - for(i = 1; i < CONFIG_STACK_SIZE/sizeof(stack[0]); i++){ + for(i = 1; i < stack_size/sizeof(stack[0]); i++){ if (stack[i] == 0xDEADBEEF) continue; printk(BIOS_SPEW, "CPU%d: stack: %p - %p, ", - core, stack, - &stack[CONFIG_STACK_SIZE/sizeof(stack[0])]); + core, stack, &stack[stack_size/sizeof(stack[0])]); printk(BIOS_SPEW, "lowest used address %p, ", &stack[i]); printk(BIOS_SPEW, "stack used: %ld bytes\n", - (unsigned long)&stack[CONFIG_STACK_SIZE / - sizeof(stack[0])] - (unsigned long)&stack[i]); + (unsigned long)&stack[stack_size / sizeof(stack[0])] + - (unsigned long)&stack[i]); return 0; } diff --git a/src/lib/thread.c b/src/lib/thread.c new file mode 100644 index 0000000000..089ae3f04a --- /dev/null +++ b/src/lib/thread.c @@ -0,0 +1,378 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static void idle_thread_init(void); + +/* There needs to be at least one thread to run the ramstate state machine. */ +#define TOTAL_NUM_THREADS (CONFIG_NUM_THREADS + 1) + +/* Storage space for the thread structs .*/ +static struct thread all_threads[TOTAL_NUM_THREADS]; + +/* All runnable (but not running) and free threads are kept on their + * respective lists. */ +static struct thread *runnable_threads; +static struct thread *free_threads; + +static inline struct cpu_info *thread_cpu_info(const struct thread *t) +{ + return (void *)(t->stack_orig); +} + +static inline int thread_can_yield(const struct thread *t) +{ + return (t != NULL && t->can_yield); +} + +/* Assumes current cpu info can switch. */ +static inline struct thread *cpu_info_to_thread(const struct cpu_info *ci) +{ + return ci->thread; +} + +static inline struct thread *current_thread(void) +{ + return cpu_info_to_thread(cpu_info()); +} + +static inline int thread_list_empty(struct thread **list) +{ + return *list == NULL; +} + +static inline struct thread *pop_thread(struct thread **list) +{ + struct thread *t; + + t = *list; + *list = t->next; + t->next = NULL; + return t; +} + +static inline void push_thread(struct thread **list, struct thread *t) +{ + t->next = *list; + *list = t; +} + +static inline void push_runnable(struct thread *t) +{ + push_thread(&runnable_threads, t); +} + +static inline struct thread *pop_runnable(void) +{ + return pop_thread(&runnable_threads); +} + +static inline struct thread *get_free_thread(void) +{ + struct thread *t; + struct cpu_info *ci; + struct cpu_info *new_ci; + + if (thread_list_empty(&free_threads)) + return NULL; + + t = pop_thread(&free_threads); + + ci = cpu_info(); + + /* Initialize the cpu_info structure on the new stack. */ + new_ci = thread_cpu_info(t); + *new_ci = *ci; + new_ci->thread = t; + + /* Reset the current stack value to the original. */ + t->stack_current = t->stack_orig; + + return t; +} + +static inline void free_thread(struct thread *t) +{ + push_thread(&free_threads, t); +} + +/* The idle thread is ran whenever there isn't anything else that is runnable. + * It's sole responsibility is to ensure progress is made by running the timer + * callbacks. */ +static void idle_thread(void *unused) +{ + /* This thread never voluntarily yields. */ + thread_prevent_coop(); + while (1) { + timers_run(); + } +} + +static void schedule(struct thread *t) +{ + struct thread *current = current_thread(); + + /* If t is NULL need to find new runnable thread. */ + if (t == NULL) { + if (thread_list_empty(&runnable_threads)) + die("Runnable thread list is empty!\n"); + t = pop_runnable(); + } else { + /* current is still runnable. */ + push_runnable(current); + } + switch_to_thread(t->stack_current, ¤t->stack_current); +} + +static void terminate_thread(struct thread *t) +{ + free_thread(t); + schedule(NULL); +} + +static void asmlinkage call_wrapper(void *unused) +{ + struct thread *current = current_thread(); + + current->entry(current->entry_arg); + terminate_thread(current); +} + +/* Block the current state transitions until thread is complete. */ +static void asmlinkage call_wrapper_block_current(void *unused) +{ + struct thread *current = current_thread(); + + boot_state_current_block(); + current->entry(current->entry_arg); + boot_state_current_unblock(); + terminate_thread(current); +} + +struct block_boot_state { + boot_state_t state; + boot_state_sequence_t seq; +}; + +/* Block the provided state until thread is complete. */ +static void asmlinkage call_wrapper_block_state(void *arg) +{ + struct block_boot_state *bbs = arg; + struct thread *current = current_thread(); + + boot_state_block(bbs->state, bbs->seq); + current->entry(current->entry_arg); + boot_state_unblock(bbs->state, bbs->seq); + terminate_thread(current); +} + +/* Prepare a thread so that it starts by executing thread_entry(thread_arg). + * Within thread_entry() it will call func(arg). */ +static void prepare_thread(struct thread *t, void *func, void *arg, + void asmlinkage (*thread_entry)(void *), + void *thread_arg) +{ + /* Stash the function and argument to run. */ + t->entry = func; + t->entry_arg = arg; + + /* All new threads can yield by default. */ + t->can_yield = 1; + + arch_prepare_thread(t, thread_entry, thread_arg); +} + +static void thread_resume_from_timeout(struct timeout_callback *tocb) +{ + struct thread *to; + + to = tocb->priv; + schedule(to); +} + +static void idle_thread_init(void) +{ + struct thread *t; + + t = get_free_thread(); + + if (t == NULL) { + die("No threads available for idle thread!\n"); + } + + /* Queue idle thread to run once all other threads have yielded. */ + prepare_thread(t, idle_thread, NULL, call_wrapper, NULL); + push_runnable(t); + /* Mark the currently executing thread to cooperate. */ + thread_cooperate(); +} + +/* Don't inline this function so the timeout_callback won't have its storage + * space on the stack cleaned up before the call to schedule(). */ +static int __attribute__((noinline)) +thread_yield_timed_callback(struct timeout_callback *tocb, unsigned microsecs) +{ + tocb->priv = current_thread(); + tocb->callback = thread_resume_from_timeout; + + if (timer_sched_callback(tocb, microsecs)) + return -1; + + /* The timer callback will wake up the current thread. */ + schedule(NULL); + return 0; +} + +static void *thread_alloc_space(struct thread *t, size_t bytes) +{ + /* Allocate the amount of space on the stack keeping the stack + * aligned to the pointer size. */ + t->stack_current -= ALIGN_UP(bytes, sizeof(uintptr_t)); + + return (void *)t->stack_current; +} + +void threads_initialize(void) +{ + int i; + struct thread *t; + u8 *stack_top; + struct cpu_info *ci; + u8 *thread_stacks; + + thread_stacks = arch_get_thread_stackbase(); + + /* Initialize the BSP thread first. The cpu_info structure is assumed + * to be just under the top of the stack. */ + t = &all_threads[0]; + ci = cpu_info(); + ci->thread = t; + t->stack_orig = (uintptr_t)ci; + t->id = 0; + + stack_top = &thread_stacks[CONFIG_STACK_SIZE] - sizeof(struct cpu_info); + for (i = 1; i < TOTAL_NUM_THREADS; i++) { + t = &all_threads[i]; + t->stack_orig = (uintptr_t)stack_top; + t->id = i; + stack_top += CONFIG_STACK_SIZE; + free_thread(t); + } + + idle_thread_init(); +} + +int thread_run(void (*func)(void *), void *arg) +{ + struct thread *current; + struct thread *t; + + current = current_thread(); + + if (!thread_can_yield(current)) { + printk(BIOS_ERR, + "thread_run() called from non-yielding context!\n"); + return -1; + } + + t = get_free_thread(); + + if (t == NULL) { + printk(BIOS_ERR, "thread_run() No more threads!\n"); + return -1; + } + + prepare_thread(t, func, arg, call_wrapper_block_current, NULL); + schedule(t); + + return 0; +} + +int thread_run_until(void (*func)(void *), void *arg, + boot_state_t state, boot_state_sequence_t seq) +{ + struct thread *current; + struct thread *t; + struct block_boot_state *bbs; + + current = current_thread(); + + if (!thread_can_yield(current)) { + printk(BIOS_ERR, + "thread_run() called from non-yielding context!\n"); + return -1; + } + + t = get_free_thread(); + + if (t == NULL) { + printk(BIOS_ERR, "thread_run() No more threads!\n"); + return -1; + } + + bbs = thread_alloc_space(t, sizeof(*bbs)); + bbs->state = state; + bbs->seq = seq; + prepare_thread(t, func, arg, call_wrapper_block_state, bbs); + schedule(t); + + return 0; +} + +int thread_yield_microseconds(unsigned microsecs) +{ + struct thread *current; + struct timeout_callback tocb; + + current = current_thread(); + + if (!thread_can_yield(current)) + return -1; + + if (thread_yield_timed_callback(&tocb, microsecs)) + return -1; + + return 0; +} + +void thread_cooperate(void) +{ + struct thread *current; + + current = current_thread(); + + if (current != NULL) + current->can_yield = 1; +} + +void thread_prevent_coop(void) +{ + struct thread *current; + + current = current_thread(); + + if (current != NULL) + current->can_yield = 0; +} diff --git a/src/lib/timer.c b/src/lib/timer.c new file mode 100644 index 0000000000..8aeaa063c1 --- /dev/null +++ b/src/lib/timer.c @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +__attribute__((weak)) void init_timer() { /* do nothing */ } + +void udelay(unsigned usec) +{ + struct stopwatch sw; + + /* + * As the timer granularity is in microseconds pad the + * requested delay by one to get at least >= requested usec delay. + */ + usec += 1; + + if (!thread_yield_microseconds(usec)) + return; + + stopwatch_init_usecs_expire(&sw, usec); + + while (!stopwatch_expired(&sw)) + ; +} diff --git a/src/lib/timer_queue.c b/src/lib/timer_queue.c new file mode 100644 index 0000000000..8d11f107a8 --- /dev/null +++ b/src/lib/timer_queue.c @@ -0,0 +1,198 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +#define MAX_TIMER_QUEUE_ENTRIES 64 + +/* The timer queue is implemented using a min heap. Therefore the first + * element is the one with smallest time to expiration. */ +struct timer_queue { + int num_entries; + int max_entries; + struct timeout_callback *queue[MAX_TIMER_QUEUE_ENTRIES]; +}; + +static struct timer_queue global_timer_queue = { + .num_entries = 0, + .max_entries = MAX_TIMER_QUEUE_ENTRIES, + .queue = { 0 }, +}; + +static inline int timer_queue_empty(struct timer_queue *tq) +{ + return tq->num_entries == 0; +} + +static inline int timer_queue_full(struct timer_queue *tq) +{ + return tq->num_entries == tq->max_entries; +} + +static inline struct timeout_callback *timer_queue_head(struct timer_queue *tq) +{ + if (timer_queue_empty(tq)) + return NULL; + return tq->queue[0]; +} + +static int timer_queue_insert(struct timer_queue *tq, + struct timeout_callback *tocb) +{ + int index; + + /* No more slots. */ + if (timer_queue_full(tq)) + return -1; + + index = tq->num_entries; + tq->num_entries++; + tq->queue[index] = tocb; + + while (index != 0) { + struct timeout_callback *parent; + int parent_index; + + parent_index = (index - 1) / 2; + parent = tq->queue[parent_index]; + + /* All other ancestors are less than or equal to the current. */ + if (mono_time_cmp(&parent->expiration, &tocb->expiration) <= 0) + break; + + /* The parent is greater than current. Swap them. */ + tq->queue[parent_index] = tocb; + tq->queue[index] = parent; + + index = parent_index; + } + + return 0; +} + +/* Get the index containing the entry with smallest value. */ +static int timer_queue_min_child_index(struct timer_queue *tq, int index) +{ + int left_child_index; + int right_child_index; + + left_child_index = 2 * index + 1; + + if (left_child_index >= tq->num_entries) + return -1; + + right_child_index = left_child_index + 1; + + if (right_child_index >= tq->num_entries) + return left_child_index; + + if (mono_time_cmp(&tq->queue[left_child_index]->expiration, + &tq->queue[right_child_index]->expiration) < 0) { + return left_child_index; + } + return right_child_index; +} + +static void timer_queue_remove_head(struct timer_queue *tq) +{ + int index; + struct timeout_callback *tocb; + + /* In order to remove the head the deepest child is replaced in the + * head slot and bubbled down the tree. */ + tq->num_entries--; + tocb = tq->queue[tq->num_entries]; + tq->queue[0] = tocb; + + index = 0; + while (1) { + int min_child_index; + struct timeout_callback *child; + + min_child_index = timer_queue_min_child_index(tq, index); + + /* No more entries to compare against. */ + if (min_child_index < 0) + break; + + child = tq->queue[min_child_index]; + + /* Current index is the correct place since it is smaller or + * equal to the smallest child. */ + if (mono_time_cmp(&tocb->expiration, &child->expiration) <= 0) + break; + + /* Need to swap with smallest child. */ + tq->queue[min_child_index] = tocb; + tq->queue[index] = child; + + index = min_child_index; + } +} + +static struct timeout_callback * +timer_queue_expired(struct timer_queue *tq, struct mono_time *current_time) +{ + struct timeout_callback *tocb; + + tocb = timer_queue_head(tq); + + if (tocb == NULL) + return NULL; + + /* The timeout callback hasn't expired yet. */ + if (mono_time_before(current_time, &tocb->expiration)) + return NULL; + + timer_queue_remove_head(tq); + + return tocb; +} + +int timer_sched_callback(struct timeout_callback *tocb, unsigned long us) +{ + struct mono_time current_time; + + if ((long)us< 0) + return -1; + + timer_monotonic_get(¤t_time); + tocb->expiration = current_time; + mono_time_add_usecs(&tocb->expiration, us); + + /* The expiration overflowed. */ + if (us != 0 && !mono_time_before(¤t_time, &tocb->expiration)) + return -1; + + return timer_queue_insert(&global_timer_queue, tocb); +} + +int timers_run(void) +{ + struct timeout_callback *tocb; + struct mono_time current_time; + + timer_monotonic_get(¤t_time); + tocb = timer_queue_expired(&global_timer_queue, ¤t_time); + + if (tocb != NULL) + tocb->callback(tocb); + + return !timer_queue_empty(&global_timer_queue); +} diff --git a/src/lib/timestamp.c b/src/lib/timestamp.c index 2f53c50e16..cae3fc5352 100644 --- a/src/lib/timestamp.c +++ b/src/lib/timestamp.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright 2011 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,101 +17,249 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ +#include +#include #include #include #include +#include #include -#ifndef __PRE_RAM__ -/* For CAR_GLOBAL... This should move out of x86 specific code */ -#include +#include + +#define MAX_TIMESTAMPS 60 + +#define MAX_TIMESTAMP_CACHE 30 + +struct __attribute__((__packed__)) timestamp_cache { + uint16_t cache_state; + uint16_t cbmem_state; + struct timestamp_table table; + struct timestamp_entry entries[MAX_TIMESTAMP_CACHE]; +}; + +#define USE_TIMESTAMP_REGION \ + (IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION) && \ + defined(__PRE_RAM__)) + +#define USE_LOCAL_TIMESTAMP_CACHE (!defined(__PRE_RAM__)) + +#define HAS_CBMEM \ + (defined(__ROMSTAGE__) || defined(__RAMSTAGE__)) + +#if USE_LOCAL_TIMESTAMP_CACHE +static struct timestamp_cache timestamp_cache; #endif -#define MAX_TIMESTAMPS 30 +enum { + TIMESTAMP_CACHE_UNINITIALIZED = 0, + TIMESTAMP_CACHE_INITIALIZED, + TIMESTAMP_CACHE_NOT_NEEDED, +}; -#ifndef __PRE_RAM__ -static struct timestamp_table* ts_table; -#endif +enum { + TIMESTAMP_CBMEM_RESET_NOT_REQD = 0, + TIMESTAMP_CBMEM_RESET_REQD, +}; -static uint64_t tsc_to_uint64(tsc_t tstamp) +static void timestamp_cache_init(struct timestamp_cache *ts_cache, + uint64_t base, uint16_t cbmem_state) { - return (((uint64_t)tstamp.hi) << 32) + tstamp.lo; + ts_cache->table.num_entries = 0; + ts_cache->table.max_entries = MAX_TIMESTAMP_CACHE; + ts_cache->table.base_time = base; + ts_cache->cache_state = TIMESTAMP_CACHE_INITIALIZED; + ts_cache->cbmem_state = cbmem_state; } -void timestamp_init(tsc_t base) +static struct timestamp_cache *timestamp_cache_get(void) { - struct timestamp_table* tst; + struct timestamp_cache *ts_cache = NULL; + +#if USE_LOCAL_TIMESTAMP_CACHE + ts_cache = ×tamp_cache; +#elif IS_ENABLED(CONFIG_HAS_PRECBMEM_TIMESTAMP_REGION) + if (_timestamp_size < sizeof(*ts_cache)) + BUG(); + ts_cache = car_get_var_ptr((void *)_timestamp); +#endif + + if (ts_cache && ts_cache->cache_state == TIMESTAMP_CACHE_UNINITIALIZED) + timestamp_cache_init(ts_cache, 0, + TIMESTAMP_CBMEM_RESET_NOT_REQD); + + return ts_cache; +} + +#if HAS_CBMEM +static struct timestamp_table *timestamp_alloc_cbmem_table(void) +{ + struct timestamp_table *tst; tst = cbmem_add(CBMEM_ID_TIMESTAMP, sizeof(struct timestamp_table) + MAX_TIMESTAMPS * sizeof(struct timestamp_entry)); - if (!tst) { - printk(BIOS_ERR, "ERROR: failed to allocate timestamp table\n"); - return; - } + if (!tst) + return NULL; - tst->base_time = tsc_to_uint64(base); + tst->base_time = 0; tst->max_entries = MAX_TIMESTAMPS; tst->num_entries = 0; -} -void timestamp_add(enum timestamp_id id, tsc_t ts_time) + return tst; +} +#endif + +static struct timestamp_table *timestamp_table_get(void) { - struct timestamp_entry *tse; -#ifdef __PRE_RAM__ - struct timestamp_table *ts_table = cbmem_find(CBMEM_ID_TIMESTAMP); -#else + MAYBE_STATIC struct timestamp_table *ts_table = NULL; + struct timestamp_cache *ts_cache; + + ts_cache = timestamp_cache_get(); + + if (ts_cache == NULL) { +#if HAS_CBMEM + ts_table = cbmem_find(CBMEM_ID_TIMESTAMP); +#endif + return ts_table; + } + + if (ts_cache->cache_state != TIMESTAMP_CACHE_NOT_NEEDED) + return &ts_cache->table; + +#if HAS_CBMEM + if (ts_cache->cbmem_state == TIMESTAMP_CBMEM_RESET_REQD) { + ts_table = timestamp_alloc_cbmem_table(); + ts_cache->cbmem_state = TIMESTAMP_CBMEM_RESET_NOT_REQD; + } + if (!ts_table) ts_table = cbmem_find(CBMEM_ID_TIMESTAMP); #endif - if (!ts_table || (ts_table->num_entries == ts_table->max_entries)) + + return ts_table; +} + +static void timestamp_add_table_entry(struct timestamp_table *ts_table, + enum timestamp_id id, uint64_t ts_time) +{ + struct timestamp_entry *tse; + + if (ts_table->num_entries == ts_table->max_entries) { + printk(BIOS_ERR, "ERROR: Dropped a timestamp entry\n"); return; + } tse = &ts_table->entries[ts_table->num_entries++]; tse->entry_id = id; - tse->entry_stamp = tsc_to_uint64(ts_time) - ts_table->base_time; + tse->entry_stamp = ts_time - ts_table->base_time; +} + +static void timestamp_sync(void) +{ + uint32_t i; + + struct timestamp_cache *ts_cache; + struct timestamp_table *ts_cache_table; + struct timestamp_table *ts_cbmem_table = NULL; + + ts_cache = timestamp_cache_get(); + + /* No timestamp cache found */ + if (ts_cache == NULL) { + printk(BIOS_ERR, "ERROR: No timestamp cache found\n"); + return; + } + + ts_cache_table = &ts_cache->table; + +#if HAS_CBMEM + ts_cbmem_table = cbmem_find(CBMEM_ID_TIMESTAMP); + + if ((ts_cache->cbmem_state == TIMESTAMP_CBMEM_RESET_REQD) || + (ts_cbmem_table == NULL)) + ts_cbmem_table = timestamp_alloc_cbmem_table(); +#endif + + if (ts_cbmem_table == NULL) { + printk(BIOS_ERR, "ERROR: No timestamp table allocated\n"); + return; + } + + if (ts_cbmem_table == ts_cache_table) { + printk(BIOS_ERR, "ERROR: Table error to sync timestamps\n"); + return; + } + + ts_cache->cache_state = TIMESTAMP_CACHE_NOT_NEEDED; + ts_cache->cbmem_state = TIMESTAMP_CBMEM_RESET_NOT_REQD; + + /* + * There can be two cases for timestamp sync: + * 1. Newly added cbmem_table will have base_time of 0. Thus, no + * adjusments are needed for the timestamps being added from cache to + * cbmem table. + * 2. Timestamps added to cache before ramstage: In this case, the + * base_time in cache table would be 0 and add_table_entry will take + * care of subtracting the appropriate base_time. + */ + for (i = 0; i < ts_cache_table->num_entries; i++) { + struct timestamp_entry *tse = &ts_cache_table->entries[i]; + timestamp_add_table_entry(ts_cbmem_table, tse->entry_id, + tse->entry_stamp); + } + + ts_cache_table->num_entries = 0; + /* Freshly added cbmem table has base_time 0. Inherit cache base_time */ + if (ts_cbmem_table->base_time == 0) + ts_cbmem_table->base_time = ts_cache_table->base_time; +} +ROMSTAGE_CBMEM_INIT_HOOK(timestamp_sync) +RAMSTAGE_CBMEM_INIT_HOOK(timestamp_sync) + +void timestamp_early_init(uint64_t base) +{ + struct timestamp_cache *ts_cache; + ts_cache = timestamp_cache_get(); + if (ts_cache == NULL) + BUG(); + timestamp_cache_init(ts_cache, base, TIMESTAMP_CBMEM_RESET_REQD); +} + +void timestamp_init(uint64_t base) +{ + struct timestamp_cache *ts_cache; + struct timestamp_table *tst; + + ts_cache = timestamp_cache_get(); + + ts_cache->cbmem_state = TIMESTAMP_CBMEM_RESET_REQD; + + tst = timestamp_table_get(); + + if (!tst) { + printk(BIOS_ERR, "ERROR: No timestamp table to init\n"); + return; + } + + tst->base_time = base; +} + +void timestamp_add(enum timestamp_id id, uint64_t ts_time) +{ + struct timestamp_table *ts_table; + + ts_table = timestamp_table_get(); + + if (!ts_table) { + printk(BIOS_ERR, "ERROR: No timestamp table found\n"); + return; + } + + timestamp_add_table_entry(ts_table, id, ts_time); } void timestamp_add_now(enum timestamp_id id) { - timestamp_add(id, rdtsc()); + timestamp_add(id, timestamp_get()); } - -#ifndef __PRE_RAM__ - -#define MAX_TIMESTAMP_CACHE 8 -struct timestamp_cache { - enum timestamp_id id; - tsc_t time; -} timestamp_cache[MAX_TIMESTAMP_CACHE] CAR_GLOBAL; - -static int timestamp_entries CAR_GLOBAL = 0; - -/** - * timestamp_stash() allows to temporarily cache time stamps. - * This is needed when time stamping before the CBMEM area - * is initialized. The function timestamp_sync() is used to - * write the time stamps to the CBMEM area. This is done in - * hardwaremain() - */ - -void timestamp_stash(enum timestamp_id id) -{ - if (timestamp_entries >= MAX_TIMESTAMP_CACHE) { - printk(BIOS_ERR, "ERROR: failed to add timestamp to cache\n"); - return; - } - timestamp_cache[timestamp_entries].id = id; - timestamp_cache[timestamp_entries].time = rdtsc(); - timestamp_entries++; -} - -void timestamp_sync(void) -{ - int i; - for (i = 0; i < timestamp_entries; i++) - timestamp_add(timestamp_cache[i].id, timestamp_cache[i].time); - timestamp_entries = 0; -} - -#endif diff --git a/src/lib/tlcl.c b/src/lib/tlcl.c new file mode 100644 index 0000000000..9c6b7d6b1e --- /dev/null +++ b/src/lib/tlcl.c @@ -0,0 +1,327 @@ +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* A lightweight TPM command library. + * + * The general idea is that TPM commands are array of bytes whose + * fields are mostly compile-time constant. The goal is to build much + * of the commands at compile time (or build time) and change some of + * the fields at run time as needed. The code in + * utility/tlcl_generator.c builds structures containing the commands, + * as well as the offsets of the fields that need to be set at run + * time. + */ + +#include +#include +#include +#include +#include +#include "tlcl_internal.h" +#include "tlcl_structures.h" + +#ifdef FOR_TEST +#include +#define VBDEBUG(format, args...) printf(format, ## args) +#else +#include +#define VBDEBUG(format, args...) printk(BIOS_DEBUG, format, ## args) +#endif + +static int tpm_send_receive(const uint8_t *request, + uint32_t request_length, + uint8_t *response, + uint32_t *response_length) +{ + size_t len = *response_length; + if (tis_sendrecv(request, request_length, response, &len)) + return VB2_ERROR_UNKNOWN; + /* check 64->32bit overflow and (re)check response buffer overflow */ + if (len > *response_length) + return VB2_ERROR_UNKNOWN; + *response_length = len; + return VB2_SUCCESS; +} + +/* Sets the size field of a TPM command. */ +static inline void set_tpm_command_size(uint8_t* buffer, uint32_t size) { + to_tpm_uint32(buffer + sizeof(uint16_t), size); +} + +/* Gets the size field of a TPM command. */ +__attribute__((unused)) +static inline int tpm_command_size(const uint8_t* buffer) { + uint32_t size; + from_tpm_uint32(buffer + sizeof(uint16_t), &size); + return (int) size; +} + +/* Gets the code field of a TPM command. */ +static inline int tpm_command_code(const uint8_t* buffer) { + uint32_t code; + from_tpm_uint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); + return code; +} + +/* Gets the return code field of a TPM result. */ +static inline int tpm_return_code(const uint8_t* buffer) { + return tpm_command_code(buffer); +} + +/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or + * DOING_SELFTEST errors are returned. + */ +static uint32_t tlcl_send_receive_no_retry(const uint8_t* request, + uint8_t* response, int max_length) { + uint32_t response_length = max_length; + uint32_t result; + + result = tpm_send_receive(request, tpm_command_size(request), + response, &response_length); + if (0 != result) { + /* Communication with TPM failed, so response is garbage */ + VBDEBUG("TPM: command 0x%x send/receive failed: 0x%x\n", + tpm_command_code(request), result); + return result; + } + /* Otherwise, use the result code from the response */ + result = tpm_return_code(response); + + /* TODO: add paranoia about returned response_length vs. max_length + * (and possibly expected length from the response header). See + * crosbug.com/17017 */ + + VBDEBUG("TPM: command 0x%x returned 0x%x\n", + tpm_command_code(request), result); + + return result; +} + + +/* Sends a TPM command and gets a response. Returns 0 if success or the TPM + * error code if error. Waits for the self test to complete if needed. */ +uint32_t tlcl_send_receive(const uint8_t* request, uint8_t* response, + int max_length) { + uint32_t result = tlcl_send_receive_no_retry(request, response, + max_length); + /* If the command fails because the self test has not completed, try it + * again after attempting to ensure that the self test has completed. */ + if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { + result = tlcl_continue_self_test(); + if (result != TPM_SUCCESS) + return result; +#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) + /* Retry only once */ + result = tlcl_send_receive_no_retry(request, response, + max_length); +#else + /* This needs serious testing. The TPM specification says: "iii. + * The caller MUST wait for the actions of TPM_ContinueSelfTest + * to complete before reissuing the command C1." But, if + * ContinueSelfTest is non-blocking, how do we know that the + * actions have completed other than trying again? */ + do { + result = tlcl_send_receive_no_retry(request, response, + max_length); + } while (result == TPM_E_DOING_SELFTEST); +#endif + } + return result; +} + +/* Sends a command and returns the error code. */ +static uint32_t send(const uint8_t* command) { + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + return tlcl_send_receive(command, response, sizeof(response)); +} + +/* Exported functions. */ + +uint32_t tlcl_lib_init(void) { + if (tis_init()) + return VB2_ERROR_UNKNOWN; + if (tis_open()) + return VB2_ERROR_UNKNOWN; + return VB2_SUCCESS; +} + +uint32_t tlcl_startup(void) { + VBDEBUG("TPM: Startup\n"); + return send(tpm_startup_cmd.buffer); +} + +uint32_t tlcl_resume(void) { + VBDEBUG("TPM: Resume\n"); + return send(tpm_resume_cmd.buffer); +} + +uint32_t tlcl_self_test_full(void) +{ + VBDEBUG("TPM: Self test full\n"); + return send(tpm_selftestfull_cmd.buffer); +} + +uint32_t tlcl_continue_self_test(void) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + VBDEBUG("TPM: Continue self test\n"); + /* Call the No Retry version of SendReceive to avoid recursion. */ + return tlcl_send_receive_no_retry(tpm_continueselftest_cmd.buffer, + response, sizeof(response)); +} + +uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size) +{ + struct s_tpm_nv_definespace_cmd cmd; + VBDEBUG("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size); + memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); + return send(cmd.buffer); +} + +uint32_t tlcl_write(uint32_t index, const void* data, uint32_t length) +{ + struct s_tpm_nv_write_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + const int total_length = + kTpmRequestHeaderLength + kWriteInfoLength + length; + + VBDEBUG("TPM: tlcl_write(0x%x, %d)\n", index, length); + memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); + assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); + set_tpm_command_size(cmd.buffer, total_length); + + to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.length, length); + memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); + + return tlcl_send_receive(cmd.buffer, response, sizeof(response)); +} + +uint32_t tlcl_read(uint32_t index, void* data, uint32_t length) +{ + struct s_tpm_nv_read_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result_length; + uint32_t result; + + VBDEBUG("TPM: tlcl_read(0x%x, %d)\n", index, length); + memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.length, length); + + result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS && length > 0) { + uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; + from_tpm_uint32(nv_read_cursor, &result_length); + nv_read_cursor += sizeof(uint32_t); + memcpy(data, nv_read_cursor, result_length); + } + + return result; +} + + +uint32_t tlcl_assert_physical_presence(void) { + VBDEBUG("TPM: Asserting physical presence\n"); + return send(tpm_ppassert_cmd.buffer); +} + +uint32_t tlcl_physical_presence_cmd_enable(void) { + VBDEBUG("TPM: Enable the physical presence command\n"); + return send(tpm_ppenable_cmd.buffer); +} + +uint32_t tlcl_finalize_physical_presence(void) { + VBDEBUG("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"); + return send(tpm_finalizepp_cmd.buffer); +} + +uint32_t tlcl_set_nv_locked(void) { + VBDEBUG("TPM: Set NV locked\n"); + return tlcl_define_space(TPM_NV_INDEX_LOCK, 0, 0); +} + +uint32_t tlcl_force_clear(void) { + VBDEBUG("TPM: Force clear\n"); + return send(tpm_forceclear_cmd.buffer); +} + +uint32_t tlcl_set_enable(void) { + VBDEBUG("TPM: Enabling TPM\n"); + return send(tpm_physicalenable_cmd.buffer); +} + +uint32_t tlcl_set_deactivated(uint8_t flag) +{ + struct s_tpm_physicalsetdeactivated_cmd cmd; + VBDEBUG("TPM: SetDeactivated(%d)\n", flag); + memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); + *(cmd.buffer + cmd.deactivated) = flag; + return send(cmd.buffer); +} + +uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS* pflags) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t size; + uint32_t result = tlcl_send_receive(tpm_getflags_cmd.buffer, response, + sizeof(response)); + if (result != TPM_SUCCESS) + return result; + from_tpm_uint32(response + kTpmResponseHeaderLength, &size); + assert(size == sizeof(TPM_PERMANENT_FLAGS)); + memcpy(pflags, response + kTpmResponseHeaderLength + sizeof(size), + sizeof(TPM_PERMANENT_FLAGS)); + return result; +} + +uint32_t tlcl_get_flags(uint8_t* disable, uint8_t* deactivated, + uint8_t *nvlocked) +{ + TPM_PERMANENT_FLAGS pflags; + uint32_t result = tlcl_get_permanent_flags(&pflags); + if (result == TPM_SUCCESS) { + if (disable) + *disable = pflags.disable; + if (deactivated) + *deactivated = pflags.deactivated; + if (nvlocked) + *nvlocked = pflags.nvLocked; + VBDEBUG("TPM: flags disable=%d, deactivated=%d, nvlocked=%d\n", + pflags.disable, pflags.deactivated, pflags.nvLocked); + } + return result; +} + +uint32_t tlcl_set_global_lock(void) +{ + uint32_t x; + VBDEBUG("TPM: Set global lock\n"); + return tlcl_write(TPM_NV_INDEX0, (uint8_t*) &x, 0); +} + +uint32_t tlcl_extend(int pcr_num, const uint8_t* in_digest, + uint8_t* out_digest) +{ + struct s_tpm_extend_cmd cmd; + uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; + uint32_t result; + + memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); + memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); + + result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + + if (out_digest) + memcpy(out_digest, response + kTpmResponseHeaderLength, + kPcrDigestLength); + return result; +} diff --git a/src/lib/tlcl_internal.h b/src/lib/tlcl_internal.h new file mode 100644 index 0000000000..8261b0d0e1 --- /dev/null +++ b/src/lib/tlcl_internal.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef TPM_LITE_TLCL_INTERNAL_H_ +#define TPM_LITE_TLCL_INTERNAL_H_ + +/* + * These numbers derive from adding the sizes of command fields as shown in the + * TPM commands manual. + */ +#define kTpmRequestHeaderLength 10 +#define kTpmResponseHeaderLength 10 +#define kTpmReadInfoLength 12 +#define kEncAuthLength 20 +#define kPcrDigestLength 20 + + +/* + * Conversion functions. to_tpm_TYPE puts a value of type TYPE into a TPM + * command buffer. from_tpm_TYPE gets a value of type TYPE from a TPM command + * buffer into a variable. + */ +__attribute__((unused)) +static inline void to_tpm_uint32(uint8_t *buffer, uint32_t x) { + buffer[0] = (uint8_t)(x >> 24); + buffer[1] = (uint8_t)((x >> 16) & 0xff); + buffer[2] = (uint8_t)((x >> 8) & 0xff); + buffer[3] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void from_tpm_uint32(const uint8_t *buffer, uint32_t *x) { + *x = ((buffer[0] << 24) | + (buffer[1] << 16) | + (buffer[2] << 8) | + buffer[3]); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void to_tpm_uint16(uint8_t *buffer, uint16_t x) { + buffer[0] = (uint8_t)(x >> 8); + buffer[1] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void from_tpm_uint16(const uint8_t *buffer, uint16_t *x) { + *x = (buffer[0] << 8) | buffer[1]; +} + +#endif /* TPM_LITE_TLCL_INTERNAL_H_ */ diff --git a/src/lib/tlcl_structures.h b/src/lib/tlcl_structures.h new file mode 100644 index 0000000000..36c1bb9ed8 --- /dev/null +++ b/src/lib/tlcl_structures.h @@ -0,0 +1,138 @@ +/* This file is automatically generated */ + +const struct s_tpm_extend_cmd{ + uint8_t buffer[34]; + uint16_t pcrNum; + uint16_t inDigest; +} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }, +10, 14, }; + +const struct s_tpm_get_random_cmd{ + uint8_t buffer[14]; + uint16_t bytesRequested; +} tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, }, +10, }; + +const struct s_tpm_getownership_cmd{ + uint8_t buffer[22]; +} tpm_getownership_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, }, +}; + +const struct s_tpm_getpermissions_cmd{ + uint8_t buffer[22]; + uint16_t index; +} tpm_getpermissions_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, }, +18, }; + +const struct s_tpm_getstclearflags_cmd{ + uint8_t buffer[22]; +} tpm_getstclearflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, }, +}; + +const struct s_tpm_getflags_cmd{ + uint8_t buffer[22]; +} tpm_getflags_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, }, +}; + +const struct s_tpm_physicalsetdeactivated_cmd{ + uint8_t buffer[11]; + uint16_t deactivated; +} tpm_physicalsetdeactivated_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }, +10, }; + +const struct s_tpm_physicalenable_cmd{ + uint8_t buffer[10]; +} tpm_physicalenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }, +}; + +const struct s_tpm_physicaldisable_cmd{ + uint8_t buffer[10]; +} tpm_physicaldisable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }, +}; + +const struct s_tpm_forceclear_cmd{ + uint8_t buffer[10]; +} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }, +}; + +const struct s_tpm_readpubek_cmd{ + uint8_t buffer[30]; +} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, +}; + +const struct s_tpm_continueselftest_cmd{ + uint8_t buffer[10]; +} tpm_continueselftest_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }, +}; + +const struct s_tpm_selftestfull_cmd{ + uint8_t buffer[10]; +} tpm_selftestfull_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }, +}; + +const struct s_tpm_resume_cmd{ + uint8_t buffer[12]; +} tpm_resume_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, }, +}; + +const struct s_tpm_savestate_cmd{ + uint8_t buffer[10]; +} tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, }, +}; + +const struct s_tpm_startup_cmd{ + uint8_t buffer[12]; +} tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, +}; + +const struct s_tpm_finalizepp_cmd{ + uint8_t buffer[12]; +} tpm_finalizepp_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, +}; + +const struct s_tpm_pplock_cmd{ + uint8_t buffer[12]; +} tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, +}; + +const struct s_tpm_ppenable_cmd{ + uint8_t buffer[12]; +} tpm_ppenable_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, }, +}; + +const struct s_tpm_ppassert_cmd{ + uint8_t buffer[12]; +} tpm_ppassert_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, }, +}; + +const struct s_tpm_pcr_read_cmd{ + uint8_t buffer[14]; + uint16_t pcrNum; +} tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }, +10, }; + +const struct s_tpm_nv_read_cmd{ + uint8_t buffer[22]; + uint16_t index; + uint16_t length; +} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }, +10, 18, }; + +const struct s_tpm_nv_write_cmd{ + uint8_t buffer[256]; + uint16_t index; + uint16_t length; + uint16_t data; +} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }, +10, 18, 22, }; + +const struct s_tpm_nv_definespace_cmd{ + uint8_t buffer[101]; + uint16_t index; + uint16_t perm; + uint16_t size; +} tpm_nv_definespace_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, }, +12, 70, 77, }; + +const int kWriteInfoLength = 12; +const int kNvDataPublicPermissionsOffset = 60; diff --git a/src/lib/tpm_error_messages.h b/src/lib/tpm_error_messages.h new file mode 100644 index 0000000000..14cb86beae --- /dev/null +++ b/src/lib/tpm_error_messages.h @@ -0,0 +1,250 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* TPM error codes. + * + * Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures + * Version 1.2 Level 2 Revision 103 26 October 2006 Draft. + */ + +#ifndef TPM_ERROR_MESSAGES_H +#define TPM_ERROR_MESSAGES_H + +#define TPM_E_BASE 0x0 +#define TPM_E_NON_FATAL 0x800 + +typedef struct tpm_error_info { + const char* name; + uint32_t code; + const char* description; +} tpm_error_info; + +tpm_error_info tpm_error_table[] = { +{ "TPM_AUTHFAIL", TPM_E_BASE + 1, +"Authentication failed" }, +{ "TPM_BADINDEX", TPM_E_BASE + 2, +"The index to a PCR, DIR or other register is incorrect" }, +{ "TPM_BAD_PARAMETER", TPM_E_BASE + 3, +"One or more parameter is bad" }, +{ "TPM_AUDITFAILURE", TPM_E_BASE + 4, +"An operation completed successfully\n\ +but the auditing of that operation failed" }, +{ "TPM_CLEAR_DISABLED", TPM_E_BASE + 5, +"The clear disable flag is set and all clear operations now require\n\ +physical access" }, +{ "TPM_DEACTIVATED", TPM_E_BASE + 6, +"The TPM is deactivated" }, +{ "TPM_DISABLED", TPM_E_BASE + 7, +"The TPM is disabled" }, +{ "TPM_DISABLED_CMD", TPM_E_BASE + 8, +"The target command has been disabled" }, +{ "TPM_FAIL", TPM_E_BASE + 9, +"The operation failed" }, +{ "TPM_BAD_ORDINAL", TPM_E_BASE + 10, +"The ordinal was unknown or inconsistent" }, +{ "TPM_INSTALL_DISABLED", TPM_E_BASE + 11, +"The ability to install an owner is disabled" }, +{ "TPM_INVALID_KEYHANDLE", TPM_E_BASE + 12, +"The key handle can not be interpreted" }, +{ "TPM_KEYNOTFOUND", TPM_E_BASE + 13, +"The key handle points to an invalid key" }, +{ "TPM_INAPPROPRIATE_ENC", TPM_E_BASE + 14, +"Unacceptable encryption scheme" }, +{ "TPM_MIGRATEFAIL", TPM_E_BASE + 15, +"Migration authorization failed" }, +{ "TPM_INVALID_PCR_INFO", TPM_E_BASE + 16, +"PCR information could not be interpreted" }, +{ "TPM_NOSPACE", TPM_E_BASE + 17, +"No room to load key" }, +{ "TPM_NOSRK", TPM_E_BASE + 18, +"There is no SRK set" }, +{ "TPM_NOTSEALED_BLOB", TPM_E_BASE + 19, +"An encrypted blob is invalid or was not created by this TPM" }, +{ "TPM_OWNER_SET", TPM_E_BASE + 20, +"There is already an Owner" }, +{ "TPM_RESOURCES", TPM_E_BASE + 21, +"The TPM has insufficient internal resources to perform the requested action" }, +{ "TPM_SHORTRANDOM", TPM_E_BASE + 22, +"A random string was too short" }, +{ "TPM_SIZE", TPM_E_BASE + 23, +"The TPM does not have the space to perform the operation" }, +{ "TPM_WRONGPCRVAL", TPM_E_BASE + 24, +"The named PCR value does not match the current PCR value" }, +{ "TPM_BAD_PARAM_SIZE", TPM_E_BASE + 25, +"The paramSize argument to the command has the incorrect value" }, +{ "TPM_SHA_THREAD", TPM_E_BASE + 26, +"There is no existing SHA-1 thread" }, +{ "TPM_SHA_ERROR", TPM_E_BASE + 27, +"The calculation is unable to proceed because the existing SHA-1\n\ +thread has already encountered an error" }, +{ "TPM_FAILEDSELFTEST", TPM_E_BASE + 28, +"Self-test has failed and the TPM has shutdown" }, +{ "TPM_AUTH2FAIL", TPM_E_BASE + 29, +"The authorization for the second key in a 2 key function\n\ +failed authorization" }, +{ "TPM_BADTAG", TPM_E_BASE + 30, +"The tag value sent to for a command is invalid" }, +{ "TPM_IOERROR", TPM_E_BASE + 31, +"An IO error occurred transmitting information to the TPM" }, +{ "TPM_ENCRYPT_ERROR", TPM_E_BASE + 32, +"The encryption process had a problem" }, +{ "TPM_DECRYPT_ERROR", TPM_E_BASE + 33, +"The decryption process did not complete" }, +{ "TPM_INVALID_AUTHHANDLE", TPM_E_BASE + 34, +"An invalid handle was used" }, +{ "TPM_NO_ENDORSEMENT", TPM_E_BASE + 35, +"The TPM does not a EK installed" }, +{ "TPM_INVALID_KEYUSAGE", TPM_E_BASE + 36, +"The usage of a key is not allowed" }, +{ "TPM_WRONG_ENTITYTYPE", TPM_E_BASE + 37, +"The submitted entity type is not allowed" }, +{ "TPM_INVALID_POSTINIT", TPM_E_BASE + 38, +"The command was received in the wrong sequence relative to TPM_Init\n\ +and a subsequent TPM_Startup" }, +{ "TPM_INAPPROPRIATE_SIG", TPM_E_BASE + 39, +"Signed data cannot include additional DER information" }, +{ "TPM_BAD_KEY_PROPERTY", TPM_E_BASE + 40, +"The key properties in TPM_KEY_PARMs are not supported by this TPM" }, +{ "TPM_BAD_MIGRATION", TPM_E_BASE + 41, +"The migration properties of this key are incorrect" }, +{ "TPM_BAD_SCHEME", TPM_E_BASE + 42, +"The signature or encryption scheme for this key is incorrect or not\n\ +permitted in this situation" }, +{ "TPM_BAD_DATASIZE", TPM_E_BASE + 43, +"The size of the data (or blob) parameter is bad or inconsistent\n\ +with the referenced key" }, +{ "TPM_BAD_MODE", TPM_E_BASE + 44, +"A mode parameter is bad, such as capArea or subCapArea for\n\ +TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence,\n\ +or migrationType for, TPM_CreateMigrationBlob" }, +{ "TPM_BAD_PRESENCE", TPM_E_BASE + 45, +"Either the physicalPresence or physicalPresenceLock bits\n\ +have the wrong value" }, +{ "TPM_BAD_VERSION", TPM_E_BASE + 46, +"The TPM cannot perform this version of the capability" }, +{ "TPM_NO_WRAP_TRANSPORT", TPM_E_BASE + 47, +"The TPM does not allow for wrapped transport sessions" }, +{ "TPM_AUDITFAIL_UNSUCCESSFUL", TPM_E_BASE + 48, +"TPM audit construction failed and the underlying command\n\ +was returning a failure code also" }, +{ "TPM_AUDITFAIL_SUCCESSFUL", TPM_E_BASE + 49, +"TPM audit construction failed and the underlying command\n\ +was returning success" }, +{ "TPM_NOTRESETABLE", TPM_E_BASE + 50, +"Attempt to reset a PCR register that does not have the resettable attribute" }, +{ "TPM_NOTLOCAL", TPM_E_BASE + 51, +"Attempt to reset a PCR register that requires locality\n\ +and locality modifier not part of command transport" }, +{ "TPM_BAD_TYPE", TPM_E_BASE + 52, +"Make identity blob not properly typed" }, +{ "TPM_INVALID_RESOURCE", TPM_E_BASE + 53, +"When saving context identified resource type does not match actual resource" }, +{ "TPM_NOTFIPS", TPM_E_BASE + 54, +"The TPM is attempting to execute a command only available when in FIPS mode" }, +{ "TPM_INVALID_FAMILY", TPM_E_BASE + 55, +"The command is attempting to use an invalid family ID" }, +{ "TPM_NO_NV_PERMISSION", TPM_E_BASE + 56, +"The permission to manipulate the NV storage is not available" }, +{ "TPM_REQUIRES_SIGN", TPM_E_BASE + 57, +"The operation requires a signed command" }, +{ "TPM_KEY_NOTSUPPORTED", TPM_E_BASE + 58, +"Wrong operation to load an NV key" }, +{ "TPM_AUTH_CONFLICT", TPM_E_BASE + 59, +"NV_LoadKey blob requires both owner and blob authorization" }, +{ "TPM_AREA_LOCKED", TPM_E_BASE + 60, +"The NV area is locked and not writable" }, +{ "TPM_BAD_LOCALITY", TPM_E_BASE + 61, +"The locality is incorrect for the attempted operation" }, +{ "TPM_READ_ONLY", TPM_E_BASE + 62, +"The NV area is read only and canât be written to" }, +{ "TPM_PER_NOWRITE", TPM_E_BASE + 63, +"There is no protection on the write to the NV area" }, +{ "TPM_FAMILYCOUNT", TPM_E_BASE + 64, +"The family count value does not match" }, +{ "TPM_WRITE_LOCKED", TPM_E_BASE + 65, +"The NV area has already been written to" }, +{ "TPM_BAD_ATTRIBUTES", TPM_E_BASE + 66, +"The NV area attributes conflict" }, +{ "TPM_INVALID_STRUCTURE", TPM_E_BASE + 67, +"The structure tag and version are invalid or inconsistent" }, +{ "TPM_KEY_OWNER_CONTROL", TPM_E_BASE + 68, +"The key is under control of the TPM Owner and can only be evicted\n\ +by the TPM Owner" }, +{ "TPM_BAD_COUNTER", TPM_E_BASE + 69, +"The counter handle is incorrect" }, +{ "TPM_NOT_FULLWRITE", TPM_E_BASE + 70, +"The write is not a complete write of the area" }, +{ "TPM_CONTEXT_GAP", TPM_E_BASE + 71, +"The gap between saved context counts is too large" }, +{ "TPM_MAXNVWRITES", TPM_E_BASE + 72, +"The maximum number of NV writes without an owner has been exceeded" }, +{ "TPM_NOOPERATOR", TPM_E_BASE + 73, +"No operator AuthData value is set" }, +{ "TPM_RESOURCEMISSING", TPM_E_BASE + 74, +"The resource pointed to by context is not loaded" }, +{ "TPM_DELEGATE_LOCK", TPM_E_BASE + 75, +"The delegate administration is locked" }, +{ "TPM_DELEGATE_FAMILY", TPM_E_BASE + 76, +"Attempt to manage a family other then the delegated family" }, +{ "TPM_DELEGATE_ADMIN", TPM_E_BASE + 77, +"Delegation table management not enabled" }, +{ "TPM_TRANSPORT_NOTEXCLUSIVE", TPM_E_BASE + 78, +"There was a command executed outside of an exclusive transport session" }, +{ "TPM_OWNER_CONTROL", TPM_E_BASE + 79, +"Attempt to context save a owner evict controlled key" }, +{ "TPM_DAA_RESOURCES", TPM_E_BASE + 80, +"The DAA command has no resources available to execute the command" }, +{ "TPM_DAA_INPUT_DATA0", TPM_E_BASE + 81, +"The consistency check on DAA parameter inputData0 has failed" }, +{ "TPM_DAA_INPUT_DATA1", TPM_E_BASE + 82, +"The consistency check on DAA parameter inputData1 has failed" }, +{ "TPM_DAA_ISSUER_SETTINGS", TPM_E_BASE + 83, +"The consistency check on DAA_issuerSettings has failed" }, +{ "TPM_DAA_TPM_SETTINGS", TPM_E_BASE + 84, +"The consistency check on DAA_tpmSpecific has failed" }, +{ "TPM_DAA_STAGE", TPM_E_BASE + 85, +"The atomic process indicated by the submitted DAA command is not\n\ +the expected process" }, +{ "TPM_DAA_ISSUER_VALIDITY", TPM_E_BASE + 86, +"The issuerâs validity check has detected an inconsistency" }, +{ "TPM_DAA_WRONG_W", TPM_E_BASE + 87, +"The consistency check on w has failed" }, +{ "TPM_BAD_HANDLE", TPM_E_BASE + 88, +"The handle is incorrect" }, +{ "TPM_BAD_DELEGATE", TPM_E_BASE + 89, +"Delegation is not correct" }, +{ "TPM_BADCONTEXT", TPM_E_BASE + 90, +"The context blob is invalid" }, +{ "TPM_TOOMANYCONTEXTS", TPM_E_BASE + 91, +"Too many contexts held by the TPM" }, +{ "TPM_MA_TICKET_SIGNATURE", TPM_E_BASE + 92, +"Migration authority signature validation failure" }, +{ "TPM_MA_DESTINATION", TPM_E_BASE + 93, +"Migration destination not authenticated" }, +{ "TPM_MA_SOURCE", TPM_E_BASE + 94, +"Migration source incorrect" }, +{ "TPM_MA_AUTHORITY", TPM_E_BASE + 95, +"Incorrect migration authority" }, +{ "TPM_PERMANENTEK", TPM_E_BASE + 97, +"Attempt to revoke the EK and the EK is not revocable" }, +{ "TPM_BAD_SIGNATURE", TPM_E_BASE + 98, +"Bad signature of CMK ticket" }, +{ "TPM_NOCONTEXTSPACE", TPM_E_BASE + 99, +"There is no room in the context list for additional contexts" }, +{ "TPM_RETRY", TPM_E_BASE + TPM_E_NON_FATAL, +"The TPM is too busy to respond to the command immediately, but\n\ +the command could be resubmitted at a later time. The TPM MAY\n\ +return TPM_RETRY for any command at any time" }, +{ "TPM_NEEDS_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 1, +"TPM_ContinueSelfTest has not been run" }, +{ "TPM_DOING_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 2, +"The TPM is currently executing the actions of TPM_ContinueSelfTest\n\ +because the ordinal required resources that have not been tested" }, +{ "TPM_DEFEND_LOCK_RUNNING", TPM_E_BASE + TPM_E_NON_FATAL + 3, +"The TPM is defending against dictionary attacks and is in some\n\ +time-out period" }, + }; + +#endif /* TPM_ERROR_MESSAGES_H */ diff --git a/src/lib/uart8250.c b/src/lib/uart8250.c index 261b90f2b2..093e8da3b2 100644 --- a/src/lib/uart8250.c +++ b/src/lib/uart8250.c @@ -40,7 +40,7 @@ static inline int uart8250_can_tx_byte(unsigned base_port) { - return inb(base_port + UART_LSR) & UART_LSR_THRE; + return inb(base_port + UART8250_LSR) & UART8250_LSR_THRE; } static inline void uart8250_wait_to_tx_byte(unsigned base_port) @@ -52,13 +52,13 @@ static inline void uart8250_wait_to_tx_byte(unsigned base_port) static inline void uart8250_wait_until_sent(unsigned base_port) { unsigned long int i = FIFO_TIMEOUT; - while (i-- && !(inb(base_port + UART_LSR) & UART_LSR_TEMT)); + while (i-- && !(inb(base_port + UART8250_LSR) & UART8250_LSR_TEMT)); } void uart8250_tx_byte(unsigned base_port, unsigned char data) { uart8250_wait_to_tx_byte(base_port); - outb(data, base_port + UART_TBR); + outb(data, base_port + UART8250_TBR); } void uart8250_tx_flush(unsigned base_port) @@ -68,7 +68,7 @@ void uart8250_tx_flush(unsigned base_port) int uart8250_can_rx_byte(unsigned base_port) { - return inb(base_port + UART_LSR) & UART_LSR_DR; + return inb(base_port + UART8250_LSR) & UART8250_LSR_DR; } unsigned char uart8250_rx_byte(unsigned base_port) @@ -77,7 +77,7 @@ unsigned char uart8250_rx_byte(unsigned base_port) while (i-- && !uart8250_can_rx_byte(base_port)); if (i) - return inb(base_port + UART_RBR); + return inb(base_port + UART8250_RBR); else return 0x0; } @@ -86,22 +86,22 @@ void uart8250_init(unsigned base_port, unsigned divisor) { DISABLE_TRACE; /* Disable interrupts */ - outb(0x0, base_port + UART_IER); + outb(0x0, base_port + UART8250_IER); /* Enable FIFOs */ - outb(UART_FCR_FIFO_EN, base_port + UART_FCR); + outb(UART8250_FCR_FIFO_EN, base_port + UART8250_FCR); /* assert DTR and RTS so the other end is happy */ - outb(UART_MCR_DTR | UART_MCR_RTS, base_port + UART_MCR); + outb(UART8250_MCR_DTR | UART8250_MCR_RTS, base_port + UART8250_MCR); /* DLAB on */ - outb(UART_LCR_DLAB | CONFIG_TTYS0_LCS, base_port + UART_LCR); + outb(UART8250_LCR_DLAB | CONFIG_TTYS0_LCS, base_port + UART8250_LCR); /* Set Baud Rate Divisor. 12 ==> 9600 Baud */ - outb(divisor & 0xFF, base_port + UART_DLL); - outb((divisor >> 8) & 0xFF, base_port + UART_DLM); + outb(divisor & 0xFF, base_port + UART8250_DLL); + outb((divisor >> 8) & 0xFF, base_port + UART8250_DLM); /* Set to 3 for 8N1 */ - outb(CONFIG_TTYS0_LCS, base_port + UART_LCR); + outb(CONFIG_TTYS0_LCS, base_port + UART8250_LCR); ENABLE_TRACE; } diff --git a/src/lib/uart8250mem.c b/src/lib/uart8250mem.c index 82248436d3..9ff4c3745c 100644 --- a/src/lib/uart8250mem.c +++ b/src/lib/uart8250mem.c @@ -40,7 +40,7 @@ static inline int uart8250_mem_can_tx_byte(unsigned base_port) { - return read8(base_port + UART_LSR) & UART_LSR_THRE; + return read8(base_port + UART8250_LSR) & UART8250_LSR_THRE; } static inline void uart8250_mem_wait_to_tx_byte(unsigned base_port) @@ -53,14 +53,14 @@ static inline void uart8250_mem_wait_to_tx_byte(unsigned base_port) static inline void uart8250_mem_wait_until_sent(unsigned base_port) { unsigned long int i = FIFO_TIMEOUT; - while(i-- && !(read8(base_port + UART_LSR) & UART_LSR_TEMT)) + while(i-- && !(read8(base_port + UART8250_LSR) & UART8250_LSR_TEMT)) udelay(1); } void uart8250_mem_tx_byte(unsigned base_port, unsigned char data) { uart8250_mem_wait_to_tx_byte(base_port); - write8(base_port + UART_TBR, data); + write8(base_port + UART8250_TBR, data); } void uart8250_mem_tx_flush(unsigned base_port) @@ -70,7 +70,7 @@ void uart8250_mem_tx_flush(unsigned base_port) int uart8250_mem_can_rx_byte(unsigned base_port) { - return read8(base_port + UART_LSR) & UART_LSR_DR; + return read8(base_port + UART8250_LSR) & UART8250_LSR_DR; } unsigned char uart8250_mem_rx_byte(unsigned base_port) @@ -79,7 +79,7 @@ unsigned char uart8250_mem_rx_byte(unsigned base_port) while(i-- && !uart8250_mem_can_rx_byte(base_port)) udelay(1); if (i) - return read8(base_port + UART_RBR); + return read8(base_port + UART8250_RBR); else return 0x0; } @@ -87,22 +87,22 @@ unsigned char uart8250_mem_rx_byte(unsigned base_port) void uart8250_mem_init(unsigned base_port, unsigned divisor) { /* Disable interrupts */ - write8(base_port + UART_IER, 0x0); + write8(base_port + UART8250_IER, 0x0); /* Enable FIFOs */ - write8(base_port + UART_FCR, UART_FCR_FIFO_EN); + write8(base_port + UART8250_FCR, UART8250_FCR_FIFO_EN); /* Assert DTR and RTS so the other end is happy */ - write8(base_port + UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + write8(base_port + UART8250_MCR, UART8250_MCR_DTR | UART8250_MCR_RTS); /* DLAB on */ - write8(base_port + UART_LCR, UART_LCR_DLAB | CONFIG_TTYS0_LCS); + write8(base_port + UART8250_LCR, UART8250_LCR_DLAB | CONFIG_TTYS0_LCS); /* Set Baud Rate Divisor. 12 ==> 9600 Baud */ - write8(base_port + UART_DLL, divisor & 0xFF); - write8(base_port + UART_DLM, (divisor >> 8) & 0xFF); + write8(base_port + UART8250_DLL, divisor & 0xFF); + write8(base_port + UART8250_DLM, (divisor >> 8) & 0xFF); /* Set to 3 for 8N1 */ - write8(base_port + UART_LCR, CONFIG_TTYS0_LCS); + write8(base_port + UART8250_LCR, CONFIG_TTYS0_LCS); } u32 uart_mem_init(void) diff --git a/src/lib/version.c b/src/lib/version.c index 4ec1eb65e1..00429bfd8e 100644 --- a/src/lib/version.c +++ b/src/lib/version.c @@ -25,16 +25,6 @@ #error COREBOOT_COMPILE_HOST not defined #endif -#ifndef COREBOOT_COMPILER -#error COREBOOT_COMPILER not defined -#endif -#ifndef COREBOOT_LINKER -#error COREBOOT_LINKER not defined -#endif -#ifndef COREBOOT_ASSEMBLER -#error COREBOOT_ASSEMBLER not defined -#endif - #ifndef COREBOOT_EXTRA_VERSION #define COREBOOT_EXTRA_VERSION "" #endif @@ -50,7 +40,4 @@ const char coreboot_compile_time[] = COREBOOT_COMPILE_TIME; const char coreboot_compile_by[] = COREBOOT_COMPILE_BY; const char coreboot_compile_host[] = COREBOOT_COMPILE_HOST; const char coreboot_compile_domain[] = COREBOOT_COMPILE_DOMAIN; -const char coreboot_compiler[] = COREBOOT_COMPILER; -const char coreboot_linker[] = COREBOOT_LINKER; -const char coreboot_assembler[] = COREBOOT_ASSEMBLER; diff --git a/src/mainboard/Kconfig b/src/mainboard/Kconfig index 66168ea0c2..62ac72f0c0 100644 --- a/src/mainboard/Kconfig +++ b/src/mainboard/Kconfig @@ -58,6 +58,8 @@ config VENDOR_GETAC bool "Getac" config VENDOR_GIGABYTE bool "GIGABYTE" +config VENDOR_GIZMOSPHERE + bool "GizmoSphere" config VENDOR_GOOGLE bool "Google" config VENDOR_HP @@ -160,6 +162,7 @@ source "src/mainboard/ecs/Kconfig" source "src/mainboard/emulation/Kconfig" source "src/mainboard/getac/Kconfig" source "src/mainboard/gigabyte/Kconfig" +source "src/mainboard/gizmosphere/Kconfig" source "src/mainboard/google/Kconfig" source "src/mainboard/hp/Kconfig" source "src/mainboard/ibase/Kconfig" @@ -338,4 +341,9 @@ config MAINBOARD_VERSION default "1.0" help Define the used version number which will be used by SMBIOS tables. + +config MAINBOARD_ENCLOSURE_TYPE + hex "System Enclosure or Chassis type" + depends on GENERATE_SMBIOS_TABLES + default 0x3 endmenu diff --git a/src/mainboard/a-trend/atc-6220/Kconfig b/src/mainboard/a-trend/atc-6220/Kconfig index 81c23a8db0..036d8e6d36 100644 --- a/src/mainboard/a-trend/atc-6220/Kconfig +++ b/src/mainboard/a-trend/atc-6220/Kconfig @@ -20,7 +20,6 @@ if BOARD_A_TREND_ATC_6220 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/a-trend/atc-6240/Kconfig b/src/mainboard/a-trend/atc-6240/Kconfig index da94c7f460..d19f92dfb5 100644 --- a/src/mainboard/a-trend/atc-6240/Kconfig +++ b/src/mainboard/a-trend/atc-6240/Kconfig @@ -20,7 +20,6 @@ if BOARD_A_TREND_ATC_6240 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/aaeon/pfm-540i_revb/Kconfig b/src/mainboard/aaeon/pfm-540i_revb/Kconfig index 9986987a37..6b156b2f30 100644 --- a/src/mainboard/aaeon/pfm-540i_revb/Kconfig +++ b/src/mainboard/aaeon/pfm-540i_revb/Kconfig @@ -2,7 +2,6 @@ if BOARD_AAEON_PFM_540I_REVB config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/abit/be6-ii_v2_0/Kconfig b/src/mainboard/abit/be6-ii_v2_0/Kconfig index feb00de620..5dc1ca04eb 100644 --- a/src/mainboard/abit/be6-ii_v2_0/Kconfig +++ b/src/mainboard/abit/be6-ii_v2_0/Kconfig @@ -20,7 +20,6 @@ if BOARD_ABIT_BE6_II_V2_0 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/advansus/a785e-i/Kconfig b/src/mainboard/advansus/a785e-i/Kconfig index 3753df8eff..76a26b65ea 100644 --- a/src/mainboard/advansus/a785e-i/Kconfig +++ b/src/mainboard/advansus/a785e-i/Kconfig @@ -2,7 +2,6 @@ if BOARD_ADVANSUS_A785E_I config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_ASB2 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/advansus/a785e-i/Makefile.inc b/src/mainboard/advansus/a785e-i/Makefile.inc index d69a9bf869..587c91ddfa 100644 --- a/src/mainboard/advansus/a785e-i/Makefile.inc +++ b/src/mainboard/advansus/a785e-i/Makefile.inc @@ -14,5 +14,5 @@ ifneq ($(CONFIG_CPU_AMD_AGESA),y) -I$(AGESA_ROOT)/Proc/CPU/ \ -I$(AGESA_ROOT)/Proc/CPU/Family - CFLAGS += $(AGESA_INC) + CFLAGS_common += $(AGESA_INC) endif diff --git a/src/mainboard/advantech/pcm-5820/Kconfig b/src/mainboard/advantech/pcm-5820/Kconfig index 25ff69cd65..86bcd7ac17 100644 --- a/src/mainboard/advantech/pcm-5820/Kconfig +++ b/src/mainboard/advantech/pcm-5820/Kconfig @@ -20,7 +20,6 @@ if BOARD_ADVANTECH_PCM_5820 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/amd/bimini_fam10/Kconfig b/src/mainboard/amd/bimini_fam10/Kconfig index 09e731cfc9..adcee81fa9 100644 --- a/src/mainboard/amd/bimini_fam10/Kconfig +++ b/src/mainboard/amd/bimini_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_BIMINI_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_ASB2 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/amd/db800/Kconfig b/src/mainboard/amd/db800/Kconfig index ee2aa0f44c..c6f99e9e93 100644 --- a/src/mainboard/amd/db800/Kconfig +++ b/src/mainboard/amd/db800/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_DB800 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/amd/dbm690t/Kconfig b/src/mainboard/amd/dbm690t/Kconfig index 74a3d66a87..38c404755c 100644 --- a/src/mainboard/amd/dbm690t/Kconfig +++ b/src/mainboard/amd/dbm690t/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_DBM690T config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_S1G1 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/amd/dinar/Kconfig b/src/mainboard/amd/dinar/Kconfig index 5d36eb0a93..dc059b5f80 100644 --- a/src/mainboard/amd/dinar/Kconfig +++ b/src/mainboard/amd/dinar/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_DINAR config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15 select CPU_AMD_SOCKET_G34 select NORTHBRIDGE_AMD_AGESA_FAMILY15_ROOT_COMPLEX diff --git a/src/mainboard/amd/dinar/get_bus_conf.c b/src/mainboard/amd/dinar/get_bus_conf.c index 128a677e7f..a59bc437d3 100644 --- a/src/mainboard/amd/dinar/get_bus_conf.c +++ b/src/mainboard/amd/dinar/get_bus_conf.c @@ -83,7 +83,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/dinar/romstage.c b/src/mainboard/amd/dinar/romstage.c index a59d142ba2..d8ca5175ef 100644 --- a/src/mainboard/amd/dinar/romstage.c +++ b/src/mainboard/amd/dinar/romstage.c @@ -154,7 +154,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) print_debug("done\n"); post_code(0x44); - copy_and_run(0); + copy_and_run(); post_code(0x45); // Should never see this post code. } diff --git a/src/mainboard/amd/inagua/Kconfig b/src/mainboard/amd/inagua/Kconfig index c30347dd84..479747c658 100644 --- a/src/mainboard/amd/inagua/Kconfig +++ b/src/mainboard/amd/inagua/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_INAGUA config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/amd/inagua/get_bus_conf.c b/src/mainboard/amd/inagua/get_bus_conf.c index d2c0b817f8..09e3b4ca02 100644 --- a/src/mainboard/amd/inagua/get_bus_conf.c +++ b/src/mainboard/amd/inagua/get_bus_conf.c @@ -71,7 +71,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/inagua/romstage.c b/src/mainboard/amd/inagua/romstage.c index a03d5a772e..ee8166a3a4 100644 --- a/src/mainboard/amd/inagua/romstage.c +++ b/src/mainboard/amd/inagua/romstage.c @@ -119,7 +119,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254(); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/amd/mahogany/Kconfig b/src/mainboard/amd/mahogany/Kconfig index 2a6f4eacd5..4b5caf1431 100644 --- a/src/mainboard/amd/mahogany/Kconfig +++ b/src/mainboard/amd/mahogany/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_MAHOGANY config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/amd/mahogany_fam10/Kconfig b/src/mainboard/amd/mahogany_fam10/Kconfig index 6691ce3fff..a841c528fb 100644 --- a/src/mainboard/amd/mahogany_fam10/Kconfig +++ b/src/mainboard/amd/mahogany_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_MAHOGANY_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2R2 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/amd/norwich/Kconfig b/src/mainboard/amd/norwich/Kconfig index dec8e01d34..eb83c1ef8e 100644 --- a/src/mainboard/amd/norwich/Kconfig +++ b/src/mainboard/amd/norwich/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_NORWICH config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/amd/parmer/Kconfig b/src/mainboard/amd/parmer/Kconfig index eb61d8c6c8..923e29dc95 100644 --- a/src/mainboard/amd/parmer/Kconfig +++ b/src/mainboard/amd/parmer/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_PARMER config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15_TN select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN diff --git a/src/mainboard/amd/parmer/get_bus_conf.c b/src/mainboard/amd/parmer/get_bus_conf.c index 3ae4c18195..d1be8b6268 100644 --- a/src/mainboard/amd/parmer/get_bus_conf.c +++ b/src/mainboard/amd/parmer/get_bus_conf.c @@ -69,7 +69,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/parmer/romstage.c b/src/mainboard/amd/parmer/romstage.c index 25f14e88ea..7cd7638539 100644 --- a/src/mainboard/amd/parmer/romstage.c +++ b/src/mainboard/amd/parmer/romstage.c @@ -151,7 +151,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); post_code(0x54); /* Should never see this post code. */ } diff --git a/src/mainboard/amd/persimmon/Kconfig b/src/mainboard/amd/persimmon/Kconfig index f3f9aa964a..1d3dc8efdf 100644 --- a/src/mainboard/amd/persimmon/Kconfig +++ b/src/mainboard/amd/persimmon/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_PERSIMMON config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/amd/persimmon/get_bus_conf.c b/src/mainboard/amd/persimmon/get_bus_conf.c index 11ec26e16e..8872bb5a1c 100644 --- a/src/mainboard/amd/persimmon/get_bus_conf.c +++ b/src/mainboard/amd/persimmon/get_bus_conf.c @@ -74,7 +74,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/persimmon/romstage.c b/src/mainboard/amd/persimmon/romstage.c index 0c8c456140..7351ae26e4 100644 --- a/src/mainboard/amd/persimmon/romstage.c +++ b/src/mainboard/amd/persimmon/romstage.c @@ -178,7 +178,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/amd/pistachio/Kconfig b/src/mainboard/amd/pistachio/Kconfig index febf265113..da20fcd671 100644 --- a/src/mainboard/amd/pistachio/Kconfig +++ b/src/mainboard/amd/pistachio/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_PISTACHIO config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/amd/rumba/Kconfig b/src/mainboard/amd/rumba/Kconfig index d600a588a4..2aea2746f4 100644 --- a/src/mainboard/amd/rumba/Kconfig +++ b/src/mainboard/amd/rumba/Kconfig @@ -20,7 +20,6 @@ if BOARD_AMD_RUMBA config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX2 select NORTHBRIDGE_AMD_GX2 select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/amd/serengeti_cheetah/Kconfig b/src/mainboard/amd/serengeti_cheetah/Kconfig index 26fa45f2be..351f0a758f 100644 --- a/src/mainboard/amd/serengeti_cheetah/Kconfig +++ b/src/mainboard/amd/serengeti_cheetah/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_SERENGETI_CHEETAH config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select SOUTHBRIDGE_AMD_AMD8132 select SOUTHBRIDGE_AMD_AMD8151 select CPU_AMD_SOCKET_F @@ -17,7 +16,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_PIRQ_TABLE select HAVE_MP_TABLE select LIFT_BSP_APIC_ID - #select AP_CODE_IN_CAR select SB_HT_CHAIN_UNITID_OFFSET_ONLY select WAIT_BEFORE_CPUS_INIT select HAVE_ACPI_TABLES diff --git a/src/mainboard/amd/serengeti_cheetah/ap_romstage.c b/src/mainboard/amd/serengeti_cheetah/ap_romstage.c deleted file mode 100644 index fa680fe3cc..0000000000 --- a/src/mainboard/amd/serengeti_cheetah/ap_romstage.c +++ /dev/null @@ -1,74 +0,0 @@ -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include -#include "console/console.c" -#include "lib/uart8250.c" -#include "console/vtxprintf.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/amd/amd8111/amd8111_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -static inline unsigned get_nodes(void) -{ - return ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1; -} - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - printk(BIOS_DEBUG, "CODE IN CACHE ON NODE: %02x\n", id.nodeid); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - * go back, but can not use stack any more, because we - * only keep ret_addr and can not restore esp, and ebp. - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - diff --git a/src/mainboard/amd/serengeti_cheetah_fam10/Kconfig b/src/mainboard/amd/serengeti_cheetah_fam10/Kconfig index 4ea8aca87c..6b76170b84 100644 --- a/src/mainboard/amd/serengeti_cheetah_fam10/Kconfig +++ b/src/mainboard/amd/serengeti_cheetah_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_SERENGETI_CHEETAH_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/amd/south_station/Kconfig b/src/mainboard/amd/south_station/Kconfig index fda0975174..0219f5c53a 100644 --- a/src/mainboard/amd/south_station/Kconfig +++ b/src/mainboard/amd/south_station/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_SOUTHSTATION config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/amd/south_station/get_bus_conf.c b/src/mainboard/amd/south_station/get_bus_conf.c index cbe19d83b6..165c683d86 100644 --- a/src/mainboard/amd/south_station/get_bus_conf.c +++ b/src/mainboard/amd/south_station/get_bus_conf.c @@ -71,7 +71,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/south_station/romstage.c b/src/mainboard/amd/south_station/romstage.c index 88c64904a6..f2ec659b46 100644 --- a/src/mainboard/amd/south_station/romstage.c +++ b/src/mainboard/amd/south_station/romstage.c @@ -111,7 +111,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) printk(BIOS_DEBUG, "passed.\n"); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/amd/thatcher/Kconfig b/src/mainboard/amd/thatcher/Kconfig index 384390c0e4..a6d7dd20a8 100644 --- a/src/mainboard/amd/thatcher/Kconfig +++ b/src/mainboard/amd/thatcher/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_THATCHER config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15_TN select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN diff --git a/src/mainboard/amd/thatcher/get_bus_conf.c b/src/mainboard/amd/thatcher/get_bus_conf.c index 3ae4c18195..d1be8b6268 100644 --- a/src/mainboard/amd/thatcher/get_bus_conf.c +++ b/src/mainboard/amd/thatcher/get_bus_conf.c @@ -69,7 +69,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/thatcher/romstage.c b/src/mainboard/amd/thatcher/romstage.c index 1f3e86dc96..601aa7e122 100644 --- a/src/mainboard/amd/thatcher/romstage.c +++ b/src/mainboard/amd/thatcher/romstage.c @@ -168,7 +168,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); post_code(0x54); /* Should never see this post code. */ } diff --git a/src/mainboard/amd/tilapia_fam10/Kconfig b/src/mainboard/amd/tilapia_fam10/Kconfig index 3c2fc520cc..039f7e2afb 100644 --- a/src/mainboard/amd/tilapia_fam10/Kconfig +++ b/src/mainboard/amd/tilapia_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_AMD_TILAPIA_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/amd/torpedo/Kconfig b/src/mainboard/amd/torpedo/Kconfig index 18e445cd0b..db72273cdd 100644 --- a/src/mainboard/amd/torpedo/Kconfig +++ b/src/mainboard/amd/torpedo/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_TORPEDO config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select DIMM_DDR3 select DIMM_UNREGISTERED select CPU_AMD_AGESA_FAMILY12 diff --git a/src/mainboard/amd/torpedo/get_bus_conf.c b/src/mainboard/amd/torpedo/get_bus_conf.c index e2bd54edf2..4444937d57 100644 --- a/src/mainboard/amd/torpedo/get_bus_conf.c +++ b/src/mainboard/amd/torpedo/get_bus_conf.c @@ -76,7 +76,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/torpedo/romstage.c b/src/mainboard/amd/torpedo/romstage.c index 8edba8022a..bbcd764e25 100644 --- a/src/mainboard/amd/torpedo/romstage.c +++ b/src/mainboard/amd/torpedo/romstage.c @@ -125,7 +125,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) post_code(0x43); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run returned!\n"); post_code(0x44); // Should never see this post code. diff --git a/src/mainboard/amd/union_station/Kconfig b/src/mainboard/amd/union_station/Kconfig index e7df47b2cb..b5dbc427e2 100644 --- a/src/mainboard/amd/union_station/Kconfig +++ b/src/mainboard/amd/union_station/Kconfig @@ -21,7 +21,6 @@ if BOARD_AMD_UNIONSTATION config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/amd/union_station/get_bus_conf.c b/src/mainboard/amd/union_station/get_bus_conf.c index cbe19d83b6..165c683d86 100644 --- a/src/mainboard/amd/union_station/get_bus_conf.c +++ b/src/mainboard/amd/union_station/get_bus_conf.c @@ -71,7 +71,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/amd/union_station/romstage.c b/src/mainboard/amd/union_station/romstage.c index 4538157fdb..efa3e41e38 100644 --- a/src/mainboard/amd/union_station/romstage.c +++ b/src/mainboard/amd/union_station/romstage.c @@ -106,7 +106,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) printk(BIOS_DEBUG, "passed.\n"); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/aopen/dxplplusu/Kconfig b/src/mainboard/aopen/dxplplusu/Kconfig index c620c9a1b7..1802b5aec7 100644 --- a/src/mainboard/aopen/dxplplusu/Kconfig +++ b/src/mainboard/aopen/dxplplusu/Kconfig @@ -2,7 +2,6 @@ if BOARD_AOPEN_DXPLPLUSU config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7505 select SOUTHBRIDGE_INTEL_I82870 diff --git a/src/mainboard/arima/hdama/Kconfig b/src/mainboard/arima/hdama/Kconfig index 408e9531e2..1e15247ae4 100644 --- a/src/mainboard/arima/hdama/Kconfig +++ b/src/mainboard/arima/hdama/Kconfig @@ -2,7 +2,6 @@ if BOARD_ARIMA_HDAMA config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/artecgroup/dbe61/Kconfig b/src/mainboard/artecgroup/dbe61/Kconfig index 55c96ba4d3..b5814fab97 100644 --- a/src/mainboard/artecgroup/dbe61/Kconfig +++ b/src/mainboard/artecgroup/dbe61/Kconfig @@ -2,7 +2,6 @@ if BOARD_ARTECGROUP_DBE61 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/asi/mb_5blgp/Kconfig b/src/mainboard/asi/mb_5blgp/Kconfig index 08ab2e0424..f69f6efafb 100644 --- a/src/mainboard/asi/mb_5blgp/Kconfig +++ b/src/mainboard/asi/mb_5blgp/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASI_MB_5BLGP config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/asi/mb_5blmp/Kconfig b/src/mainboard/asi/mb_5blmp/Kconfig index e8c8dde50c..a40c86c328 100644 --- a/src/mainboard/asi/mb_5blmp/Kconfig +++ b/src/mainboard/asi/mb_5blmp/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASI_MB_5BLMP config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/asrock/939a785gmh/Kconfig b/src/mainboard/asrock/939a785gmh/Kconfig index c94e69b64c..e0717cfffa 100644 --- a/src/mainboard/asrock/939a785gmh/Kconfig +++ b/src/mainboard/asrock/939a785gmh/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASROCK_939A785GMH config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_939 select K8_HT_FREQ_1G_SUPPORT select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/asrock/e350m1/Kconfig b/src/mainboard/asrock/e350m1/Kconfig index a308850bb4..29e89a2623 100644 --- a/src/mainboard/asrock/e350m1/Kconfig +++ b/src/mainboard/asrock/e350m1/Kconfig @@ -21,7 +21,6 @@ if BOARD_ASROCK_E350M1 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/asrock/e350m1/get_bus_conf.c b/src/mainboard/asrock/e350m1/get_bus_conf.c index 1419d79d59..0d664bd1e5 100644 --- a/src/mainboard/asrock/e350m1/get_bus_conf.c +++ b/src/mainboard/asrock/e350m1/get_bus_conf.c @@ -71,7 +71,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/asrock/e350m1/romstage.c b/src/mainboard/asrock/e350m1/romstage.c index 79f963b529..1590f51270 100644 --- a/src/mainboard/asrock/e350m1/romstage.c +++ b/src/mainboard/asrock/e350m1/romstage.c @@ -122,7 +122,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254(); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/asus/a8n_e/Kconfig b/src/mainboard/asus/a8n_e/Kconfig index 22249f6979..cdc470bb60 100644 --- a/src/mainboard/asus/a8n_e/Kconfig +++ b/src/mainboard/asus/a8n_e/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_A8N_E config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_939 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/asus/a8v-e_deluxe/Kconfig b/src/mainboard/asus/a8v-e_deluxe/Kconfig index 1f0d2e9175..dafd96e946 100644 --- a/src/mainboard/asus/a8v-e_deluxe/Kconfig +++ b/src/mainboard/asus/a8v-e_deluxe/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_A8V_E_DELUXE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_939 select K8_HT_FREQ_1G_SUPPORT select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/asus/a8v-e_se/Kconfig b/src/mainboard/asus/a8v-e_se/Kconfig index 8159a432d6..a60be54d94 100644 --- a/src/mainboard/asus/a8v-e_se/Kconfig +++ b/src/mainboard/asus/a8v-e_se/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_A8V_E_SE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_939 select K8_HT_FREQ_1G_SUPPORT select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/asus/dsbf/Kconfig b/src/mainboard/asus/dsbf/Kconfig index 392785352d..19033fe6c6 100644 --- a/src/mainboard/asus/dsbf/Kconfig +++ b/src/mainboard/asus/dsbf/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_DSBF config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_LGA771 select SOUTHBRIDGE_INTEL_I3100 select NORTHBRIDGE_INTEL_I5000 diff --git a/src/mainboard/asus/f2a85-m/Kconfig b/src/mainboard/asus/f2a85-m/Kconfig index e8f573ed37..585cb647c4 100644 --- a/src/mainboard/asus/f2a85-m/Kconfig +++ b/src/mainboard/asus/f2a85-m/Kconfig @@ -22,7 +22,6 @@ if BOARD_ASUS_F2A85_M config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15_TN select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY15_TN diff --git a/src/mainboard/asus/f2a85-m/get_bus_conf.c b/src/mainboard/asus/f2a85-m/get_bus_conf.c index 3ae4c18195..d1be8b6268 100644 --- a/src/mainboard/asus/f2a85-m/get_bus_conf.c +++ b/src/mainboard/asus/f2a85-m/get_bus_conf.c @@ -69,7 +69,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/asus/f2a85-m/romstage.c b/src/mainboard/asus/f2a85-m/romstage.c index c2fc75eff5..b7bcf43d5e 100644 --- a/src/mainboard/asus/f2a85-m/romstage.c +++ b/src/mainboard/asus/f2a85-m/romstage.c @@ -199,7 +199,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); post_code(0x54); /* Should never see this post code. */ } diff --git a/src/mainboard/asus/k8v-x/Kconfig b/src/mainboard/asus/k8v-x/Kconfig index 28c2c81642..2848315a1b 100644 --- a/src/mainboard/asus/k8v-x/Kconfig +++ b/src/mainboard/asus/k8v-x/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_K8V_X config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_754 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/asus/m2n-e/Kconfig b/src/mainboard/asus/m2n-e/Kconfig index b0e31464db..d95d1e403f 100644 --- a/src/mainboard/asus/m2n-e/Kconfig +++ b/src/mainboard/asus/m2n-e/Kconfig @@ -22,7 +22,6 @@ if BOARD_ASUS_M2N_E config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/asus/m2v-mx_se/Kconfig b/src/mainboard/asus/m2v-mx_se/Kconfig index dca4984e4d..ce33acc0fd 100644 --- a/src/mainboard/asus/m2v-mx_se/Kconfig +++ b/src/mainboard/asus/m2v-mx_se/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_M2V_MX_SE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/asus/m2v/Kconfig b/src/mainboard/asus/m2v/Kconfig index 61ffd9abbe..811abbbd6a 100644 --- a/src/mainboard/asus/m2v/Kconfig +++ b/src/mainboard/asus/m2v/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_M2V config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select QRANK_DIMM_SUPPORT diff --git a/src/mainboard/asus/m4a78-em/Kconfig b/src/mainboard/asus/m4a78-em/Kconfig index d8a31910ee..494143abe3 100644 --- a/src/mainboard/asus/m4a78-em/Kconfig +++ b/src/mainboard/asus/m4a78-em/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_M4A78_EM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDFAM10 diff --git a/src/mainboard/asus/m4a785-m/Kconfig b/src/mainboard/asus/m4a785-m/Kconfig index c2ed696c46..1081697aad 100644 --- a/src/mainboard/asus/m4a785-m/Kconfig +++ b/src/mainboard/asus/m4a785-m/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_M4A785M config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDFAM10 diff --git a/src/mainboard/asus/m4a785t-m/Kconfig b/src/mainboard/asus/m4a785t-m/Kconfig index 10f6838ea7..2626787005 100644 --- a/src/mainboard/asus/m4a785t-m/Kconfig +++ b/src/mainboard/asus/m4a785t-m/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_M4A785TM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/asus/m5a88-v/Kconfig b/src/mainboard/asus/m5a88-v/Kconfig index 5318977cb6..238c08b37e 100644 --- a/src/mainboard/asus/m5a88-v/Kconfig +++ b/src/mainboard/asus/m5a88-v/Kconfig @@ -2,7 +2,6 @@ if BOARD_ASUS_M5A88_V config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/asus/m5a88-v/Makefile.inc b/src/mainboard/asus/m5a88-v/Makefile.inc index 35b20430c6..5e4a5f4032 100644 --- a/src/mainboard/asus/m5a88-v/Makefile.inc +++ b/src/mainboard/asus/m5a88-v/Makefile.inc @@ -12,5 +12,5 @@ ifneq ($(CONFIG_CPU_AMD_AGESA),y) -I$(AGESA_ROOT)/Proc/CPU/ \ -I$(AGESA_ROOT)/Proc/CPU/Family - CFLAGS += $(AGESA_INC) + CFLAGS_common += $(AGESA_INC) endif diff --git a/src/mainboard/asus/mew-am/Kconfig b/src/mainboard/asus/mew-am/Kconfig index ffd6e220c3..ad08c31056 100644 --- a/src/mainboard/asus/mew-am/Kconfig +++ b/src/mainboard/asus/mew-am/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_MEW_AM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/asus/mew-vm/Kconfig b/src/mainboard/asus/mew-vm/Kconfig index 341c533063..58910bec8b 100644 --- a/src/mainboard/asus/mew-vm/Kconfig +++ b/src/mainboard/asus/mew-vm/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_MEW_VM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/asus/p2b-d/Kconfig b/src/mainboard/asus/p2b-d/Kconfig index 54a1bae17e..b84a14219b 100644 --- a/src/mainboard/asus/p2b-d/Kconfig +++ b/src/mainboard/asus/p2b-d/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P2B_D config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/asus/p2b-ds/Kconfig b/src/mainboard/asus/p2b-ds/Kconfig index 652b31aefe..6a70e716b4 100644 --- a/src/mainboard/asus/p2b-ds/Kconfig +++ b/src/mainboard/asus/p2b-ds/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P2B_DS config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/asus/p2b-f/Kconfig b/src/mainboard/asus/p2b-f/Kconfig index e0554ca543..07fa74474a 100644 --- a/src/mainboard/asus/p2b-f/Kconfig +++ b/src/mainboard/asus/p2b-f/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P2B_F config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/asus/p2b-ls/Kconfig b/src/mainboard/asus/p2b-ls/Kconfig index f138463808..3822eb7884 100644 --- a/src/mainboard/asus/p2b-ls/Kconfig +++ b/src/mainboard/asus/p2b-ls/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P2B_LS config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/asus/p2b/Kconfig b/src/mainboard/asus/p2b/Kconfig index a57f7fbfa2..b1b5597874 100644 --- a/src/mainboard/asus/p2b/Kconfig +++ b/src/mainboard/asus/p2b/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P2B config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/asus/p3b-f/Kconfig b/src/mainboard/asus/p3b-f/Kconfig index d47dfdbc17..07cd91ff6e 100644 --- a/src/mainboard/asus/p3b-f/Kconfig +++ b/src/mainboard/asus/p3b-f/Kconfig @@ -20,7 +20,6 @@ if BOARD_ASUS_P3B_F config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/avalue/eax-785e/Kconfig b/src/mainboard/avalue/eax-785e/Kconfig index 11fc657f1d..01354daa57 100644 --- a/src/mainboard/avalue/eax-785e/Kconfig +++ b/src/mainboard/avalue/eax-785e/Kconfig @@ -2,7 +2,6 @@ if BOARD_AVALUE_EAX_785E config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/avalue/eax-785e/Makefile.inc b/src/mainboard/avalue/eax-785e/Makefile.inc index d69a9bf869..587c91ddfa 100644 --- a/src/mainboard/avalue/eax-785e/Makefile.inc +++ b/src/mainboard/avalue/eax-785e/Makefile.inc @@ -14,5 +14,5 @@ ifneq ($(CONFIG_CPU_AMD_AGESA),y) -I$(AGESA_ROOT)/Proc/CPU/ \ -I$(AGESA_ROOT)/Proc/CPU/Family - CFLAGS += $(AGESA_INC) + CFLAGS_common += $(AGESA_INC) endif diff --git a/src/mainboard/axus/tc320/Kconfig b/src/mainboard/axus/tc320/Kconfig index 868c8d1904..97c33aaebb 100644 --- a/src/mainboard/axus/tc320/Kconfig +++ b/src/mainboard/axus/tc320/Kconfig @@ -20,7 +20,6 @@ if BOARD_AXUS_TC320 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/azza/pt-6ibd/Kconfig b/src/mainboard/azza/pt-6ibd/Kconfig index 50ac62b582..8897102d49 100644 --- a/src/mainboard/azza/pt-6ibd/Kconfig +++ b/src/mainboard/azza/pt-6ibd/Kconfig @@ -20,7 +20,6 @@ if BOARD_AZZA_PT_6IBD config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/bachmann/ot200/Kconfig b/src/mainboard/bachmann/ot200/Kconfig index 0bf4a7068a..51984e602a 100644 --- a/src/mainboard/bachmann/ot200/Kconfig +++ b/src/mainboard/bachmann/ot200/Kconfig @@ -2,7 +2,6 @@ if BOARD_BACHMANN_OT200 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/bcom/winnet100/Kconfig b/src/mainboard/bcom/winnet100/Kconfig index d0a7807ada..503c92b63c 100644 --- a/src/mainboard/bcom/winnet100/Kconfig +++ b/src/mainboard/bcom/winnet100/Kconfig @@ -20,7 +20,6 @@ if BOARD_BCOM_WINNET100 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/bcom/winnetp680/Kconfig b/src/mainboard/bcom/winnetp680/Kconfig index 78e014e65c..f6a80af816 100644 --- a/src/mainboard/bcom/winnetp680/Kconfig +++ b/src/mainboard/bcom/winnetp680/Kconfig @@ -2,7 +2,6 @@ if BOARD_BCOM_WINNETP680 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_CN700 select SOUTHBRIDGE_VIA_VT8237R diff --git a/src/mainboard/bifferos/bifferboard/Kconfig b/src/mainboard/bifferos/bifferboard/Kconfig index 4ee995803c..9d00f5e586 100644 --- a/src/mainboard/bifferos/bifferboard/Kconfig +++ b/src/mainboard/bifferos/bifferboard/Kconfig @@ -2,7 +2,9 @@ if BOARD_BIFFEROS_BIFFERBOARD config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 select ROMCC select BOARD_ROMSIZE_KB_128 select NORTHBRIDGE_RDC_R8610 diff --git a/src/mainboard/biostar/m6tba/Kconfig b/src/mainboard/biostar/m6tba/Kconfig index 8d86ab4b4e..d83ceace1a 100644 --- a/src/mainboard/biostar/m6tba/Kconfig +++ b/src/mainboard/biostar/m6tba/Kconfig @@ -20,7 +20,6 @@ if BOARD_BIOSTAR_M6TBA config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/broadcom/blast/Kconfig b/src/mainboard/broadcom/blast/Kconfig index b953b6e1c6..fd41b04bb6 100644 --- a/src/mainboard/broadcom/blast/Kconfig +++ b/src/mainboard/broadcom/blast/Kconfig @@ -2,7 +2,6 @@ if BOARD_BROADCOM_BLAST config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/compaq/deskpro_en_sff_p600/Kconfig b/src/mainboard/compaq/deskpro_en_sff_p600/Kconfig index 1242a94266..62f038cae8 100644 --- a/src/mainboard/compaq/deskpro_en_sff_p600/Kconfig +++ b/src/mainboard/compaq/deskpro_en_sff_p600/Kconfig @@ -20,7 +20,6 @@ if BOARD_COMPAQ_DESKPRO_EN_SFF_P600 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/digitallogic/adl855pc/Kconfig b/src/mainboard/digitallogic/adl855pc/Kconfig index a20a5c8a5f..8c57a89e89 100644 --- a/src/mainboard/digitallogic/adl855pc/Kconfig +++ b/src/mainboard/digitallogic/adl855pc/Kconfig @@ -2,7 +2,6 @@ if BOARD_DIGITALLOGIC_ADL855PC config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA479M select NORTHBRIDGE_INTEL_I855 select SOUTHBRIDGE_INTEL_I82801DX diff --git a/src/mainboard/digitallogic/msm586seg/Kconfig b/src/mainboard/digitallogic/msm586seg/Kconfig index d54037a058..4cd6f11430 100644 --- a/src/mainboard/digitallogic/msm586seg/Kconfig +++ b/src/mainboard/digitallogic/msm586seg/Kconfig @@ -2,7 +2,6 @@ if BOARD_DIGITALLOGIC_MSM586SEG config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SC520 select HAVE_PIRQ_TABLE select HAVE_OPTION_TABLE diff --git a/src/mainboard/digitallogic/msm800sev/Kconfig b/src/mainboard/digitallogic/msm800sev/Kconfig index 0b54906757..bc8e3ac71b 100644 --- a/src/mainboard/digitallogic/msm800sev/Kconfig +++ b/src/mainboard/digitallogic/msm800sev/Kconfig @@ -2,7 +2,6 @@ if BOARD_DIGITALLOGIC_MSM800SEV config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/eaglelion/5bcm/Kconfig b/src/mainboard/eaglelion/5bcm/Kconfig index cc507f0448..3c0a800510 100644 --- a/src/mainboard/eaglelion/5bcm/Kconfig +++ b/src/mainboard/eaglelion/5bcm/Kconfig @@ -20,7 +20,6 @@ if BOARD_EAGLELION_5BCM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/ecs/p6iwp-fe/Kconfig b/src/mainboard/ecs/p6iwp-fe/Kconfig index c88d9765b0..99170be90c 100644 --- a/src/mainboard/ecs/p6iwp-fe/Kconfig +++ b/src/mainboard/ecs/p6iwp-fe/Kconfig @@ -21,7 +21,6 @@ if BOARD_ECS_P6IWP_FE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/emulation/Kconfig b/src/mainboard/emulation/Kconfig index ea6b18077b..b7efd5f1d5 100644 --- a/src/mainboard/emulation/Kconfig +++ b/src/mainboard/emulation/Kconfig @@ -3,16 +3,24 @@ if VENDOR_EMULATION choice prompt "Mainboard model" +config BOARD_EMULATION_IMGVP_PISTACHIO + bool "ImgTec Pistachio Virtual Platform" + config BOARD_EMULATION_QEMU_X86 bool "QEMU x86" +config BOARD_EMULATION_FOUNDATION_ARMV8 + bool "Foundation ARMV8 (may also work in qemu)" + config BOARD_EMULATION_QEMU_ARMV7 bool "QEMU armv7 (vexpress-a9)" endchoice +source "src/mainboard/emulation/imgvp-pistachio/Kconfig" source "src/mainboard/emulation/qemu-x86/Kconfig" source "src/mainboard/emulation/qemu-armv7/Kconfig" +source "src/mainboard/emulation/foundation-armv8/Kconfig" config MAINBOARD_VENDOR string diff --git a/src/mainboard/emulation/foundation-armv8/Kconfig b/src/mainboard/emulation/foundation-armv8/Kconfig new file mode 100644 index 0000000000..ba9657d404 --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/Kconfig @@ -0,0 +1,53 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This software is licensed under the terms of the GNU General Public +## License version 2, as published by the Free Software Foundation, and +## may be copied, distributed, and modified under those terms. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +# To execute, do: +# ./Foundation_v8 --cores=1 --no-secure-memory --visualization \ +# --gicv3 --data=build/coreboot.rom@0x0 + +if BOARD_EMULATION_FOUNDATION_ARMV8 + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_ARMLTD_ARMV8 + select HAVE_UART_MEMORY_MAPPED + select HAVE_UART_SPECIAL + select BOARD_ROMSIZE_KB_4096 + select DYNAMIC_CBMEM + +config MAINBOARD_DIR + string + default emulation/foundation-armv8 + +config MAINBOARD_PART_NUMBER + string + default "FOUNDATION ARMV8" + +config MAX_CPUS + int + default 1 + +config MAINBOARD_VENDOR + string + default "ARM Ltd." + +config BOOTBLOCK_MAINBOARD_INIT + string + default "mainboard/emulation/foundation-armv8/bootblock.c" + +config DRAM_SIZE_MB + int + default 1024 + +endif # BOARD_EMULATION_FOUNDATION_ARMV8 diff --git a/src/mainboard/emulation/foundation-armv8/Makefile.inc b/src/mainboard/emulation/foundation-armv8/Makefile.inc new file mode 100644 index 0000000000..2f59fc073a --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/Makefile.inc @@ -0,0 +1,31 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This software is licensed under the terms of the GNU General Public +## License version 2, as published by the Free Software Foundation, and +## may be copied, distributed, and modified under those terms. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +romstage-y += romstage.c + +bootblock-y += media.c +romstage-y += media.c +ramstage-y += media.c + +bootblock-y += timer.c +romstage-y += timer.c +ramstage-y += timer.c + +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c +romstage-$(CONFIG_EARLY_CONSOLE) += uart.c +ramstage-y += uart.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/emulation/qemu-armv7/bootblock.c b/src/mainboard/emulation/foundation-armv8/bootblock.c similarity index 80% rename from src/mainboard/emulation/qemu-armv7/bootblock.c rename to src/mainboard/emulation/foundation-armv8/bootblock.c index 56546672c7..daf15b0dfa 100644 --- a/src/mainboard/emulation/qemu-armv7/bootblock.c +++ b/src/mainboard/emulation/foundation-armv8/bootblock.c @@ -18,6 +18,8 @@ void bootblock_mainboard_init(void); void bootblock_mainboard_init(void) { - console_init(); - printk(BIOS_INFO, "\n\n\n%s: ARMv7 Emulation Started.\n", __func__); + /* if you want a banner in the bootblock, you'll have to call + * console_init. + */ + //printk(BIOS_INFO, "\n\n\n%s: ARMv7 Emulation Started.\n", __func__); } diff --git a/src/mainboard/emulation/foundation-armv8/devicetree.cb b/src/mainboard/emulation/foundation-armv8/devicetree.cb new file mode 100644 index 0000000000..91534427a9 --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/devicetree.cb @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google, Inc. +## +## This software is licensed under the terms of the GNU General Public +## License version 2, as published by the Free Software Foundation, and +## may be copied, distributed, and modified under those terms. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +# TODO fill with Versatile Express board data in QEMU. +chip cpu/armltd/cortex-a9 + chip drivers/generic/generic # I2C0 controller + device i2c 6 on end # Fake component for testing + end +end diff --git a/src/mainboard/emulation/foundation-armv8/mainboard.c b/src/mainboard/emulation/foundation-armv8/mainboard.c new file mode 100644 index 0000000000..195abd0af1 --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/mainboard.c @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +static void mainboard_enable(device_t dev) +{ + printk(BIOS_INFO, "Enable foundation/armv8 device...\n"); + + ram_resource(dev, 0, (uintptr_t)_dram / KiB, + (uintptr_t)_dram / KiB + CONFIG_DRAM_SIZE_MB * KiB); +} + +struct chip_operations mainboard_ops = { + CHIP_NAME("Foundation ARMv8 Model") + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/emulation/foundation-armv8/media.c b/src/mainboard/emulation/foundation-armv8/media.c new file mode 100644 index 0000000000..0998fb3656 --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/media.c @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include + +/* Simple memory-mapped ROM emulation. */ + +static int emu_rom_open(struct cbfs_media *media) { + return 0; +} + +static void *emu_rom_map(struct cbfs_media *media, + size_t offset, size_t count) { + return (void*)(offset + _bootblock); +} + +static void *emu_rom_unmap(struct cbfs_media *media, const void *address) { + return NULL; +} + +static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset, + size_t count) { + void *ptr = emu_rom_map(media, offset, count); + memcpy(dest, ptr, count); + emu_rom_unmap(media, ptr); + return count; +} + +static int emu_rom_close(struct cbfs_media *media) { + return 0; +} + +int init_emu_rom_cbfs_media(struct cbfs_media *media); +int init_emu_rom_cbfs_media(struct cbfs_media *media) { + media->open = emu_rom_open; + media->close = emu_rom_close; + media->map = emu_rom_map; + media->unmap = emu_rom_unmap; + media->read = emu_rom_read; + return 0; +} + +int init_default_cbfs_media(struct cbfs_media *media) { + return init_emu_rom_cbfs_media(media); +} diff --git a/src/mainboard/emulation/foundation-armv8/memlayout.ld b/src/mainboard/emulation/foundation-armv8/memlayout.ld new file mode 100644 index 0000000000..475a8fbcfc --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/memlayout.ld @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +/* + * Memory map for Foundation v2 model + * Reference: ARM v8-A Foundation Model User Guide + * + * 0x00_0000_0000 - 0x00_03FF_FFFF Trusted Boot ROM + * 0x00_0400_0000 - 0x00_0403_FFFF Trusted SRAM + * 0x00_0600_0000 - 0x00_07FF_FFFF Trusted DRAM + * 0x00_1C01_0000 - 0x00_1C01_FFFF System Registers + * 0x00_1C09_0000 - 0x00_1C09_FFFF UART0 (PL011) + * 0x00_2E00_0000 - 0x00_2E00_FFFF Non-trusted SRAM + * 0x00_8000_0000 - 0x00_FFFF_FFFF DRAM (0GB - 2GB) + * 0x08_8000_0000 - 0x09_FFFF_FFFF DRAM (2GB - 8GB) + */ + +SECTIONS +{ + /* ROM_START(0x00000000) */ + BOOTBLOCK(0x00000000, 32K) + /* ROM_END(0x04000000) */ + + SRAM_START(0x04000000) + ROMSTAGE(0x04000000, 128K) + SRAM_END(0x04030000) + + DRAM_START(0x80000000) + RAMSTAGE(0x80000000, 128K) + STACK(0x90000000, 16K) +} diff --git a/src/mainboard/emulation/qemu-armv7/ramstage.c b/src/mainboard/emulation/foundation-armv8/romstage.c similarity index 80% rename from src/mainboard/emulation/qemu-armv7/ramstage.c rename to src/mainboard/emulation/foundation-armv8/romstage.c index 24d0d7ff8f..52e3cb1422 100644 --- a/src/mainboard/emulation/qemu-armv7/ramstage.c +++ b/src/mainboard/emulation/foundation-armv8/romstage.c @@ -13,12 +13,17 @@ * GNU General Public License for more details. */ +#include #include +#include -void hardwaremain(int boot_complete); void main(void) { + void *entry; + console_init(); - printk(BIOS_INFO, "hello from ramstage\n"); - hardwaremain(0); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); + + stage_exit(entry); } diff --git a/src/cpu/armltd/cortex-a9/bootblock.c b/src/mainboard/emulation/foundation-armv8/timer.c similarity index 76% rename from src/cpu/armltd/cortex-a9/bootblock.c rename to src/mainboard/emulation/foundation-armv8/timer.c index 8925439d2a..7376a26280 100644 --- a/src/cpu/armltd/cortex-a9/bootblock.c +++ b/src/mainboard/emulation/foundation-armv8/timer.c @@ -1,4 +1,6 @@ /* + * This file is part of the coreboot project. + * * Copyright (C) 2013 Google, Inc. * * This software is licensed under the terms of the GNU General Public @@ -11,7 +13,13 @@ * GNU General Public License for more details. */ -void bootblock_cpu_init(void); -void bootblock_cpu_init(void) +#include + +void udelay(unsigned int n) +{ + /* TODO provide delay here. */ +} + +void init_timer(void) { } diff --git a/src/mainboard/emulation/foundation-armv8/uart.c b/src/mainboard/emulation/foundation-armv8/uart.c new file mode 100644 index 0000000000..819c7c414d --- /dev/null +++ b/src/mainboard/emulation/foundation-armv8/uart.c @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#define FOUNDATION_UART0_IO_ADDRESS (0x1C090000) + +#define PL011_UARTCR_OFFSET (0x030) + +static void pl011_init_dev(void) +{ + static volatile uint32_t *uartcr_address = + (uint32_t *)(FOUNDATION_UART0_IO_ADDRESS + PL011_UARTCR_OFFSET); + + /* Enable TX and UART */ + *uartcr_address = *uartcr_address | (1 << 8) | (1 << 0); +} + +static void pl011_uart_tx_byte(uint8_t data) +{ + static volatile uint32_t *uart0_address = + (uint32_t *)FOUNDATION_UART0_IO_ADDRESS; + + *uart0_address = (uint32_t)data; +} + +static void pl011_uart_tx_flush(void) +{ +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver pl011_uart_console __console = { + .init = pl011_init_dev, + .tx_byte = pl011_uart_tx_byte, + .tx_flush = pl011_uart_tx_flush, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return FOUNDATION_UART0_IO_ADDRESS; +} + +#else +void uart_init(void) +{ + pl011_init_dev(); +} + +void uart_tx_byte(unsigned char data) +{ + pl011_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ + pl011_uart_tx_flush(); +} +#endif diff --git a/src/mainboard/emulation/imgvp-pistachio/Kconfig b/src/mainboard/emulation/imgvp-pistachio/Kconfig new file mode 100644 index 0000000000..068528e6d6 --- /dev/null +++ b/src/mainboard/emulation/imgvp-pistachio/Kconfig @@ -0,0 +1,53 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +if BOARD_EMULATION_IMGVP_PISTACHIO + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOOTBLOCK_CONSOLE + select CPU_IMGTEC_PISTACHIO + +config MAINBOARD_DIR + string + default emulation/imgvp-pistachio + +config MAINBOARD_PART_NUMBER + string + default "ImgTec Pistachio Virtual Platform" + +config BOOTBLOCK_MAINBOARD_INIT + string + default "mainboard/emulation/imgvp-pistachio/bootblock.c" + +config SYS_SDRAM_BASE + hex "SDRAM base address" + default 0x80000000 + +config DRAM_SIZE_MB + int + default 256 + +config HEAP_SIZE + hex + default 0x08000000 + +endif diff --git a/src/mainboard/emulation/imgvp-pistachio/Makefile.inc b/src/mainboard/emulation/imgvp-pistachio/Makefile.inc new file mode 100644 index 0000000000..8be1b22946 --- /dev/null +++ b/src/mainboard/emulation/imgvp-pistachio/Makefile.inc @@ -0,0 +1,22 @@ +# +# This file is part of the coreboot project. +# +# Copyright 2014 Imagination Technologies Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +romstage-y += romstage.c diff --git a/src/mainboard/emulation/imgvp-pistachio/bootblock.c b/src/mainboard/emulation/imgvp-pistachio/bootblock.c new file mode 100644 index 0000000000..1784a02f44 --- /dev/null +++ b/src/mainboard/emulation/imgvp-pistachio/bootblock.c @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +void bootblock_mainboard_init(void) +{ +} diff --git a/src/mainboard/emulation/imgvp-pistachio/devicetree.cb b/src/mainboard/emulation/imgvp-pistachio/devicetree.cb new file mode 100644 index 0000000000..a328b9d1cf --- /dev/null +++ b/src/mainboard/emulation/imgvp-pistachio/devicetree.cb @@ -0,0 +1,26 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +chip soc/imgtec/pistachio + chip drivers/generic/generic # I2C0 controller + device i2c 6 on end # Fake component for testing + end +end diff --git a/src/mainboard/google/snow/mainboard.h b/src/mainboard/emulation/imgvp-pistachio/mainboard.c similarity index 55% rename from src/mainboard/google/snow/mainboard.h rename to src/mainboard/emulation/imgvp-pistachio/mainboard.c index 6fe371fc99..fdae940c6f 100644 --- a/src/mainboard/google/snow/mainboard.h +++ b/src/mainboard/emulation/imgvp-pistachio/mainboard.c @@ -1,5 +1,7 @@ /* - * Copyright (C) 2013 Google Inc. + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -13,26 +15,19 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA */ -#ifndef MAINBOARD_H -#define MAINBOARD_H +#include +#include -enum snow_board_config { - SNOW_CONFIG_UNKNOWN = -1, - SNOW_CONFIG_SAMSUNG_EVT, - SNOW_CONFIG_ELPIDA_EVT, - SNOW_CONFIG_SAMSUNG_DVT, - SNOW_CONFIG_ELPIDA_DVT, - SNOW_CONFIG_SAMSUNG_PVT, - SNOW_CONFIG_ELPIDA_PVT, - SNOW_CONFIG_SAMSUNG_MP, - SNOW_CONFIG_ELPIDA_MP, - SNOW_CONFIG_RSVD, +static void mainboard_enable(device_t dev) +{ + printk(BIOS_INFO, "Enable imgvp-pistachio device...\n"); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, }; -int board_get_config(void); - -#endif /* MAINBOARD_H */ diff --git a/src/mainboard/emulation/imgvp-pistachio/romstage.c b/src/mainboard/emulation/imgvp-pistachio/romstage.c new file mode 100644 index 0000000000..ac0ea5f903 --- /dev/null +++ b/src/mainboard/emulation/imgvp-pistachio/romstage.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void main(void) +{ + void *entry; + + console_init(); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); + if (entry != (void *)-1) + stage_exit(entry); + + hlt(); +} diff --git a/src/mainboard/emulation/qemu-armv7/Kconfig b/src/mainboard/emulation/qemu-armv7/Kconfig index b66761d512..8ddf51fec0 100644 --- a/src/mainboard/emulation/qemu-armv7/Kconfig +++ b/src/mainboard/emulation/qemu-armv7/Kconfig @@ -1,7 +1,7 @@ ## ## This file is part of the coreboot project. ## -## Copyright (C) 2013 Google Inc. +## Copyright 2014 Google Inc. ## ## This software is licensed under the terms of the GNU General Public ## License version 2, as published by the Free Software Foundation, and @@ -23,11 +23,15 @@ if BOARD_EMULATION_QEMU_ARMV7 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_ARMV7 select CPU_ARMLTD_CORTEX_A9 select HAVE_UART_MEMORY_MAPPED - select DEFAULT_EARLY_CONSOLE select HAVE_UART_SPECIAL + select BOOTBLOCK_CONSOLE + select EARLY_CONSOLE + select CONSOLE_SERIAL + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 select BOARD_ROMSIZE_KB_4096 config MAINBOARD_DIR @@ -36,7 +40,7 @@ config MAINBOARD_DIR config MAINBOARD_PART_NUMBER string - default "QEMU ARMV7" + default "QEMU ARMv7" config MAX_CPUS int @@ -46,72 +50,8 @@ config MAINBOARD_VENDOR string default "ARM Ltd." -config BOOTBLOCK_MAINBOARD_INIT - string - default "mainboard/emulation/qemu-armv7/bootblock.c" - config DRAM_SIZE_MB int default 1024 -# Memory map for qemu vexpress-a9: -# -# 0x0000_0000: jump instruction (by qemu) -# 0x0001_0000: bootblock (entry of kernel / firmware) -# 0x0002_0000: romstage, assume up to 128KB in size. -# 0x0007_ff00: stack pointer -# 0x0010_0000: CBFS header -# 0x0011_0000: CBFS data -# 0x0100_0000: reserved for ramstage -# 0x1000_0000: I/O map address - -config BOOTBLOCK_BASE - hex - default 0x00010000 - -config ID_SECTION_BASE - hex - default 0x0001f000 - -config ROMSTAGE_BASE - hex - default 0x00020000 - -config ROMSTAGE_SIZE - hex - default 0x20000 - -config CBFS_HEADER_ROM_OFFSET - hex - default 0x0100000 - -config CBFS_ROM_OFFSET - hex - default 0x0110000 - -config IRAM_STACK - hex - default 0x0007ff00 - -config XIP_ROM_SIZE - hex - default ROMSTAGE_SIZE - -config SYS_SDRAM_BASE - hex "SDRAM base address" - default 0x01000000 - -config SYS_TEXT_BASE - hex "Executable code section" - default 0x04e00000 - -config RAMBASE - hex - default SYS_SDRAM_BASE - -# according to stefan, this is RAMBASE + 1M. -config RAMTOP - hex - default 0x01100000 - endif # BOARD_EMULATION_QEMU_ARMV7 diff --git a/src/mainboard/emulation/qemu-armv7/Makefile.inc b/src/mainboard/emulation/qemu-armv7/Makefile.inc index 80b392b11e..2f59fc073a 100644 --- a/src/mainboard/emulation/qemu-armv7/Makefile.inc +++ b/src/mainboard/emulation/qemu-armv7/Makefile.inc @@ -13,7 +13,6 @@ ## GNU General Public License for more details. romstage-y += romstage.c -ramstage-y += ramstage.c bootblock-y += media.c romstage-y += media.c @@ -23,6 +22,10 @@ bootblock-y += timer.c romstage-y += timer.c ramstage-y += timer.c -bootblock-$(CONFIG_EARLY_CONSOLE) += uart.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c romstage-$(CONFIG_EARLY_CONSOLE) += uart.c ramstage-y += uart.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c index d024b5d340..8e6cd46946 100644 --- a/src/mainboard/emulation/qemu-armv7/media.c +++ b/src/mainboard/emulation/qemu-armv7/media.c @@ -14,36 +14,44 @@ */ #include #include +#include #include /* Simple memory-mapped ROM emulation. */ -static int emu_rom_open(struct cbfs_media *media) { +static int emu_rom_open(struct cbfs_media *media) +{ return 0; } -static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count) { - return (void*)(offset + CONFIG_BOOTBLOCK_BASE); +static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count) +{ + return (void*)(offset + _bootblock); } -static void *emu_rom_unmap(struct cbfs_media *media, const void *address) { +static void *emu_rom_unmap(struct cbfs_media *media, const void *address) +{ return NULL; } static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count) { + size_t count) +{ void *ptr = emu_rom_map(media, offset, count); memcpy(dest, ptr, count); emu_rom_unmap(media, ptr); return count; } -static int emu_rom_close(struct cbfs_media *media) { +static int emu_rom_close(struct cbfs_media *media) +{ return 0; } int init_emu_rom_cbfs_media(struct cbfs_media *media); -int init_emu_rom_cbfs_media(struct cbfs_media *media) { + +int init_emu_rom_cbfs_media(struct cbfs_media *media) +{ media->open = emu_rom_open; media->close = emu_rom_close; media->map = emu_rom_map; @@ -52,6 +60,7 @@ int init_emu_rom_cbfs_media(struct cbfs_media *media) { return 0; } -int init_default_cbfs_media(struct cbfs_media *media) { +int init_default_cbfs_media(struct cbfs_media *media) +{ return init_emu_rom_cbfs_media(media); } diff --git a/src/mainboard/emulation/qemu-armv7/memlayout.ld b/src/mainboard/emulation/qemu-armv7/memlayout.ld new file mode 100644 index 0000000000..8990afa51a --- /dev/null +++ b/src/mainboard/emulation/qemu-armv7/memlayout.ld @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +/* + * Memory map for qemu vexpress-a9: + * + * 0x0000_0000: jump instruction (by qemu) + * 0x0001_0000: bootblock (entry of kernel / firmware) + * 0x0002_0000: romstage, assume up to 128KB in size. + * 0x0007_ff00: stack pointer + * 0x0010_0000: CBFS header + * 0x0011_0000: CBFS data + * 0x0100_0000: reserved for ramstage + * 0x1000_0000: I/O map address + */ + +SECTIONS +{ + /* TODO: does this thing emulate SRAM? */ + + BOOTBLOCK(0x10000, 64K) + ROMSTAGE(0x20000, 128K) + STACK(0x000FC000, 16K) + + DRAM_START(0x01000000) + RAMSTAGE(0x01000000) +} diff --git a/src/mainboard/emulation/qemu-armv7/romstage.c b/src/mainboard/emulation/qemu-armv7/romstage.c index 81f62b6b83..00dfecd431 100644 --- a/src/mainboard/emulation/qemu-armv7/romstage.c +++ b/src/mainboard/emulation/qemu-armv7/romstage.c @@ -14,18 +14,16 @@ */ #include -#include #include #include void main(void) { void *entry; - console_init(); - printk(BIOS_INFO, "hello from romstage\n"); - entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram"); - printk(BIOS_INFO, "entry is 0x%p, leaving romstage.\n", entry); + console_init(); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); stage_exit(entry); } diff --git a/src/mainboard/emulation/qemu-armv7/timer.c b/src/mainboard/emulation/qemu-armv7/timer.c index 53c378940d..b479d428f9 100644 --- a/src/mainboard/emulation/qemu-armv7/timer.c +++ b/src/mainboard/emulation/qemu-armv7/timer.c @@ -14,11 +14,13 @@ */ void udelay(unsigned int n); -void udelay(unsigned int n) { +void udelay(unsigned int n) +{ /* TODO provide delay here. */ } int init_timer(void); -int init_timer(void) { +int init_timer(void) +{ return 0; } diff --git a/src/mainboard/emulation/qemu-armv7/uart.c b/src/mainboard/emulation/qemu-armv7/uart.c index dfe5d0ac12..ccea598611 100644 --- a/src/mainboard/emulation/qemu-armv7/uart.c +++ b/src/mainboard/emulation/qemu-armv7/uart.c @@ -18,17 +18,20 @@ #define VEXPRESS_UART0_IO_ADDRESS (0x10009000) -static void pl011_init_dev(void) { +static void pl011_init_dev(void) +{ } -static void pl011_uart_tx_byte(unsigned char data) { - static volatile unsigned int *uart0_address = - (unsigned int *)VEXPRESS_UART0_IO_ADDRESS; +static void pl011_uart_tx_byte(uint8_t data) +{ + static volatile uint32_t *uart0_address = + (uint32_t *)VEXPRESS_UART0_IO_ADDRESS; - *uart0_address = (unsigned int)data; + *uart0_address = (uint32_t)data; } -static void pl011_uart_tx_flush(void) { +static void pl011_uart_tx_flush(void) +{ } #if !defined(__PRE_RAM__) @@ -54,7 +57,8 @@ void uart_tx_byte(unsigned char data) pl011_uart_tx_byte(data); } -void uart_tx_flush(void) { +void uart_tx_flush(void) +{ pl011_uart_tx_flush(); } #endif diff --git a/src/mainboard/emulation/qemu-x86/Kconfig b/src/mainboard/emulation/qemu-x86/Kconfig index bf21acd5c2..beb8b69a29 100644 --- a/src/mainboard/emulation/qemu-x86/Kconfig +++ b/src/mainboard/emulation/qemu-x86/Kconfig @@ -2,7 +2,6 @@ if BOARD_EMULATION_QEMU_X86 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select SOUTHBRIDGE_INTEL_I82371EB select CACHE_AS_RAM select HAVE_OPTION_TABLE diff --git a/src/mainboard/emulation/qemu-x86/cache_as_ram.inc b/src/mainboard/emulation/qemu-x86/cache_as_ram.inc index 1a7d8af696..11ac91d049 100644 --- a/src/mainboard/emulation/qemu-x86/cache_as_ram.inc +++ b/src/mainboard/emulation/qemu-x86/cache_as_ram.inc @@ -80,17 +80,12 @@ __acpi_resume_backup_done: post_code(0x3d) - /* Clear boot_complete flag. */ - xorl %ebp, %ebp __main: post_code(POST_PREPARE_RAMSTAGE) cld /* Clear direction flag. */ - movl %ebp, %esi - movl $ROMSTAGE_STACK, %esp movl %esp, %ebp - pushl %esi call copy_and_run .Lhlt: diff --git a/src/mainboard/emulation/qemu-x86/romstage.c b/src/mainboard/emulation/qemu-x86/romstage.c index 3faf947e00..74e9e8a50f 100644 --- a/src/mainboard/emulation/qemu-x86/romstage.c +++ b/src/mainboard/emulation/qemu-x86/romstage.c @@ -49,13 +49,7 @@ void main(unsigned long bist) //dump_pci_devices(); cbmem_was_initted = !cbmem_initialize(); -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(rdtsc()); timestamp_add_now(TS_START_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif - } diff --git a/src/mainboard/getac/p470/Kconfig b/src/mainboard/getac/p470/Kconfig index e7f3c95209..92ca60630f 100644 --- a/src/mainboard/getac/p470/Kconfig +++ b/src/mainboard/getac/p470/Kconfig @@ -20,7 +20,6 @@ if BOARD_GETAC_P470 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/getac/p470/smihandler.c b/src/mainboard/getac/p470/smihandler.c index 6122c82e9a..c66abadd7a 100644 --- a/src/mainboard/getac/p470/smihandler.c +++ b/src/mainboard/getac/p470/smihandler.c @@ -180,7 +180,7 @@ static void mainboard_smi_hotkey(u8 hotkey) printk(BIOS_DEBUG, "EC hotkey: %02x\n", hotkey); } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { u8 source, hotkey; send_ec_oem_command(0x5c); diff --git a/src/mainboard/gigabyte/ga-6bxc/Kconfig b/src/mainboard/gigabyte/ga-6bxc/Kconfig index 62625fbd62..8ea1abd2b3 100644 --- a/src/mainboard/gigabyte/ga-6bxc/Kconfig +++ b/src/mainboard/gigabyte/ga-6bxc/Kconfig @@ -20,7 +20,6 @@ if BOARD_GIGABYTE_GA_6BXC config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/gigabyte/ga-6bxe/Kconfig b/src/mainboard/gigabyte/ga-6bxe/Kconfig index 6e3462e261..5b35e7d379 100644 --- a/src/mainboard/gigabyte/ga-6bxe/Kconfig +++ b/src/mainboard/gigabyte/ga-6bxe/Kconfig @@ -21,7 +21,6 @@ if BOARD_GIGABYTE_GA_6BXE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/gigabyte/ga_2761gxdk/Kconfig b/src/mainboard/gigabyte/ga_2761gxdk/Kconfig index c535294c89..9756dd1eff 100644 --- a/src/mainboard/gigabyte/ga_2761gxdk/Kconfig +++ b/src/mainboard/gigabyte/ga_2761gxdk/Kconfig @@ -2,7 +2,6 @@ if BOARD_GIGABYTE_GA_2761GXDK config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/gigabyte/ga_2761gxdk/ap_romstage.c b/src/mainboard/gigabyte/ga_2761gxdk/ap_romstage.c deleted file mode 100644 index 9def81d7ac..0000000000 --- a/src/mainboard/gigabyte/ga_2761gxdk/ap_romstage.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS) - * Written by Morgan Tsai for SiS. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include - -#include "lib/uart8250.c" -#include "arch/x86/lib/printk_init.c" -#include "console/vtxprintf.c" -#include "console/console.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -//#include "cpu/x86/lapic/boot_cpu.c" -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/sis/sis966/sis966_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - //FIXME: for USBDEBUG you need to make sure dbg_info get assigned in AP - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - go back, but can not use stack any more, because we only keep ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); - - - -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - - diff --git a/src/mainboard/gigabyte/m57sli/Kconfig b/src/mainboard/gigabyte/m57sli/Kconfig index daae829478..c4b4f8af2a 100644 --- a/src/mainboard/gigabyte/m57sli/Kconfig +++ b/src/mainboard/gigabyte/m57sli/Kconfig @@ -2,7 +2,6 @@ if BOARD_GIGABYTE_M57SLI config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/gigabyte/m57sli/ap_romstage.c b/src/mainboard/gigabyte/m57sli/ap_romstage.c deleted file mode 100644 index df00eed17e..0000000000 --- a/src/mainboard/gigabyte/m57sli/ap_romstage.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include - -#include "lib/uart8250.c" -#include "arch/x86/lib/printk_init.c" -#include "console/vtxprintf.c" -#include "console/console.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -//#include "cpu/x86/lapic/boot_cpu.c" -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - //FIXME: for USBDEBUG you need to make sure dbg_info get assigned in AP - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - go back, but can not use stack any more, because we only keep ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); - - - -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - - diff --git a/src/mainboard/gigabyte/ma785gm/Kconfig b/src/mainboard/gigabyte/ma785gm/Kconfig index 8ff88b27c9..dad30d4c33 100644 --- a/src/mainboard/gigabyte/ma785gm/Kconfig +++ b/src/mainboard/gigabyte/ma785gm/Kconfig @@ -2,7 +2,6 @@ if BOARD_GIGABYTE_MA785GM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/gigabyte/ma785gmt/Kconfig b/src/mainboard/gigabyte/ma785gmt/Kconfig index 15032f6de4..5c5ce9493e 100644 --- a/src/mainboard/gigabyte/ma785gmt/Kconfig +++ b/src/mainboard/gigabyte/ma785gmt/Kconfig @@ -2,7 +2,6 @@ if BOARD_GIGABYTE_MA785GMT config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM3 select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/gigabyte/ma78gm/Kconfig b/src/mainboard/gigabyte/ma78gm/Kconfig index 20be00f150..b471d6801a 100644 --- a/src/mainboard/gigabyte/ma78gm/Kconfig +++ b/src/mainboard/gigabyte/ma78gm/Kconfig @@ -2,7 +2,6 @@ if BOARD_GIGABYTE_MA78GM config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2R2 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/gizmosphere/Kconfig b/src/mainboard/gizmosphere/Kconfig new file mode 100755 index 0000000000..fe4d77fdb2 --- /dev/null +++ b/src/mainboard/gizmosphere/Kconfig @@ -0,0 +1,16 @@ +if VENDOR_GIZMOSPHERE + +choice + prompt "Mainboard model" + +config BOARD_GIZMOSPHERE_GIZMO + bool "Gizmo" + +endchoice + +source "src/mainboard/gizmosphere/gizmo/Kconfig" +config MAINBOARD_VENDOR + string + default "GizmoSphere" + +endif # VENDOR_GIZMOSPHERE diff --git a/src/mainboard/gizmosphere/gizmo/BiosCallOuts.c b/src/mainboard/gizmosphere/gizmo/BiosCallOuts.c new file mode 100755 index 0000000000..c17ab03421 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/BiosCallOuts.c @@ -0,0 +1,473 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "agesawrapper.h" +#include "amdlib.h" +#include "BiosCallOuts.h" +#include "heapManager.h" +#include "SB800.h" +#include + +STATIC BIOS_CALLOUT_STRUCT BiosCallouts[] = +{ + {AGESA_ALLOCATE_BUFFER, + BiosAllocateBuffer + }, + + {AGESA_DEALLOCATE_BUFFER, + BiosDeallocateBuffer + }, + + {AGESA_DO_RESET, + BiosReset + }, + + {AGESA_LOCATE_BUFFER, + BiosLocateBuffer + }, + + {AGESA_READ_SPD, + BiosReadSpd + }, + + {AGESA_READ_SPD_RECOVERY, + BiosDefaultRet + }, + + {AGESA_RUNFUNC_ONAP, + BiosRunFuncOnAp + }, + + {AGESA_GNB_PCIE_SLOT_RESET, + BiosGnbPcieSlotReset + }, + + {AGESA_HOOKBEFORE_DRAM_INIT, + BiosHookBeforeDramInit + }, + + {AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY, + BiosHookBeforeDramInitRecovery + }, + + {AGESA_HOOKBEFORE_DQS_TRAINING, + BiosHookBeforeDQSTraining + }, + + {AGESA_HOOKBEFORE_EXIT_SELF_REF, + BiosHookBeforeExitSelfRefresh + }, +}; + +AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + UINTN i; + AGESA_STATUS CalloutStatus; + UINTN CallOutCount = sizeof (BiosCallouts) / sizeof (BiosCallouts [0]); + + /* + * printk(BIOS_SPEW,"%s function: %x\n", __func__, (u32) Func); + */ + + CalloutStatus = AGESA_UNSUPPORTED; + + for (i = 0; i < CallOutCount; i++) { + if (BiosCallouts[i].CalloutName == Func) { + CalloutStatus = BiosCallouts[i].CalloutPtr (Func, Data, ConfigPtr); + return CalloutStatus; + } + } + + return CalloutStatus; +} + +AGESA_STATUS BiosAllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + UINT32 AvailableHeapSize; + UINT8 *BiosHeapBaseAddr; + UINT32 CurrNodeOffset; + UINT32 PrevNodeOffset; + UINT32 FreedNodeOffset; + UINT32 BestFitNodeOffset; + UINT32 BestFitPrevNodeOffset; + UINT32 NextFreeOffset; + BIOS_BUFFER_NODE *CurrNodePtr; + BIOS_BUFFER_NODE *FreedNodePtr; + BIOS_BUFFER_NODE *BestFitNodePtr; + BIOS_BUFFER_NODE *BestFitPrevNodePtr; + BIOS_BUFFER_NODE *NextFreePtr; + BIOS_HEAP_MANAGER *BiosHeapBasePtr; + AGESA_BUFFER_PARAMS *AllocParams; + + AllocParams = ((AGESA_BUFFER_PARAMS *) ConfigPtr); + AllocParams->BufferPointer = NULL; + + AvailableHeapSize = BIOS_HEAP_SIZE - sizeof (BIOS_HEAP_MANAGER); + BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader)); + BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr; + + printk(BIOS_SPEW, "%s BiosHeapBaseAddr: %x\n", __func__, (u32) BiosHeapBaseAddr); + + if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) { + /* First allocation */ + CurrNodeOffset = sizeof (BIOS_HEAP_MANAGER); + CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset); + CurrNodePtr->BufferHandle = AllocParams->BufferHandle; + CurrNodePtr->BufferSize = AllocParams->BufferLength; + CurrNodePtr->NextNodeOffset = 0; + AllocParams->BufferPointer = (UINT8 *) CurrNodePtr + sizeof (BIOS_BUFFER_NODE); + + /* Update the remaining free space */ + FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize + sizeof (BIOS_BUFFER_NODE); + FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset); + FreedNodePtr->BufferSize = AvailableHeapSize - sizeof (BIOS_BUFFER_NODE) - CurrNodePtr->BufferSize; + FreedNodePtr->NextNodeOffset = 0; + + /* Update the offsets for Allocated and Freed nodes */ + BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset; + BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset; + } else { + /* Find out whether BufferHandle has been allocated on the heap. */ + /* If it has, return AGESA_BOUNDS_CHK */ + CurrNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; + CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset); + + while (CurrNodeOffset != 0) { + CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset); + if (CurrNodePtr->BufferHandle == AllocParams->BufferHandle) { + return AGESA_BOUNDS_CHK; + } + CurrNodeOffset = CurrNodePtr->NextNodeOffset; + /* If BufferHandle has not been allocated on the heap, CurrNodePtr here points + to the end of the allocated nodes list. + */ + + } + /* Find the node that best fits the requested buffer size */ + FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes; + PrevNodeOffset = FreedNodeOffset; + BestFitNodeOffset = 0; + BestFitPrevNodeOffset = 0; + while (FreedNodeOffset != 0) { + FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset); + if (FreedNodePtr->BufferSize >= (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) { + if (BestFitNodeOffset == 0) { + /* First node that fits the requested buffer size */ + BestFitNodeOffset = FreedNodeOffset; + BestFitPrevNodeOffset = PrevNodeOffset; + } else { + /* Find out whether current node is a better fit than the previous nodes */ + BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset); + if (BestFitNodePtr->BufferSize > FreedNodePtr->BufferSize) { + BestFitNodeOffset = FreedNodeOffset; + BestFitPrevNodeOffset = PrevNodeOffset; + } + } + } + PrevNodeOffset = FreedNodeOffset; + FreedNodeOffset = FreedNodePtr->NextNodeOffset; + } /* end of while loop */ + + + if (BestFitNodeOffset == 0) { + /* If we could not find a node that fits the requested buffer */ + /* size, return AGESA_BOUNDS_CHK */ + return AGESA_BOUNDS_CHK; + } else { + BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset); + BestFitPrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitPrevNodeOffset); + + /* If BestFitNode is larger than the requested buffer, fragment the node further */ + if (BestFitNodePtr->BufferSize > (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) { + NextFreeOffset = BestFitNodeOffset + AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE); + + NextFreePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextFreeOffset); + NextFreePtr->BufferSize = BestFitNodePtr->BufferSize - (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE)); + NextFreePtr->NextNodeOffset = BestFitNodePtr->NextNodeOffset; + } else { + /* Otherwise, next free node is NextNodeOffset of BestFitNode */ + NextFreeOffset = BestFitNodePtr->NextNodeOffset; + } + + /* If BestFitNode is the first buffer in the list, then update + StartOfFreedNodes to reflect the new free node + */ + if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes) { + BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset; + } else { + BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset; + } + + /* Add BestFitNode to the list of Allocated nodes */ + CurrNodePtr->NextNodeOffset = BestFitNodeOffset; + BestFitNodePtr->BufferSize = AllocParams->BufferLength; + BestFitNodePtr->BufferHandle = AllocParams->BufferHandle; + BestFitNodePtr->NextNodeOffset = 0; + + /* Remove BestFitNode from list of Freed nodes */ + AllocParams->BufferPointer = (UINT8 *) BestFitNodePtr + sizeof (BIOS_BUFFER_NODE); + } + } + + return AGESA_SUCCESS; +} + +AGESA_STATUS BiosDeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + + UINT8 *BiosHeapBaseAddr; + UINT32 AllocNodeOffset; + UINT32 PrevNodeOffset; + UINT32 NextNodeOffset; + UINT32 FreedNodeOffset; + UINT32 EndNodeOffset; + BIOS_BUFFER_NODE *AllocNodePtr; + BIOS_BUFFER_NODE *PrevNodePtr; + BIOS_BUFFER_NODE *FreedNodePtr; + BIOS_BUFFER_NODE *NextNodePtr; + BIOS_HEAP_MANAGER *BiosHeapBasePtr; + AGESA_BUFFER_PARAMS *AllocParams; + + AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr; + + BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader)); + BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr; + + /* Find target node to deallocate in list of allocated nodes. + Return AGESA_BOUNDS_CHK if the BufferHandle is not found + */ + AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; + AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset); + PrevNodeOffset = AllocNodeOffset; + + while (AllocNodePtr->BufferHandle != AllocParams->BufferHandle) { + if (AllocNodePtr->NextNodeOffset == 0) { + return AGESA_BOUNDS_CHK; + } + PrevNodeOffset = AllocNodeOffset; + AllocNodeOffset = AllocNodePtr->NextNodeOffset; + AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset); + } + + /* Remove target node from list of allocated nodes */ + PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset); + PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset; + + /* Zero out the buffer, and clear the BufferHandle */ + LibAmdMemFill ((UINT8 *)AllocNodePtr + sizeof (BIOS_BUFFER_NODE), 0, AllocNodePtr->BufferSize, &(AllocParams->StdHeader)); + AllocNodePtr->BufferHandle = 0; + AllocNodePtr->BufferSize += sizeof (BIOS_BUFFER_NODE); + + /* Add deallocated node in order to the list of freed nodes */ + FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes; + FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset); + + EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize; + + if (AllocNodeOffset < FreedNodeOffset) { + /* Add to the start of the freed list */ + if (EndNodeOffset == FreedNodeOffset) { + /* If the freed node is adjacent to the first node in the list, concatenate both nodes */ + AllocNodePtr->BufferSize += FreedNodePtr->BufferSize; + AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; + + /* Clear the BufferSize and NextNodeOffset of the previous first node */ + FreedNodePtr->BufferSize = 0; + FreedNodePtr->NextNodeOffset = 0; + + } else { + /* Otherwise, add freed node to the start of the list + Update NextNodeOffset and BufferSize to include the + size of BIOS_BUFFER_NODE + */ + AllocNodePtr->NextNodeOffset = FreedNodeOffset; + } + /* Update StartOfFreedNodes to the new first node */ + BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset; + } else { + /* Traverse list of freed nodes to find where the deallocated node + should be place + */ + NextNodeOffset = FreedNodeOffset; + NextNodePtr = FreedNodePtr; + while (AllocNodeOffset > NextNodeOffset) { + PrevNodeOffset = NextNodeOffset; + if (NextNodePtr->NextNodeOffset == 0) { + break; + } + NextNodeOffset = NextNodePtr->NextNodeOffset; + NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset); + } + + /* If deallocated node is adjacent to the next node, + concatenate both nodes + */ + if (NextNodeOffset == EndNodeOffset) { + NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset); + AllocNodePtr->BufferSize += NextNodePtr->BufferSize; + AllocNodePtr->NextNodeOffset = NextNodePtr->NextNodeOffset; + + NextNodePtr->BufferSize = 0; + NextNodePtr->NextNodeOffset = 0; + } else { + /*AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; */ + AllocNodePtr->NextNodeOffset = NextNodeOffset; + } + /* If deallocated node is adjacent to the previous node, + concatenate both nodes + */ + PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset); + EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize; + if (AllocNodeOffset == EndNodeOffset) { + PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset; + PrevNodePtr->BufferSize += AllocNodePtr->BufferSize; + + AllocNodePtr->BufferSize = 0; + AllocNodePtr->NextNodeOffset = 0; + } else { + PrevNodePtr->NextNodeOffset = AllocNodeOffset; + } + } + return AGESA_SUCCESS; +} + +AGESA_STATUS BiosLocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + UINT32 AllocNodeOffset; + UINT8 *BiosHeapBaseAddr; + BIOS_BUFFER_NODE *AllocNodePtr; + BIOS_HEAP_MANAGER *BiosHeapBasePtr; + AGESA_BUFFER_PARAMS *AllocParams; + + AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr; + + BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader)); + BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr; + + AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; + AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset); + + while (AllocParams->BufferHandle != AllocNodePtr->BufferHandle) { + if (AllocNodePtr->NextNodeOffset == 0) { + AllocParams->BufferPointer = NULL; + AllocParams->BufferLength = 0; + return AGESA_BOUNDS_CHK; + } else { + AllocNodeOffset = AllocNodePtr->NextNodeOffset; + AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset); + } + } + + AllocParams->BufferPointer = (UINT8 *) ((UINT8 *) AllocNodePtr + sizeof (BIOS_BUFFER_NODE)); + AllocParams->BufferLength = AllocNodePtr->BufferSize; + + return AGESA_SUCCESS; + +} + +AGESA_STATUS BiosRunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + AGESA_STATUS Status; + + Status = agesawrapper_amdlaterunaptask (Func, Data, ConfigPtr); + return Status; +} + +AGESA_STATUS BiosReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + AGESA_STATUS Status; + UINT8 Value; + UINTN ResetType; + AMD_CONFIG_PARAMS *StdHeader; + + ResetType = Data; + StdHeader = ConfigPtr; + + // + // Perform the RESET based upon the ResetType. In case of + // WARM_RESET_WHENVER and COLD_RESET_WHENEVER, the request will go to + // AmdResetManager. During the critical condition, where reset is required + // immediately, the reset will be invoked directly by writing 0x04 to port + // 0xCF9 (Reset Port). + // + switch (ResetType) { + case WARM_RESET_WHENEVER: + case COLD_RESET_WHENEVER: + break; + + case WARM_RESET_IMMEDIATELY: + case COLD_RESET_IMMEDIATELY: + Value = 0x06; + LibAmdIoWrite (AccessWidth8, 0xCf9, &Value, StdHeader); + break; + + default: + break; + } + + Status = 0; + return Status; +} + +AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + AGESA_STATUS Status; +#ifdef __PRE_RAM__ + Status = agesa_ReadSPD (Func, Data, ConfigPtr); +#else + Status = AGESA_UNSUPPORTED; +#endif + + return Status; +} + +AGESA_STATUS BiosDefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + return AGESA_UNSUPPORTED; +} +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + return AGESA_SUCCESS; +} +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDramInit (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + // Unlike AMD/Inagua, Gizmo is unable to vary the RAM voltage. + // Make sure the right speed settings are selected. + ((MEM_DATA_STRUCT*)ConfigPtr)->ParameterListPtr->DDR3Voltage = VOLT1_5; + return AGESA_SUCCESS; +} + +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDramInitRecovery (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + return AGESA_SUCCESS; +} + +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + return AGESA_SUCCESS; +} +/* PCIE slot reset control */ +AGESA_STATUS BiosGnbPcieSlotReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr) +{ + return AGESA_SUCCESS; +} diff --git a/src/mainboard/gizmosphere/gizmo/BiosCallOuts.h b/src/mainboard/gizmosphere/gizmo/BiosCallOuts.h new file mode 100755 index 0000000000..c4f4f709d4 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/BiosCallOuts.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BIOS_CALLOUT_H_ +#define _BIOS_CALLOUT_H_ + +#include "Porting.h" +#include "AGESA.h" + +#define BIOS_HEAP_START_ADDRESS 0x10000 /* HEAP during cold boot */ +#define BIOS_HEAP_SIZE 0x20000 +#define BSP_STACK_BASE_ADDR 0x30000 + +typedef struct _BIOS_HEAP_MANAGER { + //UINT32 AvailableSize; + UINT32 StartOfAllocatedNodes; + UINT32 StartOfFreedNodes; +} BIOS_HEAP_MANAGER; + +typedef struct _BIOS_BUFFER_NODE { + UINT32 BufferHandle; + UINT32 BufferSize; + UINT32 NextNodeOffset; +} BIOS_BUFFER_NODE; +/* + * CALLOUTS + */ +AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr); + +/* REQUIRED CALLOUTS + * AGESA ADVANCED CALLOUTS - CPU + */ +AGESA_STATUS BiosAllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +AGESA_STATUS BiosDeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +AGESA_STATUS BiosLocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +AGESA_STATUS BiosRunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +AGESA_STATUS BiosReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +AGESA_STATUS BiosGetIdsInitData (UINT32 Func, UINT32 Data, VOID *ConfigPtr); + +/* AGESA ADVANCED CALLOUTS - MEMORY */ +AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr); + +/* BIOS DEFAULT RET */ +AGESA_STATUS BiosDefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr); + +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDramInit (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeDramInitRecovery (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +/* Call the host environment interface to provide a user hook opportunity. */ +AGESA_STATUS BiosHookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +/* PCIE slot reset control */ +AGESA_STATUS BiosGnbPcieSlotReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr); + +#endif //_BIOS_CALLOUT_H_ diff --git a/src/mainboard/gizmosphere/gizmo/Kconfig b/src/mainboard/gizmosphere/gizmo/Kconfig new file mode 100755 index 0000000000..731a94e3f2 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/Kconfig @@ -0,0 +1,127 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2011 Advanced Micro Devices, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +if BOARD_GIZMOSPHERE_GIZMO + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_AMD_AGESA_FAMILY14 + select NORTHBRIDGE_AMD_AGESA_FAMILY14 + select SOUTHBRIDGE_AMD_CIMX_SB800 + select HAVE_OPTION_TABLE + select HAVE_PIRQ_TABLE + select HAVE_MP_TABLE + select HAVE_ACPI_RESUME + select SB_HT_CHAIN_UNITID_OFFSET_ONLY + select LIFT_BSP_APIC_ID + select SERIAL_CPU_INIT + select AMDMCT + select HAVE_ACPI_TABLES + select BOARD_ROMSIZE_KB_2048 + select GFXUMA_CONFIGURABLE + select DDR3_SOLDERED_DOWN + select EARLY_CBMEM_INIT + select CHROMEOS + select CHROMEOS_VBNV_CMOS + +config GFXUMA + bool + default y + +config PATH_TO_DDR3_SPD + string + default "../../../../src/mainboard/gizmosphere/gizmo/ddr3_spd.h" + +config DDR3_CHANNEL_MAX + int + default 0 + +config MAINBOARD_DIR + string + default gizmosphere/gizmo + +config APIC_ID_OFFSET + hex + default 0x0 + +config MAINBOARD_PART_NUMBER + string + default "Gizmo" + +config HW_MEM_HOLE_SIZEK + hex + default 0x200000 + +config MAX_CPUS + int + default 2 + +config MAX_PHYSICAL_CPUS + int + default 1 + +config HW_MEM_HOLE_SIZE_AUTO_INC + bool + default n + +config MEM_TRAIN_SEQ + int + default 2 + +config IRQ_SLOT_COUNT + int + default 11 + +config RAMTOP + hex + default 0x1000000 + +config HEAP_SIZE + hex + default 0xc0000 + +config RAMBASE + hex + default 0x200000 + +config ONBOARD_VGA_IS_PRIMARY + bool + default y + +config VGA_BIOS_FILE + string + default "pci1002,9804.rom" + +config SB800_AHCI_ROM + bool + default n + +config DRIVERS_PS2_KEYBOARD + bool + default n + +config DCACHE_RAM_SIZE + hex + default 0x8000 + help + The size of the cache-as-ram region required during bootblock + and/or romstage. Note DCACHE_RAM_SIZE and DCACHE_RAM_MRC_VAR_SIZE + must add up to a power of 2. + +endif # BOARD_GIZMOSPHERE_GIZMO diff --git a/src/mainboard/gizmosphere/gizmo/Makefile.inc b/src/mainboard/gizmosphere/gizmo/Makefile.inc new file mode 100755 index 0000000000..f610f0eb81 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/Makefile.inc @@ -0,0 +1,59 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2011 Advanced Micro Devices, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +ifeq ($(CONFIG_AHCI_BIOS),y) +stripped_ahcibios_id = $(call strip_quotes,$(CONFIG_AHCI_BIOS_ID)) +cbfs-files-$(CONFIG_AHCI_BIOS) += pci$(stripped_ahcibios_id).rom +pci$(stripped_ahcibios_id).rom-file := $(call strip_quotes,$(CONFIG_AHCI_BIOS_FILE)) +pci$(stripped_ahcibios_id).rom-type := optionrom +endif + +romstage-y += buildOpts.c +romstage-y += agesawrapper.c +romstage-y += BiosCallOuts.c +romstage-y += PlatformGnbPcie.c + +ramstage-y += buildOpts.c +ramstage-y += agesawrapper.c +ramstage-y += BiosCallOuts.c +ramstage-y += PlatformGnbPcie.c + +# We want to add the Explorer payload if SeaBIOS is the payload +ifeq ($(CONFIG_PAYLOAD_FILE),"payloads/seabios/out/bios.bin.elf") +# Explorer payload +cbfs-files-y += img/explorer +img/explorer-file := payloads/explorer/explorer.elf +img/explorer-type := payload +img/explorer-compression := lzma +endif # payload file is SeaBIOS + +# We want to add the Explorer BMP files if Explorer is present +ifneq (,$(filter $(CONFIG_PAYLOAD_FILE),"payloads/seabios/out/bios.bin.elf" "payloads/explorer/explorer.elf")) + +# Explorer Logo bitmap file +cbfs-files-y += logo.bmp +logo.bmp-file := payloads/explorer/logo.bmp +logo.bmp-type := raw + +#Keypad bitmap file +cbfs-files-y += keypad.bmp +keypad.bmp-file := payloads/explorer/keypad.bmp +keypad.bmp-type := raw + +endif # payload file is SeaBIOS OR Explorer diff --git a/src/mainboard/gizmosphere/gizmo/OptionsIds.h b/src/mainboard/gizmosphere/gizmo/OptionsIds.h new file mode 100755 index 0000000000..cf0a4bea84 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/OptionsIds.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * + * IDS Option File + * + * This file is used to switch on/off IDS features. + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: Core + * @e \$Revision: 12067 $ @e \$Date: 2009-04-11 04:34:13 +0800 (Sat, 11 Apr 2009) $ + */ +#ifndef _OPTION_IDS_H_ +#define _OPTION_IDS_H_ + +/** + * + * This file generates the defaults tables for the Integrated Debug Support + * Module. The documented build options are imported from a user controlled + * file for processing. The build options for the Integrated Debug Support + * Module are listed below: + * + * IDSOPT_IDS_ENABLED + * IDSOPT_ERROR_TRAP_ENABLED + * IDSOPT_CONTROL_ENABLED + * IDSOPT_TRACING_ENABLED + * IDSOPT_PERF_ANALYSIS + * IDSOPT_ASSERT_ENABLED + * IDS_DEBUG_PORT + * IDSOPT_CAR_CORRUPTION_CHECK_ENABLED + * + **/ + +#define IDSOPT_IDS_ENABLED TRUE +//#define IDSOPT_TRACING_ENABLED TRUE +#define IDSOPT_ASSERT_ENABLED TRUE + +//#define IDSOPT_DEBUG_ENABLED FALSE +//#undef IDSOPT_HOST_SIMNOW +//#define IDSOPT_HOST_SIMNOW FALSE +//#undef IDSOPT_HOST_HDT +//#define IDSOPT_HOST_HDT FALSE +//#define IDS_DEBUG_PORT 0x80 + +#endif diff --git a/src/mainboard/gizmosphere/gizmo/PlatformGnbPcie.c b/src/mainboard/gizmosphere/gizmo/PlatformGnbPcie.c new file mode 100755 index 0000000000..cf1fb32ec6 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/PlatformGnbPcie.c @@ -0,0 +1,166 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "AGESA.h" +#include "amdlib.h" +#include "Ids.h" +#include "heapManager.h" +#include "PlatformGnbPcieComplex.h" +#include "Filecode.h" +#include "BiosCallOuts.h" + +#define FILECODE PROC_RECOVERY_MEM_NB_ON_MRNON_FILECODE + +/*---------------------------------------------------------------------------------------*/ +/** + * OemCustomizeInitEarly + * + * Description: + * This stub function will call the host environment through the binary block + * interface (call-out port) to provide a user hook opportunity + * + * Parameters: + * @param[in] **PeiServices + * @param[in] *InitEarly + * + * @retval VOID + * + **/ +/*---------------------------------------------------------------------------------------*/ +VOID +OemCustomizeInitEarly ( + IN OUT AMD_EARLY_PARAMS *InitEarly + ) +{ + AGESA_STATUS Status; + VOID *BrazosPcieComplexListPtr; + VOID *BrazosPciePortPtr; + VOID *BrazosPcieDdiPtr; + + ALLOCATE_HEAP_PARAMS AllocHeapParams; + +PCIe_PORT_DESCRIPTOR PortList [] = { + // Initialize Port descriptor (PCIe port, Lanes 4, PCI Device Number 4, ...) + { + 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array + PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 4, 4), + PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT4_PORT_PRESENT, GNB_GPP_PORT4_CHANNEL_TYPE, 4, GNB_GPP_PORT4_HOTPLUG_SUPPORT, GNB_GPP_PORT4_SPEED_MODE, GNB_GPP_PORT4_SPEED_MODE, GNB_GPP_PORT4_LINK_ASPM, 4) + }, + #if 1 + // Initialize Port descriptor (PCIe port, Lanes 5, PCI Device Number 5, ...) + { + 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array + PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 5, 5), + PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT5_PORT_PRESENT, GNB_GPP_PORT5_CHANNEL_TYPE, 5, GNB_GPP_PORT5_HOTPLUG_SUPPORT, GNB_GPP_PORT5_SPEED_MODE, GNB_GPP_PORT5_SPEED_MODE, GNB_GPP_PORT5_LINK_ASPM, 5) + }, + // Initialize Port descriptor (PCIe port, Lanes 6, PCI Device Number 6, ...) + { + 0, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array + PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 6, 6), + PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT6_PORT_PRESENT, GNB_GPP_PORT6_CHANNEL_TYPE, 6, GNB_GPP_PORT6_HOTPLUG_SUPPORT, GNB_GPP_PORT6_SPEED_MODE, GNB_GPP_PORT6_SPEED_MODE, GNB_GPP_PORT6_LINK_ASPM, 6) + }, + // Initialize Port descriptor (PCIe port, Lanes 7, PCI Device Number 7, ...) + { + 0, + PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 7, 7), + PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT7_PORT_PRESENT, GNB_GPP_PORT7_CHANNEL_TYPE, 7, GNB_GPP_PORT7_HOTPLUG_SUPPORT, GNB_GPP_PORT7_SPEED_MODE, GNB_GPP_PORT7_SPEED_MODE, GNB_GPP_PORT7_LINK_ASPM, 7) + }, + #endif + // Initialize Port descriptor (PCIe port, Lanes 8, PCI Device Number 8, ...) + { + DESCRIPTOR_TERMINATE_LIST, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array + PCIE_ENGINE_DATA_INITIALIZER (PciePortEngine, 0, 3), + PCIE_PORT_DATA_INITIALIZER (GNB_GPP_PORT8_PORT_PRESENT, GNB_GPP_PORT8_CHANNEL_TYPE, 8, GNB_GPP_PORT8_HOTPLUG_SUPPORT, GNB_GPP_PORT8_SPEED_MODE, GNB_GPP_PORT8_SPEED_MODE, GNB_GPP_PORT8_LINK_ASPM, 0) + } +}; + +PCIe_DDI_DESCRIPTOR DdiList [] = { + // Initialize Ddi descriptor (DDI interface Lanes 8:11, DdA, ...) + { + 0, //Descriptor flags + PCIE_ENGINE_DATA_INITIALIZER (PcieDdiEngine, 8, 11), + //PCIE_DDI_DATA_INITIALIZER (ConnectorTypeDP, Aux1, Hdp1) + {ConnectorTypeDP, Aux1, Hdp1} + }, + // Initialize Ddi descriptor (DDI interface Lanes 12:15, DdB, ...) + { + DESCRIPTOR_TERMINATE_LIST, //Descriptor flags !!!IMPORTANT!!! Terminate last element of array + PCIE_ENGINE_DATA_INITIALIZER (PcieDdiEngine, 12, 15), + //PCIE_DDI_DATA_INITIALIZER (ConnectorTypeDP, Aux2, Hdp2) + {ConnectorTypeDP, Aux2, Hdp2} + } +}; + +PCIe_COMPLEX_DESCRIPTOR Brazos = { + DESCRIPTOR_TERMINATE_LIST, + 0, + &PortList[0], + &DdiList[0] +}; + + // GNB PCIe topology Porting + + // + // Allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR + // + AllocHeapParams.RequestedBufferSize = sizeof(Brazos) + sizeof(PortList) + sizeof(DdiList); + + AllocHeapParams.BufferHandle = AMD_MEM_MISC_HANDLES_START; + AllocHeapParams.Persist = HEAP_LOCAL_CACHE; + Status = HeapAllocateBuffer (&AllocHeapParams, &InitEarly->StdHeader); + if ( Status!= AGESA_SUCCESS) { + // Could not allocate buffer for PCIe_COMPLEX_DESCRIPTOR , PCIe_PORT_DESCRIPTOR and PCIe_DDI_DESCRIPTOR + ASSERT(FALSE); + return; + } + + BrazosPcieComplexListPtr = (PCIe_COMPLEX_DESCRIPTOR *) AllocHeapParams.BufferPtr; + + AllocHeapParams.BufferPtr += sizeof(Brazos); + BrazosPciePortPtr = (PCIe_PORT_DESCRIPTOR *)AllocHeapParams.BufferPtr; + + AllocHeapParams.BufferPtr += sizeof(PortList); + BrazosPcieDdiPtr = (PCIe_DDI_DESCRIPTOR *) AllocHeapParams.BufferPtr; + + LibAmdMemFill (BrazosPcieComplexListPtr, + 0, + sizeof(Brazos), + &InitEarly->StdHeader); + + LibAmdMemFill (BrazosPciePortPtr, + 0, + sizeof(PortList), + &InitEarly->StdHeader); + + LibAmdMemFill (BrazosPcieDdiPtr, + 0, + sizeof(DdiList), + &InitEarly->StdHeader); + + LibAmdMemCopy (BrazosPcieComplexListPtr, &Brazos, sizeof(Brazos), &InitEarly->StdHeader); + LibAmdMemCopy (BrazosPciePortPtr, &PortList[0], sizeof(PortList), &InitEarly->StdHeader); + LibAmdMemCopy (BrazosPcieDdiPtr, &DdiList[0], sizeof(DdiList), &InitEarly->StdHeader); + + + ((PCIe_COMPLEX_DESCRIPTOR*)BrazosPcieComplexListPtr)->PciePortList = (PCIe_PORT_DESCRIPTOR*)BrazosPciePortPtr; + ((PCIe_COMPLEX_DESCRIPTOR*)BrazosPcieComplexListPtr)->DdiLinkList = (PCIe_DDI_DESCRIPTOR*)BrazosPcieDdiPtr; + + InitEarly->GnbConfig.PcieComplexList = BrazosPcieComplexListPtr; + InitEarly->GnbConfig.PsppPolicy = 0; +} diff --git a/src/mainboard/gizmosphere/gizmo/PlatformGnbPcieComplex.h b/src/mainboard/gizmosphere/gizmo/PlatformGnbPcieComplex.h new file mode 100755 index 0000000000..69e26152c4 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/PlatformGnbPcieComplex.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _PLATFORM_GNB_PCIE_COMPLEX_H +#define _PLATFORM_GNB_PCIE_COMPLEX_H + +#include "Porting.h" +#include "AGESA.h" +#include "amdlib.h" +#include + +//GNB GPP Port4 +#define GNB_GPP_PORT4_PORT_PRESENT 1 //0:Disable 1:Enable +#define GNB_GPP_PORT4_SPEED_MODE 2 //0:Auto 1:GEN1 2:GEN2 +#define GNB_GPP_PORT4_LINK_ASPM 3 //0:Disable 1:L0s 2:L1 3:L0s+L1 +#define GNB_GPP_PORT4_CHANNEL_TYPE 4 //0:LowLoss(-3.5db) 1:HighLoss(-6db) 2:Half-swing(0db) + //3:Half-swing(-3.5db) 4:extended length (-6db) 5:extended length(-8db) +#define GNB_GPP_PORT4_HOTPLUG_SUPPORT 0 //0:Disable 1:Basic 3:Enhanced + +//GNB GPP Port5 +#define GNB_GPP_PORT5_PORT_PRESENT 1 //0:Disable 1:Enable +#define GNB_GPP_PORT5_SPEED_MODE 2 //0:Auto 1:GEN1 2:GEN2 +#define GNB_GPP_PORT5_LINK_ASPM 3 //0:Disable 1:L0s 2:L1 3:L0s+L1 +#define GNB_GPP_PORT5_CHANNEL_TYPE 4 //0:LowLoss(-3.5db) 1:HighLoss(-6db) 2:Half-swing(0db) + //3:Half-swing(-3.5db) 4:extended length (-6db) 5:extended length(-8db) +#define GNB_GPP_PORT5_HOTPLUG_SUPPORT 0 //0:Disable 1:Basic 3:Enhanced + +//GNB GPP Port6 +#define GNB_GPP_PORT6_PORT_PRESENT 1 //0:Disable 1:Enable +#define GNB_GPP_PORT6_SPEED_MODE 2 //0:Auto 1:GEN1 2:GEN2 +#define GNB_GPP_PORT6_LINK_ASPM 3 //0:Disable 1:L0s 2:L1 3:L0s+L1 +#define GNB_GPP_PORT6_CHANNEL_TYPE 4 //0:LowLoss(-3.5db) 1:HighLoss(-6db) 2:Half-swing(0db) + //3:Half-swing(-3.5db) 4:extended length (-6db) 5:extended length(-8db) +#define GNB_GPP_PORT6_HOTPLUG_SUPPORT 0 //0:Disable 1:Basic 3:Enhanced + +//GNB GPP Port7 +#define GNB_GPP_PORT7_PORT_PRESENT 1 //0:Disable 1:Enable +#define GNB_GPP_PORT7_SPEED_MODE 2 //0:Auto 1:GEN1 2:GEN2 +#define GNB_GPP_PORT7_LINK_ASPM 3 //0:Disable 1:L0s 2:L1 3:L0s+L1 +#define GNB_GPP_PORT7_CHANNEL_TYPE 4 //0:LowLoss(-3.5db) 1:HighLoss(-6db) 2:Half-swing(0db) + //3:Half-swing(-3.5db) 4:extended length (-6db) 5:extended length(-8db) +#define GNB_GPP_PORT7_HOTPLUG_SUPPORT 0 //0:Disable 1:Basic 3:Enhanced + +//GNB GPP Port8 +#define GNB_GPP_PORT8_PORT_PRESENT 1 //0:Disable 1:Enable +#define GNB_GPP_PORT8_SPEED_MODE 2 //0:Auto 1:GEN1 2:GEN2 +#define GNB_GPP_PORT8_LINK_ASPM 3 //0:Disable 1:L0s 2:L1 3:L0s+L1 +#define GNB_GPP_PORT8_CHANNEL_TYPE 4 //0:LowLoss(-3.5db) 1:HighLoss(-6db) 2:Half-swing(0db) + //3:Half-swing(-3.5db) 4:extended length (-6db) 5:extended length(-8db) +#define GNB_GPP_PORT8_HOTPLUG_SUPPORT 0 //0:Disable 1:Basic 3:Enhanced + +VOID +OemCustomizeInitEarly ( + IN OUT AMD_EARLY_PARAMS *InitEarly + ); + +#endif //_PLATFORM_GNB_PCIE_COMPLEX_H diff --git a/src/mainboard/gizmosphere/gizmo/acpi/gpe.asl b/src/mainboard/gizmosphere/gizmo/acpi/gpe.asl new file mode 100644 index 0000000000..6ad1ad4d48 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/gpe.asl @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Scope(\_GPE) { /* Start Scope GPE */ + + /* General event 3 */ + Method(_L03) { + /* DBGO("\\_GPE\\_L00\n") */ + Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */ + } + + /* Legacy PM event */ + Method(_L08) { + /* DBGO("\\_GPE\\_L08\n") */ + } + + /* Temp warning (TWarn) event */ + Method(_L09) { + /* DBGO("\\_GPE\\_L09\n") */ + /* Notify (\_TZ.TZ00, 0x80) */ + } + + /* USB controller PME# */ + Method(_L0B) { + /* DBGO("\\_GPE\\_L0B\n") */ + Notify(\_SB.PCI0.UOH1, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UOH2, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UOH3, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UOH4, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UOH5, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UOH6, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.UEH1, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */ + } + + /* ExtEvent0 SCI event */ + Method(_L10) { + /* DBGO("\\_GPE\\_L10\n") */ + } + + + /* ExtEvent1 SCI event */ + Method(_L11) { + /* DBGO("\\_GPE\\_L11\n") */ + } + + /* GPIO0 or GEvent8 event */ + Method(_L18) { + /* DBGO("\\_GPE\\_L18\n") */ + Notify(\_SB.PCI0.PBR4, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.PBR5, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.PBR6, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PCI0.PBR7, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */ + } + + /* Azalia SCI event */ + Method(_L1B) { + /* DBGO("\\_GPE\\_L1B\n") */ + Notify(\_SB.PCI0.AZHD, 0x02) /* NOTIFY_DEVICE_WAKE */ + Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */ + } +} /* End Scope GPE */ + +/* Contains the GPEs for USB overcurrent */ +#include "usb_oc.asl" + diff --git a/src/mainboard/gizmosphere/gizmo/acpi/ide.asl b/src/mainboard/gizmosphere/gizmo/acpi/ide.asl new file mode 100755 index 0000000000..b3aed9c10c --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/ide.asl @@ -0,0 +1,244 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* +Scope (_SB) { + Device(PCI0) { + Device(IDEC) { + Name(_ADR, 0x00140001) + #include "ide.asl" + } + } +} +*/ + +/* Some timing tables */ +Name(UDTT, Package(){ /* Udma timing table */ + 120, 90, 60, 45, 30, 20, 15, 0 /* UDMA modes 0 -> 6 */ +}) + +Name(MDTT, Package(){ /* MWDma timing table */ + 480, 150, 120, 0 /* Legacy DMA modes 0 -> 2 */ +}) + +Name(POTT, Package(){ /* Pio timing table */ + 600, 390, 270, 180, 120, 0 /* PIO modes 0 -> 4 */ +}) + +/* Some timing register value tables */ +Name(MDRT, Package(){ /* MWDma timing register table */ + 0x77, 0x21, 0x20, 0xFF /* Legacy DMA modes 0 -> 2 */ +}) + +Name(PORT, Package(){ + 0x99, 0x47, 0x34, 0x22, 0x20, 0x99 /* PIO modes 0 -> 4 */ +}) + +OperationRegion(ICRG, PCI_Config, 0x40, 0x20) /* ide control registers */ + Field(ICRG, AnyAcc, NoLock, Preserve) +{ + PPTS, 8, /* Primary PIO Slave Timing */ + PPTM, 8, /* Primary PIO Master Timing */ + OFFSET(0x04), PMTS, 8, /* Primary MWDMA Slave Timing */ + PMTM, 8, /* Primary MWDMA Master Timing */ + OFFSET(0x08), PPCR, 8, /* Primary PIO Control */ + OFFSET(0x0A), PPMM, 4, /* Primary PIO master Mode */ + PPSM, 4, /* Primary PIO slave Mode */ + OFFSET(0x14), PDCR, 2, /* Primary UDMA Control */ + OFFSET(0x16), PDMM, 4, /* Primary UltraDMA Mode */ + PDSM, 4, /* Primary UltraDMA Mode */ +} + +Method(GTTM, 1) /* get total time*/ +{ + Store(And(Arg0, 0x0F), Local0) /* Recovery Width */ + Increment(Local0) + Store(ShiftRight(Arg0, 4), Local1) /* Command Width */ + Increment(Local1) + Return(Multiply(30, Add(Local0, Local1))) +} + +Device(PRID) +{ + Name (_ADR, Zero) + Method(_GTM, 0) + { + NAME(OTBF, Buffer(20) { /* out buffer */ + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 + }) + + CreateDwordField(OTBF, 0, PSD0) /* PIO spd0 */ + CreateDwordField(OTBF, 4, DSD0) /* DMA spd0 */ + CreateDwordField(OTBF, 8, PSD1) /* PIO spd1 */ + CreateDwordField(OTBF, 12, DSD1) /* DMA spd1 */ + CreateDwordField(OTBF, 16, BFFG) /* buffer flags */ + + /* Just return if the channel is disabled */ + If(And(PPCR, 0x01)) { /* primary PIO control */ + Return(OTBF) + } + + /* Always tell them independent timing available and IOChannelReady used on both drives */ + Or(BFFG, 0x1A, BFFG) + + Store(GTTM(PPTM), PSD0) /* save total time of primary PIO master timming to PIO spd0 */ + Store(GTTM(PPTS), PSD1) /* save total time of primary PIO slave Timing to PIO spd1 */ + + If(And(PDCR, 0x01)) { /* It's under UDMA mode */ + Or(BFFG, 0x01, BFFG) + Store(DerefOf(Index(UDTT, PDMM)), DSD0) + } + Else { + Store(GTTM(PMTM), DSD0) /* Primary MWDMA Master Timing, DmaSpd0 */ + } + + If(And(PDCR, 0x02)) { /* It's under UDMA mode */ + Or(BFFG, 0x04, BFFG) + Store(DerefOf(Index(UDTT, PDSM)), DSD1) + } + Else { + Store(GTTM(PMTS), DSD1) /* Primary MWDMA Slave Timing, DmaSpd0 */ + } + + Return(OTBF) /* out buffer */ + } /* End Method(_GTM) */ + + Method(_STM, 3, NotSerialized) + { + NAME(INBF, Buffer(20) { /* in buffer */ + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 + }) + + CreateDwordField(INBF, 0, PSD0) /* PIO spd0 */ + CreateDwordField(INBF, 4, DSD0) /* PIO spd0 */ + CreateDwordField(INBF, 8, PSD1) /* PIO spd1 */ + CreateDwordField(INBF, 12, DSD1) /* DMA spd1 */ + CreateDwordField(INBF, 16, BFFG) /*buffer flag */ + + Store(Match(POTT, MLE, PSD0, MTR, 0, 0), Local0) + Divide(Local0, 5, PPMM,) /* Primary PIO master Mode */ + Store(Match(POTT, MLE, PSD1, MTR, 0, 0), Local1) + Divide(Local1, 5, PPSM,) /* Primary PIO slave Mode */ + + Store(DerefOf(Index(PORT, Local0)), PPTM) /* Primary PIO Master Timing */ + Store(DerefOf(Index(PORT, Local1)), PPTS) /* Primary PIO Slave Timing */ + + If(And(BFFG, 0x01)) { /* Drive 0 is under UDMA mode */ + Store(Match(UDTT, MLE, DSD0, MTR, 0, 0), Local0) + Divide(Local0, 7, PDMM,) + Or(PDCR, 0x01, PDCR) + } + Else { + If(LNotEqual(DSD0, 0xFFFFFFFF)) { + Store(Match(MDTT, MLE, DSD0, MTR, 0, 0), Local0) + Store(DerefOf(Index(MDRT, Local0)), PMTM) + } + } + + If(And(BFFG, 0x04)) { /* Drive 1 is under UDMA mode */ + Store(Match(UDTT, MLE, DSD1, MTR, 0, 0), Local0) + Divide(Local0, 7, PDSM,) + Or(PDCR, 0x02, PDCR) + } + Else { + If(LNotEqual(DSD1, 0xFFFFFFFF)) { + Store(Match(MDTT, MLE, DSD1, MTR, 0, 0), Local0) + Store(DerefOf(Index(MDRT, Local0)), PMTS) + } + } + /* Return(INBF) */ + } /*End Method(_STM) */ + Device(MST) + { + Name(_ADR, 0) + Method(_GTF) { + Name(CMBF, Buffer(21) { + 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, + 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5 + }) + CreateByteField(CMBF, 1, POMD) + CreateByteField(CMBF, 8, DMMD) + CreateByteField(CMBF, 5, CMDA) + CreateByteField(CMBF, 12, CMDB) + CreateByteField(CMBF, 19, CMDC) + + Store(0xA0, CMDA) + Store(0xA0, CMDB) + Store(0xA0, CMDC) + + Or(PPMM, 0x08, POMD) + + If(And(PDCR, 0x01)) { + Or(PDMM, 0x40, DMMD) + } + Else { + Store(Match + (MDTT, MLE, GTTM(PMTM), + MTR, 0, 0), Local0) + If(LLess(Local0, 3)) { + Or(0x20, Local0, DMMD) + } + } + Return(CMBF) + } + } /* End Device(MST) */ + + Device(SLAV) + { + Name(_ADR, 1) + Method(_GTF) { + Name(CMBF, Buffer(21) { + 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, + 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5 + }) + CreateByteField(CMBF, 1, POMD) + CreateByteField(CMBF, 8, DMMD) + CreateByteField(CMBF, 5, CMDA) + CreateByteField(CMBF, 12, CMDB) + CreateByteField(CMBF, 19, CMDC) + + Store(0xB0, CMDA) + Store(0xB0, CMDB) + Store(0xB0, CMDC) + + Or(PPSM, 0x08, POMD) + + If(And(PDCR, 0x02)) { + Or(PDSM, 0x40, DMMD) + } + Else { + Store(Match + (MDTT, MLE, GTTM(PMTS), + MTR, 0, 0), Local0) + If(LLess(Local0, 3)) { + Or(0x20, Local0, DMMD) + } + } + Return(CMBF) + } + } /* End Device(SLAV) */ +} diff --git a/src/mainboard/gizmosphere/gizmo/acpi/mainboard.asl b/src/mainboard/gizmosphere/gizmo/acpi/mainboard.asl new file mode 100644 index 0000000000..49ea44fabf --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/mainboard.asl @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Data to be patched by the BIOS during POST */ +/* FIXME the patching is not done yet! */ +/* Memory related values */ +Name(LOMH, 0x0) /* Start of unused memory in C0000-E0000 range */ +Name(PBAD, 0x0) /* Address of BIOS area (If TOM2 != 0, Addr >> 16) */ +Name(PBLN, 0x0) /* Length of BIOS area */ + +Name(PCBA, CONFIG_MMCONF_BASE_ADDRESS) /* Base address of PCIe config space */ +Name(HPBA, 0xFED00000) /* Base address of HPET table */ + +Name(SSFG, 0x0D) /* S1 support: bit 0, S2 Support: bit 1, etc. S0 & S5 assumed */ + +/* Some global data */ +Name(OSTP, 3) /* Assume nothing. WinXp = 1, Vista = 2, Linux = 3, WinCE = 4 */ +Name(OSV, Ones) /* Assume nothing */ +Name(PMOD, One) /* Assume APIC */ + +Scope(\_SB) { + Method(CkOT, 0){ + + if(LNotEqual(OSTP, Ones)) {Return(OSTP)} /* OS version was already detected */ + + if(CondRefOf(\_OSI,Local1)) + { + Store(1, OSTP) /* Assume some form of XP */ + if (\_OSI("Windows 2006")) /* Vista */ + { + Store(2, OSTP) + } + } else { + If(WCMP(\_OS,"Linux")) { + Store(3, OSTP) /* Linux */ + } Else { + Store(4, OSTP) /* Gotta be WinCE */ + } + } + Return(OSTP) + } +} + +Scope(\_SI) { + Method(_SST, 1) { + /* DBGO("\\_SI\\_SST\n") */ + /* DBGO(" New Indicator state: ") */ + /* DBGO(Arg0) */ + /* DBGO("\n") */ + } +} /* End Scope SI */ + diff --git a/src/mainboard/gizmosphere/gizmo/acpi/routing.asl b/src/mainboard/gizmosphere/gizmo/acpi/routing.asl new file mode 100755 index 0000000000..98ad4398cd --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/routing.asl @@ -0,0 +1,407 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* +DefinitionBlock ("DSDT.AML","DSDT",0x01,"XXXXXX","XXXXXXXX",0x00010001 + ) + { + #include "routing.asl" + } +*/ + +/* Routing is in System Bus scope */ +Scope(\_SB) { + Name(PR0, Package(){ + /* NB devices */ + /* Bus 0, Dev 0 - RS780 Host Controller */ + /* Bus 0, Dev 1 - PCI Bridge for Internal Graphics */ + Package(){0x0001FFFF, 0, INTC, 0 }, + Package(){0x0001FFFF, 1, INTD, 0 }, + /* Bus 0, Dev 2 - PCIe Bridge for x8 PCIe Slot (GFX0) */ + Package(){0x0002FFFF, 0, INTC, 0 }, + Package(){0x0002FFFF, 1, INTD, 0 }, + Package(){0x0002FFFF, 2, INTA, 0 }, + Package(){0x0002FFFF, 3, INTB, 0 }, + /* Bus 0, Dev 3 - PCIe graphics port 1 bridge */ + Package(){0x0003FFFF, 0, INTD, 0 }, + Package(){0x0003FFFF, 1, INTA, 0 }, + Package(){0x0003FFFF, 2, INTB, 0 }, + Package(){0x0003FFFF, 3, INTC, 0 }, + /* Bus 0, Dev 4 - PCIe Bridge for Express Card Slot */ + Package(){0x0004FFFF, 0, INTA, 0 }, + Package(){0x0004FFFF, 1, INTB, 0 }, + Package(){0x0004FFFF, 2, INTC, 0 }, + Package(){0x0004FFFF, 3, INTD, 0 }, + /* Bus 0, Dev 5 - General purpose PCIe bridge 5 */ + Package(){0x0005FFFF, 0, INTB, 0 }, + Package(){0x0005FFFF, 1, INTC, 0 }, + Package(){0x0005FFFF, 2, INTD, 0 }, + Package(){0x0005FFFF, 3, INTA, 0 }, + /* Bus 0, Dev 6 - PCIe Bridge for Ethernet Chip */ + Package(){0x0006FFFF, 0, INTC, 0 }, + Package(){0x0006FFFF, 1, INTD, 0 }, + Package(){0x0006FFFF, 2, INTA, 0 }, + Package(){0x0006FFFF, 3, INTB, 0 }, + /* Bus 0, Dev 7 - PCIe Bridge for x1 PCIe Slot */ + Package(){0x0007FFFF, 0, INTD, 0 }, + Package(){0x0007FFFF, 1, INTA, 0 }, + Package(){0x0007FFFF, 2, INTB, 0 }, + Package(){0x0007FFFF, 3, INTC, 0 }, + + Package(){0x0009FFFF, 0, INTB, 0 }, + Package(){0x0009FFFF, 1, INTC, 0 }, + Package(){0x0009FFFF, 2, INTD, 0 }, + Package(){0x0009FFFF, 3, INTA, 0 }, + + Package(){0x000AFFFF, 0, INTC, 0 }, + Package(){0x000AFFFF, 1, INTD, 0 }, + Package(){0x000AFFFF, 2, INTA, 0 }, + Package(){0x000AFFFF, 3, INTB, 0 }, + + Package(){0x000BFFFF, 0, INTD, 0 }, + Package(){0x000BFFFF, 1, INTA, 0 }, + Package(){0x000BFFFF, 2, INTB, 0 }, + Package(){0x000BFFFF, 3, INTC, 0 }, + + Package(){0x000CFFFF, 0, INTA, 0 }, + Package(){0x000CFFFF, 1, INTB, 0 }, + Package(){0x000CFFFF, 2, INTC, 0 }, + Package(){0x000CFFFF, 3, INTD, 0 }, + + /* Bus 0, Funct 8 - Southbridge port (normally hidden) */ + + /* SB devices */ + /* Bus 0, Dev 17 - SATA controller #2 */ + /* Bus 0, Dev 18 - SATA controller #1 */ + Package(){0x0011FFFF, 0, INTD, 0 }, + + /* Bus 0, Dev 19 - USB: OHCI, dev 18,19 func 0-2, dev 20 func 5; + * EHCI, dev 18, 19 func 2 */ + Package(){0x0012FFFF, 0, INTC, 0 }, + Package(){0x0012FFFF, 1, INTB, 0 }, + + Package(){0x0013FFFF, 0, INTC, 0 }, + Package(){0x0013FFFF, 1, INTB, 0 }, + + Package(){0x0016FFFF, 0, INTC, 0 }, + Package(){0x0016FFFF, 1, INTB, 0 }, + + /* Package(){0x0014FFFF, 1, INTA, 0 }, */ + + /* Bus 0, Dev 20 - F0:SMBus/ACPI,F1:IDE;F2:HDAudio;F3:LPC;F4:PCIBridge;F5:USB */ + Package(){0x0014FFFF, 0, INTA, 0 }, + Package(){0x0014FFFF, 1, INTB, 0 }, + Package(){0x0014FFFF, 2, INTC, 0 }, + Package(){0x0014FFFF, 3, INTD, 0 }, + + Package(){0x0015FFFF, 0, INTA, 0 }, + Package(){0x0015FFFF, 1, INTB, 0 }, + Package(){0x0015FFFF, 2, INTC, 0 }, + Package(){0x0015FFFF, 3, INTD, 0 }, + }) + + Name(APR0, Package(){ + /* NB devices in APIC mode */ + /* Bus 0, Dev 0 - RS780 Host Controller */ + + /* Bus 0, Dev 1 - PCI Bridge for Internal Graphics */ + Package(){0x0001FFFF, 0, 0, 18 }, + Package(){0x0001FFFF, 1, 0, 19 }, + + /* Bus 0, Dev 2 - PCIe Bridge for x8 PCIe Slot (GFX0) */ + Package(){0x0002FFFF, 0, 0, 18 }, + /* Package(){0x0002FFFF, 1, 0, 19 }, */ + /* Package(){0x0002FFFF, 2, 0, 16 }, */ + /* Package(){0x0002FFFF, 3, 0, 17 }, */ + + /* Bus 0, Dev 3 - PCIe graphics port 1 bridge */ + Package(){0x0003FFFF, 0, 0, 19 }, + Package(){0x0003FFFF, 1, 0, 16 }, + Package(){0x0003FFFF, 2, 0, 17 }, + Package(){0x0003FFFF, 3, 0, 18 }, + + /* Bus 0, Dev 4 - PCIe Bridge for Express Card Slot */ + Package(){0x0004FFFF, 0, 0, 16 }, + Package(){0x0004FFFF, 1, 0, 17 }, + Package(){0x0004FFFF, 2, 0, 18 }, + Package(){0x0004FFFF, 3, 0, 19 }, + + /* Bus 0, Dev 5 - General purpose PCIe bridge 5 */ + Package(){0x0005FFFF, 0, 0, 17 }, + Package(){0x0005FFFF, 1, 0, 18 }, + Package(){0x0005FFFF, 2, 0, 19 }, + Package(){0x0005FFFF, 3, 0, 16 }, + + /* Bus 0, Dev 6 - General purpose PCIe bridge 6 */ + Package(){0x0006FFFF, 0, 0, 18 }, + Package(){0x0006FFFF, 1, 0, 19 }, + Package(){0x0006FFFF, 2, 0, 16 }, + Package(){0x0006FFFF, 3, 0, 17 }, + + /* Bus 0, Dev 7 - PCIe Bridge for network card */ + Package(){0x0007FFFF, 0, 0, 19 }, + Package(){0x0007FFFF, 1, 0, 16 }, + Package(){0x0007FFFF, 2, 0, 17 }, + Package(){0x0007FFFF, 3, 0, 18 }, + + /* Bus 0, Dev 9 - PCIe Bridge for network card */ + Package(){0x0009FFFF, 0, 0, 17 }, + Package(){0x0009FFFF, 1, 0, 16 }, + Package(){0x0009FFFF, 2, 0, 17 }, + Package(){0x0009FFFF, 3, 0, 18 }, + /* Bus 0, Dev A - PCIe Bridge for network card */ + Package(){0x000AFFFF, 0, 0, 18 }, + Package(){0x000AFFFF, 1, 0, 16 }, + Package(){0x000AFFFF, 2, 0, 17 }, + Package(){0x000AFFFF, 3, 0, 18 }, + /* Bus 0, Funct 8 - Southbridge port (normally hidden) */ + + /* SB devices in APIC mode */ + /* Bus 0, Dev 17 - SATA controller #2 */ + /* Bus 0, Dev 18 - SATA controller #1 */ + Package(){0x0011FFFF, 0, 0, 19 }, + + /* Bus 0, Dev 19 - USB: OHCI, dev 18,19 func 0-2, dev 20 func 5; + * EHCI, dev 18, 19 func 2 */ + Package(){0x0012FFFF, 0, 0, 18 }, + Package(){0x0012FFFF, 1, 0, 17 }, + /* Package(){0x0012FFFF, 2, 0, 18 }, */ + + Package(){0x0013FFFF, 0, 0, 18 }, + Package(){0x0013FFFF, 1, 0, 17 }, + /* Package(){0x0013FFFF, 2, 0, 16 }, */ + + /* Package(){0x00140000, 0, 0, 16 }, */ + + Package(){0x0016FFFF, 0, 0, 18 }, + Package(){0x0016FFFF, 1, 0, 17 }, + + /* Bus 0, Dev 20 - F0:SMBus/ACPI, F1:IDE; F2:HDAudio; F3:LPC; F4:PCIBridge; F5:USB */ + Package(){0x0014FFFF, 0, 0, 16 }, + Package(){0x0014FFFF, 1, 0, 17 }, + Package(){0x0014FFFF, 2, 0, 18 }, + Package(){0x0014FFFF, 3, 0, 19 }, + /* Package(){0x00140004, 2, 0, 18 }, */ + /* Package(){0x00140004, 3, 0, 19 }, */ + /* Package(){0x00140005, 1, 0, 17 }, */ + /* Package(){0x00140006, 1, 0, 17 }, */ + + /* TODO: pcie */ + Package(){0x0015FFFF, 0, 0, 16 }, + Package(){0x0015FFFF, 1, 0, 17 }, + Package(){0x0015FFFF, 2, 0, 18 }, + Package(){0x0015FFFF, 3, 0, 19 }, + }) + + Name(PR1, Package(){ + /* Internal graphics - RS780 VGA, Bus1, Dev5 */ + Package(){0x0005FFFF, 0, INTA, 0 }, + Package(){0x0005FFFF, 1, INTB, 0 }, + Package(){0x0005FFFF, 2, INTC, 0 }, + Package(){0x0005FFFF, 3, INTD, 0 }, + }) + Name(APR1, Package(){ + /* Internal graphics - RS780 VGA, Bus1, Dev5 */ + Package(){0x0005FFFF, 0, 0, 18 }, + Package(){0x0005FFFF, 1, 0, 19 }, + /* Package(){0x0005FFFF, 2, 0, 20 }, */ + /* Package(){0x0005FFFF, 3, 0, 17 }, */ + }) + + Name(PS2, Package(){ + /* The external GFX - Hooked to PCIe slot 2 */ + Package(){0x0000FFFF, 0, INTC, 0 }, + Package(){0x0000FFFF, 1, INTD, 0 }, + Package(){0x0000FFFF, 2, INTA, 0 }, + Package(){0x0000FFFF, 3, INTB, 0 }, + }) + Name(APS2, Package(){ + /* The external GFX - Hooked to PCIe slot 2 */ + Package(){0x0000FFFF, 0, 0, 18 }, + Package(){0x0000FFFF, 1, 0, 19 }, + Package(){0x0000FFFF, 2, 0, 16 }, + Package(){0x0000FFFF, 3, 0, 17 }, + }) + + Name(PS4, Package(){ + /* PCIe slot - Hooked to PCIe slot 4 */ + Package(){0x0000FFFF, 0, INTA, 0 }, + Package(){0x0000FFFF, 1, INTB, 0 }, + Package(){0x0000FFFF, 2, INTC, 0 }, + Package(){0x0000FFFF, 3, INTD, 0 }, + }) + Name(APS4, Package(){ + /* PCIe slot - Hooked to PCIe slot 4 */ + Package(){0x0000FFFF, 0, 0, 16 }, + Package(){0x0000FFFF, 1, 0, 17 }, + Package(){0x0000FFFF, 2, 0, 18 }, + Package(){0x0000FFFF, 3, 0, 19 }, + }) + + Name(PS5, Package(){ + /* PCIe slot - Hooked to PCIe slot 5 */ + Package(){0x0000FFFF, 0, INTB, 0 }, + Package(){0x0000FFFF, 1, INTC, 0 }, + Package(){0x0000FFFF, 2, INTD, 0 }, + Package(){0x0000FFFF, 3, INTA, 0 }, + }) + Name(APS5, Package(){ + /* PCIe slot - Hooked to PCIe slot 5 */ + Package(){0x0000FFFF, 0, 0, 17 }, + Package(){0x0000FFFF, 1, 0, 18 }, + Package(){0x0000FFFF, 2, 0, 19 }, + Package(){0x0000FFFF, 3, 0, 16 }, + }) + + Name(PS6, Package(){ + /* PCIe slot - Hooked to PCIe slot 6 */ + Package(){0x0000FFFF, 0, INTC, 0 }, + Package(){0x0000FFFF, 1, INTD, 0 }, + Package(){0x0000FFFF, 2, INTA, 0 }, + Package(){0x0000FFFF, 3, INTB, 0 }, + }) + Name(APS6, Package(){ + /* PCIe slot - Hooked to PCIe slot 6 */ + Package(){0x0000FFFF, 0, 0, 18 }, + Package(){0x0000FFFF, 1, 0, 19 }, + Package(){0x0000FFFF, 2, 0, 16 }, + Package(){0x0000FFFF, 3, 0, 17 }, + }) + + Name(PS7, Package(){ + /* The onboard Ethernet chip - Hooked to PCIe slot 7 */ + Package(){0x0000FFFF, 0, INTD, 0 }, + Package(){0x0000FFFF, 1, INTA, 0 }, + Package(){0x0000FFFF, 2, INTB, 0 }, + Package(){0x0000FFFF, 3, INTC, 0 }, + }) + Name(APS7, Package(){ + /* The onboard Ethernet chip - Hooked to PCIe slot 7 */ + Package(){0x0000FFFF, 0, 0, 19 }, + Package(){0x0000FFFF, 1, 0, 16 }, + Package(){0x0000FFFF, 2, 0, 17 }, + Package(){0x0000FFFF, 3, 0, 18 }, + }) + + Name(PS9, Package(){ + /* PCIe slot - Hooked to PCIe slot 9 */ + Package(){0x0000FFFF, 0, INTD, 0 }, + Package(){0x0000FFFF, 1, INTA, 0 }, + Package(){0x0000FFFF, 2, INTB, 0 }, + Package(){0x0000FFFF, 3, INTC, 0 }, + }) + Name(APS9, Package(){ + /* PCIe slot - Hooked to PCIe slot 9 */ + Package(){0x0000FFFF, 0, 0, 17 }, + Package(){0x0000FFFF, 1, 0, 18 }, + Package(){0x0000FFFF, 2, 0, 19 }, + Package(){0x0000FFFF, 3, 0, 16 }, + }) + + Name(PSa, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, INTD, 0 }, + Package(){0x0000FFFF, 1, INTA, 0 }, + Package(){0x0000FFFF, 2, INTB, 0 }, + Package(){0x0000FFFF, 3, INTC, 0 }, + }) + Name(APSa, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, 0, 18 }, + Package(){0x0000FFFF, 1, 0, 19 }, + Package(){0x0000FFFF, 2, 0, 16 }, + Package(){0x0000FFFF, 3, 0, 17 }, + }) + + Name(PE0, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, INTA, 0 }, + Package(){0x0000FFFF, 1, INTB, 0 }, + Package(){0x0000FFFF, 2, INTC, 0 }, + Package(){0x0000FFFF, 3, INTD, 0 }, + }) + Name(APE0, Package(){ + /* PCIe slot - Hooked to PCIe */ + Package(){0x0000FFFF, 0, 0, 16 }, + Package(){0x0000FFFF, 1, 0, 17 }, + Package(){0x0000FFFF, 2, 0, 18 }, + Package(){0x0000FFFF, 3, 0, 19 }, + }) + + Name(PE1, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, INTB, 0 }, + Package(){0x0000FFFF, 1, INTC, 0 }, + Package(){0x0000FFFF, 2, INTD, 0 }, + Package(){0x0000FFFF, 3, INTA, 0 }, + }) + Name(APE1, Package(){ + /* PCIe slot - Hooked to PCIe */ + Package(){0x0000FFFF, 0, 0, 17 }, + Package(){0x0000FFFF, 1, 0, 18 }, + Package(){0x0000FFFF, 2, 0, 19 }, + Package(){0x0000FFFF, 3, 0, 16 }, + }) + + Name(PE2, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, INTC, 0 }, + Package(){0x0000FFFF, 1, INTD, 0 }, + Package(){0x0000FFFF, 2, INTA, 0 }, + Package(){0x0000FFFF, 3, INTB, 0 }, + }) + Name(APE2, Package(){ + /* PCIe slot - Hooked to PCIe */ + Package(){0x0000FFFF, 0, 0, 18 }, + Package(){0x0000FFFF, 1, 0, 19 }, + Package(){0x0000FFFF, 2, 0, 16 }, + Package(){0x0000FFFF, 3, 0, 17 }, + }) + + Name(PE3, Package(){ + /* PCIe slot - Hooked to PCIe slot 10 */ + Package(){0x0000FFFF, 0, INTD, 0 }, + Package(){0x0000FFFF, 1, INTA, 0 }, + Package(){0x0000FFFF, 2, INTB, 0 }, + Package(){0x0000FFFF, 3, INTC, 0 }, + }) + Name(APE3, Package(){ + /* PCIe slot - Hooked to PCIe */ + Package(){0x0000FFFF, 0, 0, 19 }, + Package(){0x0000FFFF, 1, 0, 16 }, + Package(){0x0000FFFF, 2, 0, 17 }, + Package(){0x0000FFFF, 3, 0, 18 }, + }) + + Name(PCIB, Package(){ + /* PCI slots: slot 0, slot 1, slot 2 behind Dev14, Fun4. */ + Package(){0x0005FFFF, 0, 0, 0x14 }, + Package(){0x0005FFFF, 1, 0, 0x15 }, + Package(){0x0005FFFF, 2, 0, 0x16 }, + Package(){0x0005FFFF, 3, 0, 0x17 }, + Package(){0x0006FFFF, 0, 0, 0x15 }, + Package(){0x0006FFFF, 1, 0, 0x16 }, + Package(){0x0006FFFF, 2, 0, 0x17 }, + Package(){0x0006FFFF, 3, 0, 0x14 }, + Package(){0x0007FFFF, 0, 0, 0x16 }, + Package(){0x0007FFFF, 1, 0, 0x17 }, + Package(){0x0007FFFF, 2, 0, 0x14 }, + Package(){0x0007FFFF, 3, 0, 0x15 }, + }) +} diff --git a/src/mainboard/gizmosphere/gizmo/acpi/sata.asl b/src/mainboard/gizmosphere/gizmo/acpi/sata.asl new file mode 100755 index 0000000000..dcf6deca48 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/sata.asl @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* simple name description */ + +/* +Scope (_SB) { + Device(PCI0) { + Device(SATA) { + Name(_ADR, 0x00110000) + #include "sata.asl" + } + } +} +*/ + +Name(STTM, Buffer(20) { + 0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x00, 0x00 +}) + +/* Start by clearing the PhyRdyChg bits */ +Method(_INI) { + \_GPE._L1F() +} + +Device(PMRY) +{ + Name(_ADR, 0) + Method(_GTM, 0x0, NotSerialized) { + Return(STTM) + } + Method(_STM, 0x3, NotSerialized) {} + + Device(PMST) { + Name(_ADR, 0) + Method(_STA,0) { + if (LGreater(P0IS,0)) { + return (0x0F) /* sata is visible */ + } + else { + return (0x00) /* sata is missing */ + } + } + }/* end of PMST */ + + Device(PSLA) + { + Name(_ADR, 1) + Method(_STA,0) { + if (LGreater(P1IS,0)) { + return (0x0F) /* sata is visible */ + } + else { + return (0x00) /* sata is missing */ + } + } + } /* end of PSLA */ +} /* end of PMRY */ + + +Device(SEDY) +{ + Name(_ADR, 1) /* IDE Scondary Channel */ + Method(_GTM, 0x0, NotSerialized) { + Return(STTM) + } + Method(_STM, 0x3, NotSerialized) {} + + Device(SMST) + { + Name(_ADR, 0) + Method(_STA,0) { + if (LGreater(P2IS,0)) { + return (0x0F) /* sata is visible */ + } + else { + return (0x00) /* sata is missing */ + } + } + } /* end of SMST */ + + Device(SSLA) + { + Name(_ADR, 1) + Method(_STA,0) { + if (LGreater(P3IS,0)) { + return (0x0F) /* sata is visible */ + } + else { + return (0x00) /* sata is missing */ + } + } + } /* end of SSLA */ +} /* end of SEDY */ + +/* SATA Hot Plug Support */ +Scope(\_GPE) { + Method(_L1F,0x0,NotSerialized) { + if (\_SB.P0PR) { + if (LGreater(\_SB.P0IS,0)) { + sleep(32) + } + Notify(\_SB.PCI0.STCR.PMRY.PMST, 0x01) /* NOTIFY_DEVICE_CHECK */ + store(one, \_SB.P0PR) + } + + if (\_SB.P1PR) { + if (LGreater(\_SB.P1IS,0)) { + sleep(32) + } + Notify(\_SB.PCI0.STCR.PMRY.PSLA, 0x01) /* NOTIFY_DEVICE_CHECK */ + store(one, \_SB.P1PR) + } + + if (\_SB.P2PR) { + if (LGreater(\_SB.P2IS,0)) { + sleep(32) + } + Notify(\_SB.PCI0.STCR.SEDY.SMST, 0x01) /* NOTIFY_DEVICE_CHECK */ + store(one, \_SB.P2PR) + } + + if (\_SB.P3PR) { + if (LGreater(\_SB.P3IS,0)) { + sleep(32) + } + Notify(\_SB.PCI0.STCR.SEDY.SSLA, 0x01) /* NOTIFY_DEVICE_CHECK */ + store(one, \_SB.P3PR) + } + } +} diff --git a/src/mainboard/gizmosphere/gizmo/acpi/sleep.asl b/src/mainboard/gizmosphere/gizmo/acpi/sleep.asl new file mode 100644 index 0000000000..a109151509 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/sleep.asl @@ -0,0 +1,121 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Wake status package */ +Name(WKST,Package(){Zero, Zero}) + +/* +* \_PTS - Prepare to Sleep method +* +* Entry: +* Arg0=The value of the sleeping state S1=1, S2=2, etc +* +* Exit: +* -none- +* +* The _PTS control method is executed at the beginning of the sleep process +* for S1-S5. The sleeping value is passed to the _PTS control method. This +* control method may be executed a relatively long time before entering the +* sleep state and the OS may abort the operation without notification to +* the ACPI driver. This method cannot modify the configuration or power +* state of any device in the system. +*/ +Method(\_PTS, 1) { + /* DBGO("\\_PTS\n") */ + /* DBGO("From S0 to S") */ + /* DBGO(Arg0) */ + /* DBGO("\n") */ + + /* Don't allow PCIRST# to reset USB */ + if (LEqual(Arg0,3)){ + Store(0,URRE) + } + + /* Clear sleep SMI status flag and enable sleep SMI trap. */ + /*Store(One, CSSM) + Store(One, SSEN)*/ + + /* On older chips, clear PciExpWakeDisEn */ + /*if (LLessEqual(\_SB.SBRI, 0x13)) { + * Store(0,\_SB.PWDE) + *} + */ + + /* Clear wake status structure. */ + Store(0, Index(WKST,0)) + Store(0, Index(WKST,1)) +} /* End Method(\_PTS) */ + +/* +* \_BFS OEM Back From Sleep method +* +* Entry: +* Arg0=The value of the sleeping state S1=1, S2=2 +* +* Exit: +* -none- +*/ +Method(\_BFS, 1) { + /* DBGO("\\_BFS\n") */ + /* DBGO("From S") */ + /* DBGO(Arg0) */ + /* DBGO(" to S0\n") */ +} + +/* +* \_WAK System Wake method +* +* Entry: +* Arg0=The value of the sleeping state S1=1, S2=2 +* +* Exit: +* Return package of 2 DWords +* Dword 1 - Status +* 0x00000000 wake succeeded +* 0x00000001 Wake was signaled but failed due to lack of power +* 0x00000002 Wake was signaled but failed due to thermal condition +* Dword 2 - Power Supply state +* if non-zero the effective S-state the power supply entered +*/ +Method(\_WAK, 1) { + /* DBGO("\\_WAK\n") */ + /* DBGO("From S") */ + /* DBGO(Arg0) */ + /* DBGO(" to S0\n") */ + + /* Re-enable HPET */ + Store(1,HPDE) + + /* Restore PCIRST# so it resets USB */ + if (LEqual(Arg0,3)){ + Store(1,URRE) + } + + /* Arbitrarily clear PciExpWakeStatus */ + Store(PWST, PWST) + + /* if(DeRefOf(Index(WKST,0))) { + * Store(0, Index(WKST,1)) + * } else { + * Store(Arg0, Index(WKST,1)) + * } + */ + Return(WKST) +} /* End Method(\_WAK) */ + diff --git a/src/mainboard/gizmosphere/gizmo/acpi/superio.asl b/src/mainboard/gizmosphere/gizmo/acpi/superio.asl new file mode 100644 index 0000000000..e042553bee --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/superio.asl @@ -0,0 +1,18 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* No Super I/O device or functionality yet */ diff --git a/src/mainboard/gizmosphere/gizmo/acpi/thermal.asl b/src/mainboard/gizmosphere/gizmo/acpi/thermal.asl new file mode 100644 index 0000000000..2f50475305 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/thermal.asl @@ -0,0 +1,21 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Thermal Zones have been #if 0 for a long time. + * Removing it for now because it doesn't seem to + * do anything when enabled anyway. + */ diff --git a/src/mainboard/gizmosphere/gizmo/acpi/usb_oc.asl b/src/mainboard/gizmosphere/gizmo/acpi/usb_oc.asl new file mode 100644 index 0000000000..0429ac77b2 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi/usb_oc.asl @@ -0,0 +1,174 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* simple name description */ +/* +DefinitionBlock ("DSDT.AML","DSDT",0x01,"XXXXXX","XXXXXXXX",0x00010001 + ) + { + #include "usb.asl" + } +*/ + +/* USB overcurrent mapping pins. */ +Name(UOM0, 0) +Name(UOM1, 2) +Name(UOM2, 0) +Name(UOM3, 7) +Name(UOM4, 2) +Name(UOM5, 2) +Name(UOM6, 6) +Name(UOM7, 2) +Name(UOM8, 6) +Name(UOM9, 6) + +Method(UCOC, 0) { + Sleep(20) + Store(0x13,CMTI) + Store(0,GPSL) +} + +/* USB Port 0 overcurrent uses Gpm 0 */ +If(LLessEqual(UOM0,9)) { + Scope (\_GPE) { + Method (_L13) { + UCOC() + if(LEqual(GPB0,PLC0)) { + Not(PLC0,PLC0) + Store(PLC0, \_SB.PT0D) + } + } + } +} + +/* USB Port 1 overcurrent uses Gpm 1 */ +If (LLessEqual(UOM1,9)) { + Scope (\_GPE) { + Method (_L14) { + UCOC() + if (LEqual(GPB1,PLC1)) { + Not(PLC1,PLC1) + Store(PLC1, \_SB.PT1D) + } + } + } +} + +/* USB Port 2 overcurrent uses Gpm 2 */ +If (LLessEqual(UOM2,9)) { + Scope (\_GPE) { + Method (_L15) { + UCOC() + if (LEqual(GPB2,PLC2)) { + Not(PLC2,PLC2) + Store(PLC2, \_SB.PT2D) + } + } + } +} + +/* USB Port 3 overcurrent uses Gpm 3 */ +If (LLessEqual(UOM3,9)) { + Scope (\_GPE) { + Method (_L16) { + UCOC() + if (LEqual(GPB3,PLC3)) { + Not(PLC3,PLC3) + Store(PLC3, \_SB.PT3D) + } + } + } +} + +/* USB Port 4 overcurrent uses Gpm 4 */ +If (LLessEqual(UOM4,9)) { + Scope (\_GPE) { + Method (_L19) { + UCOC() + if (LEqual(GPB4,PLC4)) { + Not(PLC4,PLC4) + Store(PLC4, \_SB.PT4D) + } + } + } +} + +/* USB Port 5 overcurrent uses Gpm 5 */ +If (LLessEqual(UOM5,9)) { + Scope (\_GPE) { + Method (_L1A) { + UCOC() + if (LEqual(GPB5,PLC5)) { + Not(PLC5,PLC5) + Store(PLC5, \_SB.PT5D) + } + } + } +} + +/* USB Port 6 overcurrent uses Gpm 6 */ +If (LLessEqual(UOM6,9)) { + Scope (\_GPE) { + /* Method (_L1C) { */ + Method (_L06) { + UCOC() + if (LEqual(GPB6,PLC6)) { + Not(PLC6,PLC6) + Store(PLC6, \_SB.PT6D) + } + } + } +} + +/* USB Port 7 overcurrent uses Gpm 7 */ +If (LLessEqual(UOM7,9)) { + Scope (\_GPE) { + /* Method (_L1D) { */ + Method (_L07) { + UCOC() + if (LEqual(GPB7,PLC7)) { + Not(PLC7,PLC7) + Store(PLC7, \_SB.PT7D) + } + } + } +} + +/* USB Port 8 overcurrent uses Gpm 8 */ +If (LLessEqual(UOM8,9)) { + Scope (\_GPE) { + Method (_L17) { + if (LEqual(G8IS,PLC8)) { + Not(PLC8,PLC8) + Store(PLC8, \_SB.PT8D) + } + } + } +} + +/* USB Port 9 overcurrent uses Gpm 9 */ +If (LLessEqual(UOM9,9)) { + Scope (\_GPE) { + Method (_L0E) { + if (LEqual(G9IS,0)) { + Store(1,\_SB.PT9D) + } + } + } +} diff --git a/src/mainboard/gizmosphere/gizmo/acpi_tables.c b/src/mainboard/gizmosphere/gizmo/acpi_tables.c new file mode 100755 index 0000000000..43ee9c9019 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/acpi_tables.c @@ -0,0 +1,321 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "agesawrapper.h" +#include +#include + +#define DUMP_ACPI_TABLES 0 + +#if DUMP_ACPI_TABLES == 1 + +static void dump_mem(u32 start, u32 end) +{ + + u32 i; + print_debug("dump_mem:"); + for (i = start; i < end; i++) { + if ((i & 0xf) == 0) { + printk(BIOS_DEBUG, "\n%08x:", i); + } + printk(BIOS_DEBUG, " %02x", (u8)*((u8 *)i)); + } + print_debug("\n"); +} +#endif + +extern const unsigned char AmlCode[]; + +unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) +{ + int lens; + msr_t msr; + char pscope[] = "\\_SB.PCI0"; + + lens = acpigen_write_scope(pscope); + msr = rdmsr(TOP_MEM); + lens += acpigen_write_name_dword("TOM1", msr.lo); + msr = rdmsr(TOP_MEM2); + /* + * Since XP only implements parts of ACPI 2.0, we can't use a qword + * here. + * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt + * slide 22ff. + * Shift value right by 20 bit to make it fit into 32bit, + * giving us 1MB granularity and a limit of almost 4Exabyte of memory. + */ + lens += acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20); + acpigen_patch_len(lens - 1); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + /* Just a dummy */ + return current; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* create all subtables for processors */ + current = acpi_create_madt_lapics(current); + + /* Write SB800 IOAPIC, only one */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + CONFIG_MAX_CPUS, IO_APIC_ADDR, 0); + + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, 0xF); + + /* 0: mean bus 0--->ISA */ + /* 0: PIC 0 */ + /* 2: APIC 2 */ + /* 5 mean: 0101 --> Edige-triggered, Active high */ + + /* create all subtables for processors */ + /* current = acpi_create_madt_lapic_nmis(current, 5, 1); */ + /* 1: LINT1 connect to NMI */ + + return current; +} + +unsigned long acpi_fill_hest(acpi_hest_t *hest) +{ + void *addr, *current; + + /* Skip the HEST header. */ + current = (void *)(hest + 1); + + addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE); + if (addr != NULL) + current += acpi_create_hest_error_source(hest, current, 0, (void *)((u32)addr + 2), *(UINT16 *)addr - 2); + + addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC); + if (addr != NULL) + current += acpi_create_hest_error_source(hest, current, 1, (void *)((u32)addr + 2), *(UINT16 *)addr - 2); + + return (unsigned long)current; +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_srat_t *srat; + acpi_slit_t *slit; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *dsdt; + acpi_header_t *ssdt; + acpi_header_t *ssdt2; + acpi_header_t *alib; + acpi_hest_t *hest; + + get_bus_conf(); /* it will get sblk, pci1234, hcdn, and sbdn */ + + /* Align ACPI tables to 16 bytes */ + start = ALIGN(start, 16); + current = start; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx...\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + + /* clear all table memory */ + memset((void *)start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, NULL); + acpi_write_rsdt(rsdt); + + /* DSDT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * DSDT at %lx\n", current); + dsdt = (acpi_header_t *)current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n",dsdt,dsdt->length); + + /* FACS */ // it needs 64 bit alignment + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * FACS at %lx\n", current); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + acpi_create_facs(facs); + + /* FADT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * FADT at %lx\n", current); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * HPET at %lx\n", current); + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + acpi_create_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * MADT at %lx\n",current); + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + acpi_add_table(rsdp, madt); + + /* HEST */ + current = ALIGN(current, 8); + hest = (acpi_hest_t *)current; + acpi_write_hest((void *)current); + acpi_add_table(rsdp, (void *)current); + current += ((acpi_header_t *)current)->length; + + /* SRAT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current); + srat = (acpi_srat_t *) agesawrapper_getlateinitptr (PICK_SRAT); + if (srat != NULL) { + memcpy((void *)current, srat, srat->header.length); + srat = (acpi_srat_t *) current; + current += srat->header.length; + acpi_add_table(rsdp, srat); + } + else { + printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n"); + } + + /* SLIT */ + current = ALIGN(current, 8); + printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current); + slit = (acpi_slit_t *) agesawrapper_getlateinitptr (PICK_SLIT); + if (slit != NULL) { + memcpy((void *)current, slit, slit->header.length); + slit = (acpi_slit_t *) current; + current += slit->header.length; + acpi_add_table(rsdp, slit); + } + else { + printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n"); + } + + /* SSDT */ + current = ALIGN(current, 16); + printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current); + alib = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_ALIB); + if (alib != NULL) { + memcpy((void *)current, alib, alib->length); + alib = (acpi_header_t *) current; + current += alib->length; + acpi_add_table(rsdp, (void *)alib); + } else { + printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL. Skipping.\n"); + } + + /* The DSDT needs additional work for the AGESA SSDT Pstate table */ + /* Keep the comment for a while. */ + current = ALIGN(current, 16); + printk(BIOS_DEBUG, "ACPI: * AGESA SSDT Pstate at %lx\n", current); + ssdt = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_PSTATE); + if (ssdt != NULL) { + memcpy((void *)current, ssdt, ssdt->length); + ssdt = (acpi_header_t *) current; + current += ssdt->length; + acpi_add_table(rsdp,ssdt); + } else { + printk(BIOS_DEBUG, " AGESA SSDT Pstate table NULL. Skipping.\n"); + } + + current = ALIGN(current, 16); + printk(BIOS_DEBUG, "ACPI: * coreboot TOM SSDT2 at %lx\n", current); + ssdt2 = (acpi_header_t *) current; + acpi_create_ssdt_generator(ssdt2, ACPI_TABLE_CREATOR); + current += ssdt2->length; + acpi_add_table(rsdp,ssdt2); + +#if DUMP_ACPI_TABLES == 1 + printk(BIOS_DEBUG, "rsdp\n"); + dump_mem(rsdp, ((void *)rsdp) + sizeof(acpi_rsdp_t)); + + printk(BIOS_DEBUG, "rsdt\n"); + dump_mem(rsdt, ((void *)rsdt) + sizeof(acpi_rsdt_t)); + + printk(BIOS_DEBUG, "madt\n"); + dump_mem(madt, ((void *)madt) + madt->header.length); + + printk(BIOS_DEBUG, "srat\n"); + dump_mem(srat, ((void *)srat) + srat->header.length); + + printk(BIOS_DEBUG, "slit\n"); + dump_mem(slit, ((void *)slit) + slit->header.length); + + printk(BIOS_DEBUG, "alib\n"); + dump_mem(ssdt, ((void *)alib) + alib->length); + + printk(BIOS_DEBUG, "ssdt\n"); + dump_mem(ssdt, ((void *)ssdt) + ssdt->length); + + printk(BIOS_DEBUG, "ssdt2\n"); + dump_mem(ssdt2, ((void *)ssdt2) + ssdt2->length); + + printk(BIOS_DEBUG, "fadt\n"); + dump_mem(fadt, ((void *)fadt) + fadt->header.length); + + printk(BIOS_DEBUG, "hest\n"); + dump_mem(hest, ((void *)hest) + hest->header.length); +#endif + + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/gizmosphere/gizmo/agesawrapper.c b/src/mainboard/gizmosphere/gizmo/agesawrapper.c new file mode 100755 index 0000000000..2270720d03 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/agesawrapper.c @@ -0,0 +1,715 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/*----------------------------------------------------------------------------- + * M O D U L E S U S E D + *----------------------------------------------------------------------------- + */ + +#include +#include +#include "agesawrapper.h" +#include "BiosCallOuts.h" +#include "cpuRegisters.h" +#include "cpuCacheInit.h" +#include "cpuApicUtilities.h" +#include "cpuEarlyInit.h" +#include "cpuLateInit.h" +#include "Dispatcher.h" +#include "cpuCacheInit.h" +#include "heapManager.h" +#include "amdlib.h" +#include "PlatformGnbPcieComplex.h" +#include "Filecode.h" +#include +#include +#include +#include + +#define FILECODE UNASSIGNED_FILE_FILECODE + +/*------------------------------------------------------------------------------ + * D E F I N I T I O N S A N D M A C R O S + *------------------------------------------------------------------------------ + */ + +#define MMCONF_ENABLE 1 + +/* ACPI table pointers returned by AmdInitLate */ +VOID *DmiTable = NULL; +VOID *AcpiPstate = NULL; +VOID *AcpiSrat = NULL; +VOID *AcpiSlit = NULL; + +VOID *AcpiWheaMce = NULL; +VOID *AcpiWheaCmc = NULL; +VOID *AcpiAlib = NULL; + +/*------------------------------------------------------------------------------ + * T Y P E D E F S A N D S T R U C T U R E S + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * P R O T O T Y P E S O F L O C A L F U N C T I O N S + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * E X P O R T E D F U N C T I O N S + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * L O C A L F U N C T I O N S + *------------------------------------------------------------------------------ + */ +UINT32 +agesawrapper_amdinitcpuio ( + VOID + ) +{ + AGESA_STATUS Status; + UINT64 MsrReg; + UINT32 PciData; + PCI_ADDR PciAddress; + AMD_CONFIG_PARAMS StdHeader; + + /* Enable legacy video routing: D18F1xF4 VGA Enable */ + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0xF4); + PciData = 1; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + + /* The platform BIOS needs to ensure the memory ranges of SB800 legacy + * devices (TPM, HPET, BIOS RAM, Watchdog Timer, I/O APIC and ACPI) are + * set to non-posted regions. + */ + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0x84); + PciData = 0x00FEDF00; // last address before processor local APIC at FEE00000 + PciData |= 1 << 7; // set NP (non-posted) bit + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0x80); + PciData = (0xFED00000 >> 8) | 3; // lowest NP address is HPET at FED00000 + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + + /* Map the remaining PCI hole as posted MMIO */ + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0x8C); + PciData = 0x00FECF00; // last address before non-posted range + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + LibAmdMsrRead (0xC001001A, &MsrReg, &StdHeader); + MsrReg = (MsrReg >> 8) | 3; + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0x88); + PciData = (UINT32)MsrReg; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + + /* Send all IO (0000-FFFF) to southbridge. */ + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0xC4); + PciData = 0x0000F000; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0x18, 1, 0xC0); + PciData = 0x00000003; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + Status = AGESA_SUCCESS; + return (UINT32)Status; +} + +UINT32 +agesawrapper_amdinitmmio ( + VOID + ) +{ + AGESA_STATUS Status; + UINT64 MsrReg; + UINT32 PciData; + PCI_ADDR PciAddress; + AMD_CONFIG_PARAMS StdHeader; + + UINT8 BusRangeVal = 0; + UINT8 BusNum; + UINT8 Index; + + /* + Set the MMIO Configuration Base Address and Bus Range onto MMIO configuration base + Address MSR register. + */ + + for (Index = 0; Index < 8; Index++) { + BusNum = CONFIG_MMCONF_BUS_NUMBER >> Index; + if (BusNum == 1) { + BusRangeVal = Index; + break; + } + } + + MsrReg = (CONFIG_MMCONF_BASE_ADDRESS | (UINT64)(BusRangeVal << 2) | MMCONF_ENABLE); + LibAmdMsrWrite (0xC0010058, &MsrReg, &StdHeader); + + /* + Set the NB_CFG MSR register. Enable CF8 extended configuration cycles. + */ + LibAmdMsrRead (0xC001001F, &MsrReg, &StdHeader); + MsrReg = MsrReg | 0x0000400000000000ull; + LibAmdMsrWrite (0xC001001F, &MsrReg, &StdHeader); + + /* Set Ontario Link Data */ + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0, 0, 0xE0); + PciData = 0x01308002; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + PciAddress.AddressValue = MAKE_SBDFO (0, 0, 0, 0, 0xE4); + PciData = (AMD_APU_SSID<<0x10)|AMD_APU_SVID; + LibAmdPciWrite(AccessWidth32, PciAddress, &PciData, &StdHeader); + + Status = AGESA_SUCCESS; + return (UINT32)Status; +} + +UINT32 +agesawrapper_amdinitreset ( + VOID + ) +{ + AGESA_STATUS status; + AMD_INTERFACE_PARAMS AmdParamStruct; + AMD_RESET_PARAMS AmdResetParams; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + LibAmdMemFill (&AmdResetParams, + 0, + sizeof (AMD_RESET_PARAMS), + &(AmdResetParams.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_RESET; + AmdParamStruct.AllocationMethod = ByHost; + AmdParamStruct.NewStructSize = sizeof(AMD_RESET_PARAMS); + AmdParamStruct.NewStructPtr = &AmdResetParams; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = NULL; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + AmdCreateStruct (&AmdParamStruct); + AmdResetParams.HtConfig.Depth = 0; + + status = AmdInitReset ((AMD_RESET_PARAMS *)AmdParamStruct.NewStructPtr); + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + AmdReleaseStruct (&AmdParamStruct); + return (UINT32)status; +} + +UINT32 +agesawrapper_amdinitearly ( + VOID + ) +{ + AGESA_STATUS status; + AMD_INTERFACE_PARAMS AmdParamStruct; + AMD_EARLY_PARAMS *AmdEarlyParamsPtr; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_EARLY; + AmdParamStruct.AllocationMethod = PreMemHeap; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + AmdCreateStruct (&AmdParamStruct); + + AmdEarlyParamsPtr = (AMD_EARLY_PARAMS *)AmdParamStruct.NewStructPtr; + OemCustomizeInitEarly (AmdEarlyParamsPtr); + + status = AmdInitEarly ((AMD_EARLY_PARAMS *)AmdParamStruct.NewStructPtr); + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + AmdReleaseStruct (&AmdParamStruct); + + return (UINT32)status; +} + +UINT32 GetHeapBase( + AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT32 heap; + +#if CONFIG_HAVE_ACPI_RESUME + /* Both romstage and ramstage has this S3 detect. */ + if (acpi_get_sleep_type() == 3) + heap = (UINT32)cbmem_find(CBMEM_ID_RESUME_SCRATCH) + (CONFIG_HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE); /* himem_heap_base + high_stack_size */ + else +#endif + heap = BIOS_HEAP_START_ADDRESS; /* low mem */ + + return heap; +} + +UINT32 +agesawrapper_amdinitpost ( + VOID + ) +{ + AGESA_STATUS status; + UINT16 i; + UINT32 *HeadPtr; + AMD_INTERFACE_PARAMS AmdParamStruct; + BIOS_HEAP_MANAGER *BiosManagerPtr; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_POST; + AmdParamStruct.AllocationMethod = PreMemHeap; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + + AmdCreateStruct (&AmdParamStruct); + status = AmdInitPost ((AMD_POST_PARAMS *)AmdParamStruct.NewStructPtr); + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + AmdReleaseStruct (&AmdParamStruct); + + /* Initialize heap space */ + BiosManagerPtr = (BIOS_HEAP_MANAGER *)GetHeapBase(&AmdParamStruct.StdHeader); + + HeadPtr = (UINT32 *) ((UINT8 *) BiosManagerPtr + sizeof (BIOS_HEAP_MANAGER)); + for (i = 0; i < ((BIOS_HEAP_SIZE/4) - (sizeof (BIOS_HEAP_MANAGER)/4)); i++) { + *HeadPtr = 0x00000000; + HeadPtr++; + } + BiosManagerPtr->StartOfAllocatedNodes = 0; + BiosManagerPtr->StartOfFreedNodes = 0; + + return (UINT32)status; +} + +UINT32 +agesawrapper_amdinitenv ( + VOID + ) +{ + AGESA_STATUS status; + AMD_INTERFACE_PARAMS AmdParamStruct; + PCI_ADDR PciAddress; + UINT32 PciValue; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + + AmdParamStruct.AgesaFunctionName = AMD_INIT_ENV; + AmdParamStruct.AllocationMethod = PostMemDram; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + AmdCreateStruct (&AmdParamStruct); + status = AmdInitEnv ((AMD_ENV_PARAMS *)AmdParamStruct.NewStructPtr); + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + /* Initialize Subordinate Bus Number and Secondary Bus Number + * In platform BIOS this address is allocated by PCI enumeration code + Modify D1F0x18 + */ + PciAddress.Address.Bus = 0; + PciAddress.Address.Device = 1; + PciAddress.Address.Function = 0; + PciAddress.Address.Register = 0x18; + /* Write to D1F0x18 */ + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x00010100; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + + /* Initialize GMM Base Address for Legacy Bridge Mode + * Modify B1D5F0x18 + */ + PciAddress.Address.Bus = 1; + PciAddress.Address.Device = 5; + PciAddress.Address.Function = 0; + PciAddress.Address.Register = 0x18; + + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x96000000; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + /* Initialize FB Base Address for Legacy Bridge Mode + * Modify B1D5F0x10 + */ + PciAddress.Address.Register = 0x10; + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x80000000; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + /* Initialize GMM Base Address for Pcie Mode + * Modify B0D1F0x18 + */ + PciAddress.Address.Bus = 0; + PciAddress.Address.Device = 1; + PciAddress.Address.Function = 0; + PciAddress.Address.Register = 0x18; + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x96000000; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + + /* Initialize FB Base Address for Pcie Mode + * Modify B0D1F0x10 + */ + PciAddress.Address.Register = 0x10; + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x80000000; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + /* Initialize MMIO Base and Limit Address + * Modify B0D1F0x20 + */ + PciAddress.Address.Bus = 0; + PciAddress.Address.Device = 1; + PciAddress.Address.Function = 0; + PciAddress.Address.Register = 0x20; + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x96009600; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + + /* Initialize MMIO Prefetchable Memory Limit and Base + * Modify B0D1F0x24 + */ + PciAddress.Address.Register = 0x24; + LibAmdPciRead (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + PciValue |= 0x8FF18001; + LibAmdPciWrite (AccessWidth32, PciAddress, &PciValue, &AmdParamStruct.StdHeader); + AmdReleaseStruct (&AmdParamStruct); + + return (UINT32)status; +} + +VOID * +agesawrapper_getlateinitptr ( + int pick + ) +{ + switch (pick) { + case PICK_DMI: + return DmiTable; + case PICK_PSTATE: + return AcpiPstate; + case PICK_SRAT: + return AcpiSrat; + case PICK_SLIT: + return AcpiSlit; + case PICK_WHEA_MCE: + return AcpiWheaMce; + case PICK_WHEA_CMC: + return AcpiWheaCmc; + case PICK_ALIB: + return AcpiAlib; + default: + return NULL; + } +} + +UINT32 +agesawrapper_amdinitmid ( + VOID + ) +{ + AGESA_STATUS status; + AMD_INTERFACE_PARAMS AmdParamStruct; + + /* Enable MMIO on AMD CPU Address Map Controller */ + agesawrapper_amdinitcpuio (); + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_MID; + AmdParamStruct.AllocationMethod = PostMemDram; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + + AmdCreateStruct (&AmdParamStruct); + + status = AmdInitMid ((AMD_MID_PARAMS *)AmdParamStruct.NewStructPtr); + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + AmdReleaseStruct (&AmdParamStruct); + + return (UINT32)status; +} + +UINT32 +agesawrapper_amdinitlate ( + VOID + ) +{ + AGESA_STATUS Status; + AMD_INTERFACE_PARAMS AmdParamStruct; + AMD_LATE_PARAMS * AmdLateParamsPtr; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_LATE; + AmdParamStruct.AllocationMethod = PostMemDram; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + + AmdCreateStruct (&AmdParamStruct); + AmdLateParamsPtr = (AMD_LATE_PARAMS *) AmdParamStruct.NewStructPtr; + + printk (BIOS_DEBUG, "agesawrapper_amdinitlate: AmdLateParamsPtr = %X\n", (u32)AmdLateParamsPtr); + + Status = AmdInitLate (AmdLateParamsPtr); + if (Status != AGESA_SUCCESS) { + agesawrapper_amdreadeventlog(); + ASSERT(Status == AGESA_SUCCESS); + } + + DmiTable = AmdLateParamsPtr->DmiTable; + AcpiPstate = AmdLateParamsPtr->AcpiPState; + AcpiSrat = AmdLateParamsPtr->AcpiSrat; + AcpiSlit = AmdLateParamsPtr->AcpiSlit; + AcpiWheaMce = AmdLateParamsPtr->AcpiWheaMce; + AcpiWheaCmc = AmdLateParamsPtr->AcpiWheaCmc; + AcpiAlib = AmdLateParamsPtr->AcpiAlib; + + printk(BIOS_DEBUG, "In %s, AGESA generated ACPI tables:\n" + " DmiTable:%p\n AcpiPstate: %p\n AcpiSrat:%p\n AcpiSlit:%p\n" + " Mce:%p\n Cmc:%p\n Alib:%p\n", + __func__, DmiTable, AcpiPstate, AcpiSrat, AcpiSlit, + AcpiWheaMce, AcpiWheaCmc, AcpiAlib); + + /* Don't release the structure until coreboot has copied the ACPI tables. + * AmdReleaseStruct (&AmdLateParams); + */ + + return (UINT32)Status; +} + +#if CONFIG_HAVE_ACPI_RESUME +UINT32 +agesawrapper_amdinitresume ( + VOID + ) +{ + AGESA_STATUS status; + AMD_INTERFACE_PARAMS AmdParamStruct; + AMD_RESUME_PARAMS *AmdResumeParamsPtr; + S3_DATA_TYPE S3DataType; + + LibAmdMemFill (&AmdParamStruct, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdParamStruct.StdHeader)); + + AmdParamStruct.AgesaFunctionName = AMD_INIT_RESUME; + AmdParamStruct.AllocationMethod = PreMemHeap; + AmdParamStruct.StdHeader.AltImageBasePtr = 0; + AmdParamStruct.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdParamStruct.StdHeader.Func = 0; + AmdParamStruct.StdHeader.ImageBasePtr = 0; + AmdCreateStruct (&AmdParamStruct); + + AmdResumeParamsPtr = (AMD_RESUME_PARAMS *)AmdParamStruct.NewStructPtr; + + AmdResumeParamsPtr->S3DataBlock.NvStorageSize = 0; + AmdResumeParamsPtr->S3DataBlock.VolatileStorageSize = 0; + S3DataType = S3DataTypeNonVolatile; + + OemAgesaGetS3Info (S3DataType, + (u32 *) &AmdResumeParamsPtr->S3DataBlock.NvStorageSize, + (void **) &AmdResumeParamsPtr->S3DataBlock.NvStorage); + + status = AmdInitResume ((AMD_RESUME_PARAMS *)AmdParamStruct.NewStructPtr); + + if (status != AGESA_SUCCESS) agesawrapper_amdreadeventlog(); + AmdReleaseStruct (&AmdParamStruct); + + return (UINT32)status; +} + +UINT32 +agesawrapper_amds3laterestore ( + VOID + ) +{ + AGESA_STATUS Status; + AMD_INTERFACE_PARAMS AmdInterfaceParams; + AMD_S3LATE_PARAMS AmdS3LateParams; + AMD_S3LATE_PARAMS *AmdS3LateParamsPtr; + S3_DATA_TYPE S3DataType; + + LibAmdMemFill (&AmdS3LateParams, + 0, + sizeof (AMD_S3LATE_PARAMS), + &(AmdS3LateParams.StdHeader)); + AmdInterfaceParams.StdHeader.ImageBasePtr = 0; + AmdInterfaceParams.AllocationMethod = ByHost; + AmdInterfaceParams.AgesaFunctionName = AMD_S3LATE_RESTORE; + AmdInterfaceParams.NewStructPtr = &AmdS3LateParams; + AmdInterfaceParams.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdS3LateParamsPtr = &AmdS3LateParams; + AmdInterfaceParams.NewStructSize = sizeof (AMD_S3LATE_PARAMS); + + AmdCreateStruct (&AmdInterfaceParams); + + AmdS3LateParamsPtr->S3DataBlock.VolatileStorageSize = 0; + S3DataType = S3DataTypeVolatile; + + OemAgesaGetS3Info (S3DataType, + (u32 *) &AmdS3LateParamsPtr->S3DataBlock.VolatileStorageSize, + (void **) &AmdS3LateParamsPtr->S3DataBlock.VolatileStorage); + + Status = AmdS3LateRestore (AmdS3LateParamsPtr); + if (Status != AGESA_SUCCESS) { + agesawrapper_amdreadeventlog(); + ASSERT(Status == AGESA_SUCCESS); + } + + return (UINT32)Status; +} + +#ifndef __PRE_RAM__ +UINT32 +agesawrapper_amdS3Save ( + VOID + ) +{ + AGESA_STATUS Status; + AMD_S3SAVE_PARAMS *AmdS3SaveParamsPtr; + AMD_INTERFACE_PARAMS AmdInterfaceParams; + S3_DATA_TYPE S3DataType; + + LibAmdMemFill (&AmdInterfaceParams, + 0, + sizeof (AMD_INTERFACE_PARAMS), + &(AmdInterfaceParams.StdHeader)); + + AmdInterfaceParams.StdHeader.ImageBasePtr = 0; + AmdInterfaceParams.StdHeader.HeapStatus = HEAP_SYSTEM_MEM; + AmdInterfaceParams.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + AmdInterfaceParams.AllocationMethod = PostMemDram; + AmdInterfaceParams.AgesaFunctionName = AMD_S3_SAVE; + AmdInterfaceParams.StdHeader.AltImageBasePtr = 0; + AmdInterfaceParams.StdHeader.Func = 0; + AmdCreateStruct(&AmdInterfaceParams); + + AmdS3SaveParamsPtr = (AMD_S3SAVE_PARAMS *)AmdInterfaceParams.NewStructPtr; + AmdS3SaveParamsPtr->StdHeader = AmdInterfaceParams.StdHeader; + + Status = AmdS3Save (AmdS3SaveParamsPtr); + if (Status != AGESA_SUCCESS) { + agesawrapper_amdreadeventlog(); + ASSERT(Status == AGESA_SUCCESS); + } + + S3DataType = S3DataTypeNonVolatile; + + Status = OemAgesaSaveS3Info ( + S3DataType, + AmdS3SaveParamsPtr->S3DataBlock.NvStorageSize, + AmdS3SaveParamsPtr->S3DataBlock.NvStorage); + + if (AmdS3SaveParamsPtr->S3DataBlock.VolatileStorageSize != 0) { + S3DataType = S3DataTypeVolatile; + + Status = OemAgesaSaveS3Info ( + S3DataType, + AmdS3SaveParamsPtr->S3DataBlock.VolatileStorageSize, + AmdS3SaveParamsPtr->S3DataBlock.VolatileStorage + ); + } + + OemAgesaSaveMtrr(); + AmdReleaseStruct (&AmdInterfaceParams); + + return (UINT32)Status; +} +#endif /* #ifndef __PRE_RAM__ */ +#endif /* CONFIG_HAVE_ACPI_RESUME */ + +UINT32 +agesawrapper_amdlaterunaptask ( + UINT32 Func, + UINT32 Data, + VOID *ConfigPtr + ) +{ + AGESA_STATUS Status; + AP_EXE_PARAMS ApExeParams; + + LibAmdMemFill (&ApExeParams, + 0, + sizeof (AP_EXE_PARAMS), + &(ApExeParams.StdHeader)); + + ApExeParams.StdHeader.AltImageBasePtr = 0; + ApExeParams.StdHeader.CalloutPtr = (CALLOUT_ENTRY) &GetBiosCallout; + ApExeParams.StdHeader.Func = 0; + ApExeParams.StdHeader.ImageBasePtr = 0; + ApExeParams.FunctionNumber = Func; + ApExeParams.RelatedDataBlock = ConfigPtr; + + Status = AmdLateRunApTask (&ApExeParams); + if (Status != AGESA_SUCCESS) { + agesawrapper_amdreadeventlog(); + ASSERT(Status == AGESA_SUCCESS); + } + + return (UINT32)Status; +} + +UINT32 +agesawrapper_amdreadeventlog ( + VOID + ) +{ + AGESA_STATUS Status; + EVENT_PARAMS AmdEventParams; + + LibAmdMemFill (&AmdEventParams, + 0, + sizeof (EVENT_PARAMS), + &(AmdEventParams.StdHeader)); + + AmdEventParams.StdHeader.AltImageBasePtr = 0; + AmdEventParams.StdHeader.CalloutPtr = NULL; + AmdEventParams.StdHeader.Func = 0; + AmdEventParams.StdHeader.ImageBasePtr = 0; + Status = AmdReadEventLog (&AmdEventParams); + while (AmdEventParams.EventClass != 0) { + printk(BIOS_DEBUG,"\nEventLog: EventClass = %lx, EventInfo = %lx.\n",AmdEventParams.EventClass,AmdEventParams.EventInfo); + printk(BIOS_DEBUG," Param1 = %lx, Param2 = %lx.\n",AmdEventParams.DataParam1,AmdEventParams.DataParam2); + printk(BIOS_DEBUG," Param3 = %lx, Param4 = %lx.\n",AmdEventParams.DataParam3,AmdEventParams.DataParam4); + Status = AmdReadEventLog (&AmdEventParams); + } + + return (UINT32)Status; +} diff --git a/src/mainboard/gizmosphere/gizmo/agesawrapper.h b/src/mainboard/gizmosphere/gizmo/agesawrapper.h new file mode 100755 index 0000000000..ba47c5336a --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/agesawrapper.h @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/*---------------------------------------------------------------------------------------- + * M O D U L E S U S E D + *---------------------------------------------------------------------------------------- + */ + +#ifndef _AGESAWRAPPER_H_ +#define _AGESAWRAPPER_H_ + +#include +#include "Porting.h" +#include "AGESA.h" + +/*---------------------------------------------------------------------------------------- + * D E F I N I T I O N S A N D M A C R O S + *---------------------------------------------------------------------------------------- + */ +/* Define AMD Ontario APPU SSID/SVID */ +#define AMD_APU_SVID 0x1022 +#define AMD_APU_SSID 0x1234 +#define PCIE_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS + +enum { + PICK_DMI, /* DMI Interface */ + PICK_PSTATE, /* Acpi Pstate SSDT Table */ + PICK_SRAT, /* SRAT Table */ + PICK_SLIT, /* SLIT Table */ + PICK_WHEA_MCE, /* WHEA MCE table */ + PICK_WHEA_CMC, /* WHEA CMV table */ + PICK_ALIB, /* SACPI SSDT table with ALIB implementation */ +}; + +/*---------------------------------------------------------------------------------------- + * T Y P E D E F S A N D S T R U C T U R E S + *---------------------------------------------------------------------------------------- + */ + +typedef struct { + UINT32 CalloutName; + AGESA_STATUS (*CalloutPtr) (UINT32 Func, UINT32 Data, VOID* ConfigPtr); +} BIOS_CALLOUT_STRUCT; + +/*---------------------------------------------------------------------------------------- + * P R O T O T Y P E S O F L O C A L F U N C T I O N S + *---------------------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------------------- + * E X P O R T E D F U N C T I O N S + *---------------------------------------------------------------------------------------- + */ + +/*--------------------------------------------------------------------------------------- + * L O C A L F U N C T I O N S + *--------------------------------------------------------------------------------------- + */ + +UINT32 agesawrapper_amdinitreset (void); +UINT32 agesawrapper_amdinitearly (void); +UINT32 agesawrapper_amdinitenv (void); +UINT32 agesawrapper_amdinitlate (void); +UINT32 agesawrapper_amdinitpost (void); +UINT32 agesawrapper_amdinitmid (void); + +UINT32 agesawrapper_amdreadeventlog (void); + +UINT32 agesawrapper_amdinitcpuio (void); +UINT32 agesawrapper_amdinitmmio (void); +UINT32 agesawrapper_amdinitresume (void); +UINT32 agesawrapper_amdS3Save (void); +UINT32 agesawrapper_amds3laterestore (void); +UINT32 agesawrapper_amdlaterunaptask (UINT32 Func, UINT32 Data, VOID *ConfigPtr); +void *agesawrapper_getlateinitptr (int pick); + +UINT32 GetHeapBase(AMD_CONFIG_PARAMS *StdHeader); + +#endif diff --git a/src/mainboard/gizmosphere/gizmo/buildOpts.c b/src/mainboard/gizmosphere/gizmo/buildOpts.c new file mode 100755 index 0000000000..7f1143be11 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/buildOpts.c @@ -0,0 +1,472 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * + * AMD User options selection for a Brazos platform solution system + * + * This file is placed in the user's platform directory and contains the + * build option selections desired for that platform. + * + * For Information about this file, see @ref platforminstall. + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: Core + * @e \$Revision: 23714 $ @e \$Date: 2009-12-09 17:28:37 -0600 (Wed, 09 Dec 2009) $ + */ + +#include "Filecode.h" +#define FILECODE PLATFORM_SPECIFIC_OPTIONS_FILECODE + + +/* Select the cpu family. */ +#define INSTALL_FAMILY_10_SUPPORT FALSE +#define INSTALL_FAMILY_12_SUPPORT FALSE +#define INSTALL_FAMILY_14_SUPPORT TRUE +#define INSTALL_FAMILY_15_SUPPORT FALSE + +/* Select the cpu socket type. */ +#define INSTALL_G34_SOCKET_SUPPORT FALSE +#define INSTALL_C32_SOCKET_SUPPORT FALSE +#define INSTALL_S1G3_SOCKET_SUPPORT FALSE +#define INSTALL_S1G4_SOCKET_SUPPORT FALSE +#define INSTALL_ASB2_SOCKET_SUPPORT FALSE +#define INSTALL_FS1_SOCKET_SUPPORT FALSE +#define INSTALL_FM1_SOCKET_SUPPORT FALSE +#define INSTALL_FP1_SOCKET_SUPPORT FALSE +#define INSTALL_FT1_SOCKET_SUPPORT TRUE +#define INSTALL_AM3_SOCKET_SUPPORT FALSE + +/* + * Agesa optional capabilities selection. + * Uncomment and mark FALSE those features you wish to include in the build. + * Comment out or mark TRUE those features you want to REMOVE from the build. + */ + +#define BLDOPT_REMOVE_FAMILY_10_SUPPORT TRUE +#define BLDOPT_REMOVE_FAMILY_12_SUPPORT TRUE +#define BLDOPT_REMOVE_FAMILY_14_SUPPORT FALSE +#define BLDOPT_REMOVE_FAMILY_15_SUPPORT TRUE + +#define BLDOPT_REMOVE_AM3_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_ASB2_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_C32_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_FM1_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_FP1_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_FS1_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_FT1_SOCKET_SUPPORT FALSE +#define BLDOPT_REMOVE_G34_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_S1G3_SOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_S1G4_SOCKET_SUPPORT TRUE + +#define BLDOPT_REMOVE_UDIMMS_SUPPORT FALSE +#define BLDOPT_REMOVE_RDIMMS_SUPPORT TRUE +#define BLDOPT_REMOVE_LRDIMMS_SUPPORT FALSE +#define BLDOPT_REMOVE_ECC_SUPPORT FALSE +//#define BLDOPT_REMOVE_DCT_INTERLEAVE TRUE +#define BLDOPT_REMOVE_BANK_INTERLEAVE FALSE +#define BLDOPT_REMOVE_NODE_INTERLEAVE TRUE +#define BLDOPT_REMOVE_PARALLEL_TRAINING FALSE +#define BLDOPT_REMOVE_DQS_TRAINING FALSE +#define BLDOPT_REMOVE_ONLINE_SPARE_SUPPORT TRUE +#define BLDOPT_REMOVE_MULTISOCKET_SUPPORT TRUE +#define BLDOPT_REMOVE_ACPI_PSTATES FALSE + #define BLDCFG_REMOVE_ACPI_PSTATES_PPC FALSE + #define BLDCFG_REMOVE_ACPI_PSTATES_PCT FALSE + #define BLDCFG_REMOVE_ACPI_PSTATES_PSD FALSE + #define BLDCFG_REMOVE_ACPI_PSTATES_PSS FALSE + #define BLDCFG_REMOVE_ACPI_PSTATES_XPSS FALSE + #define BLDCFG_FORCE_INDEPENDENT_PSD_OBJECT FALSE +#define BLDOPT_REMOVE_SRAT FALSE +#define BLDOPT_REMOVE_SLIT FALSE +#define BLDOPT_REMOVE_WHEA FALSE +#define BLDOPT_REMOVE_DMI TRUE +#define BLDOPT_REMOVE_HT_ASSIST TRUE +#define BLDOPT_REMOVE_ATM_MODE TRUE +//#define BLDOPT_REMOVE_MSG_BASED_C1E TRUE +//#define BLDOPT_REMOVE_LOW_POWER_STATE_FOR_PROCHOT TRUE +#define BLDOPT_REMOVE_MEM_RESTORE_SUPPORT FALSE +//#define BLDOPT_REMOVE_C6_STATE TRUE +#define BLDOPT_REMOVE_GFX_RECOVERY TRUE +#define BLDOPT_REMOVE_EARLY_SAMPLES TRUE + +/* + * Agesa entry points used in this implementation. + */ +#define AGESA_ENTRY_INIT_RESET TRUE +#define AGESA_ENTRY_INIT_RECOVERY FALSE +#define AGESA_ENTRY_INIT_EARLY TRUE +#define AGESA_ENTRY_INIT_POST TRUE +#define AGESA_ENTRY_INIT_ENV TRUE +#define AGESA_ENTRY_INIT_MID TRUE +#define AGESA_ENTRY_INIT_LATE TRUE +#define AGESA_ENTRY_INIT_S3SAVE TRUE +#define AGESA_ENTRY_INIT_RESUME TRUE +#define AGESA_ENTRY_INIT_LATE_RESTORE TRUE +#define AGESA_ENTRY_INIT_GENERAL_SERVICES TRUE + +#define BLDCFG_PCI_MMIO_BASE CONFIG_MMCONF_BASE_ADDRESS +#define BLDCFG_PCI_MMIO_SIZE CONFIG_MMCONF_BUS_NUMBER + +#define BLDCFG_VRM_CURRENT_LIMIT 24000 +//#define BLDCFG_VRM_NB_CURRENT_LIMIT 0 +#define BLDCFG_VRM_LOW_POWER_THRESHOLD 24000 +#define BLDCFG_VRM_NB_LOW_POWER_THRESHOLD 1 +#define BLDCFG_VRM_SLEW_RATE 5000 +//#define BLDCFG_VRM_NB_SLEW_RATE 5000 +//#define BLDCFG_VRM_ADDITIONAL_DELAY 0 +//#define BLDCFG_VRM_NB_ADDITIONAL_DELAY 0 +#define BLDCFG_VRM_HIGH_SPEED_ENABLE TRUE +//#define BLDCFG_VRM_NB_HIGH_SPEED_ENABLE FALSE +#define BLDCFG_VRM_INRUSH_CURRENT_LIMIT 6000 +//#define BLDCFG_VRM_NB_INRUSH_CURRENT_LIMIT 0 + +//#define BLDCFG_PROCESSOR_SCOPE_NAME0 'C' +//#define BLDCFG_PROCESSOR_SCOPE_NAME1 '0' +//#define BLDCFG_PROCESSOR_SCOPE_IN_SB FALSE +#define BLDCFG_PLAT_NUM_IO_APICS 3 +//#define BLDCFG_PLATFORM_C1E_MODE C1eModeDisabled +//#define BLDCFG_PLATFORM_C1E_OPDATA 0 +//#define BLDCFG_PLATFORM_C1E_MODE_OPDATA1 0 +//#define BLDCFG_PLATFORM_C1E_MODE_OPDATA2 0 +#define BLDCFG_PLATFORM_CSTATE_MODE CStateModeC6 +#define BLDCFG_PLATFORM_CSTATE_OPDATA 0x840 +#define BLDCFG_PLATFORM_CSTATE_IO_BASE_ADDRESS 0x840 +//#define BLDCFG_PLATFORM_CPB_MODE CpbModeAuto +#define BLDCFG_CORE_LEVELING_MODE CORE_LEVEL_LOWEST +#define BLDCFG_AP_MTRR_SETTINGS_LIST &OntarioApMtrrSettingsList +#define BLDCFG_AMD_PLATFORM_TYPE AMD_PLATFORM_MOBILE +//#define BLDCFG_STARTING_BUSNUM 0 +//#define BLDCFG_MAXIMUM_BUSNUM 0xf8 +//#define BLDCFG_ALLOCATED_BUSNUMS 0x20 +//#define BLDCFG_PLATFORM_DEEMPHASIS_LIST 0 +//#define BLDCFG_BUID_SWAP_LIST 0 +//#define BLDCFG_HTDEVICE_CAPABILITIES_OVERRIDE_LIST 0 +//#define BLDCFG_HTFABRIC_LIMITS_LIST 0 +//#define BLDCFG_HTCHAIN_LIMITS_LIST 0 +//#define BLDCFG_BUS_NUMBERS_LIST 0 +//#define BLDCFG_IGNORE_LINK_LIST 0 +//#define BLDCFG_LINK_SKIP_REGANG_LIST 0 +//#define BLDCFG_ADDITIONAL_TOPOLOGIES_LIST 0 +//#define BLDCFG_USE_HT_ASSIST TRUE +//#define BLDCFG_USE_ATM_MODE TRUE +//#define BLDCFG_PLATFORM_CONTROL_FLOW_MODE Nfcm +#define BLDCFG_S3_LATE_RESTORE TRUE +//#define BLDCFG_USE_32_BYTE_REFRESH FALSE +//#define BLDCFG_USE_VARIABLE_MCT_ISOC_PRIORITY FALSE +//#define BLDCFG_PLATFORM_POWER_POLICY_MODE Performance +//#define BLDCFG_SET_HTCRC_SYNC_FLOOD FALSE +//#define BLDCFG_USE_UNIT_ID_CLUMPING FALSE +//#define BLDCFG_SYSTEM_PHYSICAL_SOCKET_MAP 0 +#define BLDCFG_CFG_GNB_HD_AUDIO FALSE +//#define BLDCFG_CFG_ABM_SUPPORT FALSE +//#define BLDCFG_CFG_DYNAMIC_REFRESH_RATE 0 +//#define BLDCFG_CFG_LCD_BACK_LIGHT_CONTROL 0 +//#define BLDCFG_MEM_INIT_PSTATE 0 +//#define BLDCFG_AMD_PSTATE_CAP_VALUE 0 +#define BLDCFG_MEMORY_BUS_FREQUENCY_LIMIT DDR1333_FREQUENCY +#define BLDCFG_MEMORY_MODE_UNGANGED TRUE +//#define BLDCFG_MEMORY_QUAD_RANK_CAPABLE TRUE +//#define BLDCFG_MEMORY_QUADRANK_TYPE QUADRANK_UNBUFFERED +#define BLDCFG_MEMORY_SODIMM_CAPABLE TRUE +#define BLDCFG_MEMORY_LRDIMM_CAPABLE FALSE +#define BLDCFG_MEMORY_ENABLE_BANK_INTERLEAVING TRUE +#define BLDCFG_MEMORY_ENABLE_NODE_INTERLEAVING FALSE +#define BLDCFG_MEMORY_CHANNEL_INTERLEAVING FALSE +#define BLDCFG_MEMORY_POWER_DOWN TRUE +#define BLDCFG_POWER_DOWN_MODE POWER_DOWN_BY_CHIP_SELECT +//#define BLDCFG_ONLINE_SPARE FALSE +//#define BLDCFG_MEMORY_PARITY_ENABLE FALSE +#define BLDCFG_BANK_SWIZZLE TRUE +#define BLDCFG_TIMING_MODE_SELECT TIMING_MODE_AUTO +#define BLDCFG_MEMORY_CLOCK_SELECT DDR1333_FREQUENCY +#define BLDCFG_DQS_TRAINING_CONTROL TRUE +#define BLDCFG_IGNORE_SPD_CHECKSUM FALSE +#define BLDCFG_USE_BURST_MODE FALSE +#define BLDCFG_MEMORY_ALL_CLOCKS_ON FALSE +//#define BLDCFG_ENABLE_ECC_FEATURE TRUE +//#define BLDCFG_ECC_REDIRECTION FALSE +//#define BLDCFG_SCRUB_DRAM_RATE 0 +//#define BLDCFG_SCRUB_L2_RATE 0 +//#define BLDCFG_SCRUB_L3_RATE 0 +//#define BLDCFG_SCRUB_IC_RATE 0 +//#define BLDCFG_SCRUB_DC_RATE 0 +//#define BLDCFG_ECC_SYNC_FLOOD 0 +//#define BLDCFG_ECC_SYMBOL_SIZE 0 +//#define BLDCFG_1GB_ALIGN FALSE +#if !CONFIG_GFXUMA + #define BLDCFG_UMA_ALLOCATION_MODE UMA_NONE + #define BLDCFG_UMA_ALLOCATION_SIZE 0 +#else + #define BLDCFG_UMA_ALLOCATION_MODE UMA_AUTO + #define BLDCFG_UMA_ALLOCATION_SIZE 0 +#endif +#define BLDCFG_UMA_ABOVE4G_SUPPORT FALSE +#define BLDCFG_UMA_ALIGNMENT NO_UMA_ALIGNED +#define BLDCFG_HEAP_DRAM_ADDRESS 0xB0000 +#define BLDCFG_CFG_TEMP_PCIE_MMIO_BASE_ADDRESS 0xD0000000 + +/* + * Agesa configuration values selection. + * Uncomment and specify the value for the configuration options + * needed by the system. + */ +#include "AGESA.h" +#include "CommonReturns.h" + +/* The fixed MTRR values to be set after memory initialization. */ +CONST AP_MTRR_SETTINGS ROMDATA OntarioApMtrrSettingsList[] = +{ + { AMD_AP_MTRR_FIX64k_00000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX16k_80000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX16k_A0000, 0x0000000000000000ull }, + { AMD_AP_MTRR_FIX4k_C0000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_C8000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_D0000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_D8000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_E0000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_E8000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_F0000, 0x1E1E1E1E1E1E1E1Eull }, + { AMD_AP_MTRR_FIX4k_F8000, 0x1E1E1E1E1E1E1E1Eull }, + { CPU_LIST_TERMINAL } +}; + +/* Include the files that instantiate the configuration definitions. */ + +#include "cpuRegisters.h" +#include "cpuFamRegisters.h" +#include "cpuFamilyTranslation.h" +#include "AdvancedApi.h" +#include "heapManager.h" +#include "CreateStruct.h" +#include "cpuFeatures.h" +#include "Table.h" +#include "cpuEarlyInit.h" +#include "cpuLateInit.h" +#include "GnbInterface.h" + +/***************************************************************************** + * Define the RELEASE VERSION string + * + * The Release Version string should identify the next planned release. + * When a branch is made in preparation for a release, the release manager + * should change/confirm that the branch version of this file contains the + * string matching the desired version for the release. The trunk version of + * the file should always contain a trailing 'X'. This will make sure that a + * development build from trunk will not be confused for a released version. + * The release manager will need to remove the trailing 'X' and update the + * version string as appropriate for the release. The trunk copy of this file + * should also be updated/incremented for the next expected version, + trailing 'X' + ****************************************************************************/ +// This is the delivery package title, "BrazosPI" +// This string MUST be exactly 8 characters long +#define AGESA_PACKAGE_STRING {'c', 'b', '_', 'A', 'g', 'e', 's', 'a'} + +// This is the release version number of the AGESA component +// This string MUST be exactly 12 characters long +#define AGESA_VERSION_STRING {'V', '1', '.', '1', '.', '0', '.', '3', ' ', ' ', ' ', ' '} + +/* MEMORY_BUS_SPEED */ +#define DDR400_FREQUENCY 200 ///< DDR 400 +#define DDR533_FREQUENCY 266 ///< DDR 533 +#define DDR667_FREQUENCY 333 ///< DDR 667 +#define DDR800_FREQUENCY 400 ///< DDR 800 +#define DDR1066_FREQUENCY 533 ///< DDR 1066 +#define DDR1333_FREQUENCY 667 ///< DDR 1333 +#define DDR1600_FREQUENCY 800 ///< DDR 1600 +#define DDR1866_FREQUENCY 933 ///< DDR 1866 +#define UNSUPPORTED_DDR_FREQUENCY 934 ///< Highest limit of DDR frequency + +/* QUANDRANK_TYPE*/ +#define QUADRANK_REGISTERED 0 ///< Quadrank registered DIMM +#define QUADRANK_UNBUFFERED 1 ///< Quadrank unbuffered DIMM + +/* USER_MEMORY_TIMING_MODE */ +#define TIMING_MODE_AUTO 0 ///< Use best rate possible +#define TIMING_MODE_LIMITED 1 ///< Set user top limit +#define TIMING_MODE_SPECIFIC 2 ///< Set user specified speed + +/* POWER_DOWN_MODE */ +#define POWER_DOWN_BY_CHANNEL 0 ///< Channel power down mode +#define POWER_DOWN_BY_CHIP_SELECT 1 ///< Chip select power down mode + +// The following definitions specify the default values for various parameters in which there are +// no clearly defined defaults to be used in the common file. The values below are based on product +// and BKDG content, please consult the AGESA Memory team for consultation. +#define DFLT_SCRUB_DRAM_RATE (0) +#define DFLT_SCRUB_L2_RATE (0) +#define DFLT_SCRUB_L3_RATE (0) +#define DFLT_SCRUB_IC_RATE (0) +#define DFLT_SCRUB_DC_RATE (0) +#define DFLT_MEMORY_QUADRANK_TYPE QUADRANK_UNBUFFERED +#define DFLT_VRM_SLEW_RATE (5000) + +// Instantiate all solution relevant data. +#include "PlatformInstall.h" + +/*---------------------------------------------------------------------------------------- + * CUSTOMER OVERIDES MEMORY TABLE + *---------------------------------------------------------------------------------------- + */ + +/* + * Platform Specific Overriding Table allows IBV/OEM to pass in platform information to AGESA + * (e.g. MemClk routing, the number of DIMM slots per channel,...). If PlatformSpecificTable + * is populated, AGESA will base its settings on the data from the table. Otherwise, it will + * use its default conservative settings. + */ +CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = { + // + // The following macros are supported (use comma to separate macros): + // + // MEMCLK_DIS_MAP(SocketID, ChannelID, MemClkDisBit0CSMap,..., MemClkDisBit7CSMap) + // The MemClk pins are identified based on BKDG definition of Fn2x88[MemClkDis] bitmap. + // AGESA will base on this value to disable unused MemClk to save power. + // Example: + // BKDG definition of Fn2x88[MemClkDis] bitmap for AM3 package is like below: + // Bit AM3/S1g3 pin name + // 0 M[B,A]_CLK_H/L[0] + // 1 M[B,A]_CLK_H/L[1] + // 2 M[B,A]_CLK_H/L[2] + // 3 M[B,A]_CLK_H/L[3] + // 4 M[B,A]_CLK_H/L[4] + // 5 M[B,A]_CLK_H/L[5] + // 6 M[B,A]_CLK_H/L[6] + // 7 M[B,A]_CLK_H/L[7] + // And platform has the following routing: + // CS0 M[B,A]_CLK_H/L[4] + // CS1 M[B,A]_CLK_H/L[2] + // CS2 M[B,A]_CLK_H/L[3] + // CS3 M[B,A]_CLK_H/L[5] + // Then platform can specify the following macro: + // MEMCLK_DIS_MAP(ANY_SOCKET, ANY_CHANNEL, 0x00, 0x00, 0x02, 0x04, 0x01, 0x08, 0x00, 0x00) + // + // CKE_TRI_MAP(SocketID, ChannelID, CKETriBit0CSMap, CKETriBit1CSMap) + // The CKE pins are identified based on BKDG definition of Fn2x9C_0C[CKETri] bitmap. + // AGESA will base on this value to tristate unused CKE to save power. + // + // ODT_TRI_MAP(SocketID, ChannelID, ODTTriBit0CSMap,..., ODTTriBit3CSMap) + // The ODT pins are identified based on BKDG definition of Fn2x9C_0C[ODTTri] bitmap. + // AGESA will base on this value to tristate unused ODT pins to save power. + // + // CS_TRI_MAP(SocketID, ChannelID, CSTriBit0CSMap,..., CSTriBit7CSMap) + // The Chip select pins are identified based on BKDG definition of Fn2x9C_0C[ChipSelTri] bitmap. + // AGESA will base on this value to tristate unused Chip select to save power. + // + // NUMBER_OF_DIMMS_SUPPORTED(SocketID, ChannelID, NumberOfDimmSlotsPerChannel) + // Specifies the number of DIMM slots per channel. + // + // NUMBER_OF_CHIP_SELECTS_SUPPORTED(SocketID, ChannelID, NumberOfChipSelectsPerChannel) + // Specifies the number of Chip selects per channel. + // + // NUMBER_OF_CHANNELS_SUPPORTED(SocketID, NumberOfChannelsPerSocket) + // Specifies the number of channels per socket. + // + // OVERRIDE_DDR_BUS_SPEED(SocketID, ChannelID, USER_MEMORY_TIMING_MODE, MEMORY_BUS_SPEED) + // Specifies DDR bus speed of channel ChannelID on socket SocketID. + // + // DRAM_TECHNOLOGY(SocketID, TECHNOLOGY_TYPE) + // Specifies the DRAM technology type of socket SocketID (DDR2, DDR3,...) + // + // WRITE_LEVELING_SEED(SocketID, ChannelID, Byte0Seed, Byte1Seed, Byte2Seed, Byte3Seed, Byte4Seed, Byte5Seed, + // Byte6Seed, Byte7Seed, ByteEccSeed) + // Specifies the write leveling seed for a channel of a socket. + // + + NUMBER_OF_DIMMS_SUPPORTED (ANY_SOCKET, ANY_CHANNEL, TWO_DIMM), + NUMBER_OF_CHANNELS_SUPPORTED (ANY_SOCKET, ONE_DIMM), + + // Gizmos soldered down memory uses memory CLK0 and CLK1 on CS0 + MEMCLK_DIS_MAP(ANY_SOCKET, ANY_CHANNEL, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + + // Gizmos soldered down memory requires different seeds + WRITE_LEVELING_SEED(ANY_SOCKET, ANY_CHANNEL, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08), + HW_RXEN_SEED( ANY_SOCKET, ANY_CHANNEL, 0x41, 0x43, 0x3E, 0x42, 0x45, 0x3F, 0x41, 0x47, 0x41), + + PSO_END +}; + +/* + * These tables are optional and may be used to adjust memory timing settings + */ +#include "mm.h" +#include "mn.h" + +//DA Customer table +CONST UINT8 AGESA_MEM_TABLE_ON[][sizeof (MEM_TABLE_ALIAS)] = +{ + // Hardcoded Memory Training Values + + // The following macro should be used to override training values for your platform + // + // DQSACCESS(MTAfterDqsRwPosTrn, MTNodes, MTDcts, MTDIMMs, BFRdDqsDly, MTOverride, 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20), + // + // NOTE: + // The following training hardcode values are example values that were taken from a tilapia motherboard + // with a particular DIMM configuration. To hardcode your own values, uncomment the appropriate line in + // the table and replace the byte lane values with your own. + // + // ------------------ BYTE LANES ---------------------- + // BL0 BL1 BL2 BL3 BL4 BL5 BL6 Bl7 ECC + // Write Data Timing + // DQSACCESS(MTAfterHwWLTrnP2, MTNode0, MTDct0, MTDIMM0, BFWrDatDly, MTOverride, 0x1D, 0x20, 0x26, 0x2B, 0x37, 0x3A, 0x3e, 0x3F, 0x30),// DCT0, DIMM0 + // DQSACCESS(MTAfterHwWLTrnP2, MTNode0, MTDct0, MTDIMM1, BFWrDatDly, MTOverride, 0x1D, 0x00, 0x06, 0x0B, 0x17, 0x1A, 0x1E, 0x1F, 0x10),// DCT0, DIMM1 + // DQSACCESS(MTAfterHwWLTrnP2, MTNode0, MTDct1, MTDIMM0, BFWrDatDly, MTOverride, 0x18, 0x1D, 0x27, 0x2B, 0x3B, 0x3B, 0x3E, 0x3E, 0x30),// DCT1, DIMM0 + // DQSACCESS(MTAfterHwWLTrnP2, MTNode0, MTDct1, MTDIMM1, BFWrDatDly, MTOverride, 0x18, 0x1D, 0x1C, 0x0B, 0x17, 0x1A, 0x1D, 0x1C, 0x10),// DCT1, DIMM1 + + // DQS Receiver Enable + // DQSACCESS(MTAfterSwRxEnTrn, MTNode0, MTDct0, MTDIMM0, BFRcvEnDly, MTOverride, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),// DCT0, DIMM0 + // DQSACCESS(MTAfterSwRxEnTrn, MTNode0, MTDct0, MTDIMM1, BFRcvEnDly, MTOverride, 0x7C, 0x7D, 0x7E, 0x81, 0x88, 0x8F, 0x96, 0x9F, 0x84),// DCT0, DIMM1 + // DQSACCESS(MTAfterSwRxEnTrn, MTNode0, MTDct1, MTDIMM0, BFRcvEnDly, MTOverride, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),// DCT1, DIMM0 + // DQSACCESS(MTAfterSwRxEnTrn, MTNode0, MTDct1, MTDIMM1, BFRcvEnDly, MTOverride, 0x1C, 0x1D, 0x1E, 0x01, 0x08, 0x0F, 0x16, 0x1F, 0x04),// DCT1, DIMM1 + + // Write DQS Delays + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct0, MTDIMM0, BFWrDqsDly, MTOverride, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),// DCT0, DIMM0 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct0, MTDIMM1, BFWrDqsDly, MTOverride, 0x06, 0x0D, 0x12, 0x1A, 0x25, 0x28, 0x2C, 0x2C, 0x44),// DCT0, DIMM1 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct1, MTDIMM0, BFWrDqsDly, MTOverride, 0x07, 0x0E, 0x14, 0x1B, 0x24, 0x29, 0x2B, 0x2C, 0x1F),// DCT1, DIMM0 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct1, MTDIMM1, BFWrDqsDly, MTOverride, 0x07, 0x0C, 0x14, 0x19, 0x25, 0x28, 0x2B, 0x2B, 0x1A),// DCT1, DIMM1 + + // Read DQS Delays + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct0, MTDIMM0, BFRdDqsDly, MTOverride, 0x10, 0x10, 0x0E, 0x10, 0x10, 0x10, 0x10, 0x0E, 0x10),// DCT0, DIMM0 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct0, MTDIMM1, BFRdDqsDly, MTOverride, 0x10, 0x10, 0x0E, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x10),// DCT0, DIMM1 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct1, MTDIMM0, BFRdDqsDly, MTOverride, 0x10, 0x10, 0x0E, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x10),// DCT1, DIMM0 + // DQSACCESS(MTAfterDqsRwPosTrn, MTNode0, MTDct1, MTDIMM1, BFRdDqsDly, MTOverride, 0x10, 0x10, 0x0E, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x10),// DCT1, DIMM1 + //-------------------------------------------------------------------------------------------------------------------------------------------------- + // TABLE END + NBACCESS (MTEnd, 0, 0, 0, 0, 0), // End of Table +}; +CONST UINT8 SizeOfTableON = sizeof (AGESA_MEM_TABLE_ON) / sizeof (AGESA_MEM_TABLE_ON[0]); + +/* *************************************************************************** + * Optional User code to be included into the AGESA build + * These may be 32-bit call-out routines... + */ +//AGESA_STATUS +//AgesaReadSpd ( +// IN UINTN FcnData, +// IN OUT AGESA_READ_SPD_PARAMS *ReadSpd +// ) +//{ +// /* platform code to read an SPD... */ +// return Status; +//} + + diff --git a/src/mainboard/gizmosphere/gizmo/chromeos.c b/src/mainboard/gizmosphere/gizmo/chromeos.c new file mode 100644 index 0000000000..5a4c21790d --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/chromeos.c @@ -0,0 +1,139 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +u32 acpi_mmio_base = 0; + +#define GPIO_BASE 0x100 +#define ACPI_BLK_BASE 0x800 +#define IOMUX_BASE 0xD00 + +/* Gizmo Explorer Board GPIOS: GPIO_A, B, C, D, E, F, O, P */ +static const u8 GPIOS[] = {64, 63, 60, 55, 59, 61, 43, 47}; + +#define GPIO_SPI_WP GPIOS[0] +#define GPIO_REC_MODE GPIOS[1] +#define GPIO_DEV_MODE GPIOS[2] + +static void gpio_configure(int mode, int function, int gpiox) +{ + u8 bdata; + + bdata = read8(acpi_mmio_base + GPIO_BASE + gpiox); + if (bdata & 0x01) + printk(BIOS_DEBUG,"ERROR: GPIO is owned by IMC!\n"); + bdata &= 0x07; + + /* mode: 1=GPIO_IN 0=GPIO_OUT */ + if (mode == 0) + bdata |= 0x08; + else + bdata |= 0x28; + + write8(acpi_mmio_base + GPIO_BASE + gpiox, bdata); + write8(acpi_mmio_base + IOMUX_BASE + gpiox, (u8)function); +} + +static void gpio_init(void) +{ + u8 pm_index; + /* Find the ACPImmioAddr base address */ + for (pm_index = 0x27; pm_index > 0x23; pm_index--) { + acpi_mmio_base = acpi_mmio_base << 8; + outb(pm_index, 0xCD6); + acpi_mmio_base |= (unsigned long int) inb(0xCD7); + } + acpi_mmio_base &= 0xFFFFF000; + + gpio_configure(1, 1, GPIO_SPI_WP); + gpio_configure(1, 1, GPIO_REC_MODE); + gpio_configure(1, 1, GPIO_DEV_MODE); +} + +static u8 gpio_read(int gpiox) +{ + if (!acpi_mmio_base) + gpio_init(); + + return !((read8(acpi_mmio_base + GPIO_BASE + gpiox) & 0x80) >> 7); +} + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + /* Write Protect: GPIO64 = CHP3_SPI_WP */ + gpios->gpios[0].port = GPIO_SPI_WP; + gpios->gpios[0].polarity = ACTIVE_HIGH; + gpios->gpios[0].value = gpio_read(GPIO_SPI_WP); + strncpy((char *)gpios->gpios[0].name,"write protect", + GPIO_MAX_NAME_LENGTH); + + /* Recovery: GPIO63 = CHP3_REC_MODE# */ + gpios->gpios[1].port = GPIO_REC_MODE; + gpios->gpios[1].polarity = ACTIVE_HIGH; + gpios->gpios[1].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[1].name,"recovery", GPIO_MAX_NAME_LENGTH); + + /* Developer: GPIO60 = KBC3_DVP_MODE */ + gpios->gpios[2].port = GPIO_DEV_MODE; + gpios->gpios[2].polarity = ACTIVE_HIGH; + gpios->gpios[2].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[2].name,"developer", GPIO_MAX_NAME_LENGTH); + + /* Hard code the lid switch GPIO to open. */ + gpios->gpios[3].port = 100; + gpios->gpios[3].polarity = ACTIVE_HIGH; + gpios->gpios[3].value = 1; + strncpy((char *)gpios->gpios[3].name,"lid", GPIO_MAX_NAME_LENGTH); + + /* Power Button */ + gpios->gpios[4].port = 101; + gpios->gpios[4].polarity = ACTIVE_HIGH; + gpios->gpios[4].value = (read32(acpi_mmio_base + ACPI_BLK_BASE) >> + 8) & 1; + strncpy((char *)gpios->gpios[4].name,"power", GPIO_MAX_NAME_LENGTH); + + /* Did we load the VGA Option ROM? */ + gpios->gpios[5].port = -1; /* Indicate that this is a pseudo GPIO */ + gpios->gpios[5].polarity = ACTIVE_HIGH; + gpios->gpios[5].value = oprom_is_loaded; + strncpy((char *)gpios->gpios[5].name,"oprom", GPIO_MAX_NAME_LENGTH); +} +#endif + +int get_developer_mode_switch(void) +{ + return gpio_read(GPIO_DEV_MODE); +} + +int get_recovery_mode_switch(void) +{ + return gpio_read(GPIO_REC_MODE); +} diff --git a/src/mainboard/gizmosphere/gizmo/cmos.layout b/src/mainboard/gizmosphere/gizmo/cmos.layout new file mode 100755 index 0000000000..95ce3b50db --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/cmos.layout @@ -0,0 +1,118 @@ +#***************************************************************************** +# +# This file is part of the coreboot project. +# +# Copyright (C) 2011 Advanced Micro Devices, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#***************************************************************************** + +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +#96 288 r 0 temporary_filler +0 384 r 0 reserved_memory +384 1 e 4 boot_option +385 1 e 4 last_boot +386 1 e 1 ECC_memory +388 4 r 0 reboot_bits +392 3 e 5 baud_rate +395 1 e 1 hw_scrubber +396 1 e 1 interleave_chip_selects +397 2 e 8 max_mem_clock +399 1 e 2 multi_core +400 1 e 1 power_on_after_fail +412 4 e 6 debug_level +416 4 e 7 boot_first +420 4 e 7 boot_second +424 4 e 7 boot_third +428 4 h 0 boot_index +432 8 h 0 boot_countdown +440 4 e 9 slow_cpu +444 1 e 1 nmi +445 1 e 1 iommu +728 256 h 0 user_data +984 16 h 0 check_sum +# Reserve the extended AMD configuration registers +1000 24 r 0 amd_reserved + + + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Network +7 1 HDD +7 2 Floppy +7 8 Fallback_Network +7 9 Fallback_HDD +7 10 Fallback_Floppy +#7 3 ROM +8 0 400Mhz +8 1 333Mhz +8 2 266Mhz +8 3 200Mhz +9 0 off +9 1 87.5% +9 2 75.0% +9 3 62.5% +9 4 50.0% +9 5 37.5% +9 6 25.0% +9 7 12.5% + +checksums + +checksum 392 983 984 + + diff --git a/src/mainboard/gizmosphere/gizmo/ddr3_spd.h b/src/mainboard/gizmosphere/gizmo/ddr3_spd.h new file mode 100644 index 0000000000..585314835d --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/ddr3_spd.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +CONST UINT8 ddr3_fake_spd[256] = +{ +// Elpida 2Gb - 128M x 16 bits +// These are the memory chips that were used on Gizmo +// TODO: expand it like the other detailed SPD tables + + // SPD contents for 1GB DDR3 + // 0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF + //============================================================================================= + 0x11, 0x10, 0x0b, 0x03, 0x03, 0x11, 0x00, 0x02, 0x03, 0x52, 0x01, 0x08, 0x0c, 0x00, 0xfc, 0x00, + 0x69, 0x78, 0x69, 0x38, 0x69, 0x11, 0x20, 0x89, 0x00, 0x05, 0x3c, 0x3c, 0x01, 0x68, 0x83, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x04, 0x53, 0x61, 0x67, 0x65, 0x00, 0x00 +}; diff --git a/src/mainboard/gizmosphere/gizmo/devicetree.cb b/src/mainboard/gizmosphere/gizmo/devicetree.cb new file mode 100755 index 0000000000..f0dc5a0038 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/devicetree.cb @@ -0,0 +1,68 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2011 Advanced Micro Devices, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +chip northbridge/amd/agesa/family14/root_complex + device cpu_cluster 0 on + chip cpu/amd/agesa/family14 + device lapic 0 on end + end + end + device domain 0 on + subsystemid 0x1022 0x1510 inherit + chip northbridge/amd/agesa/family14 # CPU side of HT root complex + chip northbridge/amd/agesa/family14 # PCI side of HT root complex + device pci 0.0 on end # Root Complex + device pci 1.0 on end # Internal Graphics P2P bridge 0x9804 + device pci 4.0 off end # PCIE P2P bridge 0x9604 + device pci 5.0 on end # PCIE P2P bridge 0x9605 + device pci 6.0 off end # PCIE P2P bridge 0x9606 + device pci 7.0 off end # PCIE P2P bridge 0x9607 + device pci 8.0 off end # NB/SB Link P2P bridge + end # agesa northbridge + + chip southbridge/amd/cimx/sb800 # it is under NB/SB Link, but on the same pri bus + device pci 11.0 on end # SATA + device pci 12.0 on end # USB + device pci 12.1 on end # USB + device pci 12.2 on end # USB + device pci 13.0 on end # USB + device pci 13.1 on end # USB + device pci 13.2 on end # USB + device pci 14.0 on end # SM + device pci 14.1 on end # IDE 0x439c + device pci 14.2 on end # HDA 0x4383 + device pci 14.3 on end # LPC 0x439d + device pci 14.4 on end # PCIB 0x4384, NOTE: this device must always be enabled or removed + device pci 14.5 off end # USB 2 + device pci 15.0 on end # PCIe PortA # PCIe x4 slot off of high speed edge connector + device pci 16.0 off end # OHCI USB3 + device pci 16.2 off end # EHCI USB3 + register "gpp_configuration" = "0" #4:0:0:0 + register "boot_switch_sata_ide" = "0" # 0: boot from SATA. 1: IDE + end #southbridge/amd/cimx/sb800 + device pci 18.0 on end + device pci 18.1 on end + device pci 18.2 on end + device pci 18.3 on end + device pci 18.4 on end + device pci 18.5 on end + device pci 18.6 on end + device pci 18.7 on end + end #chip northbridge/amd/agesa/family14 # CPU side of HT root complex + end #domain +end #northbridge/amd/agesa/family14/root_complex diff --git a/src/mainboard/gizmosphere/gizmo/dsdt.asl b/src/mainboard/gizmosphere/gizmo/dsdt.asl new file mode 100755 index 0000000000..970d1cbfb6 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/dsdt.asl @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* DefinitionBlock Statement */ +DefinitionBlock ( + "DSDT.AML", /* Output filename */ + "DSDT", /* Signature */ + 0x02, /* DSDT Revision, needs to be 2 for 64bit */ + "GIZSPH", /* OEMID */ + "COREBOOT", /* TABLE ID */ + 0x00010001 /* OEM Revision */ + ) +{ /* Start of ASL file */ + /* #include */ /* Include global debug methods if needed */ + + #include "acpi/mainboard.asl" + + #include + + #include "acpi/routing.asl" + + Scope(\_SB) { + /* global utility methods expected within the \_SB scope */ + #include + + Device(PCI0) { + + /* Describe the AMD Northbridge */ + #include + + /* Describe the AMD Fusion Controller Hub Southbridge */ + #include + + } + } /* End Scope(_SB) */ + + /* Contains the supported sleep states for this chipset */ + #include + + /* Contains the Sleep methods (WAK, PTS, GTS, etc.) */ + #include "acpi/sleep.asl" + + #include "acpi/gpe.asl" + #include + #include "acpi/thermal.asl" +} +/* End of ASL file */ diff --git a/src/mainboard/gizmosphere/gizmo/get_bus_conf.c b/src/mainboard/gizmosphere/gizmo/get_bus_conf.c new file mode 100755 index 0000000000..11ec26e16e --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/get_bus_conf.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "agesawrapper.h" +#if CONFIG_AMD_SB_CIMX +#include +#endif + + +/* Global variables for MB layouts and these will be shared by irqtable mptable +* and acpi_tables busnum is default. +*/ +u8 bus_isa; +u8 bus_sb800[3]; +u32 apicid_sb800; + +/* +* Here you only need to set value in pci1234 for HT-IO that could be installed or not +* You may need to preset pci1234 for HTIO board, +* please refer to src/northbridge/amd/amdk8/get_sblk_pci1234.c for detail +*/ +u32 pci1234x[] = { + 0x0000ff0, +}; + +u32 bus_type[256]; +u32 sbdn_sb800; + +static u32 get_bus_conf_done = 0; + +#if CONFIG_HAVE_ACPI_RESUME +extern u8 acpi_slp_type; +#endif + +void get_bus_conf(void) +{ + u32 apicid_base; + u32 status; + + device_t dev; + int i, j; + + if (get_bus_conf_done == 1) + return; /* do it only once */ + + get_bus_conf_done = 1; + +/* + * This is the call to AmdInitLate. It is really in the wrong place, conceptually, + * but functionally within the coreboot model, this is the best place to make the + * call. The logically correct place to call AmdInitLate is after PCI scan is done, + * after the decision about S3 resume is made, and before the system tables are + * written into RAM. The routine that is responsible for writing the tables is + * "write_tables", called near the end of "hardwaremain". There is no platform + * specific entry point between the S3 resume decision point and the call to + * "write_tables", and the next platform specific entry points are the calls to + * the ACPI table write functions. The first of ose would seem to be the right + * place, but other table write functions, e.g. the PIRQ table write function, are + * called before the ACPI tables are written. This routine is called at the beginning + * of each of the write functions called prior to the ACPI write functions, so this + * becomes the best place for this call. + */ +#if CONFIG_HAVE_ACPI_RESUME + if (acpi_slp_type != 3) { + status = agesawrapper_amdinitlate(); + if(status) + printk(BIOS_DEBUG, "agesawrapper_amdinitlate failed: %x \n", status); + status = agesawrapper_amdS3Save(); + if(status) + printk(BIOS_DEBUG, "agesawrapper_amds3save failed: %x \n", status); + } +#else + status = agesawrapper_amdinitlate(); + if(status) + printk(BIOS_DEBUG, "agesawrapper_amdinitlate failed: %x \n", status); +#endif + sbdn_sb800 = 0; + + for (i = 0; i < 3; i++) { + bus_sb800[i] = 0; + } + + for (i = 0; i < 256; i++) { + bus_type[i] = 0; /* default ISA bus. */ + } + + bus_type[0] = 1; /* pci */ + +// bus_sb800[0] = (sysconf.pci1234[0] >> 16) & 0xff; + bus_sb800[0] = (pci1234x[0] >> 16) & 0xff; + + /* sb800 */ + dev = dev_find_slot(bus_sb800[0], PCI_DEVFN(sbdn_sb800 + 0x14, 4)); + + if (dev) { + bus_sb800[1] = pci_read_config8(dev, PCI_SECONDARY_BUS); + + bus_isa = pci_read_config8(dev, PCI_SUBORDINATE_BUS); + bus_isa++; + for (j = bus_sb800[1]; j < bus_isa; j++) + bus_type[j] = 1; + } + + for (i = 0; i < 4; i++) { + dev = dev_find_slot(bus_sb800[0], PCI_DEVFN(sbdn_sb800 + 0x14, i)); + if (dev) { + bus_sb800[2 + i] = pci_read_config8(dev, PCI_SECONDARY_BUS); + bus_isa = pci_read_config8(dev, PCI_SUBORDINATE_BUS); + bus_isa++; + } + } + + for (j = bus_sb800[2]; j < bus_isa; j++) + bus_type[j] = 1; + + + /* I/O APICs: APIC ID Version State Address */ + bus_isa = 10; + apicid_base = CONFIG_MAX_CPUS; + apicid_sb800 = apicid_base; + +#if CONFIG_AMD_SB_CIMX + sb_Late_Post(); +#endif +} diff --git a/src/mainboard/gizmosphere/gizmo/irq_tables.c b/src/mainboard/gizmosphere/gizmo/irq_tables.c new file mode 100755 index 0000000000..5323d446ef --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/irq_tables.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include + + +static void write_pirq_info(struct irq_info *pirq_info, u8 bus, u8 devfn, + u8 link0, u16 bitmap0, u8 link1, u16 bitmap1, + u8 link2, u16 bitmap2, u8 link3, u16 bitmap3, + u8 slot, u8 rfu) +{ + pirq_info->bus = bus; + pirq_info->devfn = devfn; + pirq_info->irq[0].link = link0; + pirq_info->irq[0].bitmap = bitmap0; + pirq_info->irq[1].link = link1; + pirq_info->irq[1].bitmap = bitmap1; + pirq_info->irq[2].link = link2; + pirq_info->irq[2].bitmap = bitmap2; + pirq_info->irq[3].link = link3; + pirq_info->irq[3].bitmap = bitmap3; + pirq_info->slot = slot; + pirq_info->rfu = rfu; +} +extern u8 bus_isa; +extern u8 bus_sb800[2]; +extern unsigned long sbdn_sb800; + +unsigned long write_pirq_routing_table(unsigned long addr) +{ + + struct irq_routing_table *pirq; + struct irq_info *pirq_info; + u32 slot_num; + u8 *v; + + u8 sum = 0; + int i; + + + get_bus_conf(); /* it will find out all bus num and apic that share with mptable.c and mptable.c and acpi_tables.c */ + + + /* Align the table to be 16 byte aligned. */ + addr += 15; + addr &= ~15; + + /* This table must be betweeen 0xf0000 & 0x100000 */ + printk(BIOS_INFO, "Writing IRQ routing tables to 0x%lx...", addr); + + pirq = (void *)(addr); + v = (u8 *) (addr); + + pirq->signature = PIRQ_SIGNATURE; + pirq->version = PIRQ_VERSION; + + pirq->rtr_bus = bus_sb800[0]; + pirq->rtr_devfn = ((sbdn_sb800 + 0x14) << 3) | 4; + + pirq->exclusive_irqs = 0; + + pirq->rtr_vendor = 0x1002; + pirq->rtr_device = 0x4384; + + pirq->miniport_data = 0; + + memset(pirq->rfu, 0, sizeof(pirq->rfu)); + + pirq_info = (void *)(&pirq->checksum + 1); + slot_num = 0; + + + /* pci bridge */ + write_pirq_info(pirq_info, bus_sb800[0], ((sbdn_sb800 + 0x14) << 3) | 4, + 0x1, 0xdef8, 0x2, 0xdef8, 0x3, 0xdef8, 0x4, 0xdef8, 0, + 0); + pirq_info++; + + + + slot_num++; + + + + pirq->size = 32 + 16 * slot_num; + + for (i = 0; i < pirq->size; i++) + sum += v[i]; + + sum = pirq->checksum - sum; + + if (sum != pirq->checksum) { + pirq->checksum = sum; + } + + printk(BIOS_INFO, "write_pirq_routing_table done.\n"); + + return (unsigned long)pirq_info; + +} diff --git a/src/mainboard/gizmosphere/gizmo/mainboard.c b/src/mainboard/gizmosphere/gizmo/mainboard.c new file mode 100755 index 0000000000..be8c289eeb --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/mainboard.c @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "BiosCallOuts.h" +#include +#include +#include "SBPLATFORM.h" + +void set_pcie_reset(void); +void set_pcie_dereset(void); + +/** + * TODO + * SB CIMx callback + */ +void set_pcie_reset(void) +{ +} + +/** + * TODO + * mainboard specific SB CIMx callback + */ +void set_pcie_dereset(void) +{ +} + + +/********************************************** + * Enable the dedicated functions of the board. + **********************************************/ +static void mainboard_enable(device_t dev) +{ + printk(BIOS_INFO, "Mainboard " CONFIG_MAINBOARD_PART_NUMBER " Enable.\n"); + +/* + * The mainboard is the first place that we get control in ramstage. Check + * for S3 resume and call the approriate AGESA/CIMx resume functions. + */ +#if CONFIG_HAVE_ACPI_RESUME + acpi_slp_type = acpi_get_sleep_type(); +#endif + + /* enable GPP CLK0 thru CLK1 */ + /* disable GPP CLK2 thru SLT_GFX_CLK */ + u8 *misc_mem_clk_cntrl = (u8 *)(ACPI_MMIO_BASE + MISC_BASE); + *(misc_mem_clk_cntrl + 0) = 0xFF; + *(misc_mem_clk_cntrl + 1) = 0x00; + *(misc_mem_clk_cntrl + 2) = 0x00; + *(misc_mem_clk_cntrl + 3) = 0x00; + *(misc_mem_clk_cntrl + 4) = 0x00; + + /* force the SATA port to GEN2 speeds */ + RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint8, 0xFB, 0x04); + + /* Reserve memory for VGA ROM and ACPI RSDP table so + * that Depthcharge does not wipe them away */ + reserved_ram_resource(dev, 0, 0xc0000 / KiB, 0x40000 / KiB); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/gizmosphere/gizmo/mptable.c b/src/mainboard/gizmosphere/gizmo/mptable.c new file mode 100755 index 0000000000..fd0305887c --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/mptable.c @@ -0,0 +1,160 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +extern u8 bus_sb800[2]; + +extern u32 apicid_sb800; + +extern u32 bus_type[256]; +extern u32 sbdn_sb800; + +u8 intr_data[] = { + [0x00] = 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, /* INTA# - INTH# */ + [0x08] = 0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F, /* Misc-nil,0,1,2, INT from Serial irq */ + [0x10] = 0x09,0x1F,0x1F,0x10,0x1F,0x12,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x11,0x12,0x11,0x12,0x11,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x11,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x10,0x11,0x12,0x13 +}; + +static void *smp_write_config_table(void *v) +{ + struct mp_config_table *mc; + int bus_isa; + + mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); + + mptable_init(mc, LOCAL_APIC_ADDR); + memcpy(mc->mpc_oem, "AMD ", 8); + + smp_write_processors(mc); + + get_bus_conf(); + + mptable_write_buses(mc, NULL, &bus_isa); + + /* I/O APICs: APIC ID Version State Address */ + + u32 dword; + u8 byte; + + ReadPMIO(SB_PMIOA_REG34, AccWidthUint32, &dword); + dword &= 0xFFFFFFF0; + smp_write_ioapic(mc, apicid_sb800, 0x21, dword); + + for (byte = 0x0; byte < sizeof(intr_data); byte ++) { + outb(byte | 0x80, 0xC00); + outb(intr_data[byte], 0xC01); + } + + /* I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */ +#define IO_LOCAL_INT(type, intr, apicid, pin) \ + smp_write_lintsrc(mc, (type), MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, (intr), (apicid), (pin)); + + mptable_add_isa_interrupts(mc, bus_isa, apicid_sb800, 0); + + /* PCI interrupts are level triggered, and are + * associated with a specific bus/device/function tuple. + */ +#if !CONFIG_GENERATE_ACPI_TABLES +#define PCI_INT(bus, dev, fn, pin) \ + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, (bus), (((dev)<<2)|(fn)), apicid_sb800, (pin)) +#else +#define PCI_INT(bus, dev, fn, pin) +#endif + + /* APU Internal Graphic Device*/ + PCI_INT(0x0, 0x01, 0x0, intr_data[0x02]); + PCI_INT(0x0, 0x01, 0x1, intr_data[0x03]); + + //PCI_INT(0x0, 0x14, 0x1, 0x11); /* IDE. */ + PCI_INT(0x0, 0x14, 0x0, 0x10); + /* Southbridge HD Audio: */ + PCI_INT(0x0, 0x14, 0x2, 0x12); + + PCI_INT(0x0, 0x12, 0x0, intr_data[0x30]); /* USB */ + PCI_INT(0x0, 0x12, 0x1, intr_data[0x31]); + PCI_INT(0x0, 0x13, 0x0, intr_data[0x32]); + PCI_INT(0x0, 0x13, 0x1, intr_data[0x33]); + PCI_INT(0x0, 0x16, 0x0, intr_data[0x34]); + PCI_INT(0x0, 0x16, 0x1, intr_data[0x35]); + + /* sata */ + PCI_INT(0x0, 0x11, 0x0, intr_data[0x41]); + + /* on board NIC & Slot PCIE. */ + + /* PCI slots */ + /* PCI_SLOT 0. */ + PCI_INT(bus_sb800[1], 0x5, 0x0, 0x14); + PCI_INT(bus_sb800[1], 0x5, 0x1, 0x15); + PCI_INT(bus_sb800[1], 0x5, 0x2, 0x16); + PCI_INT(bus_sb800[1], 0x5, 0x3, 0x17); + + /* PCI_SLOT 1. */ + PCI_INT(bus_sb800[1], 0x6, 0x0, 0x15); + PCI_INT(bus_sb800[1], 0x6, 0x1, 0x16); + PCI_INT(bus_sb800[1], 0x6, 0x2, 0x17); + PCI_INT(bus_sb800[1], 0x6, 0x3, 0x14); + + /* PCI_SLOT 2. */ + PCI_INT(bus_sb800[1], 0x7, 0x0, 0x16); + PCI_INT(bus_sb800[1], 0x7, 0x1, 0x17); + PCI_INT(bus_sb800[1], 0x7, 0x2, 0x14); + PCI_INT(bus_sb800[1], 0x7, 0x3, 0x15); + + PCI_INT(bus_sb800[2], 0x0, 0x0, 0x12); + PCI_INT(bus_sb800[2], 0x0, 0x1, 0x13); + PCI_INT(bus_sb800[2], 0x0, 0x2, 0x14); + + /* PCIe PortA */ + PCI_INT(0x0, 0x15, 0x0, 0x10); + /* PCIe PortB */ + PCI_INT(0x0, 0x15, 0x1, 0x11); + /* PCIe PortC */ + PCI_INT(0x0, 0x15, 0x2, 0x12); + /* PCIe PortD */ + PCI_INT(0x0, 0x15, 0x3, 0x13); + + /*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */ + IO_LOCAL_INT(mp_ExtINT, 0x0, MP_APIC_ALL, 0x0); + IO_LOCAL_INT(mp_NMI, 0x0, MP_APIC_ALL, 0x1); + /* There is no extension information... */ + + /* Compute the checksums */ + return mptable_finalize(mc); +} + +unsigned long write_smp_table(unsigned long addr) +{ + void *v; + v = smp_write_floating_table(addr, 0); + return (unsigned long)smp_write_config_table(v); +} diff --git a/src/mainboard/gizmosphere/gizmo/platform_cfg.h b/src/mainboard/gizmosphere/gizmo/platform_cfg.h new file mode 100755 index 0000000000..64d68dbe2f --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/platform_cfg.h @@ -0,0 +1,278 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef _PLATFORM_CFG_H_ +#define _PLATFORM_CFG_H_ + +/* Gizmo has no legacy P/S2 controller */ +#define LEGACY_FREE 1 + +/** + * @def BIOS_SIZE_1M + * @def BIOS_SIZE_2M + * @def BIOS_SIZE_4M + * @def BIOS_SIZE_8M + */ +#define BIOS_SIZE_1M 0 +#define BIOS_SIZE_2M 1 +#define BIOS_SIZE_4M 3 +#define BIOS_SIZE_8M 7 + +/* In SB800, default ROM size is 1M Bytes, if your platform ROM + * bigger than 1M you have to set the ROM size outside CIMx module and + * before AGESA module get call. + */ +#ifndef BIOS_SIZE +#if CONFIG_COREBOOT_ROMSIZE_KB_1024 + #define BIOS_SIZE BIOS_SIZE_1M +#elif CONFIG_COREBOOT_ROMSIZE_KB_2048 == 1 + #define BIOS_SIZE BIOS_SIZE_2M +#elif CONFIG_COREBOOT_ROMSIZE_KB_4096 == 1 + #define BIOS_SIZE BIOS_SIZE_4M +#elif CONFIG_COREBOOT_ROMSIZE_KB_8192 == 1 + #define BIOS_SIZE BIOS_SIZE_8M +#endif +#endif + +/** + * @def SPREAD_SPECTRUM + * @brief + * 0 - Disable Spread Spectrum function + * 1 - Enable Spread Spectrum function + */ +#define SPREAD_SPECTRUM 0 + +/** + * @def SB_HPET_TIMER + * @brief + * 0 - Disable hpet + * 1 - Enable hpet + */ +#define HPET_TIMER 1 + +/** + * @def USB_CONFIG + * @brief bit[0-6] used to control USB + * 0 - Disable + * 1 - Enable + * Usb Ohci1 Contoller (Bus 0 Dev 18 Func0) is define at BIT0 + * Usb Ehci1 Contoller (Bus 0 Dev 18 Func2) is define at BIT1 + * Usb Ohci2 Contoller (Bus 0 Dev 19 Func0) is define at BIT2 + * Usb Ehci2 Contoller (Bus 0 Dev 19 Func2) is define at BIT3 + * Usb Ohci3 Contoller (Bus 0 Dev 22 Func0) is define at BIT4 + * Usb Ehci3 Contoller (Bus 0 Dev 22 Func2) is define at BIT5 + * Usb Ohci4 Contoller (Bus 0 Dev 20 Func5) is define at BIT6 + */ +#define USB_CONFIG 0x7F + +/** + * @def PCI_CLOCK_CTRL + * @brief bit[0-4] used for PCI Slots Clock Control, + * 0 - disable + * 1 - enable + * PCI SLOT 0 define at BIT0 + * PCI SLOT 1 define at BIT1 + * PCI SLOT 2 define at BIT2 + * PCI SLOT 3 define at BIT3 + * PCI SLOT 4 define at BIT4 + */ +#define PCI_CLOCK_CTRL 0x00 /* PCI clocks aren't used on Gizmo */ + +/** + * @def SATA_CONTROLLER + * @brief INCHIP Sata Controller + */ +#define SATA_CONTROLLER CIMX_OPTION_ENABLED + +/** + * @def SATA_MODE + * @brief INCHIP Sata Controller Mode + * NOTE: DO NOT ALLOW SATA & IDE use same mode + */ +#define SATA_MODE CONFIG_SB800_SATA_MODE + +/** + * @brief INCHIP Sata IDE Controller Mode + */ +#define IDE_LEGACY_MODE 0 +#define IDE_NATIVE_MODE 1 + +/** + * @def SATA_IDE_MODE + * @brief INCHIP Sata IDE Controller Mode + * NOTE: DO NOT ALLOW SATA & IDE use same mode + */ +#define SATA_IDE_MODE IDE_LEGACY_MODE + +/** + * @def EXTERNAL_CLOCK + * @brief 00/10: Reference clock from crystal oscillator via + * PAD_XTALI and PAD_XTALO + * + * @def INTERNAL_CLOCK + * @brief 01/11: Reference clock from internal clock through + * CP_PLL_REFCLK_P and CP_PLL_REFCLK_N via RDL + */ +#define EXTERNAL_CLOCK 0x00 +#define INTERNAL_CLOCK 0x01 + +/* NOTE: inagua have to using internal clock, + * otherwise can not detect sata drive + */ +#define SATA_CLOCK_SOURCE INTERNAL_CLOCK + +/** + * @def SATA_PORT_MULT_CAP_RESERVED + * @brief 1 ON, 0 0FF + */ +#define SATA_PORT_MULT_CAP_RESERVED 1 + + +/** + * @def AZALIA_AUTO + * @brief Detect Azalia controller automatically. + * + * @def AZALIA_DISABLE + * @brief Disable Azalia controller. + + * @def AZALIA_ENABLE + * @brief Enable Azalia controller. + */ +#define AZALIA_AUTO 0 +#define AZALIA_DISABLE 1 +#define AZALIA_ENABLE 2 + +/** + * @brief INCHIP HDA controller + */ +#define AZALIA_CONTROLLER AZALIA_AUTO + +/** + * @def AZALIA_PIN_CONFIG + * @brief + * 0 - disable + * 1 - enable + */ +#define AZALIA_PIN_CONFIG 1 + +/** + * @def AZALIA_SDIN_PIN + * @brief + * SDIN0 is define at BIT0 & BIT1 + * 00 - GPIO PIN + * 01 - Reserved + * 10 - As a Azalia SDIN pin + * SDIN1 is define at BIT2 & BIT3 + * SDIN2 is define at BIT4 & BIT5 + * SDIN3 is define at BIT6 & BIT7 + */ +//#define AZALIA_SDIN_PIN 0xAA +#define AZALIA_SDIN_PIN 0x2A + +/** + * @def GPP_CONTROLLER + */ +#define GPP_CONTROLLER CIMX_OPTION_ENABLED + +/** + * @def GPP_CFGMODE + * @brief GPP Link Configuration + * four possible configuration: + * GPP_CFGMODE_X4000 + * GPP_CFGMODE_X2200 + * GPP_CFGMODE_X2110 + * GPP_CFGMODE_X1111 + */ +#define GPP_CFGMODE GPP_CFGMODE_X4000 + +/** + * @def NB_SB_GEN2 + * 0 - Disable + * 1 - Enable + */ +#define NB_SB_GEN2 TRUE + +/** + * @def SB_GEN2 + * 0 - Disable + * 1 - Enable + */ +#define SB_GPP_GEN2 TRUE + +/** + * @def SB_GPP_UNHIDE_PORTS + * TRUE - ports visable always, even port empty + * FALSE - ports invisable if port empty + */ +#define SB_GPP_UNHIDE_PORTS TRUE + +/** + * @def GEC_CONFIG + * 0 - Enable + * 1 - Disable + */ +#define GEC_CONFIG 0 + +const static CODECENTRY gizmo_codec_alc272[] = +{ + /* NID, PinConfig */ + {0x11, 0x411111F0}, /* S/PDIF-OUT2 unused */ + {0x12, 0x411111F0}, /* DMIC-1/2 unused */ + {0x13, 0x411111F0}, /* DMIC-3/4 unused */ + {0x14, 0x411111F0}, /* LOUT-1 unused */ + {0x15, 0x21000100}, /* LOUT2 - to Explorer */ + {0x17, 0x411111F0}, /* MONO-OUT unused */ + {0x18, 0x01A15010}, /* MIC1 */ + {0x19, 0x411111F0}, /* MIC2 unused */ + {0x1A, 0x01013010}, /* LINE1 */ + {0x1B, 0x21800101}, /* LINE2 from Explorer */ + {0x1D, 0x40100000}, /* PCBEEP */ + {0x1E, 0x411111F0}, /* S/PDIF-OUT1 unused */ + {0x21, 0x01214010}, /* HPOUT */ + {0xff, 0xffffffff} /* end of table */ +}; + +static const CODECTBLLIST codec_tablelist[] = +{ + {0x010ec0272, (CODECENTRY*)&gizmo_codec_alc272[0]}, + {0x0FFFFFFFFUL, (CODECENTRY*)0x0FFFFFFFFUL} +}; + +/** + * @def AZALIA_OEM_VERB_TABLE + * Mainboard specific codec verb table list + */ +#define AZALIA_OEM_VERB_TABLE (&codec_tablelist[0]) + +/* set up an ACPI prefered power management profile */ +/* from acpi.h + * PM_UNSPECIFIED = 0, + * PM_DESKTOP = 1, + * PM_MOBILE = 2, + * PM_WORKSTATION = 3, + * PM_ENTERPRISE_SERVER = 4, + * PM_SOHO_SERVER = 5, + * PM_APPLIANCE_PC = 6, + * PM_PERFORMANCE_SERVER = 7, + * PM_TABLET = 8 + */ +#define FADT_PM_PROFILE 1 + +#endif diff --git a/src/mainboard/gizmosphere/gizmo/romstage.c b/src/mainboard/gizmosphere/gizmo/romstage.c new file mode 100755 index 0000000000..924ea7ebf5 --- /dev/null +++ b/src/mainboard/gizmosphere/gizmo/romstage.c @@ -0,0 +1,188 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "agesawrapper.h" +#include "cpu/x86/bist.h" +#include "cpu/x86/lapic.h" +#include "drivers/pc80/i8254.c" +#include "drivers/pc80/i8259.c" +#include +#include +#include "SBPLATFORM.h" +#include "cbmem.h" +#include "cpu/amd/mtrr.h" +#include "cpu/amd/agesa/s3_resume.h" +#include "cpu/x86/lapic/boot_cpu.c" + +void disable_cache_as_ram(void); /* cache_as_ram.inc */ +void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx); + +void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) +{ + u32 val; + +#if CONFIG_HAVE_ACPI_RESUME + void *resume_backup_memory; +#endif + + + /* + * All cores: allow caching of flash chip code and data + * (there are no cache-as-ram reliability concerns with family 14h) + */ + __writemsr (0x20c, (0x0100000000ull - CONFIG_ROM_SIZE) | 5); + __writemsr (0x20d, (0x1000000000ull - CONFIG_ROM_SIZE) | 0x800); + + /* All cores: set pstate 0 (1600 MHz) early to save a few ms of boot time */ + __writemsr (0xc0010062, 0); + + if (!cpu_init_detectedx && boot_cpu()) { + post_code(0x30); + sb_Poweron_Init(); + + post_code(0x31); + + console_init(); + } + + + /* Halt if there was a built in self test failure */ + post_code(0x34); + report_bist_failure(bist); + + /* Load MPB */ + val = cpuid_eax(1); + printk(BIOS_DEBUG, "BSP Family_Model: %08x \n", val); + printk(BIOS_DEBUG, "cpu_init_detectedx = %08lx \n", cpu_init_detectedx); + + post_code(0x35); + printk(BIOS_DEBUG, "agesawrapper_amdinitmmio "); + val = agesawrapper_amdinitmmio(); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + + post_code(0x37); + printk(BIOS_DEBUG, "agesawrapper_amdinitreset "); + val = agesawrapper_amdinitreset(); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + post_code(0x39); + printk(BIOS_DEBUG, "agesawrapper_amdinitearly "); + val = agesawrapper_amdinitearly (); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + +#if CONFIG_HAVE_ACPI_RESUME + if (!acpi_is_wakeup_early()) { /* Check for S3 resume */ +#endif + post_code(0x40); + printk(BIOS_DEBUG, "agesawrapper_amdinitpost "); + val = agesawrapper_amdinitpost (); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + post_code(0x42); + printk(BIOS_DEBUG, "agesawrapper_amdinitenv "); + val = agesawrapper_amdinitenv (); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + +#if CONFIG_HAVE_ACPI_RESUME + } else { /* S3 detect */ + printk(BIOS_INFO, "S3 detected\n"); + + post_code(0x60); + printk(BIOS_DEBUG, "agesawrapper_amdinitresume "); + val = agesawrapper_amdinitresume(); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + printk(BIOS_DEBUG, "agesawrapper_amds3laterestore "); + val = agesawrapper_amds3laterestore (); + if (val) + printk(BIOS_DEBUG, "error level: %x \n", val); + else + printk(BIOS_DEBUG, "passed.\n"); + + post_code(0x61); + printk(BIOS_DEBUG, "Find resume memory location\n"); + resume_backup_memory = backup_resume(); + + post_code(0x62); + printk(BIOS_DEBUG, "Move CAR stack.\n"); + move_stack_high_mem(); + printk(BIOS_DEBUG, "stack moved to: 0x%x\n", (u32) (resume_backup_memory + HIGH_MEMORY_SAVE)); + + post_code(0x63); + disable_cache_as_ram(); + printk(BIOS_DEBUG, "CAR disabled.\n"); + set_resume_cache(); + + /* + * Copy the system memory that is in the ramstage area to the + * reserved area. + */ + if (resume_backup_memory) + memcpy(resume_backup_memory, (void *)(CONFIG_RAMBASE), HIGH_MEMORY_SAVE); + + printk(BIOS_DEBUG, "System memory saved. OK to load ramstage.\n"); + } +#endif + + /* Initialize i8259 pic */ + post_code(0x43); + setup_i8259 (); + + /* Initialize i8254 timers */ + post_code(0x44); + setup_i8254 (); + + + post_code(0x50); + copy_and_run(); + printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); + + post_code(0x54); /* Should never see this post code. */ +} diff --git a/src/mainboard/google/Kconfig b/src/mainboard/google/Kconfig index e389b597d4..9dc8168f44 100644 --- a/src/mainboard/google/Kconfig +++ b/src/mainboard/google/Kconfig @@ -26,27 +26,368 @@ config VENDOR_SPECIFIC_OPTIONS choice prompt "Mainboard model" +config BOARD_GOOGLE_AURON + bool "Auron" + help + Google Auron mainboard. + Enable this config to select the Google Auron mainboard. + Auron is a Chrome OS mainboard. + Auron is based on the Intel Broadwell platform. + +config BOARD_GOOGLE_BELTINO + bool "Beltino" + help + Google Beltino mainboard. + Enable this config to select the Google Beltino mainboard. + Beltino is a Chrome OS mainboard. + Beltino is based on the Intel Haswell platform. + +config BOARD_GOOGLE_BOLT + bool "Bolt" + help + Google Bolt mainboard. + Enable this config to select the Google Bolt mainboard. + Bolt is a Chrome OS mainboard. + Bolt is based on the Intel Haswell platform. + config BOARD_GOOGLE_BUTTERFLY bool "Butterfly" + help + Google Butterfly mainboard. + Enable this config to select the Google Butterfly mainboard. + Butterfly is a Chrome OS mainboard. + Butterfly is based on the Intel Sandy Bridge platform. + +config BOARD_GOOGLE_COSMOS + bool "Cosmos" + help + Google Cosmos mainboard. + Enable this config to select the Google Cosmos mainboard. + Cosmos is a Chrome OS mainboard. + Cosmos is based on the Marvell BG4CD platform. + +config BOARD_GOOGLE_DAISY + bool "Daisy" + help + Google Daisy mainboard. + Enable this config to select the Google Daisy mainboard. + Daisy is a Chrome OS mainboard. + Daisy is based on the Samsung Exynos 5250 platform. + +config BOARD_GOOGLE_FALCO + bool "Falco" + help + Google Falco mainboard. + Enable this config to select the Google Falco mainboard. + Falco is a Chrome OS mainboard. + Falco is based on the Intel Haswell platform. + +config BOARD_GOOGLE_JECHT + bool "Jecht" + help + Google Jecht mainboard. + Enable this config to select the Google Jecht mainboard. + Jecht is a Chrome OS mainboard. + Jecht is based on the Intel Broadwell platform. + config BOARD_GOOGLE_LINK bool "Link" + help + Google Link mainboard. + Enable this config to select the Google Link mainboard. + Link is a Chrome OS mainboard. + Link is based on the Intel Ivy Bridge platform. + +config BOARD_GOOGLE_NYAN + bool "Nyan" + help + Google Nyan mainboard. + Enable this config to select the Google Nyan mainboard. + Nyan is a Chrome OS mainboard. + Nyan is based on the Nvidia Tegra 124 platform. + +config BOARD_GOOGLE_NYAN_BIG + bool "Nyan Big" + help + Google Nyan Big mainboard. + Enable this config to select the Google Nyan Big mainboard. + Nyan Big is a Chrome OS mainboard. + Nyan Big is based on the Nvidia Tegra 124 platform. + +config BOARD_GOOGLE_NYAN_BLAZE + bool "Nyan Blaze" + help + Google Nyan Blaze mainboard. + Enable this config to select the Google Nyan Blaze mainboard. + Nyan Blaze is a Chrome OS mainboard. + Nyan Blaze is based on the Nvidia Tegra 124 platform. + +config BOARD_GOOGLE_PANTHER + bool "Panther" + help + Google Panther mainboard. + Enable this config to select the Google Panther mainboard. + Panther is a Chrome OS mainboard. + Panther is based on the Intel Haswell platform. + config BOARD_GOOGLE_PARROT bool "Parrot" -config BOARD_GOOGLE_SNOW - bool "Snow" + help + Google Parrot mainboard. + Enable this config to select the Google Parrot mainboard. + Parrot is a Chrome OS mainboard. + Parrot is based on the Intel Ivy Bridge platform. + +config BOARD_GOOGLE_PEACH_PIT + bool "Peach Pit" + help + Google Peach Pit mainboard. + Enable this config to select the Google Peach Pit mainboard. + Peach Pit is a Chrome OS mainboard. + Peach Pit is based on the Samsung Exynos 5420 platform. + +config BOARD_GOOGLE_PEPPY + bool "Peppy" + help + Google Peppy mainboard. + Enable this config to select the Google Peppy mainboard. + Peppy is a Chrome OS mainboard. + Peppy is based on the Intel Haswell platform. + +config BOARD_GOOGLE_RAMBI + bool "Rambi" + help + Google Rambi mainboard. + Enable this config to select the Google Rambi mainboard. + Rambi is a Chrome OS mainboard. + Rambi is based on the Intel Baytrail platform. + +config BOARD_GOOGLE_RUSH + bool "Rush" + help + Google Rush mainboard. + Enable this config to select the Google Rush mainboard. + Rush is a Chrome OS mainboard. + Rush is based on the Nvidia Tegra 132 platform. + +config BOARD_GOOGLE_RUSH_RYU + bool "Rush Ryu" + help + Google Ryu mainboard. + Enable this config to select the Google Ryu mainboard. + Ryu is a Chrome OS mainboard. + Ryu is based on the Nvidia Tegra 132 platform. + +config BOARD_GOOGLE_SAMUS + bool "Samus" + help + Google Saums mainboard. + Enable this config to select the Google Samus mainboard. + Samus is a Chrome OS mainboard. + Samus is based on the Intel Broadwell platform. + +config BOARD_GOOGLE_SLIPPY + bool "Slippy" + help + Google Slippy mainboard. + Enable this config to select the Google Slippy mainboard. + Slippy is a Chrome OS mainboard. + Slippy is based on the Intel Haswell platform. + +config BOARD_GOOGLE_STORM + bool "Storm" + help + Google Storm mainboard. + Enable this config to select the Google Storm mainboard. + Storm is a Chrome OS mainboard. + Storm is based on the Qualcomm IPQ806X platform. + config BOARD_GOOGLE_STOUT bool "Stout" + help + Google Stout mainboard. + Enable this config to select the Google Stout mainboard. + Stout is a Chrome OS mainboard. + Stout is based on the Intel Ivy Bridge platform. +config BOARD_GOOGLE_URARA + bool "Urara" + help + Google Urara mainboard. + Urara is an embedded device running on MIPS platorm + based on the Pistachio SOC. + +config BOARD_GOOGLE_VEYRON_BRAIN + bool "Veyron_Brain" + help + Google Veyron_Brain mainboard. + Enable this config to select the Google Veyron_Brain mainboard. + Veyron_Brain is a Chrome OS mainboard. + Veyron_Brain is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_DANGER + bool "Veyron_Danger" + help + Google Veyron_Danger mainboard. + Enable this config to select the Google Veyron_Danger mainboard. + Veyron_Danger is a Chrome OS mainboard. + Veyron_Danger is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_FIEVEL + bool "Veyron_Fievel" + help + Google Veyron_Fievel mainboard. + Enable this config to select the Google Veyron_Fievel mainboard. + Veyron_Fievel is a Chrome OS mainboard. + Veyron_Fievel is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_GUS + bool "Veyron_Gus" + help + Google Veyron_Gus mainboard. + Enable this config to select the Google Veyron_Gus mainboard. + Veyron_Gus is a Chrome OS mainboard. + Veyron_Gus is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_JAQ + bool "Veyron_Jaq" + help + Google Veyron_Jaq mainboard. + Enable this config to select the Google Veyron_Jaq mainboard. + Veyron_Jaq is a Chrome OS mainboard. + Veyron_Jaq is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_JERRY + bool "Veyron_Jerry" + help + Google Veyron_Jerry mainboard. + Enable this config to select the Google Veyron_Jerry mainboard. + Veyron_Jerry is a Chrome OS mainboard. + Veyron_Jerry is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_MICKEY + bool "Veyron_Mickey" + help + Google Veyron_Mickey mainboard. + Enable this config to select the Google Veyron_Mickey mainboard. + Veyron_Mickey is a Chrome OS mainboard. + Veyron_Mickey is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_MINNIE + bool "Veyron_Minnie" + help + Google Veyron_Minnie mainboard. + Enable this config to select the Google Veyron_Minnie mainboard. + Veyron_Minnie is a Chrome OS mainboard. + Veyron_Minnie is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_MIGHTY + bool "Veyron_Mighty" + help + Google Veyron_Mighty mainboard. + Enable this config to select the Google Veyron_Mighty mainboard. + Veyron_Mighty is a Chrome OS mainboard. + Veyron_Mighty is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_NICKY + bool "Veyron_Nicky" + help + Google Veyron_Nicky mainboard. + Enable this config to select the Google Veyron_Nicky mainboard. + Veyron_Nicky is a Chrome OS mainboard. + Veyron_Nicky is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_PINKY + bool "Veyron_Pinky" + help + Google Veyron_Pinky mainboard. + Enable this config to select the Google Veyron_Pinky mainboard. + Veyron_Pinky is a Chrome OS mainboard. + Veyron_Pinky is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_RIALTO + bool "Veyron_Rialto" + help + Google Veyron_Rialto mainboard + Enable this config to select the Google Veyron_Rialto mainboard. + Veyron_Rialto is a Chrome OS mainboard. + Veyron_Rialto is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_ROMY + bool "Veyron_Romy" + help + Google Veyron_Romy mainboard. + Enable this config to select the Google Veyron_Romy mainboard. + Veyron_Romy is a Chrome OS mainboard. + Veyron_Romy is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_SPEEDY + bool "Veyron_Speedy" + help + Google Veyron_Speedy mainboard. + Enable this config to select the Google Veyron_Speedy mainboard. + Veyron_Speedy is a Chrome OS mainboard. + Veyron_Speedy is based on the Rockchip RK3288 platform. + +config BOARD_GOOGLE_VEYRON_THEA + bool "Veyron_Thea" + help + Google Veyron_Thea mainboard. + Enable this config to select the Google Veyron_Thea mainboard. + Veyron_Thea is a Chrome OS mainboard. + Veyron_Thea is based on the Rockchip RK3288 platform. +config BOARD_GOOGLE_VEYRON_TIGER + bool "Veyron_Tiger" + help + Google Veyron_Tiger mainboard. + Enable this config to select the Google Veyron_Tiger mainboard. + Veyron_Tiger is a Chrome OS mainboard. + Veyron_Tiger is based on the Rockchip RK3288 platform. endchoice +source "src/mainboard/google/auron/Kconfig" +source "src/mainboard/google/beltino/Kconfig" +source "src/mainboard/google/bolt/Kconfig" source "src/mainboard/google/butterfly/Kconfig" +source "src/mainboard/google/cosmos/Kconfig" +source "src/mainboard/google/daisy/Kconfig" +source "src/mainboard/google/falco/Kconfig" +source "src/mainboard/google/jecht/Kconfig" source "src/mainboard/google/link/Kconfig" +source "src/mainboard/google/nyan/Kconfig" +source "src/mainboard/google/nyan_big/Kconfig" +source "src/mainboard/google/nyan_blaze/Kconfig" +source "src/mainboard/google/panther/Kconfig" source "src/mainboard/google/parrot/Kconfig" -source "src/mainboard/google/snow/Kconfig" +source "src/mainboard/google/peach_pit/Kconfig" +source "src/mainboard/google/peppy/Kconfig" +source "src/mainboard/google/rambi/Kconfig" +source "src/mainboard/google/rush/Kconfig" +source "src/mainboard/google/rush_ryu/Kconfig" +source "src/mainboard/google/samus/Kconfig" +source "src/mainboard/google/slippy/Kconfig" +source "src/mainboard/google/storm/Kconfig" source "src/mainboard/google/stout/Kconfig" +source "src/mainboard/google/urara/Kconfig" +source "src/mainboard/google/veyron_brain/Kconfig" +source "src/mainboard/google/veyron_danger/Kconfig" +source "src/mainboard/google/veyron_fievel/Kconfig" +source "src/mainboard/google/veyron_gus/Kconfig" +source "src/mainboard/google/veyron_jaq/Kconfig" +source "src/mainboard/google/veyron_jerry/Kconfig" +source "src/mainboard/google/veyron_mickey/Kconfig" +source "src/mainboard/google/veyron_mighty/Kconfig" +source "src/mainboard/google/veyron_nicky/Kconfig" +source "src/mainboard/google/veyron_pinky/Kconfig" +source "src/mainboard/google/veyron_rialto/Kconfig" +source "src/mainboard/google/veyron_romy/Kconfig" +source "src/mainboard/google/veyron_speedy/Kconfig" +source "src/mainboard/google/veyron_minnie/Kconfig" +source "src/mainboard/google/veyron_thea/Kconfig" +source "src/mainboard/google/veyron_tiger/Kconfig" config MAINBOARD_VENDOR - string - default "Google" + string "Mainboard Vendor" + default "GOOGLE" endif # VENDOR_GOOGLE diff --git a/src/mainboard/google/auron/Kconfig b/src/mainboard/google/auron/Kconfig new file mode 100644 index 0000000000..117232966e --- /dev/null +++ b/src/mainboard/google/auron/Kconfig @@ -0,0 +1,56 @@ +if BOARD_GOOGLE_AURON + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select SOC_INTEL_BROADWELL + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_REFCODE_INDEX + hex + default 0x3 + +config MAINBOARD_DIR + string + default google/auron + +config MAINBOARD_PART_NUMBER + string + default "Auron" + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +config MAINBOARD_FAMILY + string + depends on GENERATE_SMBIOS_TABLES + default "Google_Auron" + +endif diff --git a/src/mainboard/google/auron/Makefile.inc b/src/mainboard/google/auron/Makefile.inc new file mode 100644 index 0000000000..0f9978f77b --- /dev/null +++ b/src/mainboard/google/auron/Makefile.inc @@ -0,0 +1,30 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-y += spd + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +romstage-y += pei_data.c +ramstage-y += pei_data.c diff --git a/src/mainboard/google/auron/acpi/chromeos.asl b/src/mainboard/google/auron/acpi/chromeos.asl new file mode 100644 index 0000000000..fe1767db21 --- /dev/null +++ b/src/mainboard/google/auron/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "PCH-LP" }, // no recovery button + Package () { 0x0003, 1, 58, "PCH-LP" }, // firmware write protect +}) diff --git a/src/mainboard/google/auron/acpi/ec.asl b/src/mainboard/google/auron/acpi/ec.asl new file mode 100644 index 0000000000..4a15f96413 --- /dev/null +++ b/src/mainboard/google/auron/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/intel/wtm2/acpi/haswell_pci_irqs.asl b/src/mainboard/google/auron/acpi/haswell_pci_irqs.asl similarity index 53% rename from src/mainboard/intel/wtm2/acpi/haswell_pci_irqs.asl rename to src/mainboard/google/auron/acpi/haswell_pci_irqs.asl index a8b6b5f739..7ebd8e582e 100644 --- a/src/mainboard/intel/wtm2/acpi/haswell_pci_irqs.asl +++ b/src/mainboard/google/auron/acpi/haswell_pci_irqs.asl @@ -26,50 +26,61 @@ Method(_PRT) Return (Package() { // Onboard graphics (IGD) 0:2.0 Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, // High Definition Audio 0:1b.0 Package() { 0x001bffff, 0, 0, 22 }, // PCIe Root Ports 0:1c.x - Package() { 0x001cffff, 0, 0, 17 }, - Package() { 0x001cffff, 1, 0, 18 }, - Package() { 0x001cffff, 2, 0, 19 }, - Package() { 0x001cffff, 3, 0, 20 }, + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, // EHCI 0:1d.0 Package() { 0x001dffff, 0, 0, 19 }, // XHCI 0:14.0 - Package() { 0x0014ffff, 0, 0, 16 }, + Package() { 0x0014ffff, 0, 0, 18 }, // LPC devices 0:1f.0 - Package() { 0x001fffff, 0, 0, 21 }, - Package() { 0x001fffff, 1, 0, 22 }, - Package() { 0x001fffff, 2, 0, 23 }, + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, Package() { 0x001fffff, 3, 0, 16 }, // Serial IO 0:15.0 - Package() { 0x0015ffff, 0, 0, 16 }, - Package() { 0x0015ffff, 1, 0, 17 }, - Package() { 0x0015ffff, 2, 0, 18 }, - Package() { 0x0015ffff, 3, 0, 19 }, + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, // SDIO 0:17.0 - Package() { 0x0017ffff, 0, 0, 16 }, + Package() { 0x0017ffff, 0, 0, 23 }, }) } Else { Return (Package() { // Onboard graphics (IGD) 0:2.0 Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, // High Definition Audio 0:1b.0 Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, // PCIe Root Ports 0:1c.x - Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKB, 0 }, - Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, - Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKD, 0 }, - Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKE, 0 }, - // EHCI #1 0:1d.0 + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, - // EHCI #2 0:1a.0 - Package() { 0x001affff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, // LPC device 0:1f.0 - Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKF, 0 }, - Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKG, 0 }, - Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKH, 0 }, + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, }) } } diff --git a/src/mainboard/google/auron/acpi/mainboard.asl b/src/mainboard/google/auron/acpi/mainboard.asl new file mode 100644 index 0000000000..4556e2d603 --- /dev/null +++ b/src/mainboard/google/auron/acpi/mainboard.asl @@ -0,0 +1,281 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name(_HID, EisaId("PNP0C0D")) + Method(_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + + + // There is no GPIO for LID, the EC pulses WAKE# pin instead. + // There is no GPE for WAKE#, so fake it with PCI_EXP_WAKE + Name (_PRW, Package(){ 0x69, 5 }) // PCI_EXP + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } +} + +/* + * LPC Trusted Platform Module + */ +Scope (\_SB.PCI0.LPCB) +{ + #include +} + +Scope (\_SB.PCI0.I2C0) +{ + Device (ETPA) + { + Name (_HID, "ELAN0000") + Name (_DDN, "Elan Touchpad") + Name (_UID, 1) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x15, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } + + Device (CTPA) + { + Name (_HID, "CYAP0000") + Name (_DDN, "Cypress Touchpad") + Name (_UID, 3) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x67, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } + + Device (CTPB) + { + Name (_HID, "CYAP0001") + Name (_DDN, "Cypress Touchpad") + Name (_UID, 3) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x24, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } +} +Scope (\_SB.PCI0.I2C1) +{ + Device (ATSA) + { + Name (_HID, "ATML0001") + Name (_DDN, "Atmel Touchscreen") + Name (_UID, 5) + Name (_S0W, 4) + Name (ISTP, 0) /* TouchScreen */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x4a, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C1", // ResourceSource + ) + + // GPIO54 (ball L3) is PIRQW: PIRQL_GSI + PIRQL - PIRQW = PIRQW_GSI + // 27 + 3 - 14 = 38 + Interrupt (ResourceConsumer, Edge, ActiveLow) { 38 } + }) + + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TOUCHSCREEN_WAKE_GPIO, Local0) + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } + + Device (ALSI) + { + /* + * TODO(dlaurie): Need official HID. + * + * The current HID is created from the Intersil PNP + * Vendor ID "LSD" and a shortened device identifier. + */ + Name (_HID, EisaId ("LSD2918")) + Name (_DDN, "Intersil 29018 Ambient Light Sensor") + Name (_UID, 6) + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x44, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C1", // ResourceSource + ) + + // On Auron/Peppy board, IRQ is hooked to GPIO 51. + // Based on table 5-36, this is PIRQT. Then based on + // table 5-12, this is IRQ #35. + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + 35 + } + }) + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } +} diff --git a/src/mainboard/google/auron/acpi/platform.asl b/src/mainboard/google/auron/acpi/platform.asl new file mode 100644 index 0000000000..f0709b0a70 --- /dev/null +++ b/src/mainboard/google/auron/acpi/platform.asl @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/auron/acpi/superio.asl b/src/mainboard/google/auron/acpi/superio.asl new file mode 100644 index 0000000000..08b6c20feb --- /dev/null +++ b/src/mainboard/google/auron/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/auron/acpi/thermal.asl b/src/mainboard/google/auron/acpi/thermal.asl new file mode 100644 index 0000000000..4c1185a896 --- /dev/null +++ b/src/mainboard/google/auron/acpi/thermal.asl @@ -0,0 +1,206 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (TCHK, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + Method (_TMP, 0, Serialized) + { + // Get temperature from EC in deci-kelvin + Store (TCHK (), Local0) + + // Critical temperature in deci-kelvin + Store (CTOK (\TCRT), Local1) + + If (LGreaterEqual (Local0, Local1)) { + Store ("CRITICAL TEMPERATURE", Debug) + Store (Local0, Debug) + + // Wait 1 second for EC to re-poll + Sleep (1000) + + // Re-read temperature from EC + Store (TCHK (), Local0) + + Store ("RE-READ TEMPERATURE", Debug) + Store (Local0, Debug) + } + + Return (Local0) + } + + /* CTDP Down */ + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (CTL_TDP_THRESHOLD_OFF)) + } Else { + Return (CTOK (CTL_TDP_THRESHOLD_ON)) + } + } + + /* CTDP Nominal */ + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (CTL_TDP_THRESHILD_NORMAL)) + } Else { + Return (CTOK (CTL_TDP_THRESHILD_NORMAL)) + } + } + + Name (_AL0, Package () { TDP0 }) + Name (_AL1, Package () { TDP1 }) + + PowerResource (TNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + + /* Enable Power Limit */ + \_SB.PCI0.MCHC.CTLE (CTL_TDP_POWER_LIMIT) + + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + + /* Disable Power Limit */ + \_SB.PCI0.MCHC.CTLD () + + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (TNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (TDP0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { TNP0 }) + } + + Device (TDP1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { TNP1 }) + } + } +} + diff --git a/src/mainboard/intel/wtm1/acpi/video.asl b/src/mainboard/google/auron/acpi/video.asl similarity index 100% rename from src/mainboard/intel/wtm1/acpi/video.asl rename to src/mainboard/google/auron/acpi/video.asl diff --git a/src/mainboard/google/auron/acpi_tables.c b/src/mainboard/google/auron/acpi_tables.c new file mode 100644 index 0000000000..b827b607f9 --- /dev/null +++ b/src/mainboard/google/auron/acpi_tables.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thermal.h" + +extern const unsigned char AmlCode[]; + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->tmps = CTL_TDP_SENSOR_ID; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 1; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + return acpi_madt_irq_overrides(current); +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + return current; +} + +#define ALIGN_CURRENT (current = (ALIGN(current, 16))) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i = 0; i < dsdt->length; i++) { + if (*(u32 *)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, + "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> %p\n", + i, gnvs); + *(u32 *)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/auron/chromeos.c b/src/mainboard/google/auron/chromeos.c new file mode 100644 index 0000000000..3246b33515 --- /dev/null +++ b/src/mainboard/google/auron/chromeos.c @@ -0,0 +1,105 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec.h" + +/* SPI Write protect is GPIO 16 */ +#define CROS_WP_GPIO 58 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, CROS_WP_GPIO, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return get_gpio(CROS_WP_GPIO); +} diff --git a/src/mainboard/intel/wtm1/cmos.layout b/src/mainboard/google/auron/cmos.layout similarity index 100% rename from src/mainboard/intel/wtm1/cmos.layout rename to src/mainboard/google/auron/cmos.layout diff --git a/src/mainboard/google/auron/devicetree.cb b/src/mainboard/google/auron/devicetree.cb new file mode 100644 index 0000000000..77e71b8d3d --- /dev/null +++ b/src/mainboard/google/auron/devicetree.cb @@ -0,0 +1,108 @@ +chip soc/intel/broadwell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Disable DisplayPort C Hotplug + register "gpu_dp_c_hotplug" = "0x00" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "5" # 400ms + register "gpu_panel_power_up_delay" = "400" # 40ms + register "gpu_panel_power_down_delay" = "150" # 15ms + register "gpu_panel_power_backlight_on_delay" = "2100" # 210ms + register "gpu_panel_power_backlight_off_delay" = "2100" # 210ms + + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "sata_port_map" = "0x1" + register "sio_acpi_mode" = "1" + + # DTLE DATA / EDGE values + register "sata_port0_gen3_dtle" = "0x5" + register "sata_port1_gen3_dtle" = "0x5" + + # Force enable ASPM for PCIe Port1 + register "pcie_port_force_aspm" = "0x01" + + # Disable PCIe CLKOUT 2-5 and CLKOUT_XDP + register "icc_clock_disable" = "0x013c0000" + + register "s0ix_enable" = "1" + + device cpu_cluster 0 on + device lapic 0 on end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 off end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip drivers/pc80/tpm + # Rising edge interrupt + register "irq_polarity" = "2" + device pnp 0c31.0 on + irq 0x70 = 10 + end + end + chip ec/google/chromeec + device pnp 0c09.0 on end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 off end # SMBus + device pci 1f.6 on end # Thermal + end +end diff --git a/src/mainboard/google/auron/dsdt.asl b/src/mainboard/google/auron/dsdt.asl new file mode 100644 index 0000000000..f7246612ea --- /dev/null +++ b/src/mainboard/google/auron/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include + + // Mainboard specific + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/google/auron/ec.c b/src/mainboard/google/auron/ec.c new file mode 100644 index 0000000000..33d1461022 --- /dev/null +++ b/src/mainboard/google/auron/ec.c @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0) + ; + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/auron/ec.h b/src/mainboard/google/auron/ec.h new file mode 100644 index 0000000000..18a13f3b88 --- /dev/null +++ b/src/mainboard/google/auron/ec.h @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/auron/fadt.c b/src/mainboard/google/auron/fadt.c new file mode 100644 index 0000000000..6241521756 --- /dev/null +++ b/src/mainboard/google/auron/fadt.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 5; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + acpi_fill_in_fadt(fadt); + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/auron/gpio.h b/src/mainboard/google/auron/gpio.h new file mode 100644 index 0000000000..1307b5657c --- /dev/null +++ b/src/mainboard/google/auron/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AURON_GPIO_H +#define AURON_GPIO_H + +#include + +static const struct gpio_config mainboard_gpio_config[] = { + PCH_GPIO_UNUSED, /* 0: UNUSED */ + PCH_GPIO_UNUSED, /* 1: UNUSED */ + PCH_GPIO_UNUSED, /* 2: UNUSED */ + PCH_GPIO_UNUSED, /* 3: UNUSED */ + PCH_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + PCH_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + PCH_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + PCH_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + PCH_GPIO_ACPI_SCI, /* 8: LTE_WAKE_L_Q */ + PCH_GPIO_INPUT, /* 9: RAM_ID1 */ + PCH_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + PCH_GPIO_UNUSED, /* 11: UNUSED */ + PCH_GPIO_INPUT_INVERT, /* 12: TRACKPAD_INT_L (WAKE) */ + PCH_GPIO_INPUT, /* 13: RAM_ID0 */ + PCH_GPIO_INPUT, /* 14: EC_IN_RW */ + PCH_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 16: UNUSED */ + PCH_GPIO_UNUSED, /* 17: UNUSED */ + PCH_GPIO_NATIVE, /* 18: PCIE_CLKREQ_WLAN# */ + PCH_GPIO_UNUSED, /* 19: UNUSED */ + PCH_GPIO_UNUSED, /* 20: UNUSED */ + PCH_GPIO_UNUSED, /* 21: UNUSED */ + PCH_GPIO_UNUSED, /* 22: UNUSED */ + PCH_GPIO_UNUSED, /* 23: UNUSED */ + PCH_GPIO_UNUSED, /* 24: UNUSED */ + PCH_GPIO_INPUT_INVERT, /* 25: TOUCH_INT_L (WAKE) */ + PCH_GPIO_UNUSED, /* 26: UNUSED */ + PCH_GPIO_UNUSED, /* 27: UNUSED */ + PCH_GPIO_UNUSED, /* 28: UNUSED */ + PCH_GPIO_UNUSED, /* 29: UNUSED */ + PCH_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + PCH_GPIO_NATIVE, /* 31: NATIVE: ACPRESENT */ + PCH_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + PCH_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + PCH_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + PCH_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + PCH_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + PCH_GPIO_UNUSED, /* 37: UNUSED */ + PCH_GPIO_UNUSED, /* 38: UNUSED */ + PCH_GPIO_UNUSED, /* 39: UNUSED */ + PCH_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + PCH_GPIO_UNUSED, /* 41: UNUSED */ + PCH_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + PCH_GPIO_UNUSED, /* 43: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 44: PP3300_SSD_EN */ + PCH_GPIO_OUT_HIGH, /* 45: PP3300_CODEC_EN */ + PCH_GPIO_OUT_HIGH, /* 46: WLAN_DISABLE_L */ + PCH_GPIO_INPUT, /* 47: RAM_ID2 */ + PCH_GPIO_UNUSED, /* 48: UNUSED */ + PCH_GPIO_UNUSED, /* 49: UNUSED */ + PCH_GPIO_UNUSED, /* 50: UNUSED */ + PCH_GPIO_INPUT, /* 51: ALS_INT_L */ + PCH_GPIO_INPUT, /* 52: SIM_DET */ + PCH_GPIO_PIRQ, /* 53: TRACKPAD_INT_DX */ + PCH_GPIO_PIRQ, /* 54: TOUCH_INT_L_DX */ + PCH_GPIO_UNUSED, /* 55: UNUSED */ + PCH_GPIO_UNUSED, /* 56: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 57: PP3300_CCD_EN */ + PCH_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + PCH_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + PCH_GPIO_NATIVE, /* 60: NATIVE: SML0ALERT */ + PCH_GPIO_UNUSED, /* 61: UNUSED */ + PCH_GPIO_UNUSED, /* 62: UNUSED */ + PCH_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + PCH_GPIO_UNUSED, /* 64: UNUSED */ + PCH_GPIO_UNUSED, /* 65: UNUSED */ + PCH_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 67: UNUSED */ + PCH_GPIO_UNUSED, /* 68: UNUSED */ + PCH_GPIO_UNUSED, /* 69: UNUSED */ + PCH_GPIO_UNUSED, /* 70: UNUSED */ + PCH_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + PCH_GPIO_NATIVE, /* 72: NATIVE: PCH_BATLOW# */ + PCH_GPIO_NATIVE, /* 73: NATIVE: SMB1ALERT# */ + PCH_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + PCH_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + PCH_GPIO_UNUSED, /* 76: UNUSED */ + PCH_GPIO_UNUSED, /* 77: UNUSED */ + PCH_GPIO_UNUSED, /* 78: UNUSED */ + PCH_GPIO_UNUSED, /* 79: UNUSED */ + PCH_GPIO_UNUSED, /* 80: UNUSED */ + PCH_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + PCH_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + PCH_GPIO_UNUSED, /* 83: UNUSED */ + PCH_GPIO_UNUSED, /* 84: UNUSED */ + PCH_GPIO_UNUSED, /* 85: UNUSED */ + PCH_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 87: UNUSED */ + PCH_GPIO_UNUSED, /* 88: UNUSED */ + PCH_GPIO_UNUSED, /* 89: UNUSED */ + PCH_GPIO_UNUSED, /* 90: UNUSED */ + PCH_GPIO_UNUSED, /* 91: UNUSED */ + PCH_GPIO_UNUSED, /* 92: UNUSED */ + PCH_GPIO_UNUSED, /* 93: UNUSED */ + PCH_GPIO_UNUSED, /* 94: UNUSED */ + PCH_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/auron/hda_verb.h b/src/mainboard/google/auron/hda_verb.h new file mode 100644 index 0000000000..2fd30905b7 --- /dev/null +++ b/src/mainboard/google/auron/hda_verb.h @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000d, // Number of jacks (NID entries) + + 0x0017ff00, // Function Reset + 0x0017ff00, // Double Function Reset + 0x000F0000, // Pad - get vendor id + 0x000F0002, // Pad - get revision id + + /* Bits 31:28 - Codec Address */ + /* Bits 27:20 - NID */ + /* Bits 19:8 - Verb ID */ + /* Bits 7:0 - Payload */ + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - Disabled */ + 0x01271cf0, // + 0x01271d11, // + 0x01271e11, // + 0x01271f41, // + + /* Pin Complex (NID 0x14) SPKR-OUT - Internal Speakers */ + 0x01471c10, // group 1, cap 0 + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal, Location N/A + + /* Pin Complex (NID 0x17) MONO Out - Disabled */ + 0x01771cf0, // + 0x01771d11, // + 0x01771e11, // + 0x01771f41, // + + /* Pin Complex (NID 0x18) Disabled */ + 0x01871cf0, // + 0x01871d11, // + 0x01871e11, // + 0x01871f41, // + + /* Pin Complex (NID 0x19) MIC2 - 3.5mm Jack */ + 0x01971c20, // group2, cap 0 + 0x01971d10, // black, jack detect + 0x01971ea1, // Mic in, 3.5mm Jack + 0x01971f03, // connector, External left panel + + /* Pin Complex (NID 0x1A) LINE1 - Internal Mic */ + 0x01a71c11, // group 1, cap 1 + 0x01a71d01, // no connector, no jack detect + 0x01a71ea7, // mic in, analog connection + 0x01a71f90, // Fixed function, internal, Location N/A + + /* Pin Complex (NID 0x1B) LINE2 - Disabled */ + 0x01b71cf0, // + 0x01b71d11, // + 0x01b71e11, // + 0x01b71f41, // + + /* Pin Complex (NID 0x1D) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, Internal, Location N/A + + /* Pin Complex (NID 0x1E) SPDIF-OUT - Disabled*/ + 0x01e71cf0, // + 0x01e71d11, // + 0x01e71e11, // + 0x01e71f41, // + + /* Pin Complex (NID 0x21) HP-OUT - 3.5mm Jack*/ + 0x02171c21, // group2, cap 1 + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 3.5mm Jack + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/auron/mainboard.c b/src/mainboard/google/auron/mainboard.c new file mode 100644 index 0000000000..1e39eebb07 --- /dev/null +++ b/src/mainboard/google/auron/mainboard.c @@ -0,0 +1,197 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include "ec.h" +#include "onboard.h" + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = RESERVED + * bit 2 = EFP + * bit 3 = LFP + * bit 4 = RESERVED + * bit 5 = EFP3 + * bit 6 = EFP2 + * bit 7 = RESERVED + */ + X86_AX = 0x005f; + X86_CX = 0x0008; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 *cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 *pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_LIGHTSENSOR_NAME, /* name */ + BOARD_LIGHTSENSOR_IRQ, /* instance */ + BOARD_LIGHTSENSOR_I2C_BUS, /* segment */ + BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_GEN5_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/auron/onboard.h b/src/mainboard/google/auron/onboard.h new file mode 100644 index 0000000000..23726d164f --- /dev/null +++ b/src/mainboard/google/auron/onboard.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#define BOARD_LIGHTSENSOR_NAME "lightsensor" +#define BOARD_LIGHTSENSOR_IRQ 51 /* PIRQT */ +#define BOARD_LIGHTSENSOR_I2C_BUS 2 /* I2C1 */ +#define BOARD_LIGHTSENSOR_I2C_ADDR 0x44 + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ 37 /* PIRQV */ +#define BOARD_TRACKPAD_WAKE_GPIO 12 /* GPIO12 */ +#define BOARD_TRACKPAD_I2C_BUS 1 /* I2C0 */ +#define BOARD_TRACKPAD_I2C_ADDR 0x67 +#define BOARD_TRACKPAD_GEN5_I2C_ADDR 0x24 + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ 38 /* PIRQW */ +#define BOARD_TOUCHSCREEN_WAKE_GPIO 25 /* GPIO25 */ +#define BOARD_TOUCHSCREEN_I2C_BUS 2 /* I2C1 */ +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a + +#endif diff --git a/src/mainboard/google/auron/pei_data.c b/src/mainboard/google/auron/pei_data.c new file mode 100644 index 0000000000..779a62b6d6 --- /dev/null +++ b/src/mainboard/google/auron/pei_data.c @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + pei_data->ec_present = 1; + + /* One installed DIMM per channel -- can be changed by SPD init */ + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + + /* P0: LTE */ + pei_data_usb2_port(pei_data, 0, 0x0150, 1, USB_OC_PIN_SKIP, + USB_PORT_MINI_PCIE); + /* P1: POrt A, CN10 */ + pei_data_usb2_port(pei_data, 1, 0x0040, 1, 0, + USB_PORT_BACK_PANEL); + /* P2: CCD */ + pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P3: BT */ + pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_MINI_PCIE); + /* P4: Port B, CN6 */ + pei_data_usb2_port(pei_data, 4, 0x0040, 1, 2, + USB_PORT_BACK_PANEL); + /* P5: EMPTY */ + pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP, + USB_PORT_SKIP); + /* P6: SD Card */ + pei_data_usb2_port(pei_data, 6, 0x0150, 1, USB_OC_PIN_SKIP, + USB_PORT_FLEX); + /* P7: EMPTY */ + pei_data_usb2_port(pei_data, 7, 0x0000, 0, USB_OC_PIN_SKIP, + USB_PORT_SKIP); + + /* P1: Port A, CN6 */ + pei_data_usb3_port(pei_data, 0, 1, 0, 0); + /* P2: EMPTY */ + pei_data_usb3_port(pei_data, 1, 0, USB_OC_PIN_SKIP, 0); + /* P3: EMPTY */ + pei_data_usb3_port(pei_data, 2, 0, USB_OC_PIN_SKIP, 0); + /* P4: EMPTY */ + pei_data_usb3_port(pei_data, 3, 0, USB_OC_PIN_SKIP, 0); +} diff --git a/src/mainboard/google/auron/romstage.c b/src/mainboard/google/auron/romstage.c new file mode 100644 index 0000000000..cd8560e9d1 --- /dev/null +++ b/src/mainboard/google/auron/romstage.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct pei_data pei_data; + + post_code(0x32); + + /* Ensure the EC is in the right mode for recovery */ + google_chromeec_early_init(); + + /* Initialize GPIOs */ + init_gpios(mainboard_gpio_config); + + /* Fill out PEI DATA */ + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + mainboard_fill_spd_data(&pei_data); + rp->pei_data = &pei_data; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(rp); +} diff --git a/src/mainboard/google/auron/smihandler.c b/src/mainboard/google/auron/smihandler.c new file mode 100644 index 0000000000..e885ef13c4 --- /dev/null +++ b/src/mainboard/google/auron/smihandler.c @@ -0,0 +1,158 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec.h" + +/* Codec enable: GPIO45 */ +#define GPIO_PP3300_CODEC_EN 45 +/* WLAN / BT enable: GPIO46 */ +#define GPIO_WLAN_DISABLE_L 46 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0) + ; + } +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) { + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + } + + set_gpio(GPIO_PP3300_CODEC_EN, 0); + set_gpio(GPIO_WLAN_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) { + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + } + + set_gpio(GPIO_PP3300_CODEC_EN, 0); + set_gpio(GPIO_WLAN_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0) + ; +} + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0) + ; + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0) + ; + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS); + break; + } + return 0; +} diff --git a/src/mainboard/google/auron/spd/Elpida_EDJ4216EFBG.spd.hex b/src/mainboard/google/auron/spd/Elpida_EDJ4216EFBG.spd.hex new file mode 100644 index 0000000000..eb41f0bfb1 --- /dev/null +++ b/src/mainboard/google/auron/spd/Elpida_EDJ4216EFBG.spd.hex @@ -0,0 +1,17 @@ +# Elpida EDJ4216EFBG-GN-F +92 12 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 81 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 A1 CE +45 44 4A 34 32 31 36 45 46 42 47 2D 47 4E 2D 46 +00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/auron/spd/Hynix_HMT425S6AFR6A.spd.hex b/src/mainboard/google/auron/spd/Hynix_HMT425S6AFR6A.spd.hex new file mode 100644 index 0000000000..7b0932743d --- /dev/null +++ b/src/mainboard/google/auron/spd/Hynix_HMT425S6AFR6A.spd.hex @@ -0,0 +1,17 @@ +# Hynix HMT425S6AFR6A-PBA +92 12 0B 03 04 19 02 02 03 52 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 01 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 62 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 01 00 00 00 00 00 00 FF AB +48 4D 54 34 32 35 53 36 41 46 52 36 41 2D 50 42 +20 20 4E 30 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/auron/spd/Makefile.inc b/src/mainboard/google/auron/spd/Makefile.inc new file mode 100644 index 0000000000..1568a0fbd4 --- /dev/null +++ b/src/mainboard/google/auron/spd/Makefile.inc @@ -0,0 +1,54 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-y += spd.c + +SPD_BIN = $(obj)/spd.bin + +# { GPIO47, GPIO9, GPIO13 } +SPD_SOURCES = Micron_4KTF25664HZ # 0b0000 +SPD_SOURCES += Hynix_HMT425S6AFR6A # 0b0001 +SPD_SOURCES += Elpida_EDJ4216EFBG # 0b0010 +SPD_SOURCES += Micron_4KTF25664HZ # 0b0011 +SPD_SOURCES += Micron_4KTF25664HZ # 0b0100 +SPD_SOURCES += Hynix_HMT425S6AFR6A # 0b0101 +SPD_SOURCES += Elpida_EDJ4216EFBG # 0b0110 +SPD_SOURCES += empty # 0b0111 +SPD_SOURCES += empty # 0b1000 +SPD_SOURCES += empty # 0b1001 +SPD_SOURCES += empty # 0b1010 +SPD_SOURCES += empty # 0b1011 +SPD_SOURCES += empty # 0b1100 +SPD_SOURCES += empty # 0b1101 +SPD_SOURCES += empty # 0b1110 +SPD_SOURCES += empty # 0b1111 + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/spd/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab diff --git a/src/mainboard/google/auron/spd/Micron_4KTF25664HZ.spd.hex b/src/mainboard/google/auron/spd/Micron_4KTF25664HZ.spd.hex new file mode 100644 index 0000000000..cbe9e4fbfe --- /dev/null +++ b/src/mainboard/google/auron/spd/Micron_4KTF25664HZ.spd.hex @@ -0,0 +1,17 @@ +# Micron 4KTF25664HZ-1G6E1 +92 11 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2C 00 00 00 00 00 00 00 AD 75 +34 4B 54 46 32 35 36 36 34 48 5A 2D 31 47 36 45 +31 20 45 31 80 2C 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/auron/spd/empty.spd.hex b/src/mainboard/google/auron/spd/empty.spd.hex new file mode 100644 index 0000000000..9ec39f1ba4 --- /dev/null +++ b/src/mainboard/google/auron/spd/empty.spd.hex @@ -0,0 +1,16 @@ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/auron/spd/spd.c b/src/mainboard/google/auron/spd/spd.c new file mode 100644 index 0000000000..997a46e0b3 --- /dev/null +++ b/src/mainboard/google/auron/spd/spd.c @@ -0,0 +1,141 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void mainboard_print_spd_info(uint8_t spd[]) +{ + const int spd_banks[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; + const int spd_capmb[8] = { 1, 2, 4, 8, 16, 32, 64, 0 }; + const int spd_rows[8] = { 12, 13, 14, 15, 16, -1, -1, -1 }; + const int spd_cols[8] = { 9, 10, 11, 12, -1, -1, -1, -1 }; + const int spd_ranks[8] = { 1, 2, 3, 4, -1, -1, -1, -1 }; + const int spd_devw[8] = { 4, 8, 16, 32, -1, -1, -1, -1 }; + const int spd_busw[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; + char spd_name[SPD_PART_LEN+1] = { 0 }; + + int banks = spd_banks[(spd[SPD_DENSITY_BANKS] >> 4) & 7]; + int capmb = spd_capmb[spd[SPD_DENSITY_BANKS] & 7] * 256; + int rows = spd_rows[(spd[SPD_ADDRESSING] >> 3) & 7]; + int cols = spd_cols[spd[SPD_ADDRESSING] & 7]; + int ranks = spd_ranks[(spd[SPD_ORGANIZATION] >> 3) & 7]; + int devw = spd_devw[spd[SPD_ORGANIZATION] & 7]; + int busw = spd_busw[spd[SPD_BUS_DEV_WIDTH] & 7]; + + /* Module type */ + printk(BIOS_INFO, "SPD: module type is "); + switch (spd[SPD_DRAM_TYPE]) { + case SPD_DRAM_DDR3: + printk(BIOS_INFO, "DDR3\n"); + break; + case SPD_DRAM_LPDDR3: + printk(BIOS_INFO, "LPDDR3\n"); + break; + default: + printk(BIOS_INFO, "Unknown (%02x)\n", spd[SPD_DRAM_TYPE]); + break; + } + + /* Module Part Number */ + memcpy(spd_name, &spd[SPD_PART_OFF], SPD_PART_LEN); + spd_name[SPD_PART_LEN] = 0; + printk(BIOS_INFO, "SPD: module part is %s\n", spd_name); + + printk(BIOS_INFO, "SPD: banks %d, ranks %d, rows %d, columns %d, " + , banks, ranks, rows, cols); + printk(BIOS_INFO, "density %d Mb\n", capmb); + + printk(BIOS_INFO, "SPD: device width %d bits, bus width %d bits\n", + devw, busw); + + if (capmb > 0 && busw > 0 && devw > 0 && ranks > 0) { + /* SIZE = DENSITY / 8 * BUS_WIDTH / SDRAM_WIDTH * RANKS */ + printk(BIOS_INFO, "SPD: module size is %u MB (per channel)\n", + capmb / 8 * busw / devw * ranks); + } +} + +/* Copy SPD data for on-board memory */ +void mainboard_fill_spd_data(struct pei_data *pei_data) +{ + int spd_bits[3] = { + SPD_GPIO_BIT0, + SPD_GPIO_BIT1, + SPD_GPIO_BIT2 + }; + int spd_gpio[3]; + int spd_index; + int spd_file_len; + struct cbfs_file *spd_file; + + spd_gpio[0] = get_gpio(SPD_GPIO_BIT0); + spd_gpio[1] = get_gpio(SPD_GPIO_BIT1); + spd_gpio[2] = get_gpio(SPD_GPIO_BIT2); + + spd_index = spd_gpio[2] << 2 | spd_gpio[1] << 1 | spd_gpio[0]; + + printk(BIOS_DEBUG, "SPD: index %d (GPIO%d=%d GPIO%d=%d GPIO%d=%d)\n", + spd_index, + spd_bits[2], spd_gpio[2], + spd_bits[1], spd_gpio[1], + spd_bits[0], spd_gpio[0]); + + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + spd_file_len = ntohl(spd_file->len); + + if (spd_index > 3) + pei_data->dimm_channel1_disabled = 3; + + if (spd_file_len < ((spd_index + 1) * SPD_LEN)) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file_len < SPD_LEN) + die("Missing SPD data."); + + spd_index *= SPD_LEN; + + memcpy(pei_data->spd_data[0][0], + ((char *)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); + /* Index 0-2 are 4GB config with both CH0 and CH1. + * Index 4-6 are 2GB config with CH0 only. */ + if (spd_index > 3) + pei_data->dimm_channel1_disabled = 3; + else + memcpy(pei_data->spd_data[1][0], + ((char *)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); + /* Make sure a valid SPD was found */ + if (pei_data->spd_data[0][0][0] == 0) + die("Invalid SPD data."); + + mainboard_print_spd_info(pei_data->spd_data[0][0]); +} diff --git a/src/mainboard/google/auron/spd/spd.h b/src/mainboard/google/auron/spd/spd.h new file mode 100644 index 0000000000..0b1ba09fa8 --- /dev/null +++ b/src/mainboard/google/auron/spd/spd.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_SPD_H +#define MAINBOARD_SPD_H + +#define SPD_LEN 256 + +#define SPD_DRAM_TYPE 2 +#define SPD_DRAM_DDR3 0x0b +#define SPD_DRAM_LPDDR3 0xf1 +#define SPD_DENSITY_BANKS 4 +#define SPD_ADDRESSING 5 +#define SPD_ORGANIZATION 7 +#define SPD_BUS_DEV_WIDTH 8 +#define SPD_PART_OFF 128 +#define SPD_PART_LEN 18 + +/* Auron board memory configuration GPIOs */ +#define SPD_GPIO_BIT0 13 +#define SPD_GPIO_BIT1 9 +#define SPD_GPIO_BIT2 47 + +struct pei_data; +void mainboard_fill_spd_data(struct pei_data *pei_data); + +#endif diff --git a/src/mainboard/google/auron/thermal.h b/src/mainboard/google/auron/thermal.h new file mode 100644 index 0000000000..93fb3e9cff --- /dev/null +++ b/src/mainboard/google/auron/thermal.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Control TDP Settings */ +#define CTL_TDP_SENSOR_ID 0 /* PECI */ +#define CTL_TDP_POWER_LIMIT 12 /* 12W */ +#define CTL_TDP_THRESHILD_NORMAL 0 /*Normal TDP Threshold*/ +#define CTL_TDP_THRESHOLD_OFF 85 /* Normal at 85C */ +#define CTL_TDP_THRESHOLD_ON 90 /* Limited at 90C */ + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 104 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 105 + +#endif diff --git a/src/mainboard/intel/wtm1/Kconfig b/src/mainboard/google/beltino/Kconfig similarity index 67% rename from src/mainboard/intel/wtm1/Kconfig rename to src/mainboard/google/beltino/Kconfig index 65db03f29a..adba43760f 100644 --- a/src/mainboard/intel/wtm1/Kconfig +++ b/src/mainboard/google/beltino/Kconfig @@ -1,28 +1,37 @@ -if BOARD_INTEL_WTM1 +if BOARD_GOOGLE_BELTINO config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_HASWELL select SOUTHBRIDGE_INTEL_LYNXPOINT select INTEL_LYNXPOINT_LP select BOARD_ROMSIZE_KB_8192 + select SUPERIO_ITE_IT8772F + select VIRTUAL_DEV_SWITCH select HAVE_ACPI_TABLES select HAVE_OPTION_TABLE select HAVE_ACPI_RESUME select MMCONF_SUPPORT select HAVE_SMI_HANDLER select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 config MAINBOARD_DIR string - default intel/wtm1 + default google/beltino config MAINBOARD_PART_NUMBER string - default "WHITETIP MOUNTAIN 1" + default "Beltino" config MMCONF_BASE_ADDRESS hex @@ -34,10 +43,10 @@ config IRQ_SLOT_COUNT config MAX_CPUS int - default 16 + default 8 config VGA_BIOS_FILE string default "pci8086,0166.rom" -endif # BOARD_INTEL_WTM1 +endif diff --git a/src/mainboard/google/beltino/Makefile.inc b/src/mainboard/google/beltino/Makefile.inc new file mode 100644 index 0000000000..1300be6548 --- /dev/null +++ b/src/mainboard/google/beltino/Makefile.inc @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-y += lan.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + diff --git a/src/mainboard/google/beltino/acpi/chromeos.asl b/src/mainboard/google/beltino/acpi/chromeos.asl new file mode 100644 index 0000000000..0189cfa065 --- /dev/null +++ b/src/mainboard/google/beltino/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 12, "LynxPoint" }, // recovery button + Package () { 0x0003, 1, 58, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/beltino/acpi/ec.asl b/src/mainboard/google/beltino/acpi/ec.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/google/beltino/acpi/haswell_pci_irqs.asl b/src/mainboard/google/beltino/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/beltino/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/beltino/acpi/mainboard.asl b/src/mainboard/google/beltino/acpi/mainboard.asl new file mode 100644 index 0000000000..8d5ddf4aab --- /dev/null +++ b/src/mainboard/google/beltino/acpi/mainboard.asl @@ -0,0 +1,74 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } +} + +/* + * LAN connected to Root Port 3, becomes Root Port 1 after coalesce + */ +Scope (\_SB.PCI0.RP01) +{ + Device (ETH0) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { BELTINO_NIC_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BELTINO_NIC_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} + +/* + * WLAN connected to Root Port 4, becomes Root Port 2 after coalesce + */ +Scope (\_SB.PCI0.RP02) +{ + Device (WLAN) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { BELTINO_WLAN_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BELTINO_WLAN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/beltino/acpi/platform.asl b/src/mainboard/google/beltino/acpi/platform.asl new file mode 100644 index 0000000000..e6aaf75952 --- /dev/null +++ b/src/mainboard/google/beltino/acpi/platform.asl @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/beltino/acpi/superio.asl b/src/mainboard/google/beltino/acpi/superio.asl new file mode 100644 index 0000000000..e1c9d1c918 --- /dev/null +++ b/src/mainboard/google/beltino/acpi/superio.asl @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Values should match those defined in devicetree.cb */ + +#undef SIO_ENABLE_FDC0 // pnp 2e.0: Disable Floppy Controller +#undef SIO_ENABLE_INFR // pnp 2e.a: Disable Consumer IR + +#define SIO_ENABLE_PS2K // pnp 2e.5: Enable PS/2 Keyboard +#define SIO_ENABLE_PS2M // pnp 2e.6: Enable PS/2 Mouse +#define SIO_ENABLE_COM1 // pnp 2e.1: Enable Serial Port 1 +#define SIO_ENABLE_ENVC // pnp 2e.4: Enable Environmental Controller +#define SIO_ENVC_IO0 0x700 // pnp 2e.4: io 0x60 +#define SIO_ENVC_IO1 0x710 // pnp 2e.4: io 0x62 +#define SIO_ENABLE_GPIO // pnp 2e.7: Enable GPIO +#define SIO_GPIO_IO0 0x720 // pnp 2e.7: io 0x60 +#define SIO_GPIO_IO1 0x730 // pnp 2e.7: io 0x60 + +#include "superio/ite/it8772f/acpi/superio.asl" + diff --git a/src/mainboard/google/beltino/acpi/thermal.asl b/src/mainboard/google/beltino/acpi/thermal.asl new file mode 100644 index 0000000000..d5b1290b94 --- /dev/null +++ b/src/mainboard/google/beltino/acpi/thermal.asl @@ -0,0 +1,274 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (_TMP, 0, Serialized) + { + // Get CPU Temperature from PECI via SuperIO TMPIN3 + Store (\_SB.PCI0.LPCB.SIO.ENVC.TIN3, Local0) + + // Check for invalid readings + If (LOr (LEqual (Local0, 255), LEqual (Local0, 0))) { + Return (CTOK (\F2ON)) + } + + // PECI raw value is an offset from Tj_max + Subtract (255, Local0, Local1) + + // Handle values greater than Tj_max + If (LGreaterEqual (Local1, \TMAX)) { + Return (CTOK (\TMAX)) + } + + // Subtract from Tj_max to get temperature + Subtract (\TMAX, Local1, Local0) + Return (CTOK (Local0)) + } + + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (\F0OF)) + } Else { + Return (CTOK (\F0ON)) + } + } + + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (\F1OF)) + } Else { + Return (CTOK (\F1ON)) + } + } + + Method (_AC2) { + If (LLessEqual (\FLVL, 2)) { + Return (CTOK (\F2OF)) + } Else { + Return (CTOK (\F2ON)) + } + } + + Method (_AC3) { + If (LLessEqual (\FLVL, 3)) { + Return (CTOK (\F3OF)) + } Else { + Return (CTOK (\F3ON)) + } + } + + Method (_AC4) { + If (LLessEqual (\FLVL, 4)) { + Return (CTOK (\F4OF)) + } Else { + Return (CTOK (\F4ON)) + } + } + + Name (_AL0, Package () { FAN0 }) + Name (_AL1, Package () { FAN1 }) + Name (_AL2, Package () { FAN2 }) + Name (_AL3, Package () { FAN3 }) + Name (_AL4, Package () { FAN4 }) + + PowerResource (FNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + Store (\F0PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Store (\F1PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Store (\F1PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (2, \FLVL) + Store (\F2PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP2, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 2)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (2, \FLVL) + Store (\F2PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (3, \FLVL) + Store (\F3PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP3, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 3)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (3, \FLVL) + Store (\F3PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (4, \FLVL) + Store (\F4PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP4, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 4)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (4, \FLVL) + Store (\F4PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (4, \FLVL) + Store (\F4PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (FAN0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { FNP0 }) + } + + Device (FAN1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { FNP1 }) + } + + Device (FAN2) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 2) + Name (_PR0, Package () { FNP2 }) + } + + Device (FAN3) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 3) + Name (_PR0, Package () { FNP3 }) + } + + Device (FAN4) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 4) + Name (_PR0, Package () { FNP4 }) + } + } +} + diff --git a/src/mainboard/google/beltino/acpi/video.asl b/src/mainboard/google/beltino/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/beltino/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/intel/wtm1/acpi_tables.c b/src/mainboard/google/beltino/acpi_tables.c similarity index 95% rename from src/mainboard/intel/wtm1/acpi_tables.c rename to src/mainboard/google/beltino/acpi_tables.c index 16a1c6a9ed..09601004e4 100644 --- a/src/mainboard/intel/wtm1/acpi_tables.c +++ b/src/mainboard/google/beltino/acpi_tables.c @@ -31,6 +31,7 @@ #include #include #include +#include extern const unsigned char AmlCode[]; #if CONFIG_HAVE_ACPI_SLIC @@ -66,6 +67,7 @@ static void acpi_update_thermal_table(global_nvs_t *gnvs) gnvs->tcrt = CRITICAL_TEMPERATURE; gnvs->tpsv = PASSIVE_TEMPERATURE; gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 5; } static void acpi_create_gnvs(global_nvs_t *gnvs) @@ -99,10 +101,14 @@ static void acpi_create_gnvs(global_nvs_t *gnvs) #if CONFIG_CHROMEOS // TODO(reinauer) this could move elsewhere? chromeos_init_vboot(&(gnvs->chromeos)); - /* Emerald Lake has no EC (?) */ + + // SuperIO is always RO gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; #endif + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + acpi_update_thermal_table(gnvs); } @@ -285,6 +291,13 @@ unsigned long write_acpi_tables(unsigned long start) acpi_add_table(rsdp, ssdt); ALIGN_CURRENT; + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + printk(BIOS_DEBUG, "current = %lx\n", current); printk(BIOS_INFO, "ACPI: done.\n"); return current; diff --git a/src/mainboard/google/beltino/chromeos.c b/src/mainboard/google/beltino/chromeos.c new file mode 100644 index 0000000000..61f8408da5 --- /dev/null +++ b/src/mainboard/google/beltino/chromeos.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define GPIO_SPI_WP 58 +#define GPIO_REC_MODE 12 + +#define FLAG_SPI_WP 0 +#define FLAG_REC_MODE 1 +#define FLAG_DEV_MODE 2 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, GPIO_SPI_WP, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, GPIO_REC_MODE, ACTIVE_LOW, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", 1); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +int get_write_protect_state(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_SPI_WP) & 1; +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_REC_MODE) & 1; +} + +#ifdef __PRE_RAM__ +void save_chromeos_gpios(void) +{ + u32 flags = 0; + + /* Write Protect: GPIO58 = GPIO_SPI_WP, active high */ + if (get_gpio(GPIO_SPI_WP)) + flags |= (1 << FLAG_SPI_WP); + + /* Recovery: GPIO12 = RECOVERY_L, active low */ + if (!get_gpio(GPIO_REC_MODE)) + flags |= (1 << FLAG_REC_MODE); + + /* Developer: Virtual */ + + pci_write_config32(PCI_DEV(0, 0x1f, 2), SATA_SP, flags); +} +#endif diff --git a/src/mainboard/google/beltino/cmos.layout b/src/mainboard/google/beltino/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/beltino/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/beltino/devicetree.cb b/src/mainboard/google/beltino/devicetree.cb new file mode 100644 index 0000000000..1966a308c5 --- /dev/null +++ b/src/mainboard/google/beltino/devicetree.cb @@ -0,0 +1,136 @@ +chip northbridge/intel/haswell + + # Disable eDP Hotplug + register "gpu_dp_d_hotplug" = "0x00" + + # Enable DisplayPort C Hotplug with 6ms pulse + register "gpu_dp_c_hotplug" = "0x06" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) + end + end + + device domain 0 on + subsystemid 0x1ae0 0xc000 inherit + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # SuperIO range is 0x700-0x73f + register "gen2_dec" = "0x003c0701" + + register "alt_gp_smi_en" = "0x0000" + register "gpe0_en_1" = "0x00000000" + register "gpe0_en_2" = "0x00000000" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + # Enable port coalescing + register "pcie_port_coalesce" = "1" + + # Disable PCIe CLKOUT 1,5 and CLKOUT_XDP + register "icc_clock_disable" = "0x01220000" + + # Route all USB ports to XHCI per default + register "xhci_default" = "1" + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 off end # Serial I/O DMA + device pci 15.1 off end # I2C0 + device pci 15.2 off end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 off end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip superio/ite/it8772f + # Skip keyboard init + register "skip_keyboard" = "1" + # Enable PECI on TMPIN3 + register "peci_tmpin" = "3" + # Enable FAN2 + register "fan2_enable" = "1" + + device pnp 2e.0 off end # FDC + device pnp 2e.1 on # Serial Port 1 + io 0x60 = 0x3f8 + irq 0x70 = 4 + end + device pnp 2e.4 on # Environment Controller + io 0x60 = 0x700 + io 0x62 = 0x710 + irq 0x70 = 0x09 + irq 0xfa = 0x12 + end + device pnp 2e.7 on # GPIO + io 0x60 = 0x720 + io 0x62 = 0x730 + end + device pnp 2e.5 on + io 0x60 = 0x60 + io 0x62 = 0x64 + irq 0x70 = 1 + end # Keyboard + device pnp 2e.6 on + irq 0x70 = 12 + end # Mouse + device pnp 2e.a off end # IR + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/google/beltino/dsdt.asl b/src/mainboard/google/beltino/dsdt.asl new file mode 100644 index 0000000000..87076fee08 --- /dev/null +++ b/src/mainboard/google/beltino/dsdt.asl @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Mainboard devices + #include "acpi/mainboard.asl" + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include +} diff --git a/src/mainboard/intel/wtm1/fadt.c b/src/mainboard/google/beltino/fadt.c similarity index 100% rename from src/mainboard/intel/wtm1/fadt.c rename to src/mainboard/google/beltino/fadt.c diff --git a/src/mainboard/google/beltino/gpio.h b/src/mainboard/google/beltino/gpio.h new file mode 100644 index 0000000000..45f8f276f7 --- /dev/null +++ b/src/mainboard/google/beltino/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FALCO_GPIO_H +#define FALCO_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: LAN_WAKE_L_Q */ + LP_GPIO_OUT_HIGH, /* 9: PP3300_WLAN_EN */ + LP_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + LP_GPIO_UNUSED, /* 11: SMBALERT */ + LP_GPIO_INPUT_INVERT, /* 12: RECOVERY_L */ + LP_GPIO_UNUSED, /* 13: UNUSED */ + LP_GPIO_UNUSED, /* 14: UNUSED */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 16: UNUSED */ + LP_GPIO_OUT_HIGH, /* 17: PP3300_VP8_EN */ + LP_GPIO_UNUSED, /* 18: UNUSED */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_NATIVE, /* 20: NATIVE: CLK_PCIE_REQ2# */ + LP_GPIO_NATIVE, /* 21: NATIVE: CLK_PCIE_REQ3# */ + LP_GPIO_NATIVE, /* 22: NATIVE: CLK_PCIE_REQ4# */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_OUT_HIGH, /* 24: WLAN_OFF_L */ + LP_GPIO_UNUSED, /* 25: UNUSED */ + LP_GPIO_OUT_HIGH, /* 26: USB_CTL_1 */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_OUT_LOW, /* 28: USB_ILIM_SEL */ + LP_GPIO_UNUSED, /* 29: UNUSED */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSPWRACK_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: PCH_ACPRESENT */ + LP_GPIO_NATIVE, /* 32: NATIVE: CLKRUN# */ + LP_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + LP_GPIO_NATIVE, /* 41: NATIVE: USB_OC1# */ + LP_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + LP_GPIO_NATIVE, /* 43: NATIVE: USB_OC3# */ + LP_GPIO_UNUSED, /* 44: UNUSED */ + LP_GPIO_OUT_HIGH, /* 45: PP5000_CODEC_EN */ + LP_GPIO_OUT_HIGH, /* 46: BT_DISABLE_L */ + LP_GPIO_OUT_HIGH, /* 47: USB1_PWR_EN */ + LP_GPIO_UNUSED, /* 48: UNUSED */ + LP_GPIO_UNUSED, /* 49: UNUSED */ + LP_GPIO_OUT_HIGH, /* 50: VP8_DISABLE_L */ + LP_GPIO_UNUSED, /* 51: UNUSED */ + LP_GPIO_UNUSED, /* 52: UNUSED */ + LP_GPIO_UNUSED, /* 53: UNUSED */ + LP_GPIO_UNUSED, /* 54: UNUSED */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_OUT_HIGH, /* 56: USB2_PWR_EN */ + LP_GPIO_OUT_HIGH, /* 57: USB3_PWR_EN */ + LP_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + LP_GPIO_OUT_HIGH, /* 59: PP3300_LAN_EN */ + LP_GPIO_NATIVE, /* 60: NATIVE: SMB0ALERT# */ + LP_GPIO_UNUSED, /* 61: UNUSED */ + LP_GPIO_UNUSED, /* 62: UNUSED */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_UNUSED, /* 72: UNUSED */ + LP_GPIO_UNUSED, /* 73: UNUSED */ + LP_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + LP_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_UNUSED, /* 91: UNUSED */ + LP_GPIO_UNUSED, /* 92: UNUSED */ + LP_GPIO_UNUSED, /* 93: UNUSED */ + LP_GPIO_UNUSED, /* 94: UNUSED */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/beltino/hda_verb.h b/src/mainboard/google/beltino/hda_verb.h new file mode 100644 index 0000000000..ba0da1c1a4 --- /dev/null +++ b/src/mainboard/google/beltino/hda_verb.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000c, // Number of jacks (NID entries) + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - interior mobile lid */ + 0x01271c10, + 0x01271d10, + 0x01271ea6, + 0x01271fb7, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471c10, // group 1, front left/right + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/beltino/lan.c b/src/mainboard/google/beltino/lan.c new file mode 100644 index 0000000000..cd4687a866 --- /dev/null +++ b/src/mainboard/google/beltino/lan.c @@ -0,0 +1,179 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "onboard.h" + +static unsigned int search(char *p, u8 *a, unsigned int lengthp, + unsigned int lengtha) +{ + int i, j; + + /* Searching */ + for (j = 0; j <= lengtha - lengthp; j++) { + for (i = 0; i < lengthp && p[i] == a[i + j]; i++) ; + if (i >= lengthp) + return j; + } + return lengtha; +} + +static unsigned char get_hex_digit(u8 *offset) +{ + unsigned char retval = 0; + + retval = *offset - '0'; + if (retval > 0x09) { + retval = *offset - 'A' + 0x0A; + if (retval > 0x0F) + retval = *offset - 'a' + 0x0a; + } + if (retval > 0x0F) { + printk(BIOS_DEBUG, "Error: Invalid Hex digit found: %c - 0x%02x\n", + *offset, *offset); + retval = 0; + } + + return retval; +} + +static int get_mac_address(u32 *high_dword, u32 *low_dword, + u8 *search_address, u32 search_length) +{ + char key[] = "ethernet_mac"; + unsigned int offset; + int i; + + offset = search(key, search_address, sizeof(key) - 1, search_length); + if (offset == search_length) { + printk(BIOS_DEBUG, + "Error: Could not locate '%s' in VPD\n", key); + return 0; + } + printk(BIOS_DEBUG, "Located '%s' in VPD\n", key); + + offset += sizeof(key); /* move to next character */ + *high_dword = 0; + + /* Fetch the MAC address and put the octets in the correct order to + * be programmed. + * + * From RTL8105E_Series_EEPROM-Less_App_Note_1.1 + * If the MAC address is 001122334455h: + * Write 33221100h to I/O register offset 0x00 via double word access + * Write 00005544h to I/O register offset 0x04 via double word access + */ + + for (i = 0; i < 4; i++) { + *high_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *high_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + *low_dword = 0; + for (i = 0; i < 2; i++) { + *low_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *low_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + return *high_dword | *low_dword; +} + +static void program_mac_address(u16 io_base) +{ + /* Default MAC Address of A0:00:BA:D0:0B:AD */ + u32 high_dword = 0xD0BA00A0; /* high dword of mac address */ + u32 low_dword = 0x0000AD0B; /* low word of mac address as a dword */ + + void *search_address = NULL; + int search_length = find_fmap_entry("RO_VPD", &search_address); + + if (search_length == -1) + printk(BIOS_ERR, "LAN: find_fmap_entry returned -1.\n"); + else + get_mac_address(&high_dword, &low_dword, search_address, + search_length); + + if (io_base) { + printk(BIOS_DEBUG, "Realtek NIC io_base = 0x%04x\n", io_base); + printk(BIOS_DEBUG, "Programming MAC Address\n"); + + /* Disable register protection */ + outb(0xc0, io_base + 0x50); + outl(high_dword, io_base); + outl(low_dword, io_base + 0x04); + outb(0x60, io_base + 54); + /* Enable register protection again */ + outb(0x00, io_base + 0x50); + } +} + +void lan_init(void) +{ + u16 io_base = 0; + struct device *ethernet_dev = NULL; + + /* Get NIC's IO base address */ + ethernet_dev = dev_find_device(BELTINO_NIC_VENDOR_ID, + BELTINO_NIC_DEVICE_ID, 0); + if (ethernet_dev != NULL) { + io_base = pci_read_config16(ethernet_dev, 0x10) & 0xfffe; + + /* + * Battery life time - LAN PCIe should enter ASPM L1 to save + * power when LAN connection is idle. + * enable CLKREQ: LAN pci config space 0x81h=01 + */ + pci_write_config8(ethernet_dev, 0x81, 0x01); + } + + if (io_base) { + /* Program MAC address based on VPD data */ + program_mac_address(io_base); + + /* + * Program NIC LEDS + * + * RTL8105E Series EEPROM-Less Application Note, + * Section 5.6 LED Mode Configuration + * + * Step1: Write C0h to I/O register 0x50 via byte access to + * disable 'register protection' + * Step2: Write xx001111b to I/O register 0x52 via byte access + * (bit7 is LEDS1 and bit6 is LEDS0) + * Step3: Write 0x00 to I/O register 0x50 via byte access to + * enable 'register protection' + */ + outb(0xc0, io_base + 0x50); /* Disable protection */ + outb((BELTINO_NIC_LED_MODE << 6) | 0x0f, io_base + 0x52); + outb(0x00, io_base + 0x50); /* Enable register protection */ + } +} diff --git a/src/mainboard/google/beltino/mainboard.c b/src/mainboard/google/beltino/mainboard.c new file mode 100644 index 0000000000..e3823c3416 --- /dev/null +++ b/src/mainboard/google/beltino/mainboard.c @@ -0,0 +1,170 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include "onboard.h" +#include + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 * pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + lan_init(); +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/beltino/onboard.h b/src/mainboard/google/beltino/onboard.h new file mode 100644 index 0000000000..11a1e78b97 --- /dev/null +++ b/src/mainboard/google/beltino/onboard.h @@ -0,0 +1,21 @@ +#ifndef __MAINBOARD_ONBOARD_H +#define __MAINBOARD_ONBOARD_H + +#ifndef __ACPI__ +void lan_init(void); +#endif + +/* defines for programming the MAC address */ +#define BELTINO_NIC_VENDOR_ID 0x10EC +#define BELTINO_NIC_DEVICE_ID 0x8168 + +/* 0x00: White LINK LED and Amber ACTIVE LED */ +#define BELTINO_NIC_LED_MODE 0x00 + +/* NIC wake is GPIO 8 */ +#define BELTINO_NIC_WAKE_GPIO 8 + +/* WLAN wake is GPIO 10 */ +#define BELTINO_WLAN_WAKE_GPIO 10 + +#endif diff --git a/src/mainboard/intel/wtm1/romstage.c b/src/mainboard/google/beltino/romstage.c similarity index 52% rename from src/mainboard/intel/wtm1/romstage.c rename to src/mainboard/google/beltino/romstage.c index 525bd6ff49..0f39b3b1fd 100644 --- a/src/mainboard/intel/wtm1/romstage.c +++ b/src/mainboard/google/beltino/romstage.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2010 coresystems GmbH - * Copyright (C) 2011 Google Inc. + * Copyright (C) 2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,25 +19,29 @@ */ #include +#include +#include +#include #include -#include "cpu/intel/haswell/haswell.h" -#include "northbridge/intel/haswell/haswell.h" -#include "northbridge/intel/haswell/raminit.h" -#include "southbridge/intel/lynxpoint/pch.h" -#include "southbridge/intel/lynxpoint/lp_gpio.h" +#include +#include +#include +#include +#include #include "gpio.h" +#include "superio/ite/it8772f/it8772f.h" +#include "superio/ite/it8772f/early_serial.c" const struct rcba_config_instruction rcba_config[] = { /* * GFX INTA -> PIRQA (MSI) - * D28IP_P1IP WLAN INTA -> PIRQB - * D28IP_P4IP ETH0 INTB -> PIRQC - * D29IP_E1P EHCI1 INTA -> PIRQD - * D20IP_XHCI XHCI INTA -> PIRQA + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) * D31IP_SIP SATA INTA -> PIRQF (MSI) * D31IP_SMIP SMBUS INTB -> PIRQG - * D31IP_TTIP THRT INTC -> PIRQH + * D31IP_TTIP THRT INTC -> PIRQA * D27IP_ZIP HDA INTA -> PIRQG (MSI) */ @@ -49,21 +53,18 @@ const struct rcba_config_instruction rcba_config[] = { (INTB << D28IP_P4IP)), RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), - RCBA_SET_REG_32(D25IP, (NOINT << D25IP_LIP)), RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), - RCBA_SET_REG_32(D20IR, (INTA << D20IP_XHCI)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), /* Device interrupt route registers */ - RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQF, PIRQG, PIRQH, PIRQA)), - RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG)), - RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE)), - RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQH, PIRQA, PIRQB)), - RCBA_SET_REG_32(D26IR, DIR_ROUTE(PIRQE, PIRQF, PIRQG, PIRQH)), - RCBA_SET_REG_32(D25IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQA, 0, 0, 0)), + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ /* Disable unused devices (board specific) */ RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), @@ -89,30 +90,44 @@ void mainboard_romstage_entry(unsigned long bist) temp_mmio_base: 0xfed08000, system_type: 5, /* ULT */ tseg_size: CONFIG_SMM_TSEG_SIZE, - spd_addresses: { 0xa0, 0xa2, 0xa4, 0xa6 }, - ec_present: 1, + spd_addresses: { 0xa0, 0x00, 0xa4, 0x00 }, + ec_present: 0, // 0 = leave channel enabled // 1 = disable dimm 0 on channel // 2 = disable dimm 1 on channel // 3 = disable dimm 0+1 on channel dimm_channel0_disabled: 2, dimm_channel1_disabled: 2, + // Enable 2x refresh mode + ddr_refresh_2x: 1, + dq_pins_interleaved: 1, max_ddr3_freq: 1600, - usb_port_config: { - { 1, 0, 0x0040 }, /* P0: */ - { 1, 0, 0x0040 }, /* P1: */ - { 1, 0, 0x0040 }, /* P2: */ - { 1, 0, 0x0040 }, /* P3: */ - { 1, 0, 0x0040 }, /* P4: */ - { 1, 0, 0x0040 }, /* P5: */ - { 1, 0, 0x0040 }, /* P6: */ - { 1, 0, 0x0040 }, /* P7: */ - { 1, 0, 0x0040 }, /* P8: */ - { 1, 0, 0x0040 }, /* P9: */ - { 1, 0, 0x0040 }, /* P10: */ - { 1, 0, 0x0000 }, /* P11: */ - { 1, 0, 0x0040 }, /* P12: */ - { 1, 0, 0x0040 }, /* P13: */ + usb_xhci_on_resume: 1, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0064, 1, 0, /* P0: VP8 */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 0, /* P1: Port A, CN22 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 1, /* P2: Port B, CN23 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: WLAN */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 2, /* P4: Port C, CN25 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 2, /* P5: Port D, CN25 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P6: Card Reader */ + USB_PORT_INTERNAL }, + { 0x0000, 0, 0, /* P7: N/C */ + USB_PORT_SKIP }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; CN22 */ + { 1, 1 }, /* P2; CN23 */ + { 1, 2 }, /* P3; CN25 */ + { 1, 2 }, /* P4; CN25 */ }, }; @@ -123,6 +138,13 @@ void mainboard_romstage_entry(unsigned long bist) .bist = bist, }; + /* Early SuperIO setup */ + it8772f_kill_watchdog(); + it8772f_ac_resume_southbridge(); + pch_enable_lpc(); + it8772f_enable_serial(PNP_DEV(IT8772F_BASE, IT8772F_SP1), + CONFIG_TTYS0_BASE); + /* Call into the real romstage main with this board's attributes. */ romstage_common(&romstage_params); } diff --git a/src/mainboard/google/beltino/smihandler.c b/src/mainboard/google/beltino/smihandler.c new file mode 100644 index 0000000000..2ad249848a --- /dev/null +++ b/src/mainboard/google/beltino/smihandler.c @@ -0,0 +1,161 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* GPIO46 controls the WLAN_DISABLE_L signal. */ +#define GPIO_WLAN_DISABLE_L 46 +#define GPIO_LTE_DISABLE_L 59 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +#if 0 +static u8 mainboard_smi_ec(void) +{ + u8 cmd = 0;// google_chromeec_get_event(); + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + return cmd; +} +#endif + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ +#if 0 + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +#endif +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + //if (smm_get_gnvs()->s3u0 == 0) + // google_chromeec_set_usb_charge_mode( + // 0, USB_CHARGE_MODE_DISABLED); + //if (smm_get_gnvs()->s3u1 == 0) + // google_chromeec_set_usb_charge_mode( + // 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S3. */ + //set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + //set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + //google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + //if (smm_get_gnvs()->s5u0 == 0) + // google_chromeec_set_usb_charge_mode( + // 0, USB_CHARGE_MODE_DISABLED); + //if (smm_get_gnvs()->s5u1 == 0) + // google_chromeec_set_usb_charge_mode( + // 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S5. */ + //set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + //set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + //google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + //google_chromeec_set_smi_mask(0); + //google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + //while (google_chromeec_get_event() != 0); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + //google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + //while (google_chromeec_get_event() != 0); + //google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + //google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + //while (google_chromeec_get_event() != 0); + //google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/beltino/thermal.h b/src/mainboard/google/beltino/thermal.h new file mode 100644 index 0000000000..794065eb7a --- /dev/null +++ b/src/mainboard/google/beltino/thermal.h @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Fan is OFF */ +#define FAN4_THRESHOLD_OFF 0 +#define FAN4_THRESHOLD_ON 0 +#define FAN4_PWM 0x00 + +/* Fan is at LOW speed */ +#define FAN3_THRESHOLD_OFF 48 +#define FAN3_THRESHOLD_ON 55 +#define FAN3_PWM 0x40 + +/* Fan is at MEDIUM speed */ +#define FAN2_THRESHOLD_OFF 52 +#define FAN2_THRESHOLD_ON 64 +#define FAN2_PWM 0x80 + +/* Fan is at HIGH speed */ +#define FAN1_THRESHOLD_OFF 60 +#define FAN1_THRESHOLD_ON 68 +#define FAN1_PWM 0xb0 + +/* Fan is at FULL speed */ +#define FAN0_THRESHOLD_OFF 66 +#define FAN0_THRESHOLD_ON 78 +#define FAN0_PWM 0xff + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 100 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 90 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/google/bolt/Kconfig b/src/mainboard/google/bolt/Kconfig new file mode 100644 index 0000000000..0307a10d32 --- /dev/null +++ b/src/mainboard/google/bolt/Kconfig @@ -0,0 +1,53 @@ +if BOARD_GOOGLE_BOLT + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_HASWELL + select SOUTHBRIDGE_INTEL_LYNXPOINT + select INTEL_LYNXPOINT_LP + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config MAINBOARD_DIR + string + default google/bolt + +config MAINBOARD_PART_NUMBER + string + default "Bolt" + +config MMCONF_BASE_ADDRESS + hex + default 0xf0000000 + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/bolt/Makefile.inc b/src/mainboard/google/bolt/Makefile.inc new file mode 100644 index 0000000000..57f6f45e04 --- /dev/null +++ b/src/mainboard/google/bolt/Makefile.inc @@ -0,0 +1,46 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +## DIMM SPD for on-board memory +SPD_BIN = $(obj)/spd.bin + +# Order of names in SPD_SOURCES is important! +SPD_SOURCES = micron_4Gb_1600_1.35v_x16 + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab +spd.bin-position := 0xfffec000 diff --git a/src/mainboard/google/bolt/acpi/chromeos.asl b/src/mainboard/google/bolt/acpi/chromeos.asl new file mode 100644 index 0000000000..8017659436 --- /dev/null +++ b/src/mainboard/google/bolt/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "LynxPoint" }, // no recovery button + Package () { 0x0003, 1, 16, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/bolt/acpi/ec.asl b/src/mainboard/google/bolt/acpi/ec.asl new file mode 100644 index 0000000000..e008daf48a --- /dev/null +++ b/src/mainboard/google/bolt/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/intel/wtm1/acpi/haswell_pci_irqs.asl b/src/mainboard/google/bolt/acpi/haswell_pci_irqs.asl similarity index 54% rename from src/mainboard/intel/wtm1/acpi/haswell_pci_irqs.asl rename to src/mainboard/google/bolt/acpi/haswell_pci_irqs.asl index a8b6b5f739..aa4a862074 100644 --- a/src/mainboard/intel/wtm1/acpi/haswell_pci_irqs.asl +++ b/src/mainboard/google/bolt/acpi/haswell_pci_irqs.asl @@ -26,50 +26,61 @@ Method(_PRT) Return (Package() { // Onboard graphics (IGD) 0:2.0 Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, // High Definition Audio 0:1b.0 Package() { 0x001bffff, 0, 0, 22 }, // PCIe Root Ports 0:1c.x - Package() { 0x001cffff, 0, 0, 17 }, - Package() { 0x001cffff, 1, 0, 18 }, - Package() { 0x001cffff, 2, 0, 19 }, - Package() { 0x001cffff, 3, 0, 20 }, + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, // EHCI 0:1d.0 Package() { 0x001dffff, 0, 0, 19 }, // XHCI 0:14.0 - Package() { 0x0014ffff, 0, 0, 16 }, + Package() { 0x0014ffff, 0, 0, 18 }, // LPC devices 0:1f.0 Package() { 0x001fffff, 0, 0, 21 }, - Package() { 0x001fffff, 1, 0, 22 }, - Package() { 0x001fffff, 2, 0, 23 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, Package() { 0x001fffff, 3, 0, 16 }, // Serial IO 0:15.0 - Package() { 0x0015ffff, 0, 0, 16 }, - Package() { 0x0015ffff, 1, 0, 17 }, - Package() { 0x0015ffff, 2, 0, 18 }, - Package() { 0x0015ffff, 3, 0, 19 }, + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, // SDIO 0:17.0 - Package() { 0x0017ffff, 0, 0, 16 }, + Package() { 0x0017ffff, 0, 0, 23 }, }) } Else { Return (Package() { // Onboard graphics (IGD) 0:2.0 Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, // High Definition Audio 0:1b.0 Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, // PCIe Root Ports 0:1c.x - Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKB, 0 }, - Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, - Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKD, 0 }, - Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKE, 0 }, - // EHCI #1 0:1d.0 + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, - // EHCI #2 0:1a.0 - Package() { 0x001affff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, // LPC device 0:1f.0 - Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKF, 0 }, - Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKG, 0 }, - Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKH, 0 }, + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, }) } } diff --git a/src/mainboard/google/bolt/acpi/mainboard.asl b/src/mainboard/google/bolt/acpi/mainboard.asl new file mode 100644 index 0000000000..c62a96e1fb --- /dev/null +++ b/src/mainboard/google/bolt/acpi/mainboard.asl @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name(_HID, EisaId("PNP0C0D")) + Method(_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } + + Device (TPAD) + { + Name (_ADR, 0x0) + Name (_UID, 1) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + + VendorShort (ADDR) + { + BOARD_TRACKPAD_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } + + Device (TSCR) + { + Name (_ADR, 0x0) + Name (_UID, 2) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + + VendorShort (ADDR) + { + BOARD_TOUCHSCREEN_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TOUCHSCREEN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/bolt/acpi/platform.asl b/src/mainboard/google/bolt/acpi/platform.asl new file mode 100644 index 0000000000..208d76a0e9 --- /dev/null +++ b/src/mainboard/google/bolt/acpi/platform.asl @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + /* Update AC status */ + Store (\_SB.PCI0.LPCB.EC0.ACEX, Local0) + if (LNotEqual (Local0, \PWRS)) { + Store (Local0, \PWRS) + Notify (\_SB.PCI0.LPCB.EC0.AC, 0x80) + } + + /* Update LID status */ + Store (\_SB.PCI0.LPCB.EC0.LIDS, Local0) + if (LNotEqual (Local0, \LIDS)) { + Store (Local0, \LIDS) + Notify (\_SB.LID0, 0x80) + } + + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/bolt/acpi/superio.asl b/src/mainboard/google/bolt/acpi/superio.asl new file mode 100644 index 0000000000..5120d90768 --- /dev/null +++ b/src/mainboard/google/bolt/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/bolt/acpi/thermal.asl b/src/mainboard/google/bolt/acpi/thermal.asl new file mode 100644 index 0000000000..69b6ac9834 --- /dev/null +++ b/src/mainboard/google/bolt/acpi/thermal.asl @@ -0,0 +1,173 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (_TMP, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + /* CTDP Down */ + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (\F0OF)) + } Else { + Return (CTOK (\F0ON)) + } + } + + /* CTDP Nominal */ + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (\F1OF)) + } Else { + Return (CTOK (\F1ON)) + } + } + + Name (_AL0, Package () { TDP0 }) + Name (_AL1, Package () { TDP1 }) + + PowerResource (TNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + \_SB.PCI0.MCHC.STND () + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + \_SB.PCI0.MCHC.STDN () + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (TNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (TDP0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { TNP0 }) + } + + Device (TDP1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { TNP1 }) + } + } +} + diff --git a/src/mainboard/google/bolt/acpi/video.asl b/src/mainboard/google/bolt/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/bolt/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/bolt/acpi_tables.c b/src/mainboard/google/bolt/acpi_tables.c new file mode 100644 index 0000000000..7a3ccea50c --- /dev/null +++ b/src/mainboard/google/bolt/acpi_tables.c @@ -0,0 +1,292 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +#include +#include +#include "thermal.h" + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->tmps = CTDP_SENSOR_ID; + + gnvs->f1of = CTDP_NOMINAL_THRESHOLD_OFF; + gnvs->f1on = CTDP_NOMINAL_THRESHOLD_ON; + + gnvs->f0of = CTDP_DOWN_THRESHOLD_OFF; + gnvs->f0on = CTDP_DOWN_THRESHOLD_ON; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 1; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* CBMEM TOC */ + gnvs->cmem = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +#if CONFIG_CHROMEOS + // TODO(reinauer) this could move elsewhere? + chromeos_init_vboot(&(gnvs->chromeos)); + + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif + + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/bolt/chromeos.c b/src/mainboard/google/bolt/chromeos.c new file mode 100644 index 0000000000..7bc0ce1a03 --- /dev/null +++ b/src/mainboard/google/bolt/chromeos.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_EC_GOOGLE_CHROMEEC +#include "ec.h" +#include +#endif + +/* SPI Write protect is GPIO 16 */ +#define CROS_WP_GPIO 16 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +#else + return 0; +#endif +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, CROS_WP_GPIO, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +#else + return 0; +#endif +} + +int get_write_protect_state(void) +{ + return get_gpio(CROS_WP_GPIO); +} diff --git a/src/mainboard/google/bolt/cmos.layout b/src/mainboard/google/bolt/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/bolt/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/bolt/devicetree.cb b/src/mainboard/google/bolt/devicetree.cb new file mode 100644 index 0000000000..f514bb4ff7 --- /dev/null +++ b/src/mainboard/google/bolt/devicetree.cb @@ -0,0 +1,115 @@ +chip northbridge/intel/haswell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Disable DDI2 Hotplug + register "gpu_dp_c_hotplug" = "0x00" + + # Enable DDI1 Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "6" # 500ms + register "gpu_panel_power_up_delay" = "2000" # 200ms + register "gpu_panel_power_down_delay" = "500" # 50ms + register "gpu_panel_power_backlight_on_delay" = "2000" # 200ms + register "gpu_panel_power_backlight_off_delay" = "2000" # 200ms + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "9" # ACPI(C2) = MWAIT(C7S) + register "c3_battery" = "12" # ACPI(C3) = MWAIT(C10) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "9" # ACPI(C2) = MWAIT(C7S) + register "c3_acpower" = "12" # ACPI(C3) = MWAIT(C10) + end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 off end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip ec/google/chromeec + # We only have one init function that + # we need to call to initialize the + # keyboard part of the EC. + device pnp ff.1 on # dummy address + end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/intel/wtm1/dsdt.asl b/src/mainboard/google/bolt/dsdt.asl similarity index 86% rename from src/mainboard/intel/wtm1/dsdt.asl rename to src/mainboard/google/bolt/dsdt.asl index 81e39c324d..1316ebfcd3 100644 --- a/src/mainboard/intel/wtm1/dsdt.asl +++ b/src/mainboard/google/bolt/dsdt.asl @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011 Google Inc. + * Copyright (C) 2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +25,13 @@ DefinitionBlock( "DSDT", 0x02, // DSDT revision: ACPI v2.0 "COREv4", // OEM id - "COREBOOT", // OEM table id + "COREBOOT", // OEM table id 0x20110725 // OEM revision ) { // Some generic macros #include "acpi/platform.asl" + #include "acpi/mainboard.asl" // global NVS and variables #include @@ -38,9 +39,8 @@ DefinitionBlock( // General Purpose Events //#include "acpi/gpe.asl" - #include "acpi/thermal.asl" - - #include "../../../cpu/intel/haswell/acpi/cpu.asl" + // CPU + #include Scope (\_SB) { Device (PCI0) @@ -50,9 +50,13 @@ DefinitionBlock( } } + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific #include "acpi/chromeos.asl" #include - /* Chipset specific sleep states */ + // Chipset specific sleep states #include } diff --git a/src/mainboard/google/bolt/ec.c b/src/mainboard/google/bolt/ec.c new file mode 100644 index 0000000000..0919f0feec --- /dev/null +++ b/src/mainboard/google/bolt/ec.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/bolt/ec.h b/src/mainboard/google/bolt/ec.h new file mode 100644 index 0000000000..11d2453837 --- /dev/null +++ b/src/mainboard/google/bolt/ec.h @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/bolt/elpida_4Gb_1600_x16.spd.hex b/src/mainboard/google/bolt/elpida_4Gb_1600_x16.spd.hex new file mode 100644 index 0000000000..ef36c39b49 --- /dev/null +++ b/src/mainboard/google/bolt/elpida_4Gb_1600_x16.spd.hex @@ -0,0 +1,32 @@ +92 10 0b 03 04 19 02 02 +03 52 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 81 +20 08 3c 3c 01 40 83 81 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 11 42 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 02 fe 00 +11 52 00 00 00 07 7f 37 +45 42 4a 32 30 55 47 36 +45 42 55 30 2d 47 4e 2d +46 20 30 20 02 fe 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/bolt/fadt.c b/src/mainboard/google/bolt/fadt.c new file mode 100644 index 0000000000..7afbbfa698 --- /dev/null +++ b/src/mainboard/google/bolt/fadt.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = get_pmbase(); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/bolt/gpio.h b/src/mainboard/google/bolt/gpio.h new file mode 100644 index 0000000000..ff6069c7e1 --- /dev/null +++ b/src/mainboard/google/bolt/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BOLT_GPIO_H +#define BOLT_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: PCH_LTE_WAKE_L */ + LP_GPIO_UNUSED, /* 9: UNUSED */ + LP_GPIO_ACPI_SCI, /* 10: PCH_WLAN_WAKE_L */ + LP_GPIO_UNUSED, /* 11: UNUSED */ + LP_GPIO_UNUSED, /* 12: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 13: TRACKPAD_INT_L (WAKE) */ + LP_GPIO_INPUT_INVERT, /* 14: TOUCH_INT_L (WAKE) */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_INPUT, /* 16: PCH_WP */ + LP_GPIO_UNUSED, /* 17: UNUSED */ + LP_GPIO_NATIVE, /* 18: PCIE_WLAN_CLKREQ_L */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_UNUSED, /* 20: UNUSED */ + LP_GPIO_UNUSED, /* 21: UNUSED */ + LP_GPIO_UNUSED, /* 22: UNUSED */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_UNUSED, /* 24: UNUSED */ + LP_GPIO_INPUT, /* 25: EC_IN_RW */ + LP_GPIO_UNUSED, /* 26: UNUSED */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_UNUSED, /* 28: UNUSED */ + LP_GPIO_INPUT, /* 29: NATIVE: WLAN_OFF_L */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: ACOK_BUF */ + LP_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + LP_GPIO_NATIVE, /* 33: NATIVE: SSD_DEVSLP */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: PCH_USB1_OC_L */ + LP_GPIO_NATIVE, /* 41: NATIVE: PCH_USB2_OC_L */ + LP_GPIO_UNUSED, /* 42: UNUSED */ + LP_GPIO_UNUSED, /* 43: UNUSED */ + LP_GPIO_OUT_HIGH, /* 44: PP3300_SSD_EN */ + LP_GPIO_OUT_HIGH, /* 45: PP3300_CODEC_EN */ + LP_GPIO_OUT_HIGH, /* 46: WLAN_DISABLE_L */ + LP_GPIO_UNUSED, /* 47: UNUSED */ + LP_GPIO_OUT_HIGH, /* 48: TPM_LP_EN_L */ + LP_GPIO_OUT_HIGH, /* 49: HDMI_CEC */ + LP_GPIO_UNUSED, /* 50: UNUSED */ + LP_GPIO_INPUT, /* 51: ALS_INT_L */ + LP_GPIO_INPUT, /* 52: SIM_DET */ + LP_GPIO_PIRQ, /* 53: TRACKPAD_INT_L_R (PIRQV) */ + LP_GPIO_PIRQ, /* 54: TOUCH_INT_L_R (PIRQW) */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_UNUSED, /* 56: UNUSED */ + LP_GPIO_OUT_HIGH, /* 57: PP3300_AUTOBAHN_EN */ + LP_GPIO_UNUSED, /* 58: UNUSED */ + LP_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + LP_GPIO_UNUSED, /* 60: UNUSED */ + LP_GPIO_NATIVE, /* 61: NATIVE: PCH_SUS_STAT */ + LP_GPIO_NATIVE, /* 62: NATIVE: PCH_SUSCLK */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_UNUSED, /* 72: UNUSED */ + LP_GPIO_UNUSED, /* 73: UNUSED */ + LP_GPIO_UNUSED, /* 74: UNUSED */ + LP_GPIO_UNUSED, /* 75: UNUSED */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: PCH_HDA_SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_NATIVE, /* 91: NATIVE: UART0_PCHRX_BTTX */ + LP_GPIO_NATIVE, /* 92: NATIVE: UART0_PCHTX_BTRX */ + LP_GPIO_NATIVE, /* 93: NATIVE: UART0_PCHRTS_BTCTS_L */ + LP_GPIO_NATIVE, /* 94: NATIVE: UART0_PCHCTS_BTRTS_L */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/bolt/hda_verb.h b/src/mainboard/google/bolt/hda_verb.h new file mode 100644 index 0000000000..958b6c23de --- /dev/null +++ b/src/mainboard/google/bolt/hda_verb.h @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000b, // Number of jacks (NID entries) + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - interior mobile lid */ + 0x01271c10, + 0x01271d10, + 0x01271ea6, + 0x01271fb7, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471c10, // group 1, front left/right + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + +}; + diff --git a/src/mainboard/google/bolt/mainboard.c b/src/mainboard/google/bolt/mainboard.c new file mode 100644 index 0000000000..3bf26e3f21 --- /dev/null +++ b/src/mainboard/google/bolt/mainboard.c @@ -0,0 +1,202 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include "ec.h" +#include "onboard.h" + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_LIGHTSENSOR_NAME, /* name */ + BOARD_LIGHTSENSOR_IRQ, /* instance */ + BOARD_LIGHTSENSOR_I2C_BUS, /* segment */ + BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/bolt/micron_4Gb_1600_1.35v_x16.spd.hex b/src/mainboard/google/bolt/micron_4Gb_1600_1.35v_x16.spd.hex new file mode 100644 index 0000000000..7ed2663fe1 --- /dev/null +++ b/src/mainboard/google/bolt/micron_4Gb_1600_1.35v_x16.spd.hex @@ -0,0 +1,32 @@ +92 11 0b 03 04 19 02 02 +03 11 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 81 +20 08 3c 3c 01 40 83 05 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 01 02 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2c 00 +00 00 00 00 00 00 ad 75 +34 4b 54 46 32 35 36 36 +34 48 5a 2d 31 47 36 45 +31 20 45 31 80 2c 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff diff --git a/src/mainboard/google/bolt/onboard.h b/src/mainboard/google/bolt/onboard.h new file mode 100644 index 0000000000..393fd9df2f --- /dev/null +++ b/src/mainboard/google/bolt/onboard.h @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#define BOARD_LIGHTSENSOR_NAME "lightsensor" +#define BOARD_LIGHTSENSOR_IRQ 51 /* PIRQT */ +#define BOARD_LIGHTSENSOR_I2C_BUS 2 /* I2C1 */ +#define BOARD_LIGHTSENSOR_I2C_ADDR 0x44 + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ 37 /* PIRQV */ +#define BOARD_TRACKPAD_WAKE_GPIO 13 /* GPIO13 */ +#define BOARD_TRACKPAD_I2C_BUS 1 /* I2C0 */ +#define BOARD_TRACKPAD_I2C_ADDR 0x67 + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ 38 /* PIRQW */ +#define BOARD_TOUCHSCREEN_WAKE_GPIO 14 /* GPIO14 */ +#define BOARD_TOUCHSCREEN_I2C_BUS 2 /* I2C1 */ +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a + +#endif diff --git a/src/mainboard/google/bolt/romstage.c b/src/mainboard/google/bolt/romstage.c new file mode 100644 index 0000000000..a74f10c2ef --- /dev/null +++ b/src/mainboard/google/bolt/romstage.c @@ -0,0 +1,164 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +const struct rcba_config_instruction rcba_config[] = { + + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), + RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), + RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), + RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ + + /* Disable unused devices (board specific) */ + RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), + + RCBA_END_CONFIG, +}; + +/* Copy SPD data for on-board memory */ +static void copy_spd(struct pei_data *peid) +{ + struct cbfs_file *spd_file; + int spd_index = 0; /* No GPIO selection, force index 0 for now */ + + printk(BIOS_DEBUG, "SPD index %d\n", spd_index); + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + + if (ntohl(spd_file->len) < + ((spd_index + 1) * sizeof(peid->spd_data[0]))) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file->len < sizeof(peid->spd_data[0])) + die("Missing SPD data."); + + memcpy(peid->spd_data[0], + ((char*)CBFS_SUBHEADER(spd_file)) + + spd_index * sizeof(peid->spd_data[0]), + sizeof(peid->spd_data[0])); +} + +void mainboard_romstage_entry(unsigned long bist) +{ + struct pei_data pei_data = { + pei_version: PEI_VERSION, + mchbar: DEFAULT_MCHBAR, + dmibar: DEFAULT_DMIBAR, + epbar: DEFAULT_EPBAR, + pciexbar: DEFAULT_PCIEXBAR, + smbusbar: SMBUS_IO_BASE, + wdbbar: 0x4000000, + wdbsize: 0x1000, + hpet_address: HPET_ADDR, + rcba: DEFAULT_RCBA, + pmbase: DEFAULT_PMBASE, + gpiobase: DEFAULT_GPIOBASE, + temp_mmio_base: 0xfed08000, + system_type: 5, /* ULT */ + tseg_size: CONFIG_SMM_TSEG_SIZE, + spd_addresses: { 0xff, 0x00, 0xff, 0x00 }, + ec_present: 1, + // 0 = leave channel enabled + // 1 = disable dimm 0 on channel + // 2 = disable dimm 1 on channel + // 3 = disable dimm 0+1 on channel + dimm_channel0_disabled: 2, + dimm_channel1_disabled: 2, + max_ddr3_freq: 1600, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + /* P0: HOST PORT - J7 */ + { 0x0040, 1, 0, USB_PORT_BACK_PANEL }, + /* P1: HOST PORT - J6 */ + { 0x0040, 1, 1, USB_PORT_BACK_PANEL }, + /* P2: EMPTY */ + { 0x0000, 0, USB_OC_PIN_SKIP, USB_PORT_SKIP }, + /* P3: SD CARD */ + { 0x0040, 1, USB_OC_PIN_SKIP, USB_PORT_FLEX }, + /* P4: EMPTY */ + { 0x0000, 0, USB_OC_PIN_SKIP, USB_PORT_SKIP }, + /* P5: WWAN */ + { 0x0040, 1, USB_OC_PIN_SKIP, USB_PORT_MINI_PCIE }, + /* P6: CAMERA */ + { 0x0040, 1, USB_OC_PIN_SKIP, USB_PORT_FLEX }, + /* P7: BT */ + { 0x0040, 1, USB_OC_PIN_SKIP, USB_PORT_MINI_PCIE }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1: HOST PORT - J7 */ + { 1, 1 }, /* P2: HOST PORT - J6 */ + { 0, USB_OC_PIN_SKIP }, /* P3: EMPTY */ + { 0, USB_OC_PIN_SKIP }, /* P4: EMPTY */ + }, + }; + + struct romstage_params romstage_params = { + .pei_data = &pei_data, + .gpio_map = &mainboard_gpio_map, + .rcba_config = &rcba_config[0], + .bist = bist, + .copy_spd = copy_spd, + }; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(&romstage_params); +} diff --git a/src/mainboard/google/bolt/samsung_4Gb_1600_1.35v_x16.spd.hex b/src/mainboard/google/bolt/samsung_4Gb_1600_1.35v_x16.spd.hex new file mode 100644 index 0000000000..5beb5fcf17 --- /dev/null +++ b/src/mainboard/google/bolt/samsung_4Gb_1600_1.35v_x16.spd.hex @@ -0,0 +1,32 @@ +92 11 0b 03 04 19 02 02 +03 11 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 81 +f0 0a 3c 3c 01 40 83 01 +00 80 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 11 02 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 ce 01 +00 00 00 00 00 00 6a 04 +4d 34 37 31 42 35 36 37 +34 42 48 30 2d 59 4b 30 +20 20 00 00 80 ce 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/bolt/smihandler.c b/src/mainboard/google/bolt/smihandler.c new file mode 100644 index 0000000000..ba563f11cb --- /dev/null +++ b/src/mainboard/google/bolt/smihandler.c @@ -0,0 +1,180 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include EC functions */ +#include +#include "ec.h" + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(get_pmbase() + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, get_pmbase() + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +static void bolt_wlan_off(void) +{ + u16 gpio_base = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc; + u32 gpio_conf; + + /* Make sure pin is owned by GPIO subsystem and not ACPI */ + gpio_conf = inl(gpio_base + GPIO_OWNER(0)); + gpio_conf |= GPIO_OWNER_GPIO << 29; + outl(gpio_conf, gpio_base + GPIO_OWNER(0)); + + /* Set GPIO29 config to only be reset on RSMRST */ + gpio_conf = inl(gpio_base + GPIO_RESET(0)); + gpio_conf |= GPIO_RESET_RSMRST << 29; + outl(gpio_conf, gpio_base + GPIO_RESET(0)); + + /* Set WLAN_OFF_L (GPIO29) as Output GPIO driven high */ + gpio_conf = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH; + outl(gpio_conf, gpio_base + GPIO_CONFIG0(29)); +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s3u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s5u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + break; + } + + /* Set WLAN_OFF GPIO state */ + bolt_wlan_off(); + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/bolt/thermal.h b/src/mainboard/google/bolt/thermal.h new file mode 100644 index 0000000000..32eec0e5fa --- /dev/null +++ b/src/mainboard/google/bolt/thermal.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Config TDP Sensor ID */ +#define CTDP_SENSOR_ID 0 /* PECI */ + +/* Config TDP Nominal */ +#define CTDP_NOMINAL_THRESHOLD_OFF 0 +#define CTDP_NOMINAL_THRESHOLD_ON 0 + +/* Config TDP Down */ +#define CTDP_DOWN_THRESHOLD_OFF 75 +#define CTDP_DOWN_THRESHOLD_ON 85 + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 99 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/google/butterfly/Kconfig b/src/mainboard/google/butterfly/Kconfig index b0ebe788fa..f643428ea1 100644 --- a/src/mainboard/google/butterfly/Kconfig +++ b/src/mainboard/google/butterfly/Kconfig @@ -2,7 +2,6 @@ if BOARD_GOOGLE_BUTTERFLY config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 @@ -16,6 +15,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_SMI_HANDLER select GFXUMA select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB select EARLY_CBMEM_INIT diff --git a/src/mainboard/google/butterfly/chromeos.c b/src/mainboard/google/butterfly/chromeos.c index b5a645fb24..ffa2454991 100644 --- a/src/mainboard/google/butterfly/chromeos.c +++ b/src/mainboard/google/butterfly/chromeos.c @@ -28,8 +28,6 @@ #include #include "ec.h" -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 #define WP_GPIO 6 #define DEVMODE_GPIO 54 #define FORCE_RECOVERY_MODE 0 diff --git a/src/mainboard/google/butterfly/mainboard.c b/src/mainboard/google/butterfly/mainboard.c index a1d912643d..b11c22678f 100644 --- a/src/mainboard/google/butterfly/mainboard.c +++ b/src/mainboard/google/butterfly/mainboard.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011-2012 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2011-2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -191,15 +191,15 @@ void mainboard_suspend_resume(void) outb(0xcb, 0xb2); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - int res = -1; + int res = 0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); + __func__, X86_AX); - switch (regs->eax & 0xffff) { + switch (X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -208,11 +208,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x00; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CL = 0x00; /* Use video bios default */ + res = 1; break; case 0x5f35: /* @@ -226,11 +224,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; /* Use video bios default */ + res = 1; break; case 0x5f51: /* @@ -240,148 +236,46 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0001; /* Int-LVDS */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0001; /* Int-LVDS */ + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch (X86_CH) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + X86_CH); + break; } break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x00; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) - * bit 2 = EFP - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) - * bit 6 = EFP2 - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; /* Use video bios default */ - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 1; /* Int-LVDS */ - break; - case 0x5f70: - switch (M.x86.R_CH) { - case 0: - /* Get Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CL = 0; - break; - case 1: - /* Set Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - case 2: - /* Get SG/Non-SG mode */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - M.x86.R_CH); - return 0; - } - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (*yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 *cim_verb_data; @@ -449,40 +343,19 @@ static void mainboard_init(device_t dev) } } -static int butterfly_smbios_type41(int *handle, unsigned long *current, - const char *name, u8 irq, u8 addr) -{ - struct smbios_type41 *t = (struct smbios_type41 *)*current; - int len = sizeof(struct smbios_type41); - - memset(t, 0, sizeof(struct smbios_type41)); - t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION; - t->handle = *handle; - t->length = len - 2; - t->reference_designation = smbios_add_string(t->eos, name); - t->device_type = SMBIOS_DEVICE_TYPE_OTHER; - t->device_status = 1; - t->device_type_instance = irq; - t->segment_group_number = 0; - t->bus_number = addr; - t->function_number = 0; - t->device_number = 0; - - len = t->length + smbios_string_table_len(t->eos); - *current += len; - *handle += 1; - return len; -} - static int butterfly_onboard_smbios_data(device_t dev, int *handle, unsigned long *current) { int len = 0; - len += butterfly_smbios_type41(handle, current, - BUTTERFLY_TRACKPAD_NAME, - BUTTERFLY_TRACKPAD_IRQ, - BUTTERFLY_TRACKPAD_I2C_ADDR); + len += smbios_write_type41( + current, handle, + BUTTERFLY_TRACKPAD_NAME, /* name */ + BUTTERFLY_TRACKPAD_IRQ, /* instance */ + 0, /* segment */ + BUTTERFLY_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ return len; } @@ -494,9 +367,9 @@ static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; dev->ops->get_smbios_data = butterfly_onboard_smbios_data; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/google/butterfly/mainboard_smi.c b/src/mainboard/google/butterfly/mainboard_smi.c index e2f00e17c9..a40e4288ba 100644 --- a/src/mainboard/google/butterfly/mainboard_smi.c +++ b/src/mainboard/google/butterfly/mainboard_smi.c @@ -52,7 +52,7 @@ int mainboard_io_trap_handler(int smif) return 1; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { printk(BIOS_DEBUG, "warn: unknown mainboard_smi_gpi: %x\n", gpi_sts); } diff --git a/src/mainboard/google/butterfly/romstage.c b/src/mainboard/google/butterfly/romstage.c index 5e2b713a41..02040d2c74 100644 --- a/src/mainboard/google/butterfly/romstage.c +++ b/src/mainboard/google/butterfly/romstage.c @@ -118,15 +118,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { pei_version: PEI_VERSION, mchbar: DEFAULT_MCHBAR, @@ -171,11 +169,10 @@ void main(unsigned long bist) { 0, 4, 0x0000 }, /* P12: Empty */ { 0, 4, 0x0000 }, /* P13: Empty */ }, + ddr_refresh_rate_config: 2, /* Force double refresh rate */ }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -240,14 +237,13 @@ void main(unsigned long bist) post_code(0x3a); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3c); rcba_config(); @@ -287,15 +283,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/google/cosmos/Kconfig b/src/mainboard/google/cosmos/Kconfig new file mode 100644 index 0000000000..895fd0573e --- /dev/null +++ b/src/mainboard/google/cosmos/Kconfig @@ -0,0 +1,60 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_COSMOS + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_2048 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select HAVE_HARD_RESET + select MAINBOARD_HAS_BOOTBLOCK_INIT + select RETURN_FROM_VERSTAGE + select SOC_MARVELL_BG4CD + select SPI_FLASH + select SPI_FLASH_SPANSION + +config MAINBOARD_DIR + string + default google/cosmos + +config MAINBOARD_PART_NUMBER + string + default "Cosmos" + +config MAINBOARD_VENDOR + string + default "Google" + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRAM_SIZE_MB + int + default 1024 + +endif # BOARD_GOOGLE_COSMOS diff --git a/src/mainboard/google/cosmos/Makefile.inc b/src/mainboard/google/cosmos/Makefile.inc new file mode 100644 index 0000000000..3e970fb07a --- /dev/null +++ b/src/mainboard/google/cosmos/Makefile.inc @@ -0,0 +1,40 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/cosmos/boardid.c b/src/mainboard/google/cosmos/boardid.c new file mode 100644 index 0000000000..8b61891a13 --- /dev/null +++ b/src/mainboard/google/cosmos/boardid.c @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +uint8_t board_id(void) +{ + return -1; +} diff --git a/src/cpu/samsung/exynos5250/bootblock.c b/src/mainboard/google/cosmos/bootblock.c similarity index 87% rename from src/cpu/samsung/exynos5250/bootblock.c rename to src/mainboard/google/cosmos/bootblock.c index 949468fbef..d5bffea8f0 100644 --- a/src/cpu/samsung/exynos5250/bootblock.c +++ b/src/mainboard/google/cosmos/bootblock.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 The Chromium OS Authors + * Copyright 2014 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -void bootblock_cpu_init(void); -void bootblock_cpu_init(void) +#include + +void bootblock_mainboard_init(void) { } diff --git a/src/mainboard/google/cosmos/chromeos.c b/src/mainboard/google/cosmos/chromeos.c new file mode 100644 index 0000000000..0ad05c8f6f --- /dev/null +++ b/src/mainboard/google/cosmos/chromeos.c @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return 0; +} + +int get_write_protect_state(void) +{ + return 0; +} + diff --git a/src/mainboard/google/cosmos/devicetree.cb b/src/mainboard/google/cosmos/devicetree.cb new file mode 100644 index 0000000000..b82d57cdfb --- /dev/null +++ b/src/mainboard/google/cosmos/devicetree.cb @@ -0,0 +1,23 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/marvell/bg4cd + device cpu_cluster 0 on end +end diff --git a/src/mainboard/google/cosmos/mainboard.c b/src/mainboard/google/cosmos/mainboard.c new file mode 100644 index 0000000000..5866fea606 --- /dev/null +++ b/src/mainboard/google/cosmos/mainboard.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +static void mainboard_init(device_t dev) +{ +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ +} diff --git a/src/mainboard/google/cosmos/memlayout.ld b/src/mainboard/google/cosmos/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/cosmos/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/cosmos/reset.c b/src/mainboard/google/cosmos/reset.c new file mode 100644 index 0000000000..8020fbfbed --- /dev/null +++ b/src/mainboard/google/cosmos/reset.c @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +void hard_reset(void) +{ + while (1) + ; +} diff --git a/src/mainboard/google/cosmos/romstage.c b/src/mainboard/google/cosmos/romstage.c new file mode 100644 index 0000000000..f16d782a10 --- /dev/null +++ b/src/mainboard/google/cosmos/romstage.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "timer.h" + +void main(void) +{ + void *entry; + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = timestamp_get(); + start_romstage_time = timestamp_get(); + + console_init(); + + before_dram_time = timestamp_get(); + + sdram_init(); + + after_dram_time = timestamp_get(); + + mmu_init(); + mmu_config_range(0, 4096, DCACHE_OFF); + dcache_mmu_enable(); + + cbmem_initialize_empty(); + + timestamp_init(base_time); + timestamp_add(TS_START_ROMSTAGE, start_romstage_time); + timestamp_add(TS_BEFORE_INITRAM, before_dram_time); + timestamp_add(TS_AFTER_INITRAM, after_dram_time); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add(TS_START_COPYRAM, timestamp_get()); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add(TS_END_COPYRAM, timestamp_get()); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/daisy/Kconfig b/src/mainboard/google/daisy/Kconfig new file mode 100644 index 0000000000..ef73db52d3 --- /dev/null +++ b/src/mainboard/google/daisy/Kconfig @@ -0,0 +1,56 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_DAISY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_SAMSUNG_EXYNOS5250 + select HAVE_UART_MEMORY_MAPPED + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_I2C + select BOARD_ROMSIZE_KB_4096 + select DRIVER_MAXIM_MAX77686 + select CHROMEOS + select CHROMEOS_VBNV_EC + select DRIVER_TI_TPS65090 + select MAINBOARD_HAS_NATIVE_VGA_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + +config MAINBOARD_DIR + string + default google/daisy + +config MAINBOARD_PART_NUMBER + string + default "Daisy" + +config MAX_CPUS + int + default 2 + +config DRAM_SIZE_MB + int + default 2048 + +config EC_GOOGLE_CHROMEEC_I2C_BUS + hex + default 4 + +endif # BOARD_GOOGLE_DAISY diff --git a/src/mainboard/google/snow/Makefile.inc b/src/mainboard/google/daisy/Makefile.inc similarity index 80% rename from src/mainboard/google/snow/Makefile.inc rename to src/mainboard/google/daisy/Makefile.inc index 46e366fa7d..95bf78d1b8 100644 --- a/src/mainboard/google/snow/Makefile.inc +++ b/src/mainboard/google/daisy/Makefile.inc @@ -1,7 +1,7 @@ ## ## This file is part of the coreboot project. ## -## Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. +## Copyright 2012 Google Inc. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -17,10 +17,15 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -romstage-y += mainboard.c +bootblock-y += wakeup.c + romstage-y += memory.c romstage-y += romstage.c +romstage-y += wakeup.c -# ramstage-y += ec.c -ramstage-y += ramstage.c +ramstage-y += mainboard.c ramstage-y += chromeos.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/daisy/chromeos.c b/src/mainboard/google/daisy/chromeos.c new file mode 100644 index 0000000000..cb945777bf --- /dev/null +++ b/src/mainboard/google/daisy/chromeos.c @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = EXYNOS5_GPD1; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get_value(GPIO_D16); // WP_GPIO + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = EXYNOS5_GPX3; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = gpio_get_value(GPIO_X35); // LID_GPIO + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: virtual GPIO active low */ + gpios->gpios[count].port = EXYNOS5_GPX1; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = + gpio_get_value(GPIO_X13); // POWER_GPIO + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get_value(GPIO_Y10)) // RECMODE_GPIO + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get_value(GPIO_D16); +} diff --git a/src/mainboard/google/daisy/devicetree.cb b/src/mainboard/google/daisy/devicetree.cb new file mode 100644 index 0000000000..2552e070e0 --- /dev/null +++ b/src/mainboard/google/daisy/devicetree.cb @@ -0,0 +1,33 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/samsung/exynos5250 + device cpu_cluster 0 on end + register "xres" = "1366" + register "yres" = "768" + register "framebuffer_bits_per_pixel" = "16" + # complex magic timing! + register "clkval_f" = "2" + register "upper_margin" = "14" + register "lower_margin" = "3" + register "vsync" = "5" + register "left_margin" = "80" + register "right_margin" = "48" + register "hsync" = "32" +end diff --git a/src/mainboard/google/daisy/exynos5250.h b/src/mainboard/google/daisy/exynos5250.h new file mode 100644 index 0000000000..98d36f92e4 --- /dev/null +++ b/src/mainboard/google/daisy/exynos5250.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* I2C */ +#define I2C_0_SPEED 100000 +#define I2C_SLAVE 0 + +/* Voltages */ +#define VDD_ARM_MV 1300 // 1.3V +#define VDD_INT_UV 1012500 // 1.0125V +#define VDD_MIF_MV 1000 // 1.0V +#define VDD_G3D_MV 1200 // 1.2V +#define VDD_LDO2_MV 1500 // 1.5V +#define VDD_LDO3_MV 1800 // 1.8V +#define VDD_LDO5_MV 1800 // 1.8V +#define VDD_LDO10_MV 1800 // 1.8V + diff --git a/src/mainboard/google/daisy/mainboard.c b/src/mainboard/google/daisy/mainboard.c new file mode 100644 index 0000000000..4356c474d3 --- /dev/null +++ b/src/mainboard/google/daisy/mainboard.c @@ -0,0 +1,362 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos5250.h" + +#define MMC0_GPIO_PIN (58) + +/* convenient shorthand (in MB) */ +#define DRAM_START ((uintptr_t)_dram/MiB) +#define DRAM_SIZE CONFIG_DRAM_SIZE_MB +#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */ + +static struct edid edid = { + .ha = 1366, + .va = 768, + .framebuffer_bits_per_pixel = 16, + .x_resolution = 1366, + .y_resolution = 768, + .bytes_per_line = 2 * 1366 +}; + +/* TODO: transplanted DP stuff, clean up once we have something that works */ +static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */ +static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */ +static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */ + +static void exynos_dp_bridge_setup(void) +{ + exynos_pinmux_dphpd(); + + gpio_set_value(dp_pd_l, 1); + gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT); + gpio_set_pull(dp_pd_l, GPIO_PULL_NONE); + + gpio_set_value(dp_rst_l, 0); + gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT); + gpio_set_pull(dp_rst_l, GPIO_PULL_NONE); + udelay(10); + gpio_set_value(dp_rst_l, 1); +} + +static void exynos_dp_bridge_init(void) +{ + /* De-assert PD (and possibly RST) to power up the bridge */ + gpio_set_value(dp_pd_l, 1); + gpio_set_value(dp_rst_l, 1); + + /* + * We need to wait for 90ms after bringing up the bridge since + * there is a phantom "high" on the HPD chip during its + * bootup. The phantom high comes within 7ms of de-asserting + * PD and persists for at least 15ms. The real high comes + * roughly 50ms after PD is de-asserted. The phantom high + * makes it hard for us to know when the NXP chip is up. + */ + udelay(90000); +} + +static int exynos_dp_hotplug(void) +{ + /* Check HPD. If it's high, we're all good. */ + return gpio_get_value(dp_hpd) ? 0 : 1; +} + +static void exynos_dp_reset(void) +{ + gpio_set_value(dp_pd_l, 0); + gpio_set_value(dp_rst_l, 0); + /* paranoid delay period (300ms) */ + udelay(300 * 1000); +} + +/* + * This delay is T3 in the LCD timing spec (defined as >200ms). We set + * this down to 60ms since that's the approximate maximum amount of time + * it'll take a bridge to start outputting LVDS data. The delay of + * >200ms is just a conservative value to avoid turning on the backlight + * when there's random LCD data on the screen. Shaving 140ms off the + * boot is an acceptable trade-off. + */ +#define LCD_T3_DELAY_MS 60 + +#define LCD_T5_DELAY_MS 10 +#define LCD_T6_DELAY_MS 10 + +static void backlight_pwm(void) +{ + /*Configure backlight PWM as a simple output high (100% brightness) */ + gpio_direction_output(GPIO_B20, 1); + udelay(LCD_T6_DELAY_MS * 1000); +} + +static void backlight_en(void) +{ + /* Configure GPIO for LCD_BL_EN */ + gpio_direction_output(GPIO_X30, 1); +} + +#define TPS65090_BUS 4 /* Daisy-specific */ + +#define FET1_CTRL 0x0f +#define FET4_CTRL 0x12 +#define FET6_CTRL 0x14 + +static void lcd_vdd(void) +{ + /* Enable FET6, lcd panel */ + tps65090_fet_enable(TPS65090_BUS, FET6_CTRL); +} + +static void backlight_vdd(void) +{ + /* Enable FET1, backlight */ + tps65090_fet_enable(TPS65090_BUS, FET1_CTRL); + udelay(LCD_T5_DELAY_MS * 1000); +} + +static void sdmmc_vdd(void) +{ + /* Enable FET4, P3.3V_SDCARD */ + tps65090_fet_enable(TPS65090_BUS, FET4_CTRL); +} + +static enum exynos5_gpio_pin usb_host_vbus = GPIO_X11; +static enum exynos5_gpio_pin usb_drd_vbus = GPIO_X27; +/* static enum exynos5_gpio_pin hsic_reset_l = GPIO_E10; */ + +static void prepare_usb(void) +{ + /* Kick this reset off early so it gets at least 100ms to settle */ + reset_usb_drd_dwc3(); +} + +static void setup_usb(void) +{ + /* HSIC not needed in firmware on this board */ + setup_usb_drd_phy(); + setup_usb_drd_dwc3(); + setup_usb_host_phy(0); + + gpio_direction_output(usb_host_vbus, 1); + gpio_direction_output(usb_drd_vbus, 1); +} + +//static struct video_info smdk5250_dp_config = { +static struct video_info dp_video_info = { + /* FIXME: fix video_info struct to use const for name */ + .name = (char *)"eDP-LVDS NXP PTN3460", + + .h_sync_polarity = 0, + .v_sync_polarity = 0, + .interlaced = 0, + + .color_space = COLOR_RGB, + .dynamic_range = VESA, + .ycbcr_coeff = COLOR_YCBCR601, + .color_depth = COLOR_8, + + .link_rate = LINK_RATE_2_70GBPS, + .lane_count = LANE_COUNT2, +}; + +/* FIXME: move some place more appropriate */ +#define MAX_DP_TRIES 5 + +/* + * This function disables the USB3.0 PLL to save power + */ +static void disable_usb30_pll(void) +{ + enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11; + + gpio_direction_output(usb3_pll_l, 0); +} + +static void setup_storage(void) +{ + /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ + if (clock_set_mshci(PERIPH_ID_SDMMC0)) + printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__); + if (gpio_direction_output(MMC0_GPIO_PIN, 1)) { + printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__); + } + gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE); + gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X); + exynos_pinmux_sdmmc0(); + + /* MMC2: Removable, 4 bit mode, no GPIO. */ + /* (Must be after romstage to avoid breaking SDMMC boot.) */ + clock_set_mshci(PERIPH_ID_SDMMC2); + exynos_pinmux_sdmmc2(); +} + +static void gpio_init(void) +{ + /* Set up the I2C busses. */ + exynos_pinmux_i2c0(); + exynos_pinmux_i2c1(); + exynos_pinmux_i2c2(); + exynos_pinmux_i2c3(); + exynos_pinmux_i2c4(); + exynos_pinmux_i2c7(); + + /* Set up the GPIOs used to arbitrate for I2C bus 4. */ + gpio_set_pull(GPIO_F03, GPIO_PULL_NONE); + gpio_set_pull(GPIO_E04, GPIO_PULL_NONE); + gpio_direction_output(GPIO_F03, 1); + gpio_direction_input(GPIO_E04); + + /* Set up the GPIO used to enable the audio codec. */ + gpio_set_pull(GPIO_X17, GPIO_PULL_NONE); + gpio_set_pull(GPIO_X15, GPIO_PULL_NONE); + gpio_direction_output(GPIO_X17, 1); + gpio_direction_output(GPIO_X15, 1); + + /* Set up the I2S busses. */ + exynos_pinmux_i2s0(); + exynos_pinmux_i2s1(); +} + +/* this happens after cpu_init where exynos resources are set */ +static void mainboard_init(device_t dev) +{ + int dp_tries; + struct s5p_dp_device dp_device = { + .base = exynos_dp1, + .video_info = &dp_video_info, + }; + void *fb_addr = (void *)(get_fb_base_kb() * KiB); + + prepare_usb(); + gpio_init(); + setup_storage(); + + i2c_init(TPS65090_BUS, I2C_0_SPEED, I2C_SLAVE); + i2c_init(7, I2C_0_SPEED, I2C_SLAVE); + + tmu_init(&exynos5250_tmu_info); + + /* Clock Gating all the unused IP's to save power */ + clock_gate(); + + /* Disable USB3.0 PLL to save 250mW of power */ + disable_usb30_pll(); + + sdmmc_vdd(); + + set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr); + + lcd_vdd(); + + // FIXME: should timeout + do { + udelay(50); + } while (!exynos_dp_hotplug()); + + exynos_dp_bridge_setup(); + for (dp_tries = 1; dp_tries <= MAX_DP_TRIES; dp_tries++) { + exynos_dp_bridge_init(); + if (exynos_dp_hotplug()) { + exynos_dp_reset(); + continue; + } + + if (dp_controller_init(&dp_device)) + continue; + + udelay(LCD_T3_DELAY_MS * 1000); + + backlight_vdd(); + backlight_pwm(); + backlight_en(); + /* if we're here, we're successful */ + break; + } + + if (dp_tries > MAX_DP_TRIES) + printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__); + + setup_usb(); + + // Uncomment to get excessive GPIO output: + // gpio_info(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; + + /* set up dcache and MMU */ + /* FIXME: this should happen via resource allocator */ + exynos5250_config_l2_cache(); + mmu_init(); + mmu_config_range(0, DRAM_START, DCACHE_OFF); + mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF); + dcache_mmu_enable(); + + const unsigned epll_hz = 192000000; + const unsigned sample_rate = 48000; + const unsigned lr_frame_size = 256; + clock_epll_set_rate(epll_hz); + clock_select_i2s_clk_source(); + clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size); + + power_enable_xclkout(); +} + +struct chip_operations mainboard_ops = { + .name = "Samsung/Google ARM Chromebook", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} diff --git a/src/mainboard/google/daisy/memlayout.ld b/src/mainboard/google/daisy/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/daisy/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/snow/memory.c b/src/mainboard/google/daisy/memory.c similarity index 85% rename from src/mainboard/google/snow/memory.c rename to src/mainboard/google/daisy/memory.c index ba8c91fd6e..71abb8142b 100644 --- a/src/mainboard/google/snow/memory.c +++ b/src/mainboard/google/daisy/memory.c @@ -1,9 +1,8 @@ /* - * This file is part of the coreboot project. It is based off code - * from Das U-Boot. + * This file is part of the coreboot project. * * Copyright (C) 2012 Samsung Electronics - * Copyright (C) 2013 The ChromiumOS Authors. + * Copyright 2013 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,17 +18,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include - -#include "mainboard.h" - -struct mem_timings mem_timings[] = { +const struct mem_timings mem_timings[] = { { .mem_manuf = MEM_MANUF_ELPIDA, .mem_type = DDR_MODE_DDR3, @@ -450,35 +447,88 @@ struct mem_timings mem_timings[] = { } }; +#define BOARD_ID0_GPIO 88 /* GPD0, pin 0 */ +#define BOARD_ID1_GPIO 89 /* GPD0, pin 1 */ + +enum board_config { + DAISY_CONFIG_UNKNOWN = -1, + DAISY_CONFIG_SAMSUNG_EVT, + DAISY_CONFIG_ELPIDA_EVT, + DAISY_CONFIG_SAMSUNG_DVT, + DAISY_CONFIG_ELPIDA_DVT, + DAISY_CONFIG_SAMSUNG_PVT, + DAISY_CONFIG_ELPIDA_PVT, + DAISY_CONFIG_SAMSUNG_MP, + DAISY_CONFIG_ELPIDA_MP, + DAISY_CONFIG_RSVD, +}; + +struct { + enum mvl3 id0, id1; + enum board_config config; +} id_map[] = { + /* ID0 ID1 config */ + { LOGIC_0, LOGIC_0, DAISY_CONFIG_SAMSUNG_MP }, + { LOGIC_0, LOGIC_1, DAISY_CONFIG_ELPIDA_MP }, + { LOGIC_1, LOGIC_0, DAISY_CONFIG_SAMSUNG_DVT }, + { LOGIC_1, LOGIC_1, DAISY_CONFIG_ELPIDA_DVT }, + { LOGIC_0, LOGIC_Z, DAISY_CONFIG_SAMSUNG_PVT }, + { LOGIC_1, LOGIC_Z, DAISY_CONFIG_ELPIDA_PVT }, + { LOGIC_Z, LOGIC_0, DAISY_CONFIG_SAMSUNG_MP }, + { LOGIC_Z, LOGIC_Z, DAISY_CONFIG_ELPIDA_MP }, + { LOGIC_Z, LOGIC_1, DAISY_CONFIG_RSVD }, +}; + +static int board_get_config(void) +{ + int i; + int id0, id1; + enum board_config config = DAISY_CONFIG_UNKNOWN; + + id0 = gpio_read_mvl3(BOARD_ID0_GPIO); + id1 = gpio_read_mvl3(BOARD_ID1_GPIO); + if (id0 < 0 || id1 < 0) + return -1; + + for (i = 0; i < ARRAY_SIZE(id_map); i++) { + if (id0 == id_map[i].id0 && id1 == id_map[i].id1) { + config = id_map[i].config; + break; + } + } + + return config; +} + struct mem_timings *get_mem_timings(void) { int i; - enum snow_board_config board_config; + enum board_config config; enum ddr_mode mem_type; unsigned int frequency_mhz; enum mem_manuf mem_manuf; - struct mem_timings *mem; - - board_config = board_get_config(); - switch (board_config) { - case SNOW_CONFIG_ELPIDA_EVT: - case SNOW_CONFIG_ELPIDA_DVT: - case SNOW_CONFIG_ELPIDA_PVT: - case SNOW_CONFIG_ELPIDA_MP: + const struct mem_timings *mem; + + config = board_get_config(); + switch (config) { + case DAISY_CONFIG_ELPIDA_EVT: + case DAISY_CONFIG_ELPIDA_DVT: + case DAISY_CONFIG_ELPIDA_PVT: + case DAISY_CONFIG_ELPIDA_MP: mem_manuf = MEM_MANUF_ELPIDA; mem_type = DDR_MODE_DDR3; frequency_mhz = 800; break; - case SNOW_CONFIG_SAMSUNG_EVT: - case SNOW_CONFIG_SAMSUNG_DVT: - case SNOW_CONFIG_SAMSUNG_PVT: - case SNOW_CONFIG_SAMSUNG_MP: + case DAISY_CONFIG_SAMSUNG_EVT: + case DAISY_CONFIG_SAMSUNG_DVT: + case DAISY_CONFIG_SAMSUNG_PVT: + case DAISY_CONFIG_SAMSUNG_MP: mem_manuf = MEM_MANUF_SAMSUNG; mem_type = DDR_MODE_DDR3; frequency_mhz = 800; break; default: - printk(BIOS_CRIT, "Unable to determine board config\n"); + printk(BIOS_CRIT, "Unknown board configuration.\n"); return NULL; } @@ -487,7 +537,7 @@ struct mem_timings *get_mem_timings(void) if (mem->mem_type == mem_type && mem->frequency_mhz == frequency_mhz && mem->mem_manuf == mem_manuf) - return mem; + return (struct mem_timings *)mem; } return NULL; diff --git a/src/mainboard/google/daisy/romstage.c b/src/mainboard/google/daisy/romstage.c new file mode 100644 index 0000000000..5463fe4ff3 --- /dev/null +++ b/src/mainboard/google/daisy/romstage.c @@ -0,0 +1,195 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos5250.h" + +#define PMIC_BUS 0 + +static void setup_power(int is_resume) +{ + int error = 0; + + power_init(); + + if (is_resume) { + return; + } + + /* Initialize I2C bus to configure PMIC. */ + exynos_pinmux_i2c0(); + i2c_init(0, I2C_0_SPEED, 0x00); + + printk(BIOS_DEBUG, "%s: Setting up PMIC...\n", __func__); + /* + * We're using CR1616 coin cell battery that is non-rechargeable + * battery. But, BBCHOSTEN bit of the BBAT Charger Register in + * MAX77686 is enabled by default for charging coin cell. + * + * Also, we cannot meet the coin cell reverse current spec. in UL + * standard if BBCHOSTEN bit is enabled. + * + * Disable Coin BATT Charging + */ + error = max77686_disable_backup_batt(PMIC_BUS); + + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK2, VDD_ARM_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK3, VDD_INT_UV, + REG_ENABLE, MAX77686_UV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK1, VDD_MIF_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK4, VDD_G3D_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO2, VDD_LDO2_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO3, VDD_LDO3_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO5, VDD_LDO5_MV, + REG_ENABLE, MAX77686_MV); + error |= max77686_volsetting(PMIC_BUS, PMIC_LDO10, VDD_LDO10_MV, + REG_ENABLE, MAX77686_MV); + + error |= max77686_enable_32khz_cp(PMIC_BUS); + + if (error) { + printk(BIOS_CRIT, "%s: PMIC error: %#x\n", __func__, error); + die("Failed to intialize PMIC.\n"); + } +} + +static void setup_graphics(void) +{ + exynos_pinmux_dphpd(); +} + +static void setup_gpio(void) +{ + gpio_direction_input(GPIO_D16); // WP_GPIO + gpio_set_pull(GPIO_D16, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_Y10); // RECMODE_GPIO + gpio_set_pull(GPIO_Y10, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X35); // LID_GPIO + gpio_set_pull(GPIO_X35, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X13); // POWER_GPIO + gpio_set_pull(GPIO_X13, GPIO_PULL_NONE); +} + +static void setup_memory(struct mem_timings *mem, int is_resume) +{ + printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: %d\n", + mem->mem_manuf, + mem->mem_type, + mem->mpll_mdiv, + mem->frequency_mhz); + + if (ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE, !is_resume)) { + die("Failed to initialize memory controller.\n"); + } +} + +static struct mem_timings *setup_clock(void) +{ + struct mem_timings *mem = get_mem_timings(); + struct arm_clk_ratios *arm_ratios = get_arm_clk_ratios(); + if (!mem) { + die("Unable to auto-detect memory timings\n"); + } + system_clock_init(mem, arm_ratios); + return mem; +} + +void main(void) +{ + struct mem_timings *mem; + void *entry; + int is_resume = (get_wakeup_state() != IS_NOT_WAKEUP); + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = timestamp_get(); + + start_romstage_time = timestamp_get(); + + /* Clock must be initialized before console_init, otherwise you may need + * to re-initialize serial console drivers again. */ + mem = setup_clock(); + + console_init(); + exception_init(); + + setup_power(is_resume); + + before_dram_time = timestamp_get(); + + setup_memory(mem, is_resume); + + after_dram_time = timestamp_get(); + + /* This needs to happen on normal boots and on resume. */ + trustzone_init(); + + if (is_resume) { + wakeup(); + } + + setup_gpio(); + setup_graphics(); + + /* Set SPI (primary CBFS media) clock to 50MHz and configure pinmux. */ + exynos_pinmux_spi1(); + clock_set_rate(PERIPH_ID_SPI1, 50000000); + + cbmem_initialize_empty(); + + timestamp_init(base_time); + timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); + timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); + timestamp_add(TS_AFTER_INITRAM, after_dram_time ); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/daisy/wakeup.c b/src/mainboard/google/daisy/wakeup.c new file mode 100644 index 0000000000..ffd6a4521a --- /dev/null +++ b/src/mainboard/google/daisy/wakeup.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +int wakeup_need_reset(void) +{ + /* The "wake up" event is not reliable (known as "bad wakeup") and needs + * reset if GPIO value is high. */ + return gpio_get_value(GPIO_Y10); +} + diff --git a/src/mainboard/google/falco/Elpida_EDJ4216EFBG.spd.hex b/src/mainboard/google/falco/Elpida_EDJ4216EFBG.spd.hex new file mode 100644 index 0000000000..eb41f0bfb1 --- /dev/null +++ b/src/mainboard/google/falco/Elpida_EDJ4216EFBG.spd.hex @@ -0,0 +1,17 @@ +# Elpida EDJ4216EFBG-GN-F +92 12 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 81 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 A1 CE +45 44 4A 34 32 31 36 45 46 42 47 2D 47 4E 2D 46 +00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/falco/Hynix_HMT425S6AFR6A.spd.hex b/src/mainboard/google/falco/Hynix_HMT425S6AFR6A.spd.hex new file mode 100644 index 0000000000..7b0932743d --- /dev/null +++ b/src/mainboard/google/falco/Hynix_HMT425S6AFR6A.spd.hex @@ -0,0 +1,17 @@ +# Hynix HMT425S6AFR6A-PBA +92 12 0B 03 04 19 02 02 03 52 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 01 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 62 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 01 00 00 00 00 00 00 FF AB +48 4D 54 34 32 35 53 36 41 46 52 36 41 2D 50 42 +20 20 4E 30 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/falco/Kconfig b/src/mainboard/google/falco/Kconfig new file mode 100644 index 0000000000..6542dc37e8 --- /dev/null +++ b/src/mainboard/google/falco/Kconfig @@ -0,0 +1,55 @@ +if BOARD_GOOGLE_FALCO + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_HASWELL + select SOUTHBRIDGE_INTEL_LYNXPOINT + select INTEL_LYNXPOINT_LP + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select MAINBOARD_HAS_NATIVE_VGA_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config MAINBOARD_DIR + string + default google/falco + +config MAINBOARD_PART_NUMBER + string + default "Falco" + +config MMCONF_BASE_ADDRESS + hex + default 0xf0000000 + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/falco/Makefile.inc b/src/mainboard/google/falco/Makefile.inc new file mode 100644 index 0000000000..416e9c55fa --- /dev/null +++ b/src/mainboard/google/falco/Makefile.inc @@ -0,0 +1,54 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += gma.c i915io.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +## DIMM SPD for on-board memory +SPD_BIN = $(obj)/spd.bin + +# Order of names in SPD_SOURCES is important! +SPD_SOURCES = Micron_4KTF25664HZ # 4GB / CH0 + CH1 (RAM_ID=000) +SPD_SOURCES += Hynix_HMT425S6AFR6A # 4GB / CH0 + CH1 (RAM_ID=001) +SPD_SOURCES += Elpida_EDJ4216EFBG # 4GB / CH0 + CH1 (RAM_ID=010) +SPD_SOURCES += Micron_4KTF25664HZ # 2GB / CH0 only (RAM_ID=011) +SPD_SOURCES += Hynix_HMT425S6AFR6A # 2GB / CH0 only (RAM_ID=100) +SPD_SOURCES += Elpida_EDJ4216EFBG # 2GB / CH0 only (RAM_ID=101) +SPD_SOURCES += Samsung_M471B5674QH0 # 4GB / CH0 + CH1 (RAM_ID=110) +SPD_SOURCES += Samsung_M471B5674QH0 # 2GB / CH0 only (RAM_ID=111) + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab +spd.bin-position := 0xfffec000 diff --git a/src/mainboard/google/falco/Micron_4KTF25664HZ.spd.hex b/src/mainboard/google/falco/Micron_4KTF25664HZ.spd.hex new file mode 100644 index 0000000000..cbe9e4fbfe --- /dev/null +++ b/src/mainboard/google/falco/Micron_4KTF25664HZ.spd.hex @@ -0,0 +1,17 @@ +# Micron 4KTF25664HZ-1G6E1 +92 11 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2C 00 00 00 00 00 00 00 AD 75 +34 4B 54 46 32 35 36 36 34 48 5A 2D 31 47 36 45 +31 20 45 31 80 2C 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/falco/Samsung_M471B5674QH0.spd.hex b/src/mainboard/google/falco/Samsung_M471B5674QH0.spd.hex new file mode 100644 index 0000000000..c2a23cdebf --- /dev/null +++ b/src/mainboard/google/falco/Samsung_M471B5674QH0.spd.hex @@ -0,0 +1,17 @@ +# Samsung M471B5674QH0-YK0 (K4B4G1646Q) +92 12 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 01 +00 00 00 00 00 00 00 00 00 88 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 11 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 CE 01 00 00 00 00 00 00 6C F9 +4D 34 37 31 42 35 36 37 34 51 48 30 2D 59 4B 30 +20 20 00 00 80 CE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/falco/acpi/chromeos.asl b/src/mainboard/google/falco/acpi/chromeos.asl new file mode 100644 index 0000000000..4e9035be3b --- /dev/null +++ b/src/mainboard/google/falco/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "LynxPoint" }, // no recovery button + Package () { 0x0003, 1, 58, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/falco/acpi/ec.asl b/src/mainboard/google/falco/acpi/ec.asl new file mode 100644 index 0000000000..438e31e6b3 --- /dev/null +++ b/src/mainboard/google/falco/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/google/falco/acpi/haswell_pci_irqs.asl b/src/mainboard/google/falco/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/falco/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/falco/acpi/mainboard.asl b/src/mainboard/google/falco/acpi/mainboard.asl new file mode 100644 index 0000000000..84e8a255d3 --- /dev/null +++ b/src/mainboard/google/falco/acpi/mainboard.asl @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name(_HID, EisaId("PNP0C0D")) + Method(_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } + + Device (TPAD) + { + Name (_ADR, 0x0) + Name (_UID, 1) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + + VendorShort (ADDR) + { + BOARD_TRACKPAD_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } + + Device (TSCR) + { + Name (_ADR, 0x0) + Name (_UID, 2) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + + VendorShort (ADDR) + { + BOARD_TOUCHSCREEN_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TOUCHSCREEN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/falco/acpi/platform.asl b/src/mainboard/google/falco/acpi/platform.asl new file mode 100644 index 0000000000..208d76a0e9 --- /dev/null +++ b/src/mainboard/google/falco/acpi/platform.asl @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + /* Update AC status */ + Store (\_SB.PCI0.LPCB.EC0.ACEX, Local0) + if (LNotEqual (Local0, \PWRS)) { + Store (Local0, \PWRS) + Notify (\_SB.PCI0.LPCB.EC0.AC, 0x80) + } + + /* Update LID status */ + Store (\_SB.PCI0.LPCB.EC0.LIDS, Local0) + if (LNotEqual (Local0, \LIDS)) { + Store (Local0, \LIDS) + Notify (\_SB.LID0, 0x80) + } + + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/falco/acpi/superio.asl b/src/mainboard/google/falco/acpi/superio.asl new file mode 100644 index 0000000000..18da3d07fd --- /dev/null +++ b/src/mainboard/google/falco/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/falco/acpi/thermal.asl b/src/mainboard/google/falco/acpi/thermal.asl new file mode 100644 index 0000000000..d07c8070f1 --- /dev/null +++ b/src/mainboard/google/falco/acpi/thermal.asl @@ -0,0 +1,137 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + // Handler for throttle requests on this platform + // 0 = Stop throttling + // 1 = Start throttling + Method (THRT, 1, Serialized) + { + If (LEqual (Arg0, 0)) { + /* Disable Power Limit */ + \_SB.PCI0.MCHC.CTLD () + } Else { + /* Enable Power Limit */ + \_SB.PCI0.MCHC.CTLE (\F0PW) + } + } + + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (TCHK, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + Method (_TMP, 0, Serialized) + { + // Get temperature from EC in deci-kelvin + Store (TCHK (), Local0) + + // Critical temperature in deci-kelvin + Store (CTOK (\TCRT), Local1) + + If (LGreaterEqual (Local0, Local1)) { + Store ("CRITICAL TEMPERATURE", Debug) + Store (Local0, Debug) + + // Wait 1 second for EC to re-poll + Sleep (1000) + + // Re-read temperature from EC + Store (TCHK (), Local0) + + Store ("RE-READ TEMPERATURE", Debug) + Store (Local0, Debug) + } + + Return (Local0) + } + } +} + diff --git a/src/mainboard/google/falco/acpi/video.asl b/src/mainboard/google/falco/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/falco/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/falco/acpi_tables.c b/src/mainboard/google/falco/acpi_tables.c new file mode 100644 index 0000000000..ba084a11d9 --- /dev/null +++ b/src/mainboard/google/falco/acpi_tables.c @@ -0,0 +1,286 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +#include +#include +#include "thermal.h" + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->tmps = TEMPERATURE_SENSOR_ID; + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->f0pw = EC_THROTTLE_POWER_LIMIT; + gnvs->flvl = 1; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* CBMEM TOC */ + gnvs->cmem = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +#if CONFIG_CHROMEOS + // TODO(reinauer) this could move elsewhere? + chromeos_init_vboot(&(gnvs->chromeos)); + + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif + + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/falco/chromeos.c b/src/mainboard/google/falco/chromeos.c new file mode 100644 index 0000000000..913b6f33fc --- /dev/null +++ b/src/mainboard/google/falco/chromeos.c @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_EC_GOOGLE_CHROMEEC +#include "ec.h" +#include +#endif + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +#else + return 0; +#endif +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, 58, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +#else + return 0; +#endif +} + +int get_write_protect_state(void) +{ + return get_gpio(58); +} diff --git a/src/mainboard/google/falco/cmos.layout b/src/mainboard/google/falco/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/falco/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/falco/devicetree.cb b/src/mainboard/google/falco/devicetree.cb new file mode 100644 index 0000000000..428a0609aa --- /dev/null +++ b/src/mainboard/google/falco/devicetree.cb @@ -0,0 +1,121 @@ +chip northbridge/intel/haswell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Disable DisplayPort C Hotplug + register "gpu_dp_c_hotplug" = "0x00" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "5" # 400ms (T4) + register "gpu_panel_power_up_delay" = "600" # 60ms (T1+T2) + register "gpu_panel_power_down_delay" = "600" # 60ms (T3+T7) + register "gpu_panel_power_backlight_on_delay" = "2100" # 210ms (T5) + register "gpu_panel_power_backlight_off_delay" = "2100" # 210ms (T6) + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) + end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + # Force enable ASPM for PCIe Port 1 + register "pcie_port_force_aspm" = "0x01" + + # Disable PCIe CLKOUT 1-5 and CLKOUT_XDP + register "icc_clock_disable" = "0x013e0000" + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 off end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip ec/google/chromeec + # We only have one init function that + # we need to call to initialize the + # keyboard part of the EC. + device pnp ff.1 on # dummy address + end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/google/falco/dsdt.asl b/src/mainboard/google/falco/dsdt.asl new file mode 100644 index 0000000000..1316ebfcd3 --- /dev/null +++ b/src/mainboard/google/falco/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + #include "acpi/mainboard.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include +} diff --git a/src/mainboard/google/falco/ec.c b/src/mainboard/google/falco/ec.c new file mode 100644 index 0000000000..0919f0feec --- /dev/null +++ b/src/mainboard/google/falco/ec.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/falco/ec.h b/src/mainboard/google/falco/ec.h new file mode 100644 index 0000000000..c61d3da233 --- /dev/null +++ b/src/mainboard/google/falco/ec.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/falco/fadt.c b/src/mainboard/google/falco/fadt.c new file mode 100644 index 0000000000..7afbbfa698 --- /dev/null +++ b/src/mainboard/google/falco/fadt.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = get_pmbase(); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/falco/gma.c b/src/mainboard/google/falco/gma.c new file mode 100644 index 0000000000..8e47ed6d00 --- /dev/null +++ b/src/mainboard/google/falco/gma.c @@ -0,0 +1,255 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "mainboard.h" + +/* + * Here is the rough outline of how we bring up the display: + * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD + * 2. Source determines video mode by reading DPCD receiver capability field + * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD + * 0000Dh). + * 3. Sink replies DPCD receiver capability field. + * 4. Source starts EDID read thru I2C-over-AUX. + * 5. Sink replies EDID thru I2C-over-AUX. + * 6. Source determines link configuration, such as MAX_LINK_RATE and + * MAX_LANE_COUNT. Source also determines which type of eDP Authentication + * method to use and writes DPCD link configuration field (DPCD 00100h to + * 0010Ah) including eDP configuration set (DPCD 0010Ah). + * 7. Source starts link training. Sink does clock recovery and equalization. + * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh). + * 9. Sink replies DPCD link status field. If main link is not stable, Source + * repeats Step 7. + * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video + * parameters and recovers stream clock. + * 11. Source sends video data. + */ + +/* how many bytes do we need for the framebuffer? + * Well, this gets messy. To get an exact answer, we have + * to ask the panel, but we'd rather zero the memory + * and set up the gtt while the panel powers up. So, + * we take a reasonable guess, secure in the knowledge that the + * MRC has to overestimate the number of bytes used. + * 8 MiB is a very safe guess. There may be a better way later, but + * fact is, the initial framebuffer is only very temporary. And taking + * a little long is ok; this is done much faster than the AUX + * channel is ready for IO. + */ +#define FRAME_BUFFER_BYTES (8*MiB) +/* how many 4096-byte pages do we need for the framebuffer? + * There are hard ways to get this, and easy ways: + * there are FRAME_BUFFER_BYTES/4096 pages, since pages are 4096 + * on this chip (and in fact every Intel graphics chip we've seen). + */ +#define FRAME_BUFFER_PAGES (FRAME_BUFFER_BYTES/(4096)) + +extern int oprom_is_loaded; + +static int i915_init_done = 0; + +/* fill the palette. */ +static void palette(void) +{ + int i; + unsigned long color = 0; + + for(i = 0; i < 256; i++, color += 0x010101){ + gtt_write(_LGC_PALETTE_A + (i<<2),color); + } +} + +void mainboard_train_link(struct intel_dp *intel_dp) +{ + u8 read_val; + u8 link_status[DP_LINK_STATUS_SIZE]; + + gtt_write(DP_TP_CTL(intel_dp->port),DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE); + gtt_write(DP_A, DP_PORT_EN | DP_LINK_TRAIN_PAT_1 | DP_LINK_TRAIN_PAT_1_CPT | DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0 | DP_PORT_WIDTH_1 | DP_PLL_FREQ_270MHZ | DP_SYNC_VS_HIGH |0x80000011); + + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, DP_TRAINING_PATTERN_1 | DP_LINK_QUAL_PATTERN_DISABLE | DP_SYMBOL_ERROR_COUNT_BOTH); + intel_dp_get_lane_count(intel_dp, &read_val); + intel_dp_set_training_lane0(intel_dp, DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0); + intel_dp_get_link_status(intel_dp, link_status); + + gtt_write(DP_TP_CTL(intel_dp->port),DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT2); + + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, DP_TRAINING_PATTERN_2 | DP_LINK_QUAL_PATTERN_DISABLE | DP_SYMBOL_ERROR_COUNT_BOTH); + intel_dp_get_link_status(intel_dp, link_status); + intel_dp_get_lane_align_status(intel_dp, &read_val); + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, DP_TRAINING_PATTERN_DISABLE | DP_LINK_QUAL_PATTERN_DISABLE | DP_SYMBOL_ERROR_COUNT_BOTH); +} + +#define TEST_GFX 0 + +#if TEST_GFX +static void test_gfx(struct intel_dp *dp) +{ + int i; + + /* This is a sanity test code which fills the screen with two bands -- + green and blue. It is very useful to ensure all the initializations + are made right. Thus, to be used only for testing, not otherwise + */ + for (i = 0; i < (dp->edid.va - 4); i++) { + u32 *l; + int j; + u32 tcolor = 0x0ff; + for (j = 0; j < (dp->edid.ha-4); j++) { + if (j == (dp->edid.ha/2)) { + tcolor = 0xff00; + } + l = (u32*)(graphics + i * dp->stride + j * sizeof(tcolor)); + memcpy(l,&tcolor,sizeof(tcolor)); + } + } +} +#else +static void test_gfx(struct intel_dp *dp) {} +#endif + + +void mainboard_set_port_clk_dp(struct intel_dp *intel_dp) +{ + u32 ddi_pll_sel = 0; + + switch (intel_dp->link_bw) { + case DP_LINK_BW_1_62: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; + break; + case DP_LINK_BW_2_7: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; + break; + case DP_LINK_BW_5_4: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; + break; + default: + printk(BIOS_ERR, "invalid link bw %d\n", intel_dp->link_bw); + return; + } + + gtt_write(PORT_CLK_SEL(intel_dp->port), ddi_pll_sel); +} + +int panel_lightup(struct intel_dp *dp, unsigned int init_fb) +{ + int i; + int edid_ok; + int pixels = FRAME_BUFFER_BYTES/64; + + void runio(struct intel_dp *dp); + + dp->gen = 8; // This is gen 8 which we believe is Haswell + dp->is_haswell = 1; + dp->DP = 0x2; + /* These values are used for training the link */ + dp->lane_count = 2; + dp->link_bw = DP_LINK_BW_2_7; + dp->pipe = PIPE_A; + dp->port = PORT_A; + dp->plane = PLANE_A; + dp->clock = 160000; + dp->pipe_bits_per_pixel = 32; + dp->type = INTEL_OUTPUT_EDP; + dp->output_reg = DP_A; + /* observed from YABEL. */ + dp->aux_clock_divider = 0xe1; + dp->precharge = 3; + + /* 1. Normal mode: Set the first page to zero and make + all GTT entries point to the same page + 2. Developer/Recovery mode: We do not zero out all + the pages pointed to by GTT in order to avoid wasting time */ + if (init_fb){ + set_translation_table(0, FRAME_BUFFER_PAGES, dp->physbase, 4096); + memset((void *)dp->graphics, 0x55, FRAME_BUFFER_PAGES*4096); + } else { + set_translation_table(0, FRAME_BUFFER_PAGES, dp->physbase, 0); + memset((void*)dp->graphics, 0, 4096); + } + + dp->address = 0x50; + + if ( !intel_dp_get_dpcd(dp) ) + goto fail; + + intel_dp_i2c_aux_ch(dp, MODE_I2C_WRITE, 0, NULL); + for(dp->edidlen = i = 0; i < sizeof(dp->rawedid); i++){ + if (intel_dp_i2c_aux_ch(dp, MODE_I2C_READ, + 0x50, &dp->rawedid[i]) < 0) + break; + dp->edidlen++; + } + + edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid, 0); + printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok); + + compute_display_params(dp); + + intel_ddi_set_pipe_settings(dp); + + runio(dp); + + palette(); + + pixels = dp->edid.mode.ha * (dp->edid.mode.va-4) * 4; + printk(BIOS_SPEW, "ha=%d, va=%d\n",dp->edid.mode.ha, dp->edid.mode.va); + + test_gfx(dp); + + set_vbe_mode_info_valid(&dp->edid, (uintptr_t)dp->graphics); + i915_init_done = 1; + oprom_is_loaded = 1; + return 1; + +fail: + printk(BIOS_SPEW, "Graphics could not be started;"); + printk(BIOS_SPEW, "Returning.\n"); + return 0; +} diff --git a/src/mainboard/google/falco/gpio.h b/src/mainboard/google/falco/gpio.h new file mode 100644 index 0000000000..3af0d59c7f --- /dev/null +++ b/src/mainboard/google/falco/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FALCO_GPIO_H +#define FALCO_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: LTE_WAKE_L_Q */ + LP_GPIO_INPUT, /* 9: RAM_ID1 */ + LP_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + LP_GPIO_UNUSED, /* 11: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 12: TRACKPAD_INT_L (WAKE) */ + LP_GPIO_INPUT, /* 13: RAM_ID0 */ + LP_GPIO_INPUT, /* 14: EC_IN_RW */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 16: UNUSED */ + LP_GPIO_UNUSED, /* 17: UNUSED */ + LP_GPIO_NATIVE, /* 18: PCIE_CLKREQ_WLAN# */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_UNUSED, /* 20: UNUSED */ + LP_GPIO_UNUSED, /* 21: UNUSED */ + LP_GPIO_UNUSED, /* 22: UNUSED */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_UNUSED, /* 24: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 25: TOUCH_INT_L (WAKE) */ + LP_GPIO_UNUSED, /* 26: UNUSED */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_UNUSED, /* 28: UNUSED */ + LP_GPIO_UNUSED, /* 29: UNUSED */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: ACPRESENT */ + LP_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + LP_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + LP_GPIO_UNUSED, /* 41: UNUSED */ + LP_GPIO_UNUSED, /* 42: UNUSED */ + LP_GPIO_NATIVE, /* 43: NATIVE: USB_OC3# */ + LP_GPIO_UNUSED, /* 44: UNUSED */ + LP_GPIO_UNUSED, /* 45: UNUSED */ + LP_GPIO_OUT_HIGH, /* 46: WLAN_DISABLE_L */ + LP_GPIO_INPUT, /* 47: RAM_ID2 */ + LP_GPIO_UNUSED, /* 48: UNUSED */ + LP_GPIO_UNUSED, /* 49: UNUSED */ + LP_GPIO_UNUSED, /* 50: UNUSED */ + LP_GPIO_INPUT, /* 51: ALS_INT_L */ + LP_GPIO_INPUT, /* 52: SIM_DET */ + LP_GPIO_PIRQ, /* 53: TRACKPAD_INT_DX (PIRQV) */ + LP_GPIO_PIRQ, /* 54: TOUCH_INT_L_DX (PIRQW) */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_UNUSED, /* 56: UNUSED */ + LP_GPIO_UNUSED, /* 57: UNUSED */ + LP_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + LP_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + LP_GPIO_NATIVE, /* 60: NATIVE: SML0ALERT */ + LP_GPIO_UNUSED, /* 61: UNUSED */ + LP_GPIO_UNUSED, /* 62: UNUSED */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_UNUSED, /* 72: UNUSED */ + LP_GPIO_UNUSED, /* 73: UNUSED */ + LP_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + LP_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_UNUSED, /* 91: UNUSED */ + LP_GPIO_UNUSED, /* 92: UNUSED */ + LP_GPIO_UNUSED, /* 93: UNUSED */ + LP_GPIO_UNUSED, /* 94: UNUSED */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/falco/hda_verb.h b/src/mainboard/google/falco/hda_verb.h new file mode 100644 index 0000000000..ae7dbb31bc --- /dev/null +++ b/src/mainboard/google/falco/hda_verb.h @@ -0,0 +1,117 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000d, // Number of jacks (NID entries) + + 0x0017ff00, // Function Reset + 0x0017ff00, // Double Function Reset + 0x000F0000, // Pad - get vendor id + 0x000F0002, // Pad - get revision id + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - interior mobile lid */ + 0x01271c10, + 0x01271d10, + 0x01271ea6, + 0x01271fb7, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471c10, // group 1, front left/right + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/falco/i915io.c b/src/mainboard/google/falco/i915io.c new file mode 100644 index 0000000000..0e59a7effa --- /dev/null +++ b/src/mainboard/google/falco/i915io.c @@ -0,0 +1,130 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* This code was originally generated using an i915tool program. It has been + * improved by hand. + */ + +#include +#include +#include +#include +#include +#include "mainboard.h" + +/* this function will either be renamed or subsumed into ./gma.c:i915_lightup */ +void runio(struct intel_dp *dp); + +void runio(struct intel_dp *dp) +{ + u8 read_val; + + intel_dp_wait_panel_power_control(0xabcd0008); + + /* vbios spins at this point. Some haswell weirdness? */ + intel_dp_wait_panel_power_control(0xabcd0008); + + /* This should be a function like intel_panel_enable_backlight + However, we are not sure how the value 0x3a9 comes up. + It has to do something with PWM frequency */ + gtt_write(BLC_PWM_CPU_CTL,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL2,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL1,BLM_PCH_PWM_ENABLE); + + gtt_write(DEIIR,0x00008000); + intel_dp_wait_reg(DEIIR, 0x00000000); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + + intel_dp_sink_dpms(dp, 0); + + intel_dp_get_max_downspread(dp, &read_val); + + intel_dp_set_m_n_regs(dp); + + intel_dp_set_resolution(dp); + + gtt_write(PIPESRC(dp->pipe),dp->pipesrc); + gtt_write(PIPECONF(dp->transcoder),0x00000000); + gtt_write(PCH_TRANSCONF(dp->pipe),0x00000000); + + mainboard_set_port_clk_dp(dp); + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(DSPCNTR(dp->plane),DISPLAY_PLANE_ENABLE|DISPPLANE_BGRX888); + gtt_write(DEIIR,0x00000080); + + gtt_write(TRANS_DDI_FUNC_CTL_EDP,dp->flags); + gtt_write(PIPECONF(dp->transcoder),PIPECONF_ENABLE|PIPECONF_DITHER_EN); + + intel_dp_wait_panel_power_control(0xabcd000a); + + /* what is this doing? Not sure yet. */ + intel_dp_i2c_write(dp, 0x0); + intel_dp_i2c_read(dp, &read_val); + intel_dp_i2c_write(dp, 0x04); + intel_dp_i2c_read(dp, &read_val); + intel_dp_i2c_write(dp, 0x7e); + intel_dp_i2c_read(dp, &read_val); + + /* this needs to be a call to a function */ + gtt_write(DP_A, DP_LINK_TRAIN_PAT_1 | DP_LINK_TRAIN_PAT_1_CPT | DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0 | DP_PORT_WIDTH_1 | DP_PLL_FREQ_270MHZ | DP_SCRAMBLING_DISABLE_IRONLAKE | DP_SYNC_VS_HIGH |0x00000091); + gtt_write(DP_TP_CTL(dp->port),DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE); + gtt_write(DP_A, DP_PORT_EN | DP_LINK_TRAIN_PAT_1 | DP_LINK_TRAIN_PAT_1_CPT | DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0 | DP_PORT_WIDTH_1 | DP_ENHANCED_FRAMING | DP_PLL_FREQ_270MHZ | DP_SCRAMBLING_DISABLE_IRONLAKE | DP_SYNC_VS_HIGH |0x80040091); + + /* we may need to move these *after* power well power up and *before* PCH_PP_CONTROL in gma.c */ + gtt_write(PCH_PP_ON_DELAYS, PANEL_PORT_SELECT_LVDS |(/* PANEL_POWER_UP_DELAY_MASK */0x1<<16)|(/* PANEL_LIGHT_ON_DELAY_MASK */0xa<<0)|0x0001000a); + gtt_write(PCH_PP_ON_DELAYS, PANEL_PORT_SELECT_LVDS |(/* PANEL_POWER_UP_DELAY_MASK */0x7d0<<16)|(/* PANEL_LIGHT_ON_DELAY_MASK */0xa<<0)|0x07d0000a); + + intel_dp_set_bw(dp); + intel_dp_set_lane_count(dp); + + mainboard_train_link(dp); + + /* need a function: intel_ddi_set_tp or similar */ + gtt_write(DP_TP_CTL(dp->port),DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE | DP_TP_CTL_LINK_TRAIN_IDLE); + gtt_write(DP_TP_CTL(dp->port),DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE | DP_TP_CTL_LINK_TRAIN_NORMAL); + + gtt_write(BLC_PWM_CPU_CTL,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL2,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL1,0x80000000); + + /* some of this is not needed. */ + gtt_write(DIGITAL_PORT_HOTPLUG_CNTRL, DIGITAL_PORTA_HOTPLUG_ENABLE ); + + gtt_write(SDEIIR,0x00000000); + gtt_write(DEIIR,0x00000000); + gtt_write(DEIIR,0x00008000); + intel_dp_wait_reg(DEIIR, 0x00000000); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(PIPESRC(dp->pipe),dp->pipesrc); + + gtt_write(DEIIR,0x00000080); + intel_dp_wait_reg(DEIIR, 0x00000000); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(DSPCNTR(dp->plane),DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); + + gtt_write(PCH_PP_CONTROL,EDP_BLC_ENABLE | PANEL_POWER_RESET | PANEL_POWER_ON); + + gtt_write(SDEIIR,0x00000000); + gtt_write(SDEIIR,0x00000000); + gtt_write(DEIIR,0x00000000); +} + diff --git a/src/mainboard/google/falco/mainboard.c b/src/mainboard/google/falco/mainboard.c new file mode 100644 index 0000000000..60e8663ab6 --- /dev/null +++ b/src/mainboard/google/falco/mainboard.c @@ -0,0 +1,207 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include "ec.h" +#include "onboard.h" + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 * pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_LIGHTSENSOR_NAME, /* name */ + BOARD_LIGHTSENSOR_IRQ, /* instance */ + BOARD_LIGHTSENSOR_I2C_BUS, /* segment */ + BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/falco/mainboard.h b/src/mainboard/google/falco/mainboard.h new file mode 100644 index 0000000000..f47fffda2a --- /dev/null +++ b/src/mainboard/google/falco/mainboard.h @@ -0,0 +1,25 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MAINBOARD_H_ +#define __MAINBOARD_H_ +void mainboard_train_link(struct intel_dp *intel_dp); +void mainboard_set_port_clk_dp(struct intel_dp *intel_dp); + +#endif diff --git a/src/mainboard/google/falco/onboard.h b/src/mainboard/google/falco/onboard.h new file mode 100644 index 0000000000..23e8f1e062 --- /dev/null +++ b/src/mainboard/google/falco/onboard.h @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#define BOARD_LIGHTSENSOR_NAME "lightsensor" +#define BOARD_LIGHTSENSOR_IRQ 51 /* PIRQT */ +#define BOARD_LIGHTSENSOR_I2C_BUS 2 /* I2C1 */ +#define BOARD_LIGHTSENSOR_I2C_ADDR 0x44 + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ 37 /* PIRQV */ +#define BOARD_TRACKPAD_WAKE_GPIO 12 /* GPIO12 */ +#define BOARD_TRACKPAD_I2C_BUS 1 /* I2C0 */ +#define BOARD_TRACKPAD_I2C_ADDR 0x67 + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ 38 /* PIRQW */ +#define BOARD_TOUCHSCREEN_WAKE_GPIO 25 /* GPIO25 */ +#define BOARD_TOUCHSCREEN_I2C_BUS 2 /* I2C1 */ +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a + +#endif diff --git a/src/mainboard/google/falco/romstage.c b/src/mainboard/google/falco/romstage.c new file mode 100644 index 0000000000..d95c326fdf --- /dev/null +++ b/src/mainboard/google/falco/romstage.c @@ -0,0 +1,176 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +const struct rcba_config_instruction rcba_config[] = { + + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), + RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), + RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), + RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ + + /* Disable unused devices (board specific) */ + RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), + + RCBA_END_CONFIG, +}; + +/* Copy SPD data for on-board memory */ +static void copy_spd(struct pei_data *peid) +{ + const int gpio_vector[] = {13, 9, 47, -1}; + int spd_index = get_gpios(gpio_vector); + struct cbfs_file *spd_file; + + printk(BIOS_DEBUG, "SPD index %d\n", spd_index); + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + + if (ntohl(spd_file->len) < + ((spd_index + 1) * sizeof(peid->spd_data[0]))) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file->len < sizeof(peid->spd_data[0])) + die("Missing SPD data."); + + /* Index 0-2,6 are 4GB config with both CH0 and CH1 + * Index 3-5,7 are 2GB config with CH0 only + */ + switch (spd_index) { + case 3: case 4: case 5: case 7: + peid->dimm_channel1_disabled = 3; + } + + memcpy(peid->spd_data[0], + ((char*)CBFS_SUBHEADER(spd_file)) + + spd_index * sizeof(peid->spd_data[0]), + sizeof(peid->spd_data[0])); +} + +void mainboard_romstage_entry(unsigned long bist) +{ + struct pei_data pei_data = { + pei_version: PEI_VERSION, + mchbar: DEFAULT_MCHBAR, + dmibar: DEFAULT_DMIBAR, + epbar: DEFAULT_EPBAR, + pciexbar: DEFAULT_PCIEXBAR, + smbusbar: SMBUS_IO_BASE, + wdbbar: 0x4000000, + wdbsize: 0x1000, + hpet_address: HPET_ADDR, + rcba: DEFAULT_RCBA, + pmbase: DEFAULT_PMBASE, + gpiobase: DEFAULT_GPIOBASE, + temp_mmio_base: 0xfed08000, + system_type: 5, /* ULT */ + tseg_size: CONFIG_SMM_TSEG_SIZE, + spd_addresses: { 0xff, 0x00, 0xff, 0x00 }, + ec_present: 1, + // 0 = leave channel enabled + // 1 = disable dimm 0 on channel + // 2 = disable dimm 1 on channel + // 3 = disable dimm 0+1 on channel + dimm_channel0_disabled: 2, + dimm_channel1_disabled: 2, + // Enable 2x refresh mode + ddr_refresh_2x: 1, + max_ddr3_freq: 1600, + usb_xhci_on_resume: 1, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0064, 1, 0, /* P0: Port A, CN8 */ + USB_PORT_BACK_PANEL }, + { 0x0052, 1, 0, /* P1: Port B, CN9 */ + USB_PORT_BACK_PANEL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P2: CCD */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: BT */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P4: LTE */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P5: TOUCH */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P6: SD Card */ + USB_PORT_INTERNAL }, + { 0x0123, 1, 3, /* P7: USB2 Port */ + USB_PORT_INTERNAL }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; Port A, CN8 */ + { 1, 0 }, /* P2; Port B, CN9 */ + { 0, USB_OC_PIN_SKIP }, /* P3; */ + { 0, USB_OC_PIN_SKIP }, /* P4; */ + }, + }; + + struct romstage_params romstage_params = { + .pei_data = &pei_data, + .gpio_map = &mainboard_gpio_map, + .rcba_config = &rcba_config[0], + .bist = bist, + .copy_spd = copy_spd, + }; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(&romstage_params); +} diff --git a/src/mainboard/google/falco/smihandler.c b/src/mainboard/google/falco/smihandler.c new file mode 100644 index 0000000000..bf2165f7ea --- /dev/null +++ b/src/mainboard/google/falco/smihandler.c @@ -0,0 +1,173 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include EC functions */ +#include +#include "ec.h" + +/* GPIO46 controls the WLAN_DISABLE_L signal. */ +#define GPIO_WLAN_DISABLE_L 46 +#define GPIO_LTE_DISABLE_L 59 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(get_pmbase() + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, get_pmbase() + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s3u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S3. */ + set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s5u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S5. */ + set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/falco/thermal.h b/src/mainboard/google/falco/thermal.h new file mode 100644 index 0000000000..332e5a0320 --- /dev/null +++ b/src/mainboard/google/falco/thermal.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +#define TEMPERATURE_SENSOR_ID 0 /* PECI */ + +/* Power level to set when EC requests throttle */ +#define EC_THROTTLE_POWER_LIMIT 12 /* 12W */ + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 99 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/google/jecht/Kconfig b/src/mainboard/google/jecht/Kconfig new file mode 100644 index 0000000000..67ae96fb08 --- /dev/null +++ b/src/mainboard/google/jecht/Kconfig @@ -0,0 +1,55 @@ +if BOARD_GOOGLE_JECHT + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select SOC_INTEL_BROADWELL + select BOARD_ROMSIZE_KB_8192 + select SUPERIO_ITE_IT8772F + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_REFCODE_INDEX + hex + default 0x3 + +config MAINBOARD_DIR + string + default google/jecht + +config MAINBOARD_PART_NUMBER + string + default "Jecht" + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +config MAINBOARD_FAMILY + string + depends on GENERATE_SMBIOS_TABLES + default "Google_Jecht" + +endif diff --git a/src/mainboard/google/jecht/Makefile.inc b/src/mainboard/google/jecht/Makefile.inc new file mode 100644 index 0000000000..54c8da9e6b --- /dev/null +++ b/src/mainboard/google/jecht/Makefile.inc @@ -0,0 +1,28 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-y += spd +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-y += lan.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +romstage-y += pei_data.c +ramstage-y += pei_data.c diff --git a/src/mainboard/google/jecht/acpi/chromeos.asl b/src/mainboard/google/jecht/acpi/chromeos.asl new file mode 100644 index 0000000000..fe1767db21 --- /dev/null +++ b/src/mainboard/google/jecht/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "PCH-LP" }, // no recovery button + Package () { 0x0003, 1, 58, "PCH-LP" }, // firmware write protect +}) diff --git a/src/mainboard/google/jecht/acpi/ec.asl b/src/mainboard/google/jecht/acpi/ec.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/google/jecht/acpi/haswell_pci_irqs.asl b/src/mainboard/google/jecht/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/jecht/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/jecht/acpi/mainboard.asl b/src/mainboard/google/jecht/acpi/mainboard.asl new file mode 100644 index 0000000000..2eac86d1bd --- /dev/null +++ b/src/mainboard/google/jecht/acpi/mainboard.asl @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } +} + +/* + * LPC Trusted Platform Module + */ +Scope (\_SB.PCI0.LPCB) +{ + #include +} + +/* + * LAN connected to Root Port 3, becomes Root Port 1 after coalesce + */ +Scope (\_SB.PCI0.RP01) +{ + Device (ETH0) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { PANTHER_NIC_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (PANTHER_NIC_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + } +} + +/* + * WLAN connected to Root Port 4, becomes Root Port 2 after coalesce + */ +Scope (\_SB.PCI0.RP02) +{ + Device (WLAN) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { PANTHER_WLAN_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (PANTHER_WLAN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/jecht/acpi/platform.asl b/src/mainboard/google/jecht/acpi/platform.asl new file mode 100644 index 0000000000..f0709b0a70 --- /dev/null +++ b/src/mainboard/google/jecht/acpi/platform.asl @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/jecht/acpi/superio.asl b/src/mainboard/google/jecht/acpi/superio.asl new file mode 100644 index 0000000000..e1c9d1c918 --- /dev/null +++ b/src/mainboard/google/jecht/acpi/superio.asl @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Values should match those defined in devicetree.cb */ + +#undef SIO_ENABLE_FDC0 // pnp 2e.0: Disable Floppy Controller +#undef SIO_ENABLE_INFR // pnp 2e.a: Disable Consumer IR + +#define SIO_ENABLE_PS2K // pnp 2e.5: Enable PS/2 Keyboard +#define SIO_ENABLE_PS2M // pnp 2e.6: Enable PS/2 Mouse +#define SIO_ENABLE_COM1 // pnp 2e.1: Enable Serial Port 1 +#define SIO_ENABLE_ENVC // pnp 2e.4: Enable Environmental Controller +#define SIO_ENVC_IO0 0x700 // pnp 2e.4: io 0x60 +#define SIO_ENVC_IO1 0x710 // pnp 2e.4: io 0x62 +#define SIO_ENABLE_GPIO // pnp 2e.7: Enable GPIO +#define SIO_GPIO_IO0 0x720 // pnp 2e.7: io 0x60 +#define SIO_GPIO_IO1 0x730 // pnp 2e.7: io 0x60 + +#include "superio/ite/it8772f/acpi/superio.asl" + diff --git a/src/mainboard/google/jecht/acpi/thermal.asl b/src/mainboard/google/jecht/acpi/thermal.asl new file mode 100644 index 0000000000..95f3e12f42 --- /dev/null +++ b/src/mainboard/google/jecht/acpi/thermal.asl @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (TCHK, 0, Serialized) + { + // Get CPU Temperature from PECI via SuperIO TMPIN3 + Store (\_SB.PCI0.LPCB.SIO.ENVC.TIN3, Local0) + + // Check for "no reading available + If (LEqual (Local0, 0x80)) { + Return (CTOK (0)) + } + + // Check for invalid readings + If (LOr (LEqual (Local0, 255), LEqual (Local0, 0))) { + Return (CTOK (0)) + } + + // PECI raw value is an offset from Tj_max + Subtract (255, Local0, Local1) + + // Handle values greater than Tj_max + If (LGreaterEqual (Local1, \TMAX)) { + Return (CTOK (0)) + } + + // Subtract from Tj_max to get temperature + Subtract (\TMAX, Local1, Local0) + Return (CTOK (Local0)) + } + + Method (_TMP, 0, Serialized) + { + // Get temperature from SuperIO in deci-kelvin + Store (TCHK (), Local0) + + // Critical temperature in deci-kelvin + Store (CTOK (\TMAX), Local1) + + If (LGreaterEqual (Local0, Local1)) { + Store ("CRITICAL TEMPERATURE", Debug) + Store (Local0, Debug) + + // Wait 1 second for SuperIO to re-poll + Sleep (1000) + + // Re-read temperature from SuperIO + Store (TCHK (), Local0) + + Store ("RE-READ TEMPERATURE", Debug) + Store (Local0, Debug) + } + + Return (Local0) + } + } +} + diff --git a/src/mainboard/google/jecht/acpi/video.asl b/src/mainboard/google/jecht/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/jecht/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/jecht/acpi_tables.c b/src/mainboard/google/jecht/acpi_tables.c new file mode 100644 index 0000000000..efb17dc730 --- /dev/null +++ b/src/mainboard/google/jecht/acpi_tables.c @@ -0,0 +1,218 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thermal.h" + +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + + gnvs->tmps = TEMPERATURE_SENSOR_ID; + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + return acpi_madt_irq_overrides(current); +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + return current; +} + +#define ALIGN_CURRENT (current = (ALIGN(current, 16))) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i = 0; i < dsdt->length; i++) { + if (*(u32 *)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, + "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> %p\n", + i, gnvs); + *(u32 *)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/jecht/chromeos.c b/src/mainboard/google/jecht/chromeos.c new file mode 100644 index 0000000000..f9f5fbfafe --- /dev/null +++ b/src/mainboard/google/jecht/chromeos.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_SPI_WP 58 +#define GPIO_REC_MODE 12 + +#define FLAG_SPI_WP 0 +#define FLAG_REC_MODE 1 +#define FLAG_DEV_MODE 2 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, GPIO_SPI_WP, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, GPIO_REC_MODE, ACTIVE_LOW, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", 1); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +int get_write_protect_state(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_SPI_WP) & 1; +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_REC_MODE) & 1; +} + +#ifdef __PRE_RAM__ +void save_chromeos_gpios(void) +{ + u32 flags = 0; + + /* Write Protect: GPIO58 = GPIO_SPI_WP, active high */ + if (get_gpio(GPIO_SPI_WP)) + flags |= (1 << FLAG_SPI_WP); + + /* Recovery: GPIO12 = RECOVERY_L, active low */ + if (!get_gpio(GPIO_REC_MODE)) + flags |= (1 << FLAG_REC_MODE); + + /* Developer: Virtual */ + + pci_write_config32(PCI_DEV(0, 0x1f, 2), SATA_SP, flags); +} +#endif diff --git a/src/mainboard/google/jecht/cmos.layout b/src/mainboard/google/jecht/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/jecht/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/jecht/devicetree.cb b/src/mainboard/google/jecht/devicetree.cb new file mode 100644 index 0000000000..7fcf11f5f1 --- /dev/null +++ b/src/mainboard/google/jecht/devicetree.cb @@ -0,0 +1,122 @@ +chip soc/intel/broadwell + + # Disable eDP Hotplug + register "gpu_dp_d_hotplug" = "0x00" + + # Enable DisplayPort C Hotplug with 6ms pulse + register "gpu_dp_c_hotplug" = "0x06" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + + + + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # SuperIO range is 0x700-0x73f + register "gen2_dec" = "0x003c0701" + + register "alt_gp_smi_en" = "0x0000" + register "gpe0_en_1" = "0x00000000" + register "gpe0_en_2" = "0x00000000" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "sata_port_map" = "0x1" + register "sata_devslp_disable" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + # Force enable ASPM for PCIe Port 4 + register "pcie_port_force_aspm" = "0x10" + + # Enable port coalescing + register "pcie_port_coalesce" = "1" + + # Disable PCIe CLKOUT 1,5 and CLKOUT_XDP + register "icc_clock_disable" = "0x01220000" + + device cpu_cluster 0 on + device lapic 0 on end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 off end # Serial I/O DMA + device pci 15.1 off end # I2C0 + device pci 15.2 off end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 off end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip superio/ite/it8772f + # Skip keyboard init + register "skip_keyboard" = "1" + # Enable PECI on TMPIN3 + register "peci_tmpin" = "3" + # Enable FAN2 + register "fan2_enable" = "1" + + device pnp 2e.0 off end # FDC + device pnp 2e.1 on # Serial Port 1 + io 0x60 = 0x3f8 + irq 0x70 = 4 + end + device pnp 2e.4 on # Environment Controller + io 0x60 = 0x700 + io 0x62 = 0x710 + irq 0x70 = 0x09 + irq 0xf2 = 0x20 + irq 0xf4 = 0x0 + irq 0xfa = 0x12 + end + device pnp 2e.7 on # GPIO + io 0x60 = 0x720 + io 0x62 = 0x730 + end + device pnp 2e.5 on + io 0x60 = 0x60 + io 0x62 = 0x64 + irq 0x70 = 1 + end # Keyboard + device pnp 2e.6 on + irq 0x70 = 12 + end # Mouse + device pnp 2e.a off end # IR + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end +end diff --git a/src/mainboard/google/jecht/dsdt.asl b/src/mainboard/google/jecht/dsdt.asl new file mode 100644 index 0000000000..f7246612ea --- /dev/null +++ b/src/mainboard/google/jecht/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include + + // Mainboard specific + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/google/jecht/fadt.c b/src/mainboard/google/jecht/fadt.c new file mode 100644 index 0000000000..627769ac3d --- /dev/null +++ b/src/mainboard/google/jecht/fadt.c @@ -0,0 +1,158 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = ACPI_BASE_ADDRESS; + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 5; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/jecht/gpio.h b/src/mainboard/google/jecht/gpio.h new file mode 100644 index 0000000000..c50aabe750 --- /dev/null +++ b/src/mainboard/google/jecht/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JECHT_GPIO_H +#define JECHT_GPIO_H + +#include + +static const struct gpio_config mainboard_gpio_config[] = { + PCH_GPIO_UNUSED, /* 0: UNUSED */ + PCH_GPIO_UNUSED, /* 1: UNUSED */ + PCH_GPIO_UNUSED, /* 2: UNUSED */ + PCH_GPIO_UNUSED, /* 3: UNUSED */ + PCH_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + PCH_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + PCH_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + PCH_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + PCH_GPIO_ACPI_SCI, /* 8: LAN_WAKE_L_Q */ + PCH_GPIO_OUT_HIGH, /* 9: PP3300_WLAN_EN */ + PCH_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + PCH_GPIO_UNUSED, /* 11: SMBALERT */ + PCH_GPIO_INPUT_INVERT, /* 12: RECOVERY_L */ + PCH_GPIO_UNUSED, /* 13: UNUSED */ + PCH_GPIO_UNUSED, /* 14: UNUSED */ + PCH_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 16: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 17: PP3300_VP8_EN */ + PCH_GPIO_UNUSED, /* 18: UNUSED */ + PCH_GPIO_UNUSED, /* 19: UNUSED */ + PCH_GPIO_NATIVE, /* 20: NATIVE: CLK_PCIE_REQ2# */ + PCH_GPIO_NATIVE, /* 21: NATIVE: CLK_PCIE_REQ3# */ + PCH_GPIO_NATIVE, /* 22: NATIVE: CLK_PCIE_REQ4# */ + PCH_GPIO_UNUSED, /* 23: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 24: WLAN_OFF_L */ + PCH_GPIO_UNUSED, /* 25: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 26: USB_CTL_1 */ + PCH_GPIO_UNUSED, /* 27: UNUSED */ + PCH_GPIO_OUT_LOW, /* 28: USB_ILIM_SEL */ + PCH_GPIO_UNUSED, /* 29: UNUSED */ + PCH_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSPWRACK_L */ + PCH_GPIO_NATIVE, /* 31: NATIVE: PCH_ACPRESENT */ + PCH_GPIO_NATIVE, /* 32: NATIVE: CLKRUN# */ + PCH_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + PCH_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + PCH_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + PCH_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + PCH_GPIO_UNUSED, /* 37: UNUSED */ + PCH_GPIO_UNUSED, /* 38: UNUSED */ + PCH_GPIO_UNUSED, /* 39: UNUSED */ + PCH_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + PCH_GPIO_NATIVE, /* 41: NATIVE: USB_OC1# */ + PCH_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + PCH_GPIO_NATIVE, /* 43: NATIVE: USB_OC3# */ + PCH_GPIO_UNUSED, /* 44: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 45: PP5000_CODEC_EN */ + PCH_GPIO_OUT_HIGH, /* 46: BT_DISABLE_L */ + PCH_GPIO_OUT_HIGH, /* 47: USB1_PWR_EN */ + PCH_GPIO_UNUSED, /* 48: UNUSED */ + PCH_GPIO_UNUSED, /* 49: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 50: VP8_DISABLE_L */ + PCH_GPIO_UNUSED, /* 51: UNUSED */ + PCH_GPIO_UNUSED, /* 52: UNUSED */ + PCH_GPIO_UNUSED, /* 53: UNUSED */ + PCH_GPIO_UNUSED, /* 54: UNUSED */ + PCH_GPIO_UNUSED, /* 55: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 56: USB2_PWR_EN */ + PCH_GPIO_OUT_HIGH, /* 57: USB3_PWR_EN */ + PCH_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + PCH_GPIO_OUT_HIGH, /* 59: PP3300_LAN_EN */ + PCH_GPIO_NATIVE, /* 60: NATIVE: SMB0ALERT# */ + PCH_GPIO_UNUSED, /* 61: UNUSED */ + PCH_GPIO_UNUSED, /* 62: UNUSED */ + PCH_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + PCH_GPIO_UNUSED, /* 64: UNUSED */ + PCH_GPIO_UNUSED, /* 65: UNUSED */ + PCH_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 67: UNUSED */ + PCH_GPIO_UNUSED, /* 68: UNUSED */ + PCH_GPIO_UNUSED, /* 69: UNUSED */ + PCH_GPIO_UNUSED, /* 70: UNUSED */ + PCH_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + PCH_GPIO_UNUSED, /* 72: UNUSED */ + PCH_GPIO_UNUSED, /* 73: UNUSED */ + PCH_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + PCH_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + PCH_GPIO_UNUSED, /* 76: UNUSED */ + PCH_GPIO_UNUSED, /* 77: UNUSED */ + PCH_GPIO_UNUSED, /* 78: UNUSED */ + PCH_GPIO_UNUSED, /* 79: UNUSED */ + PCH_GPIO_UNUSED, /* 80: UNUSED */ + PCH_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + PCH_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + PCH_GPIO_UNUSED, /* 83: UNUSED */ + PCH_GPIO_UNUSED, /* 84: UNUSED */ + PCH_GPIO_UNUSED, /* 85: UNUSED */ + PCH_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + PCH_GPIO_UNUSED, /* 87: UNUSED */ + PCH_GPIO_UNUSED, /* 88: UNUSED */ + PCH_GPIO_UNUSED, /* 89: UNUSED */ + PCH_GPIO_UNUSED, /* 90: UNUSED */ + PCH_GPIO_UNUSED, /* 91: UNUSED */ + PCH_GPIO_UNUSED, /* 92: UNUSED */ + PCH_GPIO_UNUSED, /* 93: UNUSED */ + PCH_GPIO_UNUSED, /* 94: UNUSED */ + PCH_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/jecht/hda_verb.h b/src/mainboard/google/jecht/hda_verb.h new file mode 100644 index 0000000000..cec56ebb26 --- /dev/null +++ b/src/mainboard/google/jecht/hda_verb.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000c, // Number of jacks (NID entries) + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC */ + 0x01271cf0, + 0x01271d11, + 0x01271e11, + 0x01271f41, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471cf0, + 0x01471d11, + 0x01471e11, + 0x01471f40, + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/jecht/lan.c b/src/mainboard/google/jecht/lan.c new file mode 100644 index 0000000000..a8f7968e77 --- /dev/null +++ b/src/mainboard/google/jecht/lan.c @@ -0,0 +1,179 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "onboard.h" + +static unsigned int search(char *p, u8 *a, unsigned int lengthp, + unsigned int lengtha) +{ + int i, j; + + /* Searching */ + for (j = 0; j <= lengtha - lengthp; j++) { + for (i = 0; i < lengthp && p[i] == a[i + j]; i++) ; + if (i >= lengthp) + return j; + } + return lengtha; +} + +static unsigned char get_hex_digit(u8 *offset) +{ + unsigned char retval = 0; + + retval = *offset - '0'; + if (retval > 0x09) { + retval = *offset - 'A' + 0x0A; + if (retval > 0x0F) + retval = *offset - 'a' + 0x0a; + } + if (retval > 0x0F) { + printk(BIOS_DEBUG, "Error: Invalid Hex digit found: %c - 0x%02x\n", + *offset, *offset); + retval = 0; + } + + return retval; +} + +static int get_mac_address(u32 *high_dword, u32 *low_dword, + u8 *search_address, u32 search_length) +{ + char key[] = "ethernet_mac"; + unsigned int offset; + int i; + + offset = search(key, search_address, sizeof(key) - 1, search_length); + if (offset == search_length) { + printk(BIOS_DEBUG, + "Error: Could not locate '%s' in VPD\n", key); + return 0; + } + printk(BIOS_DEBUG, "Located '%s' in VPD\n", key); + + offset += sizeof(key); /* move to next character */ + *high_dword = 0; + + /* Fetch the MAC address and put the octets in the correct order to + * be programmed. + * + * From RTL8105E_Series_EEPROM-Less_App_Note_1.1 + * If the MAC address is 001122334455h: + * Write 33221100h to I/O register offset 0x00 via double word access + * Write 00005544h to I/O register offset 0x04 via double word access + */ + + for (i = 0; i < 4; i++) { + *high_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *high_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + *low_dword = 0; + for (i = 0; i < 2; i++) { + *low_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *low_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + return *high_dword | *low_dword; +} + +static void program_mac_address(u16 io_base) +{ + /* Default MAC Address of A0:00:BA:D0:0B:AD */ + u32 high_dword = 0xD0BA00A0; /* high dword of mac address */ + u32 low_dword = 0x0000AD0B; /* low word of mac address as a dword */ + + void *search_address = NULL; + int search_length = find_fmap_entry("RO_VPD", &search_address); + + if (search_length == -1) + printk(BIOS_ERR, "LAN: find_fmap_entry returned -1.\n"); + else + get_mac_address(&high_dword, &low_dword, search_address, + search_length); + + if (io_base) { + printk(BIOS_DEBUG, "Realtek NIC io_base = 0x%04x\n", io_base); + printk(BIOS_DEBUG, "Programming MAC Address\n"); + + /* Disable register protection */ + outb(0xc0, io_base + 0x50); + outl(high_dword, io_base); + outl(low_dword, io_base + 0x04); + outb(0x60, io_base + 54); + /* Enable register protection again */ + outb(0x00, io_base + 0x50); + } +} + +void lan_init(void) +{ + u16 io_base = 0; + struct device *ethernet_dev = NULL; + + /* Get NIC's IO base address */ + ethernet_dev = dev_find_device(JECHT_NIC_VENDOR_ID, + JECHT_NIC_DEVICE_ID, 0); + if (ethernet_dev != NULL) { + io_base = pci_read_config16(ethernet_dev, 0x10) & 0xfffe; + + /* + * Battery life time - LAN PCIe should enter ASPM L1 to save + * power when LAN connection is idle. + * enable CLKREQ: LAN pci config space 0x81h=01 + */ + pci_write_config8(ethernet_dev, 0x81, 0x01); + } + + if (io_base) { + /* Program MAC address based on VPD data */ + program_mac_address(io_base); + + /* + * Program NIC LEDS + * + * RTL8105E Series EEPROM-Less Application Note, + * Section 5.6 LED Mode Configuration + * + * Step1: Write C0h to I/O register 0x50 via byte access to + * disable 'register protection' + * Step2: Write xx001111b to I/O register 0x52 via byte access + * (bit7 is LEDS1 and bit6 is LEDS0) + * Step3: Write 0x00 to I/O register 0x50 via byte access to + * enable 'register protection' + */ + outb(0xc0, io_base + 0x50); /* Disable protection */ + outb((JECHT_NIC_LED_MODE << 6) | 0x0f, io_base + 0x52); + outb(0x00, io_base + 0x50); /* Enable register protection */ + } +} diff --git a/src/mainboard/google/jecht/mainboard.c b/src/mainboard/google/jecht/mainboard.c new file mode 100644 index 0000000000..43b236812b --- /dev/null +++ b/src/mainboard/google/jecht/mainboard.c @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include "onboard.h" + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 *cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 *pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + lan_init(); +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/jecht/onboard.h b/src/mainboard/google/jecht/onboard.h new file mode 100644 index 0000000000..65d30b1932 --- /dev/null +++ b/src/mainboard/google/jecht/onboard.h @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#ifndef __ACPI__ +void lan_init(void); +#endif + +/* defines for programming the MAC address */ +#define JECHT_NIC_VENDOR_ID 0x10EC +#define JECHT_NIC_DEVICE_ID 0x8168 + +/* 0x00: White LINK LED and Amber ACTIVE LED */ +#define JECHT_NIC_LED_MODE 0x00 + +/* NIC wake is GPIO 8 */ +#define JECHT_NIC_WAKE_GPIO 8 + +/* WLAN wake is GPIO 10 */ +#define JECHT_WLAN_WAKE_GPIO 10 + +#endif diff --git a/src/mainboard/google/jecht/pei_data.c b/src/mainboard/google/jecht/pei_data.c new file mode 100644 index 0000000000..32abfc5544 --- /dev/null +++ b/src/mainboard/google/jecht/pei_data.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + pei_data->ec_present = 0; + + /* P0: VP8 */ + pei_data_usb2_port(pei_data, 0, 0x0064, 1, 0, + USB_PORT_MINI_PCIE); + /* P1: Port A, CN22 */ + pei_data_usb2_port(pei_data, 1, 0x0040, 1, 0, + USB_PORT_INTERNAL); + /* P2: Port B, CN23 */ + pei_data_usb2_port(pei_data, 2, 0x0040, 1, 1, + USB_PORT_INTERNAL); + /* P3: WLAN */ + pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_MINI_PCIE); + /* P4: Port C, CN25 */ + pei_data_usb2_port(pei_data, 4, 0x0040, 1, 2, + USB_PORT_INTERNAL); + /* P5: Port D, CN25 */ + pei_data_usb2_port(pei_data, 5, 0x0040, 1, 2, + USB_PORT_INTERNAL); + /* P6: Card Reader */ + pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P7: EMPTY */ + pei_data_usb2_port(pei_data, 7, 0x0000, 0, 0, + USB_PORT_SKIP); + + /* P1: CN22 */ + pei_data_usb3_port(pei_data, 0, 1, 0, 0); + /* P2: CN23 */ + pei_data_usb3_port(pei_data, 1, 1, 1, 0); + /* P3: CN25 */ + pei_data_usb3_port(pei_data, 2, 1, 2, 0); + /* P4: CN25 */ + pei_data_usb3_port(pei_data, 3, 1, 2, 0); +} diff --git a/src/mainboard/google/jecht/romstage.c b/src/mainboard/google/jecht/romstage.c new file mode 100644 index 0000000000..34b1a76028 --- /dev/null +++ b/src/mainboard/google/jecht/romstage.c @@ -0,0 +1,60 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" +#include "superio/ite/it8772f/it8772f.h" +#include "superio/ite/it8772f/early_serial.c" + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct pei_data pei_data; + + post_code(0x32); + + /* Initialize GPIOs */ + init_gpios(mainboard_gpio_config); + + /* Fill out PEI DATA */ + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + mainboard_fill_spd_data(&pei_data); + rp->pei_data = &pei_data; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(rp); +} + +void mainboard_pre_console_init(void) +{ + /* Early SuperIO setup */ + it8772f_kill_watchdog(); + it8772f_ac_resume_southbridge(); + it8772f_enable_serial(PNP_DEV(IT8772F_BASE, IT8772F_SP1), + CONFIG_TTYS0_BASE); +} diff --git a/src/mainboard/google/jecht/smihandler.c b/src/mainboard/google/jecht/smihandler.c new file mode 100644 index 0000000000..20c9213cc7 --- /dev/null +++ b/src/mainboard/google/jecht/smihandler.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + return 1; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + break; + case 5: + break; + } +} + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APM_CNT_ACPI_ENABLE: + break; + case APM_CNT_ACPI_DISABLE: + break; + } + return 0; +} diff --git a/src/mainboard/google/jecht/spd/Makefile.inc b/src/mainboard/google/jecht/spd/Makefile.inc new file mode 100644 index 0000000000..41c5c1b14e --- /dev/null +++ b/src/mainboard/google/jecht/spd/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-y += spd.c diff --git a/src/mainboard/google/jecht/spd/spd.c b/src/mainboard/google/jecht/spd/spd.c new file mode 100644 index 0000000000..605ccb1e21 --- /dev/null +++ b/src/mainboard/google/jecht/spd/spd.c @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Copy SPD data for on-board memory */ +void mainboard_fill_spd_data(struct pei_data *pei_data) +{ + pei_data->spd_addresses[0] = 0xa0; + pei_data->spd_addresses[1] = 0x00; + pei_data->spd_addresses[2] = 0xa4; + pei_data->spd_addresses[3] = 0x00; + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + // Enable 2x refresh mode + pei_data->ddr_refresh_2x = 1; + pei_data->dq_pins_interleaved = 1; +} diff --git a/src/mainboard/google/jecht/spd/spd.h b/src/mainboard/google/jecht/spd/spd.h new file mode 100644 index 0000000000..3b01cc38eb --- /dev/null +++ b/src/mainboard/google/jecht/spd/spd.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_SPD_H +#define MAINBOARD_SPD_H + +struct pei_data; +void mainboard_fill_spd_data(struct pei_data *pei_data); + +#endif diff --git a/src/mainboard/google/jecht/thermal.h b/src/mainboard/google/jecht/thermal.h new file mode 100644 index 0000000000..338b16d890 --- /dev/null +++ b/src/mainboard/google/jecht/thermal.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +#define TEMPERATURE_SENSOR_ID 0 /* PECI */ + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 104 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 105 + +#endif diff --git a/src/mainboard/google/link/Kconfig b/src/mainboard/google/link/Kconfig index dc9771014f..264c59fc6d 100644 --- a/src/mainboard/google/link/Kconfig +++ b/src/mainboard/google/link/Kconfig @@ -2,7 +2,6 @@ if BOARD_GOOGLE_LINK config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 @@ -16,6 +15,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_SMI_HANDLER select GFXUMA select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB select SERIRQ_CONTINUOUS_MODE select MAINBOARD_HAS_NATIVE_VGA_INIT diff --git a/src/mainboard/google/link/acpi/thermal.asl b/src/mainboard/google/link/acpi/thermal.asl index 357c096a17..b5775da1ee 100644 --- a/src/mainboard/google/link/acpi/thermal.asl +++ b/src/mainboard/google/link/acpi/thermal.asl @@ -48,6 +48,11 @@ Scope (\_TZ) // Get CPU Temperature from TIN9/PECI via EC Store (\_SB.PCI0.LPCB.EC0.TIN9, Local0) + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + // Check for sensor not present If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { Return (CTOK(0)) diff --git a/src/mainboard/google/link/chromeos.c b/src/mainboard/google/link/chromeos.c index 17a4b18e6a..47db2ffb6e 100644 --- a/src/mainboard/google/link/chromeos.c +++ b/src/mainboard/google/link/chromeos.c @@ -30,8 +30,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 static int get_lid_switch(void) { @@ -107,8 +105,7 @@ int get_recovery_mode_switch(void) u32 ec_events; /* If a switch is set, we don't need to look at events. */ - if (ec_switches & (EC_SWITCH_KEYBOARD_RECOVERY | - EC_SWITCH_DEDICATED_RECOVERY)) + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) return 1; /* Else check if the EC has posted the keyboard recovery event. */ diff --git a/src/mainboard/google/link/ec.h b/src/mainboard/google/link/ec.h index 6133f97984..0044347aa3 100644 --- a/src/mainboard/google/link/ec.h +++ b/src/mainboard/google/link/ec.h @@ -22,7 +22,7 @@ #include -#define EC_SCI_GPI 7 /* GPIO7 is EC_SCI# */ +#define EC_SCI_GPI 23 /* GPIO7/GPE23 is EC_SCI# */ #define EC_SMI_GPI 8 /* GPIO8 is EC_SMI# */ #define LINK_EC_SCI_EVENTS \ diff --git a/src/mainboard/google/link/i915.c b/src/mainboard/google/link/i915.c index ec959ab2fc..c06f19f27d 100644 --- a/src/mainboard/google/link/i915.c +++ b/src/mainboard/google/link/i915.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include "i915io.h" @@ -148,6 +147,7 @@ extern int niodefs; static int i915_init_done = 0; /* fill the palette. This runs when the P opcode is hit. */ +/* and, yes, it's needed for even 32 bits per pixel */ static void palette(void) { int i; @@ -158,32 +158,6 @@ static void palette(void) } } -int vbe_mode_info_valid(void); -int vbe_mode_info_valid(void) -{ - return i915_init_done; -} - -void fill_lb_framebuffer(struct lb_framebuffer *framebuffer); -void fill_lb_framebuffer(struct lb_framebuffer *framebuffer) -{ - printk(BIOS_SPEW, "fill_lb_framebuffer: graphics is %p\n", (void *)graphics); - framebuffer->physical_address = graphics; - framebuffer->x_resolution = 2560; - framebuffer->y_resolution = 1700; - framebuffer->bytes_per_line = 10240; - framebuffer->bits_per_pixel = 32; - framebuffer->red_mask_pos = 16; - framebuffer->red_mask_size = 8; - framebuffer->green_mask_pos = 8; - framebuffer->green_mask_size = 8; - framebuffer->blue_mask_pos = 0; - framebuffer->blue_mask_size = 8; - framebuffer->reserved_mask_pos = 0; - framebuffer->reserved_mask_size = 0; - -} - static unsigned long times[4096]; static int run(int index) @@ -269,6 +243,7 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase, unsigned int pmmio, unsigned int pgfx) { static struct edid edid; + int edid_ok; int index; u32 auxin[16], auxout[16]; @@ -283,7 +258,10 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase, globalstart = rdtscll(); - decode_edid((unsigned char *)&link_edid_data, sizeof(link_edid_data), &edid); + edid_ok = decode_edid((unsigned char *)&link_edid_data, + sizeof(link_edid_data), &edid, 0); + printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok); + edid.framebuffer_bits_per_pixel = 32; htotal = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16); printk(BIOS_SPEW, "I915_WRITE(HTOTAL(pipe), %08x)\n", htotal); @@ -399,6 +377,7 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase, (void *)graphics, FRAME_BUFFER_BYTES); memset((void *)graphics, 0, FRAME_BUFFER_BYTES); printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds()); + set_vbe_mode_info_valid(&edid, (uintptr_t)graphics); i915_init_done = 1; oprom_is_loaded = 1; return 0; diff --git a/src/mainboard/google/link/mainboard.c b/src/mainboard/google/link/mainboard.c index f0afd817ec..08b1c02a96 100644 --- a/src/mainboard/google/link/mainboard.c +++ b/src/mainboard/google/link/mainboard.c @@ -25,7 +25,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -61,15 +61,15 @@ void mainboard_suspend_resume(void) outb(0xcb, 0xb2); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - int res=-1; + int res = 0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); + __func__, X86_AX); - switch(regs->eax & 0xffff) { + switch(X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -78,11 +78,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x00; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CL = 0x00; /* Use video bios default */ + res = 1; break; case 0x5f35: /* @@ -96,11 +94,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; /* Use video bios default */ + res = 1; break; case 0x5f51: /* @@ -110,152 +106,48 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0003; /* eDP */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0003; /* eDP */ + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch (X86_CH) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + X86_CH); + break; } break; case 0x5fac: - res = 0; + res = 1; break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x00; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) - * bit 2 = EFP - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) - * bit 6 = EFP2 - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; /* Use video bios default */ - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 3; /* eDP */ - break; - case 0x5f70: - switch (M.x86.R_CH) { - case 0: - /* Get Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CL = 0; - break; - case 1: - /* Set Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - case 2: - /* Get SG/Non-SG mode */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - M.x86.R_CH); - return 0; - } - break; - case 0x5fac: - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 * cim_verb_data; @@ -288,50 +180,37 @@ static void mainboard_init(device_t dev) } } -static int link_smbios_type41(int *handle, unsigned long *current, - const char *name, u8 irq, u8 addr) -{ - struct smbios_type41 *t = (struct smbios_type41 *)*current; - int len = sizeof(struct smbios_type41); - - memset(t, 0, sizeof(struct smbios_type41)); - t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION; - t->handle = *handle; - t->length = len - 2; - t->reference_designation = smbios_add_string(t->eos, name); - t->device_type = SMBIOS_DEVICE_TYPE_OTHER; - t->device_status = 1; - t->device_type_instance = irq; - t->segment_group_number = 0; - t->bus_number = addr; - t->function_number = 0; - t->device_number = 0; - - len = t->length + smbios_string_table_len(t->eos); - *current += len; - *handle += 1; - return len; -} - static int link_onboard_smbios_data(device_t dev, int *handle, unsigned long *current) { int len = 0; - len += link_smbios_type41(handle, current, - LINK_LIGHTSENSOR_NAME, - LINK_LIGHTSENSOR_IRQ, - LINK_LIGHTSENSOR_I2C_ADDR); + len += smbios_write_type41( + current, handle, + LINK_LIGHTSENSOR_NAME, /* name */ + LINK_LIGHTSENSOR_IRQ, /* instance */ + 0, /* segment */ + LINK_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ - len += link_smbios_type41(handle, current, - LINK_TRACKPAD_NAME, - LINK_TRACKPAD_IRQ, - LINK_TRACKPAD_I2C_ADDR); + len += smbios_write_type41( + current, handle, + LINK_TRACKPAD_NAME, /* name */ + LINK_TRACKPAD_IRQ, /* instance */ + 0, /* segment */ + LINK_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ - len += link_smbios_type41(handle, current, - LINK_TOUCHSCREEN_NAME, - LINK_TOUCHSCREEN_IRQ, - LINK_TOUCHSCREEN_I2C_ADDR); + len += smbios_write_type41( + current, handle, + LINK_TOUCHSCREEN_NAME, /* name */ + LINK_TOUCHSCREEN_IRQ, /* instance */ + 0, /* segment */ + LINK_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ return len; } @@ -343,9 +222,9 @@ static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; dev->ops->get_smbios_data = link_onboard_smbios_data; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/google/link/mainboard_smi.c b/src/mainboard/google/link/mainboard_smi.c index a4c4a50351..3785121f22 100644 --- a/src/mainboard/google/link/mainboard_smi.c +++ b/src/mainboard/google/link/mainboard_smi.c @@ -80,7 +80,7 @@ static u8 mainboard_smi_ec(void) return cmd; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { if (gpi_sts & (1 << EC_SMI_GPI)) { /* Process all pending events */ diff --git a/src/mainboard/google/link/romstage.c b/src/mainboard/google/link/romstage.c index f20a7226ab..a122b10d78 100644 --- a/src/mainboard/google/link/romstage.c +++ b/src/mainboard/google/link/romstage.c @@ -154,15 +154,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { pei_version: PEI_VERSION, mchbar: DEFAULT_MCHBAR, @@ -209,9 +207,7 @@ void main(unsigned long bist) }, }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -283,14 +279,13 @@ void main(unsigned long bist) post_code(0x3a); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3c); rcba_config(); @@ -330,15 +325,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/google/nyan/Kconfig b/src/mainboard/google/nyan/Kconfig new file mode 100644 index 0000000000..8a39bb7b80 --- /dev/null +++ b/src/mainboard/google/nyan/Kconfig @@ -0,0 +1,100 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_NYAN + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select SOC_NVIDIA_TEGRA124 + select TEGRA124_MODEL_CD570M + select MAINBOARD_HAS_BOOTBLOCK_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + select SPI_FLASH + select SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/nyan + +config MAINBOARD_PART_NUMBER + string + default "Nyan" + +choice + prompt "BCT boot media" + default NYAN_BCT_CFG_SPI + help + Which boot media to configure the BCT for. + +config NYAN_BCT_CFG_SPI + bool "SPI" + help + Configure the BCT for booting from SPI. + +config NYAN_BCT_CFG_EMMC + bool "eMMC" + help + Configure the BCT for booting from eMMC. + +endchoice + +config BOOT_MEDIA_SPI_BUS + int "SPI bus with boot media ROM" + range 1 6 + depends on NYAN_BCT_CFG_SPI + default 4 + help + Which SPI bus the boot media is connected to. + +config BOOT_MEDIA_SPI_CHIP_SELECT + int "Chip select for SPI boot media" + range 0 3 + depends on NYAN_BCT_CFG_SPI + default 0 + help + Which chip select to use for boot media. + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 1 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config FLASHMAP_OFFSET + hex + default 0x00100000 + +config DRIVER_TPM_I2C_BUS + hex + default 0x2 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +endif # BOARD_GOOGLE_NYAN diff --git a/src/mainboard/google/nyan/Makefile.inc b/src/mainboard/google/nyan/Makefile.inc new file mode 100644 index 0000000000..9357e3e325 --- /dev/null +++ b/src/mainboard/google/nyan/Makefile.inc @@ -0,0 +1,46 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# Add a handler for BCT config files +$(call add-special-class,bct-cfg) +bct-cfg-handler= $(eval $(obj)/generated/bct.cfg: $(1)$(2)) + +$(obj)/generated/bct.cfg: + @printf " CAT $(subst $(obj)/,,$(@))\n" + cat $^ > $@ + +subdirs-y += bct + +bootblock-y += boardid.c +bootblock-y += bootblock.c +bootblock-y += pmic.c +bootblock-y += reset.c + +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += early_configs.c + +ramstage-y += reset.c +ramstage-y += boardid.c +ramstage-y += mainboard.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/nyan/bct/Makefile.inc b/src/mainboard/google/nyan/bct/Makefile.inc new file mode 100644 index 0000000000..f5efad4e84 --- /dev/null +++ b/src/mainboard/google/nyan/bct/Makefile.inc @@ -0,0 +1,27 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bct-cfg-$(CONFIG_NYAN_BCT_CFG_EMMC) += emmc.cfg +bct-cfg-$(CONFIG_NYAN_BCT_CFG_SPI) += spi.cfg +bct-cfg-y += odmdata.cfg +bct-cfg-y += jtag.cfg + +# Note when SDRAM config (sdram-*.cfg) files are changed, we have to regenerate +# the include files (sdram-*.inc) by running "./cfg2inc.sh sdram-*.cfg". +# TODO(hungte) Change cfg2inc.sh to NVIDIA's official tool in cbootimage. diff --git a/src/mainboard/google/nyan/bct/cfg2inc.sh b/src/mainboard/google/nyan/bct/cfg2inc.sh new file mode 100755 index 0000000000..a9c629b523 --- /dev/null +++ b/src/mainboard/google/nyan/bct/cfg2inc.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This file is part of the coreboot project. +# +# Copyright 2014 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +bct_cfg2inc() { + local in_file="$1" + local out_file="$2" + echo "{ /* generated from ${in_file}; do not edit. */" >"${out_file}" + # Note currently we can only handle DDR3 type memory, even in C + # implementation. + sed "/^#.*$/d; s/^SDRAM.0./ /; s/\r$//; s/;$/,/;" \ + "${in_file}" >> "${out_file}" + echo "}," >>"${out_file}" +} + +for file in $@; do + echo "Generating $file => ${file%cfg}inc..." + bct_cfg2inc "${file}" "${file%cfg}inc" +done diff --git a/src/mainboard/google/nyan/bct/emmc.cfg b/src/mainboard/google/nyan/bct/emmc.cfg new file mode 100644 index 0000000000..be8f79fd07 --- /dev/null +++ b/src/mainboard/google/nyan/bct/emmc.cfg @@ -0,0 +1,13 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 0x00004000; +PageSize = 0x00000200; +PartitionSize = 0x01000000; + +DevType[0] = NvBootDevType_Sdmmc; +DeviceParam[0].SdmmcParams.ClockDivider = 0x00000009; +DeviceParam[0].SdmmcParams.DataWidth = NvBootSdmmcDataWidth_8Bit; +DeviceParam[0].SdmmcParams.MaxPowerClassSupported = 0x00000000; +DeviceParam[0].SdmmcParams.MultiPageSupport = 0x00000000; diff --git a/src/mainboard/google/nyan/bct/jtag.cfg b/src/mainboard/google/nyan/bct/jtag.cfg new file mode 100644 index 0000000000..f43e143377 --- /dev/null +++ b/src/mainboard/google/nyan/bct/jtag.cfg @@ -0,0 +1,16 @@ +# +# Set JtagCtrl to 1 to reenable Jtag +# +JtagCtrl = 0; +# +# Fill in chip unique id +# +# ChipUid can be found by running tegrarcm in tegra recovery mode +# (also hooking up A-A USB cable) and looking for console output +# on line starting with "Chip UID:" +# +# Command example: +# $ sudo tegrarcm --bct=/build/nyan/firmware/bct/board.bct --bootloader=/build/nyan/firmware/u-boot.bin --loadaddr=0x80108000 +# Where board.bct and u-boot.bin do not have to be prebuilt. +# +ChipUid = 0x00000000000000000000000000000000; diff --git a/src/mainboard/google/nyan/bct/odmdata.cfg b/src/mainboard/google/nyan/bct/odmdata.cfg new file mode 100644 index 0000000000..d0ab2bf8fb --- /dev/null +++ b/src/mainboard/google/nyan/bct/odmdata.cfg @@ -0,0 +1 @@ +OdmData = 0x80080000; diff --git a/src/mainboard/google/nyan/bct/sdram-hynix-2GB-792.inc b/src/mainboard/google/nyan/bct/sdram-hynix-2GB-792.inc new file mode 100644 index 0000000000..d175e7b4e4 --- /dev/null +++ b/src/mainboard/google/nyan/bct/sdram-hynix-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-792-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cd, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000007, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000003, + .EmcEInputDuration = 0x0000000c, + .EmcPutermExtra = 0x00090000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000002, + .EmcQSafe = 0x00000011, + .EmcRdv = 0x00000017, + .EmcRdvMask = 0x00000019, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017eb, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005fa, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000003, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c7, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d7, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x0000182c, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000002, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80001d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200018, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f7000e, + .EmcMrsWaitCnt2 = 0x00f7000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x000040a0, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003025, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00701b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0000000e, + .EmcDllXformAddr1 = 0x0000000e, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0000000e, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x0000000b, + .EmcDllXformDq1 = 0x0000000b, + .EmcDllXformDq2 = 0x0000000b, + .EmcDllXformDq3 = 0x0000000b, + .EmcDllXformDq4 = 0x0000000b, + .EmcDllXformDq5 = 0x0000000b, + .EmcDllXformDq6 = 0x0000000b, + .EmcDllXformDq7 = 0x0000000b, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80001d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0020013d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000707, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x017fffff, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0505003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000005, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08050202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x736c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan/bct/sdram-hynix-2GB-924.inc b/src/mainboard/google/nyan/bct/sdram-hynix-2GB-924.inc new file mode 100644 index 0000000000..b10a696447 --- /dev/null +++ b/src/mainboard/google/nyan/bct/sdram-hynix-2GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-2GB-924.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430101, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000002b, + .EmcRfc = 0x000000f0, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001e, + .EmcRp = 0x0000000b, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x0000000a, + .EmcW2r = 0x0000000f, + .EmcR2p = 0x00000005, + .EmcW2p = 0x00000016, + .EmcRdRcd = 0x0000000b, + .EmcWrRcd = 0x0000000b, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000007, + .EmcWdvMask = 0x00000007, + .EmcQUse = 0x0000000d, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000f, + .EmcPutermExtra = 0x000a0000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000016, + .EmcRdv = 0x0000001a, + .EmcRdvMask = 0x0000001c, + .EmcQpop = 0x00000011, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x00001be7, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000006f9, + .EmcPdEx2Wr = 0x00000004, + .EmcPdEx2Rd = 0x00000015, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000e7, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x000000fb, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000006, + .EmcTckesr = 0x00000007, + .EmcTpd = 0x00000006, + .EmcTfaw = 0x00000022, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x0000000a, + .EmcTClkStop = 0x0000000a, + .EmcTRefBw = 0x00001c28, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000f15, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200020, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00cd000e, + .EmcMrsWaitCnt2 = 0x00cd000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800037ea, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00400b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x007fc005, + .EmcDllXformDqs1 = 0x007fc005, + .EmcDllXformDqs2 = 0x007f8008, + .EmcDllXformDqs3 = 0x007f8008, + .EmcDllXformDqs4 = 0x007fc005, + .EmcDllXformDqs5 = 0x007f8008, + .EmcDllXformDqs6 = 0x007fc005, + .EmcDllXformDqs7 = 0x007fc005, + .EmcDllXformDqs8 = 0x007fc005, + .EmcDllXformDqs9 = 0x007fc005, + .EmcDllXformDqs10 = 0x007f8008, + .EmcDllXformDqs11 = 0x007f8008, + .EmcDllXformDqs12 = 0x007fc005, + .EmcDllXformDqs13 = 0x007f8008, + .EmcDllXformDqs14 = 0x007fc005, + .EmcDllXformDqs15 = 0x007fc005, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00018000, + .EmcDllXformAddr1 = 0x00018000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00018000, + .EmcDllXformAddr4 = 0x00018000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00000007, + .EmcDllXformDq1 = 0x00000007, + .EmcDllXformDq2 = 0x00000007, + .EmcDllXformDq3 = 0x00000007, + .EmcDllXformDq4 = 0x00000007, + .EmcDllXformDq5 = 0x00000007, + .EmcDllXformDq6 = 0x00000007, + .EmcDllXformDq7 = 0x00000007, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x0000004c, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000f15, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x5d569720, + .EmcXm2DqsPadCtrl4 = 0x00492492, + .EmcXm2DqsPadCtrl5 = 0x00552452, + .EmcXm2DqsPadCtrl6 = 0x61751800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000005, + .McEmemArbTimingRp = 0x00000006, + .McEmemArbTimingRc = 0x00000016, + .McEmemArbTimingRas = 0x0000000e, + .McEmemArbTimingFaw = 0x00000011, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000007, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09070202, + .McEmemArbDaCovers = 0x001a1016, + .McEmemArbMisc0 = 0x734e2a17, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan/bct/sdram-hynix-4GB-300.inc b/src/mainboard/google/nyan/bct/sdram-hynix-4GB-300.inc new file mode 100644 index 0000000000..21bf5158a0 --- /dev/null +++ b/src/mainboard/google/nyan/bct/sdram-hynix-4GB-300.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-4GB-300.cfg, do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000032, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x00000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430f0f, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000000d, + .EmcRfc = 0x00000067, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000009, + .EmcRp = 0x00000003, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x00000008, + .EmcR2p = 0x00000002, + .EmcW2p = 0x00000009, + .EmcRdRcd = 0x00000003, + .EmcWrRcd = 0x00000003, + .EmcRrd = 0x00000002, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000003, + .EmcWdvMask = 0x00000003, + .EmcQUse = 0x00000005, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x00000007, + .EmcPutermExtra = 0x00020000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x0000000e, + .EmcRdv = 0x00000010, + .EmcRdvMask = 0x00000012, + .EmcQpop = 0x00000009, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x000008e4, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000239, + .EmcPdEx2Wr = 0x00000001, + .EmcPdEx2Rd = 0x00000008, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000065, + .EmcRw2Pden = 0x0000000e, + .EmcTxsr = 0x0000006c, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000009, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000924, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000321, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200000, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x0117000e, + .EmcMrsWaitCnt2 = 0x0117000e, + .EmcCfg = 0x73340000, + .EmcCfg2 = 0x000008d5, + .EmcCfgPipe = 0x000052a3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800012d7, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040128, + .EmcDllXformDqs0 = 0x00030000, + .EmcDllXformDqs1 = 0x00030000, + .EmcDllXformDqs2 = 0x00030000, + .EmcDllXformDqs3 = 0x00030000, + .EmcDllXformDqs4 = 0x00030000, + .EmcDllXformDqs5 = 0x00030000, + .EmcDllXformDqs6 = 0x00030000, + .EmcDllXformDqs7 = 0x00030000, + .EmcDllXformDqs8 = 0x00030000, + .EmcDllXformDqs9 = 0x00030000, + .EmcDllXformDqs10 = 0x00030000, + .EmcDllXformDqs11 = 0x00030000, + .EmcDllXformDqs12 = 0x00030000, + .EmcDllXformDqs13 = 0x00030000, + .EmcDllXformDqs14 = 0x00030000, + .EmcDllXformDqs15 = 0x00030000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00084000, + .EmcDllXformAddr1 = 0x00084000, + .EmcDllXformAddr2 = 0x00010000, + .EmcDllXformAddr3 = 0x00084000, + .EmcDllXformAddr4 = 0x00084000, + .EmcDllXformAddr5 = 0x00010000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00060000, + .EmcDllXformDq1 = 0x00060000, + .EmcDllXformDq2 = 0x00060000, + .EmcDllXformDq3 = 0x00060000, + .EmcDllXformDq4 = 0x00006000, + .EmcDllXformDq5 = 0x00006000, + .EmcDllXformDq6 = 0x00006000, + .EmcDllXformDq7 = 0x00006000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000002, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000321, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x01231339, + .EmcXm2DqsPadCtrl3 = 0x51451420, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000096, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x08000004, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000002, + .McEmemArbTimingRc = 0x00000007, + .McEmemArbTimingRas = 0x00000004, + .McEmemArbTimingFaw = 0x00000005, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000007, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040202, + .McEmemArbDaCovers = 0x000b0607, + .McEmemArbMisc0 = 0x77450e08, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan/bct/sdram-hynix-4GB-792.inc b/src/mainboard/google/nyan/bct/sdram-hynix-4GB-792.inc new file mode 100644 index 0000000000..70f6ccd02b --- /dev/null +++ b/src/mainboard/google/nyan/bct/sdram-hynix-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-4GB-792.cfg, do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430808, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000024, + .EmcRfc = 0x00000114, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000017, + .EmcRdvMask = 0x00000019, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x0000010d, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x0000011e, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200018, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x006f000e, + .EmcMrsWaitCnt2 = 0x006f000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x000040a0, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00038000, + .EmcDllXformAddr1 = 0x00038000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00038000, + .EmcDllXformAddr4 = 0x00038000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000005, + .EmcDliTrimTxDqs1 = 0x00000005, + .EmcDliTrimTxDqs2 = 0x00000003, + .EmcDliTrimTxDqs3 = 0x00000005, + .EmcDliTrimTxDqs4 = 0x00000005, + .EmcDliTrimTxDqs5 = 0x00000002, + .EmcDliTrimTxDqs6 = 0x00000005, + .EmcDliTrimTxDqs7 = 0x00000005, + .EmcDliTrimTxDqs8 = 0x00000005, + .EmcDliTrimTxDqs9 = 0x00000005, + .EmcDliTrimTxDqs10 = 0x00000003, + .EmcDliTrimTxDqs11 = 0x00000005, + .EmcDliTrimTxDqs12 = 0x00000005, + .EmcDliTrimTxDqs13 = 0x00000002, + .EmcDliTrimTxDqs14 = 0x00000005, + .EmcDliTrimTxDqs15 = 0x00000005, + .EmcDllXformDq0 = 0x00000009, + .EmcDllXformDq1 = 0x0000000c, + .EmcDllXformDq2 = 0x00000008, + .EmcDllXformDq3 = 0x0000000a, + .EmcDllXformDq4 = 0x0000000a, + .EmcDllXformDq5 = 0x00000008, + .EmcDllXformDq6 = 0x0000000a, + .EmcDllXformDq7 = 0x00000008, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x746c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan/bct/sdram-unused.inc b/src/mainboard/google/nyan/bct/sdram-unused.inc new file mode 100644 index 0000000000..bef63dcecc --- /dev/null +++ b/src/mainboard/google/nyan/bct/sdram-unused.inc @@ -0,0 +1,4 @@ +{ /* dummy. */ + .MemoryType = NvBootMemoryType_Unused, + 0, +}, diff --git a/src/mainboard/google/nyan/bct/spi.cfg b/src/mainboard/google/nyan/bct/spi.cfg new file mode 100644 index 0000000000..7d05363446 --- /dev/null +++ b/src/mainboard/google/nyan/bct/spi.cfg @@ -0,0 +1,33 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 32768; +PageSize = 2048; +PartitionSize = 4194304; + +Bctcopy = 1; + +DevType[0] = NvBootDevType_Spi; +DeviceParam[0].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[0].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[0].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[0].SpiFlashParams.PageSize2kor16k = 0; + +DevType[1] = NvBootDevType_Spi; +DeviceParam[1].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[1].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[1].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[1].SpiFlashParams.PageSize2kor16k = 0; + +DevType[2] = NvBootDevType_Spi; +DeviceParam[2].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[2].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[2].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[2].SpiFlashParams.PageSize2kor16k = 0; + +DevType[3] = NvBootDevType_Spi; +DeviceParam[3].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[3].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[3].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[3].SpiFlashParams.PageSize2kor16k = 0; diff --git a/src/mainboard/google/nyan/boardid.c b/src/mainboard/google/nyan/boardid.c new file mode 100644 index 0000000000..85a55fc329 --- /dev/null +++ b/src/mainboard/google/nyan/boardid.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + + if (id < 0) { + id = gpio_get(GPIO(Q3)) << 0 | + gpio_get(GPIO(T1)) << 1 | + gpio_get(GPIO(X1)) << 2 | + gpio_get(GPIO(X4)) << 3; + printk(BIOS_SPEW, "Board ID: %#x.\n", id); + } + + return id; +} diff --git a/src/mainboard/google/nyan/bootblock.c b/src/mainboard/google/nyan/bootblock.c new file mode 100644 index 0000000000..bc3cd3efa2 --- /dev/null +++ b/src/mainboard/google/nyan/bootblock.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME: move back to soc code? */ + +#include "pmic.h" + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta); + + clock_configure_source(mselect, PLLP, 102000); + + /* The PMIC is on I2C5 and can run at 400 KHz. */ + clock_configure_i2c_scl_freq(i2c5, PLLP, 400); + + /* TODO: We should be able to set this to 50MHz, but that did not seem + * reliable. */ + clock_configure_source(sbc4, PLLP, 33333); +} + +void bootblock_mainboard_init(void) +{ + set_clock_sources(); + + clock_enable_clear_reset(CLK_L_CACHE2 | CLK_L_TMR, + CLK_H_I2C5 | CLK_H_APBDMA, + 0, CLK_V_MSELECT, 0, 0); + + // Board ID GPIOs, bits 0-3. + gpio_input(GPIO(Q3)); + gpio_input(GPIO(T1)); + gpio_input(GPIO(X1)); + gpio_input(GPIO(X4)); + + // I2C5 (PMU) clock. + pinmux_set_config(PINMUX_PWR_I2C_SCL_INDEX, + PINMUX_PWR_I2C_SCL_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + // I2C5 (PMU) data. + pinmux_set_config(PINMUX_PWR_I2C_SDA_INDEX, + PINMUX_PWR_I2C_SDA_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + i2c_init(4); + pmic_init(4); + + /* SPI4 data out (MOSI) */ + pinmux_set_config(PINMUX_GPIO_PG6_INDEX, + PINMUX_GPIO_PG6_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 data in (MISO) */ + pinmux_set_config(PINMUX_GPIO_PG7_INDEX, + PINMUX_GPIO_PG7_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 clock */ + pinmux_set_config(PINMUX_GPIO_PG5_INDEX, + PINMUX_GPIO_PG5_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + /* SPI4 chip select 0 */ + pinmux_set_config(PINMUX_GPIO_PI3_INDEX, + PINMUX_GPIO_PI3_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + + tegra_spi_init(4); +} diff --git a/src/mainboard/google/nyan/chromeos.c b/src/mainboard/google/nyan/chromeos.c new file mode 100644 index 0000000000..cb276b939a --- /dev/null +++ b/src/mainboard/google/nyan/chromeos.c @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO(R1); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO(R1)); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO(R4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: active low */ + gpios->gpios[count].port = GPIO(Q0); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: active high */ + gpios->gpios[count].port = GPIO(U4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: active low (output) */ + gpios->gpios[count].port = GPIO(I5); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO(R1)); +} diff --git a/src/mainboard/google/nyan/devicetree.cb b/src/mainboard/google/nyan/devicetree.cb new file mode 100644 index 0000000000..8919941360 --- /dev/null +++ b/src/mainboard/google/nyan/devicetree.cb @@ -0,0 +1,94 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/nvidia/tegra124 + device cpu_cluster 0 on end +# N.B. We ae not using the device tree in an effective way. +# We need to change this in future such that the on-soc +# devices are 'chips', which will allow us to go at them +# in parallel. This is even easier on the ARM SOCs since there +# are no single-access resources such as the infamous +# cf8/cfc registers found on PCs. + register "display_controller" = "TEGRA_ARM_DISPLAYA" + register "xres" = "1366" + register "yres" = "768" + + # bits per pixel and color depth + register "framebuffer_bits_per_pixel" = "16" + register "color_depth" = "6" + # "6" is defined as COLOR_DEPTH_B5G6R5 in dc_reg.h + + register "panel_bits_per_pixel" = "18" + + register "cache_policy" = "DCACHE_WRITETHROUGH" + + # With some help from the mainbaord designer + register "backlight_en_gpio" = "GPIO(H2)" + register "lvds_shutdown_gpio" = "0" + register "backlight_vdd_gpio" = "GPIO(P2)" + register "panel_vdd_gpio" = "0" + register "pwm" = "1" + + # various panel delay time + register "vdd_delay_ms" = "200" + register "pwm_to_bl_delay_ms" = "10" + register "vdd_to_hpd_delay_ms" = "200" + register "hpd_unplug_min_us" = "2000" + register "hpd_plug_min_us" = "250" + register "hpd_irq_min_us" = "250" + +# How to compute these: xrandr --verbose will give you this: +#Detailed mode: Clock 285.250 MHz, 272 mm x 181 mm +# 2560 2608 2640 2720 hborder 0 +# 1700 1703 1713 1749 vborder 0 +#Then you can compute your values: +#H front porch = 2608 - 2560 = 48 +#H sync = 2640 - 2608 = 32 +#H back porch = 2720 - 2640 = 80 +#V front porch = 1703 - 1700 = 3 +#V sync = 1713 - 1703 = 10 +#V back porch = 1749 - 1713 = 36 +#href_to_sync and vref_to_sync are from the vendor +#this is just an example for a Pixel panel; other panels differ. +# Here is a peppy panel: +# 1366x768 (0x45) 76.4MHz -HSync -VSync *current +preferred +# h: width 1366 start 1502 end 1532 total 1592 +# v: height 768 start 776 end 788 total 800 + register "href_to_sync" = "1" + register "hfront_porch" = "136" + register "hsync_width" = "30" + register "hback_porch" = "60" + + register "vref_to_sync" = "1" + register "vfront_porch" = "8" + register "vsync_width" = "12" + register "vback_porch" = "12" + + register "pixel_clock" = "76400000" + + # link configurations + register "lane_count" = "1" + register "enhanced_framing" = "1" + register "link_bw" = "10" + # "10" is defined as SOR_LINK_SPEED_G2_7 in sor.h + + register "drive_current" = "0x40404040" + register "preemphasis" = "0x0f0f0f0f" + register "postcursor" = "0" +end diff --git a/src/mainboard/google/nyan/early_configs.c b/src/mainboard/google/nyan/early_configs.c new file mode 100644 index 0000000000..de9fe8ef9d --- /dev/null +++ b/src/mainboard/google/nyan/early_configs.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void setup_pinmux(void) +{ + /* Write protect. */ + gpio_input_pullup(GPIO(R1)); + /* Recovery mode. */ + gpio_input_pullup(GPIO(Q7)); + /* Lid switch. */ + gpio_input_pullup(GPIO(R4)); + /* Power switch. */ + gpio_input_pullup(GPIO(Q0)); + /* Developer mode. */ + gpio_input_pullup(GPIO(Q6)); + /* EC in RW. */ + gpio_input_pullup(GPIO(U4)); + + /* route PU4/5 to GMI to remove conflict w/PWM1/2. */ + pinmux_set_config(PINMUX_GPIO_PU4_INDEX, + PINMUX_GPIO_PU4_FUNC_NOR); /* s/b GMI */ + pinmux_set_config(PINMUX_GPIO_PU5_INDEX, + PINMUX_GPIO_PU5_FUNC_NOR); /* s/b GMI */ + + /* SOC and TPM reset GPIO, active low. */ + gpio_output(GPIO(I5), 1); + + /* SPI1 MOSI */ + pinmux_set_config(PINMUX_ULPI_CLK_INDEX, PINMUX_ULPI_CLK_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 MISO */ + pinmux_set_config(PINMUX_ULPI_DIR_INDEX, PINMUX_ULPI_DIR_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 SCLK */ + pinmux_set_config(PINMUX_ULPI_NXT_INDEX, PINMUX_ULPI_NXT_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 CS0 */ + pinmux_set_config(PINMUX_ULPI_STP_INDEX, PINMUX_ULPI_STP_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + + /* I2C3 (cam) clock. */ + pinmux_set_config(PINMUX_CAM_I2C_SCL_INDEX, + PINMUX_CAM_I2C_SCL_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + /* I2C3 (cam) data. */ + pinmux_set_config(PINMUX_CAM_I2C_SDA_INDEX, + PINMUX_CAM_I2C_SDA_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + + /* switch unused pin to GPIO */ + gpio_set_mode(GPIO(X3), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X4), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X5), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X6), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X7), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(W3), GPIO_MODE_GPIO); +} + +static void configure_ec_spi_bus(void) +{ + clock_configure_source(sbc1, CLK_M, 3000); +} + +static void configure_tpm_i2c_bus(void) +{ + clock_configure_i2c_scl_freq(i2c3, PLLP, 400); + + i2c_init(2); +} + +void early_mainboard_init(void) +{ + clock_enable_clear_reset(0, CLK_H_SBC1, CLK_U_I2C3, 0, 0, 0); + setup_pinmux(); + configure_ec_spi_bus(); + configure_tpm_i2c_bus(); +} diff --git a/src/mainboard/google/nyan/mainboard.c b/src/mainboard/google/nyan/mainboard.c new file mode 100644 index 0000000000..ff4bc15084 --- /dev/null +++ b/src/mainboard/google/nyan/mainboard.c @@ -0,0 +1,274 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* + * The max98090 codec and the temperature sensor are on I2C1. These + * can both run at 400 KHz, but the kernel sets the bus to 100 KHz. + */ + clock_configure_i2c_scl_freq(i2c1, PLLP, 100); + + /* + * MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's + * maximum speed (48MHz) so we can change SDCLK by second stage divisor + * in payloads, without touching base clock. + */ + clock_configure_source(sdmmc3, PLLP, 48000); + clock_configure_source(sdmmc4, PLLP, 48000); + + /* External peripheral 1: audio codec (max98090) using 12MHz CLK1. + * Note the source id of CLK_M for EXTPERIPH1 is 3. */ + clock_configure_irregular_source(extperiph1, CLK_M, 12000, 3); + + /* + * We need 1.5MHz. So, we use CLK_M. CLK_DIVIDER macro returns a divisor + * (0xe) a little bit off from the ideal value (0xd) but it's good + * enough for beeps. The source id of CLK_M for I2S is 6. + */ + clock_configure_irregular_source(i2s1, CLK_M, 1500, 6); + + /* Note source id of PLLP for HOST1x is 4. */ + clock_configure_irregular_source(host1x, PLLP, 408000, 4); + + /* Use PLLD_OUT0 as clock source for disp1 */ + clrsetbits_le32(&clk_rst->clk_src_disp1, + CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + 2 /*PLLD_OUT0 */ << CLK_SOURCE_SHIFT); + +} + +static void setup_pinmux(void) +{ + // I2C1 clock. + pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX, + PINMUX_GEN1_I2C_SCL_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C1 data. + pinmux_set_config(PINMUX_GEN1_I2C_SDA_INDEX, + PINMUX_GEN1_I2C_SDA_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C2 clock. + pinmux_set_config(PINMUX_GEN2_I2C_SCL_INDEX, + PINMUX_GEN2_I2C_SCL_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C2 data. + pinmux_set_config(PINMUX_GEN2_I2C_SDA_INDEX, + PINMUX_GEN2_I2C_SDA_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C4 (DDC) clock. + pinmux_set_config(PINMUX_DDC_SCL_INDEX, + PINMUX_DDC_SCL_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + // I2C4 (DDC) data. + pinmux_set_config(PINMUX_DDC_SDA_INDEX, + PINMUX_DDC_SDA_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + + // TODO(hungte) Revice pinmux setup, make nice little SoC functions for + // every single logical thing instead of dumping a wall of code below. + uint32_t pin_up = PINMUX_PULL_UP | PINMUX_INPUT_ENABLE, + pin_down = PINMUX_PULL_DOWN | PINMUX_INPUT_ENABLE, + pin_none = PINMUX_PULL_NONE | PINMUX_INPUT_ENABLE; + + // MMC3 (sdcard reader) + pinmux_set_config(PINMUX_SDMMC3_CLK_INDEX, + PINMUX_SDMMC3_CLK_FUNC_SDMMC3 | pin_none); + pinmux_set_config(PINMUX_SDMMC3_CMD_INDEX, + PINMUX_SDMMC3_CMD_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT0_INDEX, + PINMUX_SDMMC3_DAT0_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT1_INDEX, + PINMUX_SDMMC3_DAT1_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT2_INDEX, + PINMUX_SDMMC3_DAT2_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT3_INDEX, + PINMUX_SDMMC3_DAT3_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_IN_INDEX, + PINMUX_SDMMC3_CLK_LB_IN_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_OUT_INDEX, + PINMUX_SDMMC3_CLK_LB_OUT_FUNC_SDMMC3 | pin_down); + + // MMC3 Card Detect pin. + gpio_input_pullup(GPIO(V2)); + // Disable SD card reader power so it can be reset even on warm boot. + // Payloads must enable power before accessing SD card slots. + gpio_output(GPIO(R0), 0); + + // MMC4 (eMMC) + pinmux_set_config(PINMUX_SDMMC4_CLK_INDEX, + PINMUX_SDMMC4_CLK_FUNC_SDMMC4 | pin_none); + pinmux_set_config(PINMUX_SDMMC4_CMD_INDEX, + PINMUX_SDMMC4_CMD_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT0_INDEX, + PINMUX_SDMMC4_DAT0_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT1_INDEX, + PINMUX_SDMMC4_DAT1_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT2_INDEX, + PINMUX_SDMMC4_DAT2_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT3_INDEX, + PINMUX_SDMMC4_DAT3_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT4_INDEX, + PINMUX_SDMMC4_DAT4_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT5_INDEX, + PINMUX_SDMMC4_DAT5_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT6_INDEX, + PINMUX_SDMMC4_DAT6_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT7_INDEX, + PINMUX_SDMMC4_DAT7_FUNC_SDMMC4 | pin_up); + + /* We pull the USB VBUS signals up but keep them as inputs since the + * voltage source likes to drive them low on overcurrent conditions */ + gpio_input_pullup(GPIO(N4)); /* USB VBUS EN0 */ + gpio_input_pullup(GPIO(N5)); /* USB VBUS EN1 */ + + /* Clock output 1 (for external peripheral) */ + pinmux_set_config(PINMUX_DAP_MCLK1_INDEX, + PINMUX_DAP_MCLK1_FUNC_EXTPERIPH1 | PINMUX_PULL_NONE); + + /* I2S1 */ + pinmux_set_config(PINMUX_DAP2_DIN_INDEX, + PINMUX_DAP2_DIN_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_DOUT_INDEX, + PINMUX_DAP2_DOUT_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_FS_INDEX, + PINMUX_DAP2_FS_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_SCLK_INDEX, + PINMUX_DAP2_SCLK_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + + /* PWM1 */ + pinmux_set_config(PINMUX_GPIO_PH1_INDEX, + PINMUX_GPIO_PH1_FUNC_PWM1 | PINMUX_PULL_NONE); + + /* DP HPD */ + pinmux_set_config(PINMUX_DP_HPD_INDEX, + PINMUX_DP_HPD_FUNC_DP | PINMUX_INPUT_ENABLE); +} + +static void setup_kernel_info(void) +{ + // Setup required information for Linux kernel. + + // pmc.odmdata: [18:19]: console type, [15:17]: UART id. + // TODO(hungte) This should be done by filling BCT values, or derived + // from CONFIG_CONSOLE_SERIAL_UART[A-E]. Right now we simply copy the + // value defined in BCT. + struct tegra_pmc_regs *pmc = (void*)TEGRA_PMC_BASE; + writel(0x80080000, &pmc->odmdata); + + // Not strictly info, but kernel graphics driver needs this region locked down + struct tegra_mc_regs *mc = (void *)TEGRA_MC_BASE; + writel(0, &mc->video_protect_bom); + writel(0, &mc->video_protect_size_mb); + writel(1, &mc->video_protect_reg_ctrl); +} + +static void setup_ec_spi(void) +{ + struct tegra_spi_channel *spi; + + spi = tegra_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS); +} + +static void mainboard_init(device_t dev) +{ + set_clock_sources(); + + clock_external_output(1); /* For external MAX98090 audio codec. */ + + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * conntected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (In our + * case, I2S/APBIF/AUDIO) will hang. + * + * Note that CLK_H_MEM (MC) and CLK_H_EMC should be already either + * initialized by BootROM, or in romstage SDRAM initialization. + */ + clock_enable_clear_reset(CLK_L_GPIO | CLK_L_I2C1 | CLK_L_SDMMC4 | + CLK_L_I2S0 | CLK_L_I2S1 | CLK_L_I2S2 | + CLK_L_SPDIF | CLK_L_USBD | CLK_L_DISP1 | + CLK_L_HOST1X | CLK_L_PWM, + + CLK_H_I2C2 | CLK_H_PMC | CLK_H_USB3, + + CLK_U_CSITE | CLK_U_SDMMC3, + + CLK_V_I2C4 | CLK_V_EXTPERIPH1 | CLK_V_APBIF | + CLK_V_AUDIO | CLK_V_I2S3 | CLK_V_I2S4 | + CLK_V_DAM0 | CLK_V_DAM1 | CLK_V_DAM2, + + CLK_W_DVFS | CLK_W_AMX0 | CLK_W_ADX0, + + CLK_X_DPAUX | CLK_X_SOR0 | CLK_X_AMX1 | + CLK_X_ADX1 | CLK_X_AFC0 | CLK_X_AFC1 | + CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | + CLK_X_AFC5); + + usb_setup_utmip((void*)TEGRA_USBD_BASE); + /* USB2 is the camera, we don't need it in firmware */ + usb_setup_utmip((void*)TEGRA_USB3_BASE); + + setup_pinmux(); + + i2c_init(0); + i2c_init(1); + i2c_init(3); + + setup_kernel_info(); + clock_init_arm_generic_timer(); + setup_ec_spi(); + elog_init(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "nyan", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} diff --git a/src/mainboard/google/nyan/memlayout.ld b/src/mainboard/google/nyan/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/nyan/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/nyan/pmic.c b/src/mainboard/google/nyan/pmic.c new file mode 100644 index 0000000000..532b32992c --- /dev/null +++ b/src/mainboard/google/nyan/pmic.c @@ -0,0 +1,116 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pmic.h" + +enum { + AS3722_I2C_ADDR = 0x40 +}; + +struct as3722_init_reg { + u8 reg; + u8 val; + u8 delay; +}; + +static struct as3722_init_reg init_list[] = { + {AS3722_SDO0, 0x3C, 1}, + {AS3722_SDO1, 0x32, 0}, + {AS3722_LDO3, 0x59, 0}, + {AS3722_SDO2, 0x3C, 0}, + {AS3722_SDO3, 0x00, 0}, + {AS3722_SDO4, 0x00, 0}, + {AS3722_SDO5, 0x50, 0}, + {AS3722_SDO6, 0x28, 1}, + {AS3722_LDO0, 0x8A, 0}, + {AS3722_LDO1, 0x00, 0}, + {AS3722_LDO2, 0x10, 0}, + {AS3722_LDO4, 0x00, 0}, + {AS3722_LDO5, 0x00, 0}, + {AS3722_LDO6, 0x00, 0}, + {AS3722_LDO7, 0x00, 0}, + {AS3722_LDO9, 0x00, 0}, + {AS3722_LDO10, 0x00, 0}, + {AS3722_LDO11, 0x00, 1}, +}; + +static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) +{ + if (i2c_writeb(bus, AS3722_I2C_ADDR, reg, val)) { + printk(BIOS_ERR, "%s: reg = 0x%02X, value = 0x%02X failed!\n", + __func__, reg, val); + /* Reset the SoC on any PMIC write error */ + hard_reset(); + } else { + if (delay) + udelay(500); + } +} + +static void pmic_slam_defaults(unsigned bus) +{ + int i; + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + struct as3722_init_reg *reg = &init_list[i]; + pmic_write_reg(bus, reg->reg, reg->val, reg->delay); + } +} + +void pmic_init(unsigned bus) +{ + /* + * Don't need to set up VDD_CORE - already done - by OTP + * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled. + * Don't write LDCONTROL - it's already 0xFF, i.e. all LDOs enabled. + */ + + /* Restore PMIC POR defaults, in case kernel changed 'em */ + pmic_slam_defaults(bus); + + /* First set VDD_CPU to 1.2V, then enable the VDD_CPU regulator. */ + if (board_id() == 0) + pmic_write_reg(bus, 0x00, 0x3c, 1); + else + pmic_write_reg(bus, 0x00, 0x50, 1); + + /* First set VDD_GPU to 1.0V, then enable the VDD_GPU regulator. */ + pmic_write_reg(bus, 0x06, 0x28, 1); + + /* + * First set +1.2V_GEN_AVDD to 1.2V, then enable the +1.2V_GEN_AVDD + * regulator. + */ + pmic_write_reg(bus, 0x12, 0x10, 1); + + /* + * Panel power GPIO O4. Set mode for GPIO4 (0x0c to 7), then set + * the value (register 0x20 bit 4) + */ + pmic_write_reg(bus, 0x0c, 0x07, 0); + pmic_write_reg(bus, 0x20, 0x10, 1); +} diff --git a/src/mainboard/google/nyan/pmic.h b/src/mainboard/google/nyan/pmic.h new file mode 100644 index 0000000000..dd65808e57 --- /dev/null +++ b/src/mainboard/google/nyan/pmic.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_PMIC_H__ +#define __MAINBOARD_GOOGLE_NYAN_PMIC_H__ + +enum { + AS3722_SDO0 = 0, + AS3722_SDO1, + AS3722_SDO2, + AS3722_SDO3, + AS3722_SDO4, + AS3722_SDO5, + AS3722_SDO6, + + AS3722_LDO0 = 0x10, + AS3722_LDO1, + AS3722_LDO2, + AS3722_LDO3, + AS3722_LDO4, + AS3722_LDO5, + AS3722_LDO6, + AS3722_LDO7, + + AS3722_LDO9 = 0x19, + AS3722_LDO10, + AS3722_LDO11, +}; + +void pmic_init(unsigned bus); + +#endif /* __MAINBOARD_GOOGLE_NYAN_PMIC_H__ */ diff --git a/src/mainboard/google/nyan/reset.c b/src/mainboard/google/nyan/reset.c new file mode 100644 index 0000000000..e58890e604 --- /dev/null +++ b/src/mainboard/google/nyan/reset.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void hard_reset(void) +{ + gpio_output(GPIO(I5), 0); + while(1); +} diff --git a/src/mainboard/google/nyan/romstage.c b/src/mainboard/google/nyan/romstage.c new file mode 100644 index 0000000000..a65d7f6ce4 --- /dev/null +++ b/src/mainboard/google/nyan/romstage.c @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdram_configs.h" + +static void __attribute__((noinline)) romstage(void) +{ + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + exception_init(); + + sdram_init(get_sdram_config()); + + /* used for MMU and CBMEM setup, in MB */ + u32 dram_start_mb = (uintptr_t)_dram/MiB; + u32 dram_end_mb = sdram_max_addressable_mb(); + u32 dram_size_mb = dram_end_mb - dram_start_mb; + + configure_l2_cache(); + mmu_init(); + /* Device memory below DRAM is uncached. */ + mmu_config_range(0, dram_start_mb, DCACHE_OFF); + /* SRAM is cached. MMU code will round size up to page size. */ + mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB), + DCACHE_WRITEBACK); + /* DRAM is cached. */ + mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK); + /* A window for DMA is uncached. */ + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + /* The space above DRAM is uncached. */ + if (dram_end_mb < 4096) + mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF); + mmu_disable_range(0, 1); + dcache_mmu_enable(); + + /* + * A watchdog reset only resets part of the system so it ends up in + * a funny state. If that happens, we need to reset the whole machine. + */ + if (power_reset_status() == POWER_RESET_WATCHDOG) { + printk(BIOS_INFO, "Watchdog reset detected, rebooting.\n"); + hard_reset(); + } + + cbmem_initialize_empty(); + + early_mainboard_init(); + + vboot_verify_firmware(romstage_handoff_find_or_add()); + + timestamp_add_now(TS_START_COPYRAM); + void *entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + "fallback/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + + stage_exit(entry); +} + +/* Stub to force arm_init_caches to the top, before any stack/memory accesses */ +void main(void) +{ + asm volatile ("bl arm_init_caches" + ::: "r0","r1","r2","r3","r4","r5","ip"); + romstage(); +} diff --git a/src/mainboard/google/nyan/sdram_configs.c b/src/mainboard/google/nyan/sdram_configs.c new file mode 100644 index 0000000000..d99f6bd833 --- /dev/null +++ b/src/mainboard/google/nyan/sdram_configs.c @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "sdram_configs.h" + +static struct sdram_params sdram_configs[] = { +#include "bct/sdram-hynix-2GB-924.inc" /* ram_code = 0000 */ +#include "bct/sdram-hynix-4GB-792.inc" /* ram_code = 0001 */ +#include "bct/sdram-unused.inc" /* ram_code = 0010 */ +#include "bct/sdram-unused.inc" /* ram_code = 0011 */ +#include "bct/sdram-unused.inc" /* ram_code = 0100 */ +#include "bct/sdram-unused.inc" /* ram_code = 0101 */ +#include "bct/sdram-unused.inc" /* ram_code = 0110 */ +#include "bct/sdram-unused.inc" /* ram_code = 0111 */ +#include "bct/sdram-unused.inc" /* ram_code = 1000 */ +#include "bct/sdram-unused.inc" /* ram_code = 1001 */ +#include "bct/sdram-unused.inc" /* ram_code = 1010 */ +#include "bct/sdram-unused.inc" /* ram_code = 1011 */ +#include "bct/sdram-unused.inc" /* ram_code = 1100 */ +#include "bct/sdram-unused.inc" /* ram_code = 1101 */ +#include "bct/sdram-unused.inc" /* ram_code = 1110 */ +#include "bct/sdram-unused.inc" /* ram_code = 1111 */ +}; + +const struct sdram_params *get_sdram_config() +{ + uint32_t ramcode = sdram_get_ram_code(); + /* + * If we need to apply some special hacks to RAMCODE mapping (ex, by + * board_id), do that now. + */ + + printk(BIOS_SPEW, "%s: RAMCODE=%d\n", __func__, ramcode); + if (ramcode >= sizeof(sdram_configs) / sizeof(sdram_configs[0]) || + sdram_configs[ramcode].MemoryType == NvBootMemoryType_Unused) { + die("Invalid RAMCODE."); + } + + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/nyan/sdram_configs.h b/src/mainboard/google/nyan/sdram_configs.h new file mode 100644 index 0000000000..4a5ae68f4a --- /dev/null +++ b/src/mainboard/google/nyan/sdram_configs.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_SDRAM_CONFIG_H__ +#define __MAINBOARD_GOOGLE_NYAN_SDRAM_CONFIG_H__ + +#include + +/* Loads SDRAM configurations for current system. */ +const struct sdram_params *get_sdram_config(void); + +#endif /* __MAINBOARD_GOOGLE_NYAN_SDRAM_CONFIG_H__ */ diff --git a/src/mainboard/google/nyan_big/Kconfig b/src/mainboard/google/nyan_big/Kconfig new file mode 100644 index 0000000000..9105076095 --- /dev/null +++ b/src/mainboard/google/nyan_big/Kconfig @@ -0,0 +1,101 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_NYAN_BIG + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select SOC_NVIDIA_TEGRA124 + select SPI_FLASH + select SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B + select TEGRA124_MODEL_CD570M + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/nyan_big + +config MAINBOARD_PART_NUMBER + string + default "Nyan Big" + +choice + prompt "BCT boot media" + default NYAN_BIG_BCT_CFG_SPI + help + Which boot media to configure the BCT for. + +config NYAN_BIG_BCT_CFG_SPI + bool "SPI" + help + Configure the BCT for booting from SPI. + +config NYAN_BIG_BCT_CFG_EMMC + bool "eMMC" + help + Configure the BCT for booting from eMMC. + +endchoice + +config BOOT_MEDIA_SPI_BUS + int "SPI bus with boot media ROM" + range 1 6 + depends on NYAN_BIG_BCT_CFG_SPI + default 4 + help + Which SPI bus the boot media is connected to. + +config BOOT_MEDIA_SPI_CHIP_SELECT + int "Chip select for SPI boot media" + range 0 3 + depends on NYAN_BIG_BCT_CFG_SPI + default 0 + help + Which chip select to use for boot media. + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 1 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config FLASHMAP_OFFSET + hex + default 0x00100000 + +config DRIVER_TPM_I2C_BUS + hex + default 0x2 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +endif # BOARD_GOOGLE_NYAN_BIG diff --git a/src/mainboard/google/nyan_big/Makefile.inc b/src/mainboard/google/nyan_big/Makefile.inc new file mode 100644 index 0000000000..5ba341c2da --- /dev/null +++ b/src/mainboard/google/nyan_big/Makefile.inc @@ -0,0 +1,45 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# Add a handler for BCT config files +$(call add-special-class,bct-cfg) +bct-cfg-handler= $(eval $(obj)/generated/bct.cfg: $(1)$(2)) + +$(obj)/generated/bct.cfg: + @printf " CAT $(subst $(obj)/,,$(@))\n" + cat $^ > $@ + +subdirs-y += bct + +bootblock-y += bootblock.c +bootblock-y += pmic.c +bootblock-y += reset.c + +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += early_configs.c + +ramstage-y += reset.c +ramstage-y += boardid.c +ramstage-y += mainboard.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/nyan_big/bct/Makefile.inc b/src/mainboard/google/nyan_big/bct/Makefile.inc new file mode 100644 index 0000000000..b8501aefa5 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/Makefile.inc @@ -0,0 +1,27 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bct-cfg-$(CONFIG_NYAN_BIG_BCT_CFG_EMMC) += emmc.cfg +bct-cfg-$(CONFIG_NYAN_BIG_BCT_CFG_SPI) += spi.cfg +bct-cfg-y += odmdata.cfg +bct-cfg-y += jtag.cfg + +# Note when SDRAM config (sdram-*.cfg) files are changed, we have to regenerate +# the include files (sdram-*.inc). See ../../nyan/bct/Makefile.inc for more +# information. diff --git a/src/mainboard/google/nyan_big/bct/emmc.cfg b/src/mainboard/google/nyan_big/bct/emmc.cfg new file mode 100644 index 0000000000..c93cf4685b --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/emmc.cfg @@ -0,0 +1,13 @@ +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 0x00004000; +PageSize = 0x00000200; +PartitionSize = 0x01000000; + +DevType[0] = NvBootDevType_Sdmmc; +DeviceParam[0].SdmmcParams.ClockDivider = 0x00000009; +DeviceParam[0].SdmmcParams.DataWidth = NvBootSdmmcDataWidth_8Bit; +DeviceParam[0].SdmmcParams.MaxPowerClassSupported = 0x00000000; +DeviceParam[0].SdmmcParams.MultiPageSupport = 0x00000000; diff --git a/src/mainboard/google/nyan_big/bct/jtag.cfg b/src/mainboard/google/nyan_big/bct/jtag.cfg new file mode 100644 index 0000000000..f43e143377 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/jtag.cfg @@ -0,0 +1,16 @@ +# +# Set JtagCtrl to 1 to reenable Jtag +# +JtagCtrl = 0; +# +# Fill in chip unique id +# +# ChipUid can be found by running tegrarcm in tegra recovery mode +# (also hooking up A-A USB cable) and looking for console output +# on line starting with "Chip UID:" +# +# Command example: +# $ sudo tegrarcm --bct=/build/nyan/firmware/bct/board.bct --bootloader=/build/nyan/firmware/u-boot.bin --loadaddr=0x80108000 +# Where board.bct and u-boot.bin do not have to be prebuilt. +# +ChipUid = 0x00000000000000000000000000000000; diff --git a/src/mainboard/google/nyan_big/bct/odmdata.cfg b/src/mainboard/google/nyan_big/bct/odmdata.cfg new file mode 100644 index 0000000000..d0ab2bf8fb --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/odmdata.cfg @@ -0,0 +1 @@ +OdmData = 0x80080000; diff --git a/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-204.inc b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-204.inc new file mode 100644 index 0000000000..d75e0b5272 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-204-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000035, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000003, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000032, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x00000038, + .EmcTxsrDll = 0x00000038, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80001221, + .EmcEmrs = 0x80100003, + .EmcEmrs2 = 0x80200008, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x00004000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00004000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00094000, + .EmcDllXformDq3 = 0x00094000, + .EmcDllXformDq4 = 0x00009400, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80001221, + .EmcWarmBootMrsExtra = 0x80100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0405, + .McEmemArbMisc0 = 0x73840a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-792.inc b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-792.inc new file mode 100644 index 0000000000..67a0cd41ed --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Nike_0224_2GB__ODTCTT_792Mhz_V02.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000007, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab198, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200418, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f8000c, + .EmcMrsWaitCnt2 = 0x00f8000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0080089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000005, + .EmcDllXformDqs1 = 0x00000005, + .EmcDllXformDqs2 = 0x00000005, + .EmcDllXformDqs3 = 0x00000005, + .EmcDllXformDqs4 = 0x00000005, + .EmcDllXformDqs5 = 0x00000005, + .EmcDllXformDqs6 = 0x00000005, + .EmcDllXformDqs7 = 0x00000005, + .EmcDllXformDqs8 = 0x00000005, + .EmcDllXformDqs9 = 0x00000005, + .EmcDllXformDqs10 = 0x00000005, + .EmcDllXformDqs11 = 0x00000005, + .EmcDllXformDqs12 = 0x00000005, + .EmcDllXformDqs13 = 0x00000005, + .EmcDllXformDqs14 = 0x00000005, + .EmcDllXformDqs15 = 0x00000005, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00034000, + .EmcDllXformAddr1 = 0x00034000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00034000, + .EmcDllXformAddr4 = 0x00034000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000009, + .EmcDliTrimTxDqs4 = 0x00000009, + .EmcDliTrimTxDqs5 = 0x00000007, + .EmcDliTrimTxDqs6 = 0x00000009, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000009, + .EmcDliTrimTxDqs12 = 0x00000009, + .EmcDliTrimTxDqs13 = 0x00000007, + .EmcDliTrimTxDqs14 = 0x00000009, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000a, + .EmcDllXformDq1 = 0x0000000a, + .EmcDllXformDq2 = 0x0000000a, + .EmcDllXformDq3 = 0x0000000a, + .EmcDllXformDq4 = 0x0000000a, + .EmcDllXformDq5 = 0x0000000a, + .EmcDllXformDq6 = 0x0000000a, + .EmcDllXformDq7 = 0x0000000a, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x80000005, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000101, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-924.inc b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-924.inc new file mode 100644 index 0000000000..e4d4faf24a --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-hynix-2GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-924-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430404, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000002b, + .EmcRfc = 0x000000ef, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001e, + .EmcRp = 0x0000000b, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000f, + .EmcR2p = 0x00000005, + .EmcW2p = 0x00000016, + .EmcRdRcd = 0x0000000b, + .EmcWrRcd = 0x0000000b, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000c, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000e, + .EmcPutermExtra = 0x000a0000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000015, + .EmcRdv = 0x0000001b, + .EmcRdvMask = 0x0000001d, + .EmcQpop = 0x00000010, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x00001be9, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000006fa, + .EmcPdEx2Wr = 0x00000004, + .EmcPdEx2Rd = 0x00000015, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000e6, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x000000fa, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000006, + .EmcTckesr = 0x00000007, + .EmcTpd = 0x00000006, + .EmcTfaw = 0x00000022, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x0000000a, + .EmcTClkStop = 0x0000000a, + .EmcTRefBw = 0x00001c29, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000002, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000f15, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200020, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00ce000e, + .EmcMrsWaitCnt2 = 0x00ce000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x000008a5, + .EmcCfgPipe = 0x00000000, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800037ed, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00401b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000005, + .EmcDllXformDqs1 = 0x00000005, + .EmcDllXformDqs2 = 0x00000005, + .EmcDllXformDqs3 = 0x00000005, + .EmcDllXformDqs4 = 0x00000005, + .EmcDllXformDqs5 = 0x00000005, + .EmcDllXformDqs6 = 0x00000005, + .EmcDllXformDqs7 = 0x00000005, + .EmcDllXformDqs8 = 0x00000005, + .EmcDllXformDqs9 = 0x00000005, + .EmcDllXformDqs10 = 0x00000005, + .EmcDllXformDqs11 = 0x00000005, + .EmcDllXformDqs12 = 0x00000005, + .EmcDllXformDqs13 = 0x00000005, + .EmcDllXformDqs14 = 0x00000005, + .EmcDllXformDqs15 = 0x00000005, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0000400e, + .EmcDllXformAddr1 = 0x0000400e, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0000400e, + .EmcDllXformAddr4 = 0x0000400e, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00000006, + .EmcDllXformDq1 = 0x00000006, + .EmcDllXformDq2 = 0x00000006, + .EmcDllXformDq3 = 0x00000006, + .EmcDllXformDq4 = 0x00000006, + .EmcDllXformDq5 = 0x00000006, + .EmcDllXformDq6 = 0x00000006, + .EmcDllXformDq7 = 0x00000006, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x0000004c, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000f15, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0020013d, + .EmcXm2DqsPadCtrl3 = 0x55555520, + .EmcXm2DqsPadCtrl4 = 0x003cf3cf, + .EmcXm2DqsPadCtrl5 = 0x003cf3cf, + .EmcXm2DqsPadCtrl6 = 0x55555500, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000005, + .McEmemArbTimingRp = 0x00000006, + .McEmemArbTimingRc = 0x00000016, + .McEmemArbTimingRas = 0x0000000e, + .McEmemArbTimingFaw = 0x00000011, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09060202, + .McEmemArbDaCovers = 0x001a1016, + .McEmemArbMisc0 = 0x734e2a17, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-204.inc b/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-204.inc new file mode 100644 index 0000000000..2feede7239 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0100-204-4GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000047, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000003, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000044, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x0000004a, + .EmcTxsrDll = 0x0000004a, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00001221, + .EmcEmrs = 0x00100003, + .EmcEmrs2 = 0x00200008, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x00004000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00004000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00094000, + .EmcDllXformDq3 = 0x00094000, + .EmcDllXformDq4 = 0x00009400, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00001221, + .EmcWarmBootMrsExtra = 0x00100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0405, + .McEmemArbMisc0 = 0x74a40a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-792.inc b/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-792.inc new file mode 100644 index 0000000000..4b556fdb7a --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-hynix-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Nike_PVT_ODT_CTT_4GB_792MHz_V16.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000024, + .EmcRfc = 0x00000114, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000007, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x0000010d, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x0000011e, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab198, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200418, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x006f000e, + .EmcMrsWaitCnt2 = 0x006f000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0080089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x007fc007, + .EmcDllXformDqs1 = 0x007fc008, + .EmcDllXformDqs2 = 0x007f400c, + .EmcDllXformDqs3 = 0x007fc007, + .EmcDllXformDqs4 = 0x007f4006, + .EmcDllXformDqs5 = 0x007f8004, + .EmcDllXformDqs6 = 0x007f8005, + .EmcDllXformDqs7 = 0x007f8004, + .EmcDllXformDqs8 = 0x007fc007, + .EmcDllXformDqs9 = 0x007fc008, + .EmcDllXformDqs10 = 0x007f400c, + .EmcDllXformDqs11 = 0x007fc007, + .EmcDllXformDqs12 = 0x007f4006, + .EmcDllXformDqs13 = 0x007f8004, + .EmcDllXformDqs14 = 0x007f8005, + .EmcDllXformDqs15 = 0x007f8004, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00034000, + .EmcDllXformAddr1 = 0x00034000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00034000, + .EmcDllXformAddr4 = 0x00034000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000006, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000009, + .EmcDliTrimTxDqs4 = 0x00000006, + .EmcDliTrimTxDqs5 = 0x00000007, + .EmcDliTrimTxDqs6 = 0x00000006, + .EmcDliTrimTxDqs7 = 0x00000006, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000009, + .EmcDliTrimTxDqs12 = 0x00000006, + .EmcDliTrimTxDqs13 = 0x00000007, + .EmcDliTrimTxDqs14 = 0x00000006, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x80000005, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00492492, + .EmcXm2DqsPadCtrl5 = 0x00492492, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000101, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x746c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-kingston-2GB-792.inc b/src/mainboard/google/nyan_big/bct/sdram-kingston-2GB-792.inc new file mode 100644 index 0000000000..5f1c1175f6 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-kingston-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Nike_2GB_Kin_792Mhz_ODTCTT_V06_0507.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000007, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab198, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200418, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f8000c, + .EmcMrsWaitCnt2 = 0x00f8000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0080089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000009, + .EmcDllXformDqs1 = 0x00000009, + .EmcDllXformDqs2 = 0x00000009, + .EmcDllXformDqs3 = 0x00000007, + .EmcDllXformDqs4 = 0x00000006, + .EmcDllXformDqs5 = 0x00000006, + .EmcDllXformDqs6 = 0x007fc009, + .EmcDllXformDqs7 = 0x00000006, + .EmcDllXformDqs8 = 0x00000009, + .EmcDllXformDqs9 = 0x00000009, + .EmcDllXformDqs10 = 0x00000009, + .EmcDllXformDqs11 = 0x00000007, + .EmcDllXformDqs12 = 0x00000006, + .EmcDllXformDqs13 = 0x00000007, + .EmcDllXformDqs14 = 0x00000009, + .EmcDllXformDqs15 = 0x00000007, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00034002, + .EmcDllXformAddr1 = 0x00034002, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00034002, + .EmcDllXformAddr4 = 0x00034002, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000009, + .EmcDliTrimTxDqs4 = 0x00000009, + .EmcDliTrimTxDqs5 = 0x00000007, + .EmcDliTrimTxDqs6 = 0x00000009, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000009, + .EmcDliTrimTxDqs12 = 0x00000009, + .EmcDliTrimTxDqs13 = 0x00000007, + .EmcDliTrimTxDqs14 = 0x00000009, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x80000005, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x004d34d3, + .EmcXm2DqsPadCtrl5 = 0x004d34d3, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000101, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_big/bct/sdram-unused.inc b/src/mainboard/google/nyan_big/bct/sdram-unused.inc new file mode 100644 index 0000000000..bef63dcecc --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/sdram-unused.inc @@ -0,0 +1,4 @@ +{ /* dummy. */ + .MemoryType = NvBootMemoryType_Unused, + 0, +}, diff --git a/src/mainboard/google/nyan_big/bct/spi.cfg b/src/mainboard/google/nyan_big/bct/spi.cfg new file mode 100644 index 0000000000..e9f85d52c6 --- /dev/null +++ b/src/mainboard/google/nyan_big/bct/spi.cfg @@ -0,0 +1,34 @@ +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 32768; +PageSize = 2048; +PartitionSize = 4194304; + +Bctcopy = 1; + +DevType[0] = NvBootDevType_Spi; +DeviceParam[0].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[0].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[0].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[0].SpiFlashParams.PageSize2kor16k = 0; + +DevType[1] = NvBootDevType_Spi; +DeviceParam[1].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[1].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[1].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[1].SpiFlashParams.PageSize2kor16k = 0; + +DevType[2] = NvBootDevType_Spi; +DeviceParam[2].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[2].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[2].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[2].SpiFlashParams.PageSize2kor16k = 0; + +DevType[3] = NvBootDevType_Spi; +DeviceParam[3].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[3].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[3].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[3].SpiFlashParams.PageSize2kor16k = 0; + diff --git a/src/mainboard/google/nyan_big/boardid.c b/src/mainboard/google/nyan_big/boardid.c new file mode 100644 index 0000000000..1905c79e16 --- /dev/null +++ b/src/mainboard/google/nyan_big/boardid.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + gpio_t gpio[] = {[3] = GPIO(X4), [2] = GPIO(X1), /* X4 is MSB */ + [1] = GPIO(T1), [0] = GPIO(Q3),}; /* Q3 is LSB */ + + if (id < 0) { + id = gpio_base3_value(gpio, ARRAY_SIZE(gpio)); + + printk(BIOS_SPEW, "Board TRISTATE ID: %d.\n", id); + } + + return id; +} diff --git a/src/mainboard/google/nyan_big/bootblock.c b/src/mainboard/google/nyan_big/bootblock.c new file mode 100644 index 0000000000..c471cb841a --- /dev/null +++ b/src/mainboard/google/nyan_big/bootblock.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME: move back to soc code? */ + +#include "pmic.h" + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta); + + clock_configure_source(mselect, PLLP, 102000); + + /* The PMIC is on I2C5 and can run at 400 KHz. */ + clock_configure_i2c_scl_freq(i2c5, PLLP, 400); + + /* TODO: We should be able to set this to 50MHz, but that did not seem + * reliable. */ + clock_configure_source(sbc4, PLLP, 33333); +} + +void bootblock_mainboard_init(void) +{ + set_clock_sources(); + + clock_enable_clear_reset(CLK_L_CACHE2 | CLK_L_TMR, + CLK_H_I2C5 | CLK_H_APBDMA, + 0, CLK_V_MSELECT, 0, 0); + + // Board ID GPIOs, bits 0-3. + gpio_input(GPIO(Q3)); + gpio_input(GPIO(T1)); + gpio_input(GPIO(X1)); + gpio_input(GPIO(X4)); + + // I2C5 (PMU) clock. + pinmux_set_config(PINMUX_PWR_I2C_SCL_INDEX, + PINMUX_PWR_I2C_SCL_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + // I2C5 (PMU) data. + pinmux_set_config(PINMUX_PWR_I2C_SDA_INDEX, + PINMUX_PWR_I2C_SDA_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + i2c_init(4); + pmic_init(4); + + /* SPI4 data out (MOSI) */ + pinmux_set_config(PINMUX_GPIO_PG6_INDEX, + PINMUX_GPIO_PG6_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 data in (MISO) */ + pinmux_set_config(PINMUX_GPIO_PG7_INDEX, + PINMUX_GPIO_PG7_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 clock */ + pinmux_set_config(PINMUX_GPIO_PG5_INDEX, + PINMUX_GPIO_PG5_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + /* SPI4 chip select 0 */ + pinmux_set_config(PINMUX_GPIO_PI3_INDEX, + PINMUX_GPIO_PI3_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + + tegra_spi_init(4); +} diff --git a/src/mainboard/google/nyan_big/chromeos.c b/src/mainboard/google/nyan_big/chromeos.c new file mode 100644 index 0000000000..e4fbfdac10 --- /dev/null +++ b/src/mainboard/google/nyan_big/chromeos.c @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO(R1); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO(R1)); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO(R4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: active low */ + gpios->gpios[count].port = GPIO(Q0); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: active high */ + gpios->gpios[count].port = GPIO(U4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: active low (output) */ + gpios->gpios[count].port = GPIO(I5); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO(R1)); +} diff --git a/src/mainboard/google/nyan_big/devicetree.cb b/src/mainboard/google/nyan_big/devicetree.cb new file mode 100644 index 0000000000..8919941360 --- /dev/null +++ b/src/mainboard/google/nyan_big/devicetree.cb @@ -0,0 +1,94 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/nvidia/tegra124 + device cpu_cluster 0 on end +# N.B. We ae not using the device tree in an effective way. +# We need to change this in future such that the on-soc +# devices are 'chips', which will allow us to go at them +# in parallel. This is even easier on the ARM SOCs since there +# are no single-access resources such as the infamous +# cf8/cfc registers found on PCs. + register "display_controller" = "TEGRA_ARM_DISPLAYA" + register "xres" = "1366" + register "yres" = "768" + + # bits per pixel and color depth + register "framebuffer_bits_per_pixel" = "16" + register "color_depth" = "6" + # "6" is defined as COLOR_DEPTH_B5G6R5 in dc_reg.h + + register "panel_bits_per_pixel" = "18" + + register "cache_policy" = "DCACHE_WRITETHROUGH" + + # With some help from the mainbaord designer + register "backlight_en_gpio" = "GPIO(H2)" + register "lvds_shutdown_gpio" = "0" + register "backlight_vdd_gpio" = "GPIO(P2)" + register "panel_vdd_gpio" = "0" + register "pwm" = "1" + + # various panel delay time + register "vdd_delay_ms" = "200" + register "pwm_to_bl_delay_ms" = "10" + register "vdd_to_hpd_delay_ms" = "200" + register "hpd_unplug_min_us" = "2000" + register "hpd_plug_min_us" = "250" + register "hpd_irq_min_us" = "250" + +# How to compute these: xrandr --verbose will give you this: +#Detailed mode: Clock 285.250 MHz, 272 mm x 181 mm +# 2560 2608 2640 2720 hborder 0 +# 1700 1703 1713 1749 vborder 0 +#Then you can compute your values: +#H front porch = 2608 - 2560 = 48 +#H sync = 2640 - 2608 = 32 +#H back porch = 2720 - 2640 = 80 +#V front porch = 1703 - 1700 = 3 +#V sync = 1713 - 1703 = 10 +#V back porch = 1749 - 1713 = 36 +#href_to_sync and vref_to_sync are from the vendor +#this is just an example for a Pixel panel; other panels differ. +# Here is a peppy panel: +# 1366x768 (0x45) 76.4MHz -HSync -VSync *current +preferred +# h: width 1366 start 1502 end 1532 total 1592 +# v: height 768 start 776 end 788 total 800 + register "href_to_sync" = "1" + register "hfront_porch" = "136" + register "hsync_width" = "30" + register "hback_porch" = "60" + + register "vref_to_sync" = "1" + register "vfront_porch" = "8" + register "vsync_width" = "12" + register "vback_porch" = "12" + + register "pixel_clock" = "76400000" + + # link configurations + register "lane_count" = "1" + register "enhanced_framing" = "1" + register "link_bw" = "10" + # "10" is defined as SOR_LINK_SPEED_G2_7 in sor.h + + register "drive_current" = "0x40404040" + register "preemphasis" = "0x0f0f0f0f" + register "postcursor" = "0" +end diff --git a/src/mainboard/google/nyan_big/early_configs.c b/src/mainboard/google/nyan_big/early_configs.c new file mode 100644 index 0000000000..de9fe8ef9d --- /dev/null +++ b/src/mainboard/google/nyan_big/early_configs.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void setup_pinmux(void) +{ + /* Write protect. */ + gpio_input_pullup(GPIO(R1)); + /* Recovery mode. */ + gpio_input_pullup(GPIO(Q7)); + /* Lid switch. */ + gpio_input_pullup(GPIO(R4)); + /* Power switch. */ + gpio_input_pullup(GPIO(Q0)); + /* Developer mode. */ + gpio_input_pullup(GPIO(Q6)); + /* EC in RW. */ + gpio_input_pullup(GPIO(U4)); + + /* route PU4/5 to GMI to remove conflict w/PWM1/2. */ + pinmux_set_config(PINMUX_GPIO_PU4_INDEX, + PINMUX_GPIO_PU4_FUNC_NOR); /* s/b GMI */ + pinmux_set_config(PINMUX_GPIO_PU5_INDEX, + PINMUX_GPIO_PU5_FUNC_NOR); /* s/b GMI */ + + /* SOC and TPM reset GPIO, active low. */ + gpio_output(GPIO(I5), 1); + + /* SPI1 MOSI */ + pinmux_set_config(PINMUX_ULPI_CLK_INDEX, PINMUX_ULPI_CLK_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 MISO */ + pinmux_set_config(PINMUX_ULPI_DIR_INDEX, PINMUX_ULPI_DIR_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 SCLK */ + pinmux_set_config(PINMUX_ULPI_NXT_INDEX, PINMUX_ULPI_NXT_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 CS0 */ + pinmux_set_config(PINMUX_ULPI_STP_INDEX, PINMUX_ULPI_STP_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + + /* I2C3 (cam) clock. */ + pinmux_set_config(PINMUX_CAM_I2C_SCL_INDEX, + PINMUX_CAM_I2C_SCL_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + /* I2C3 (cam) data. */ + pinmux_set_config(PINMUX_CAM_I2C_SDA_INDEX, + PINMUX_CAM_I2C_SDA_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + + /* switch unused pin to GPIO */ + gpio_set_mode(GPIO(X3), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X4), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X5), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X6), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X7), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(W3), GPIO_MODE_GPIO); +} + +static void configure_ec_spi_bus(void) +{ + clock_configure_source(sbc1, CLK_M, 3000); +} + +static void configure_tpm_i2c_bus(void) +{ + clock_configure_i2c_scl_freq(i2c3, PLLP, 400); + + i2c_init(2); +} + +void early_mainboard_init(void) +{ + clock_enable_clear_reset(0, CLK_H_SBC1, CLK_U_I2C3, 0, 0, 0); + setup_pinmux(); + configure_ec_spi_bus(); + configure_tpm_i2c_bus(); +} diff --git a/src/mainboard/google/nyan_big/mainboard.c b/src/mainboard/google/nyan_big/mainboard.c new file mode 100644 index 0000000000..5e12c91975 --- /dev/null +++ b/src/mainboard/google/nyan_big/mainboard.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* + * The max98090 codec and the temperature sensor are on I2C1. These + * can both run at 400 KHz, but the kernel sets the bus to 100 KHz. + */ + clock_configure_i2c_scl_freq(i2c1, PLLP, 100); + + /* + * MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's + * maximum speed (48MHz) so we can change SDCLK by second stage divisor + * in payloads, without touching base clock. + */ + clock_configure_source(sdmmc3, PLLP, 48000); + clock_configure_source(sdmmc4, PLLP, 48000); + + /* External peripheral 1: audio codec (max98090) using 12MHz CLK1. + * Note the source id of CLK_M for EXTPERIPH1 is 3. */ + clock_configure_irregular_source(extperiph1, CLK_M, 12000, 3); + + /* + * We need 1.5MHz. So, we use CLK_M. CLK_DIVIDER macro returns a divisor + * (0xe) a little bit off from the ideal value (0xd) but it's good + * enough for beeps. The source id of CLK_M for I2S is 6. + */ + clock_configure_irregular_source(i2s1, CLK_M, 1500, 6); + + /* Note source id of PLLP for HOST1x is 4. */ + clock_configure_irregular_source(host1x, PLLP, 408000, 4); + + /* Use PLLD_OUT0 as clock source for disp1 */ + clrsetbits_le32(&clk_rst->clk_src_disp1, + CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + 2 /*PLLD_OUT0 */ << CLK_SOURCE_SHIFT); + +} + +static void setup_pinmux(void) +{ + // I2C1 clock. + pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX, + PINMUX_GEN1_I2C_SCL_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C1 data. + pinmux_set_config(PINMUX_GEN1_I2C_SDA_INDEX, + PINMUX_GEN1_I2C_SDA_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C2 clock. + pinmux_set_config(PINMUX_GEN2_I2C_SCL_INDEX, + PINMUX_GEN2_I2C_SCL_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C2 data. + pinmux_set_config(PINMUX_GEN2_I2C_SDA_INDEX, + PINMUX_GEN2_I2C_SDA_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C4 (DDC) clock. + pinmux_set_config(PINMUX_DDC_SCL_INDEX, + PINMUX_DDC_SCL_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + // I2C4 (DDC) data. + pinmux_set_config(PINMUX_DDC_SDA_INDEX, + PINMUX_DDC_SDA_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + + // TODO(hungte) Revice pinmux setup, make nice little SoC functions for + // every single logical thing instead of dumping a wall of code below. + uint32_t pin_up = PINMUX_PULL_UP | PINMUX_INPUT_ENABLE, + pin_down = PINMUX_PULL_DOWN | PINMUX_INPUT_ENABLE, + pin_none = PINMUX_PULL_NONE | PINMUX_INPUT_ENABLE; + + // MMC3 (sdcard reader) + pinmux_set_config(PINMUX_SDMMC3_CLK_INDEX, + PINMUX_SDMMC3_CLK_FUNC_SDMMC3 | pin_none); + pinmux_set_config(PINMUX_SDMMC3_CMD_INDEX, + PINMUX_SDMMC3_CMD_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT0_INDEX, + PINMUX_SDMMC3_DAT0_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT1_INDEX, + PINMUX_SDMMC3_DAT1_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT2_INDEX, + PINMUX_SDMMC3_DAT2_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT3_INDEX, + PINMUX_SDMMC3_DAT3_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_IN_INDEX, + PINMUX_SDMMC3_CLK_LB_IN_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_OUT_INDEX, + PINMUX_SDMMC3_CLK_LB_OUT_FUNC_SDMMC3 | pin_down); + + // MMC3 Card Detect pin. + gpio_input_pullup(GPIO(V2)); + // Disable SD card reader power so it can be reset even on warm boot. + // Payloads must enable power before accessing SD card slots. + gpio_output(GPIO(R0), 0); + + // MMC4 (eMMC) + pinmux_set_config(PINMUX_SDMMC4_CLK_INDEX, + PINMUX_SDMMC4_CLK_FUNC_SDMMC4 | pin_none); + pinmux_set_config(PINMUX_SDMMC4_CMD_INDEX, + PINMUX_SDMMC4_CMD_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT0_INDEX, + PINMUX_SDMMC4_DAT0_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT1_INDEX, + PINMUX_SDMMC4_DAT1_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT2_INDEX, + PINMUX_SDMMC4_DAT2_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT3_INDEX, + PINMUX_SDMMC4_DAT3_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT4_INDEX, + PINMUX_SDMMC4_DAT4_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT5_INDEX, + PINMUX_SDMMC4_DAT5_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT6_INDEX, + PINMUX_SDMMC4_DAT6_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT7_INDEX, + PINMUX_SDMMC4_DAT7_FUNC_SDMMC4 | pin_up); + + /* We pull the USB VBUS signals up but keep them as inputs since the + * voltage source likes to drive them low on overcurrent conditions */ + gpio_input_pullup(GPIO(N4)); /* USB VBUS EN0 */ + gpio_input_pullup(GPIO(N5)); /* USB VBUS EN1 */ + + /* Clock output 1 (for external peripheral) */ + pinmux_set_config(PINMUX_DAP_MCLK1_INDEX, + PINMUX_DAP_MCLK1_FUNC_EXTPERIPH1 | PINMUX_PULL_NONE); + + /* I2S1 */ + pinmux_set_config(PINMUX_DAP2_DIN_INDEX, + PINMUX_DAP2_DIN_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_DOUT_INDEX, + PINMUX_DAP2_DOUT_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_FS_INDEX, + PINMUX_DAP2_FS_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_SCLK_INDEX, + PINMUX_DAP2_SCLK_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + + /* PWM1 */ + pinmux_set_config(PINMUX_GPIO_PH1_INDEX, + PINMUX_GPIO_PH1_FUNC_PWM1 | PINMUX_PULL_NONE); + + /* DP HPD */ + pinmux_set_config(PINMUX_DP_HPD_INDEX, + PINMUX_DP_HPD_FUNC_DP | PINMUX_INPUT_ENABLE); +} + +static void setup_kernel_info(void) +{ + // Setup required information for Linux kernel. + + // pmc.odmdata: [18:19]: console type, [15:17]: UART id. + // TODO(hungte) This should be done by filling BCT values, or derived + // from CONFIG_CONSOLE_SERIAL_UART[A-E]. Right now we simply copy the + // value defined in BCT. + struct tegra_pmc_regs *pmc = (void*)TEGRA_PMC_BASE; + writel(0x80080000, &pmc->odmdata); + + // Not strictly info, but kernel graphics driver needs this region locked down + struct tegra_mc_regs *mc = (void *)TEGRA_MC_BASE; + writel(0, &mc->video_protect_bom); + writel(0, &mc->video_protect_size_mb); + writel(1, &mc->video_protect_reg_ctrl); +} + +static void setup_ec_spi(void) +{ + struct tegra_spi_channel *spi; + + spi = tegra_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS); +} + +static void mainboard_init(device_t dev) +{ + set_clock_sources(); + + clock_external_output(1); /* For external MAX98090 audio codec. */ + + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * conntected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (In our + * case, I2S/APBIF/AUDIO) will hang. + */ + clock_enable_clear_reset(CLK_L_GPIO | CLK_L_I2C1 | CLK_L_SDMMC4 | + CLK_L_I2S0 | CLK_L_I2S1 | CLK_L_I2S2 | + CLK_L_SPDIF | CLK_L_USBD | CLK_L_DISP1 | + CLK_L_HOST1X | CLK_L_PWM, + + CLK_H_EMC | CLK_H_I2C2 | CLK_H_PMC | + CLK_H_MEM | CLK_H_USB3, + + CLK_U_CSITE | CLK_U_SDMMC3, + + CLK_V_I2C4 | CLK_V_EXTPERIPH1 | CLK_V_APBIF | + CLK_V_AUDIO | CLK_V_I2S3 | CLK_V_I2S4 | + CLK_V_DAM0 | CLK_V_DAM1 | CLK_V_DAM2, + + CLK_W_DVFS | CLK_W_AMX0 | CLK_W_ADX0, + + CLK_X_DPAUX | CLK_X_SOR0 | CLK_X_AMX1 | + CLK_X_ADX1 | CLK_X_AFC0 | CLK_X_AFC1 | + CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | + CLK_X_AFC5); + + usb_setup_utmip((void*)TEGRA_USBD_BASE); + /* USB2 is the camera, we don't need it in firmware */ + usb_setup_utmip((void*)TEGRA_USB3_BASE); + + setup_pinmux(); + + i2c_init(0); + i2c_init(1); + i2c_init(3); + + setup_kernel_info(); + clock_init_arm_generic_timer(); + setup_ec_spi(); + elog_init(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "nyan_big", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} diff --git a/src/mainboard/google/nyan_big/memlayout.ld b/src/mainboard/google/nyan_big/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/nyan_big/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/nyan_big/pmic.c b/src/mainboard/google/nyan_big/pmic.c new file mode 100644 index 0000000000..16f043c024 --- /dev/null +++ b/src/mainboard/google/nyan_big/pmic.c @@ -0,0 +1,114 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pmic.h" + +enum { + AS3722_I2C_ADDR = 0x40 +}; + +struct as3722_init_reg { + u8 reg; + u8 val; + u8 delay; +}; + +static struct as3722_init_reg init_list[] = { + {AS3722_SDO0, 0x3C, 1}, + {AS3722_SDO1, 0x32, 0}, + {AS3722_LDO3, 0x59, 0}, + {AS3722_SDO2, 0x3C, 0}, + {AS3722_SDO3, 0x00, 0}, + {AS3722_SDO4, 0x00, 0}, + {AS3722_SDO5, 0x50, 0}, + {AS3722_SDO6, 0x28, 1}, + {AS3722_LDO0, 0x8A, 0}, + {AS3722_LDO1, 0x00, 0}, + {AS3722_LDO2, 0x10, 0}, + {AS3722_LDO4, 0x00, 0}, + {AS3722_LDO5, 0x00, 0}, + {AS3722_LDO6, 0x00, 0}, + {AS3722_LDO7, 0x00, 0}, + {AS3722_LDO9, 0x00, 0}, + {AS3722_LDO10, 0x00, 0}, + {AS3722_LDO11, 0x00, 1}, +}; + +static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) +{ + if (i2c_writeb(bus, AS3722_I2C_ADDR, reg, val)) { + printk(BIOS_ERR, "%s: reg = 0x%02X, value = 0x%02X failed!\n", + __func__, reg, val); + /* Reset the SoC on any PMIC write error */ + hard_reset(); + } else { + if (delay) + udelay(500); + } +} + +static void pmic_slam_defaults(unsigned bus) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + struct as3722_init_reg *reg = &init_list[i]; + pmic_write_reg(bus, reg->reg, reg->val, reg->delay); + } +} + +void pmic_init(unsigned bus) +{ + /* + * Don't need to set up VDD_CORE - already done - by OTP + * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled. + * Don't write LDCONTROL - it's already 0xFF, i.e. all LDOs enabled. + */ + + /* Restore PMIC POR defaults, in case kernel changed 'em */ + pmic_slam_defaults(bus); + + /* First set VDD_CPU to 1.2V, then enable the VDD_CPU regulator. */ + pmic_write_reg(bus, 0x00, 0x50, 1); + + /* First set VDD_GPU to 1.0V, then enable the VDD_GPU regulator. */ + pmic_write_reg(bus, 0x06, 0x28, 1); + + /* + * First set +1.2V_GEN_AVDD to 1.2V, then enable the +1.2V_GEN_AVDD + * regulator. + */ + pmic_write_reg(bus, 0x12, 0x10, 1); + + /* + * Panel power GPIO O4. Set mode for GPIO4 (0x0c to 7), then set + * the value (register 0x20 bit 4) + */ + pmic_write_reg(bus, 0x0c, 0x07, 0); + pmic_write_reg(bus, 0x20, 0x10, 1); +} diff --git a/src/mainboard/google/nyan_big/pmic.h b/src/mainboard/google/nyan_big/pmic.h new file mode 100644 index 0000000000..a64159908c --- /dev/null +++ b/src/mainboard/google/nyan_big/pmic.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_BIG_PMIC_H__ +#define __MAINBOARD_GOOGLE_NYAN_BIG_PMIC_H__ + +enum { + AS3722_SDO0 = 0, + AS3722_SDO1, + AS3722_SDO2, + AS3722_SDO3, + AS3722_SDO4, + AS3722_SDO5, + AS3722_SDO6, + + AS3722_LDO0 = 0x10, + AS3722_LDO1, + AS3722_LDO2, + AS3722_LDO3, + AS3722_LDO4, + AS3722_LDO5, + AS3722_LDO6, + AS3722_LDO7, + + AS3722_LDO9 = 0x19, + AS3722_LDO10, + AS3722_LDO11, +}; + +void pmic_init(unsigned bus); + +#endif /* __MAINBOARD_GOOGLE_NYAN_BIG_PMIC_H__ */ diff --git a/src/mainboard/google/nyan_big/reset.c b/src/mainboard/google/nyan_big/reset.c new file mode 100644 index 0000000000..e58890e604 --- /dev/null +++ b/src/mainboard/google/nyan_big/reset.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void hard_reset(void) +{ + gpio_output(GPIO(I5), 0); + while(1); +} diff --git a/src/mainboard/google/nyan_big/romstage.c b/src/mainboard/google/nyan_big/romstage.c new file mode 100644 index 0000000000..a65d7f6ce4 --- /dev/null +++ b/src/mainboard/google/nyan_big/romstage.c @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdram_configs.h" + +static void __attribute__((noinline)) romstage(void) +{ + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + exception_init(); + + sdram_init(get_sdram_config()); + + /* used for MMU and CBMEM setup, in MB */ + u32 dram_start_mb = (uintptr_t)_dram/MiB; + u32 dram_end_mb = sdram_max_addressable_mb(); + u32 dram_size_mb = dram_end_mb - dram_start_mb; + + configure_l2_cache(); + mmu_init(); + /* Device memory below DRAM is uncached. */ + mmu_config_range(0, dram_start_mb, DCACHE_OFF); + /* SRAM is cached. MMU code will round size up to page size. */ + mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB), + DCACHE_WRITEBACK); + /* DRAM is cached. */ + mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK); + /* A window for DMA is uncached. */ + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + /* The space above DRAM is uncached. */ + if (dram_end_mb < 4096) + mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF); + mmu_disable_range(0, 1); + dcache_mmu_enable(); + + /* + * A watchdog reset only resets part of the system so it ends up in + * a funny state. If that happens, we need to reset the whole machine. + */ + if (power_reset_status() == POWER_RESET_WATCHDOG) { + printk(BIOS_INFO, "Watchdog reset detected, rebooting.\n"); + hard_reset(); + } + + cbmem_initialize_empty(); + + early_mainboard_init(); + + vboot_verify_firmware(romstage_handoff_find_or_add()); + + timestamp_add_now(TS_START_COPYRAM); + void *entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + "fallback/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + + stage_exit(entry); +} + +/* Stub to force arm_init_caches to the top, before any stack/memory accesses */ +void main(void) +{ + asm volatile ("bl arm_init_caches" + ::: "r0","r1","r2","r3","r4","r5","ip"); + romstage(); +} diff --git a/src/mainboard/google/nyan_big/sdram_configs.c b/src/mainboard/google/nyan_big/sdram_configs.c new file mode 100644 index 0000000000..7904b4e94b --- /dev/null +++ b/src/mainboard/google/nyan_big/sdram_configs.c @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "sdram_configs.h" + +static struct sdram_params sdram_configs[] = { +#include "bct/sdram-unused.inc" /* ram_code = 0000 */ +#include "bct/sdram-hynix-2GB-792.inc" /* ram_code = 0001 */ +#include "bct/sdram-unused.inc" /* ram_code = 0010 */ +#include "bct/sdram-unused.inc" /* ram_code = 0011 */ +#include "bct/sdram-hynix-4GB-792.inc" /* ram_code = 0100 */ +#include "bct/sdram-unused.inc" /* ram_code = 0101 */ +#include "bct/sdram-kingston-2GB-792.inc" /* ram_code = 0110 */ +#include "bct/sdram-unused.inc" /* ram_code = 0111 */ +#include "bct/sdram-unused.inc" /* ram_code = 1000 */ +#include "bct/sdram-unused.inc" /* ram_code = 1001 */ +#include "bct/sdram-unused.inc" /* ram_code = 1010 */ +#include "bct/sdram-unused.inc" /* ram_code = 1011 */ +#include "bct/sdram-unused.inc" /* ram_code = 1100 */ +#include "bct/sdram-unused.inc" /* ram_code = 1101 */ +#include "bct/sdram-unused.inc" /* ram_code = 1110 */ +#include "bct/sdram-unused.inc" /* ram_code = 1111 */ +}; + +const struct sdram_params *get_sdram_config() +{ + uint32_t ramcode = sdram_get_ram_code(); + /* + * If we need to apply some special hacks to RAMCODE mapping (ex, by + * board_id), do that now. + */ + + printk(BIOS_SPEW, "%s: RAMCODE=%d\n", __func__, ramcode); + if (ramcode >= sizeof(sdram_configs) / sizeof(sdram_configs[0]) || + sdram_configs[ramcode].MemoryType == NvBootMemoryType_Unused) { + die("Invalid RAMCODE."); + } + + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/nyan_big/sdram_configs.h b/src/mainboard/google/nyan_big/sdram_configs.h new file mode 100644 index 0000000000..6c3bda097a --- /dev/null +++ b/src/mainboard/google/nyan_big/sdram_configs.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_BIG_SDRAM_CONFIG_H__ +#define __MAINBOARD_GOOGLE_NYAN_BIG_SDRAM_CONFIG_H__ + +#include + +/* Loads SDRAM configurations for current system. */ +const struct sdram_params *get_sdram_config(void); + +#endif /* __MAINBOARD_GOOGLE_NYAN_BIG_SDRAM_CONFIG_H__ */ diff --git a/src/mainboard/google/nyan_blaze/Kconfig b/src/mainboard/google/nyan_blaze/Kconfig new file mode 100644 index 0000000000..5b744977b7 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/Kconfig @@ -0,0 +1,102 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_NYAN_BLAZE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select SOC_NVIDIA_TEGRA124 + select TEGRA124_MODEL_CD570M + select MAINBOARD_HAS_BOOTBLOCK_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + select SPI_FLASH + select SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/nyan_blaze + +config MAINBOARD_PART_NUMBER + string + default "Nyan Blaze" + +choice + prompt "BCT boot media" + default NYAN_BLAZE_BCT_CFG_SPI + help + Which boot media to configure the BCT for. + +config NYAN_BLAZE_BCT_CFG_SPI + bool "SPI" + help + Configure the BCT for booting from SPI. + +config NYAN_BLAZE_BCT_CFG_EMMC + bool "eMMC" + help + Configure the BCT for booting from eMMC. + +endchoice + +config BOOT_MEDIA_SPI_BUS + int "SPI bus with boot media ROM" + range 1 6 + depends on NYAN_BLAZE_BCT_CFG_SPI + default 4 + help + Which SPI bus the boot media is connected to. + +config BOOT_MEDIA_SPI_CHIP_SELECT + int "Chip select for SPI boot media" + range 0 3 + depends on NYAN_BLAZE_BCT_CFG_SPI + default 0 + help + Which chip select to use for boot media. + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 1 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 if VBOOT2_VERIFY_FIRMWARE + default 0x2 + +config FLASHMAP_OFFSET + hex + default 0x00100000 + +config DRIVER_TPM_I2C_BUS + hex + default 0x2 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +endif # BOARD_GOOGLE_NYAN_BLAZE diff --git a/src/mainboard/google/nyan_blaze/Makefile.inc b/src/mainboard/google/nyan_blaze/Makefile.inc new file mode 100644 index 0000000000..53f974daba --- /dev/null +++ b/src/mainboard/google/nyan_blaze/Makefile.inc @@ -0,0 +1,50 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# Add a handler for BCT config files +$(call add-special-class,bct-cfg) +bct-cfg-handler= $(eval $(obj)/generated/bct.cfg: $(1)$(2)) + +$(obj)/generated/bct.cfg: + @printf " CAT $(subst $(obj)/,,$(@))\n" + cat $^ > $@ + +subdirs-y += bct + +bootblock-y += bootblock.c +bootblock-y += pmic.c +bootblock-y += reset.c + +verstage-y += early_configs.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += early_configs.c +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += sdram_configs.c + +ramstage-y += reset.c +ramstage-y += boardid.c +ramstage-y += mainboard.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/nyan_blaze/bct/Makefile.inc b/src/mainboard/google/nyan_blaze/bct/Makefile.inc new file mode 100644 index 0000000000..343d7e894c --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/Makefile.inc @@ -0,0 +1,27 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bct-cfg-$(CONFIG_NYAN_BLAZE_BCT_CFG_EMMC) += emmc.cfg +bct-cfg-$(CONFIG_NYAN_BLAZE_BCT_CFG_SPI) += spi.cfg +bct-cfg-y += odmdata.cfg +bct-cfg-y += jtag.cfg + +# Note when SDRAM config (sdram-*.cfg) files are changed, we have to regenerate +# the include files (sdram-*.inc). See ../../nyan/bct/Makefile.inc for more +# information. diff --git a/src/mainboard/google/nyan_blaze/bct/emmc.cfg b/src/mainboard/google/nyan_blaze/bct/emmc.cfg new file mode 100644 index 0000000000..c93cf4685b --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/emmc.cfg @@ -0,0 +1,13 @@ +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 0x00004000; +PageSize = 0x00000200; +PartitionSize = 0x01000000; + +DevType[0] = NvBootDevType_Sdmmc; +DeviceParam[0].SdmmcParams.ClockDivider = 0x00000009; +DeviceParam[0].SdmmcParams.DataWidth = NvBootSdmmcDataWidth_8Bit; +DeviceParam[0].SdmmcParams.MaxPowerClassSupported = 0x00000000; +DeviceParam[0].SdmmcParams.MultiPageSupport = 0x00000000; diff --git a/src/mainboard/google/nyan_blaze/bct/jtag.cfg b/src/mainboard/google/nyan_blaze/bct/jtag.cfg new file mode 100644 index 0000000000..f43e143377 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/jtag.cfg @@ -0,0 +1,16 @@ +# +# Set JtagCtrl to 1 to reenable Jtag +# +JtagCtrl = 0; +# +# Fill in chip unique id +# +# ChipUid can be found by running tegrarcm in tegra recovery mode +# (also hooking up A-A USB cable) and looking for console output +# on line starting with "Chip UID:" +# +# Command example: +# $ sudo tegrarcm --bct=/build/nyan/firmware/bct/board.bct --bootloader=/build/nyan/firmware/u-boot.bin --loadaddr=0x80108000 +# Where board.bct and u-boot.bin do not have to be prebuilt. +# +ChipUid = 0x00000000000000000000000000000000; diff --git a/src/mainboard/google/nyan_blaze/bct/odmdata.cfg b/src/mainboard/google/nyan_blaze/bct/odmdata.cfg new file mode 100644 index 0000000000..d0ab2bf8fb --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/odmdata.cfg @@ -0,0 +1 @@ +OdmData = 0x80080000; diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-204.inc b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-204.inc new file mode 100644 index 0000000000..d75e0b5272 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-204-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000035, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000003, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000032, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x00000038, + .EmcTxsrDll = 0x00000038, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80001221, + .EmcEmrs = 0x80100003, + .EmcEmrs2 = 0x80200008, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x00004000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00004000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00094000, + .EmcDllXformDq3 = 0x00094000, + .EmcDllXformDq4 = 0x00009400, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80001221, + .EmcWarmBootMrsExtra = 0x80100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0405, + .McEmemArbMisc0 = 0x73840a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-792.inc new file mode 100644 index 0000000000..3d79a5efd3 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Hynix_2GB_H5TC4G63AFR_PBA_792MHz_0703_PVT_Modify.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200018, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f8000c, + .EmcMrsWaitCnt2 = 0x00f8000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x0000000a, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000a, + .EmcDliTrimTxDqs7 = 0x0000000a, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x0000000a, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000a, + .EmcDliTrimTxDqs15 = 0x0000000a, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00492492, + .EmcXm2DqsPadCtrl5 = 0x00492492, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-924.inc b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-924.inc new file mode 100644 index 0000000000..e4d4faf24a --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-2GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-924-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430404, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000002b, + .EmcRfc = 0x000000ef, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001e, + .EmcRp = 0x0000000b, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000f, + .EmcR2p = 0x00000005, + .EmcW2p = 0x00000016, + .EmcRdRcd = 0x0000000b, + .EmcWrRcd = 0x0000000b, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000c, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000e, + .EmcPutermExtra = 0x000a0000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000015, + .EmcRdv = 0x0000001b, + .EmcRdvMask = 0x0000001d, + .EmcQpop = 0x00000010, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x00001be9, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000006fa, + .EmcPdEx2Wr = 0x00000004, + .EmcPdEx2Rd = 0x00000015, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000e6, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x000000fa, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000006, + .EmcTckesr = 0x00000007, + .EmcTpd = 0x00000006, + .EmcTfaw = 0x00000022, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x0000000a, + .EmcTClkStop = 0x0000000a, + .EmcTRefBw = 0x00001c29, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000002, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000f15, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200020, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00ce000e, + .EmcMrsWaitCnt2 = 0x00ce000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x000008a5, + .EmcCfgPipe = 0x00000000, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800037ed, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00401b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000005, + .EmcDllXformDqs1 = 0x00000005, + .EmcDllXformDqs2 = 0x00000005, + .EmcDllXformDqs3 = 0x00000005, + .EmcDllXformDqs4 = 0x00000005, + .EmcDllXformDqs5 = 0x00000005, + .EmcDllXformDqs6 = 0x00000005, + .EmcDllXformDqs7 = 0x00000005, + .EmcDllXformDqs8 = 0x00000005, + .EmcDllXformDqs9 = 0x00000005, + .EmcDllXformDqs10 = 0x00000005, + .EmcDllXformDqs11 = 0x00000005, + .EmcDllXformDqs12 = 0x00000005, + .EmcDllXformDqs13 = 0x00000005, + .EmcDllXformDqs14 = 0x00000005, + .EmcDllXformDqs15 = 0x00000005, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0000400e, + .EmcDllXformAddr1 = 0x0000400e, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0000400e, + .EmcDllXformAddr4 = 0x0000400e, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00000006, + .EmcDllXformDq1 = 0x00000006, + .EmcDllXformDq2 = 0x00000006, + .EmcDllXformDq3 = 0x00000006, + .EmcDllXformDq4 = 0x00000006, + .EmcDllXformDq5 = 0x00000006, + .EmcDllXformDq6 = 0x00000006, + .EmcDllXformDq7 = 0x00000006, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x0000004c, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000f15, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0020013d, + .EmcXm2DqsPadCtrl3 = 0x55555520, + .EmcXm2DqsPadCtrl4 = 0x003cf3cf, + .EmcXm2DqsPadCtrl5 = 0x003cf3cf, + .EmcXm2DqsPadCtrl6 = 0x55555500, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000005, + .McEmemArbTimingRp = 0x00000006, + .McEmemArbTimingRc = 0x00000016, + .McEmemArbTimingRas = 0x0000000e, + .McEmemArbTimingFaw = 0x00000011, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09060202, + .McEmemArbDaCovers = 0x001a1016, + .McEmemArbMisc0 = 0x734e2a17, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-204.inc b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-204.inc new file mode 100644 index 0000000000..2feede7239 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0100-204-4GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000047, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000003, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000044, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x0000004a, + .EmcTxsrDll = 0x0000004a, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00001221, + .EmcEmrs = 0x00100003, + .EmcEmrs2 = 0x00200008, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x00004000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00004000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00094000, + .EmcDllXformDq3 = 0x00094000, + .EmcDllXformDq4 = 0x00009400, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00001221, + .EmcWarmBootMrsExtra = 0x00100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000303, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0405, + .McEmemArbMisc0 = 0x74a40a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-792.inc new file mode 100644 index 0000000000..057d93b4fc --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-hynix-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Hynix_4GB_H5TC8G63AFR_PBA_792MHz_0714.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430808, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000024, + .EmcRfc = 0x00000114, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x0000010d, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x0000011e, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200018, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x006f000e, + .EmcMrsWaitCnt2 = 0x006f000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00008004, + .EmcDllXformDqs5 = 0x00004006, + .EmcDllXformDqs6 = 0x00000006, + .EmcDllXformDqs7 = 0x00008004, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00008004, + .EmcDllXformDqs13 = 0x00004006, + .EmcDllXformDqs14 = 0x00000006, + .EmcDllXformDqs15 = 0x00008004, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x0000000a, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000a, + .EmcDliTrimTxDqs7 = 0x0000000a, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x0000000a, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000a, + .EmcDliTrimTxDqs15 = 0x0000000a, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x69A69A20, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514510, + .EmcXm2DqsPadCtrl6 = 0x69865A00, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x746c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-micron-2GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-micron-2GB-792.inc new file mode 100644 index 0000000000..c24242ef0c --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-micron-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Micron_2GB_MT41K256M16HA_792MHz_0623.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200018, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f8000c, + .EmcMrsWaitCnt2 = 0x00f8000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x0000000a, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000a, + .EmcDliTrimTxDqs7 = 0x0000000a, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x0000000a, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000a, + .EmcDliTrimTxDqs15 = 0x0000000a, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-micron-4GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-micron-4GB-792.inc new file mode 100644 index 0000000000..e8726534c8 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-micron-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Micron_4GB_MT41K512M16TNA-125_792MHz_0707.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xA1430404, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200018, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00b6000c, + .EmcMrsWaitCnt2 = 0x00b6000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00004008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x0000000a, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000a, + .EmcDliTrimTxDqs7 = 0x0000000a, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x0000000a, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000a, + .EmcDliTrimTxDqs15 = 0x0000000a, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x007F800E, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0007F80E, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00555555, + .EmcXm2DqsPadCtrl5 = 0x00555555, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-204.inc b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-204.inc new file mode 100644 index 0000000000..e3eff15e27 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from mainboard/google/nyan_blaze/bct/Baileys_Samsung_2GB_K4B4G1646Q_HYK0_204MHz_0414.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000035, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000005, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000032, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x00000038, + .EmcTxsrDll = 0x00000038, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80001221, + .EmcEmrs = 0x80100003, + .EmcEmrs2 = 0x80200008, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x0000c000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x0000c000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00090000, + .EmcDllXformDq3 = 0x00090000, + .EmcDllXformDq4 = 0x00009000, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80001221, + .EmcWarmBootMrsExtra = 0x80100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000505, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0505, + .McEmemArbMisc0 = 0x73840a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-792.inc new file mode 100644 index 0000000000..9d180cc9f1 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Samsung_2GB_K4B4G1646Q_HYK0_792MHz_0623_merged.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cc, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c6, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d6, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200018, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f8000c, + .EmcMrsWaitCnt2 = 0x00f8000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000006, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000006, + .EmcDllXformDqs3 = 0x00000006, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000005, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x0000000a, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000a, + .EmcDliTrimTxDqs7 = 0x0000000a, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000005, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x0000000a, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000a, + .EmcDliTrimTxDqs15 = 0x0000000a, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x71C71C20, + .EmcXm2DqsPadCtrl4 = 0x00596596, + .EmcXm2DqsPadCtrl5 = 0x00596596, + .EmcXm2DqsPadCtrl6 = 0x71C71C00, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x734c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-204.inc b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-204.inc new file mode 100644 index 0000000000..e00542704e --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-204.inc @@ -0,0 +1,311 @@ +{ /* generated from mainboard/google/nyan_blaze/bct/Baileys_Samsung_4GB_K4B8G1646Q_204MHz_0413.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000022, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x40000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000009, + .EmcRfc = 0x00000047, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000007, + .EmcRp = 0x00000002, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x0000000a, + .EmcR2p = 0x00000005, + .EmcW2p = 0x0000000b, + .EmcRdRcd = 0x00000002, + .EmcWrRcd = 0x00000002, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000003, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000005, + .EmcWdvMask = 0x00000005, + .EmcQUse = 0x00000006, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000004, + .EmcEInputDuration = 0x00000006, + .EmcPutermExtra = 0x00010000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000003, + .EmcQSafe = 0x0000000d, + .EmcRdv = 0x0000000f, + .EmcRdvMask = 0x00000011, + .EmcQpop = 0x0000000a, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x00000607, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000181, + .EmcPdEx2Wr = 0x00000002, + .EmcPdEx2Rd = 0x00000002, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000044, + .EmcRw2Pden = 0x0000000f, + .EmcTxsr = 0x0000004a, + .EmcTxsrDll = 0x0000004a, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000007, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000638, + .EmcFbioCfg5 = 0x106aa298, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00001221, + .EmcEmrs = 0x00100003, + .EmcEmrs2 = 0x00200008, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x000c000c, + .EmcMrsWaitCnt2 = 0x000c000c, + .EmcCfg = 0x73240000, + .EmcCfg2 = 0x0000088d, + .EmcCfgPipe = 0x0000d2b3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80000d22, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040008, + .EmcDllXformDqs0 = 0x00064000, + .EmcDllXformDqs1 = 0x00064000, + .EmcDllXformDqs2 = 0x00064000, + .EmcDllXformDqs3 = 0x00064000, + .EmcDllXformDqs4 = 0x00064000, + .EmcDllXformDqs5 = 0x00064000, + .EmcDllXformDqs6 = 0x00064000, + .EmcDllXformDqs7 = 0x00064000, + .EmcDllXformDqs8 = 0x00064000, + .EmcDllXformDqs9 = 0x00064000, + .EmcDllXformDqs10 = 0x00064000, + .EmcDllXformDqs11 = 0x00064000, + .EmcDllXformDqs12 = 0x00064000, + .EmcDllXformDqs13 = 0x00064000, + .EmcDllXformDqs14 = 0x00064000, + .EmcDllXformDqs15 = 0x00064000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00000000, + .EmcDllXformAddr1 = 0x00000000, + .EmcDllXformAddr2 = 0x0000c000, + .EmcDllXformAddr3 = 0x00000000, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x0000c000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00090000, + .EmcDllXformDq1 = 0x00090000, + .EmcDllXformDq2 = 0x00090000, + .EmcDllXformDq3 = 0x00090000, + .EmcDllXformDq4 = 0x00009000, + .EmcDllXformDq5 = 0x00009000, + .EmcDllXformDq6 = 0x00009000, + .EmcDllXformDq7 = 0x00009000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000003, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00001221, + .EmcWarmBootMrsExtra = 0x00100003, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0130b118, + .EmcXm2DqsPadCtrl3 = 0x51451400, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000505, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000066, + .EmcBgbiasCtl0 = 0x00000008, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x01000003, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000001, + .McEmemArbTimingRc = 0x00000005, + .McEmemArbTimingRas = 0x00000002, + .McEmemArbTimingFaw = 0x00000004, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x00000008, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040203, + .McEmemArbDaCovers = 0x000a0505, + .McEmemArbMisc0 = 0x74a40a06, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-792.inc b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-792.inc new file mode 100644 index 0000000000..a66857075d --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-samsung-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from Samsung_4GB_K4B8G1646Q_792MHz_0703.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430F0F, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x00000114, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001a, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000018, + .EmcRdvMask = 0x0000001a, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x0000010d, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x0000011e, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200018, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x006f000c, + .EmcMrsWaitCnt2 = 0x006f000c, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000009, + .EmcDllXformDqs1 = 0x00000009, + .EmcDllXformDqs2 = 0x00008004, + .EmcDllXformDqs3 = 0x00000009, + .EmcDllXformDqs4 = 0x00000009, + .EmcDllXformDqs5 = 0x007f400c, + .EmcDllXformDqs6 = 0x007f800b, + .EmcDllXformDqs7 = 0x00000007, + .EmcDllXformDqs8 = 0x00000009, + .EmcDllXformDqs9 = 0x00000009, + .EmcDllXformDqs10 = 0x00008004, + .EmcDllXformDqs11 = 0x00000009, + .EmcDllXformDqs12 = 0x00000009, + .EmcDllXformDqs13 = 0x007f400c, + .EmcDllXformDqs14 = 0x007f800b, + .EmcDllXformDqs15 = 0x00000007, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0002c000, + .EmcDllXformAddr1 = 0x0002c000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0002c000, + .EmcDllXformAddr4 = 0x0002c000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000008, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x00000008, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x00000008, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000008, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x00000008, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x00000008, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000c, + .EmcDllXformDq1 = 0x0000000c, + .EmcDllXformDq2 = 0x0000000c, + .EmcDllXformDq3 = 0x0000000c, + .EmcDllXformDq4 = 0x0000000c, + .EmcDllXformDq5 = 0x0000000c, + .EmcDllXformDq6 = 0x0000000c, + .EmcDllXformDq7 = 0x0000000c, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x69a69c20, + .EmcXm2DqsPadCtrl4 = 0x00596596, + .EmcXm2DqsPadCtrl5 = 0x00618618, + .EmcXm2DqsPadCtrl6 = 0x69969a00, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000202, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x01643752, + .EmcSwizzleRank0Byte1 = 0x34675021, + .EmcSwizzleRank0Byte2 = 0x63170254, + .EmcSwizzleRank0Byte3 = 0x14065327, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x73541062, + .EmcSwizzleRank1Byte1 = 0x10637254, + .EmcSwizzleRank1Byte2 = 0x62043715, + .EmcSwizzleRank1Byte3 = 0x73015624, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00160d13, + .McEmemArbMisc0 = 0x746c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000000b, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xfff00000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000000, + .McMtsCarveoutRegCtrl = 0x00000000, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/sdram-unused.inc b/src/mainboard/google/nyan_blaze/bct/sdram-unused.inc new file mode 100644 index 0000000000..bef63dcecc --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/sdram-unused.inc @@ -0,0 +1,4 @@ +{ /* dummy. */ + .MemoryType = NvBootMemoryType_Unused, + 0, +}, diff --git a/src/mainboard/google/nyan_blaze/bct/spi.cfg b/src/mainboard/google/nyan_blaze/bct/spi.cfg new file mode 100644 index 0000000000..e9f85d52c6 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bct/spi.cfg @@ -0,0 +1,34 @@ +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00350001; +BlockSize = 32768; +PageSize = 2048; +PartitionSize = 4194304; + +Bctcopy = 1; + +DevType[0] = NvBootDevType_Spi; +DeviceParam[0].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[0].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[0].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[0].SpiFlashParams.PageSize2kor16k = 0; + +DevType[1] = NvBootDevType_Spi; +DeviceParam[1].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[1].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[1].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[1].SpiFlashParams.PageSize2kor16k = 0; + +DevType[2] = NvBootDevType_Spi; +DeviceParam[2].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[2].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[2].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[2].SpiFlashParams.PageSize2kor16k = 0; + +DevType[3] = NvBootDevType_Spi; +DeviceParam[3].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[3].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[3].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[3].SpiFlashParams.PageSize2kor16k = 0; + diff --git a/src/mainboard/google/nyan_blaze/boardid.c b/src/mainboard/google/nyan_blaze/boardid.c new file mode 100644 index 0000000000..1905c79e16 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/boardid.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + gpio_t gpio[] = {[3] = GPIO(X4), [2] = GPIO(X1), /* X4 is MSB */ + [1] = GPIO(T1), [0] = GPIO(Q3),}; /* Q3 is LSB */ + + if (id < 0) { + id = gpio_base3_value(gpio, ARRAY_SIZE(gpio)); + + printk(BIOS_SPEW, "Board TRISTATE ID: %d.\n", id); + } + + return id; +} diff --git a/src/mainboard/google/nyan_blaze/bootblock.c b/src/mainboard/google/nyan_blaze/bootblock.c new file mode 100644 index 0000000000..c471cb841a --- /dev/null +++ b/src/mainboard/google/nyan_blaze/bootblock.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME: move back to soc code? */ + +#include "pmic.h" + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta); + + clock_configure_source(mselect, PLLP, 102000); + + /* The PMIC is on I2C5 and can run at 400 KHz. */ + clock_configure_i2c_scl_freq(i2c5, PLLP, 400); + + /* TODO: We should be able to set this to 50MHz, but that did not seem + * reliable. */ + clock_configure_source(sbc4, PLLP, 33333); +} + +void bootblock_mainboard_init(void) +{ + set_clock_sources(); + + clock_enable_clear_reset(CLK_L_CACHE2 | CLK_L_TMR, + CLK_H_I2C5 | CLK_H_APBDMA, + 0, CLK_V_MSELECT, 0, 0); + + // Board ID GPIOs, bits 0-3. + gpio_input(GPIO(Q3)); + gpio_input(GPIO(T1)); + gpio_input(GPIO(X1)); + gpio_input(GPIO(X4)); + + // I2C5 (PMU) clock. + pinmux_set_config(PINMUX_PWR_I2C_SCL_INDEX, + PINMUX_PWR_I2C_SCL_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + // I2C5 (PMU) data. + pinmux_set_config(PINMUX_PWR_I2C_SDA_INDEX, + PINMUX_PWR_I2C_SDA_FUNC_I2CPMU | PINMUX_INPUT_ENABLE); + i2c_init(4); + pmic_init(4); + + /* SPI4 data out (MOSI) */ + pinmux_set_config(PINMUX_GPIO_PG6_INDEX, + PINMUX_GPIO_PG6_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 data in (MISO) */ + pinmux_set_config(PINMUX_GPIO_PG7_INDEX, + PINMUX_GPIO_PG7_FUNC_SPI4 | PINMUX_INPUT_ENABLE | + PINMUX_PULL_UP); + /* SPI4 clock */ + pinmux_set_config(PINMUX_GPIO_PG5_INDEX, + PINMUX_GPIO_PG5_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + /* SPI4 chip select 0 */ + pinmux_set_config(PINMUX_GPIO_PI3_INDEX, + PINMUX_GPIO_PI3_FUNC_SPI4 | PINMUX_INPUT_ENABLE); + + tegra_spi_init(4); +} diff --git a/src/mainboard/google/nyan_blaze/chromeos.c b/src/mainboard/google/nyan_blaze/chromeos.c new file mode 100644 index 0000000000..e4fbfdac10 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/chromeos.c @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO(R1); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO(R1)); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO(R4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: active low */ + gpios->gpios[count].port = GPIO(Q0); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: active high */ + gpios->gpios[count].port = GPIO(U4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: active low (output) */ + gpios->gpios[count].port = GPIO(I5); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO(R1)); +} diff --git a/src/mainboard/google/nyan_blaze/devicetree.cb b/src/mainboard/google/nyan_blaze/devicetree.cb new file mode 100644 index 0000000000..8919941360 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/devicetree.cb @@ -0,0 +1,94 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/nvidia/tegra124 + device cpu_cluster 0 on end +# N.B. We ae not using the device tree in an effective way. +# We need to change this in future such that the on-soc +# devices are 'chips', which will allow us to go at them +# in parallel. This is even easier on the ARM SOCs since there +# are no single-access resources such as the infamous +# cf8/cfc registers found on PCs. + register "display_controller" = "TEGRA_ARM_DISPLAYA" + register "xres" = "1366" + register "yres" = "768" + + # bits per pixel and color depth + register "framebuffer_bits_per_pixel" = "16" + register "color_depth" = "6" + # "6" is defined as COLOR_DEPTH_B5G6R5 in dc_reg.h + + register "panel_bits_per_pixel" = "18" + + register "cache_policy" = "DCACHE_WRITETHROUGH" + + # With some help from the mainbaord designer + register "backlight_en_gpio" = "GPIO(H2)" + register "lvds_shutdown_gpio" = "0" + register "backlight_vdd_gpio" = "GPIO(P2)" + register "panel_vdd_gpio" = "0" + register "pwm" = "1" + + # various panel delay time + register "vdd_delay_ms" = "200" + register "pwm_to_bl_delay_ms" = "10" + register "vdd_to_hpd_delay_ms" = "200" + register "hpd_unplug_min_us" = "2000" + register "hpd_plug_min_us" = "250" + register "hpd_irq_min_us" = "250" + +# How to compute these: xrandr --verbose will give you this: +#Detailed mode: Clock 285.250 MHz, 272 mm x 181 mm +# 2560 2608 2640 2720 hborder 0 +# 1700 1703 1713 1749 vborder 0 +#Then you can compute your values: +#H front porch = 2608 - 2560 = 48 +#H sync = 2640 - 2608 = 32 +#H back porch = 2720 - 2640 = 80 +#V front porch = 1703 - 1700 = 3 +#V sync = 1713 - 1703 = 10 +#V back porch = 1749 - 1713 = 36 +#href_to_sync and vref_to_sync are from the vendor +#this is just an example for a Pixel panel; other panels differ. +# Here is a peppy panel: +# 1366x768 (0x45) 76.4MHz -HSync -VSync *current +preferred +# h: width 1366 start 1502 end 1532 total 1592 +# v: height 768 start 776 end 788 total 800 + register "href_to_sync" = "1" + register "hfront_porch" = "136" + register "hsync_width" = "30" + register "hback_porch" = "60" + + register "vref_to_sync" = "1" + register "vfront_porch" = "8" + register "vsync_width" = "12" + register "vback_porch" = "12" + + register "pixel_clock" = "76400000" + + # link configurations + register "lane_count" = "1" + register "enhanced_framing" = "1" + register "link_bw" = "10" + # "10" is defined as SOR_LINK_SPEED_G2_7 in sor.h + + register "drive_current" = "0x40404040" + register "preemphasis" = "0x0f0f0f0f" + register "postcursor" = "0" +end diff --git a/src/mainboard/google/nyan_blaze/early_configs.c b/src/mainboard/google/nyan_blaze/early_configs.c new file mode 100644 index 0000000000..de9fe8ef9d --- /dev/null +++ b/src/mainboard/google/nyan_blaze/early_configs.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void setup_pinmux(void) +{ + /* Write protect. */ + gpio_input_pullup(GPIO(R1)); + /* Recovery mode. */ + gpio_input_pullup(GPIO(Q7)); + /* Lid switch. */ + gpio_input_pullup(GPIO(R4)); + /* Power switch. */ + gpio_input_pullup(GPIO(Q0)); + /* Developer mode. */ + gpio_input_pullup(GPIO(Q6)); + /* EC in RW. */ + gpio_input_pullup(GPIO(U4)); + + /* route PU4/5 to GMI to remove conflict w/PWM1/2. */ + pinmux_set_config(PINMUX_GPIO_PU4_INDEX, + PINMUX_GPIO_PU4_FUNC_NOR); /* s/b GMI */ + pinmux_set_config(PINMUX_GPIO_PU5_INDEX, + PINMUX_GPIO_PU5_FUNC_NOR); /* s/b GMI */ + + /* SOC and TPM reset GPIO, active low. */ + gpio_output(GPIO(I5), 1); + + /* SPI1 MOSI */ + pinmux_set_config(PINMUX_ULPI_CLK_INDEX, PINMUX_ULPI_CLK_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 MISO */ + pinmux_set_config(PINMUX_ULPI_DIR_INDEX, PINMUX_ULPI_DIR_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 SCLK */ + pinmux_set_config(PINMUX_ULPI_NXT_INDEX, PINMUX_ULPI_NXT_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + /* SPI1 CS0 */ + pinmux_set_config(PINMUX_ULPI_STP_INDEX, PINMUX_ULPI_STP_FUNC_SPI1 | + PINMUX_PULL_NONE | + PINMUX_INPUT_ENABLE); + + /* I2C3 (cam) clock. */ + pinmux_set_config(PINMUX_CAM_I2C_SCL_INDEX, + PINMUX_CAM_I2C_SCL_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + /* I2C3 (cam) data. */ + pinmux_set_config(PINMUX_CAM_I2C_SDA_INDEX, + PINMUX_CAM_I2C_SDA_FUNC_I2C3 | PINMUX_INPUT_ENABLE); + + /* switch unused pin to GPIO */ + gpio_set_mode(GPIO(X3), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X4), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X5), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X6), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(X7), GPIO_MODE_GPIO); + gpio_set_mode(GPIO(W3), GPIO_MODE_GPIO); +} + +static void configure_ec_spi_bus(void) +{ + clock_configure_source(sbc1, CLK_M, 3000); +} + +static void configure_tpm_i2c_bus(void) +{ + clock_configure_i2c_scl_freq(i2c3, PLLP, 400); + + i2c_init(2); +} + +void early_mainboard_init(void) +{ + clock_enable_clear_reset(0, CLK_H_SBC1, CLK_U_I2C3, 0, 0, 0); + setup_pinmux(); + configure_ec_spi_bus(); + configure_tpm_i2c_bus(); +} diff --git a/src/mainboard/google/nyan_blaze/mainboard.c b/src/mainboard/google/nyan_blaze/mainboard.c new file mode 100644 index 0000000000..f539910039 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/mainboard.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + /* + * The max98090 codec and the temperature sensor are on I2C1. These + * can both run at 400 KHz, but the kernel sets the bus to 100 KHz. + */ + clock_configure_i2c_scl_freq(i2c1, PLLP, 100); + + /* + * MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's + * maximum speed (48MHz) so we can change SDCLK by second stage divisor + * in payloads, without touching base clock. + */ + clock_configure_source(sdmmc3, PLLP, 48000); + clock_configure_source(sdmmc4, PLLP, 48000); + + /* External peripheral 1: audio codec (max98090) using 12MHz CLK1. + * Note the source id of CLK_M for EXTPERIPH1 is 3. */ + clock_configure_irregular_source(extperiph1, CLK_M, 12000, 3); + + /* + * We need 1.5MHz. So, we use CLK_M. CLK_DIVIDER macro returns a divisor + * (0xe) a little bit off from the ideal value (0xd) but it's good + * enough for beeps. The source id of CLK_M for I2S is 6. + */ + clock_configure_irregular_source(i2s1, CLK_M, 1500, 6); + + /* Note source id of PLLP for HOST1x is 4. */ + clock_configure_irregular_source(host1x, PLLP, 408000, 4); + + /* Use PLLD_OUT0 as clock source for disp1 */ + clrsetbits_le32(&clk_rst->clk_src_disp1, + CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + 2 /*PLLD_OUT0 */ << CLK_SOURCE_SHIFT); + +} + +static void setup_pinmux(void) +{ + // I2C1 clock. + pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX, + PINMUX_GEN1_I2C_SCL_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C1 data. + pinmux_set_config(PINMUX_GEN1_I2C_SDA_INDEX, + PINMUX_GEN1_I2C_SDA_FUNC_I2C1 | PINMUX_INPUT_ENABLE); + // I2C2 clock. + pinmux_set_config(PINMUX_GEN2_I2C_SCL_INDEX, + PINMUX_GEN2_I2C_SCL_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C2 data. + pinmux_set_config(PINMUX_GEN2_I2C_SDA_INDEX, + PINMUX_GEN2_I2C_SDA_FUNC_I2C2 | PINMUX_INPUT_ENABLE | + PINMUX_OPEN_DRAIN); + // I2C4 (DDC) clock. + pinmux_set_config(PINMUX_DDC_SCL_INDEX, + PINMUX_DDC_SCL_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + // I2C4 (DDC) data. + pinmux_set_config(PINMUX_DDC_SDA_INDEX, + PINMUX_DDC_SDA_FUNC_I2C4 | PINMUX_INPUT_ENABLE); + + // TODO(hungte) Revice pinmux setup, make nice little SoC functions for + // every single logical thing instead of dumping a wall of code below. + uint32_t pin_up = PINMUX_PULL_UP | PINMUX_INPUT_ENABLE, + pin_down = PINMUX_PULL_DOWN | PINMUX_INPUT_ENABLE, + pin_none = PINMUX_PULL_NONE | PINMUX_INPUT_ENABLE; + + // MMC3 (sdcard reader) + pinmux_set_config(PINMUX_SDMMC3_CLK_INDEX, + PINMUX_SDMMC3_CLK_FUNC_SDMMC3 | pin_none); + pinmux_set_config(PINMUX_SDMMC3_CMD_INDEX, + PINMUX_SDMMC3_CMD_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT0_INDEX, + PINMUX_SDMMC3_DAT0_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT1_INDEX, + PINMUX_SDMMC3_DAT1_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT2_INDEX, + PINMUX_SDMMC3_DAT2_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_DAT3_INDEX, + PINMUX_SDMMC3_DAT3_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_IN_INDEX, + PINMUX_SDMMC3_CLK_LB_IN_FUNC_SDMMC3 | pin_up); + pinmux_set_config(PINMUX_SDMMC3_CLK_LB_OUT_INDEX, + PINMUX_SDMMC3_CLK_LB_OUT_FUNC_SDMMC3 | pin_down); + + // MMC3 Card Detect pin. + gpio_input_pullup(GPIO(V2)); + // Disable SD card reader power so it can be reset even on warm boot. + // Payloads must enable power before accessing SD card slots. + gpio_output(GPIO(R0), 0); + + // MMC4 (eMMC) + pinmux_set_config(PINMUX_SDMMC4_CLK_INDEX, + PINMUX_SDMMC4_CLK_FUNC_SDMMC4 | pin_none); + pinmux_set_config(PINMUX_SDMMC4_CMD_INDEX, + PINMUX_SDMMC4_CMD_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT0_INDEX, + PINMUX_SDMMC4_DAT0_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT1_INDEX, + PINMUX_SDMMC4_DAT1_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT2_INDEX, + PINMUX_SDMMC4_DAT2_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT3_INDEX, + PINMUX_SDMMC4_DAT3_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT4_INDEX, + PINMUX_SDMMC4_DAT4_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT5_INDEX, + PINMUX_SDMMC4_DAT5_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT6_INDEX, + PINMUX_SDMMC4_DAT6_FUNC_SDMMC4 | pin_up); + pinmux_set_config(PINMUX_SDMMC4_DAT7_INDEX, + PINMUX_SDMMC4_DAT7_FUNC_SDMMC4 | pin_up); + + /* We pull the USB VBUS signals up but keep them as inputs since the + * voltage source likes to drive them low on overcurrent conditions */ + gpio_input_pullup(GPIO(N4)); /* USB VBUS EN0 */ + gpio_input_pullup(GPIO(N5)); /* USB VBUS EN1 */ + + /* Clock output 1 (for external peripheral) */ + pinmux_set_config(PINMUX_DAP_MCLK1_INDEX, + PINMUX_DAP_MCLK1_FUNC_EXTPERIPH1 | PINMUX_PULL_NONE); + + /* I2S1 */ + pinmux_set_config(PINMUX_DAP2_DIN_INDEX, + PINMUX_DAP2_DIN_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_DOUT_INDEX, + PINMUX_DAP2_DOUT_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_FS_INDEX, + PINMUX_DAP2_FS_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_DAP2_SCLK_INDEX, + PINMUX_DAP2_SCLK_FUNC_I2S1 | PINMUX_INPUT_ENABLE); + + /* PWM1 */ + pinmux_set_config(PINMUX_GPIO_PH1_INDEX, + PINMUX_GPIO_PH1_FUNC_PWM1 | PINMUX_PULL_NONE); + + /* DP HPD */ + pinmux_set_config(PINMUX_DP_HPD_INDEX, + PINMUX_DP_HPD_FUNC_DP | PINMUX_INPUT_ENABLE); +} + +static void setup_kernel_info(void) +{ + // Setup required information for Linux kernel. + + // pmc.odmdata: [18:19]: console type, [15:17]: UART id. + // TODO(hungte) This should be done by filling BCT values, or derived + // from CONFIG_CONSOLE_SERIAL_UART[A-E]. Right now we simply copy the + // value defined in BCT. + struct tegra_pmc_regs *pmc = (void*)TEGRA_PMC_BASE; + writel(0x80080000, &pmc->odmdata); + + // Not strictly info, but kernel graphics driver needs this region locked down + struct tegra_mc_regs *mc = (void *)TEGRA_MC_BASE; + writel(0, &mc->video_protect_bom); + writel(0, &mc->video_protect_size_mb); + writel(1, &mc->video_protect_reg_ctrl); +} + +static void setup_ec_spi(void) +{ + struct tegra_spi_channel *spi; + + spi = tegra_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS); +} + +static void mainboard_init(device_t dev) +{ + set_clock_sources(); + + clock_external_output(1); /* For external MAX98090 audio codec. */ + + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * conntected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (In our + * case, I2S/APBIF/AUDIO) will hang. + */ + clock_enable_clear_reset(CLK_L_GPIO | CLK_L_I2C1 | CLK_L_SDMMC4 | + CLK_L_I2S0 | CLK_L_I2S1 | CLK_L_I2S2 | + CLK_L_SPDIF | CLK_L_USBD | CLK_L_DISP1 | + CLK_L_HOST1X | CLK_L_PWM, + + CLK_H_EMC | CLK_H_I2C2 | CLK_H_PMC | + CLK_H_MEM | CLK_H_USB2 | CLK_H_USB3, + + CLK_U_CSITE | CLK_U_SDMMC3, + + CLK_V_I2C4 | CLK_V_EXTPERIPH1 | CLK_V_APBIF | + CLK_V_AUDIO | CLK_V_I2S3 | CLK_V_I2S4 | + CLK_V_DAM0 | CLK_V_DAM1 | CLK_V_DAM2, + + CLK_W_DVFS | CLK_W_AMX0 | CLK_W_ADX0, + + CLK_X_DPAUX | CLK_X_SOR0 | CLK_X_AMX1 | + CLK_X_ADX1 | CLK_X_AFC0 | CLK_X_AFC1 | + CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | + CLK_X_AFC5); + + usb_setup_utmip((void*)TEGRA_USBD_BASE); + usb_setup_utmip((void*)TEGRA_USB2_BASE); + usb_setup_utmip((void*)TEGRA_USB3_BASE); + + setup_pinmux(); + + i2c_init(0); + i2c_init(1); + i2c_init(3); + + setup_kernel_info(); + clock_init_arm_generic_timer(); + setup_ec_spi(); + elog_init(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "nyan_blaze", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} diff --git a/src/mainboard/google/nyan_blaze/memlayout.ld b/src/mainboard/google/nyan_blaze/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/nyan_blaze/pmic.c b/src/mainboard/google/nyan_blaze/pmic.c new file mode 100644 index 0000000000..16f043c024 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/pmic.c @@ -0,0 +1,114 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pmic.h" + +enum { + AS3722_I2C_ADDR = 0x40 +}; + +struct as3722_init_reg { + u8 reg; + u8 val; + u8 delay; +}; + +static struct as3722_init_reg init_list[] = { + {AS3722_SDO0, 0x3C, 1}, + {AS3722_SDO1, 0x32, 0}, + {AS3722_LDO3, 0x59, 0}, + {AS3722_SDO2, 0x3C, 0}, + {AS3722_SDO3, 0x00, 0}, + {AS3722_SDO4, 0x00, 0}, + {AS3722_SDO5, 0x50, 0}, + {AS3722_SDO6, 0x28, 1}, + {AS3722_LDO0, 0x8A, 0}, + {AS3722_LDO1, 0x00, 0}, + {AS3722_LDO2, 0x10, 0}, + {AS3722_LDO4, 0x00, 0}, + {AS3722_LDO5, 0x00, 0}, + {AS3722_LDO6, 0x00, 0}, + {AS3722_LDO7, 0x00, 0}, + {AS3722_LDO9, 0x00, 0}, + {AS3722_LDO10, 0x00, 0}, + {AS3722_LDO11, 0x00, 1}, +}; + +static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) +{ + if (i2c_writeb(bus, AS3722_I2C_ADDR, reg, val)) { + printk(BIOS_ERR, "%s: reg = 0x%02X, value = 0x%02X failed!\n", + __func__, reg, val); + /* Reset the SoC on any PMIC write error */ + hard_reset(); + } else { + if (delay) + udelay(500); + } +} + +static void pmic_slam_defaults(unsigned bus) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + struct as3722_init_reg *reg = &init_list[i]; + pmic_write_reg(bus, reg->reg, reg->val, reg->delay); + } +} + +void pmic_init(unsigned bus) +{ + /* + * Don't need to set up VDD_CORE - already done - by OTP + * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled. + * Don't write LDCONTROL - it's already 0xFF, i.e. all LDOs enabled. + */ + + /* Restore PMIC POR defaults, in case kernel changed 'em */ + pmic_slam_defaults(bus); + + /* First set VDD_CPU to 1.2V, then enable the VDD_CPU regulator. */ + pmic_write_reg(bus, 0x00, 0x50, 1); + + /* First set VDD_GPU to 1.0V, then enable the VDD_GPU regulator. */ + pmic_write_reg(bus, 0x06, 0x28, 1); + + /* + * First set +1.2V_GEN_AVDD to 1.2V, then enable the +1.2V_GEN_AVDD + * regulator. + */ + pmic_write_reg(bus, 0x12, 0x10, 1); + + /* + * Panel power GPIO O4. Set mode for GPIO4 (0x0c to 7), then set + * the value (register 0x20 bit 4) + */ + pmic_write_reg(bus, 0x0c, 0x07, 0); + pmic_write_reg(bus, 0x20, 0x10, 1); +} diff --git a/src/mainboard/google/nyan_blaze/pmic.h b/src/mainboard/google/nyan_blaze/pmic.h new file mode 100644 index 0000000000..b65490844f --- /dev/null +++ b/src/mainboard/google/nyan_blaze/pmic.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_BLAZE_PMIC_H__ +#define __MAINBOARD_GOOGLE_NYAN_BLAZE_PMIC_H__ + +enum { + AS3722_SDO0 = 0, + AS3722_SDO1, + AS3722_SDO2, + AS3722_SDO3, + AS3722_SDO4, + AS3722_SDO5, + AS3722_SDO6, + + AS3722_LDO0 = 0x10, + AS3722_LDO1, + AS3722_LDO2, + AS3722_LDO3, + AS3722_LDO4, + AS3722_LDO5, + AS3722_LDO6, + AS3722_LDO7, + + AS3722_LDO9 = 0x19, + AS3722_LDO10, + AS3722_LDO11, +}; + +void pmic_init(unsigned bus); + +#endif /* __MAINBOARD_GOOGLE_NYAN_BLAZE_PMIC_H__ */ diff --git a/src/mainboard/google/nyan_blaze/reset.c b/src/mainboard/google/nyan_blaze/reset.c new file mode 100644 index 0000000000..e58890e604 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/reset.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void hard_reset(void) +{ + gpio_output(GPIO(I5), 0); + while(1); +} diff --git a/src/mainboard/google/nyan_blaze/romstage.c b/src/mainboard/google/nyan_blaze/romstage.c new file mode 100644 index 0000000000..837b681825 --- /dev/null +++ b/src/mainboard/google/nyan_blaze/romstage.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdram_configs.h" + +static void __attribute__((noinline)) romstage(void) +{ + void *entry = NULL; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + exception_init(); + + sdram_init(get_sdram_config()); + + /* used for MMU and CBMEM setup, in MB */ + u32 dram_start_mb = (uintptr_t)_dram/MiB; + u32 dram_end_mb = sdram_max_addressable_mb(); + u32 dram_size_mb = dram_end_mb - dram_start_mb; + +#if !CONFIG_VBOOT2_VERIFY_FIRMWARE + configure_l2_cache(); + mmu_init(); + /* Device memory below DRAM is uncached. */ + mmu_config_range(0, dram_start_mb, DCACHE_OFF); + /* SRAM is cached. MMU code will round size up to page size. */ + mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB), + DCACHE_WRITEBACK); + /* The space above DRAM is uncached. */ + if (dram_end_mb < 4096) + mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF); + mmu_disable_range(0, 1); + dcache_mmu_enable(); +#endif + + /* DRAM is cached. */ + mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK); + /* A window for DMA is uncached. */ + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + /* + * A watchdog reset only resets part of the system so it ends up in + * a funny state. If that happens, we need to reset the whole machine. + */ + if (power_reset_status() == POWER_RESET_WATCHDOG) { + printk(BIOS_INFO, "Watchdog reset detected, rebooting.\n"); + hard_reset(); + } + + cbmem_initialize_empty(); + +#if CONFIG_VBOOT2_VERIFY_FIRMWARE + entry = vboot2_load_ramstage(); +#else + early_mainboard_init(); + vboot_verify_firmware(romstage_handoff_find_or_add()); +#endif + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + stage_exit(entry); +} + +/* Stub to force arm_init_caches to the top, before any stack/memory accesses */ +void main(void) +{ +#if !CONFIG_VBOOT2_VERIFY_FIRMWARE + asm volatile ("bl arm_init_caches" + ::: "r0","r1","r2","r3","r4","r5","ip"); +#endif + romstage(); +} diff --git a/src/mainboard/google/nyan_blaze/sdram_configs.c b/src/mainboard/google/nyan_blaze/sdram_configs.c new file mode 100644 index 0000000000..94c9203b5f --- /dev/null +++ b/src/mainboard/google/nyan_blaze/sdram_configs.c @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "sdram_configs.h" + +static struct sdram_params sdram_configs[] = { +#include "bct/sdram-hynix-2GB-792.inc" /* ram_code = 0000 */ +#include "bct/sdram-micron-2GB-792.inc" /* ram_code = 0001 */ +#include "bct/sdram-samsung-2GB-792.inc" /* ram_code = 0010 */ +#include "bct/sdram-hynix-2GB-204.inc" /* ram_code = 0011 */ +#include "bct/sdram-unused.inc" /* ram_code = 0100 */ +#include "bct/sdram-unused.inc" /* ram_code = 0101 */ +#include "bct/sdram-unused.inc" /* ram_code = 0110 */ +#include "bct/sdram-unused.inc" /* ram_code = 0111 */ +#include "bct/sdram-hynix-4GB-792.inc" /* ram_code = 1000 */ +#include "bct/sdram-micron-4GB-792.inc" /* ram_code = 1001 */ +#include "bct/sdram-samsung-4GB-792.inc" /* ram_code = 1010 */ +#include "bct/sdram-hynix-2GB-204.inc" /* ram_code = 1011 */ +#include "bct/sdram-unused.inc" /* ram_code = 1100 */ +#include "bct/sdram-unused.inc" /* ram_code = 1101 */ +#include "bct/sdram-unused.inc" /* ram_code = 1110 */ +#include "bct/sdram-unused.inc" /* ram_code = 1111 */ +}; + +const struct sdram_params *get_sdram_config() +{ + uint32_t ramcode = sdram_get_ram_code(); + /* + * If we need to apply some special hacks to RAMCODE mapping (ex, by + * board_id), do that now. + */ + + printk(BIOS_SPEW, "%s: RAMCODE=%d\n", __func__, ramcode); + if (ramcode >= sizeof(sdram_configs) / sizeof(sdram_configs[0]) || + sdram_configs[ramcode].MemoryType == NvBootMemoryType_Unused) { + die("Invalid RAMCODE."); + } + + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/nyan_blaze/sdram_configs.h b/src/mainboard/google/nyan_blaze/sdram_configs.h new file mode 100644 index 0000000000..e5f987339f --- /dev/null +++ b/src/mainboard/google/nyan_blaze/sdram_configs.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_NYAN_BLAZE_SDRAM_CONFIG_H__ +#define __MAINBOARD_GOOGLE_NYAN_BLAZE_SDRAM_CONFIG_H__ + +#include + +/* Loads SDRAM configurations for current system. */ +const struct sdram_params *get_sdram_config(void); + +#endif /* __MAINBOARD_GOOGLE_NYAN_BLAZE_SDRAM_CONFIG_H__ */ diff --git a/src/mainboard/google/panther/Kconfig b/src/mainboard/google/panther/Kconfig new file mode 100644 index 0000000000..5a7376a82e --- /dev/null +++ b/src/mainboard/google/panther/Kconfig @@ -0,0 +1,53 @@ +if BOARD_GOOGLE_PANTHER + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_HASWELL + select SOUTHBRIDGE_INTEL_LYNXPOINT + select INTEL_LYNXPOINT_LP + select BOARD_ROMSIZE_KB_8192 + select SUPERIO_ITE_IT8772F + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select PHYSICAL_REC_SWITCH + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x1 + +config MAINBOARD_DIR + string + default google/panther + +config MAINBOARD_PART_NUMBER + string + default "Panther" + +config MMCONF_BASE_ADDRESS + hex + default 0xf0000000 + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/panther/Makefile.inc b/src/mainboard/google/panther/Makefile.inc new file mode 100644 index 0000000000..1300be6548 --- /dev/null +++ b/src/mainboard/google/panther/Makefile.inc @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-y += lan.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + diff --git a/src/mainboard/google/panther/acpi/chromeos.asl b/src/mainboard/google/panther/acpi/chromeos.asl new file mode 100644 index 0000000000..0189cfa065 --- /dev/null +++ b/src/mainboard/google/panther/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 12, "LynxPoint" }, // recovery button + Package () { 0x0003, 1, 58, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/panther/acpi/ec.asl b/src/mainboard/google/panther/acpi/ec.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/google/panther/acpi/haswell_pci_irqs.asl b/src/mainboard/google/panther/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/panther/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/panther/acpi/mainboard.asl b/src/mainboard/google/panther/acpi/mainboard.asl new file mode 100644 index 0000000000..867c1e03ea --- /dev/null +++ b/src/mainboard/google/panther/acpi/mainboard.asl @@ -0,0 +1,74 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } +} + +/* + * LAN connected to Root Port 3, becomes Root Port 1 after coalesce + */ +Scope (\_SB.PCI0.RP01) +{ + Device (ETH0) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { PANTHER_NIC_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (PANTHER_NIC_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} + +/* + * WLAN connected to Root Port 4, becomes Root Port 2 after coalesce + */ +Scope (\_SB.PCI0.RP02) +{ + Device (WLAN) + { + Name (_ADR, 0x00000000) + Name (_PRW, Package() { PANTHER_WLAN_WAKE_GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (PANTHER_WLAN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/panther/acpi/platform.asl b/src/mainboard/google/panther/acpi/platform.asl new file mode 100644 index 0000000000..1c70d4974a --- /dev/null +++ b/src/mainboard/google/panther/acpi/platform.asl @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + /* Initialize thermal defaults */ + \_TZ.THRM._INI () + + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/panther/acpi/superio.asl b/src/mainboard/google/panther/acpi/superio.asl new file mode 100644 index 0000000000..e1c9d1c918 --- /dev/null +++ b/src/mainboard/google/panther/acpi/superio.asl @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Values should match those defined in devicetree.cb */ + +#undef SIO_ENABLE_FDC0 // pnp 2e.0: Disable Floppy Controller +#undef SIO_ENABLE_INFR // pnp 2e.a: Disable Consumer IR + +#define SIO_ENABLE_PS2K // pnp 2e.5: Enable PS/2 Keyboard +#define SIO_ENABLE_PS2M // pnp 2e.6: Enable PS/2 Mouse +#define SIO_ENABLE_COM1 // pnp 2e.1: Enable Serial Port 1 +#define SIO_ENABLE_ENVC // pnp 2e.4: Enable Environmental Controller +#define SIO_ENVC_IO0 0x700 // pnp 2e.4: io 0x60 +#define SIO_ENVC_IO1 0x710 // pnp 2e.4: io 0x62 +#define SIO_ENABLE_GPIO // pnp 2e.7: Enable GPIO +#define SIO_GPIO_IO0 0x720 // pnp 2e.7: io 0x60 +#define SIO_GPIO_IO1 0x730 // pnp 2e.7: io 0x60 + +#include "superio/ite/it8772f/acpi/superio.asl" + diff --git a/src/mainboard/google/panther/acpi/thermal.asl b/src/mainboard/google/panther/acpi/thermal.asl new file mode 100644 index 0000000000..9486d3ccf2 --- /dev/null +++ b/src/mainboard/google/panther/acpi/thermal.asl @@ -0,0 +1,342 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + // Start fan at state 4 = lowest temp state + Method (_INI) + { + Store (4, \FLVL) + Store (\F4PW, \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + + Method (TCHK, 0, Serialized) + { + // Get CPU Temperature from PECI via SuperIO TMPIN3 + Store (\_SB.PCI0.LPCB.SIO.ENVC.TIN3, Local0) + + // Check for "no reading available + If (LEqual (Local0, 0x80)) { + Return (CTOK (\F0ON)) + } + + // Check for invalid readings + If (LOr (LEqual (Local0, 255), LEqual (Local0, 0))) { + Return (CTOK (\F0ON)) + } + + // PECI raw value is an offset from Tj_max + Subtract (255, Local0, Local1) + + // Handle values greater than Tj_max + If (LGreaterEqual (Local1, \TMAX)) { + Return (CTOK (\TMAX)) + } + + // Subtract from Tj_max to get temperature + Subtract (\TMAX, Local1, Local0) + Return (CTOK (Local0)) + } + + Method (_TMP, 0, Serialized) + { + // Get temperature from SuperIO in deci-kelvin + Store (TCHK (), Local0) + + // Critical temperature in deci-kelvin + Store (CTOK (\TMAX), Local1) + + If (LGreaterEqual (Local0, Local1)) { + Store ("CRITICAL TEMPERATURE", Debug) + Store (Local0, Debug) + + // Wait 1 second for SuperIO to re-poll + Sleep (1000) + + // Re-read temperature from SuperIO + Store (TCHK (), Local0) + + Store ("RE-READ TEMPERATURE", Debug) + Store (Local0, Debug) + } + + Return (Local0) + } + + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (\F0OF)) + } Else { + Return (CTOK (\F0ON)) + } + } + + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (\F1OF)) + } Else { + Return (CTOK (\F1ON)) + } + } + + Method (_AC2) { + If (LLessEqual (\FLVL, 2)) { + Return (CTOK (\F2OF)) + } Else { + Return (CTOK (\F2ON)) + } + } + + Method (_AC3) { + If (LLessEqual (\FLVL, 3)) { + Return (CTOK (\F3OF)) + } Else { + Return (CTOK (\F3ON)) + } + } + + Method (_AC4) { + If (LLessEqual (\FLVL, 4)) { + Return (CTOK (\F4OF)) + } Else { + Return (CTOK (\F4ON)) + } + } + + Name (_AL0, Package () { FAN0 }) + Name (_AL1, Package () { FAN1 }) + Name (_AL2, Package () { FAN2 }) + Name (_AL3, Package () { FAN3 }) + Name (_AL4, Package () { FAN4 }) + + PowerResource (FNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + If (LNot (_STA ())) { + Store (0, \FLVL) + Store (\F0PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + Method (_OFF) { + If (_STA ()) { + Store (1, \FLVL) + Store (\F1PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + } + + PowerResource (FNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + If (LNot (_STA ())) { + Store (1, \FLVL) + Store (\F1PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + Method (_OFF) { + If (_STA ()) { + Store (2, \FLVL) + Store (\F2PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + } + + PowerResource (FNP2, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 2)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + If (LNot (_STA ())) { + Store (2, \FLVL) + Store (\F2PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + Method (_OFF) { + If (_STA ()) { + Store (3, \FLVL) + Store (\F3PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + } + + PowerResource (FNP3, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 3)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + If (LNot (_STA ())) { + Store (3, \FLVL) + Store (\F3PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + Method (_OFF) { + If (_STA ()) { + Store (4, \FLVL) + Store (\F4PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + } + + PowerResource (FNP4, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 4)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + If (LNot (_STA ())) { + Store (4, \FLVL) + Store (\F4PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + Method (_OFF) { + If (_STA ()) { + Store (4, \FLVL) + Store (\F4PW, + \_SB.PCI0.LPCB.SIO.ENVC.F2PS) + Notify (\_TZ.THRM, 0x81) + } + } + } + + Device (FAN0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { FNP0 }) + } + + Device (FAN1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { FNP1 }) + } + + Device (FAN2) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 2) + Name (_PR0, Package () { FNP2 }) + } + + Device (FAN3) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 3) + Name (_PR0, Package () { FNP3 }) + } + + Device (FAN4) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 4) + Name (_PR0, Package () { FNP4 }) + } + } +} + diff --git a/src/mainboard/google/panther/acpi/video.asl b/src/mainboard/google/panther/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/panther/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/panther/acpi_tables.c b/src/mainboard/google/panther/acpi_tables.c new file mode 100644 index 0000000000..09601004e4 --- /dev/null +++ b/src/mainboard/google/panther/acpi_tables.c @@ -0,0 +1,304 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +#include +#include +#include "thermal.h" + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->f4of = FAN4_THRESHOLD_OFF; + gnvs->f4on = FAN4_THRESHOLD_ON; + gnvs->f4pw = FAN4_PWM; + + gnvs->f3of = FAN3_THRESHOLD_OFF; + gnvs->f3on = FAN3_THRESHOLD_ON; + gnvs->f3pw = FAN3_PWM; + + gnvs->f2of = FAN2_THRESHOLD_OFF; + gnvs->f2on = FAN2_THRESHOLD_ON; + gnvs->f2pw = FAN2_PWM; + + gnvs->f1of = FAN1_THRESHOLD_OFF; + gnvs->f1on = FAN1_THRESHOLD_ON; + gnvs->f1pw = FAN1_PWM; + + gnvs->f0of = FAN0_THRESHOLD_OFF; + gnvs->f0on = FAN0_THRESHOLD_ON; + gnvs->f0pw = FAN0_PWM; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 5; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* CBMEM TOC */ + gnvs->cmem = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +#if CONFIG_CHROMEOS + // TODO(reinauer) this could move elsewhere? + chromeos_init_vboot(&(gnvs->chromeos)); + + // SuperIO is always RO + gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; +#endif + + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/panther/chromeos.c b/src/mainboard/google/panther/chromeos.c new file mode 100644 index 0000000000..61f8408da5 --- /dev/null +++ b/src/mainboard/google/panther/chromeos.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define GPIO_SPI_WP 58 +#define GPIO_REC_MODE 12 + +#define FLAG_SPI_WP 0 +#define FLAG_REC_MODE 1 +#define FLAG_DEV_MODE 2 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, GPIO_SPI_WP, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, GPIO_REC_MODE, ACTIVE_LOW, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", 1); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +int get_write_protect_state(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_SPI_WP) & 1; +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + device_t dev; +#ifdef __PRE_RAM__ + dev = PCI_DEV(0, 0x1f, 2); +#else + dev = dev_find_slot(0, PCI_DEVFN(0x1f, 2)); +#endif + return (pci_read_config32(dev, SATA_SP) >> FLAG_REC_MODE) & 1; +} + +#ifdef __PRE_RAM__ +void save_chromeos_gpios(void) +{ + u32 flags = 0; + + /* Write Protect: GPIO58 = GPIO_SPI_WP, active high */ + if (get_gpio(GPIO_SPI_WP)) + flags |= (1 << FLAG_SPI_WP); + + /* Recovery: GPIO12 = RECOVERY_L, active low */ + if (!get_gpio(GPIO_REC_MODE)) + flags |= (1 << FLAG_REC_MODE); + + /* Developer: Virtual */ + + pci_write_config32(PCI_DEV(0, 0x1f, 2), SATA_SP, flags); +} +#endif diff --git a/src/mainboard/google/panther/cmos.layout b/src/mainboard/google/panther/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/panther/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/panther/devicetree.cb b/src/mainboard/google/panther/devicetree.cb new file mode 100644 index 0000000000..d37b622268 --- /dev/null +++ b/src/mainboard/google/panther/devicetree.cb @@ -0,0 +1,142 @@ +chip northbridge/intel/haswell + + # Disable eDP Hotplug + register "gpu_dp_d_hotplug" = "0x00" + + # Enable DisplayPort C Hotplug with 6ms pulse + register "gpu_dp_c_hotplug" = "0x06" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) + end + end + + device domain 0 on + subsystemid 0x1ae0 0xc000 inherit + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # SuperIO range is 0x700-0x73f + register "gen2_dec" = "0x003c0701" + + register "alt_gp_smi_en" = "0x0000" + register "gpe0_en_1" = "0x00000000" + register "gpe0_en_2" = "0x00000000" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + register "sata_devslp_disable" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + # Force enable ASPM for PCIe Port 4 + register "pcie_port_force_aspm" = "0x10" + + # Enable port coalescing + register "pcie_port_coalesce" = "1" + + # Disable PCIe CLKOUT 1,5 and CLKOUT_XDP + register "icc_clock_disable" = "0x01220000" + + # Route all USB ports to XHCI per default + register "xhci_default" = "1" + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 off end # Serial I/O DMA + device pci 15.1 off end # I2C0 + device pci 15.2 off end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 off end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip superio/ite/it8772f + # Skip keyboard init + register "skip_keyboard" = "1" + # Enable PECI on TMPIN3 + register "peci_tmpin" = "3" + # Enable FAN2 + register "fan2_enable" = "1" + + device pnp 2e.0 off end # FDC + device pnp 2e.1 on # Serial Port 1 + io 0x60 = 0x3f8 + irq 0x70 = 4 + end + device pnp 2e.4 on # Environment Controller + io 0x60 = 0x700 + io 0x62 = 0x710 + irq 0x70 = 0x09 + irq 0xf2 = 0x20 + irq 0xf4 = 0x0 + irq 0xfa = 0x12 + end + device pnp 2e.7 on # GPIO + io 0x60 = 0x720 + io 0x62 = 0x730 + end + device pnp 2e.5 on + io 0x60 = 0x60 + io 0x62 = 0x64 + irq 0x70 = 1 + end # Keyboard + device pnp 2e.6 on + irq 0x70 = 12 + end # Mouse + device pnp 2e.a off end # IR + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/google/panther/dsdt.asl b/src/mainboard/google/panther/dsdt.asl new file mode 100644 index 0000000000..87076fee08 --- /dev/null +++ b/src/mainboard/google/panther/dsdt.asl @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Mainboard devices + #include "acpi/mainboard.asl" + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include +} diff --git a/src/mainboard/google/panther/fadt.c b/src/mainboard/google/panther/fadt.c new file mode 100644 index 0000000000..7afbbfa698 --- /dev/null +++ b/src/mainboard/google/panther/fadt.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = get_pmbase(); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/panther/gpio.h b/src/mainboard/google/panther/gpio.h new file mode 100644 index 0000000000..9951984d5f --- /dev/null +++ b/src/mainboard/google/panther/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FALCO_GPIO_H +#define FALCO_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: LAN_WAKE_L_Q */ + LP_GPIO_OUT_HIGH, /* 9: PP3300_WLAN_EN */ + LP_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + LP_GPIO_UNUSED, /* 11: SMBALERT */ + LP_GPIO_INPUT_INVERT, /* 12: RECOVERY_L */ + LP_GPIO_UNUSED, /* 13: UNUSED */ + LP_GPIO_UNUSED, /* 14: UNUSED */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 16: UNUSED */ + LP_GPIO_OUT_HIGH, /* 17: PP3300_VP8_EN */ + LP_GPIO_UNUSED, /* 18: UNUSED */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_NATIVE, /* 20: NATIVE: CLK_PCIE_REQ2# */ + LP_GPIO_NATIVE, /* 21: NATIVE: CLK_PCIE_REQ3# */ + LP_GPIO_NATIVE, /* 22: NATIVE: CLK_PCIE_REQ4# */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_OUT_HIGH, /* 24: WLAN_OFF_L */ + LP_GPIO_UNUSED, /* 25: UNUSED */ + LP_GPIO_OUT_HIGH, /* 26: USB_CTL_1 */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_OUT_LOW, /* 28: USB_ILIM_SEL */ + LP_GPIO_UNUSED, /* 29: UNUSED */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSPWRACK_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: PCH_ACPRESENT */ + LP_GPIO_NATIVE, /* 32: NATIVE: CLKRUN# */ + LP_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + LP_GPIO_NATIVE, /* 41: NATIVE: USB_OC1# */ + LP_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + LP_GPIO_NATIVE, /* 43: NATIVE: USB_OC3# */ + LP_GPIO_UNUSED, /* 44: UNUSED */ + LP_GPIO_OUT_HIGH, /* 45: PP5000_CODEC_EN */ + LP_GPIO_OUT_HIGH, /* 46: BT_DISABLE_L */ + LP_GPIO_OUT_HIGH, /* 47: USB1_PWR_EN */ + LP_GPIO_UNUSED, /* 48: UNUSED */ + LP_GPIO_UNUSED, /* 49: UNUSED */ + LP_GPIO_OUT_HIGH, /* 50: VP8_DISABLE_L */ + LP_GPIO_UNUSED, /* 51: UNUSED */ + LP_GPIO_UNUSED, /* 52: UNUSED */ + LP_GPIO_UNUSED, /* 53: UNUSED */ + LP_GPIO_UNUSED, /* 54: UNUSED */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_OUT_HIGH, /* 56: USB2_PWR_EN */ + LP_GPIO_OUT_HIGH, /* 57: USB3_PWR_EN */ + LP_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + LP_GPIO_OUT_HIGH, /* 59: PP3300_LAN_EN */ + LP_GPIO_NATIVE, /* 60: NATIVE: SMB0ALERT# */ + LP_GPIO_UNUSED, /* 61: UNUSED */ + LP_GPIO_UNUSED, /* 62: UNUSED */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_UNUSED, /* 72: UNUSED */ + LP_GPIO_UNUSED, /* 73: UNUSED */ + LP_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + LP_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_UNUSED, /* 91: UNUSED */ + LP_GPIO_UNUSED, /* 92: UNUSED */ + LP_GPIO_UNUSED, /* 93: UNUSED */ + LP_GPIO_UNUSED, /* 94: UNUSED */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/panther/hda_verb.h b/src/mainboard/google/panther/hda_verb.h new file mode 100644 index 0000000000..cec56ebb26 --- /dev/null +++ b/src/mainboard/google/panther/hda_verb.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000c, // Number of jacks (NID entries) + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC */ + 0x01271cf0, + 0x01271d11, + 0x01271e11, + 0x01271f41, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471cf0, + 0x01471d11, + 0x01471e11, + 0x01471f40, + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/panther/lan.c b/src/mainboard/google/panther/lan.c new file mode 100644 index 0000000000..06178a75b8 --- /dev/null +++ b/src/mainboard/google/panther/lan.c @@ -0,0 +1,179 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "onboard.h" + +static unsigned int search(char *p, u8 *a, unsigned int lengthp, + unsigned int lengtha) +{ + int i, j; + + /* Searching */ + for (j = 0; j <= lengtha - lengthp; j++) { + for (i = 0; i < lengthp && p[i] == a[i + j]; i++) ; + if (i >= lengthp) + return j; + } + return lengtha; +} + +static unsigned char get_hex_digit(u8 *offset) +{ + unsigned char retval = 0; + + retval = *offset - '0'; + if (retval > 0x09) { + retval = *offset - 'A' + 0x0A; + if (retval > 0x0F) + retval = *offset - 'a' + 0x0a; + } + if (retval > 0x0F) { + printk(BIOS_DEBUG, "Error: Invalid Hex digit found: %c - 0x%02x\n", + *offset, *offset); + retval = 0; + } + + return retval; +} + +static int get_mac_address(u32 *high_dword, u32 *low_dword, + u8 *search_address, u32 search_length) +{ + char key[] = "ethernet_mac"; + unsigned int offset; + int i; + + offset = search(key, search_address, sizeof(key) - 1, search_length); + if (offset == search_length) { + printk(BIOS_DEBUG, + "Error: Could not locate '%s' in VPD\n", key); + return 0; + } + printk(BIOS_DEBUG, "Located '%s' in VPD\n", key); + + offset += sizeof(key); /* move to next character */ + *high_dword = 0; + + /* Fetch the MAC address and put the octets in the correct order to + * be programmed. + * + * From RTL8105E_Series_EEPROM-Less_App_Note_1.1 + * If the MAC address is 001122334455h: + * Write 33221100h to I/O register offset 0x00 via double word access + * Write 00005544h to I/O register offset 0x04 via double word access + */ + + for (i = 0; i < 4; i++) { + *high_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *high_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + *low_dword = 0; + for (i = 0; i < 2; i++) { + *low_dword |= (get_hex_digit(search_address + offset) + << (4 + (i * 8))); + *low_dword |= (get_hex_digit(search_address + offset + 1) + << (i * 8)); + offset += 3; + } + + return *high_dword | *low_dword; +} + +static void program_mac_address(u16 io_base) +{ + /* Default MAC Address of A0:00:BA:D0:0B:AD */ + u32 high_dword = 0xD0BA00A0; /* high dword of mac address */ + u32 low_dword = 0x0000AD0B; /* low word of mac address as a dword */ + + void *search_address = NULL; + int search_length = find_fmap_entry("RO_VPD", &search_address); + + if (search_length == -1) + printk(BIOS_ERR, "LAN: find_fmap_entry returned -1.\n"); + else + get_mac_address(&high_dword, &low_dword, search_address, + search_length); + + if (io_base) { + printk(BIOS_DEBUG, "Realtek NIC io_base = 0x%04x\n", io_base); + printk(BIOS_DEBUG, "Programming MAC Address\n"); + + /* Disable register protection */ + outb(0xc0, io_base + 0x50); + outl(high_dword, io_base); + outl(low_dword, io_base + 0x04); + outb(0x60, io_base + 54); + /* Enable register protection again */ + outb(0x00, io_base + 0x50); + } +} + +void lan_init(void) +{ + u16 io_base = 0; + struct device *ethernet_dev = NULL; + + /* Get NIC's IO base address */ + ethernet_dev = dev_find_device(PANTHER_NIC_VENDOR_ID, + PANTHER_NIC_DEVICE_ID, 0); + if (ethernet_dev != NULL) { + io_base = pci_read_config16(ethernet_dev, 0x10) & 0xfffe; + + /* + * Battery life time - LAN PCIe should enter ASPM L1 to save + * power when LAN connection is idle. + * enable CLKREQ: LAN pci config space 0x81h=01 + */ + pci_write_config8(ethernet_dev, 0x81, 0x01); + } + + if (io_base) { + /* Program MAC address based on VPD data */ + program_mac_address(io_base); + + /* + * Program NIC LEDS + * + * RTL8105E Series EEPROM-Less Application Note, + * Section 5.6 LED Mode Configuration + * + * Step1: Write C0h to I/O register 0x50 via byte access to + * disable 'register protection' + * Step2: Write xx001111b to I/O register 0x52 via byte access + * (bit7 is LEDS1 and bit6 is LEDS0) + * Step3: Write 0x00 to I/O register 0x50 via byte access to + * enable 'register protection' + */ + outb(0xc0, io_base + 0x50); /* Disable protection */ + outb((PANTHER_NIC_LED_MODE << 6) | 0x0f, io_base + 0x52); + outb(0x00, io_base + 0x50); /* Enable register protection */ + } +} diff --git a/src/mainboard/google/panther/mainboard.c b/src/mainboard/google/panther/mainboard.c new file mode 100644 index 0000000000..e3823c3416 --- /dev/null +++ b/src/mainboard/google/panther/mainboard.c @@ -0,0 +1,170 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include "onboard.h" +#include + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 * pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + lan_init(); +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/panther/onboard.h b/src/mainboard/google/panther/onboard.h new file mode 100644 index 0000000000..0b67017113 --- /dev/null +++ b/src/mainboard/google/panther/onboard.h @@ -0,0 +1,21 @@ +#ifndef __MAINBOARD_ONBOARD_H +#define __MAINBOARD_ONBOARD_H + +#ifndef __ACPI__ +void lan_init(void); +#endif + +/* defines for programming the MAC address */ +#define PANTHER_NIC_VENDOR_ID 0x10EC +#define PANTHER_NIC_DEVICE_ID 0x8168 + +/* 0x00: White LINK LED and Amber ACTIVE LED */ +#define PANTHER_NIC_LED_MODE 0x00 + +/* NIC wake is GPIO 8 */ +#define PANTHER_NIC_WAKE_GPIO 8 + +/* WLAN wake is GPIO 10 */ +#define PANTHER_WLAN_WAKE_GPIO 10 + +#endif diff --git a/src/mainboard/google/panther/romstage.c b/src/mainboard/google/panther/romstage.c new file mode 100644 index 0000000000..0f39b3b1fd --- /dev/null +++ b/src/mainboard/google/panther/romstage.c @@ -0,0 +1,150 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" +#include "superio/ite/it8772f/it8772f.h" +#include "superio/ite/it8772f/early_serial.c" + +const struct rcba_config_instruction rcba_config[] = { + + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), + RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), + RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), + RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ + + /* Disable unused devices (board specific) */ + RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), + + RCBA_END_CONFIG, +}; + +void mainboard_romstage_entry(unsigned long bist) +{ + struct pei_data pei_data = { + pei_version: PEI_VERSION, + mchbar: DEFAULT_MCHBAR, + dmibar: DEFAULT_DMIBAR, + epbar: DEFAULT_EPBAR, + pciexbar: DEFAULT_PCIEXBAR, + smbusbar: SMBUS_IO_BASE, + wdbbar: 0x4000000, + wdbsize: 0x1000, + hpet_address: HPET_ADDR, + rcba: DEFAULT_RCBA, + pmbase: DEFAULT_PMBASE, + gpiobase: DEFAULT_GPIOBASE, + temp_mmio_base: 0xfed08000, + system_type: 5, /* ULT */ + tseg_size: CONFIG_SMM_TSEG_SIZE, + spd_addresses: { 0xa0, 0x00, 0xa4, 0x00 }, + ec_present: 0, + // 0 = leave channel enabled + // 1 = disable dimm 0 on channel + // 2 = disable dimm 1 on channel + // 3 = disable dimm 0+1 on channel + dimm_channel0_disabled: 2, + dimm_channel1_disabled: 2, + // Enable 2x refresh mode + ddr_refresh_2x: 1, + dq_pins_interleaved: 1, + max_ddr3_freq: 1600, + usb_xhci_on_resume: 1, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0064, 1, 0, /* P0: VP8 */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 0, /* P1: Port A, CN22 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 1, /* P2: Port B, CN23 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: WLAN */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 2, /* P4: Port C, CN25 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, 2, /* P5: Port D, CN25 */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P6: Card Reader */ + USB_PORT_INTERNAL }, + { 0x0000, 0, 0, /* P7: N/C */ + USB_PORT_SKIP }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; CN22 */ + { 1, 1 }, /* P2; CN23 */ + { 1, 2 }, /* P3; CN25 */ + { 1, 2 }, /* P4; CN25 */ + }, + }; + + struct romstage_params romstage_params = { + .pei_data = &pei_data, + .gpio_map = &mainboard_gpio_map, + .rcba_config = &rcba_config[0], + .bist = bist, + }; + + /* Early SuperIO setup */ + it8772f_kill_watchdog(); + it8772f_ac_resume_southbridge(); + pch_enable_lpc(); + it8772f_enable_serial(PNP_DEV(IT8772F_BASE, IT8772F_SP1), + CONFIG_TTYS0_BASE); + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(&romstage_params); +} diff --git a/src/mainboard/google/panther/smihandler.c b/src/mainboard/google/panther/smihandler.c new file mode 100644 index 0000000000..2ad249848a --- /dev/null +++ b/src/mainboard/google/panther/smihandler.c @@ -0,0 +1,161 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* GPIO46 controls the WLAN_DISABLE_L signal. */ +#define GPIO_WLAN_DISABLE_L 46 +#define GPIO_LTE_DISABLE_L 59 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +#if 0 +static u8 mainboard_smi_ec(void) +{ + u8 cmd = 0;// google_chromeec_get_event(); + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + return cmd; +} +#endif + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ +#if 0 + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +#endif +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + //if (smm_get_gnvs()->s3u0 == 0) + // google_chromeec_set_usb_charge_mode( + // 0, USB_CHARGE_MODE_DISABLED); + //if (smm_get_gnvs()->s3u1 == 0) + // google_chromeec_set_usb_charge_mode( + // 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S3. */ + //set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + //set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + //google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + //if (smm_get_gnvs()->s5u0 == 0) + // google_chromeec_set_usb_charge_mode( + // 0, USB_CHARGE_MODE_DISABLED); + //if (smm_get_gnvs()->s5u1 == 0) + // google_chromeec_set_usb_charge_mode( + // 1, USB_CHARGE_MODE_DISABLED); + + /* Prevent leak from standby rail to WLAN rail in S5. */ + //set_gpio(GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + //set_gpio(GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + //google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + //google_chromeec_set_smi_mask(0); + //google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + //while (google_chromeec_get_event() != 0); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + //google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + //while (google_chromeec_get_event() != 0); + //google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + //google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + //while (google_chromeec_get_event() != 0); + //google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/panther/thermal.h b/src/mainboard/google/panther/thermal.h new file mode 100644 index 0000000000..7a9656143d --- /dev/null +++ b/src/mainboard/google/panther/thermal.h @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Fan is OFF */ +#define FAN4_THRESHOLD_OFF 0 +#define FAN4_THRESHOLD_ON 0 +#define FAN4_PWM 0x00 + +/* Fan is at LOW speed */ +#define FAN3_THRESHOLD_OFF 40 +#define FAN3_THRESHOLD_ON 50 +#define FAN3_PWM 0x5a + +/* Fan is at MEDIUM speed */ +#define FAN2_THRESHOLD_OFF 58 +#define FAN2_THRESHOLD_ON 67 +#define FAN2_PWM 0xa6 + +/* Fan is at HIGH speed */ +#define FAN1_THRESHOLD_OFF 67 +#define FAN1_THRESHOLD_ON 75 +#define FAN1_PWM 0xc0 + +/* Fan is at FULL speed */ +#define FAN0_THRESHOLD_OFF 85 +#define FAN0_THRESHOLD_ON 90 +#define FAN0_PWM 0xff + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 98 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 90 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/google/parrot/Kconfig b/src/mainboard/google/parrot/Kconfig index d400c8828b..2986cf73c3 100644 --- a/src/mainboard/google/parrot/Kconfig +++ b/src/mainboard/google/parrot/Kconfig @@ -2,7 +2,6 @@ if BOARD_GOOGLE_PARROT config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 @@ -16,6 +15,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_SMI_HANDLER select GFXUMA select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB select EARLY_CBMEM_INIT diff --git a/src/mainboard/google/parrot/chromeos.c b/src/mainboard/google/parrot/chromeos.c index 8a647dcfb5..54458692e4 100644 --- a/src/mainboard/google/parrot/chromeos.c +++ b/src/mainboard/google/parrot/chromeos.c @@ -28,8 +28,6 @@ #include #include "ec.h" -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 #ifndef __PRE_RAM__ #include diff --git a/src/mainboard/google/parrot/mainboard.c b/src/mainboard/google/parrot/mainboard.c index 38227235de..34cb24e87e 100644 --- a/src/mainboard/google/parrot/mainboard.c +++ b/src/mainboard/google/parrot/mainboard.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2011 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -49,15 +49,15 @@ void mainboard_suspend_resume(void) outb(0xe1, 0xb2); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - int res=-1; + int res = 0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); + __func__, X86_AX); - switch(regs->eax & 0xffff) { + switch(X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -66,11 +66,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x00; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CL = 0x00; /* Use video bios default */ + res = 1; break; case 0x5f35: /* @@ -84,11 +82,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; /* Use video bios default */ + res = 1; break; case 0x5f51: /* @@ -98,148 +94,46 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0003; /* eDP */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0003; /* eDP */ + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch (X86_CH) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + X86_CH); + break; } break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x00; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) - * bit 2 = EFP - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) - * bit 6 = EFP2 - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; /* Use video bios default */ - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 3; /* eDP */ - break; - case 0x5f70: - switch (M.x86.R_CH) { - case 0: - /* Get Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CL = 0; - break; - case 1: - /* Set Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - case 2: - /* Get SG/Non-SG mode */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - M.x86.R_CH); - return 0; - } - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 * cim_verb_data; @@ -262,49 +156,31 @@ static void mainboard_init(device_t dev) parrot_ec_init(); } -static int parrot_smbios_type41(int *handle, unsigned long *current, - const char *name, u8 irq, u8 addr) -{ - struct smbios_type41 *t = (struct smbios_type41 *)*current; - int len = sizeof(struct smbios_type41); - - memset(t, 0, sizeof(struct smbios_type41)); - t->type = SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION; - t->handle = *handle; - t->length = len - 2; - t->reference_designation = smbios_add_string(t->eos, name); - t->device_type = SMBIOS_DEVICE_TYPE_OTHER; - t->device_status = 1; - t->device_type_instance = irq; - t->segment_group_number = 0; - t->bus_number = addr; - t->function_number = 0; - t->device_number = 0; - - len = t->length + smbios_string_table_len(t->eos); - *current += len; - *handle += 1; - return len; -} - static int parrot_onboard_smbios_data(device_t dev, int *handle, unsigned long *current) { int len = 0; u8 hardware_version = parrot_rev(); if (hardware_version < 0x2) { /* DVT vs PVT */ - len += parrot_smbios_type41(handle, current, - PARROT_TRACKPAD_NAME, - PARROT_TRACKPAD_IRQ_DVT, - PARROT_TRACKPAD_I2C_ADDR); + len += smbios_write_type41( + current, handle, + PARROT_TRACKPAD_NAME, /* name */ + PARROT_TRACKPAD_IRQ_DVT, /* instance */ + 0, /* segment */ + PARROT_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ } else { - len += parrot_smbios_type41(handle, current, - PARROT_TRACKPAD_NAME, - PARROT_TRACKPAD_IRQ_PVT, - PARROT_TRACKPAD_I2C_ADDR); + len += smbios_write_type41( + current, handle, + PARROT_TRACKPAD_NAME, /* name */ + PARROT_TRACKPAD_IRQ_PVT, /* instance */ + 0, /* segment */ + PARROT_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ } - return len; } @@ -315,9 +191,9 @@ static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; dev->ops->get_smbios_data = parrot_onboard_smbios_data; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/google/parrot/romstage.c b/src/mainboard/google/parrot/romstage.c index 9968226f81..78758d5935 100644 --- a/src/mainboard/google/parrot/romstage.c +++ b/src/mainboard/google/parrot/romstage.c @@ -119,15 +119,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { pei_version: PEI_VERSION, mchbar: DEFAULT_MCHBAR, @@ -174,9 +172,7 @@ void main(unsigned long bist) }, }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -241,14 +237,13 @@ void main(unsigned long bist) post_code(0x3a); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3c); rcba_config(); @@ -288,15 +283,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/google/parrot/smihandler.c b/src/mainboard/google/parrot/smihandler.c index a5f6ba2e3d..72a3a1b61a 100644 --- a/src/mainboard/google/parrot/smihandler.c +++ b/src/mainboard/google/parrot/smihandler.c @@ -125,7 +125,7 @@ static u8 mainboard_smi_ec(void) return src; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { u32 pm1_cnt; diff --git a/src/mainboard/google/peach_pit/Kconfig b/src/mainboard/google/peach_pit/Kconfig new file mode 100644 index 0000000000..97beb67d35 --- /dev/null +++ b/src/mainboard/google/peach_pit/Kconfig @@ -0,0 +1,51 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_PEACH_PIT + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_SAMSUNG_EXYNOS5420 + select HAVE_UART_MEMORY_MAPPED + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select MAINBOARD_HAS_NATIVE_VGA_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + select DRIVER_PARADE_PS8625 + +config MAINBOARD_DIR + string + default google/peach_pit + +config MAINBOARD_PART_NUMBER + string + default "Peach Pit" + +config DRAM_SIZE_MB + int + default 2048 + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 2 + +endif # BOARD_GOOGLE_PEACH_PIT diff --git a/src/mainboard/google/peach_pit/Makefile.inc b/src/mainboard/google/peach_pit/Makefile.inc new file mode 100644 index 0000000000..95bf78d1b8 --- /dev/null +++ b/src/mainboard/google/peach_pit/Makefile.inc @@ -0,0 +1,31 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bootblock-y += wakeup.c + +romstage-y += memory.c +romstage-y += romstage.c +romstage-y += wakeup.c + +ramstage-y += mainboard.c +ramstage-y += chromeos.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/peach_pit/chromeos.c b/src/mainboard/google/peach_pit/chromeos.c new file mode 100644 index 0000000000..b8d82dfd2d --- /dev/null +++ b/src/mainboard/google/peach_pit/chromeos.c @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = EXYNOS5_GPX3; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get_value(GPIO_X30); // WP_GPIO + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = EXYNOS5_GPX3; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = gpio_get_value(GPIO_X34); // LID_GPIO + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: virtual GPIO active low */ + gpios->gpios[count].port = EXYNOS5_GPX1; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = + gpio_get_value(GPIO_X12); // POWER_GPIO + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get_value(GPIO_X07)) // RECMODE_GPIO + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get_value(GPIO_X30); +} diff --git a/src/mainboard/google/peach_pit/devicetree.cb b/src/mainboard/google/peach_pit/devicetree.cb new file mode 100644 index 0000000000..568daf86ef --- /dev/null +++ b/src/mainboard/google/peach_pit/devicetree.cb @@ -0,0 +1,33 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/samsung/exynos5420 + device cpu_cluster 0 on end + register "xres" = "1366" + register "yres" = "768" + register "framebuffer_bits_per_pixel" = "16" + # complex magic timing! + register "clkval_f" = "2" + register "upper_margin" = "14" + register "lower_margin" = "3" + register "vsync" = "5" + register "left_margin" = "80" + register "right_margin" = "48" + register "hsync" = "32" +end diff --git a/src/mainboard/google/peach_pit/mainboard.c b/src/mainboard/google/peach_pit/mainboard.c new file mode 100644 index 0000000000..7de939cc00 --- /dev/null +++ b/src/mainboard/google/peach_pit/mainboard.c @@ -0,0 +1,496 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* convenient shorthand (in MB) */ +#define DRAM_START ((uintptr_t)_dram/MiB) +#define DRAM_SIZE CONFIG_DRAM_SIZE_MB + +static struct edid edid = { + .ha = 1366, + .va = 768, + .framebuffer_bits_per_pixel = 16, + .x_resolution = 1366, + .y_resolution = 768, + .bytes_per_line = 2 * 1366 +}; + +/* from the fdt */ +static struct vidinfo vidinfo = { + .vl_freq = 60, + .vl_col = 1366, + .vl_row = 768, + .vl_width = 1366, + .vl_height = 768, + .vl_clkp = 1, + .vl_dp = 1, + .vl_bpix = 4, + .vl_hspw = 32, + .vl_hbpd = 40, + .vl_hfpd = 40, + .vl_vspw = 6, + .vl_vbpd = 10, + .vl_vfpd = 12, + .vl_cmd_allow_len = 0xf, + .win_id = 3, + .dp_enabled = 1, + .dual_lcd_enabled = 0, + .interface_mode = FIMD_RGB_INTERFACE, +}; + +static unsigned char panel_edid[] = { + 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x06,0xaf,0x5c,0x31,0x00,0x00,0x00,0x00, + 0x00,0x16,0x01,0x03,0x80,0x1a,0x0e,0x78, + 0x0a,0x99,0x85,0x95,0x55,0x56,0x92,0x28, + 0x22,0x50,0x54,0x00,0x00,0x00,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0xa3,0x1b, + 0x56,0x7e,0x50,0x00,0x16,0x30,0x30,0x20, + 0x36,0x00,0x00,0x90,0x10,0x00,0x00,0x18, + 0x6d,0x12,0x56,0x7e,0x50,0x00,0x16,0x30, + 0x30,0x20,0x36,0x00,0x00,0x90,0x10,0x00, + 0x00,0x18,0x00,0x00,0x00,0xfe,0x00,0x41, + 0x55,0x4f,0x0a,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xfe, + 0x00,0x42,0x31,0x31,0x36,0x58,0x57,0x30, + 0x33,0x20,0x56,0x31,0x20,0x0a,0x00,0x3d, + 0x00,0xc0,0x00,0x00,0x27,0xfd,0x00,0x20, + 0x02,0x59,0x07,0x00,0x64,0x3e,0x07,0x02, + 0x00,0x00,0xcd,0x12,0x59,0xff,0x10,0x03, + 0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00, + 0x9c,0x3f,0x07,0x02,0x31,0xf9,0x00,0x20, + 0x59,0xff,0x10,0x03,0x00,0x00,0x00,0x00, + 0xbc,0x3e,0x07,0x02,0xc0,0x9b,0x01,0x20, + 0x00,0x00,0x00,0x00,0xdb,0xf8,0x00,0x20, + 0x98,0x3e,0x07,0x02,0x8b,0xaf,0x00,0x20, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe5,0xcd,0x16,0x00,0xe9,0xcd,0x16,0x00, + 0xe8,0x03,0x00,0x00,0x6c,0x55,0x01,0x20, + 0x2c,0x01,0x00,0x00,0x85,0xbb,0x00,0x20, + 0xe8,0x03,0x00,0x00,0xe9,0xcd,0x16,0x00, +}; + +static const struct parade_write parade_writes[] = { + { 0x02, 0xa1, 0x01 }, /* HPD low */ + /* + * SW setting + * [1:0] SW output 1.2V voltage is lower to 96% + */ + { 0x04, 0x14, 0x01 }, + /* + * RCO SS setting + * [5:4] = b01 0.5%, b10 1%, b11 1.5% + */ + { 0x04, 0xe3, 0x20 }, + { 0x04, 0xe2, 0x80 }, /* [7] RCO SS enable */ + /* + * RPHY Setting + * [3:2] CDR tune wait cycle before + * measure for fine tune b00: 1us, + * 01: 0.5us, 10:2us, 11:4us. + */ + { 0x04, 0x8a, 0x0c }, + { 0x04, 0x89, 0x08 }, /* [3] RFD always on */ + /* + * CTN lock in/out: + * 20000ppm/80000ppm. Lock out 2 + * times. + */ + { 0x04, 0x71, 0x2d }, + /* + * 2.7G CDR settings + * NOF=40LSB for HBR CDR setting + */ + { 0x04, 0x7d, 0x07 }, + { 0x04, 0x7b, 0x00 }, /* [1:0] Fmin=+4bands */ + { 0x04, 0x7a, 0xfd }, /* [7:5] DCO_FTRNG=+-40% */ + /* + * 1.62G CDR settings + * [5:2]NOF=64LSB [1:0]DCO scale is 2/5 + */ + { 0x04, 0xc0, 0x12 }, + { 0x04, 0xc1, 0x92 }, /* Gitune=-37% */ + { 0x04, 0xc2, 0x1c }, /* Fbstep=100% */ + { 0x04, 0x32, 0x80 }, /* [7] LOS signal disable */ + /* + * RPIO Setting + * [7:4] LVDS driver bias current : + * 75% (250mV swing) + */ + { 0x04, 0x00, 0xb0 }, + /* + * [7:6] Right-bar GPIO output strength is 8mA + */ + { 0x04, 0x15, 0x40 }, + /* EQ Training State Machine Setting */ + { 0x04, 0x54, 0x10 }, /* RCO calibration start */ + /* [4:0] MAX_LANE_COUNT set to one lane */ + { 0x01, 0x02, 0x81 }, + /* [4:0] LANE_COUNT_SET set to one lane */ + { 0x01, 0x21, 0x81 }, + { 0x00, 0x52, 0x20 }, + { 0x00, 0xf1, 0x03 }, /* HPD CP toggle enable */ + { 0x00, 0x62, 0x41 }, + /* Counter number, add 1ms counter delay */ + { 0x00, 0xf6, 0x01 }, + /* + * [6]PWM function control by + * DPCD0040f[7], default is PWM + * block always works. + */ + { 0x00, 0x77, 0x06 }, + /* + * 04h Adjust VTotal tolerance to + * fix the 30Hz no display issue + */ + { 0x00, 0x4c, 0x04 }, + /* DPCD00400='h00, Parade OUI = 'h001cf8 */ + { 0x01, 0xc0, 0x00 }, + { 0x01, 0xc1, 0x1c }, /* DPCD00401='h1c */ + { 0x01, 0xc2, 0xf8 }, /* DPCD00402='hf8 */ + /* + * DPCD403~408 = ASCII code + * D2SLV5='h4432534c5635 + */ + { 0x01, 0xc3, 0x44 }, + { 0x01, 0xc4, 0x32 }, /* DPCD404 */ + { 0x01, 0xc5, 0x53 }, /* DPCD405 */ + { 0x01, 0xc6, 0x4c }, /* DPCD406 */ + { 0x01, 0xc7, 0x56 }, /* DPCD407 */ + { 0x01, 0xc8, 0x35 }, /* DPCD408 */ + /* + * DPCD40A, Initial Code major revision + * '01' + */ + { 0x01, 0xca, 0x01 }, + /* DPCD40B, Initial Code minor revision '05' */ + { 0x01, 0xcb, 0x05 }, + /* DPCD720, Select external PWM */ + { 0x01, 0xa5, 0x80 }, + /* + * Set LVDS output as 6bit-VESA mapping, + * single LVDS channel + */ + { 0x01, 0xcc, 0x13 }, + /* Enable SSC set by register */ + { 0x02, 0xb1, 0x20 }, + /* + * Set SSC enabled and +/-1% central + * spreading + */ + { 0x04, 0x10, 0x16 }, + /* MPU Clock source: LC => RCO */ + { 0x04, 0x59, 0x60 }, + { 0x04, 0x54, 0x14 }, /* LC -> RCO */ + { 0x02, 0xa1, 0x91 } /* HPD high */ +}; + +/* TODO: transplanted DP stuff, clean up once we have something that works */ +static enum exynos5_gpio_pin dp_pd_l = GPIO_X35; /* active low */ +static enum exynos5_gpio_pin dp_rst_l = GPIO_Y77; /* active low */ +static enum exynos5_gpio_pin dp_hpd = GPIO_X26; /* active high */ +static enum exynos5_gpio_pin bl_pwm = GPIO_B20; /* active high */ +static enum exynos5_gpio_pin bl_en = GPIO_X22; /* active high */ + +static void parade_dp_bridge_setup(void) +{ + int i; + + gpio_set_value(dp_pd_l, 1); + gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT); + gpio_set_pull(dp_pd_l, GPIO_PULL_NONE); + + gpio_set_value(dp_rst_l, 0); + gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT); + gpio_set_pull(dp_rst_l, GPIO_PULL_NONE); + udelay(10); + gpio_set_value(dp_rst_l, 1); + + + gpio_set_pull(dp_hpd, GPIO_PULL_NONE); + gpio_cfg_pin(dp_hpd, GPIO_INPUT); + + /* De-assert PD (and possibly RST) to power up the bridge. */ + gpio_set_value(dp_pd_l, 1); + gpio_set_value(dp_rst_l, 1); + + /* Hang around for the bridge to come up. */ + mdelay(40); + + /* Configure the bridge chip. */ + exynos_pinmux_i2c7(); + i2c_init(7, 100000, 0x00); + + parade_ps8625_bridge_setup(7, 0x48, parade_writes, + ARRAY_SIZE(parade_writes)); + /* Spin until the display is ready. + * It's quite important to try really hard to get the display up, + * so be generous. It will typically be ready in only 5 ms. and + * we're out of here. + * If it's not ready after a second, then we're in big trouble. + */ + for(i = 0; i < 1000; i++){ + if (gpio_get_value(dp_hpd)) + break; + mdelay(1); + } +} + +/* + * This delay is T3 in the LCD timing spec (defined as >200ms). We set + * this down to 60ms since that's the approximate maximum amount of time + * it'll take a bridge to start outputting LVDS data. The delay of + * >200ms is just a conservative value to avoid turning on the backlight + * when there's random LCD data on the screen. Shaving 140ms off the + * boot is an acceptable trade-off. + */ +#define LCD_T3_DELAY_MS 60 + +#define LCD_T5_DELAY_MS 10 +#define LCD_T6_DELAY_MS 10 + +static void backlight_pwm(void) +{ + /*Configure backlight PWM as a simple output high (100% brightness) */ + gpio_direction_output(bl_pwm, 1); + udelay(LCD_T6_DELAY_MS * 1000); +} + +static void backlight_en(void) +{ + /* Configure GPIO for LCD_BL_EN */ + gpio_direction_output(bl_en, 1); +} + +static enum exynos5_gpio_pin usb_drd0_vbus = GPIO_H00; +static enum exynos5_gpio_pin usb_drd1_vbus = GPIO_H01; +/* static enum exynos5_gpio_pin hsic_reset_l = GPIO_X24; */ + +static void prepare_usb(void) +{ + /* Kick these resets off early so they get at least 100ms to settle */ + reset_usb_drd0_dwc3(); + reset_usb_drd1_dwc3(); +} + +static void setup_usb(void) +{ + /* HSIC and USB HOST port not needed in firmware on this board */ + setup_usb_drd0_phy(); + setup_usb_drd1_phy(); + + setup_usb_drd0_dwc3(); + setup_usb_drd1_dwc3(); + + gpio_direction_output(usb_drd0_vbus, 1); + gpio_direction_output(usb_drd1_vbus, 1); +} + +static struct edp_video_info dp_video_info = { + .master_mode = 0, + .h_sync_polarity = 0, + .v_sync_polarity = 0, + .interlaced = 0, + .color_space = COLOR_RGB, + .dynamic_range = VESA, + .ycbcr_coeff = COLOR_YCBCR601, + .color_depth = COLOR_8, +}; + +/* FIXME: move some place more appropriate */ +#define MAX_DP_TRIES 5 + +static void setup_storage(void) +{ + /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ + if (clock_set_dwmci(PERIPH_ID_SDMMC0)) + printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__); + exynos_pinmux_sdmmc0(); + + /* MMC2: Removable, 4 bit mode, no GPIO. */ + /* (Must be after romstage to avoid breaking SDMMC boot.) */ + clock_set_dwmci(PERIPH_ID_SDMMC2); + exynos_pinmux_sdmmc2(); +} + +static void gpio_init(void) +{ + /* Set up the I2C busses. */ + exynos_pinmux_i2c2(); + exynos_pinmux_i2c4(); + exynos_pinmux_i2c7(); + exynos_pinmux_i2c8(); + exynos_pinmux_i2c9(); + exynos_pinmux_i2c10(); +} + +enum { + FET_CTRL_WAIT = 3 << 2, + FET_CTRL_ADENFET = 1 << 1, + FET_CTRL_ENFET = 1 << 0 +}; + +static void tps65090_thru_ec_fet_set(int index) +{ + uint8_t value = FET_CTRL_ADENFET | FET_CTRL_WAIT | FET_CTRL_ENFET; + + if (google_chromeec_i2c_xfer(0x48, 0xe + index, 1, &value, 1, 0)) { + printk(BIOS_ERR, + "Error sending i2c pass through command to EC.\n"); + return; + } +} + +static void lcd_vdd(void) +{ + /* Enable FET6, lcd panel */ + tps65090_thru_ec_fet_set(6); +} + +static void backlight_vdd(void) +{ + /* Enable FET1, backlight */ + tps65090_thru_ec_fet_set(1); +} + +static void sdmmc_vdd(void) +{ + /* Enable FET4, P3.3V_SDCARD */ + tps65090_thru_ec_fet_set(4); +} + +/* this happens after cpu_init where exynos resources are set */ +static void mainboard_init(device_t dev) +{ + /* we'll stick with the crummy u-boot struct for now.*/ + /* doing this as an auto since the struct has to be writeable */ + struct edp_device_info device_info; + + void *fb_addr = (void *)(get_fb_base_kb() * KiB); + + prepare_usb(); + gpio_init(); + setup_storage(); + tmu_init(&exynos5420_tmu_info); + + /* Clock Gating all the unused IP's to save power */ + clock_gate(); + + sdmmc_vdd(); + + set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr); + + /* + * The reset value for FIMD SYSMMU register MMU_CTRL:0x14640000 + * should be 0 according to the datasheet, but has experimentally + * been found to come up as 3. This means FIMD SYSMMU is on by + * default on Exynos5420. For now we are disabling FIMD SYSMMU. + */ + writel(0x0, (void *)0x14640000); + writel(0x0, (void *)0x14680000); + + lcd_vdd(); + + /* Start the fimd running before you do the phy and lcd setup. + * why do fimd before training etc? + * because we need a data stream from + * the fimd or the clock recovery step fails. + */ + vidinfo.screen_base = fb_addr; + exynos_fimd_lcd_init(&vidinfo); + + parade_dp_bridge_setup(); + + /* this might get more dynamic in future ... */ + memset(&device_info, 0, sizeof(device_info)); + device_info.disp_info.name = (char *)"Peach Pit display"; + device_info.disp_info.h_total = 1366; + device_info.disp_info.v_total = 768; + device_info.video_info = dp_video_info; + device_info.raw_edid = panel_edid; + exynos_init_dp(&device_info); + + backlight_vdd(); + backlight_pwm(); + backlight_en(); + + setup_usb(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; + + /* set up caching for the DRAM */ + mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + const unsigned epll_hz = 192000000; + const unsigned sample_rate = 48000; + const unsigned lr_frame_size = 256; + clock_epll_set_rate(epll_hz); + clock_select_i2s_clk_source(); + clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size); + + power_enable_xclkout(); +} + +struct chip_operations mainboard_ops = { + .name = "Samsung/Google ARM Chromebook", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} diff --git a/src/mainboard/google/peach_pit/memlayout.ld b/src/mainboard/google/peach_pit/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/peach_pit/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/peach_pit/memory.c b/src/mainboard/google/peach_pit/memory.c new file mode 100644 index 0000000000..6db329626c --- /dev/null +++ b/src/mainboard/google/peach_pit/memory.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +const struct mem_timings mem_timings = { + .mem_manuf = MEM_MANUF_SAMSUNG, + .mem_type = DDR_MODE_DDR3, + .frequency_mhz = 800, + .direct_cmd_msr = { + 0x00020018, 0x00030000, 0x00010046, 0x00000d70, + 0x00000c70 + }, + .timing_ref = 0x000000bb, + .timing_row = 0x6836650f, + .timing_data = 0x3630580b, + .timing_power = 0x41000a26, + .phy0_dqs = 0x08080808, + .phy1_dqs = 0x08080808, + .phy0_dq = 0x08080808, + .phy1_dq = 0x08080808, + .phy0_tFS = 0x8, + .phy1_tFS = 0x8, + .phy0_pulld_dqs = 0xf, + .phy1_pulld_dqs = 0xf, + + .lpddr3_ctrl_phy_reset = 0x1, + .ctrl_start_point = 0x10, + .ctrl_inc = 0x10, + .ctrl_start = 0x1, + .ctrl_dll_on = 0x1, + .ctrl_ref = 0x8, + + .ctrl_force = 0x1a, + .ctrl_rdlat = 0x0b, + .ctrl_bstlen = 0x08, + + .fp_resync = 0x8, + .iv_size = 0x7, + .dfi_init_start = 1, + .aref_en = 1, + + .rd_fetch = 0x3, + + .zq_mode_dds = 0x7, + .zq_mode_term = 0x1, + .zq_mode_noterm = 1, + + /* + * Dynamic Clock: Always Running + * Memory Burst length: 8 + * Number of chips: 1 + * Memory Bus width: 32 bit + * Memory Type: DDR3 + * Additional Latancy for PLL: 0 Cycle + */ + .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE | + DMC_MEMCONTROL_DPWRDN_DISABLE | + DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE | + DMC_MEMCONTROL_DSREF_DISABLE | + DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) | + DMC_MEMCONTROL_MEM_TYPE_DDR3 | + DMC_MEMCONTROL_MEM_WIDTH_32BIT | + DMC_MEMCONTROL_NUM_CHIP_1 | + DMC_MEMCONTROL_BL_8 | + DMC_MEMCONTROL_PZQ_DISABLE | + DMC_MEMCONTROL_MRR_BYTE_7_0, + /* + * For channel interleaving, the chip_base needs to be set to + * half the bus address. So for a base address of 0x2000_0000, + * the chip_base value is 0x20 without interleaving and 0x10 + * with channel interleaving. See note in section 17.14. + */ + .membaseconfig0 = (0x10 << 16) | DMC_CHIP_MASK_1GB, + .memconfig = DMC_MEMCONFIG_CHIP_MAP_SPLIT | + DMC_MEMCONFIGx_CHIP_COL_10 | + DMC_MEMCONFIGx_CHIP_ROW_15 | + DMC_MEMCONFIGx_CHIP_BANK_8, + .prechconfig_tp_cnt = 0xff, + .dpwrdn_cyc = 0xff, + .dsref_cyc = 0xffff, + .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE | + DMC_CONCONTROL_TIMEOUT_LEVEL0 | + DMC_CONCONTROL_RD_FETCH_DISABLE | + DMC_CONCONTROL_AREF_EN_DISABLE | + DMC_CONCONTROL_IO_PD_CON_DISABLE, + .dmc_channels = 1, + .chips_per_channel = 1, + .chips_to_configure = 1, + .send_zq_init = 1, + .gate_leveling_enable = 1, +}; diff --git a/src/mainboard/google/peach_pit/romstage.c b/src/mainboard/google/peach_pit/romstage.c new file mode 100644 index 0000000000..d997e34d74 --- /dev/null +++ b/src/mainboard/google/peach_pit/romstage.c @@ -0,0 +1,292 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMIC_I2C_BUS 4 + +struct pmic_write +{ + int or_orig; // Whether to or in the original value. + uint8_t reg; // Register to write. + uint8_t val; // Value to write. +}; + +/* + * Use read-modify-write for MAX77802 control registers and clobber the + * output voltage setting (BUCK?DVS?) registers. + */ +struct pmic_write pmic_writes[] = +{ + { 1, MAX77802_REG_PMIC_32KHZ, MAX77802_32KHCP_EN }, + { 0, MAX77802_REG_PMIC_BUCK1DVS1, MAX77802_BUCK1DVS1_1V }, + { 1, MAX77802_REG_PMIC_BUCK1CTRL, MAX77802_BUCK_TYPE1_ON | + MAX77802_BUCK_TYPE1_IGNORE_PWRREQ }, + { 0, MAX77802_REG_PMIC_BUCK2DVS1, MAX77802_BUCK2DVS1_1_2625V }, + { 1, MAX77802_REG_PMIC_BUCK2CTRL1, MAX77802_BUCK_TYPE2_ON | + MAX77802_BUCK_TYPE2_IGNORE_PWRREQ }, + { 0, MAX77802_REG_PMIC_BUCK3DVS1, MAX77802_BUCK3DVS1_1V }, + { 1, MAX77802_REG_PMIC_BUCK3CTRL1, MAX77802_BUCK_TYPE2_ON | + MAX77802_BUCK_TYPE2_IGNORE_PWRREQ }, + { 0, MAX77802_REG_PMIC_BUCK4DVS1, MAX77802_BUCK4DVS1_1V }, + { 1, MAX77802_REG_PMIC_BUCK4CTRL1, MAX77802_BUCK_TYPE2_ON | + MAX77802_BUCK_TYPE2_IGNORE_PWRREQ }, + { 0, MAX77802_REG_PMIC_BUCK6DVS1, MAX77802_BUCK6DVS1_1V }, + { 1, MAX77802_REG_PMIC_BUCK6CTRL, MAX77802_BUCK_TYPE1_ON | + MAX77802_BUCK_TYPE1_IGNORE_PWRREQ }, + /* Disable Boost(bypass) OUTPUT */ + { 0, MAX77802_REG_PMIC_BOOSTCTRL, MAX77802_BOOSTCTRL_OFF}, +}; + +static int setup_power(int is_resume) +{ + int error = 0; + int i; + + power_init(); + + if (is_resume) { + return 0; + } + + /* Initialize I2C bus to configure PMIC. */ + exynos_pinmux_i2c4(); + i2c_init(PMIC_I2C_BUS, 1000000, 0x00); /* 1MHz */ + + for (i = 0; i < ARRAY_SIZE(pmic_writes); i++) { + uint8_t data = 0; + uint8_t reg = pmic_writes[i].reg; + + if (pmic_writes[i].or_orig) + error |= i2c_readb(4, MAX77802_I2C_ADDR, reg, &data); + + data |= pmic_writes[i].val; + error |= i2c_writeb(4, MAX77802_I2C_ADDR, reg, data); + } + + return error; +} + +static void setup_ec(void) +{ + /* SPI2 (EC) is slower and needs to work in half-duplex mode with + * single byte bus width. */ + clock_set_rate(PERIPH_ID_SPI2, 5000000); + exynos_pinmux_spi2(); +} + +static void setup_gpio(void) +{ + gpio_direction_input(GPIO_X30); // WP_GPIO + gpio_set_pull(GPIO_X30, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X07); // RECMODE_GPIO + gpio_set_pull(GPIO_X07, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X34); // LID_GPIO + gpio_set_pull(GPIO_X34, GPIO_PULL_NONE); + + gpio_direction_input(GPIO_X12); // POWER_GPIO + gpio_set_pull(GPIO_X12, GPIO_PULL_NONE); +} + +static void setup_memory(struct mem_timings *mem, int is_resume) +{ + printk(BIOS_SPEW, "manufacturer: 0x%x type: 0x%x, div: 0x%x, mhz: %d\n", + mem->mem_manuf, + mem->mem_type, + mem->mpll_mdiv, + mem->frequency_mhz); + + if (ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE, !is_resume)) { + die("Failed to initialize memory controller.\n"); + } +} + +#define PRIMITIVE_MEM_TEST 0 +#if PRIMITIVE_MEM_TEST +static unsigned long primitive_mem_test(void) +{ + unsigned long *l = (void *)0x40000000; + int bad = 0; + unsigned long i; + for(i = 0; i < 256*1048576; i++){ + if (! (i%1048576)) + printk(BIOS_SPEW, "%lu ...", i); + l[i] = 0xffffffff - i; + } + + for(i = 0; i < 256*1048576; i++){ + if (! (i%1048576)) + printk(BIOS_SPEW, "%lu ...", i); + if (l[i] != (0xffffffff - i)){ + printk(BIOS_SPEW, "%p: want %08lx got %08lx\n", l, l[i], 0xffffffff - i); + bad++; + } + } + + printk(BIOS_SPEW, "%d errors\n", bad); + + return bad; +} +#else +#define primitive_mem_test() +#endif + +#define SIMPLE_SPI_TEST 0 +#if SIMPLE_SPI_TEST +/* here is a simple SPI debug test, known to fid trouble */ +static void simple_spi_test(void) +{ + struct cbfs_media default_media, *media; + int i, amt = 4 * MiB, errors = 0; + //u32 *data = (void *)0x40000000; + u32 data[1024]; + u32 in; + + amt = sizeof(data); + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + printk(BIOS_SPEW, "Failed to initialize default media.\n"); + return; + } + + + media->open(media); + if (media->read(media, data, (size_t) 0, amt) < amt){ + printk(BIOS_SPEW, "simple_spi_test fails\n"); + return; + } + + + for(i = 0; i < amt; i += 4){ + if (media->read(media, &in, (size_t) i, 4) < 1){ + printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i); + return; + } + if (data[i/4] != in){ + errors++; + printk(BIOS_SPEW, "BAD at %d(%p):\nRAM %08lx\nSPI %08lx\n", + i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in); + /* reread it to see which is wrong. */ + if (media->read(media, &in, (size_t) i, 4) < 1){ + printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i); + return; + } + printk(BIOS_SPEW, "RTRY at %d(%p):\nRAM %08lx\nSPI %08lx\n", + i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in); + } + + } + printk(BIOS_SPEW, "%d errors\n", errors); +} +#else +#define simple_spi_test() +#endif + +void main(void) +{ + + extern struct mem_timings mem_timings; + void *entry; + int is_resume = (get_wakeup_state() != IS_NOT_WAKEUP); + int power_init_failed; + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = timestamp_get(); + + start_romstage_time = timestamp_get(); + + exynos5420_config_smp(); + power_init_failed = setup_power(is_resume); + + /* Clock must be initialized before console_init, otherwise you may need + * to re-initialize serial console drivers again. */ + system_clock_init(); + + exynos_pinmux_uart3(); + console_init(); + exception_init(); + + if (power_init_failed) + die("Failed to intialize power.\n"); + + /* re-initialize PMIC I2C channel after (re-)setting system clocks */ + i2c_init(PMIC_I2C_BUS, 1000000, 0x00); /* 1MHz */ + + before_dram_time = timestamp_get(); + + setup_memory(&mem_timings, is_resume); + + after_dram_time = timestamp_get(); + + primitive_mem_test(); + + trustzone_init(); + + if (is_resume) { + wakeup(); + } + + setup_gpio(); + setup_ec(); + + simple_spi_test(); + /* Set SPI (primary CBFS media) clock to 50MHz. */ + /* if this is uncommented SPI will not work correctly. */ + clock_set_rate(PERIPH_ID_SPI1, 50000000); + exynos_pinmux_spi1(); + simple_spi_test(); + + cbmem_initialize_empty(); + + timestamp_init(base_time); + timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); + timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); + timestamp_add(TS_AFTER_INITRAM, after_dram_time ); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); + simple_spi_test(); + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/include/pc80/tpm.h b/src/mainboard/google/peach_pit/wakeup.c similarity index 72% rename from src/include/pc80/tpm.h rename to src/mainboard/google/peach_pit/wakeup.c index 2eff15a09a..8a9f3e2da3 100644 --- a/src/include/pc80/tpm.h +++ b/src/mainboard/google/peach_pit/wakeup.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * Copyright 2013 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,13 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef TPM_H_ -#define TPM_H_ +#include +#include -int tis_init(void); -int tis_open(void); -int tis_close(void); -int tis_sendrecv(const u8 *sendbuf, size_t send_size, u8 *recvbuf, - size_t *recv_len); +int wakeup_need_reset(void) +{ + /* The "wake up" event is not reliable (known as "bad wakeup") and needs + * reset if the TPM reset mask GPIO value is high. */ + return gpio_get_value(GPIO_X06); +} -#endif /* TPM_H_ */ diff --git a/src/mainboard/google/peppy/Elpida_EDJ4216EFBG.spd.hex b/src/mainboard/google/peppy/Elpida_EDJ4216EFBG.spd.hex new file mode 100644 index 0000000000..eb41f0bfb1 --- /dev/null +++ b/src/mainboard/google/peppy/Elpida_EDJ4216EFBG.spd.hex @@ -0,0 +1,17 @@ +# Elpida EDJ4216EFBG-GN-F +92 12 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 81 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 A1 CE +45 44 4A 34 32 31 36 45 46 42 47 2D 47 4E 2D 46 +00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/peppy/Hynix_HMT425S6AFR6A.spd.hex b/src/mainboard/google/peppy/Hynix_HMT425S6AFR6A.spd.hex new file mode 100644 index 0000000000..7b0932743d --- /dev/null +++ b/src/mainboard/google/peppy/Hynix_HMT425S6AFR6A.spd.hex @@ -0,0 +1,17 @@ +# Hynix HMT425S6AFR6A-PBA +92 12 0B 03 04 19 02 02 03 52 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 01 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 62 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 01 00 00 00 00 00 00 FF AB +48 4D 54 34 32 35 53 36 41 46 52 36 41 2D 50 42 +20 20 4E 30 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/peppy/Kconfig b/src/mainboard/google/peppy/Kconfig new file mode 100644 index 0000000000..676e7945ca --- /dev/null +++ b/src/mainboard/google/peppy/Kconfig @@ -0,0 +1,57 @@ +if BOARD_GOOGLE_PEPPY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_HASWELL + select SOUTHBRIDGE_INTEL_LYNXPOINT + select INTEL_LYNXPOINT_LP + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select MAINBOARD_HAS_NATIVE_VGA_INIT + select MAINBOARD_DO_NATIVE_VGA_INIT + select INTEL_DP + select INTEL_DDI + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config MAINBOARD_DIR + string + default google/peppy + +config MAINBOARD_PART_NUMBER + string + default "Peppy" + +config MMCONF_BASE_ADDRESS + hex + default 0xf0000000 + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/peppy/Makefile.inc b/src/mainboard/google/peppy/Makefile.inc new file mode 100644 index 0000000000..5a6ba97a14 --- /dev/null +++ b/src/mainboard/google/peppy/Makefile.inc @@ -0,0 +1,53 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += gma.c i915io.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +## DIMM SPD for on-board memory +SPD_BIN = $(obj)/spd.bin + +# Order of names in SPD_SOURCES is important! +SPD_SOURCES = Micron_4KTF25664HZ # 0: 4GB / CH0 + CH1 +SPD_SOURCES += Hynix_HMT425S6AFR6A # 1: 4GB / CH0 + CH1 +SPD_SOURCES += Elpida_EDJ4216EFBG # 2: 4GB / CH0 + CH1 +SPD_SOURCES += Micron_4KTF25664HZ # 3: Reserved / place holder +SPD_SOURCES += Micron_4KTF25664HZ # 4: 2GB / CH0 + CH1 +SPD_SOURCES += Hynix_HMT425S6AFR6A # 5: 2GB / CH0 + CH1 +SPD_SOURCES += Elpida_EDJ4216EFBG # 6: 2GB / CH0 + CH1 + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab +spd.bin-position := 0xfffec000 diff --git a/src/mainboard/google/peppy/Micron_4KTF25664HZ.spd.hex b/src/mainboard/google/peppy/Micron_4KTF25664HZ.spd.hex new file mode 100644 index 0000000000..cbe9e4fbfe --- /dev/null +++ b/src/mainboard/google/peppy/Micron_4KTF25664HZ.spd.hex @@ -0,0 +1,17 @@ +# Micron 4KTF25664HZ-1G6E1 +92 11 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2C 00 00 00 00 00 00 00 AD 75 +34 4B 54 46 32 35 36 36 34 48 5A 2D 31 47 36 45 +31 20 45 31 80 2C 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/peppy/acpi/chromeos.asl b/src/mainboard/google/peppy/acpi/chromeos.asl new file mode 100644 index 0000000000..4e9035be3b --- /dev/null +++ b/src/mainboard/google/peppy/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "LynxPoint" }, // no recovery button + Package () { 0x0003, 1, 58, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/peppy/acpi/ec.asl b/src/mainboard/google/peppy/acpi/ec.asl new file mode 100644 index 0000000000..56ebddc97f --- /dev/null +++ b/src/mainboard/google/peppy/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/google/peppy/acpi/haswell_pci_irqs.asl b/src/mainboard/google/peppy/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/peppy/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/peppy/acpi/mainboard.asl b/src/mainboard/google/peppy/acpi/mainboard.asl new file mode 100644 index 0000000000..194b76e6d8 --- /dev/null +++ b/src/mainboard/google/peppy/acpi/mainboard.asl @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name(_HID, EisaId("PNP0C0D")) + Method(_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } + + Device (TPAD) + { + Name (_ADR, 0x0) + Name (_UID, 1) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + + VendorShort (ADDR) + { + BOARD_TRACKPAD_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } + + Device (TSCR) + { + Name (_ADR, 0x0) + Name (_UID, 2) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + + VendorShort (ADDR) + { + BOARD_TOUCHSCREEN_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TOUCHSCREEN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/peppy/acpi/platform.asl b/src/mainboard/google/peppy/acpi/platform.asl new file mode 100644 index 0000000000..208d76a0e9 --- /dev/null +++ b/src/mainboard/google/peppy/acpi/platform.asl @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + /* Update AC status */ + Store (\_SB.PCI0.LPCB.EC0.ACEX, Local0) + if (LNotEqual (Local0, \PWRS)) { + Store (Local0, \PWRS) + Notify (\_SB.PCI0.LPCB.EC0.AC, 0x80) + } + + /* Update LID status */ + Store (\_SB.PCI0.LPCB.EC0.LIDS, Local0) + if (LNotEqual (Local0, \LIDS)) { + Store (Local0, \LIDS) + Notify (\_SB.LID0, 0x80) + } + + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/peppy/acpi/superio.asl b/src/mainboard/google/peppy/acpi/superio.asl new file mode 100644 index 0000000000..c652f4fdc7 --- /dev/null +++ b/src/mainboard/google/peppy/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/peppy/acpi/thermal.asl b/src/mainboard/google/peppy/acpi/thermal.asl new file mode 100644 index 0000000000..67f83ef142 --- /dev/null +++ b/src/mainboard/google/peppy/acpi/thermal.asl @@ -0,0 +1,179 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (_TMP, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + /* CTDP Down */ + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (\F0OF)) + } Else { + Return (CTOK (\F0ON)) + } + } + + /* CTDP Nominal */ + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (\F1OF)) + } Else { + Return (CTOK (\F1ON)) + } + } + + Name (_AL0, Package () { TDP0 }) + Name (_AL1, Package () { TDP1 }) + + PowerResource (TNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + + /* Enable Power Limit */ + \_SB.PCI0.MCHC.CTLE (\F0PW) + + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + + /* Disable Power Limit */ + \_SB.PCI0.MCHC.CTLD () + + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (TNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (TDP0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { TNP0 }) + } + + Device (TDP1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { TNP1 }) + } + } +} + diff --git a/src/mainboard/google/peppy/acpi/video.asl b/src/mainboard/google/peppy/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/peppy/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/peppy/acpi_tables.c b/src/mainboard/google/peppy/acpi_tables.c new file mode 100644 index 0000000000..4d862ca29a --- /dev/null +++ b/src/mainboard/google/peppy/acpi_tables.c @@ -0,0 +1,295 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +#include +#include +#include "thermal.h" + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->tmps = CTL_TDP_SENSOR_ID; + + /* Normal TDP */ + gnvs->f1of = 0; + gnvs->f1on = 0; + + /* Limited TDP */ + gnvs->f0of = CTL_TDP_THRESHOLD_OFF; + gnvs->f0on = CTL_TDP_THRESHOLD_ON; + gnvs->f0pw = CTL_TDP_POWER_LIMIT; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 1; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* CBMEM TOC */ + gnvs->cmem = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +#if CONFIG_CHROMEOS + // TODO(reinauer) this could move elsewhere? + chromeos_init_vboot(&(gnvs->chromeos)); + + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif + + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/peppy/chromeos.c b/src/mainboard/google/peppy/chromeos.c new file mode 100644 index 0000000000..913b6f33fc --- /dev/null +++ b/src/mainboard/google/peppy/chromeos.c @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_EC_GOOGLE_CHROMEEC +#include "ec.h" +#include +#endif + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +#else + return 0; +#endif +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, 58, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +#else + return 0; +#endif +} + +int get_write_protect_state(void) +{ + return get_gpio(58); +} diff --git a/src/mainboard/google/peppy/cmos.layout b/src/mainboard/google/peppy/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/peppy/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/peppy/devicetree.cb b/src/mainboard/google/peppy/devicetree.cb new file mode 100644 index 0000000000..4c0d02d662 --- /dev/null +++ b/src/mainboard/google/peppy/devicetree.cb @@ -0,0 +1,125 @@ +chip northbridge/intel/haswell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Disable DisplayPort C Hotplug + register "gpu_dp_c_hotplug" = "0x00" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "5" # 400ms + register "gpu_panel_power_up_delay" = "400" # 40ms + register "gpu_panel_power_down_delay" = "150" # 15ms + register "gpu_panel_power_backlight_on_delay" = "2100" # 210ms + register "gpu_panel_power_backlight_off_delay" = "2100" # 210ms + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) + end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + + # DTLE DATA / EDGE values + register "sata_port0_gen3_dtle" = "0x5" + register "sata_port1_gen3_dtle" = "0x5" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + # Force enable ASPM for PCIe Port1 + register "pcie_port_force_aspm" = "0x01" + + # Disable PCIe CLKOUT 2-5 and CLKOUT_XDP + register "icc_clock_disable" = "0x013c0000" + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 off end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip ec/google/chromeec + # We only have one init function that + # we need to call to initialize the + # keyboard part of the EC. + device pnp ff.1 on # dummy address + end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/google/peppy/dsdt.asl b/src/mainboard/google/peppy/dsdt.asl new file mode 100644 index 0000000000..1316ebfcd3 --- /dev/null +++ b/src/mainboard/google/peppy/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + #include "acpi/mainboard.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include +} diff --git a/src/mainboard/google/peppy/ec.c b/src/mainboard/google/peppy/ec.c new file mode 100644 index 0000000000..0919f0feec --- /dev/null +++ b/src/mainboard/google/peppy/ec.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/peppy/ec.h b/src/mainboard/google/peppy/ec.h new file mode 100644 index 0000000000..11d2453837 --- /dev/null +++ b/src/mainboard/google/peppy/ec.h @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/peppy/fadt.c b/src/mainboard/google/peppy/fadt.c new file mode 100644 index 0000000000..7afbbfa698 --- /dev/null +++ b/src/mainboard/google/peppy/fadt.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = get_pmbase(); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/peppy/gma.c b/src/mainboard/google/peppy/gma.c new file mode 100644 index 0000000000..c86f9de0d8 --- /dev/null +++ b/src/mainboard/google/peppy/gma.c @@ -0,0 +1,280 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "mainboard.h" + +/* + * Here is the rough outline of how we bring up the display: + * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD + * 2. Source determines video mode by reading DPCD receiver capability field + * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD + * 0000Dh). + * 3. Sink replies DPCD receiver capability field. + * 4. Source starts EDID read thru I2C-over-AUX. + * 5. Sink replies EDID thru I2C-over-AUX. + * 6. Source determines link configuration, such as MAX_LINK_RATE and + * MAX_LANE_COUNT. Source also determines which type of eDP Authentication + * method to use and writes DPCD link configuration field (DPCD 00100h to + * 0010Ah) including eDP configuration set (DPCD 0010Ah). + * 7. Source starts link training. Sink does clock recovery and equalization. + * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh). + * 9. Sink replies DPCD link status field. If main link is not stable, Source + * repeats Step 7. + * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video + * parameters and recovers stream clock. + * 11. Source sends video data. + */ + +/* how many bytes do we need for the framebuffer? + * Well, this gets messy. To get an exact answer, we have + * to ask the panel, but we'd rather zero the memory + * and set up the gtt while the panel powers up. So, + * we take a reasonable guess, secure in the knowledge that the + * MRC has to overestimate the number of bytes used. + * 8 MiB is a very safe guess. There may be a better way later, but + * fact is, the initial framebuffer is only very temporary. And taking + * a little long is ok; this is done much faster than the AUX + * channel is ready for IO. + */ +#define FRAME_BUFFER_BYTES (8*MiB) +/* how many 4096-byte pages do we need for the framebuffer? + * There are hard ways to get this, and easy ways: + * there are FRAME_BUFFER_BYTES/4096 pages, since pages are 4096 + * on this chip (and in fact every Intel graphics chip we've seen). + */ +#define FRAME_BUFFER_PAGES (FRAME_BUFFER_BYTES/(4096)) + +extern int oprom_is_loaded; + +static int i915_init_done = 0; + +/* fill the palette. */ +static void palette(void) +{ + int i; + unsigned long color = 0; + + for(i = 0; i < 256; i++, color += 0x010101){ + gtt_write(_LGC_PALETTE_A + (i<<2),color); + } +} + +void mainboard_train_link(struct intel_dp *intel_dp) +{ + u8 read_val; + u8 link_status[DP_LINK_STATUS_SIZE]; + + gtt_write(DP_TP_CTL(intel_dp->port), + DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE); + gtt_write(DDI_BUF_CTL_A, + DDI_BUF_CTL_ENABLE| + DDI_A_4_LANES|DDI_PORT_WIDTH_X1|DDI_INIT_DISPLAY_DETECTED|0x80000011); + + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, + DP_TRAINING_PATTERN_1 | DP_LINK_QUAL_PATTERN_DISABLE | + DP_SYMBOL_ERROR_COUNT_BOTH); + + intel_dp_set_training_lane0(intel_dp, + DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0); + intel_dp_get_link_status(intel_dp, link_status); + + gtt_write(DP_TP_CTL(intel_dp->port), + DP_TP_CTL_ENABLE | + DP_TP_CTL_ENHANCED_FRAME_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT2); + + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, DP_TRAINING_PATTERN_2 | + DP_LINK_QUAL_PATTERN_DISABLE | DP_SYMBOL_ERROR_COUNT_BOTH); + intel_dp_get_link_status(intel_dp, link_status); + intel_dp_get_lane_align_status(intel_dp, &read_val); + intel_dp_get_training_pattern(intel_dp, &read_val); + intel_dp_set_training_pattern(intel_dp, DP_TRAINING_PATTERN_DISABLE | + DP_LINK_QUAL_PATTERN_DISABLE | DP_SYMBOL_ERROR_COUNT_BOTH); +} + +/* This variable controls whether the test_gfx function below puts up + * color bars or not. In previous revs we ifdef'd the test_gfx function out + * but it's handy, especially when using a JTAG debugger + * to be able to enable and disable a test graphics. + */ +int show_test = 0; + +static void test_gfx(struct intel_dp *dp) +{ + int i; + + if (!show_test) + return; + /* This is a sanity test code which fills the screen with two bands -- + green and blue. It is very useful to ensure all the initializations + are made right. Thus, to be used only for testing, not otherwise + */ + + for (i = 0; i < (dp->edid.mode.va - 4); i++) { + u32 *l; + int j; + u32 tcolor = 0x0ff; + for (j = 0; j < (dp->edid.mode.ha-4); j++) { + if (j == (dp->edid.mode.ha/2)) { + tcolor = 0xff00; + } + l = (u32*)(dp->graphics + i * dp->stride + j * sizeof(tcolor)); + memcpy(l,&tcolor,sizeof(tcolor)); + } + } + printk(BIOS_SPEW, "sleep 10\n"); + delay(10); +} + +void mainboard_set_port_clk_dp(struct intel_dp *intel_dp) +{ + u32 ddi_pll_sel = 0; + + switch (intel_dp->link_bw) { + case DP_LINK_BW_1_62: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; + break; + case DP_LINK_BW_2_7: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; + break; + case DP_LINK_BW_5_4: + ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; + break; + default: + printk(BIOS_ERR, "invalid link bw %d\n", intel_dp->link_bw); + return; + } + + gtt_write(PORT_CLK_SEL(intel_dp->port), ddi_pll_sel); +} + +int panel_lightup(struct intel_dp *dp, unsigned int init_fb) +{ + int i; + int edid_ok; + int pixels = FRAME_BUFFER_BYTES/64; + + gtt_write(PCH_PP_CONTROL,0xabcd000f); + delay(1); + + void runio(struct intel_dp *dp); + /* hard codes -- stuff you can only know from the mainboard */ + dp->gen = 8; // This is gen 8 which we believe is Haswell + dp->is_haswell = 1; + dp->DP = 0x2; + dp->pipe = PIPE_A; + dp->port = PORT_A; + dp->plane = PLANE_A; + dp->pipe_bits_per_pixel = 24; + dp->type = INTEL_OUTPUT_EDP; + dp->output_reg = DP_A; + /* observed from YABEL. */ + dp->aux_clock_divider = 0xe1; + dp->precharge = 3; + + /* 1. Normal mode: Set the first page to zero and make + all GTT entries point to the same page + 2. Developer/Recovery mode: Set up a tasteful color + so people know we are alive. */ + if (init_fb || show_test) { + set_translation_table(0, FRAME_BUFFER_PAGES, dp->physbase, + 4096); + memset((void *)dp->graphics, 0x55, FRAME_BUFFER_PAGES*4096); + } else { + set_translation_table(0, FRAME_BUFFER_PAGES, dp->physbase, 0); + memset((void*)dp->graphics, 0, 4096); + } + + dp->address = 0x50; + + if ( !intel_dp_get_dpcd(dp) ) + goto fail; + + intel_dp_i2c_aux_ch(dp, MODE_I2C_WRITE, 0, NULL); + for(dp->edidlen = i = 0; i < sizeof(dp->rawedid); i++){ + if (intel_dp_i2c_aux_ch(dp, MODE_I2C_READ, + 0x50, &dp->rawedid[i]) < 0) + break; + dp->edidlen++; + } + + edid_ok = decode_edid(dp->rawedid, dp->edidlen, &dp->edid, 0); + + printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok); + + compute_display_params(dp); + + printk(BIOS_SPEW, "pixel_clock is %i, link_clock is %i\n", + dp->edid.mode.pixel_clock, dp->edid.link_clock); + + intel_ddi_set_pipe_settings(dp); + + runio(dp); + + palette(); + + pixels = dp->edid.mode.ha * (dp->edid.mode.va-4) * 4; + printk(BIOS_SPEW, "ha=%d, va=%d\n",dp->edid.mode.ha, dp->edid.mode.va); + test_gfx(dp); + + set_vbe_mode_info_valid(&dp->edid, (uintptr_t)dp->graphics); + i915_init_done = 1; + oprom_is_loaded = 1; + return 1; + +fail: + printk(BIOS_SPEW, "Graphics could not be started;"); + /* unclear we will *ever* want to do this. */ + if (0){ + printk(BIOS_SPEW, "Turn off power and wait ..."); + gtt_write(PCH_PP_CONTROL,0xabcd0000); + udelay(600000); + gtt_write(PCH_PP_CONTROL,0xabcd000f); + } + printk(BIOS_SPEW, "Returning.\n"); + return 0; +} diff --git a/src/mainboard/google/peppy/gpio.h b/src/mainboard/google/peppy/gpio.h new file mode 100644 index 0000000000..32b1928072 --- /dev/null +++ b/src/mainboard/google/peppy/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PEPPY_GPIO_H +#define PEPPY_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: LTE_WAKE_L_Q */ + LP_GPIO_INPUT, /* 9: RAM_ID1 */ + LP_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + LP_GPIO_UNUSED, /* 11: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 12: TRACKPAD_INT_L (WAKE) */ + LP_GPIO_INPUT, /* 13: RAM_ID0 */ + LP_GPIO_INPUT, /* 14: EC_IN_RW */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 16: UNUSED */ + LP_GPIO_UNUSED, /* 17: UNUSED */ + LP_GPIO_NATIVE, /* 18: PCIE_CLKREQ_WLAN# */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_UNUSED, /* 20: UNUSED */ + LP_GPIO_UNUSED, /* 21: UNUSED */ + LP_GPIO_UNUSED, /* 22: UNUSED */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_UNUSED, /* 24: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 25: TOUCH_INT_L (WAKE) */ + LP_GPIO_UNUSED, /* 26: UNUSED */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_UNUSED, /* 28: UNUSED */ + LP_GPIO_UNUSED, /* 29: UNUSED */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: ACPRESENT */ + LP_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + LP_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + LP_GPIO_UNUSED, /* 41: UNUSED */ + LP_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + LP_GPIO_UNUSED, /* 43: UNUSED */ + LP_GPIO_OUT_HIGH, /* 44: PP3300_SSD_EN */ + LP_GPIO_OUT_HIGH, /* 45: PP3300_CODEC_EN */ + LP_GPIO_OUT_HIGH, /* 46: WLAN_DISABLE_L */ + LP_GPIO_INPUT, /* 47: RAM_ID2 */ + LP_GPIO_UNUSED, /* 48: UNUSED */ + LP_GPIO_UNUSED, /* 49: UNUSED */ + LP_GPIO_UNUSED, /* 50: UNUSED */ + LP_GPIO_INPUT, /* 51: ALS_INT_L */ + LP_GPIO_INPUT, /* 52: SIM_DET */ + LP_GPIO_PIRQ, /* 53: TRACKPAD_INT_DX */ + LP_GPIO_PIRQ, /* 54: TOUCH_INT_L_DX */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_UNUSED, /* 56: UNUSED */ + LP_GPIO_OUT_HIGH, /* 57: PP3300_CCD_EN */ + LP_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + LP_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + LP_GPIO_NATIVE, /* 60: NATIVE: SML0ALERT */ + LP_GPIO_UNUSED, /* 61: UNUSED */ + LP_GPIO_UNUSED, /* 62: UNUSED */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_NATIVE, /* 72: NATIVE: PCH_BATLOW# */ + LP_GPIO_NATIVE, /* 73: NATIVE: SMB1ALERT# */ + LP_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + LP_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_UNUSED, /* 91: UNUSED */ + LP_GPIO_UNUSED, /* 92: UNUSED */ + LP_GPIO_UNUSED, /* 93: UNUSED */ + LP_GPIO_UNUSED, /* 94: UNUSED */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/peppy/hda_verb.h b/src/mainboard/google/peppy/hda_verb.h new file mode 100644 index 0000000000..ec1b57d02e --- /dev/null +++ b/src/mainboard/google/peppy/hda_verb.h @@ -0,0 +1,117 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000c, // Number of jacks (NID entries) + + /* Bits 31:28 - Codec Address */ + /* Bits 27:20 - NID */ + /* Bits 19:8 - Verb ID */ + /* Bits 7:0 - Payload */ + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - Disabled */ + 0x01271cf0, // + 0x01271d11, // + 0x01271e11, // + 0x01271f41, // + + /* Pin Complex (NID 0x14) SPKR-OUT - Internal Speakers */ + 0x01471c10, // group 1, cap 0 + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal, Location N/A + + /* Pin Complex (NID 0x17) MONO Out - Disabled */ + 0x01771cf0, // + 0x01771d11, // + 0x01771e11, // + 0x01771f41, // + + /* Pin Complex (NID 0x18) Disabled */ + 0x01871cf0, // + 0x01871d11, // + 0x01871e11, // + 0x01871f41, // + + /* Pin Complex (NID 0x19) MIC2 - 3.5mm Jack */ + 0x01971c20, // group2, cap 0 + 0x01971d10, // black, jack detect + 0x01971ea1, // Mic in, 3.5mm Jack + 0x01971f03, // connector, External left panel + + /* Pin Complex (NID 0x1A) LINE1 - Internal Mic */ + 0x01a71c11, // group 1, cap 1 + 0x01a71d01, // no connector, no jack detect + 0x01a71ea7, // mic in, analog connection + 0x01a71f90, // Fixed function, internal, Location N/A + + /* Pin Complex (NID 0x1B) LINE2 - Disabled */ + 0x01b71cf0, // + 0x01b71d11, // + 0x01b71e11, // + 0x01b71f41, // + + /* Pin Complex (NID 0x1D) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, Internal, Location N/A + + /* Pin Complex (NID 0x1E) SPDIF-OUT - Disabled*/ + 0x01e71cf0, // + 0x01e71d11, // + 0x01e71e11, // + 0x01e71f41, // + + /* Pin Complex (NID 0x21) HP-OUT - 3.5mm Jack*/ + 0x02171c21, // group2, cap 1 + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 3.5mm Jack + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/peppy/i915io.c b/src/mainboard/google/peppy/i915io.c new file mode 100644 index 0000000000..cf8400496b --- /dev/null +++ b/src/mainboard/google/peppy/i915io.c @@ -0,0 +1,144 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include "mainboard.h" + +void runio(struct intel_dp *dp, int verbose); +void runio(struct intel_dp *dp, int verbose) +{ + u8 read_val; + gtt_write(DDI_BUF_CTL_A, + DDI_BUF_IS_IDLE|DDI_A_4_LANES|DDI_PORT_WIDTH_X1|DDI_INIT_DISPLAY_DETECTED + |0x00000091); + + intel_prepare_ddi(); + + gtt_write(BLC_PWM_CPU_CTL,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL2,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL1,0x80000000); + + gtt_write(DEIIR,0x00008000); + intel_dp_wait_reg(DEIIR, 0x00000000); + gtt_write(DSPSTRIDE(dp->plane), dp->stride); + gtt_write(DSPADDR(dp->plane), 0x00000000); + + printk(BIOS_SPEW, "DP_SET_POWER"); + + intel_dp_sink_dpms(dp, 0); + + intel_dp_set_m_n_regs(dp); + + intel_dp_get_max_downspread(dp, &read_val); + + intel_dp_set_resolution(dp); + + gtt_write(PIPESRC(dp->pipe),dp->pipesrc); + gtt_write(PIPECONF(dp->transcoder),0x00000000); + gtt_write(PCH_TRANSCONF(dp->pipe),0x00000000); + + mainboard_set_port_clk_dp(dp); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(DSPCNTR(dp->plane),DISPLAY_PLANE_ENABLE|DISPPLANE_BGRX888); + + gtt_write(DEIIR,0x00000080); + intel_dp_wait_reg(DEIIR, 0x00000000); + + /* There is some reason we removed these three calls from + * slippy/gma.c -- I dont remember why!! */ + gtt_write(PF_WIN_POS(dp->pipe),dp->pfa_pos); + gtt_write(PF_CTL(dp->pipe),dp->pfa_ctl); + gtt_write(PF_WIN_SZ(dp->pipe),dp->pfa_sz); + + gtt_write(TRANS_DDI_FUNC_CTL_EDP,dp->flags); + gtt_write(PIPECONF(dp->transcoder),PIPECONF_ENABLE|PIPECONF_DITHER_EN); + + /* what is this doing? Not sure yet. But we don't seem to be + * able to live without it.*/ + intel_dp_i2c_write(dp, 0x0); + intel_dp_i2c_read(dp, &read_val); + intel_dp_i2c_write(dp, 0x04); + intel_dp_i2c_read(dp, &read_val); + intel_dp_i2c_write(dp, 0x7e); + intel_dp_i2c_read(dp, &read_val); + + gtt_write(DDI_BUF_CTL_A, + DDI_BUF_IS_IDLE| + DDI_A_4_LANES|DDI_PORT_WIDTH_X1|DDI_INIT_DISPLAY_DETECTED + |0x00000091); + + gtt_write(TRANS_DDI_FUNC_CTL_EDP+0x10,0x00000001); + gtt_write(DP_TP_CTL(dp->port),DP_TP_CTL_ENABLE | + DP_TP_CTL_ENHANCED_FRAME_ENABLE); + + gtt_write(DDI_BUF_CTL_A, + DDI_BUF_CTL_ENABLE| + /* another undocumented setting. Surprised? */ 0x40000 | + DDI_BUF_IS_IDLE|DDI_A_4_LANES| + DDI_PORT_WIDTH_X1|DDI_INIT_DISPLAY_DETECTED| + 0x80040091); + + intel_dp_set_bw(dp); + + intel_dp_set_lane_count(dp); + + mainboard_train_link(dp); + + gtt_write(DP_TP_CTL(dp->port), + DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE | + DP_TP_CTL_LINK_TRAIN_IDLE); + + gtt_write(DP_TP_CTL(dp->port), + DP_TP_CTL_ENABLE | DP_TP_CTL_ENHANCED_FRAME_ENABLE | + DP_TP_CTL_LINK_TRAIN_NORMAL); + + gtt_write(BLC_PWM_CPU_CTL,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL2,0x03a903a9); + gtt_write(BLC_PWM_PCH_CTL1,0x80000000); + + /* some of this is not needed. But with a total lack of docs, well ...*/ + gtt_write(DIGITAL_PORT_HOTPLUG_CNTRL, DIGITAL_PORTA_HOTPLUG_ENABLE ); + + gtt_write(SDEIIR,0x00000000); + gtt_write(DEIIR,0x00000000); + gtt_write(DEIIR,0x00008000); + intel_dp_wait_reg(DEIIR, 0x00000000); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(PIPESRC(dp->pipe),dp->pipesrc); + + gtt_write(DEIIR,0x00000080); + intel_dp_wait_reg(DEIIR, 0x00000000); + + gtt_write(DSPSTRIDE(dp->plane),dp->stride); + gtt_write(DSPCNTR(dp->plane),DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); + + gtt_write(PCH_PP_CONTROL,EDP_BLC_ENABLE | EDP_BLC_ENABLE | PANEL_POWER_ON); + + gtt_write(SDEIIR,0x00000000); + gtt_write(SDEIIR,0x00000000); + gtt_write(DEIIR,0x00000000); + +} + diff --git a/src/mainboard/google/peppy/mainboard.c b/src/mainboard/google/peppy/mainboard.c new file mode 100644 index 0000000000..60e8663ab6 --- /dev/null +++ b/src/mainboard/google/peppy/mainboard.c @@ -0,0 +1,207 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include "ec.h" +#include "onboard.h" + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 * pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_LIGHTSENSOR_NAME, /* name */ + BOARD_LIGHTSENSOR_IRQ, /* instance */ + BOARD_LIGHTSENSOR_I2C_BUS, /* segment */ + BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/peppy/mainboard.h b/src/mainboard/google/peppy/mainboard.h new file mode 100644 index 0000000000..f47fffda2a --- /dev/null +++ b/src/mainboard/google/peppy/mainboard.h @@ -0,0 +1,25 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MAINBOARD_H_ +#define __MAINBOARD_H_ +void mainboard_train_link(struct intel_dp *intel_dp); +void mainboard_set_port_clk_dp(struct intel_dp *intel_dp); + +#endif diff --git a/src/mainboard/google/peppy/onboard.h b/src/mainboard/google/peppy/onboard.h new file mode 100644 index 0000000000..003659490c --- /dev/null +++ b/src/mainboard/google/peppy/onboard.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#define BOARD_LIGHTSENSOR_NAME "lightsensor" +#define BOARD_LIGHTSENSOR_IRQ 51 /* PIRQT */ +#define BOARD_LIGHTSENSOR_I2C_BUS 2 /* I2C1 */ +#define BOARD_LIGHTSENSOR_I2C_ADDR 0x44 + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ 37 /* PIRQV */ +#define BOARD_TRACKPAD_WAKE_GPIO 12 /* GPIO12 */ +#define BOARD_TRACKPAD_I2C_BUS 1 /* I2C0 */ +#define BOARD_TRACKPAD_I2C_ADDR 0x67 + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ 38 /* PIRQW */ +#define BOARD_TOUCHSCREEN_WAKE_GPIO 25 /* GPIO25 */ +#define BOARD_TOUCHSCREEN_I2C_BUS 2 /* I2C1 */ +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a + +#define PEPPY_BOARD_VERSION_PROTO 0 +#define PEPPY_BOARD_VERSION_EVT 1 + +#endif diff --git a/src/mainboard/google/peppy/romstage.c b/src/mainboard/google/peppy/romstage.c new file mode 100644 index 0000000000..c6696c09f6 --- /dev/null +++ b/src/mainboard/google/peppy/romstage.c @@ -0,0 +1,185 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "cpu/intel/haswell/haswell.h" +#include "ec/google/chromeec/ec.h" +#include "northbridge/intel/haswell/haswell.h" +#include "northbridge/intel/haswell/raminit.h" +#include "southbridge/intel/lynxpoint/pch.h" +#include "southbridge/intel/lynxpoint/lp_gpio.h" +#include "gpio.h" +#include "onboard.h" + +const struct rcba_config_instruction rcba_config[] = { + + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), + RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), + RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), + RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ + + /* Disable unused devices (board specific) */ + RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), + + RCBA_END_CONFIG, +}; + +/* Copy SPD data for on-board memory */ +static void copy_spd(struct pei_data *peid) +{ + const int gpio_vector[] = {13, 9, 47, -1}; + int spd_index = get_gpios(gpio_vector); + struct cbfs_file *spd_file; + + printk(BIOS_DEBUG, "SPD index %d\n", spd_index); + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + + switch (google_chromeec_get_board_version()) { + case PEPPY_BOARD_VERSION_PROTO: + /* Index 0 is 2GB config with CH0 only. */ + if (spd_index == 0) + peid->dimm_channel1_disabled = 3; + break; + + case PEPPY_BOARD_VERSION_EVT: + default: + /* Index 0-2 are 4GB config with both CH0 and CH1. + * Index 4-6 are 2GB config with CH0 only. */ + if (spd_index > 3) + peid->dimm_channel1_disabled = 3; + break; + } + + if (ntohl(spd_file->len) < + ((spd_index + 1) * sizeof(peid->spd_data[0]))) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file->len < sizeof(peid->spd_data[0])) + die("Missing SPD data."); + + memcpy(peid->spd_data[0], + ((char*)CBFS_SUBHEADER(spd_file)) + + spd_index * sizeof(peid->spd_data[0]), + sizeof(peid->spd_data[0])); +} + +void mainboard_romstage_entry(unsigned long bist) +{ + struct pei_data pei_data = { + pei_version: PEI_VERSION, + mchbar: DEFAULT_MCHBAR, + dmibar: DEFAULT_DMIBAR, + epbar: DEFAULT_EPBAR, + pciexbar: DEFAULT_PCIEXBAR, + smbusbar: SMBUS_IO_BASE, + wdbbar: 0x4000000, + wdbsize: 0x1000, + hpet_address: HPET_ADDR, + rcba: DEFAULT_RCBA, + pmbase: DEFAULT_PMBASE, + gpiobase: DEFAULT_GPIOBASE, + temp_mmio_base: 0xfed08000, + system_type: 5, /* ULT */ + tseg_size: CONFIG_SMM_TSEG_SIZE, + spd_addresses: { 0xff, 0x00, 0xff, 0x00 }, + ec_present: 1, + // 0 = leave channel enabled + // 1 = disable dimm 0 on channel + // 2 = disable dimm 1 on channel + // 3 = disable dimm 0+1 on channel + dimm_channel0_disabled: 2, + dimm_channel1_disabled: 2, + max_ddr3_freq: 1600, + usb_xhci_on_resume: 1, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0150, 1, USB_OC_PIN_SKIP, /* P0: LTE */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 0, /* P1: Port A, CN10 */ + USB_PORT_BACK_PANEL }, + { 0x0080, 1, USB_OC_PIN_SKIP, /* P2: CCD */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: BT */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 2, /* P4: Port B, CN6 */ + USB_PORT_BACK_PANEL }, + { 0x0000, 0, USB_OC_PIN_SKIP, /* P5: EMPTY */ + USB_PORT_SKIP }, + { 0x0150, 1, USB_OC_PIN_SKIP, /* P6: SD Card */ + USB_PORT_FLEX }, + { 0x0000, 0, USB_OC_PIN_SKIP, /* P7: EMPTY */ + USB_PORT_SKIP }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; Port A, CN6 */ + { 0, USB_OC_PIN_SKIP }, /* P2; */ + { 0, USB_OC_PIN_SKIP }, /* P3; */ + { 0, USB_OC_PIN_SKIP }, /* P4; */ + }, + }; + + struct romstage_params romstage_params = { + .pei_data = &pei_data, + .gpio_map = &mainboard_gpio_map, + .rcba_config = &rcba_config[0], + .bist = bist, + .copy_spd = copy_spd, + }; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(&romstage_params); +} diff --git a/src/mainboard/google/peppy/smihandler.c b/src/mainboard/google/peppy/smihandler.c new file mode 100644 index 0000000000..f2254683a2 --- /dev/null +++ b/src/mainboard/google/peppy/smihandler.c @@ -0,0 +1,170 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include EC functions */ +#include +#include "ec.h" + +/* Codec enable: GPIO45 */ +#define GPIO_PP3300_CODEC_EN 45 +/* WLAN / BT enable: GPIO46 */ +#define GPIO_WLAN_DISABLE_L 46 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(get_pmbase() + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, get_pmbase() + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s3u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + set_gpio(GPIO_PP3300_CODEC_EN, 0); + set_gpio(GPIO_WLAN_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s5u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + set_gpio(GPIO_PP3300_CODEC_EN, 0); + set_gpio(GPIO_WLAN_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/peppy/thermal.h b/src/mainboard/google/peppy/thermal.h new file mode 100644 index 0000000000..afa439164c --- /dev/null +++ b/src/mainboard/google/peppy/thermal.h @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Control TDP Settings */ +#define CTL_TDP_SENSOR_ID 0 /* PECI */ +#define CTL_TDP_POWER_LIMIT 12 /* 12W */ +#define CTL_TDP_THRESHOLD_OFF 80 /* Normal at 80C */ +#define CTL_TDP_THRESHOLD_ON 85 /* Limited at 85C */ + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 99 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/google/rambi/Kconfig b/src/mainboard/google/rambi/Kconfig new file mode 100644 index 0000000000..2018373204 --- /dev/null +++ b/src/mainboard/google/rambi/Kconfig @@ -0,0 +1,42 @@ +if BOARD_GOOGLE_RAMBI + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select SOC_INTEL_BAYTRAIL + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select ENABLE_BUILTIN_COM1 + select BOARD_ROMSIZE_KB_8192 + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select ALWAYS_LOAD_OPROM + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_REFCODE_INDEX + hex + default 0x3 + +config MAINBOARD_DIR + string + default google/rambi + +config MAINBOARD_PART_NUMBER + string + default "Rambi" + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +config SPD_CBFS_ADDRESS + hex "Location of SPD in CBFS" + default 0xfffec000 + +endif # BOARD_INTEL_BAYLEYBAY diff --git a/src/mainboard/google/rambi/Makefile.inc b/src/mainboard/google/rambi/Makefile.inc new file mode 100644 index 0000000000..b399022144 --- /dev/null +++ b/src/mainboard/google/rambi/Makefile.inc @@ -0,0 +1,29 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-y += spd + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += gpio.c +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c +ramstage-y += irqroute.c +ramstage-y += w25q64.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c diff --git a/src/mainboard/google/rambi/acpi/chromeos.asl b/src/mainboard/google/rambi/acpi/chromeos.asl new file mode 100644 index 0000000000..e748fb868e --- /dev/null +++ b/src/mainboard/google/rambi/acpi/chromeos.asl @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Fields are in the following order. + * - Type: recovery = 1 developer mode = 2 write protect = 3 + * - Active Level - if -1 not a valid gpio + * - GPIO number encoding - if -1 not a valid gpio + * - Chipset Name + * + * Note: On Bay Trail we need to encode gpios within the 3 separate banks + * with the MMIO offset of each banks space. e.g. GPIO_SUS[8] would be encoded + * as 0x2008 where the SUS offset (IO_BASE_OFFSET_GPSSUS) is 0x2000. + */ + +Name(OIPG, Package() { + // No physical recovery button + Package () { 0x0001, 0, 0xFFFFFFFF, "BayTrail" }, + Package () { 0x0003, 1, 0x2006, "BayTrail" }, +}) diff --git a/src/mainboard/google/rambi/acpi/dptf.asl b/src/mainboard/google/rambi/acpi/dptf.asl new file mode 100644 index 0000000000..507b7c686f --- /dev/null +++ b/src/mainboard/google/rambi/acpi/dptf.asl @@ -0,0 +1,74 @@ +#define DPTF_CPU_PASSIVE 80 +#define DPTF_CPU_CRITICAL 90 + +#define DPTF_TSR0_SENSOR_ID 1 +#define DPTF_TSR0_SENSOR_NAME "TMP432_Internal" +#define DPTF_TSR0_PASSIVE 48 +#define DPTF_TSR0_CRITICAL 70 + +#define DPTF_TSR1_SENSOR_ID 2 +#define DPTF_TSR1_SENSOR_NAME "TMP432_Power_top" +#define DPTF_TSR1_PASSIVE 60 +#define DPTF_TSR1_CRITICAL 70 + +#define DPTF_TSR2_SENSOR_ID 3 +#define DPTF_TSR2_SENSOR_NAME "TMP432_CPU_bottom" +#define DPTF_TSR2_PASSIVE 55 +#define DPTF_TSR2_CRITICAL 70 + +#define DPTF_ENABLE_CHARGER + +/* Charger performance states, board-specific values from charger and EC */ +Name (CHPS, Package () { + Package () { 0, 0, 0, 0, 255, 0x6a4, "mA", 0 }, /* 1.7A (MAX) */ + Package () { 0, 0, 0, 0, 24, 0x600, "mA", 0 }, /* 1.5A */ + Package () { 0, 0, 0, 0, 16, 0x400, "mA", 0 }, /* 1.0A */ + Package () { 0, 0, 0, 0, 8, 0x200, "mA", 0 }, /* 0.5A */ + Package () { 0, 0, 0, 0, 0, 0x000, "mA", 0 }, /* 0.0A */ +}) + +/* Mainboard specific _PDL is 1GHz */ +Name (MPDL, 8) + +Name (DTRT, Package () { + /* CPU Throttle Effect on CPU */ + Package () { \_SB.DPTF.TCPU, \_SB.DPTF.TCPU, 100, 50, 0, 0, 0, 0 }, + + /* CPU Effect on Temp Sensor 0 */ + Package () { \_SB.DPTF.TCPU, \_SB.DPTF.TSR0, 100, 600, 0, 0, 0, 0 }, + +#ifdef DPTF_ENABLE_CHARGER + /* Charger Effect on Temp Sensor 1 */ + Package () { \_SB.DPTF.TCHG, \_SB.DPTF.TSR1, 200, 600, 0, 0, 0, 0 }, +#endif + + /* CPU Effect on Temp Sensor 1 */ + Package () { \_SB.DPTF.TCPU, \_SB.DPTF.TSR1, 100, 600, 0, 0, 0, 0 }, + + /* CPU Effect on Temp Sensor 2 */ + Package () { \_SB.DPTF.TCPU, \_SB.DPTF.TSR2, 100, 600, 0, 0, 0, 0 }, +}) + +Name (MPPC, Package () +{ + 0x2, // Revision + Package () { // Power Limit 1 + 0, // PowerLimitIndex, 0 for Power Limit 1 + 1600, // PowerLimitMinimum + 6200, // PowerLimitMaximum + 1000, // TimeWindowMinimum + 1000, // TimeWindowMaximum + 200 // StepSize + }, + Package () { // Power Limit 2 + 1, // PowerLimitIndex, 1 for Power Limit 2 + 8000, // PowerLimitMinimum + 8000, // PowerLimitMaximum + 1000, // TimeWindowMinimum + 1000, // TimeWindowMaximum + 1000 // StepSize + } +}) + +/* Include Baytrail DPTF */ +#include diff --git a/src/mainboard/google/rambi/acpi/ec.asl b/src/mainboard/google/rambi/acpi/ec.asl new file mode 100644 index 0000000000..9a4cd4a1a8 --- /dev/null +++ b/src/mainboard/google/rambi/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/google/rambi/acpi/mainboard.asl b/src/mainboard/google/rambi/acpi/mainboard.asl new file mode 100644 index 0000000000..e6a7448030 --- /dev/null +++ b/src/mainboard/google/rambi/acpi/mainboard.asl @@ -0,0 +1,365 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name (_HID, EisaId ("PNP0C0D")) + Name (_PRW, Package() { BOARD_PCH_WAKE_GPIO, 0x5 }) + Method (_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + } + + Device (PWRB) + { + Name (_HID, EisaId ("PNP0C0C")) + Name (_UID, 1) + } + + /* Wake device for touchpad */ + Device (TPAD) + { + Name (_HID, EisaId ("PNP0C0E")) + Name (_UID, 1) + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Name (RBUF, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_CRS) + { + /* Only return interrupt if I2C1 is PCI mode */ + If (LEqual (\S1EN, 0)) { + Return (^RBUF) + } + } + } + + /* Wake device for touchscreen */ + Device (TSCR) + { + Name (_HID, EisaId ("PNP0C0E")) + Name (_UID, 2) + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Name (RBUF, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + }) + + Method (_CRS) + { + /* Only return interrupt if I2C6 is PCI mode */ + If (LEqual (\S6EN, 0)) { + Return (^RBUF) + } + } + } +} + +Scope (\_SB.I2C1) +{ + Device (ATPB) + { + Name (_HID, "ATML0000") + Name (_DDN, "Atmel Touchpad Bootloader") + Name (_UID, 1) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x25, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C1", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } + + Device (ATPA) + { + Name (_HID, "ATML0000") + Name (_DDN, "Atmel Touchpad") + Name (_UID, 2) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x4b, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C1", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } + + Device (ETPA) + { + Name (_HID, "ELAN0000") + Name (_DDN, "Elan Touchpad") + Name (_UID, 3) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x15, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C1", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } +} + +Scope (\_SB.I2C2) +{ + Device (CODC) + { + /* + * TODO(dlaurie): Need official HID. + * + * The current HID is created from the Maxim Integrated + * PCI Vendor ID 193Ch and a shortened device identifier. + */ + Name (_HID, "193C9890") + Name (_DDN, "Maxim 98090 Codec") + Name (_UID, 1) + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x10, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C2", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_CODEC_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } +} + +Scope (\_SB.I2C5) +{ + Device (ALSI) + { + /* + * TODO(dlaurie): Need official HID. + * + * The current HID is created from the Intersil PNP + * Vendor ID "LSD" and a shortened device identifier. + */ + Name (_HID, EisaId ("LSD2918")) + Name (_DDN, "Intersil 29018 Ambient Light Sensor") + Name (_UID, 1) + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x44, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C5", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_ALS_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S5EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } +} + +Scope (\_SB.I2C6) +{ + Device (ATSB) + { + Name (_HID, "ATML0001") + Name (_DDN, "Atmel Touchscreen Bootloader") + Name (_UID, 4) + Name (ISTP, 0) /* TouchScreen */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x26, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C6", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S6EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } + + Device (ATSA) + { + Name (_HID, "ATML0001") + Name (_DDN, "Atmel Touchscreen") + Name (_UID, 5) + Name (ISTP, 0) /* TouchScreen */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x4a, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.I2C6", // ResourceSource + ) + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + }) + + Method (_STA) + { + If (LEqual (\S6EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Allow device to power off in S0 */ + Name (_S0W, 4) + } +} + +Scope (\_SB.LPEA) +{ + Name (GBUF, ResourceTemplate () + { + /* Jack Detect (index 0) */ + GpioInt (Edge, ActiveHigh, Exclusive, PullNone,, + "\\_SB.GPSC") { 14 } + + /* Mic Detect (index 1) */ + GpioInt (Edge, ActiveHigh, Exclusive, PullNone,, + "\\_SB.GPSC") { 15 } + }) +} diff --git a/src/mainboard/google/rambi/acpi/superio.asl b/src/mainboard/google/rambi/acpi/superio.asl new file mode 100644 index 0000000000..3199ed5314 --- /dev/null +++ b/src/mainboard/google/rambi/acpi/superio.asl @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +// Override default IRQ settings +#define SIO_EC_PS2K_IRQ Interrupt(ResourceConsumer, Edge, ActiveLow) {BOARD_I8042_IRQ} + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/rambi/acpi/video.asl b/src/mainboard/google/rambi/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/rambi/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/rambi/acpi_tables.c b/src/mainboard/google/rambi/acpi_tables.c new file mode 100644 index 0000000000..981116bfe4 --- /dev/null +++ b/src/mainboard/google/rambi/acpi_tables.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* Enable DPTF */ + gnvs->dpte = 1; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + current = acpi_madt_irq_overrides(current); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/rambi/chromeos.c b/src/mainboard/google/rambi/chromeos.c new file mode 100644 index 0000000000..b29b0791c3 --- /dev/null +++ b/src/mainboard/google/rambi/chromeos.c @@ -0,0 +1,136 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_EC_GOOGLE_CHROMEEC +#include "ec.h" +#include +#endif + +/* The WP status pin lives on GPIO_SSUS_6 which is pad 36 in the SUS well. */ +#define WP_STATUS_PAD 36 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +#else + /* Default to force open. */ + return 1; +#endif +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int port, int polarity, + const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = port; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "write protect", + get_write_protect_state()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + recovery_mode_enabled()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +#else + return 0; +#endif +} + +int clear_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + const uint32_t kb_rec_mask = + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY); + /* Unconditionally clear the EC recovery request. */ + return google_chromeec_clear_events_b(kb_rec_mask); +#else + return 0; +#endif +} + +int get_write_protect_state(void) +{ + /* + * The vboot loader queries this function in romstage. The GPIOs have + * not been set up yet as that configuration is done in ramstage. The + * hardware defaults to an input but there is a 20K pulldown. Externally + * there is a 10K pullup. Disable the internal pull in romstage so that + * there isn't any ambiguity in the reading. + */ +#if defined(__PRE_RAM__) + ssus_disable_internal_pull(WP_STATUS_PAD); +#endif + + /* WP is enabled when the pin is reading high. */ + return ssus_get_gpio(WP_STATUS_PAD); +} + diff --git a/src/mainboard/google/rambi/cmos.layout b/src/mainboard/google/rambi/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/rambi/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/rambi/devicetree.cb b/src/mainboard/google/rambi/devicetree.cb new file mode 100644 index 0000000000..5914a62608 --- /dev/null +++ b/src/mainboard/google/rambi/devicetree.cb @@ -0,0 +1,102 @@ +chip soc/intel/baytrail + + # SATA port enable mask (2 ports) + register "sata_port_map" = "0x1" + register "sata_ahci" = "0x1" + register "ide_legacy_combined" = "0x0" + + # Route USB ports to XHCI + register "usb_route_to_xhci" = "1" + + # USB Port Disable Mask + register "usb2_port_disable_mask" = "0x0" + register "usb3_port_disable_mask" = "0x0" + + # USB PHY settings + # TODO: These values are from Baytrail and need tuned for Rambi board + register "usb2_per_port_lane0" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup0" = "0x0300401d" + register "usb2_per_port_lane1" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup1" = "0x0300401d" + register "usb2_per_port_lane2" = "0x00049209" + register "usb2_per_port_rcomp_hs_pullup2" = "0x01004015" + register "usb2_per_port_lane3" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup3" = "0x0300401d" + register "usb2_comp_bg" = "0x4700" + + # LPE audio codec settings + register "lpe_codec_clk_freq" = "25" # 25MHz clock + register "lpe_codec_clk_num" = "0" # PMC_PLT_CLK[0] + + # SD Card controller + register "sdcard_cap_low" = "0x036864b2" + register "sdcard_cap_high" = "0x0" + + # Enable devices in ACPI mode + register "lpe_acpi_mode" = "1" + register "lpss_acpi_mode" = "1" + register "scc_acpi_mode" = "1" + + # Allow PCIe devices to wake system from suspend + register "pcie_wake_enable" = "1" + + # Enable PIPEA as DP_C + register "gpu_pipea_port_select" = "2" # DP_C + register "gpu_pipea_power_cycle_delay" = "6" # 600ms + register "gpu_pipea_power_on_delay" = "5000" # 500ms + register "gpu_pipea_light_on_delay" = "70" # 7ms + register "gpu_pipea_power_off_delay" = "500" # 50ms + register "gpu_pipea_light_off_delay" = "2000" # 200ms + + # VR PS2 control + register "vnn_ps2_enable" = "1" + register "vcc_ps2_enable" = "1" + + # Disable SLP_X stretching after SUS power well fail. + register "disable_slp_x_stretch_sus_fail" = "1" + + device cpu_cluster 0 on + device lapic 0 on end + end + device domain 0 on + device pci 00.0 on end # SoC router + device pci 02.0 on end # GFX + device pci 11.0 off end # SDIO + device pci 12.0 on end # SD + device pci 13.0 on end # SATA + device pci 14.0 on end # XHCI + device pci 15.0 on end # LPE + device pci 17.0 on end # MMC + device pci 18.0 on end # SIO_DMA1 + device pci 18.1 on end # I2C1 + device pci 18.2 on end # I2C2 + device pci 18.3 off end # I2C3 + device pci 18.4 off end # I2C4 + device pci 18.5 on end # I2C5 + device pci 18.6 on end # I2C6 + device pci 18.7 off end # I2C7 + device pci 1a.0 on end # TXE + device pci 1b.0 on end # HDA + device pci 1c.0 on end # PCIE_PORT1 + device pci 1c.1 on end # PCIE_PORT2 + device pci 1c.2 off end # PCIE_PORT3 + device pci 1c.3 off end # PCIE_PORT4 + device pci 1d.0 on end # EHCI + device pci 1e.0 on end # SIO_DMA2 + device pci 1e.1 off end # PWM1 + device pci 1e.2 off end # PWM2 + device pci 1e.3 off end # HSUART1 + device pci 1e.4 off end # HSUART2 + device pci 1e.5 off end # SPI + device pci 1f.0 on + chip ec/google/chromeec + # We only have one init function that + # we need to call to initialize the + # keyboard part of the EC. + device pnp ff.1 on # dummy address + end + end + end # LPC Bridge + device pci 1f.3 off end # SMBus + end +end diff --git a/src/mainboard/google/rambi/dsdt.asl b/src/mainboard/google/rambi/dsdt.asl new file mode 100644 index 0000000000..01b816b47d --- /dev/null +++ b/src/mainboard/google/rambi/dsdt.asl @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x05, // DSDT revision: ACPI v5.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include + + // global NVS and variables + #include + + #include + + Scope (\_SB) { + Device (PCI0) + { + //#include + #include + } + + /* Dynamic Platform Thermal Framework */ + #include "acpi/dptf.asl" + } + + #include "acpi/chromeos.asl" + #include + + /* Chipset specific sleep states */ + #include + + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/google/rambi/ec.c b/src/mainboard/google/rambi/ec.c new file mode 100644 index 0000000000..c055d615a7 --- /dev/null +++ b/src/mainboard/google/rambi/ec.c @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/rambi/ec.h b/src/mainboard/google/rambi/ec.h new file mode 100644 index 0000000000..bd98b2acbc --- /dev/null +++ b/src/mainboard/google/rambi/ec.h @@ -0,0 +1,66 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +/* GPIO_S0_000 is EC_SCI#, but it is bit 24 in GPE_STS */ +#define EC_SCI_GPI 24 +/* GPIO_S5_07 is EC_SMI#, but it is bit 23 in GPE_STS and ALT_GPIO_SMI. */ +#define EC_SMI_GPI 23 + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/rambi/fadt.c b/src/mainboard/google/rambi/fadt.c new file mode 100644 index 0000000000..dfd258fa8b --- /dev/null +++ b/src/mainboard/google/rambi/fadt.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + acpi_fill_in_fadt(fadt); + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/rambi/gpio.c b/src/mainboard/google/rambi/gpio.c new file mode 100644 index 0000000000..45f536db21 --- /dev/null +++ b/src/mainboard/google/rambi/gpio.c @@ -0,0 +1,235 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "irqroute.h" + +/* TODO(SHAWNN): Modify gpios labeled 'INT' for interrupt handling */ +/* NCORE GPIOs */ +static const struct soc_gpio_map gpncore_gpio_map[] = { + GPIO_FUNC2, /* S0_NC00 - INT_HDMI_HPD - INT */ + GPIO_FUNC2, /* S0_NC01 - HDMI_DDCDATA_SW */ + GPIO_FUNC2, /* S0_NC02 - HDMI_DDCCLK_SW */ + GPIO_NC, /* S0_NC03 - NC */ + GPIO_NC, /* S0_NC04 - NC */ + GPIO_NC, /* S0_NC05 - NC */ + GPIO_FUNC2, /* S0_NC06 - EDP_HPD_L */ + GPIO_INPUT, /* S0_NC07 - DDI1_DDCDATA - STRAP */ + GPIO_NC, /* S0_NC08 - NC */ + GPIO_OUT_HIGH, /* S0_NC09 - SOC_DISP_ON_C */ + GPIO_FUNC2, /* S0_NC10 - SOC_EDP_BLON_C */ + GPIO_FUNC2, /* S0_NC11 - SOC_DPST_PWM_C */ + GPIO_NC, /* S0_NC12 - NC */ + GPIO_INPUT, /* S0_NC13 - GPIO_NC13 - STRAP */ + GPIO_NC, /* S0_NC14 - NC */ + GPIO_DEFAULT, /* S0_NC15 - XDP_GPIO_S0_NC15 */ + GPIO_DEFAULT, /* S0_NC16 - XDP_GPIO_S0_NC16 */ + GPIO_DEFAULT, /* S0_NC17 - XDP_GPIO_S0_NC17 */ + GPIO_DEFAULT, /* S0_NC18 - XDP_GPIO_S0_NC18 */ + GPIO_DEFAULT, /* S0_NC19 - XDP_GPIO_S0_NC19 */ + GPIO_DEFAULT, /* S0_NC20 - XDP_GPIO_S0_NC20 */ + GPIO_DEFAULT, /* S0_NC21 - XDP_GPIO_S0_NC21 */ + GPIO_DEFAULT, /* S0_NC22 - XDP_GPIO_S0_NC22 */ + GPIO_DEFAULT, /* S0_NC23 - XDP_GPIO_S0_NC23 */ + GPIO_NC, /* S0_NC24 - NC */ + GPIO_NC, /* S0_NC25 - NC */ + GPIO_NC, /* S0_NC26 - NC */ + GPIO_END +}; + +/* SCORE GPIOs */ +static const struct soc_gpio_map gpscore_gpio_map[] = { + GPIO_ACPI_SCI, /* S0_SC000 - SOC_KBC_SCI - INT */ + GPIO_FUNC2, /* S0_SC001 - SATA_DEVSLP_C */ + GPIO_NC, /* S0-SC002 - SATA_LED_R_N (NC/PU) */ + GPIO_FUNC1, /* S0-SC003 - PCIE_CLKREQ_IMAGE# */ + GPIO_FUNC1, /* S0-SC004 - PCIE_CLKREQ_WLAN# */ + GPIO_NC, /* S0-SC005 - PCIE_CLKREQ_LAN# (NC) */ + GPIO_NC, /* S0-SC006 - PCIE_CLKREQ3# (NC) */ + GPIO_FUNC(2, PULL_DISABLE, 10K), /* S0-SC007 - SD3_WP external pull */ + GPIO_NC, /* S0-SC008 - ACZ_RST# (NC) */ + GPIO_NC, /* S0-SC009 - ACZ_SYNC (NC) */ + GPIO_NC, /* S0-SC010 - ACZ_BCLK (NC) */ + GPIO_NC, /* S0-SC011 - ACZ_STDOUT (NC) */ + GPIO_NC, /* S0-SC012 - PCH_AZ_CODEC_SDIN0 (NC) */ + GPIO_NC, /* S0-SC013 - NC */ + GPIO_INPUT, /* S0-SC014 - DET_TRIGGER - INT */ + GPIO_INPUT, /* S0-SC015 - AJACK_MICPRES_L - INT */ + GPIO_FUNC(3, PULL_DOWN, 20K), /* S0-SC016 - MMC1_45_CLK */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC017 - MMC1_45_D[0] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC018 - MMC1_45_D[1] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC019 - MMC1_45_D[2] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC020 - MMC1_45_D[3] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC021 - MMC1_45_D[4] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC022 - MMC1_45_D[5] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC023 - MMC1_45_D[6] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC024 - MMC1_45_D[7] */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC025 - MMC1_45_CMD */ + GPIO_FUNC(3, PULL_UP, 20K), /* S0-SC026 - MMC1_45_RST */ + GPIO_NC, /* S0-SC027 - NC */ + GPIO_NC, /* S0-SC028 - NC */ + GPIO_NC, /* S0-SC029 - NC */ + GPIO_NC, /* S0-SC030 - NC */ + GPIO_NC, /* S0-SC031 - NC */ + GPIO_NC, /* S0-SC032 - NC */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* S0-SC033 - SD3_CLK */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC034 - SD3_D0 */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC035 - SD3_D1 */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC036 - SD3_D2 */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC037 - SD3_D3 */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC038 - SD3_CD# */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC039 - SD3_CMD */ + GPIO_NC, /* S0-SC040 - SDMMC3_1P8_EN - TP3 */ + GPIO_FUNC(1, PULL_UP, 20K), /* S0-SC041 - SDIO3_PWR_EN# */ + GPIO_FUNC1, /* S0-SC042 - LPC_LAD0 */ + GPIO_FUNC1, /* S0-SC043 - LPC-LAD1 */ + GPIO_FUNC1, /* S0-SC044 - LPC_LAD2 */ + GPIO_FUNC1, /* S0-SC045 - LPC_LAD3 */ + GPIO_FUNC1, /* S0-SC046 - LPC_LFRAME# */ + GPIO_FUNC1, /* S0-SC047 - PCLK_TPM */ + GPIO_FUNC1, /* S0-SC048 - CLK_PCI_EC */ + GPIO_FUNC1, /* S0-SC049 - LPC_CLKRUN_L */ + GPIO_NC, /* S0-SC050 - IRQ_SERIRQ */ + GPIO_NC, /* S0-SC051 - SMB_SOC_DATA (XDP) */ + GPIO_NC, /* S0-SC052 - SMB_SOC_CLK (XDP) */ + GPIO_NC, /* S0-SC053 - SMB_SOC_ALERTB (NC) */ + GPIO_DEFAULT, /* S0-SC054 - NC */ + GPIO_DIRQ, /* S0-SC055 - TRACKPAD_INT_DX */ + GPIO_INPUT, /* S0-SC056 - GPIO_S0_SC_56 - STRAP */ + GPIO_FUNC1, /* S0-SC057 - PCH_UART_TXD */ + GPIO_INPUT, /* S0-SC058 - SIM_DET_C */ + GPIO_INPUT_LEGACY, /* S0-SC059 - EC_IN_RW_C */ + GPIO_NC, /* S0-SC060 - NC */ + GPIO_FUNC1, /* S0-SC061 - SOC_UART_RX */ + GPIO_FUNC1, /* S0-SC062 - I2S_BCLK */ + GPIO_FUNC1, /* S0-SC063 - I2S_LRCLK */ + GPIO_FUNC1, /* S0-SC064 - I2S_DIN */ + GPIO_FUNC1, /* S0-SC065 - I2S_DOUT */ + GPIO_FUNC1, /* S0-SC066 - SIO_SPI_CS# */ + GPIO_FUNC1, /* S0-SC067 - SIO_SPI_MISO */ + GPIO_FUNC1, /* S0-SC068 - SIO_SPI_MOSI */ + GPIO_FUNC1, /* S0-SC069 - SIO_SPI_CLK */ + GPIO_DIRQ, /* S0-SC070 - ALS_INT_L - INT */ + GPIO_NC, /* S0-SC071 - NC */ + GPIO_DIRQ, /* S0-SC072 - TOUCH_INT_L_DX */ + GPIO_NC, /* S0-SC073 - NC */ + GPIO_NC, /* S0-SC074 - SIO_UART2_RXD (NC) */ + GPIO_NC, /* S0-SC075 - SIO_UART2_TXD (NC) */ + GPIO_INPUT, /* S0-SC076 - BIOS_STRAP - STRAP */ + GPIO_INPUT, /* S0-SC077 - SOC_OVERRIDE - STRAP */ + GPIO_FUNC1, /* S0-SC078 - I2C_0_SDA */ + GPIO_FUNC1, /* S0-SC079 - I2C_0_SCL */ + GPIO_FUNC1, /* S0-SC080 - I2C_1_SDA */ + GPIO_FUNC1, /* S0-SC081 - I2C_1_SCL */ + GPIO_NC, /* S0-SC082 - NC */ + GPIO_NC, /* S0-SC083 - NC */ + GPIO_NC, /* S0-SC084 - NC */ + GPIO_NC, /* S0-SC085 - NC */ + GPIO_FUNC1, /* S0-SC086 - I2C_4_SDA */ + GPIO_FUNC1, /* S0-SC087 - I2C_4_SCL */ + GPIO_FUNC1, /* S0-SC088 - I2C_5_SDA */ + GPIO_FUNC1, /* S0-SC089 - I2C_5_SCL */ + GPIO_NC, /* S0-SC090 - NC */ + GPIO_NC, /* S0-SC091 - NC */ + GPIO_NC, /* S0-SC092 - I2C_NGFF_SDA (NC/PU) */ + GPIO_NC, /* S0-SC093 - I2C_NGFF_SCL (NC/PU) */ + GPIO_NC, /* S0-SC094 - NC */ + GPIO_NC, /* S0-SC095 - SIO_PWM1 (NC) */ + GPIO_FUNC1, /* S0-SC096 - I2S_MCLK */ + GPIO_NC, /* S0-SC097 - NC */ + GPIO_NC, /* S0-SC098 - NC */ + GPIO_NC, /* S0-SC099 - NC */ + GPIO_NC, /* S0-SC100 - NC */ + GPIO_DIRQ, /* S0-SC101 - KBD_IRQ# */ + GPIO_END +}; + +/* SSUS GPIOs */ +static const struct soc_gpio_map gpssus_gpio_map[] = { + GPIO_ACPI_WAKE, /* S500 - PCH_WAKE# */ + GPIO_ACPI_WAKE, /* S501 - TRACKPAD_INT# - INT */ + GPIO_ACPI_WAKE, /* S502 - TOUCH_INT# - INT */ + GPIO_FUNC6, /* S503 - LTE_WAKE_L# - INT */ + GPIO_NC, /* S504 - SOC_JTAG2_TDO (NC/PU) */ + GPIO_FUNC1, /* S505 - SUS_CLK_WLAN (NC) */ + GPIO_INPUT_PU, /* S506 - PCH_SPI_WP */ + GPIO_ACPI_SMI, /* S507 - SOC_KBC_SMI - INT */ + GPIO_NC, /* S508 - NC */ + GPIO_DIRQ, /* S509 - MUX_AUD_INT1# */ + GPIO_OUT_HIGH, /* S510 - WIFI_DISABLE_L */ + GPIO_FUNC0, /* S511 - SUSPWRDNACK */ + GPIO_FUNC0, /* S512 - WIFI_SUSCLK */ + GPIO_FUNC0, /* S513 - SLP_SX */ + GPIO_NC, /* S514 - NC */ + GPIO_FUNC0, /* S515 - WLAN_WAKE_L - INT */ + GPIO_FUNC0, /* S516 - PCH_PWRBTN_L */ + GPIO_NC, /* S517 - NC */ + GPIO_FUNC0, /* S518 - SUS_STAT# */ + GPIO_FUNC0, /* S519 - USB_OC0# */ + GPIO_FUNC0, /* S520 - USB_OC1# */ + GPIO_NC, /* S521 - NC */ + GPIO_NC, /* S522 - XDP_GPIO_DFX0 */ + GPIO_NC, /* S523 - XDP_GPIO_DFX1 */ + GPIO_NC, /* S524 - XDP_GPIO_DFX2 */ + GPIO_NC, /* S525 - XDP_GPIO_DFX3 */ + GPIO_NC, /* S526 - XDP_GPIO_DFX4 */ + GPIO_NC, /* S527 - XDP_GPIO_DFX5 */ + GPIO_NC, /* S528 - XDP_GPIO_DFX6 */ + GPIO_NC, /* S529 - XDP_GPIO_DFX7 */ + GPIO_NC, /* S530 - XDP_GPIO_DFX8 */ + GPIO_NC, /* S531 - NC */ + GPIO_NC, /* S532 - NC */ + GPIO_NC, /* S533 - NC */ + GPIO_NC, /* S534 - NC */ + GPIO_OUT_HIGH, /* S535 - LTE_DISABLE_L */ + GPIO_NC, /* S536 - NC */ + GPIO_INPUT, /* S537 - RAM_ID0 */ + GPIO_INPUT, /* S538 - RAM_ID1 */ + GPIO_INPUT, /* S539 - RAM_ID2 */ + GPIO_NC, /* S540 - NC */ + GPIO_NC, /* S541 - NC */ + GPIO_NC, /* S542 - NC */ + GPIO_NC, /* S543 - NC */ + GPIO_END +}; + +static const u8 core_dedicated_irq[GPIO_MAX_DIRQS] = { + [TPAD_IRQ_OFFSET] = TPAD_IRQ_GPIO, + [TOUCH_IRQ_OFFSET] = TOUCH_IRQ_GPIO, + [I8042_IRQ_OFFSET] = I8042_IRQ_GPIO, + [ALS_IRQ_OFFSET] = ALS_IRQ_GPIO, +}; + +static const u8 sus_dedicated_irq[GPIO_MAX_DIRQS] = { + [CODEC_IRQ_OFFSET] = CODEC_IRQ_GPIO, +}; + +static struct soc_gpio_config gpio_config = { + .ncore = gpncore_gpio_map, + .score = gpscore_gpio_map, + .ssus = gpssus_gpio_map, + .core_dirq = &core_dedicated_irq, + .sus_dirq = &sus_dedicated_irq, +}; + +struct soc_gpio_config* mainboard_get_gpios(void) +{ + return &gpio_config; +} diff --git a/src/mainboard/google/rambi/irqroute.c b/src/mainboard/google/rambi/irqroute.c new file mode 100644 index 0000000000..552be8f605 --- /dev/null +++ b/src/mainboard/google/rambi/irqroute.c @@ -0,0 +1,22 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "irqroute.h" + +DEFINE_IRQ_ROUTES; diff --git a/src/mainboard/google/rambi/irqroute.h b/src/mainboard/google/rambi/irqroute.h new file mode 100644 index 0000000000..074e47093e --- /dev/null +++ b/src/mainboard/google/rambi/irqroute.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#define PCI_DEV_PIRQ_ROUTES \ + PCI_DEV_PIRQ_ROUTE(GFX_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SDIO_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SD_DEV, C, D, E, F), \ + PCI_DEV_PIRQ_ROUTE(SATA_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(XHCI_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(LPE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(MMC_DEV, D, E, F, G), \ + PCI_DEV_PIRQ_ROUTE(SIO1_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(TXE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(HDA_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(PCIE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(EHCI_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SIO2_DEV, B, C, D, E), \ + PCI_DEV_PIRQ_ROUTE(PCU_DEV, A, B, C, D) + +#define PIRQ_PIC_ROUTES \ + PIRQ_PIC(A, DISABLE), \ + PIRQ_PIC(B, DISABLE), \ + PIRQ_PIC(C, DISABLE), \ + PIRQ_PIC(D, DISABLE), \ + PIRQ_PIC(E, DISABLE), \ + PIRQ_PIC(F, DISABLE), \ + PIRQ_PIC(G, DISABLE), \ + PIRQ_PIC(H, DISABLE) + +/* CORE bank DIRQs - up to 16 supported */ +#define TPAD_IRQ_OFFSET 0 +#define TOUCH_IRQ_OFFSET 1 +#define I8042_IRQ_OFFSET 2 +#define ALS_IRQ_OFFSET 3 +/* Corresponding SCORE GPIO pins */ +#define TPAD_IRQ_GPIO 55 +#define TOUCH_IRQ_GPIO 72 +#define I8042_IRQ_GPIO 101 +#define ALS_IRQ_GPIO 70 + +/* SUS bank DIRQs - up to 16 supported */ +#define CODEC_IRQ_OFFSET 0 +/* Corresponding SUS GPIO pins */ +#define CODEC_IRQ_GPIO 9 diff --git a/src/mainboard/google/rambi/mainboard.c b/src/mainboard/google/rambi/mainboard.c new file mode 100644 index 0000000000..90a7495269 --- /dev/null +++ b/src/mainboard/google/rambi/mainboard.c @@ -0,0 +1,187 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include +#include "ec.h" +#include "onboard.h" +#include +#include + +void mainboard_suspend_resume(void) +{ +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 1; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV + * bit 2 = EFP (HDMI) + * bit 3 = LFP (eDP)* + * bit 4 = CRT2 + * bit 5 = TV2 + * bit 6 = EFP2 + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0008; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +static void edp_vdden_cb(void *unused) +{ + ncore_select_func(SOC_DDI1_VDDEN_PAD, PAD_FUNC2); +} + +BOOT_STATE_INIT_ENTRIES(edp_vdden_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, edp_vdden_cb, NULL), +}; diff --git a/src/mainboard/google/rambi/mainboard_smi.c b/src/mainboard/google/rambi/mainboard_smi.c new file mode 100644 index 0000000000..57c5835e9a --- /dev/null +++ b/src/mainboard/google/rambi/mainboard_smi.c @@ -0,0 +1,146 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include "ec.h" + +#include +#include + +/* The wake gpio is SUS_GPIO[0]. */ +#define WAKE_GPIO_EN SUS_GPIO_EN0 + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static uint8_t mainboard_smi_ec(void) +{ + uint8_t cmd = google_chromeec_get_event(); + uint16_t pmbase = get_pmbase(); + uint32_t pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(pmbase + PM1_CNT); + pm1_cnt |= SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT); + outl(pm1_cnt, pmbase + PM1_CNT); + break; + } + + return cmd; +} + +/* The entire 32-bit ALT_GPIO_SMI register is passed as a parameter. Note, that + * this includes the enable bits in the lower 16 bits. */ +void mainboard_smi_gpi(uint32_t alt_gpio_smi) +{ + if (alt_gpio_smi & (1 << EC_SMI_GPI)) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +void mainboard_smi_sleep(uint8_t slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s3u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + /* Enable wake pin in GPE block. */ + enable_gpe(WAKE_GPIO_EN); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s5u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); +} + +int mainboard_smi_apmc(uint8_t apmc) +{ + switch (apmc) { + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/rambi/onboard.h b/src/mainboard/google/rambi/onboard.h new file mode 100644 index 0000000000..8ea2e8a475 --- /dev/null +++ b/src/mainboard/google/rambi/onboard.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#include "irqroute.h" + +/* PCH wake signal from EC. */ +#define BOARD_PCH_WAKE_GPIO ACPI_ENABLE_WAKE_SUS_GPIO(0) + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ GPIO_S0_DED_IRQ(TPAD_IRQ_OFFSET) +#define BOARD_TRACKPAD_WAKE_GPIO ACPI_ENABLE_WAKE_SUS_GPIO(1) +#define BOARD_TRACKPAD_I2C_BUS 0 +#define BOARD_TRACKPAD_I2C_ADDR 0x4b + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ GPIO_S0_DED_IRQ(TOUCH_IRQ_OFFSET) +#define BOARD_TOUCHSCREEN_WAKE_GPIO ACPI_ENABLE_WAKE_SUS_GPIO(2) +#define BOARD_TOUCHSCREEN_I2C_BUS 5 +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a /* TODO(shawnn): Check this */ + +#define BOARD_I8042_IRQ GPIO_S0_DED_IRQ(I8042_IRQ_OFFSET) +#define BOARD_CODEC_IRQ GPIO_S5_DED_IRQ(CODEC_IRQ_OFFSET) +#define BOARD_ALS_IRQ GPIO_S0_DED_IRQ(ALS_IRQ_OFFSET) + +#endif diff --git a/src/mainboard/google/rambi/romstage.c b/src/mainboard/google/rambi/romstage.c new file mode 100644 index 0000000000..d9fbc0cced --- /dev/null +++ b/src/mainboard/google/rambi/romstage.c @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * RAM_ID[2:0] are on GPIO_SSUS[39:37] + * 0b000 - 4GiB total - 2 x 2GiB Micron MT41K256M16HA-125:E 1600MHz + * 0b001 - 4GiB total - 2 x 2GiB Hynix H5TC4G63AFR-PBA 1600MHz + * 0b010 - 2GiB total - 2 x 1GiB Micron MT41K128M16JT-125:K 1600MHz + * 0b011 - 2GiB total - 2 x 1GiB Hynix H5TC2G63FFR-PBA 1600MHz + * 0b100 - 2GiB total - 1 x 2GiB Micron MT41K256M16HA-125:E 1600MHz + * 0b101 - 2GiB total - 1 x 2GiB Hynix H5TC4G63AFR-PBA 1600MHz + */ +static const uint32_t dual_channel_config = + (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); + +#define SPD_SIZE 256 +#define GPIO_SSUS_37_PAD 57 +#define GPIO_SSUS_38_PAD 50 +#define GPIO_SSUS_39_PAD 58 + +static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual) +{ + int ram_id = 0; + + /* The ram_id[2:0] pullups on rambi are too large for the default 20K + * pulldown on the pad. Therefore, disable the internal pull resistor to + * read high values correctly. */ + ssus_disable_internal_pull(GPIO_SSUS_37_PAD); + ssus_disable_internal_pull(GPIO_SSUS_38_PAD); + ssus_disable_internal_pull(GPIO_SSUS_39_PAD); + + ram_id |= (ssus_get_gpio(GPIO_SSUS_37_PAD) << 0); + ram_id |= (ssus_get_gpio(GPIO_SSUS_38_PAD) << 1); + ram_id |= (ssus_get_gpio(GPIO_SSUS_39_PAD) << 2); + + printk(BIOS_DEBUG, "ram_id=%d, total_spds: %d\n", ram_id, total_spds); + + if (ram_id >= total_spds) + return NULL; + + /* Single channel configs */ + if (dual_channel_config & (1 << ram_id)) + *dual = 1; + + return &spd_file_content[SPD_SIZE * ram_id]; +} + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct cbfs_file *spd_file; + void *spd_content; + int dual_channel = 0; + + struct mrc_params mp = { + .mainboard = { + .dram_type = DRAM_DDR3L, + .dram_info_location = DRAM_INFO_SPD_MEM, + .weaker_odt_settings = 1, + }, + }; + + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + + /* Both channels are always present. */ + spd_content = get_spd_pointer(CBFS_SUBHEADER(spd_file), + ntohl(spd_file->len) / SPD_SIZE, + &dual_channel); + mp.mainboard.dram_data[0] = spd_content; + if (dual_channel) + mp.mainboard.dram_data[1] = spd_content; + + rp->mrc_params = ∓ + romstage_common(rp); +} diff --git a/src/mainboard/google/rambi/spd/Makefile.inc b/src/mainboard/google/rambi/spd/Makefile.inc new file mode 100644 index 0000000000..70ba9108c7 --- /dev/null +++ b/src/mainboard/google/rambi/spd/Makefile.inc @@ -0,0 +1,50 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +SPD_BIN = $(obj)/spd.bin + +# Order matters for SPD sources. The following indicies +# define the SPD data to use. +# 0b000 - 4GiB total - 2 x 2GiB Micron MT41K256M16HA-125:E 1600MHz +# 0b001 - 4GiB total - 2 x 2GiB Hynix H5TC4G63AFR-PBA 1600MHz +# 0b010 - 2GiB total - 2 x 1GiB Micron MT41K128M16JT-125:K 1600MHz +# 0b011 - 2GiB total - 2 x 1GiB Hynix H5TC2G63FFR-PBA 1600MHz +# 0b100 - 2GiB total - 1 x 2GiB Micron MT41K256M16HA-125:E 1600MHz +# 0b101 - 2GiB total - 1 x 2GiB Hynix H5TC4G63AFR-PBA 1600MHz +SPD_SOURCES = micron_2GiB_dimm_MT41K256M16HA-125 +SPD_SOURCES += hynix_2GiB_dimm_H5TC4G63AFR-PBA +SPD_SOURCES += micron_1GiB_dimm_MT41K128M16JT-125 +SPD_SOURCES += hynix_1GiB_dimm_H5TC2G63FFR-PBA +SPD_SOURCES += micron_2GiB_dimm_MT41K256M16HA-125 +SPD_SOURCES += hynix_2GiB_dimm_H5TC4G63AFR-PBA + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/spd/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab +spd.bin-position := $(CONFIG_SPD_CBFS_ADDRESS) diff --git a/src/mainboard/google/rambi/spd/hynix_1GiB_dimm_H5TC2G63FFR-PBA.spd.hex b/src/mainboard/google/rambi/spd/hynix_1GiB_dimm_H5TC2G63FFR-PBA.spd.hex new file mode 100644 index 0000000000..4bd8e0eca6 --- /dev/null +++ b/src/mainboard/google/rambi/spd/hynix_1GiB_dimm_H5TC2G63FFR-PBA.spd.hex @@ -0,0 +1,32 @@ +92 12 0b 03 03 11 02 02 +03 52 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 81 +00 05 3c 3c 01 40 83 01 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 11 22 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 ad 01 +00 00 00 00 00 00 41 5f +48 4d 54 33 31 32 53 36 +44 46 52 36 41 2d 50 42 +20 20 4e 30 80 ad 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff diff --git a/src/mainboard/google/rambi/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex b/src/mainboard/google/rambi/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex new file mode 100644 index 0000000000..ff4fd29862 --- /dev/null +++ b/src/mainboard/google/rambi/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex @@ -0,0 +1,32 @@ +92 12 0b 03 04 19 02 02 +03 52 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 81 +20 08 3c 3c 01 40 83 01 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 11 62 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 ad 01 +00 00 00 00 00 00 ff ab +48 4d 54 34 32 35 53 36 +41 46 52 36 41 2d 50 42 +20 20 4e 30 80 ad 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff diff --git a/src/mainboard/google/rambi/spd/micron_1GiB_dimm_MT41K128M16JT-125.spd.hex b/src/mainboard/google/rambi/spd/micron_1GiB_dimm_MT41K128M16JT-125.spd.hex new file mode 100644 index 0000000000..f99c92a2a7 --- /dev/null +++ b/src/mainboard/google/rambi/spd/micron_1GiB_dimm_MT41K128M16JT-125.spd.hex @@ -0,0 +1,32 @@ +92 11 0b 03 03 11 02 02 +03 11 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 86 +50 00 3c 3c 01 40 83 05 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 01 02 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2c 00 +00 00 00 00 00 00 6a 15 +34 4b 54 46 32 35 36 36 +34 48 5a 2d 31 47 36 45 +31 20 45 31 80 2c 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff diff --git a/src/mainboard/google/rambi/spd/micron_2GiB_dimm_MT41K256M16HA-125.spd.hex b/src/mainboard/google/rambi/spd/micron_2GiB_dimm_MT41K256M16HA-125.spd.hex new file mode 100644 index 0000000000..f3bcb56245 --- /dev/null +++ b/src/mainboard/google/rambi/spd/micron_2GiB_dimm_MT41K256M16HA-125.spd.hex @@ -0,0 +1,32 @@ +92 11 0b 03 04 19 02 02 +03 11 01 08 0a 00 fe 00 +69 78 69 3c 69 11 18 86 +20 08 3c 3c 01 40 83 05 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 0f 01 02 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2c 00 +00 00 00 00 00 00 19 d2 +34 4b 54 46 32 35 36 36 +34 48 5a 2d 31 47 36 45 +31 20 45 31 80 2c 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff +ff ff ff ff ff ff ff ff diff --git a/src/mainboard/google/rambi/w25q64.c b/src/mainboard/google/rambi/w25q64.c new file mode 100644 index 0000000000..9692b4c10a --- /dev/null +++ b/src/mainboard/google/rambi/w25q64.c @@ -0,0 +1,74 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +/* + * SPI lockdown configuration W25Q64FW. + */ +#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */ +#define SPI_OPTYPE_0 0x01 /* Write, no address */ + +#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */ +#define SPI_OPTYPE_1 0x03 /* Write, address required */ + +#define SPI_OPMENU_2 0x03 /* READ: Read Data */ +#define SPI_OPTYPE_2 0x02 /* Read, address required */ + +#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */ +#define SPI_OPTYPE_3 0x00 /* Read, no address */ + +#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */ +#define SPI_OPTYPE_4 0x03 /* Write, address required */ + +#define SPI_OPMENU_5 0x9f /* RDID: Read ID */ +#define SPI_OPTYPE_5 0x00 /* Read, no address */ + +#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */ +#define SPI_OPTYPE_6 0x03 /* Write, address required */ + +#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */ +#define SPI_OPTYPE_7 0x02 /* Read, address required */ + +#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */ +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0 << 0)) +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | (SPI_OPMENU_4 << 0)) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | (SPI_OPMENU_0 << 0)) +#define SPI_VSCC (WG_64_BYTE | EO(0x20) | BES_4_KB) + +static const struct spi_config spi_config = { + .preop = SPI_OPPREFIX, + .optype = SPI_OPTYPE, + .opmenu = { SPI_OPMENU_LOWER, SPI_OPMENU_UPPER }, + .lvscc = SPI_VSCC, + .uvscc = SPI_VSCC, +}; + +int mainboard_get_spi_config(struct spi_config *cfg) +{ + memcpy(cfg, &spi_config, sizeof(*cfg)); + + return 0; +} diff --git a/src/mainboard/google/rush/Kconfig b/src/mainboard/google/rush/Kconfig new file mode 100644 index 0000000000..6e4f5134f8 --- /dev/null +++ b/src/mainboard/google/rush/Kconfig @@ -0,0 +1,104 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_RUSH + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select MAINBOARD_DO_NATIVE_VGA_INIT + select SPI_FLASH + select SOC_NVIDIA_TEGRA132 + select MAINBOARD_DO_SOR_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select VIRTUAL_DEV_SWITCH + select ARCH_SPINTABLE + +config MAINBOARD_DIR + string + default google/rush + +config MAINBOARD_PART_NUMBER + string + default "Rush" + +config DRAM_SIZE_MB + int + default 2048 + +choice + prompt "BCT boot media" + default RUSH_BCT_CFG_SPI + help + Which boot media to configure the BCT for. + +config RUSH_BCT_CFG_SPI + bool "SPI" + help + Configure the BCT for booting from SPI. + +config RUSH_BCT_CFG_EMMC + bool "eMMC" + help + Configure the BCT for booting from eMMC. + +endchoice + +config BOOT_MEDIA_SPI_BUS + int "SPI bus with boot media ROM" + range 1 6 + depends on RUSH_BCT_CFG_SPI + default 4 + help + Which SPI bus the boot media is connected to. + +config BOOT_MEDIA_SPI_CHIP_SELECT + int "Chip select for SPI boot media" + range 0 3 + depends on RUSH_BCT_CFG_SPI + default 0 + help + Which chip select to use for boot media. + +# For rush, we are using vboot2. Thus, index for stages: +# VBOOT_ROMSTAGE_INDEX -> Use default value of 0x2 +# VBOOT_RAMSTAGE_INDEX -> Use 0x3 +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config DRIVER_TPM_I2C_BUS + hex + default 0x2 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 1 + +endif # BOARD_GOOGLE_RUSH diff --git a/src/mainboard/google/rush/Makefile.inc b/src/mainboard/google/rush/Makefile.inc new file mode 100644 index 0000000000..3a8be57b20 --- /dev/null +++ b/src/mainboard/google/rush/Makefile.inc @@ -0,0 +1,51 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# Add a handler for BCT config files +$(call add-special-class,bct-cfg) +bct-cfg-handler= $(eval $(obj)/generated/bct.cfg: $(1)$(2)) + +$(obj)/generated/bct.cfg: + @printf " CAT $(subst $(obj)/,,$(@))\n" + cat $^ > $@ + +subdirs-y += bct + +bootblock-y += bootblock.c +bootblock-y += pmic.c +bootblock-y += reset.c + +verstage-y += verstage.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += chromeos.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld +verstage-y += memlayout.ld \ No newline at end of file diff --git a/src/mainboard/google/rush/bct/Makefile.inc b/src/mainboard/google/rush/bct/Makefile.inc new file mode 100644 index 0000000000..d4a2c24201 --- /dev/null +++ b/src/mainboard/google/rush/bct/Makefile.inc @@ -0,0 +1,27 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bct-cfg-$(CONFIG_RUSH_BCT_CFG_EMMC) += emmc.cfg +bct-cfg-$(CONFIG_RUSH_BCT_CFG_SPI) += spi.cfg +bct-cfg-y += odmdata.cfg +bct-cfg-y += jtag.cfg + +# Note when SDRAM config (sdram-*.cfg) files are changed, we have to regenerate +# the include files (sdram-*.inc) by running "./cfg2inc.sh sdram-*.cfg". +# TODO(hungte) Change cfg2inc.sh to NVIDIA's official tool in cbootimage. diff --git a/src/mainboard/google/rush/bct/cfg2inc.sh b/src/mainboard/google/rush/bct/cfg2inc.sh new file mode 100755 index 0000000000..a9c629b523 --- /dev/null +++ b/src/mainboard/google/rush/bct/cfg2inc.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This file is part of the coreboot project. +# +# Copyright 2014 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +bct_cfg2inc() { + local in_file="$1" + local out_file="$2" + echo "{ /* generated from ${in_file}; do not edit. */" >"${out_file}" + # Note currently we can only handle DDR3 type memory, even in C + # implementation. + sed "/^#.*$/d; s/^SDRAM.0./ /; s/\r$//; s/;$/,/;" \ + "${in_file}" >> "${out_file}" + echo "}," >>"${out_file}" +} + +for file in $@; do + echo "Generating $file => ${file%cfg}inc..." + bct_cfg2inc "${file}" "${file%cfg}inc" +done diff --git a/src/mainboard/google/rush/bct/emmc.cfg b/src/mainboard/google/rush/bct/emmc.cfg new file mode 100644 index 0000000000..430ffd6d4b --- /dev/null +++ b/src/mainboard/google/rush/bct/emmc.cfg @@ -0,0 +1,13 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00130001; +BlockSize = 0x00004000; +PageSize = 0x00000200; +PartitionSize = 0x01000000; + +DevType[0] = NvBootDevType_Sdmmc; +DeviceParam[0].SdmmcParams.ClockDivider = 0x00000009; +DeviceParam[0].SdmmcParams.DataWidth = NvBootSdmmcDataWidth_8Bit; +DeviceParam[0].SdmmcParams.MaxPowerClassSupported = 0x00000000; +DeviceParam[0].SdmmcParams.MultiPageSupport = 0x00000000; diff --git a/src/mainboard/google/rush/bct/jtag.cfg b/src/mainboard/google/rush/bct/jtag.cfg new file mode 100644 index 0000000000..f43e143377 --- /dev/null +++ b/src/mainboard/google/rush/bct/jtag.cfg @@ -0,0 +1,16 @@ +# +# Set JtagCtrl to 1 to reenable Jtag +# +JtagCtrl = 0; +# +# Fill in chip unique id +# +# ChipUid can be found by running tegrarcm in tegra recovery mode +# (also hooking up A-A USB cable) and looking for console output +# on line starting with "Chip UID:" +# +# Command example: +# $ sudo tegrarcm --bct=/build/nyan/firmware/bct/board.bct --bootloader=/build/nyan/firmware/u-boot.bin --loadaddr=0x80108000 +# Where board.bct and u-boot.bin do not have to be prebuilt. +# +ChipUid = 0x00000000000000000000000000000000; diff --git a/src/mainboard/google/rush/bct/odmdata.cfg b/src/mainboard/google/rush/bct/odmdata.cfg new file mode 100644 index 0000000000..d0ab2bf8fb --- /dev/null +++ b/src/mainboard/google/rush/bct/odmdata.cfg @@ -0,0 +1 @@ +OdmData = 0x80080000; diff --git a/src/mainboard/google/rush/bct/sdram-hynix-2GB-792.inc b/src/mainboard/google/rush/bct/sdram-hynix-2GB-792.inc new file mode 100644 index 0000000000..60bf4168f7 --- /dev/null +++ b/src/mainboard/google/rush/bct/sdram-hynix-2GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-0001-792-2GB.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000025, + .EmcRfc = 0x000000cd, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000007, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000003, + .EmcEInputDuration = 0x0000000c, + .EmcPutermExtra = 0x00090000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000002, + .EmcQSafe = 0x00000011, + .EmcRdv = 0x00000017, + .EmcRdvMask = 0x00000019, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017eb, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005fa, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000003, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000c7, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x000000d7, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x0000182c, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000002, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80001d71, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200018, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00f7000e, + .EmcMrsWaitCnt2 = 0x00f7000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x000040a0, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003025, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00701b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x0000000e, + .EmcDllXformAddr1 = 0x0000000e, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x0000000e, + .EmcDllXformAddr4 = 0x00000000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x0000000b, + .EmcDllXformDq1 = 0x0000000b, + .EmcDllXformDq2 = 0x0000000b, + .EmcDllXformDq3 = 0x0000000b, + .EmcDllXformDq4 = 0x0000000b, + .EmcDllXformDq5 = 0x0000000b, + .EmcDllXformDq6 = 0x0000000b, + .EmcDllXformDq7 = 0x0000000b, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80001d71, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0020013d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000707, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x017fffff, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0505003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000005, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08050202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x736c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xf8000000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush/bct/sdram-hynix-2GB-924.inc b/src/mainboard/google/rush/bct/sdram-hynix-2GB-924.inc new file mode 100644 index 0000000000..44d77cb4d9 --- /dev/null +++ b/src/mainboard/google/rush/bct/sdram-hynix-2GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-2GB-924.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430101, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000000, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000002b, + .EmcRfc = 0x000000f0, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x0000001e, + .EmcRp = 0x0000000b, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x0000000a, + .EmcW2r = 0x0000000f, + .EmcR2p = 0x00000005, + .EmcW2p = 0x00000016, + .EmcRdRcd = 0x0000000b, + .EmcWrRcd = 0x0000000b, + .EmcRrd = 0x00000004, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000007, + .EmcWdvMask = 0x00000007, + .EmcQUse = 0x0000000d, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000f, + .EmcPutermExtra = 0x000a0000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000016, + .EmcRdv = 0x0000001a, + .EmcRdvMask = 0x0000001c, + .EmcQpop = 0x00000011, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x00001be7, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000006f9, + .EmcPdEx2Wr = 0x00000004, + .EmcPdEx2Rd = 0x00000015, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x000000e7, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x000000fb, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000006, + .EmcTckesr = 0x00000007, + .EmcTpd = 0x00000006, + .EmcTfaw = 0x00000022, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x0000000a, + .EmcTClkStop = 0x0000000a, + .EmcTRefBw = 0x00001c28, + .EmcFbioCfg5 = 0x104ab898, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x80000f15, + .EmcEmrs = 0x80100002, + .EmcEmrs2 = 0x80200020, + .EmcEmrs3 = 0x80300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x00cd000e, + .EmcMrsWaitCnt2 = 0x00cd000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800037ea, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00400b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000002, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x007fc005, + .EmcDllXformDqs1 = 0x007fc005, + .EmcDllXformDqs2 = 0x007f8008, + .EmcDllXformDqs3 = 0x007f8008, + .EmcDllXformDqs4 = 0x007fc005, + .EmcDllXformDqs5 = 0x007f8008, + .EmcDllXformDqs6 = 0x007fc005, + .EmcDllXformDqs7 = 0x007fc005, + .EmcDllXformDqs8 = 0x007fc005, + .EmcDllXformDqs9 = 0x007fc005, + .EmcDllXformDqs10 = 0x007f8008, + .EmcDllXformDqs11 = 0x007f8008, + .EmcDllXformDqs12 = 0x007fc005, + .EmcDllXformDqs13 = 0x007f8008, + .EmcDllXformDqs14 = 0x007fc005, + .EmcDllXformDqs15 = 0x007fc005, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00018000, + .EmcDllXformAddr1 = 0x00018000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00018000, + .EmcDllXformAddr4 = 0x00018000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00000007, + .EmcDllXformDq1 = 0x00000007, + .EmcDllXformDq2 = 0x00000007, + .EmcDllXformDq3 = 0x00000007, + .EmcDllXformDq4 = 0x00000007, + .EmcDllXformDq5 = 0x00000007, + .EmcDllXformDq6 = 0x00000007, + .EmcDllXformDq7 = 0x00000007, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x0000004c, + .EmcZcalMrwCmd = 0x80000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x00000000, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x80000f15, + .EmcWarmBootMrsExtra = 0x80100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fff2f97, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x5d569720, + .EmcXm2DqsPadCtrl4 = 0x00492492, + .EmcXm2DqsPadCtrl5 = 0x00552452, + .EmcXm2DqsPadCtrl6 = 0x61751800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000000, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00000800, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000005, + .McEmemArbTimingRp = 0x00000006, + .McEmemArbTimingRc = 0x00000016, + .McEmemArbTimingRas = 0x0000000e, + .McEmemArbTimingFaw = 0x00000011, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000007, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09070202, + .McEmemArbDaCovers = 0x001a1016, + .McEmemArbMisc0 = 0x734e2a17, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0xf8000000, + .McMtsCarveoutAdrHi = 0x00000000, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush/bct/sdram-hynix-4GB-300.inc b/src/mainboard/google/rush/bct/sdram-hynix-4GB-300.inc new file mode 100644 index 0000000000..62b067f8c4 --- /dev/null +++ b/src/mainboard/google/rush/bct/sdram-hynix-4GB-300.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-4GB-300.cfg, do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000032, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x00000002, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430f0f, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000000d, + .EmcRfc = 0x00000067, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000009, + .EmcRp = 0x00000003, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000005, + .EmcW2r = 0x00000008, + .EmcR2p = 0x00000002, + .EmcW2p = 0x00000009, + .EmcRdRcd = 0x00000003, + .EmcWrRcd = 0x00000003, + .EmcRrd = 0x00000002, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000003, + .EmcWdvMask = 0x00000003, + .EmcQUse = 0x00000005, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x00000007, + .EmcPutermExtra = 0x00020000, + .EmcPutermWidth = 0x00000003, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x0000000e, + .EmcRdv = 0x00000010, + .EmcRdvMask = 0x00000012, + .EmcQpop = 0x00000009, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000003, + .EmcRefresh = 0x000008e4, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000239, + .EmcPdEx2Wr = 0x00000001, + .EmcPdEx2Rd = 0x00000008, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000065, + .EmcRw2Pden = 0x0000000e, + .EmcTxsr = 0x0000006c, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000005, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000009, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000005, + .EmcTClkStop = 0x00000005, + .EmcTRefBw = 0x00000924, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000321, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200000, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x0117000e, + .EmcMrsWaitCnt2 = 0x0117000e, + .EmcCfg = 0x73340000, + .EmcCfg2 = 0x000008d5, + .EmcCfgPipe = 0x000052a3, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800012d7, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0x002c00a0, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040128, + .EmcDllXformDqs0 = 0x00030000, + .EmcDllXformDqs1 = 0x00030000, + .EmcDllXformDqs2 = 0x00030000, + .EmcDllXformDqs3 = 0x00030000, + .EmcDllXformDqs4 = 0x00030000, + .EmcDllXformDqs5 = 0x00030000, + .EmcDllXformDqs6 = 0x00030000, + .EmcDllXformDqs7 = 0x00030000, + .EmcDllXformDqs8 = 0x00030000, + .EmcDllXformDqs9 = 0x00030000, + .EmcDllXformDqs10 = 0x00030000, + .EmcDllXformDqs11 = 0x00030000, + .EmcDllXformDqs12 = 0x00030000, + .EmcDllXformDqs13 = 0x00030000, + .EmcDllXformDqs14 = 0x00030000, + .EmcDllXformDqs15 = 0x00030000, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00084000, + .EmcDllXformAddr1 = 0x00084000, + .EmcDllXformAddr2 = 0x00010000, + .EmcDllXformAddr3 = 0x00084000, + .EmcDllXformAddr4 = 0x00084000, + .EmcDllXformAddr5 = 0x00010000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000000, + .EmcDliTrimTxDqs1 = 0x00000000, + .EmcDliTrimTxDqs2 = 0x00000000, + .EmcDliTrimTxDqs3 = 0x00000000, + .EmcDliTrimTxDqs4 = 0x00000000, + .EmcDliTrimTxDqs5 = 0x00000000, + .EmcDliTrimTxDqs6 = 0x00000000, + .EmcDliTrimTxDqs7 = 0x00000000, + .EmcDliTrimTxDqs8 = 0x00000000, + .EmcDliTrimTxDqs9 = 0x00000000, + .EmcDliTrimTxDqs10 = 0x00000000, + .EmcDliTrimTxDqs11 = 0x00000000, + .EmcDliTrimTxDqs12 = 0x00000000, + .EmcDliTrimTxDqs13 = 0x00000000, + .EmcDliTrimTxDqs14 = 0x00000000, + .EmcDliTrimTxDqs15 = 0x00000000, + .EmcDllXformDq0 = 0x00060000, + .EmcDllXformDq1 = 0x00060000, + .EmcDllXformDq2 = 0x00060000, + .EmcDllXformDq3 = 0x00060000, + .EmcDllXformDq4 = 0x00006000, + .EmcDllXformDq5 = 0x00006000, + .EmcDllXformDq6 = 0x00006000, + .EmcDllXformDq7 = 0x00006000, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000002, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000002, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000321, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x10000280, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x01231339, + .EmcXm2DqsPadCtrl3 = 0x51451420, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc081, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000096, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x08000004, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000001, + .McEmemArbTimingRp = 0x00000002, + .McEmemArbTimingRc = 0x00000007, + .McEmemArbTimingRas = 0x00000004, + .McEmemArbTimingFaw = 0x00000005, + .McEmemArbTimingRrd = 0x00000001, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000007, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000004, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06040202, + .McEmemArbDaCovers = 0x000b0607, + .McEmemArbMisc0 = 0x77450e08, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush/bct/sdram-hynix-4GB-792.inc b/src/mainboard/google/rush/bct/sdram-hynix-4GB-792.inc new file mode 100644 index 0000000000..7e5f66688e --- /dev/null +++ b/src/mainboard/google/rush/bct/sdram-hynix-4GB-792.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-4GB-792.cfg, do not edit. */ + .MemoryType = NvBootMemoryType_Ddr3, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x00000042, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430808, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000001, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000024, + .EmcRfc = 0x00000114, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000019, + .EmcRp = 0x0000000a, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000008, + .EmcW2r = 0x0000000d, + .EmcR2p = 0x00000004, + .EmcW2p = 0x00000013, + .EmcRdRcd = 0x0000000a, + .EmcWrRcd = 0x0000000a, + .EmcRrd = 0x00000003, + .EmcRext = 0x00000002, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000006, + .EmcWdvMask = 0x00000006, + .EmcQUse = 0x0000000b, + .EmcQuseWidth = 0x00000002, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000002, + .EmcEInputDuration = 0x0000000d, + .EmcPutermExtra = 0x00080000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000001, + .EmcQSafe = 0x00000014, + .EmcRdv = 0x00000017, + .EmcRdvMask = 0x00000019, + .EmcQpop = 0x0000000f, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000017e2, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000005f8, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000011, + .EmcPChg2Pden = 0x00000001, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x0000010d, + .EmcRw2Pden = 0x00000018, + .EmcTxsr = 0x0000011e, + .EmcTxsrDll = 0x00000200, + .EmcTcke = 0x00000005, + .EmcTckesr = 0x00000006, + .EmcTpd = 0x00000005, + .EmcTfaw = 0x0000001d, + .EmcTrpab = 0x00000000, + .EmcTClkStable = 0x00000008, + .EmcTClkStop = 0x00000008, + .EmcTRefBw = 0x00001822, + .EmcFbioCfg5 = 0x104ab098, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000d71, + .EmcEmrs = 0x00100002, + .EmcEmrs2 = 0x00200018, + .EmcEmrs3 = 0x00300000, + .EmcMrw1 = 0x00000000, + .EmcMrw2 = 0x00000000, + .EmcMrw3 = 0x00000000, + .EmcMrw4 = 0x00000000, + .EmcMrwExtra = 0x00000000, + .EmcWarmBootMrwExtra = 0x00000000, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x00000000, + .EmcMrwResetNInitWait = 0x00000000, + .EmcMrsWaitCnt = 0x006f000e, + .EmcMrsWaitCnt2 = 0x006f000e, + .EmcCfg = 0x73300000, + .EmcCfg2 = 0x0000089d, + .EmcCfgPipe = 0x000040a0, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80003012, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00700b1, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x00040000, + .EmcDllXformDqs0 = 0x00000008, + .EmcDllXformDqs1 = 0x00000008, + .EmcDllXformDqs2 = 0x00000008, + .EmcDllXformDqs3 = 0x00000008, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x00000008, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x00000008, + .EmcDllXformDqs9 = 0x00000008, + .EmcDllXformDqs10 = 0x00000008, + .EmcDllXformDqs11 = 0x00000008, + .EmcDllXformDqs12 = 0x00000008, + .EmcDllXformDqs13 = 0x00000008, + .EmcDllXformDqs14 = 0x00000008, + .EmcDllXformDqs15 = 0x00000008, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00038000, + .EmcDllXformAddr1 = 0x00038000, + .EmcDllXformAddr2 = 0x00000000, + .EmcDllXformAddr3 = 0x00038000, + .EmcDllXformAddr4 = 0x00038000, + .EmcDllXformAddr5 = 0x00000000, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000005, + .EmcDliTrimTxDqs1 = 0x00000005, + .EmcDliTrimTxDqs2 = 0x00000003, + .EmcDliTrimTxDqs3 = 0x00000005, + .EmcDliTrimTxDqs4 = 0x00000005, + .EmcDliTrimTxDqs5 = 0x00000002, + .EmcDliTrimTxDqs6 = 0x00000005, + .EmcDliTrimTxDqs7 = 0x00000005, + .EmcDliTrimTxDqs8 = 0x00000005, + .EmcDliTrimTxDqs9 = 0x00000005, + .EmcDliTrimTxDqs10 = 0x00000003, + .EmcDliTrimTxDqs11 = 0x00000005, + .EmcDliTrimTxDqs12 = 0x00000005, + .EmcDliTrimTxDqs13 = 0x00000002, + .EmcDliTrimTxDqs14 = 0x00000005, + .EmcDliTrimTxDqs15 = 0x00000005, + .EmcDllXformDq0 = 0x00000009, + .EmcDllXformDq1 = 0x0000000c, + .EmcDllXformDq2 = 0x00000008, + .EmcDllXformDq3 = 0x0000000a, + .EmcDllXformDq4 = 0x0000000a, + .EmcDllXformDq5 = 0x00000008, + .EmcDllXformDq6 = 0x0000000a, + .EmcDllXformDq7 = 0x00000008, + .WarmBootWait = 0x00000002, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00020000, + .EmcZcalWaitCnt = 0x00000042, + .EmcZcalMrwCmd = 0x00000000, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x80000011, + .EmcZcalInitDev1 = 0x40000011, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000d71, + .EmcWarmBootMrsExtra = 0x00100002, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000002, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00002002, + .PmcIoDpd3Req = 0x4fffffff, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x00000000, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000000, + .EmcXm2CmdPadCtrl = 0x100002a0, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00111111, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120113d, + .EmcXm2DqsPadCtrl3 = 0x61861820, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x61861800, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc085, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f108, + .EmcXm2VttGenPadCtrl = 0x07070004, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x016eeeee, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00003120, + .EmcSwizzleRank0Byte0 = 0x25143067, + .EmcSwizzleRank0Byte1 = 0x45367102, + .EmcSwizzleRank0Byte2 = 0x47106253, + .EmcSwizzleRank0Byte3 = 0x04362175, + .EmcSwizzleRank1ByteCfg = 0x00003120, + .EmcSwizzleRank1Byte0 = 0x71546032, + .EmcSwizzleRank1Byte1 = 0x35104276, + .EmcSwizzleRank1Byte2 = 0x27043615, + .EmcSwizzleRank1Byte3 = 0x72306145, + .EmcDsrVttgenDrv = 0x0606003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080303, + .McEmemAdrCfgDev1 = 0x00080303, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000b, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000004, + .McEmemArbTimingRp = 0x00000005, + .McEmemArbTimingRc = 0x00000013, + .McEmemArbTimingRas = 0x0000000c, + .McEmemArbTimingFaw = 0x0000000f, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000003, + .McEmemArbTimingWap2Pre = 0x0000000c, + .McEmemArbTimingR2R = 0x00000002, + .McEmemArbTimingW2W = 0x00000002, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000008, + .McEmemArbDaTurns = 0x08060202, + .McEmemArbDaCovers = 0x00170e13, + .McEmemArbMisc0 = 0x746c2414, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000000, + .EmcCaTrainingTimingCntl1 = 0x1f7df7df, + .EmcCaTrainingTimingCntl2 = 0x0000001f, + .SwizzleRankByteEncode = 0x0000006f, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush/bct/sdram-unused.inc b/src/mainboard/google/rush/bct/sdram-unused.inc new file mode 100644 index 0000000000..bef63dcecc --- /dev/null +++ b/src/mainboard/google/rush/bct/sdram-unused.inc @@ -0,0 +1,4 @@ +{ /* dummy. */ + .MemoryType = NvBootMemoryType_Unused, + 0, +}, diff --git a/src/mainboard/google/rush/bct/spi.cfg b/src/mainboard/google/rush/bct/spi.cfg new file mode 100644 index 0000000000..a5ded0bd68 --- /dev/null +++ b/src/mainboard/google/rush/bct/spi.cfg @@ -0,0 +1,31 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00130001; +BlockSize = 32768; +PageSize = 2048; +PartitionSize = 4194304; + +DevType[0] = NvBootDevType_Spi; +DeviceParam[0].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[0].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[0].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[0].SpiFlashParams.PageSize2kor16k = 0; + +DevType[1] = NvBootDevType_Spi; +DeviceParam[1].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[1].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[1].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[1].SpiFlashParams.PageSize2kor16k = 0; + +DevType[2] = NvBootDevType_Spi; +DeviceParam[2].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[2].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[2].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[2].SpiFlashParams.PageSize2kor16k = 0; + +DevType[3] = NvBootDevType_Spi; +DeviceParam[3].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[3].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[3].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[3].SpiFlashParams.PageSize2kor16k = 0; diff --git a/src/mainboard/google/rush/boardid.c b/src/mainboard/google/rush/boardid.c new file mode 100644 index 0000000000..0c9d2c5e70 --- /dev/null +++ b/src/mainboard/google/rush/boardid.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + + if (id < 0) { + id = gpio_get(GPIO(Q3)) << 0 | + gpio_get(GPIO(T1)) << 1 | + gpio_get(GPIO(X1)) << 2 | + gpio_get(GPIO(X4)) << 3; + printk(BIOS_SPEW, "Board ID: %#x.\n", id); + } + + return id; +} diff --git a/src/mainboard/google/rush/bootblock.c b/src/mainboard/google/rush/bootblock.c new file mode 100644 index 0000000000..2d099fb6c3 --- /dev/null +++ b/src/mainboard/google/rush/bootblock.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME: move back to soc code? */ + +#include "pmic.h" + +static const struct pad_config uart_console_pads[] = { + /* UARTA: tx and rx. */ + PAD_CFG_SFIO(KB_ROW9, PINMUX_PULL_NONE, UA3), + PAD_CFG_SFIO(KB_ROW10, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, UA3), + /* + * Disable UART2 pads as they are default connected to UARTA controller. + */ + PAD_CFG_UNUSED(UART2_RXD), + PAD_CFG_UNUSED(UART2_TXD), + PAD_CFG_UNUSED(UART2_RTS_N), + PAD_CFG_UNUSED(UART2_CTS_N), +}; + +static const struct pad_config padcfgs[] = { + /* Board ID bits 3:0 */ + PAD_CFG_GPIO_INPUT(GPIO_X4_AUD, PINMUX_PULL_NONE), + PAD_CFG_GPIO_INPUT(GPIO_X1_AUD, PINMUX_PULL_NONE), + PAD_CFG_GPIO_INPUT(KB_ROW17, PINMUX_PULL_NONE), + PAD_CFG_GPIO_INPUT(KB_COL3, PINMUX_PULL_NONE), + + /* Power Button */ + PAD_CFG_GPIO_INPUT(KB_COL0, PINMUX_PULL_NONE), + + /* Lid Open Switch */ + PAD_CFG_GPIO_INPUT(KB_ROW4, PINMUX_PULL_UP), +}; + +static const struct pad_config i2cpad[] = { + /* PMIC i2C bus */ + PAD_CFG_SFIO(PWR_I2C_SCL, PINMUX_INPUT_ENABLE, I2CPMU), + PAD_CFG_SFIO(PWR_I2C_SDA, PINMUX_INPUT_ENABLE, I2CPMU), +}; + +static const struct pad_config spipad[] = { + /* SPI fLash: mosi, miso, clk, cs0 */ + PAD_CFG_SFIO(GPIO_PG6, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SPI4), + PAD_CFG_SFIO(GPIO_PG7, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SPI4), + PAD_CFG_SFIO(GPIO_PG5, PINMUX_INPUT_ENABLE, SPI4), + PAD_CFG_SFIO(GPIO_PI3, PINMUX_INPUT_ENABLE, SPI4), +}; + +static const struct funit_cfg funitcfgs[] = { + FUNIT_CFG(I2C5, PLLP, 400, i2cpad, ARRAY_SIZE(i2cpad)), + FUNIT_CFG(SBC4, PLLP, 33333, spipad, ARRAY_SIZE(spipad)), +}; + +void bootblock_mainboard_early_init(void) +{ + soc_configure_pads(uart_console_pads, ARRAY_SIZE(uart_console_pads)); +} + +static void set_clock_sources(void) +{ + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, CLK_RST_REG(clk_src_uarta)); +} + +void bootblock_mainboard_init(void) +{ + set_clock_sources(); + + /* Set up the pads required to load romstage. */ + soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs)); + soc_configure_funits(funitcfgs, ARRAY_SIZE(funitcfgs)); + + i2c_init(4); + pmic_init(4); + + tegra_spi_init(4); +} diff --git a/src/mainboard/google/rush/chromeos.c b/src/mainboard/google/rush/chromeos.c new file mode 100644 index 0000000000..b4a7f8faab --- /dev/null +++ b/src/mainboard/google/rush/chromeos.c @@ -0,0 +1,102 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO(R1); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO(R1)); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO(R4); + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power: active low */ + gpios->gpios[count].port = GPIO(Q0); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: active low (output) */ + gpios->gpios[count].port = GPIO(I5); + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO(R1)); +} diff --git a/src/mainboard/google/snow/devicetree.cb b/src/mainboard/google/rush/devicetree.cb similarity index 71% rename from src/mainboard/google/snow/devicetree.cb rename to src/mainboard/google/rush/devicetree.cb index 4c88ea8e98..98284fc4e6 100644 --- a/src/mainboard/google/snow/devicetree.cb +++ b/src/mainboard/google/rush/devicetree.cb @@ -1,7 +1,7 @@ ## ## This file is part of the coreboot project. ## -## Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. +## Copyright 2014 Google Inc. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -17,16 +17,11 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -# FIXME: this is just a stub for now -chip cpu/samsung/exynos5250 +chip soc/nvidia/tegra132 + register "spintable_addr" = "0x80000008" -device cpu_cluster 0 on -end - -device domain 0 on - chip drivers/generic/generic # I2C0 controller - device i2c 6 on end # ? - device i2c 9 on end # ? + device cpu_cluster 0 on + device cpu 0 on end + device cpu 1 on end end end -end diff --git a/src/mainboard/google/rush/ec_dummy.c b/src/mainboard/google/rush/ec_dummy.c new file mode 100644 index 0000000000..01a935c79f --- /dev/null +++ b/src/mainboard/google/rush/ec_dummy.c @@ -0,0 +1,9 @@ +/* Dummy CHROMEEC file to provide stub functions for vboot compilation */ + +#include + +int google_chromeec_vbnv_context(int is_read, uint8_t *data, int len); +int google_chromeec_vbnv_context(int is_read, uint8_t *data, int len) +{ + return 0; +} diff --git a/src/mainboard/google/rush/mainboard.c b/src/mainboard/google/rush/mainboard.c new file mode 100644 index 0000000000..0b85cc0356 --- /dev/null +++ b/src/mainboard/google/rush/mainboard.c @@ -0,0 +1,164 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct pad_config sdmmc3_pad[] = { + /* MMC3(SDCARD) */ + PAD_CFG_SFIO(SDMMC3_CLK, PINMUX_INPUT_ENABLE, SDMMC3), + PAD_CFG_SFIO(SDMMC3_CMD, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_DAT0, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_DAT1, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_DAT2, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_DAT3, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_CLK_LB_IN, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC3), + PAD_CFG_SFIO(SDMMC3_CLK_LB_OUT, PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN, SDMMC3), + /* MMC3 Card Detect pin */ + PAD_CFG_GPIO_INPUT(SDMMC3_CD_N, PINMUX_PULL_UP), + /* Disable SD card reader power so it can be reset even on warm boot. + Payloads must enable power before accessing SD card slots. */ + PAD_CFG_GPIO_OUT0(KB_ROW0, PINMUX_PULL_NONE), +}; + +static const struct pad_config sdmmc4_pad[] = { + /* MMC4 (eMMC) */ + PAD_CFG_SFIO(SDMMC4_CLK, PINMUX_INPUT_ENABLE, SDMMC4), + PAD_CFG_SFIO(SDMMC4_CMD, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT0, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT1, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT2, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT3, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT4, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT5, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT6, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT7, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SDMMC4), +}; + +static const struct pad_config padcfgs[] = { + /* We pull the USB VBUS signals up but keep them as inputs since the + * voltage source likes to drive them low on overcurrent conditions */ + PAD_CFG_GPIO_INPUT(USB_VBUS_EN0, PINMUX_PULL_UP), + PAD_CFG_GPIO_INPUT(USB_VBUS_EN1, PINMUX_PULL_UP), +}; + +static const struct pad_config i2c1_pad[] = { + /* GEN1 I2C */ + PAD_CFG_SFIO(GEN1_I2C_SCL, PINMUX_INPUT_ENABLE, I2C1), + PAD_CFG_SFIO(GEN1_I2C_SDA, PINMUX_INPUT_ENABLE, I2C1), +}; + +static const struct funit_cfg funitcfgs[] = { + FUNIT_CFG(SDMMC3, PLLP, 48000, sdmmc3_pad, ARRAY_SIZE(sdmmc3_pad)), + FUNIT_CFG(SDMMC4, PLLP, 48000, sdmmc4_pad, ARRAY_SIZE(sdmmc4_pad)), + FUNIT_CFG(I2C1, PLLP, 100, i2c1_pad, ARRAY_SIZE(i2c1_pad)), +}; + +static void setup_ec_spi(void) +{ + struct tegra_spi_channel *spi; + + spi = tegra_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS); +} + +static void setup_usb(void) +{ + clock_enable_clear_reset(CLK_L_USBD, CLK_H_USB3, 0, 0, 0, 0); + + usb_setup_utmip((void *)TEGRA_USBD_BASE); + usb_setup_utmip((void *)TEGRA_USB3_BASE); +} + +static const struct pad_config i2s1_pad[] = { + /* I2S1 */ + PAD_CFG_SFIO(DAP2_SCLK, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_FS, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_DOUT, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_DIN, PINMUX_INPUT_ENABLE | PINMUX_TRISTATE, I2S1), + /* codec MCLK via EXTPERIPH1 */ + PAD_CFG_SFIO(DAP_MCLK1, PINMUX_PULL_NONE, EXTPERIPH1), +}; + +static const struct funit_cfg audio_funit[] = { + /* We need 1.5MHz for I2S1. So we use CLK_M */ + FUNIT_CFG(I2S1, CLK_M, 1500, i2s1_pad, ARRAY_SIZE(i2s1_pad)), +}; + +/* Audio init: clocks and enables/resets */ +static void setup_audio(void) +{ + /* + * External peripheral 1: audio codec (max98090) uses 12MHz CLK1 + * NOTE: We can't use a funits struct/call here because EXTPERIPH1/2/3 + * don't have BASE regs or CAR RST/ENA bits. Also, the mux setting for + * EXTPERIPH1/DAP_MCLK1 is rolled into the I2S1 padcfg. + */ + clock_configure_source(extperiph1, CLK_M, 12000); + + soc_configure_funits(audio_funit, ARRAY_SIZE(audio_funit)); + + clock_external_output(1); /* For external MAX98090 audio codec. */ + + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (in our + * case, I2S/APBIF/AUDIO) will hang. + */ + clock_enable_audio(); +} + +static void mainboard_init(device_t dev) +{ + soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs)); + soc_configure_funits(funitcfgs, ARRAY_SIZE(funitcfgs)); + + setup_ec_spi(); + setup_usb(); + + setup_audio(); + i2c_init(I2C1_BUS); /* for max98090 codec */ +} + +void display_startup(device_t dev) +{ + dp_display_startup(dev); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "rush", + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/google/rush/memlayout.ld b/src/mainboard/google/rush/memlayout.ld new file mode 100644 index 0000000000..a71dcb8508 --- /dev/null +++ b/src/mainboard/google/rush/memlayout.ld @@ -0,0 +1,6 @@ +#if IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE) +#include +#else +#include +#endif + diff --git a/src/mainboard/google/rush/pmic.c b/src/mainboard/google/rush/pmic.c new file mode 100644 index 0000000000..75508fb36f --- /dev/null +++ b/src/mainboard/google/rush/pmic.c @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "pmic.h" +#include "reset.h" + +enum { + AS3722_I2C_ADDR = 0x40 +}; + +struct as3722_init_reg { + u8 reg; + u8 val; + u8 delay; +}; + +static struct as3722_init_reg init_list[] = { + {AS3722_SDO0, 0x3C, 1}, + {AS3722_SDO1, 0x32, 0}, + {AS3722_LDO3, 0x59, 0}, + {AS3722_SDO2, 0x3C, 0}, + {AS3722_SDO3, 0x00, 0}, + {AS3722_SDO4, 0x00, 0}, + {AS3722_SDO5, 0x50, 0}, + {AS3722_SDO6, 0x28, 1}, + {AS3722_LDO0, 0x8A, 0}, + {AS3722_LDO1, 0x00, 0}, + {AS3722_LDO2, 0x10, 0}, + {AS3722_LDO4, 0x00, 0}, + {AS3722_LDO5, 0x00, 0}, + {AS3722_LDO6, 0x00, 0}, + {AS3722_LDO7, 0x00, 0}, + {AS3722_LDO9, 0x00, 0}, + {AS3722_LDO10, 0x00, 0}, + {AS3722_LDO11, 0x00, 1}, +}; + +static void pmic_write_reg(unsigned bus, uint8_t reg, uint8_t val, int delay) +{ + if (i2c_writeb(bus, AS3722_I2C_ADDR, reg, val)) { + printk(BIOS_ERR, "%s: reg = 0x%02X, value = 0x%02X failed!\n", + __func__, reg, val); + /* Reset the SoC on any PMIC write error */ + cpu_reset(); + } else { + if (delay) + udelay(500); + } +} + +static void pmic_slam_defaults(unsigned bus) +{ + int i; + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + struct as3722_init_reg *reg = &init_list[i]; + pmic_write_reg(bus, reg->reg, reg->val, reg->delay); + } +} + +void pmic_init(unsigned bus) +{ + /* + * Don't need to set up VDD_CORE - already done - by OTP + * Don't write SDCONTROL - it's already 0x7F, i.e. all SDs enabled. + * Don't write LDCONTROL - it's already 0xFF, i.e. all LDOs enabled. + */ + + /* Restore PMIC POR defaults, in case kernel changed 'em */ + pmic_slam_defaults(bus); + + /* SDO0: Set VDD_CPU to 1.2V. */ + pmic_write_reg(bus, 0x00, 0x50, 1); + + /* SDO6: Set VDD_GPU to 1.0V. */ + pmic_write_reg(bus, 0x06, 0x28, 1); + + /* LDO2: Set +1.2V_GEN_AVDD to 1.2V */ + pmic_write_reg(bus, 0x12, 0x10, 1); + + /* + * Panel power GPIO O4. Set mode for GPIO4 (0x0c to 7), then set + * the value (register 0x20 bit 4) + */ + pmic_write_reg(bus, 0x0c, 0x07, 0); + pmic_write_reg(bus, 0x20, 0x10, 1); + + printk(BIOS_DEBUG, "PMIC init done\n"); +} diff --git a/src/mainboard/google/rush/pmic.h b/src/mainboard/google/rush/pmic.h new file mode 100644 index 0000000000..b56c513416 --- /dev/null +++ b/src/mainboard/google/rush/pmic.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_RUSH_PMIC_H__ +#define __MAINBOARD_GOOGLE_RUSH_PMIC_H__ + +enum { + AS3722_SDO0 = 0, + AS3722_SDO1, + AS3722_SDO2, + AS3722_SDO3, + AS3722_SDO4, + AS3722_SDO5, + AS3722_SDO6, + + AS3722_LDO0 = 0x10, + AS3722_LDO1, + AS3722_LDO2, + AS3722_LDO3, + AS3722_LDO4, + AS3722_LDO5, + AS3722_LDO6, + AS3722_LDO7, + + AS3722_LDO9 = 0x19, + AS3722_LDO10, + AS3722_LDO11, +}; + +void pmic_init(unsigned bus); + +#endif /* __MAINBOARD_GOOGLE_RUSH_PMIC_H__ */ diff --git a/src/mainboard/google/rush/reset.c b/src/mainboard/google/rush/reset.c new file mode 100644 index 0000000000..0fc6320489 --- /dev/null +++ b/src/mainboard/google/rush/reset.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void hard_reset(void) +{ + gpio_output(GPIO(I5), 0); + while(1); +} diff --git a/src/mainboard/google/rush/romstage.c b/src/mainboard/google/rush/romstage.c new file mode 100644 index 0000000000..88b7d382c1 --- /dev/null +++ b/src/mainboard/google/rush/romstage.c @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +static const struct pad_config padcfgs[] = { + /* SOC_WARM_RESET_L */ + PAD_CFG_GPIO_OUT1(GPIO_PI5, PINMUX_PULL_UP), +}; + +static const struct pad_config i2cpad[] = { + /* TPM I2C */ + PAD_CFG_SFIO(CAM_I2C_SCL, PINMUX_INPUT_ENABLE, I2C3), + PAD_CFG_SFIO(CAM_I2C_SDA, PINMUX_INPUT_ENABLE, I2C3), +}; + +static const struct pad_config spipad[] = { + /* EC on SPI1: mosi, miso, clk, cs */ + PAD_CFG_SFIO(ULPI_CLK, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_DIR, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_NXT, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_STP, PINMUX_INPUT_ENABLE, SPI1), +}; + +static const struct funit_cfg funitcfgs[] = { + FUNIT_CFG(SBC1, CLK_M, 3000, spipad, ARRAY_SIZE(spipad)), + FUNIT_CFG(I2C3, PLLP, 400, i2cpad, ARRAY_SIZE(i2cpad)), +}; + +void romstage_mainboard_init(void) +{ + /* Bring up controller interfaces for ramstage loading. */ + soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs)); + soc_configure_funits(funitcfgs, ARRAY_SIZE(funitcfgs)); + + /* TPM I2C bus */ + i2c_init(2); +} + +void mainboard_configure_pmc(void) +{ +} + +void mainboard_enable_vdd_cpu(void) +{ + /* VDD_CPU is already enabled in bootblock. */ +} diff --git a/src/mainboard/google/rush/sdram_configs.c b/src/mainboard/google/rush/sdram_configs.c new file mode 100644 index 0000000000..462fec2afe --- /dev/null +++ b/src/mainboard/google/rush/sdram_configs.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +static struct sdram_params sdram_configs[] = { +#include "bct/sdram-hynix-2GB-924.inc" /* ram_code = 0000 */ +#include "bct/sdram-hynix-4GB-792.inc" /* ram_code = 0001 */ +#include "bct/sdram-unused.inc" /* ram_code = 0010 */ +#include "bct/sdram-unused.inc" /* ram_code = 0011 */ +#include "bct/sdram-unused.inc" /* ram_code = 0100 */ +#include "bct/sdram-unused.inc" /* ram_code = 0101 */ +#include "bct/sdram-unused.inc" /* ram_code = 0110 */ +#include "bct/sdram-unused.inc" /* ram_code = 0111 */ +#include "bct/sdram-unused.inc" /* ram_code = 1000 */ +#include "bct/sdram-unused.inc" /* ram_code = 1001 */ +#include "bct/sdram-unused.inc" /* ram_code = 1010 */ +#include "bct/sdram-unused.inc" /* ram_code = 1011 */ +#include "bct/sdram-unused.inc" /* ram_code = 1100 */ +#include "bct/sdram-unused.inc" /* ram_code = 1101 */ +#include "bct/sdram-unused.inc" /* ram_code = 1110 */ +#include "bct/sdram-unused.inc" /* ram_code = 1111 */ +}; + +const struct sdram_params *get_sdram_config() +{ + uint32_t ramcode = sdram_get_ram_code(); + /* + * If we need to apply some special hacks to RAMCODE mapping (ex, by + * board_id), do that now. + */ + + printk(BIOS_SPEW, "%s: RAMCODE=%d\n", __func__, ramcode); + if (ramcode >= sizeof(sdram_configs) / sizeof(sdram_configs[0]) || + sdram_configs[ramcode].MemoryType == NvBootMemoryType_Unused) { + die("Invalid RAMCODE."); + } + + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/rush/verstage.c b/src/mainboard/google/rush/verstage.c new file mode 100644 index 0000000000..0150e465a7 --- /dev/null +++ b/src/mainboard/google/rush/verstage.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static const struct pad_config i2cpad[] = { + /* TPM I2C */ + PAD_CFG_SFIO(CAM_I2C_SCL, PINMUX_INPUT_ENABLE, I2C3), + PAD_CFG_SFIO(CAM_I2C_SDA, PINMUX_INPUT_ENABLE, I2C3), +}; + +static const struct pad_config spipad[] = { + /* EC on SPI1: mosi, miso, clk, cs */ + PAD_CFG_SFIO(ULPI_CLK, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_DIR, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_NXT, PINMUX_INPUT_ENABLE, SPI1), + PAD_CFG_SFIO(ULPI_STP, PINMUX_INPUT_ENABLE, SPI1), +}; + +static const struct funit_cfg funitcfgs[] = { + FUNIT_CFG(SBC1, CLK_M, 3000, spipad, ARRAY_SIZE(spipad)), + FUNIT_CFG(I2C3, PLLP, 400, i2cpad, ARRAY_SIZE(i2cpad)), +}; + +void verstage_mainboard_init(void) +{ + soc_configure_funits(funitcfgs, ARRAY_SIZE(funitcfgs)); + + /* TPM I2C bus */ + i2c_init(2); +} diff --git a/src/mainboard/google/rush_ryu/Kconfig b/src/mainboard/google/rush_ryu/Kconfig new file mode 100644 index 0000000000..60e1b79e23 --- /dev/null +++ b/src/mainboard/google/rush_ryu/Kconfig @@ -0,0 +1,101 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_RUSH_RYU + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_8192 + select CHROMEOS + select CHROMEOS_VBNV_EC + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_I2C + select EC_GOOGLE_CHROMEEC_I2C_PROTO3 + select EC_SOFTWARE_SYNC + select MAINBOARD_DO_NATIVE_VGA_INIT + select SPI_FLASH + select SOC_NVIDIA_TEGRA132 + select MAINBOARD_DO_DSI_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select VIRTUAL_DEV_SWITCH + select ARCH_SPINTABLE + +config MAINBOARD_DIR + string + default google/rush_ryu + +config MAINBOARD_PART_NUMBER + string + default "Rush Ryu" + +choice + prompt "BCT boot media" + default RUSH_RYU_BCT_CFG_SPI + help + Which boot media to configure the BCT for. + +config RUSH_RYU_BCT_CFG_SPI + bool "SPI" + help + Configure the BCT for booting from SPI. + +config RUSH_RYU_BCT_CFG_EMMC + bool "eMMC" + help + Configure the BCT for booting from eMMC. + +endchoice + +config BOOT_MEDIA_SPI_BUS + int "SPI bus with boot media ROM" + range 1 6 + depends on RUSH_RYU_BCT_CFG_SPI + default 4 + help + Which SPI bus the boot media is connected to. + +config BOOT_MEDIA_SPI_CHIP_SELECT + int "Chip select for SPI boot media" + range 0 3 + depends on RUSH_RYU_BCT_CFG_SPI + default 0 + help + Which chip select to use for boot media. + +# For ryu, we are using vboot2. Thus, index for stages: +# VBOOT_ROMSTAGE_INDEX -> Use default value of 0x2 +# VBOOT_RAMSTAGE_INDEX -> Use 0x3 +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config DRIVER_TPM_I2C_BUS + hex + default 0x2 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config EC_GOOGLE_CHROMEEC_I2C_BUS + hex + default 1 + +endif # BOARD_GOOGLE_RUSH_RYU diff --git a/src/mainboard/google/rush_ryu/Makefile.inc b/src/mainboard/google/rush_ryu/Makefile.inc new file mode 100644 index 0000000000..1bc92d107c --- /dev/null +++ b/src/mainboard/google/rush_ryu/Makefile.inc @@ -0,0 +1,52 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# Add a handler for BCT config files +$(call add-special-class,bct-cfg) +bct-cfg-handler= $(eval $(obj)/generated/bct.cfg: $(1)$(2)) + +$(obj)/generated/bct.cfg: + @printf " CAT $(subst $(obj)/,,$(@))\n" + cat $^ > $@ + +subdirs-y += bct + +bootblock-y += bootblock.c +bootblock-y += pmic.c +bootblock-y += reset.c + +verstage-y += verstage.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += chromeos.c +romstage-y += pmic.c +romstage-y += reset.c +romstage-y += romstage.c +romstage-y += sdram_configs.c + +ramstage-y += boardid.c +ramstage-y += mainboard.c +ramstage-y += reset.c +ramstage-y += pmic.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld +verstage-y += memlayout.ld diff --git a/src/mainboard/google/rush_ryu/bct/Makefile.inc b/src/mainboard/google/rush_ryu/bct/Makefile.inc new file mode 100644 index 0000000000..f4e97198bf --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/Makefile.inc @@ -0,0 +1,29 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bct-cfg-$(CONFIG_RUSH_RYU_BCT_CFG_EMMC) += emmc.cfg +bct-cfg-$(CONFIG_RUSH_RYU_BCT_CFG_SPI) += spi.cfg +bct-cfg-y += odmdata.cfg +bct-cfg-y += jtag.cfg +#NOTE: When full LPDDR3 SDRAM config is done in bootblock, remove this +bct-cfg-$(CONFIG_BOOTROM_SDRAM_INIT) += sdram-4GB-924.cfg + +# Note when SDRAM config (sdram-*.cfg) files are changed, we have to regenerate +# the include files (sdram-*.inc) by running "./cfg2inc.sh sdram-*.cfg". +# TODO(hungte) Change cfg2inc.sh to NVIDIA's official tool in cbootimage. diff --git a/src/mainboard/google/rush_ryu/bct/cfg2inc.sh b/src/mainboard/google/rush_ryu/bct/cfg2inc.sh new file mode 100755 index 0000000000..a9c629b523 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/cfg2inc.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# This file is part of the coreboot project. +# +# Copyright 2014 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +bct_cfg2inc() { + local in_file="$1" + local out_file="$2" + echo "{ /* generated from ${in_file}; do not edit. */" >"${out_file}" + # Note currently we can only handle DDR3 type memory, even in C + # implementation. + sed "/^#.*$/d; s/^SDRAM.0./ /; s/\r$//; s/;$/,/;" \ + "${in_file}" >> "${out_file}" + echo "}," >>"${out_file}" +} + +for file in $@; do + echo "Generating $file => ${file%cfg}inc..." + bct_cfg2inc "${file}" "${file%cfg}inc" +done diff --git a/src/mainboard/google/rush_ryu/bct/emmc.cfg b/src/mainboard/google/rush_ryu/bct/emmc.cfg new file mode 100644 index 0000000000..430ffd6d4b --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/emmc.cfg @@ -0,0 +1,13 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00130001; +BlockSize = 0x00004000; +PageSize = 0x00000200; +PartitionSize = 0x01000000; + +DevType[0] = NvBootDevType_Sdmmc; +DeviceParam[0].SdmmcParams.ClockDivider = 0x00000009; +DeviceParam[0].SdmmcParams.DataWidth = NvBootSdmmcDataWidth_8Bit; +DeviceParam[0].SdmmcParams.MaxPowerClassSupported = 0x00000000; +DeviceParam[0].SdmmcParams.MultiPageSupport = 0x00000000; diff --git a/src/mainboard/google/rush_ryu/bct/jtag.cfg b/src/mainboard/google/rush_ryu/bct/jtag.cfg new file mode 100644 index 0000000000..f43e143377 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/jtag.cfg @@ -0,0 +1,16 @@ +# +# Set JtagCtrl to 1 to reenable Jtag +# +JtagCtrl = 0; +# +# Fill in chip unique id +# +# ChipUid can be found by running tegrarcm in tegra recovery mode +# (also hooking up A-A USB cable) and looking for console output +# on line starting with "Chip UID:" +# +# Command example: +# $ sudo tegrarcm --bct=/build/nyan/firmware/bct/board.bct --bootloader=/build/nyan/firmware/u-boot.bin --loadaddr=0x80108000 +# Where board.bct and u-boot.bin do not have to be prebuilt. +# +ChipUid = 0x00000000000000000000000000000000; diff --git a/src/mainboard/google/rush_ryu/bct/odmdata.cfg b/src/mainboard/google/rush_ryu/bct/odmdata.cfg new file mode 100644 index 0000000000..d0ab2bf8fb --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/odmdata.cfg @@ -0,0 +1 @@ +OdmData = 0x80080000; diff --git a/src/mainboard/google/rush_ryu/bct/sdram-4GB-924.cfg b/src/mainboard/google/rush_ryu/bct/sdram-4GB-924.cfg new file mode 100644 index 0000000000..4291a0b669 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/sdram-4GB-924.cfg @@ -0,0 +1,1387 @@ +# CFG Version SEC02 - Samsung_4GB_K4E6E304ED-EGCF +# Do not edit. Generated by T132_emc_reg_toolV6.0.4 V6.0.4. Command: +# T132_emc_reg_toolV6.0.4 -i Samsung_4GB_K4E6E304ED-EGCF_lpddr3.par -b A44_924MHz_emc_reg.txt 1.08225 +# -o A44_64_924_tool_emcregtoolv4.cfg -dram_board_cfg 3 -round_trip_dly_ps 589.6 +# Parameter file: Samsung_4GB_K4E6E304ED-EGCF_lpddr3.par, tck = 1.08 ns (924.00 MHz) +# bkv file: A44_924MHz_emc_reg.txt +SDRAM[0].MemoryType = NvBootMemoryType_LpDdr2; +SDRAM[0].PllMInputDivider = 0x00000001; +SDRAM[0].PllMFeedbackDivider = 0x0000004d; +SDRAM[0].PllMStableTime = 0x0000012c; +SDRAM[0].PllMSetupControl = 0x00000000; +SDRAM[0].PllMSelectDiv2 = 0x00000000; +SDRAM[0].PllMPDLshiftPh45 = 0x00000001; +SDRAM[0].PllMPDLshiftPh90 = 0x00000001; +SDRAM[0].PllMPDLshiftPh135 = 0x00000001; +SDRAM[0].PllMKCP = 0x00000000; +SDRAM[0].PllMKVCO = 0x00000000; +SDRAM[0].EmcBctSpare0 = 0x00000000; +SDRAM[0].EmcBctSpare1 = 0x00000000; +SDRAM[0].EmcBctSpare2 = 0x00000000; +SDRAM[0].EmcBctSpare3 = 0x00000000; +SDRAM[0].EmcBctSpare4 = 0x00000000; +SDRAM[0].EmcBctSpare5 = 0x00000000; +SDRAM[0].EmcBctSpare6 = 0x00000000; +SDRAM[0].EmcBctSpare7 = 0x00000000; +SDRAM[0].EmcBctSpare8 = 0x00000000; +SDRAM[0].EmcBctSpare9 = 0x00000000; +SDRAM[0].EmcBctSpare10 = 0x00000000; +SDRAM[0].EmcBctSpare11 = 0x00000000; +SDRAM[0].EmcClockSource = 0x80000000; +SDRAM[0].EmcAutoCalInterval = 0x001fffff; +SDRAM[0].EmcAutoCalConfig = 0xa1430000; +SDRAM[0].EmcAutoCalConfig2 = 0x00000000; +SDRAM[0].EmcAutoCalConfig3 = 0x00000000; +SDRAM[0].EmcAutoCalWait = 0x00000190; +SDRAM[0].EmcAdrCfg = 0x00000001; +SDRAM[0].EmcPinProgramWait = 0x00000000; +SDRAM[0].EmcPinExtraWait = 0x00000000; +SDRAM[0].EmcTimingControlWait = 0x00000000; +SDRAM[0].EmcRc = 0x00000037; +SDRAM[0].EmcRfc = 0x00000078; +SDRAM[0].EmcRfcSlr = 0x00000000; +SDRAM[0].EmcRas = 0x00000026; +SDRAM[0].EmcRp = 0x00000010; +SDRAM[0].EmcR2r = 0x00000000; +SDRAM[0].EmcW2w = 0x00000000; +SDRAM[0].EmcR2w = 0x00000010; +SDRAM[0].EmcW2r = 0x00000010; +SDRAM[0].EmcR2p = 0x00000006; +SDRAM[0].EmcW2p = 0x00000017; +SDRAM[0].EmcRdRcd = 0x00000010; +SDRAM[0].EmcWrRcd = 0x00000010; +SDRAM[0].EmcRrd = 0x00000009; +SDRAM[0].EmcRext = 0x00000005; +SDRAM[0].EmcWext = 0x00000000; +SDRAM[0].EmcWdv = 0x00000007; +SDRAM[0].EmcWdvMask = 0x00000007; +SDRAM[0].EmcQUse = 0x00000011; +SDRAM[0].EmcQuseWidth = 0x00000004; +SDRAM[0].EmcIbdly = 0x00000000; +SDRAM[0].EmcEInput = 0x00000006; +SDRAM[0].EmcEInputDuration = 0x00000011; +SDRAM[0].EmcPutermExtra = 0x000e0000; +SDRAM[0].EmcPutermWidth = 0x00000006; +SDRAM[0].EmcPutermAdj = 0x00000000; +SDRAM[0].EmcCdbCntl1 = 0x00000000; +SDRAM[0].EmcCdbCntl2 = 0x00000000; +SDRAM[0].EmcCdbCntl3 = 0x00000000; +SDRAM[0].EmcQRst = 0x00000005; +SDRAM[0].EmcQSafe = 0x00000018; +SDRAM[0].EmcRdv = 0x00000020; +SDRAM[0].EmcRdvMask = 0x00000022; +SDRAM[0].EmcQpop = 0x00000017; +SDRAM[0].EmcCtt = 0x00000000; +SDRAM[0].EmcCttDuration = 0x00000006; +SDRAM[0].EmcRefresh = 0x00000dd4; +SDRAM[0].EmcBurstRefreshNum = 0x00000000; +SDRAM[0].EmcPreRefreshReqCnt = 0x00000375; +SDRAM[0].EmcPdEx2Wr = 0x00000006; +SDRAM[0].EmcPdEx2Rd = 0x00000006; +SDRAM[0].EmcPChg2Pden = 0x00000010; +SDRAM[0].EmcAct2Pden = 0x00000000; +SDRAM[0].EmcAr2Pden = 0x00000001; +SDRAM[0].EmcRw2Pden = 0x0000001b; +SDRAM[0].EmcTxsr = 0x00000082; +SDRAM[0].EmcTxsrDll = 0x00000082; +SDRAM[0].EmcTcke = 0x00000007; +SDRAM[0].EmcTckesr = 0x0000000e; +SDRAM[0].EmcTpd = 0x00000007; +SDRAM[0].EmcTfaw = 0x0000002d; +SDRAM[0].EmcTrpab = 0x00000014; +SDRAM[0].EmcTClkStable = 0x00000003; +SDRAM[0].EmcTClkStop = 0x00000003; +SDRAM[0].EmcTRefBw = 0x00000f04; +SDRAM[0].EmcFbioCfg5 = 0x1363a896; +SDRAM[0].EmcFbioCfg6 = 0x00000000; +SDRAM[0].EmcFbioSpare = 0x00000000; +SDRAM[0].EmcCfgRsv = 0xff00ff00; +SDRAM[0].EmcMrs = 0x00000000; +SDRAM[0].EmcEmrs = 0x00000000; +SDRAM[0].EmcEmrs2 = 0x00000000; +SDRAM[0].EmcEmrs3 = 0x00000000; +SDRAM[0].EmcMrw1 = 0x00010083; +SDRAM[0].EmcMrw2 = 0x0002001c; +SDRAM[0].EmcMrw3 = 0x00030001; +SDRAM[0].EmcMrw4 = 0x800b0000; +SDRAM[0].EmcMrwExtra = 0x00010083; +SDRAM[0].EmcWarmBootMrwExtra = 0x0002001c; +SDRAM[0].EmcWarmBootExtraModeRegWriteEnable = 0x00000000; +SDRAM[0].EmcExtraModeRegWriteEnable = 0x00000000; +SDRAM[0].EmcMrwResetCommand = 0x003f00fc; +SDRAM[0].EmcMrwResetNInitWait = 0x0000000a; +SDRAM[0].EmcMrsWaitCnt = 0x039c0019; +SDRAM[0].EmcMrsWaitCnt2 = 0x039c0019; +SDRAM[0].EmcCfg = 0xf3300000; +SDRAM[0].EmcCfg2 = 0x0000089f; +SDRAM[0].EmcCfgPipe = 0x00004080; +SDRAM[0].EmcDbg = 0x01000c00; +SDRAM[0].EmcCmdQ = 0x10004408; +SDRAM[0].EmcMc2EmcQ = 0x06000404; +SDRAM[0].EmcDynSelfRefControl = 0x80001c77; +SDRAM[0].AhbArbitrationXbarCtrlMemInitDone = 0x00000001; +SDRAM[0].EmcCfgDigDll = 0xe00400b9; +SDRAM[0].EmcCfgDigDllPeriod = 0x00008000; +SDRAM[0].EmcDevSelect = 0x00000000; +SDRAM[0].EmcSelDpdCtrl = 0x0004001c; +SDRAM[0].EmcDllXformDqs0 = 0x007fc00a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs1 = 0x007fc00a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs2 = 0x007fc00a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs3 = 0x007fc00a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs4 = 0x007f800c; ##0x007f800a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs5 = 0x00000008; ##0x007fc008; ##0x007f400a; +SDRAM[0].EmcDllXformDqs6 = 0x007f800a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs7 = 0x007fc00a; ##0x007f800a; ##0x007f400a; +SDRAM[0].EmcDllXformDqs8 = 0x007f400a; +SDRAM[0].EmcDllXformDqs9 = 0x007f400a; +SDRAM[0].EmcDllXformDqs10 = 0x007f400a; +SDRAM[0].EmcDllXformDqs11 = 0x007f400a; +SDRAM[0].EmcDllXformDqs12 = 0x007f400a; +SDRAM[0].EmcDllXformDqs13 = 0x007f400a; +SDRAM[0].EmcDllXformDqs14 = 0x007f400a; +SDRAM[0].EmcDllXformDqs15 = 0x007f400a; +SDRAM[0].EmcDllXformQUse0 = 0x00000000; +SDRAM[0].EmcDllXformQUse1 = 0x00000000; +SDRAM[0].EmcDllXformQUse2 = 0x00000000; +SDRAM[0].EmcDllXformQUse3 = 0x00000000; +SDRAM[0].EmcDllXformQUse4 = 0x00000000; +SDRAM[0].EmcDllXformQUse5 = 0x00000000; +SDRAM[0].EmcDllXformQUse6 = 0x00000000; +SDRAM[0].EmcDllXformQUse7 = 0x00000000; +SDRAM[0].EmcDllXformAddr0 = 0x00018002; ##0x00020000; ##0x0001c000 +SDRAM[0].EmcDllXformAddr1 = 0x00018002; ##0x00020000; ##0x0001c000 +SDRAM[0].EmcDllXformAddr2 = 0x00000008; ##0x00000006 +SDRAM[0].EmcDllXformAddr3 = 0x00018002; ##0x00020000; ##0x0001c000 +SDRAM[0].EmcDllXformAddr4 = 0x00018002; ##0x00020000; ##0x0001c000 +SDRAM[0].EmcDllXformAddr5 = 0x00000008; ##0x00000006 +SDRAM[0].EmcDllXformQUse8 = 0x00000000; +SDRAM[0].EmcDllXformQUse9 = 0x00000000; +SDRAM[0].EmcDllXformQUse10 = 0x00000000; +SDRAM[0].EmcDllXformQUse11 = 0x00000000; +SDRAM[0].EmcDllXformQUse12 = 0x00000000; +SDRAM[0].EmcDllXformQUse13 = 0x00000000; +SDRAM[0].EmcDllXformQUse14 = 0x00000000; +SDRAM[0].EmcDllXformQUse15 = 0x00000000; +SDRAM[0].EmcDliTrimTxDqs0 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs1 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs2 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs3 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs4 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs5 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs6 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs7 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs8 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs9 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs10 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs11 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs12 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs13 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs14 = 0x00000008; +SDRAM[0].EmcDliTrimTxDqs15 = 0x00000008; +SDRAM[0].EmcDllXformDq0 = 0x0000000c; +SDRAM[0].EmcDllXformDq1 = 0x0000000c; +SDRAM[0].EmcDllXformDq2 = 0x0000000c; +SDRAM[0].EmcDllXformDq3 = 0x0000000c; +SDRAM[0].EmcDllXformDq4 = 0x0000000c; +SDRAM[0].EmcDllXformDq5 = 0x0000000c; +SDRAM[0].EmcDllXformDq6 = 0x0000000c; +SDRAM[0].EmcDllXformDq7 = 0x0000000c; +SDRAM[0].WarmBootWait = 0x00000001; +SDRAM[0].EmcCttTermCtrl = 0x00000802; +SDRAM[0].EmcOdtWrite = 0x00000000; +SDRAM[0].EmcOdtRead = 0x00000000; +SDRAM[0].EmcZcalInterval = 0x00064000; +SDRAM[0].EmcZcalWaitCnt = 0x00000058; +SDRAM[0].EmcZcalMrwCmd = 0x000a0056; +SDRAM[0].EmcMrsResetDll = 0x00000000; +SDRAM[0].EmcZcalInitDev0 = 0x840a00ff; +SDRAM[0].EmcZcalInitDev1 = 0x440a00ff; +SDRAM[0].EmcZcalInitWait = 0x00000001; +SDRAM[0].EmcZcalWarmColdBootEnables = 0x00000003; +SDRAM[0].EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab; +SDRAM[0].EmcZqCalDdr3WarmBoot = 0x00000000; +SDRAM[0].EmcZcalWarmBootWait = 0x00000001; +SDRAM[0].EmcMrsWarmBootEnable = 0x00000001; +SDRAM[0].EmcMrsResetDllWait = 0x00000000; +SDRAM[0].EmcMrsExtra = 0x00000000; +SDRAM[0].EmcWarmBootMrsExtra = 0x00000000; +SDRAM[0].EmcEmrsDdr2DllEnable = 0x00000000; +SDRAM[0].EmcMrsDdr2DllReset = 0x00000000; +SDRAM[0].EmcEmrsDdr2OcdCalib = 0x00000000; +SDRAM[0].EmcDdr2Wait = 0x00000000; +SDRAM[0].EmcClkenOverride = 0x00000000; +SDRAM[0].McDisExtraSnapLevels = 0x00000000; +SDRAM[0].EmcExtraRefreshNum = 0x00000002; +SDRAM[0].EmcClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[0].McClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[0].EmcCfgDigDllPeriodWarmBoot = 0x00000003; +SDRAM[0].PmcVddpSel = 0x00000001; +SDRAM[0].PmcVddpSelWait = 0x00000002; +SDRAM[0].PmcDdrPwr = 0x00000003; +SDRAM[0].PmcDdrCfg = 0x00001000; +SDRAM[0].PmcIoDpd3Req = 0x4ffefef7; +SDRAM[0].PmcIoDpd3ReqWait = 0x00000000; +SDRAM[0].PmcRegShort = 0x0000330f; +SDRAM[0].PmcNoIoPower = 0x00000000; +SDRAM[0].PmcPorDpdCtrlWait = 0x00000001; +SDRAM[0].EmcXm2CmdPadCtrl = 0x00000220; +SDRAM[0].EmcXm2CmdPadCtrl2 = 0x770c0000; +SDRAM[0].EmcXm2CmdPadCtrl3 = 0x050c0000; +SDRAM[0].EmcXm2CmdPadCtrl4 = 0x00000000; +SDRAM[0].EmcXm2CmdPadCtrl5 = 0x00100100; +SDRAM[0].EmcXm2DqsPadCtrl = 0x770c1414; +SDRAM[0].EmcXm2DqsPadCtrl2 = 0x0120103d; +SDRAM[0].EmcXm2DqsPadCtrl3 = 0x55555520; ##0x65965920; +SDRAM[0].EmcXm2DqsPadCtrl4 = 0x00596596; +SDRAM[0].EmcXm2DqsPadCtrl5 = 0x00596596; +SDRAM[0].EmcXm2DqsPadCtrl6 = 0x55555500; ##0x65965900; +SDRAM[0].EmcXm2DqPadCtrl = 0x770c2990; +SDRAM[0].EmcXm2DqPadCtrl2 = 0x00000000; +SDRAM[0].EmcXm2DqPadCtrl3 = 0x00000000; +SDRAM[0].EmcXm2ClkPadCtrl = 0x77ffc004; +SDRAM[0].EmcXm2ClkPadCtrl2 = 0x00000000; +SDRAM[0].EmcXm2CompPadCtrl = 0x81f1f008; +SDRAM[0].EmcXm2VttGenPadCtrl = 0x07070000; +SDRAM[0].EmcXm2VttGenPadCtrl2 = 0x00000000; +SDRAM[0].EmcXm2VttGenPadCtrl3 = 0x015ddddd; +SDRAM[0].EmcAcpdControl = 0x00000000; +SDRAM[0].EmcSwizzleRank0ByteCfg = 0x00001032; +SDRAM[0].EmcSwizzleRank0Byte0 = 0x53067142; +SDRAM[0].EmcSwizzleRank0Byte1 = 0x73025146; +SDRAM[0].EmcSwizzleRank0Byte2 = 0x20136475; +SDRAM[0].EmcSwizzleRank0Byte3 = 0x46273150; +SDRAM[0].EmcSwizzleRank1ByteCfg = 0x00003210; +SDRAM[0].EmcSwizzleRank1Byte0 = 0x73451026; +SDRAM[0].EmcSwizzleRank1Byte1 = 0x73025146; +SDRAM[0].EmcSwizzleRank1Byte2 = 0x20641735; +SDRAM[0].EmcSwizzleRank1Byte3 = 0x42136075; +SDRAM[0].EmcDsrVttgenDrv = 0x0000003f; +SDRAM[0].EmcTxdsrvttgen = 0x00000000; +SDRAM[0].EmcBgbiasCtl0 = 0x00000000; +SDRAM[0].McEmemAdrCfg = 0x00000001; +SDRAM[0].McEmemAdrCfgDev0 = 0x00080304; +SDRAM[0].McEmemAdrCfgDev1 = 0x00080304; +SDRAM[0].McEmemAdrCfgBankMask0 = 0x00001248; +SDRAM[0].McEmemAdrCfgBankMask1 = 0x00002490; +SDRAM[0].McEmemAdrCfgBankMask2 = 0x00000920; +SDRAM[0].McEmemAdrCfgBankSwizzle3 = 0x00000001; +SDRAM[0].McEmemCfg = 0x00001000; +SDRAM[0].McEmemArbCfg = 0x0e00000d; +SDRAM[0].McEmemArbOutstandingReq = 0x80000040; +SDRAM[0].McEmemArbTimingRcd = 0x00000007; +SDRAM[0].McEmemArbTimingRp = 0x00000008; +SDRAM[0].McEmemArbTimingRc = 0x0000001b; +SDRAM[0].McEmemArbTimingRas = 0x00000012; +SDRAM[0].McEmemArbTimingFaw = 0x00000017; +SDRAM[0].McEmemArbTimingRrd = 0x00000004; +SDRAM[0].McEmemArbTimingRap2Pre = 0x00000004; +SDRAM[0].McEmemArbTimingWap2Pre = 0x0000000e; +SDRAM[0].McEmemArbTimingR2R = 0x00000004; +SDRAM[0].McEmemArbTimingW2W = 0x00000001; +SDRAM[0].McEmemArbTimingR2W = 0x00000009; +SDRAM[0].McEmemArbTimingW2R = 0x00000009; +SDRAM[0].McEmemArbDaTurns = 0x09090104; +SDRAM[0].McEmemArbDaCovers = 0x001e141b; +SDRAM[0].McEmemArbMisc0 = 0x71ae2a1c; +SDRAM[0].McEmemArbMisc1 = 0x70000f02; +SDRAM[0].McEmemArbRing1Throttle = 0x001f0000; +SDRAM[0].McEmemArbOverride = 0x10000000; +SDRAM[0].McEmemArbOverride1 = 0x00000000; +SDRAM[0].McEmemArbRsv = 0xff00ff00; +SDRAM[0].McClkenOverride = 0x00000000; +SDRAM[0].McStatControl = 0x00000000; +SDRAM[0].McDisplaySnapRing = 0x00000003; +SDRAM[0].McVideoProtectBom = 0xfff00000; +SDRAM[0].McVideoProtectBomAdrHi = 0x00000000; +SDRAM[0].McVideoProtectSizeMb = 0x00000000; +SDRAM[0].McVideoProtectVprOverride = 0xe4bac743; +SDRAM[0].McVideoProtectVprOverride1 = 0x00000013; +SDRAM[0].McVideoProtectGpuOverride0 = 0x00000000; +SDRAM[0].McVideoProtectGpuOverride1 = 0x00000000; +SDRAM[0].McSecCarveoutBom = 0xfff00000; +SDRAM[0].McSecCarveoutAdrHi = 0x00000000; +SDRAM[0].McSecCarveoutSizeMb = 0x00000000; +SDRAM[0].McVideoProtectWriteAccess = 0x00000000; +SDRAM[0].McSecCarveoutProtectWriteAccess = 0x00000000; +SDRAM[0].EmcCaTrainingEnable = 0x00000001; +SDRAM[0].EmcCaTrainingTimingCntl1 = 0x09257359; +SDRAM[0].EmcCaTrainingTimingCntl2 = 0x00000017; +SDRAM[0].SwizzleRankByteEncode = 0x00000008; +SDRAM[0].BootRomPatchControl = 0x00000000; +SDRAM[0].BootRomPatchData = 0x00000000; +SDRAM[0].McMtsCarveoutBom = 0x78000000; +SDRAM[0].McMtsCarveoutAdrHi = 0x00000001; +SDRAM[0].McMtsCarveoutSizeMb = 0x00000080; +SDRAM[0].McMtsCarveoutRegCtrl = 0x00000001; +#@ MC_MLL_MPCORER_PTSA_RATE {0x7001944c} = 0x00000017; +#@ MC_PTSA_GRANT_DECREMENT {0x70019960} = 0x000001bb; +#@ MC_LATENCY_ALLOWANCE_XUSB_0 {0x7001937c} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_XUSB_1 {0x70019380} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_TSEC_0 {0x70019390} = 0x006e003c; +#@ MC_LATENCY_ALLOWANCE_SDMMCA_0 {0x700193b8} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAA_0 {0x700193bc} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_SDMMC_0 {0x700193c0} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAB_0 {0x700193c4} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_PPCS_0 {0x70019344} = 0x00270049; +#@ MC_LATENCY_ALLOWANCE_PPCS_1 {0x70019348} = 0x006e0080; +#@ MC_LATENCY_ALLOWANCE_MPCORE_0 {0x70019320} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_MPCORELP_0 {0x70019324} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_HC_0 {0x70019310} = 0x00080016; +#@ MC_LATENCY_ALLOWANCE_HC_1 {0x70019314} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_AVPC_0 {0x700192e4} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_GPU_0 {0x700193ac} = 0x006e0019; +#@ MC_LATENCY_ALLOWANCE_MSENC_0 {0x70019328} = 0x006e0018; +#@ MC_LATENCY_ALLOWANCE_HDA_0 {0x70019318} = 0x006e0024; +#@ MC_LATENCY_ALLOWANCE_VIC_0 {0x70019394} = 0x006e001b; +#@ MC_LATENCY_ALLOWANCE_VI2_0 {0x70019398} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_ISP2_0 {0x70019370} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2_1 {0x70019374} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_ISP2B_0 {0x70019384} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2B_1 {0x70019388} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_0 {0x70019354} = 0x00d400ff; +#@ MC_LATENCY_ALLOWANCE_VDE_1 {0x70019358} = 0x00510029; +#@ MC_LATENCY_ALLOWANCE_VDE_2 {0x7001935c} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_3 {0x70019360} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_SATA_0 {0x70019350} = 0x006e0065; +#@ MC_LATENCY_ALLOWANCE_AFI_0 {0x700192e0} = 0x006e001c; +# +# CFG Version 01 HYNIX +# Do not edit. Generated by T132_emc_reg_toolV6.0.4 V6.0.4. Command: +# T132_emc_reg_toolV6.0.4 -i denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par -b A44_924MHz_emc_reg.txt 1.08225 +# -o A44_64_924_tool_emcregtoolv4.cfg -dram_board_cfg 3 -round_trip_dly_ps 589.6 +# Parameter file: denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par, tck = 1.08 ns (924.00 MHz) +# bkv file: A44_924MHz_emc_reg.txt +SDRAM[1].MemoryType = NvBootMemoryType_LpDdr2; +SDRAM[1].PllMInputDivider = 0x00000001; +SDRAM[1].PllMFeedbackDivider = 0x0000004d; +SDRAM[1].PllMStableTime = 0x0000012c; +SDRAM[1].PllMSetupControl = 0x00000000; +SDRAM[1].PllMSelectDiv2 = 0x00000000; +SDRAM[1].PllMPDLshiftPh45 = 0x00000001; +SDRAM[1].PllMPDLshiftPh90 = 0x00000001; +SDRAM[1].PllMPDLshiftPh135 = 0x00000001; +SDRAM[1].PllMKCP = 0x00000000; +SDRAM[1].PllMKVCO = 0x00000000; +SDRAM[1].EmcBctSpare0 = 0x00000000; +SDRAM[1].EmcBctSpare1 = 0x00000000; +SDRAM[1].EmcBctSpare2 = 0x00000000; +SDRAM[1].EmcBctSpare3 = 0x00000000; +SDRAM[1].EmcBctSpare4 = 0x00000000; +SDRAM[1].EmcBctSpare5 = 0x00000000; +SDRAM[1].EmcBctSpare6 = 0x00000000; +SDRAM[1].EmcBctSpare7 = 0x00000000; +SDRAM[1].EmcBctSpare8 = 0x00000000; +SDRAM[1].EmcBctSpare9 = 0x00000000; +SDRAM[1].EmcBctSpare10 = 0x00000000; +SDRAM[1].EmcBctSpare11 = 0x00000000; +SDRAM[1].EmcClockSource = 0x80000000; +SDRAM[1].EmcAutoCalInterval = 0x001fffff; +SDRAM[1].EmcAutoCalConfig = 0xa1430000; +SDRAM[1].EmcAutoCalConfig2 = 0x00000000; +SDRAM[1].EmcAutoCalConfig3 = 0x00000000; +SDRAM[1].EmcAutoCalWait = 0x00000190; +SDRAM[1].EmcAdrCfg = 0x00000001; +SDRAM[1].EmcPinProgramWait = 0x00000000; +SDRAM[1].EmcPinExtraWait = 0x00000000; +SDRAM[1].EmcTimingControlWait = 0x00000000; +SDRAM[1].EmcRc = 0x00000037; +SDRAM[1].EmcRfc = 0x00000078; +SDRAM[1].EmcRfcSlr = 0x00000000; +SDRAM[1].EmcRas = 0x00000026; +SDRAM[1].EmcRp = 0x00000010; +SDRAM[1].EmcR2r = 0x00000000; +SDRAM[1].EmcW2w = 0x00000000; +SDRAM[1].EmcR2w = 0x00000010; +SDRAM[1].EmcW2r = 0x00000010; +SDRAM[1].EmcR2p = 0x00000006; +SDRAM[1].EmcW2p = 0x00000017; +SDRAM[1].EmcRdRcd = 0x00000010; +SDRAM[1].EmcWrRcd = 0x00000010; +SDRAM[1].EmcRrd = 0x00000009; +SDRAM[1].EmcRext = 0x00000005; +SDRAM[1].EmcWext = 0x00000000; +SDRAM[1].EmcWdv = 0x00000007; +SDRAM[1].EmcWdvMask = 0x00000007; +SDRAM[1].EmcQUse = 0x00000011; +SDRAM[1].EmcQuseWidth = 0x00000004; +SDRAM[1].EmcIbdly = 0x00000000; +SDRAM[1].EmcEInput = 0x00000006; +SDRAM[1].EmcEInputDuration = 0x00000011; +SDRAM[1].EmcPutermExtra = 0x000e0000; +SDRAM[1].EmcPutermWidth = 0x00000006; +SDRAM[1].EmcPutermAdj = 0x00000000; +SDRAM[1].EmcCdbCntl1 = 0x00000000; +SDRAM[1].EmcCdbCntl2 = 0x00000000; +SDRAM[1].EmcCdbCntl3 = 0x00000000; +SDRAM[1].EmcQRst = 0x00000005; +SDRAM[1].EmcQSafe = 0x00000018; +SDRAM[1].EmcRdv = 0x00000020; +SDRAM[1].EmcRdvMask = 0x00000022; +SDRAM[1].EmcQpop = 0x00000017; +SDRAM[1].EmcCtt = 0x00000000; +SDRAM[1].EmcCttDuration = 0x00000006; +SDRAM[1].EmcRefresh = 0x00000dd4; +SDRAM[1].EmcBurstRefreshNum = 0x00000000; +SDRAM[1].EmcPreRefreshReqCnt = 0x00000375; +SDRAM[1].EmcPdEx2Wr = 0x00000006; +SDRAM[1].EmcPdEx2Rd = 0x00000006; +SDRAM[1].EmcPChg2Pden = 0x00000010; +SDRAM[1].EmcAct2Pden = 0x00000000; +SDRAM[1].EmcAr2Pden = 0x00000001; +SDRAM[1].EmcRw2Pden = 0x0000001b; +SDRAM[1].EmcTxsr = 0x00000082; +SDRAM[1].EmcTxsrDll = 0x00000082; +SDRAM[1].EmcTcke = 0x00000007; +SDRAM[1].EmcTckesr = 0x0000000e; +SDRAM[1].EmcTpd = 0x00000007; +SDRAM[1].EmcTfaw = 0x0000002d; +SDRAM[1].EmcTrpab = 0x00000014; +SDRAM[1].EmcTClkStable = 0x00000003; +SDRAM[1].EmcTClkStop = 0x00000003; +SDRAM[1].EmcTRefBw = 0x00000f04; +SDRAM[1].EmcFbioCfg5 = 0x1363a896; +SDRAM[1].EmcFbioCfg6 = 0x00000000; +SDRAM[1].EmcFbioSpare = 0x00000000; +SDRAM[1].EmcCfgRsv = 0xff00ff00; +SDRAM[1].EmcMrs = 0x00000000; +SDRAM[1].EmcEmrs = 0x00000000; +SDRAM[1].EmcEmrs2 = 0x00000000; +SDRAM[1].EmcEmrs3 = 0x00000000; +SDRAM[1].EmcMrw1 = 0x00010083; +SDRAM[1].EmcMrw2 = 0x0002001c; +SDRAM[1].EmcMrw3 = 0x00030001; +SDRAM[1].EmcMrw4 = 0x800b0000; +SDRAM[1].EmcMrwExtra = 0x00010083; +SDRAM[1].EmcWarmBootMrwExtra = 0x0002001c; +SDRAM[1].EmcWarmBootExtraModeRegWriteEnable = 0x00000000; +SDRAM[1].EmcExtraModeRegWriteEnable = 0x00000000; +SDRAM[1].EmcMrwResetCommand = 0x003f00fc; +SDRAM[1].EmcMrwResetNInitWait = 0x0000000a; +SDRAM[1].EmcMrsWaitCnt = 0x039c0019; +SDRAM[1].EmcMrsWaitCnt2 = 0x039c0019; +SDRAM[1].EmcCfg = 0xd3300000; +SDRAM[1].EmcCfg2 = 0x0000089f; +SDRAM[1].EmcCfgPipe = 0x00004080; +SDRAM[1].EmcDbg = 0x01000c00; +SDRAM[1].EmcCmdQ = 0x10004408; +SDRAM[1].EmcMc2EmcQ = 0x06000404; +SDRAM[1].EmcDynSelfRefControl = 0x80001c77; +SDRAM[1].AhbArbitrationXbarCtrlMemInitDone = 0x00000001; +SDRAM[1].EmcCfgDigDll = 0xe00400b9; +SDRAM[1].EmcCfgDigDllPeriod = 0x00008000; +SDRAM[1].EmcDevSelect = 0x00000000; +SDRAM[1].EmcSelDpdCtrl = 0x0004001c; +SDRAM[1].EmcDllXformDqs0 = 0x0000000a; ##0x007fc008; ##0x0000000a; +SDRAM[1].EmcDllXformDqs1 = 0x0000000a; +SDRAM[1].EmcDllXformDqs2 = 0x0000000c; ##0x0000000a; +SDRAM[1].EmcDllXformDqs3 = 0x0000000a; ##0x007f800a; ##0x0000000a; +SDRAM[1].EmcDllXformDqs4 = 0x00000008; ##0x007fc00a; ##0x0000000a; +SDRAM[1].EmcDllXformDqs5 = 0x00004008; ##0x0000000a; +SDRAM[1].EmcDllXformDqs6 = 0x0000000a; ##0x0000000a; +SDRAM[1].EmcDllXformDqs7 = 0x00000008; ##0x007f800a; ##0x0000000a; +SDRAM[1].EmcDllXformDqs8 = 0x0000000a; +SDRAM[1].EmcDllXformDqs9 = 0x0000000a; +SDRAM[1].EmcDllXformDqs10 = 0x0000000a; +SDRAM[1].EmcDllXformDqs11 = 0x0000000a; +SDRAM[1].EmcDllXformDqs12 = 0x0000000a; +SDRAM[1].EmcDllXformDqs13 = 0x0000000a; +SDRAM[1].EmcDllXformDqs14 = 0x0000000a; +SDRAM[1].EmcDllXformDqs15 = 0x0000000a; +SDRAM[1].EmcDllXformQUse0 = 0x00000000; +SDRAM[1].EmcDllXformQUse1 = 0x00000000; +SDRAM[1].EmcDllXformQUse2 = 0x00000000; +SDRAM[1].EmcDllXformQUse3 = 0x00000000; +SDRAM[1].EmcDllXformQUse4 = 0x00000000; +SDRAM[1].EmcDllXformQUse5 = 0x00000000; +SDRAM[1].EmcDllXformQUse6 = 0x00000000; +SDRAM[1].EmcDllXformQUse7 = 0x00000000; +SDRAM[1].EmcDllXformAddr0 = 0x00024002; ##0x00028002; ##0x00020000; +SDRAM[1].EmcDllXformAddr1 = 0x00024002; ##0x00028002; ##0x00020000; +SDRAM[1].EmcDllXformAddr2 = 0x00000008; ##0x00000006 +SDRAM[1].EmcDllXformAddr3 = 0x00024002; ##0x00028002; ##0x00020000; +SDRAM[1].EmcDllXformAddr4 = 0x00024002; ##0x00028002; ##0x00020000; +SDRAM[1].EmcDllXformAddr5 = 0x00000008; ##0x00000006 +SDRAM[1].EmcDllXformQUse8 = 0x00000000; +SDRAM[1].EmcDllXformQUse9 = 0x00000000; +SDRAM[1].EmcDllXformQUse10 = 0x00000000; +SDRAM[1].EmcDllXformQUse11 = 0x00000000; +SDRAM[1].EmcDllXformQUse12 = 0x00000000; +SDRAM[1].EmcDllXformQUse13 = 0x00000000; +SDRAM[1].EmcDllXformQUse14 = 0x00000000; +SDRAM[1].EmcDllXformQUse15 = 0x00000000; +SDRAM[1].EmcDliTrimTxDqs0 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs1 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs2 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs3 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs4 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs5 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs6 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs7 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs8 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs9 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs10 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs11 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs12 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs13 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs14 = 0x00000008; +SDRAM[1].EmcDliTrimTxDqs15 = 0x00000008; +SDRAM[1].EmcDllXformDq0 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq1 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq2 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq3 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq4 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq5 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq6 = 0x0000000e; ##0x0000000c; +SDRAM[1].EmcDllXformDq7 = 0x0000000e; ##0x0000000c; +SDRAM[1].WarmBootWait = 0x00000001; +SDRAM[1].EmcCttTermCtrl = 0x00000802; +SDRAM[1].EmcOdtWrite = 0x00000000; +SDRAM[1].EmcOdtRead = 0x00000000; +SDRAM[1].EmcZcalInterval = 0x00064000; +SDRAM[1].EmcZcalWaitCnt = 0x00000058; +SDRAM[1].EmcZcalMrwCmd = 0x000a0056; +SDRAM[1].EmcMrsResetDll = 0x00000000; +SDRAM[1].EmcZcalInitDev0 = 0x840a00ff; +SDRAM[1].EmcZcalInitDev1 = 0x440a00ff; +SDRAM[1].EmcZcalInitWait = 0x00000001; +SDRAM[1].EmcZcalWarmColdBootEnables = 0x00000003; +SDRAM[1].EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab; +SDRAM[1].EmcZqCalDdr3WarmBoot = 0x00000000; +SDRAM[1].EmcZcalWarmBootWait = 0x00000001; +SDRAM[1].EmcMrsWarmBootEnable = 0x00000001; +SDRAM[1].EmcMrsResetDllWait = 0x00000000; +SDRAM[1].EmcMrsExtra = 0x00000000; +SDRAM[1].EmcWarmBootMrsExtra = 0x00000000; +SDRAM[1].EmcEmrsDdr2DllEnable = 0x00000000; +SDRAM[1].EmcMrsDdr2DllReset = 0x00000000; +SDRAM[1].EmcEmrsDdr2OcdCalib = 0x00000000; +SDRAM[1].EmcDdr2Wait = 0x00000000; +SDRAM[1].EmcClkenOverride = 0x00000000; +SDRAM[1].McDisExtraSnapLevels = 0x00000000; +SDRAM[1].EmcExtraRefreshNum = 0x00000002; +SDRAM[1].EmcClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[1].McClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[1].EmcCfgDigDllPeriodWarmBoot = 0x00000003; +SDRAM[1].PmcVddpSel = 0x00000001; +SDRAM[1].PmcVddpSelWait = 0x00000002; +SDRAM[1].PmcDdrPwr = 0x00000003; +SDRAM[1].PmcDdrCfg = 0x00001000; +SDRAM[1].PmcIoDpd3Req = 0x4ffefef7; +SDRAM[1].PmcIoDpd3ReqWait = 0x00000000; +SDRAM[1].PmcRegShort = 0x0000330f; +SDRAM[1].PmcNoIoPower = 0x00000000; +SDRAM[1].PmcPorDpdCtrlWait = 0x00000001; +SDRAM[1].EmcXm2CmdPadCtrl = 0x00000220; +SDRAM[1].EmcXm2CmdPadCtrl2 = 0x770c0000; +SDRAM[1].EmcXm2CmdPadCtrl3 = 0x050c0000; +SDRAM[1].EmcXm2CmdPadCtrl4 = 0x00000000; +SDRAM[1].EmcXm2CmdPadCtrl5 = 0x00100100; +SDRAM[1].EmcXm2DqsPadCtrl = 0x770c1414; +SDRAM[1].EmcXm2DqsPadCtrl2 = 0x0120103d; +SDRAM[1].EmcXm2DqsPadCtrl3 = 0x55555520; ##0x65965920; +SDRAM[1].EmcXm2DqsPadCtrl4 = 0x00492492; ##0x00596596; +SDRAM[1].EmcXm2DqsPadCtrl5 = 0x00492492; ##0x00596596; +SDRAM[1].EmcXm2DqsPadCtrl6 = 0x55555500; ##0x65965900; +SDRAM[1].EmcXm2DqPadCtrl = 0x770c2990; +SDRAM[1].EmcXm2DqPadCtrl2 = 0x00000000; +SDRAM[1].EmcXm2DqPadCtrl3 = 0x00000000; +SDRAM[1].EmcXm2ClkPadCtrl = 0x77ffc004; +SDRAM[1].EmcXm2ClkPadCtrl2 = 0x00000000; +SDRAM[1].EmcXm2CompPadCtrl = 0x81f1f008; +SDRAM[1].EmcXm2VttGenPadCtrl = 0x07070000; +SDRAM[1].EmcXm2VttGenPadCtrl2 = 0x00000000; +SDRAM[1].EmcXm2VttGenPadCtrl3 = 0x015ddddd; +SDRAM[1].EmcAcpdControl = 0x00000000; +SDRAM[1].EmcSwizzleRank0ByteCfg = 0x00001032; +SDRAM[1].EmcSwizzleRank0Byte0 = 0x53067142; +SDRAM[1].EmcSwizzleRank0Byte1 = 0x73025146; +SDRAM[1].EmcSwizzleRank0Byte2 = 0x20136475; +SDRAM[1].EmcSwizzleRank0Byte3 = 0x46273150; +SDRAM[1].EmcSwizzleRank1ByteCfg = 0x00003210; +SDRAM[1].EmcSwizzleRank1Byte0 = 0x73451026; +SDRAM[1].EmcSwizzleRank1Byte1 = 0x73025146; +SDRAM[1].EmcSwizzleRank1Byte2 = 0x20641735; +SDRAM[1].EmcSwizzleRank1Byte3 = 0x42136075; +SDRAM[1].EmcDsrVttgenDrv = 0x0000003f; +SDRAM[1].EmcTxdsrvttgen = 0x00000000; +SDRAM[1].EmcBgbiasCtl0 = 0x00000000; +SDRAM[1].McEmemAdrCfg = 0x00000001; +SDRAM[1].McEmemAdrCfgDev0 = 0x00080304; +SDRAM[1].McEmemAdrCfgDev1 = 0x00080304; +SDRAM[1].McEmemAdrCfgBankMask0 = 0x00001248; +SDRAM[1].McEmemAdrCfgBankMask1 = 0x00002490; +SDRAM[1].McEmemAdrCfgBankMask2 = 0x00000920; +SDRAM[1].McEmemAdrCfgBankSwizzle3 = 0x00000001; +SDRAM[1].McEmemCfg = 0x00001000; +SDRAM[1].McEmemArbCfg = 0x0e00000d; +SDRAM[1].McEmemArbOutstandingReq = 0x80000040; +SDRAM[1].McEmemArbTimingRcd = 0x00000007; +SDRAM[1].McEmemArbTimingRp = 0x00000008; +SDRAM[1].McEmemArbTimingRc = 0x0000001b; +SDRAM[1].McEmemArbTimingRas = 0x00000012; +SDRAM[1].McEmemArbTimingFaw = 0x00000017; +SDRAM[1].McEmemArbTimingRrd = 0x00000004; +SDRAM[1].McEmemArbTimingRap2Pre = 0x00000004; +SDRAM[1].McEmemArbTimingWap2Pre = 0x0000000e; +SDRAM[1].McEmemArbTimingR2R = 0x00000004; +SDRAM[1].McEmemArbTimingW2W = 0x00000001; +SDRAM[1].McEmemArbTimingR2W = 0x00000009; +SDRAM[1].McEmemArbTimingW2R = 0x00000009; +SDRAM[1].McEmemArbDaTurns = 0x09090104; +SDRAM[1].McEmemArbDaCovers = 0x001e141b; +SDRAM[1].McEmemArbMisc0 = 0x71ae2a1c; +SDRAM[1].McEmemArbMisc1 = 0x70000f02; +SDRAM[1].McEmemArbRing1Throttle = 0x001f0000; +SDRAM[1].McEmemArbOverride = 0x10000000; +SDRAM[1].McEmemArbOverride1 = 0x00000000; +SDRAM[1].McEmemArbRsv = 0xff00ff00; +SDRAM[1].McClkenOverride = 0x00000000; +SDRAM[1].McStatControl = 0x00000000; +SDRAM[1].McDisplaySnapRing = 0x00000003; +SDRAM[1].McVideoProtectBom = 0xfff00000; +SDRAM[1].McVideoProtectBomAdrHi = 0x00000000; +SDRAM[1].McVideoProtectSizeMb = 0x00000000; +SDRAM[1].McVideoProtectVprOverride = 0xe4bac743; +SDRAM[1].McVideoProtectVprOverride1 = 0x00000013; +SDRAM[1].McVideoProtectGpuOverride0 = 0x00000000; +SDRAM[1].McVideoProtectGpuOverride1 = 0x00000000; +SDRAM[1].McSecCarveoutBom = 0xfff00000; +SDRAM[1].McSecCarveoutAdrHi = 0x00000000; +SDRAM[1].McSecCarveoutSizeMb = 0x00000000; +SDRAM[1].McVideoProtectWriteAccess = 0x00000000; +SDRAM[1].McSecCarveoutProtectWriteAccess = 0x00000000; +SDRAM[1].EmcCaTrainingEnable = 0x00000001; +SDRAM[1].EmcCaTrainingTimingCntl1 = 0x09257359; +SDRAM[1].EmcCaTrainingTimingCntl2 = 0x00000017; +SDRAM[1].SwizzleRankByteEncode = 0x00000008; +SDRAM[1].BootRomPatchControl = 0x00000000; +SDRAM[1].BootRomPatchData = 0x00000000; +SDRAM[1].McMtsCarveoutBom = 0x78000000; +SDRAM[1].McMtsCarveoutAdrHi = 0x00000001; +SDRAM[1].McMtsCarveoutSizeMb = 0x00000080; +SDRAM[1].McMtsCarveoutRegCtrl = 0x00000001; +#@ MC_MLL_MPCORER_PTSA_RATE {0x7001944c} = 0x00000017; +#@ MC_PTSA_GRANT_DECREMENT {0x70019960} = 0x000001bb; +#@ MC_LATENCY_ALLOWANCE_XUSB_0 {0x7001937c} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_XUSB_1 {0x70019380} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_TSEC_0 {0x70019390} = 0x006e003c; +#@ MC_LATENCY_ALLOWANCE_SDMMCA_0 {0x700193b8} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAA_0 {0x700193bc} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_SDMMC_0 {0x700193c0} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAB_0 {0x700193c4} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_PPCS_0 {0x70019344} = 0x00270049; +#@ MC_LATENCY_ALLOWANCE_PPCS_1 {0x70019348} = 0x006e0080; +#@ MC_LATENCY_ALLOWANCE_MPCORE_0 {0x70019320} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_MPCORELP_0 {0x70019324} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_HC_0 {0x70019310} = 0x00080016; +#@ MC_LATENCY_ALLOWANCE_HC_1 {0x70019314} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_AVPC_0 {0x700192e4} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_GPU_0 {0x700193ac} = 0x006e0019; +#@ MC_LATENCY_ALLOWANCE_MSENC_0 {0x70019328} = 0x006e0018; +#@ MC_LATENCY_ALLOWANCE_HDA_0 {0x70019318} = 0x006e0024; +#@ MC_LATENCY_ALLOWANCE_VIC_0 {0x70019394} = 0x006e001b; +#@ MC_LATENCY_ALLOWANCE_VI2_0 {0x70019398} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_ISP2_0 {0x70019370} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2_1 {0x70019374} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_ISP2B_0 {0x70019384} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2B_1 {0x70019388} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_0 {0x70019354} = 0x00d400ff; +#@ MC_LATENCY_ALLOWANCE_VDE_1 {0x70019358} = 0x00510029; +#@ MC_LATENCY_ALLOWANCE_VDE_2 {0x7001935c} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_3 {0x70019360} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_SATA_0 {0x70019350} = 0x006e0065; +#@ MC_LATENCY_ALLOWANCE_AFI_0 {0x700192e0} = 0x006e001c; +# +# CFG Version MICRON +# Do not edit. Generated by T132_emc_reg_toolV6.0.4 V6.0.4. Command: +# T132_emc_reg_toolV6.0.4 -i denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par -b A44_924MHz_emc_reg.txt 1.08225 +# -o A44_64_924_tool_emcregtoolv4.cfg -dram_board_cfg 3 -round_trip_dly_ps 589.6 +# Parameter file: denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par, tck = 1.08 ns (924.00 MHz) +# bkv file: A44_924MHz_emc_reg.txt +SDRAM[2].MemoryType = NvBootMemoryType_LpDdr2; +SDRAM[2].PllMInputDivider = 0x00000001; +SDRAM[2].PllMFeedbackDivider = 0x0000004d; +SDRAM[2].PllMStableTime = 0x0000012c; +SDRAM[2].PllMSetupControl = 0x00000000; +SDRAM[2].PllMSelectDiv2 = 0x00000000; +SDRAM[2].PllMPDLshiftPh45 = 0x00000001; +SDRAM[2].PllMPDLshiftPh90 = 0x00000001; +SDRAM[2].PllMPDLshiftPh135 = 0x00000001; +SDRAM[2].PllMKCP = 0x00000000; +SDRAM[2].PllMKVCO = 0x00000000; +SDRAM[2].EmcBctSpare0 = 0x00000000; +SDRAM[2].EmcBctSpare1 = 0x00000000; +SDRAM[2].EmcBctSpare2 = 0x00000000; +SDRAM[2].EmcBctSpare3 = 0x00000000; +SDRAM[2].EmcBctSpare4 = 0x00000000; +SDRAM[2].EmcBctSpare5 = 0x00000000; +SDRAM[2].EmcBctSpare6 = 0x00000000; +SDRAM[2].EmcBctSpare7 = 0x00000000; +SDRAM[2].EmcBctSpare8 = 0x00000000; +SDRAM[2].EmcBctSpare9 = 0x00000000; +SDRAM[2].EmcBctSpare10 = 0x00000000; +SDRAM[2].EmcBctSpare11 = 0x00000000; +SDRAM[2].EmcClockSource = 0x80000000; +SDRAM[2].EmcAutoCalInterval = 0x001fffff; +SDRAM[2].EmcAutoCalConfig = 0xa1430000; +SDRAM[2].EmcAutoCalConfig2 = 0x00000000; +SDRAM[2].EmcAutoCalConfig3 = 0x00000000; +SDRAM[2].EmcAutoCalWait = 0x00000190; +SDRAM[2].EmcAdrCfg = 0x00000001; +SDRAM[2].EmcPinProgramWait = 0x00000000; +SDRAM[2].EmcPinExtraWait = 0x00000000; +SDRAM[2].EmcTimingControlWait = 0x00000000; +SDRAM[2].EmcRc = 0x00000037; +SDRAM[2].EmcRfc = 0x00000078; +SDRAM[2].EmcRfcSlr = 0x00000000; +SDRAM[2].EmcRas = 0x00000026; +SDRAM[2].EmcRp = 0x00000010; +SDRAM[2].EmcR2r = 0x00000000; +SDRAM[2].EmcW2w = 0x00000000; +SDRAM[2].EmcR2w = 0x00000010; +SDRAM[2].EmcW2r = 0x00000010; +SDRAM[2].EmcR2p = 0x00000006; +SDRAM[2].EmcW2p = 0x00000017; +SDRAM[2].EmcRdRcd = 0x00000010; +SDRAM[2].EmcWrRcd = 0x00000010; +SDRAM[2].EmcRrd = 0x00000009; +SDRAM[2].EmcRext = 0x00000005; +SDRAM[2].EmcWext = 0x00000000; +SDRAM[2].EmcWdv = 0x00000007; +SDRAM[2].EmcWdvMask = 0x00000007; +SDRAM[2].EmcQUse = 0x00000011; +SDRAM[2].EmcQuseWidth = 0x00000004; +SDRAM[2].EmcIbdly = 0x00000000; +SDRAM[2].EmcEInput = 0x00000006; +SDRAM[2].EmcEInputDuration = 0x00000011; +SDRAM[2].EmcPutermExtra = 0x000e0000; +SDRAM[2].EmcPutermWidth = 0x00000006; +SDRAM[2].EmcPutermAdj = 0x00000000; +SDRAM[2].EmcCdbCntl1 = 0x00000000; +SDRAM[2].EmcCdbCntl2 = 0x00000000; +SDRAM[2].EmcCdbCntl3 = 0x00000000; +SDRAM[2].EmcQRst = 0x00000005; +SDRAM[2].EmcQSafe = 0x00000018; +SDRAM[2].EmcRdv = 0x00000020; +SDRAM[2].EmcRdvMask = 0x00000022; +SDRAM[2].EmcQpop = 0x00000017; +SDRAM[2].EmcCtt = 0x00000000; +SDRAM[2].EmcCttDuration = 0x00000006; +SDRAM[2].EmcRefresh = 0x00000dd4; +SDRAM[2].EmcBurstRefreshNum = 0x00000000; +SDRAM[2].EmcPreRefreshReqCnt = 0x00000375; +SDRAM[2].EmcPdEx2Wr = 0x00000006; +SDRAM[2].EmcPdEx2Rd = 0x00000006; +SDRAM[2].EmcPChg2Pden = 0x00000010; +SDRAM[2].EmcAct2Pden = 0x00000000; +SDRAM[2].EmcAr2Pden = 0x00000001; +SDRAM[2].EmcRw2Pden = 0x0000001b; +SDRAM[2].EmcTxsr = 0x00000082; +SDRAM[2].EmcTxsrDll = 0x00000082; +SDRAM[2].EmcTcke = 0x00000007; +SDRAM[2].EmcTckesr = 0x0000000e; +SDRAM[2].EmcTpd = 0x00000007; +SDRAM[2].EmcTfaw = 0x0000002d; +SDRAM[2].EmcTrpab = 0x00000014; +SDRAM[2].EmcTClkStable = 0x00000003; +SDRAM[2].EmcTClkStop = 0x00000003; +SDRAM[2].EmcTRefBw = 0x00000f04; +SDRAM[2].EmcFbioCfg5 = 0x1363a896; +SDRAM[2].EmcFbioCfg6 = 0x00000000; +SDRAM[2].EmcFbioSpare = 0x00000000; +SDRAM[2].EmcCfgRsv = 0xff00ff00; +SDRAM[2].EmcMrs = 0x00000000; +SDRAM[2].EmcEmrs = 0x00000000; +SDRAM[2].EmcEmrs2 = 0x00000000; +SDRAM[2].EmcEmrs3 = 0x00000000; +SDRAM[2].EmcMrw1 = 0x00010083; +SDRAM[2].EmcMrw2 = 0x0002001c; +SDRAM[2].EmcMrw3 = 0x00030001; +SDRAM[2].EmcMrw4 = 0x800b0000; +SDRAM[2].EmcMrwExtra = 0x00010083; +SDRAM[2].EmcWarmBootMrwExtra = 0x0002001c; +SDRAM[2].EmcWarmBootExtraModeRegWriteEnable = 0x00000000; +SDRAM[2].EmcExtraModeRegWriteEnable = 0x00000000; +SDRAM[2].EmcMrwResetCommand = 0x003f00fc; +SDRAM[2].EmcMrwResetNInitWait = 0x0000000a; +SDRAM[2].EmcMrsWaitCnt = 0x039c0019; +SDRAM[2].EmcMrsWaitCnt2 = 0x039c0019; +SDRAM[2].EmcCfg = 0xf3300000; +SDRAM[2].EmcCfg2 = 0x0000089f; +SDRAM[2].EmcCfgPipe = 0x00004080; +SDRAM[2].EmcDbg = 0x01000c00; +SDRAM[2].EmcCmdQ = 0x10004408; +SDRAM[2].EmcMc2EmcQ = 0x06000404; +SDRAM[2].EmcDynSelfRefControl = 0x80001c77; +SDRAM[2].AhbArbitrationXbarCtrlMemInitDone = 0x00000001; +SDRAM[2].EmcCfgDigDll = 0xe00400b9; +SDRAM[2].EmcCfgDigDllPeriod = 0x00008000; +SDRAM[2].EmcDevSelect = 0x00000000; +SDRAM[2].EmcSelDpdCtrl = 0x0004001c; +SDRAM[2].EmcDllXformDqs0 = 0x00004006; ##0x007f400a; +SDRAM[2].EmcDllXformDqs1 = 0x007f800c; ##0x007f400a; +SDRAM[2].EmcDllXformDqs2 = 0x007fc008; ##0x007f400a; +SDRAM[2].EmcDllXformDqs3 = 0x007f400c; ##0x007f400a; +SDRAM[2].EmcDllXformDqs4 = 0x007fc006; ##0x007f400a; +SDRAM[2].EmcDllXformDqs5 = 0x00000006; ##0x007f400a; +SDRAM[2].EmcDllXformDqs6 = 0x007f800a; ##0x007f400a; +SDRAM[2].EmcDllXformDqs7 = 0x007f800c; ##0x007f400a; +SDRAM[2].EmcDllXformDqs8 = 0x007f400a; +SDRAM[2].EmcDllXformDqs9 = 0x007f400a; +SDRAM[2].EmcDllXformDqs10 = 0x007f400a; +SDRAM[2].EmcDllXformDqs11 = 0x007f400a; +SDRAM[2].EmcDllXformDqs12 = 0x007f400a; +SDRAM[2].EmcDllXformDqs13 = 0x007f400a; +SDRAM[2].EmcDllXformDqs14 = 0x007f400a; +SDRAM[2].EmcDllXformDqs15 = 0x007f400a; +SDRAM[2].EmcDllXformQUse0 = 0x00000000; +SDRAM[2].EmcDllXformQUse1 = 0x00000000; +SDRAM[2].EmcDllXformQUse2 = 0x00000000; +SDRAM[2].EmcDllXformQUse3 = 0x00000000; +SDRAM[2].EmcDllXformQUse4 = 0x00000000; +SDRAM[2].EmcDllXformQUse5 = 0x00000000; +SDRAM[2].EmcDllXformQUse6 = 0x00000000; +SDRAM[2].EmcDllXformQUse7 = 0x00000000; +SDRAM[2].EmcDllXformAddr0 = 0x00018004; ##0x0001c000; +SDRAM[2].EmcDllXformAddr1 = 0x00018004; ##0x0001c000; +SDRAM[2].EmcDllXformAddr2 = 0x00000008; ##0x00000006; +SDRAM[2].EmcDllXformAddr3 = 0x00014004; ##0x0001c000; +SDRAM[2].EmcDllXformAddr4 = 0x0001c002; ##0x0001c000; +SDRAM[2].EmcDllXformAddr5 = 0x00000008; ##0x00000006; +SDRAM[2].EmcDllXformQUse8 = 0x00000000; +SDRAM[2].EmcDllXformQUse9 = 0x00000000; +SDRAM[2].EmcDllXformQUse10 = 0x00000000; +SDRAM[2].EmcDllXformQUse11 = 0x00000000; +SDRAM[2].EmcDllXformQUse12 = 0x00000000; +SDRAM[2].EmcDllXformQUse13 = 0x00000000; +SDRAM[2].EmcDllXformQUse14 = 0x00000000; +SDRAM[2].EmcDllXformQUse15 = 0x00000000; +SDRAM[2].EmcDliTrimTxDqs0 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs1 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs2 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs3 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs4 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs5 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs6 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs7 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs8 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs9 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs10 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs11 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs12 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs13 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs14 = 0x00000008; +SDRAM[2].EmcDliTrimTxDqs15 = 0x00000008; +SDRAM[2].EmcDllXformDq0 = 0x0000000a; +SDRAM[2].EmcDllXformDq1 = 0x0000000a; +SDRAM[2].EmcDllXformDq2 = 0x0000000a; +SDRAM[2].EmcDllXformDq3 = 0x0000000a; +SDRAM[2].EmcDllXformDq4 = 0x0000000a; +SDRAM[2].EmcDllXformDq5 = 0x0000000a; +SDRAM[2].EmcDllXformDq6 = 0x0000000a; +SDRAM[2].EmcDllXformDq7 = 0x0000000a; +SDRAM[2].WarmBootWait = 0x00000001; +SDRAM[2].EmcCttTermCtrl = 0x00000802; +SDRAM[2].EmcOdtWrite = 0x00000000; +SDRAM[2].EmcOdtRead = 0x00000000; +SDRAM[2].EmcZcalInterval = 0x00064000; +SDRAM[2].EmcZcalWaitCnt = 0x00000058; +SDRAM[2].EmcZcalMrwCmd = 0x000a0056; +SDRAM[2].EmcMrsResetDll = 0x00000000; +SDRAM[2].EmcZcalInitDev0 = 0x840a00ff; +SDRAM[2].EmcZcalInitDev1 = 0x440a00ff; +SDRAM[2].EmcZcalInitWait = 0x00000001; +SDRAM[2].EmcZcalWarmColdBootEnables = 0x00000003; +SDRAM[2].EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab; +SDRAM[2].EmcZqCalDdr3WarmBoot = 0x00000000; +SDRAM[2].EmcZcalWarmBootWait = 0x00000001; +SDRAM[2].EmcMrsWarmBootEnable = 0x00000001; +SDRAM[2].EmcMrsResetDllWait = 0x00000000; +SDRAM[2].EmcMrsExtra = 0x00000000; +SDRAM[2].EmcWarmBootMrsExtra = 0x00000000; +SDRAM[2].EmcEmrsDdr2DllEnable = 0x00000000; +SDRAM[2].EmcMrsDdr2DllReset = 0x00000000; +SDRAM[2].EmcEmrsDdr2OcdCalib = 0x00000000; +SDRAM[2].EmcDdr2Wait = 0x00000000; +SDRAM[2].EmcClkenOverride = 0x00000000; +SDRAM[2].McDisExtraSnapLevels = 0x00000000; +SDRAM[2].EmcExtraRefreshNum = 0x00000002; +SDRAM[2].EmcClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[2].McClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[2].EmcCfgDigDllPeriodWarmBoot = 0x00000003; +SDRAM[2].PmcVddpSel = 0x00000001; +SDRAM[2].PmcVddpSelWait = 0x00000002; +SDRAM[2].PmcDdrPwr = 0x00000003; +SDRAM[2].PmcDdrCfg = 0x00001000; +SDRAM[2].PmcIoDpd3Req = 0x4ffefef7; +SDRAM[2].PmcIoDpd3ReqWait = 0x00000000; +SDRAM[2].PmcRegShort = 0x0000330f; +SDRAM[2].PmcNoIoPower = 0x00000000; +SDRAM[2].PmcPorDpdCtrlWait = 0x00000001; +SDRAM[2].EmcXm2CmdPadCtrl = 0x00000220; +SDRAM[2].EmcXm2CmdPadCtrl2 = 0x770c0000; +SDRAM[2].EmcXm2CmdPadCtrl3 = 0x050c0000; +SDRAM[2].EmcXm2CmdPadCtrl4 = 0x00000000; +SDRAM[2].EmcXm2CmdPadCtrl5 = 0x00100100; +SDRAM[2].EmcXm2DqsPadCtrl = 0x770c1414; +SDRAM[2].EmcXm2DqsPadCtrl2 = 0x0120103d; +SDRAM[2].EmcXm2DqsPadCtrl3 = 0x65965920; +SDRAM[2].EmcXm2DqsPadCtrl4 = 0x00596596; +SDRAM[2].EmcXm2DqsPadCtrl5 = 0x00596596; +SDRAM[2].EmcXm2DqsPadCtrl6 = 0x65965900; +SDRAM[2].EmcXm2DqPadCtrl = 0x770c2990; +SDRAM[2].EmcXm2DqPadCtrl2 = 0x00000000; +SDRAM[2].EmcXm2DqPadCtrl3 = 0x00000000; +SDRAM[2].EmcXm2ClkPadCtrl = 0x77ffc004; +SDRAM[2].EmcXm2ClkPadCtrl2 = 0x00000000; +SDRAM[2].EmcXm2CompPadCtrl = 0x81f1f008; +SDRAM[2].EmcXm2VttGenPadCtrl = 0x07070000; +SDRAM[2].EmcXm2VttGenPadCtrl2 = 0x00000000; +SDRAM[2].EmcXm2VttGenPadCtrl3 = 0x015ddddd; +SDRAM[2].EmcAcpdControl = 0x00000000; +SDRAM[2].EmcSwizzleRank0ByteCfg = 0x00001032; +SDRAM[2].EmcSwizzleRank0Byte0 = 0x53067142; +SDRAM[2].EmcSwizzleRank0Byte1 = 0x73025146; +SDRAM[2].EmcSwizzleRank0Byte2 = 0x20136475; +SDRAM[2].EmcSwizzleRank0Byte3 = 0x46273150; +SDRAM[2].EmcSwizzleRank1ByteCfg = 0x00003210; +SDRAM[2].EmcSwizzleRank1Byte0 = 0x73451026; +SDRAM[2].EmcSwizzleRank1Byte1 = 0x73025146; +SDRAM[2].EmcSwizzleRank1Byte2 = 0x20641735; +SDRAM[2].EmcSwizzleRank1Byte3 = 0x42136075; +SDRAM[2].EmcDsrVttgenDrv = 0x0000003f; +SDRAM[2].EmcTxdsrvttgen = 0x00000000; +SDRAM[2].EmcBgbiasCtl0 = 0x00000000; +SDRAM[2].McEmemAdrCfg = 0x00000001; +SDRAM[2].McEmemAdrCfgDev0 = 0x00080304; +SDRAM[2].McEmemAdrCfgDev1 = 0x00080304; +SDRAM[2].McEmemAdrCfgBankMask0 = 0x00001248; +SDRAM[2].McEmemAdrCfgBankMask1 = 0x00002490; +SDRAM[2].McEmemAdrCfgBankMask2 = 0x00000920; +SDRAM[2].McEmemAdrCfgBankSwizzle3 = 0x00000001; +SDRAM[2].McEmemCfg = 0x00001000; +SDRAM[2].McEmemArbCfg = 0x0e00000d; +SDRAM[2].McEmemArbOutstandingReq = 0x80000040; +SDRAM[2].McEmemArbTimingRcd = 0x00000007; +SDRAM[2].McEmemArbTimingRp = 0x00000008; +SDRAM[2].McEmemArbTimingRc = 0x0000001b; +SDRAM[2].McEmemArbTimingRas = 0x00000012; +SDRAM[2].McEmemArbTimingFaw = 0x00000017; +SDRAM[2].McEmemArbTimingRrd = 0x00000004; +SDRAM[2].McEmemArbTimingRap2Pre = 0x00000004; +SDRAM[2].McEmemArbTimingWap2Pre = 0x0000000e; +SDRAM[2].McEmemArbTimingR2R = 0x00000004; +SDRAM[2].McEmemArbTimingW2W = 0x00000001; +SDRAM[2].McEmemArbTimingR2W = 0x00000009; +SDRAM[2].McEmemArbTimingW2R = 0x00000009; +SDRAM[2].McEmemArbDaTurns = 0x09090104; +SDRAM[2].McEmemArbDaCovers = 0x001e141b; +SDRAM[2].McEmemArbMisc0 = 0x71ae2a1c; +SDRAM[2].McEmemArbMisc1 = 0x70000f02; +SDRAM[2].McEmemArbRing1Throttle = 0x001f0000; +SDRAM[2].McEmemArbOverride = 0x10000000; +SDRAM[2].McEmemArbOverride1 = 0x00000000; +SDRAM[2].McEmemArbRsv = 0xff00ff00; +SDRAM[2].McClkenOverride = 0x00000000; +SDRAM[2].McStatControl = 0x00000000; +SDRAM[2].McDisplaySnapRing = 0x00000003; +SDRAM[2].McVideoProtectBom = 0xfff00000; +SDRAM[2].McVideoProtectBomAdrHi = 0x00000000; +SDRAM[2].McVideoProtectSizeMb = 0x00000000; +SDRAM[2].McVideoProtectVprOverride = 0xe4bac743; +SDRAM[2].McVideoProtectVprOverride1 = 0x00000013; +SDRAM[2].McVideoProtectGpuOverride0 = 0x00000000; +SDRAM[2].McVideoProtectGpuOverride1 = 0x00000000; +SDRAM[2].McSecCarveoutBom = 0xfff00000; +SDRAM[2].McSecCarveoutAdrHi = 0x00000000; +SDRAM[2].McSecCarveoutSizeMb = 0x00000000; +SDRAM[2].McVideoProtectWriteAccess = 0x00000000; +SDRAM[2].McSecCarveoutProtectWriteAccess = 0x00000000; +SDRAM[2].EmcCaTrainingEnable = 0x00000001; +SDRAM[2].EmcCaTrainingTimingCntl1 = 0x09257359; +SDRAM[2].EmcCaTrainingTimingCntl2 = 0x00000017; +SDRAM[2].SwizzleRankByteEncode = 0x00000008; +SDRAM[2].BootRomPatchControl = 0x00000000; +SDRAM[2].BootRomPatchData = 0x00000000; +SDRAM[2].McMtsCarveoutBom = 0x78000000; +SDRAM[2].McMtsCarveoutAdrHi = 0x00000001; +SDRAM[2].McMtsCarveoutSizeMb = 0x00000080; +SDRAM[2].McMtsCarveoutRegCtrl = 0x00000001; +#@ MC_MLL_MPCORER_PTSA_RATE {0x7001944c} = 0x00000017; +#@ MC_PTSA_GRANT_DECREMENT {0x70019960} = 0x000001bb; +#@ MC_LATENCY_ALLOWANCE_XUSB_0 {0x7001937c} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_XUSB_1 {0x70019380} = 0x006e0038; +#@ MC_LATENCY_ALLOWANCE_TSEC_0 {0x70019390} = 0x006e003c; +#@ MC_LATENCY_ALLOWANCE_SDMMCA_0 {0x700193b8} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAA_0 {0x700193bc} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_SDMMC_0 {0x700193c0} = 0x006e0090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAB_0 {0x700193c4} = 0x006e0041; +#@ MC_LATENCY_ALLOWANCE_PPCS_0 {0x70019344} = 0x00270049; +#@ MC_LATENCY_ALLOWANCE_PPCS_1 {0x70019348} = 0x006e0080; +#@ MC_LATENCY_ALLOWANCE_MPCORE_0 {0x70019320} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_MPCORELP_0 {0x70019324} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_HC_0 {0x70019310} = 0x00080016; +#@ MC_LATENCY_ALLOWANCE_HC_1 {0x70019314} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_AVPC_0 {0x700192e4} = 0x006e0004; +#@ MC_LATENCY_ALLOWANCE_GPU_0 {0x700193ac} = 0x006e0019; +#@ MC_LATENCY_ALLOWANCE_MSENC_0 {0x70019328} = 0x006e0018; +#@ MC_LATENCY_ALLOWANCE_HDA_0 {0x70019318} = 0x006e0024; +#@ MC_LATENCY_ALLOWANCE_VIC_0 {0x70019394} = 0x006e001b; +#@ MC_LATENCY_ALLOWANCE_VI2_0 {0x70019398} = 0x0000006e; +#@ MC_LATENCY_ALLOWANCE_ISP2_0 {0x70019370} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2_1 {0x70019374} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_ISP2B_0 {0x70019384} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2B_1 {0x70019388} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_0 {0x70019354} = 0x00d400ff; +#@ MC_LATENCY_ALLOWANCE_VDE_1 {0x70019358} = 0x00510029; +#@ MC_LATENCY_ALLOWANCE_VDE_2 {0x7001935c} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_VDE_3 {0x70019360} = 0x006e006e; +#@ MC_LATENCY_ALLOWANCE_SATA_0 {0x70019350} = 0x006e0065; +#@ MC_LATENCY_ALLOWANCE_AFI_0 {0x700192e0} = 0x006e001c; +# +# CFG Version 01 Spare (using Micron part) +# Do not edit. Generated by T132_emc_reg_toolV6.0.4 V6.0.4. Command: +# T132_emc_reg_toolV6.0.4 -i denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par -b A44_528MHz_emc_reg.txt 1.89394 +# -o A44_64_528_tool_emcregtoolv4.cfg -dram_board_cfg 3 -round_trip_dly_ps 589.6 +# Parameter file: denali_sil_lpddr3_edfa232a2ma_4GB_X64_933.par, tck = 1.89 ns (528.00 MHz) +# bkv file: A44_528MHz_emc_reg.txt +SDRAM[3].MemoryType = NvBootMemoryType_LpDdr2; +SDRAM[3].PllMInputDivider = 0x00000001; +SDRAM[3].PllMFeedbackDivider = 0x0000002c; +SDRAM[3].PllMStableTime = 0x0000012c; +SDRAM[3].PllMSetupControl = 0x00000000; +SDRAM[3].PllMSelectDiv2 = 0x00000000; +SDRAM[3].PllMPDLshiftPh45 = 0x00000001; +SDRAM[3].PllMPDLshiftPh90 = 0x00000001; +SDRAM[3].PllMPDLshiftPh135 = 0x00000001; +SDRAM[3].PllMKCP = 0x00000000; +SDRAM[3].PllMKVCO = 0x00000000; +SDRAM[3].EmcBctSpare0 = 0x00000000; +SDRAM[3].EmcBctSpare1 = 0x00000000; +SDRAM[3].EmcBctSpare2 = 0x00000000; +SDRAM[3].EmcBctSpare3 = 0x00000000; +SDRAM[3].EmcBctSpare4 = 0x00000000; +SDRAM[3].EmcBctSpare5 = 0x00000000; +SDRAM[3].EmcBctSpare6 = 0x00000000; +SDRAM[3].EmcBctSpare7 = 0x00000000; +SDRAM[3].EmcBctSpare8 = 0x00000000; +SDRAM[3].EmcBctSpare9 = 0x00000000; +SDRAM[3].EmcBctSpare10 = 0x00000000; +SDRAM[3].EmcBctSpare11 = 0x00000000; +SDRAM[3].EmcClockSource = 0x80000000; +SDRAM[3].EmcAutoCalInterval = 0x001fffff; +SDRAM[3].EmcAutoCalConfig = 0xa1430000; +SDRAM[3].EmcAutoCalConfig2 = 0x00000000; +SDRAM[3].EmcAutoCalConfig3 = 0x00000000; +SDRAM[3].EmcAutoCalWait = 0x00000190; +SDRAM[3].EmcAdrCfg = 0x00000001; +SDRAM[3].EmcPinProgramWait = 0x00000000; +SDRAM[3].EmcPinExtraWait = 0x00000000; +SDRAM[3].EmcTimingControlWait = 0x00000000; +SDRAM[3].EmcRc = 0x0000001f; +SDRAM[3].EmcRfc = 0x00000044; +SDRAM[3].EmcRfcSlr = 0x00000000; +SDRAM[3].EmcRas = 0x00000016; +SDRAM[3].EmcRp = 0x00000009; +SDRAM[3].EmcR2r = 0x00000000; +SDRAM[3].EmcW2w = 0x00000000; +SDRAM[3].EmcR2w = 0x0000000a; +SDRAM[3].EmcW2r = 0x00000009; +SDRAM[3].EmcR2p = 0x00000003; +SDRAM[3].EmcW2p = 0x0000000d; +SDRAM[3].EmcRdRcd = 0x00000009; +SDRAM[3].EmcWrRcd = 0x00000009; +SDRAM[3].EmcRrd = 0x00000005; +SDRAM[3].EmcRext = 0x00000004; +SDRAM[3].EmcWext = 0x00000000; +SDRAM[3].EmcWdv = 0x00000002; +SDRAM[3].EmcWdvMask = 0x00000002; +SDRAM[3].EmcQUse = 0x00000008; +SDRAM[3].EmcQuseWidth = 0x00000003; +SDRAM[3].EmcIbdly = 0x00000000; +SDRAM[3].EmcEInput = 0x00000003; +SDRAM[3].EmcEInputDuration = 0x0000000a; +SDRAM[3].EmcPutermExtra = 0x00050000; +SDRAM[3].EmcPutermWidth = 0x00000004; +SDRAM[3].EmcPutermAdj = 0x00000000; +SDRAM[3].EmcCdbCntl1 = 0x00000000; +SDRAM[3].EmcCdbCntl2 = 0x00000000; +SDRAM[3].EmcCdbCntl3 = 0x00000000; +SDRAM[3].EmcQRst = 0x00000002; +SDRAM[3].EmcQSafe = 0x00000011; +SDRAM[3].EmcRdv = 0x00000015; +SDRAM[3].EmcRdvMask = 0x00000017; +SDRAM[3].EmcQpop = 0x0000000d; +SDRAM[3].EmcCtt = 0x00000000; +SDRAM[3].EmcCttDuration = 0x00000004; +SDRAM[3].EmcRefresh = 0x000007cd; +SDRAM[3].EmcBurstRefreshNum = 0x00000000; +SDRAM[3].EmcPreRefreshReqCnt = 0x000001f3; +SDRAM[3].EmcPdEx2Wr = 0x00000003; +SDRAM[3].EmcPdEx2Rd = 0x00000003; +SDRAM[3].EmcPChg2Pden = 0x00000009; +SDRAM[3].EmcAct2Pden = 0x00000000; +SDRAM[3].EmcAr2Pden = 0x00000001; +SDRAM[3].EmcRw2Pden = 0x00000011; +SDRAM[3].EmcTxsr = 0x0000004a; +SDRAM[3].EmcTxsrDll = 0x0000004a; +SDRAM[3].EmcTcke = 0x00000004; +SDRAM[3].EmcTckesr = 0x00000008; +SDRAM[3].EmcTpd = 0x00000004; +SDRAM[3].EmcTfaw = 0x00000019; +SDRAM[3].EmcTrpab = 0x0000000c; +SDRAM[3].EmcTClkStable = 0x00000003; +SDRAM[3].EmcTClkStop = 0x00000003; +SDRAM[3].EmcTRefBw = 0x00000895; +SDRAM[3].EmcFbioCfg5 = 0x1363a096; +SDRAM[3].EmcFbioCfg6 = 0x00000000; +SDRAM[3].EmcFbioSpare = 0x00000000; +SDRAM[3].EmcCfgRsv = 0xff00ff00; +SDRAM[3].EmcMrs = 0x00000000; +SDRAM[3].EmcEmrs = 0x00000000; +SDRAM[3].EmcEmrs2 = 0x00000000; +SDRAM[3].EmcEmrs3 = 0x00000000; +SDRAM[3].EmcMrw1 = 0x000100c3; +SDRAM[3].EmcMrw2 = 0x00020006; +SDRAM[3].EmcMrw3 = 0x00030001; +SDRAM[3].EmcMrw4 = 0x800b0000; +SDRAM[3].EmcMrwExtra = 0x000100c3; +SDRAM[3].EmcWarmBootMrwExtra = 0x00020006; +SDRAM[3].EmcWarmBootExtraModeRegWriteEnable = 0x00000000; +SDRAM[3].EmcExtraModeRegWriteEnable = 0x00000000; +SDRAM[3].EmcMrwResetCommand = 0x003f00fc; +SDRAM[3].EmcMrwResetNInitWait = 0x0000000a; +SDRAM[3].EmcMrsWaitCnt = 0x02100013; +SDRAM[3].EmcMrsWaitCnt2 = 0x02100013; +SDRAM[3].EmcCfg = 0xf3300000; +SDRAM[3].EmcCfg2 = 0x0000089f; +SDRAM[3].EmcCfgPipe = 0x000042a0; +SDRAM[3].EmcDbg = 0x01000c00; +SDRAM[3].EmcCmdQ = 0x10004408; +SDRAM[3].EmcMc2EmcQ = 0x06000404; +SDRAM[3].EmcDynSelfRefControl = 0x800010b3; +SDRAM[3].AhbArbitrationXbarCtrlMemInitDone = 0x00000001; +SDRAM[3].EmcCfgDigDll = 0xe01200b9; +SDRAM[3].EmcCfgDigDllPeriod = 0x00008000; +SDRAM[3].EmcDevSelect = 0x00000000; +SDRAM[3].EmcSelDpdCtrl = 0x0004001c; +SDRAM[3].EmcDllXformDqs0 = 0x007f400a; +SDRAM[3].EmcDllXformDqs1 = 0x007f400a; +SDRAM[3].EmcDllXformDqs2 = 0x007f400a; +SDRAM[3].EmcDllXformDqs3 = 0x007f400a; +SDRAM[3].EmcDllXformDqs4 = 0x007f400a; +SDRAM[3].EmcDllXformDqs5 = 0x007f400a; +SDRAM[3].EmcDllXformDqs6 = 0x007f400a; +SDRAM[3].EmcDllXformDqs7 = 0x007f400a; +SDRAM[3].EmcDllXformDqs8 = 0x007f400a; +SDRAM[3].EmcDllXformDqs9 = 0x007f400a; +SDRAM[3].EmcDllXformDqs10 = 0x007f400a; +SDRAM[3].EmcDllXformDqs11 = 0x007f400a; +SDRAM[3].EmcDllXformDqs12 = 0x007f400a; +SDRAM[3].EmcDllXformDqs13 = 0x007f400a; +SDRAM[3].EmcDllXformDqs14 = 0x007f400a; +SDRAM[3].EmcDllXformDqs15 = 0x007f400a; +SDRAM[3].EmcDllXformQUse0 = 0x00000000; +SDRAM[3].EmcDllXformQUse1 = 0x00000000; +SDRAM[3].EmcDllXformQUse2 = 0x00000000; +SDRAM[3].EmcDllXformQUse3 = 0x00000000; +SDRAM[3].EmcDllXformQUse4 = 0x00000000; +SDRAM[3].EmcDllXformQUse5 = 0x00000000; +SDRAM[3].EmcDllXformQUse6 = 0x00000000; +SDRAM[3].EmcDllXformQUse7 = 0x00000000; +SDRAM[3].EmcDllXformAddr0 = 0x00024000; +SDRAM[3].EmcDllXformAddr1 = 0x00024000; +SDRAM[3].EmcDllXformAddr2 = 0x00000006; +SDRAM[3].EmcDllXformAddr3 = 0x00024000; +SDRAM[3].EmcDllXformAddr4 = 0x00024000; +SDRAM[3].EmcDllXformAddr5 = 0x00000006; +SDRAM[3].EmcDllXformQUse8 = 0x00000000; +SDRAM[3].EmcDllXformQUse9 = 0x00000000; +SDRAM[3].EmcDllXformQUse10 = 0x00000000; +SDRAM[3].EmcDllXformQUse11 = 0x00000000; +SDRAM[3].EmcDllXformQUse12 = 0x00000000; +SDRAM[3].EmcDllXformQUse13 = 0x00000000; +SDRAM[3].EmcDllXformQUse14 = 0x00000000; +SDRAM[3].EmcDllXformQUse15 = 0x00000000; +SDRAM[3].EmcDliTrimTxDqs0 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs1 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs2 = 0x00000008; +SDRAM[3].EmcDliTrimTxDqs3 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs4 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs5 = 0x00000008; +SDRAM[3].EmcDliTrimTxDqs6 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs7 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs8 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs9 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs10 = 0x00000008; +SDRAM[3].EmcDliTrimTxDqs11 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs12 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs13 = 0x00000008; +SDRAM[3].EmcDliTrimTxDqs14 = 0x0000000b; +SDRAM[3].EmcDliTrimTxDqs15 = 0x0000000b; +SDRAM[3].EmcDllXformDq0 = 0x0000000c; +SDRAM[3].EmcDllXformDq1 = 0x0000000c; +SDRAM[3].EmcDllXformDq2 = 0x0000000c; +SDRAM[3].EmcDllXformDq3 = 0x0000000c; +SDRAM[3].EmcDllXformDq4 = 0x0000000c; +SDRAM[3].EmcDllXformDq5 = 0x0000000c; +SDRAM[3].EmcDllXformDq6 = 0x0000000c; +SDRAM[3].EmcDllXformDq7 = 0x0000000c; +SDRAM[3].WarmBootWait = 0x00000001; +SDRAM[3].EmcCttTermCtrl = 0x00000802; +SDRAM[3].EmcOdtWrite = 0x00000000; +SDRAM[3].EmcOdtRead = 0x00000000; +SDRAM[3].EmcZcalInterval = 0x00064000; +SDRAM[3].EmcZcalWaitCnt = 0x00000034; +SDRAM[3].EmcZcalMrwCmd = 0x000a0056; +SDRAM[3].EmcMrsResetDll = 0x00000000; +SDRAM[3].EmcZcalInitDev0 = 0x840a00ff; +SDRAM[3].EmcZcalInitDev1 = 0x440a00ff; +SDRAM[3].EmcZcalInitWait = 0x00000001; +SDRAM[3].EmcZcalWarmColdBootEnables = 0x00000003; +SDRAM[3].EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab; +SDRAM[3].EmcZqCalDdr3WarmBoot = 0x00000000; +SDRAM[3].EmcZcalWarmBootWait = 0x00000001; +SDRAM[3].EmcMrsWarmBootEnable = 0x00000001; +SDRAM[3].EmcMrsResetDllWait = 0x00000000; +SDRAM[3].EmcMrsExtra = 0x00000000; +SDRAM[3].EmcWarmBootMrsExtra = 0x00000000; +SDRAM[3].EmcEmrsDdr2DllEnable = 0x00000000; +SDRAM[3].EmcMrsDdr2DllReset = 0x00000000; +SDRAM[3].EmcEmrsDdr2OcdCalib = 0x00000000; +SDRAM[3].EmcDdr2Wait = 0x00000000; +SDRAM[3].EmcClkenOverride = 0x00000000; +SDRAM[3].McDisExtraSnapLevels = 0x00000000; +SDRAM[3].EmcExtraRefreshNum = 0x00000002; +SDRAM[3].EmcClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[3].McClkenOverrideAllWarmBoot = 0x00000000; +SDRAM[3].EmcCfgDigDllPeriodWarmBoot = 0x00000003; +SDRAM[3].PmcVddpSel = 0x00000001; +SDRAM[3].PmcVddpSelWait = 0x00000002; +SDRAM[3].PmcDdrPwr = 0x00000003; +SDRAM[3].PmcDdrCfg = 0x00001000; +SDRAM[3].PmcIoDpd3Req = 0x4ffefef7; +SDRAM[3].PmcIoDpd3ReqWait = 0x00000000; +SDRAM[3].PmcRegShort = 0x0000330f; +SDRAM[3].PmcNoIoPower = 0x00000000; +SDRAM[3].PmcPorDpdCtrlWait = 0x00000001; +SDRAM[3].EmcXm2CmdPadCtrl = 0x00000220; +SDRAM[3].EmcXm2CmdPadCtrl2 = 0x770c0000; +SDRAM[3].EmcXm2CmdPadCtrl3 = 0x050c0000; +SDRAM[3].EmcXm2CmdPadCtrl4 = 0x00000000; +SDRAM[3].EmcXm2CmdPadCtrl5 = 0x00100100; +SDRAM[3].EmcXm2DqsPadCtrl = 0x770c1414; +SDRAM[3].EmcXm2DqsPadCtrl2 = 0x0123123d; +SDRAM[3].EmcXm2DqsPadCtrl3 = 0x51451420; +SDRAM[3].EmcXm2DqsPadCtrl4 = 0x00514514; +SDRAM[3].EmcXm2DqsPadCtrl5 = 0x00514514; +SDRAM[3].EmcXm2DqsPadCtrl6 = 0x51451400; +SDRAM[3].EmcXm2DqPadCtrl = 0x770c2990; +SDRAM[3].EmcXm2DqPadCtrl2 = 0x00000000; +SDRAM[3].EmcXm2DqPadCtrl3 = 0x00000000; +SDRAM[3].EmcXm2ClkPadCtrl = 0x77ffc004; +SDRAM[3].EmcXm2ClkPadCtrl2 = 0x00000000; +SDRAM[3].EmcXm2CompPadCtrl = 0x81f1f008; +SDRAM[3].EmcXm2VttGenPadCtrl = 0x07070000; +SDRAM[3].EmcXm2VttGenPadCtrl2 = 0x0000003f; +SDRAM[3].EmcXm2VttGenPadCtrl3 = 0x015ddddd; +SDRAM[3].EmcAcpdControl = 0x00000000; +SDRAM[3].EmcSwizzleRank0ByteCfg = 0x00001032; +SDRAM[3].EmcSwizzleRank0Byte0 = 0x53067142; +SDRAM[3].EmcSwizzleRank0Byte1 = 0x73025146; +SDRAM[3].EmcSwizzleRank0Byte2 = 0x20136475; +SDRAM[3].EmcSwizzleRank0Byte3 = 0x46273150; +SDRAM[3].EmcSwizzleRank1ByteCfg = 0x00003210; +SDRAM[3].EmcSwizzleRank1Byte0 = 0x73451026; +SDRAM[3].EmcSwizzleRank1Byte1 = 0x73025146; +SDRAM[3].EmcSwizzleRank1Byte2 = 0x20641735; +SDRAM[3].EmcSwizzleRank1Byte3 = 0x42136075; +SDRAM[3].EmcDsrVttgenDrv = 0x0000003f; +SDRAM[3].EmcTxdsrvttgen = 0x00000000; +SDRAM[3].EmcBgbiasCtl0 = 0x00000000; +SDRAM[3].McEmemAdrCfg = 0x00000001; +SDRAM[3].McEmemAdrCfgDev0 = 0x00080304; +SDRAM[3].McEmemAdrCfgDev1 = 0x00080304; +SDRAM[3].McEmemAdrCfgBankMask0 = 0x00001248; +SDRAM[3].McEmemAdrCfgBankMask1 = 0x00002490; +SDRAM[3].McEmemAdrCfgBankMask2 = 0x00000920; +SDRAM[3].McEmemAdrCfgBankSwizzle3 = 0x00000001; +SDRAM[3].McEmemCfg = 0x00001000; +SDRAM[3].McEmemArbCfg = 0x0f000007; +SDRAM[3].McEmemArbOutstandingReq = 0x80000040; +SDRAM[3].McEmemArbTimingRcd = 0x00000003; +SDRAM[3].McEmemArbTimingRp = 0x00000004; +SDRAM[3].McEmemArbTimingRc = 0x00000010; +SDRAM[3].McEmemArbTimingRas = 0x0000000a; +SDRAM[3].McEmemArbTimingFaw = 0x0000000d; +SDRAM[3].McEmemArbTimingRrd = 0x00000002; +SDRAM[3].McEmemArbTimingRap2Pre = 0x00000002; +SDRAM[3].McEmemArbTimingWap2Pre = 0x00000009; +SDRAM[3].McEmemArbTimingR2R = 0x00000003; +SDRAM[3].McEmemArbTimingW2W = 0x00000001; +SDRAM[3].McEmemArbTimingR2W = 0x00000006; +SDRAM[3].McEmemArbTimingW2R = 0x00000006; +SDRAM[3].McEmemArbDaTurns = 0x06060103; +SDRAM[3].McEmemArbDaCovers = 0x00120b10; +SDRAM[3].McEmemArbMisc0 = 0x71c81811; +SDRAM[3].McEmemArbMisc1 = 0x70000f03; +SDRAM[3].McEmemArbRing1Throttle = 0x001f0000; +SDRAM[3].McEmemArbOverride = 0x10000000; +SDRAM[3].McEmemArbOverride1 = 0x00000000; +SDRAM[3].McEmemArbRsv = 0xff00ff00; +SDRAM[3].McClkenOverride = 0x00000000; +SDRAM[3].McStatControl = 0x00000000; +SDRAM[3].McDisplaySnapRing = 0x00000003; +SDRAM[3].McVideoProtectBom = 0xfff00000; +SDRAM[3].McVideoProtectBomAdrHi = 0x00000000; +SDRAM[3].McVideoProtectSizeMb = 0x00000000; +SDRAM[3].McVideoProtectVprOverride = 0xe4bac743; +SDRAM[3].McVideoProtectVprOverride1 = 0x00000013; +SDRAM[3].McVideoProtectGpuOverride0 = 0x00000000; +SDRAM[3].McVideoProtectGpuOverride1 = 0x00000000; +SDRAM[3].McSecCarveoutBom = 0xfff00000; +SDRAM[3].McSecCarveoutAdrHi = 0x00000000; +SDRAM[3].McSecCarveoutSizeMb = 0x00000000; +SDRAM[3].McVideoProtectWriteAccess = 0x00000000; +SDRAM[3].McSecCarveoutProtectWriteAccess = 0x00000000; +SDRAM[3].EmcCaTrainingEnable = 0x00000001; +SDRAM[3].EmcCaTrainingTimingCntl1 = 0x09257359; +SDRAM[3].EmcCaTrainingTimingCntl2 = 0x00000017; +SDRAM[3].SwizzleRankByteEncode = 0x00000008; +SDRAM[3].BootRomPatchControl = 0x00000000; +SDRAM[3].BootRomPatchData = 0x00000000; +SDRAM[3].McMtsCarveoutBom = 0x78000000; +SDRAM[3].McMtsCarveoutAdrHi = 0x00000001; +SDRAM[3].McMtsCarveoutSizeMb = 0x00000080; +SDRAM[3].McMtsCarveoutRegCtrl = 0x00000001; +#@ MC_MLL_MPCORER_PTSA_RATE {0x7001944c} = 0x0000000d; +#@ MC_PTSA_GRANT_DECREMENT {0x70019960} = 0x000000fd; +#@ MC_LATENCY_ALLOWANCE_XUSB_0 {0x7001937c} = 0x00c10038; +#@ MC_LATENCY_ALLOWANCE_XUSB_1 {0x70019380} = 0x00c10038; +#@ MC_LATENCY_ALLOWANCE_TSEC_0 {0x70019390} = 0x00c1003c; +#@ MC_LATENCY_ALLOWANCE_SDMMCA_0 {0x700193b8} = 0x00c10090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAA_0 {0x700193bc} = 0x00c10041; +#@ MC_LATENCY_ALLOWANCE_SDMMC_0 {0x700193c0} = 0x00c10090; +#@ MC_LATENCY_ALLOWANCE_SDMMCAB_0 {0x700193c4} = 0x00c10041; +#@ MC_LATENCY_ALLOWANCE_PPCS_0 {0x70019344} = 0x00270049; +#@ MC_LATENCY_ALLOWANCE_PPCS_1 {0x70019348} = 0x00c10080; +#@ MC_LATENCY_ALLOWANCE_MPCORE_0 {0x70019320} = 0x00c10004; +#@ MC_LATENCY_ALLOWANCE_MPCORELP_0 {0x70019324} = 0x00c10004; +#@ MC_LATENCY_ALLOWANCE_HC_0 {0x70019310} = 0x00080021; +#@ MC_LATENCY_ALLOWANCE_HC_1 {0x70019314} = 0x000000c1; +#@ MC_LATENCY_ALLOWANCE_AVPC_0 {0x700192e4} = 0x00c10004; +#@ MC_LATENCY_ALLOWANCE_GPU_0 {0x700193ac} = 0x00c10026; +#@ MC_LATENCY_ALLOWANCE_MSENC_0 {0x70019328} = 0x00c1001a; +#@ MC_LATENCY_ALLOWANCE_HDA_0 {0x70019318} = 0x00c10024; +#@ MC_LATENCY_ALLOWANCE_VIC_0 {0x70019394} = 0x00c10029; +#@ MC_LATENCY_ALLOWANCE_VI2_0 {0x70019398} = 0x000000c1; +#@ MC_LATENCY_ALLOWANCE_ISP2_0 {0x70019370} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2_1 {0x70019374} = 0x00c100c1; +#@ MC_LATENCY_ALLOWANCE_ISP2B_0 {0x70019384} = 0x00000036; +#@ MC_LATENCY_ALLOWANCE_ISP2B_1 {0x70019388} = 0x00c100c1; +#@ MC_LATENCY_ALLOWANCE_VDE_0 {0x70019354} = 0x00d400ff; +#@ MC_LATENCY_ALLOWANCE_VDE_1 {0x70019358} = 0x00510029; +#@ MC_LATENCY_ALLOWANCE_VDE_2 {0x7001935c} = 0x00c100c1; +#@ MC_LATENCY_ALLOWANCE_VDE_3 {0x70019360} = 0x00c100c1; +#@ MC_LATENCY_ALLOWANCE_SATA_0 {0x70019350} = 0x00c10065; +#@ MC_LATENCY_ALLOWANCE_AFI_0 {0x700192e0} = 0x00c1002a; diff --git a/src/mainboard/google/rush_ryu/bct/sdram-hynix-4GB-924.inc b/src/mainboard/google/rush_ryu/bct/sdram-hynix-4GB-924.inc new file mode 100644 index 0000000000..bf40ef5b03 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/sdram-hynix-4GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-hynix-4GB-924.cfg; do not edit. This is Hynix LPDDR3 */ + .MemoryType = NvBootMemoryType_LpDdr2, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000000, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000037, + .EmcRfc = 0x00000078, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000026, + .EmcRp = 0x00000010, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000010, + .EmcW2r = 0x00000010, + .EmcR2p = 0x00000006, + .EmcW2p = 0x00000017, + .EmcRdRcd = 0x00000010, + .EmcWrRcd = 0x00000010, + .EmcRrd = 0x00000009, + .EmcRext = 0x00000005, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000007, + .EmcWdvMask = 0x00000007, + .EmcQUse = 0x00000011, + .EmcQuseWidth = 0x00000004, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000006, + .EmcEInputDuration = 0x00000011, + .EmcPutermExtra = 0x000e0000, + .EmcPutermWidth = 0x00000006, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000005, + .EmcQSafe = 0x00000018, + .EmcRdv = 0x00000020, + .EmcRdvMask = 0x00000022, + .EmcQpop = 0x00000017, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000006, + .EmcRefresh = 0x00000dd4, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000375, + .EmcPdEx2Wr = 0x00000006, + .EmcPdEx2Rd = 0x00000006, + .EmcPChg2Pden = 0x00000010, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000001, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x00000082, + .EmcTxsrDll = 0x00000082, + .EmcTcke = 0x00000007, + .EmcTckesr = 0x0000000e, + .EmcTpd = 0x00000007, + .EmcTfaw = 0x0000002d, + .EmcTrpab = 0x00000014, + .EmcTClkStable = 0x00000003, + .EmcTClkStop = 0x00000003, + .EmcTRefBw = 0x00000f04, + .EmcFbioCfg5 = 0x1363a896, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000000, + .EmcEmrs = 0x00000000, + .EmcEmrs2 = 0x00000000, + .EmcEmrs3 = 0x00000000, + .EmcMrw1 = 0x00010083, + .EmcMrw2 = 0x0002001c, + .EmcMrw3 = 0x00030001, + .EmcMrw4 = 0x800b0000, + .EmcMrwExtra = 0x00010083, + .EmcWarmBootMrwExtra = 0x0002001c, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x003f00fc, + .EmcMrwResetNInitWait = 0x0000000a, + .EmcMrsWaitCnt = 0x039c0019, + .EmcMrsWaitCnt2 = 0x039c0019, + .EmcCfg = 0xd3300000, + .EmcCfg2 = 0x0000089f, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80001c77, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00400b9, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x0004001c, + .EmcDllXformDqs0 = 0x0000000a, + .EmcDllXformDqs1 = 0x0000000a, + .EmcDllXformDqs2 = 0x0000000c, + .EmcDllXformDqs3 = 0x0000000a, + .EmcDllXformDqs4 = 0x00000008, + .EmcDllXformDqs5 = 0x00004008, + .EmcDllXformDqs6 = 0x0000000a, + .EmcDllXformDqs7 = 0x00000008, + .EmcDllXformDqs8 = 0x0000000a, + .EmcDllXformDqs9 = 0x0000000a, + .EmcDllXformDqs10 = 0x0000000a, + .EmcDllXformDqs11 = 0x0000000a, + .EmcDllXformDqs12 = 0x0000000a, + .EmcDllXformDqs13 = 0x0000000a, + .EmcDllXformDqs14 = 0x0000000a, + .EmcDllXformDqs15 = 0x0000000a, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00024002, + .EmcDllXformAddr1 = 0x00024002, + .EmcDllXformAddr2 = 0x00000008, + .EmcDllXformAddr3 = 0x00024002, + .EmcDllXformAddr4 = 0x00024002, + .EmcDllXformAddr5 = 0x00000008, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000008, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x00000008, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x00000008, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000008, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x00000008, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x00000008, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000e, + .EmcDllXformDq1 = 0x0000000e, + .EmcDllXformDq2 = 0x0000000e, + .EmcDllXformDq3 = 0x0000000e, + .EmcDllXformDq4 = 0x0000000e, + .EmcDllXformDq5 = 0x0000000e, + .EmcDllXformDq6 = 0x0000000e, + .EmcDllXformDq7 = 0x0000000e, + .WarmBootWait = 0x00000001, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00064000, + .EmcZcalWaitCnt = 0x00000058, + .EmcZcalMrwCmd = 0x000a0056, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x840a00ff, + .EmcZcalInitDev1 = 0x440a00ff, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000000, + .EmcWarmBootMrsExtra = 0x00000000, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000001, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00001000, + .PmcIoDpd3Req = 0x4ffefef7, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x0000330f, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000001, + .EmcXm2CmdPadCtrl = 0x00000220, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00100100, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120103d, + .EmcXm2DqsPadCtrl3 = 0x55555520, + .EmcXm2DqsPadCtrl4 = 0x00492492, + .EmcXm2DqsPadCtrl5 = 0x00492492, + .EmcXm2DqsPadCtrl6 = 0x55555500, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc004, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f008, + .EmcXm2VttGenPadCtrl = 0x07070000, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x015ddddd, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00001032, + .EmcSwizzleRank0Byte0 = 0x53067142, + .EmcSwizzleRank0Byte1 = 0x73025146, + .EmcSwizzleRank0Byte2 = 0x20136475, + .EmcSwizzleRank0Byte3 = 0x46273150, + .EmcSwizzleRank1ByteCfg = 0x00003210, + .EmcSwizzleRank1Byte0 = 0x73451026, + .EmcSwizzleRank1Byte1 = 0x73025146, + .EmcSwizzleRank1Byte2 = 0x20641735, + .EmcSwizzleRank1Byte3 = 0x42136075, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080304, + .McEmemAdrCfgDev1 = 0x00080304, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000007, + .McEmemArbTimingRp = 0x00000008, + .McEmemArbTimingRc = 0x0000001b, + .McEmemArbTimingRas = 0x00000012, + .McEmemArbTimingFaw = 0x00000017, + .McEmemArbTimingRrd = 0x00000004, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000004, + .McEmemArbTimingW2W = 0x00000001, + .McEmemArbTimingR2W = 0x00000009, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09090104, + .McEmemArbDaCovers = 0x001e141b, + .McEmemArbMisc0 = 0x71ae2a1c, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000001, + .EmcCaTrainingTimingCntl1 = 0x09257359, + .EmcCaTrainingTimingCntl2 = 0x00000017, + .SwizzleRankByteEncode = 0x00000008, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-528.inc b/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-528.inc new file mode 100644 index 0000000000..52180ccff6 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-528.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-micron-4GB-528.cfg; do not edit. */ + .MemoryType = NvBootMemoryType_LpDdr2, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000002c, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000000, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x0000001f, + .EmcRfc = 0x00000044, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000016, + .EmcRp = 0x00000009, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x0000000a, + .EmcW2r = 0x00000009, + .EmcR2p = 0x00000003, + .EmcW2p = 0x0000000d, + .EmcRdRcd = 0x00000009, + .EmcWrRcd = 0x00000009, + .EmcRrd = 0x00000005, + .EmcRext = 0x00000004, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000002, + .EmcWdvMask = 0x00000002, + .EmcQUse = 0x00000008, + .EmcQuseWidth = 0x00000003, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000003, + .EmcEInputDuration = 0x0000000a, + .EmcPutermExtra = 0x00050000, + .EmcPutermWidth = 0x00000004, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000002, + .EmcQSafe = 0x00000011, + .EmcRdv = 0x00000015, + .EmcRdvMask = 0x00000017, + .EmcQpop = 0x0000000d, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000004, + .EmcRefresh = 0x000007cd, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x000001f3, + .EmcPdEx2Wr = 0x00000003, + .EmcPdEx2Rd = 0x00000003, + .EmcPChg2Pden = 0x00000009, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000001, + .EmcRw2Pden = 0x00000011, + .EmcTxsr = 0x0000004a, + .EmcTxsrDll = 0x0000004a, + .EmcTcke = 0x00000004, + .EmcTckesr = 0x00000008, + .EmcTpd = 0x00000004, + .EmcTfaw = 0x00000019, + .EmcTrpab = 0x0000000c, + .EmcTClkStable = 0x00000003, + .EmcTClkStop = 0x00000003, + .EmcTRefBw = 0x00000895, + .EmcFbioCfg5 = 0x1363a096, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000000, + .EmcEmrs = 0x00000000, + .EmcEmrs2 = 0x00000000, + .EmcEmrs3 = 0x00000000, + .EmcMrw1 = 0x000100c3, + .EmcMrw2 = 0x00020006, + .EmcMrw3 = 0x00030001, + .EmcMrw4 = 0x800b0000, + .EmcMrwExtra = 0x000100c3, + .EmcWarmBootMrwExtra = 0x00020006, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x003f00fc, + .EmcMrwResetNInitWait = 0x0000000a, + .EmcMrsWaitCnt = 0x02100013, + .EmcMrsWaitCnt2 = 0x02100013, + .EmcCfg = 0xf3300000, + .EmcCfg2 = 0x0000089f, + .EmcCfgPipe = 0x000042a0, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x800010b3, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe01200b9, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x0004001c, + .EmcDllXformDqs0 = 0x007f400a, + .EmcDllXformDqs1 = 0x007f400a, + .EmcDllXformDqs2 = 0x007f400a, + .EmcDllXformDqs3 = 0x007f400a, + .EmcDllXformDqs4 = 0x007f400a, + .EmcDllXformDqs5 = 0x007f400a, + .EmcDllXformDqs6 = 0x007f400a, + .EmcDllXformDqs7 = 0x007f400a, + .EmcDllXformDqs8 = 0x007f400a, + .EmcDllXformDqs9 = 0x007f400a, + .EmcDllXformDqs10 = 0x007f400a, + .EmcDllXformDqs11 = 0x007f400a, + .EmcDllXformDqs12 = 0x007f400a, + .EmcDllXformDqs13 = 0x007f400a, + .EmcDllXformDqs14 = 0x007f400a, + .EmcDllXformDqs15 = 0x007f400a, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00024000, + .EmcDllXformAddr1 = 0x00024000, + .EmcDllXformAddr2 = 0x00000006, + .EmcDllXformAddr3 = 0x00024000, + .EmcDllXformAddr4 = 0x00024000, + .EmcDllXformAddr5 = 0x00000006, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x0000000b, + .EmcDliTrimTxDqs1 = 0x0000000b, + .EmcDliTrimTxDqs2 = 0x00000008, + .EmcDliTrimTxDqs3 = 0x0000000b, + .EmcDliTrimTxDqs4 = 0x0000000b, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x0000000b, + .EmcDliTrimTxDqs7 = 0x0000000b, + .EmcDliTrimTxDqs8 = 0x0000000b, + .EmcDliTrimTxDqs9 = 0x0000000b, + .EmcDliTrimTxDqs10 = 0x00000008, + .EmcDliTrimTxDqs11 = 0x0000000b, + .EmcDliTrimTxDqs12 = 0x0000000b, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x0000000b, + .EmcDliTrimTxDqs15 = 0x0000000b, + .EmcDllXformDq0 = 0x0000000c, + .EmcDllXformDq1 = 0x0000000c, + .EmcDllXformDq2 = 0x0000000c, + .EmcDllXformDq3 = 0x0000000c, + .EmcDllXformDq4 = 0x0000000c, + .EmcDllXformDq5 = 0x0000000c, + .EmcDllXformDq6 = 0x0000000c, + .EmcDllXformDq7 = 0x0000000c, + .WarmBootWait = 0x00000001, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00064000, + .EmcZcalWaitCnt = 0x00000034, + .EmcZcalMrwCmd = 0x000a0056, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x840a00ff, + .EmcZcalInitDev1 = 0x440a00ff, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000000, + .EmcWarmBootMrsExtra = 0x00000000, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000001, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00001000, + .PmcIoDpd3Req = 0x4ffefef7, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x0000330f, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000001, + .EmcXm2CmdPadCtrl = 0x00000220, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00100100, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0123123d, + .EmcXm2DqsPadCtrl3 = 0x51451420, + .EmcXm2DqsPadCtrl4 = 0x00514514, + .EmcXm2DqsPadCtrl5 = 0x00514514, + .EmcXm2DqsPadCtrl6 = 0x51451400, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc004, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f008, + .EmcXm2VttGenPadCtrl = 0x07070000, + .EmcXm2VttGenPadCtrl2 = 0x0000003f, + .EmcXm2VttGenPadCtrl3 = 0x015ddddd, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00001032, + .EmcSwizzleRank0Byte0 = 0x53067142, + .EmcSwizzleRank0Byte1 = 0x73025146, + .EmcSwizzleRank0Byte2 = 0x20136475, + .EmcSwizzleRank0Byte3 = 0x46273150, + .EmcSwizzleRank1ByteCfg = 0x00003210, + .EmcSwizzleRank1Byte0 = 0x73451026, + .EmcSwizzleRank1Byte1 = 0x73025146, + .EmcSwizzleRank1Byte2 = 0x20641735, + .EmcSwizzleRank1Byte3 = 0x42136075, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080304, + .McEmemAdrCfgDev1 = 0x00080304, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0f000007, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000003, + .McEmemArbTimingRp = 0x00000004, + .McEmemArbTimingRc = 0x00000010, + .McEmemArbTimingRas = 0x0000000a, + .McEmemArbTimingFaw = 0x0000000d, + .McEmemArbTimingRrd = 0x00000002, + .McEmemArbTimingRap2Pre = 0x00000002, + .McEmemArbTimingWap2Pre = 0x00000009, + .McEmemArbTimingR2R = 0x00000003, + .McEmemArbTimingW2W = 0x00000001, + .McEmemArbTimingR2W = 0x00000006, + .McEmemArbTimingW2R = 0x00000006, + .McEmemArbDaTurns = 0x06060103, + .McEmemArbDaCovers = 0x00120b10, + .McEmemArbMisc0 = 0x71c81811, + .McEmemArbMisc1 = 0x70000f03, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000001, + .EmcCaTrainingTimingCntl1 = 0x09257359, + .EmcCaTrainingTimingCntl2 = 0x00000017, + .SwizzleRankByteEncode = 0x00000008, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-924.inc b/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-924.inc new file mode 100644 index 0000000000..5f2594b927 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/sdram-micron-4GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-micron-4GB-924.cfg; do not edit. This is Micron LPDDR3 */ + .MemoryType = NvBootMemoryType_LpDdr2, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000000, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000037, + .EmcRfc = 0x00000078, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000026, + .EmcRp = 0x00000010, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000010, + .EmcW2r = 0x00000010, + .EmcR2p = 0x00000006, + .EmcW2p = 0x00000017, + .EmcRdRcd = 0x00000010, + .EmcWrRcd = 0x00000010, + .EmcRrd = 0x00000009, + .EmcRext = 0x00000005, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000007, + .EmcWdvMask = 0x00000007, + .EmcQUse = 0x00000011, + .EmcQuseWidth = 0x00000004, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000006, + .EmcEInputDuration = 0x00000011, + .EmcPutermExtra = 0x000e0000, + .EmcPutermWidth = 0x00000006, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000005, + .EmcQSafe = 0x00000018, + .EmcRdv = 0x00000020, + .EmcRdvMask = 0x00000022, + .EmcQpop = 0x00000017, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000006, + .EmcRefresh = 0x00000dd4, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000375, + .EmcPdEx2Wr = 0x00000006, + .EmcPdEx2Rd = 0x00000006, + .EmcPChg2Pden = 0x00000010, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000001, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x00000082, + .EmcTxsrDll = 0x00000082, + .EmcTcke = 0x00000007, + .EmcTckesr = 0x0000000e, + .EmcTpd = 0x00000007, + .EmcTfaw = 0x0000002d, + .EmcTrpab = 0x00000014, + .EmcTClkStable = 0x00000003, + .EmcTClkStop = 0x00000003, + .EmcTRefBw = 0x00000f04, + .EmcFbioCfg5 = 0x1363a896, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000000, + .EmcEmrs = 0x00000000, + .EmcEmrs2 = 0x00000000, + .EmcEmrs3 = 0x00000000, + .EmcMrw1 = 0x00010083, + .EmcMrw2 = 0x0002001c, + .EmcMrw3 = 0x00030001, + .EmcMrw4 = 0x800b0000, + .EmcMrwExtra = 0x00010083, + .EmcWarmBootMrwExtra = 0x0002001c, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x003f00fc, + .EmcMrwResetNInitWait = 0x0000000a, + .EmcMrsWaitCnt = 0x039c0019, + .EmcMrsWaitCnt2 = 0x039c0019, + .EmcCfg = 0xf3300000, + .EmcCfg2 = 0x0000089f, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80001c77, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00400b9, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x0004001c, + .EmcDllXformDqs0 = 0x00004006, + .EmcDllXformDqs1 = 0x007f800c, + .EmcDllXformDqs2 = 0x007fc008, + .EmcDllXformDqs3 = 0x007f400c, + .EmcDllXformDqs4 = 0x007fc006, + .EmcDllXformDqs5 = 0x00000006, + .EmcDllXformDqs6 = 0x007f800a, + .EmcDllXformDqs7 = 0x007f800c, + .EmcDllXformDqs8 = 0x007f400a, + .EmcDllXformDqs9 = 0x007f400a, + .EmcDllXformDqs10 = 0x007f400a, + .EmcDllXformDqs11 = 0x007f400a, + .EmcDllXformDqs12 = 0x007f400a, + .EmcDllXformDqs13 = 0x007f400a, + .EmcDllXformDqs14 = 0x007f400a, + .EmcDllXformDqs15 = 0x007f400a, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00018004, + .EmcDllXformAddr1 = 0x00018004, + .EmcDllXformAddr2 = 0x00000008, + .EmcDllXformAddr3 = 0x00014004, + .EmcDllXformAddr4 = 0x0001c002, + .EmcDllXformAddr5 = 0x00000008, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000008, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x00000008, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x00000008, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000008, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x00000008, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x00000008, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000a, + .EmcDllXformDq1 = 0x0000000a, + .EmcDllXformDq2 = 0x0000000a, + .EmcDllXformDq3 = 0x0000000a, + .EmcDllXformDq4 = 0x0000000a, + .EmcDllXformDq5 = 0x0000000a, + .EmcDllXformDq6 = 0x0000000a, + .EmcDllXformDq7 = 0x0000000a, + .WarmBootWait = 0x00000001, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00064000, + .EmcZcalWaitCnt = 0x00000058, + .EmcZcalMrwCmd = 0x000a0056, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x840a00ff, + .EmcZcalInitDev1 = 0x440a00ff, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000000, + .EmcWarmBootMrsExtra = 0x00000000, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000001, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00001000, + .PmcIoDpd3Req = 0x4ffefef7, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x0000330f, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000001, + .EmcXm2CmdPadCtrl = 0x00000220, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00100100, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120103d, + .EmcXm2DqsPadCtrl3 = 0x65965920, + .EmcXm2DqsPadCtrl4 = 0x00596596, + .EmcXm2DqsPadCtrl5 = 0x00596596, + .EmcXm2DqsPadCtrl6 = 0x65965900, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc004, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f008, + .EmcXm2VttGenPadCtrl = 0x07070000, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x015ddddd, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00001032, + .EmcSwizzleRank0Byte0 = 0x53067142, + .EmcSwizzleRank0Byte1 = 0x73025146, + .EmcSwizzleRank0Byte2 = 0x20136475, + .EmcSwizzleRank0Byte3 = 0x46273150, + .EmcSwizzleRank1ByteCfg = 0x00003210, + .EmcSwizzleRank1Byte0 = 0x73451026, + .EmcSwizzleRank1Byte1 = 0x73025146, + .EmcSwizzleRank1Byte2 = 0x20641735, + .EmcSwizzleRank1Byte3 = 0x42136075, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080304, + .McEmemAdrCfgDev1 = 0x00080304, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000007, + .McEmemArbTimingRp = 0x00000008, + .McEmemArbTimingRc = 0x0000001b, + .McEmemArbTimingRas = 0x00000012, + .McEmemArbTimingFaw = 0x00000017, + .McEmemArbTimingRrd = 0x00000004, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000004, + .McEmemArbTimingW2W = 0x00000001, + .McEmemArbTimingR2W = 0x00000009, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09090104, + .McEmemArbDaCovers = 0x001e141b, + .McEmemArbMisc0 = 0x71ae2a1c, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000001, + .EmcCaTrainingTimingCntl1 = 0x09257359, + .EmcCaTrainingTimingCntl2 = 0x00000017, + .SwizzleRankByteEncode = 0x00000008, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush_ryu/bct/sdram-samsung-4GB-924.inc b/src/mainboard/google/rush_ryu/bct/sdram-samsung-4GB-924.inc new file mode 100644 index 0000000000..8f19db26a9 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/sdram-samsung-4GB-924.inc @@ -0,0 +1,311 @@ +{ /* generated from sdram-4GB-924.cfg; do not edit. This is SAMSUNG LPDDR3 */ + .MemoryType = NvBootMemoryType_LpDdr2, + .PllMInputDivider = 0x00000001, + .PllMFeedbackDivider = 0x0000004d, + .PllMStableTime = 0x0000012c, + .PllMSetupControl = 0x00000000, + .PllMSelectDiv2 = 0x00000000, + .PllMPDLshiftPh45 = 0x00000001, + .PllMPDLshiftPh90 = 0x00000001, + .PllMPDLshiftPh135 = 0x00000001, + .PllMKCP = 0x00000000, + .PllMKVCO = 0x00000000, + .EmcBctSpare0 = 0x00000000, + .EmcBctSpare1 = 0x00000000, + .EmcBctSpare2 = 0x00000000, + .EmcBctSpare3 = 0x00000000, + .EmcBctSpare4 = 0x00000000, + .EmcBctSpare5 = 0x00000000, + .EmcBctSpare6 = 0x00000000, + .EmcBctSpare7 = 0x00000000, + .EmcBctSpare8 = 0x00000000, + .EmcBctSpare9 = 0x00000000, + .EmcBctSpare10 = 0x00000000, + .EmcBctSpare11 = 0x00000000, + .EmcClockSource = 0x80000000, + .EmcAutoCalInterval = 0x001fffff, + .EmcAutoCalConfig = 0xa1430000, + .EmcAutoCalConfig2 = 0x00000000, + .EmcAutoCalConfig3 = 0x00000000, + .EmcAutoCalWait = 0x00000190, + .EmcAdrCfg = 0x00000001, + .EmcPinProgramWait = 0x00000000, + .EmcPinExtraWait = 0x00000000, + .EmcTimingControlWait = 0x00000000, + .EmcRc = 0x00000037, + .EmcRfc = 0x00000078, + .EmcRfcSlr = 0x00000000, + .EmcRas = 0x00000026, + .EmcRp = 0x00000010, + .EmcR2r = 0x00000000, + .EmcW2w = 0x00000000, + .EmcR2w = 0x00000010, + .EmcW2r = 0x00000010, + .EmcR2p = 0x00000006, + .EmcW2p = 0x00000017, + .EmcRdRcd = 0x00000010, + .EmcWrRcd = 0x00000010, + .EmcRrd = 0x00000009, + .EmcRext = 0x00000005, + .EmcWext = 0x00000000, + .EmcWdv = 0x00000007, + .EmcWdvMask = 0x00000007, + .EmcQUse = 0x00000011, + .EmcQuseWidth = 0x00000004, + .EmcIbdly = 0x00000000, + .EmcEInput = 0x00000006, + .EmcEInputDuration = 0x00000011, + .EmcPutermExtra = 0x000e0000, + .EmcPutermWidth = 0x00000006, + .EmcPutermAdj = 0x00000000, + .EmcCdbCntl1 = 0x00000000, + .EmcCdbCntl2 = 0x00000000, + .EmcCdbCntl3 = 0x00000000, + .EmcQRst = 0x00000005, + .EmcQSafe = 0x00000018, + .EmcRdv = 0x00000020, + .EmcRdvMask = 0x00000022, + .EmcQpop = 0x00000017, + .EmcCtt = 0x00000000, + .EmcCttDuration = 0x00000006, + .EmcRefresh = 0x00000dd4, + .EmcBurstRefreshNum = 0x00000000, + .EmcPreRefreshReqCnt = 0x00000375, + .EmcPdEx2Wr = 0x00000006, + .EmcPdEx2Rd = 0x00000006, + .EmcPChg2Pden = 0x00000010, + .EmcAct2Pden = 0x00000000, + .EmcAr2Pden = 0x00000001, + .EmcRw2Pden = 0x0000001b, + .EmcTxsr = 0x00000082, + .EmcTxsrDll = 0x00000082, + .EmcTcke = 0x00000007, + .EmcTckesr = 0x0000000e, + .EmcTpd = 0x00000007, + .EmcTfaw = 0x0000002d, + .EmcTrpab = 0x00000014, + .EmcTClkStable = 0x00000003, + .EmcTClkStop = 0x00000003, + .EmcTRefBw = 0x00000f04, + .EmcFbioCfg5 = 0x1363a896, + .EmcFbioCfg6 = 0x00000000, + .EmcFbioSpare = 0x00000000, + .EmcCfgRsv = 0xff00ff00, + .EmcMrs = 0x00000000, + .EmcEmrs = 0x00000000, + .EmcEmrs2 = 0x00000000, + .EmcEmrs3 = 0x00000000, + .EmcMrw1 = 0x00010083, + .EmcMrw2 = 0x0002001c, + .EmcMrw3 = 0x00030001, + .EmcMrw4 = 0x800b0000, + .EmcMrwExtra = 0x00010083, + .EmcWarmBootMrwExtra = 0x0002001c, + .EmcWarmBootExtraModeRegWriteEnable = 0x00000000, + .EmcExtraModeRegWriteEnable = 0x00000000, + .EmcMrwResetCommand = 0x003f00fc, + .EmcMrwResetNInitWait = 0x0000000a, + .EmcMrsWaitCnt = 0x039c0019, + .EmcMrsWaitCnt2 = 0x039c0019, + .EmcCfg = 0xf3300000, + .EmcCfg2 = 0x0000089f, + .EmcCfgPipe = 0x00004080, + .EmcDbg = 0x01000c00, + .EmcCmdQ = 0x10004408, + .EmcMc2EmcQ = 0x06000404, + .EmcDynSelfRefControl = 0x80001c77, + .AhbArbitrationXbarCtrlMemInitDone = 0x00000001, + .EmcCfgDigDll = 0xe00400b9, + .EmcCfgDigDllPeriod = 0x00008000, + .EmcDevSelect = 0x00000000, + .EmcSelDpdCtrl = 0x0004001c, + .EmcDllXformDqs0 = 0x007fc00a, + .EmcDllXformDqs1 = 0x007fc00a, + .EmcDllXformDqs2 = 0x007fc00a, + .EmcDllXformDqs3 = 0x007fc00a, + .EmcDllXformDqs4 = 0x007f800c, + .EmcDllXformDqs5 = 0x00000008, + .EmcDllXformDqs6 = 0x007f800a, + .EmcDllXformDqs7 = 0x007fc00a, + .EmcDllXformDqs8 = 0x007f400a, + .EmcDllXformDqs9 = 0x007f400a, + .EmcDllXformDqs10 = 0x007f400a, + .EmcDllXformDqs11 = 0x007f400a, + .EmcDllXformDqs12 = 0x007f400a, + .EmcDllXformDqs13 = 0x007f400a, + .EmcDllXformDqs14 = 0x007f400a, + .EmcDllXformDqs15 = 0x007f400a, + .EmcDllXformQUse0 = 0x00000000, + .EmcDllXformQUse1 = 0x00000000, + .EmcDllXformQUse2 = 0x00000000, + .EmcDllXformQUse3 = 0x00000000, + .EmcDllXformQUse4 = 0x00000000, + .EmcDllXformQUse5 = 0x00000000, + .EmcDllXformQUse6 = 0x00000000, + .EmcDllXformQUse7 = 0x00000000, + .EmcDllXformAddr0 = 0x00018002, + .EmcDllXformAddr1 = 0x00018002, + .EmcDllXformAddr2 = 0x00000008, + .EmcDllXformAddr3 = 0x00018002, + .EmcDllXformAddr4 = 0x00018002, + .EmcDllXformAddr5 = 0x00000008, + .EmcDllXformQUse8 = 0x00000000, + .EmcDllXformQUse9 = 0x00000000, + .EmcDllXformQUse10 = 0x00000000, + .EmcDllXformQUse11 = 0x00000000, + .EmcDllXformQUse12 = 0x00000000, + .EmcDllXformQUse13 = 0x00000000, + .EmcDllXformQUse14 = 0x00000000, + .EmcDllXformQUse15 = 0x00000000, + .EmcDliTrimTxDqs0 = 0x00000008, + .EmcDliTrimTxDqs1 = 0x00000008, + .EmcDliTrimTxDqs2 = 0x00000008, + .EmcDliTrimTxDqs3 = 0x00000008, + .EmcDliTrimTxDqs4 = 0x00000008, + .EmcDliTrimTxDqs5 = 0x00000008, + .EmcDliTrimTxDqs6 = 0x00000008, + .EmcDliTrimTxDqs7 = 0x00000008, + .EmcDliTrimTxDqs8 = 0x00000008, + .EmcDliTrimTxDqs9 = 0x00000008, + .EmcDliTrimTxDqs10 = 0x00000008, + .EmcDliTrimTxDqs11 = 0x00000008, + .EmcDliTrimTxDqs12 = 0x00000008, + .EmcDliTrimTxDqs13 = 0x00000008, + .EmcDliTrimTxDqs14 = 0x00000008, + .EmcDliTrimTxDqs15 = 0x00000008, + .EmcDllXformDq0 = 0x0000000c, + .EmcDllXformDq1 = 0x0000000c, + .EmcDllXformDq2 = 0x0000000c, + .EmcDllXformDq3 = 0x0000000c, + .EmcDllXformDq4 = 0x0000000c, + .EmcDllXformDq5 = 0x0000000c, + .EmcDllXformDq6 = 0x0000000c, + .EmcDllXformDq7 = 0x0000000c, + .WarmBootWait = 0x00000001, + .EmcCttTermCtrl = 0x00000802, + .EmcOdtWrite = 0x00000000, + .EmcOdtRead = 0x00000000, + .EmcZcalInterval = 0x00064000, + .EmcZcalWaitCnt = 0x00000058, + .EmcZcalMrwCmd = 0x000a0056, + .EmcMrsResetDll = 0x00000000, + .EmcZcalInitDev0 = 0x840a00ff, + .EmcZcalInitDev1 = 0x440a00ff, + .EmcZcalInitWait = 0x00000001, + .EmcZcalWarmColdBootEnables = 0x00000003, + .EmcMrwLpddr2ZcalWarmBoot = 0x040a00ab, + .EmcZqCalDdr3WarmBoot = 0x00000000, + .EmcZcalWarmBootWait = 0x00000001, + .EmcMrsWarmBootEnable = 0x00000001, + .EmcMrsResetDllWait = 0x00000000, + .EmcMrsExtra = 0x00000000, + .EmcWarmBootMrsExtra = 0x00000000, + .EmcEmrsDdr2DllEnable = 0x00000000, + .EmcMrsDdr2DllReset = 0x00000000, + .EmcEmrsDdr2OcdCalib = 0x00000000, + .EmcDdr2Wait = 0x00000000, + .EmcClkenOverride = 0x00000000, + .McDisExtraSnapLevels = 0x00000000, + .EmcExtraRefreshNum = 0x00000002, + .EmcClkenOverrideAllWarmBoot = 0x00000000, + .McClkenOverrideAllWarmBoot = 0x00000000, + .EmcCfgDigDllPeriodWarmBoot = 0x00000003, + .PmcVddpSel = 0x00000001, + .PmcVddpSelWait = 0x00000002, + .PmcDdrPwr = 0x00000003, + .PmcDdrCfg = 0x00001000, + .PmcIoDpd3Req = 0x4ffefef7, + .PmcIoDpd3ReqWait = 0x00000000, + .PmcRegShort = 0x0000330f, + .PmcNoIoPower = 0x00000000, + .PmcPorDpdCtrlWait = 0x00000001, + .EmcXm2CmdPadCtrl = 0x00000220, + .EmcXm2CmdPadCtrl2 = 0x770c0000, + .EmcXm2CmdPadCtrl3 = 0x050c0000, + .EmcXm2CmdPadCtrl4 = 0x00000000, + .EmcXm2CmdPadCtrl5 = 0x00100100, + .EmcXm2DqsPadCtrl = 0x770c1414, + .EmcXm2DqsPadCtrl2 = 0x0120103d, + .EmcXm2DqsPadCtrl3 = 0x55555520, + .EmcXm2DqsPadCtrl4 = 0x00596596, + .EmcXm2DqsPadCtrl5 = 0x00596596, + .EmcXm2DqsPadCtrl6 = 0x55555500, + .EmcXm2DqPadCtrl = 0x770c2990, + .EmcXm2DqPadCtrl2 = 0x00000000, + .EmcXm2DqPadCtrl3 = 0x00000000, + .EmcXm2ClkPadCtrl = 0x77ffc004, + .EmcXm2ClkPadCtrl2 = 0x00000000, + .EmcXm2CompPadCtrl = 0x81f1f008, + .EmcXm2VttGenPadCtrl = 0x07070000, + .EmcXm2VttGenPadCtrl2 = 0x00000000, + .EmcXm2VttGenPadCtrl3 = 0x015ddddd, + .EmcAcpdControl = 0x00000000, + .EmcSwizzleRank0ByteCfg = 0x00001032, + .EmcSwizzleRank0Byte0 = 0x53067142, + .EmcSwizzleRank0Byte1 = 0x73025146, + .EmcSwizzleRank0Byte2 = 0x20136475, + .EmcSwizzleRank0Byte3 = 0x46273150, + .EmcSwizzleRank1ByteCfg = 0x00003210, + .EmcSwizzleRank1Byte0 = 0x73451026, + .EmcSwizzleRank1Byte1 = 0x73025146, + .EmcSwizzleRank1Byte2 = 0x20641735, + .EmcSwizzleRank1Byte3 = 0x42136075, + .EmcDsrVttgenDrv = 0x0000003f, + .EmcTxdsrvttgen = 0x00000000, + .EmcBgbiasCtl0 = 0x00000000, + .McEmemAdrCfg = 0x00000001, + .McEmemAdrCfgDev0 = 0x00080304, + .McEmemAdrCfgDev1 = 0x00080304, + .McEmemAdrCfgBankMask0 = 0x00001248, + .McEmemAdrCfgBankMask1 = 0x00002490, + .McEmemAdrCfgBankMask2 = 0x00000920, + .McEmemAdrCfgBankSwizzle3 = 0x00000001, + .McEmemCfg = 0x00001000, + .McEmemArbCfg = 0x0e00000d, + .McEmemArbOutstandingReq = 0x80000040, + .McEmemArbTimingRcd = 0x00000007, + .McEmemArbTimingRp = 0x00000008, + .McEmemArbTimingRc = 0x0000001b, + .McEmemArbTimingRas = 0x00000012, + .McEmemArbTimingFaw = 0x00000017, + .McEmemArbTimingRrd = 0x00000004, + .McEmemArbTimingRap2Pre = 0x00000004, + .McEmemArbTimingWap2Pre = 0x0000000e, + .McEmemArbTimingR2R = 0x00000004, + .McEmemArbTimingW2W = 0x00000001, + .McEmemArbTimingR2W = 0x00000009, + .McEmemArbTimingW2R = 0x00000009, + .McEmemArbDaTurns = 0x09090104, + .McEmemArbDaCovers = 0x001e141b, + .McEmemArbMisc0 = 0x71ae2a1c, + .McEmemArbMisc1 = 0x70000f02, + .McEmemArbRing1Throttle = 0x001f0000, + .McEmemArbOverride = 0x10000000, + .McEmemArbOverride1 = 0x00000000, + .McEmemArbRsv = 0xff00ff00, + .McClkenOverride = 0x00000000, + .McStatControl = 0x00000000, + .McDisplaySnapRing = 0x00000003, + .McVideoProtectBom = 0xfff00000, + .McVideoProtectBomAdrHi = 0x00000000, + .McVideoProtectSizeMb = 0x00000000, + .McVideoProtectVprOverride = 0xe4bac743, + .McVideoProtectVprOverride1 = 0x00000013, + .McVideoProtectGpuOverride0 = 0x00000000, + .McVideoProtectGpuOverride1 = 0x00000000, + .McSecCarveoutBom = 0xfff00000, + .McSecCarveoutAdrHi = 0x00000000, + .McSecCarveoutSizeMb = 0x00000000, + .McVideoProtectWriteAccess = 0x00000000, + .McSecCarveoutProtectWriteAccess = 0x00000000, + .EmcCaTrainingEnable = 0x00000001, + .EmcCaTrainingTimingCntl1 = 0x09257359, + .EmcCaTrainingTimingCntl2 = 0x00000017, + .SwizzleRankByteEncode = 0x00000008, + .BootRomPatchControl = 0x00000000, + .BootRomPatchData = 0x00000000, + .McMtsCarveoutBom = 0x78000000, + .McMtsCarveoutAdrHi = 0x00000001, + .McMtsCarveoutSizeMb = 0x00000080, + .McMtsCarveoutRegCtrl = 0x00000001, +}, diff --git a/src/mainboard/google/rush_ryu/bct/spi.cfg b/src/mainboard/google/rush_ryu/bct/spi.cfg new file mode 100644 index 0000000000..a5ded0bd68 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bct/spi.cfg @@ -0,0 +1,31 @@ +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Distributed under the terms of the GNU General Public License v2 + +Version = 0x00130001; +BlockSize = 32768; +PageSize = 2048; +PartitionSize = 4194304; + +DevType[0] = NvBootDevType_Spi; +DeviceParam[0].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[0].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[0].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[0].SpiFlashParams.PageSize2kor16k = 0; + +DevType[1] = NvBootDevType_Spi; +DeviceParam[1].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[1].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[1].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[1].SpiFlashParams.PageSize2kor16k = 0; + +DevType[2] = NvBootDevType_Spi; +DeviceParam[2].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[2].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[2].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[2].SpiFlashParams.PageSize2kor16k = 0; + +DevType[3] = NvBootDevType_Spi; +DeviceParam[3].SpiFlashParams.ReadCommandTypeFast = NV_FALSE; +DeviceParam[3].SpiFlashParams.ClockDivider = 0x16; +DeviceParam[3].SpiFlashParams.ClockSource = NvBootSpiClockSource_PllPOut0; +DeviceParam[3].SpiFlashParams.PageSize2kor16k = 0; diff --git a/src/mainboard/google/rush_ryu/boardid.c b/src/mainboard/google/rush_ryu/boardid.c new file mode 100644 index 0000000000..9c4d18407d --- /dev/null +++ b/src/mainboard/google/rush_ryu/boardid.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "gpio.h" + +uint8_t board_id(void) +{ + static int id = -1; + + if (id < 0) { + gpio_t gpio[] = {[1] = BD_ID1, [0] = BD_ID0}; /* ID0 is LSB */ + + id = gpio_base3_value(gpio, ARRAY_SIZE(gpio)); + } + + return id; +} diff --git a/src/mainboard/google/rush_ryu/bootblock.c b/src/mainboard/google/rush_ryu/bootblock.c new file mode 100644 index 0000000000..2272ce1370 --- /dev/null +++ b/src/mainboard/google/rush_ryu/bootblock.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pmic.h" + +static const struct pad_config uart_console_pads[] = { + /* UARTA: tx and rx. */ + PAD_CFG_SFIO(KB_ROW9, PINMUX_PULL_NONE, UA3), + PAD_CFG_SFIO(KB_ROW10, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, UA3), + /* + * Disable UART2 pads as they are default connected to UARTA controller. + */ + PAD_CFG_UNUSED(UART2_RXD), + PAD_CFG_UNUSED(UART2_TXD), + PAD_CFG_UNUSED(UART2_RTS_N), + PAD_CFG_UNUSED(UART2_CTS_N), +}; + +static const struct pad_config pmic_pads[] = { + PAD_CFG_SFIO(PWR_I2C_SCL, PINMUX_INPUT_ENABLE, I2CPMU), + PAD_CFG_SFIO(PWR_I2C_SDA, PINMUX_INPUT_ENABLE, I2CPMU), +}; + +static const struct pad_config spiflash_pads[] = { + /* mosi, miso, clk, cs0 */ + PAD_CFG_SFIO(GPIO_PG6, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SPI4), + PAD_CFG_SFIO(GPIO_PG7, PINMUX_INPUT_ENABLE | PINMUX_PULL_UP, SPI4), + PAD_CFG_SFIO(GPIO_PG5, PINMUX_INPUT_ENABLE, SPI4), + PAD_CFG_SFIO(GPIO_PI3, PINMUX_INPUT_ENABLE, SPI4), +}; + +static const struct funit_cfg funits[] = { + /* PMIC on I2C5 (PWR_I2C* pads) at 400kHz. */ + FUNIT_CFG(I2C5, PLLP, 400, pmic_pads, ARRAY_SIZE(pmic_pads)), + /* SPI flash at 33MHz on SPI4 controller. */ + FUNIT_CFG(SBC4, PLLP, 33333, spiflash_pads, ARRAY_SIZE(spiflash_pads)), +}; + +void bootblock_mainboard_early_init(void) +{ + soc_configure_pads(uart_console_pads, ARRAY_SIZE(uart_console_pads)); +} + +static void set_clock_sources(void) +{ + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, CLK_RST_REG(clk_src_uarta)); +} + +static const struct pad_config padcfgs[] = { + /* Board build id bits 1:0 */ + PAD_CFG_GPIO_INPUT(KB_COL4, PINMUX_PULL_NONE), + PAD_CFG_GPIO_INPUT(KB_COL3, PINMUX_PULL_NONE), +}; + +void bootblock_mainboard_init(void) +{ + set_clock_sources(); + + /* Set up controllers and pads to load romstage. */ + soc_configure_funits(funits, ARRAY_SIZE(funits)); + soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs)); + + i2c_init(I2CPWR_BUS); + pmic_init(I2CPWR_BUS); +} diff --git a/src/mainboard/google/rush_ryu/chromeos.c b/src/mainboard/google/rush_ryu/chromeos.c new file mode 100644 index 0000000000..6781b39954 --- /dev/null +++ b/src/mainboard/google/rush_ryu/chromeos.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gpio.h" + +static inline uint32_t get_pwr_btn_polarity(void) +{ + if (board_id() < BOARD_ID_PROTO_3) + return ACTIVE_HIGH; + + return ACTIVE_LOW; +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = WRITE_PROTECT_L; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(WRITE_PROTECT_L); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* TODO(adurbin): add lid switch */ + + /* Power: active low / high depending on board id */ + gpios->gpios[count].port = POWER_BUTTON; + gpios->gpios[count].polarity = get_pwr_btn_polarity(); + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: virtual GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: active high */ + gpios->gpios[count].port = EC_IN_RW; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: active low (output) */ + gpios->gpios[count].port = AP_SYS_RESET_L; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(WRITE_PROTECT_L); +} diff --git a/src/mainboard/google/rush_ryu/devicetree.cb b/src/mainboard/google/rush_ryu/devicetree.cb new file mode 100644 index 0000000000..f621e006d8 --- /dev/null +++ b/src/mainboard/google/rush_ryu/devicetree.cb @@ -0,0 +1,55 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/nvidia/tegra132 + register "spintable_addr" = "0x80000008" + + device cpu_cluster 0 on + device cpu 0 on end + device cpu 1 on end + end + + register "display_controller" = "TEGRA_ARM_DISPLAYA" + register "xres" = "2560" + register "yres" = "1800" + + # bits per pixel and color depth + register "framebuffer_bits_per_pixel" = "32" + register "color_depth" = "12" + + # framebuffer resolution + register "display_xres" = "1280" + register "display_yres" = "800" + + register "href_to_sync" = "1" + register "hfront_porch" = "80" + register "hsync_width" = "80" + register "hback_porch" = "80" + + register "vref_to_sync" = "1" + register "vfront_porch" = "4" + register "vsync_width" = "4" + register "vback_porch" = "4" + register "refresh" = "60" + + # kernel driver + register "pixel_clock" = "301620000" + + register "win_opt" = "DSI_ENABLE" +end diff --git a/src/mainboard/google/rush_ryu/gpio.h b/src/mainboard/google/rush_ryu/gpio.h new file mode 100644 index 0000000000..8fa7c3d07d --- /dev/null +++ b/src/mainboard/google/rush_ryu/gpio.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_RUSH_RYU_GPIO_H__ +#define __MAINBOARD_GOOGLE_RUSH_RYU_GPIO_H__ + +#include +#include + +/* Board ID definitions. */ +enum { + BOARD_REV0 = BASE3(0, 0), + BOARD_REV1 = BASE3(0, 1), + BOARD_REV2 = BASE3(0, Z), + BOARD_REV3 = BASE3(1, 0), + BOARD_REV4 = BASE3(1, 1), + BOARD_REV5 = BASE3(1, Z), + BOARD_REV6 = BASE3(Z, 0), + BOARD_REV7 = BASE3(Z, 1), + BOARD_REV8 = BASE3(Z, Z), + + BOARD_ID_PROTO_0 = BOARD_REV0, + BOARD_ID_PROTO_1 = BOARD_REV1, + BOARD_ID_PROTO_3 = BOARD_REV2, + BOARD_ID_EVT = BOARD_REV3, + BOARD_ID_DVT = BOARD_REV4, + BOARD_ID_PVT = BOARD_REV5, + BOARD_ID_MP = BOARD_REV6, +}; + +enum { + /* Board ID related GPIOS. */ + BD_ID0 = GPIO(Q3), + BD_ID1 = GPIO(Q4), + /* LTE modem related GPIOs */ + MODEM_RESET = GPIO(S3), + MODEM_PWR_ON = GPIO(S4), + MDM_DET = GPIO(V1), + /* Warm reset */ + AP_SYS_RESET_L = GPIO(I5), + /* Write Protect */ + SPI_1V8_WP_L = GPIO(R1), + WRITE_PROTECT_L = SPI_1V8_WP_L, + /* Power button - Depending on board id, maybe active high / low */ + BTN_AP_PWR = GPIO(Q0), + POWER_BUTTON = BTN_AP_PWR, + /* EC in RW signal */ + EC_IN_RW = GPIO(U4), + + /* Panel related GPIOs */ + LCD_EN = GPIO(H5), + LCD_RST_L = GPIO(H3), + EN_VDD18_LCD = GPIO(X0), + EN_VDD_LCD = GPIO(BB6), /* P1/P3 board */ +}; + +#endif /* __MAINBOARD_GOOGLE_RUSH_RYU_GPIO_H__ */ diff --git a/src/mainboard/google/rush_ryu/mainboard.c b/src/mainboard/google/rush_ryu/mainboard.c new file mode 100644 index 0000000000..11b4c2d669 --- /dev/null +++ b/src/mainboard/google/rush_ryu/mainboard.c @@ -0,0 +1,294 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" +#include "pmic.h" + +static const struct pad_config mmcpads[] = { + /* MMC4 (eMMC) */ + PAD_CFG_SFIO(SDMMC4_CLK, PINMUX_INPUT_ENABLE|PINMUX_PULL_DOWN, SDMMC4), + PAD_CFG_SFIO(SDMMC4_CMD, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT0, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT1, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT2, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT3, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT4, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT5, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT6, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), + PAD_CFG_SFIO(SDMMC4_DAT7, PINMUX_INPUT_ENABLE|PINMUX_PULL_UP, SDMMC4), +}; + +static const struct pad_config audio_codec_pads[] = { + /* H1 is CODEC_RST_L and R2(ROW2) is AUDIO_ENABLE */ + PAD_CFG_GPIO_OUT1(GPIO_PH1, PINMUX_PULL_DOWN), + PAD_CFG_GPIO_OUT1(KB_ROW2, PINMUX_PULL_DOWN), +}; + +static const struct funit_cfg funits[] = { + /* MMC on SDMMC4 controller at 48MHz. */ + FUNIT_CFG(SDMMC4, PLLP, 48000, mmcpads, ARRAY_SIZE(mmcpads)), + /* I2C6 for audio, temp sensor, etc. Enable codec via GPIOs/muxes */ + FUNIT_CFG(I2C6, PLLP, 400, audio_codec_pads, ARRAY_SIZE(audio_codec_pads)), + FUNIT_CFG_USB(USBD), +}; + +/* HACK: For proto boards before proto3, we want to disable ec sw sync */ +static void fix_ec_sw_sync(void) +{ + struct vboot_handoff *vh; + + if (board_id() >= BOARD_ID_PROTO_3) + return; + + vh = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vh == NULL) { + printk(BIOS_ERR, "No vboot handoff struct found\n"); + return; + } + + VbSharedDataHeader *vb_sd = (VbSharedDataHeader *)vh->shared_data; + vb_sd->flags &= ~VBSD_EC_SOFTWARE_SYNC; +} + +static const struct pad_config lcd_gpio_padcfgs[] = { + /* LCD_EN */ + PAD_CFG_GPIO_OUT0(GPIO_PH5, PINMUX_PULL_UP), + /* LCD_RST_L */ + PAD_CFG_GPIO_OUT0(GPIO_PH3, PINMUX_PULL_UP), + /* EN_VDD_LCD */ + PAD_CFG_GPIO_OUT0(GPIO_PBB6, PINMUX_PULL_NONE), + /* EN_VDD18_LCD */ + PAD_CFG_GPIO_OUT0(DVFS_PWM, PINMUX_PULL_DOWN), +}; + +static void configure_display_clocks(void) +{ + u32 lclks = CLK_L_HOST1X | CLK_L_DISP1; /* dc */ + u32 hclks = CLK_H_MIPI_CAL | CLK_H_DSI; /* mipi phy, mipi-dsi a */ + u32 uclks = CLK_U_DSIB; /* mipi-dsi b */ + u32 xclks = CLK_X_CLK72MHZ; /* clk src of mipi_cal */ + + clock_enable_clear_reset(lclks, hclks, uclks, 0, 0, xclks); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); +} + +static int enable_lcd_vdd(void) +{ + uint8_t data; + + /* Set 1.20V to power AVDD_DSI_CSI */ + pmic_write_reg(I2CPWR_BUS, TI65913_LDO5_VOLTAGE, + VSEL_1200, 1); + pmic_write_reg(I2CPWR_BUS, TI65913_LDO5_CTRL, + TI65913_MODE_ACTIVE_ON, 1); + + /* + * Enable VDD_LCD + * + * Use different GPIO based on board id + */ + switch (board_id()) { + case BOARD_ID_PROTO_0: + /* Select PMIC GPIO_6's primary function */ + pmic_read_reg(I2CPWR_BUS, TI65913_PAD2, &data); + pmic_write_reg(I2CPWR_BUS, TI65913_PAD2, + PAD2_GPIO_6_PRIMARY(data), 0); + + /* Set PMIC_GPIO_6 as output */ + pmic_read_reg(I2CPWR_BUS, TI65913_GPIO_DATA_DIR, &data); + pmic_write_reg(I2CPWR_BUS, TI65913_GPIO_DATA_DIR, + TI65913_GPIO_6_OUTPUT, 0); + + /* Set PMIC_GPIO_6 output high */ + pmic_read_reg(I2CPWR_BUS, TI65913_GPIO_DATA_OUT, &data); + pmic_write_reg(I2CPWR_BUS, TI65913_GPIO_DATA_OUT, + TI65913_GPIO_6_HIGH, 1); + break; + case BOARD_ID_PROTO_1: + case BOARD_ID_PROTO_3: + gpio_set(EN_VDD_LCD, 1); + break; + default: /* unknown board */ + return -1; + } + /* wait for 2ms */ + mdelay(2); + + /* Enable PP1800_LCDIO to panel */ + gpio_set(EN_VDD18_LCD, 1); + /* wait for 1ms */ + mdelay(1); + + /* Set panel EN and RST signals */ + gpio_set(LCD_EN, 1); /* enable */ + /* wait for min 10ms */ + mdelay(10); + gpio_set(LCD_RST_L, 1); /* clear reset */ + /* wait for min 3ms */ + mdelay(3); + + return 0; +} + +static const struct pad_config i2s1_pad[] = { + /* I2S1 */ + PAD_CFG_SFIO(DAP2_SCLK, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_FS, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_DOUT, PINMUX_INPUT_ENABLE, I2S1), + PAD_CFG_SFIO(DAP2_DIN, PINMUX_INPUT_ENABLE | PINMUX_TRISTATE, I2S1), + /* codec MCLK via EXTPERIPH1 */ + PAD_CFG_SFIO(DAP_MCLK1, PINMUX_PULL_NONE, EXTPERIPH1), +}; + +static const struct funit_cfg audio_funit[] = { + /* We need 1.5MHz for I2S1. So we use CLK_M */ + FUNIT_CFG(I2S1, CLK_M, 1500, i2s1_pad, ARRAY_SIZE(i2s1_pad)), +}; + +static int configure_display_blocks(void) +{ + /* set and enable panel related vdd */ + if (enable_lcd_vdd()) + return -1; + + /* enable display related clocks */ + configure_display_clocks(); + + return 0; +} + +/* Audio init: clocks and enables/resets */ +static void setup_audio(void) +{ + /* + * External peripheral 1: audio codec (RT5677) uses 12MHz CLK1 + * NOTE: We can't use a funits struct/call here because EXTPERIPH1/2/3 + * don't have BASE regs or CAR RST/ENA bits. Also, the mux setting for + * EXTPERIPH1/DAP_MCLK1 is rolled into the I2S1 padcfg. + */ + clock_configure_source(extperiph1, CLK_M, 12000); + + soc_configure_funits(audio_funit, ARRAY_SIZE(audio_funit)); + + clock_external_output(1); /* For external RT5677 audio codec. */ + + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (in our + * case, I2S/APBIF/AUDIO) will hang. + */ + clock_enable_audio(); +} + +#define AD4567_DEV 0x34 +#define PWR_CTL 0 +#define DAC_CTL 2 +#define SPWDN (1 << 0) +#define DAC_MUTE (1 << 6) +#define DAC_FS (0x7 << 0) +#define SR_32K_48KHZ 0x2 + +static void enable_ad4567_spkr_amp(void) +{ + uint8_t reg_byte; + + if (board_id() >= BOARD_ID_PROTO_3) + return; + /* + * I2C6, device 0x34 is an AD4567 speaker amp on P0/P1. + * It needs to have a couple of regs tweaked to turn it on + * so it can provide audio output to the mono speaker on P0/P1. + */ + i2c_readb(I2C6_BUS, AD4567_DEV, PWR_CTL, ®_byte); + reg_byte &= ~SPWDN; // power up amp + i2c_writeb(I2C6_BUS, AD4567_DEV, PWR_CTL, reg_byte); + + /* The next 2 settings are defaults, but set them anyway */ + i2c_readb(I2C6_BUS, AD4567_DEV, DAC_CTL, ®_byte); + reg_byte &= ~DAC_MUTE; // unmute DAC (default) + reg_byte &= ~DAC_FS; // mask sample rate bits + reg_byte |= SR_32K_48KHZ; // set 32K-48KHz sample rate (default) + i2c_writeb(I2C6_BUS, AD4567_DEV, DAC_CTL, reg_byte); +} + +static void mainboard_init(device_t dev) +{ + soc_configure_funits(funits, ARRAY_SIZE(funits)); + + /* I2C6 bus (audio, etc.) */ + soc_configure_i2c6pad(); + i2c_init(I2C6_BUS); + + setup_audio(); + /* Temp hack for P1 board: Enable speaker amp (powerup, etc.) */ + enable_ad4567_spkr_amp(); + + elog_init(); + elog_add_boot_reason(); + + fix_ec_sw_sync(); + + /* configure panel gpio pads */ + soc_configure_pads(lcd_gpio_padcfgs, ARRAY_SIZE(lcd_gpio_padcfgs)); + + /* if panel needs to bringup */ + if (!vboot_skip_display_init()) + configure_display_blocks(); +} + +void display_startup(device_t dev) +{ + dsi_display_startup(dev); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "rush_ryu", + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/google/rush_ryu/memlayout.ld b/src/mainboard/google/rush_ryu/memlayout.ld new file mode 100644 index 0000000000..d8fdb9a94b --- /dev/null +++ b/src/mainboard/google/rush_ryu/memlayout.ld @@ -0,0 +1,5 @@ +#if IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE) +#include +#else +#include +#endif diff --git a/src/mainboard/google/rush_ryu/pmic.c b/src/mainboard/google/rush_ryu/pmic.c new file mode 100644 index 0000000000..00d1ab476f --- /dev/null +++ b/src/mainboard/google/rush_ryu/pmic.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "pmic.h" +#include "reset.h" + +#define PAGE_ADDR(reg) ((reg >> 8) & 0xff) +#define PAGE_OFFSET(reg) (reg & 0xff) + +struct ti65913_init_reg { + u16 reg; + u8 val; + u8 delay; +}; + +static struct ti65913_init_reg init_list[] = { +//TODO(twarren@nvidia.com): Add slams back to defaults +// {TI65913_SMPS12_VOLTAGE, 0x38, 0}, +// {TI65913_SMPS12_CTRL, 0x01, 1}, +//etc. +}; + +int pmic_read_reg(unsigned bus, uint16_t reg, uint8_t *data) +{ + if (i2c_readb(bus, PAGE_ADDR(reg), PAGE_OFFSET(reg), data)) { + printk(BIOS_ERR, "%s: page = 0x%02X, reg = 0x%02X failed!\n", + __func__, PAGE_ADDR(reg), PAGE_OFFSET(reg)); + return -1; + } + return 0; +} + +void pmic_write_reg(unsigned bus, uint16_t reg, uint8_t val, int delay) +{ + if (i2c_writeb(bus, PAGE_ADDR(reg), PAGE_OFFSET(reg), val)) { + printk(BIOS_ERR, "%s: page = 0x%02X, reg = 0x%02X, " + "value = 0x%02X failed!\n", + __func__, PAGE_ADDR(reg), PAGE_OFFSET(reg), val); + /* Reset the SoC on any PMIC write error */ + cpu_reset(); + } else { + if (delay) + udelay(500); + } +} + +static void pmic_slam_defaults(unsigned bus) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(init_list); i++) { + struct ti65913_init_reg *reg = &init_list[i]; + pmic_write_reg(bus, reg->reg, reg->val, reg->delay); + } +} + +void pmic_init(unsigned bus) +{ + /* Restore PMIC POR defaults, in case kernel changed 'em */ + pmic_slam_defaults(bus); + + /* A44: Set VDD_CPU to 1.0V. */ + pmic_write_reg(bus, TI65913_SMPS12_VOLTAGE, 0x38, 0); + pmic_write_reg(bus, TI65913_SMPS12_CTRL, 0x01, 1); + + printk(BIOS_DEBUG, "PMIC init done\n"); +} diff --git a/src/mainboard/google/rush_ryu/pmic.h b/src/mainboard/google/rush_ryu/pmic.h new file mode 100644 index 0000000000..b32211e650 --- /dev/null +++ b/src/mainboard/google/rush_ryu/pmic.h @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_RUSH_RYU_PMIC_H__ +#define __MAINBOARD_GOOGLE_RUSH_RYU_PMIC_H__ + +#include + +/* A44/Ryu has a TI 65913 PMIC on bus 4 (PWR_I2C) */ +enum { + TI65913_I2C_ADDR_PAGE1 = 0x58, + TI65913_I2C_ADDR_PAGE2 = 0x59 +}; + +enum { + /* Registers in PAGE1 */ + TI65913_SMPS12_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x20, + TI65913_SMPS12_TSTEP, + TI65913_SMPS12_FORCE, + TI65913_SMPS12_VOLTAGE, + + TI65913_SMPS3_CTRL, + TI65913_SMPS3_VOLTAGE = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x27, + + TI65913_SMPS45_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x28, + TI65913_SMPS45_TSTEP, + TI65913_SMPS45_FORCE, + TI65913_SMPS45_VOLTAGE, + + TI65913_SMPS6_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x2C, + TI65913_SMPS6_TSTEP, + TI65913_SMPS6_FORCE, + TI65913_SMPS6_VOLTAGE, + + TI65913_SMPS7_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x30, + TI65913_SMPS7_VOLTAGE = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x33, + + TI65913_SMPS8_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x34, + TI65913_SMPS8_TSTEP, + TI65913_SMPS8_FORCE, + TI65913_SMPS8_VOLTAGE, + + TI65913_SMPS9_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x38, + TI65913_SMPS9_VOLTAGE = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x3B, + + TI65913_SMPS10_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x3C, + TI65913_SMPS10_STATUS = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x3F, + + TI65913_LDO1_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x50, + TI65913_LDO1_VOLTAGE, + TI65913_LDO2_CTRL, + TI65913_LDO2_VOLTAGE, + TI65913_LDO3_CTRL, + TI65913_LDO3_VOLTAGE, + TI65913_LDO4_CTRL, + TI65913_LDO4_VOLTAGE, + TI65913_LDO5_CTRL, + TI65913_LDO5_VOLTAGE, + TI65913_LDO6_CTRL, + TI65913_LDO6_VOLTAGE, + TI65913_LDO7_CTRL, + TI65913_LDO7_VOLTAGE, + TI65913_LDO8_CTRL, + TI65913_LDO8_VOLTAGE, + TI65913_LDO9_CTRL, + TI65913_LDO9_VOLTAGE, + + TI65913_LDOLN_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x62, + TI65913_LDOLN_VOLTAGE, + TI65913_LDOUSB_CTRL, + TI65913_LDOUSB_VOLTAGE, + + TI65913_LDO_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x6A, + TI65913_LDO_PD_CTRL1, + TI65913_LDO_PD_CTRL2, + + TI65913_LDO_SHORT_STATUS1 = (TI65913_I2C_ADDR_PAGE1 << 8) | 0x6D, + TI65913_LDO_SHORT_STATUS2, + + TI65913_CLK32KGAUDIO_CTRL = (TI65913_I2C_ADDR_PAGE1 << 8) | 0xD5, + + TI65913_PAD2 = (TI65913_I2C_ADDR_PAGE1 << 8) | 0xFB, + + /* Registers in PAGE2 */ + TI65913_GPIO_DATA_IN = (TI65913_I2C_ADDR_PAGE2 << 8) | 0x80, + TI65913_GPIO_DATA_DIR, + TI65913_GPIO_DATA_OUT, +}; + +/* Voltage selection */ +enum { + VSEL_1200 = 0x07, +}; + +/* + * TI65913_LDO5_CTRL + * TI65913_CLK32KGAUDIO_CTRL + */ +#define TI65913_MODE_ACTIVE_ON (1 << 0) + +/* + * select PRIMARY or SECONDARY function on PAD2 + */ +#define PAD2_GPIO_6_PRIMARY(data) \ + ((data) & ~(1 << 3)) /* clear bit 3 */ +#define PAD2_GPIO_5_SEC_CLK32KGAUDIO(data) \ + (((data) & ~(0x03 << 1)) | (0x01 << 1)) /* bit 2:1 = 01 */ + +/* TI65913_GPIO_DATA_DIR */ +#define TI65913_GPIO_6_OUTPUT (1 << 6) + +/* TI65913_GPIO_DATA_OUT */ +#define TI65913_GPIO_6_HIGH (1 << 6) + +int pmic_read_reg(unsigned bus, uint16_t reg, uint8_t *data); +void pmic_write_reg(unsigned bus, uint16_t reg, uint8_t val, int delay); +void pmic_init(unsigned bus); + +#endif /* __MAINBOARD_GOOGLE_RUSH_RYU_PMIC_H__ */ diff --git a/src/mainboard/google/rush_ryu/reset.c b/src/mainboard/google/rush_ryu/reset.c new file mode 100644 index 0000000000..7ccb2de28b --- /dev/null +++ b/src/mainboard/google/rush_ryu/reset.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "gpio.h" + +void hard_reset(void) +{ + gpio_output(AP_SYS_RESET_L, 0); + while(1); +} diff --git a/src/mainboard/google/rush_ryu/romstage.c b/src/mainboard/google/rush_ryu/romstage.c new file mode 100644 index 0000000000..a54a5cac2f --- /dev/null +++ b/src/mainboard/google/rush_ryu/romstage.c @@ -0,0 +1,119 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpio.h" +#include "pmic.h" + +static const struct pad_config padcfgs[] = { + /* AP_SYS_RESET_L */ + PAD_CFG_GPIO_OUT1(GPIO_PI5, PINMUX_PULL_UP), + /* WP_L */ + PAD_CFG_GPIO_INPUT(KB_ROW1, PINMUX_PULL_NONE), + /* MODEM_RESET */ + PAD_CFG_GPIO_OUT0(KB_ROW11, PINMUX_PULL_DOWN), + /* MODEM_PWR_ON */ + PAD_CFG_GPIO_OUT0(KB_ROW12, PINMUX_PULL_DOWN), + /* MDM_DET - expected to be pulled down by LTE modem */ + PAD_CFG_GPIO_INPUT(GPIO_PV1, PINMUX_PULL_UP), + /* Power Button - active high / low depending on board id */ + PAD_CFG_GPIO_INPUT(KB_COL0, PINMUX_PULL_UP), + /* BTN_AP_VOLD_L - active low */ + PAD_CFG_GPIO_INPUT(KB_COL6, PINMUX_PULL_UP), + /* BTN_AP_VOLU_L - active low */ + PAD_CFG_GPIO_INPUT(KB_COL7, PINMUX_PULL_UP), +}; + +static const struct pad_config tpm_pads[] = { + PAD_CFG_SFIO(CAM_I2C_SCL, PINMUX_INPUT_ENABLE, I2C3), + PAD_CFG_SFIO(CAM_I2C_SDA, PINMUX_INPUT_ENABLE, I2C3), +}; + +static const struct pad_config ec_i2c_pads[] = { + PAD_CFG_SFIO(GEN2_I2C_SCL, PINMUX_OPEN_DRAIN|PINMUX_INPUT_ENABLE, I2C2), + PAD_CFG_SFIO(GEN2_I2C_SDA, PINMUX_OPEN_DRAIN|PINMUX_INPUT_ENABLE, I2C2), +}; + +static const struct funit_cfg funits[] = { + /* TPM on I2C3 @ 400kHz */ + FUNIT_CFG(I2C3, PLLP, 400, tpm_pads, ARRAY_SIZE(tpm_pads)), + /* EC on I2C2 - pulled to 3.3V @ 100kHz */ + FUNIT_CFG(I2C2, PLLP, 100, ec_i2c_pads, ARRAY_SIZE(ec_i2c_pads)), +}; + +static void lte_modem_init(void) +{ + int mdm_det; + uint8_t data; + + /* A LTE modem is present if MDM_DET is pulled down by the modem */ + mdm_det = gpio_get(MDM_DET); + if (mdm_det == 1) + return; + + printk(BIOS_DEBUG, "Found LTE modem\n"); + + /* Enable PMIC CLK32KGAUDIO to drive CLK_MDM_32K */ + pmic_read_reg(I2CPWR_BUS, TI65913_PAD2, &data); + pmic_write_reg(I2CPWR_BUS, TI65913_PAD2, + PAD2_GPIO_5_SEC_CLK32KGAUDIO(data), 0); + pmic_write_reg(I2CPWR_BUS, TI65913_CLK32KGAUDIO_CTRL, + TI65913_MODE_ACTIVE_ON, 0); + + /* FULL_CARD_POWER_OFF# (A44: MODEM_PWR_ON) and RESET# + * (A44: MODEM_RESET) of the LTE modem are actively low and initially + * pulled down by the pad config. To properly enable the LTE modem, + * de-assert FULL_CARD_POWER_OFF#, wait for at least 10ms, and then + * de-assert RESET#. + */ + gpio_output(MODEM_PWR_ON, 1); + udelay(15000); + gpio_output(MODEM_RESET, 1); +} + +void romstage_mainboard_init(void) +{ + /* Bring up controller interfaces for ramstage loading. */ + soc_configure_funits(funits, ARRAY_SIZE(funits)); + soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs)); + + /* TPM */ + i2c_init(I2C3_BUS); + /* EC */ + i2c_init(I2C2_BUS); + + lte_modem_init(); +} + +void mainboard_configure_pmc(void) +{ +} + +void mainboard_enable_vdd_cpu(void) +{ + /* VDD_CPU is already enabled in bootblock. */ +} diff --git a/src/mainboard/google/rush_ryu/sdram_configs.c b/src/mainboard/google/rush_ryu/sdram_configs.c new file mode 100644 index 0000000000..66978d3df4 --- /dev/null +++ b/src/mainboard/google/rush_ryu/sdram_configs.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static const struct sdram_params sdram_configs[] = { +#include "bct/sdram-samsung-4GB-924.inc" /* ram_code = 00 */ +#include "bct/sdram-hynix-4GB-924.inc" /* ram_code = 01 */ +#include "bct/sdram-micron-4GB-924.inc" /* ram_code = 10 */ +#include "bct/sdram-micron-4GB-528.inc" /* ram_code = 11 */ +}; + +const struct sdram_params *get_sdram_config() +{ + uint32_t ramcode = sdram_get_ram_code(); + + /* + * If we need to apply some special hacks to RAMCODE mapping (ex, by + * board_id), do that now. + */ + + ramcode &= 0x3; /* Only bits 1:0 used on Ryu */ + printk(BIOS_SPEW, "%s: RAMCODE=%d\n", __func__, ramcode); + + if (ramcode >= ARRAY_SIZE(sdram_configs) || + sdram_configs[ramcode].MemoryType == NvBootMemoryType_Unused) { + die("Invalid RAMCODE."); + } + + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/rush_ryu/verstage.c b/src/mainboard/google/rush_ryu/verstage.c new file mode 100644 index 0000000000..ed83f036b5 --- /dev/null +++ b/src/mainboard/google/rush_ryu/verstage.c @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "gpio.h" +#include "pmic.h" + +static const struct pad_config tpm_pads[] = { + PAD_CFG_SFIO(CAM_I2C_SCL, PINMUX_INPUT_ENABLE, I2C3), + PAD_CFG_SFIO(CAM_I2C_SDA, PINMUX_INPUT_ENABLE, I2C3), +}; + +static const struct pad_config ec_i2c_pads[] = { + PAD_CFG_SFIO(GEN2_I2C_SCL, PINMUX_OPEN_DRAIN|PINMUX_INPUT_ENABLE, I2C2), + PAD_CFG_SFIO(GEN2_I2C_SDA, PINMUX_OPEN_DRAIN|PINMUX_INPUT_ENABLE, I2C2), +}; + +static const struct funit_cfg funits[] = { + /* TPM on I2C3 @ 400kHz */ + FUNIT_CFG(I2C3, PLLP, 400, tpm_pads, ARRAY_SIZE(tpm_pads)), + /* EC on I2C2 - pulled to 3.3V @ 100kHz */ + FUNIT_CFG(I2C2, PLLP, 100, ec_i2c_pads, ARRAY_SIZE(ec_i2c_pads)), +}; + +void verstage_mainboard_init(void) +{ + soc_configure_funits(funits, ARRAY_SIZE(funits)); + + /* TPM */ + i2c_init(I2C3_BUS); + /* EC */ + i2c_init(I2C2_BUS); +} diff --git a/src/mainboard/google/samus/Kconfig b/src/mainboard/google/samus/Kconfig new file mode 100644 index 0000000000..7365883c6f --- /dev/null +++ b/src/mainboard/google/samus/Kconfig @@ -0,0 +1,53 @@ +if BOARD_GOOGLE_SAMUS + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select SOC_INTEL_BROADWELL + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VBOOT_EC_SLOW_UPDATE + select VBOOT_OPROM_MATTERS + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config VBOOT_REFCODE_INDEX + hex + default 0x4 + +config MAINBOARD_DIR + string + default google/samus + +config MAINBOARD_PART_NUMBER + string + default "Samus" + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/samus/Makefile.inc b/src/mainboard/google/samus/Makefile.inc new file mode 100644 index 0000000000..9bf6ff2a44 --- /dev/null +++ b/src/mainboard/google/samus/Makefile.inc @@ -0,0 +1,35 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2013 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-y += spd + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +romstage-y += pei_data.c +ramstage-y += pei_data.c + +romstage-y += board_version.c +ramstage-y += board_version.c + +romstage-$(CONFIG_PLATFORM_USES_FSP) += fsp.c diff --git a/src/mainboard/google/samus/acpi/chromeos.asl b/src/mainboard/google/samus/acpi/chromeos.asl new file mode 100644 index 0000000000..d490f60ce7 --- /dev/null +++ b/src/mainboard/google/samus/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name (OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "INT3437:00" }, // no recovery button + Package () { 0x0003, 1, 16, "INT3437:00" }, // firmware write protect +}) diff --git a/src/mainboard/google/samus/acpi/ec.asl b/src/mainboard/google/samus/acpi/ec.asl new file mode 100644 index 0000000000..d110e51311 --- /dev/null +++ b/src/mainboard/google/samus/acpi/ec.asl @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* Enable EC backed ALS device in ACPI */ +#define EC_ENABLE_ALS_DEVICE + +/* Enable EC backed PD MCU device in ACPI */ +#define EC_ENABLE_PD_MCU_DEVICE + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/google/samus/acpi/mainboard.asl b/src/mainboard/google/samus/acpi/mainboard.asl new file mode 100644 index 0000000000..4ade8e2912 --- /dev/null +++ b/src/mainboard/google/samus/acpi/mainboard.asl @@ -0,0 +1,335 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#undef ENABLE_TOUCH_WAKE + +Scope (\_SB) +{ + Device (LID0) + { + Name (_HID, EisaId("PNP0C0D")) + Method (_LID, 0) + { + Return (\_SB.PCI0.LPCB.EC0.LIDS) + } + + // EC wake is GPIO27 which is a special DeepSX wake pin + Name (_PRW, Package(){ 0x70, 5 }) // GP27_EN + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } + + // Keyboard Backlight interface via EC + Device (KBLT) { + Name (_HID, "GOOG0002") + Name (_UID, 1) + + // Read current backlight value + Method (KBQC, 0) + { + Return (\_SB.PCI0.LPCB.EC0.KBLV) + } + + // Write new backlight value + Method (KBCM, 1) + { + Store (Arg0, \_SB.PCI0.LPCB.EC0.KBLV) + } + } +} + +/* + * LPC Trusted Platform Module + */ +Scope (\_SB.PCI0.LPCB) +{ + #include +} + +/* + * WLAN connected to Root Port 3, becomes Root Port 1 after coalesce + */ +Scope (\_SB.PCI0.RP01) +{ + Device (WLAN) + { + Name (_ADR, 0x00000000) + + /* GPIO10 is PCH_WLAN_WAKE_L */ + Name (GPIO, 10) + + Name (_PRW, Package() { GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (^GPIO) + } + } + } +} + +Scope (\_SB.PCI0.I2C0) +{ + Device (ATPB) + { + Name (_HID, "ATML0000") + Name (_DDN, "Atmel Touchpad Bootloader") + Name (_UID, 1) + Name (_S0W, 4) + Name (ISTP, 1) /* Touchpad */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x26, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + + // GPIO13 is PIRQL + Interrupt (ResourceConsumer, Edge, ActiveLow) { 27 } + }) + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } + + Device (ATPA) + { + Name (_HID, "ATML0000") + Name (_DDN, "Atmel Touchpad") + Name (_UID, 2) + Name (_S0W, 4) + Name (ISTP, 1) /* Touchpad */ + Name (GPIO, 9) /* TRACKPAD_INT_L (WAKE) */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x4a, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + + // GPIO13 is PIRQL + Interrupt (ResourceConsumer, Edge, ActiveLow) { 27 } + }) + + Name (_PRW, Package() { GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (^GPIO) + } + } + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } + + Device (CODC) + { + /* + * TODO(kane): Need official HID. + * + */ + Name (_HID, "RT5677CE") + Name (_DDN, "RT5667 Codec") + Name (_UID, 1) + Name (WAKE, 45) /* DSP_INT (use as codec wake) */ + + Name (DCLK, 0) /* RT5677_DMIC_CLK1 */ + Name (PCLK, 1) /* RT5677_PDM_CLK_DIV2 (~3MHz) */ + Name (IN1, 1) /* IN1 differential */ + Name (IN2, 0) /* IN2 not differential */ + Name (OUT1, 1) /* LOUT1 differential */ + Name (OUT2, 1) /* LOUT2 differential */ + Name (OUT3, 0) /* LOUT3 differential */ + Name (ASRC, 1) /* Enable I2S1 ASRC */ + Name (JD1, 0) /* JackDetect1 is not used */ + Name (JD2, 2) /* Use GPIO5 as JackDetect2 */ + Name (JD3, 3) /* Use GPIO6 as JackDetect3 */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x2c, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C0", // ResourceSource + ) + + /* GPIO46 is PIRQO (use HOTWORD_DET as codec IRQ) */ + Interrupt (ResourceConsumer, Edge, ActiveHigh) { 30 } + + /* + * Codec GPIOs are 1-based in the schematic + * + * [0] = Jack Detect (INPUT) + * [1] = Mic Present (INPUT) + * [2] = Interrupt to the host (OUTPUT) + * [3] = Interrupt to the host (OUTPUT) + * [4] = Headphone amp control (OUTPUT) + */ + + /* Index 0: Jack Detect - PLUG_DET is GPIO5 */ + GpioIo (Exclusive, PullUp, , , IoRestrictionInputOnly, + "\\_SB.PCI0.I2C0.CODC") { 4 } + + /* Index 1: Mic Present - MIC_PRESENT_L is GPIO6 */ + GpioIo (Exclusive, PullUp, , , IoRestrictionInputOnly, + "\\_SB.PCI0.I2C0.CODC") { 5 } + + /* Index 2: Codec IRQ - HOTWORD_DET_L is GPIO1 */ + GpioIo (Exclusive, PullUp, , , IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C0.CODC") { 0 } + + /* Index 3: Codec Wake - DSP_INT is GPIO4 */ + GpioIo (Exclusive, PullUp, , , IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C0.CODC") { 3 } + + /* Index 4: Headphone amp - HP_AMP_SHDN_L is GPIO2 */ + GpioIo (Exclusive, PullDown, , , IoRestrictionOutputOnly, + "\\_SB.PCI0.I2C0.CODC") { 1 } + }) + + Name (_PRW, Package() { WAKE, 3 }) + + Method (_DSW, 3, NotSerialized) + { + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (^WAKE) + } + } + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } +} + +Scope (\_SB.PCI0.I2C1) +{ + Device (ATSB) + { + Name (_HID, "ATML0001") + Name (_DDN, "Atmel Touchscreen Bootloader") + Name (_UID, 4) + Name (_S0W, 4) + Name (ISTP, 0) /* TouchScreen */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x27, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C1", // ResourceSource + ) + + // GPIO14 is PIRQM + Interrupt (ResourceConsumer, Edge, ActiveLow) { 28 } + }) + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } + + Device (ATSA) + { + Name (_HID, "ATML0001") + Name (_DDN, "Atmel Touchscreen") + Name (_UID, 5) + Name (_S0W, 4) + Name (ISTP, 0) /* TouchScreen */ + Name (GPIO, 14) /* TOUCH_INT_L */ + + Name (_CRS, ResourceTemplate() + { + I2cSerialBus ( + 0x4b, // SlaveAddress + ControllerInitiated, // SlaveMode + 400000, // ConnectionSpeed + AddressingMode7Bit, // AddressingMode + "\\_SB.PCI0.I2C1", // ResourceSource + ) + + // GPIO14 is PIRQM + Interrupt (ResourceConsumer, Edge, ActiveLow) { 28 } + }) + +#ifdef ENABLE_TOUCH_WAKE + Name (_PRW, Package() { GPIO, 3 }) + + Method (_DSW, 3, NotSerialized) + { + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GPIO.GWAK (^GPIO) + } + } +#endif + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + } +} diff --git a/src/mainboard/google/samus/acpi/superio.asl b/src/mainboard/google/samus/acpi/superio.asl new file mode 100644 index 0000000000..92b8d76be9 --- /dev/null +++ b/src/mainboard/google/samus/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/samus/acpi/thermal.asl b/src/mainboard/google/samus/acpi/thermal.asl new file mode 100644 index 0000000000..c80ae8ed81 --- /dev/null +++ b/src/mainboard/google/samus/acpi/thermal.asl @@ -0,0 +1,123 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (TCHK, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + Method (_TMP, 0, Serialized) + { + // Get temperature from EC in deci-kelvin + Store (TCHK (), Local0) + + // Critical temperature in deci-kelvin + Store (CTOK (\TCRT), Local1) + + If (LGreaterEqual (Local0, Local1)) { + Store ("CRITICAL TEMPERATURE", Debug) + Store (Local0, Debug) + + // Wait 1 second for EC to re-poll + Sleep (1000) + + // Re-read temperature from EC + Store (TCHK (), Local0) + + Store ("RE-READ TEMPERATURE", Debug) + Store (Local0, Debug) + } + + Return (Local0) + } + } +} + diff --git a/src/mainboard/google/samus/acpi/video.asl b/src/mainboard/google/samus/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/samus/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/samus/acpi_tables.c b/src/mainboard/google/samus/acpi_tables.c new file mode 100644 index 0000000000..05e41200b4 --- /dev/null +++ b/src/mainboard/google/samus/acpi_tables.c @@ -0,0 +1,217 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thermal.h" + +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + + gnvs->tmps = TEMPERATURE_SENSOR_ID; + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + return acpi_madt_irq_overrides(current); +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/samus/board_version.c b/src/mainboard/google/samus/board_version.c new file mode 100644 index 0000000000..4575dd58bd --- /dev/null +++ b/src/mainboard/google/samus/board_version.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "board_version.h" + +const char *samus_board_version(void) +{ + switch (google_chromeec_get_board_version()) { + case SAMUS_EC_BOARD_VERSION_EVT1: + return "EVT1"; + case SAMUS_EC_BOARD_VERSION_EVT2: + return "EVT2"; + case SAMUS_EC_BOARD_VERSION_EVT3: + return "EVT3"; + case SAMUS_EC_BOARD_VERSION_EVT4: + return "EVT4"; + default: + return "Unknown"; + } +} diff --git a/src/mainboard/google/samus/board_version.h b/src/mainboard/google/samus/board_version.h new file mode 100644 index 0000000000..8b3fea38b0 --- /dev/null +++ b/src/mainboard/google/samus/board_version.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SAMUS_BOARD_VERSION_H +#define SAMUS_BOARD_VERSION_H + +#define SAMUS_EC_BOARD_VERSION_EVT1 3 +#define SAMUS_EC_BOARD_VERSION_EVT2 4 +#define SAMUS_EC_BOARD_VERSION_EVT3 5 +#define SAMUS_EC_BOARD_VERSION_EVT4 0 + +const char *samus_board_version(void); + +#endif diff --git a/src/mainboard/google/samus/chromeos.c b/src/mainboard/google/samus/chromeos.c new file mode 100644 index 0000000000..209969ad89 --- /dev/null +++ b/src/mainboard/google/samus/chromeos.c @@ -0,0 +1,105 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec.h" + +/* SPI Write protect is GPIO 16 */ +#define CROS_WP_GPIO 16 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, CROS_WP_GPIO, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return get_gpio(CROS_WP_GPIO); +} diff --git a/src/mainboard/google/samus/cmos.layout b/src/mainboard/google/samus/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/samus/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/samus/devicetree.cb b/src/mainboard/google/samus/devicetree.cb new file mode 100644 index 0000000000..26b7b4141a --- /dev/null +++ b/src/mainboard/google/samus/devicetree.cb @@ -0,0 +1,108 @@ +chip soc/intel/broadwell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Enable DDI1 Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Enable DDI2 Hotplug with 6ms pulse + register "gpu_dp_c_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "6" # 500ms + register "gpu_panel_power_up_delay" = "2000" # 200ms + register "gpu_panel_power_down_delay" = "500" # 50ms + register "gpu_panel_power_backlight_on_delay" = "2000" # 200ms + register "gpu_panel_power_backlight_off_delay" = "2000" # 200ms + + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "sata_port_map" = "0x1" + register "sio_acpi_mode" = "1" + + # Set I2C0 to 1.8V + register "sio_i2c0_voltage" = "1" + + # Force enable ASPM for PCIe Port 3 + register "pcie_port_force_aspm" = "0x04" + register "pcie_port_coalesce" = "1" + + # Disable PCIe CLKOUT 1-5 and CLKOUT_XDP + register "icc_clock_disable" = "0x013b0000" + + # Disable S0ix for now + register "s0ix_enable" = "0" + + device cpu_cluster 0 on + device lapic 0 on end + end + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + device pci 13.0 on end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 on end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 off end # High Definition Audio + device pci 1c.0 off end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 off end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip drivers/pc80/tpm + # Rising edge interrupt + register "irq_polarity" = "2" + device pnp 0c31.0 on + irq 0x70 = 10 + end + end + chip ec/google/chromeec + device pnp 0c09.0 on end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 off end # SMBus + device pci 1f.6 on end # Thermal + end +end diff --git a/src/mainboard/google/samus/dsdt.asl b/src/mainboard/google/samus/dsdt.asl new file mode 100644 index 0000000000..722e0c9c93 --- /dev/null +++ b/src/mainboard/google/samus/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include + + // Mainboard specific + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/google/samus/ec.c b/src/mainboard/google/samus/ec.c new file mode 100644 index 0000000000..e79ba38840 --- /dev/null +++ b/src/mainboard/google/samus/ec.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/samus/ec.h b/src/mainboard/google/samus/ec.h new file mode 100644 index 0000000000..1ba16777ce --- /dev/null +++ b/src/mainboard/google/samus/ec.h @@ -0,0 +1,66 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/samus/fadt.c b/src/mainboard/google/samus/fadt.c new file mode 100644 index 0000000000..d68a1ce657 --- /dev/null +++ b/src/mainboard/google/samus/fadt.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 5; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + acpi_fill_in_fadt(fadt); + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/samus/fsp.c b/src/mainboard/google/samus/fsp.c new file mode 100644 index 0000000000..3c10fb25c3 --- /dev/null +++ b/src/mainboard/google/samus/fsp.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include // hexdump +#include +#include +#include + +void board_fsp_memory_init_params( + struct romstage_params *params, + FSP_INFO_HEADER *fsp_header, + FSP_MEMORY_INIT_PARAMS *fsp_memory_init_params) +{ + FSP_INIT_RT_COMMON_BUFFER *rt_buffer; + UPD_DATA_REGION *upd_data; + + /* Set the memory configuration */ + rt_buffer = fsp_memory_init_params->RtBufferPtr; + upd_data = rt_buffer->UpdDataRgnPtr; + if (params->pei_data->spd_data[0][0][0] != 0) { + upd_data->SpdDataBuffer_0_0 = + (UINT32)(¶ms->pei_data->spd_data[0][0]); + upd_data->SpdDataBuffer_1_0 = + (UINT32)(¶ms->pei_data->spd_data[1][0]); + printk(BIOS_SPEW, "0x%08x: SpdDataBuffer_0_0\n", + upd_data->SpdDataBuffer_0_0); + printk(BIOS_SPEW, "0x%08x: SpdDataBuffer_0_1\n", + upd_data->SpdDataBuffer_0_1); + printk(BIOS_SPEW, "0x%08x: SpdDataBuffer_1_0\n", + upd_data->SpdDataBuffer_0_0); + printk(BIOS_SPEW, "0x%08x: SpdDataBuffer_1_1\n", + upd_data->SpdDataBuffer_0_1); + } + + /* Enable/disable the devices */ + upd_data->PcdEnableLan = 0; +} + diff --git a/src/mainboard/google/samus/gpio.h b/src/mainboard/google/samus/gpio.h new file mode 100644 index 0000000000..c9795a294c --- /dev/null +++ b/src/mainboard/google/samus/gpio.h @@ -0,0 +1,129 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_GPIO_H +#define MAINBOARD_GPIO_H + +#include + +#define SAMUS_GPIO_PP3300_AUTOBAHN_EN 23 +#define SAMUS_GPIO_SSD_RESET_L 47 +#define SAMUS_GPIO_WLAN_DISABLE_L 42 +#define SAMUS_GPIO_LTE_DISABLE_L 59 + +static const struct gpio_config mainboard_gpio_config[] = { + PCH_GPIO_UNUSED, /* 0: UNUSED */ + PCH_GPIO_UNUSED, /* 1: UNUSED */ + PCH_GPIO_UNUSED, /* 2: UNUSED */ + PCH_GPIO_UNUSED, /* 3: UNUSED */ + PCH_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + PCH_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + PCH_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + PCH_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + PCH_GPIO_ACPI_SCI, /* 8: PCH_LTE_WAKE_L */ + PCH_GPIO_INPUT_INVERT, /* 9: TRACKPAD_INT_L (WAKE) */ + PCH_GPIO_ACPI_SCI, /* 10: PCH_WLAN_WAKE_L */ + PCH_GPIO_UNUSED, /* 11: UNUSED */ + PCH_GPIO_UNUSED, /* 12: UNUSED */ + PCH_GPIO_PIRQ, /* 13: TRACKPAD_INT_L (PIRQL) */ + PCH_GPIO_PIRQ, /* 14: TOUCH_INT_L (PIRQM) */ + PCH_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + PCH_GPIO_INPUT, /* 16: PCH_WP */ + PCH_GPIO_UNUSED, /* 17: UNUSED */ + PCH_GPIO_UNUSED, /* 18: UNUSED */ + PCH_GPIO_UNUSED, /* 19: UNUSED */ + PCH_GPIO_NATIVE, /* 20: PCIE_WLAN_CLKREQ_L */ + PCH_GPIO_OUT_HIGH, /* 21: PP3300_SSD_EN */ + PCH_GPIO_UNUSED, /* 22: UNUSED */ + PCH_GPIO_OUT_LOW, /* 23: PP3300_AUTOBAHN_EN */ + PCH_GPIO_UNUSED, /* 24: UNUSED */ + PCH_GPIO_INPUT, /* 25: EC_IN_RW */ + PCH_GPIO_UNUSED, /* 26: UNUSED */ + PCH_GPIO_ACPI_SCI, /* 27: PCH_WAKE_L */ + PCH_GPIO_UNUSED, /* 28: UNUSED */ + PCH_GPIO_UNUSED, /* 29: UNUSED */ + PCH_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + PCH_GPIO_NATIVE, /* 31: NATIVE: ACOK_BUF */ + PCH_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + PCH_GPIO_NATIVE, /* 33: NATIVE: SSD_DEVSLP */ + PCH_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + PCH_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + PCH_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + PCH_GPIO_UNUSED, /* 37: UNUSED */ + PCH_GPIO_UNUSED, /* 38: UNUSED */ + PCH_GPIO_UNUSED, /* 39: UNUSED */ + PCH_GPIO_NATIVE, /* 40: NATIVE: PCH_USB1_OC_L */ + PCH_GPIO_NATIVE, /* 41: NATIVE: PCH_USB2_OC_L */ + PCH_GPIO_UNUSED, /* 42: WLAN_DISABLE_L */ + PCH_GPIO_OUT_HIGH, /* 43: PP1800_CODEC_EN */ + PCH_GPIO_UNUSED, /* 44: UNUSED */ + PCH_GPIO_ACPI_SCI, /* 45: DSP_INT - Codec Wake */ + PCH_GPIO_PIRQ, /* 46: HOTWORD_DET_L_3V3 (PIRQO) - Codec IRQ */ + PCH_GPIO_OUT_LOW, /* 47: SSD_RESET_L */ + PCH_GPIO_UNUSED, /* 48: UNUSED */ + PCH_GPIO_UNUSED, /* 49: UNUSED */ + PCH_GPIO_UNUSED, /* 50: UNUSED */ + PCH_GPIO_UNUSED, /* 51: UNUSED */ + PCH_GPIO_INPUT, /* 52: SIM_DET */ + PCH_GPIO_UNUSED, /* 53: UNUSED */ + PCH_GPIO_UNUSED, /* 54: UNUSED */ + PCH_GPIO_UNUSED, /* 55: UNUSED */ + PCH_GPIO_UNUSED, /* 56: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 57: CODEC_RESET_L */ + PCH_GPIO_UNUSED, /* 58: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + PCH_GPIO_UNUSED, /* 60: UNUSED */ + PCH_GPIO_NATIVE, /* 61: NATIVE: PCH_SUS_STAT */ + PCH_GPIO_NATIVE, /* 62: NATIVE: PCH_SUSCLK */ + PCH_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + PCH_GPIO_UNUSED, /* 64: UNUSED */ + PCH_GPIO_INPUT, /* 65: RAM_ID3 */ + PCH_GPIO_INPUT, /* 66: RAM_ID3_OLD (STRAP) */ + PCH_GPIO_INPUT, /* 67: RAM_ID0 */ + PCH_GPIO_INPUT, /* 68: RAM_ID1 */ + PCH_GPIO_INPUT, /* 69: RAM_ID2 */ + PCH_GPIO_UNUSED, /* 70: UNUSED */ + PCH_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + PCH_GPIO_UNUSED, /* 72: UNUSED */ + PCH_GPIO_UNUSED, /* 73: UNUSED */ + PCH_GPIO_UNUSED, /* 74: UNUSED */ + PCH_GPIO_UNUSED, /* 75: UNUSED */ + PCH_GPIO_UNUSED, /* 76: UNUSED */ + PCH_GPIO_UNUSED, /* 77: UNUSED */ + PCH_GPIO_UNUSED, /* 78: UNUSED */ + PCH_GPIO_UNUSED, /* 79: UNUSED */ + PCH_GPIO_UNUSED, /* 80: UNUSED */ + PCH_GPIO_UNUSED, /* 81: UNUSED */ + PCH_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + PCH_GPIO_NATIVE, /* 83: GSPI0_CS */ + PCH_GPIO_NATIVE, /* 84: GSPI0_CLK */ + PCH_GPIO_NATIVE, /* 85: GSPI0_MISO */ + PCH_GPIO_NATIVE, /* 86: GSPI0_MOSI (STRAP) */ + PCH_GPIO_UNUSED, /* 87: UNUSED */ + PCH_GPIO_UNUSED, /* 88: UNUSED */ + PCH_GPIO_OUT_HIGH, /* 89: PP3300_SD_EN */ + PCH_GPIO_UNUSED, /* 90: UNUSED */ + PCH_GPIO_UNUSED, /* 91: UNUSED */ + PCH_GPIO_UNUSED, /* 92: UNUSED */ + PCH_GPIO_UNUSED, /* 93: UNUSED */ + PCH_GPIO_UNUSED, /* 94: UNUSED */ + PCH_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/samus/mainboard.c b/src/mainboard/google/samus/mainboard.c new file mode 100644 index 0000000000..734e8e756a --- /dev/null +++ b/src/mainboard/google/samus/mainboard.c @@ -0,0 +1,101 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "board_version.h" +#include "ec.h" + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = RESERVED + * bit 2 = EFP + * bit 3 = LFP + * bit 4 = RESERVED + * bit 5 = EFP3 + * bit 6 = EFP2 + * bit 7 = RESERVED + */ + X86_AX = 0x005f; + X86_CX = 0x0008; + res = 1; + break; + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +void mainboard_suspend_resume(void) +{ +} + +const char *smbios_mainboard_version(void) +{ + return samus_board_version(); +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; diff --git a/src/mainboard/google/samus/pei_data.c b/src/mainboard/google/samus/pei_data.c new file mode 100644 index 0000000000..6f98a4b6c4 --- /dev/null +++ b/src/mainboard/google/samus/pei_data.c @@ -0,0 +1,81 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + /* DQ byte map for Samus board */ + const u8 dq_map[2][6][2] = { + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } }, + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } }; + /* DQS CPU<>DRAM map for Samus board */ + const u8 dqs_map[2][8] = { + { 2, 0, 1, 3, 6, 4, 7, 5 }, + { 2, 1, 0, 3, 6, 5, 4, 7 } }; + + pei_data->ec_present = 1; + + /* One installed DIMM per channel */ + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + + memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); + memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); + + /* P0: HOST PORT */ + pei_data_usb2_port(pei_data, 0, 0x0080, 1, 0, + USB_PORT_BACK_PANEL); + /* P1: HOST PORT */ + pei_data_usb2_port(pei_data, 1, 0x0080, 1, 1, + USB_PORT_BACK_PANEL); + /* P2: RAIDEN */ + pei_data_usb2_port(pei_data, 2, 0x0080, 1, USB_OC_PIN_SKIP, + USB_PORT_BACK_PANEL); + /* P3: SD CARD */ + pei_data_usb2_port(pei_data, 3, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P4: RAIDEN */ + pei_data_usb2_port(pei_data, 4, 0x0080, 1, USB_OC_PIN_SKIP, + USB_PORT_BACK_PANEL); + /* P5: WWAN (Disabled) */ + pei_data_usb2_port(pei_data, 5, 0x0000, 0, USB_OC_PIN_SKIP, + USB_PORT_SKIP); + /* P6: CAMERA */ + pei_data_usb2_port(pei_data, 6, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + /* P7: BT */ + pei_data_usb2_port(pei_data, 7, 0x0040, 1, USB_OC_PIN_SKIP, + USB_PORT_INTERNAL); + + /* P1: HOST PORT */ + pei_data_usb3_port(pei_data, 0, 1, 0, 0); + /* P2: HOST PORT */ + pei_data_usb3_port(pei_data, 1, 1, 1, 0); + /* P3: RAIDEN */ + pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0); + /* P4: RAIDEN */ + pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0); +} diff --git a/src/mainboard/google/samus/romstage.c b/src/mainboard/google/samus/romstage.c new file mode 100644 index 0000000000..1692b74790 --- /dev/null +++ b/src/mainboard/google/samus/romstage.c @@ -0,0 +1,71 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "board_version.h" + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct pei_data pei_data; + + post_code(0x31); + + if (rp->power_state->prev_sleep_state != SLEEP_STATE_S3) + google_chromeec_kbbacklight(100); + + printk(BIOS_INFO, "MLB: board version %s\n", samus_board_version()); + + /* Ensure the EC and PD are in the right mode for recovery */ + google_chromeec_early_pd_init(); + google_chromeec_early_init(); + + /* Initialize GPIOs */ + init_gpios(mainboard_gpio_config); + + /* Fill out PEI DATA */ + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + mainboard_fill_spd_data(&pei_data); + rp->pei_data = &pei_data; + + /* Initliaze memory */ + romstage_common(rp); + + /* Bring SSD out of reset */ + set_gpio(SAMUS_GPIO_SSD_RESET_L, GPIO_OUT_HIGH); + + /* + * Enable PP3300_AUTOBAHN_EN after initial GPIO setup + * to prevent possible brownout. + */ + set_gpio(SAMUS_GPIO_PP3300_AUTOBAHN_EN, GPIO_OUT_HIGH); +} diff --git a/src/mainboard/google/samus/smihandler.c b/src/mainboard/google/samus/smihandler.c new file mode 100644 index 0000000000..77f35a6277 --- /dev/null +++ b/src/mainboard/google/samus/smihandler.c @@ -0,0 +1,158 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ec.h" +#include "gpio.h" + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) { + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + } + + /* Put SSD in reset to prevent leak. */ + set_gpio(SAMUS_GPIO_SSD_RESET_L, 0); + /* Prevent leak from standby rail to WLAN rail in S3. */ + set_gpio(SAMUS_GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + set_gpio(SAMUS_GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) { + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + } + + /* Put SSD in reset to prevent leak. */ + set_gpio(SAMUS_GPIO_SSD_RESET_L, 0); + /* Prevent leak from standby rail to WLAN rail in S5. */ + set_gpio(SAMUS_GPIO_WLAN_DISABLE_L, 0); + /* Disable LTE */ + set_gpio(SAMUS_GPIO_LTE_DISABLE_L, 0); + + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); +} + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/samus/spd/Makefile.inc b/src/mainboard/google/samus/spd/Makefile.inc new file mode 100644 index 0000000000..f51434a406 --- /dev/null +++ b/src/mainboard/google/samus/spd/Makefile.inc @@ -0,0 +1,54 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-y += spd.c + +SPD_BIN = $(obj)/spd.bin + +# { GPIO65, GPIO67, GPIO68, GPIO69 } +SPD_SOURCES = empty # 0b0000 +SPD_SOURCES += empty # 0b0001 +SPD_SOURCES += empty # 0b0010 +SPD_SOURCES += empty # 0b0011 +SPD_SOURCES += empty # 0b0100 +SPD_SOURCES += empty # 0b0101 +SPD_SOURCES += samsung_4 # 0b0110 +SPD_SOURCES += empty # 0b0111 +SPD_SOURCES += hynix_4 # 0b1000 +SPD_SOURCES += empty # 0b1001 +SPD_SOURCES += samsung_8 # 0b1010 +SPD_SOURCES += empty # 0b1011 +SPD_SOURCES += hynix_8 # 0b1100 +SPD_SOURCES += hynix_16 # 0b1101 +SPD_SOURCES += empty # 0b1110 +SPD_SOURCES += elpida_16 # 0b1111 + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/spd/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab diff --git a/src/mainboard/google/samus/spd/elpida_16.spd.hex b/src/mainboard/google/samus/spd/elpida_16.spd.hex new file mode 100644 index 0000000000..5594164816 --- /dev/null +++ b/src/mainboard/google/samus/spd/elpida_16.spd.hex @@ -0,0 +1,18 @@ +# Elpida EDFB232A1MA +# banks 8, ranks 2, rows 15, columns 11, density 8192 Mb, x16 +91 20 F1 03 05 1A 05 0A 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 90 06 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 +45 44 46 42 32 33 32 41 31 4D 41 2D 47 44 2D 46 +00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/elpida_4.spd.hex b/src/mainboard/google/samus/spd/elpida_4.spd.hex new file mode 100644 index 0000000000..e73ba6201c --- /dev/null +++ b/src/mainboard/google/samus/spd/elpida_4.spd.hex @@ -0,0 +1,16 @@ +92 11 F1 03 04 11 02 0B 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 +45 44 46 38 31 33 32 41 33 4D 41 2D 47 44 2D 46 +20 20 32 2E 30 20 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/elpida_8.spd.hex b/src/mainboard/google/samus/spd/elpida_8.spd.hex new file mode 100644 index 0000000000..b790943fdc --- /dev/null +++ b/src/mainboard/google/samus/spd/elpida_8.spd.hex @@ -0,0 +1,16 @@ +92 11 F1 03 04 12 02 0A 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 02 FE 00 00 00 00 00 00 00 00 00 +45 44 46 41 32 33 32 41 32 4D 41 2D 47 44 2D 46 +20 20 32 2E 30 20 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/empty.spd.hex b/src/mainboard/google/samus/spd/empty.spd.hex new file mode 100644 index 0000000000..9ec39f1ba4 --- /dev/null +++ b/src/mainboard/google/samus/spd/empty.spd.hex @@ -0,0 +1,16 @@ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/hynix_16.spd.hex b/src/mainboard/google/samus/spd/hynix_16.spd.hex new file mode 100644 index 0000000000..a03d4ed464 --- /dev/null +++ b/src/mainboard/google/samus/spd/hynix_16.spd.hex @@ -0,0 +1,18 @@ +# Hynix H9CCNNNCLTMLAR LPDDR3 +# banks 8, ranks 2, rows 15, columns 11, density 8192 Mb, x16 +91 20 F1 03 05 1A 05 0A 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 90 06 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 00 00 00 55 00 00 00 00 00 +48 39 43 43 4E 4E 4E 43 4C 54 4D 4C 41 52 00 00 +00 00 00 00 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/hynix_4.spd.hex b/src/mainboard/google/samus/spd/hynix_4.spd.hex new file mode 100644 index 0000000000..93e65a70dd --- /dev/null +++ b/src/mainboard/google/samus/spd/hynix_4.spd.hex @@ -0,0 +1,18 @@ +# Hynix H9CCNNNBLTMLAR-NTM LPDDR3 +# banks 8, ranks 2, rows 14, columns 10, density 4096 Mb, x32 +91 20 F1 03 04 11 05 0B 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 10 04 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 00 00 00 55 00 00 00 00 00 +48 39 43 43 4E 4E 4E 42 4C 54 4D 4C 41 52 2D 4E +54 4D 00 00 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/hynix_8.spd.hex b/src/mainboard/google/samus/spd/hynix_8.spd.hex new file mode 100644 index 0000000000..15737e443a --- /dev/null +++ b/src/mainboard/google/samus/spd/hynix_8.spd.hex @@ -0,0 +1,18 @@ +# Hynix H9CCNNNBLTMLAR-NTM LPDDR3 +# banks 8, ranks 2, rows 14, columns 11, density 4096 Mb, x16 +91 20 F1 03 04 12 05 0A 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 10 04 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 00 00 00 55 00 00 00 00 00 +48 39 43 43 4E 4E 4E 42 4C 54 4D 4C 41 52 2D 4E +54 4D 00 00 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/samsung_4.spd.hex b/src/mainboard/google/samus/spd/samsung_4.spd.hex new file mode 100644 index 0000000000..4b82a3a6c7 --- /dev/null +++ b/src/mainboard/google/samus/spd/samsung_4.spd.hex @@ -0,0 +1,16 @@ +91 20 F1 03 04 11 05 0B 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 10 04 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 CE 01 00 00 55 00 00 00 00 00 +4B 34 45 38 45 33 30 34 45 44 2D 45 47 43 45 20 +20 20 00 00 80 CE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/samsung_8.spd.hex b/src/mainboard/google/samus/spd/samsung_8.spd.hex new file mode 100644 index 0000000000..c0a8fca4ea --- /dev/null +++ b/src/mainboard/google/samus/spd/samsung_8.spd.hex @@ -0,0 +1,16 @@ +91 20 F1 03 04 12 05 0A 03 11 01 08 0A 00 50 01 +78 78 90 50 90 11 50 E0 10 04 3C 3C 01 90 00 00 +00 80 00 00 00 00 00 A8 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 CE 01 00 00 55 00 00 00 00 00 +4B 34 45 36 45 33 30 34 45 44 2D 45 47 43 45 20 +20 20 00 00 80 CE 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/src/mainboard/google/samus/spd/spd.c b/src/mainboard/google/samus/spd/spd.c new file mode 100644 index 0000000000..4f4f9efac9 --- /dev/null +++ b/src/mainboard/google/samus/spd/spd.c @@ -0,0 +1,134 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void mainboard_print_spd_info(uint8_t spd[]) +{ + const int spd_banks[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; + const int spd_capmb[8] = { 1, 2, 4, 8, 16, 32, 64, 0 }; + const int spd_rows[8] = { 12, 13, 14, 15, 16, -1, -1, -1 }; + const int spd_cols[8] = { 9, 10, 11, 12, -1, -1, -1, -1 }; + const int spd_ranks[8] = { 1, 2, 3, 4, -1, -1, -1, -1 }; + const int spd_devw[8] = { 4, 8, 16, 32, -1, -1, -1, -1 }; + const int spd_busw[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; + char spd_name[SPD_PART_LEN+1] = { 0 }; + + int banks = spd_banks[(spd[SPD_DENSITY_BANKS] >> 4) & 7]; + int capmb = spd_capmb[spd[SPD_DENSITY_BANKS] & 7] * 256; + int rows = spd_rows[(spd[SPD_ADDRESSING] >> 3) & 7]; + int cols = spd_cols[spd[SPD_ADDRESSING] & 7]; + int ranks = spd_ranks[(spd[SPD_ORGANIZATION] >> 3) & 7]; + int devw = spd_devw[spd[SPD_ORGANIZATION] & 7]; + int busw = spd_busw[spd[SPD_BUS_DEV_WIDTH] & 7]; + + /* Module type */ + printk(BIOS_INFO, "SPD: module type is "); + switch (spd[SPD_DRAM_TYPE]) { + case SPD_DRAM_DDR3: + printk(BIOS_INFO, "DDR3\n"); + break; + case SPD_DRAM_LPDDR3: + printk(BIOS_INFO, "LPDDR3\n"); + break; + default: + printk(BIOS_INFO, "Unknown (%02x)\n", spd[SPD_DRAM_TYPE]); + break; + } + + /* Module Part Number */ + memcpy(spd_name, &spd[SPD_PART_OFF], SPD_PART_LEN); + spd_name[SPD_PART_LEN] = 0; + printk(BIOS_INFO, "SPD: module part is %s\n", spd_name); + + printk(BIOS_INFO, "SPD: banks %d, ranks %d, rows %d, columns %d, " + "density %d Mb\n", banks, ranks, rows, cols, capmb); + printk(BIOS_INFO, "SPD: device width %d bits, bus width %d bits\n", + devw, busw); + + if (capmb > 0 && busw > 0 && devw > 0 && ranks > 0) { + /* SIZE = DENSITY / 8 * BUS_WIDTH / SDRAM_WIDTH * RANKS */ + printk(BIOS_INFO, "SPD: module size is %u MB (per channel)\n", + capmb / 8 * busw / devw * ranks); + } +} + +/* Copy SPD data for on-board memory */ +void mainboard_fill_spd_data(struct pei_data *pei_data) +{ + int spd_bits[4] = { + SPD_GPIO_BIT0, + SPD_GPIO_BIT1, + SPD_GPIO_BIT2, + SPD_GPIO_BIT3 + }; + int spd_gpio[4]; + int spd_index; + int spd_file_len; + struct cbfs_file *spd_file; + + spd_gpio[0] = get_gpio(spd_bits[0]); + spd_gpio[1] = get_gpio(spd_bits[1]); + spd_gpio[2] = get_gpio(spd_bits[2]); + spd_gpio[3] = get_gpio(spd_bits[3]); + + spd_index = (spd_gpio[3] << 3) | (spd_gpio[2] << 2) | + (spd_gpio[1] << 1) | spd_gpio[0]; + + printk(BIOS_DEBUG, "SPD: index %d (GPIO%d=%d GPIO%d=%d " + "GPIO%d=%d GPIO%d=%d)\n", spd_index, + spd_bits[3], spd_gpio[3], spd_bits[2], spd_gpio[2], + spd_bits[1], spd_gpio[1], spd_bits[0], spd_gpio[0]); + + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + spd_file_len = ntohl(spd_file->len); + + if (spd_file_len < ((spd_index + 1) * SPD_LEN)) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file_len < SPD_LEN) + die("Missing SPD data."); + + /* Assume same memory in both channels */ + spd_index *= SPD_LEN; + memcpy(pei_data->spd_data[0][0], + ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); + memcpy(pei_data->spd_data[1][0], + ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); + + /* Make sure a valid SPD was found */ + if (pei_data->spd_data[0][0][0] == 0) + die("Invalid SPD data."); + + mainboard_print_spd_info(pei_data->spd_data[0][0]); +} diff --git a/src/mainboard/google/samus/spd/spd.h b/src/mainboard/google/samus/spd/spd.h new file mode 100644 index 0000000000..27d14691b7 --- /dev/null +++ b/src/mainboard/google/samus/spd/spd.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_SPD_H +#define MAINBOARD_SPD_H + +#define SPD_LEN 256 + +#define SPD_DRAM_TYPE 2 +#define SPD_DRAM_DDR3 0x0b +#define SPD_DRAM_LPDDR3 0xf1 +#define SPD_DENSITY_BANKS 4 +#define SPD_ADDRESSING 5 +#define SPD_ORGANIZATION 7 +#define SPD_BUS_DEV_WIDTH 8 +#define SPD_PART_OFF 128 +#define SPD_PART_LEN 18 + +/* Samus board memory configuration GPIOs */ +#define SPD_GPIO_BIT0 69 +#define SPD_GPIO_BIT1 68 +#define SPD_GPIO_BIT2 67 +#define SPD_GPIO_BIT3 65 + +struct pei_data; +void mainboard_fill_spd_data(struct pei_data *pei_data); + +#endif diff --git a/src/mainboard/google/samus/thermal.h b/src/mainboard/google/samus/thermal.h new file mode 100644 index 0000000000..2e3f450535 --- /dev/null +++ b/src/mainboard/google/samus/thermal.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +#define TEMPERATURE_SENSOR_ID 0 /* PECI */ + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 104 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 95 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 105 + +#endif diff --git a/src/mainboard/google/slippy/Hynix_HMT425S6AFR6A.spd.hex b/src/mainboard/google/slippy/Hynix_HMT425S6AFR6A.spd.hex new file mode 100644 index 0000000000..7b0932743d --- /dev/null +++ b/src/mainboard/google/slippy/Hynix_HMT425S6AFR6A.spd.hex @@ -0,0 +1,17 @@ +# Hynix HMT425S6AFR6A-PBA +92 12 0B 03 04 19 02 02 03 52 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 01 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 11 62 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 AD 01 00 00 00 00 00 00 FF AB +48 4D 54 34 32 35 53 36 41 46 52 36 41 2D 50 42 +20 20 4E 30 80 AD 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/slippy/Kconfig b/src/mainboard/google/slippy/Kconfig new file mode 100644 index 0000000000..d8d840b4aa --- /dev/null +++ b/src/mainboard/google/slippy/Kconfig @@ -0,0 +1,55 @@ +if BOARD_GOOGLE_SLIPPY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select CPU_INTEL_SOCKET_RPGA989 + select NORTHBRIDGE_INTEL_HASWELL + select SOUTHBRIDGE_INTEL_LYNXPOINT + select INTEL_LYNXPOINT_LP + select BOARD_ROMSIZE_KB_8192 + select EC_GOOGLE_CHROMEEC + select EC_SOFTWARE_SYNC + select VIRTUAL_DEV_SWITCH + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select INTEL_DP + select INTEL_DDI + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config MAINBOARD_DIR + string + default google/slippy + +config MAINBOARD_PART_NUMBER + string + default "Slippy" + +config MMCONF_BASE_ADDRESS + hex + default 0xf0000000 + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 8 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/google/slippy/Makefile.inc b/src/mainboard/google/slippy/Makefile.inc new file mode 100644 index 0000000000..6e3ddb6e32 --- /dev/null +++ b/src/mainboard/google/slippy/Makefile.inc @@ -0,0 +1,47 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-$(CONFIG_EC_GOOGLE_CHROMEEC) += ec.c + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +## DIMM SPD for on-board memory +SPD_BIN = $(obj)/spd.bin + +# Order of names in SPD_SOURCES is important! +SPD_SOURCES = Micron_4KTF25664HZ +SPD_SOURCES += Hynix_HMT425S6AFR6A + +SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/$(f).spd.hex) + +# Include spd rom data +$(SPD_BIN): $(SPD_DEPS) + for f in $+; \ + do for c in $$(cat $$f | grep -v ^#); \ + do echo -e -n "\\x$$c"; \ + done; \ + done > $@ + +cbfs-files-y += spd.bin +spd.bin-file := $(SPD_BIN) +spd.bin-type := 0xab +spd.bin-position := 0xfffec000 diff --git a/src/mainboard/google/slippy/Micron_4KTF25664HZ.spd.hex b/src/mainboard/google/slippy/Micron_4KTF25664HZ.spd.hex new file mode 100644 index 0000000000..cbe9e4fbfe --- /dev/null +++ b/src/mainboard/google/slippy/Micron_4KTF25664HZ.spd.hex @@ -0,0 +1,17 @@ +# Micron 4KTF25664HZ-1G6E1 +92 11 0B 03 04 19 02 02 03 11 01 08 0A 00 FE 00 +69 78 69 3C 69 11 18 81 20 08 3C 3C 01 40 83 05 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 0F 01 02 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 80 2C 00 00 00 00 00 00 00 AD 75 +34 4B 54 46 32 35 36 36 34 48 5A 2D 31 47 36 45 +31 20 45 31 80 2C 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF diff --git a/src/mainboard/google/slippy/acpi/chromeos.asl b/src/mainboard/google/slippy/acpi/chromeos.asl new file mode 100644 index 0000000000..4e9035be3b --- /dev/null +++ b/src/mainboard/google/slippy/acpi/chromeos.asl @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "LynxPoint" }, // no recovery button + Package () { 0x0003, 1, 58, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/google/slippy/acpi/ec.asl b/src/mainboard/google/slippy/acpi/ec.asl new file mode 100644 index 0000000000..c5f45d9326 --- /dev/null +++ b/src/mainboard/google/slippy/acpi/ec.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +/* ACPI code for EC functions */ +#include diff --git a/src/mainboard/google/slippy/acpi/haswell_pci_irqs.asl b/src/mainboard/google/slippy/acpi/haswell_pci_irqs.asl new file mode 100644 index 0000000000..7ebd8e582e --- /dev/null +++ b/src/mainboard/google/slippy/acpi/haswell_pci_irqs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for IvyBridge */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/mainboard/google/slippy/acpi/mainboard.asl b/src/mainboard/google/slippy/acpi/mainboard.asl new file mode 100644 index 0000000000..130df62196 --- /dev/null +++ b/src/mainboard/google/slippy/acpi/mainboard.asl @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include + +Scope (\_SB) +{ + Device (LID0) + { + Name(_HID, EisaId("PNP0C0D")) + Method(_LID, 0) + { + Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS) + Return (\LIDS) + } + } + + Device (PWRB) + { + Name(_HID, EisaId("PNP0C0C")) + } + + Device (TPAD) + { + Name (_ADR, 0x0) + Name (_UID, 1) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TRACKPAD_IRQ + } + + VendorShort (ADDR) + { + BOARD_TRACKPAD_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TRACKPAD_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } + + Device (TSCR) + { + Name (_ADR, 0x0) + Name (_UID, 2) + + // Report as a Sleep Button device so Linux will + // automatically enable it as a wake source + Name (_HID, EisaId("PNP0C0E")) + + Name (_CRS, ResourceTemplate() + { + Interrupt (ResourceConsumer, Edge, ActiveLow) + { + BOARD_TOUCHSCREEN_IRQ + } + + VendorShort (ADDR) + { + BOARD_TOUCHSCREEN_I2C_ADDR + } + }) + + Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 }) + + Method (_DSW, 3, NotSerialized) + { + Store (BOARD_TOUCHSCREEN_WAKE_GPIO, Local0) + + If (LEqual (Arg0, 1)) { + // Enable GPIO as wake source + \_SB.PCI0.LPCB.GWAK (Local0) + } + } + } +} diff --git a/src/mainboard/google/slippy/acpi/platform.asl b/src/mainboard/google/slippy/acpi/platform.asl new file mode 100644 index 0000000000..208d76a0e9 --- /dev/null +++ b/src/mainboard/google/slippy/acpi/platform.asl @@ -0,0 +1,86 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + /* Update AC status */ + Store (\_SB.PCI0.LPCB.EC0.ACEX, Local0) + if (LNotEqual (Local0, \PWRS)) { + Store (Local0, \PWRS) + Notify (\_SB.PCI0.LPCB.EC0.AC, 0x80) + } + + /* Update LID status */ + Store (\_SB.PCI0.LPCB.EC0.LIDS, Local0) + if (LNotEqual (Local0, \LIDS)) { + Store (Local0, \LIDS) + Notify (\_SB.LID0, 0x80) + } + + Return(Package(){0,0}) +} diff --git a/src/mainboard/google/slippy/acpi/superio.asl b/src/mainboard/google/slippy/acpi/superio.asl new file mode 100644 index 0000000000..a83f23e1ab --- /dev/null +++ b/src/mainboard/google/slippy/acpi/superio.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mainboard configuration */ +#include + +#define SIO_EC_MEMMAP_ENABLE // EC Memory Map Resources +#define SIO_EC_HOST_ENABLE // EC Host Interface Resources +#define SIO_EC_ENABLE_PS2K // Enable PS/2 Keyboard +#define SIO_EC_ENABLE_COM1 // Enable Serial Port 1 + +/* ACPI code for EC SuperIO functions */ +#include diff --git a/src/mainboard/google/slippy/acpi/thermal.asl b/src/mainboard/google/slippy/acpi/thermal.asl new file mode 100644 index 0000000000..69b6ac9834 --- /dev/null +++ b/src/mainboard/google/slippy/acpi/thermal.asl @@ -0,0 +1,173 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 10 seconds + Name (_TZP, 100) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (_TMP, 0, Serialized) + { + // Get Temperature from TIN# set in NVS + Store (\_SB.PCI0.LPCB.EC0.TINS (TMPS), Local0) + + // Check for sensor not calibrated + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNCA)) { + Return (CTOK(0)) + } + + // Check for sensor not present + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNPR)) { + Return (CTOK(0)) + } + + // Check for sensor not powered + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TNOP)) { + Return (CTOK(0)) + } + + // Check for sensor bad reading + If (LEqual (Local0, \_SB.PCI0.LPCB.EC0.TBAD)) { + Return (CTOK(0)) + } + + // Adjust by offset to get Kelvin + Add (\_SB.PCI0.LPCB.EC0.TOFS, Local0, Local0) + + // Convert to 1/10 Kelvin + Multiply (Local0, 10, Local0) + Return (Local0) + } + + /* CTDP Down */ + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (\F0OF)) + } Else { + Return (CTOK (\F0ON)) + } + } + + /* CTDP Nominal */ + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (\F1OF)) + } Else { + Return (CTOK (\F1ON)) + } + } + + Name (_AL0, Package () { TDP0 }) + Name (_AL1, Package () { TDP1 }) + + PowerResource (TNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + \_SB.PCI0.MCHC.STND () + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + \_SB.PCI0.MCHC.STDN () + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (TNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (TDP0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { TNP0 }) + } + + Device (TDP1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { TNP1 }) + } + } +} + diff --git a/src/mainboard/google/slippy/acpi/video.asl b/src/mainboard/google/slippy/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/google/slippy/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/google/slippy/acpi_tables.c b/src/mainboard/google/slippy/acpi_tables.c new file mode 100644 index 0000000000..7a3ccea50c --- /dev/null +++ b/src/mainboard/google/slippy/acpi_tables.c @@ -0,0 +1,292 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +#include +#include +#include "thermal.h" + +static void acpi_update_thermal_table(global_nvs_t *gnvs) +{ + gnvs->tmps = CTDP_SENSOR_ID; + + gnvs->f1of = CTDP_NOMINAL_THRESHOLD_OFF; + gnvs->f1on = CTDP_NOMINAL_THRESHOLD_ON; + + gnvs->f0of = CTDP_DOWN_THRESHOLD_OFF; + gnvs->f0on = CTDP_DOWN_THRESHOLD_ON; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; + gnvs->flvl = 1; +} + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->apic = 1; + gnvs->mpen = 1; /* Enable Multi Processing */ + gnvs->pcnt = dev_count_cpu(); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* CBMEM TOC */ + gnvs->cmem = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* IGD Displays */ + gnvs->ndid = 3; + gnvs->did[0] = 0x80000100; + gnvs->did[1] = 0x80000240; + gnvs->did[2] = 0x80000410; + gnvs->did[3] = 0x80000410; + gnvs->did[4] = 0x00000005; + +#if CONFIG_CHROMEOS + // TODO(reinauer) this could move elsewhere? + chromeos_init_vboot(&(gnvs->chromeos)); + + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif + + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + + acpi_update_thermal_table(gnvs); +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + /* INT_SRC_OVR */ + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 0, 2, 0); + current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) + current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; +#if CONFIG_HAVE_ACPI_SLIC + acpi_header_t *slic; +#endif + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + +#if CONFIG_HAVE_ACPI_SLIC + printk(BIOS_DEBUG, "ACPI: * SLIC\n"); + slic = (acpi_header_t *)current; + current += acpi_create_slic(current); + ALIGN_CURRENT; + acpi_add_table(rsdp, slic); +#endif + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * SSDT2\n"); + ssdt = (acpi_header_t *)current; + acpi_create_serialio_ssdt(ssdt); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/google/slippy/chromeos.c b/src/mainboard/google/slippy/chromeos.c new file mode 100644 index 0000000000..913b6f33fc --- /dev/null +++ b/src/mainboard/google/slippy/chromeos.c @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#if CONFIG_EC_GOOGLE_CHROMEEC +#include "ec.h" +#include +#endif + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static int get_lid_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + + return !!(ec_switches & EC_SWITCH_LID_OPEN); +#else + return 0; +#endif +} + +static void fill_lb_gpio(struct lb_gpio *gpio, int num, + int polarity, const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = num; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + else if (num >= 0) + gpio->value = get_gpio(num); + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, 58, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", + get_recovery_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", + get_developer_mode_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", + get_lid_switch()); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +/* The dev-switch is virtual */ +int get_developer_mode_switch(void) +{ + return 0; +} + +/* There are actually two recovery switches. One is the magic keyboard chord, + * the other is driven by Servo. */ +int get_recovery_mode_switch(void) +{ +#if CONFIG_EC_GOOGLE_CHROMEEC + u8 ec_switches = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES); + u32 ec_events; + + /* If a switch is set, we don't need to look at events. */ + if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) + return 1; + + /* Else check if the EC has posted the keyboard recovery event. */ + ec_events = google_chromeec_get_events_b(); + + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +#else + return 0; +#endif +} + +int get_write_protect_state(void) +{ + return get_gpio(58); +} diff --git a/src/mainboard/google/slippy/cmos.layout b/src/mainboard/google/slippy/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/google/slippy/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/google/slippy/devicetree.cb b/src/mainboard/google/slippy/devicetree.cb new file mode 100644 index 0000000000..06ca93c9f4 --- /dev/null +++ b/src/mainboard/google/slippy/devicetree.cb @@ -0,0 +1,115 @@ +chip northbridge/intel/haswell + + # Enable eDP Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Disable DisplayPort C Hotplug + register "gpu_dp_c_hotplug" = "0x00" + + # Enable HDMI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "5" # 400ms + register "gpu_panel_power_up_delay" = "400" # 40ms + register "gpu_panel_power_down_delay" = "150" # 15ms + register "gpu_panel_power_backlight_on_delay" = "2100" # 210ms + register "gpu_panel_power_backlight_off_delay" = "2100" # 210ms + + device cpu_cluster 0 on + chip cpu/intel/socket_rPGA989 + device lapic 0 on end + end + chip cpu/intel/haswell + # Magic APIC ID to locate this chip + device lapic 0xACAC off end + + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) + + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) + end + end + + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + + chip southbridge/intel/lynxpoint + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + # EC range is 0x800-0x9ff + register "gen1_dec" = "0x00fc0801" + register "gen2_dec" = "0x00fc0901" + + # EC_SMI is GPIO34 + register "alt_gp_smi_en" = "0x0004" + register "gpe0_en_1" = "0x00000000" + # EC_SCI is GPIO36 + register "gpe0_en_2" = "0x00000010" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "ide_legacy_combined" = "0x0" + register "sata_ahci" = "0x1" + register "sata_port_map" = "0x1" + + register "sio_acpi_mode" = "0" + register "sio_i2c0_voltage" = "0" # 3.3V + register "sio_i2c1_voltage" = "0" # 3.3V + + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 off end # PCIe Port #2 + device pci 1c.2 off end # PCIe Port #3 + device pci 1c.3 off end # PCIe Port #4 + device pci 1c.4 off end # PCIe Port #5 + device pci 1c.5 off end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on + chip ec/google/chromeec + # We only have one init function that + # we need to call to initialize the + # keyboard part of the EC. + device pnp ff.1 on # dummy address + end + end + end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/google/slippy/dsdt.asl b/src/mainboard/google/slippy/dsdt.asl new file mode 100644 index 0000000000..1316ebfcd3 --- /dev/null +++ b/src/mainboard/google/slippy/dsdt.asl @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + #include "acpi/mainboard.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include +} diff --git a/src/mainboard/google/slippy/ec.c b/src/mainboard/google/slippy/ec.c new file mode 100644 index 0000000000..0919f0feec --- /dev/null +++ b/src/mainboard/google/slippy/ec.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "ec.h" + +void mainboard_ec_init(void) +{ + printk(BIOS_DEBUG, "mainboard_ec_init\n"); + post_code(0xf0); + + /* Restore SCI event mask on resume. */ + if (acpi_slp_type == 3) { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S3_WAKE_EVENTS); + + /* Disable SMI and wake events */ + google_chromeec_set_smi_mask(0); + + /* Clear pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + } else { + google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS | + MAINBOARD_EC_S5_WAKE_EVENTS); + } + + /* Clear wake events, these are enabled on entry to sleep */ + google_chromeec_set_wake_mask(0); + + post_code(0xf1); +} diff --git a/src/mainboard/google/slippy/ec.h b/src/mainboard/google/slippy/ec.h new file mode 100644 index 0000000000..11d2453837 --- /dev/null +++ b/src/mainboard/google/slippy/ec.h @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_EC_H +#define MAINBOARD_EC_H + +#include + +#define EC_SCI_GPI 36 /* GPIO36 is EC_SCI# */ +#define EC_SMI_GPI 34 /* GPIO34 is EC_SMI# */ + +#define MAINBOARD_EC_SCI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER)) + +#define MAINBOARD_EC_SMI_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED)) + +/* EC can wake from S5 with lid or power button */ +#define MAINBOARD_EC_S5_WAKE_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON)) + +/* EC can wake from S3 with lid or power button or key press */ +#define MAINBOARD_EC_S3_WAKE_EVENTS \ + (MAINBOARD_EC_S5_WAKE_EVENTS |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED)) + +/* Log EC wake events plus EC shutdown events */ +#define MAINBOARD_EC_LOG_EVENTS \ + (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\ + EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)) + +#ifndef __ACPI__ +extern void mainboard_ec_init(void); +#endif + +#endif diff --git a/src/mainboard/google/slippy/fadt.c b/src/mainboard/google/slippy/fadt.c new file mode 100644 index 0000000000..7afbbfa698 --- /dev/null +++ b/src/mainboard/google/slippy/fadt.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + u16 pmbase = get_pmbase(); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->sci_int = 0x9; + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + 0x4; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + 0x50; + fadt->pm_tmr_blk = pmbase + 0x8; + fadt->gpe0_blk = pmbase + 0x80; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/google/slippy/gpio.h b/src/mainboard/google/slippy/gpio.h new file mode 100644 index 0000000000..2d47ea7a6c --- /dev/null +++ b/src/mainboard/google/slippy/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SLIPPY_GPIO_H +#define SLIPPY_GPIO_H + +struct pch_lp_gpio_map; + +const struct pch_lp_gpio_map mainboard_gpio_map[] = { + LP_GPIO_UNUSED, /* 0: UNUSED */ + LP_GPIO_UNUSED, /* 1: UNUSED */ + LP_GPIO_UNUSED, /* 2: UNUSED */ + LP_GPIO_UNUSED, /* 3: UNUSED */ + LP_GPIO_NATIVE, /* 4: NATIVE: I2C0_SDA_GPIO4 */ + LP_GPIO_NATIVE, /* 5: NATIVE: I2C0_SCL_GPIO5 */ + LP_GPIO_NATIVE, /* 6: NATIVE: I2C1_SDA_GPIO6 */ + LP_GPIO_NATIVE, /* 7: NATIVE: I2C1_SCL_GPIO7 */ + LP_GPIO_ACPI_SCI, /* 8: LTE_WAKE_L_Q */ + LP_GPIO_INPUT, /* 9: RAM_ID1 */ + LP_GPIO_ACPI_SCI, /* 10: WLAN_WAKE_L_Q */ + LP_GPIO_UNUSED, /* 11: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 12: TRACKPAD_INT_L (WAKE) */ + LP_GPIO_INPUT, /* 13: RAM_ID0 */ + LP_GPIO_INPUT, /* 14: EC_IN_RW */ + LP_GPIO_UNUSED, /* 15: UNUSED (STRAP) */ + LP_GPIO_OUT_LOW, /* 16: PCH_SSD_12_EN (iSSD VDDC) */ + LP_GPIO_OUT_LOW, /* 17: PCH_SSD_18_EN (iSSD VCCQ) */ + LP_GPIO_NATIVE, /* 18: PCIE_CLKREQ_WLAN# */ + LP_GPIO_UNUSED, /* 19: UNUSED */ + LP_GPIO_UNUSED, /* 20: UNUSED */ + LP_GPIO_UNUSED, /* 21: UNUSED */ + LP_GPIO_UNUSED, /* 22: UNUSED */ + LP_GPIO_UNUSED, /* 23: UNUSED */ + LP_GPIO_UNUSED, /* 24: UNUSED */ + LP_GPIO_INPUT_INVERT, /* 25: TOUCH_INT_L (WAKE) */ + LP_GPIO_UNUSED, /* 26: UNUSED */ + LP_GPIO_UNUSED, /* 27: UNUSED */ + LP_GPIO_UNUSED, /* 28: UNUSED */ + LP_GPIO_UNUSED, /* 29: UNUSED */ + LP_GPIO_NATIVE, /* 30: NATIVE: PCH_SUSWARN_L */ + LP_GPIO_NATIVE, /* 31: NATIVE: ACPRESENT */ + LP_GPIO_NATIVE, /* 32: NATIVE: LPC_CLKRUN_L */ + LP_GPIO_NATIVE, /* 33: NATIVE: DEVSLP0 */ + LP_GPIO_ACPI_SMI, /* 34: EC_SMI_L */ + LP_GPIO_ACPI_SMI, /* 35: PCH_NMI_DBG_L (route in NMI_EN) */ + LP_GPIO_ACPI_SCI, /* 36: EC_SCI_L */ + LP_GPIO_UNUSED, /* 37: UNUSED */ + LP_GPIO_UNUSED, /* 38: UNUSED */ + LP_GPIO_UNUSED, /* 39: UNUSED */ + LP_GPIO_NATIVE, /* 40: NATIVE: USB_OC0# */ + LP_GPIO_UNUSED, /* 41: UNUSED */ + LP_GPIO_NATIVE, /* 42: NATIVE: USB_OC2# */ + LP_GPIO_UNUSED, /* 43: UNUSED */ + LP_GPIO_OUT_LOW, /* 44: PP3300_SSD_EN (iSSD VCC_FLASH) */ + LP_GPIO_OUT_HIGH, /* 45: PP3300_CODEC_EN */ + LP_GPIO_OUT_HIGH, /* 46: WLAN_DISABLE_L */ + LP_GPIO_INPUT, /* 47: RAM_ID2 */ + LP_GPIO_UNUSED, /* 48: UNUSED */ + LP_GPIO_OUT_LOW, /* 49: PP3300_SSD_IO_EN (iSSD VCC_IO) */ + LP_GPIO_UNUSED, /* 50: UNUSED */ + LP_GPIO_INPUT, /* 51: ALS_INT_L */ + LP_GPIO_INPUT, /* 52: SIM_DET */ + LP_GPIO_PIRQ, /* 53: TRACKPAD_INT_DX (PIRQV) */ + LP_GPIO_PIRQ, /* 54: TOUCH_INT_L_DX (PIRQW) */ + LP_GPIO_UNUSED, /* 55: UNUSED */ + LP_GPIO_UNUSED, /* 56: UNUSED */ + LP_GPIO_OUT_HIGH, /* 57: PP3300_CCD_EN */ + LP_GPIO_INPUT, /* 58: PCH_SPI_WP_D */ + LP_GPIO_OUT_HIGH, /* 59: LTE_DISABLE_L */ + LP_GPIO_NATIVE, /* 60: NATIVE: SML0ALERT */ + LP_GPIO_NATIVE, /* 61: NATIVE: PCH_SUS_STAT */ + LP_GPIO_NATIVE, /* 62: NATIVE: PCH_SUS_CLK */ + LP_GPIO_NATIVE, /* 63: NATIVE: PCH_SLP_S5_L */ + LP_GPIO_UNUSED, /* 64: UNUSED */ + LP_GPIO_UNUSED, /* 65: UNUSED */ + LP_GPIO_UNUSED, /* 66: UNUSED */ + LP_GPIO_UNUSED, /* 67: UNUSED */ + LP_GPIO_UNUSED, /* 68: UNUSED */ + LP_GPIO_UNUSED, /* 69: UNUSED */ + LP_GPIO_UNUSED, /* 70: UNUSED */ + LP_GPIO_NATIVE, /* 71: NATIVE: MODPHY_EN */ + LP_GPIO_NATIVE, /* 72: NATIVE: PCH_BATLOW# */ + LP_GPIO_NATIVE, /* 73: NATIVE: SMB1ALERT# */ + LP_GPIO_NATIVE, /* 74: NATIVE: SMB_ME1_DAT */ + LP_GPIO_NATIVE, /* 75: NATIVE: SMB_ME1_CLK */ + LP_GPIO_UNUSED, /* 76: UNUSED */ + LP_GPIO_UNUSED, /* 77: UNUSED */ + LP_GPIO_UNUSED, /* 78: UNUSED */ + LP_GPIO_UNUSED, /* 79: UNUSED */ + LP_GPIO_UNUSED, /* 80: UNUSED */ + LP_GPIO_NATIVE, /* 81: NATIVE: SPKR */ + LP_GPIO_NATIVE, /* 82: NATIVE: EC_RCIN_L */ + LP_GPIO_UNUSED, /* 83: UNUSED */ + LP_GPIO_UNUSED, /* 84: UNUSED */ + LP_GPIO_UNUSED, /* 85: UNUSED */ + LP_GPIO_UNUSED, /* 86: UNUSED (STRAP) */ + LP_GPIO_UNUSED, /* 87: UNUSED */ + LP_GPIO_UNUSED, /* 88: UNUSED */ + LP_GPIO_UNUSED, /* 89: UNUSED */ + LP_GPIO_UNUSED, /* 90: UNUSED */ + LP_GPIO_UNUSED, /* 91: UNUSED */ + LP_GPIO_UNUSED, /* 92: UNUSED */ + LP_GPIO_UNUSED, /* 93: UNUSED */ + LP_GPIO_UNUSED, /* 94: UNUSED */ + LP_GPIO_END +}; + +#endif diff --git a/src/mainboard/google/slippy/hda_verb.h b/src/mainboard/google/slippy/hda_verb.h new file mode 100644 index 0000000000..ba0da1c1a4 --- /dev/null +++ b/src/mainboard/google/slippy/hda_verb.h @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static const u32 mainboard_cim_verb_data[] = { + /* coreboot specific header */ + 0x10ec0283, // Codec Vendor / Device ID: Realtek ALC283 + 0x10ec0283, // Subsystem ID + 0x0000000c, // Number of jacks (NID entries) + + /* NID 0x01, HDA Codec Subsystem ID Verb Table: 0x10ec0283 */ + 0x00172083, + 0x00172102, + 0x001722ec, + 0x00172310, + + /* Pin Widget Verb Table */ + + /* Pin Complex (NID 0x12) DMIC - interior mobile lid */ + 0x01271c10, + 0x01271d10, + 0x01271ea6, + 0x01271fb7, + + /* Pin Complex (NID 0x14) SPKR-OUT PORTD */ + 0x01471c10, // group 1, front left/right + 0x01471d01, // no connector, no jack detect + 0x01471e17, // speaker out, analog + 0x01471f90, // fixed function, internal + + /* Pin Complex (NID 0x17) */ + 0x01771cf0, + 0x01771d11, + 0x01771e11, + 0x01771f41, + + /* Pin Complex (NID 0x18) MIC1 PORTB */ + 0x01971c11, // group 1, cap 1 + 0x01971d10, // black, jack detect + 0x01971ea7, // mic in, analog + 0x01971f03, // connector, left panel + + /* Pin Complex (NID 0x19) MIC2 PORTF */ + 0x01871cf0, + 0x01871d11, + 0x01871e11, + 0x01871f41, + + /* Pin Complex (NID 0x1A) LINE1 PORTC */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1B) LINE2 PORTE */ + 0x01a71cf0, + 0x01a71d11, + 0x01a71e11, + 0x01a71f41, + + /* Pin Complex (NID 0x1d) PCBeep */ + 0x01d71c2d, // eapd low on ex-amp, laptop, custom enable + 0x01d71d81, // mute spkr on hpout + 0x01d71e15, // pcbeep en able, checksum + 0x01d71f40, // no physical, internal + + /* Pin Complex (NID 0x1E) SPDIF-OUT */ + 0x01e71cf0, + 0x01e71d11, + 0x01e71e11, + 0x01e71f41, + + /* Pin Complex (NID 0x21) HPOUT PORT-I */ + 0x02171c1f, // group1, + 0x02171d10, // black, jack detect + 0x02171e21, // HPOut, 1/8 stereo + 0x02171f03, // connector, left panel + + /* Undocumented settings from Realtek (needed for beep_gen) */ + /* Widget node 0x20 */ + 0x02050010, + 0x02040c20, + 0x0205001b, + 0x0204081b, +}; + +static const u32 mainboard_pc_beep_verbs[] = { + 0x00170500, /* power up everything (codec, dac, adc, mixers) */ + 0x01470740, /* enable speaker out */ + 0x01470c02, /* set speaker EAPD pin */ + 0x0143b01f, /* unmute speaker */ + 0x00c37100, /* unmute mixer nid 0xc input 1 */ + 0x00b37410, /* unmute mixer nid 0xb beep input and set volume */ +}; + +static const u32 mainboard_pc_beep_verbs_size = + sizeof(mainboard_pc_beep_verbs) / sizeof(mainboard_pc_beep_verbs[0]); diff --git a/src/mainboard/google/slippy/mainboard.c b/src/mainboard/google/slippy/mainboard.c new file mode 100644 index 0000000000..60e8663ab6 --- /dev/null +++ b/src/mainboard/google/slippy/mainboard.c @@ -0,0 +1,207 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include "ec.h" +#include "onboard.h" + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 0; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; +extern const u32 * pc_beep_verbs; +extern u32 pc_beep_verbs_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); + pc_beep_verbs = mainboard_pc_beep_verbs; + pc_beep_verbs_size = mainboard_pc_beep_verbs_size; + +} + +static void mainboard_init(device_t dev) +{ + mainboard_ec_init(); +} + +static int mainboard_smbios_data(device_t dev, int *handle, + unsigned long *current) +{ + int len = 0; + + len += smbios_write_type41( + current, handle, + BOARD_LIGHTSENSOR_NAME, /* name */ + BOARD_LIGHTSENSOR_IRQ, /* instance */ + BOARD_LIGHTSENSOR_I2C_BUS, /* segment */ + BOARD_LIGHTSENSOR_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TRACKPAD_NAME, /* name */ + BOARD_TRACKPAD_IRQ, /* instance */ + BOARD_TRACKPAD_I2C_BUS, /* segment */ + BOARD_TRACKPAD_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + len += smbios_write_type41( + current, handle, + BOARD_TOUCHSCREEN_NAME, /* name */ + BOARD_TOUCHSCREEN_IRQ, /* instance */ + BOARD_TOUCHSCREEN_I2C_BUS, /* segment */ + BOARD_TOUCHSCREEN_I2C_ADDR, /* bus */ + 0, /* device */ + 0); /* function */ + + return len; +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; + dev->ops->get_smbios_data = mainboard_smbios_data; +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/slippy/mainboard.h b/src/mainboard/google/slippy/mainboard.h new file mode 100644 index 0000000000..f47fffda2a --- /dev/null +++ b/src/mainboard/google/slippy/mainboard.h @@ -0,0 +1,25 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MAINBOARD_H_ +#define __MAINBOARD_H_ +void mainboard_train_link(struct intel_dp *intel_dp); +void mainboard_set_port_clk_dp(struct intel_dp *intel_dp); + +#endif diff --git a/src/mainboard/google/slippy/onboard.h b/src/mainboard/google/slippy/onboard.h new file mode 100644 index 0000000000..23e8f1e062 --- /dev/null +++ b/src/mainboard/google/slippy/onboard.h @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ONBOARD_H +#define ONBOARD_H + +#define BOARD_LIGHTSENSOR_NAME "lightsensor" +#define BOARD_LIGHTSENSOR_IRQ 51 /* PIRQT */ +#define BOARD_LIGHTSENSOR_I2C_BUS 2 /* I2C1 */ +#define BOARD_LIGHTSENSOR_I2C_ADDR 0x44 + +#define BOARD_TRACKPAD_NAME "trackpad" +#define BOARD_TRACKPAD_IRQ 37 /* PIRQV */ +#define BOARD_TRACKPAD_WAKE_GPIO 12 /* GPIO12 */ +#define BOARD_TRACKPAD_I2C_BUS 1 /* I2C0 */ +#define BOARD_TRACKPAD_I2C_ADDR 0x67 + +#define BOARD_TOUCHSCREEN_NAME "touchscreen" +#define BOARD_TOUCHSCREEN_IRQ 38 /* PIRQW */ +#define BOARD_TOUCHSCREEN_WAKE_GPIO 25 /* GPIO25 */ +#define BOARD_TOUCHSCREEN_I2C_BUS 2 /* I2C1 */ +#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a + +#endif diff --git a/src/mainboard/google/slippy/romstage.c b/src/mainboard/google/slippy/romstage.c new file mode 100644 index 0000000000..fdbac97695 --- /dev/null +++ b/src/mainboard/google/slippy/romstage.c @@ -0,0 +1,203 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "cpu/intel/haswell/haswell.h" +#include "northbridge/intel/haswell/haswell.h" +#include "northbridge/intel/haswell/raminit.h" +#include "southbridge/intel/lynxpoint/pch.h" +#include "southbridge/intel/lynxpoint/lp_gpio.h" +#include "gpio.h" + +const struct rcba_config_instruction rcba_config[] = { + + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), + RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), + RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), + RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), + RCBA_SET_REG_32(D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)),/* LPC */ + RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)),/* EHCI */ + RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)),/* PCIE */ + RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)),/* HDA */ + RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)),/* ME */ + RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)),/* SIO */ + RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)),/* XHCI */ + RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)),/* SDIO */ + + /* Disable unused devices (board specific) */ + RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), + + RCBA_END_CONFIG, +}; + +/* Copy SPD data for on-board memory */ +static void copy_spd(struct pei_data *peid) +{ + const int gpio_vector[] = {13, 9, 47, -1}; + int spd_index = get_gpios(gpio_vector); + struct cbfs_file *spd_file; + + printk(BIOS_DEBUG, "SPD index %d\n", spd_index); + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + if (!spd_file) + die("SPD data not found."); + + if (ntohl(spd_file->len) < + ((spd_index + 1) * sizeof(peid->spd_data[0]))) { + printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); + spd_index = 0; + } + + if (spd_file->len < sizeof(peid->spd_data[0])) + die("Missing SPD data."); + + memcpy(peid->spd_data[0], + ((char*)CBFS_SUBHEADER(spd_file)) + + spd_index * sizeof(peid->spd_data[0]), + sizeof(peid->spd_data[0])); +} + +/* + * Power Sequencing for SanDisk i100/i110 SSD + * + * Must be sequenced in this order with specified timing. + * + * 1. VCC_IO : 30us - 100ms + * 2. VCC_FLASH : 70us - 10ms + * 3. VCCQ : 70us - 10ms + * 4. VDDC : 30us - 100ms + * + * There is no feedback to know if the voltage has stabilized + * so this implementation will use the max ramp times. That + * means it adds significantly to the boot time. + */ +static void issd_power_sequence(void) +{ + struct gpio_seq { + int gpio; + int wait_ms; + } issd_gpio_seq[] = { + { 49, 100 }, /* VCC_IO: GPIO 49, wait 100ms */ + { 44, 10 }, /* VCC_FLASH: GPIO 44, wait 10ms */ + { 17, 10 }, /* VCCQ: GPIO 17, wait 10ms */ + { 16, 100 }, /* VDDC: GPIO 16, wait 100ms */ + }; + int step; + + for (step = 0; step < ARRAY_SIZE(issd_gpio_seq); step++) { + set_gpio(issd_gpio_seq[step].gpio, 1); + udelay(issd_gpio_seq[step].wait_ms * 1000); + } +} + +void mainboard_romstage_entry(unsigned long bist) +{ + struct pei_data pei_data = { + pei_version: PEI_VERSION, + mchbar: DEFAULT_MCHBAR, + dmibar: DEFAULT_DMIBAR, + epbar: DEFAULT_EPBAR, + pciexbar: DEFAULT_PCIEXBAR, + smbusbar: SMBUS_IO_BASE, + wdbbar: 0x4000000, + wdbsize: 0x1000, + hpet_address: HPET_ADDR, + rcba: DEFAULT_RCBA, + pmbase: DEFAULT_PMBASE, + gpiobase: DEFAULT_GPIOBASE, + temp_mmio_base: 0xfed08000, + system_type: 5, /* ULT */ + tseg_size: CONFIG_SMM_TSEG_SIZE, + spd_addresses: { 0xff, 0x00, 0xff, 0x00 }, + ec_present: 1, + // 0 = leave channel enabled + // 1 = disable dimm 0 on channel + // 2 = disable dimm 1 on channel + // 3 = disable dimm 0+1 on channel + dimm_channel0_disabled: 2, + dimm_channel1_disabled: 2, + max_ddr3_freq: 1600, + usb_xhci_on_resume: 1, + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0150, 1, USB_OC_PIN_SKIP, /* P0: LTE */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 0, /* P1: Port A, CN10 */ + USB_PORT_BACK_PANEL }, + { 0x0080, 1, USB_OC_PIN_SKIP, /* P2: CCD */ + USB_PORT_INTERNAL }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: BT */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 2, /* P4: Port B, CN6 */ + USB_PORT_BACK_PANEL }, + { 0x0000, 0, USB_OC_PIN_SKIP, /* P5: EMPTY */ + USB_PORT_SKIP }, + { 0x0150, 1, USB_OC_PIN_SKIP, /* P6: SD Card */ + USB_PORT_FLEX }, + { 0x0000, 0, USB_OC_PIN_SKIP, /* P7: EMPTY */ + USB_PORT_SKIP }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; Port A, CN10 */ + { 1, 2 }, /* P2; Port B, CN6 */ + { 0, USB_OC_PIN_SKIP }, /* P3; */ + { 0, USB_OC_PIN_SKIP }, /* P4; */ + }, + }; + + struct romstage_params romstage_params = { + .pei_data = &pei_data, + .gpio_map = &mainboard_gpio_map, + .rcba_config = &rcba_config[0], + .bist = bist, + .copy_spd = copy_spd, + }; + + /* Call into the real romstage main with this board's attributes. */ + romstage_common(&romstage_params); + + /* Power sequence the iSSD module */ + issd_power_sequence(); +} diff --git a/src/mainboard/google/slippy/smihandler.c b/src/mainboard/google/slippy/smihandler.c new file mode 100644 index 0000000000..dd0a60528a --- /dev/null +++ b/src/mainboard/google/slippy/smihandler.c @@ -0,0 +1,157 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include EC functions */ +#include +#include "ec.h" + +int mainboard_io_trap_handler(int smif) +{ + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; + break; + default: + return 0; + } + + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; +} + +static u8 mainboard_smi_ec(void) +{ + u8 cmd = google_chromeec_get_event(); + u32 pm1_cnt; + +#if CONFIG_ELOG_GSMI + /* Log this event */ + if (cmd) + elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd); +#endif + + switch (cmd) { + case EC_HOST_EVENT_LID_CLOSED: + printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n"); + + /* Go to S5 */ + pm1_cnt = inl(get_pmbase() + PM1_CNT); + pm1_cnt |= (0xf << 10); + outl(pm1_cnt, get_pmbase() + PM1_CNT); + break; + } + + return cmd; +} + +/* gpi_sts is GPIO 47:32 */ +void mainboard_smi_gpi(u32 gpi_sts) +{ + if (gpi_sts & (1 << (EC_SMI_GPI - 32))) { + /* Process all pending events */ + while (mainboard_smi_ec() != 0); + } +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + /* Disable USB charging if required */ + switch (slp_typ) { + case 3: + if (smm_get_gnvs()->s3u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s3u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS); + break; + case 5: + if (smm_get_gnvs()->s5u0 == 0) + google_chromeec_set_usb_charge_mode( + 0, USB_CHARGE_MODE_DISABLED); + if (smm_get_gnvs()->s5u1 == 0) + google_chromeec_set_usb_charge_mode( + 1, USB_CHARGE_MODE_DISABLED); + /* Enable wake events */ + google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS); + break; + } + + /* Disable SCI and SMI events */ + google_chromeec_set_smi_mask(0); + google_chromeec_set_sci_mask(0); + + /* Clear pending events that may trigger immediate wake */ + while (google_chromeec_get_event() != 0); +} + +#define APMC_FINALIZE 0xcb + +static int mainboard_finalized = 0; + +int mainboard_smi_apmc(u8 apmc) +{ + switch (apmc) { + case APMC_FINALIZE: + if (mainboard_finalized) { + printk(BIOS_DEBUG, "SMI#: Already finalized\n"); + return 0; + } + + intel_pch_finalize_smm(); + intel_northbridge_haswell_finalize_smm(); + intel_cpu_haswell_finalize_smm(); + + mainboard_finalized = 1; + break; + case APM_CNT_ACPI_ENABLE: + google_chromeec_set_smi_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS); + break; + case APM_CNT_ACPI_DISABLE: + google_chromeec_set_sci_mask(0); + /* Clear all pending events */ + while (google_chromeec_get_event() != 0); + google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);; + break; + } + return 0; +} diff --git a/src/mainboard/google/slippy/thermal.h b/src/mainboard/google/slippy/thermal.h new file mode 100644 index 0000000000..eeedf2551d --- /dev/null +++ b/src/mainboard/google/slippy/thermal.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef THERMAL_H +#define THERMAL_H + +/* Config TDP Sensor ID */ +#define CTDP_SENSOR_ID 0 /* PECI */ + +/* Config TDP Nominal */ +#define CTDP_NOMINAL_THRESHOLD_OFF 0 +#define CTDP_NOMINAL_THRESHOLD_ON 0 + +/* Config TDP Down */ +#define CTDP_DOWN_THRESHOLD_OFF 80 +#define CTDP_DOWN_THRESHOLD_ON 90 + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 104 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 100 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 105 + +#endif diff --git a/src/mainboard/google/snow/Kconfig b/src/mainboard/google/snow/Kconfig deleted file mode 100644 index 85b90a5a3a..0000000000 --- a/src/mainboard/google/snow/Kconfig +++ /dev/null @@ -1,165 +0,0 @@ -## -## This file is part of the coreboot project. -## -## Copyright 2013 Google Inc. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; version 2 of the License. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -## - -if BOARD_GOOGLE_SNOW - -config BOARD_SPECIFIC_OPTIONS # dummy - def_bool y - select ARCH_ARMV7 - select CPU_SAMSUNG_EXYNOS5 - select HAVE_UART_MEMORY_MAPPED -# select EC_GOOGLE_CHROMEEC - select BOARD_ROMSIZE_KB_4096 - select DRIVER_MAXIM_MAX77686 -# select HAVE_ACPI_TABLES -# select MMCONF_SUPPORT - select EXYNOS_DISPLAYPORT - select CHROMEOS - -config MAINBOARD_DIR - string - default google/snow - -config MAINBOARD_PART_NUMBER - string - default "SNOW" - -#config MMCONF_BASE_ADDRESS -# hex -# default 0xf0000000 - -#config IRQ_SLOT_COUNT -# int -# default 18 - -config MAX_CPUS - int - default 2 - -config MAINBOARD_VENDOR - string - default "Samsung" - -config BOOTBLOCK_MAINBOARD_INIT - string - default "mainboard/google/snow/bootblock.c" - -config DRAM_SIZE_MB - int - default 2048 - -config NR_DRAM_BANKS - int - default 1 - -choice - prompt "Serial Console UART" - default CONSOLE_SERIAL_UART3 - depends on CONSOLE_SERIAL_UART - -config CONSOLE_SERIAL_UART0 - bool "UART0" - help - Serial console on UART0 - -config CONSOLE_SERIAL_UART1 - bool "UART1" - help - Serial console on UART1 - -config CONSOLE_SERIAL_UART2 - bool "UART2" - help - Serial console on UART2 - -config CONSOLE_SERIAL_UART3 - bool "UART3" - help - Serial console on UART3 - -endchoice - -config CONSOLE_SERIAL_UART_ADDRESS - hex - depends on CONSOLE_SERIAL_UART - default 0x12c00000 if CONSOLE_SERIAL_UART0 - default 0x12c10000 if CONSOLE_SERIAL_UART1 - default 0x12c20000 if CONSOLE_SERIAL_UART2 - default 0x12c30000 if CONSOLE_SERIAL_UART3 - help - Map the UART names to the respective MMIO address. - -################################################################# -# stuff from smdk5250.h # -# FIXME: can we move some of these to exynos5250's Kconfig? # -################################################################# -config SYS_I2C_SPEED - int - default 100000 - -config SYS_I2C_SLAVE - hex - default 0x0 - -config I2C_MULTI_BUS - bool - default y - -#config HARD_I2C -# bool -# default y -#CMD_I2C -#I2C_EDID -#DRIVER_S3C24X0_I2C - -config VDD_ARM_MV - int - default 1300 #1.3V - -config VDD_INT_UV - int - default 1012500 # 1.0125v - -config VDD_MIF_MV - int - default 1000 # 1.0v - -config VDD_G3D_MV - int - default 1200 # 1.2v - -config VDD_LDO2_MV - int - default 1500 # 1.5v - -config VDD_LDO3_MV - int - default 1800 # 1.8v - -config VDD_LDO5_MV - int - default 1800 # 1.8v - -config VDD_LDO10_MV - int - default 1800 # 1.8v - -######### smdk5250.h ######## - -endif # BOARD_GOOGLE_SNOW diff --git a/src/mainboard/google/snow/chromeos.c b/src/mainboard/google/snow/chromeos.c deleted file mode 100644 index d29aa2a72c..0000000000 --- a/src/mainboard/google/snow/chromeos.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2013 Google, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 -#define WP_GPIO 6 -#define DEVMODE_GPIO 54 -#define FORCE_RECOVERY_MODE 0 -#define FORCE_DEVELOPER_MODE 0 -#define LID_OPEN 3 -#define POWER_BUTTON 3 - -#include - -#define GPIO_COUNT 6 - -void fill_lb_gpios(struct lb_gpios *gpios) -{ - struct exynos5_gpio_part1 *gpio_pt1; - struct exynos5_gpio_part2 *gpio_pt2; - - gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); - gpios->count = GPIO_COUNT; - - gpio_pt1 = (struct exynos5_gpio_part1 *)EXYNOS5_GPIO_PART1_BASE; - gpio_pt2 = (struct exynos5_gpio_part2 *)EXYNOS5_GPIO_PART2_BASE; - - /* Write Protect: active Low */ - gpios->gpios[0].port = EXYNOS5_GPD1; - gpios->gpios[0].polarity = ACTIVE_LOW; - gpios->gpios[0].value = s5p_gpio_get_value(&gpio_pt1->d1, WP_GPIO); - strncpy((char *)gpios->gpios[0].name,"write protect", - GPIO_MAX_NAME_LENGTH); - - /* Recovery: active high */ - gpios->gpios[1].port = EXYNOS5_GPY1; - gpios->gpios[1].polarity = ACTIVE_HIGH; - gpios->gpios[1].value = s5p_gpio_get_value(&gpio_pt1->y1, FORCE_RECOVERY_MODE); - strncpy((char *)gpios->gpios[1].name,"recovery", GPIO_MAX_NAME_LENGTH); - - /* Lid: the "switch" comes from the EC */ - gpios->gpios[2].port = EXYNOS5_GPX3; - gpios->gpios[2].polarity = ACTIVE_LOW; - gpios->gpios[2].value = s5p_gpio_get_value(&gpio_pt2->x3, LID_OPEN); - strncpy((char *)gpios->gpios[2].name,"lid", GPIO_MAX_NAME_LENGTH); - - /* Power: virtual GPIO active low */ - gpios->gpios[3].port = -1; - gpios->gpios[3].polarity = ACTIVE_LOW; - gpios->gpios[3].value = 1; - strncpy((char *)gpios->gpios[3].name,"power", GPIO_MAX_NAME_LENGTH); - - /* Developer: virtual GPIO active high */ - gpios->gpios[4].port = -1; - gpios->gpios[4].polarity = ACTIVE_HIGH; - gpios->gpios[4].value = 0; - strncpy((char *)gpios->gpios[4].name,"developer", - GPIO_MAX_NAME_LENGTH); - - /* Was VGA Option ROM loaded? */ - gpios->gpios[5].port = -1; /* Indicate that this is a pseudo GPIO */ - gpios->gpios[5].polarity = ACTIVE_HIGH; - gpios->gpios[5].value = 0; - strncpy((char *)gpios->gpios[5].name,"oprom", GPIO_MAX_NAME_LENGTH); - - printk(BIOS_ERR, "Added %d GPIOS size %d\n", GPIO_COUNT, gpios->size); - -} - -int get_developer_mode_switch(void) -{ - int dev_mode = 0; - - printk(BIOS_DEBUG,"FORCING DEVELOPER MODE.\n"); - - dev_mode = 1; - printk(BIOS_DEBUG,"DEVELOPER MODE FROM GPIO %d: %x\n",DEVMODE_GPIO, - dev_mode); - - return dev_mode; -} - -int get_recovery_mode_switch(void) -{ - int ec_rec_mode = 0; - - return ec_rec_mode; -} - -int get_recovery_mode_from_vbnv(void) -{ - return 1; -} diff --git a/src/mainboard/google/snow/mainboard.c b/src/mainboard/google/snow/mainboard.c deleted file mode 100644 index 4a0d181cd0..0000000000 --- a/src/mainboard/google/snow/mainboard.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include -#include - -#include "mainboard.h" - -#define SNOW_BOARD_ID0_GPIO 88 /* GPD0, pin 0 */ -#define SNOW_BOARD_ID1_GPIO 89 /* GPD0, pin 1 */ - -struct { - enum mvl3 id0, id1; - enum snow_board_config config; -} snow_id_map[] = { - /* ID0 ID1 config */ - { LOGIC_0, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, - { LOGIC_0, LOGIC_1, SNOW_CONFIG_ELPIDA_MP }, - { LOGIC_1, LOGIC_0, SNOW_CONFIG_SAMSUNG_DVT }, - { LOGIC_1, LOGIC_1, SNOW_CONFIG_ELPIDA_DVT }, - { LOGIC_0, LOGIC_Z, SNOW_CONFIG_SAMSUNG_PVT }, - { LOGIC_1, LOGIC_Z, SNOW_CONFIG_ELPIDA_PVT }, - { LOGIC_Z, LOGIC_0, SNOW_CONFIG_SAMSUNG_MP }, - { LOGIC_Z, LOGIC_Z, SNOW_CONFIG_ELPIDA_MP }, - { LOGIC_Z, LOGIC_1, SNOW_CONFIG_RSVD }, -}; - -int board_get_config(void) -{ - int i; - int id0, id1; - enum snow_board_config config = SNOW_CONFIG_UNKNOWN; - - id0 = gpio_read_mvl3(SNOW_BOARD_ID0_GPIO); - id1 = gpio_read_mvl3(SNOW_BOARD_ID1_GPIO); - if (id0 < 0 || id1 < 0) - return -1; - printk(BIOS_DEBUG, "%s: id0: %u, id1: %u\n", __func__, id0, id1); - - for (i = 0; i < ARRAY_SIZE(snow_id_map); i++) { - if (id0 == snow_id_map[i].id0 && id1 == snow_id_map[i].id1) { - config = snow_id_map[i].config; - break; - } - } - - return config; -} - -#if 0 -struct chip_operations mainboard_ops = { - .name = "Samsung/Google ARM Chromebook", - .enable_dev = mainboard_enable, -}; -#endif diff --git a/src/mainboard/google/snow/ramstage.c b/src/mainboard/google/snow/ramstage.c deleted file mode 100644 index 908162914f..0000000000 --- a/src/mainboard/google/snow/ramstage.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 The ChromeOS Authors - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include - -#include - -/* convenient shorthand (in MB) */ -#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20) -#define DRAM_SIZE CONFIG_DRAM_SIZE_MB -#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */ - -void hardwaremain(int boot_complete); -void main(void) -{ - console_init(); - printk(BIOS_INFO, "hello from ramstage; now with deluxe exception handling.\n"); - - /* set up coreboot tables */ - high_tables_size = CONFIG_COREBOOT_TABLES_SIZE; - high_tables_base = CONFIG_SYS_SDRAM_BASE + - ((unsigned)CONFIG_DRAM_SIZE_MB << 20ULL) - - CONFIG_COREBOOT_TABLES_SIZE; - cbmem_init(high_tables_base, high_tables_size); - - /* set up dcache and MMU */ - /* FIXME: this should happen via resource allocator */ - exynos5250_config_l2_cache(); - mmu_init(); - mmu_config_range(0, DRAM_START, DCACHE_OFF); - mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); - mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF); - dcache_invalidate_all(); - dcache_mmu_enable(); - - /* this is going to move, but we must have it now and we're not sure where */ - exception_init(); - - const unsigned epll_hz = 192000000; - const unsigned sample_rate = 48000; - const unsigned lr_frame_size = 256; - clock_epll_set_rate(epll_hz); - clock_select_i2s_clk_source(); - clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size); - - power_enable_xclkout(); - - hardwaremain(0); -} diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c deleted file mode 100644 index ca7ba9c23b..0000000000 --- a/src/mainboard/google/snow/romstage.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mainboard.h" - -#define MMC0_GPIO_PIN (58) - -#if 0 -static int board_wakeup_permitted(void) -{ - const int gpio = GPIO_Y10; - int is_bad_wake; - - /* We're a bad wakeup if the gpio was defined and was high */ - is_bad_wake = ((gpio != -1) && gpio_get_value(gpio)); - - return !is_bad_wake; -} -#endif - -static int setup_pmic(void) -{ - int error = 0; - - /* - * We're using CR1616 coin cell battery that is non-rechargeable - * battery. But, BBCHOSTEN bit of the BBAT Charger Register in - * MAX77686 is enabled by default for charging coin cell. - * - * Also, we cannot meet the coin cell reverse current spec. in UL - * standard if BBCHOSTEN bit is enabled. - * - * Disable Coin BATT Charging - */ - error = max77686_disable_backup_batt(); - - error |= max77686_volsetting(PMIC_BUCK2, CONFIG_VDD_ARM_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_BUCK3, CONFIG_VDD_INT_UV, - REG_ENABLE, MAX77686_UV); - error |= max77686_volsetting(PMIC_BUCK1, CONFIG_VDD_MIF_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_BUCK4, CONFIG_VDD_G3D_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_LDO2, CONFIG_VDD_LDO2_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_LDO3, CONFIG_VDD_LDO3_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_LDO5, CONFIG_VDD_LDO5_MV, - REG_ENABLE, MAX77686_MV); - error |= max77686_volsetting(PMIC_LDO10, CONFIG_VDD_LDO10_MV, - REG_ENABLE, MAX77686_MV); - - if (error) - printk(BIOS_CRIT, "%s: Error during PMIC setup\n", __func__); - - return error; -} - -static void initialize_s5p_mshc(void) -{ - /* MMC0: Fixed, 8 bit mode, connected with GPIO. */ - if (clock_set_mshci(PERIPH_ID_SDMMC0)) - printk(BIOS_CRIT, "Failed to set clock for SDMMC0.\n"); - if (gpio_direction_output(MMC0_GPIO_PIN, 1)) { - printk(BIOS_CRIT, "Unable to power on SDMMC0.\n"); - } - gpio_set_pull(MMC0_GPIO_PIN, EXYNOS_GPIO_PULL_NONE); - gpio_set_drv(MMC0_GPIO_PIN, EXYNOS_GPIO_DRV_4X); - exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE); - - /* MMC2: Removable, 4 bit mode, no GPIO. */ - clock_set_mshci(PERIPH_ID_SDMMC2); - exynos_pinmux_config(PERIPH_ID_SDMMC2, 0); -} - -static void graphics(void) -{ - exynos_pinmux_config(PERIPH_ID_DPHPD, 0); -} - -void main(void) -{ - struct mem_timings *mem; - struct arm_clk_ratios *arm_ratios; - int ret; - void *entry; - - clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ - - /* Clock must be initialized before console_init, otherwise you may need - * to re-initialize serial console drivers again. */ - mem = get_mem_timings(); - arm_ratios = get_arm_clk_ratios(); - system_clock_init(mem, arm_ratios); - - console_init(); - - i2c_set_early_reg(0x12c60000); - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - if (power_init()) - power_shutdown(); - if (setup_pmic()) - power_shutdown(); - - if (!mem) { - printk(BIOS_CRIT, "Unable to auto-detect memory timings\n"); - while(1); - } - printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n", - mem->mem_manuf, - mem->mem_type, - mem->mpll_mdiv, - mem->frequency_mhz); - - ret = ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE); - if (ret) { - printk(BIOS_ERR, "Memory controller init failed, err: %x\n", - ret); - while(1); - } - - initialize_s5p_mshc(); - - graphics(); - - entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram"); - printk(BIOS_INFO, "entry is 0x%p, leaving romstage.\n", entry); - - stage_exit(entry); -} diff --git a/src/mainboard/google/storm/Kconfig b/src/mainboard/google/storm/Kconfig new file mode 100644 index 0000000000..fabbf850f5 --- /dev/null +++ b/src/mainboard/google/storm/Kconfig @@ -0,0 +1,53 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_STORM + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_8192 + select CHROMEOS + select COMMON_CBFS_SPI_WRAPPER + select HAVE_HARD_RESET + select MAINBOARD_HAS_BOOTBLOCK_INIT + select RETURN_FROM_VERSTAGE + select SOC_QC_IPQ806X + select SPI_FLASH + select SPI_FLASH_SPANSION + +config BOARD_VARIANT_AP148 + bool "pick this to build an image for ap148" + default n + +config MAINBOARD_DIR + string + default google/storm + +config MAINBOARD_PART_NUMBER + string + default "AP148" if BOARD_VARIANT_AP148 + default "Storm" + +config DRAM_SIZE_MB + int + default 512 if BOARD_VARIANT_AP148 + default 1024 + +endif # BOARD_GOOGLE_STORM diff --git a/src/mainboard/google/storm/Makefile.inc b/src/mainboard/google/storm/Makefile.inc new file mode 100644 index 0000000000..bcd786865a --- /dev/null +++ b/src/mainboard/google/storm/Makefile.inc @@ -0,0 +1,40 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bootblock-y += cdp.c +bootblock-y += reset.c + +verstage-y += cdp.c +verstage-y += chromeos.c +verstage-y += memlayout.ld +verstage-y += reset.c + +romstage-y += romstage.c +romstage-y += cdp.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += cdp.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/storm/boardid.c b/src/mainboard/google/storm/boardid.c new file mode 100644 index 0000000000..c4f54a5186 --- /dev/null +++ b/src/mainboard/google/storm/boardid.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +/* + * Storm boards dedicate to the board ID three GPIOs in tertiary mode: 29, 30 + * and 68. On proto0 GPIO68 is used and tied low, so it reads as 'zero' by + * gpio_base3_value(), whereas the other two pins are not connected + * and read as 'two'. This results in gpio_base3_value() returning + * 8 on proto0. + * + * Three tertitiary signals could represent 27 different values. To make + * calculated board ID value continuous and starting at zero, offset the + * calculated value by 19 (i.e. 27 - 8) and return modulo 27 of the offset + * number. This results in proto0 returning zero as the board ID, the future + * revisions will have the inputs configured to match the actual board + * revision. + */ + +static int board_id_value = -1; + +static uint8_t get_board_id(void) +{ + uint8_t bid; + gpio_t hw_rev_gpios[] = {[2] = 68, [1] = 30, [0] = 29}; /* 29 is LSB */ + int offset = 19; + + bid = gpio_base3_value(hw_rev_gpios, ARRAY_SIZE(hw_rev_gpios)); + bid = (bid + offset) % 27; + printk(BIOS_INFO, "Board ID %d\n", bid); + + return bid; +} + +uint8_t board_id(void) +{ + if (board_id_value < 0) + board_id_value = get_board_id(); + + return board_id_value; +} diff --git a/src/mainboard/google/storm/cdp.c b/src/mainboard/google/storm/cdp.c new file mode 100644 index 0000000000..fd906891a1 --- /dev/null +++ b/src/mainboard/google/storm/cdp.c @@ -0,0 +1,368 @@ + +/* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */ + +#include +#include +#include +#include +#include +#include + +void ipq_configure_gpio(const gpio_func_data_t *gpio, unsigned count) +{ + int i; + + for (i = 0; i < count; i++) { + gpio_tlmm_config(gpio->gpio, gpio->func, gpio->dir, + gpio->pull, gpio->drvstr, gpio->enable); + gpio++; + } +} + +#if 0 +/* Watchdog bite time set to default reset value */ +#define RESET_WDT_BITE_TIME 0x31F3 + +/* Watchdog bark time value is ketp larger than the watchdog timeout + * of 0x31F3, effectively disabling the watchdog bark interrupt + */ +#define RESET_WDT_BARK_TIME (5 * RESET_WDT_BITE_TIME) + +/* + * If SMEM is not found, we provide a value, that will prevent the + * environment from being written to random location in the flash. + * + * NAND: In the case of NAND, we do this by setting ENV_RANGE to + * zero. If ENV_RANGE < ENV_SIZE, then environment is not written. + * + * SPI Flash: In the case of SPI Flash, we do this by setting the + * flash_index to -1. + */ + +loff_t board_env_offset; +loff_t board_env_range; +extern int nand_env_device; + +board_ipq806x_params_t *gboard_param; +extern int ipq_gmac_eth_initialize(const char *ethaddr); +uchar ipq_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD}; + +/******************************************************* +Function description: Board specific initialization. +I/P : None +O/P : integer, 0 - no error. + +********************************************************/ +static board_ipq806x_params_t *get_board_param(unsigned int machid) +{ + unsigned int index = 0; + + for (index = 0; index < NUM_IPQ806X_BOARDS; index++) { + if (machid == board_params[index].machid) + return &board_params[index]; + } + BUG_ON(index == NUM_IPQ806X_BOARDS); + printf("cdp: Invalid machine id 0x%x\n", machid); + for (;;); +} + +int board_init() +{ + int ret; + uint32_t start_blocks; + uint32_t size_blocks; + loff_t board_env_size; + ipq_smem_flash_info_t *sfi = &ipq_smem_flash_info; + + /* + * after relocation gboard_param is reset to NULL + * initialize again + */ + gd->bd->bi_boot_params = IPQ_BOOT_PARAMS_ADDR; + gd->bd->bi_arch_number = smem_get_board_machtype(); + gboard_param = get_board_param(gd->bd->bi_arch_number); + + /* + * Should be inited, before env_relocate() is called, + * since env. offset is obtained from SMEM. + */ + ret = smem_ptable_init(); + if (ret < 0) { + printf("cdp: SMEM init failed\n"); + return ret; + } + + ret = smem_get_boot_flash(&sfi->flash_type, + &sfi->flash_index, + &sfi->flash_chip_select, + &sfi->flash_block_size); + if (ret < 0) { + printf("cdp: get boot flash failed\n"); + return ret; + } + + if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) { + nand_env_device = CONFIG_IPQ_NAND_NAND_INFO_IDX; + } else if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) { + nand_env_device = CONFIG_IPQ_SPI_NAND_INFO_IDX; + } else { + printf("BUG: unsupported flash type : %d\n", sfi->flash_type); + BUG(); + } + + ret = smem_getpart("0:APPSBLENV", &start_blocks, &size_blocks); + if (ret < 0) { + printf("cdp: get environment part failed\n"); + return ret; + } + + board_env_offset = ((loff_t) sfi->flash_block_size) * start_blocks; + board_env_size = ((loff_t) sfi->flash_block_size) * size_blocks; + board_env_range = CONFIG_ENV_SIZE; + BUG_ON(board_env_size < CONFIG_ENV_SIZE); + + return 0; +} + +void enable_caches(void) +{ + icache_enable(); + /* When dcache is enabled it causes the tftp timeout CR is raised CR.No: 513868. + * disabing dcache now to make tftp to work */ +#if (CONFIG_IPQ_CACHE_ENABLE == 1) + dcache_enable(); +#endif +} + + +/******************************************************* +Function description: DRAM initialization. +I/P : None +O/P : integer, 0 - no error. + +********************************************************/ + +int dram_init(void) +{ + struct smem_ram_ptable rtable; + int i; + int mx = ARRAY_SIZE(rtable.parts); + + if (smem_ram_ptable_init(&rtable) > 0) { + gd->ram_size = 0; + for (i = 0; i < mx; i++) { + if (rtable.parts[i].category == RAM_PARTITION_SDRAM + && rtable.parts[i].type == RAM_PARTITION_SYS_MEMORY) { + gd->ram_size += rtable.parts[i].size; + } + } + gboard_param->ddr_size = gd->ram_size; + } else { + gd->ram_size = gboard_param->ddr_size; + } + return 0; +} + +/******************************************************* +Function description: initi Dram Bank size +I/P : None +O/P : integer, 0 - no error. + +********************************************************/ + + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = IPQ_KERNEL_START_ADDR; + gd->bd->bi_dram[0].size = gboard_param->ddr_size - GENERATED_IPQ_RESERVE_SIZE; + +} + +/********************************************************** +Function description: Display board information on console. +I/P : None +O/P : integer, 0 - no error. + +**********************************************************/ + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("Board: %s\n", sysinfo.board_string); + return 0; +} +#endif /* CONFIG_DISPLAY_BOARDINFO */ + +void reset_cpu(ulong addr) +{ + printf("\nResetting with watch dog!\n"); + + writel(0, APCS_WDT0_EN); + writel(1, APCS_WDT0_RST); + writel(RESET_WDT_BARK_TIME, APCS_WDT0_BARK_TIME); + writel(RESET_WDT_BITE_TIME, APCS_WDT0_BITE_TIME); + writel(1, APCS_WDT0_EN); + writel(1, APCS_WDT0_CPU0_WDOG_EXPIRED_ENABLE); + + for(;;); +} + +#endif + +static void configure_nand_gpio(void) +{ + /* EBI2 CS, CLE, ALE, WE, OE */ + gpio_tlmm_config(34, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(35, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(36, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(37, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(38, 1, 0, GPIO_NO_PULL, GPIO_10MA, GPIO_DISABLE); + + /* EBI2 BUSY */ + gpio_tlmm_config(39, 1, 0, GPIO_PULL_UP, GPIO_10MA, GPIO_DISABLE); + + /* EBI2 D7 - D0 */ + gpio_tlmm_config(40, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(41, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(42, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(43, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(44, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(45, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(46, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); + gpio_tlmm_config(47, 1, 0, GPIO_KEEPER, GPIO_10MA, GPIO_DISABLE); +} + +void board_nand_init(void) +{ + struct ebi2cr_regs *ebi2_regs; + + if (board_id() != BOARD_ID_PROTO_0_2_NAND) + return; + + ebi2_regs = (struct ebi2cr_regs *) EBI2CR_BASE; + + nand_clock_config(); + configure_nand_gpio(); + + /* NAND Flash is connected to CS0 */ + clrsetbits_le32(&ebi2_regs->chip_select_cfg0, CS0_CFG_MASK, + CS0_CFG_SERIAL_FLASH_DEVICE); +} + +#if 0 + +void ipq_get_part_details(void) +{ + int ret, i; + uint32_t start; /* block number */ + uint32_t size; /* no. of blocks */ + + ipq_smem_flash_info_t *smem = &ipq_smem_flash_info; + + struct { char *name; ipq_part_entry_t *part; } entries[] = { + { "0:HLOS", &smem->hlos }, + { "0:NSS0", &smem->nss[0] }, + { "0:NSS1", &smem->nss[1] }, + }; + + for (i = 0; i < ARRAY_SIZE(entries); i++) { + ret = smem_getpart(entries[i].name, &start, &size); + if (ret < 0) { + ipq_part_entry_t *part = entries[i].part; + printf("cdp: get part failed for %s\n", entries[i].name); + part->offset = 0xBAD0FF5E; + part->size = 0xBAD0FF5E; + } + ipq_set_part_entry(smem, entries[i].part, start, size); + } + + return; +} + +/* + * Get the kernel partition details from SMEM and populate the, + * environment with sufficient information for the boot command to + * load and execute the kernel. + */ +int board_late_init(void) +{ + unsigned int machid; + + ipq_get_part_details(); + + /* get machine type from SMEM and set in env */ + machid = gd->bd->bi_arch_number; + if (machid != 0) { + setenv_addr("machid", (void *)machid); + gd->bd->bi_arch_number = machid; + } + + return 0; +} + +/* + * This function is called in the very beginning. + * Retreive the machtype info from SMEM and map the board specific + * parameters. Shared memory region at Dram address 0x40400000 + * contains the machine id/ board type data polulated by SBL. + */ +int board_early_init_f(void) +{ + gboard_param = get_board_param(smem_get_board_machtype()); + + return 0; +} + +/* + * Gets the ethernet address from the ART partition table and return the value + */ +int get_eth_mac_address(uchar *enetaddr, uint no_of_macs) +{ + s32 ret; + u32 start_blocks; + u32 size_blocks; + u32 length = (6 * no_of_macs); + u32 flash_type; + loff_t art_offset; + + if (ipq_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH) + flash_type = CONFIG_IPQ_SPI_NAND_INFO_IDX; + else if (ipq_smem_flash_info.flash_type == SMEM_BOOT_NAND_FLASH) + flash_type = CONFIG_IPQ_NAND_NAND_INFO_IDX; + else { + printf("Unknown flash type\n"); + return -EINVAL; + } + + ret = smem_getpart("0:ART", &start_blocks, &size_blocks); + if (ret < 0) { + printf("No ART partition found\n"); + return ret; + } + + /* + * ART partition 0th position (6 * 4) 24 bytes will contain the + * 4 MAC Address. First 0-5 bytes for GMAC0, Second 6-11 bytes + * for GMAC1, 12-17 bytes for GMAC2 and 18-23 bytes for GMAC3 + */ + art_offset = ((loff_t) ipq_smem_flash_info.flash_block_size * start_blocks); + + ret = nand_read(&nand_info[flash_type], art_offset, &length, enetaddr); + if (ret < 0) + printf("ART partition read failed..\n"); + return ret; +} + +int board_eth_init(bd_t *bis) +{ + int status; + + ipq_gmac_common_init(gboard_param->gmac_cfg); + + ipq_configure_gpio(gboard_param->gmac_gpio, + gboard_param->gmac_gpio_count); + + status = ipq_gmac_init(gboard_param->gmac_cfg); + return status; +} +#endif diff --git a/src/mainboard/google/storm/chromeos.c b/src/mainboard/google/storm/chromeos.c new file mode 100644 index 0000000000..819aab558c --- /dev/null +++ b/src/mainboard/google/storm/chromeos.c @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define FAKE_GPIO_NUM -1 + +struct gpio_desc { + gpio_t gpio_num; + const char *gpio_name; + uint32_t fake_value; +}; + +/* Actual GPIO switch names */ +#define DEVELOPER_GPIO_NAME "developer" +#define RECOVERY_GPIO_NAME "recovery" +#define WRITE_PROTECT_GPIO_NAME "write protect" + +static const struct gpio_desc descriptors[] = { + { 15, DEVELOPER_GPIO_NAME }, + { 16, RECOVERY_GPIO_NAME }, + { 17, WRITE_PROTECT_GPIO_NAME }, + { FAKE_GPIO_NUM, "power", 1 }, /* Power never pressed. */ + { FAKE_GPIO_NUM, "lid", 0 } /* Lid always open. */ +}; + +static void fill_lb_gpio(struct lb_gpio *pgpio, const struct gpio_desc *pdesc) +{ + gpio_t gpio_num = pdesc->gpio_num; + + pgpio->port = gpio_num; + if (gpio_num == FAKE_GPIO_NUM) { + pgpio->value = pdesc->fake_value; + } else { + gpio_tlmm_config_set(gpio_num, GPIO_FUNC_DISABLE, + GPIO_NO_PULL, GPIO_2MA, GPIO_DISABLE); + udelay(10); /* Should be enough to settle. */ + pgpio->value = gpio_get(gpio_num); + } + pgpio->polarity = ACTIVE_LOW; + strncpy((char *)pgpio->name, pdesc->gpio_name, sizeof(pgpio->name)); + + printk(BIOS_INFO, "%s: %s: port %d value %d\n", + __func__, pgpio->name, pgpio->port, pgpio->value); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(descriptors); i++) + fill_lb_gpio(gpios->gpios + i, descriptors + i); + + + gpios->size = sizeof(*gpios) + sizeof(struct lb_gpio) * i; + gpios->count = i; +} + +static int get_switch_value(const char *switch_name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(descriptors); i++) + if (!strcmp(descriptors[i].gpio_name, switch_name)) { + struct lb_gpio gpio; + + fill_lb_gpio(&gpio, descriptors + i); + return gpio.value ^ !gpio.polarity; + } + return -1; +} + +int get_developer_mode_switch(void) +{ + return get_switch_value(DEVELOPER_GPIO_NAME); +} + +int get_recovery_mode_switch(void) +{ + return get_switch_value(RECOVERY_GPIO_NAME); +} + +int get_write_protect_state(void) +{ + return get_switch_value(WRITE_PROTECT_GPIO_NAME); +} + diff --git a/src/mainboard/google/storm/devicetree.cb b/src/mainboard/google/storm/devicetree.cb new file mode 100644 index 0000000000..40ba9c8775 --- /dev/null +++ b/src/mainboard/google/storm/devicetree.cb @@ -0,0 +1,22 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +chip soc/qualcomm/ipq806x + device cpu_cluster 0 on end +end diff --git a/src/mainboard/google/storm/mainboard.c b/src/mainboard/google/storm/mainboard.c new file mode 100644 index 0000000000..c1d5fac2ad --- /dev/null +++ b/src/mainboard/google/storm/mainboard.c @@ -0,0 +1,145 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* convenient shorthand (in MB) */ +#define DRAM_START ((uintptr_t)_dram / MiB) +#define DRAM_SIZE (CONFIG_DRAM_SIZE_MB) +#define DRAM_END (DRAM_START + DRAM_SIZE) + +/* DMA memory for drivers */ +#define DMA_START ((uintptr_t)_dma_coherent / MiB) +#define DMA_SIZE (_dma_coherent_size / MiB) + +#define USB_ENABLE_GPIO 51 + +static void setup_usb(void) +{ +#if !CONFIG_BOARD_VARIANT_AP148 + gpio_tlmm_config_set(USB_ENABLE_GPIO, FUNC_SEL_GPIO, + GPIO_PULL_UP, GPIO_10MA, GPIO_ENABLE); + gpio_set(USB_ENABLE_GPIO, 1); +#endif + usb_clock_config(); + + setup_usb_host1(); +} + +static void setup_mmu(void) +{ + dcache_mmu_disable(); + + /* Map Device memory. */ + mmu_config_range(0, DRAM_START, DCACHE_OFF); + /* Disable Page 0 for trapping NULL pointer references. */ + mmu_disable_range(0, 1); + /* Map DRAM memory */ + mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK); + /* Map DMA memory */ + mmu_config_range(DMA_START, DMA_SIZE, DCACHE_OFF); + + mmu_disable_range(DRAM_END, 4096 - DRAM_END); + + mmu_init(); + + dcache_mmu_enable(); +} + +#define TPM_RESET_GPIO 22 +static void setup_tpm(void) +{ + if (board_id() != BOARD_ID_PROTO_0) + return; /* Only proto0 have TPM reset connected to GPIO22 */ + + gpio_tlmm_config_set(TPM_RESET_GPIO, FUNC_SEL_GPIO, GPIO_PULL_UP, + GPIO_4MA, GPIO_ENABLE); + /* + * Generate a reset pulse. The spec calls for 80 us minimum, let's + * make it twice as long. If the output was driven low originally, the + * reset pulse will be even longer. + */ + gpio_set(TPM_RESET_GPIO, 0); + udelay(160); + gpio_set(TPM_RESET_GPIO, 1); +} + +#define SW_RESET_GPIO 26 +static void assert_sw_reset(void) +{ + if (board_id() == BOARD_ID_PROTO_0) + return; + + /* + * only proto0.2 and later care about this. We want to keep the + * ethernet switch in reset, otherwise it comes up in default + * (bridging) mode. + */ + gpio_tlmm_config_set(SW_RESET_GPIO, FUNC_SEL_GPIO, + GPIO_PULL_UP, GPIO_4MA, GPIO_ENABLE); + + gpio_set(SW_RESET_GPIO, 1); +} + +static void mainboard_init(device_t dev) +{ + setup_mmu(); + setup_usb(); + assert_sw_reset(); + setup_tpm(); + /* Functionally a 0-cost no-op if NAND is not present */ + board_nand_init(); + + /* Copy WIFI calibration data into CBMEM. */ + cbmem_add_vpd_calibration_data(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .name = "storm", + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; + + /* Retrieve the switch interface MAC addressses. */ + lb_table_add_macs_from_vpd(header); +} diff --git a/src/mainboard/google/storm/memlayout.ld b/src/mainboard/google/storm/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/storm/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/storm/reset.c b/src/mainboard/google/storm/reset.c new file mode 100644 index 0000000000..8020fbfbed --- /dev/null +++ b/src/mainboard/google/storm/reset.c @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +void hard_reset(void) +{ + while (1) + ; +} diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/storm/romstage.c similarity index 60% rename from src/mainboard/google/snow/bootblock.c rename to src/mainboard/google/storm/romstage.c index 17a3267a6e..37142fd7f1 100644 --- a/src/mainboard/google/snow/bootblock.c +++ b/src/mainboard/google/storm/romstage.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 The ChromiumOS Authors. All rights reserved. + * Copyright 2014 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,23 +17,26 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include +#include #include -#include +#include #include -#include -#include +#include +#include -#define I2C0_BASE 0x12c60000 - -void bootblock_mainboard_init(void); -void bootblock_mainboard_init(void) +void main(void) { - exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); -#if CONFIG_EARLY_CONSOLE - exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); + void *entry; + + cbmem_initialize(); console_init(); - printk(BIOS_INFO, "\n\n\n%s: UART initialized\n", __func__); + +#if CONFIG_VBOOT2_VERIFY_FIRMWARE + entry = vboot2_load_ramstage(); +#else + vboot_verify_firmware(romstage_handoff_find_or_add()); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage"); #endif + + stage_exit(entry); } diff --git a/src/mainboard/google/stout/Kconfig b/src/mainboard/google/stout/Kconfig index a15d9335ae..de39c66277 100644 --- a/src/mainboard/google/stout/Kconfig +++ b/src/mainboard/google/stout/Kconfig @@ -2,7 +2,6 @@ if BOARD_GOOGLE_STOUT config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 @@ -15,6 +14,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_SMI_HANDLER select GFXUMA select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB config MAINBOARD_DIR diff --git a/src/mainboard/google/stout/chromeos.c b/src/mainboard/google/stout/chromeos.c index 7a861ec191..4442d43a04 100644 --- a/src/mainboard/google/stout/chromeos.c +++ b/src/mainboard/google/stout/chromeos.c @@ -32,8 +32,6 @@ #include #define GPIO_COUNT 7 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 static int ec_in_rec_mode; static int ec_rec_flag_good; diff --git a/src/mainboard/google/stout/mainboard.c b/src/mainboard/google/stout/mainboard.c index 4af0ff5cf3..7f6b7ddd07 100644 --- a/src/mainboard/google/stout/mainboard.c +++ b/src/mainboard/google/stout/mainboard.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2011 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -49,15 +49,15 @@ void mainboard_suspend_resume(void) ec_write_cmd(EC_CMD_NOTIFY_ACPI_ENTER); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - int res=-1; + int res = 0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); + __func__, X86_AX); - switch(regs->eax & 0xffff) { + switch(X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -66,11 +66,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x00; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CL = 0x00; /* Use video bios default */ + res = 1; break; case 0x5f35: /* @@ -84,11 +82,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; /* Use video bios default */ - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; /* Use video bios default */ + res = 1; break; case 0x5f51: /* @@ -98,148 +94,46 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0001; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch (X86_CH) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + X86_CH); + break; } break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CL = 0x00; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) - * bit 2 = EFP - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) - * bit 6 = EFP2 - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; /* Use video bios default */ - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 1; - break; - case 0x5f70: - switch (M.x86.R_CH) { - case 0: - /* Get Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CL = 0; - break; - case 1: - /* Set Mux */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - case 2: - /* Get SG/Non-SG mode */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - M.x86.R_CH); - return 0; - } - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 * cim_verb_data; @@ -280,9 +174,9 @@ static void mainboard_init(device_t dev) static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/google/stout/mainboard_smi.c b/src/mainboard/google/stout/mainboard_smi.c index 79810466c6..29ea8f233e 100644 --- a/src/mainboard/google/stout/mainboard_smi.c +++ b/src/mainboard/google/stout/mainboard_smi.c @@ -73,7 +73,7 @@ static u8 mainboard_smi_ec(void) return cmd; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { if (gpi_sts & (1 << EC_SMI_GPI)) { /* Process all pending events */ diff --git a/src/mainboard/google/stout/romstage.c b/src/mainboard/google/stout/romstage.c index 14820ddc65..e1d85d7db5 100644 --- a/src/mainboard/google/stout/romstage.c +++ b/src/mainboard/google/stout/romstage.c @@ -158,15 +158,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { pei_version: PEI_VERSION, mchbar: DEFAULT_MCHBAR, @@ -218,9 +216,7 @@ void main(unsigned long bist) }, }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -290,14 +286,13 @@ void main(unsigned long bist) post_code(0x3a); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3b); /* Perform some initialization that must run before stage2 */ early_pch_init(); @@ -345,15 +340,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/google/urara/Kconfig b/src/mainboard/google/urara/Kconfig new file mode 100644 index 0000000000..16a09fe34c --- /dev/null +++ b/src/mainboard/google/urara/Kconfig @@ -0,0 +1,54 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +if BOARD_GOOGLE_URARA + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOOTBLOCK_CONSOLE + select CHROMEOS + select SPI_FLASH_WINBOND + select CPU_IMGTEC_PISTACHIO + select COMMON_CBFS_SPI_WRAPPER + select MAINBOARD_HAS_BOOTBLOCK_INIT + select SPI_FLASH + +config MAINBOARD_DIR + string + default "google/urara" + +config MAINBOARD_PART_NUMBER + string + default "ImgTec Pistachio Virtual Platform" + +config DRAM_SIZE_MB + int + default 256 + +config TTYS0_LCS + int + default 3 + +config BOOT_MEDIA_SPI_BUS + int "SPI bus for boot media" + default 1 + +endif diff --git a/src/mainboard/google/urara/Makefile.inc b/src/mainboard/google/urara/Makefile.inc new file mode 100644 index 0000000000..00c62e8046 --- /dev/null +++ b/src/mainboard/google/urara/Makefile.inc @@ -0,0 +1,27 @@ +# +# This file is part of the coreboot project. +# +# Copyright 2014 Imagination Technologies Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +ramstage-y += chromeos.c +ramstage-y += mainboard.c + +bootblock-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/urara/chromeos.c b/src/mainboard/google/urara/chromeos.c new file mode 100644 index 0000000000..cc8c79bfe1 --- /dev/null +++ b/src/mainboard/google/urara/chromeos.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + printk(BIOS_ERR, "%s unsupported, but called\n", __func__); +} diff --git a/src/mainboard/google/urara/devicetree.cb b/src/mainboard/google/urara/devicetree.cb new file mode 100644 index 0000000000..e3eb091027 --- /dev/null +++ b/src/mainboard/google/urara/devicetree.cb @@ -0,0 +1,27 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +chip soc/imgtec/pistachio + device cpu_cluster 0 on end + chip drivers/generic/generic # I2C0 controller + device i2c 6 on end # Fake component for testing + end +end diff --git a/src/mainboard/google/urara/mainboard.c b/src/mainboard/google/urara/mainboard.c new file mode 100644 index 0000000000..1909fc861f --- /dev/null +++ b/src/mainboard/google/urara/mainboard.c @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +static void mainboard_enable(device_t dev) +{ + printk(BIOS_INFO, "Enable Pistachio device...\n"); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/google/urara/memlayout.ld b/src/mainboard/google/urara/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/urara/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_brain/Kconfig b/src/mainboard/google/veyron_brain/Kconfig new file mode 100644 index 0000000000..7a7f8b5ce3 --- /dev/null +++ b/src/mainboard/google/veyron_brain/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_BRAIN + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_brain + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Brain" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Brain, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_BRAIN diff --git a/src/mainboard/google/veyron_brain/Makefile.inc b/src/mainboard/google/veyron_brain/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_brain/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_brain/board.h b/src/mainboard/google/veyron_brain/board.h new file mode 100644 index 0000000000..6e6a62c834 --- /dev/null +++ b/src/mainboard/google/veyron_brain/board.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_BRAIN_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_BRAIN_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_BRAIN_BOARD_H */ diff --git a/src/mainboard/google/veyron_brain/boardid.c b/src/mainboard/google/veyron_brain/boardid.c new file mode 100644 index 0000000000..513754f048 --- /dev/null +++ b/src/mainboard/google/veyron_brain/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_brain/bootblock.c b/src/mainboard/google/veyron_brain/bootblock.c new file mode 100644 index 0000000000..57c76f8efc --- /dev/null +++ b/src/mainboard/google/veyron_brain/bootblock.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + gpio_output(GPIO(7, A, 0), 1); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_brain/chromeos.c b/src/mainboard/google/veyron_brain/chromeos.c new file mode 100644 index 0000000000..14f078c81b --- /dev/null +++ b/src/mainboard/google/veyron_brain/chromeos.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_brain/devicetree.cb b/src/mainboard/google/veyron_brain/devicetree.cb new file mode 100644 index 0000000000..49d9f12626 --- /dev/null +++ b/src/mainboard/google/veyron_brain/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_HDMI" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_brain/mainboard.c b/src/mainboard/google/veyron_brain/mainboard.c new file mode 100644 index 0000000000..00110be94e --- /dev/null +++ b/src/mainboard/google/veyron_brain/mainboard.c @@ -0,0 +1,129 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USB2_PWR_EN */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); +} + +static void configure_hdmi(void) +{ + rk808_configure_switch(2, 1); /* VCC18_LCD (HDMI_AVDD_1V8) */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD (HDMI_AVDD_1V0) */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* set POWER_HDMI_ON */ + gpio_output(GPIO(7, A, 2), 1); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_emmc(); + configure_codec(); + configure_vop(); + configure_hdmi(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + return; +} diff --git a/src/mainboard/google/veyron_brain/memlayout.ld b/src/mainboard/google/veyron_brain/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_brain/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_brain/reset.c b/src/mainboard/google/veyron_brain/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_brain/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_brain/romstage.c b/src/mainboard/google/veyron_brain/romstage.c new file mode 100644 index 0000000000..65d353a5e3 --- /dev/null +++ b/src/mainboard/google/veyron_brain/romstage.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_brain/sdram_configs.c b/src/mainboard/google/veyron_brain/sdram_configs.c new file mode 100644 index 0000000000..19e46d308d --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_configs.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry and Mighty cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_brain/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_brain/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_brain/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_danger/Kconfig b/src/mainboard/google/veyron_danger/Kconfig new file mode 100644 index 0000000000..0e282bf71e --- /dev/null +++ b/src/mainboard/google/veyron_danger/Kconfig @@ -0,0 +1,82 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_DANGER + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + +config MAINBOARD_DIR + string + default google/veyron_danger + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Danger" + +config MAINBOARD_VENDOR + string + default "Google" + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRAM_SIZE_MB + int + default 2048 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_DANGER diff --git a/src/mainboard/google/veyron_danger/Makefile.inc b/src/mainboard/google/veyron_danger/Makefile.inc new file mode 100644 index 0000000000..aa8aa3ceb7 --- /dev/null +++ b/src/mainboard/google/veyron_danger/Makefile.inc @@ -0,0 +1,43 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdmmc.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c +ramstage-y += sdmmc.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_danger/board.h b/src/mainboard/google/veyron_danger/board.h new file mode 100644 index 0000000000..2301aade40 --- /dev/null +++ b/src/mainboard/google/veyron_danger/board.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_DANGER_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_DANGER_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 3) +#define GPIO_RESET GPIO(0, B, 5) +#define GPIO_LCDC_BL GPIO(7, A, 7) + +void sdmmc_power_off(void); +void sdmmc_power_on(void); +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_DANGER_BOARD_H */ diff --git a/src/mainboard/google/veyron_danger/boardid.c b/src/mainboard/google/veyron_danger/boardid.c new file mode 100644 index 0000000000..ea67c7266a --- /dev/null +++ b/src/mainboard/google/veyron_danger/boardid.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; +#if 0 + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); +#endif + code = 0; + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_danger/bootblock.c b/src/mainboard/google/veyron_danger/bootblock.c new file mode 100644 index 0000000000..7ff5b78a07 --- /dev/null +++ b/src/mainboard/google/veyron_danger/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + gpio_output(GPIO(7, A, 0), 1); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + if (rkclk_was_watchdog_reset()) { + printk(BIOS_INFO, "Last reset was watchdog... rebooting via GPIO!\n"); + hard_reset(); + } + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 11*MHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_danger/chromeos.c b/src/mainboard/google/veyron_danger/chromeos.c new file mode 100644 index 0000000000..82f3e7a7cd --- /dev/null +++ b/src/mainboard/google/veyron_danger/chromeos.c @@ -0,0 +1,105 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_DEV_MODE GPIO(7, B, 2) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input(GPIO_DEV_MODE); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: Danger has a physical dev switch that is active low */ + gpios->gpios[count].port = GPIO_DEV_MODE.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return !gpio_get(GPIO_DEV_MODE); +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_danger/devicetree.cb b/src/mainboard/google/veyron_danger/devicetree.cb new file mode 100644 index 0000000000..1c70b57bf4 --- /dev/null +++ b/src/mainboard/google/veyron_danger/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_AUTO_DETECT" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_danger/mainboard.c b/src/mainboard/google/veyron_danger/mainboard.c new file mode 100644 index 0000000000..808cfafba6 --- /dev/null +++ b/src/mainboard/google/veyron_danger/mainboard.c @@ -0,0 +1,185 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + sdmmc_power_on(); + + gpio_input(GPIO(7, A, 5)); /* SDMMC_DET_L */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + /* + * BL_EN gates VCC_LCD. This might be changed in future revisions + * of the board so that the display can be stablized before we + * turn on the backlight. + * + * To minimize display corruption, turn off LCDC_BL before + * powering on the backlight. + */ + switch (board_id()) { + case 0: + gpio_output(GPIO(7, A, 3), 1); + break; + default: + gpio_output(GPIO(7, A, 2), 1); + break; + } + + gpio_output(GPIO_LCDC_BL, 0); + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* EDP_HPD setup */ + switch (board_id()) { + case 0: + /* not present */ + break; + default: + /* Unlike other Veyrons, Danger has external pull resistors on + * EDP_HPD. Default for GPIO(7, B, 3) is pull-down, set to + * float. + */ + gpio_input(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); + break; + } +} + +static void configure_hdmi(void) +{ + rk808_configure_switch(2, 1); /* VCC18_LCD (HDMI_AVDD_1V8) */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD (HDMI_AVDD_1V0) */ + + /* set POWER_HDMI_EN */ + switch (board_id()) { + case 0: + gpio_output(GPIO(7, A, 2), 1); + break; + default: + gpio_output(GPIO(5, C, 3), 1); + break; + } +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + configure_hdmi(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO_LCDC_BL, 1); +} diff --git a/src/mainboard/google/veyron_danger/memlayout.ld b/src/mainboard/google/veyron_danger/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_danger/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_danger/reset.c b/src/mainboard/google/veyron_danger/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_danger/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_danger/romstage.c b/src/mainboard/google/veyron_danger/romstage.c new file mode 100644 index 0000000000..291fd6c923 --- /dev/null +++ b/src/mainboard/google/veyron_danger/romstage.c @@ -0,0 +1,121 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + CONFIG_DRAM_SIZE_MB, DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_danger/sdmmc.c b/src/mainboard/google/veyron_danger/sdmmc.c new file mode 100644 index 0000000000..b60f2e6a73 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdmmc.c @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "board.h" + +#include + +static void sdmmc_power(int enable) +{ + switch (board_id()) { + case 0: + /* VCC33_SD is tied to VCC33_SYS and is always on */ + break; + default: + rk808_configure_ldo(4, enable ? 3300 : 0); /* VCC33_SD_LDO */ + rk808_configure_ldo(5, enable ? 3300 : 0); /* VCCIO_SD */ + break; + } +} + +void sdmmc_power_off(void) +{ + sdmmc_power(0); +} + +void sdmmc_power_on(void) +{ + sdmmc_power(1); +} diff --git a/src/mainboard/google/veyron_danger/sdram_configs.c b/src/mainboard/google/veyron_danger/sdram_configs.c new file mode 100644 index 0000000000..b1a546a43b --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_configs.c @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry, Mighty, Danger and Rialto + * cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode; + + /* early boards had incorrect config */ + if (board_id() == 0) + return &sdram_configs[0]; + + ramcode = ram_code(); + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_danger/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_danger/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_danger/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_fievel/Kconfig b/src/mainboard/google/veyron_fievel/Kconfig new file mode 100644 index 0000000000..07414abf79 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_FIEVEL + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_fievel + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Fievel" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Fievel, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_FIEVEL diff --git a/src/mainboard/google/veyron_fievel/Makefile.inc b/src/mainboard/google/veyron_fievel/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_fievel/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_fievel/board.h b/src/mainboard/google/veyron_fievel/board.h new file mode 100644 index 0000000000..56e8e1b60b --- /dev/null +++ b/src/mainboard/google/veyron_fievel/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_FIEVEL_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_FIEVEL_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) +#define GPIO_BACKLIGHT GPIO(7, A, 2) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_FIEVEL_BOARD_H */ diff --git a/src/mainboard/google/veyron_fievel/boardid.c b/src/mainboard/google/veyron_fievel/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_fievel/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_fievel/bootblock.c b/src/mainboard/google/veyron_fievel/bootblock.c new file mode 100644 index 0000000000..5e15b4f637 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/bootblock.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + gpio_output(GPIO(7, A, 3), 0); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_fievel/chromeos.c b/src/mainboard/google/veyron_fievel/chromeos.c new file mode 100644 index 0000000000..068c379a0c --- /dev/null +++ b/src/mainboard/google/veyron_fievel/chromeos.c @@ -0,0 +1,111 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_fievel/devicetree.cb b/src/mainboard/google/veyron_fievel/devicetree.cb new file mode 100644 index 0000000000..49d9f12626 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_HDMI" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_fievel/mainboard.c b/src/mainboard/google/veyron_fievel/mainboard.c new file mode 100644 index 0000000000..2e1424f9a5 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/mainboard.c @@ -0,0 +1,157 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void enable_5v_drv(void) +{ + /* EN pin of NB679 for USB, Speaker, HDMI, TouchScreen*/ + gpio_output(GPIO(7, C, 5), 1); +} + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USB_OTG_PWR_EN */ + gpio_output(GPIO(5, C, 2), 1); /* HUB_USB1_PWR_EN */ + gpio_output(GPIO(5, B, 6), 1); /* HUB_USB2_PWR_EN */ + gpio_output(GPIO(5, B, 4), 1); /* USB_OTG_CTL1 */ + gpio_output(GPIO(5, C, 1), 1); /* HUB_USB1_CTL1 */ + gpio_output(GPIO(5, B, 5), 1); /* HUB_USB2_CTL1 */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + rk808_configure_ldo(2, 1800); /* VCC18_LCD */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD */ + rk808_configure_switch(1, 1); /* LCDC33_VDD */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void configure_hdmi(void) +{ + /* HDMI I2C */ + writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda); + writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl); + + gpio_output(GPIO(5, C, 3), 1); /* VCC50_HDMI_EN */ +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + gpio_output(GPIO(7, A, 5), 0); /* Init buzzer gpio for depthcharge */ + + enable_5v_drv(); + configure_usb(); + configure_emmc(); + configure_codec(); + configure_vop(); + configure_hdmi(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; + + /* Retrieve the on-board Ethernet MAC address. */ + lb_table_add_macs_from_vpd(header); +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL_PWM */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_fievel/memlayout.ld b/src/mainboard/google/veyron_fievel/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_fievel/reset.c b/src/mainboard/google/veyron_fievel/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_fievel/romstage.c b/src/mainboard/google/veyron_fievel/romstage.c new file mode 100644 index 0000000000..65d353a5e3 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/romstage.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_fievel/sdram_configs.c b/src/mainboard/google/veyron_fievel/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_fievel/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_fievel/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_gus/Kconfig b/src/mainboard/google/veyron_gus/Kconfig new file mode 100644 index 0000000000..15c7be3d5d --- /dev/null +++ b/src/mainboard/google/veyron_gus/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_GUS + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_gus + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Gus" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_GUS diff --git a/src/mainboard/google/veyron_gus/Makefile.inc b/src/mainboard/google/veyron_gus/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_gus/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_gus/board.h b/src/mainboard/google/veyron_gus/board.h new file mode 100644 index 0000000000..29b2b9b23d --- /dev/null +++ b/src/mainboard/google/veyron_gus/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_GUS_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_GUS_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_GUS_BOARD_H */ diff --git a/src/mainboard/google/veyron_gus/boardid.c b/src/mainboard/google/veyron_gus/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_gus/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_gus/bootblock.c b/src/mainboard/google/veyron_gus/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_gus/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_gus/chromeos.c b/src/mainboard/google/veyron_gus/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_gus/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_gus/devicetree.cb b/src/mainboard/google/veyron_gus/devicetree.cb new file mode 100644 index 0000000000..59a18267aa --- /dev/null +++ b/src/mainboard/google/veyron_gus/devicetree.cb @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_gus/mainboard.c b/src/mainboard/google/veyron_gus/mainboard.c new file mode 100644 index 0000000000..f762eb3515 --- /dev/null +++ b/src/mainboard/google/veyron_gus/mainboard.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_gus/memlayout.ld b/src/mainboard/google/veyron_gus/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_gus/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_gus/reset.c b/src/mainboard/google/veyron_gus/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_gus/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_gus/romstage.c b/src/mainboard/google/veyron_gus/romstage.c new file mode 100644 index 0000000000..293e1e2710 --- /dev/null +++ b/src/mainboard/google/veyron_gus/romstage.c @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Increase frequency in RW in case it was set up too low by old RO. */ + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_gus/sdram_configs.c b/src/mainboard/google/veyron_gus/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_gus/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_gus/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_gus/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_jaq/Kconfig b/src/mainboard/google/veyron_jaq/Kconfig new file mode 100644 index 0000000000..ad4b7f295d --- /dev/null +++ b/src/mainboard/google/veyron_jaq/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_JAQ + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_jaq + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Jaq" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_JAQ diff --git a/src/mainboard/google/veyron_jaq/Makefile.inc b/src/mainboard/google/veyron_jaq/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_jaq/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_jaq/board.h b/src/mainboard/google/veyron_jaq/board.h new file mode 100644 index 0000000000..7920746069 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_JAQ_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_JAQ_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_JAQ_BOARD_H */ diff --git a/src/mainboard/google/veyron_jaq/boardid.c b/src/mainboard/google/veyron_jaq/boardid.c new file mode 100644 index 0000000000..513754f048 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_jaq/bootblock.c b/src/mainboard/google/veyron_jaq/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_jaq/chromeos.c b/src/mainboard/google/veyron_jaq/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_jaq/devicetree.cb b/src/mainboard/google/veyron_jaq/devicetree.cb new file mode 100644 index 0000000000..59a18267aa --- /dev/null +++ b/src/mainboard/google/veyron_jaq/devicetree.cb @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_jaq/mainboard.c b/src/mainboard/google/veyron_jaq/mainboard.c new file mode 100644 index 0000000000..f762eb3515 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/mainboard.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_jaq/memlayout.ld b/src/mainboard/google/veyron_jaq/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_jaq/reset.c b/src/mainboard/google/veyron_jaq/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_jaq/romstage.c b/src/mainboard/google/veyron_jaq/romstage.c new file mode 100644 index 0000000000..293e1e2710 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/romstage.c @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Increase frequency in RW in case it was set up too low by old RO. */ + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_jaq/sdram_configs.c b/src/mainboard/google/veyron_jaq/sdram_configs.c new file mode 100644 index 0000000000..19e46d308d --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_configs.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry and Mighty cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jaq/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_jaq/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_jerry/Kconfig b/src/mainboard/google/veyron_jerry/Kconfig new file mode 100644 index 0000000000..836101306c --- /dev/null +++ b/src/mainboard/google/veyron_jerry/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_JERRY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_jerry + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Jerry" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_JERRY diff --git a/src/mainboard/google/veyron_jerry/Makefile.inc b/src/mainboard/google/veyron_jerry/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_jerry/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_jerry/board.h b/src/mainboard/google/veyron_jerry/board.h new file mode 100644 index 0000000000..bf00b1b3e5 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_JERRY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_JERRY_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_JERRY_BOARD_H */ diff --git a/src/mainboard/google/veyron_jerry/boardid.c b/src/mainboard/google/veyron_jerry/boardid.c new file mode 100644 index 0000000000..513754f048 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_jerry/bootblock.c b/src/mainboard/google/veyron_jerry/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_jerry/chromeos.c b/src/mainboard/google/veyron_jerry/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_jerry/devicetree.cb b/src/mainboard/google/veyron_jerry/devicetree.cb new file mode 100644 index 0000000000..97b63d177e --- /dev/null +++ b/src/mainboard/google/veyron_jerry/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_EDP" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_jerry/mainboard.c b/src/mainboard/google/veyron_jerry/mainboard.c new file mode 100644 index 0000000000..1c1b70d036 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/mainboard.c @@ -0,0 +1,167 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + switch (board_id()) { + case 2: + rk808_configure_switch(2, 1); /* VCC18_LCD */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + break; + default: + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); + break; + } +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + switch (board_id()) { + case 2: + gpio_output(GPIO(7, A, 0), 0); /* BL_EN */ + gpio_output(GPIO(7, A, 2), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO(7, A, 0), 1); /* BL_EN */ + break; + default: + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(120); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ + break; + } +} diff --git a/src/mainboard/google/veyron_jerry/memlayout.ld b/src/mainboard/google/veyron_jerry/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_jerry/reset.c b/src/mainboard/google/veyron_jerry/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_jerry/romstage.c b/src/mainboard/google/veyron_jerry/romstage.c new file mode 100644 index 0000000000..293e1e2710 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/romstage.c @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Increase frequency in RW in case it was set up too low by old RO. */ + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_jerry/sdram_configs.c b/src/mainboard/google/veyron_jerry/sdram_configs.c new file mode 100644 index 0000000000..19e46d308d --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_configs.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry and Mighty cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_jerry/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_jerry/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_mickey/Kconfig b/src/mainboard/google/veyron_mickey/Kconfig new file mode 100644 index 0000000000..956cd40874 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_MICKEY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_mickey + +config MAINBOARD_PART_NUMBER + string + default "Veyron_mickey" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Mickey, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_MICKEY diff --git a/src/mainboard/google/veyron_mickey/Makefile.inc b/src/mainboard/google/veyron_mickey/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_mickey/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_mickey/board.h b/src/mainboard/google/veyron_mickey/board.h new file mode 100644 index 0000000000..f0f4f71fb6 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/board.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_MICKEY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_MICKEY_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_MICKEY_BOARD_H */ diff --git a/src/mainboard/google/veyron_mickey/boardid.c b/src/mainboard/google/veyron_mickey/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_mickey/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_mickey/bootblock.c b/src/mainboard/google/veyron_mickey/bootblock.c new file mode 100644 index 0000000000..57c76f8efc --- /dev/null +++ b/src/mainboard/google/veyron_mickey/bootblock.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + gpio_output(GPIO(7, A, 0), 1); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_mickey/chromeos.c b/src/mainboard/google/veyron_mickey/chromeos.c new file mode 100644 index 0000000000..8d2cc0749f --- /dev/null +++ b/src/mainboard/google/veyron_mickey/chromeos.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_RECOVERY GPIO(0, B, 1) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_mickey/devicetree.cb b/src/mainboard/google/veyron_mickey/devicetree.cb new file mode 100644 index 0000000000..49d9f12626 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_HDMI" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_mickey/mainboard.c b/src/mainboard/google/veyron_mickey/mainboard.c new file mode 100644 index 0000000000..35e7e5f59e --- /dev/null +++ b/src/mainboard/google/veyron_mickey/mainboard.c @@ -0,0 +1,134 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USB2_PWR_EN */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_i2s(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + rk808_configure_ldo(8, 1800); /* VCC18_LCD (HDMI_AVDD_1V8) */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD (HDMI_AVDD_1V0) */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ +} + +static void configure_hdmi(void) +{ + gpio_output(GPIO(7, B, 3), 1); /* POWER_HDMI_ON */ +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_emmc(); + configure_i2s(); + configure_vop(); + configure_hdmi(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); + + /* If recovery mode is detected, reduce frequency and voltage to reduce + * heat in case machine is left unattended. chrome-os-partner:41201. */ + if (recovery_mode_enabled()) { + printk(BIOS_DEBUG, "Reducing APLL freq for recovery mode.\n"); + rkclk_configure_cpu(APLL_600_MHZ); + rk808_configure_buck(1, 900); + } +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + return; +} diff --git a/src/mainboard/google/veyron_mickey/memlayout.ld b/src/mainboard/google/veyron_mickey/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_mickey/reset.c b/src/mainboard/google/veyron_mickey/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_mickey/romstage.c b/src/mainboard/google/veyron_mickey/romstage.c new file mode 100644 index 0000000000..65d353a5e3 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/romstage.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_mickey/sdram_configs.c b/src/mainboard/google/veyron_mickey/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..cb92d34571 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,79 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..c2293d5621 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,79 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..a90856a425 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,79 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8e0c37acf2 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..8ad3338775 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,79 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..57dca32179 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..94ee5b18ad --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..89dfd69ad1 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,79 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..c3e8fe4ab4 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + /* 40 Ohms instead of 34.3 due to bad PCB routing on Mickey. */ + .mr[3] = 0x2 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 1, +}, diff --git a/src/mainboard/google/veyron_mickey/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_mickey/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_mighty/Kconfig b/src/mainboard/google/veyron_mighty/Kconfig new file mode 100644 index 0000000000..be33aaccb2 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_MIGHTY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_mighty + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Mighty" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_MIGHTY diff --git a/src/mainboard/google/veyron_mighty/Makefile.inc b/src/mainboard/google/veyron_mighty/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_mighty/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_mighty/board.h b/src/mainboard/google/veyron_mighty/board.h new file mode 100644 index 0000000000..32310549e9 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_MIGHTY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_MIGHTY_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_MIGHTY_BOARD_H */ diff --git a/src/mainboard/google/veyron_mighty/boardid.c b/src/mainboard/google/veyron_mighty/boardid.c new file mode 100644 index 0000000000..513754f048 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_mighty/bootblock.c b/src/mainboard/google/veyron_mighty/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_mighty/chromeos.c b/src/mainboard/google/veyron_mighty/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_mighty/devicetree.cb b/src/mainboard/google/veyron_mighty/devicetree.cb new file mode 100644 index 0000000000..97b63d177e --- /dev/null +++ b/src/mainboard/google/veyron_mighty/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_EDP" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_mighty/mainboard.c b/src/mainboard/google/veyron_mighty/mainboard.c new file mode 100644 index 0000000000..8f10beeb1a --- /dev/null +++ b/src/mainboard/google/veyron_mighty/mainboard.c @@ -0,0 +1,167 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + switch (board_id()) { + case 0: + rk808_configure_switch(2, 1); /* VCC18_LCD */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + break; + default: + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); + break; + } +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + switch (board_id()) { + case 0: + gpio_output(GPIO(7, A, 0), 0); /* BL_EN */ + gpio_output(GPIO(7, A, 2), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO(7, A, 0), 1); /* BL_EN */ + break; + default: + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ + break; + } +} diff --git a/src/mainboard/google/veyron_mighty/memlayout.ld b/src/mainboard/google/veyron_mighty/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_mighty/reset.c b/src/mainboard/google/veyron_mighty/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_mighty/romstage.c b/src/mainboard/google/veyron_mighty/romstage.c new file mode 100644 index 0000000000..293e1e2710 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/romstage.c @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Increase frequency in RW in case it was set up too low by old RO. */ + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_mighty/sdram_configs.c b/src/mainboard/google/veyron_mighty/sdram_configs.c new file mode 100644 index 0000000000..19e46d308d --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_configs.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry and Mighty cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_mighty/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_mighty/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_minnie/Kconfig b/src/mainboard/google/veyron_minnie/Kconfig new file mode 100644 index 0000000000..a37f3272ec --- /dev/null +++ b/src/mainboard/google/veyron_minnie/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_MINNIE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_minnie + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Minnie" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_MINNIE diff --git a/src/mainboard/google/veyron_minnie/Makefile.inc b/src/mainboard/google/veyron_minnie/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_minnie/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_minnie/board.h b/src/mainboard/google/veyron_minnie/board.h new file mode 100644 index 0000000000..7944bcd51c --- /dev/null +++ b/src/mainboard/google/veyron_minnie/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_MINNIE_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_MINNIE_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_MINNIE_BOARD_H */ diff --git a/src/mainboard/google/veyron_minnie/boardid.c b/src/mainboard/google/veyron_minnie/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_minnie/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_minnie/bootblock.c b/src/mainboard/google/veyron_minnie/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_minnie/chromeos.c b/src/mainboard/google/veyron_minnie/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_minnie/devicetree.cb b/src/mainboard/google/veyron_minnie/devicetree.cb new file mode 100644 index 0000000000..97b63d177e --- /dev/null +++ b/src/mainboard/google/veyron_minnie/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_EDP" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_minnie/mainboard.c b/src/mainboard/google/veyron_minnie/mainboard.c new file mode 100644 index 0000000000..f762eb3515 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/mainboard.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_minnie/memlayout.ld b/src/mainboard/google/veyron_minnie/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_minnie/reset.c b/src/mainboard/google/veyron_minnie/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_minnie/romstage.c b/src/mainboard/google/veyron_minnie/romstage.c new file mode 100644 index 0000000000..e22a04e14b --- /dev/null +++ b/src/mainboard/google/veyron_minnie/romstage.c @@ -0,0 +1,127 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_minnie/sdram_configs.c b/src/mainboard/google/veyron_minnie/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_minnie/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_minnie/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_nicky/Kconfig b/src/mainboard/google/veyron_nicky/Kconfig new file mode 100644 index 0000000000..1b66758f5e --- /dev/null +++ b/src/mainboard/google/veyron_nicky/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_NICKY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_nicky + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Nicky" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_NICKY diff --git a/src/mainboard/google/veyron_nicky/Makefile.inc b/src/mainboard/google/veyron_nicky/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_nicky/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_nicky/board.h b/src/mainboard/google/veyron_nicky/board.h new file mode 100644 index 0000000000..3cd80e935f --- /dev/null +++ b/src/mainboard/google/veyron_nicky/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_NICKY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_NICKY_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_NICKY_BOARD_H */ diff --git a/src/mainboard/google/veyron_nicky/boardid.c b/src/mainboard/google/veyron_nicky/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_nicky/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_nicky/bootblock.c b/src/mainboard/google/veyron_nicky/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_nicky/chromeos.c b/src/mainboard/google/veyron_nicky/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_nicky/devicetree.cb b/src/mainboard/google/veyron_nicky/devicetree.cb new file mode 100644 index 0000000000..59a18267aa --- /dev/null +++ b/src/mainboard/google/veyron_nicky/devicetree.cb @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_nicky/mainboard.c b/src/mainboard/google/veyron_nicky/mainboard.c new file mode 100644 index 0000000000..f762eb3515 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/mainboard.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_nicky/memlayout.ld b/src/mainboard/google/veyron_nicky/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_nicky/reset.c b/src/mainboard/google/veyron_nicky/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_nicky/romstage.c b/src/mainboard/google/veyron_nicky/romstage.c new file mode 100644 index 0000000000..c27459186e --- /dev/null +++ b/src/mainboard/google/veyron_nicky/romstage.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_nicky/sdram_configs.c b/src/mainboard/google/veyron_nicky/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_nicky/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_nicky/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_pinky/Kconfig b/src/mainboard/google/veyron_pinky/Kconfig new file mode 100644 index 0000000000..a67a04a512 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_PINKY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_pinky + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Pinky" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_PINKY diff --git a/src/mainboard/google/veyron_pinky/Makefile.inc b/src/mainboard/google/veyron_pinky/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_pinky/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_pinky/board.h b/src/mainboard/google/veyron_pinky/board.h new file mode 100644 index 0000000000..72c1e0c2d8 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_PINKY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_PINKY_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET (board_id() > 0 ? GPIO(0, B, 5) : GPIO(0, B, 2)) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_PINKY_BOARD_H */ diff --git a/src/mainboard/google/veyron_pinky/boardid.c b/src/mainboard/google/veyron_pinky/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_pinky/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_pinky/bootblock.c b/src/mainboard/google/veyron_pinky/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_pinky/chromeos.c b/src/mainboard/google/veyron_pinky/chromeos.c new file mode 100644 index 0000000000..b64bae0a46 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/chromeos.c @@ -0,0 +1,150 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID (board_id() > 0 ? GPIO(0, A, 6) : GPIO(7, B, 5)) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = board_id() > 1 ? ACTIVE_LOW : + ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_pinky/devicetree.cb b/src/mainboard/google/veyron_pinky/devicetree.cb new file mode 100644 index 0000000000..97b63d177e --- /dev/null +++ b/src/mainboard/google/veyron_pinky/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_EDP" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_pinky/mainboard.c b/src/mainboard/google/veyron_pinky/mainboard.c new file mode 100644 index 0000000000..841815a534 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/mainboard.c @@ -0,0 +1,213 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + + switch (board_id()) { + case 0: + gpio_output(GPIO(7, B, 3), 1); /* 5V_DRV */ + break; + case 1: + break; /* 5V_DRV moved to EC in rev2 */ + default: + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV, again */ + break; + } +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + switch (board_id()) { + case 0: + rk808_configure_ldo(8, 3300); /* VCCIO_SD */ + gpio_output(GPIO(7, C, 5), 1); /* SD_EN */ + break; + default: + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + break; + } + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + switch (board_id()) { + case 0: + case 1: + /* + * Use a pullup instead of a drive since the output is 3.3V and + * really should be 1.8V (oops). The external pulldown will help + * bring the voltage down if we only drive with a pullup here. + */ + gpio_input_pullup(GPIO(7, B, 4)); /* EMMC_RST_L */ + break; + default: + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ + break; + } +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + switch (board_id()) { + case 0: + rk808_configure_ldo(5, 1800); /* VCC18_CODEC */ + break; + default: + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + break; + } + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + switch (board_id()) { + case 0: + rk808_configure_ldo(4, 1800); /* VCC18_LCD */ + rk808_configure_ldo(6, 1000); /* VCC10_LCD */ + gpio_output(GPIO(7, B, 7), 1); /* LCD_EN */ + break; + case 1: + case 2: + rk808_configure_switch(2, 1); /* VCC18_LCD */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + break; + default: + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); + break; + } +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + switch (board_id()) { + case 0: + case 1: + case 2: + gpio_output(GPIO(7, A, 0), 0); /* BL_EN */ + gpio_output(GPIO(7, A, 2), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO(7, A, 0), 1); /* BL_EN */ + break; + default: + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ + break; + } +} diff --git a/src/mainboard/google/veyron_pinky/memlayout.ld b/src/mainboard/google/veyron_pinky/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_pinky/reset.c b/src/mainboard/google/veyron_pinky/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_pinky/romstage.c b/src/mainboard/google/veyron_pinky/romstage.c new file mode 100644 index 0000000000..81a412e1a5 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/romstage.c @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + switch (board_id()) { + case 0: + rk808_configure_ldo(8, 0); /* VCCIO_SD */ + gpio_output(GPIO(7, C, 5), 0); /* SD_EN */ + break; + default: + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ + break; + } +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_pinky/sdram_configs.c b/src/mainboard/google/veyron_pinky/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_pinky/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_pinky/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_rialto/Kconfig b/src/mainboard/google/veyron_rialto/Kconfig new file mode 100644 index 0000000000..4161856018 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc. +## + +if BOARD_GOOGLE_VEYRON_RIALTO + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_rialto + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Rialto" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Rialto, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_RIALTO diff --git a/src/mainboard/google/veyron_rialto/Makefile.inc b/src/mainboard/google/veyron_rialto/Makefile.inc new file mode 100644 index 0000000000..a027c6d014 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc. +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_rialto/board.h b/src/mainboard/google/veyron_rialto/board.h new file mode 100644 index 0000000000..5fd45dba53 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/board.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_RIALTO_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_RIALTO_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_RIALTO_BOARD_H */ diff --git a/src/mainboard/google/veyron_rialto/boardid.c b/src/mainboard/google/veyron_rialto/boardid.c new file mode 100644 index 0000000000..f7cddcc4fe --- /dev/null +++ b/src/mainboard/google/veyron_rialto/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_rialto/bootblock.c b/src/mainboard/google/veyron_rialto/bootblock.c new file mode 100644 index 0000000000..86222397de --- /dev/null +++ b/src/mainboard/google/veyron_rialto/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Turn on all leds */ + gpio_output(GPIO(7, A, 0), 1); /* LED_READY */ + gpio_output(GPIO(7, B, 5), 1); /* Ready2_LED */ + gpio_output(GPIO(7, B, 3), 1); /* LED_SYNCING */ + gpio_output(GPIO(7, B, 7), 1); /* LED_ERROR */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1416_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_rialto/chromeos.c b/src/mainboard/google/veyron_rialto/chromeos.c new file mode 100644 index 0000000000..4baf876e0f --- /dev/null +++ b/src/mainboard/google/veyron_rialto/chromeos.c @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY_SERVO GPIO(0, B, 1) +#define GPIO_RECOVERY_PUSHKEY GPIO(7, B, 1) + + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY_SERVO); + gpio_input_pullup(GPIO_RECOVERY_PUSHKEY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + /* Note for early development, we want to support both servo and + * pushkey recovery buttons in firmware boot stages. + */ + gpios->gpios[count].port = GPIO_RECOVERY_PUSHKEY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = !get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + // Both RECOVERY_SERVO and RECOVERY_PUSHKEY are low active. + return !(gpio_get(GPIO_RECOVERY_SERVO) && + gpio_get(GPIO_RECOVERY_PUSHKEY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} diff --git a/src/mainboard/google/veyron_rialto/devicetree.cb b/src/mainboard/google/veyron_rialto/devicetree.cb new file mode 100644 index 0000000000..c40bbbbc4e --- /dev/null +++ b/src/mainboard/google/veyron_rialto/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc. +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_NONE" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_rialto/mainboard.c b/src/mainboard/google/veyron_rialto/mainboard.c new file mode 100644 index 0000000000..78398c557c --- /dev/null +++ b/src/mainboard/google/veyron_rialto/mainboard.c @@ -0,0 +1,127 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USB2_PWR_EN */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_3g(void) +{ + /* Force 3G modem off to avoid confusing the EHCI host and + * causing problems during enumeration/init */ + gpio_output(GPIO(5, C, 1), 1); /* 3G_SHUTDOWN */ + gpio_output(GPIO(4, D, 2), 0); /* 3G_ON_OFF */ +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_emmc(); + configure_codec(); + configure_3g(); + /* No video. */ + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); + + /* If recovery mode is detected, reduce frequency and voltage to reduce + * heat in case machine is left unattended. chrome-os-partner:41201. */ + if (recovery_mode_enabled()) { + printk(BIOS_DEBUG, "Reducing APLL freq for recovery mode.\n"); + rkclk_configure_cpu(APLL_600_MHZ); + rk808_configure_buck(1, 900); + } +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + return; +} diff --git a/src/mainboard/google/veyron_rialto/memlayout.ld b/src/mainboard/google/veyron_rialto/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_rialto/reset.c b/src/mainboard/google/veyron_rialto/reset.c new file mode 100644 index 0000000000..f35860844f --- /dev/null +++ b/src/mainboard/google/veyron_rialto/reset.c @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1) + ; +} diff --git a/src/mainboard/google/veyron_rialto/romstage.c b/src/mainboard/google/veyron_rialto/romstage.c new file mode 100644 index 0000000000..ec06e861e6 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/romstage.c @@ -0,0 +1,130 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + + timestamp_add_now(TS_BEFORE_INITRAM); + + sdram_init(get_sdram_config()); + + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_rialto/sdram_configs.c b/src/mainboard/google/veyron_rialto/sdram_configs.c new file mode 100644 index 0000000000..6c4f3e6f7a --- /dev/null +++ b/src/mainboard/google/veyron_rialto/sdram_configs.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-K4E8E304EE-1GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-K4E6E304EB-2GB-1CH.inc"/* ram_code = 0001 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 1111 */ +/* Brain, Jaq, Jerry, Mighty, Danger and Rialto + * cannot support tri-state, see b/36279493! */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 16, "Must have 16 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E6E304EB-2GB-1CH.inc b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E6E304EB-2GB-1CH.inc new file mode 100644 index 0000000000..df3bb2a729 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E6E304EB-2GB-1CH.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x0, + .col = 0x0, + .bk = 0x0, + .bw = 0x0, + .dbw = 0x0, + .row_3_4 = 0x0, + .cs0_row = 0x0, + .cs1_row = 0x0 + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 1, + .stride = 22, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E8E304EE-1GB.inc b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E8E304EE-1GB.inc new file mode 100644 index 0000000000..9afd04fdd1 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-lpddr3-K4E8E304EE-1GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x0, + .col = 0x0, + .bk = 0x0, + .bw = 0x0, + .dbw = 0x0, + .row_3_4 = 0x0, + .cs0_row = 0x0, + .cs1_row = 0x0 + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 1, + .stride = 22, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_rialto/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_rialto/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_romy/Kconfig b/src/mainboard/google/veyron_romy/Kconfig new file mode 100644 index 0000000000..0cb16d0bcc --- /dev/null +++ b/src/mainboard/google/veyron_romy/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_ROMY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_romy + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Romy" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Romy, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_ROMY diff --git a/src/mainboard/google/veyron_romy/Makefile.inc b/src/mainboard/google/veyron_romy/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_romy/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_romy/board.h b/src/mainboard/google/veyron_romy/board.h new file mode 100644 index 0000000000..d3ffda6ad4 --- /dev/null +++ b/src/mainboard/google/veyron_romy/board.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_ROMY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_ROMY_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_ROMY_BOARD_H */ diff --git a/src/mainboard/google/veyron_romy/boardid.c b/src/mainboard/google/veyron_romy/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_romy/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_romy/bootblock.c b/src/mainboard/google/veyron_romy/bootblock.c new file mode 100644 index 0000000000..57c76f8efc --- /dev/null +++ b/src/mainboard/google/veyron_romy/bootblock.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + gpio_output(GPIO(7, A, 0), 1); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_romy/chromeos.c b/src/mainboard/google/veyron_romy/chromeos.c new file mode 100644 index 0000000000..14f078c81b --- /dev/null +++ b/src/mainboard/google/veyron_romy/chromeos.c @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_romy/devicetree.cb b/src/mainboard/google/veyron_romy/devicetree.cb new file mode 100644 index 0000000000..1c70b57bf4 --- /dev/null +++ b/src/mainboard/google/veyron_romy/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_AUTO_DETECT" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_romy/mainboard.c b/src/mainboard/google/veyron_romy/mainboard.c new file mode 100644 index 0000000000..5c27353941 --- /dev/null +++ b/src/mainboard/google/veyron_romy/mainboard.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + rk808_configure_switch(2, 1); /* VCC18_LCD (HDMI_AVDD_1V8) */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD (HDMI_AVDD_1V0) */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + return; +} diff --git a/src/mainboard/google/veyron_romy/memlayout.ld b/src/mainboard/google/veyron_romy/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_romy/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_romy/reset.c b/src/mainboard/google/veyron_romy/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_romy/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_romy/romstage.c b/src/mainboard/google/veyron_romy/romstage.c new file mode 100644 index 0000000000..65d353a5e3 --- /dev/null +++ b/src/mainboard/google/veyron_romy/romstage.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_romy/sdram_configs.c b/src/mainboard/google/veyron_romy/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_romy/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_romy/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_romy/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_speedy/Kconfig b/src/mainboard/google/veyron_speedy/Kconfig new file mode 100644 index 0000000000..64ff56ae58 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_SPEEDY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_speedy + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Speedy" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_SPEEDY diff --git a/src/mainboard/google/veyron_speedy/Makefile.inc b/src/mainboard/google/veyron_speedy/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_speedy/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_speedy/board.h b/src/mainboard/google/veyron_speedy/board.h new file mode 100644 index 0000000000..9a2170065a --- /dev/null +++ b/src/mainboard/google/veyron_speedy/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_SPEEDY_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_SPEEDY_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_SPEEDY_BOARD_H */ diff --git a/src/mainboard/google/veyron_speedy/boardid.c b/src/mainboard/google/veyron_speedy/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_speedy/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_speedy/bootblock.c b/src/mainboard/google/veyron_speedy/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_speedy/chromeos.c b/src/mainboard/google/veyron_speedy/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_speedy/devicetree.cb b/src/mainboard/google/veyron_speedy/devicetree.cb new file mode 100644 index 0000000000..97b63d177e --- /dev/null +++ b/src/mainboard/google/veyron_speedy/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_EDP" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_speedy/mainboard.c b/src/mainboard/google/veyron_speedy/mainboard.c new file mode 100644 index 0000000000..8f10beeb1a --- /dev/null +++ b/src/mainboard/google/veyron_speedy/mainboard.c @@ -0,0 +1,167 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + switch (board_id()) { + case 0: + rk808_configure_switch(2, 1); /* VCC18_LCD */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + break; + default: + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); + break; + } +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + switch (board_id()) { + case 0: + gpio_output(GPIO(7, A, 0), 0); /* BL_EN */ + gpio_output(GPIO(7, A, 2), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO(7, A, 0), 1); /* BL_EN */ + break; + default: + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ + break; + } +} diff --git a/src/mainboard/google/veyron_speedy/memlayout.ld b/src/mainboard/google/veyron_speedy/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_speedy/reset.c b/src/mainboard/google/veyron_speedy/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_speedy/romstage.c b/src/mainboard/google/veyron_speedy/romstage.c new file mode 100644 index 0000000000..e22a04e14b --- /dev/null +++ b/src/mainboard/google/veyron_speedy/romstage.c @@ -0,0 +1,127 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_speedy/sdram_configs.c b/src/mainboard/google/veyron_speedy/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_speedy/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_speedy/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_thea/Kconfig b/src/mainboard/google/veyron_thea/Kconfig new file mode 100644 index 0000000000..e710eef7cc --- /dev/null +++ b/src/mainboard/google/veyron_thea/Kconfig @@ -0,0 +1,89 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_THEA + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_EC + select COMMON_CBFS_SPI_WRAPPER + select EC_GOOGLE_CHROMEEC + select EC_GOOGLE_CHROMEEC_SPI + select EC_SOFTWARE_SYNC + select ELOG + select RAM_CODE_SUPPORT + select SOC_ROCKCHIP_RK3288 + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select HAVE_HARD_RESET + select RETURN_FROM_VERSTAGE + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_thea + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Thea" + +config MAINBOARD_VENDOR + string + default "Google" + +config EC_GOOGLE_CHROMEEC_SPI_BUS + hex + default 0 + +config EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US + int + default 100 + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x3 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_THEA diff --git a/src/mainboard/google/veyron_thea/Makefile.inc b/src/mainboard/google/veyron_thea/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_thea/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_thea/board.h b/src/mainboard/google/veyron_thea/board.h new file mode 100644 index 0000000000..c5e75fa972 --- /dev/null +++ b/src/mainboard/google/veyron_thea/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_THEA_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_THEA_BOARD_H + +#include +#include + +#define GPIO_BACKLIGHT GPIO(7, A, 2) +#define GPIO_RESET GPIO(0, B, 5) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_THEA_BOARD_H */ diff --git a/src/mainboard/google/veyron_thea/boardid.c b/src/mainboard/google/veyron_thea/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_thea/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_thea/bootblock.c b/src/mainboard/google/veyron_thea/bootblock.c new file mode 100644 index 0000000000..ebef491a41 --- /dev/null +++ b/src/mainboard/google/veyron_thea/bootblock.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + /* spi0 for chrome ec */ + writel(IOMUX_SPI0, &rk3288_grf->iomux_spi0); + rockchip_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, 8250*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_thea/chromeos.c b/src/mainboard/google/veyron_thea/chromeos.c new file mode 100644 index 0000000000..e0f816cdc1 --- /dev/null +++ b/src/mainboard/google/veyron_thea/chromeos.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_LID GPIO(0, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) +#define GPIO_ECINRW GPIO(0, A, 7) +#define GPIO_ECIRQ GPIO(7, A, 7) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input_pullup(GPIO_LID); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); + gpio_input(GPIO_ECIRQ); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_recovery_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Lid: active high */ + gpios->gpios[count].port = GPIO_LID.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH); + count++; + + /* Power:GPIO active high */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC in RW: GPIO active high */ + gpios->gpios[count].port = GPIO_ECINRW.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC in RW", + GPIO_MAX_NAME_LENGTH); + count++; + + /* EC interrupt: GPIO active high */ + gpios->gpios[count].port = GPIO_ECIRQ.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "EC interrupt", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + uint32_t ec_events; + + /* The GPIO is active low. */ + if (!gpio_get(GPIO_RECOVERY)) + return 1; + + ec_events = google_chromeec_get_events_b(); + return !!(ec_events & + EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_thea/devicetree.cb b/src/mainboard/google/veyron_thea/devicetree.cb new file mode 100644 index 0000000000..59a18267aa --- /dev/null +++ b/src/mainboard/google/veyron_thea/devicetree.cb @@ -0,0 +1,25 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_thea/mainboard.c b/src/mainboard/google/veyron_thea/mainboard.c new file mode 100644 index 0000000000..f762eb3515 --- /dev/null +++ b/src/mainboard/google/veyron_thea/mainboard.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 3), 1); /* HOST1_PWR_EN */ + gpio_output(GPIO(0, B, 4), 1); /* USBOTG_PWREN_H */ + gpio_output(GPIO(7, C, 5), 1); /* 5V_DRV */ +} + +static void configure_sdmmc(void) +{ + writel(IOMUX_SDMMC0, &rk3288_grf->iomux_sdmmc0); + + /* use sdmmc0 io, disable JTAG function */ + writel(RK_CLRBITS(1 << 12), &rk3288_grf->soc_con0); + + /* Note: these power rail definitions are copied in romstage.c */ + rk808_configure_ldo(4, 3300); /* VCCIO_SD */ + rk808_configure_ldo(5, 3300); /* VCC33_SD */ + + gpio_input(GPIO(7, A, 5)); /* SD_DET */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + gpio_output(GPIO(2, B, 5), 1); /* AVDD_1V8_DISP_EN */ + rk808_configure_ldo(7, 2500); /* VCC10_LCD_PWREN_H */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + rk808_configure_switch(1, 1); /* VCC33_LCD */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + configure_usb(); + configure_sdmmc(); + configure_emmc(); + configure_codec(); + configure_vop(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_thea/memlayout.ld b/src/mainboard/google/veyron_thea/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_thea/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_thea/reset.c b/src/mainboard/google/veyron_thea/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_thea/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_thea/romstage.c b/src/mainboard/google/veyron_thea/romstage.c new file mode 100644 index 0000000000..c27459186e --- /dev/null +++ b/src/mainboard/google/veyron_thea/romstage.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +static void sdmmc_power_off(void) +{ + rk808_configure_ldo(4, 0); /* VCCIO_SD */ + rk808_configure_ldo(5, 0); /* VCC33_SD */ +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* Need to power cycle SD card to ensure it is properly reset. */ + sdmmc_power_off(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_thea/sdram_configs.c b/src/mainboard/google/veyron_thea/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_thea/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_thea/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_thea/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/google/veyron_tiger/Kconfig b/src/mainboard/google/veyron_tiger/Kconfig new file mode 100644 index 0000000000..b25606ace1 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/Kconfig @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +if BOARD_GOOGLE_VEYRON_TIGER + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_ID_SUPPORT + select BOARD_ROMSIZE_KB_4096 + select CHROMEOS + select CHROMEOS_VBNV_FLASH + select COMMON_CBFS_SPI_WRAPPER + select ELOG + select HAVE_HARD_RESET + select MAINBOARD_DO_NATIVE_VGA_INIT + select MAINBOARD_HAS_BOOTBLOCK_INIT + select PHYSICAL_REC_SWITCH + select RAM_CODE_SUPPORT + select RETURN_FROM_VERSTAGE + select SOC_ROCKCHIP_RK3288 + select SPI_FLASH + select SPI_FLASH_GIGADEVICE + select SPI_FLASH_WINBOND + select VIRTUAL_DEV_SWITCH + +config MAINBOARD_DIR + string + default google/veyron_tiger + +config MAINBOARD_PART_NUMBER + string + default "Veyron_Tiger" + +config MAINBOARD_VENDOR + string + default "Google" + +# The 'ecrwhash' is removed from FMAP on Tiger, since we don't have EC. +# As a result, we have to hack RAMSTAGE and ROMSTAGE index until there are +# better approaches for vboot2 to find right index. +config VBOOT_RAMSTAGE_INDEX + hex + default 0x2 + +config VBOOT_ROMSTAGE_INDEX + hex + default 0x1 + +config BOOT_MEDIA_SPI_BUS + hex + default 2 + +config DRIVER_TPM_I2C_BUS + hex + default 0x1 + +config DRIVER_TPM_I2C_ADDR + hex + default 0x20 + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0xFF690000 + +config PMIC_BUS + int + default 0 + +endif # BOARD_GOOGLE_VEYRON_TIGER diff --git a/src/mainboard/google/veyron_tiger/Makefile.inc b/src/mainboard/google/veyron_tiger/Makefile.inc new file mode 100644 index 0000000000..b56af8c38e --- /dev/null +++ b/src/mainboard/google/veyron_tiger/Makefile.inc @@ -0,0 +1,41 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +bootblock-y += bootblock.c +bootblock-y += boardid.c +bootblock-y += chromeos.c +bootblock-y += reset.c + +verstage-y += boardid.c +verstage-y += chromeos.c +verstage-y += reset.c + +romstage-y += boardid.c +romstage-y += romstage.c +romstage-y += sdram_configs.c +romstage-y += reset.c + +ramstage-y += boardid.c +ramstage-y += chromeos.c +ramstage-y += mainboard.c +ramstage-y += reset.c + +bootblock-y += memlayout.ld +verstage-y += memlayout.ld +romstage-y += memlayout.ld +ramstage-y += memlayout.ld diff --git a/src/mainboard/google/veyron_tiger/board.h b/src/mainboard/google/veyron_tiger/board.h new file mode 100644 index 0000000000..958a65a8ef --- /dev/null +++ b/src/mainboard/google/veyron_tiger/board.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MAINBOARD_GOOGLE_VEYRON_TIGER_BOARD_H +#define __MAINBOARD_GOOGLE_VEYRON_TIGER_BOARD_H + +#include +#include + +#define GPIO_RESET GPIO(0, B, 5) +#define GPIO_BACKLIGHT GPIO(7, A, 2) + +void setup_chromeos_gpios(void); + +#endif /* __MAINBOARD_GOOGLE_VEYRON_TIGER_BOARD_H */ diff --git a/src/mainboard/google/veyron_tiger/boardid.c b/src/mainboard/google/veyron_tiger/boardid.c new file mode 100644 index 0000000000..65509d25ab --- /dev/null +++ b/src/mainboard/google/veyron_tiger/boardid.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +uint8_t board_id(void) +{ + static int id = -1; + static gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ + + if (id < 0) { + id = gpio_base2_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "Board ID: %d.\n", id); + } + + return id; +} + +uint32_t ram_code(void) +{ + uint32_t code; + static gpio_t pins[] = {[3] = GPIO(8, A, 3), [2] = GPIO(8, A, 2), + [1] = GPIO(8, A, 1), [0] = GPIO(8, A, 0)}; /* GPIO8_A0 is LSB */ + + code = gpio_binary_first_base3_value(pins, ARRAY_SIZE(pins)); + printk(BIOS_SPEW, "RAM Config: %u.\n", code); + + return code; +} diff --git a/src/mainboard/google/veyron_tiger/bootblock.c b/src/mainboard/google/veyron_tiger/bootblock.c new file mode 100644 index 0000000000..5e15b4f637 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/bootblock.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +void bootblock_mainboard_early_init() +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART)) { + assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UART2_BASE); + writel(IOMUX_UART2, &rk3288_grf->iomux_uart2); + } + +} + +void bootblock_mainboard_init(void) +{ + if (rkclk_was_watchdog_reset()) + reboot_from_watchdog(); + + gpio_output(GPIO(7, A, 3), 0); /* Power LED */ + + /* Up VDD_CPU (BUCK1) to 1.4V to support max CPU frequency (1.8GHz). */ + setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL); + setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA); + assert(CONFIG_PMIC_BUS == 0); /* must correspond with IOMUX */ + i2c_init(CONFIG_PMIC_BUS, 400*KHz); + + /* Slowly raise to max CPU voltage to prevent overshoot */ + rk808_configure_buck(1, 1200); + udelay(175);/* Must wait for voltage to stabilize,2mV/us */ + rk808_configure_buck(1, 1400); + udelay(100);/* Must wait for voltage to stabilize,2mV/us */ + rkclk_configure_cpu(APLL_1800_MHZ); + + /* i2c1 for tpm */ + writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1); + i2c_init(1, 400*KHz); + + /* spi2 for firmware ROM */ + writel(IOMUX_SPI2_CSCLK, &rk3288_grf->iomux_spi2csclk); + writel(IOMUX_SPI2_TXRX, &rk3288_grf->iomux_spi2txrx); + rockchip_spi_init(CONFIG_BOOT_MEDIA_SPI_BUS, 24750*KHz); + + setup_chromeos_gpios(); +} diff --git a/src/mainboard/google/veyron_tiger/chromeos.c b/src/mainboard/google/veyron_tiger/chromeos.c new file mode 100644 index 0000000000..068c379a0c --- /dev/null +++ b/src/mainboard/google/veyron_tiger/chromeos.c @@ -0,0 +1,111 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "board.h" + +#define GPIO_WP GPIO(7, A, 6) +#define GPIO_POWER GPIO(0, A, 5) +#define GPIO_RECOVERY GPIO(0, B, 1) + +void setup_chromeos_gpios(void) +{ + gpio_input(GPIO_WP); + gpio_input(GPIO_POWER); + gpio_input_pullup(GPIO_RECOVERY); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + int count = 0; + + /* Write Protect: active low */ + gpios->gpios[count].port = GPIO_WP.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_WP); + strncpy((char *)gpios->gpios[count].name, "write protect", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Recovery: active low */ + gpios->gpios[count].port = GPIO_RECOVERY.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = gpio_get(GPIO_RECOVERY); + strncpy((char *)gpios->gpios[count].name, "recovery", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Power Button: GPIO active low */ + gpios->gpios[count].port = GPIO_POWER.raw; + gpios->gpios[count].polarity = ACTIVE_LOW; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "power", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Developer: GPIO active high */ + gpios->gpios[count].port = -1; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = get_developer_mode_switch(); + strncpy((char *)gpios->gpios[count].name, "developer", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Reset: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_RESET.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "reset", + GPIO_MAX_NAME_LENGTH); + count++; + + /* Backlight: GPIO active high (output) */ + gpios->gpios[count].port = GPIO_BACKLIGHT.raw; + gpios->gpios[count].polarity = ACTIVE_HIGH; + gpios->gpios[count].value = -1; + strncpy((char *)gpios->gpios[count].name, "backlight", + GPIO_MAX_NAME_LENGTH); + count++; + + gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio)); + gpios->count = count; + + printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size); +} + +int get_developer_mode_switch(void) +{ + return 0; +} + +int get_recovery_mode_switch(void) +{ + return !gpio_get(GPIO_RECOVERY); +} + +int get_write_protect_state(void) +{ + return !gpio_get(GPIO_WP); +} + diff --git a/src/mainboard/google/veyron_tiger/devicetree.cb b/src/mainboard/google/veyron_tiger/devicetree.cb new file mode 100644 index 0000000000..1c70b57bf4 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/devicetree.cb @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# TODO fill with Versatile Express board data in QEMU. +chip soc/rockchip/rk3288 + device cpu_cluster 0 on end + register "vop_id" = "1" + register "vop_mode" = "VOP_MODE_AUTO_DETECT" + register "framebuffer_bits_per_pixel" = "16" +end diff --git a/src/mainboard/google/veyron_tiger/mainboard.c b/src/mainboard/google/veyron_tiger/mainboard.c new file mode 100644 index 0000000000..5435faa0c7 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/mainboard.c @@ -0,0 +1,156 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void enable_5v_drv(void) +{ + /* EN pin of NB679 for USB, Speaker, HDMI, TouchScreen*/ + gpio_output(GPIO(7, C, 5), 1); +} + +static void configure_usb(void) +{ + gpio_output(GPIO(0, B, 4), 1); /* USB_OTG_PWR_EN */ + gpio_output(GPIO(5, C, 2), 1); /* HUB_USB1_PWR_EN */ + gpio_output(GPIO(5, B, 6), 1); /* HUB_USB2_PWR_EN */ + gpio_output(GPIO(5, B, 4), 1); /* USB_OTG_CTL1 */ + gpio_output(GPIO(5, C, 1), 1); /* HUB_USB1_CTL1 */ + gpio_output(GPIO(5, B, 5), 1); /* HUB_USB2_CTL1 */ +} + +static void configure_emmc(void) +{ + writel(IOMUX_EMMCDATA, &rk3288_grf->iomux_emmcdata); + writel(IOMUX_EMMCPWREN, &rk3288_grf->iomux_emmcpwren); + writel(IOMUX_EMMCCMD, &rk3288_grf->iomux_emmccmd); + + gpio_output(GPIO(2, B, 1), 1); /* EMMC_RST_L */ +} + +static void configure_codec(void) +{ + writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2); /* CODEC I2C */ + i2c_init(2, 400*KHz); /* CODEC I2C */ + + writel(IOMUX_I2S, &rk3288_grf->iomux_i2s); + writel(IOMUX_I2SCLK, &rk3288_grf->iomux_i2sclk); + + rk808_configure_ldo(6, 1800); /* VCC18_CODEC */ + + /* AUDIO IO domain 1.8V voltage selection */ + writel(RK_SETBITS(1 << 6), &rk3288_grf->io_vsel); + rkclk_configure_i2s(12288000); +} + +static void configure_vop(void) +{ + writel(IOMUX_LCDC, &rk3288_grf->iomux_lcdc); + + /* lcdc(vop) iodomain select 1.8V */ + writel(RK_SETBITS(1 << 0), &rk3288_grf->io_vsel); + + rk808_configure_ldo(2, 1800); /* VCC18_LCD */ + rk808_configure_ldo(7, 1000); /* VDD10_LCD */ + rk808_configure_switch(1, 1); /* LCDC33_VDD */ + gpio_output(GPIO(7, B, 6), 1); /* LCD_EN */ + + /* enable edp HPD */ + gpio_input_pulldown(GPIO(7, B, 3)); + writel(IOMUX_EDP_HOTPLUG, &rk3288_grf->iomux_edp_hotplug); +} + +static void configure_hdmi(void) +{ + /* HDMI I2C */ + writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda); + writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl); + + gpio_output(GPIO(5, C, 3), 1); /* VCC50_HDMI_EN */ +} + +static void mainboard_init(device_t dev) +{ + gpio_output(GPIO_RESET, 0); + + enable_5v_drv(); + configure_usb(); + configure_emmc(); + configure_codec(); + configure_vop(); + configure_hdmi(); + + elog_init(); + elog_add_watchdog_reset(); + elog_add_boot_reason(); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = &mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + +void lb_board(struct lb_header *header) +{ + struct lb_range *dma; + + dma = (struct lb_range *)lb_new_record(header); + dma->tag = LB_TAB_DMA; + dma->size = sizeof(*dma); + dma->range_start = (uintptr_t)_dma_coherent; + dma->range_size = _dma_coherent_size; + + /* Retrieve the on-board Ethernet MAC address. */ + lb_table_add_macs_from_vpd(header); +} + +void mainboard_power_on_backlight(void) +{ + gpio_output(GPIO(2, B, 4), 1); /* BL_PWR_EN */ + mdelay(20); + gpio_output(GPIO(7, A, 0), 1); /* LCD_BL_PWM */ + mdelay(10); + gpio_output(GPIO_BACKLIGHT, 1); /* BL_EN */ +} diff --git a/src/mainboard/google/veyron_tiger/memlayout.ld b/src/mainboard/google/veyron_tiger/memlayout.ld new file mode 100644 index 0000000000..ead7f47838 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/memlayout.ld @@ -0,0 +1 @@ +#include diff --git a/src/mainboard/google/veyron_tiger/reset.c b/src/mainboard/google/veyron_tiger/reset.c new file mode 100644 index 0000000000..9cbe9c1551 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/reset.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "board.h" + +void hard_reset(void) +{ + gpio_output(GPIO_RESET, 1); + while (1); +} diff --git a/src/mainboard/google/veyron_tiger/romstage.c b/src/mainboard/google/veyron_tiger/romstage.c new file mode 100644 index 0000000000..65d353a5e3 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/romstage.c @@ -0,0 +1,118 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board.h" + +static void regulate_vdd_log(unsigned int mv) +{ + unsigned int duty_ns; + const u32 period_ns = 2000; /* pwm period: 2000ns */ + const u32 max_regulator_mv = 1350; /* 1.35V */ + const u32 min_regulator_mv = 870; /* 0.87V */ + + writel(IOMUX_PWM1, &rk3288_grf->iomux_pwm1); + + assert((mv >= min_regulator_mv) && (mv <= max_regulator_mv)); + + duty_ns = (max_regulator_mv - mv) * period_ns / + (max_regulator_mv - min_regulator_mv); + + pwm_init(1, period_ns, duty_ns); +} + +static void configure_l2ctlr(void) +{ + uint32_t l2ctlr; + + l2ctlr = read_l2ctlr(); + l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */ + + /* + * Data RAM write latency: 2 cycles + * Data RAM read latency: 2 cycles + * Data RAM setup latency: 1 cycle + * Tag RAM write latency: 1 cycle + * Tag RAM read latency: 1 cycle + * Tag RAM setup latency: 1 cycle + */ + l2ctlr |= (1 << 3 | 1 << 0); + write_l2ctlr(l2ctlr); +} + +void main(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + configure_l2ctlr(); + tsadc_init(); + + /* vdd_log 1200mv is enough for ddr run 666Mhz */ + regulate_vdd_log(1200); + timestamp_add_now(TS_BEFORE_INITRAM); + sdram_init(get_sdram_config()); + timestamp_add_now(TS_AFTER_INITRAM); + + /* Now that DRAM is up, add mappings for it and DMA coherency buffer. */ + mmu_config_range((uintptr_t)_dram/MiB, + sdram_size_mb(), DCACHE_WRITEBACK); + mmu_config_range((uintptr_t)_dma_coherent/MiB, + _dma_coherent_size/MiB, DCACHE_OFF); + + cbmem_initialize_empty(); + + entry = vboot2_load_ramstage(); + + if (entry == NULL) { + timestamp_add_now(TS_START_COPYRAM); + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + timestamp_add_now(TS_END_COPYRAM); + if (entry == (void *)-1) + die("failed to load ramstage\n"); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + stage_exit(entry); +} diff --git a/src/mainboard/google/veyron_tiger/sdram_configs.c b/src/mainboard/google/veyron_tiger/sdram_configs.c new file mode 100644 index 0000000000..04d559c425 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_configs.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +static struct rk3288_sdram_params sdram_configs[] = { +#include "sdram_inf/sdram-lpddr3-samsung-2GB.inc" /* ram_code = 0000 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB.inc" /* ram_code = 0001 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc" /* ram_code = 0010 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc" /* ram_code = 0011 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 0101 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 0110 */ +#include "sdram_inf/sdram-lpddr3-elpida-2GB.inc" /* ram_code = 0111 */ +#include "sdram_inf/sdram-lpddr3-samsung-4GB.inc" /* ram_code = 1000 */ +#include "sdram_inf/sdram-lpddr3-hynix-4GB.inc" /* ram_code = 1001 */ +#include "sdram_inf/sdram-ddr3-nanya-2GB.inc" /* ram_code = 1010 */ +#include "sdram_inf/sdram-lpddr3-elpida-4GB.inc" /* ram_code = 1011 */ +#include "sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc" /* ram_code = 1100 */ +#include "sdram_inf/sdram-ddr3-hynix-2GB.inc" /* ram_code = 1101 */ +#include "sdram_inf/sdram-ddr3-samsung-4GB.inc" /* ram_code = 1110 */ +#include "sdram_inf/sdram-ddr3-hynix-4GB.inc" /* ram_code = 1111 */ +#include "sdram_inf/sdram-ddr3-samsung-2GB.inc" /* ram_code = 000Z */ +#include "sdram_inf/sdram-lpddr3-micron-2GB-D2.inc" /* ram_code = 001Z */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z0 */ +#include "sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc" /* ram_code = 00Z1 */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 00ZZ */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 010Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 011Z */ +#include "sdram_inf/sdram-unused.inc" /* ram_code = 01Z0 */ +}; +_Static_assert(ARRAY_SIZE(sdram_configs) == 24, "Must have 24 sdram_configs!"); + +const struct rk3288_sdram_params *get_sdram_config() +{ + u32 ramcode = ram_code(); + + if (ramcode >= ARRAY_SIZE(sdram_configs) + || sdram_configs[ramcode].dramtype == UNUSED) + die("Invalid RAMCODE."); + return &sdram_configs[ramcode]; +} diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-2GB.inc new file mode 100644 index 0000000000..659cfd4b88 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynic H5TC4G63CFR(0101b) or H5TC4G63AFR(1101b) chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-4GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-4GB.inc new file mode 100644 index 0000000000..9f2ca8a7d2 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-hynix-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Hynix H5TC8G63xxx chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-nanya-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-nanya-2GB.inc new file mode 100644 index 0000000000..bd82e7b774 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-nanya-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Nanya NT5CC256M16DP chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-2GB.inc new file mode 100644 index 0000000000..d2186ac8a3 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4B4G1646D-BYK0/K4B4G1646E-BYK0/K4B4G1646Q-HYK0 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 9, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-4GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-4GB.inc new file mode 100644 index 0000000000..a32f1a6129 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-ddr3-samsung-4GB.inc @@ -0,0 +1,78 @@ +{ + /* 4 Samsung K4B8G1646Q chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x29A, + .tinit = 0xC8, + .trsth = 0x1F4, + .togcnt100n = 0x42, + .trefi = 0x4E, + .tmrd = 0x4, + .trfc = 0xEA, + .trp = 0xA, + .trtw = 0x5, + .tal = 0x0, + .tcl = 0xA, + .tcwl = 0x7, + .tras = 0x19, + .trc = 0x24, + .trcd = 0xA, + .trrd = 0x7, + .trtp = 0x5, + .twr = 0xA, + .twtr = 0x5, + .texsr = 0x200, + .txp = 0x5, + .txpdll = 0x10, + .tzqcs = 0x40, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x7, + .tcksrx = 0x7, + .tcke = 0x4, + .tmod = 0xC, + .trstl = 0x43, + .tzqcl = 0x100, + .tmrr = 0x0, + .tckesr = 0x5, + .tdpd = 0x0 + }, + { + .dtpr0 = 0x48F9AAB4, + .dtpr1 = 0xEA0910, + .dtpr2 = 0x1002C200, + .mr[0] = 0xA60, + .mr[1] = 0x40, + .mr[2] = 0x10, + .mr[3] = 0x0 + }, + .noc_timing = 0x30B25564, + .noc_activate = 0x627, + .ddrconfig = 3, + .ddr_freq = 666*MHz, + .dramtype = DDR3, + .num_channels = 2, + .stride = 13, + .odt = 1 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-2GB.inc new file mode 100644 index 0000000000..ef82b27781 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA F8132A3MA-GD-F chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-4GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-4GB.inc new file mode 100644 index 0000000000..e071646bf4 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-elpida-4GB.inc @@ -0,0 +1,78 @@ +{ + /* two ELPIDA FA232A2MA-GC-F chips */ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0 +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc new file mode 100644 index 0000000000..8d22e6c55a --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-2ranks.inc @@ -0,0 +1,78 @@ +{ + /* Hynix H9CCNNNBPTBLBR-NUD chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc new file mode 100644 index 0000000000..8737bd3ec7 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB-BK.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNNBKTALBR-NUD chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB.inc new file mode 100644 index 0000000000..1c35c90047 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-2GB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Hynix H9CCNNN8GTMLAR chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-4GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-4GB.inc new file mode 100644 index 0000000000..a48ac42a0e --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-hynix-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc new file mode 100644 index 0000000000..179cf5b5d4 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-micron-2GB-D2.inc @@ -0,0 +1,78 @@ +{ + /* 2 Micron DDMT52L256M64D2PP-107 chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc new file mode 100644 index 0000000000..c4ce972bd0 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB-24EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E8E324EB-EGCF chips */ + { + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x1, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB.inc new file mode 100644 index 0000000000..0f15ba5074 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-2GB.inc @@ -0,0 +1,78 @@ +{ + /* two Samsung K4E8E304ED-EGCE000 chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 2, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 9, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc new file mode 100644 index 0000000000..6b6df57a49 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB-04EB.inc @@ -0,0 +1,78 @@ +{ + /* 2 Samsung K4E6E304EB-EGCE chips */ + { + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + }, + { + .rank = 0x2, + .col = 0xA, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x2, + .row_3_4 = 0x0, + .cs0_row = 0xF, + .cs1_row = 0xF + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 3, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB.inc new file mode 100644 index 0000000000..09d260bc23 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-lpddr3-samsung-4GB.inc @@ -0,0 +1,77 @@ +{ + { + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + }, + { + .rank = 0x2, + .col = 0xB, + .bk = 0x3, + .bw = 0x2, + .dbw = 0x1, + .row_3_4 = 0x0, + .cs0_row = 0xE, + .cs1_row = 0xE + } + }, + { + .togcnt1u = 0x215, + .tinit = 0xC8, + .trsth = 0x0, + .togcnt100n = 0x35, + .trefi = 0x26, + .tmrd = 0x2, + .trfc = 0x70, + .trp = 0x2000D, + .trtw = 0x6, + .tal = 0x0, + .tcl = 0x8, + .tcwl = 0x4, + .tras = 0x17, + .trc = 0x24, + .trcd = 0xD, + .trrd = 0x6, + .trtp = 0x4, + .twr = 0x8, + .twtr = 0x4, + .texsr = 0x76, + .txp = 0x4, + .txpdll = 0x0, + .tzqcs = 0x30, + .tzqcsi = 0x0, + .tdqs = 0x1, + .tcksre = 0x2, + .tcksrx = 0x2, + .tcke = 0x4, + .tmod = 0x0, + .trstl = 0x0, + .tzqcl = 0xC0, + .tmrr = 0x4, + .tckesr = 0x8, + .tdpd = 0x1F4 + }, + { + .dtpr0 = 0x48D7DD93, + .dtpr1 = 0x187008D8, + .dtpr2 = 0x121076, + .mr[0] = 0x0, + .mr[1] = 0xC3, + .mr[2] = 0x6, + .mr[3] = 0x1 + }, + .noc_timing = 0x20D266A4, + .noc_activate = 0x5B6, + .ddrconfig = 6, + .ddr_freq = 533*MHz, + .dramtype = LPDDR3, + .num_channels = 2, + .stride = 13, + .odt = 0, +}, diff --git a/src/mainboard/google/veyron_tiger/sdram_inf/sdram-unused.inc b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-unused.inc new file mode 100644 index 0000000000..06498f7f14 --- /dev/null +++ b/src/mainboard/google/veyron_tiger/sdram_inf/sdram-unused.inc @@ -0,0 +1,3 @@ +{ + .dramtype= UNUSED +}, \ No newline at end of file diff --git a/src/mainboard/hp/dl145_g1/Kconfig b/src/mainboard/hp/dl145_g1/Kconfig index 16b5733c38..017b3a2e5d 100644 --- a/src/mainboard/hp/dl145_g1/Kconfig +++ b/src/mainboard/hp/dl145_g1/Kconfig @@ -2,7 +2,6 @@ if BOARD_HP_DL145_G1 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/hp/dl145_g3/Kconfig b/src/mainboard/hp/dl145_g3/Kconfig index bee23f7553..c0a763bca5 100644 --- a/src/mainboard/hp/dl145_g3/Kconfig +++ b/src/mainboard/hp/dl145_g3/Kconfig @@ -2,7 +2,6 @@ if BOARD_HP_DL145_G3 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/hp/dl165_g6_fam10/Kconfig b/src/mainboard/hp/dl165_g6_fam10/Kconfig index 32abeec96a..214d9482b3 100644 --- a/src/mainboard/hp/dl165_g6_fam10/Kconfig +++ b/src/mainboard/hp/dl165_g6_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_HP_DL165_G6_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select NORTHBRIDGE_AMD_AMDFAM10 select NORTHBRIDGE_AMD_AMDFAM10_ROOT_COMPLEX diff --git a/src/mainboard/hp/e_vectra_p2706t/Kconfig b/src/mainboard/hp/e_vectra_p2706t/Kconfig index e78238c61d..c5aa340ce1 100644 --- a/src/mainboard/hp/e_vectra_p2706t/Kconfig +++ b/src/mainboard/hp/e_vectra_p2706t/Kconfig @@ -24,7 +24,6 @@ if BOARD_HP_E_VECTRA_P2706T config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/ibase/mb899/Kconfig b/src/mainboard/ibase/mb899/Kconfig index 6b3bdfa4bb..22182a470a 100644 --- a/src/mainboard/ibase/mb899/Kconfig +++ b/src/mainboard/ibase/mb899/Kconfig @@ -2,7 +2,6 @@ if BOARD_IBASE_MB899 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/ibase/mb899/mainboard.c b/src/mainboard/ibase/mb899/mainboard.c index 4fc7d0490d..dbbc598fe5 100644 --- a/src/mainboard/ibase/mb899/mainboard.c +++ b/src/mainboard/ibase/mb899/mainboard.c @@ -20,13 +20,13 @@ #include #include #include -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include #include -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { #define BOOT_DISPLAY_DEFAULT 0 @@ -213,7 +213,7 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/ibm/e325/Kconfig b/src/mainboard/ibm/e325/Kconfig index 5cfc6cd142..13da191376 100644 --- a/src/mainboard/ibm/e325/Kconfig +++ b/src/mainboard/ibm/e325/Kconfig @@ -2,7 +2,6 @@ if BOARD_IBM_E325 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/ibm/e326/Kconfig b/src/mainboard/ibm/e326/Kconfig index c79d2c0f84..0707e1b6da 100644 --- a/src/mainboard/ibm/e326/Kconfig +++ b/src/mainboard/ibm/e326/Kconfig @@ -2,7 +2,6 @@ if BOARD_IBM_E326 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/iei/juki-511p/Kconfig b/src/mainboard/iei/juki-511p/Kconfig index 38071c37b6..2ebcac9363 100644 --- a/src/mainboard/iei/juki-511p/Kconfig +++ b/src/mainboard/iei/juki-511p/Kconfig @@ -20,7 +20,6 @@ if BOARD_IEI_JUKI_511P config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/iei/kino-780am2-fam10/Kconfig b/src/mainboard/iei/kino-780am2-fam10/Kconfig index 4c02a62c0a..a18bcc67a3 100644 --- a/src/mainboard/iei/kino-780am2-fam10/Kconfig +++ b/src/mainboard/iei/kino-780am2-fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_IEI_KINO_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2R2 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/iei/nova4899r/Kconfig b/src/mainboard/iei/nova4899r/Kconfig index 36db67bf49..8d0a9a4751 100644 --- a/src/mainboard/iei/nova4899r/Kconfig +++ b/src/mainboard/iei/nova4899r/Kconfig @@ -20,7 +20,6 @@ if BOARD_IEI_NOVA_4899R config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/iei/pcisa-lx-800-r10/Kconfig b/src/mainboard/iei/pcisa-lx-800-r10/Kconfig index 69e106e750..74a3c102de 100644 --- a/src/mainboard/iei/pcisa-lx-800-r10/Kconfig +++ b/src/mainboard/iei/pcisa-lx-800-r10/Kconfig @@ -2,7 +2,6 @@ if BOARD_IEI_PCISA_LX_800_R10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/iei/pm-lx-800-r11/Kconfig b/src/mainboard/iei/pm-lx-800-r11/Kconfig index e443c6c8d6..61c27722c1 100644 --- a/src/mainboard/iei/pm-lx-800-r11/Kconfig +++ b/src/mainboard/iei/pm-lx-800-r11/Kconfig @@ -23,7 +23,6 @@ if BOARD_IEI_PM_LX_800_R11 config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/iei/pm-lx2-800-r10/Kconfig b/src/mainboard/iei/pm-lx2-800-r10/Kconfig index 1485c94894..8e92e69c69 100644 --- a/src/mainboard/iei/pm-lx2-800-r10/Kconfig +++ b/src/mainboard/iei/pm-lx2-800-r10/Kconfig @@ -23,7 +23,6 @@ if BOARD_IEI_PM_LX2_800_R10 config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/intel/Kconfig b/src/mainboard/intel/Kconfig index 3594a30c5a..d51f6b4ed8 100644 --- a/src/mainboard/intel/Kconfig +++ b/src/mainboard/intel/Kconfig @@ -21,10 +21,12 @@ config BOARD_INTEL_XE7501DEVKIT bool "XE7501devkit" config BOARD_INTEL_BASKING_RIDGE bool "Basking Ridge CRB" -config BOARD_INTEL_WTM1 - bool "Whitetip Mountain 1 CRB" config BOARD_INTEL_WTM2 bool "Whitetip Mountain 2 CRB" +config BOARD_INTEL_BAYLEYBAY + bool "Bayley Bay CRB" +config BOARD_INTEL_PEARLVALLEY + bool "Pearl Valley CRB" endchoice @@ -37,8 +39,9 @@ source "src/mainboard/intel/jarrell/Kconfig" source "src/mainboard/intel/mtarvon/Kconfig" source "src/mainboard/intel/truxton/Kconfig" source "src/mainboard/intel/xe7501devkit/Kconfig" -source "src/mainboard/intel/wtm1/Kconfig" source "src/mainboard/intel/wtm2/Kconfig" +source "src/mainboard/intel/bayleybay/Kconfig" +source "src/mainboard/intel/pearlvalley/Kconfig" config MAINBOARD_VENDOR string diff --git a/src/mainboard/intel/baskingridge/Kconfig b/src/mainboard/intel/baskingridge/Kconfig index 24630797c7..076f63eb03 100644 --- a/src/mainboard/intel/baskingridge/Kconfig +++ b/src/mainboard/intel/baskingridge/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_BASKING_RIDGE config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_HASWELL select SOUTHBRIDGE_INTEL_LYNXPOINT @@ -14,7 +13,9 @@ config BOARD_SPECIFIC_OPTIONS # dummy select MMCONF_SUPPORT select HAVE_SMI_HANDLER select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB + select LAPIC_MONOTONIC_TIMER config MAINBOARD_DIR string diff --git a/src/mainboard/intel/baskingridge/acpi/chromeos.asl b/src/mainboard/intel/baskingridge/acpi/chromeos.asl index 307e2e2cd9..da4fb40133 100644 --- a/src/mainboard/intel/baskingridge/acpi/chromeos.asl +++ b/src/mainboard/intel/baskingridge/acpi/chromeos.asl @@ -18,7 +18,7 @@ */ Name(OIPG, Package() { - Package() { 0x001, 0, 22, "CougarPoint" }, // recovery button - Package() { 0x002, 1, 57, "CougarPoint" }, // developer switch - Package() { 0x003, 0, 48, "CougarPoint" }, // firmware write protect + Package () { 0x0001, 1, 69, "LynxPoint" }, // recovery + Package () { 0x0002, 0, 48, "LynxPoint" }, // developer + Package () { 0x0003, 0, 22, "LynxPoint" }, // firmware write protect }) diff --git a/src/mainboard/intel/baskingridge/acpi_tables.c b/src/mainboard/intel/baskingridge/acpi_tables.c index c4adcd71d9..f4b74bc83a 100644 --- a/src/mainboard/intel/baskingridge/acpi_tables.c +++ b/src/mainboard/intel/baskingridge/acpi_tables.c @@ -106,6 +106,9 @@ static void acpi_create_gnvs(global_nvs_t *gnvs) gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; #endif + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); + acpi_update_thermal_table(gnvs); } diff --git a/src/mainboard/intel/baskingridge/chromeos.c b/src/mainboard/intel/baskingridge/chromeos.c index 6bf5116c64..8f0e92d1e9 100644 --- a/src/mainboard/intel/baskingridge/chromeos.c +++ b/src/mainboard/intel/baskingridge/chromeos.c @@ -29,8 +29,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 void fill_lb_gpios(struct lb_gpios *gpios) { diff --git a/src/mainboard/intel/baskingridge/devicetree.cb b/src/mainboard/intel/baskingridge/devicetree.cb index fa3f3e7773..a173aaa662 100644 --- a/src/mainboard/intel/baskingridge/devicetree.cb +++ b/src/mainboard/intel/baskingridge/devicetree.cb @@ -17,13 +17,13 @@ chip northbridge/intel/haswell # Magic APIC ID to locate this chip device lapic 0xACAC off end - register "c1_battery" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_battery" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_battery" = "5" # ACPI(C3) = MWAIT(C7) + register "c1_battery" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_battery" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_battery" = "9" # ACPI(C3) = MWAIT(C7S) - register "c1_acpower" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_acpower" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_acpower" = "5" # ACPI(C3) = MWAIT(C7) + register "c1_acpower" = "2" # ACPI(C1) = MWAIT(C1E) + register "c2_acpower" = "3" # ACPI(C2) = MWAIT(C3) + register "c3_acpower" = "9" # ACPI(C3) = MWAIT(C7S) end end diff --git a/src/mainboard/intel/baskingridge/mainboard.c b/src/mainboard/intel/baskingridge/mainboard.c index c7b0ee00ac..69943cb036 100644 --- a/src/mainboard/intel/baskingridge/mainboard.c +++ b/src/mainboard/intel/baskingridge/mainboard.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright (C) 2011 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -42,15 +42,15 @@ void mainboard_suspend_resume(void) outb(0xcb, 0xb2); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - int res=-1; + int res = 0; - printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); - switch(regs->eax & 0xffff) { + switch (X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -59,11 +59,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x01; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; break; case 0x5f35: /* @@ -77,11 +75,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 0x5f51: /* @@ -91,129 +87,47 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0003; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch ((X86_CX >> 8) & 0xff) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; } break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0001; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) * - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) * - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 3; - break; - case 0x5f70: - /* Unknown */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 * cim_verb_data; @@ -230,9 +144,9 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/intel/baskingridge/mainboard_smi.c b/src/mainboard/intel/baskingridge/mainboard_smi.c index e543494b25..f24af67579 100644 --- a/src/mainboard/intel/baskingridge/mainboard_smi.c +++ b/src/mainboard/intel/baskingridge/mainboard_smi.c @@ -84,7 +84,6 @@ int mainboard_smi_apmc(u8 apmc) return 0; } - intel_me_finalize_smm(); intel_pch_finalize_smm(); intel_northbridge_haswell_finalize_smm(); intel_cpu_haswell_finalize_smm(); diff --git a/src/mainboard/intel/baskingridge/romstage.c b/src/mainboard/intel/baskingridge/romstage.c index 36592541a0..a0b242badf 100644 --- a/src/mainboard/intel/baskingridge/romstage.c +++ b/src/mainboard/intel/baskingridge/romstage.c @@ -93,21 +93,45 @@ void mainboard_romstage_entry(unsigned long bist) dimm_channel0_disabled: 0, dimm_channel1_disabled: 0, max_ddr3_freq: 1600, - usb_port_config: { - { 1, 0, 0x0040 }, /* P0: Back USB3 port (OC0) */ - { 1, 0, 0x0040 }, /* P1: Back USB3 port (OC0) */ - { 1, 1, 0x0040 }, /* P2: Flex Port on bottom (OC1) */ - { 1, 8, 0x0040 }, /* P3: Docking connector (no OC) */ - { 1, 8, 0x0040 }, /* P4: Mini PCIE (no OC) */ - { 1, 1, 0x0040 }, /* P5: USB eSATA header (OC1) */ - { 1, 3, 0x0040 }, /* P6: Front Header J8H2 (OC3) */ - { 1, 3, 0x0040 }, /* P7: Front Header J8H2 (OC3) */ - { 1, 4, 0x0040 }, /* P8: USB/LAN Jack (OC4) */ - { 1, 4, 0x0040 }, /* P9: USB/LAN Jack (OC4) */ - { 1, 5, 0x0040 }, /* P10: Front Header J7H3 (OC5) */ - { 1, 5, 0x0040 }, /* P11: Front Header J7H3 (OC5) */ - { 1, 6, 0x0040 }, /* P12: USB/DP Jack (OC6) */ - { 1, 6, 0x0040 }, /* P13: USB/DP Jack (OC6) */ + usb2_ports: { + /* Length, Enable, OCn#, Location */ + { 0x0040, 1, 0, /* P0: Back USB3 port (OC0) */ + USB_PORT_BACK_PANEL }, + { 0x0040, 1, 0, /* P1: Back USB3 port (OC0) */ + USB_PORT_BACK_PANEL }, + { 0x0040, 1, 1, /* P2: Flex Port on bottom (OC1) */ + USB_PORT_FLEX }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P3: Dock connector */ + USB_PORT_DOCK }, + { 0x0040, 1, USB_OC_PIN_SKIP, /* P4: Mini PCIE */ + USB_PORT_MINI_PCIE }, + { 0x0040, 1, 1, /* P5: USB eSATA header (OC1) */ + USB_PORT_FLEX }, + { 0x0040, 1, 3, /* P6: Front Header J8H2 (OC3) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 3, /* P7: Front Header J8H2 (OC3) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 4, /* P8: USB/LAN Jack (OC4) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 4, /* P9: USB/LAN Jack (OC4) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 5, /* P10: Front Header J7H3 (OC5) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 5, /* P11: Front Header J7H3 (OC5) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 6, /* P12: USB/DP Jack (OC6) */ + USB_PORT_FRONT_PANEL }, + { 0x0040, 1, 6, /* P13: USB/DP Jack (OC6) */ + USB_PORT_FRONT_PANEL }, + }, + usb3_ports: { + /* Enable, OCn# */ + { 1, 0 }, /* P1; */ + { 1, 0 }, /* P2; */ + { 1, 0 }, /* P3; */ + { 1, 0 }, /* P4; */ + { 1, 0 }, /* P6; */ + { 1, 0 }, /* P6; */ }, }; @@ -116,6 +140,7 @@ void mainboard_romstage_entry(unsigned long bist) .gpio_map = &mainboard_gpio_map, .rcba_config = &rcba_config[0], .bist = bist, + .copy_spd = NULL, }; /* Call into the real romstage main with this board's attributes. */ diff --git a/src/mainboard/intel/bayleybay/Kconfig b/src/mainboard/intel/bayleybay/Kconfig new file mode 100644 index 0000000000..97120d2113 --- /dev/null +++ b/src/mainboard/intel/bayleybay/Kconfig @@ -0,0 +1,26 @@ +if BOARD_INTEL_BAYLEYBAY + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select SOC_INTEL_BAYTRAIL + select ENABLE_BUILTIN_COM1 + select BOARD_ROMSIZE_KB_8192 + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select CHROMEOS + select CHROMEOS_VBNV_CMOS + +config MAINBOARD_DIR + string + default intel/bayleybay + +config MAINBOARD_PART_NUMBER + string + default "BAYLEY BAY" + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif # BOARD_INTEL_BAYLEYBAY diff --git a/src/mainboard/intel/wtm1/Makefile.inc b/src/mainboard/intel/bayleybay/Makefile.inc similarity index 89% rename from src/mainboard/intel/wtm1/Makefile.inc rename to src/mainboard/intel/bayleybay/Makefile.inc index 658c96c77e..bb9ba94fc8 100644 --- a/src/mainboard/intel/wtm1/Makefile.inc +++ b/src/mainboard/intel/bayleybay/Makefile.inc @@ -1,7 +1,7 @@ ## ## This file is part of the coreboot project. ## -## Copyright (C) 2011 Google Inc. +## Copyright (C) 2013 Google Inc. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -19,5 +19,7 @@ romstage-$(CONFIG_CHROMEOS) += chromeos.c ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += gpio.c +ramstage-y += irqroute.c smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c diff --git a/src/mainboard/intel/bayleybay/acpi/chromeos.asl b/src/mainboard/intel/bayleybay/acpi/chromeos.asl new file mode 100644 index 0000000000..40ffcf0156 --- /dev/null +++ b/src/mainboard/intel/bayleybay/acpi/chromeos.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFF, "LynxPoint" }, // recovery + Package () { 0x0002, 0, 0xFF, "LynxPoint" }, // developer + Package () { 0x0003, 0, 0xFF, "LynxPoint" }, // firmware write protect +}) diff --git a/src/mainboard/intel/bayleybay/acpi/ec.asl b/src/mainboard/intel/bayleybay/acpi/ec.asl new file mode 100644 index 0000000000..9ae5951aca --- /dev/null +++ b/src/mainboard/intel/bayleybay/acpi/ec.asl @@ -0,0 +1,37 @@ +Device (EC0) +{ + Name (_HID, EISAID ("PNP0C09")) + Name (_UID, 1) + Name (_GPE, 10) // GPIO 10 is SMC_RUNTIME_SCI_N + + OperationRegion (ERAM, EmbeddedControl, 0x00, 0xff) + Field (ERAM, ByteAcc, Lock, Preserve) + { + Offset (0x03), + ACPR, 1, // AC Power (1=present) + , 2, + CFAN, 1, // CPU Fan (1=on) + , 2, + LIDS, 1, // Lid State (1=open) + , 1, + SPTR, 8, // SMBUS Protocol Register + SSTS, 8, // SMBUS Status Register + SADR, 8, // SMBUS Address Register + SCMD, 8, // SMBUS Command Register + SBFR, 256, // SMBUS Block Buffer + SCNT, 8, // SMBUS Block Count + + Offset (0x3a), + ECMD, 8, // EC Command Register + + Offset (0x82), + PECL, 8, // PECI fractional (1/64 Celsius) + PECH, 8, // PECI integer (Celsius) + } + + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x62, 0x62, 0, 1) + IO (Decode16, 0x66, 0x66, 0, 1) + }) +} diff --git a/src/mainboard/intel/bayleybay/acpi/mainboard.asl b/src/mainboard/intel/bayleybay/acpi/mainboard.asl new file mode 100644 index 0000000000..99dc630b91 --- /dev/null +++ b/src/mainboard/intel/bayleybay/acpi/mainboard.asl @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (PWRB) +{ + Name(_HID, EisaId("PNP0C0C")) + + // Wake from deep sleep via GPIO27 + Name(_PRW, Package(){27, 4}) +} +Scope (\_SB.LPEA) +{ + Name (GBUF, ResourceTemplate () + { + //There is no LPE device on bayleybay + //If we don't add this Name space here, it will cause compile error + }) +} + diff --git a/src/mainboard/intel/wtm1/acpi/superio.asl b/src/mainboard/intel/bayleybay/acpi/superio.asl similarity index 100% rename from src/mainboard/intel/wtm1/acpi/superio.asl rename to src/mainboard/intel/bayleybay/acpi/superio.asl diff --git a/src/mainboard/intel/wtm1/acpi/thermal.asl b/src/mainboard/intel/bayleybay/acpi/thermal.asl similarity index 100% rename from src/mainboard/intel/wtm1/acpi/thermal.asl rename to src/mainboard/intel/bayleybay/acpi/thermal.asl diff --git a/src/mainboard/intel/bayleybay/acpi/video.asl b/src/mainboard/intel/bayleybay/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/intel/bayleybay/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/intel/bayleybay/acpi_tables.c b/src/mainboard/intel/bayleybay/acpi_tables.c new file mode 100644 index 0000000000..981116bfe4 --- /dev/null +++ b/src/mainboard/intel/bayleybay/acpi_tables.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + gnvs->s3u1 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* TPM Present */ + gnvs->tpmp = 1; + + /* Enable DPTF */ + gnvs->dpte = 1; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + current = acpi_madt_irq_overrides(current); + + return current; +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + // Not implemented + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + /* No NUMA, no SRAT */ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/intel/bayleybay/chromeos.c b/src/mainboard/intel/bayleybay/chromeos.c new file mode 100644 index 0000000000..082f9efa4c --- /dev/null +++ b/src/mainboard/intel/bayleybay/chromeos.c @@ -0,0 +1,77 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +/* Compile-time settings for developer and recovery mode. */ +#define DEV_MODE_SETTING 1 +#define REC_MODE_SETTING 0 + +#ifndef __PRE_RAM__ +#include + +#define GPIO_COUNT 6 + +static void fill_lb_gpio(struct lb_gpio *gpio, int polarity, + const char *name, int force) +{ + memset(gpio, 0, sizeof(*gpio)); + gpio->port = -1; + gpio->polarity = polarity; + if (force >= 0) + gpio->value = force; + strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH); +} + +void fill_lb_gpios(struct lb_gpios *gpios) +{ + struct lb_gpio *gpio; + + gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio)); + gpios->count = GPIO_COUNT; + + gpio = gpios->gpios; + fill_lb_gpio(gpio++, ACTIVE_HIGH, "write protect", 0); + fill_lb_gpio(gpio++, ACTIVE_HIGH, "recovery", REC_MODE_SETTING); + fill_lb_gpio(gpio++, ACTIVE_HIGH, "developer", DEV_MODE_SETTING); + fill_lb_gpio(gpio++, ACTIVE_HIGH, "lid", 1); // force open + fill_lb_gpio(gpio++, ACTIVE_HIGH, "power", 0); + fill_lb_gpio(gpio++, ACTIVE_HIGH, "oprom", oprom_is_loaded); +} +#endif + +int get_developer_mode_switch(void) +{ + return DEV_MODE_SETTING; +} + +int get_recovery_mode_switch(void) +{ + return REC_MODE_SETTING; +} + +int get_write_protect_state(void) +{ + return 0; +} + diff --git a/src/mainboard/intel/bayleybay/cmos.layout b/src/mainboard/intel/bayleybay/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/intel/bayleybay/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/intel/bayleybay/devicetree.cb b/src/mainboard/intel/bayleybay/devicetree.cb new file mode 100644 index 0000000000..fe4a3212e1 --- /dev/null +++ b/src/mainboard/intel/bayleybay/devicetree.cb @@ -0,0 +1,75 @@ +chip soc/intel/baytrail + + #bayleybay will need itp all the time + register "enable_xdp_tap" = "1" + + # SATA port enable mask (2 ports) + register "sata_port_map" = "0x1" + register "sata_ahci" = "0x1" + register "ide_legacy_combined" = "0x0" + + # Route USB ports to XHCI + register "usb_route_to_xhci" = "1" + + # USB Port Disable Mask + register "usb2_port_disable_mask" = "0x0" + register "usb3_port_disable_mask" = "0x0" + + # USB PHY settings + # TODO: These values are from Baytrail and need tuned for Rambi board + register "usb2_per_port_lane0" = "0x0004f201" + register "usb2_per_port_rcomp_hs_pullup0" = "0x05004015" + register "usb2_per_port_lane1" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup1" = "0x00004011" + register "usb2_per_port_lane2" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup2" = "0x00004011" + register "usb2_per_port_lane3" = "0x00049a09" + register "usb2_per_port_rcomp_hs_pullup3" = "0x00004011" + # Allow PCIe devices to wake system from suspend + register "pcie_wake_enable" = "1" + + # VR PS2 control + register "vnn_ps2_enable" = "1" + register "vcc_ps2_enable" = "1" + + # Disable SLP_X stretching after SUS power well fail. + register "disable_slp_x_stretch_sus_fail" = "1" + + device cpu_cluster 0 on + device lapic 0 on end + end + device domain 0 on + device pci 00.0 on end # SoC router + device pci 02.0 on end # GFX + device pci 11.0 off end # SDIO + device pci 13.0 on end # SATA + device pci 14.0 on end # XHCI + device pci 15.0 on end # LPE + device pci 16.0 off end # SD + device pci 17.0 off end # MMC + device pci 18.0 on end # SIO_DMA1 + device pci 18.1 on end # I2C1 + device pci 18.2 on end # I2C2 + device pci 18.3 off end # I2C3 + device pci 18.4 off end # I2C4 + device pci 18.5 on end # I2C5 + device pci 18.6 on end # I2C6 + device pci 18.7 off end # I2C7 + device pci 1a.0 on end # TXE + device pci 1b.0 on end # HDA + device pci 1c.0 on end # PCIE_PORT1 + device pci 1c.1 on end # PCIE_PORT2 + device pci 1c.2 off end # PCIE_PORT3 + device pci 1c.3 off end # PCIE_PORT4 + device pci 1d.0 off end # EHCI + device pci 1e.0 on end # SIO_DMA2 + device pci 1e.1 off end # PWM1 + device pci 1e.2 off end # PWM2 + device pci 1e.3 off end # HSUART1 + device pci 1e.4 off end # HSUART2 + device pci 1e.5 off end # SPI + device pci 1f.0 on + end # LPC Bridge + device pci 1f.3 off end # SMBus + end +end diff --git a/src/mainboard/intel/bayleybay/dsdt.asl b/src/mainboard/intel/bayleybay/dsdt.asl new file mode 100644 index 0000000000..6d18aa079d --- /dev/null +++ b/src/mainboard/intel/bayleybay/dsdt.asl @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x05, // DSDT revision: ACPI v5.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include + + // global NVS and variables + #include + + #include + + Scope (\_SB) { + Device (PCI0) + { + //#include + #include + } + } + + #include "acpi/chromeos.asl" + #include + + /* Chipset specific sleep states */ + #include + + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/intel/bayleybay/fadt.c b/src/mainboard/intel/bayleybay/fadt.c new file mode 100644 index 0000000000..dfd258fa8b --- /dev/null +++ b/src/mainboard/intel/bayleybay/fadt.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + acpi_fill_in_fadt(fadt); + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/intel/bayleybay/gpio.c b/src/mainboard/intel/bayleybay/gpio.c new file mode 100644 index 0000000000..f8f730379f --- /dev/null +++ b/src/mainboard/intel/bayleybay/gpio.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "irqroute.h" + +/* NCORE GPIOs */ +static const struct soc_gpio_map gpncore_gpio_map[] = { + GPIO_FUNC(2, PULL_UP, 20K), /* GPIO 0 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 1 */ + GPIO_FUNC(2, PULL_UP, 20K), /* GPIO 2 */ + GPIO_INPUT_PD_20K, /* GPIO 3 */ + GPIO_INPUT_PD_20K, /* GPIO 4 */ + GPIO_INPUT_PD_20K, /* GPIO 5 */ + GPIO_FUNC(2, PULL_UP, 20K), /* GPIO 6 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 7 */ + GPIO_FUNC(2, PULL_UP, 20K), /* GPIO 8 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 9 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 10 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 11 */ + GPIO_INPUT_PD_20K, /* GPIO 12 */ + GPIO_INPUT_PD_20K, /* GPIO 13 */ + GPIO_INPUT_PU_20K, /* GPIO 14 */ + GPIO_OUT_LOW, /* GPIO 15 */ + GPIO_OUT_LOW, /* GPIO 16 */ + GPIO_INPUT_PD_20K, /* GPIO 17 */ + GPIO_INPUT_PD_20K, /* GPIO 18 */ + GPIO_OUT_LOW, /* GPIO 19 */ + GPIO_OUT_LOW, /* GPIO 20 */ + GPIO_OUT_LOW, /* GPIO 21 */ + GPIO_OUT_LOW, /* GPIO 22 */ + GPIO_OUT_LOW, /* GPIO 23 */ + GPIO_OUT_LOW, /* GPIO 24 */ + GPIO_OUT_LOW, /* GPIO 25 */ + GPIO_OUT_LOW, /* GPIO 26 */ + GPIO_END +}; + +/* SCORE GPIOs */ +static const struct soc_gpio_map gpscore_gpio_map[] = { + GPIO_DIRQ_EDGEHIGH_PD_20K, /* GPIO 0 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 1 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 2 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 3 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 4 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 5 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 6 */ + GPIO_FUNC(2, PULL_UP, 20K), /* GPIO 7 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 8 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 9 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 10 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 11 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 12 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 13 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 14 */ + GPIO_FUNC(2, PULL_DOWN, 20K), /* GPIO 15 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 16 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 17 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 18 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 19 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 20 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 21 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 22 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 23 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 24 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 25 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 26 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 27 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 28 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 29 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 30 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 31 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 32 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 33 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 34 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 35 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 36 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 37 */ + GPIO_DIRQ_EDGEBOTH_PU_20K, /* GPIO 38 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 39 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 40 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 41 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 42 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 43 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 44 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 45 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 46 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 47 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 48 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 49 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 50 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 51 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 52 */ + GPIO_FUNC(1, PULL_UP, 20K), /* GPIO 53 */ + GPIO_FUNC(1, PULL_DOWN, 20K), /* GPIO 54 */ + GPIO_OUT_LOW, /* GPIO 55 */ + GPIO_INPUT, /* GPIO 56 */ + GPIO_FUNC1, /* GPIO 57 */ + GPIO_INPUT, /* GPIO 58 */ + GPIO_OUT_HIGH, /* GPIO 59 */ + GPIO_OUT_HIGH, /* GPIO 60 */ + GPIO_FUNC1, /* GPIO 61 */ + GPIO_FUNC1, /* GPIO 62 */ + GPIO_FUNC1, /* GPIO 63 */ + GPIO_FUNC1, /* GPIO 64 */ + GPIO_FUNC1, /* GPIO 65 */ + GPIO_FUNC1, /* GPIO 66 */ + GPIO_FUNC1, /* GPIO 67 */ + GPIO_FUNC1, /* GPIO 68 */ + GPIO_FUNC1, /* GPIO 69 */ + GPIO_FUNC1, /* GPIO 70 */ + GPIO_FUNC1, /* GPIO 71 */ + GPIO_FUNC1, /* GPIO 72 */ + GPIO_FUNC1, /* GPIO 73 */ + GPIO_FUNC1, /* GPIO 74 */ + GPIO_FUNC1, /* GPIO 75 */ + GPIO_FUNC1, /* GPIO 76 */ + GPIO_FUNC1, /* GPIO 77 */ + GPIO_FUNC1, /* GPIO 78 */ + GPIO_FUNC1, /* GPIO 79 */ + GPIO_FUNC1, /* GPIO 80 */ + GPIO_FUNC1, /* GPIO 81 */ + GPIO_FUNC1, /* GPIO 82 */ + GPIO_FUNC1, /* GPIO 83 */ + GPIO_FUNC1, /* GPIO 84 */ + GPIO_FUNC1, /* GPIO 85 */ + GPIO_FUNC1, /* GPIO 86 */ + GPIO_FUNC1, /* GPIO 87 */ + GPIO_FUNC1, /* GPIO 88 */ + GPIO_FUNC1, /* GPIO 89 */ + GPIO_FUNC1, /* GPIO 90 */ + GPIO_FUNC1, /* GPIO 91 */ + GPIO_FUNC0, /* GPIO 92 */ + GPIO_FUNC0, /* GPIO 93 */ + GPIO_DIRQ, /* GPIO 94 */ + GPIO_OUT_LOW, /* GPIO 95 */ + GPIO_FUNC1, /* GPIO 96 */ + GPIO_OUT_LOW, /* GPIO 97 */ + GPIO_OUT_LOW, /* GPIO 98 */ + GPIO_FUNC1, /* GPIO 99 */ + GPIO_OUT_HIGH, /* GPIO 100 */ + GPIO_FUNC1, /* GPIO 101 */ + GPIO_END +}; + +/* SSUS GPIOs */ +static const struct soc_gpio_map gpssus_gpio_map[] = { + GPIO_DIRQ_EDGELOW_PU_20K,/* GPIO 0 */ + GPIO_FUNC6, /* GPIO 1 */ + GPIO_FUNC6, /* GPIO 2 */ + GPIO_DIRQ_LEVELLOW_PU_20K, /* GPIO 3 */ + GPIO_DIRQ_EDGEHIGH_PD_20K, /* GPIO 4 */ + GPIO_FUNC1, /* GPIO 5 */ + GPIO_DIRQ_LEVELLOW_PU_20K, /* GPIO 6 */ + GPIO_INPUT_PD_20K, /* GPIO 7 */ + GPIO_OUT_HIGH, /* GPIO 8 */ + GPIO_OUT_LOW, /* GPIO 9 */ + GPIO_DIRQ_LEVELLOW_PU_20K, /* GPIO 10 */ + GPIO_FUNC0, /* GPIO 11 */ + GPIO_FUNC0, /* GPIO 12 */ + GPIO_FUNC0, /* GPIO 13 */ + GPIO_OUT_HIGH, /* GPIO 14 */ + GPIO_FUNC0, /* GPIO 15 */ + GPIO_FUNC0, /* GPIO 16 */ + GPIO_DIRQ_LEVELHIGH_NO_PULL, /* GPIO 17 */ + GPIO_FUNC0, /* GPIO 18 */ + GPIO_FUNC0, /* GPIO 19 */ + GPIO_FUNC0, /* GPIO 20 */ + GPIO_NC, /* GPIO 21 */ + GPIO_NC, /* XDP_GPIO_DFX0 */ + GPIO_NC, /* XDP_GPIO_DFX1 */ + GPIO_NC, /* XDP_GPIO_DFX2 */ + GPIO_NC, /* XDP_GPIO_DFX3 */ + GPIO_NC, /* XDP_GPIO_DFX4 */ + GPIO_NC, /* XDP_GPIO_DFX5 */ + GPIO_NC, /* XDP_GPIO_DFX6 */ + GPIO_NC, /* XDP_GPIO_DFX7 */ + GPIO_NC, /* XDP_GPIO_DFX8 */ + GPIO_OUT_LOW, /* GPIO 31 */ + GPIO_OUT_LOW, /* GPIO 32 */ + GPIO_OUT_LOW, /* GPIO 33 */ + GPIO_INPUT, /* GPIO 34 */ + GPIO_OUT_LOW, /* GPIO 35 */ + GPIO_OUT_LOW, /* GPIO 36 */ + GPIO_OUT_HIGH, /* GPIO 37 */ + GPIO_INPUT, /* GPIO 38 */ + GPIO_INPUT, /* GPIO 39 */ + GPIO_INPUT, /* GPIO 40 */ + GPIO_OUT_HIGH, /* GPIO 41 */ + GPIO_INPUT, /* GPIO 42 */ + GPIO_INPUT, /* GPIO 43 */ + GPIO_END +}; + + + +static struct soc_gpio_config gpio_config = { + .ncore = gpncore_gpio_map, + .score = gpscore_gpio_map, + .ssus = gpssus_gpio_map, + .core_dirq = NULL, + .sus_dirq = NULL, +}; + +struct soc_gpio_config* mainboard_get_gpios(void) +{ + return &gpio_config; +} diff --git a/src/mainboard/intel/bayleybay/irqroute.c b/src/mainboard/intel/bayleybay/irqroute.c new file mode 100644 index 0000000000..552be8f605 --- /dev/null +++ b/src/mainboard/intel/bayleybay/irqroute.c @@ -0,0 +1,22 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "irqroute.h" + +DEFINE_IRQ_ROUTES; diff --git a/src/mainboard/intel/bayleybay/irqroute.h b/src/mainboard/intel/bayleybay/irqroute.h new file mode 100644 index 0000000000..2f75a2b951 --- /dev/null +++ b/src/mainboard/intel/bayleybay/irqroute.h @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#define PCI_DEV_PIRQ_ROUTES \ + PCI_DEV_PIRQ_ROUTE(GFX_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SDIO_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SD_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SATA_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(XHCI_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(LPE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(MMC_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SIO1_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(TXE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(HDA_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(PCIE_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(EHCI_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(SIO2_DEV, A, B, C, D), \ + PCI_DEV_PIRQ_ROUTE(PCU_DEV, A, B, C, D) + +#define PIRQ_PIC_ROUTES \ + PIRQ_PIC(A, DISABLE), \ + PIRQ_PIC(B, DISABLE), \ + PIRQ_PIC(C, DISABLE), \ + PIRQ_PIC(D, DISABLE), \ + PIRQ_PIC(E, DISABLE), \ + PIRQ_PIC(F, DISABLE), \ + PIRQ_PIC(G, DISABLE), \ + PIRQ_PIC(H, DISABLE) diff --git a/src/mainboard/intel/bayleybay/mainboard.c b/src/mainboard/intel/bayleybay/mainboard.c new file mode 100644 index 0000000000..0092034c9e --- /dev/null +++ b/src/mainboard/intel/bayleybay/mainboard.c @@ -0,0 +1,143 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include + +void mainboard_suspend_resume(void) +{ + /* Call SMM finalize() handlers before resume */ + outb(0xcb, 0xb2); +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 1; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/intel/wtm1/mainboard_smi.c b/src/mainboard/intel/bayleybay/mainboard_smi.c similarity index 81% rename from src/mainboard/intel/wtm1/mainboard_smi.c rename to src/mainboard/intel/bayleybay/mainboard_smi.c index 3ffc68441d..dc60e07e5e 100644 --- a/src/mainboard/intel/wtm1/mainboard_smi.c +++ b/src/mainboard/intel/bayleybay/mainboard_smi.c @@ -20,11 +20,7 @@ #include #include #include -#include -#include -#include -#include -#include +#include int mainboard_io_trap_handler(int smif) { @@ -60,11 +56,6 @@ int mainboard_smi_apmc(u8 apmc) return 0; } - intel_me_finalize_smm(); - intel_pch_finalize_smm(); - intel_northbridge_haswell_finalize_smm(); - intel_cpu_haswell_finalize_smm(); - mainboard_finalized = 1; break; } diff --git a/src/mainboard/intel/bayleybay/romstage.c b/src/mainboard/intel/bayleybay/romstage.c new file mode 100644 index 0000000000..5e5debc644 --- /dev/null +++ b/src/mainboard/intel/bayleybay/romstage.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct mrc_params mp = { + .mainboard = { + .dram_type = DRAM_DDR3L, + .dram_info_location = DRAM_INFO_SPD_SMBUS, + .spd_addrs = { 0xa0, 0xa2 }, + }, + }; + rp->mrc_params = ∓ + romstage_common(rp); +} diff --git a/src/mainboard/intel/bayleybay/thermal.h b/src/mainboard/intel/bayleybay/thermal.h new file mode 100644 index 0000000000..f771014215 --- /dev/null +++ b/src/mainboard/intel/bayleybay/thermal.h @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BAYLEYBAY_THERMAL_H +#define BAYLEYBAY_THERMAL_H + +/* Fan is OFF */ +#define FAN4_THRESHOLD_OFF 0 +#define FAN4_THRESHOLD_ON 0 +#define FAN4_PWM 0x00 + +/* Fan is at LOW speed */ +#define FAN3_THRESHOLD_OFF 48 +#define FAN3_THRESHOLD_ON 55 +#define FAN3_PWM 0x40 + +/* Fan is at MEDIUM speed */ +#define FAN2_THRESHOLD_OFF 52 +#define FAN2_THRESHOLD_ON 64 +#define FAN2_PWM 0x80 + +/* Fan is at HIGH speed */ +#define FAN1_THRESHOLD_OFF 60 +#define FAN1_THRESHOLD_ON 68 +#define FAN1_PWM 0xb0 + +/* Fan is at FULL speed */ +#define FAN0_THRESHOLD_OFF 66 +#define FAN0_THRESHOLD_ON 78 +#define FAN0_PWM 0xff + +/* Temperature which OS will shutdown at */ +#define CRITICAL_TEMPERATURE 100 + +/* Temperature which OS will throttle CPU */ +#define PASSIVE_TEMPERATURE 90 + +/* Tj_max value for calculating PECI CPU temperature */ +#define MAX_TEMPERATURE 100 + +#endif diff --git a/src/mainboard/intel/d810e2cb/Kconfig b/src/mainboard/intel/d810e2cb/Kconfig index 91edf33cdf..85b0e6cb99 100644 --- a/src/mainboard/intel/d810e2cb/Kconfig +++ b/src/mainboard/intel/d810e2cb/Kconfig @@ -20,7 +20,6 @@ if BOARD_INTEL_D810E2CB config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_FC_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801BX diff --git a/src/mainboard/intel/d945gclf/Kconfig b/src/mainboard/intel/d945gclf/Kconfig index cc9ceb5ce9..cc8c58af8d 100644 --- a/src/mainboard/intel/d945gclf/Kconfig +++ b/src/mainboard/intel/d945gclf/Kconfig @@ -20,7 +20,6 @@ if BOARD_INTEL_D945GCLF config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_441 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GC diff --git a/src/mainboard/intel/eagleheights/Kconfig b/src/mainboard/intel/eagleheights/Kconfig index 0b765f920e..008e44d656 100644 --- a/src/mainboard/intel/eagleheights/Kconfig +++ b/src/mainboard/intel/eagleheights/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_EAGLEHEIGHTS config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_BGA956 select NORTHBRIDGE_INTEL_I3100 select SOUTHBRIDGE_INTEL_I3100 diff --git a/src/mainboard/intel/emeraldlake2/Kconfig b/src/mainboard/intel/emeraldlake2/Kconfig index 20685f35a7..9217aa66b6 100644 --- a/src/mainboard/intel/emeraldlake2/Kconfig +++ b/src/mainboard/intel/emeraldlake2/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_EMERALDLAKE2 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_RPGA989 select NORTHBRIDGE_INTEL_IVYBRIDGE select SOUTHBRIDGE_INTEL_C216 @@ -14,6 +13,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select MMCONF_SUPPORT select GFXUMA #select CHROMEOS + #select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB select EARLY_CBMEM_INIT diff --git a/src/mainboard/intel/emeraldlake2/chromeos.c b/src/mainboard/intel/emeraldlake2/chromeos.c index 4d998ec4e8..4938ff6fec 100644 --- a/src/mainboard/intel/emeraldlake2/chromeos.c +++ b/src/mainboard/intel/emeraldlake2/chromeos.c @@ -28,8 +28,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 void fill_lb_gpios(struct lb_gpios *gpios) { diff --git a/src/mainboard/intel/emeraldlake2/mainboard.c b/src/mainboard/intel/emeraldlake2/mainboard.c index 92704c984c..5f7d224b32 100644 --- a/src/mainboard/intel/emeraldlake2/mainboard.c +++ b/src/mainboard/intel/emeraldlake2/mainboard.c @@ -156,7 +156,7 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/intel/emeraldlake2/romstage.c b/src/mainboard/intel/emeraldlake2/romstage.c index 88bcced67c..a74358402a 100644 --- a/src/mainboard/intel/emeraldlake2/romstage.c +++ b/src/mainboard/intel/emeraldlake2/romstage.c @@ -170,15 +170,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { pei_version: PEI_VERSION, mchbar: DEFAULT_MCHBAR, @@ -223,9 +221,7 @@ void main(unsigned long bist) }, }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -289,14 +285,13 @@ void main(unsigned long bist) post_code(0x3a); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3b); /* Perform some initialization that must run before stage2 */ early_pch_init(); @@ -342,15 +337,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/intel/jarrell/Kconfig b/src/mainboard/intel/jarrell/Kconfig index 2a62777449..6ecbc870f1 100644 --- a/src/mainboard/intel/jarrell/Kconfig +++ b/src/mainboard/intel/jarrell/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_JARRELL config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7520 select SOUTHBRIDGE_INTEL_PXHD diff --git a/src/mainboard/intel/mtarvon/Kconfig b/src/mainboard/intel/mtarvon/Kconfig index af40cad18c..4097fa7a23 100644 --- a/src/mainboard/intel/mtarvon/Kconfig +++ b/src/mainboard/intel/mtarvon/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_MTARVON config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA479M select NORTHBRIDGE_INTEL_I3100 select SOUTHBRIDGE_INTEL_I3100 diff --git a/src/mainboard/intel/pearlvalley/Kconfig b/src/mainboard/intel/pearlvalley/Kconfig new file mode 100644 index 0000000000..dd3f1b0d1e --- /dev/null +++ b/src/mainboard/intel/pearlvalley/Kconfig @@ -0,0 +1,48 @@ +if BOARD_INTEL_PEARLVALLEY + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select SOC_INTEL_BROADWELL + select BOARD_ROMSIZE_KB_8192 + select HAVE_ACPI_TABLES + select HAVE_OPTION_TABLE + select HAVE_ACPI_RESUME + select MMCONF_SUPPORT + select HAVE_SMI_HANDLER + select CHROMEOS + select CHROMEOS_VBNV_CMOS + select EXTERNAL_MRC_BLOB + select CACHE_ROM + select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x1 + +config VBOOT_REFCODE_INDEX + hex + default 0x2 + +config MAINBOARD_DIR + string + default intel/pearlvalley + +config MAINBOARD_PART_NUMBER + string + default "Pearl Valley CRB" + +config IRQ_SLOT_COUNT + int + default 18 + +config MAX_CPUS + int + default 16 + +config VGA_BIOS_FILE + string + default "pci8086,0166.rom" + +endif diff --git a/src/mainboard/intel/pearlvalley/Makefile.inc b/src/mainboard/intel/pearlvalley/Makefile.inc new file mode 100644 index 0000000000..13a4a35256 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/Makefile.inc @@ -0,0 +1,26 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2011 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +romstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_CHROMEOS) += chromeos.c + +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c + +romstage-y += pei_data.c +ramstage-y += pei_data.c diff --git a/src/mainboard/intel/pearlvalley/acpi/chromeos.asl b/src/mainboard/intel/pearlvalley/acpi/chromeos.asl new file mode 100644 index 0000000000..4cd6dedf46 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/acpi/chromeos.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name(OIPG, Package() { + Package () { 0x0001, 0, 0xFFFFFFFF, "PCH-LP" }, // recovery + Package () { 0x0002, 0, 0xFFFFFFFF, "PCH-LP" }, // developer + Package () { 0x0003, 0, 0xFFFFFFFF, "PCH-LP" }, // firmware write protect +}) diff --git a/src/mainboard/intel/pearlvalley/acpi/ec.asl b/src/mainboard/intel/pearlvalley/acpi/ec.asl new file mode 100644 index 0000000000..9ae5951aca --- /dev/null +++ b/src/mainboard/intel/pearlvalley/acpi/ec.asl @@ -0,0 +1,37 @@ +Device (EC0) +{ + Name (_HID, EISAID ("PNP0C09")) + Name (_UID, 1) + Name (_GPE, 10) // GPIO 10 is SMC_RUNTIME_SCI_N + + OperationRegion (ERAM, EmbeddedControl, 0x00, 0xff) + Field (ERAM, ByteAcc, Lock, Preserve) + { + Offset (0x03), + ACPR, 1, // AC Power (1=present) + , 2, + CFAN, 1, // CPU Fan (1=on) + , 2, + LIDS, 1, // Lid State (1=open) + , 1, + SPTR, 8, // SMBUS Protocol Register + SSTS, 8, // SMBUS Status Register + SADR, 8, // SMBUS Address Register + SCMD, 8, // SMBUS Command Register + SBFR, 256, // SMBUS Block Buffer + SCNT, 8, // SMBUS Block Count + + Offset (0x3a), + ECMD, 8, // EC Command Register + + Offset (0x82), + PECL, 8, // PECI fractional (1/64 Celsius) + PECH, 8, // PECI integer (Celsius) + } + + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x62, 0x62, 0, 1) + IO (Decode16, 0x66, 0x66, 0, 1) + }) +} diff --git a/src/mainboard/intel/wtm1/acpi/mainboard.asl b/src/mainboard/intel/pearlvalley/acpi/mainboard.asl similarity index 89% rename from src/mainboard/intel/wtm1/acpi/mainboard.asl rename to src/mainboard/intel/pearlvalley/acpi/mainboard.asl index 6b15331b81..09cff9aa64 100644 --- a/src/mainboard/intel/wtm1/acpi/mainboard.asl +++ b/src/mainboard/intel/pearlvalley/acpi/mainboard.asl @@ -19,10 +19,10 @@ * MA 02110-1301 USA */ -Device (PWRB) +Scope (\_SB) { - Name(_HID, EisaId("PNP0C0C")) - - // Wake - Name(_PRW, Package(){0x1d, 0x05}) + Device (PWRB) + { + Name (_HID, EisaId("PNP0C0C")) + } } diff --git a/src/mainboard/intel/wtm1/acpi/platform.asl b/src/mainboard/intel/pearlvalley/acpi/platform.asl similarity index 100% rename from src/mainboard/intel/wtm1/acpi/platform.asl rename to src/mainboard/intel/pearlvalley/acpi/platform.asl diff --git a/src/mainboard/intel/wtm1/acpi/chromeos.asl b/src/mainboard/intel/pearlvalley/acpi/superio.asl similarity index 84% rename from src/mainboard/intel/wtm1/acpi/chromeos.asl rename to src/mainboard/intel/pearlvalley/acpi/superio.asl index c6b258b4e2..9092a6c79d 100644 --- a/src/mainboard/intel/wtm1/acpi/chromeos.asl +++ b/src/mainboard/intel/pearlvalley/acpi/superio.asl @@ -17,7 +17,4 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -Name(OIPG, Package() { - // This GPIO is not available but the package cannot be empty - Package () { 0x0001, 0, 0, "LynxPoint" }, // recovery -}) +/* Values should match those defined in devicetree.cb */ diff --git a/src/mainboard/intel/pearlvalley/acpi/thermal.asl b/src/mainboard/intel/pearlvalley/acpi/thermal.asl new file mode 100644 index 0000000000..27d5105868 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/acpi/thermal.asl @@ -0,0 +1,247 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Thermal Zone +#include "../thermal.h" + +Scope (\_TZ) +{ + ThermalZone (THRM) + { + Name (_TC1, 0x02) + Name (_TC2, 0x05) + + // Thermal zone polling frequency: 0 seconds + Name (_TZP, 0) + + // Thermal sampling period for passive cooling: 2 seconds + Name (_TSP, 20) + + // Convert from Degrees C to 1/10 Kelvin for ACPI + Method (CTOK, 1) { + // 10th of Degrees C + Multiply (Arg0, 10, Local0) + + // Convert to Kelvin + Add (Local0, 2732, Local0) + + Return (Local0) + } + + // Threshold for OS to shutdown + Method (_CRT, 0, Serialized) + { + Return (CTOK (\TCRT)) + } + + // Threshold for passive cooling + Method (_PSV, 0, Serialized) + { + Return (CTOK (\TPSV)) + } + + // Processors used for passive cooling + Method (_PSL, 0, Serialized) + { + Return (\PPKG ()) + } + + Method (_TMP, 0, Serialized) + { + Return (CTOK (30)) + } + + Method (_AC0) { + If (LLessEqual (\FLVL, 0)) { + Return (CTOK (FAN0_THRESHOLD_OFF)) + } Else { + Return (CTOK (FAN0_THRESHOLD_ON)) + } + } + + Method (_AC1) { + If (LLessEqual (\FLVL, 1)) { + Return (CTOK (FAN1_THRESHOLD_OFF)) + } Else { + Return (CTOK (FAN1_THRESHOLD_ON)) + } + } + + Method (_AC2) { + If (LLessEqual (\FLVL, 2)) { + Return (CTOK (FAN2_THRESHOLD_OFF)) + } Else { + Return (CTOK (FAN2_THRESHOLD_ON)) + } + } + + Method (_AC3) { + If (LLessEqual (\FLVL, 3)) { + Return (CTOK (FAN3_THRESHOLD_OFF)) + } Else { + Return (CTOK (FAN3_THRESHOLD_ON)) + } + } + + Method (_AC4) { + If (LLessEqual (\FLVL, 4)) { + Return (CTOK (FAN4_THRESHOLD_OFF)) + } Else { + Return (CTOK (FAN4_THRESHOLD_ON)) + } + } + + Name (_AL0, Package () { FAN0 }) + Name (_AL1, Package () { FAN1 }) + Name (_AL2, Package () { FAN2 }) + Name (_AL3, Package () { FAN3 }) + Name (_AL4, Package () { FAN4 }) + + PowerResource (FNP0, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 0)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (0, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP1, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 1)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (1, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (2, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP2, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 2)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (2, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (3, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP3, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 3)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (3, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (4, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + PowerResource (FNP4, 0, 0) + { + Method (_STA) { + If (LLessEqual (\FLVL, 4)) { + Return (One) + } Else { + Return (Zero) + } + } + Method (_ON) { + Store (4, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + Method (_OFF) { + Store (4, \FLVL) + Notify (\_TZ.THRM, 0x81) + } + } + + Device (FAN0) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 0) + Name (_PR0, Package () { FNP0 }) + } + + Device (FAN1) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 1) + Name (_PR0, Package () { FNP1 }) + } + + Device (FAN2) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 2) + Name (_PR0, Package () { FNP2 }) + } + + Device (FAN3) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 3) + Name (_PR0, Package () { FNP3 }) + } + + Device (FAN4) + { + Name (_HID, EISAID ("PNP0C0B")) + Name (_UID, 4) + Name (_PR0, Package () { FNP4 }) + } + } +} + diff --git a/src/mainboard/intel/pearlvalley/acpi/video.asl b/src/mainboard/intel/pearlvalley/acpi/video.asl new file mode 100644 index 0000000000..3ececa912b --- /dev/null +++ b/src/mainboard/intel/pearlvalley/acpi/video.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Brightness write +Method (BRTW, 1, Serialized) +{ + // TODO +} + +// Hot Key Display Switch +Method (HKDS, 1, Serialized) +{ + // TODO +} + +// Lid Switch Display Switch +Method (LSDS, 1, Serialized) +{ + // TODO +} + +// Brightness Notification +Method(BRTN,1,Serialized) +{ + // TODO (no displays defined yet) +} + diff --git a/src/mainboard/intel/pearlvalley/acpi_tables.c b/src/mainboard/intel/pearlvalley/acpi_tables.c new file mode 100644 index 0000000000..2525a3d947 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/acpi_tables.c @@ -0,0 +1,216 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thermal.h" + +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) +{ + acpi_init_gnvs(gnvs); + + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; + + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; + + gnvs->tcrt = CRITICAL_TEMPERATURE; + gnvs->tpsv = PASSIVE_TEMPERATURE; + gnvs->tmax = MAX_TEMPERATURE; +} + +unsigned long acpi_fill_madt(unsigned long current) +{ + /* Local APICs */ + current = acpi_create_madt_lapics(current); + + /* IOAPIC */ + current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, + 2, IO_APIC_ADDR, 0); + + return acpi_madt_irq_overrides(current); +} + +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id) +{ + generate_cpu_entries(); + return (unsigned long) (acpigen_get_current()); +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + return current; +} + +unsigned long acpi_fill_srat(unsigned long current) +{ + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long write_acpi_tables(unsigned long start) +{ + unsigned long current; + int i; + acpi_rsdp_t *rsdp; + acpi_rsdt_t *rsdt; + acpi_xsdt_t *xsdt; + acpi_hpet_t *hpet; + acpi_madt_t *madt; + acpi_mcfg_t *mcfg; + acpi_fadt_t *fadt; + acpi_facs_t *facs; + acpi_header_t *ssdt; + acpi_header_t *dsdt; + global_nvs_t *gnvs; + + current = start; + + /* Align ACPI tables to 16byte */ + ALIGN_CURRENT; + + printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start); + + /* We need at least an RSDP and an RSDT Table */ + rsdp = (acpi_rsdp_t *) current; + current += sizeof(acpi_rsdp_t); + ALIGN_CURRENT; + rsdt = (acpi_rsdt_t *) current; + current += sizeof(acpi_rsdt_t); + ALIGN_CURRENT; + xsdt = (acpi_xsdt_t *) current; + current += sizeof(acpi_xsdt_t); + ALIGN_CURRENT; + + /* clear all table memory */ + memset((void *) start, 0, current - start); + + acpi_write_rsdp(rsdp, rsdt, xsdt); + acpi_write_rsdt(rsdt); + acpi_write_xsdt(xsdt); + + printk(BIOS_DEBUG, "ACPI: * FACS\n"); + facs = (acpi_facs_t *) current; + current += sizeof(acpi_facs_t); + ALIGN_CURRENT; + acpi_create_facs(facs); + + printk(BIOS_DEBUG, "ACPI: * DSDT\n"); + dsdt = (acpi_header_t *) current; + memcpy(dsdt, &AmlCode, sizeof(acpi_header_t)); + current += dsdt->length; + memcpy(dsdt, &AmlCode, dsdt->length); + + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "ACPI: * FADT\n"); + fadt = (acpi_fadt_t *) current; + current += sizeof(acpi_fadt_t); + ALIGN_CURRENT; + + acpi_create_fadt(fadt, facs, dsdt); + acpi_add_table(rsdp, fadt); + + /* + * We explicitly add these tables later on: + */ + printk(BIOS_DEBUG, "ACPI: * HPET\n"); + + hpet = (acpi_hpet_t *) current; + current += sizeof(acpi_hpet_t); + ALIGN_CURRENT; + acpi_create_intel_hpet(hpet); + acpi_add_table(rsdp, hpet); + + /* If we want to use HPET Timers Linux wants an MADT */ + printk(BIOS_DEBUG, "ACPI: * MADT\n"); + + madt = (acpi_madt_t *) current; + acpi_create_madt(madt); + current += madt->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, madt); + + printk(BIOS_DEBUG, "ACPI: * MCFG\n"); + mcfg = (acpi_mcfg_t *) current; + acpi_create_mcfg(mcfg); + current += mcfg->header.length; + ALIGN_CURRENT; + acpi_add_table(rsdp, mcfg); + + /* Update GNVS pointer into CBMEM */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n"); + gnvs = (global_nvs_t *)current; + } + + for (i=0; i < dsdt->length; i++) { + if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) { + printk(BIOS_DEBUG, "ACPI: Patching up global NVS in " + "DSDT at offset 0x%04x -> %p\n", i, gnvs); + *(u32*)(((u32)dsdt) + i) = (unsigned long)gnvs; + acpi_save_gnvs((unsigned long)gnvs); + break; + } + } + + /* And fill it */ + acpi_create_gnvs(gnvs); + + /* And tell SMI about it */ + smm_setup_structures(gnvs, NULL, NULL); + + current += sizeof(global_nvs_t); + ALIGN_CURRENT; + + /* We patched up the DSDT, so we need to recalculate the checksum */ + dsdt->checksum = 0; + dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, + dsdt->length); + + printk(BIOS_DEBUG, "ACPI: * SSDT\n"); + ssdt = (acpi_header_t *)current; + acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR); + current += ssdt->length; + acpi_add_table(rsdp, ssdt); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + printk(BIOS_INFO, "ACPI: done.\n"); + return current; +} diff --git a/src/mainboard/intel/wtm1/chromeos.c b/src/mainboard/intel/pearlvalley/chromeos.c similarity index 85% rename from src/mainboard/intel/wtm1/chromeos.c rename to src/mainboard/intel/pearlvalley/chromeos.c index f8960764f0..003cc217a7 100644 --- a/src/mainboard/intel/wtm1/chromeos.c +++ b/src/mainboard/intel/pearlvalley/chromeos.c @@ -22,14 +22,16 @@ #include #include #include -#include +#include + +/* Compile-time settings for developer and recovery mode. */ +#define DEV_MODE_SETTING 0 +#define REC_MODE_SETTING 0 #ifndef __PRE_RAM__ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 static void fill_lb_gpio(struct lb_gpio *gpio, int num, int polarity, const char *name, int force) @@ -53,8 +55,8 @@ void fill_lb_gpios(struct lb_gpios *gpios) gpio = gpios->gpios; fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "write protect", 0); - fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", 0); // force off - fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", 1); // force on + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery", REC_MODE_SETTING); + fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer", DEV_MODE_SETTING); fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", 1); // force open fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0); fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded); @@ -63,12 +65,12 @@ void fill_lb_gpios(struct lb_gpios *gpios) int get_developer_mode_switch(void) { - return 1; // force on + return DEV_MODE_SETTING; } int get_recovery_mode_switch(void) { - return 0; // force off + return REC_MODE_SETTING; } int get_write_protect_state(void) diff --git a/src/mainboard/intel/pearlvalley/cmos.layout b/src/mainboard/intel/pearlvalley/cmos.layout new file mode 100644 index 0000000000..afdd3c66ca --- /dev/null +++ b/src/mainboard/intel/pearlvalley/cmos.layout @@ -0,0 +1,139 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2007-2008 coresystems GmbH +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +# ----------------------------------------------------------------- +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +# ----------------------------------------------------------------- +# Status Register A +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +# ----------------------------------------------------------------- +# Status Register B +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +0 120 r 0 reserved_memory +#120 264 r 0 unused + +# ----------------------------------------------------------------- +# RTC_BOOT_BYTE (coreboot hardcoded) +384 1 e 4 boot_option +385 1 e 4 last_boot +388 4 r 0 reboot_bits +#390 2 r 0 unused? + +# ----------------------------------------------------------------- +# coreboot config options: console +392 3 e 5 baud_rate +395 4 e 6 debug_level +#399 1 r 0 unused + +# coreboot config options: cpu +400 1 e 2 hyper_threading +#401 7 r 0 unused + +# coreboot config options: southbridge +408 1 e 1 nmi +409 2 e 7 power_on_after_fail +#411 5 r 0 unused + +# coreboot config options: bootloader +#Used by ChromeOS: +416 128 r 0 vbnv +#544 440 r 0 unused + +# SandyBridge MRC Scrambler Seed values +896 32 r 0 mrc_scrambler_seed +928 32 r 0 mrc_scrambler_seed_s3 + +# coreboot config options: check sums +984 16 h 0 check_sum +#1000 24 r 0 amd_reserved + +# ----------------------------------------------------------------- + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 1 Emergency +6 2 Alert +6 3 Critical +6 4 Error +6 5 Warning +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Disable +7 1 Enable +7 2 Keep +# ----------------------------------------------------------------- +checksums + +checksum 392 415 984 + + diff --git a/src/mainboard/intel/pearlvalley/devicetree.cb b/src/mainboard/intel/pearlvalley/devicetree.cb new file mode 100644 index 0000000000..65395e6f14 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/devicetree.cb @@ -0,0 +1,79 @@ +chip soc/intel/broadwell + + # Enable DisplayPort 1 Hotplug with 6ms pulse + register "gpu_dp_d_hotplug" = "0x06" + + # Enable DisplayPort 0 Hotplug with 6ms pulse + register "gpu_dp_c_hotplug" = "0x06" + + # Enable DVI Hotplug with 6ms pulse + register "gpu_dp_b_hotplug" = "0x06" + + # Set backlight PWM values for eDP + register "gpu_cpu_backlight" = "0x00000200" + register "gpu_pch_backlight" = "0x04000000" + + # Enable Panel and configure power delays + register "gpu_panel_port_select" = "1" # eDP + register "gpu_panel_power_cycle_delay" = "6" # 500ms + register "gpu_panel_power_up_delay" = "2000" # 200ms + register "gpu_panel_power_down_delay" = "500" # 50ms + register "gpu_panel_power_backlight_on_delay" = "2000" # 200ms + register "gpu_panel_power_backlight_off_delay" = "2000" # 200ms + + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + register "alt_gp_smi_en" = "0x0000" + register "gpe0_en_1" = "0x00000400" + register "gpe0_en_2" = "0x00000000" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "sata_port_map" = "0x2" + register "sio_acpi_mode" = "1" + register "s0ix_enable" = "1" + + device cpu_cluster 0 on + device lapic 0 on end + end + device domain 0 on + device pci 00.0 on end # host bridge + device pci 02.0 on end # vga controller + device pci 03.0 on end # mini-hd audio + device pci 13.0 on end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 off end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 on end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 on end # PCIe Port #6 + device pci 1d.0 off end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal + end +end diff --git a/src/mainboard/intel/pearlvalley/dsdt.asl b/src/mainboard/intel/pearlvalley/dsdt.asl new file mode 100644 index 0000000000..f8d3caedaa --- /dev/null +++ b/src/mainboard/intel/pearlvalley/dsdt.asl @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +//#define ENABLE_TPM + +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, // DSDT revision: ACPI v2.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20110725 // OEM revision +) +{ + // Some generic macros + #include "acpi/platform.asl" + + // global NVS and variables + #include + + // General Purpose Events + //#include "acpi/gpe.asl" + + // CPU + #include + + Scope (\_SB) { + Device (PCI0) + { + #include + #include + } + } + + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific + #include "acpi/chromeos.asl" + #include + + // Chipset specific sleep states + #include + + // Mainboard specific + #include "acpi/mainboard.asl" +} diff --git a/src/mainboard/intel/pearlvalley/fadt.c b/src/mainboard/intel/pearlvalley/fadt.c new file mode 100644 index 0000000000..a876e1f97a --- /dev/null +++ b/src/mainboard/intel/pearlvalley/fadt.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + memset((void *) fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = sizeof(acpi_fadt_t); + header->revision = 5; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 1; + + fadt->firmware_ctrl = (unsigned long) facs; + fadt->dsdt = (unsigned long) dsdt; + fadt->model = 1; + fadt->preferred_pm_profile = PM_MOBILE; + + fadt->x_firmware_ctl_l = (unsigned long)facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (unsigned long)dsdt; + fadt->x_dsdt_h = 0; + + acpi_fill_in_fadt(fadt); + + header->checksum = + acpi_checksum((void *) fadt, header->length); +} diff --git a/src/mainboard/intel/pearlvalley/gpio.h b/src/mainboard/intel/pearlvalley/gpio.h new file mode 100644 index 0000000000..20e548b04c --- /dev/null +++ b/src/mainboard/intel/pearlvalley/gpio.h @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAINBOARD_GPIO_H +#define MAINBOARD_GPIO_H + +#include + +static const struct gpio_config mainboard_gpio_config[] = { + PCH_GPIO_NATIVE, /* 0: UART1_RXD_R */ + PCH_GPIO_NATIVE, /* 1: UART1_TXD_R */ + PCH_GPIO_NATIVE, /* 2: UART1_RST_N_R */ + PCH_GPIO_NATIVE, /* 3: UART1_CTS_N_R */ + PCH_GPIO_NATIVE, /* 4: I2C0_SDA_R */ + PCH_GPIO_NATIVE, /* 5: I2C0_SCL */ + PCH_GPIO_NATIVE, /* 6: I2C1_SDA */ + PCH_GPIO_NATIVE, /* 7: I2C1_SCL */ + PCH_GPIO_INPUT, /* 8: M.2_WLAN_WAKE_CTRL_N */ + PCH_GPIO_INPUT, /* 9: M.2_BT_UART_WAKE_N */ + PCH_GPIO_INPUT, /* 10: M.2_WWAN_RSVD_WAKE_N */ + PCH_GPIO_UNUSED, /* 11: PCH_GPIO11 / BT_DEV_WAKE */ + PCH_GPIO_NATIVE, /* 12: PM_LANPHY_ENABLE */ + PCH_GPIO_OUT_HIGH, /* 13: LAN_PWREN_N */ + PCH_GPIO_IRQ_EDGE, /* 14: SENSOR_HUB_INT_R_N */ + PCH_GPIO_OUT_HIGH, /* 15: USB32_P0_PWREN_R */ + PCH_GPIO_OUT_LOW, /* 16: LAN_RST_N */ + PCH_GPIO_OUT_LOW, /* 17: CRIT_TEMP_REP_R_N */ + PCH_GPIO_NATIVE, /* 18: CLK_REQ_P0_SLOT3_R_N */ + PCH_GPIO_NATIVE, /* 19: CLK_REQ_P1 */ + PCH_GPIO_NATIVE, /* 20: CLK_REQ_P2_M.2_WLAN_R_N */ + PCH_GPIO_NATIVE, /* 21: CLK_REQ_P3_SLOT2_R_N */ + PCH_GPIO_NATIVE, /* 22: CLK_REQ_P4_SLOT1_LAN_N */ + PCH_GPIO_NATIVE, /* 23: CLK_REQ_P5_M.2_SSD_FLEX_R_N */ + PCH_GPIO_OUT_LOW, /* 24: M.2_WWAN_DISABLE_N_ME_LED */ + PCH_GPIO_INPUT, /* 25: USB_WAKEOUT_INTRUDET_N */ + PCH_GPIO_IRQ_EDGE, /* 26: NFC_IRQ_MGP5 */ + PCH_GPIO_ACPI_SCI, /* 27: SMC_WAKE_SCI_N */ + PCH_GPIO_OUT_LOW, /* 28: PCH_NFC_RESET */ + PCH_GPIO_OUT_HIGH, /* 29: PCH_SLP_WLAN_N */ + PCH_GPIO_NATIVE, /* 30: SUS_PWR_ACK_R */ + PCH_GPIO_NATIVE, /* 31: AC_PRESENT_R */ + PCH_GPIO_NATIVE, /* 32: PM_CKRUN_N */ + PCH_GPIO_NATIVE, /* 33: SATA3_PHYSLP */ + PCH_GPIO_INPUT, /* 34: SATA_ESATA_ODD_PRSNT_R_N */ + PCH_GPIO_NATIVE, /* 35: GP35_SATAPHYPC */ + PCH_GPIO_INPUT, /* 36: M.2_SSD_SATA2_PCIE1_DET_N */ + PCH_GPIO_INPUT, /* 37: M.2_SSD_SATA3_PCIE0_DET_N */ + PCH_GPIO_NATIVE, /* 38: SATA1_PHYSLP_DIRECT */ + PCH_GPIO_ACPI_SMI, /* 39: SMC_EXTSMI_R_N */ + PCH_GPIO_NATIVE, /* 40: USB_OC_0_N */ + PCH_GPIO_NATIVE, /* 41: USB_OC_1_3_N */ + PCH_GPIO_NATIVE, /* 42: TP_USB_OC */ + PCH_GPIO_OUT_HIGH, /* 43: USB32_P1_PWREN_R */ + PCH_GPIO_OUT_LOW, /* 44: SH_DFU_R */ + PCH_GPIO_INPUT, /* 45: M.2_WLAN_WIFI_WAKE_N */ + PCH_GPIO_OUT_HIGH, /* 46: POWER_BUTTON */ + PCH_GPIO_IRQ_EDGE, /* 47: SPI_TPM_HDR_IRQ_N */ + PCH_GPIO_OUT_LOW, /* 48: CLK_REQ_PCIE_PWRGD_R */ + PCH_GPIO_INPUT, /* 49: SENSOR_HUB_I2C_WAKE_R */ + PCH_GPIO_IRQ_EDGE, /* 50: EC_HID_INTR */ + PCH_GPIO_INPUT, /* 51: GPIO_51 */ + PCH_GPIO_ACPI_SCI, /* 52: SMC_RUNTIME_SCI_R_N */ + PCH_GPIO_INPUT, /* 53: GNSS_I2C_IRQ_WAKE */ + PCH_GPIO_INPUT, /* 54: GP54_M.2_WWAN_UIM_SIM_DET */ + PCH_GPIO_INPUT, /* 55: CARD_READER_DET_N */ + PCH_GPIO_UNUSED, /* 56: TP_GPIO56 (NO CONNECTION) */ + PCH_GPIO_OUT_HIGH, /* 57: M.2_WWAN_PWREN */ + PCH_GPIO_OUT_LOW, /* 58: WIFI_RF_KILL_SH_PWREN */ + PCH_GPIO_OUT_LOW, /* 59: PCH_BT_RF_KILL_N */ + PCH_GPIO_UNUSED, /* 60: TP_GP60 */ + PCH_GPIO_NATIVE, /* 61: PM_SUS_STAT_N */ + PCH_GPIO_NATIVE, /* 62: SUS_CLK_PCH */ + PCH_GPIO_NATIVE, /* 63: SLP_S5_R_N */ + PCH_GPIO_NATIVE, /* 64: M.2_WLAN_SDIO_CLK_R */ + PCH_GPIO_NATIVE, /* 65: M.2_WLAN_SDIO_CMD_R */ + PCH_GPIO_NATIVE, /* 66: M.2_WLAN_SDIO_DAT0_R */ + PCH_GPIO_NATIVE, /* 67: M.2_WLAN_SDIO_DAT1_R */ + PCH_GPIO_NATIVE, /* 68: M.2_WLAN_SDIO_DAT2_R */ + PCH_GPIO_NATIVE, /* 69: M.2_WLAN_SDIO_DAT3_R */ + PCH_GPIO_NATIVE, /* 70: M.2_WLAN_WIFI_PWREN */ + PCH_GPIO_NATIVE, /* 71: MPHY_PWREN */ + PCH_GPIO_NATIVE, /* 72: PM_BATLOW_R_N */ + PCH_GPIO_NATIVE, /* 73: PCH_NOT_N */ + PCH_GPIO_NATIVE, /* 74: SML1_DATA */ + PCH_GPIO_NATIVE, /* 75: SML1_CLK */ + PCH_GPIO_NATIVE, /* 76: GP76_USB3MPHYPC */ + PCH_GPIO_OUT_LOW, /* 77: M.2_WIFI_RST_N */ + PCH_GPIO_INPUT, /* 78: EXTTS_SNI_DRV0_PCH */ + PCH_GPIO_IRQ_EDGE, /* 79: TP_GPIO79 */ + PCH_GPIO_INPUT, /* 80: EXTTS_SNI_DRV1_PCH */ + PCH_GPIO_NATIVE, /* 81: PCH_HDA_SPKR */ + PCH_GPIO_NATIVE, /* 82: H_RCIN_N */ + PCH_GPIO_NATIVE, /* 83: GSPI0_CS_R_N */ + PCH_GPIO_NATIVE, /* 84: GSPI0_CLK_R */ + PCH_GPIO_NATIVE, /* 85: GSPI0_MISO_R */ + PCH_GPIO_NATIVE, /* 86: GSPI0_MOSI_BBS0_R */ + PCH_GPIO_OUT_HIGH, /* 87: GSPI1_CS_R_N / TOUCH_PNL_PWREN */ + PCH_GPIO_NATIVE, /* 88: GSPI1_CLK_R */ + PCH_GPIO_OUT_LOW, /* 89: GSPI1_MISO_R / TOUCH_PANEL_RST_N */ + PCH_GPIO_OUT_HIGH, /* 90: GSPI1_MOSI_R / SATA1_PWR_EN */ + PCH_GPIO_NATIVE, /* 91: UART0_RXD */ + PCH_GPIO_NATIVE, /* 92: UART0_TXD */ + PCH_GPIO_NATIVE, /* 93: UART0_RTS_N */ + PCH_GPIO_NATIVE, /* 94: UART0_CTS_N */ + PCH_GPIO_END +}; + +#endif diff --git a/src/mainboard/intel/wtm1/hda_verb.h b/src/mainboard/intel/pearlvalley/hda_verb.h similarity index 100% rename from src/mainboard/intel/wtm1/hda_verb.h rename to src/mainboard/intel/pearlvalley/hda_verb.h diff --git a/src/mainboard/intel/pearlvalley/mainboard.c b/src/mainboard/intel/pearlvalley/mainboard.c new file mode 100644 index 0000000000..86182d8450 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/mainboard.c @@ -0,0 +1,154 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +#include +#endif +#include +#include +#include +#include +#include +#include "hda_verb.h" + +void mainboard_suspend_resume(void) +{ +} + +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) +{ + int res = 1; + + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); + + switch (X86_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) * + * bit 2 = EFP * + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) * + * bit 6 = EFP2 * + * bit 7 = LFP2 + */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; + break; + case 0x5f70: + switch ((X86_CX >> 8) & 0xff) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; + } + break; + + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; +} +#endif + +/* Audio Setup */ + +extern const u32 * cim_verb_data; +extern u32 cim_verb_data_size; + +static void verb_setup(void) +{ + cim_verb_data = mainboard_cim_verb_data; + cim_verb_data_size = sizeof(mainboard_cim_verb_data); +} + +// mainboard_enable is executed as first thing after +// enumerate_buses(). + +static void mainboard_enable(device_t dev) +{ +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN + /* Install custom int15 handler for VGA OPROM */ + mainboard_interrupt_handlers(0x15, &int15_handler); +#endif + verb_setup(); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; + diff --git a/src/mainboard/intel/pearlvalley/pei_data.c b/src/mainboard/intel/pearlvalley/pei_data.c new file mode 100644 index 0000000000..9ad740fcaf --- /dev/null +++ b/src/mainboard/intel/pearlvalley/pei_data.c @@ -0,0 +1,71 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + /* DQ byte map for Samus board */ + const u8 dq_map[2][6][2] = { + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } }, + { { 0x0F, 0xF0 }, { 0x00, 0xF0 }, { 0x0F, 0xF0 }, + { 0x0F, 0x00 }, { 0xFF, 0x00 }, { 0xFF, 0x00 } } }; + /* DQS CPU<>DRAM map for Samus board */ + const u8 dqs_map[2][8] = { + { 2, 0, 3, 1, 5, 7, 6, 4 }, + { 3, 1, 2, 0, 6, 4, 5, 7 } }; + + /* One installed DIMM per channel */ + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + + pei_data->spd_addresses[0] = 0xa2; + pei_data->spd_addresses[2] = 0xa2; + + memcpy(pei_data->dq_map, dq_map, sizeof(dq_map)); + memcpy(pei_data->dqs_map, dqs_map, sizeof(dqs_map)); + + pei_data_usb2_port(pei_data, 0, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 1, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 2, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 3, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 4, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 5, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 6, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 7, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + + pei_data_usb3_port(pei_data, 0, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 1, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0); +} diff --git a/src/mainboard/intel/pearlvalley/romstage.c b/src/mainboard/intel/pearlvalley/romstage.c new file mode 100644 index 0000000000..6f99137283 --- /dev/null +++ b/src/mainboard/intel/pearlvalley/romstage.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "gpio.h" + +void mainboard_romstage_entry(struct romstage_params *rp) +{ + struct pei_data pei_data; + + post_code(0x31); + + printk(BIOS_INFO, "MLB: Intel Pearl Valley CRB\n"); + + /* Initialize GPIOs */ + init_gpios(mainboard_gpio_config); + + /* Fill out PEI DATA */ + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + rp->pei_data = &pei_data; + + romstage_common(rp); +} diff --git a/src/cpu/samsung/exynos5250/soc.c b/src/mainboard/intel/pearlvalley/smihandler.c similarity index 57% rename from src/cpu/samsung/exynos5250/soc.c rename to src/mainboard/intel/pearlvalley/smihandler.c index be28d8c38d..1c4edef81c 100644 --- a/src/cpu/samsung/exynos5250/soc.c +++ b/src/mainboard/intel/pearlvalley/smihandler.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * Copyright (C) 2008-2009 coresystems GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,31 +17,29 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include +#include +#include +#include +#include +#include -#include - -enum periph_id exynos5_get_periph_id(unsigned base_addr) +int mainboard_io_trap_handler(int smif) { - enum periph_id id = PERIPH_ID_NONE; - - switch (base_addr) { - case EXYNOS5_UART0_BASE: - id = PERIPH_ID_UART0; - break; - case EXYNOS5_UART1_BASE: - id = PERIPH_ID_UART1; - break; - case EXYNOS5_UART2_BASE: - id = PERIPH_ID_UART2; - break; - case EXYNOS5_UART3_BASE: - id = PERIPH_ID_UART3; + switch (smif) { + case 0x99: + printk(BIOS_DEBUG, "Sample\n"); + smm_get_gnvs()->smif = 0; break; default: - break; + return 0; } - return id; + /* On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + * + * For now, we force the return value to 0 and log all traps to + * see what's going on. + */ + //gnvs->smif = 0; + return 1; } diff --git a/src/mainboard/intel/wtm1/thermal.h b/src/mainboard/intel/pearlvalley/thermal.h similarity index 96% rename from src/mainboard/intel/wtm1/thermal.h rename to src/mainboard/intel/pearlvalley/thermal.h index e6116b6f5d..ce48c6148b 100644 --- a/src/mainboard/intel/wtm1/thermal.h +++ b/src/mainboard/intel/pearlvalley/thermal.h @@ -17,8 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef WTM2_THERMAL_H -#define WTM2_THERMAL_H +#ifndef MAINBOARD_THERMAL_H +#define MAINBOARD_THERMAL_H /* Fan is OFF */ #define FAN4_THRESHOLD_OFF 0 diff --git a/src/mainboard/intel/truxton/Kconfig b/src/mainboard/intel/truxton/Kconfig index 5f7de086e7..5aa4b57cfd 100644 --- a/src/mainboard/intel/truxton/Kconfig +++ b/src/mainboard/intel/truxton/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_TRUXTON config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_EP80579 select NORTHBRIDGE_INTEL_I3100 select SOUTHBRIDGE_INTEL_I3100 diff --git a/src/mainboard/intel/wtm1/devicetree.cb b/src/mainboard/intel/wtm1/devicetree.cb deleted file mode 100644 index be4fe51b41..0000000000 --- a/src/mainboard/intel/wtm1/devicetree.cb +++ /dev/null @@ -1,84 +0,0 @@ -chip northbridge/intel/haswell - - # Enable DisplayPort 1 Hotplug with 6ms pulse - register "gpu_dp_d_hotplug" = "0x06" - - # Enable DisplayPort 0 Hotplug with 6ms pulse - register "gpu_dp_c_hotplug" = "0x06" - - # Enable DVI Hotplug with 6ms pulse - register "gpu_dp_b_hotplug" = "0x06" - - device cpu_cluster 0 on - chip cpu/intel/socket_rPGA989 - device lapic 0 on end - end - chip cpu/intel/haswell - # Magic APIC ID to locate this chip - device lapic 0xACAC off end - - register "c1_battery" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_battery" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_battery" = "5" # ACPI(C3) = MWAIT(C7) - - register "c1_acpower" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_acpower" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_acpower" = "5" # ACPI(C3) = MWAIT(C7) - end - end - - device domain 0 on - device pci 00.0 on end # host bridge - device pci 02.0 on end # vga controller - - chip southbridge/intel/lynxpoint # Intel Series 8 Lynx Point PCH - register "pirqa_routing" = "0x8b" - register "pirqb_routing" = "0x8a" - register "pirqc_routing" = "0x8b" - register "pirqd_routing" = "0x8b" - register "pirqe_routing" = "0x80" - register "pirqf_routing" = "0x80" - register "pirqg_routing" = "0x80" - register "pirqh_routing" = "0x80" - - register "alt_gp_smi_en" = "0x0000" - register "gpe0_en_1" = "0x00000000" - register "gpe0_en_2" = "0x00000000" - register "gpe0_en_3" = "0x00000000" - register "gpe0_en_4" = "0x00000000" - - register "ide_legacy_combined" = "0x0" - register "sata_ahci" = "0x1" - register "sata_port_map" = "0x2" - - device pci 13.0 on end # Smart Sound Audio DSP - device pci 14.0 on end # USB3 XHCI - device pci 15.0 off end # Serial I/O DMA - device pci 15.1 off end # I2C0 - device pci 15.2 off end # I2C1 - device pci 15.3 off end # GSPI0 - device pci 15.4 off end # GSPI1 - device pci 15.5 off end # UART0 - device pci 15.6 off end # UART1 - device pci 16.0 on end # Management Engine Interface 1 - device pci 16.1 off end # Management Engine Interface 2 - device pci 16.2 off end # Management Engine IDE-R - device pci 16.3 off end # Management Engine KT - device pci 17.0 off end # SDIO - device pci 19.0 on end # GbE - device pci 1b.0 on end # High Definition Audio - device pci 1c.0 on end # PCIe Port #1 - device pci 1c.1 on end # PCIe Port #2 - device pci 1c.2 on end # PCIe Port #3 - device pci 1c.3 on end # PCIe Port #4 - device pci 1c.4 on end # PCIe Port #5 - device pci 1c.5 on end # PCIe Port #6 - device pci 1d.0 on end # USB2 EHCI - device pci 1e.0 off end # PCI bridge - device pci 1f.0 on end # LPC bridge - device pci 1f.2 on end # SATA Controller - device pci 1f.3 on end # SMBus - device pci 1f.6 on end # Thermal - end - end -end diff --git a/src/mainboard/intel/wtm1/gpio.h b/src/mainboard/intel/wtm1/gpio.h deleted file mode 100644 index 9f813d6b8a..0000000000 --- a/src/mainboard/intel/wtm1/gpio.h +++ /dev/null @@ -1,371 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2012 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INTEL_WTM1_GPIO_H -#define INTEL_WTM1_GPIO_H - -#include "southbridge/intel/lynxpoint/lp_gpio.h" - -const struct pch_lp_gpio_map mainboard_gpio_map[] = { - /* UART1_RXD */ - { .gpio = 0, - .conf0 = GPIO_MODE_NATIVE }, - /* UART1_TXD */ - { .gpio = 1, - .conf0 = GPIO_MODE_NATIVE }, - /* UART1_RTSD */ - { .gpio = 2, - .conf0 = GPIO_MODE_NATIVE }, - /* UART1_CTSB */ - { .gpio = 3, - .conf0 = GPIO_MODE_NATIVE }, - /* I2C0_SDA */ - { .gpio = 4, - .conf0 = GPIO_MODE_NATIVE }, - /* I2C0_SCL */ - { .gpio = 5, - .conf0 = GPIO_MODE_NATIVE }, - /* I2C1_SDA */ - { .gpio = 6, - .conf0 = GPIO_MODE_NATIVE }, - /* I2C1_SCL */ - { .gpio = 7, - .conf0 = GPIO_MODE_NATIVE }, - /* PCIE_SLOT3_WAKE_R_N / ICC_EN_N */ - { .gpio = 8, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCH_GPIO9 / XDP_FN5 */ - { .gpio = 9, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCH_GPIO10 / XDP_FN6 */ - { .gpio = 10, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* SMBALERTB / PCH_GPIO11 / AMB_THRM_R_N */ - { .gpio = 11, - .conf0 = GPIO_MODE_NATIVE }, - /* PM_LANPHY_ENABLE */ - { .gpio = 12, - .conf0 = GPIO_MODE_NATIVE }, - /* USB30_P0_PWREN */ - { .gpio = 13, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SENSOR_HUB_INT_R_N */ - { .gpio = 14, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* HOST_ALERT1_R_N */ - { .gpio = 15, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* LAN_RST_N */ - { .gpio = 16, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* CRIT_TEMP_REP_N */ - { .gpio = 17, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW }, - /* SRC0CLKRQB */ - { .gpio = 18, - .conf0 = GPIO_MODE_NATIVE }, - /* SRC1CLKRQB */ - { .gpio = 19, - .conf0 = GPIO_MODE_NATIVE }, - /* SRC2CLKRQB */ - { .gpio = 20, - .conf0 = GPIO_MODE_NATIVE }, - /* SRC3CLKRQB */ - { .gpio = 21, - .conf0 = GPIO_MODE_NATIVE }, - /* SRC4CLKRQB_TRST2 */ - { .gpio = 22, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SRC5CLKRQB_TDI2 */ - { .gpio = 23, - .conf0 = GPIO_MODE_NATIVE }, - /* BT_ALERT_ME_LED */ - { .gpio = 24, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* USB_WAKEOUT_N / USB2_4_5_PWREN */ - { .gpio = 25, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* NFC_IRQ_MGP5 */ - { .gpio = 26, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* SMC_WAKE_SCI_N */ - { .gpio = 27, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE }, - /* PCH_NFC_RESET_CMNHDR */ - { .gpio = 28, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SLP_WLANB */ - { .gpio = 29, - .conf0 = GPIO_MODE_NATIVE }, - /* SUSWARNB_SUSPWRDNACK_MGPIO1 */ - { .gpio = 30, - .conf0 = GPIO_MODE_NATIVE }, - /* ACPRESENT_MGPIO2 */ - { .gpio = 31, - .conf0 = GPIO_MODE_NATIVE }, - /* CLKRUNB */ - { .gpio = 32, - .conf0 = GPIO_MODE_NATIVE }, - /* SATA0_PHYSLP */ - { .gpio = 33, - .conf0 = GPIO_MODE_NATIVE }, - /* SMC_EXTSMI_R_N */ - { .gpio = 34, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SATA_DIRECT_ODD_PRSNT_R_N */ - { .gpio = 35, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* CMNHDR_PEDET2 */ - { .gpio = 36, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* MSATA_MPCIE_DET_N */ - { .gpio = 37, - .conf0 = GPIO_MODE_NATIVE }, - /* SATA1_PHYSLP_DIRECT */ - { .gpio = 38, - .conf0 = GPIO_MODE_NATIVE }, - /* SATA2_PHYSLP_CMNHDR */ - { .gpio = 39, - .conf0 = GPIO_MODE_NATIVE }, - /* USB_OC_0_1_R_N */ - { .gpio = 40, - .conf0 = GPIO_MODE_NATIVE }, - /* USB_OC_6_7_R_N */ - { .gpio = 41, - .conf0 = GPIO_MODE_NATIVE }, - /* USB_OC_4_5_R_N */ - { .gpio = 42, - .conf0 = GPIO_MODE_NATIVE }, - /* USB32_P1_PWREN */ - { .gpio = 43, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SNSR_HUB_RST_N */ - { .gpio = 44, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCIE_SLOT4_WAKE_N */ - { .gpio = 45, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SNSR_HUB_PWREN_N */ - { .gpio = 46, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SPI_TPM_HDR_IRQ_N */ - { .gpio = 47, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* SLOT5_RST_GYRO_INT2_N */ - { .gpio = 48, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* GPS_EN_NGFF_ALS_INT_N */ - { .gpio = 49, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* TOUCH_PANEL_INTR_N */ - { .gpio = 50, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* PCIE_SLOT5_WAKE_R_N */ - { .gpio = 51, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* GYRO_INT1_CLV / TOUCH_RST_N */ - { .gpio = 52, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* CODEC_IRQ */ - { .gpio = 53, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* PCH_MC_WAKE_R_N */ - { .gpio = 54, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* THCP_INTR_N */ - { .gpio = 55, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* PCIE_SLOT4_RST_N */ - { .gpio = 56, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCIE_SLOT4_PWREN_N */ - { .gpio = 57, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SPI_TPM_HDR_PWREN_N */ - { .gpio = 58, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCIE_SLOT3_RST_N */ - { .gpio = 59, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCIE_SLOT3_PWREN_N */ - { .gpio = 60, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SUS_STATB */ - { .gpio = 61, - .conf0 = GPIO_MODE_NATIVE }, - /* SUSCLK */ - { .gpio = 62, - .conf0 = GPIO_MODE_NATIVE }, - /* SLP_S5B */ - { .gpio = 63, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_CLK */ - { .gpio = 64, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_CMD */ - { .gpio = 65, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_D0 */ - { .gpio = 66, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_D1 */ - { .gpio = 67, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_D2 */ - { .gpio = 68, - .conf0 = GPIO_MODE_NATIVE }, - /* SDIO_D3 */ - { .gpio = 69, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_VDD_EN_CMNHDR_R */ - { .gpio = 70, - .conf0 = GPIO_MODE_NATIVE }, - /* MPHY_PWREN */ - { .gpio = 71, - .conf0 = GPIO_MODE_NATIVE }, - /* PM_BATLOW_R_N */ - { .gpio = 72, - .conf0 = GPIO_MODE_NATIVE }, - /* PCH_GP73_MGP8 / PCH_HOT_N */ - { .gpio = 73, - .conf0 = GPIO_MODE_NATIVE }, - /* SML1_DATA */ - { .gpio = 74, - .conf0 = GPIO_MODE_NATIVE }, - /* SML1_DATA */ - { .gpio = 75, - .conf0 = GPIO_MODE_NATIVE }, - /* PCH_AUDIO_PWR_N */ - { .gpio = 76, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* MPCIE_RST_N */ - { .gpio = 77, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* EXTTS_SNI_DRV0_PCH */ - { .gpio = 78, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SIO1007_IRQ_N */ - { .gpio = 79, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_ACPI, - .route = GPIO_ROUTE_SCI, - .irqen = GPIO_IRQ_ENABLE }, - /* EXTTS_SNI_DRV1_PCH */ - { .gpio = 80, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SPKR */ - { .gpio = 81, - .conf0 = GPIO_MODE_NATIVE }, - /* RCINB */ - { .gpio = 82, - .conf0 = GPIO_MODE_NATIVE }, - /* MC_3.3_PWREN_N */ - { .gpio = 83, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCIE_SLOT5_PWREN_N */ - { .gpio = 84, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* MC_1.5_PWREN_N */ - { .gpio = 85, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SATA_ODD_PWRGT_R */ - { .gpio = 86, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* PECI_HDR / PCH_RF_KILL_N */ - { .gpio = 87, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* TCHP_PWREN_N */ - { .gpio = 88, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* TOUCH_PWREN_N */ - { .gpio = 89, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SATA1_PWR_EN_N */ - { .gpio = 90, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* UART0_RXD */ - { .gpio = 91, - .conf0 = GPIO_MODE_NATIVE }, - /* UART0_TXD */ - { .gpio = 92, - .conf0 = GPIO_MODE_NATIVE }, - /* UART0_RTSB */ - { .gpio = 93, - .conf0 = GPIO_MODE_NATIVE }, - /* UART0_CTSB */ - { .gpio = 94, - .conf0 = GPIO_MODE_NATIVE }, - /* END */ - { .gpio = GPIO_LIST_END } -}; - -#endif diff --git a/src/mainboard/intel/wtm1/mainboard.c b/src/mainboard/intel/wtm1/mainboard.c deleted file mode 100644 index f5b00546f7..0000000000 --- a/src/mainboard/intel/wtm1/mainboard.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007-2009 coresystems GmbH - * Copyright (C) 2011 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -#include -#endif -#include -#include -#include -#include -#include -#include "hda_verb.h" -#include - -void mainboard_suspend_resume(void) -{ - /* Call SMM finalize() handlers before resume */ - outb(0xcb, 0xb2); -} - -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) -{ - int res=-1; - - printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); - - switch(regs->eax & 0xffff) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - * 0 = video bios default - */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x01; - res = 0; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) * - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) * - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0003; - res = 0; - break; - case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { - case 0: - /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; - break; - case 1: - /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; - break; - case 2: - /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; - } - break; - - default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); - break; - } - return res; -} -#endif - -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0001; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) * - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) * - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 3; - break; - case 0x5f70: - /* Unknown */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - -/* Audio Setup */ - -extern const u32 * cim_verb_data; -extern u32 cim_verb_data_size; - -static void verb_setup(void) -{ - cim_verb_data = mainboard_cim_verb_data; - cim_verb_data_size = sizeof(mainboard_cim_verb_data); -} - -// mainboard_enable is executed as first thing after -// enumerate_buses(). - -static void mainboard_enable(device_t dev) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE - /* Install custom int15 handler for VGA OPROM */ - int15_install(); -#endif - verb_setup(); -} - -struct chip_operations mainboard_ops = { - .enable_dev = mainboard_enable, -}; - diff --git a/src/mainboard/intel/wtm2/Kconfig b/src/mainboard/intel/wtm2/Kconfig index 4065110a0d..5d5b147fed 100644 --- a/src/mainboard/intel/wtm2/Kconfig +++ b/src/mainboard/intel/wtm2/Kconfig @@ -2,11 +2,7 @@ if BOARD_INTEL_WTM2 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 - select CPU_INTEL_SOCKET_RPGA989 - select NORTHBRIDGE_INTEL_HASWELL - select SOUTHBRIDGE_INTEL_LYNXPOINT - select INTEL_LYNXPOINT_LP + select SOC_INTEL_BROADWELL select BOARD_ROMSIZE_KB_8192 select HAVE_ACPI_TABLES select HAVE_OPTION_TABLE @@ -14,9 +10,20 @@ config BOARD_SPECIFIC_OPTIONS # dummy select MMCONF_SUPPORT select HAVE_SMI_HANDLER select CHROMEOS + select CHROMEOS_VBNV_CMOS select EXTERNAL_MRC_BLOB select CACHE_ROM select MARK_GRAPHICS_MEM_WRCOMB + select MONOTONIC_TIMER_MSR + select CHROMEOS_RAMOOPS_DYNAMIC + +config VBOOT_RAMSTAGE_INDEX + hex + default 0x1 + +config VBOOT_REFCODE_INDEX + hex + default 0x2 config MAINBOARD_DIR string @@ -26,10 +33,6 @@ config MAINBOARD_PART_NUMBER string default "WHITETIP MOUNTAIN 2" -config MMCONF_BASE_ADDRESS - hex - default 0xf0000000 - config IRQ_SLOT_COUNT int default 18 diff --git a/src/mainboard/intel/wtm2/Makefile.inc b/src/mainboard/intel/wtm2/Makefile.inc index 658c96c77e..c96e0d968b 100644 --- a/src/mainboard/intel/wtm2/Makefile.inc +++ b/src/mainboard/intel/wtm2/Makefile.inc @@ -19,5 +19,11 @@ romstage-$(CONFIG_CHROMEOS) += chromeos.c ramstage-$(CONFIG_CHROMEOS) += chromeos.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += i915.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += graphics.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += intel_dp.c smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c + +romstage-y += pei_data.c +ramstage-y += pei_data.c diff --git a/src/mainboard/intel/wtm2/acpi/chromeos.asl b/src/mainboard/intel/wtm2/acpi/chromeos.asl index c6b258b4e2..4cd6dedf46 100644 --- a/src/mainboard/intel/wtm2/acpi/chromeos.asl +++ b/src/mainboard/intel/wtm2/acpi/chromeos.asl @@ -18,6 +18,7 @@ */ Name(OIPG, Package() { - // This GPIO is not available but the package cannot be empty - Package () { 0x0001, 0, 0, "LynxPoint" }, // recovery + Package () { 0x0001, 0, 0xFFFFFFFF, "PCH-LP" }, // recovery + Package () { 0x0002, 0, 0xFFFFFFFF, "PCH-LP" }, // developer + Package () { 0x0003, 0, 0xFFFFFFFF, "PCH-LP" }, // firmware write protect }) diff --git a/src/mainboard/intel/wtm2/acpi/thermal.asl b/src/mainboard/intel/wtm2/acpi/thermal.asl index 00a8750a36..27d5105868 100644 --- a/src/mainboard/intel/wtm2/acpi/thermal.asl +++ b/src/mainboard/intel/wtm2/acpi/thermal.asl @@ -18,6 +18,7 @@ */ // Thermal Zone +#include "../thermal.h" Scope (\_TZ) { @@ -68,41 +69,41 @@ Scope (\_TZ) Method (_AC0) { If (LLessEqual (\FLVL, 0)) { - Return (CTOK (\F0OF)) + Return (CTOK (FAN0_THRESHOLD_OFF)) } Else { - Return (CTOK (\F0ON)) + Return (CTOK (FAN0_THRESHOLD_ON)) } } Method (_AC1) { If (LLessEqual (\FLVL, 1)) { - Return (CTOK (\F1OF)) + Return (CTOK (FAN1_THRESHOLD_OFF)) } Else { - Return (CTOK (\F1ON)) + Return (CTOK (FAN1_THRESHOLD_ON)) } } Method (_AC2) { If (LLessEqual (\FLVL, 2)) { - Return (CTOK (\F2OF)) + Return (CTOK (FAN2_THRESHOLD_OFF)) } Else { - Return (CTOK (\F2ON)) + Return (CTOK (FAN2_THRESHOLD_ON)) } } Method (_AC3) { If (LLessEqual (\FLVL, 3)) { - Return (CTOK (\F3OF)) + Return (CTOK (FAN3_THRESHOLD_OFF)) } Else { - Return (CTOK (\F3ON)) + Return (CTOK (FAN3_THRESHOLD_ON)) } } Method (_AC4) { If (LLessEqual (\FLVL, 4)) { - Return (CTOK (\F4OF)) + Return (CTOK (FAN4_THRESHOLD_OFF)) } Else { - Return (CTOK (\F4ON)) + Return (CTOK (FAN4_THRESHOLD_ON)) } } diff --git a/src/mainboard/intel/wtm2/acpi_tables.c b/src/mainboard/intel/wtm2/acpi_tables.c index 16a1c6a9ed..2525a3d947 100644 --- a/src/mainboard/intel/wtm2/acpi_tables.c +++ b/src/mainboard/intel/wtm2/acpi_tables.c @@ -29,83 +29,27 @@ #include #include #include -#include -#include - -extern const unsigned char AmlCode[]; -#if CONFIG_HAVE_ACPI_SLIC -unsigned long acpi_create_slic(unsigned long current); -#endif - -#include -#include +#include +#include #include "thermal.h" -static void acpi_update_thermal_table(global_nvs_t *gnvs) +extern const unsigned char AmlCode[]; + +static void acpi_create_gnvs(global_nvs_t *gnvs) { - gnvs->f4of = FAN4_THRESHOLD_OFF; - gnvs->f4on = FAN4_THRESHOLD_ON; - gnvs->f4pw = FAN4_PWM; + acpi_init_gnvs(gnvs); - gnvs->f3of = FAN3_THRESHOLD_OFF; - gnvs->f3on = FAN3_THRESHOLD_ON; - gnvs->f3pw = FAN3_PWM; + /* Enable USB ports in S3 */ + gnvs->s3u0 = 1; - gnvs->f2of = FAN2_THRESHOLD_OFF; - gnvs->f2on = FAN2_THRESHOLD_ON; - gnvs->f2pw = FAN2_PWM; - - gnvs->f1of = FAN1_THRESHOLD_OFF; - gnvs->f1on = FAN1_THRESHOLD_ON; - gnvs->f1pw = FAN1_PWM; - - gnvs->f0of = FAN0_THRESHOLD_OFF; - gnvs->f0on = FAN0_THRESHOLD_ON; - gnvs->f0pw = FAN0_PWM; + /* Disable USB ports in S5 */ + gnvs->s5u0 = 0; gnvs->tcrt = CRITICAL_TEMPERATURE; gnvs->tpsv = PASSIVE_TEMPERATURE; gnvs->tmax = MAX_TEMPERATURE; } -static void acpi_create_gnvs(global_nvs_t *gnvs) -{ - gnvs->apic = 1; - gnvs->mpen = 1; /* Enable Multi Processing */ - gnvs->pcnt = dev_count_cpu(); - - /* Enable USB ports in S3 */ - gnvs->s3u0 = 1; - gnvs->s3u1 = 1; - - /* Disable USB ports in S5 */ - gnvs->s5u0 = 0; - gnvs->s5u1 = 0; - - /* CBMEM TOC */ - gnvs->cmem = 0; - - /* TPM Present */ - gnvs->tpmp = 1; - - /* IGD Displays */ - gnvs->ndid = 3; - gnvs->did[0] = 0x80000100; - gnvs->did[1] = 0x80000240; - gnvs->did[2] = 0x80000410; - gnvs->did[3] = 0x80000410; - gnvs->did[4] = 0x00000005; - -#if CONFIG_CHROMEOS - // TODO(reinauer) this could move elsewhere? - chromeos_init_vboot(&(gnvs->chromeos)); - /* Emerald Lake has no EC (?) */ - gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; -#endif - - acpi_update_thermal_table(gnvs); -} - unsigned long acpi_fill_madt(unsigned long current) { /* Local APICs */ @@ -115,13 +59,7 @@ unsigned long acpi_fill_madt(unsigned long current) current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, 2, IO_APIC_ADDR, 0); - /* INT_SRC_OVR */ - current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) - current, 0, 0, 2, 0); - current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) - current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH); - - return current; + return acpi_madt_irq_overrides(current); } unsigned long acpi_fill_ssdt_generator(unsigned long current, @@ -133,13 +71,11 @@ unsigned long acpi_fill_ssdt_generator(unsigned long current, unsigned long acpi_fill_slit(unsigned long current) { - // Not implemented return current; } unsigned long acpi_fill_srat(unsigned long current) { - /* No NUMA, no SRAT */ return current; } @@ -156,9 +92,6 @@ unsigned long write_acpi_tables(unsigned long start) acpi_mcfg_t *mcfg; acpi_fadt_t *fadt; acpi_facs_t *facs; -#if CONFIG_HAVE_ACPI_SLIC - acpi_header_t *slic; -#endif acpi_header_t *ssdt; acpi_header_t *dsdt; global_nvs_t *gnvs; @@ -268,15 +201,7 @@ unsigned long write_acpi_tables(unsigned long start) dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length); printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt, - dsdt->length); - -#if CONFIG_HAVE_ACPI_SLIC - printk(BIOS_DEBUG, "ACPI: * SLIC\n"); - slic = (acpi_header_t *)current; - current += acpi_create_slic(current); - ALIGN_CURRENT; - acpi_add_table(rsdp, slic); -#endif + dsdt->length); printk(BIOS_DEBUG, "ACPI: * SSDT\n"); ssdt = (acpi_header_t *)current; diff --git a/src/mainboard/intel/wtm2/chromeos.c b/src/mainboard/intel/wtm2/chromeos.c index 594b4a75d3..374f1155ca 100644 --- a/src/mainboard/intel/wtm2/chromeos.c +++ b/src/mainboard/intel/wtm2/chromeos.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include /* Compile-time settings for developer and recovery mode. */ #define DEV_MODE_SETTING 1 @@ -32,8 +32,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 static void fill_lb_gpio(struct lb_gpio *gpio, int num, int polarity, const char *name, int force) diff --git a/src/mainboard/intel/wtm2/devicetree.cb b/src/mainboard/intel/wtm2/devicetree.cb index 5e1ca3aba4..54b2bffd32 100644 --- a/src/mainboard/intel/wtm2/devicetree.cb +++ b/src/mainboard/intel/wtm2/devicetree.cb @@ -1,4 +1,4 @@ -chip northbridge/intel/haswell +chip soc/intel/broadwell # Enable DisplayPort 1 Hotplug with 6ms pulse register "gpu_dp_d_hotplug" = "0x06" @@ -9,80 +9,58 @@ chip northbridge/intel/haswell # Enable DVI Hotplug with 6ms pulse register "gpu_dp_b_hotplug" = "0x06" + register "pirqa_routing" = "0x8b" + register "pirqb_routing" = "0x8a" + register "pirqc_routing" = "0x8b" + register "pirqd_routing" = "0x8b" + register "pirqe_routing" = "0x80" + register "pirqf_routing" = "0x80" + register "pirqg_routing" = "0x80" + register "pirqh_routing" = "0x80" + + register "alt_gp_smi_en" = "0x0000" + register "gpe0_en_1" = "0x00000400" + register "gpe0_en_2" = "0x00000000" + register "gpe0_en_3" = "0x00000000" + register "gpe0_en_4" = "0x00000000" + + register "sata_port_map" = "0x2" + register "sio_acpi_mode" = "1" + device cpu_cluster 0 on - chip cpu/intel/socket_rPGA989 - device lapic 0 on end - end - chip cpu/intel/haswell - # Magic APIC ID to locate this chip - device lapic 0xACAC off end - - register "c1_battery" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_battery" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_battery" = "5" # ACPI(C3) = MWAIT(C7) - - register "c1_acpower" = "3" # ACPI(C1) = MWAIT(C3) - register "c2_acpower" = "4" # ACPI(C2) = MWAIT(C6) - register "c3_acpower" = "5" # ACPI(C3) = MWAIT(C7) - end + device lapic 0 on end end - device domain 0 on device pci 00.0 on end # host bridge device pci 02.0 on end # vga controller - - chip southbridge/intel/lynxpoint # Intel Series 8 Lynx Point PCH - register "pirqa_routing" = "0x8b" - register "pirqb_routing" = "0x8a" - register "pirqc_routing" = "0x8b" - register "pirqd_routing" = "0x8b" - register "pirqe_routing" = "0x80" - register "pirqf_routing" = "0x80" - register "pirqg_routing" = "0x80" - register "pirqh_routing" = "0x80" - - register "alt_gp_smi_en" = "0x0000" - register "gpe0_en_1" = "0x00000400" - register "gpe0_en_2" = "0x00000000" - register "gpe0_en_3" = "0x00000000" - register "gpe0_en_4" = "0x00000000" - - register "ide_legacy_combined" = "0x0" - register "sata_ahci" = "0x1" - register "sata_port_map" = "0x2" - - register "sio_acpi_mode" = "1" - register "sio_i2c0_voltage" = "1" # 1.8V - register "sio_i2c1_voltage" = "1" # 1.8V - - device pci 13.0 on end # Smart Sound Audio DSP - device pci 14.0 on end # USB3 XHCI - device pci 15.0 on end # Serial I/O DMA - device pci 15.1 on end # I2C0 - device pci 15.2 on end # I2C1 - device pci 15.3 on end # GSPI0 - device pci 15.4 on end # GSPI1 - device pci 15.5 on end # UART0 - device pci 15.6 on end # UART1 - device pci 16.0 on end # Management Engine Interface 1 - device pci 16.1 off end # Management Engine Interface 2 - device pci 16.2 off end # Management Engine IDE-R - device pci 16.3 off end # Management Engine KT - device pci 17.0 on end # SDIO - device pci 19.0 on end # GbE - device pci 1b.0 on end # High Definition Audio - device pci 1c.0 on end # PCIe Port #1 - device pci 1c.1 on end # PCIe Port #2 - device pci 1c.2 on end # PCIe Port #3 - device pci 1c.3 on end # PCIe Port #4 - device pci 1c.4 on end # PCIe Port #5 - device pci 1c.5 on end # PCIe Port #6 - device pci 1d.0 on end # USB2 EHCI - device pci 1e.0 off end # PCI bridge - device pci 1f.0 on end # LPC bridge - device pci 1f.2 on end # SATA Controller - device pci 1f.3 on end # SMBus - device pci 1f.6 on end # Thermal - end + device pci 03.0 on end # mini-hd audio + device pci 13.0 off end # Smart Sound Audio DSP + device pci 14.0 on end # USB3 XHCI + device pci 15.0 on end # Serial I/O DMA + device pci 15.1 on end # I2C0 + device pci 15.2 on end # I2C1 + device pci 15.3 off end # GSPI0 + device pci 15.4 off end # GSPI1 + device pci 15.5 off end # UART0 + device pci 15.6 off end # UART1 + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 17.0 off end # SDIO + device pci 19.0 off end # GbE + device pci 1b.0 on end # High Definition Audio + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 on end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 on end # PCIe Port #6 + device pci 1d.0 off end # USB2 EHCI + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on end # LPC bridge + device pci 1f.2 on end # SATA Controller + device pci 1f.3 on end # SMBus + device pci 1f.6 on end # Thermal end end diff --git a/src/mainboard/intel/wtm2/dsdt.asl b/src/mainboard/intel/wtm2/dsdt.asl index 112a47ab4a..b920cd458b 100644 --- a/src/mainboard/intel/wtm2/dsdt.asl +++ b/src/mainboard/intel/wtm2/dsdt.asl @@ -33,26 +33,32 @@ DefinitionBlock( #include "acpi/platform.asl" // global NVS and variables - #include + #include // General Purpose Events //#include "acpi/gpe.asl" - #include "acpi/thermal.asl" - - #include "../../../cpu/intel/haswell/acpi/cpu.asl" + // CPU + #include Scope (\_SB) { Device (PCI0) { - #include - #include + #include + #include } } + // Thermal handler + #include "acpi/thermal.asl" + + // Chrome OS specific #include "acpi/chromeos.asl" #include - /* Chipset specific sleep states */ - #include + // Chipset specific sleep states + #include + + // Mainboard specific + #include "acpi/mainboard.asl" } diff --git a/src/mainboard/intel/wtm2/fadt.c b/src/mainboard/intel/wtm2/fadt.c index 7afbbfa698..a876e1f97a 100644 --- a/src/mainboard/intel/wtm2/fadt.c +++ b/src/mainboard/intel/wtm2/fadt.c @@ -18,20 +18,16 @@ */ #include -#include -#include -#include -#include +#include void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) { acpi_header_t *header = &(fadt->header); - u16 pmbase = get_pmbase(); memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = 5; memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); @@ -42,114 +38,12 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) fadt->model = 1; fadt->preferred_pm_profile = PM_MOBILE; - fadt->sci_int = 0x9; - fadt->smi_cmd = APM_CNT; - fadt->acpi_enable = APM_CNT_ACPI_ENABLE; - fadt->acpi_disable = APM_CNT_ACPI_DISABLE; - fadt->s4bios_req = 0x0; - fadt->pstate_cnt = 0; - - fadt->pm1a_evt_blk = pmbase; - fadt->pm1b_evt_blk = 0x0; - fadt->pm1a_cnt_blk = pmbase + 0x4; - fadt->pm1b_cnt_blk = 0x0; - fadt->pm2_cnt_blk = pmbase + 0x50; - fadt->pm_tmr_blk = pmbase + 0x8; - fadt->gpe0_blk = pmbase + 0x80; - fadt->gpe1_blk = 0; - - fadt->pm1_evt_len = 4; - fadt->pm1_cnt_len = 2; - fadt->pm2_cnt_len = 1; - fadt->pm_tmr_len = 4; - fadt->gpe0_blk_len = 32; - fadt->gpe1_blk_len = 0; - fadt->gpe1_base = 0; - fadt->cst_cnt = 0; - fadt->p_lvl2_lat = 1; - fadt->p_lvl3_lat = 87; - fadt->flush_size = 1024; - fadt->flush_stride = 16; - fadt->duty_offset = 1; - fadt->duty_width = 0; - fadt->day_alrm = 0xd; - fadt->mon_alrm = 0x00; - fadt->century = 0x00; - fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; - - fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | - ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | - ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | - ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; - - fadt->reset_reg.space_id = 1; - fadt->reset_reg.bit_width = 8; - fadt->reset_reg.bit_offset = 0; - fadt->reset_reg.resv = 0; - fadt->reset_reg.addrl = 0xcf9; - fadt->reset_reg.addrh = 0; - - fadt->reset_value = 6; fadt->x_firmware_ctl_l = (unsigned long)facs; fadt->x_firmware_ctl_h = 0; fadt->x_dsdt_l = (unsigned long)dsdt; fadt->x_dsdt_h = 0; - fadt->x_pm1a_evt_blk.space_id = 1; - fadt->x_pm1a_evt_blk.bit_width = 32; - fadt->x_pm1a_evt_blk.bit_offset = 0; - fadt->x_pm1a_evt_blk.resv = 0; - fadt->x_pm1a_evt_blk.addrl = pmbase; - fadt->x_pm1a_evt_blk.addrh = 0x0; - - fadt->x_pm1b_evt_blk.space_id = 1; - fadt->x_pm1b_evt_blk.bit_width = 0; - fadt->x_pm1b_evt_blk.bit_offset = 0; - fadt->x_pm1b_evt_blk.resv = 0; - fadt->x_pm1b_evt_blk.addrl = 0x0; - fadt->x_pm1b_evt_blk.addrh = 0x0; - - fadt->x_pm1a_cnt_blk.space_id = 1; - fadt->x_pm1a_cnt_blk.bit_width = 16; - fadt->x_pm1a_cnt_blk.bit_offset = 0; - fadt->x_pm1a_cnt_blk.resv = 0; - fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4; - fadt->x_pm1a_cnt_blk.addrh = 0x0; - - fadt->x_pm1b_cnt_blk.space_id = 1; - fadt->x_pm1b_cnt_blk.bit_width = 0; - fadt->x_pm1b_cnt_blk.bit_offset = 0; - fadt->x_pm1b_cnt_blk.resv = 0; - fadt->x_pm1b_cnt_blk.addrl = 0x0; - fadt->x_pm1b_cnt_blk.addrh = 0x0; - - fadt->x_pm2_cnt_blk.space_id = 1; - fadt->x_pm2_cnt_blk.bit_width = 8; - fadt->x_pm2_cnt_blk.bit_offset = 0; - fadt->x_pm2_cnt_blk.resv = 0; - fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50; - fadt->x_pm2_cnt_blk.addrh = 0x0; - - fadt->x_pm_tmr_blk.space_id = 1; - fadt->x_pm_tmr_blk.bit_width = 32; - fadt->x_pm_tmr_blk.bit_offset = 0; - fadt->x_pm_tmr_blk.resv = 0; - fadt->x_pm_tmr_blk.addrl = pmbase + 0x8; - fadt->x_pm_tmr_blk.addrh = 0x0; - - fadt->x_gpe0_blk.space_id = 0; - fadt->x_gpe0_blk.bit_width = 0; - fadt->x_gpe0_blk.bit_offset = 0; - fadt->x_gpe0_blk.resv = 0; - fadt->x_gpe0_blk.addrl = 0; - fadt->x_gpe0_blk.addrh = 0x0; - - fadt->x_gpe1_blk.space_id = 1; - fadt->x_gpe1_blk.bit_width = 0; - fadt->x_gpe1_blk.bit_offset = 0; - fadt->x_gpe1_blk.resv = 0; - fadt->x_gpe1_blk.addrl = 0x0; - fadt->x_gpe1_blk.addrh = 0x0; + acpi_fill_in_fadt(fadt); header->checksum = acpi_checksum((void *) fadt, header->length); diff --git a/src/mainboard/intel/wtm2/gpio.h b/src/mainboard/intel/wtm2/gpio.h index 179259c0b1..f4825bac41 100644 --- a/src/mainboard/intel/wtm2/gpio.h +++ b/src/mainboard/intel/wtm2/gpio.h @@ -20,350 +20,105 @@ #ifndef INTEL_WTM2_GPIO_H #define INTEL_WTM2_GPIO_H -#include "southbridge/intel/lynxpoint/lp_gpio.h" +#include -const struct pch_lp_gpio_map mainboard_gpio_map[] = { - /* LPSS_UART1_RXD */ - { .gpio = 0, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART1_TXD */ - { .gpio = 1, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART1_RTS_N_R */ - { .gpio = 2, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART1_CTS_N */ - { .gpio = 3, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_I2C0_SDA_R */ - { .gpio = 4, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_I2C0_SCL */ - { .gpio = 5, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_I2C1_SDA */ - { .gpio = 6, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_I2C1_SCL */ - { .gpio = 7, - .conf0 = GPIO_MODE_NATIVE }, - /* NGFF_SLTA_WIFI_WAKE_N */ - { .gpio = 8, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* ACCEL_INT2_MCP (NGFF_SLTA_UART_WAKE_N) */ - { .gpio = 9, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* SMC_RUNTIME_SCI_N */ - { .gpio = 10, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_ACPI, - .route = GPIO_ROUTE_SCI }, - /* AMB_THRM_R_N */ - { .gpio = 11, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* PM_LANPHY_ENABLE */ - { .gpio = 12, - .conf0 = GPIO_MODE_NATIVE }, - /* USB32_P0_PWREN */ - { .gpio = 13, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SH_INT_ACCEL_DRDY_USB_INT_N */ - { .gpio = 14, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* LAN_PWREN_N */ - { .gpio = 15, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* LAN_RST_N */ - { .gpio = 16, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* CRIT_TEMP_REP_R_N (NGFF_SLTB_CARD_PRESENT_SSD_N) */ - { .gpio = 17, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW }, - /* TBT_FORCE_PWR */ - { .gpio = 18, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* EC_IN_RW */ - { .gpio = 19, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE, - .owner = GPIO_OWNER_GPIO }, - /* CK_REQ_P2_NGFFSLTA_N_R */ - { .gpio = 20, - .conf0 = GPIO_MODE_NATIVE }, - /* CK_PCIE_LAN_REQ_N */ - { .gpio = 21, - .conf0 = GPIO_MODE_NATIVE }, - /* CK_REQ_P4_TBT_N */ - { .gpio = 22, - .conf0 = GPIO_MODE_NATIVE }, - /* CK_REQ_P5_N */ - { .gpio = 23, - .conf0 = GPIO_MODE_NATIVE }, - /* ME_PG_LED (NGFF_SLTB_WWN_CRD_PRSNT) */ - { .gpio = 24, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* USB_WAKEOUT_N */ - { .gpio = 25, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE }, - /* NFC_IRQ_MGP5 */ - { .gpio = 26, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* SMC_WAKE_SCI_N */ - { .gpio = 27, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE }, - /* PCH_NFC_RESET */ - { .gpio = 28, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* PCH_SLP_WLAN_N */ - { .gpio = 29, - .conf0 = GPIO_MODE_NATIVE }, - /* SUS_PWR_ACK_R */ - { .gpio = 30, - .conf0 = GPIO_MODE_NATIVE }, - /* AC_PRESENT_R */ - { .gpio = 31, - .conf0 = GPIO_MODE_NATIVE }, - /* PM_CKRUN_N */ - { .gpio = 32, - .conf0 = GPIO_MODE_NATIVE }, - /* SATA0_PHYSLP */ - { .gpio = 33, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* ESATA_DET_N */ - { .gpio = 34, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SATA_DIRECT_PRSNT_R_N */ - { .gpio = 35, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* NGFF_SSD_SATA2_PCIE1_DET_N */ - { .gpio = 36, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* NGFF_SSD_SATA3_PCIE0_DET_N */ - { .gpio = 37, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SATA1_PHYSLP_DIRECT */ - { .gpio = 38, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* SMC_EXTSMI_N_R */ - { .gpio = 39, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_ACPI, - .route = GPIO_ROUTE_SMI }, - /* USB_OC_0_1_R_N */ - { .gpio = 40, - .conf0 = GPIO_MODE_NATIVE }, - /* USB_OC_2_6_R_N */ - { .gpio = 41, - .conf0 = GPIO_MODE_NATIVE }, - /* TBT_CIO_PLUG_SMI_N_R */ - { .gpio = 42, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_DISABLE }, - /* USB32_P1_PWREN */ - { .gpio = 43, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SENSOR_HUB_RST_N */ - { .gpio = 44, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* GYRO_INT2_MCP_R (TBT_WAKE_Q_N) */ - { .gpio = 45, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SNSR_HUB_PWREN */ - { .gpio = 46, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SPI_TPM_HDR_IRQ_N */ - { .gpio = 47, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* PCIE_TBT_RST_N */ - { .gpio = 48, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* COMBO_JD */ - { .gpio = 49, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* TOUCH_PANEL_INTR_N */ - { .gpio = 50, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* PCH_WIFI_RF_KILL_N */ - { .gpio = 51, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* TOUCH_PNL_RST_N_R */ - { .gpio = 52, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SNSR_HUB_I2C_WAKE / ALS_INT_MCP (NGFF_SLTB_WWAN_SSD_DET2) */ - { .gpio = 53, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO }, - /* NGFF_SLTB_SSD_MC_WAKE_N */ - { .gpio = 54, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO }, - /* TOUCHPAD_INTR_N */ - { .gpio = 55, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, - .conf1 = GPIO_SENSE_ENABLE, - .owner = GPIO_OWNER_GPIO, - .irqen = GPIO_IRQ_ENABLE }, - /* NGFF_SLTB_WWAN_SSD_DET1 */ - { .gpio = 56, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* NGFF_SLTB_WWAN_PWREN */ - { .gpio = 57, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* SLATEMODE_HALLOUT_R */ - { .gpio = 58, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* USB2_CAM_PWREN */ - { .gpio = 59, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* USB_CR_PWREN_N */ - { .gpio = 60, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* PM_SUS_STAT_N */ - { .gpio = 61, - .conf0 = GPIO_MODE_NATIVE }, - /* SUS_CK */ - { .gpio = 62, - .conf0 = GPIO_MODE_NATIVE }, - /* SLP_S5_R_N */ - { .gpio = 63, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_CLK_CMNHDR_R */ - { .gpio = 64, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_CMD_CMNHDR_R */ - { .gpio = 65, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_D0_CMNHDR_R */ - { .gpio = 66, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_D1_CMNHDR_R */ - { .gpio = 67, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_D2_CMNHDR_R */ - { .gpio = 68, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_SDIO_D3_CMNHDR_R1 */ - { .gpio = 69, - .conf0 = GPIO_MODE_NATIVE }, - /* NGFF_SLTA_WIFI_PWREN_N_R (SDIO_POWER_EN) */ - { .gpio = 70, - .conf0 = GPIO_MODE_NATIVE }, - /* MPHY_PWREN */ - { .gpio = 71, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* PM_BATLOW_R_N */ - { .gpio = 72, - .conf0 = GPIO_MODE_NATIVE }, - /* PCH_NOT_N */ - { .gpio = 73, - .conf0 = GPIO_MODE_NATIVE }, - /* SML1_DATA */ - { .gpio = 74, - .conf0 = GPIO_MODE_NATIVE }, - /* SML1_CK */ - { .gpio = 75, - .conf0 = GPIO_MODE_NATIVE }, - /* PCH_AUDIO_PWR_R */ - { .gpio = 76, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, - .conf1 = GPIO_SENSE_DISABLE }, - /* PC_SLTB_SSD_RST_N_R */ - { .gpio = 77, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* PM_EXTTS0_EC_N */ - { .gpio = 78, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* SIO1007_IRQ_N */ - { .gpio = 79, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* PM_EXTTS1_R_N */ - { .gpio = 80, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT }, - /* PCH_HDA_SPKR */ - { .gpio = 81, - .conf0 = GPIO_MODE_NATIVE }, - /* H_RCIN_N */ - { .gpio = 82, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI0_CS_R_N */ - { .gpio = 83, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI0_CLK_R */ - { .gpio = 84, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI0_MISO_R */ - { .gpio = 85, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI0_MOSI_BBS0_R */ - { .gpio = 86, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI1_CS_R_N */ - { .gpio = 87, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI1_CLK_R */ - { .gpio = 88, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_GSPI1_MISO_R */ - { .gpio = 89, - .conf0 = GPIO_MODE_NATIVE }, - /* NGFF_SLTA_WIFI_RST_N */ - { .gpio = 90, - .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, - .conf1 = GPIO_SENSE_DISABLE }, - /* LPSS_UART0_RXD */ - { .gpio = 91, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART0_TXD */ - { .gpio = 92, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART0_RTS_N */ - { .gpio = 93, - .conf0 = GPIO_MODE_NATIVE }, - /* LPSS_UART0_CTS_N */ - { .gpio = 94, - .conf0 = GPIO_MODE_NATIVE }, - /* END */ - { .gpio = GPIO_LIST_END } +static const struct gpio_config mainboard_gpio_config[] = { + PCH_GPIO_NATIVE, /* 0: LPSS_UART1_RXD */ + PCH_GPIO_NATIVE, /* 1: LPSS_UART1_TXD */ + PCH_GPIO_NATIVE, /* 2: LPSS_UART1_RTS_N_R */ + PCH_GPIO_NATIVE, /* 3: LPSS_UART1_CTS_N */ + PCH_GPIO_NATIVE, /* 4: LPSS_I2C0_SDA_R */ + PCH_GPIO_NATIVE, /* 5: LPSS_I2C0_SCL */ + PCH_GPIO_NATIVE, /* 6: LPSS_I2C1_SDA */ + PCH_GPIO_NATIVE, /* 7: LPSS_I2C1_SCL */ + PCH_GPIO_UNUSED, /* 8: NGFF_SLTA_WIFI_WAKE_N */ + PCH_GPIO_UNUSED, /* 9: ACCEL_INT2_MCP */ + PCH_GPIO_ACPI_SCI, /* 10: SMC_RUNTIME_SCI_N */ + PCH_GPIO_UNUSED, /* 11: AMB_THRM_R_N */ + PCH_GPIO_NATIVE, /* 12: PM_LANPHY_ENABLE */ + PCH_GPIO_OUT_HIGH, /* 13: USB32_P0_PWREN */ + PCH_GPIO_IRQ_EDGE, /* 14: SH_INT_ACCEL_DRDY_USB_INT_N */ + PCH_GPIO_OUT_HIGH, /* 15: LAN_PWREN_N */ + PCH_GPIO_OUT_HIGH, /* 16: LAN_RST_N */ + PCH_GPIO_OUT_LOW, /* 17: CRIT_TEMP_REP_R_N */ + PCH_GPIO_UNUSED, /* 18: TBT_FORCE_PWR */ + PCH_GPIO_INPUT, /* 19: EC_IN_RW */ + PCH_GPIO_NATIVE, /* 20: CK_REQ_P2_NGFFSLTA_N_R */ + PCH_GPIO_NATIVE, /* 21: CK_PCIE_LAN_REQ_N */ + PCH_GPIO_NATIVE, /* 22: CK_REQ_P4_TBT_N */ + PCH_GPIO_NATIVE, /* 23: CK_REQ_P5_N */ + PCH_GPIO_OUT_LOW, /* 24: ME_PG_LED */ + PCH_GPIO_INPUT, /* 25: USB_WAKEOUT_N */ + PCH_GPIO_IRQ_EDGE, /* 26: NFC_IRQ_MGP5 */ + PCH_GPIO_ACPI_SCI, /* 27: SMC_WAKE_SCI_N */ + PCH_GPIO_OUT_LOW, /* 28: PCH_NFC_RESET */ + PCH_GPIO_NATIVE, /* 29: PCH_SLP_WLAN_N */ + PCH_GPIO_NATIVE, /* 30: SUS_PWR_ACK_R */ + PCH_GPIO_NATIVE, /* 31: AC_PRESENT_R */ + PCH_GPIO_NATIVE, /* 32: PM_CKRUN_N */ + PCH_GPIO_OUT_LOW, /* 33: SATA0_PHYSLP */ + PCH_GPIO_INPUT, /* 34: ESATA_DET_N */ + PCH_GPIO_INPUT, /* 35: SATA_DIRECT_PRSNT_R_N */ + PCH_GPIO_INPUT, /* 36: NGFF_SSD_SATA2_PCIE1_DET_N */ + PCH_GPIO_INPUT, /* 37: NGFF_SSD_SATA3_PCIE0_DET_N */ + PCH_GPIO_OUT_LOW, /* 38: SATA1_PHYSLP_DIRECT */ + PCH_GPIO_ACPI_SMI, /* 39: SMC_EXTSMI_N_R */ + PCH_GPIO_NATIVE, /* 40: USB_OC_0_1_R_N */ + PCH_GPIO_NATIVE, /* 41: USB_OC_2_6_R_N */ + PCH_GPIO_INPUT, /* 42: TBT_CIO_PLUG_SMI_N_R */ + PCH_GPIO_OUT_HIGH, /* 43: USB32_P1_PWREN */ + PCH_GPIO_INPUT, /* 44: SENSOR_HUB_RST_N */ + PCH_GPIO_INPUT, /* 45: GYRO_INT2_MCP_R */ + PCH_GPIO_OUT_HIGH, /* 46: SNSR_HUB_PWREN */ + PCH_GPIO_IRQ_EDGE, /* 47: SPI_TPM_HDR_IRQ_N */ + PCH_GPIO_OUT_HIGH, /* 48: PCIE_TBT_RST_N */ + PCH_GPIO_INPUT, /* 49: COMBO_JD */ + PCH_GPIO_IRQ_EDGE, /* 50: TOUCH_PANEL_INTR_N */ + PCH_GPIO_OUT_HIGH, /* 51: PCH_WIFI_RF_KILL_N */ + PCH_GPIO_OUT_HIGH, /* 52: TOUCH_PNL_RST_N_R */ + PCH_GPIO_INPUT, /* 53: SNSR_HUB_I2C_WAKE / ALS_INT_MCP */ + PCH_GPIO_ACPI_SCI, /* 54: NGFF_SLTB_SSD_MC_WAKE_N */ + PCH_GPIO_IRQ_EDGE, /* 55: TOUCHPAD_INTR_N */ + PCH_GPIO_INPUT, /* 56: NGFF_SLTB_WWAN_SSD_DET1 */ + PCH_GPIO_OUT_HIGH, /* 57: NGFF_SLTB_WWAN_PWREN */ + PCH_GPIO_OUT_LOW, /* 58: SLATEMODE_HALLOUT_R */ + PCH_GPIO_OUT_HIGH, /* 59: USB2_CAM_PWREN */ + PCH_GPIO_OUT_LOW, /* 60: USB_CR_PWREN_N */ + PCH_GPIO_NATIVE, /* 61: PM_SUS_STAT_N */ + PCH_GPIO_NATIVE, /* 62: SUS_CK */ + PCH_GPIO_NATIVE, /* 63: SLP_S5_R_N */ + PCH_GPIO_NATIVE, /* 64: LPSS_SDIO_CLK_CMNHDR_R */ + PCH_GPIO_NATIVE, /* 65: LPSS_SDIO_CMD_CMNHDR_R */ + PCH_GPIO_NATIVE, /* 66: LPSS_SDIO_D0_CMNHDR_R */ + PCH_GPIO_NATIVE, /* 67: LPSS_SDIO_D1_CMNHDR_R */ + PCH_GPIO_NATIVE, /* 68: LPSS_SDIO_D2_CMNHDR_R */ + PCH_GPIO_NATIVE, /* 69: LPSS_SDIO_D3_CMNHDR_R1 */ + PCH_GPIO_NATIVE, /* 70: NGFF_SLTA_WIFI_PWREN_N_R */ + PCH_GPIO_OUT_HIGH, /* 71: MPHY_PWREN */ + PCH_GPIO_NATIVE, /* 72: PM_BATLOW_R_N */ + PCH_GPIO_NATIVE, /* 73: PCH_NOT_N */ + PCH_GPIO_NATIVE, /* 74: SML1_DATA */ + PCH_GPIO_NATIVE, /* 75: SML1_CK */ + PCH_GPIO_OUT_HIGH, /* 76: PCH_AUDIO_PWR_R */ + PCH_GPIO_OUT_LOW, /* 77: PC_SLTB_SSD_RST_N_R */ + PCH_GPIO_INPUT, /* 78: PM_EXTTS0_EC_N */ + PCH_GPIO_IRQ_EDGE, /* 79: SIO1007_IRQ_N */ + PCH_GPIO_INPUT, /* 80: PM_EXTTS1_R_N */ + PCH_GPIO_NATIVE, /* 81: PCH_HDA_SPKR */ + PCH_GPIO_NATIVE, /* 82: H_RCIN_N */ + PCH_GPIO_NATIVE, /* 83: LPSS_GSPI0_CS_R_N */ + PCH_GPIO_NATIVE, /* 84: LPSS_GSPI0_CLK_R */ + PCH_GPIO_NATIVE, /* 85: LPSS_GSPI0_MISO_R */ + PCH_GPIO_NATIVE, /* 86: LPSS_GSPI0_MOSI_BBS0_R */ + PCH_GPIO_NATIVE, /* 87: LPSS_GSPI1_CS_R_N */ + PCH_GPIO_NATIVE, /* 88: LPSS_GSPI1_CLK_R */ + PCH_GPIO_NATIVE, /* 89: LPSS_GSPI1_MISO_R */ + PCH_GPIO_OUT_LOW, /* 90: NGFF_SLTA_WIFI_RST_N */ + PCH_GPIO_NATIVE, /* 91: LPSS_UART0_RXD */ + PCH_GPIO_NATIVE, /* 92: LPSS_UART0_TXD */ + PCH_GPIO_NATIVE, /* 93: LPSS_UART0_RTS_N */ + PCH_GPIO_NATIVE, /* 94: LPSS_UART0_CTS_N */ + PCH_GPIO_END }; #endif diff --git a/src/mainboard/intel/wtm2/graphics.c b/src/mainboard/intel/wtm2/graphics.c new file mode 100644 index 0000000000..6d375e6a27 --- /dev/null +++ b/src/mainboard/intel/wtm2/graphics.c @@ -0,0 +1,89 @@ +/* +* This file is part of the coreboot project. +* +* Copyright 2013 Google Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +/* this file was for the most part machine generated, and in future + * will be all machine generated. Avoid editing. + */ +#include +#include + +void graphics_register_reset(u32 aux_ctl, u32 aux_data, int verbose) +{ + + io_i915_write32(0x80000000,0x45400); + io_i915_write32(0x00000000,_CURACNTR); + io_i915_write32((/* PIPEA */0x0<<24)|0x00000000,_DSPACNTR); + io_i915_write32(0x00000000,_DSPBCNTR); + io_i915_write32(0x80000000,CPU_VGACNTRL); + io_i915_write32(0x00000000,_DSPASIZE+0xc); + io_i915_write32(0x00000000,_DSPBSURF); + io_i915_write32(0x00000000,0x4f050); + io_i915_write32( DP_LINK_TRAIN_PAT_1 | DP_LINK_TRAIN_PAT_1_CPT | + DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0 | DP_PORT_WIDTH_1 | + DP_PLL_FREQ_270MHZ | DP_SCRAMBLING_DISABLE_IRONLAKE | + DP_SYNC_VS_HIGH |0x00000091,DP_A); + io_i915_write32(0x00200090,_FDI_RXA_MISC); + io_i915_write32(0x0a000000,_FDI_RXA_MISC); + /* not yet documented anywhere that we can find. */ + io_i915_write32(0x00000070,0x46408); + io_i915_write32(0x04000000,0x42090); + io_i915_write32(0x40000000,0x4f050); + io_i915_write32(0x00000000,0x9840); + io_i915_write32(0xa4000000,0x42090); + io_i915_write32(0x00004000,0x42080); + io_i915_write32(0x00ffffff,0x64f80); + io_i915_write32(0x0007000e,0x64f84); + io_i915_write32(0x00d75fff,0x64f88); + io_i915_write32(0x000f000a,0x64f8c); + io_i915_write32(0x00c30fff,0x64f90); + io_i915_write32(0x00060006,0x64f94); + io_i915_write32(0x00aaafff,0x64f98); + io_i915_write32(0x001e0000,0x64f9c); + io_i915_write32(0x00ffffff,0x64fa0); + io_i915_write32(0x000f000a,0x64fa4); + io_i915_write32(0x00d75fff,0x64fa8); + io_i915_write32(0x00160004,0x64fac); + io_i915_write32(0x00c30fff,0x64fb0); + io_i915_write32(0x001e0000,0x64fb4); + io_i915_write32(0x00ffffff,0x64fb8); + io_i915_write32(0x00060006,0x64fbc); + io_i915_write32(0x00d75fff,0x64fc0); + io_i915_write32(0x001e0000,0x64fc4); + io_i915_write32(0x00ffffff,0x64e00); + io_i915_write32(0x0006000e,0x64e04); + io_i915_write32(0x00d75fff,0x64e08); + io_i915_write32(0x0005000a,0x64e0c); + io_i915_write32(0x00c30fff,0x64e10); + io_i915_write32(0x00040006,0x64e14); + io_i915_write32(0x80aaafff,0x64e18); + io_i915_write32(0x000b0000,0x64e1c); + io_i915_write32(0x00ffffff,0x64e20); + io_i915_write32(0x0005000a,0x64e24); + io_i915_write32(0x00d75fff,0x64e28); + io_i915_write32(0x000c0004,0x64e2c); + io_i915_write32(0x80c30fff,0x64e30); + io_i915_write32(0x000b0000,0x64e34); + io_i915_write32(0x00ffffff,0x64e38); + io_i915_write32(0x00040006,0x64e3c); + io_i915_write32(0x80d75fff,0x64e40); + io_i915_write32(0x000b0000,0x64e44); + /* end not yet documented. */ + io_i915_write32(0x10000000,SDEISR+0x30); +} + + diff --git a/src/mainboard/intel/wtm2/i915.c b/src/mainboard/intel/wtm2/i915.c new file mode 100644 index 0000000000..df8813888f --- /dev/null +++ b/src/mainboard/intel/wtm2/i915.c @@ -0,0 +1,236 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hda_verb.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* how many bytes do we need for the framebuffer? + * Well, this gets messy. To get an exact answer, we have + * to ask the panel, but we'd rather zero the memory + * and set up the gtt while the panel powers up. So, + * we take a reasonable guess, secure in the knowledge that the + * MRC has to overestimate the number of bytes used. + * 8 MiB is a very safe guess. There may be a better way later, but + * fact is, the initial framebuffer is only very temporary. And taking + * a little long is ok; this is done much faster than the AUX + * channel is ready for IO. + */ +#define FRAME_BUFFER_BYTES (8*MiB) +/* how many 4096-byte pages do we need for the framebuffer? + * There are hard ways to get this, and easy ways: + * there are FRAME_BUFFER_BYTES/4096 pages, since pages are 4096 + * on this chip (and in fact every Intel graphics chip we've seen). + */ +#define FRAME_BUFFER_PAGES (FRAME_BUFFER_BYTES/(4096)) + +static int verbose = 0; + +static unsigned int *mmio; +static unsigned int graphics; +static unsigned short addrport; +static unsigned short dataport; +static unsigned int physbase; +extern int oprom_is_loaded; + +const u32 link_edid_data[] = { + 0xffffff00, 0x00ffffff, 0x0379e430, 0x00000000, + 0x04011500, 0x96121ba5, 0xa2d54f02, 0x26935259, + 0x00545017, 0x01010000, 0x01010101, 0x01010101, + 0x01010101, 0x6f6d0101, 0xa4a0a000, 0x20306031, + 0xb510003a, 0x19000010, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x4c00fe00, + 0x69442047, 0x616c7073, 0x20200a79, 0xfe000000, + 0x31504c00, 0x45513932, 0x50532d31, 0x24003141, +}; + +static int ioread = 0, iowrite = 0; + +static char *regname(unsigned long addr) +{ + static char name[16]; + sprintf(name, "0x%lx", addr); + return name; +} + +unsigned long io_i915_read32(unsigned long addr) +{ + unsigned long val; + outl(addr, addrport); + val = inl(dataport); + ioread += 2; + if (verbose & vio)printk(BIOS_SPEW, "%s: Got %08lx\n", regname(addr), val); + return val; +} + +void io_i915_write32(unsigned long val, unsigned long addr) +{ + if (verbose & vio)printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val); + outl(addr, addrport); + outl(val, dataport); + iowrite += 2; +} + +/* GTT is the Global Translation Table for the graphics pipeline. + * It is used to translate graphics addresses to physical + * memory addresses. As in the CPU, GTTs map 4K pages. + * The setgtt function adds a further bit of flexibility: + * it allows you to set a range (the first two parameters) to point + * to a physical address (third parameter);the physical address is + * incremented by a count (fourth parameter) for each GTT in the + * range. + * Why do it this way? For ultrafast startup, + * we can point all the GTT entries to point to one page, + * and set that page to 0s: + * memset(physbase, 0, 4096); + * setgtt(0, 4250, physbase, 0); + * this takes about 2 ms, and is a win because zeroing + * the page takes a up to 200 ms. + * This call sets the GTT to point to a linear range of pages + * starting at physbase. + */ + +static void +setgtt(int start, int end, unsigned long base, int inc) +{ + int i; + + for(i = start; i < end; i++){ + u32 word = base + i*inc; + io_i915_write32(word|1,(i*4)|1); + } +} + +static unsigned long tickspermicrosecond = 1795; +static unsigned long long globalstart; + +static unsigned long +microseconds(unsigned long long start, unsigned long long end) +{ + unsigned long ret; + ret = ((end - start)/tickspermicrosecond); + return ret; +} + +static unsigned long globalmicroseconds(void) +{ + return microseconds(globalstart, rdtscll()); +} + +static int i915_init_done = 0; + +int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio, + unsigned int gfx); + +int i915lightup(unsigned int pphysbase, unsigned int piobase, + unsigned int pmmio, unsigned int pgfx) +{ + int must_cycle_power = 0; + + /* frame buffer pointer */ + u32 *l; + int i; + unsigned long before_gtt, after_gtt; + + mmio = (void *)pmmio; + addrport = piobase; + dataport = addrport + 4; + physbase = pphysbase; + graphics = pgfx; + printk(BIOS_SPEW, + "i915lightup: graphics %p mmio %p" + "addrport %04x physbase %08x\n", + (void *)graphics, mmio, addrport, physbase); + globalstart = rdtscll(); + + /* turn it on. The VBIOS does it this way, so we hope that's ok. */ + verbose = 0; + io_i915_write32(0xabcd000f, PCH_PP_CONTROL); + + /* the AUX channel needs a small amount of time to spin up. + * Rather than udelay, do some useful work: + * Zero out the frame buffer memory, + * and set the global translation table (GTT) + */ + printk(BIOS_SPEW, "Set not-White (%08x) for %d pixels\n", 0xffffff, + FRAME_BUFFER_BYTES/sizeof(u32)); + for(l = (u32 *)graphics, i = 0; + i < FRAME_BUFFER_BYTES/sizeof(u32); i++){ + l[i] = 0x1122ff; + } + printk(BIOS_SPEW, "GTT: set %d pages starting at %p\n", + FRAME_BUFFER_PAGES, (void *)physbase); + before_gtt = globalmicroseconds(); + setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096); + after_gtt = globalmicroseconds(); + + /* The reset is basically harmless, and can be + * repeated by the VBIOS in any event. + */ + + graphics_register_reset(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, verbose); + + /* failures after this point can return without + * powering off the panel. + */ + + if (1) + goto fail; + /* failures after this point MUST power off the panel + * and wait 600 ms. + */ + + i915_init_done = 1; + oprom_is_loaded = 1; + return 1; + +fail: + printk(BIOS_SPEW, "Graphics could not be started;"); + if (must_cycle_power){ + printk(BIOS_SPEW, "Turn off power and wait ..."); + io_i915_write32(0xabcd0000, PCH_PP_CONTROL); + udelay(600000); + } + printk(BIOS_SPEW, "Returning.\n"); + return 0; + +} diff --git a/src/mainboard/intel/wtm2/intel_dp.c b/src/mainboard/intel/wtm2/intel_dp.c new file mode 100644 index 0000000000..e7222a3f2b --- /dev/null +++ b/src/mainboard/intel/wtm2/intel_dp.c @@ -0,0 +1,167 @@ +/* + * Copyright 2013 Google Inc. + * Copyright © 2008 Intel Corporation + * + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Keith Packard + * + */ + +#include +#include +#include +#include + +u32 +pack_aux(u32 *src32, int src_bytes) +{ + u8 *src = (u8 *)src32; + int i; + u32 v = 0; + + if (src_bytes > 4) + src_bytes = 4; + for (i = 0; i < src_bytes; i++) + v |= ((u32) src[i]) << ((3-i) * 8); + return v; +} + +void +unpack_aux(u32 src, u8 *dst, int dst_bytes) +{ + + int i; + if (dst_bytes > 4) + dst_bytes = 4; + for (i = 0; i < dst_bytes; i++) + dst[i] = src >> ((3-i) * 8); +} + +int +intel_dp_aux_ch(u32 ch_ctl, u32 ch_data, u32 *send, int send_bytes, + u8 *recv, int recv_size) +{ + int i; + int recv_bytes; + u32 status; + u32 aux_clock_divider; + int try, precharge = 5; + + /* The clock divider is based off the hrawclk, + * and would like to run at 2MHz. So, take the + * hrawclk value and divide by 2 and use that + * + * Note that PCH attached eDP panels should use a 125MHz input + * clock divider. + */ + /* 200 on link */ + aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */ + + /* Try to wait for any previous AUX channel activity */ + for (try = 0; try < 3; try++) { + status = io_i915_read32(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + udelay(1000); + } + + if (try == 3) { + printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__); + status = io_i915_read32(ch_ctl); + printk(BIOS_SPEW, "dp_aux_ch not started status 0x%08x\n", + status); + return -1; + } + + /* Must try at least 3 times according to DP spec */ + for (try = 0; try < 5; try++) { + /* Load the send data into the aux channel data registers */ + for (i = 0; i < send_bytes; i += 4) + io_i915_write32(send[i], ch_data + i); + + /* Send the command and wait for it to complete */ + io_i915_write32( + DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR, ch_ctl); + for (;;) { + status = io_i915_read32(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + udelay(100); + } + + /* Clear done status and any errors */ + io_i915_write32( + status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR, ch_ctl); + + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR)) + continue; + if (status & DP_AUX_CH_CTL_DONE) + break; + } + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { + printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_SPEW, "dp_aux_ch not done status 0x%08x\n", status); + return -1; + } + + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ + if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { + printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_SPEW, "dp_aux_ch receive error status 0x%08x\n", status); + return -1; + } + + /* Timeouts occur when the device isn't connected, so they're + * "normal" -- don't fill the kernel log with these */ + if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { + printk(BIOS_SPEW, "[000000.0] [drm:%s], ", __func__); + printk(BIOS_SPEW, "dp_aux_ch timeout status 0x%08x\n", status); + return -1; + } + + /* Unload any bytes sent back from the other side */ + recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> + DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(io_i915_read32(ch_data + i), + recv + i, recv_bytes - i); + + return recv_bytes; +} diff --git a/src/mainboard/intel/wtm2/mainboard.c b/src/mainboard/intel/wtm2/mainboard.c index f5b00546f7..dfb8b3a77b 100644 --- a/src/mainboard/intel/wtm2/mainboard.c +++ b/src/mainboard/intel/wtm2/mainboard.c @@ -25,7 +25,7 @@ #include #include #include -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -34,23 +34,16 @@ #include #include #include "hda_verb.h" -#include -void mainboard_suspend_resume(void) +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN +static int int15_handler(void) { - /* Call SMM finalize() handlers before resume */ - outb(0xcb, 0xb2); -} + int res = 1; -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static int int15_handler(struct eregs *regs) -{ - int res=-1; + printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", + __func__, X86_AX, X86_BX, X86_CX, X86_DX); - printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, regs->eax & 0xffff); - - switch(regs->eax & 0xffff) { + switch (X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -59,11 +52,9 @@ static int int15_handler(struct eregs *regs) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffffff00; - regs->ecx |= 0x01; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0001; + res = 1; break; case 0x5f35: /* @@ -77,11 +68,9 @@ static int int15_handler(struct eregs *regs) * bit 6 = EFP2 * * bit 7 = LFP2 */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 0x5f51: /* @@ -91,129 +80,47 @@ static int int15_handler(struct eregs *regs) * 02h = SVDO-LVDS, LFP driven by SVDO decoder * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0003; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0003; + res = 1; break; case 0x5f70: - switch ((regs->ecx >> 8) & 0xff) { + switch ((X86_CX >> 8) & 0xff) { case 0: /* Get Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 1: /* Set Mux */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; case 2: /* Get SG/Non-SG mode */ - regs->eax &= 0xffff0000; - regs->eax |= 0x005f; - regs->ecx &= 0xffff0000; - regs->ecx |= 0x0000; - res = 0; + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; break; default: /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((regs->ecx >> 8) & 0xff)); - return 0; + printk(BIOS_DEBUG, + "Unknown INT15 5f70 function: 0x%02x\n", + ((X86_CX >> 8) & 0xff)); + break; } break; default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - regs->eax & 0xffff); + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); break; } return res; } #endif -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); - - switch (M.x86.R_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0001; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) * - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) * - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0x0000; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 3; - break; - case 0x5f70: - /* Unknown */ - M.x86.R_AX = 0x005f; - M.x86.R_CX = 0; - break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - M.x86.R_AX); - return 0; - } - - /* Interrupt handled */ - return 1; -} -#endif - -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE -static void int15_install(void) -{ -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL - typedef int (* yabel_handleIntFunc)(void); - extern yabel_handleIntFunc yabel_intFuncArray[256]; - yabel_intFuncArray[0x15] = int15_handler; -#endif -#ifdef CONFIG_PCI_OPTION_ROM_RUN_REALMODE - mainboard_interrupt_handlers(0x15, &int15_handler); -#endif -} -#endif - /* Audio Setup */ extern const u32 * cim_verb_data; @@ -230,9 +137,9 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ - int15_install(); + mainboard_interrupt_handlers(0x15, &int15_handler); #endif verb_setup(); } diff --git a/src/mainboard/intel/wtm2/mainboard_smi.c b/src/mainboard/intel/wtm2/mainboard_smi.c index 3ffc68441d..1c4edef81c 100644 --- a/src/mainboard/intel/wtm2/mainboard_smi.c +++ b/src/mainboard/intel/wtm2/mainboard_smi.c @@ -20,11 +20,8 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include int mainboard_io_trap_handler(int smif) { @@ -46,27 +43,3 @@ int mainboard_io_trap_handler(int smif) //gnvs->smif = 0; return 1; } - -#define APMC_FINALIZE 0xcb - -static int mainboard_finalized = 0; - -int mainboard_smi_apmc(u8 apmc) -{ - switch (apmc) { - case APMC_FINALIZE: - if (mainboard_finalized) { - printk(BIOS_DEBUG, "SMI#: Already finalized\n"); - return 0; - } - - intel_me_finalize_smm(); - intel_pch_finalize_smm(); - intel_northbridge_haswell_finalize_smm(); - intel_cpu_haswell_finalize_smm(); - - mainboard_finalized = 1; - break; - } - return 0; -} diff --git a/src/mainboard/intel/wtm2/pei_data.c b/src/mainboard/intel/wtm2/pei_data.c new file mode 100644 index 0000000000..f77895a3c3 --- /dev/null +++ b/src/mainboard/intel/wtm2/pei_data.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + /* One installed DIMM per channel */ + pei_data->dimm_channel0_disabled = 2; + pei_data->dimm_channel1_disabled = 2; + + pei_data->spd_addresses[0] = 0xa2; + pei_data->spd_addresses[2] = 0xa2; + + pei_data_usb2_port(pei_data, 0, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 1, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 2, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 3, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 4, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 5, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 6, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + pei_data_usb2_port(pei_data, 7, 0x40, 1, USB_OC_PIN_SKIP, + USB_PORT_FRONT_PANEL); + + pei_data_usb3_port(pei_data, 0, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 1, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 2, 1, USB_OC_PIN_SKIP, 0); + pei_data_usb3_port(pei_data, 3, 1, USB_OC_PIN_SKIP, 0); +} diff --git a/src/mainboard/intel/wtm2/romstage.c b/src/mainboard/intel/wtm2/romstage.c index 440b35f4fe..d3ec418556 100644 --- a/src/mainboard/intel/wtm2/romstage.c +++ b/src/mainboard/intel/wtm2/romstage.c @@ -18,111 +18,28 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include -#include "cpu/intel/haswell/haswell.h" -#include "northbridge/intel/haswell/haswell.h" -#include "northbridge/intel/haswell/raminit.h" -#include "southbridge/intel/lynxpoint/pch.h" -#include "southbridge/intel/lynxpoint/lp_gpio.h" +#include +#include +#include +#include +#include +#include #include "gpio.h" -const struct rcba_config_instruction rcba_config[] = { - - /* - * GFX INTA -> PIRQA (MSI) - * D28IP_P1IP WLAN INTA -> PIRQB - * D28IP_P4IP ETH0 INTB -> PIRQC - * D29IP_E1P EHCI1 INTA -> PIRQD - * D20IP_XHCI XHCI INTA -> PIRQA - * D31IP_SIP SATA INTA -> PIRQF (MSI) - * D31IP_SMIP SMBUS INTB -> PIRQG - * D31IP_TTIP THRT INTC -> PIRQH - * D27IP_ZIP HDA INTA -> PIRQG (MSI) - */ - - /* Device interrupt pin register (board specific) */ - RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | - (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), - RCBA_SET_REG_32(D29IP, (INTA << D29IP_E1P)), - RCBA_SET_REG_32(D28IP, (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | - (INTB << D28IP_P4IP)), - RCBA_SET_REG_32(D27IP, (INTA << D27IP_ZIP)), - RCBA_SET_REG_32(D26IP, (INTA << D26IP_E2P)), - RCBA_SET_REG_32(D25IP, (NOINT << D25IP_LIP)), - RCBA_SET_REG_32(D22IP, (NOINT << D22IP_MEI1IP)), - RCBA_SET_REG_32(D20IR, (INTA << D20IP_XHCI)), - - /* Device interrupt route registers */ - RCBA_SET_REG_32(D31IR, DIR_ROUTE(PIRQF, PIRQG, PIRQH, PIRQA)), - RCBA_SET_REG_32(D29IR, DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG)), - RCBA_SET_REG_32(D28IR, DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE)), - RCBA_SET_REG_32(D27IR, DIR_ROUTE(PIRQG, PIRQH, PIRQA, PIRQB)), - RCBA_SET_REG_32(D26IR, DIR_ROUTE(PIRQE, PIRQF, PIRQG, PIRQH)), - RCBA_SET_REG_32(D25IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D22IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D21IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D20IR, DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), - RCBA_SET_REG_32(D23IR, DIR_ROUTE(PIRQA, 0, 0, 0)), - - /* Disable unused devices (board specific) */ - RCBA_RMW_REG_32(FD, ~0, PCH_DISABLE_ALWAYS), - - RCBA_END_CONFIG, -}; - -void mainboard_romstage_entry(unsigned long bist) +void mainboard_romstage_entry(struct romstage_params *rp) { - struct pei_data pei_data = { - pei_version: PEI_VERSION, - mchbar: DEFAULT_MCHBAR, - dmibar: DEFAULT_DMIBAR, - epbar: DEFAULT_EPBAR, - pciexbar: DEFAULT_PCIEXBAR, - smbusbar: SMBUS_IO_BASE, - wdbbar: 0x4000000, - wdbsize: 0x1000, - hpet_address: HPET_ADDR, - rcba: DEFAULT_RCBA, - pmbase: DEFAULT_PMBASE, - gpiobase: DEFAULT_GPIOBASE, - temp_mmio_base: 0xfed08000, - system_type: 5, /* ULT */ - tseg_size: CONFIG_SMM_TSEG_SIZE, - spd_addresses: { 0xa2, 0x00, 0xa2, 0x00 }, - ec_present: 1, - // 0 = leave channel enabled - // 1 = disable dimm 0 on channel - // 2 = disable dimm 1 on channel - // 3 = disable dimm 0+1 on channel - dimm_channel0_disabled: 2, - dimm_channel1_disabled: 2, - max_ddr3_freq: 1600, - usb_port_config: { - { 1, 0, 0x0040 }, /* P0: */ - { 1, 0, 0x0040 }, /* P1: */ - { 1, 0, 0x0040 }, /* P2: */ - { 1, 0, 0x0040 }, /* P3: */ - { 1, 0, 0x0040 }, /* P4: */ - { 1, 0, 0x0040 }, /* P5: */ - { 1, 0, 0x0040 }, /* P6: */ - { 0, 0, 0x0040 }, /* P7: Disable SDCARD due to hang */ - { 1, 0, 0x0040 }, /* P8: */ - { 1, 0, 0x0040 }, /* P9: */ - { 1, 0, 0x0040 }, /* P10: */ - { 1, 0, 0x0000 }, /* P11: */ - { 1, 0, 0x0040 }, /* P12: */ - { 1, 0, 0x0040 }, /* P13: */ - }, - }; + struct pei_data pei_data; - struct romstage_params romstage_params = { - .pei_data = &pei_data, - .gpio_map = &mainboard_gpio_map, - .rcba_config = &rcba_config[0], - .bist = bist, - }; + post_code(0x32); - /* Call into the real romstage main with this board's attributes. */ - romstage_common(&romstage_params); + /* Initialize GPIOs */ + init_gpios(mainboard_gpio_config); + + /* Fill out PEI DATA */ + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + rp->pei_data = &pei_data; + + romstage_common(rp); } diff --git a/src/mainboard/intel/xe7501devkit/Kconfig b/src/mainboard/intel/xe7501devkit/Kconfig index 276b1f7b5b..923d39a645 100644 --- a/src/mainboard/intel/xe7501devkit/Kconfig +++ b/src/mainboard/intel/xe7501devkit/Kconfig @@ -2,7 +2,6 @@ if BOARD_INTEL_XE7501DEVKIT config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7501 select SOUTHBRIDGE_INTEL_I82870 diff --git a/src/mainboard/iwave/iWRainbowG6/Kconfig b/src/mainboard/iwave/iWRainbowG6/Kconfig index 7e05aaea80..a2b19fd9bf 100644 --- a/src/mainboard/iwave/iWRainbowG6/Kconfig +++ b/src/mainboard/iwave/iWRainbowG6/Kconfig @@ -3,7 +3,6 @@ if BOARD_IWAVE_RAINBOW_G6 # TODO: move options to chipset components as appropriate config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_441 select NORTHBRIDGE_INTEL_SCH select SOUTHBRIDGE_INTEL_SCH diff --git a/src/mainboard/iwill/dk8_htx/Kconfig b/src/mainboard/iwill/dk8_htx/Kconfig index d6b4c63149..7689ab5bf0 100644 --- a/src/mainboard/iwill/dk8_htx/Kconfig +++ b/src/mainboard/iwill/dk8_htx/Kconfig @@ -2,7 +2,6 @@ if BOARD_IWILL_DK8_HTX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/iwill/dk8s2/Kconfig b/src/mainboard/iwill/dk8s2/Kconfig index 6476d50b89..d27ebb0565 100644 --- a/src/mainboard/iwill/dk8s2/Kconfig +++ b/src/mainboard/iwill/dk8s2/Kconfig @@ -2,7 +2,6 @@ if BOARD_IWILL_DK8S2 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/iwill/dk8x/Kconfig b/src/mainboard/iwill/dk8x/Kconfig index e09a27bdf0..0450facd3b 100644 --- a/src/mainboard/iwill/dk8x/Kconfig +++ b/src/mainboard/iwill/dk8x/Kconfig @@ -2,7 +2,6 @@ if BOARD_IWILL_DK8X config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/jetway/j7f24/Kconfig b/src/mainboard/jetway/j7f24/Kconfig index fa17eba65f..74d2767f5e 100644 --- a/src/mainboard/jetway/j7f24/Kconfig +++ b/src/mainboard/jetway/j7f24/Kconfig @@ -3,7 +3,6 @@ if BOARD_JETWAY_J7F24 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_CN700 select SOUTHBRIDGE_VIA_VT8237R diff --git a/src/mainboard/jetway/pa78vm5/Kconfig b/src/mainboard/jetway/pa78vm5/Kconfig index 11dd1e5b97..668882351d 100644 --- a/src/mainboard/jetway/pa78vm5/Kconfig +++ b/src/mainboard/jetway/pa78vm5/Kconfig @@ -2,7 +2,6 @@ if BOARD_JETWAY_PA78VM5 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2R2 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/kontron/986lcd-m/Kconfig b/src/mainboard/kontron/986lcd-m/Kconfig index 0dd28da5a9..b174f572e6 100644 --- a/src/mainboard/kontron/986lcd-m/Kconfig +++ b/src/mainboard/kontron/986lcd-m/Kconfig @@ -2,7 +2,6 @@ if BOARD_KONTRON_986LCD_M config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/kontron/986lcd-m/mainboard.c b/src/mainboard/kontron/986lcd-m/mainboard.c index 061944ad82..0bee70e1ee 100644 --- a/src/mainboard/kontron/986lcd-m/mainboard.c +++ b/src/mainboard/kontron/986lcd-m/mainboard.c @@ -37,7 +37,7 @@ #define BOOT_DISPLAY_EFP2 (1 << 6) #define BOOT_DISPLAY_LCD2 (1 << 7) -#if CONFIG_VGA_ROM_RUN +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { /* This int15 handler is Intel IGD. specific. Other chipsets need other @@ -221,7 +221,7 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/kontron/kt690/Kconfig b/src/mainboard/kontron/kt690/Kconfig index db75d87a1d..caf42c791d 100644 --- a/src/mainboard/kontron/kt690/Kconfig +++ b/src/mainboard/kontron/kt690/Kconfig @@ -2,7 +2,6 @@ if BOARD_KONTRON_KT690 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_S1G1 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/lanner/em8510/Kconfig b/src/mainboard/lanner/em8510/Kconfig index 1a306cf804..e042e81b4e 100644 --- a/src/mainboard/lanner/em8510/Kconfig +++ b/src/mainboard/lanner/em8510/Kconfig @@ -2,7 +2,6 @@ if BOARD_LANNER_EM8510 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA479M select NORTHBRIDGE_INTEL_I855 select SOUTHBRIDGE_INTEL_I82801DX diff --git a/src/mainboard/lenovo/t60/Kconfig b/src/mainboard/lenovo/t60/Kconfig index 379d1ec27f..9ebb2f69dd 100644 --- a/src/mainboard/lenovo/t60/Kconfig +++ b/src/mainboard/lenovo/t60/Kconfig @@ -2,7 +2,6 @@ if BOARD_LENOVO_T60 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/lenovo/t60/smihandler.c b/src/mainboard/lenovo/t60/smihandler.c index f4bad8b581..093996b402 100644 --- a/src/mainboard/lenovo/t60/smihandler.c +++ b/src/mainboard/lenovo/t60/smihandler.c @@ -152,7 +152,7 @@ static void mainboard_smi_handle_ec_sci(void) } } -void mainboard_smi_gpi(u16 gpi) +void mainboard_smi_gpi(u32 gpi) { if (gpi & (1 << 12)) mainboard_smi_handle_ec_sci(); diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig index 231110bc53..865858591d 100644 --- a/src/mainboard/lenovo/x60/Kconfig +++ b/src/mainboard/lenovo/x60/Kconfig @@ -2,7 +2,6 @@ if BOARD_LENOVO_X60 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/lenovo/x60/smihandler.c b/src/mainboard/lenovo/x60/smihandler.c index 5a7130fe5f..090f0377bc 100644 --- a/src/mainboard/lenovo/x60/smihandler.c +++ b/src/mainboard/lenovo/x60/smihandler.c @@ -158,7 +158,7 @@ static void mainboard_smi_handle_ec_sci(void) } } -void mainboard_smi_gpi(u16 gpi) +void mainboard_smi_gpi(u32 gpi) { if (gpi & (1 << 12)) mainboard_smi_handle_ec_sci(); diff --git a/src/mainboard/lippert/frontrunner-af/Kconfig b/src/mainboard/lippert/frontrunner-af/Kconfig index f56c048ffc..c9881e04b7 100644 --- a/src/mainboard/lippert/frontrunner-af/Kconfig +++ b/src/mainboard/lippert/frontrunner-af/Kconfig @@ -21,7 +21,6 @@ if BOARD_LIPPERT_FRONTRUNNER_AF config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/lippert/frontrunner-af/get_bus_conf.c b/src/mainboard/lippert/frontrunner-af/get_bus_conf.c index 11ec26e16e..8872bb5a1c 100644 --- a/src/mainboard/lippert/frontrunner-af/get_bus_conf.c +++ b/src/mainboard/lippert/frontrunner-af/get_bus_conf.c @@ -74,7 +74,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/lippert/frontrunner-af/romstage.c b/src/mainboard/lippert/frontrunner-af/romstage.c index 0e1b1340fb..2dae8fe8ed 100644 --- a/src/mainboard/lippert/frontrunner-af/romstage.c +++ b/src/mainboard/lippert/frontrunner-af/romstage.c @@ -182,7 +182,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/lippert/frontrunner/Kconfig b/src/mainboard/lippert/frontrunner/Kconfig index ba1d5f14d9..fdba7baa83 100644 --- a/src/mainboard/lippert/frontrunner/Kconfig +++ b/src/mainboard/lippert/frontrunner/Kconfig @@ -2,7 +2,6 @@ if BOARD_LIPPERT_FRONTRUNNER config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX2 select NORTHBRIDGE_AMD_GX2 select SOUTHBRIDGE_AMD_CS5535 diff --git a/src/mainboard/lippert/hurricane-lx/Kconfig b/src/mainboard/lippert/hurricane-lx/Kconfig index 64e16318c4..4e41bbd16a 100644 --- a/src/mainboard/lippert/hurricane-lx/Kconfig +++ b/src/mainboard/lippert/hurricane-lx/Kconfig @@ -2,7 +2,6 @@ if BOARD_LIPPERT_HURRICANE_LX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/lippert/literunner-lx/Kconfig b/src/mainboard/lippert/literunner-lx/Kconfig index c4684c94e2..c3aab0e918 100644 --- a/src/mainboard/lippert/literunner-lx/Kconfig +++ b/src/mainboard/lippert/literunner-lx/Kconfig @@ -2,7 +2,6 @@ if BOARD_LIPPERT_LITERUNNER_LX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/lippert/roadrunner-lx/Kconfig b/src/mainboard/lippert/roadrunner-lx/Kconfig index f5ec9b9d77..051713a27d 100644 --- a/src/mainboard/lippert/roadrunner-lx/Kconfig +++ b/src/mainboard/lippert/roadrunner-lx/Kconfig @@ -2,7 +2,6 @@ if BOARD_LIPPERT_ROADRUNNER_LX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/lippert/spacerunner-lx/Kconfig b/src/mainboard/lippert/spacerunner-lx/Kconfig index c4a2ce8937..65645fdbf0 100644 --- a/src/mainboard/lippert/spacerunner-lx/Kconfig +++ b/src/mainboard/lippert/spacerunner-lx/Kconfig @@ -2,7 +2,6 @@ if BOARD_LIPPERT_SPACERUNNER_LX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/lippert/toucan-af/Kconfig b/src/mainboard/lippert/toucan-af/Kconfig index 6696ca6e77..cc1c900224 100644 --- a/src/mainboard/lippert/toucan-af/Kconfig +++ b/src/mainboard/lippert/toucan-af/Kconfig @@ -21,7 +21,6 @@ if BOARD_LIPPERT_TOUCAN_AF config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY14 select NORTHBRIDGE_AMD_AGESA_FAMILY14_ROOT_COMPLEX select NORTHBRIDGE_AMD_AGESA_FAMILY14 diff --git a/src/mainboard/lippert/toucan-af/get_bus_conf.c b/src/mainboard/lippert/toucan-af/get_bus_conf.c index 11ec26e16e..8872bb5a1c 100644 --- a/src/mainboard/lippert/toucan-af/get_bus_conf.c +++ b/src/mainboard/lippert/toucan-af/get_bus_conf.c @@ -74,7 +74,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/lippert/toucan-af/romstage.c b/src/mainboard/lippert/toucan-af/romstage.c index 043af85353..76282e867b 100644 --- a/src/mainboard/lippert/toucan-af/romstage.c +++ b/src/mainboard/lippert/toucan-af/romstage.c @@ -182,7 +182,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) setup_i8254 (); post_code(0x50); - copy_and_run(0); + copy_and_run(); printk(BIOS_ERR, "Error: copy_and_run() returned!\n"); post_code(0x54); /* Should never see this post code. */ diff --git a/src/mainboard/mitac/6513wu/Kconfig b/src/mainboard/mitac/6513wu/Kconfig index e55298228e..6228a6ec68 100644 --- a/src/mainboard/mitac/6513wu/Kconfig +++ b/src/mainboard/mitac/6513wu/Kconfig @@ -20,7 +20,6 @@ if BOARD_MITAC_6513WU config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/msi/ms6119/Kconfig b/src/mainboard/msi/ms6119/Kconfig index 7705522787..00ed0d9dfa 100644 --- a/src/mainboard/msi/ms6119/Kconfig +++ b/src/mainboard/msi/ms6119/Kconfig @@ -20,7 +20,6 @@ if BOARD_MSI_MS_6119 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/msi/ms6147/Kconfig b/src/mainboard/msi/ms6147/Kconfig index 9b51a492f4..fa4af805cf 100644 --- a/src/mainboard/msi/ms6147/Kconfig +++ b/src/mainboard/msi/ms6147/Kconfig @@ -20,7 +20,6 @@ if BOARD_MSI_MS_6147 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/msi/ms6156/Kconfig b/src/mainboard/msi/ms6156/Kconfig index 58654f68cb..840751cba7 100644 --- a/src/mainboard/msi/ms6156/Kconfig +++ b/src/mainboard/msi/ms6156/Kconfig @@ -20,7 +20,6 @@ if BOARD_MSI_MS_6156 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/msi/ms6178/Kconfig b/src/mainboard/msi/ms6178/Kconfig index 4baee5eb4a..cc70e76160 100644 --- a/src/mainboard/msi/ms6178/Kconfig +++ b/src/mainboard/msi/ms6178/Kconfig @@ -20,7 +20,6 @@ if BOARD_MSI_MS_6178 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/msi/ms7135/Kconfig b/src/mainboard/msi/ms7135/Kconfig index f1577a95ed..c0705dc86b 100644 --- a/src/mainboard/msi/ms7135/Kconfig +++ b/src/mainboard/msi/ms7135/Kconfig @@ -2,7 +2,6 @@ if BOARD_MSI_MS7135 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_754 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/msi/ms7260/Kconfig b/src/mainboard/msi/ms7260/Kconfig index efabd512f1..aa8b3a26d2 100644 --- a/src/mainboard/msi/ms7260/Kconfig +++ b/src/mainboard/msi/ms7260/Kconfig @@ -2,7 +2,6 @@ if BOARD_MSI_MS7260 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_AM2 select DIMM_DDR2 select NORTHBRIDGE_AMD_AMDK8 diff --git a/src/mainboard/msi/ms7260/ap_romstage.c b/src/mainboard/msi/ms7260/ap_romstage.c deleted file mode 100644 index f0a3dc4af5..0000000000 --- a/src/mainboard/msi/ms7260/ap_romstage.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * (Written by Yinghai Lu for AMD) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include -#include "lib/uart8259.c" - -#include "console/console.c" -#include -#include "northbridge/amd/amdk8/raminit.h" -#include "lib/delay.c" -/* #include "cpu/x86/lapic/boot_cpu.c" */ -#include "northbridge/amd/amdk8/reset_test.c" -#include "northbridge/amd/amdk8/debug.c" -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" -#include "northbridge/amd/amdk8/amdk8_f.h" -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; /* in CACHE */ - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); /* in RAM */ - struct node_core_id id; - - id = get_node_core_id_x(); - - /* FIXME: For USBDEBUG you need to make sure dbg_info gets - * assigned in AP. - */ - print_debug("CODE IN CACHE ON NODE:"); - print_debug_hex8(id.nodeid); - print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* Go back, but cannot use stack any more, because we only - * keep ret_addr and can not restore esp, and ebp. - */ - __asm__ __volatile__( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - : : "a" (ret_addr) - ); -} - -#include - -void x86_exception(struct eregs *info) -{ - while (1) - hlt(); -} diff --git a/src/mainboard/msi/ms9185/Kconfig b/src/mainboard/msi/ms9185/Kconfig index dc19d98cfc..54f76faef0 100644 --- a/src/mainboard/msi/ms9185/Kconfig +++ b/src/mainboard/msi/ms9185/Kconfig @@ -2,7 +2,6 @@ if BOARD_MSI_MS9185 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/msi/ms9282/Kconfig b/src/mainboard/msi/ms9282/Kconfig index d5716323a3..4869626900 100644 --- a/src/mainboard/msi/ms9282/Kconfig +++ b/src/mainboard/msi/ms9282/Kconfig @@ -2,7 +2,6 @@ if BOARD_MSI_MS9282 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/msi/ms9652_fam10/Kconfig b/src/mainboard/msi/ms9652_fam10/Kconfig index 852efd44be..a61d25b9bd 100644 --- a/src/mainboard/msi/ms9652_fam10/Kconfig +++ b/src/mainboard/msi/ms9652_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_MSI_MS9652_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/nec/powermate2000/Kconfig b/src/mainboard/nec/powermate2000/Kconfig index 82c2f9d613..6fddcc108a 100644 --- a/src/mainboard/nec/powermate2000/Kconfig +++ b/src/mainboard/nec/powermate2000/Kconfig @@ -20,7 +20,6 @@ if BOARD_NEC_POWERMATE_2000 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I82810 select SOUTHBRIDGE_INTEL_I82801AX diff --git a/src/mainboard/newisys/khepri/Kconfig b/src/mainboard/newisys/khepri/Kconfig index 6ee4bf094c..0cfc071cf2 100644 --- a/src/mainboard/newisys/khepri/Kconfig +++ b/src/mainboard/newisys/khepri/Kconfig @@ -2,7 +2,6 @@ if BOARD_NEWISYS_KHEPRI config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/nokia/ip530/Kconfig b/src/mainboard/nokia/ip530/Kconfig index 58d6d37290..bb726885e1 100644 --- a/src/mainboard/nokia/ip530/Kconfig +++ b/src/mainboard/nokia/ip530/Kconfig @@ -20,7 +20,6 @@ if BOARD_NOKIA_IP530 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_PGA370 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/nvidia/l1_2pvv/Kconfig b/src/mainboard/nvidia/l1_2pvv/Kconfig index 3eae434de4..b5c4a9a0b7 100644 --- a/src/mainboard/nvidia/l1_2pvv/Kconfig +++ b/src/mainboard/nvidia/l1_2pvv/Kconfig @@ -2,7 +2,6 @@ if BOARD_NVIDIA_L1_2PVV config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/nvidia/l1_2pvv/ap_romstage.c b/src/mainboard/nvidia/l1_2pvv/ap_romstage.c deleted file mode 100644 index 005de7bed6..0000000000 --- a/src/mainboard/nvidia/l1_2pvv/ap_romstage.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include -#include "lib/uart8250.c" -#include "arch/x86/lib/printk_init.c" -#include "console/vtxprintf.c" -#include "console/console.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - //FIXME: for USBDEBUG you need to make sure dbg_info get assigned in AP - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - * go back, but can not use stack any more, because we only keep - * ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} diff --git a/src/mainboard/pcengines/alix1c/Kconfig b/src/mainboard/pcengines/alix1c/Kconfig index 315b7edbf6..1d6786c1d7 100644 --- a/src/mainboard/pcengines/alix1c/Kconfig +++ b/src/mainboard/pcengines/alix1c/Kconfig @@ -2,7 +2,6 @@ if BOARD_PCENGINES_ALIX1C config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/pcengines/alix2d/Kconfig b/src/mainboard/pcengines/alix2d/Kconfig index 2343d70ed8..6ba4090266 100644 --- a/src/mainboard/pcengines/alix2d/Kconfig +++ b/src/mainboard/pcengines/alix2d/Kconfig @@ -2,7 +2,6 @@ if BOARD_PCENGINES_ALIX2D || BOARD_PCENGINES_ALIX6 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/rca/rm4100/Kconfig b/src/mainboard/rca/rm4100/Kconfig index ecbd2ccafc..975977f250 100644 --- a/src/mainboard/rca/rm4100/Kconfig +++ b/src/mainboard/rca/rm4100/Kconfig @@ -2,7 +2,6 @@ if BOARD_RCA_RM4100 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCBGA479 select NORTHBRIDGE_INTEL_I82830 select SOUTHBRIDGE_INTEL_I82801DX diff --git a/src/mainboard/roda/rk886ex/Kconfig b/src/mainboard/roda/rk886ex/Kconfig index 84a8543fc4..a37d6794c3 100644 --- a/src/mainboard/roda/rk886ex/Kconfig +++ b/src/mainboard/roda/rk886ex/Kconfig @@ -2,7 +2,6 @@ if BOARD_RODA_RK886EX config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCPGA478 select NORTHBRIDGE_INTEL_I945 select NORTHBRIDGE_INTEL_SUBTYPE_I945GM diff --git a/src/mainboard/roda/rk886ex/mainboard.c b/src/mainboard/roda/rk886ex/mainboard.c index 575aa9b24e..9504701d77 100644 --- a/src/mainboard/roda/rk886ex/mainboard.c +++ b/src/mainboard/roda/rk886ex/mainboard.c @@ -60,7 +60,7 @@ static void backlight_enable(void) #define BOOT_DISPLAY_EFP2 (1 << 6) #define BOOT_DISPLAY_LCD2 (1 << 7) -#if CONFIG_VGA_ROM_RUN +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { /* This int15 handler is Intel IGD. specific. Other chipsets need other @@ -124,7 +124,7 @@ static void mainboard_enable(device_t dev) /* Disable Dummy DCC -> GP45 = 1 */ outb(inb(0x60f) | (1 << 5), 0x60f); -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/roda/rk9/Kconfig b/src/mainboard/roda/rk9/Kconfig index 4bf90886c1..1f2e7b20a3 100644 --- a/src/mainboard/roda/rk9/Kconfig +++ b/src/mainboard/roda/rk9/Kconfig @@ -2,7 +2,6 @@ if BOARD_RODA_RK9 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_BGA956 select NORTHBRIDGE_INTEL_GM45 select SOUTHBRIDGE_INTEL_I82801IX diff --git a/src/mainboard/roda/rk9/smihandler.c b/src/mainboard/roda/rk9/smihandler.c index fe68c4b5e5..baa038ea0b 100644 --- a/src/mainboard/roda/rk9/smihandler.c +++ b/src/mainboard/roda/rk9/smihandler.c @@ -50,7 +50,7 @@ int mainboard_io_trap_handler(int smif) return 1; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { if (gpi_sts & (1 << 1)) { printk(BIOS_DEBUG, "EC/SMI\n"); diff --git a/src/mainboard/samsung/lumpy/Kconfig b/src/mainboard/samsung/lumpy/Kconfig index a169726e35..b0776cd481 100644 --- a/src/mainboard/samsung/lumpy/Kconfig +++ b/src/mainboard/samsung/lumpy/Kconfig @@ -2,9 +2,9 @@ if BOARD_SAMSUNG_LUMPY config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select BOARD_ROMSIZE_KB_8192 select CHROMEOS + select CHROMEOS_VBNV_CMOS select CPU_INTEL_SOCKET_RPGA989 select EC_SMSC_MEC1308 select EXTERNAL_MRC_BLOB diff --git a/src/mainboard/samsung/lumpy/chromeos.c b/src/mainboard/samsung/lumpy/chromeos.c index afbdeeb9d0..b708fa3582 100644 --- a/src/mainboard/samsung/lumpy/chromeos.c +++ b/src/mainboard/samsung/lumpy/chromeos.c @@ -39,8 +39,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 void fill_lb_gpios(struct lb_gpios *gpios) { diff --git a/src/mainboard/samsung/lumpy/mainboard.c b/src/mainboard/samsung/lumpy/mainboard.c index be9a0464e5..c1749f7026 100644 --- a/src/mainboard/samsung/lumpy/mainboard.c +++ b/src/mainboard/samsung/lumpy/mainboard.c @@ -49,111 +49,15 @@ void mainboard_suspend_resume(void) send_ec_command(EC_ACPI_ENABLE); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { int res=0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, X86_EAX & 0xffff); + __func__, X86_AX); - switch(X86_EAX & 0xffff) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - * 0 = video bios default - */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffffff00; - X86_ECX |= 0x00; - res = 1; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0001; - res = 1; - break; - case 0x5f70: - switch ((X86_ECX >> 8) & 0xff) { - case 0: - /* Get Mux */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 1: - /* Set Mux */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 2: - /* Get SG/Non-SG mode */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - default: - /* FIXME: Interrupt was not handled, but return success? */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((X86_ECX >> 8) & 0xff)); - return 1; - } - break; - - default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - X86_EAX & 0xffff); - break; - } - return res; -} -#endif - -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, X86_AX, X86_BX, X86_CX, X86_DX); - - switch (X86_AX) { + switch(X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -164,6 +68,7 @@ static int int15_handler(void) */ X86_AX = 0x005f; X86_CL = 0x00; + res = 1; break; case 0x5f35: /* @@ -179,6 +84,7 @@ static int int15_handler(void) */ X86_AX = 0x005f; X86_CX = 0x0000; + res = 1; break; case 0x5f51: /* @@ -189,44 +95,42 @@ static int int15_handler(void) * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ X86_AX = 0x005f; - X86_CX = 1; + X86_CX = 0x0001; + res = 1; break; case 0x5f70: switch (X86_CH) { case 0: /* Get Mux */ - printk(BIOS_DEBUG, "Get Mux\n"); X86_AX = 0x005f; - X86_CL = 0; + X86_CX = 0x0000; + res = 1; break; case 1: - printk(BIOS_DEBUG, "Set Mux\n"); /* Set Mux */ - X86_AX = 0x005f; - X86_CX = 0; + X86_EAX = 0x005f; + X86_ECX = 0x0000; + res = 1; break; case 2: - printk(BIOS_DEBUG, "Get SG Mode\n"); /* Get SG/Non-SG mode */ X86_AX = 0x005f; - X86_CX = 0; + X86_CX = 0x0000; + res = 1; break; default: - /* Interrupt was not handled */ + /* FIXME: Interrupt was not handled, but return success? */ printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", X86_CH); - return 0; + return 1; } break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - X86_AX); - return 0; - } - /* Interrupt handled */ - return 1; + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; } #endif @@ -302,7 +206,7 @@ static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; dev->ops->get_smbios_data = lumpy_onboard_smbios_data; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index b941021f9e..2bc5f34602 100644 --- a/src/mainboard/samsung/lumpy/romstage.c +++ b/src/mainboard/samsung/lumpy/romstage.c @@ -137,15 +137,12 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); struct pei_data pei_data = { .mchbar = DEFAULT_MCHBAR, @@ -196,9 +193,7 @@ void main(unsigned long bist) spd_blob *spd_data; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -311,14 +306,13 @@ void main(unsigned long bist) post_code(0x39); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3a); /* Perform some initialization that must run before stage2 */ early_pch_init(); @@ -362,15 +356,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/samsung/lumpy/smihandler.c b/src/mainboard/samsung/lumpy/smihandler.c index 9306a02118..417ccd87fb 100644 --- a/src/mainboard/samsung/lumpy/smihandler.c +++ b/src/mainboard/samsung/lumpy/smihandler.c @@ -70,7 +70,7 @@ static u8 mainboard_smi_ec(void) return cmd; } -void mainboard_smi_gpi(u16 gpi_sts) +void mainboard_smi_gpi(u32 gpi_sts) { if (gpi_sts & (1 << EC_SMI_GPI)) { /* Process all pending EC requests */ diff --git a/src/mainboard/samsung/stumpy/Kconfig b/src/mainboard/samsung/stumpy/Kconfig index fa7d03d0b9..853cb84fed 100644 --- a/src/mainboard/samsung/stumpy/Kconfig +++ b/src/mainboard/samsung/stumpy/Kconfig @@ -2,9 +2,9 @@ if BOARD_SAMSUNG_STUMPY config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select BOARD_ROMSIZE_KB_8192 select CHROMEOS + select CHROMEOS_VBNV_CMOS select CPU_INTEL_SOCKET_RPGA989 select EXTERNAL_MRC_BLOB select GFXUMA @@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select SOUTHBRIDGE_INTEL_BD82X6X select SUPERIO_ITE_IT8772F select EARLY_CBMEM_INIT + select PHYSICAL_REC_SWITCH config MAINBOARD_DIR string diff --git a/src/mainboard/samsung/stumpy/chromeos.c b/src/mainboard/samsung/stumpy/chromeos.c index e639fd3cbd..c141083ed4 100644 --- a/src/mainboard/samsung/stumpy/chromeos.c +++ b/src/mainboard/samsung/stumpy/chromeos.c @@ -36,8 +36,6 @@ #include #define GPIO_COUNT 6 -#define ACTIVE_LOW 0 -#define ACTIVE_HIGH 1 void fill_lb_gpios(struct lb_gpios *gpios) { diff --git a/src/mainboard/samsung/stumpy/mainboard.c b/src/mainboard/samsung/stumpy/mainboard.c index cbf5af76e6..30612db271 100644 --- a/src/mainboard/samsung/stumpy/mainboard.c +++ b/src/mainboard/samsung/stumpy/mainboard.c @@ -42,15 +42,15 @@ void mainboard_suspend_resume(void) outb(0xcb, 0xb2); } -#if defined(CONFIG_PCI_OPTION_ROM_RUN_REALMODE) && CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { int res=0; printk(BIOS_DEBUG, "%s: INT15 function %04x!\n", - __func__, X86_EAX & 0xffff); + __func__, X86_AX); - switch(X86_EAX & 0xffff) { + switch(X86_AX) { case 0x5f34: /* * Set Panel Fitting Hook: @@ -59,103 +59,9 @@ static int int15_handler(void) * bit 0 = Centering (do not set with bit1 or bit2) * 0 = video bios default */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffffff00; - X86_ECX |= 0x01; - res = 1; - break; - case 0x5f35: - /* - * Boot Display Device Hook: - * bit 0 = CRT - * bit 1 = TV (eDP) * - * bit 2 = EFP * - * bit 3 = LFP - * bit 4 = CRT2 - * bit 5 = TV2 (eDP) * - * bit 6 = EFP2 * - * bit 7 = LFP2 - */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 0x5f51: - /* - * Hook to select active LFP configuration: - * 00h = No LVDS, VBIOS does not enable LVDS - * 01h = Int-LVDS, LFP driven by integrated LVDS decoder - * 02h = SVDO-LVDS, LFP driven by SVDO decoder - * 03h = eDP, LFP Driven by Int-DisplayPort encoder - */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0003; - res = 1; - break; - case 0x5f70: - switch ((X86_ECX >> 8) & 0xff) { - case 0: - /* Get Mux */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 1: - /* Set Mux */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - case 2: - /* Get SG/Non-SG mode */ - X86_EAX &= 0xffff0000; - X86_EAX |= 0x005f; - X86_ECX &= 0xffff0000; - X86_ECX |= 0x0000; - res = 1; - break; - default: - /* FIXME: Interrupt was not handled, but return sucess? */ - printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", - ((X86_ECX >> 8) & 0xff)); - return 1; - } - break; - - default: - printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", - X86_EAX & 0xffff); - break; - } - return res; -} -#endif - -#if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL) && CONFIG_PCI_OPTION_ROM_RUN_YABEL -static int int15_handler(void) -{ - printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n", - __func__, X86_AX, X86_BX, X86_CX, X86_DX); - - switch (X86_AX) { - case 0x5f34: - /* - * Set Panel Fitting Hook: - * bit 2 = Graphics Stretching - * bit 1 = Text Stretching - * bit 0 = Centering (do not set with bit1 or bit2) - */ X86_AX = 0x005f; - X86_CX = 0x0001; + X86_CL = 0x01; + res = 1; break; case 0x5f35: /* @@ -171,6 +77,7 @@ static int int15_handler(void) */ X86_AX = 0x005f; X86_CX = 0x0000; + res = 1; break; case 0x5f51: /* @@ -181,22 +88,42 @@ static int int15_handler(void) * 03h = eDP, LFP Driven by Int-DisplayPort encoder */ X86_AX = 0x005f; - X86_CX = 3; + X86_CX = 0x0003; + res = 1; break; case 0x5f70: - /* Unknown */ - X86_AX = 0x005f; - X86_CX = 0; + switch (X86_CH) { + case 0: + /* Get Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + X86_AX = 0x005f; + X86_CX = 0x0000; + res = 1; + break; + default: + /* FIXME: Interrupt was not handled, but return sucess? */ + printk(BIOS_DEBUG, "Unknown INT15 5f70 function: 0x%02x\n", + X86_CH); + return 1; + } break; - default: - /* Interrupt was not handled */ - printk(BIOS_DEBUG, "Unknown INT15 function: 0x%04x\n", - X86_AX); - return 0; - } - /* Interrupt handled */ - return 1; + default: + printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", X86_AX); + break; + } + return res; } #endif @@ -220,7 +147,7 @@ static void verb_setup(void) static void mainboard_enable(device_t dev) { -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL || CONFIG_PCI_OPTION_ROM_RUN_REALMODE +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/samsung/stumpy/romstage.c b/src/mainboard/samsung/stumpy/romstage.c index dda3ab5301..523d5c00ab 100644 --- a/src/mainboard/samsung/stumpy/romstage.c +++ b/src/mainboard/samsung/stumpy/romstage.c @@ -173,15 +173,13 @@ void main(unsigned long bist) u32 pm1_cnt; u16 pm1_sts; -#if CONFIG_COLLECT_TIMESTAMPS - tsc_t start_romstage_time; - tsc_t before_dram_time; - tsc_t after_dram_time; - tsc_t base_time = { - .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), - .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) - }; -#endif + uint64_t start_romstage_time; + uint64_t before_dram_time; + uint64_t after_dram_time; + uint64_t base_time = + (uint64_t)pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) << 32 || + pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc); + struct pei_data pei_data = { mchbar: DEFAULT_MCHBAR, dmibar: DEFAULT_DMIBAR, @@ -224,9 +222,7 @@ void main(unsigned long bist) }, }; -#if CONFIG_COLLECT_TIMESTAMPS - start_romstage_time = rdtsc(); -#endif + start_romstage_time = timestamp_get(); if (bist == 0) enable_lapic(); @@ -316,14 +312,13 @@ void main(unsigned long bist) post_code(0x39); pei_data.boot_mode = boot_mode; -#if CONFIG_COLLECT_TIMESTAMPS - before_dram_time = rdtsc(); -#endif + + before_dram_time = timestamp_get(); + sdram_initialize(&pei_data); -#if CONFIG_COLLECT_TIMESTAMPS - after_dram_time = rdtsc(); -#endif + after_dram_time = timestamp_get(); + post_code(0x3a); /* Perform some initialization that must run before stage2 */ early_pch_init(); @@ -366,15 +361,10 @@ void main(unsigned long bist) #if CONFIG_CHROMEOS init_chromeos(boot_mode); #endif -#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); timestamp_add(TS_AFTER_INITRAM, after_dram_time ); timestamp_add_now(TS_END_ROMSTAGE); -#endif -#if CONFIG_CONSOLE_CBMEM - /* Keep this the last thing this function does. */ - cbmemc_reinit(); -#endif } diff --git a/src/mainboard/siemens/sitemp_g1p1/Kconfig b/src/mainboard/siemens/sitemp_g1p1/Kconfig index 81ba5e7320..6e418b2bf7 100644 --- a/src/mainboard/siemens/sitemp_g1p1/Kconfig +++ b/src/mainboard/siemens/sitemp_g1p1/Kconfig @@ -2,7 +2,6 @@ if BOARD_SIEMENS_SITEMP_G1P1 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_S1G1 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/soyo/sy-6ba-plus-iii/Kconfig b/src/mainboard/soyo/sy-6ba-plus-iii/Kconfig index 096aa7cd6c..a268bad992 100644 --- a/src/mainboard/soyo/sy-6ba-plus-iii/Kconfig +++ b/src/mainboard/soyo/sy-6ba-plus-iii/Kconfig @@ -20,7 +20,6 @@ if BOARD_SOYO_SY_6BA_PLUS_III config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/sunw/ultra40/Kconfig b/src/mainboard/sunw/ultra40/Kconfig index 491e3fa5a5..ce77109b64 100644 --- a/src/mainboard/sunw/ultra40/Kconfig +++ b/src/mainboard/sunw/ultra40/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUNW_ULTRA40 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/supermicro/h8dme/Kconfig b/src/mainboard/supermicro/h8dme/Kconfig index 221ccb2dbf..de527fabd5 100644 --- a/src/mainboard/supermicro/h8dme/Kconfig +++ b/src/mainboard/supermicro/h8dme/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_H8DME config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED @@ -15,7 +14,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy select HAVE_OPTION_TABLE select HAVE_PIRQ_TABLE select HAVE_MP_TABLE - #select AP_CODE_IN_CAR select LIFT_BSP_APIC_ID select BOARD_ROMSIZE_KB_1024 select RAMINIT_SYSINFO diff --git a/src/mainboard/supermicro/h8dme/ap_romstage.c b/src/mainboard/supermicro/h8dme/ap_romstage.c deleted file mode 100644 index ed2d16a781..0000000000 --- a/src/mainboard/supermicro/h8dme/ap_romstage.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include - -#include "console/console.c" -#include "lib/uart8250.c" -#include "console/vtxprintf.c" -#include "./arch/x86/lib/printk_init.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -//#include "cpu/x86/lapic/boot_cpu.c" -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -static inline unsigned get_nodes(void) -{ - return ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1; -} - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - * go back, but can not use stack any more, because we only keep ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - diff --git a/src/mainboard/supermicro/h8dmr/Kconfig b/src/mainboard/supermicro/h8dmr/Kconfig index 3cc296a985..3c569a3086 100644 --- a/src/mainboard/supermicro/h8dmr/Kconfig +++ b/src/mainboard/supermicro/h8dmr/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_H8DMR config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/supermicro/h8dmr/ap_romstage.c b/src/mainboard/supermicro/h8dmr/ap_romstage.c deleted file mode 100644 index 8008bb25c9..0000000000 --- a/src/mainboard/supermicro/h8dmr/ap_romstage.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include - -#include "console/console.c" -#include "lib/uart8250.c" -#include "console/vtxprintf.c" -#include "./arch/x86/lib/printk_init.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -//#include "cpu/x86/lapic/boot_cpu.c" -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -static inline unsigned get_nodes(void) -{ - return ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60)>>4) & 7) + 1; -} - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - go back, but can not use stack any more, because we only keep ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); - - - -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - - diff --git a/src/mainboard/supermicro/h8dmr_fam10/Kconfig b/src/mainboard/supermicro/h8dmr_fam10/Kconfig index 94b56eaa1d..4032e27b37 100644 --- a/src/mainboard/supermicro/h8dmr_fam10/Kconfig +++ b/src/mainboard/supermicro/h8dmr_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_H8DMR_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/supermicro/h8qgi/Kconfig b/src/mainboard/supermicro/h8qgi/Kconfig index cd4fb69d1b..e906817bcd 100644 --- a/src/mainboard/supermicro/h8qgi/Kconfig +++ b/src/mainboard/supermicro/h8qgi/Kconfig @@ -21,7 +21,6 @@ if BOARD_SUPERMICRO_H8QGI config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15 select CPU_AMD_SOCKET_G34 select NORTHBRIDGE_AMD_AGESA_FAMILY15_ROOT_COMPLEX diff --git a/src/mainboard/supermicro/h8qgi/get_bus_conf.c b/src/mainboard/supermicro/h8qgi/get_bus_conf.c index 7682eec927..817dd09e25 100644 --- a/src/mainboard/supermicro/h8qgi/get_bus_conf.c +++ b/src/mainboard/supermicro/h8qgi/get_bus_conf.c @@ -63,7 +63,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/supermicro/h8qgi/romstage.c b/src/mainboard/supermicro/h8qgi/romstage.c index 45422bbfbb..0d251132f5 100644 --- a/src/mainboard/supermicro/h8qgi/romstage.c +++ b/src/mainboard/supermicro/h8qgi/romstage.c @@ -128,7 +128,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) print_debug("done\n"); post_code(0x51); - copy_and_run(0); + copy_and_run(); /* We will not return, Should never see this message and post code. */ print_debug("should not be here -\n"); diff --git a/src/mainboard/supermicro/h8qme_fam10/Kconfig b/src/mainboard/supermicro/h8qme_fam10/Kconfig index 6ba6130119..8a30071fcb 100644 --- a/src/mainboard/supermicro/h8qme_fam10/Kconfig +++ b/src/mainboard/supermicro/h8qme_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_H8QME_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/supermicro/h8scm/Kconfig b/src/mainboard/supermicro/h8scm/Kconfig index 4833bed311..b860f9ecb9 100644 --- a/src/mainboard/supermicro/h8scm/Kconfig +++ b/src/mainboard/supermicro/h8scm/Kconfig @@ -21,7 +21,6 @@ if BOARD_SUPERMICRO_H8SCM config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15 select CPU_AMD_SOCKET_C32 select NORTHBRIDGE_AMD_AGESA_FAMILY15_ROOT_COMPLEX diff --git a/src/mainboard/supermicro/h8scm/get_bus_conf.c b/src/mainboard/supermicro/h8scm/get_bus_conf.c index 3dc8471656..b2cd1a2cab 100644 --- a/src/mainboard/supermicro/h8scm/get_bus_conf.c +++ b/src/mainboard/supermicro/h8scm/get_bus_conf.c @@ -63,7 +63,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/supermicro/h8scm/romstage.c b/src/mainboard/supermicro/h8scm/romstage.c index 3219fdafe5..5dccf78653 100644 --- a/src/mainboard/supermicro/h8scm/romstage.c +++ b/src/mainboard/supermicro/h8scm/romstage.c @@ -136,7 +136,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) print_debug("done\n"); post_code(0x51); - copy_and_run(0); + copy_and_run(); /* We will not return, Should never see this message and post code. */ print_debug("should not be here -\n"); diff --git a/src/mainboard/supermicro/h8scm_fam10/Kconfig b/src/mainboard/supermicro/h8scm_fam10/Kconfig index 5e28aeade0..ce64b231d6 100644 --- a/src/mainboard/supermicro/h8scm_fam10/Kconfig +++ b/src/mainboard/supermicro/h8scm_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_H9SCM_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_C32_NON_AGESA select DIMM_DDR3 select DIMM_REGISTERED diff --git a/src/mainboard/supermicro/x6dai_g/Kconfig b/src/mainboard/supermicro/x6dai_g/Kconfig index 90a800cee0..4999320d68 100644 --- a/src/mainboard/supermicro/x6dai_g/Kconfig +++ b/src/mainboard/supermicro/x6dai_g/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X6DAI_G config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7525 select SOUTHBRIDGE_INTEL_ESB6300 diff --git a/src/mainboard/supermicro/x6dhe_g/Kconfig b/src/mainboard/supermicro/x6dhe_g/Kconfig index 03bb0a8508..b6001c5c44 100644 --- a/src/mainboard/supermicro/x6dhe_g/Kconfig +++ b/src/mainboard/supermicro/x6dhe_g/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X6DHE_G config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7520 select SOUTHBRIDGE_INTEL_ESB6300 diff --git a/src/mainboard/supermicro/x6dhe_g2/Kconfig b/src/mainboard/supermicro/x6dhe_g2/Kconfig index 397087cc36..022cbfe086 100644 --- a/src/mainboard/supermicro/x6dhe_g2/Kconfig +++ b/src/mainboard/supermicro/x6dhe_g2/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X6DHE_G2 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7520 select SOUTHBRIDGE_INTEL_I82801EX diff --git a/src/mainboard/supermicro/x6dhr_ig/Kconfig b/src/mainboard/supermicro/x6dhr_ig/Kconfig index 0b25fcdb94..e02b2dda50 100644 --- a/src/mainboard/supermicro/x6dhr_ig/Kconfig +++ b/src/mainboard/supermicro/x6dhr_ig/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X6DHR_IG config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7520 select SOUTHBRIDGE_INTEL_I82801EX diff --git a/src/mainboard/supermicro/x6dhr_ig2/Kconfig b/src/mainboard/supermicro/x6dhr_ig2/Kconfig index 70df01ae34..9c8e4a6900 100644 --- a/src/mainboard/supermicro/x6dhr_ig2/Kconfig +++ b/src/mainboard/supermicro/x6dhr_ig2/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X6DHR_IG2 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7520 select SOUTHBRIDGE_INTEL_I82801EX diff --git a/src/mainboard/supermicro/x7db8/Kconfig b/src/mainboard/supermicro/x7db8/Kconfig index 47fb4b94c1..e9deda8882 100644 --- a/src/mainboard/supermicro/x7db8/Kconfig +++ b/src/mainboard/supermicro/x7db8/Kconfig @@ -2,7 +2,6 @@ if BOARD_SUPERMICRO_X7DB8 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_LGA771 select SOUTHBRIDGE_INTEL_I3100 select NORTHBRIDGE_INTEL_I5000 diff --git a/src/mainboard/technexion/tim5690/Kconfig b/src/mainboard/technexion/tim5690/Kconfig index d1e41c2502..4991a650de 100644 --- a/src/mainboard/technexion/tim5690/Kconfig +++ b/src/mainboard/technexion/tim5690/Kconfig @@ -2,7 +2,6 @@ if BOARD_TECHNEXION_TIM5690 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_S1G1 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/technexion/tim8690/Kconfig b/src/mainboard/technexion/tim8690/Kconfig index 691ebe6318..5a42b88387 100644 --- a/src/mainboard/technexion/tim8690/Kconfig +++ b/src/mainboard/technexion/tim8690/Kconfig @@ -2,7 +2,6 @@ if BOARD_TECHNEXION_TIM8690 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_S1G1 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/technologic/ts5300/Kconfig b/src/mainboard/technologic/ts5300/Kconfig index 8def16dc8e..0006fd7903 100644 --- a/src/mainboard/technologic/ts5300/Kconfig +++ b/src/mainboard/technologic/ts5300/Kconfig @@ -2,7 +2,6 @@ if BOARD_TECHNOLOGIC_TS5300 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SC520 select ROMCC select HAVE_OPTION_TABLE diff --git a/src/mainboard/televideo/tc7020/Kconfig b/src/mainboard/televideo/tc7020/Kconfig index ab41e5b921..6d77f5901f 100644 --- a/src/mainboard/televideo/tc7020/Kconfig +++ b/src/mainboard/televideo/tc7020/Kconfig @@ -20,7 +20,6 @@ if BOARD_TELEVIDEO_TC7020 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX1 select NORTHBRIDGE_AMD_GX1 select SOUTHBRIDGE_AMD_CS5530 diff --git a/src/mainboard/thomson/ip1000/Kconfig b/src/mainboard/thomson/ip1000/Kconfig index b1988ddae6..971c41c475 100644 --- a/src/mainboard/thomson/ip1000/Kconfig +++ b/src/mainboard/thomson/ip1000/Kconfig @@ -2,7 +2,6 @@ if BOARD_THOMSON_IP1000 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MFCBGA479 select NORTHBRIDGE_INTEL_I82830 select SOUTHBRIDGE_INTEL_I82801DX diff --git a/src/mainboard/thomson/ip1000/mainboard.c b/src/mainboard/thomson/ip1000/mainboard.c index 909c9f61f8..a23c6db872 100644 --- a/src/mainboard/thomson/ip1000/mainboard.c +++ b/src/mainboard/thomson/ip1000/mainboard.c @@ -21,7 +21,7 @@ #include #include #include -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN #include #endif #include @@ -86,7 +86,7 @@ static void flash_gpios(void) } -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN static int int15_handler(void) { #define BOOT_DISPLAY_DEFAULT 0 @@ -141,7 +141,7 @@ static void mainboard_init(device_t dev) static void mainboard_enable(device_t dev) { dev->ops->init = mainboard_init; -#if CONFIG_PCI_OPTION_ROM_RUN_YABEL +#if CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN /* Install custom int15 handler for VGA OPROM */ mainboard_interrupt_handlers(0x15, &int15_handler); #endif diff --git a/src/mainboard/traverse/geos/Kconfig b/src/mainboard/traverse/geos/Kconfig index 3139d7dc1b..945ab0975b 100644 --- a/src/mainboard/traverse/geos/Kconfig +++ b/src/mainboard/traverse/geos/Kconfig @@ -2,7 +2,6 @@ if BOARD_TRAVERSE_GEOS config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/tyan/s1846/Kconfig b/src/mainboard/tyan/s1846/Kconfig index b4e6c9216c..e491d3fc4e 100644 --- a/src/mainboard/tyan/s1846/Kconfig +++ b/src/mainboard/tyan/s1846/Kconfig @@ -20,7 +20,6 @@ if BOARD_TYAN_S1846 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SLOT_1 select NORTHBRIDGE_INTEL_I440BX select SOUTHBRIDGE_INTEL_I82371EB diff --git a/src/mainboard/tyan/s2735/Kconfig b/src/mainboard/tyan/s2735/Kconfig index f908908b09..a13db8bb48 100644 --- a/src/mainboard/tyan/s2735/Kconfig +++ b/src/mainboard/tyan/s2735/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2735 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_INTEL_SOCKET_MPGA604 select NORTHBRIDGE_INTEL_E7501 select SOUTHBRIDGE_INTEL_I82870 diff --git a/src/mainboard/tyan/s2850/Kconfig b/src/mainboard/tyan/s2850/Kconfig index 2d0742308c..73d2f181a0 100644 --- a/src/mainboard/tyan/s2850/Kconfig +++ b/src/mainboard/tyan/s2850/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2850 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2875/Kconfig b/src/mainboard/tyan/s2875/Kconfig index d9e7bac010..ecf9a7b1a6 100644 --- a/src/mainboard/tyan/s2875/Kconfig +++ b/src/mainboard/tyan/s2875/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2875 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2880/Kconfig b/src/mainboard/tyan/s2880/Kconfig index 93dadac2d2..4b24baf317 100644 --- a/src/mainboard/tyan/s2880/Kconfig +++ b/src/mainboard/tyan/s2880/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2880 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2881/Kconfig b/src/mainboard/tyan/s2881/Kconfig index 2f10a61b43..2a5bac1e04 100644 --- a/src/mainboard/tyan/s2881/Kconfig +++ b/src/mainboard/tyan/s2881/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2881 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2882/Kconfig b/src/mainboard/tyan/s2882/Kconfig index 145fdfcafd..4a53f38e25 100644 --- a/src/mainboard/tyan/s2882/Kconfig +++ b/src/mainboard/tyan/s2882/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2882 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2885/Kconfig b/src/mainboard/tyan/s2885/Kconfig index 595d7e0815..01797ae1ea 100644 --- a/src/mainboard/tyan/s2885/Kconfig +++ b/src/mainboard/tyan/s2885/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2885 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2891/Kconfig b/src/mainboard/tyan/s2891/Kconfig index f30e1406c0..a7bf8a796e 100644 --- a/src/mainboard/tyan/s2891/Kconfig +++ b/src/mainboard/tyan/s2891/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2891 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2892/Kconfig b/src/mainboard/tyan/s2892/Kconfig index 3fab23a8a1..437f8966b1 100644 --- a/src/mainboard/tyan/s2892/Kconfig +++ b/src/mainboard/tyan/s2892/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2892 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2895/Kconfig b/src/mainboard/tyan/s2895/Kconfig index 5037ca82f0..0a6a26ec28 100644 --- a/src/mainboard/tyan/s2895/Kconfig +++ b/src/mainboard/tyan/s2895/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2895 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s2912/Kconfig b/src/mainboard/tyan/s2912/Kconfig index f653478756..e579804e88 100644 --- a/src/mainboard/tyan/s2912/Kconfig +++ b/src/mainboard/tyan/s2912/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2912 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/tyan/s2912/ap_romstage.c b/src/mainboard/tyan/s2912/ap_romstage.c deleted file mode 100644 index e22d2a5af4..0000000000 --- a/src/mainboard/tyan/s2912/ap_romstage.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 AMD - * Written by Yinghai Lu for AMD. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0 - -#include -#include -#include -#include -#include -#include -#include -#include "console/console.c" - -#include -#include "northbridge/amd/amdk8/raminit.h" - -#include "lib/delay.c" - -//#include "cpu/x86/lapic/boot_cpu.c" -#include "northbridge/amd/amdk8/reset_test.c" - -#include "northbridge/amd/amdk8/debug.c" - -#include "southbridge/nvidia/mcp55/mcp55_early_ctrl.c" - -#include "northbridge/amd/amdk8/amdk8_f.h" - -#include "cpu/x86/mtrr.h" -#include "cpu/amd/mtrr.h" -#include "cpu/x86/tsc.h" - -#include "northbridge/amd/amdk8/amdk8_f_pci.c" -#include "northbridge/amd/amdk8/raminit_f_dqs.c" - -#include "cpu/amd/dualcore/dualcore.c" - -void hardwaremain(int ret_addr) -{ - struct sys_info *sysinfo = &sysinfo_car; // in CACHE - struct sys_info *sysinfox = ((CONFIG_RAMTOP) - sizeof(*sysinfox)); // in RAM - - struct node_core_id id; - - id = get_node_core_id_x(); - - //FIXME: for USBDEBUG you need to make sure dbg_info get assigned in AP - print_debug("CODE IN CACHE ON NODE:"); print_debug_hex8(id.nodeid); print_debug("\n"); - - train_ram(id.nodeid, sysinfo, sysinfox); - - /* - go back, but can not use stack any more, because we only keep ret_addr and can not restore esp, and ebp - */ - - __asm__ volatile ( - "movl %0, %%edi\n\t" - "jmp *%%edi\n\t" - :: "a"(ret_addr) - ); -} - -#include - -void x86_exception(struct eregs *info) -{ - do { - hlt(); - } while(1); -} - diff --git a/src/mainboard/tyan/s2912_fam10/Kconfig b/src/mainboard/tyan/s2912_fam10/Kconfig index 085148fcd3..b85cba96de 100644 --- a/src/mainboard/tyan/s2912_fam10/Kconfig +++ b/src/mainboard/tyan/s2912_fam10/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S2912_FAM10 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_F_1207 select DIMM_DDR2 select DIMM_REGISTERED diff --git a/src/mainboard/tyan/s4880/Kconfig b/src/mainboard/tyan/s4880/Kconfig index 5040a6a3ce..d338c0548f 100644 --- a/src/mainboard/tyan/s4880/Kconfig +++ b/src/mainboard/tyan/s4880/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S4880 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s4882/Kconfig b/src/mainboard/tyan/s4882/Kconfig index ee67bae92b..9d5576171e 100644 --- a/src/mainboard/tyan/s4882/Kconfig +++ b/src/mainboard/tyan/s4882/Kconfig @@ -2,7 +2,6 @@ if BOARD_TYAN_S4882 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_SOCKET_940 select NORTHBRIDGE_AMD_AMDK8 select NORTHBRIDGE_AMD_AMDK8_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s8226/Kconfig b/src/mainboard/tyan/s8226/Kconfig index e2fe1e8e6e..76e8568182 100644 --- a/src/mainboard/tyan/s8226/Kconfig +++ b/src/mainboard/tyan/s8226/Kconfig @@ -21,7 +21,6 @@ if BOARD_TYAN_S8226 config BOARD_SPECIFIC_OPTIONS def_bool y - select ARCH_X86 select CPU_AMD_AGESA_FAMILY15 select CPU_AMD_SOCKET_C32 select NORTHBRIDGE_AMD_AGESA_FAMILY15_ROOT_COMPLEX diff --git a/src/mainboard/tyan/s8226/get_bus_conf.c b/src/mainboard/tyan/s8226/get_bus_conf.c index 5c119f2657..d45e1ad354 100644 --- a/src/mainboard/tyan/s8226/get_bus_conf.c +++ b/src/mainboard/tyan/s8226/get_bus_conf.c @@ -63,7 +63,7 @@ void get_bus_conf(void) * call. The logically correct place to call AmdInitLate is after PCI scan is done, * after the decision about S3 resume is made, and before the system tables are * written into RAM. The routine that is responsible for writing the tables is - * "write_tables", called near the end of "hardwaremain". There is no platform + * "write_tables", called near the end of "main". There is no platform * specific entry point between the S3 resume decision point and the call to * "write_tables", and the next platform specific entry points are the calls to * the ACPI table write functions. The first of ose would seem to be the right diff --git a/src/mainboard/tyan/s8226/romstage.c b/src/mainboard/tyan/s8226/romstage.c index ee16ceb57f..b4f9523d5c 100644 --- a/src/mainboard/tyan/s8226/romstage.c +++ b/src/mainboard/tyan/s8226/romstage.c @@ -136,7 +136,7 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx) post_code(0x51); setup_i8259 (); setup_i8254 (); - copy_and_run(0); + copy_and_run(); /* We will not return, Should never see this message and post code. */ print_debug("should not be here -\n"); diff --git a/src/mainboard/via/epia-cn/Kconfig b/src/mainboard/via/epia-cn/Kconfig index e7920e77aa..266e7e9d1f 100644 --- a/src/mainboard/via/epia-cn/Kconfig +++ b/src/mainboard/via/epia-cn/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_EPIA_CN config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_CN700 select SOUTHBRIDGE_VIA_VT8237R diff --git a/src/mainboard/via/epia-m/Kconfig b/src/mainboard/via/epia-m/Kconfig index 634e8b1529..6b5c340b75 100644 --- a/src/mainboard/via/epia-m/Kconfig +++ b/src/mainboard/via/epia-m/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_EPIA_M config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C3 select NORTHBRIDGE_VIA_VT8623 select SOUTHBRIDGE_VIA_VT8235 diff --git a/src/mainboard/via/epia-m700/Kconfig b/src/mainboard/via/epia-m700/Kconfig index 2fff8e0722..78c6069483 100644 --- a/src/mainboard/via/epia-m700/Kconfig +++ b/src/mainboard/via/epia-m700/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_EPIA_M700 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_VX800 select SUPERIO_WINBOND_W83697HF diff --git a/src/mainboard/via/epia-n/Kconfig b/src/mainboard/via/epia-n/Kconfig index 2b327b708d..3ea6878df9 100644 --- a/src/mainboard/via/epia-n/Kconfig +++ b/src/mainboard/via/epia-n/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_EPIA_N config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C3 select NORTHBRIDGE_VIA_CN400 select SOUTHBRIDGE_VIA_VT8237R diff --git a/src/mainboard/via/epia/Kconfig b/src/mainboard/via/epia/Kconfig index 60ce4f593e..7ee1ed8dcd 100644 --- a/src/mainboard/via/epia/Kconfig +++ b/src/mainboard/via/epia/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_EPIA config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C3 select NORTHBRIDGE_VIA_VT8601 select SOUTHBRIDGE_VIA_VT8231 diff --git a/src/mainboard/via/pc2500e/Kconfig b/src/mainboard/via/pc2500e/Kconfig index 70aa8d75fb..97f20880b8 100644 --- a/src/mainboard/via/pc2500e/Kconfig +++ b/src/mainboard/via/pc2500e/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_PC2500E config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_CN700 select SOUTHBRIDGE_VIA_VT8237R diff --git a/src/mainboard/via/vt8454c/Kconfig b/src/mainboard/via/vt8454c/Kconfig index 1f5e95a696..ef608f584e 100644 --- a/src/mainboard/via/vt8454c/Kconfig +++ b/src/mainboard/via/vt8454c/Kconfig @@ -2,7 +2,6 @@ if BOARD_VIA_VT8454C config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_VIA_C7 select NORTHBRIDGE_VIA_CX700 select SUPERIO_VIA_VT1211 diff --git a/src/mainboard/winent/pl6064/Kconfig b/src/mainboard/winent/pl6064/Kconfig index 7db7de5791..3a36f29393 100644 --- a/src/mainboard/winent/pl6064/Kconfig +++ b/src/mainboard/winent/pl6064/Kconfig @@ -2,7 +2,6 @@ if BOARD_WINENT_PL6064 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_LX select NORTHBRIDGE_AMD_LX select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/mainboard/wyse/s50/Kconfig b/src/mainboard/wyse/s50/Kconfig index d8d2628f48..fbb5246d34 100644 --- a/src/mainboard/wyse/s50/Kconfig +++ b/src/mainboard/wyse/s50/Kconfig @@ -20,7 +20,6 @@ if BOARD_WYSE_S50 config BOARD_SPECIFIC_OPTIONS # dummy def_bool y - select ARCH_X86 select CPU_AMD_GEODE_GX2 select NORTHBRIDGE_AMD_GX2 select SOUTHBRIDGE_AMD_CS5536 diff --git a/src/northbridge/amd/agesa/Kconfig b/src/northbridge/amd/agesa/Kconfig index 3d1253115d..32842d731d 100644 --- a/src/northbridge/amd/agesa/Kconfig +++ b/src/northbridge/amd/agesa/Kconfig @@ -31,6 +31,14 @@ config S3_VGA_ROM_RUN bool default n +config DDR3_SOLDERED_DOWN + bool + default n + +config CBFS_SIZE + hex "Size of CBFS filesystem in ROM" + default ROM_SIZE + source src/northbridge/amd/agesa/family10/Kconfig source src/northbridge/amd/agesa/family12/Kconfig source src/northbridge/amd/agesa/family14/Kconfig diff --git a/src/northbridge/amd/agesa/family14/acpi/northbridge.asl b/src/northbridge/amd/agesa/family14/acpi/northbridge.asl new file mode 100644 index 0000000000..24417066ef --- /dev/null +++ b/src/northbridge/amd/agesa/family14/acpi/northbridge.asl @@ -0,0 +1,130 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Note: Only need HID on Primary Bus */ +External (TOM1) +External (TOM2) +Name(_HID, EISAID("PNP0A08")) /* PCI Express Root Bridge */ +Name(_CID, EISAID("PNP0A03")) /* PCI Root Bridge */ +Name(_ADR, 0x00180000) /* Dev# = BSP Dev#, Func# = 0 */ + +/* Describe the Northbridge devices */ +Device(AMRT) { + Name(_ADR, 0x00000000) +} /* end AMRT */ + +/* The internal GFX bridge */ +Device(AGPB) { + Name(_ADR, 0x00010000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APR1) } /* APIC mode */ + Return (PR1) /* PIC Mode */ + } +} /* end AGPB */ + +/* The internal GFX bridge */ +Device(HDMI) { + Name(_ADR, 0x00010001) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APR1) } /* APIC mode */ + Return (PR1) /* PIC Mode */ + } +} /* end HDMI */ + +/* Dev 2 & 3 are external GFX bridges, not used in Family14 */ + +/* Dev4 GPP0 Root Port Bridge */ +Device(PBR4) { + Name(_ADR, 0x00040000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APS4) } /* APIC mode */ + Return (PS4) /* PIC Mode */ + } /* end _PRT */ +} /* end PBR4 */ + +/* Dev5 GPP1 Root Port Bridge */ +Device(PBR5) { + Name(_ADR, 0x00050000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APS5) } /* APIC mode */ + Return (PS5) /* PIC Mode */ + } /* end _PRT */ +} /* end PBR5 */ + +/* Dev6 GPP2 Root Port Bridge */ +Device(PBR6) { + Name(_ADR, 0x00060000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APS6) } /* APIC mode */ + Return (PS6) /* PIC Mode */ + } /* end _PRT */ +} /* end PBR6 */ + +/* The onboard EtherNet chip */ +Device(PBR7) { + Name(_ADR, 0x00070000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APS7) } /* APIC mode */ + Return (PS7) /* PIC Mode */ + } /* end _PRT */ +} /* end PBR7 */ + +Device(PE20) { + Name(_ADR, 0x00150000) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APE0) } /* APIC mode */ + Return (PE0) /* PIC Mode */ + } /* end _PRT */ +} /* end PE20 */ + +Device(PE21) { + Name(_ADR, 0x00150001) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APE1) } /* APIC mode */ + Return (PE1) /* PIC Mode */ + } /* end _PRT */ +} /* end PE21 */ + +Device(PE22) { + Name(_ADR, 0x00150002) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APE2) } /* APIC mode */ + Return (APE2) /* PIC Mode */ + } /* end _PRT */ +} /* end PE22 */ + +Device(PE23) { + Name(_ADR, 0x00150003) + Name(_PRW, Package() {0x18, 4}) + Method(_PRT,0) { + If(PMOD){ Return(APE3) } /* APIC mode */ + Return (PE3) /* PIC Mode */ + } /* end _PRT */ +} /* end PE23 */ + + diff --git a/src/northbridge/amd/agesa/family14/dimmSpd.c b/src/northbridge/amd/agesa/family14/dimmSpd.c index a3f5bb3627..8603389024 100644 --- a/src/northbridge/amd/agesa/family14/dimmSpd.c +++ b/src/northbridge/amd/agesa/family14/dimmSpd.c @@ -29,9 +29,15 @@ #include "dimmSpd.h" #include "chip.h" +#if CONFIG_DDR3_SOLDERED_DOWN +#include CONFIG_PATH_TO_DDR3_SPD +AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc ); +#endif + /* uncomment for source level debug - GDB gets really confused otherwise. */ //#pragma optimize ("", off) +#if !CONFIG_DDR3_SOLDERED_DOWN /** * Read a single SPD byte. If the first byte is being read, set up the * address and offset. Following bytes auto increment. @@ -143,3 +149,71 @@ AGESA_STATUS agesa_ReadSPD(UINT32 unused1, UINT32 unused2, void *infoptr) return AGESA_ERROR; return readspd(SMBUS0_BASE_ADDRESS, spdAddress, (void *)info->Buffer, 128); } + +#else // CONFIG_DDR3_SOLDERED_DOWN +/* + * Get the SPD from the mainboard + */ +AGESA_STATUS agesa_ReadSPD(UINT32 unused1, UINT32 unused2, void *infoptr) +{ + UINT8 *spd_ptr; + UINT16 index, crc; + + AGESA_READ_SPD_PARAMS *info = infoptr; + ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + + if ((dev == 0) || (dev->chip_info == 0)) + return AGESA_ERROR; + + if (info->MemChannelId > CONFIG_DDR3_CHANNEL_MAX) return AGESA_ERROR; + if (info->SocketId != 0) return AGESA_ERROR; + if (info->DimmId != 0) return AGESA_ERROR; + + /* read the bytes from the table */ + spd_ptr = (UINT8 *)info->Buffer; + for (index = 0; index < 128; index++) + spd_ptr[index] = ddr3_fake_spd[index]; + + /* If CRC bytes are zeroes, calculate and store the CRC of the fake table */ + if ((spd_ptr[126] == 0) && (spd_ptr[127] == 0)) { + calc_fake_spd_crc( spd_ptr, &crc ); + spd_ptr[126] = (UINT8)(crc & 0xFF); + spd_ptr[127] = (UINT8)(crc>>8); + } + + /* print out the table */ + printk(BIOS_SPEW, "\nDump the fake SPD for Channel %d\n",info->MemChannelId); + for (index = 0; index < 128; index++) { + if((index&0x0F)==0x00) printk(BIOS_SPEW, "%02x: ",index); + printk(BIOS_SPEW, "%02x ", spd_ptr[index]); + if((index&0x0F)==0x0F) printk(BIOS_SPEW, "\n"); + } + return AGESA_SUCCESS; +} + +AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc ) +{ + INT16 i; + INT16 j; + INT16 jmax; + + /* should the CRC be done on bytes 0-116 or 0-125 ? */ + if (SPDPtr[0] & 0x80) + jmax = 117; + else jmax = 126; + + *crc = 0; /* zero out the CRC */ + + for (j = 0; j < jmax; j++) { + *crc = *crc ^ ((UINT16)SPDPtr[j] << 8); + for (i = 0; i < 8; i++) { + if (*crc & 0x8000) { + *crc = (*crc << 1) ^ 0x1021; + } else { + *crc = (*crc << 1); + } + } + } + return TRUE; +} +#endif diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.c b/src/northbridge/amd/agesa/family15tn/dimmSpd.c index 5b8a9b522c..2e8a82a665 100644 --- a/src/northbridge/amd/agesa/family15tn/dimmSpd.c +++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.c @@ -27,9 +27,14 @@ #include "dimmSpd.h" #include "chip.h" +#if CONFIG_DDR3_SOLDERED_DOWN +#include CONFIG_PATH_TO_DDR3_SPD +AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc ); +#endif #define DIMENSION(array)(sizeof (array)/ sizeof (array [0])) +#if !CONFIG_DDR3_SOLDERED_DOWN /*----------------------------------------------------------------------------- * * readSmbusByteData - read a single SPD byte from any offset @@ -158,3 +163,70 @@ AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PA setupFch (ioBase); return readspd (ioBase, spdAddress, (void *) info->Buffer, 128); } + +#else // CONFIG_DDR3_SOLDERED_DOWN +/* + * Get the SPD from the mainboard + */ +AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info) +{ + UINT8 *spd_ptr; + UINT16 index, crc; + + ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + + if ((dev == 0) || (dev->chip_info == 0)) + return AGESA_ERROR; + + if (info->MemChannelId > CONFIG_DDR3_CHANNEL_MAX) return AGESA_ERROR; + if (info->SocketId != 0) return AGESA_ERROR; + if (info->DimmId != 0) return AGESA_ERROR; + + /* read the bytes from the table */ + spd_ptr = (UINT8 *)info->Buffer; + for (index = 0; index < 128; index++) + spd_ptr[index] = ddr3_fake_spd[index]; + + /* If CRC bytes are zeroes, calculate and store the CRC of the fake table */ + if ((spd_ptr[126] == 0) && (spd_ptr[127] == 0)) { + calc_fake_spd_crc( spd_ptr, &crc ); + spd_ptr[126] = (UINT8)(crc & 0xFF); + spd_ptr[127] = (UINT8)(crc>>8); + } + + /* print out the table */ + printk(BIOS_SPEW, "\nDump the fake SPD for Channel %d\n",info->MemChannelId); + for (index = 0; index < 128; index++) { + if((index&0x0F)==0x00) printk(BIOS_SPEW, "%02x: ",index); + printk(BIOS_SPEW, "%02x ", spd_ptr[index]); + if((index&0x0F)==0x0F) printk(BIOS_SPEW, "\n"); + } + return AGESA_SUCCESS; +} + +AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc ) +{ + INT16 i; + INT16 j; + INT16 jmax; + + /* should the CRC be done on bytes 0-116 or 0-125 ? */ + if (SPDPtr[0] & 0x80) + jmax = 117; + else jmax = 126; + + *crc = 0; /* zero out the CRC */ + + for (j = 0; j < jmax; j++) { + *crc = *crc ^ ((UINT16)SPDPtr[j] << 8); + for (i = 0; i < 8; i++) { + if (*crc & 0x8000) { + *crc = (*crc << 1) ^ 0x1021; + } else { + *crc = (*crc << 1); + } + } + } + return TRUE; +} +#endif diff --git a/src/northbridge/amd/amdfam10/amdfam10.h b/src/northbridge/amd/amdfam10/amdfam10.h index eded51555a..c6ec572024 100644 --- a/src/northbridge/amd/amdfam10/amdfam10.h +++ b/src/northbridge/amd/amdfam10/amdfam10.h @@ -1033,7 +1033,7 @@ struct nodes_info_t { u32 up_planes; // down planes will be [up_planes, planes) } __attribute__((packed)); -/* be careful with the alignment of sysinfo, bacause sysinfo may be shared by coreboot_car and coreboot_ram stage. and coreboot_ram may be running at 64bit later.*/ +/* be careful with the alignment of sysinfo, bacause sysinfo may be shared by coreboot_car and ramstage stage. and ramstage may be running at 64bit later.*/ #if !CONFIG_AMDMCT //#define MEM_CS_COPY 1 diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c index 6994c394e8..e5c18a8f45 100644 --- a/src/northbridge/amd/amdfam10/raminit_amdmct.c +++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c @@ -120,7 +120,7 @@ static void print_t(const char *strval) #endif /* DDR2 */ -#include +#include struct sys_info sysinfo_car CAR_GLOBAL; int mctRead_SPD(u32 smaddr, u32 reg) diff --git a/src/northbridge/amd/amdk8/get_sblk_pci1234.c b/src/northbridge/amd/amdk8/get_sblk_pci1234.c index e5bcdcb9c1..a4943bd2b9 100644 --- a/src/northbridge/amd/amdk8/get_sblk_pci1234.c +++ b/src/northbridge/amd/amdk8/get_sblk_pci1234.c @@ -80,7 +80,7 @@ unsigned node_link_to_bus(unsigned node, unsigned link) * pci1234[0] will record the south bridge link and bus range * pci1234[i] will record HT chain i. * - * For example, on the Tyan S2885 coreboot_ram will put the AMD8151 chain (HT + * For example, on the Tyan S2885 ramstage will put the AMD8151 chain (HT * link 0) into the register 0xE0, and the AMD8131/8111 HT chain into the * register 0xE4. * diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c index 33a3245644..4aaa1bb385 100644 --- a/src/northbridge/amd/amdk8/raminit.c +++ b/src/northbridge/amd/amdk8/raminit.c @@ -14,7 +14,7 @@ #include "option_table.h" #endif -#include +#include struct sys_info sysinfo_car CAR_GLOBAL; #if (CONFIG_RAMTOP & (CONFIG_RAMTOP -1)) != 0 diff --git a/src/northbridge/amd/amdk8/raminit_f.c b/src/northbridge/amd/amdk8/raminit_f.c index c1882d7cef..64271b56f0 100644 --- a/src/northbridge/amd/amdk8/raminit_f.c +++ b/src/northbridge/amd/amdk8/raminit_f.c @@ -39,7 +39,7 @@ #endif -#include +#include struct sys_info sysinfo_car CAR_GLOBAL; #if (CONFIG_RAMTOP & (CONFIG_RAMTOP -1)) != 0 diff --git a/src/northbridge/amd/amdk8/raminit_f_dqs.c b/src/northbridge/amd/amdk8/raminit_f_dqs.c index a7a4538f30..08a3bab6c7 100644 --- a/src/northbridge/amd/amdk8/raminit_f_dqs.c +++ b/src/northbridge/amd/amdk8/raminit_f_dqs.c @@ -2103,16 +2103,8 @@ static inline void train_ram_on_node(unsigned nodeid, unsigned coreid, struct sy memcpy(sysinfo, sysinfox, sizeof(*sysinfo)); #endif set_top_mem_ap(sysinfo->tom_k, sysinfo->tom2_k); // keep the ap's tom consistent with bsp's - #if !CONFIG_AP_CODE_IN_CAR printk(BIOS_DEBUG, "CODE IN ROM AND RUN ON NODE: %02x\n", nodeid); train_ram(nodeid, sysinfo, sysinfox); - #else - /* Can copy dqs_timing to ap cache and run from cache? - * we need coreboot_ap_car.rom? and treat it as coreboot_ram.rom for ap ? - */ - copy_and_run_ap_code_in_car(retcall); - // will go back by jump - #endif } } #endif diff --git a/src/northbridge/intel/e7501/raminit.h b/src/northbridge/intel/e7501/raminit.h index df0e9291a3..05c3889aa2 100644 --- a/src/northbridge/intel/e7501/raminit.h +++ b/src/northbridge/intel/e7501/raminit.h @@ -15,8 +15,6 @@ struct mem_controller { uint16_t channel1[MAX_DIMM_SOCKETS_PER_CHANNEL]; }; -#ifndef __ROMCC__ void sdram_initialize(int controllers, const struct mem_controller *ctrl); -#endif #endif /* RAMINIT_H */ diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig index 12f865a2e3..48d12743bf 100644 --- a/src/northbridge/intel/haswell/Kconfig +++ b/src/northbridge/intel/haswell/Kconfig @@ -23,6 +23,8 @@ config NORTHBRIDGE_INTEL_HASWELL select CPU_INTEL_HASWELL select REQUIRES_BLOB select MMCONF_SUPPORT_DEFAULT + select INTEL_DDI + select INTEL_DP if NORTHBRIDGE_INTEL_HASWELL @@ -82,14 +84,6 @@ config DCACHE_RAM_ROMSTAGE_STACK_SIZE The amount of anticipated stack usage from the data cache during pre-ram rom stage execution. -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_MRC bool "Add a System Agent binary" help @@ -118,4 +112,13 @@ config CBFS_SIZE This option allows to limit the size of the CBFS portion in the firmware image. +config PRE_GRAPHICS_DELAY + int "Graphics initialization delay in ms" + default 0 + help + On some systems, coreboot boots so fast that connected monitors + (mostly TVs) won't be able to wake up fast enough to talk to the + VBIOS. On those systems we need to wait for a bit before executing + the VBIOS. + endif diff --git a/src/northbridge/intel/haswell/Makefile.inc b/src/northbridge/intel/haswell/Makefile.inc index 896360d9ec..2a3e6fb7ce 100644 --- a/src/northbridge/intel/haswell/Makefile.inc +++ b/src/northbridge/intel/haswell/Makefile.inc @@ -22,6 +22,7 @@ ramstage-y += gma.c ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c ramstage-y += mrccache.c +ramstage-y += minihd.c romstage-y += raminit.c romstage-y += mrccache.c @@ -29,7 +30,6 @@ romstage-y += early_init.c romstage-y += report_platform.c romstage-y += ../../../arch/x86/lib/walkcbfs.S -smm-$(CONFIG_HAVE_SMI_HANDLER) += udelay.c smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c # We don't ship that, but booting without it is bound to fail @@ -37,5 +37,3 @@ cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE)) mrc.bin-position := 0xfffa0000 mrc.bin-type := 0xab - -$(obj)/northbridge/intel/haswell/acpi.ramstage.o : $(obj)/build.h diff --git a/src/northbridge/intel/haswell/acpi/hostbridge.asl b/src/northbridge/intel/haswell/acpi/hostbridge.asl index 681f6dc1fd..30ee3e548e 100644 --- a/src/northbridge/intel/haswell/acpi/hostbridge.asl +++ b/src/northbridge/intel/haswell/acpi/hostbridge.asl @@ -106,35 +106,45 @@ Device (MCHC) Name (CTCN, 0) /* CTDP Nominal Select */ Name (CTCD, 1) /* CTDP Down Select */ Name (CTCU, 2) /* CTDP Up Select */ + Name (SPL1, 0) /* Saved PL1 value */ - OperationRegion (MCHB, SystemMemory, DEFAULT_MCHBAR, 0x8000) + OperationRegion (MCHB, SystemMemory, Add(DEFAULT_MCHBAR,0x5000), 0x1000) Field (MCHB, DWordAcc, Lock, Preserve) { - Offset (0x5930), + Offset (0x930), /* PACKAGE_POWER_SKU */ CTDN, 15, /* CTDP Nominal PL1 */ - Offset (0x59a0), + Offset (0x938), /* PACKAGE_POWER_SKU_UNIT */ + PUNI, 4, /* Power Units */ + , 4, + EUNI, 5, /* Energy Units */ + , 3, + TUNI, 4, /* Time Units */ + Offset (0x958), /* PLATFORM_INFO */ + , 40, + LFM_, 8, /* Maximum Efficiency Ratio (LFM) */ + Offset (0x9a0), /* TURBO_POWER_LIMIT1 */ PL1V, 15, /* Power Limit 1 Value */ PL1E, 1, /* Power Limit 1 Enable */ PL1C, 1, /* Power Limit 1 Clamp */ PL1T, 7, /* Power Limit 1 Time */ - Offset (0x59a4), + Offset (0x9a4), /* TURBO_POWER_LIMIT2 */ PL2V, 15, /* Power Limit 2 Value */ PL2E, 1, /* Power Limit 2 Enable */ PL2C, 1, /* Power Limit 2 Clamp */ PL2T, 7, /* Power Limit 2 Time */ - Offset (0x5f3c), + Offset (0xf3c), /* CONFIG_TDP_NOMINAL */ TARN, 8, /* CTDP Nominal Turbo Activation Ratio */ - Offset (0x5f40), + Offset (0xf40), /* CONFIG_TDP_LEVEL1 */ CTDD, 15, /* CTDP Down PL1 */ - , 1, + , 1, TARD, 8, /* CTDP Down Turbo Activation Ratio */ - Offset (0x5f48), + Offset (0xf48), /* MSR_CONFIG_TDP_LEVEL2 */ CTDU, 15, /* CTDP Up PL1 */ - , 1, + , 1, TARU, 8, /* CTDP Up Turbo Activation Ratio */ - Offset (0x5f50), + Offset (0xf50), /* CONFIG_TDP_CONTROL */ CTCS, 2, /* CTDP Select */ - Offset (0x5f54), + Offset (0xf54), /* TURBO_ACTIVATION_RATIO */ TARS, 8, /* Turbo Activation Ratio Select */ } @@ -166,7 +176,19 @@ Device (MCHC) Return (0) } - /* Set TDP Down */ + /* Calculate PL2 based on chip type */ + Method (CPL2, 1, NotSerialized) + { + If (\ISLP ()) { + /* Haswell ULT PL2 = 25W */ + Return (Multiply (25, 8)) + } Else { + /* Haswell Mobile PL2 = 1.25 * PL1 */ + Return (Divide (Multiply (Arg0, 125), 100)) + } + } + + /* Set Config TDP Down */ Method (STND, 0, Serialized) { If (Acquire (CTCM, 100)) { @@ -189,8 +211,8 @@ Device (MCHC) Store (PSSS (TARD), PPCM) PPCN () - /* Set PL2 to 1.25 * PL1 */ - Divide (Multiply (CTDD, 125), 100, Local0, PL2V) + /* Set PL2 */ + Store (CPL2 (CTDD), PL2V) /* Set PL1 */ Store (CTDD, PL1V) @@ -202,7 +224,7 @@ Device (MCHC) Return (1) } - /* Set TDP Nominal from Down */ + /* Set Config TDP Nominal from Down */ Method (STDN, 0, Serialized) { If (Acquire (CTCM, 100)) { @@ -218,8 +240,8 @@ Device (MCHC) /* Set PL1 */ Store (CTDN, PL1V) - /* Set PL2 to 1.25 * PL1 */ - Divide (Multiply (CTDN, 125), 100, Local0, PL2V) + /* Set PL2 */ + Store (CPL2 (CTDN), PL2V) /* Set PPC limit and notify OS */ Store (PSSS (TARN), PPCM) @@ -237,6 +259,66 @@ Device (MCHC) Release (CTCM) Return (1) } + + /* Calculate PL1 value based on requested TDP */ + Method (TDPP, 1, NotSerialized) + { + Return (Multiply (ShiftLeft (Subtract (PUNI, 1), 2), Arg0)) + } + + /* Enable Controllable TDP to limit PL1 to requested value */ + Method (CTLE, 1, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + + Store ("Enable PL1 Limit", Debug) + + /* Set _PPC to LFM */ + Store (PSSS (LFM_), Local0) + Add (Local0, 1, PPCM) + \PPCN () + + /* Set TAR to LFM-1 */ + Subtract (LFM_, 1, TARS) + + /* Set PL1 to desired value */ + Store (PL1V, SPL1) + Store (TDPP (Arg0), PL1V) + + /* Set PL1 CLAMP bit */ + Store (One, PL1C) + + Release (CTCM) + Return (1) + } + + /* Disable Controllable TDP */ + Method (CTLD, 0, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + + Store ("Disable PL1 Limit", Debug) + + /* Clear PL1 CLAMP bit */ + Store (Zero, PL1C) + + /* Set PL1 to normal value */ + Store (SPL1, PL1V) + + /* Set TAR to 0 */ + Store (Zero, TARS) + + /* Set _PPC to 0 */ + Store (Zero, PPCM) + \PPCN () + + Release (CTCM) + Return (1) + } } // Current Resource Settings diff --git a/src/northbridge/intel/haswell/early_init.c b/src/northbridge/intel/haswell/early_init.c index 5b364189e9..7f9f1876b1 100644 --- a/src/northbridge/intel/haswell/early_init.c +++ b/src/northbridge/intel/haswell/early_init.c @@ -103,8 +103,9 @@ void haswell_early_initialization(int chipset_type) /* Setup all BARs required for early PCIe and raminit */ haswell_setup_bars(); - /* Device Enable */ - pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, DEVEN_HOST | DEVEN_IGD); + /* Device Enable: IGD and Mini-HD Audio */ + pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, + DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN); haswell_setup_graphics(); } diff --git a/src/northbridge/intel/haswell/gma.c b/src/northbridge/intel/haswell/gma.c index 0a67b6a851..f8351e2238 100644 --- a/src/northbridge/intel/haswell/gma.c +++ b/src/northbridge/intel/haswell/gma.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2011 Chromium OS Authors + * Copyright 2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,10 +23,77 @@ #include #include #include +#include +#include +#include +#include +#include #include "chip.h" #include "haswell.h" +#if CONFIG_CHROMEOS +#include +#endif + +struct gt_reg { + u32 reg; + u32 andmask; + u32 ormask; +}; + +static const struct gt_reg haswell_gt_setup[] = { + /* Enable Counters */ + { 0x0a248, 0x00000000, 0x00000016 }, + { 0x0a000, 0x00000000, 0x00070020 }, + { 0x0a180, 0xff3fffff, 0x15000000 }, + /* Enable DOP Clock Gating */ + { 0x09424, 0x00000000, 0x000003fd }, + /* Enable Unit Level Clock Gating */ + { 0x09400, 0x00000000, 0x00000080 }, + { 0x09404, 0x00000000, 0x40401000 }, + { 0x09408, 0x00000000, 0x00000000 }, + { 0x0940c, 0x00000000, 0x02000001 }, + { 0x0a008, 0x00000000, 0x08000000 }, + /* Wake Rate Limits */ + { 0x0a090, 0xffffffff, 0x00000000 }, + { 0x0a098, 0xffffffff, 0x03e80000 }, + { 0x0a09c, 0xffffffff, 0x00280000 }, + { 0x0a0a8, 0xffffffff, 0x0001e848 }, + { 0x0a0ac, 0xffffffff, 0x00000019 }, + /* Render/Video/Blitter Idle Max Count */ + { 0x02054, 0x00000000, 0x0000000a }, + { 0x12054, 0x00000000, 0x0000000a }, + { 0x22054, 0x00000000, 0x0000000a }, + /* RC Sleep / RCx Thresholds */ + { 0x0a0b0, 0xffffffff, 0x00000000 }, + { 0x0a0b4, 0xffffffff, 0x000003e8 }, + { 0x0a0b8, 0xffffffff, 0x0000c350 }, + /* RP Settings */ + { 0x0a010, 0xffffffff, 0x000f4240 }, + { 0x0a014, 0xffffffff, 0x12060000 }, + { 0x0a02c, 0xffffffff, 0x0000e808 }, + { 0x0a030, 0xffffffff, 0x0003bd08 }, + { 0x0a068, 0xffffffff, 0x000101d0 }, + { 0x0a06c, 0xffffffff, 0x00055730 }, + { 0x0a070, 0xffffffff, 0x0000000a }, + /* RP Control */ + { 0x0a024, 0x00000000, 0x00000b92 }, + /* HW RC6 Control */ + { 0x0a090, 0x00000000, 0x88040000 }, + /* Video Frequency Request */ + { 0x0a00c, 0x00000000, 0x08000000 }, + { 0 }, +}; + +static const struct gt_reg haswell_gt_lock[] = { + { 0x0a248, 0xffffffff, 0x80000000 }, + { 0x0a004, 0xffffffff, 0x00000010 }, + { 0x0a080, 0xffffffff, 0x00000004 }, + { 0x0a180, 0xffffffff, 0x80000000 }, + { 0 }, +}; + /* some vga option roms are used for several chipsets but they only have one * PCI ID in their header. If we encounter such an option rom, we need to do * the mapping ourselfes @@ -59,20 +126,80 @@ u32 map_oprom_vendev(u32 vendev) return new_vendev; } -static struct resource *gtt_res = NULL; +/* GTT is the Global Translation Table for the graphics pipeline. + * It is used to translate graphics addresses to physical + * memory addresses. As in the CPU, GTTs map 4K pages. + * The setgtt function adds a further bit of flexibility: + * it allows you to set a range (the first two parameters) to point + * to a physical address (third parameter);the physical address is + * incremented by a count (fourth parameter) for each GTT in the + * range. + * Why do it this way? For ultrafast startup, + * we can point all the GTT entries to point to one page, + * and set that page to 0s: + * memset(physbase, 0, 4096); + * setgtt(0, 4250, physbase, 0); + * this takes about 2 ms, and is a win because zeroing + * the page takes a up to 200 ms. + * This call sets the GTT to point to a linear range of pages + * starting at physbase. + */ -static inline u32 gtt_read(u32 reg) +#define GTT_PTE_BASE (2 << 20) + +void +set_translation_table(int start, int end, u64 base, int inc) { - return read32(gtt_res->base + reg); + int i; + + for(i = start; i < end; i++){ + u64 physical_address = base + i*inc; + /* swizzle the 32:39 bits to 4:11 */ + u32 word = physical_address | ((physical_address >> 28) & 0xff0) | 1; + /* note: we've confirmed by checking + * the values that mrc does no + * useful setup before we run this. + */ + gtt_write(GTT_PTE_BASE + i * 4, word); + gtt_read(GTT_PTE_BASE + i * 4); + } } -static inline void gtt_write(u32 reg, u32 data) +static struct resource *gtt_res = NULL; + +unsigned long gtt_read(unsigned long reg) +{ + u32 val; + val = read32(gtt_res->base + reg); + return val; + +} + +void gtt_write(unsigned long reg, unsigned long data) { write32(gtt_res->base + reg, data); } +static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask) +{ + u32 val = gtt_read(reg); + val &= andmask; + val |= ormask; + gtt_write(reg, val); +} + +static inline void gtt_write_regs(const struct gt_reg *gt) +{ + for (; gt && gt->reg; gt++) { + if (gt->andmask) + gtt_rmw(gt->reg, gt->andmask, gt->ormask); + else + gtt_write(gt->reg, gt->ormask); + } +} + #define GTT_RETRY 1000 -static int gtt_poll(u32 reg, u32 mask, u32 value) +int gtt_poll(u32 reg, u32 mask, u32 value) { unsigned try = GTT_RETRY; u32 data; @@ -88,6 +215,19 @@ static int gtt_poll(u32 reg, u32 mask, u32 value) return 0; } +static void power_well_enable(void) +{ + gtt_write(HSW_PWR_WELL_CTL1, HSW_PWR_WELL_ENABLE); + gtt_poll(HSW_PWR_WELL_CTL1, HSW_PWR_WELL_STATE, HSW_PWR_WELL_STATE); +#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + /* In the native graphics case, we've got about 20 ms. + * after we power up the the AUX channel until we can talk to it. + * So get that going right now. We can't turn on the panel, yet, just VDD. + */ + gtt_write(PCH_PP_CONTROL, PCH_PP_UNLOCK| EDP_FORCE_VDD | PANEL_POWER_RESET); +#endif +} + static void gma_pm_init_pre_vbios(struct device *dev) { printk(BIOS_DEBUG, "GT Power Management Init\n"); @@ -96,6 +236,8 @@ static void gma_pm_init_pre_vbios(struct device *dev) if (!gtt_res || !gtt_res->base) return; + power_well_enable(); + /* * Enable RC6 */ @@ -105,92 +247,190 @@ static void gma_pm_init_pre_vbios(struct device *dev) gtt_write(0x0a188, 0x00010001); gtt_poll(0x130044, 1 << 0, 1 << 0); - /* Enable counters and lock */ - gtt_write(0x0a248, 0x80000016); - gtt_write(0x0a000, 0x00070020); - gtt_write(0x0a180, 0xc5000020); + /* GT Settings */ + gtt_write_regs(haswell_gt_setup); - /* Enable DOP clock gating */ - gtt_write(0x09424, 0x00000001); + /* Wait for Mailbox Ready */ + gtt_poll(0x138124, (1 << 31), (0 << 31)); + /* Mailbox Data - RC6 VIDS */ + gtt_write(0x138128, 0x00000000); + /* Mailbox Command */ + gtt_write(0x138124, 0x80000004); + /* Wait for Mailbox Ready */ + gtt_poll(0x138124, (1 << 31), (0 << 31)); - /* Enable unit level clock gating */ - gtt_write(0x09400, 0x00000080); - gtt_write(0x09404, 0x40401000); - gtt_write(0x09408, 0x00000000); - gtt_write(0x0940c, 0x02000001); - - /* Configure max ilde count */ - gtt_write(0x02054, 0x0000000a); - gtt_write(0x12054, 0x0000000a); - gtt_write(0x22054, 0x0000000a); - - gtt_write(0x0a008, 0x10000000); - gtt_write(0x0a024, 0x00000b92); + /* Enable PM Interrupts */ + gtt_write(GEN6_PMIER, GEN6_PM_MBOX_EVENT | GEN6_PM_THERMAL_EVENT | + GEN6_PM_RP_DOWN_TIMEOUT | GEN6_PM_RP_UP_THRESHOLD | + GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_UP_EI_EXPIRED | + GEN6_PM_RP_DOWN_EI_EXPIRED); /* Enable RC6 in idle */ gtt_write(0x0a094, 0x00040000); + + /* PM Lock Settings */ + gtt_write_regs(haswell_gt_lock); } -static void gma_pm_init_post_vbios(struct device *dev) +static void init_display_planes(void) +{ + int pipe, plane; + + /* Disable cursor mode */ + for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) { + gtt_write(CURCNTR_IVB(pipe), CURSOR_MODE_DISABLE); + gtt_write(CURBASE_IVB(pipe), 0x00000000); + } + + /* Disable primary plane and set surface base address*/ + for (plane = PLANE_A; plane <= PLANE_C; plane++) { + gtt_write(DSPCNTR(plane), DISPLAY_PLANE_DISABLE); + gtt_write(DSPSURF(plane), 0x00000000); + } + + /* Disable VGA display */ + gtt_write(CPU_VGACNTRL, CPU_VGA_DISABLE); +} + +static void gma_setup_panel(struct device *dev) { struct northbridge_intel_haswell_config *conf = dev->chip_info; u32 reg32; printk(BIOS_DEBUG, "GT Power Management Init (post VBIOS)\n"); - /* Disable Force Wake */ - gtt_write(0x0a188, 0x00010000); - gtt_poll(0x130044, 1 << 0, 0 << 0); - /* Setup Digital Port Hotplug */ - reg32 = gtt_read(0xc4030); + reg32 = gtt_read(PCH_PORT_HOTPLUG); if (!reg32) { reg32 = (conf->gpu_dp_b_hotplug & 0x7) << 2; reg32 |= (conf->gpu_dp_c_hotplug & 0x7) << 10; reg32 |= (conf->gpu_dp_d_hotplug & 0x7) << 18; - gtt_write(0xc4030, reg32); + gtt_write(PCH_PORT_HOTPLUG, reg32); } /* Setup Panel Power On Delays */ - reg32 = gtt_read(0xc7208); + reg32 = gtt_read(PCH_PP_ON_DELAYS); if (!reg32) { reg32 = (conf->gpu_panel_port_select & 0x3) << 30; reg32 |= (conf->gpu_panel_power_up_delay & 0x1fff) << 16; reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff); - gtt_write(0xc7208, reg32); + gtt_write(PCH_PP_ON_DELAYS, reg32); } /* Setup Panel Power Off Delays */ - reg32 = gtt_read(0xc720c); + reg32 = gtt_read(PCH_PP_OFF_DELAYS); if (!reg32) { reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16; reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff); - gtt_write(0xc720c, reg32); + gtt_write(PCH_PP_OFF_DELAYS, reg32); } /* Setup Panel Power Cycle Delay */ if (conf->gpu_panel_power_cycle_delay) { - reg32 = gtt_read(0xc7210); + reg32 = gtt_read(PCH_PP_DIVISOR); reg32 &= ~0xff; reg32 |= conf->gpu_panel_power_cycle_delay & 0xff; - gtt_write(0xc7210, reg32); + gtt_write(PCH_PP_DIVISOR, reg32); } /* Enable Backlight if needed */ if (conf->gpu_cpu_backlight) { - gtt_write(0x48250, (1 << 31)); - gtt_write(0x48254, conf->gpu_cpu_backlight); + gtt_write(BLC_PWM_CPU_CTL2, BLC_PWM2_ENABLE); + gtt_write(BLC_PWM_CPU_CTL, conf->gpu_cpu_backlight); } if (conf->gpu_pch_backlight) { - gtt_write(0xc8250, (1 << 31)); - gtt_write(0xc8254, conf->gpu_pch_backlight); + gtt_write(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE); + gtt_write(BLC_PWM_PCH_CTL2, conf->gpu_pch_backlight); } + + /* Get display,pipeline,and DDI registers into a basic sane state */ + power_well_enable(); + + init_display_planes(); + + /* DDI-A params set: + bit 0: Display detected (RO) + bit 4: DDI A supports 4 lanes and DDI E is not used + bit 7: DDI buffer is idle + */ + gtt_write(DDI_BUF_CTL_A, DDI_BUF_IS_IDLE | DDI_A_4_LANES | DDI_INIT_DISPLAY_DETECTED); + + /* Set FDI registers - is this required? */ + gtt_write(_FDI_RXA_MISC, 0x00200090); + gtt_write(_FDI_RXA_MISC, 0x0a000000); + + /* Enable the handshake with PCH display when processing reset */ + gtt_write(NDE_RSTWRN_OPT, RST_PCH_HNDSHK_EN); + + /* undocumented */ + gtt_write(0x42090, 0x04000000); + gtt_write(0x9840, 0x00000000); + gtt_write(0x42090, 0xa4000000); + + gtt_write(SOUTH_DSPCLK_GATE_D, PCH_LP_PARTITION_LEVEL_DISABLE); + + /* undocumented */ + gtt_write(0x42080, 0x00004000); + + /* Prepare DDI buffers for DP and FDI */ + intel_prepare_ddi(); + + /* Hot plug detect buffer enabled for port A */ + gtt_write(DIGITAL_PORT_HOTPLUG_CNTRL, DIGITAL_PORTA_HOTPLUG_ENABLE); + + /* Enable HPD buffer for digital port D and B */ + gtt_write(PCH_PORT_HOTPLUG, PORTD_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE); + + /* Bits 4:0 - Power cycle delay (default 0x6 --> 500ms) + Bits 31:8 - Reference divider (0x0004af ----> 24MHz) + */ + gtt_write(PCH_PP_DIVISOR, 0x0004af06); +} + +static void gma_pm_init_post_vbios(struct device *dev) +{ + int cdclk = 0; + int devid = pci_read_config16(dev, PCI_DEVICE_ID); + int gpu_is_ulx = 0; + + if (devid == 0x0a0e || devid == 0x0a1e) + gpu_is_ulx = 1; + + /* CD Frequency */ + if ((gtt_read(0x42014) & 0x1000000) || gpu_is_ulx || haswell_is_ult()) + cdclk = 0; /* fixed frequency */ + else + cdclk = 2; /* variable frequency */ + + if (gpu_is_ulx || cdclk != 0) + gtt_rmw(0x130040, 0xf7ffffff, 0x04000000); + else + gtt_rmw(0x130040, 0xf3ffffff, 0x00000000); + + /* More magic */ + if (haswell_is_ult() || gpu_is_ulx) { + if (!gpu_is_ulx) + gtt_write(0x138128, 0x00000000); + else + gtt_write(0x138128, 0x00000001); + gtt_write(0x13812c, 0x00000000); + gtt_write(0x138124, 0x80000017); + } + + /* Disable Force Wake */ + gtt_write(0x0a188, 0x00010000); + gtt_poll(0x130044, 1 << 0, 0 << 0); + gtt_write(0x0a188, 0x00000001); } static void gma_func0_init(struct device *dev) { +#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + struct northbridge_intel_haswell_config *conf = dev->chip_info; + struct intel_dp dp; +#endif + int lightup_ok = 0; u32 reg32; - /* IGD needs to be Bus Master */ reg32 = pci_read_config32(dev, PCI_COMMAND); reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; @@ -199,8 +439,35 @@ static void gma_func0_init(struct device *dev) /* Init graphics power management */ gma_pm_init_pre_vbios(dev); - /* PCI Init, will run VBIOS */ - pci_dev_init(dev); + /* Post VBIOS init */ + gma_setup_panel(dev); + +#if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + printk(BIOS_SPEW, "NATIVE graphics, run native enable\n"); + /* Default set to 1 since it might be required for + stuff like seabios */ + unsigned int init_fb = 1; + + /* the BAR for graphics space is a well known number for + * sandy and ivy. And the resource code renumbers it. + * So it's almost like having two hardcodes. + */ + dp.graphics = (void *)((uintptr_t)dev->resource_list[1].base); + dp.physbase = pci_read_config32(dev, 0x5c) & ~0xf; + dp.panel_power_down_delay = conf->gpu_panel_power_down_delay; + dp.panel_power_up_delay = conf->gpu_panel_power_up_delay; + dp.panel_power_cycle_delay = conf->gpu_panel_power_cycle_delay; + +#ifdef CONFIG_CHROMEOS + init_fb = developer_mode_enabled() || recovery_mode_enabled(); +#endif + lightup_ok = panel_lightup(&dp, init_fb); +#endif + if (! lightup_ok) { + printk(BIOS_SPEW, "FUI did not run; using VBIOS\n"); + mdelay(CONFIG_PRE_GRAPHICS_DELAY); + pci_dev_init(dev); + } /* Post VBIOS init */ gma_pm_init_post_vbios(dev); diff --git a/src/northbridge/intel/haswell/haswell.h b/src/northbridge/intel/haswell/haswell.h index ba88722452..55f6f284e4 100644 --- a/src/northbridge/intel/haswell/haswell.h +++ b/src/northbridge/intel/haswell/haswell.h @@ -26,23 +26,6 @@ #define HASWELL_DESKTOP 1 #define HASWELL_SERVER 2 -/* Device ID for SandyBridge and IvyBridge */ -#define BASE_REV_SNB 0x00 -#define BASE_REV_IVB 0x50 -#define BASE_REV_MASK 0x50 - -/* SandyBridge CPU stepping */ -#define SNB_STEP_D0 (BASE_REV_SNB + 5) /* Also J0 */ -#define SNB_STEP_D1 (BASE_REV_SNB + 6) -#define SNB_STEP_D2 (BASE_REV_SNB + 7) /* Also J1/Q0 */ - -/* IvyBridge CPU stepping */ -#define IVB_STEP_A0 (BASE_REV_IVB + 0) -#define IVB_STEP_B0 (BASE_REV_IVB + 2) -#define IVB_STEP_C0 (BASE_REV_IVB + 4) -#define IVB_STEP_K0 (BASE_REV_IVB + 5) -#define IVB_STEP_D0 (BASE_REV_IVB + 6) - /* Intel Enhanced Debug region */ #define IED_SIZE CONFIG_IED_REGION_SIZE @@ -67,12 +50,14 @@ #define GGC 0x50 /* GMCH Graphics Control */ #define DEVEN 0x54 /* Device Enable */ -#define DEVEN_PEG60 (1 << 13) -#define DEVEN_IGD (1 << 4) -#define DEVEN_PEG10 (1 << 3) -#define DEVEN_PEG11 (1 << 2) -#define DEVEN_PEG12 (1 << 1) -#define DEVEN_HOST (1 << 0) +#define DEVEN_D7EN (1 << 14) +#define DEVEN_D4EN (1 << 7) +#define DEVEN_D3EN (1 << 5) +#define DEVEN_D2EN (1 << 4) +#define DEVEN_D1F0EN (1 << 3) +#define DEVEN_D1F1EN (1 << 2) +#define DEVEN_D1F2EN (1 << 1) +#define DEVEN_D0EN (1 << 0) #define PAM0 0x80 #define PAM1 0x81 @@ -123,9 +108,14 @@ #define MCHBAR32(x) *((volatile u32 *)(DEFAULT_MCHBAR + x)) #define MCHBAR32_OR(x, or) MCHBAR32(x) = (MCHBAR32(x) | (or)) -#define SSKPD 0x5d14 /* 16bit (scratchpad) */ #define BIOS_RESET_CPL 0x5da8 /* 8bit */ +/* Some power MSRs are also represented in MCHBAR */ +#define MCH_PKG_POWER_LIMIT_LO 0x59a0 +#define MCH_PKG_POWER_LIMIT_HI 0x59a4 +#define MCH_DDR_POWER_LIMIT_LO 0x58e0 +#define MCH_DDR_POWER_LIMIT_HI 0x58e4 + /* * EPBAR - Egress Port Root Complex Register Block */ @@ -210,9 +200,9 @@ struct ied_header { #ifdef __SMM__ void intel_northbridge_haswell_finalize_smm(void); #else /* !__SMM__ */ -int bridge_silicon_revision(void); void haswell_early_initialization(int chipset_type); void haswell_late_initialization(void); +void set_translation_table(int start, int end, u64 base, int inc); /* debugging functions */ void print_pci_devices(void); @@ -237,8 +227,6 @@ struct mrc_data_container { struct mrc_data_container *find_current_mrc_cache(void); #if !defined(__PRE_RAM__) -void update_mrc_cache(void); - #include "gma.h" int init_igd_opregion(igd_opregion_t *igd_opregion); #endif diff --git a/src/northbridge/intel/haswell/minihd.c b/src/northbridge/intel/haswell/minihd.c new file mode 100644 index 0000000000..cef61263be --- /dev/null +++ b/src/northbridge/intel/haswell/minihd.c @@ -0,0 +1,140 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const u32 minihd_verb_table[] = { + /* coreboot specific header */ + 0x80862807, // Codec Vendor / Device ID: Intel Haswell Mini-HD + 0x00000000, // Subsystem ID + 0x00000004, // Number of jacks + + /* Enable 3rd Pin and Converter Widget */ + 0x00878101, + + /* Pin Widget 5 - PORT B */ + 0x00571C10, + 0x00571D00, + 0x00571E56, + 0x00571F18, + + /* Pin Widget 6 - PORT C */ + 0x00671C20, + 0x00671D00, + 0x00671E56, + 0x00671F18, + + /* Pin Widget 7 - PORT D */ + 0x00771C30, + 0x00771D00, + 0x00771E56, + 0x00771F18, + + /* Disable 3rd Pin and Converter Widget */ + 0x00878100, + + /* Dummy entries to fill out the table */ + 0x00878100, + 0x00878100, +}; + +static void minihd_init(struct device *dev) +{ + struct resource *res; + u32 base, reg32; + int codec_mask, i; + + /* Find base address */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "Mini-HD: base = %08x\n", (u32)base); + + /* Set Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER); + + /* Mini-HD configuration */ + reg32 = read32(base + 0x100c); + reg32 &= 0xfffc0000; + reg32 |= 0x4; + write32(base + 0x100c, reg32); + + reg32 = read32(base + 0x1010); + reg32 &= 0xfffc0000; + reg32 |= 0x4b; + write32(base + 0x1010, reg32); + + /* Init the codec and write the verb table */ + codec_mask = hda_codec_detect(base); + + if (codec_mask) { + for (i = 3; i >= 0; i--) { + if (codec_mask & (1 << i)) + hda_codec_init(base, i, + sizeof(minihd_verb_table), + minihd_verb_table); + } + } +} + +static void minihd_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + } +} + +static struct pci_operations minihd_pci_ops = { + .set_subsystem = minihd_set_subsystem, +}; + +static struct device_operations minihd_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = minihd_init, + .scan_bus = 0, + .ops_pci = &minihd_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { 0x0a0c, 0 }; + +static const struct pci_driver haswell_minihd __pci_driver = { + .ops = &minihd_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; + diff --git a/src/northbridge/intel/haswell/mrccache.c b/src/northbridge/intel/haswell/mrccache.c index 032bae4131..cbfcd8ce40 100644 --- a/src/northbridge/intel/haswell/mrccache.c +++ b/src/northbridge/intel/haswell/mrccache.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -153,7 +154,7 @@ static struct mrc_data_container *find_next_mrc_cache return mrc_cache; } -void update_mrc_cache(void) +static void update_mrc_cache(void *unused) { printk(BIOS_DEBUG, "Updating MRC cache data.\n"); struct mrc_data_container *current = cbmem_find(CBMEM_ID_MRCDATA); @@ -191,7 +192,7 @@ void update_mrc_cache(void) // 1. use spi_flash_probe() to find the flash, then spi_init(); - struct spi_flash *flash = spi_flash_probe(0, 0, 1000000, SPI_MODE_3); + struct spi_flash *flash = spi_flash_probe(0, 0); if (!flash) { printk(BIOS_DEBUG, "Could not find SPI device\n"); return; @@ -222,6 +223,11 @@ void update_mrc_cache(void) flash->write(flash, to_flash_offset(cache), current->mrc_data_size + sizeof(*current), current); } + +BOOT_STATE_INIT_ENTRIES(mrc_cache_update) = { + BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, + update_mrc_cache, NULL), +}; #endif struct mrc_data_container *find_current_mrc_cache(void) diff --git a/src/northbridge/intel/haswell/northbridge.c b/src/northbridge/intel/haswell/northbridge.c index 16196ad6ad..ec8fdd5702 100644 --- a/src/northbridge/intel/haswell/northbridge.c +++ b/src/northbridge/intel/haswell/northbridge.c @@ -39,25 +39,6 @@ #include "chip.h" #include "haswell.h" -static int bridge_revision_id = -1; - -int bridge_silicon_revision(void) -{ - if (bridge_revision_id < 0) { - uint8_t stepping = cpuid_eax(1) & 0xf; - uint8_t bridge_id = pci_read_config16( - dev_find_slot(0, PCI_DEVFN(0, 0)), - PCI_DEVICE_ID) & 0xf0; - bridge_revision_id = bridge_id | stepping; - } - return bridge_revision_id; -} - -void cbmem_post_handling(void) -{ - update_mrc_cache(); -} - static int get_pcie_bar(device_t dev, unsigned int index, u32 *base, u32 *len) { u32 pciexbar_reg; @@ -317,6 +298,7 @@ static void mc_report_map_entries(device_t dev, uint64_t *values) static void mc_add_dram_resources(device_t dev) { unsigned long base_k, size_k; + unsigned long touud_k; unsigned long index; struct resource *resource; uint64_t mc_values[NUM_MAP_ENTRIES]; @@ -401,8 +383,9 @@ static void mc_add_dram_resources(device_t dev) /* 4GiB -> TOUUD */ base_k = 4096 * 1024; /* 4GiB */ - size_k = (unsigned long)(mc_values[TOUUD_REG] >> 10) - base_k; - if (size_k > 0) + touud_k = mc_values[TOUUD_REG] >> 10; + size_k = touud_k - base_k; + if (touud_k > base_k) ram_resource(dev, index++, base_k, size_k); /* Reserve everything between A segment and 1MB: @@ -443,84 +426,22 @@ static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device) } } -static void northbridge_dmi_init(struct device *dev) -{ - u32 reg32; - - /* Clear error status bits */ - DMIBAR32(0x1c4) = 0xffffffff; - DMIBAR32(0x1d0) = 0xffffffff; - - /* Steps prior to DMI ASPM */ - if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) { - reg32 = DMIBAR32(0x250); - reg32 &= ~((1 << 22)|(1 << 20)); - reg32 |= (1 << 21); - DMIBAR32(0x250) = reg32; - } - - reg32 = DMIBAR32(0x238); - reg32 |= (1 << 29); - DMIBAR32(0x238) = reg32; - - if (bridge_silicon_revision() >= SNB_STEP_D0) { - reg32 = DMIBAR32(0x1f8); - reg32 |= (1 << 16); - DMIBAR32(0x1f8) = reg32; - } else if (bridge_silicon_revision() >= SNB_STEP_D1) { - reg32 = DMIBAR32(0x1f8); - reg32 &= ~(1 << 26); - reg32 |= (1 << 16); - DMIBAR32(0x1f8) = reg32; - - reg32 = DMIBAR32(0x1fc); - reg32 |= (1 << 12) | (1 << 23); - DMIBAR32(0x1fc) = reg32; - } - - /* Enable ASPM on SNB link, should happen before PCH link */ - if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) { - reg32 = DMIBAR32(0xd04); - reg32 |= (1 << 4); - DMIBAR32(0xd04) = reg32; - } - - reg32 = DMIBAR32(0x88); - reg32 |= (1 << 1) | (1 << 0); - DMIBAR32(0x88) = reg32; -} - static void northbridge_init(struct device *dev) { - u8 bios_reset_cpl; - u32 bridge_type; + u8 bios_reset_cpl, pair; - northbridge_dmi_init(dev); - - bridge_type = MCHBAR32(0x5f10); - bridge_type &= ~0xff; - - if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) { - /* Enable Power Aware Interrupt Routing */ - u8 pair = MCHBAR8(0x5418); - pair &= ~0xf; /* Clear 3:0 */ - pair |= 0x4; /* Fixed Priority */ - MCHBAR8(0x5418) = pair; - - /* 30h for IvyBridge */ - bridge_type |= 0x30; - } else { - /* 20h for Sandybridge */ - bridge_type |= 0x20; - } - MCHBAR32(0x5f10) = bridge_type; + /* Enable Power Aware Interrupt Routing */ + pair = MCHBAR8(0x5418); + pair &= ~0x7; /* Clear 2:0 */ + pair |= 0x4; /* Fixed Priority */ + MCHBAR8(0x5418) = pair; /* - * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU + * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU * that BIOS has initialized memory and power management */ bios_reset_cpl = MCHBAR8(BIOS_RESET_CPL); - bios_reset_cpl |= 1; + bios_reset_cpl |= 3; MCHBAR8(BIOS_RESET_CPL) = bios_reset_cpl; printk(BIOS_DEBUG, "Set BIOS_RESET_CPL\n"); @@ -528,16 +449,6 @@ static void northbridge_init(struct device *dev) mdelay(1); set_power_limits(28); - /* - * CPUs with configurable TDP also need power limits set - * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT. - */ - if (cpu_config_tdp_levels()) { - msr_t msr = rdmsr(MSR_PKG_POWER_LIMIT); - MCHBAR32(0x59A0) = msr.lo; - MCHBAR32(0x59A4) = msr.hi; - } - /* Set here before graphics PM init */ MCHBAR32(0x5500) = 0x00100001; } diff --git a/src/northbridge/intel/haswell/pei_data.h b/src/northbridge/intel/haswell/pei_data.h index 280c73b75a..f92c0a68e0 100644 --- a/src/northbridge/intel/haswell/pei_data.h +++ b/src/northbridge/intel/haswell/pei_data.h @@ -31,7 +31,37 @@ #define PEI_DATA_H typedef void (*tx_byte_func)(unsigned char byte); -#define PEI_VERSION 10 +#define PEI_VERSION 15 + +#define MAX_USB2_PORTS 16 +#define MAX_USB3_PORTS 16 +#define USB_OC_PIN_SKIP 8 + +enum usb2_port_location { + USB_PORT_BACK_PANEL = 0, + USB_PORT_FRONT_PANEL, + USB_PORT_DOCK, + USB_PORT_MINI_PCIE, + USB_PORT_FLEX, + USB_PORT_INTERNAL, + USB_PORT_SKIP +}; + +/* Usb Port Length: + * [16:4] = length in inches in octal format + * [3:0] = decimal point + */ +struct usb2_port_setting { + uint16_t length; + uint8_t enable; + uint8_t over_current_pin; + uint8_t location; +} __attribute__((packed)); + +struct usb3_port_setting { + uint8_t enable; + uint8_t over_current_pin; +} __attribute__((packed)); struct pei_data { @@ -53,12 +83,16 @@ struct pei_data uint8_t spd_addresses[4]; int boot_mode; int ec_present; + int gbe_enable; // 0 = leave channel enabled // 1 = disable dimm 0 on channel // 2 = disable dimm 1 on channel // 3 = disable dimm 0+1 on channel int dimm_channel0_disabled; int dimm_channel1_disabled; + /* Enable 2x Refresh Mode */ + int ddr_refresh_2x; + int dq_pins_interleaved; /* Data read from flash and passed into MRC */ unsigned char *mrc_input; unsigned int mrc_input_len; @@ -66,33 +100,14 @@ struct pei_data unsigned char *mrc_output; unsigned int mrc_output_len; /* - * Max frequency DDR3 could be ran at. Could be one of four values: 800, - * 1067, 1333, 1600 - */ + * Max frequency DDR3 could be ran at. Could be one of four values: 800, + * 1067, 1333, 1600 + */ uint32_t max_ddr3_freq; - /* - * USB Port Configuration: - * [0] = enable - * [1] = overcurrent pin - * [2] = length - * - * Ports 0-7 can be mapped to OC0-OC3 - * Ports 8-13 can be mapped to OC4-OC7 - * - * Port Length - * MOBILE: - * < 0x050 = Setting 1 (back panel, 1-5in, lowest tx amplitude) - * < 0x140 = Setting 2 (back panel, 5-14in, highest tx amplitude) - * DESKTOP: - * < 0x080 = Setting 1 (front/back panel, <8in, lowest tx amplitude) - * < 0x130 = Setting 2 (back panel, 8-13in, higher tx amplitude) - * < 0x150 = Setting 3 (back panel, 13-15in, higest tx amplitude) - */ - uint16_t usb_port_config[16][3]; - /* SPD data array for onboard RAM. Specify address 0xf0, - * 0xf1, 0xf2, 0xf3 to index one of the 4 slots in - * spd_address for a given "DIMM". - */ + /* Route all USB ports to XHCI controller in resume path */ + int usb_xhci_on_resume; + struct usb2_port_setting usb2_ports[MAX_USB2_PORTS]; + struct usb3_port_setting usb3_ports[MAX_USB3_PORTS]; uint8_t spd_data[4][256]; tx_byte_func tx_byte; } __attribute__((packed)); diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index c1095a7eb7..1b1a42b365 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -123,14 +123,14 @@ static void report_memory_config(void) ((ch_conf >> 22) & 1) ? "on" : "off"); printk(BIOS_DEBUG, " rank interleave %s\n", ((ch_conf >> 21) & 1) ? "on" : "off"); - printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n", + printk(BIOS_DEBUG, " DIMMA %d MB width %s %s rank%s\n", ((ch_conf >> 0) & 0xff) * 256, - ((ch_conf >> 19) & 1) ? 16 : 8, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", ((ch_conf >> 17) & 1) ? "dual" : "single", ((ch_conf >> 16) & 1) ? "" : ", selected"); - printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n", + printk(BIOS_DEBUG, " DIMMB %d MB width %s %s rank%s\n", ((ch_conf >> 8) & 0xff) * 256, - ((ch_conf >> 20) & 1) ? 16 : 8, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", ((ch_conf >> 18) & 1) ? "dual" : "single", ((ch_conf >> 16) & 1) ? ", selected" : ""); } @@ -156,7 +156,9 @@ void sdram_initialize(struct pei_data *pei_data) /* If MRC data is not found we cannot continue S3 resume. */ if (pei_data->boot_mode == 2 && !pei_data->mrc_input) { - printk(BIOS_DEBUG, "Giving up in sdram_initialize: No MRC data\n"); + post_code(POST_RESUME_FAILURE); + printk(BIOS_DEBUG, "Giving up in sdram_initialize: " + "No MRC data\n"); outb(0x6, 0xcf9); while(1) { hlt(); diff --git a/src/northbridge/intel/haswell/udelay.c b/src/northbridge/intel/haswell/udelay.c deleted file mode 100644 index f5d541e8e1..0000000000 --- a/src/northbridge/intel/haswell/udelay.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007-2008 coresystems GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include "cpu/intel/haswell/haswell.h" - -/* Simple 32- to 64-bit multiplication. Uses 16-bit words to avoid overflow. */ -static inline void multiply_to_tsc(tsc_t *const tsc, const u32 a, const u32 b) -{ - tsc->lo = (a & 0xffff) * (b & 0xffff); - tsc->hi = ((tsc->lo >> 16) - + ((a & 0xffff) * (b >> 16)) - + ((b & 0xffff) * (a >> 16))); - tsc->lo = ((tsc->hi & 0xffff) << 16) | (tsc->lo & 0xffff); - tsc->hi = ((a >> 16) * (b >> 16)) + (tsc->hi >> 16); -} - -void udelay(u32 us) -{ - u32 dword; - tsc_t tsc, tsc1, tscd; - msr_t msr; - u32 divisor; - u32 d; /* ticks per us */ - - msr = rdmsr(MSR_PLATFORM_INFO); - divisor = (msr.lo >> 8) & 0xff; - - d = HASWELL_BCLK * divisor; - multiply_to_tsc(&tscd, us, d); - - tsc1 = rdtsc(); - dword = tsc1.lo + tscd.lo; - if ((dword < tsc1.lo) || (dword < tscd.lo)) { - tsc1.hi++; - } - tsc1.lo = dword; - tsc1.hi += tscd.hi; - - do { - tsc = rdtsc(); - } while ((tsc.hi < tsc1.hi) - || ((tsc.hi == tsc1.hi) && (tsc.lo <= tsc1.lo))); -} diff --git a/src/northbridge/intel/i3100/raminit.h b/src/northbridge/intel/i3100/raminit.h index 03e145826a..ea6c60f1aa 100644 --- a/src/northbridge/intel/i3100/raminit.h +++ b/src/northbridge/intel/i3100/raminit.h @@ -30,8 +30,6 @@ struct mem_controller { u16 channel1[DIMM_SOCKETS]; }; -#ifndef __ROMCC__ void sdram_initialize(int controllers, const struct mem_controller *ctrl); -#endif #endif diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig index 6c9ae99fcd..56d2cd7a38 100644 --- a/src/northbridge/intel/sandybridge/Kconfig +++ b/src/northbridge/intel/sandybridge/Kconfig @@ -107,14 +107,6 @@ config DCACHE_RAM_MRC_VAR_SIZE hex default 0x4000 -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_MRC bool "Add a System Agent binary" help diff --git a/src/northbridge/intel/sandybridge/Makefile.inc b/src/northbridge/intel/sandybridge/Makefile.inc index 01b328b4bf..516a884120 100644 --- a/src/northbridge/intel/sandybridge/Makefile.inc +++ b/src/northbridge/intel/sandybridge/Makefile.inc @@ -42,5 +42,3 @@ ifeq ($(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE),y) mrc.bin-position := 0xfffe0000 endif mrc.bin-type := 0xab - -$(obj)/northbridge/intel/sandybridge/acpi.ramstage.o : $(obj)/build.h diff --git a/src/northbridge/intel/sandybridge/mrccache.c b/src/northbridge/intel/sandybridge/mrccache.c index 9c6330ca34..38e0afab51 100644 --- a/src/northbridge/intel/sandybridge/mrccache.c +++ b/src/northbridge/intel/sandybridge/mrccache.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -153,7 +154,7 @@ static struct mrc_data_container *find_next_mrc_cache return mrc_cache; } -void update_mrc_cache(void) +static void update_mrc_cache(void *unused) { printk(BIOS_DEBUG, "Updating MRC cache data.\n"); struct mrc_data_container *current = cbmem_find(CBMEM_ID_MRCDATA); @@ -191,7 +192,7 @@ void update_mrc_cache(void) // 1. use spi_flash_probe() to find the flash, then spi_init(); - struct spi_flash *flash = spi_flash_probe(0, 0, 1000000, SPI_MODE_3); + struct spi_flash *flash = spi_flash_probe(0, 0); if (!flash) { printk(BIOS_DEBUG, "Could not find SPI device\n"); return; @@ -222,6 +223,11 @@ void update_mrc_cache(void) flash->write(flash, to_flash_offset(cache), current->mrc_data_size + sizeof(*current), current); } + +BOOT_STATE_INIT_ENTRIES(mrc_cache_update) = { + BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, + update_mrc_cache, NULL), +}; #endif struct mrc_data_container *find_current_mrc_cache(void) diff --git a/src/northbridge/intel/sandybridge/northbridge.c b/src/northbridge/intel/sandybridge/northbridge.c index b8022b8cea..0a413b4c7b 100644 --- a/src/northbridge/intel/sandybridge/northbridge.c +++ b/src/northbridge/intel/sandybridge/northbridge.c @@ -60,11 +60,6 @@ int bridge_silicon_revision(void) static const int legacy_hole_base_k = 0xa0000 / 1024; static const int legacy_hole_size_k = 384; -void cbmem_post_handling(void) -{ - update_mrc_cache(); -} - static int get_pcie_bar(u32 *base, u32 *len) { device_t dev; diff --git a/src/northbridge/intel/sandybridge/pei_data.h b/src/northbridge/intel/sandybridge/pei_data.h index fb56873d2b..5e0ff0f56b 100644 --- a/src/northbridge/intel/sandybridge/pei_data.h +++ b/src/northbridge/intel/sandybridge/pei_data.h @@ -38,7 +38,7 @@ typedef struct { } pch_usb3_controller_settings; typedef void (*tx_byte_func)(unsigned char byte); -#define PEI_VERSION 5 +#define PEI_VERSION 6 struct pei_data { @@ -61,6 +61,7 @@ struct pei_data uint8_t ts_addresses[4]; int boot_mode; int ec_present; + int gbe_enable; // 0 = leave channel enabled // 1 = disable dimm 0 on channel // 2 = disable dimm 1 on channel @@ -120,6 +121,14 @@ struct pei_data * 2 2N */ int nmode; + /* DDR refresh rate config. JEDEC Standard No.21-C Annex K allows + * for DIMM SPD data to specify whether double-rate is required for + * extended operating temperature range. + * 0 Enable double rate based upon temperature thresholds + * 1 Normal rate + * 2 Always enable double rate + */ + int ddr_refresh_rate_config; } __attribute__((packed)); #endif diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index 78eedb89db..172872d552 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -63,6 +63,9 @@ static void save_mrc_data(struct pei_data *pei_data) int output_len = ALIGN(pei_data->mrc_output_len, 16); /* Save the MRC S3 restore data to cbmem */ + /* TODO: cbmem_initialize() must not be called twice! Most sandybridge + * boards call it again from mainboard/romstage.c. Clean up these code + * paths to ensure it is called at most once with every config. */ cbmem_initialize(); mrcdata = cbmem_add (CBMEM_ID_MRCDATA, diff --git a/src/northbridge/intel/sandybridge/sandybridge.h b/src/northbridge/intel/sandybridge/sandybridge.h index bb1b1a396f..291ea46d8b 100644 --- a/src/northbridge/intel/sandybridge/sandybridge.h +++ b/src/northbridge/intel/sandybridge/sandybridge.h @@ -233,8 +233,6 @@ struct mrc_data_container { struct mrc_data_container *find_current_mrc_cache(void); #if !defined(__PRE_RAM__) -void update_mrc_cache(void); - #include "gma.h" int init_igd_opregion(igd_opregion_t *igd_opregion); #endif diff --git a/src/northbridge/via/cx700/lpc.c b/src/northbridge/via/cx700/lpc.c index 22e8743e8e..8e48b30e07 100644 --- a/src/northbridge/via/cx700/lpc.c +++ b/src/northbridge/via/cx700/lpc.c @@ -283,7 +283,7 @@ static void cx700_lpc_init(struct device *dev) setup_i8259(); /* Start the Real Time Clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/northbridge/via/vx800/Makefile.inc b/src/northbridge/via/vx800/Makefile.inc index 39ebdbd998..5e34c691c2 100644 --- a/src/northbridge/via/vx800/Makefile.inc +++ b/src/northbridge/via/vx800/Makefile.inc @@ -23,5 +23,6 @@ ramstage-y += vga.c ramstage-y += lpc.c ramstage-y += ide.c +bootblock-y += romstrap.ld + chipset_bootblock_inc += $(src)/northbridge/via/vx800/romstrap.inc -chipset_bootblock_lds += $(src)/northbridge/via/vx800/romstrap.lds diff --git a/src/northbridge/via/vx800/examples/chipset_init.c b/src/northbridge/via/vx800/examples/chipset_init.c index 1e06d478b6..3f9c70fe10 100644 --- a/src/northbridge/via/vx800/examples/chipset_init.c +++ b/src/northbridge/via/vx800/examples/chipset_init.c @@ -604,7 +604,7 @@ void init_VIA_chipset(void) * In the dev_enumerate() phase, */ -void hardwaremain(int boot_complete) +void main(void) { struct lb_memory *lb_mem; #if CONFIG_HAVE_ACPI_RESUME diff --git a/src/northbridge/via/vx800/lpc.c b/src/northbridge/via/vx800/lpc.c index 9e1fa57837..a1b8ff3e4c 100644 --- a/src/northbridge/via/vx800/lpc.c +++ b/src/northbridge/via/vx800/lpc.c @@ -295,7 +295,7 @@ static void vx800_sb_init(struct device *dev) pci_write_config8(dev, 0x40, 0x54); // Start the rtc - rtc_init(0); + cmos_init(0); } /* total kludge to get lxb to call our childrens set/enable functions - these are diff --git a/src/northbridge/via/vx800/romstrap.lds b/src/northbridge/via/vx800/romstrap.ld similarity index 100% rename from src/northbridge/via/vx800/romstrap.lds rename to src/northbridge/via/vx800/romstrap.ld diff --git a/src/soc/Kconfig b/src/soc/Kconfig new file mode 100644 index 0000000000..8e0dad9263 --- /dev/null +++ b/src/soc/Kconfig @@ -0,0 +1,7 @@ +source src/soc/imgtec/Kconfig +source src/soc/intel/Kconfig +source src/soc/marvell/Kconfig +source src/soc/nvidia/Kconfig +source src/soc/qualcomm/Kconfig +source src/soc/samsung/Kconfig +source src/soc/rockchip/Kconfig diff --git a/src/soc/Makefile.inc b/src/soc/Makefile.inc new file mode 100644 index 0000000000..2886727a64 --- /dev/null +++ b/src/soc/Makefile.inc @@ -0,0 +1,10 @@ +################################################################################ +## Subdirectories +################################################################################ +subdirs-y += imgtec +subdirs-y += intel +subdirs-y += marvell +subdirs-y += nvidia +subdirs-y += qualcomm +subdirs-y += samsung +subdirs-y += rockchip diff --git a/src/soc/imgtec/Kconfig b/src/soc/imgtec/Kconfig new file mode 100644 index 0000000000..df51850f70 --- /dev/null +++ b/src/soc/imgtec/Kconfig @@ -0,0 +1 @@ +source src/soc/imgtec/pistachio/Kconfig diff --git a/src/soc/imgtec/Makefile.inc b/src/soc/imgtec/Makefile.inc new file mode 100644 index 0000000000..60a99091a1 --- /dev/null +++ b/src/soc/imgtec/Makefile.inc @@ -0,0 +1 @@ +subdirs-$(CONFIG_CPU_IMGTEC_PISTACHIO) += pistachio diff --git a/src/soc/imgtec/pistachio/Kconfig b/src/soc/imgtec/pistachio/Kconfig new file mode 100644 index 0000000000..f9d369a83a --- /dev/null +++ b/src/soc/imgtec/pistachio/Kconfig @@ -0,0 +1,41 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +config CPU_IMGTEC_PISTACHIO + select CPU_MIPS + select DYNAMIC_CBMEM + select GENERIC_UDELAY + select HAVE_MONOTONIC_TIMER + select CONSOLE_SERIAL + select EARLY_CONSOLE + select HAVE_UART_MEMORY_MAPPED + select HAVE_UART_SPECIAL + select SPI_ATOMIC_SEQUENCING + select GENERIC_GPIO_LIB + bool + +if CPU_IMGTEC_PISTACHIO + +config BOOTBLOCK_CPU_INIT + string + default "soc/imgtec/pistachio/bootblock.c" + +endif diff --git a/src/soc/imgtec/pistachio/Makefile.inc b/src/soc/imgtec/pistachio/Makefile.inc new file mode 100644 index 0000000000..15d7c944a7 --- /dev/null +++ b/src/soc/imgtec/pistachio/Makefile.inc @@ -0,0 +1,55 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2014 Imagination Technologies +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of +# the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# + +# We enable CBFS_SPI_WRAPPER for Pistachio targets. +bootblock-y += spi.c +romstage-y += spi.c +ramstage-y += spi.c + +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c +romstage-y += uart.c +ramstage-y += uart.c +endif + +bootblock-y += monotonic_timer.c + +ramstage-y += cbmem.c +ramstage-y += monotonic_timer.c +ramstage-y += soc.c + +romstage-y += cbmem.c +romstage-y += romstage.c +romstage-y += monotonic_timer.c + +INCLUDES += -Isrc/soc/imgtec/pistachio/include/ + +# Generate the actual coreboot bootblock code +$(objcbfs)/bootblock.raw: $(objcbfs)/bootblock.elf + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + $(OBJCOPY_bootblock) -O binary $< $@.tmp + @mv $@.tmp $@ + +# Create a complete bootblock which will start up the system +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw $(BIMGTOOL) + @printf " BIMGTOOL $(subst $(obj)/,,$(@))\n" + $(BIMGTOOL) $< $@ $(call loadaddr,bootblock) + diff --git a/src/soc/imgtec/pistachio/bootblock.c b/src/soc/imgtec/pistachio/bootblock.c new file mode 100644 index 0000000000..90112646c4 --- /dev/null +++ b/src/soc/imgtec/pistachio/bootblock.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +static void bootblock_cpu_init(void) +{ + uint32_t cause; + + /* + * Make sure the count register is counting by clearing the "Disable + * Counter" bit, in case it is set. + */ + cause = read_c0_cause(); + if (cause & C0_CAUSE_DC) + write_c0_cause(cause & ~(C0_CAUSE_DC)); + + /* And make sure that it starts from zero. */ + write_c0_count(0); +} diff --git a/src/soc/imgtec/pistachio/cbmem.c b/src/soc/imgtec/pistachio/cbmem.c new file mode 100644 index 0000000000..e717544922 --- /dev/null +++ b/src/soc/imgtec/pistachio/cbmem.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include + +void *cbmem_top(void) +{ + return _dram + (CONFIG_DRAM_SIZE_MB << 20); +} + diff --git a/src/soc/imgtec/pistachio/include/soc/cpu.h b/src/soc/imgtec/pistachio/include/soc/cpu.h new file mode 100644 index 0000000000..72775b5cbe --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/cpu.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOC_IMGTEC_DANUBE_CPU_H__ +#define __SOC_IMGTEC_DANUBE_CPU_H__ + +#define IMG_SPIM0_BASE_ADDRESS 0xB8100F00 +#define IMG_SPIM1_BASE_ADDRESS 0xB8101000 + +/* + * Reading at this address allows to identify the platform the code is running + * on. + */ +#define IMG_PLATFORM_ID() (*((unsigned *)0xB8149060)) +#define IMG_PLATFORM_ID_SILICON 0xF00D0006 + +#endif diff --git a/src/soc/imgtec/pistachio/include/soc/gpio.h b/src/soc/imgtec/pistachio/include/soc/gpio.h new file mode 100644 index 0000000000..8cd3e3f3f6 --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/gpio.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_IMGTECH_PISTACHIO_GPIO_H__ +#define __SOC_IMGTECH_PISTACHIO_GPIO_H__ + +typedef unsigned gpio_t; + +#endif // __SOC_IMGTECH_PISTACHIO_GPIO_H__ diff --git a/src/soc/imgtec/pistachio/include/soc/memlayout.ld b/src/soc/imgtec/pistachio/include/soc/memlayout.ld new file mode 100644 index 0000000000..554ebfc04f --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/memlayout.ld @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +SECTIONS +{ + DRAM_START(0x80000000) + RAMSTAGE(0x80000000, 128K) + + /* GRAM becomes the SRAM. */ + SRAM_START(0x9a000000) + BOOTBLOCK(0x9a000000, 16K) + ROMSTAGE(0x9a004000, 32K) + STACK(0x9a01c000, 8K) + PRERAM_CBMEM_CONSOLE(0x9a01e000, 8K) + SRAM_END(0x9a020000) + + /* Let's use SRAM for CBFS cache. */ + CBFS_CACHE(0x9b000000, 64K) +} diff --git a/src/soc/imgtec/pistachio/include/soc/spi.h b/src/soc/imgtec/pistachio/include/soc/spi.h new file mode 100644 index 0000000000..8b4f06bfbb --- /dev/null +++ b/src/soc/imgtec/pistachio/include/soc/spi.h @@ -0,0 +1,358 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#ifndef __SOC_IMGTEC_DANUBE_SPI_H__ +#define __SOC_IMGTEC_DANUBE_SPI_H__ + +#include +#include + +#define spi_read_reg_field(regval, field) \ +( \ + ((field##_MASK) == 0xFFFFFFFF) ? \ + (regval) : \ + (((regval) & (field##_MASK)) >> (field##_SHIFT))\ +) + +#define spi_write_reg_field(regval, field, val) \ +( \ + ((field##_MASK) == 0xFFFFFFFF) ? \ + (val) : \ + (((regval) & ~(field##_MASK)) | \ + (((val) << (field##_SHIFT)) & (field##_MASK))) \ +) + +/* + * Parameter register + * Each of these corresponds to a single port (ie CS line) in the interface + * Fields Name Description + * ====== ==== =========== + * b31:24 CLK_RATE Bit Clock rate = (24.576 * value / 512) MHz + * b23:16 CS_SETUP Chip Select setup = (40 * value) ns + * b15:8 CS_HOLD Chip Select hold = (40 * value) ns + * b7:0 CS_DELAY Chip Select delay = (40 * value) ns + */ + +#define SPIM_CLK_DIVIDE_MASK (0xFF000000) +#define SPIM_CS_SETUP_MASK (0x00FF0000) +#define SPIM_CS_HOLD_MASK (0x0000FF00) +#define SPIM_CS_DELAY_MASK (0x000000FF) +#define SPIM_CS_PARAM_MASK (SPIM_CS_SETUP_MASK \ + | SPIM_CS_HOLD_MASK \ + | SPIM_CS_DELAY_MASK) + +#define SPIM_CLK_DIVIDE_SHIFT (24) +#define SPIM_CS_SETUP_SHIFT (16) +#define SPIM_CS_HOLD_SHIFT (8) +#define SPIM_CS_DELAY_SHIFT (0) +#define SPIM_CS_PARAM_SHIFT (0) + +/* Control register */ + +#define SPFI_DRIBBLE_COUNT_MASK (0x000e0000) +#define SPFI_MEMORY_IF_MASK (0x00008000) +#define SPIM_BYTE_DELAY_MASK (0x00004000) +#define SPIM_CS_DEASSERT_MASK (0x00002000) +#define SPIM_CONTINUE_MASK (0x00001000) +#define SPIM_SOFT_RESET_MASK (0x00000800) +#define SPIM_SEND_DMA_MASK (0x00000400) +#define SPIM_GET_DMA_MASK (0x00000200) +#define SPIM_EDGE_TX_RX_MASK (0x00000100) +#define SPFI_TRNSFR_MODE_MASK (0x000000e0) +#define SPFI_TRNSFR_MODE_DQ_MASK (0x0000001c) +#define SPFI_TX_RX_MASK (0x00000002) +#define SPFI_EN_MASK (0x00000001) + +#define SPFI_DRIBBLE_COUNT_SHIFT (17) +#define SPFI_MEMORY_IF_SHIFT (15) +#define SPIM_BYTE_DELAY_SHIFT (14) +#define SPIM_CS_DEASSERT_SHIFT (13) +#define SPIM_CONTINUE_SHIFT (12) +#define SPIM_SOFT_RESET_SHIFT (11) +#define SPIM_SEND_DMA_SHIFT (10) +#define SPIM_GET_DMA_SHIFT (9) +#define SPIM_EDGE_TX_RX_SHIFT (8) +#define SPFI_TRNSFR_MODE_SHIFT (5) +#define SPFI_TRNSFR_MODE_DQ_SHIFT (2) +#define SPFI_TX_RX_SHIFT (1) +#define SPFI_EN_SHIFT (0) + +/* Transaction register*/ + +#define SPFI_TSIZE_MASK (0xffff0000) +#define SPFI_CMD_LENGTH_MASK (0x0000e000) +#define SPFI_ADDR_LENGTH_MASK (0x00001c00) +#define SPFI_DUMMY_LENGTH_MASK (0x000003e0) +#define SPFI_PI_LENGTH_MASK (0x0000001c) + +#define SPFI_TSIZE_SHIFT (16) +#define SPFI_CMD_LENGTH_SHIFT (13) +#define SPFI_ADDR_LENGTH_SHIFT (10) +#define SPFI_DUMMY_LENGTH_SHIFT (5) +#define SPFI_PI_LENGTH_SHIFT (2) + +/* Port state register */ + +#define SPFI_PORT_SELECT_MASK (0x00700000) +/* WARNING the following bits are reversed */ +#define SPFI_CLOCK0_IDLE_MASK (0x000f8000) +#define SPFI_CLOCK0_PHASE_MASK (0x00007c00) +#define SPFI_CS0_IDLE_MASK (0x000003e0) +#define SPFI_DATA0_IDLE_MASK (0x0000001f) + +#define SPIM_CLOCK0_IDLE_MASK (0x000f8000) +#define SPIM_CLOCK0_PHASE_MASK (0x00007c00) +#define SPIM_CS0_IDLE_MASK (0x000003e0) +#define SPIM_DATA0_IDLE_MASK (0x0000001f) + +#define SPIM_PORT0_MASK (0x00084210) + +#define SPFI_PORT_SELECT_SHIFT (20) +/* WARNING the following bits are reversed, bit 0 is highest */ +#define SPFI_CLOCK0_IDLE_SHIFT (19) +#define SPFI_CLOCK0_PHASE_SHIFT (14) +#define SPFI_CS0_IDLE_SHIFT (9) +#define SPFI_DATA0_IDLE_SHIFT (4) + +#define SPIM_CLOCK0_IDLE_SHIFT (19) +#define SPIM_CLOCK0_PHASE_SHIFT (14) +#define SPIM_CS0_IDLE_SHIFT (9) +#define SPIM_DATA0_IDLE_SHIFT (4) + + +/* + * Interrupt registers + * SPFI_GDOF_MASK means Rx buffer full, not an overflow, because clock stalls + * SPFI_SDUF_MASK means Tx buffer empty, not an underflow, because clock stalls + */ +#define SPFI_IACCESS_MASK (0x00001000) +#define SPFI_GDEX8BIT_MASK (0x00000800) +#define SPFI_ALLDONE_MASK (0x00000200) +#define SPFI_GDFUL_MASK (0x00000100) +#define SPFI_GDHF_MASK (0x00000080) +#define SPFI_GDEX32BIT_MASK (0x00000040) +#define SPFI_GDTRIG_MASK (0x00000020) +#define SPFI_SDFUL_MASK (0x00000008) +#define SPFI_SDHF_MASK (0x00000004) +#define SPFI_SDE_MASK (0x00000002) +#define SPFI_SDTRIG_MASK (0x00000001) + +#define SPFI_IACCESS_SHIFT (12) +#define SPFI_GDEX8BIT_SHIFT (11) +#define SPFI_ALLDONE_SHIFT (9) +#define SPFI_GDFUL_SHIFT (8) +#define SPFI_GDHF_SHIFT (7) +#define SPFI_GDEX32BIT_SHIFT (6) +#define SPFI_GDTRIG_SHIFT (5) +#define SPFI_SDFUL_SHIFT (3) +#define SPFI_SDHF_SHIFT (2) +#define SPFI_SDE_SHIFT (1) +#define SPFI_SDTRIG_SHIFT (0) + + +/* SPFI register block */ + +#define SPFI_PORT_0_PARAM_REG_OFFSET (0x00) +#define SPFI_PORT_1_PARAM_REG_OFFSET (0x04) +#define SPFI_PORT_2_PARAM_REG_OFFSET (0x08) +#define SPFI_PORT_3_PARAM_REG_OFFSET (0x0C) +#define SPFI_PORT_4_PARAM_REG_OFFSET (0x10) +#define SPFI_CONTROL_REG_OFFSET (0x14) +#define SPFI_TRANSACTION_REG_OFFSET (0x18) +#define SPFI_PORT_STATE_REG_OFFSET (0x1C) + +#define SPFI_SEND_LONG_REG_OFFSET (0x20) +#define SPFI_SEND_BYTE_REG_OFFSET (0x24) +#define SPFI_GET_LONG_REG_OFFSET (0x28) +#define SPFI_GET_BYTE_REG_OFFSET (0x2C) + +#define SPFI_INT_STATUS_REG_OFFSET (0x30) +#define SPFI_INT_ENABLE_REG_OFFSET (0x34) +#define SPFI_INT_CLEAR_REG_OFFSET (0x38) + +#define SPFI_IMMEDIATE_STATUS_REG_OFFSET (0x3c) + +#define SPFI_FLASH_BASE_ADDRESS_REG_OFFSET (0x48) +#define SPFI_FLASH_STATUS_REG_OFFSET (0x4C) + +#define IMG_FALSE 0 +#define IMG_TRUE 1 + +/* Number of SPIM interfaces*/ +#define SPIM_NUM_BLOCKS 2 +/* Number of chip select lines supported by the SPI master port. */ +#define SPIM_NUM_PORTS_PER_BLOCK (SPIM_DUMMY_CS) +/* Maximum transfer size (in bytes) for the SPI master port. */ +#define SPIM_MAX_TRANSFER_BYTES (0xFFFF) +/* Maximum size of a flash command: command bytes+address_bytes. */ +#define SPIM_MAX_FLASH_COMMAND_BYTES (0x8) +/* Write operation to fifo done in blocks of 16 words (64 bytes) */ +#define SPIM_MAX_BLOCK_BYTES (0x40) +/* Number of tries until timeout error is returned*/ +#define SPI_TIMEOUT_VALUE_US 500000 + +/* SPIM initialisation function return value.*/ +enum spim_return { + /* Initialisation parameters are valid. */ + SPIM_OK = 0, + /* Mode parameter is invalid. */ + SPIM_INVALID_SPI_MODE, + /* Chip select idle level is invalid. */ + SPIM_INVALID_CS_IDLE_LEVEL, + /* Data idle level is invalid. */ + SPIM_INVALID_DATA_IDLE_LEVEL, + /* Chip select line parameter is invalid. */ + SPIM_INVALID_CS_LINE, + /* Transfer size parameter is invalid. */ + SPIM_INVALID_SIZE, + /* Read/write parameter is invalid. */ + SPIM_INVALID_READ_WRITE, + /* Continue parameter is invalid. */ + SPIM_INVALID_CONTINUE, + /* Invalid block index */ + SPIM_INVALID_BLOCK_INDEX, + /* Extended error values */ + /* Invalid bit rate */ + SPIM_INVALID_BIT_RATE, + /* Invalid CS hold value */ + SPIM_INVALID_CS_HOLD_VALUE, + /* API function called before API is initialised */ + SPIM_API_NOT_INITIALISED, + /* SPI driver initialisation failed */ + SPIM_DRIVER_INIT_ERROR, + /* Invalid transfer description */ + SPIM_INVALID_TRANSFER_DESC, + /* Timeout */ + SPIM_TIMEOUT + +}; + +/* This type defines the SPI Mode.*/ +enum spim_mode { + /* Mode 0 (clock idle low, data valid on first clock transition). */ + SPIM_MODE_0 = 0, + /* Mode 1 (clock idle low, data valid on second clock transition). */ + SPIM_MODE_1, + /* Mode 2 (clock idle high, data valid on first clock transition). */ + SPIM_MODE_2, + /* Mode 3 (clock idle high, data valid on second clock transition). */ + SPIM_MODE_3 + +}; + +/* This type defines the SPIM device numbers (chip select lines). */ +enum spim_device { + /* Device 0 (CS0). */ + SPIM_DEVICE0 = 0, + /* Device 1 (CS1). */ + SPIM_DEVICE1, + /* Device 2 (CS2). */ + SPIM_DEVICE2, + /* Device 3 (CS3). */ + SPIM_DEVICE3, + /* Device 4 (CS4). */ + SPIM_DEVICE4, + /* Dummy chip select. */ + SPIM_DUMMY_CS + +}; + +/* This structure defines communication parameters for a slave device */ +struct spim_device_parameters { + /* Bit rate value.*/ + unsigned char bitrate; + /* + * Chip select set up time. + * Time taken between chip select going active and activity occurring + * on the clock, calculated by dividing the desired set up time in ns + * by the Input clock period. (setup time / Input clock freq) + */ + unsigned char cs_setup; + /* + * Chip select hold time. + * Time after the last clock pulse before chip select goes inactive, + * calculated by dividing the desired hold time in ns by the + * Input clock period (hold time / Input clock freq). + */ + unsigned char cs_hold; + /* + * Chip select delay time (CS minimum inactive time). + * Minimum time after chip select goes inactive before chip select + * can go active again, calculated by dividing the desired delay time + * in ns by the Input clock period (delay time / Input clock freq). + */ + unsigned char cs_delay; + /* SPI Mode. */ + enum spim_mode spi_mode; + /* Chip select idle level (0=low, 1=high, Others=invalid). */ + unsigned int cs_idle_level; + /* Data idle level (0=low, 1=high, Others=invalid). */ + unsigned int data_idle_level; + +}; + +/* Command transfer mode */ +enum command_mode { + /* Command, address, dummy and PI cycles are transferred on sio0 */ + SPIM_CMD_MODE_0 = 0, + /* + * Command and Address is transferred on sio0 port only but dummy + * cycles and PI is transferred on all the interface ports. + */ + SPIM_CMD_MODE_1, + /* + * Command is transferred on sio0 port only but address, dummy + * and PI is transferred on all the interface portS + */ + SPIM_CMD_MODE_2, + /* + * Command, address, dummy and PI bytes are transferred on all + * the interfaces + */ + SPIM_CMD_MODE_3 +}; + +/* Data transfer mode */ +enum transfer_mode { + /* Transfer data in single mode */ + SPIM_DMODE_SINGLE = 0, + /* Transfer data in dual mode */ + SPIM_DMODE_DUAL, + /* Transfer data in quad mode */ + SPIM_DMODE_QUAD +}; + +/* This structure contains parameters that describe an SPIM operation. */ +struct spim_buffer { + /* The buffer to read from or write to. */ + unsigned char *buffer; + + /* Number of bytes to read/write. Valid range is 0 to 65536 bytes. */ + unsigned int size; + + /* Read/write select. TRUE for read, FALSE for write, Others-invalid.*/ + int isread; + + /* + * ByteDelay select. + * Selects whether or not a delay is inserted between bytes. + * 0 - Minimum inter-byte delay + * 1 - Inter-byte delay of (cs_hold/master_clk half period)*master_clk. + */ + int inter_byte_delay; +}; + +#endif /* __SOC_IMGTEC_DANUBE_SPI_H__ */ diff --git a/src/soc/imgtec/pistachio/monotonic_timer.c b/src/soc/imgtec/pistachio/monotonic_timer.c new file mode 100644 index 0000000000..99c147b7c2 --- /dev/null +++ b/src/soc/imgtec/pistachio/monotonic_timer.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static int get_count_mhz_freq(void) +{ + static unsigned count_mhz_freq; + + if (!count_mhz_freq) { + if (IMG_PLATFORM_ID() != IMG_PLATFORM_ID_SILICON) + count_mhz_freq = 25; /* FPGA board */ + /* + * Will need some means of finding out the counter + * frequency on a real SOC + */ + } + return count_mhz_freq; +} + +void timer_monotonic_get(struct mono_time *mt) +{ + mt->microseconds = (long)timestamp_get(); +} + +uint64_t timestamp_get(void) +{ + return read_c0_count()/get_count_mhz_freq(); +} diff --git a/src/soc/imgtec/pistachio/romstage.c b/src/soc/imgtec/pistachio/romstage.c new file mode 100644 index 0000000000..53ca898fed --- /dev/null +++ b/src/soc/imgtec/pistachio/romstage.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void main(void) +{ + void *entry; + + console_init(); + + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + if (entry != (void *)-1) + stage_exit(entry); + + hlt(); +} diff --git a/src/soc/imgtec/pistachio/soc.c b/src/soc/imgtec/pistachio/soc.c new file mode 100644 index 0000000000..7c2884f0a6 --- /dev/null +++ b/src/soc/imgtec/pistachio/soc.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 The Chromium OS Authors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static void soc_read_resources(device_t dev) +{ + ram_resource(dev, 0, (uintptr_t)_dram / KiB, + (CONFIG_DRAM_SIZE_MB * MiB) / KiB); +} + +static void soc_init(device_t dev) +{ + printk(BIOS_INFO, "CPU: Imgtec Pistachio\n"); +} + +static struct device_operations soc_ops = { + .read_resources = soc_read_resources, + .init = soc_init, +}; + +static void enable_soc_dev(device_t dev) +{ + dev->ops = &soc_ops; +} + +struct chip_operations soc_imgtec_pistachio_ops = { + CHIP_NAME("SOC: Imgtec Pistachio") + .enable_dev = enable_soc_dev, +}; diff --git a/src/soc/imgtec/pistachio/spi.c b/src/soc/imgtec/pistachio/spi.c new file mode 100644 index 0000000000..e7b16589b9 --- /dev/null +++ b/src/soc/imgtec/pistachio/spi.c @@ -0,0 +1,544 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if !CONFIG_SPI_ATOMIC_SEQUENCING +#error "Unsupported SPI driver API" +#endif + +/* Imgtec controller uses 16 bit packet length. */ +#define IMGTEC_SPI_MAX_TRANSFER_SIZE ((1 << 16) - 1) + +struct img_spi_slave { + struct spi_slave slave; + /* SPIM instance device parameters */ + struct spim_device_parameters device_parameters; + /* SPIM instance base address */ + u32 base; + /* Boolean property that is TRUE if API has been initialised */ + int initialised; +}; + +/* Allocate memory for the maximum number of devices */ +static struct +img_spi_slave img_spi_slaves[SPIM_NUM_BLOCKS*SPIM_NUM_PORTS_PER_BLOCK]; + +/* + * Wait for the bit at the shift position to be set in reg + * If the bit is not set in SPI_TIMEOUT_VALUE_US return with error + */ +static int wait_status(u32 reg, u32 shift) +{ + struct stopwatch sw; + + stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_VALUE_US); + while (!(read32(reg) & (1 << shift))) { + if (stopwatch_expired(&sw)) + return -SPIM_TIMEOUT; + } + return SPIM_OK; +} + +/* Transmitter function. Fills TX FIFO with data before enabling SPIM */ +static int transmitdata(struct spi_slave *slave, u8 *buffer, u32 size) +{ + u32 blocksize, base, write_data; + int ret; + + base = container_of(slave, struct img_spi_slave, slave)->base; + while (size) { + /* Wait until FIFO empty */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_SDE_MASK); + ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, + SPFI_SDE_SHIFT); + if (ret) + return ret; + + /* + * Write to FIFO in blocks of 16 words (64 bytes) + * Do 32bit writes first. + */ + blocksize = SPIM_MAX_BLOCK_BYTES; + while ((size >= sizeof(u32)) && blocksize) { + memcpy(&write_data, buffer, sizeof(u32)); + write32(base + SPFI_SEND_LONG_REG_OFFSET, write_data); + buffer += sizeof(u32); + size -= sizeof(u32); + blocksize -= sizeof(u32); + } + while (size && blocksize) { + write32(base + SPFI_SEND_BYTE_REG_OFFSET, *buffer); + buffer++; + size--; + blocksize--; + } + } + return SPIM_OK; +} + +/* Receiver function */ +static int receivedata(struct spi_slave *slave, u8 *buffer, u32 size) +{ + u32 read_data, base; + int ret; + + base = container_of(slave, struct img_spi_slave, slave)->base; + /* + * Do 32bit reads first. Clear status GDEX32BIT here so that the first + * status reg. read gets the actual bit state + */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK); + while (size >= sizeof(u32)) { + ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, + SPFI_GDEX32BIT_SHIFT); + if (ret) + return ret; + read_data = read32(base + SPFI_GET_LONG_REG_OFFSET); + memcpy(buffer, &read_data, sizeof(u32)); + buffer += sizeof(u32); + size -= sizeof(u32); + /* Clear interrupt status on GDEX32BITL */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK); + } + + /* + * Do the remaining 8bit reads. Clear status GDEX8BIT here so that + * the first status reg. read gets the actual bit state + */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK); + while (size) { + ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, + SPFI_GDEX8BIT_SHIFT); + if (ret) + return ret; + *buffer = read32(base + SPFI_GET_BYTE_REG_OFFSET); + buffer++; + size--; + /* Clear interrupt status on SPFI_GDEX8BIT */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK); + } + return SPIM_OK; +} + +/* Sets port parameters in port state register. */ +static void setparams(struct spi_slave *slave, u32 port, + struct spim_device_parameters *params) +{ + u32 spim_parameters, port_state, base; + + spim_parameters = 0; + + base = container_of(slave, struct img_spi_slave, slave)->base; + port_state = read32(base + SPFI_PORT_STATE_REG_OFFSET); + port_state &= ~((SPIM_PORT0_MASK>>port)|SPFI_PORT_SELECT_MASK); + port_state |= params->cs_idle_level<<(SPIM_CS0_IDLE_SHIFT-port); + port_state |= + params->data_idle_level<<(SPIM_DATA0_IDLE_SHIFT-port); + + /* Clock idle level and phase */ + switch (params->spi_mode) { + case SPIM_MODE_0: + break; + case SPIM_MODE_1: + port_state |= (1 << (SPIM_CLOCK0_PHASE_SHIFT - port)); + break; + case SPIM_MODE_2: + port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port)); + break; + case SPIM_MODE_3: + port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port)) | + (1 << (SPIM_CLOCK0_PHASE_SHIFT - port)); + break; + } + /* Set port state register */ + write32(base + SPFI_PORT_STATE_REG_OFFSET, port_state); + + /* Set up values to be written to device parameter register */ + spim_parameters |= params->bitrate << SPIM_CLK_DIVIDE_SHIFT; + spim_parameters |= params->cs_setup << SPIM_CS_SETUP_SHIFT; + spim_parameters |= params->cs_hold << SPIM_CS_HOLD_SHIFT; + spim_parameters |= params->cs_delay << SPIM_CS_DELAY_SHIFT; + + write32(base + SPFI_PORT_0_PARAM_REG_OFFSET + 4 * port, + spim_parameters); +} + +/* Sets up transaction register */ +static u32 transaction_reg_setup(struct spim_buffer *first, + struct spim_buffer *second) +{ + u32 reg = 0; + + /* 2nd transfer exists? */ + if (second) { + /* + * If second transfer exists, it's a "command followed by data" + * type of transfer and first transfer is defined by + * CMD_LENGTH, ADDR_LENGTH, DUMMY_LENGTH... fields of + * transaction register + */ + reg = spi_write_reg_field(reg, SPFI_CMD_LENGTH, 1); + reg = spi_write_reg_field(reg, SPFI_ADDR_LENGTH, + first->size - 1); + reg = spi_write_reg_field(reg, SPFI_DUMMY_LENGTH, 0); + /* Set data size (size of the second transfer) */ + reg = spi_write_reg_field(reg, SPFI_TSIZE, second->size); + } else { + /* Set data size, in this case size of the 1st transfer */ + reg = spi_write_reg_field(reg, SPFI_TSIZE, first->size); + } + return reg; +} + +/* Sets up control register */ +static u32 control_reg_setup(struct spim_buffer *first, + struct spim_buffer *second) +{ + u32 reg; + + /* Enable SPFI */ + reg = SPFI_EN_MASK; + reg |= first->inter_byte_delay ? SPIM_BYTE_DELAY_MASK : 0; + + /* Set up the transfer mode */ + reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE_DQ, SPIM_CMD_MODE_0); + reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE, SPIM_DMODE_SINGLE); + + if (second) { + /* Set TX bit if the 2nd transaction is 'send' */ + reg = spi_write_reg_field(reg, SPFI_TX_RX, + second->isread ? 0 : 1); + /* + * Set send/get DMA for both transactions + * (first is always 'send') + */ + reg = spi_write_reg_field(reg, SPIM_SEND_DMA, 1); + if (second->isread) + reg = spi_write_reg_field(reg, SPIM_GET_DMA, 1); + + } else { + /* Set TX bit if the 1st transaction is 'send' */ + reg |= first->isread ? 0 : SPFI_TX_RX_MASK; + /* Set send/get DMA */ + reg |= first->isread ? SPIM_GET_DMA_MASK : SPIM_SEND_DMA_MASK; + } + return reg; +} + +/* Checks the given buffer information */ +static int check_buffers(struct spi_slave *slave, struct spim_buffer *first, + struct spim_buffer *second){ + + if (!(container_of(slave, struct img_spi_slave, slave)->initialised)) + return -SPIM_API_NOT_INITIALISED; + /* + * First operation must always be defined + * It can be either a read or a write and its size cannot be bigge + * than SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF) + */ + if (!first) + return -SPIM_INVALID_READ_WRITE; + if (first->size > SPIM_MAX_TRANSFER_BYTES) + return -SPIM_INVALID_SIZE; + if (first->isread > 1) + return -SPIM_INVALID_READ_WRITE; + /* Check operation parameters for 'second' */ + if (second) { + /* + * If the second operation is defined it must be a read + * operation and its size must not be bigger than + * SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF) + */ + if (second->size > SPIM_MAX_TRANSFER_BYTES) + return -SPIM_INVALID_SIZE; + if (!second->isread) + return -SPIM_INVALID_READ_WRITE; + /* + * If the second operations is defined, the first operation + * must be a write and its size cannot be bigger than + * SPIM_MAX_FLASH_COMMAND_BYTES(8): command size (1) + + * address size (7). + */ + if (first->isread) + return -SPIM_INVALID_READ_WRITE; + if (first->size > SPIM_MAX_FLASH_COMMAND_BYTES) + return -SPIM_INVALID_SIZE; + + } + return SPIM_OK; +} + +/* Checks the set bitrate */ +static int check_bitrate(u32 rate) +{ + /* Bitrate must be 1, 2, 4, 8, 16, 32, 64, or 128 */ + switch (rate) { + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + return SPIM_OK; + default: + return -SPIM_INVALID_BIT_RATE; + } + return -SPIM_INVALID_BIT_RATE; +} + +/* Checks device parameters for errors */ +static int check_device_params(struct spim_device_parameters *pdev_param) +{ + if (pdev_param->spi_mode < SPIM_MODE_0 || + pdev_param->spi_mode > SPIM_MODE_3) + return -SPIM_INVALID_SPI_MODE; + if (check_bitrate(pdev_param->bitrate) != SPIM_OK) + return -SPIM_INVALID_BIT_RATE; + if (pdev_param->cs_idle_level > 1) + return -SPIM_INVALID_CS_IDLE_LEVEL; + if (pdev_param->data_idle_level > 1) + return -SPIM_INVALID_DATA_IDLE_LEVEL; + return SPIM_OK; +} + +/* Function that carries out read/write operations */ +static int spim_io(struct spi_slave *slave, struct spim_buffer *first, + struct spim_buffer *second) +{ + u32 reg, base; + int i, trans_count, ret; + struct spim_buffer *transaction[2]; + + base = container_of(slave, struct img_spi_slave, slave)->base; + + ret = check_buffers(slave, first, second); + if (ret) + return ret; + + /* + * Soft reset peripheral internals, this will terminate any + * pending transactions + */ + write32(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK); + write32(base + SPFI_CONTROL_REG_OFFSET, 0); + /* Port state register */ + reg = read32(base + SPFI_PORT_STATE_REG_OFFSET); + reg = spi_write_reg_field(reg, SPFI_PORT_SELECT, slave->cs); + write32(base + SPFI_PORT_STATE_REG_OFFSET, reg); + /* Set transaction register */ + reg = transaction_reg_setup(first, second); + write32(base + SPFI_TRANSACTION_REG_OFFSET, reg); + /* Clear status */ + write32(base + SPFI_INT_CLEAR_REG_OFFSET, 0xffffffff); + /* Set control register */ + reg = control_reg_setup(first, second); + write32(base + SPFI_CONTROL_REG_OFFSET, reg); + /* First transaction always exists */ + transaction[0] = first; + trans_count = 1; + /* Is there a second transaction? */ + if (second) { + transaction[1] = second; + trans_count++; + } + /* Now write/read FIFO's */ + for (i = 0; i < trans_count; i++) { + /* Which transaction to execute, "Send" or "Get"? */ + if (transaction[i]->isread) { + /* Get */ + ret = receivedata(slave, transaction[i]->buffer, + transaction[i]->size); + if (ret) { + printk(BIOS_ERR, + "%s: Error: receive data failed.\n", + __func__); + return ret; + } + } else { + /* Send */ + ret = transmitdata(slave, transaction[i]->buffer, + transaction[i]->size); + if (ret) { + printk(BIOS_ERR, + "%s: Error: transmit data failed.\n", + __func__); + return ret; + } + } + } + + /* Wait for end of the transaction */ + ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET, + SPFI_ALLDONE_SHIFT); + if (ret) + return ret; + /* + * Soft reset peripheral internals, this will terminate any + * pending transactions + */ + write32(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK); + write32(base + SPFI_CONTROL_REG_OFFSET, 0); + + return SPIM_OK; +} + +/* Initialization, must be called once on start up */ +void spi_init(void) +{ + /* Clear everything just in case */ + memset(img_spi_slaves, 0, sizeof(img_spi_slaves)); +} + +/* Set up communications parameters for a SPI slave. */ +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + + struct img_spi_slave *img_slave = NULL; + struct spi_slave *slave; + struct spim_device_parameters *device_parameters; + u32 base; + + switch (bus) { + case 0: + base = IMG_SPIM0_BASE_ADDRESS; + break; + case 1: + base = IMG_SPIM1_BASE_ADDRESS; + break; + default: + printk(BIOS_ERR, "%s: Error: unsupported bus.\n", + __func__); + return NULL; + } + if (cs > SPIM_DEVICE4) { + printk(BIOS_ERR, "%s: Error: unsupported chipselect.\n", + __func__); + return NULL; + } + + img_slave = img_spi_slaves + bus * SPIM_NUM_PORTS_PER_BLOCK + cs; + slave = &(img_slave->slave); + device_parameters = &(img_slave->device_parameters); + + img_slave->base = base; + slave->bus = bus; + slave->cs = cs; + slave->rw = SPI_READ_FLAG | SPI_WRITE_FLAG; + slave->max_transfer_size = IMGTEC_SPI_MAX_TRANSFER_SIZE; + + device_parameters->bitrate = 64; + device_parameters->cs_setup = 0; + device_parameters->cs_hold = 0; + device_parameters->cs_delay = 0; + device_parameters->spi_mode = SPIM_MODE_0; + device_parameters->cs_idle_level = 1; + device_parameters->data_idle_level = 0; + img_slave->initialised = IMG_FALSE; + + return slave; +} + +/* Claim the bus and prepare it for communication */ +int spi_claim_bus(struct spi_slave *slave) +{ + int ret; + struct img_spi_slave *img_slave; + + if (!slave) { + printk(BIOS_ERR, "%s: Error: slave was not set up.\n", + __func__); + return -SPIM_API_NOT_INITIALISED; + } + img_slave = container_of(slave, struct img_spi_slave, slave); + if (img_slave->initialised) + return SPIM_OK; + /* Check device parameters */ + ret = check_device_params(&(img_slave->device_parameters)); + if (ret) { + printk(BIOS_ERR, "%s: Error: incorrect device parameters.\n", + __func__); + return ret; + } + /* Set device parameters */ + setparams(slave, slave->cs, &(img_slave->device_parameters)); + /* Soft reset peripheral internals */ + write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, + SPIM_SOFT_RESET_MASK); + write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0); + img_slave->initialised = IMG_TRUE; + return SPIM_OK; +} + +/* Release the SPI bus */ +void spi_release_bus(struct spi_slave *slave) +{ + struct img_spi_slave *img_slave; + + if (!slave) { + printk(BIOS_ERR, "%s: Error: slave was not set up.\n", + __func__); + return; + } + img_slave = container_of(slave, struct img_spi_slave, slave); + img_slave->initialised = IMG_FALSE; + /* Soft reset peripheral internals */ + write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, + SPIM_SOFT_RESET_MASK); + write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0); +} + +/* SPI transfer */ +int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout, + void *din, unsigned int bytesin) +{ + struct spim_buffer buff_0; + struct spim_buffer buff_1; + + if (!slave) { + printk(BIOS_ERR, "%s: Error: slave was not set up.\n", + __func__); + return -SPIM_API_NOT_INITIALISED; + } + if (!dout && !din) { + printk(BIOS_ERR, "%s: Error: both buffers are NULL.\n", + __func__); + return -SPIM_INVALID_TRANSFER_DESC; + } + /* If we only have a read or a write operation + * the parameters for it will be put in the first buffer + */ + buff_0.buffer = (dout) ? (void *)dout : (void *)din; + buff_0.size = (dout) ? bytesout : bytesin; + buff_0.isread = (dout) ? IMG_FALSE : IMG_TRUE; + buff_0.inter_byte_delay = 0; + + if (dout && din) { + /* Set up the read buffer to recieve our data */ + buff_1.buffer = din; + buff_1.size = bytesin; + buff_1.isread = IMG_TRUE; + buff_1.inter_byte_delay = 0; + } + return spim_io(slave, &buff_0, (dout && din) ? &buff_1 : NULL); +} diff --git a/src/soc/imgtec/pistachio/uart.c b/src/soc/imgtec/pistachio/uart.c new file mode 100644 index 0000000000..53bf21d226 --- /dev/null +++ b/src/soc/imgtec/pistachio/uart.c @@ -0,0 +1,217 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Eric Biederman + * Copyright (C) 2006-2010 coresystems GmbH + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +/* Should support 8250, 16450, 16550, 16550A type UARTs */ + +/* Expected character delay at 1200bps is 9ms for a working UART + * and no flow-control. Assume UART as stuck if shift register + * or FIFO takes more than 50ms per character to appear empty. + */ +#define SINGLE_CHAR_TIMEOUT (50 * 1000) +#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT) +#define UART_SHIFT 2 + +#define GEN_ACCESSOR(name, idx) \ +static inline uint8_t read_##name(unsigned base_port) \ +{ \ + return read8(base_port + (idx << UART_SHIFT)); \ +} \ + \ +static inline void write_##name(unsigned base_port, uint8_t val) \ +{ \ + write8(base_port + (idx << UART_SHIFT), val); \ +} + +GEN_ACCESSOR(rbr, UART8250_RBR) +GEN_ACCESSOR(tbr, UART8250_TBR) +GEN_ACCESSOR(ier, UART8250_IER) +GEN_ACCESSOR(fcr, UART8250_FCR) +GEN_ACCESSOR(lcr, UART8250_LCR) +GEN_ACCESSOR(mcr, UART8250_MCR) +GEN_ACCESSOR(lsr, UART8250_LSR) +GEN_ACCESSOR(dll, UART8250_DLL) +GEN_ACCESSOR(dlm, UART8250_DLM) + +static int uart8250_mem_can_tx_byte(unsigned base_port) +{ + return read_lsr(base_port) & UART8250_LSR_THRE; +} + +static void uart8250_mem_tx_byte(unsigned base_port, unsigned char data) +{ + unsigned long int i = SINGLE_CHAR_TIMEOUT; + while (i-- && !uart8250_mem_can_tx_byte(base_port)) + udelay(1); + write_tbr(base_port, data); +} + +static void uart8250_mem_tx_flush(unsigned base_port) +{ + unsigned long int i = FIFO_TIMEOUT; + while (i-- && !(read_lsr(base_port) & UART8250_LSR_TEMT)) + udelay(1); +} + +static int uart8250_mem_can_rx_byte(unsigned base_port) +{ + return read_lsr(base_port) & UART8250_LSR_DR; +} + +static unsigned char uart8250_mem_rx_byte(unsigned base_port) +{ + unsigned long int i = SINGLE_CHAR_TIMEOUT; + while (i-- && !uart8250_mem_can_rx_byte(base_port)) + udelay(1); + if (i) + return read_rbr(base_port); + else + return 0x0; +} + +static void uart8250_mem_init(unsigned base_port, unsigned divisor) +{ + /* Disable interrupts */ + write_ier(base_port, 0x0); + /* Enable FIFOs */ + write_fcr(base_port, UART8250_FCR_FIFO_EN); + + /* Assert DTR and RTS so the other end is happy */ + write_mcr(base_port, UART8250_MCR_DTR | UART8250_MCR_RTS); + + /* DLAB on */ + write_lcr(base_port, UART8250_LCR_DLAB | CONFIG_TTYS0_LCS); + + write_dll(base_port, divisor & 0xFF); + write_dlm(base_port, (divisor >> 8) & 0xFF); + + /* Set to 3 for 8N1 */ + write_lcr(base_port, CONFIG_TTYS0_LCS); +} + +static unsigned int uart_platform_refclk(void) +{ + /* TODO: this is entirely arbitrary */ + return 1000000; +} + +static unsigned int uart_platform_base(int idx) +{ + switch (idx) { + case 0: + return 0xb8101400; + + case 1: + return 0xb8101500; + + default: + return 0x0; + } +} + +/* Calculate divisor. Do not floor but round to nearest integer. */ +static unsigned int uart_baudrate_divisor(unsigned int baudrate, + unsigned int refclk, unsigned int oversample) +{ + return (1 + (2 * refclk) / (baudrate * oversample)) / 2; +} + +static void pistachio_uart_init(void) +{ + u32 base = uart_platform_base(0); + if (!base) + return; + + unsigned int div; + div = uart_baudrate_divisor(CONFIG_TTYS0_BAUD, + uart_platform_refclk(), 16); + uart8250_mem_init(base, div); +} + +static void pistachio_uart_tx_byte(unsigned char data) +{ + u32 base = uart_platform_base(0); + if (!base) + return; + uart8250_mem_tx_byte(base, data); +} + +static unsigned char pistachio_uart_rx_byte(void) +{ + u32 base = uart_platform_base(0); + if (!base) + return 0xff; + return uart8250_mem_rx_byte(base); +} + +static void pistachio_uart_tx_flush(void) +{ + u32 base = uart_platform_base(0); + if (!base) + return; + uart8250_mem_tx_flush(base); +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver pistachio_uart_console __console = { + .init = pistachio_uart_init, + .tx_byte = pistachio_uart_tx_byte, + .tx_flush = pistachio_uart_tx_flush, + .rx_byte = pistachio_uart_rx_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return uart_platform_base(0); +} + +#else /* __PRE_RAM__ */ + +void uart_init(void) +{ + pistachio_uart_init(); +} + +void uart_tx_byte(unsigned char data) +{ + pistachio_uart_tx_byte(data); +} + +unsigned char uart_rx_byte(void) +{ + return pistachio_uart_rx_byte(); +} + +void uart_tx_flush(void) +{ + pistachio_uart_tx_flush(); +} + +#endif /* __PRE_RAM__ */ diff --git a/src/soc/intel/Kconfig b/src/soc/intel/Kconfig new file mode 100644 index 0000000000..64a7fe015f --- /dev/null +++ b/src/soc/intel/Kconfig @@ -0,0 +1,3 @@ +source src/soc/intel/baytrail/Kconfig +source src/soc/intel/broadwell/Kconfig +source src/soc/intel/common/Kconfig diff --git a/src/soc/intel/Makefile.inc b/src/soc/intel/Makefile.inc new file mode 100644 index 0000000000..8cdcbae460 --- /dev/null +++ b/src/soc/intel/Makefile.inc @@ -0,0 +1,2 @@ +subdirs-$(CONFIG_SOC_INTEL_BAYTRAIL) += baytrail +subdirs-$(CONFIG_SOC_INTEL_BROADWELL) += broadwell diff --git a/src/soc/intel/baytrail/Kconfig b/src/soc/intel/baytrail/Kconfig new file mode 100644 index 0000000000..b0550c98cf --- /dev/null +++ b/src/soc/intel/baytrail/Kconfig @@ -0,0 +1,189 @@ + +config SOC_INTEL_BAYTRAIL + bool + help + Bay Trail M/D part support. + +if SOC_INTEL_BAYTRAIL + +config CPU_SPECIFIC_OPTIONS + def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 + select ALT_CBFS_LOAD_PAYLOAD + select BACKUP_DEFAULT_SMM_REGION + select CACHE_MRC_SETTINGS + select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM + select CACHE_ROM + select CAR_MIGRATION + select COLLECT_TIMESTAMPS + select CPU_MICROCODE_IN_CBFS + select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED + select DYNAMIC_CBMEM + select HAS_PRECBMEM_TIMESTAMP_REGION + select HAVE_MONOTONIC_TIMER + select HAVE_SMI_HANDLER + select HAVE_HARD_RESET + select MMCONF_SUPPORT + select MMCONF_SUPPORT_DEFAULT + select RELOCATABLE_MODULES + select PARALLEL_MP + select PCIEXP_ASPM + select PCIEXP_COMMON_CLOCK + select SMM_MODULES + select SMM_TSEG + select SMP + select SPI_FLASH + select SSE2 + select TSC_CONSTANT_RATE + select TSC_MONOTONIC_TIMER + select TSC_SYNC_MFENCE + select UDELAY_TSC + +config BOOTBLOCK_CPU_INIT + string + default "soc/intel/baytrail/bootblock/bootblock.c" + +config MMCONF_BASE_ADDRESS + hex + default 0xe0000000 + +config MAX_CPUS + int + default 4 + +config CPU_ADDR_BITS + int + default 36 + +config SMM_TSEG_SIZE + hex + default 0x800000 + +config SMM_RESERVED_SIZE + hex + default 0x100000 + +config MICROCODE_INCLUDE_PATH + string + default "src/soc/intel/baytrail" + +config HAVE_MRC + bool "Add a Memory Reference Code binary" + default y + help + Select this option to add a blob containing + memory reference code. + Note: Without this binary coreboot will not work + +if HAVE_MRC + +config MRC_FILE + string "Intel System Agent path and filename" + default "mrc.bin" + help + The path and filename of the file to use as System Agent + binary. + +config MRC_BIN_ADDRESS + hex + default 0xfffa0000 + +config MRC_RMT + bool "Enable MRC RMT training + debug prints" + default n + +endif # HAVE_MRC + +# Cache As RAM region layout: +# +# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE + DCACHE_RAM_MRC_VAR_SIZE +# | MRC usage | +# | | +# +-------------+ DCACHE_RAM_BASE + DCACHE_RAM_SIZE +# | Stack |\ +# | | | * DCACHE_RAM_ROMSTAGE_STACK_SIZE +# | v |/ +# +-------------+ +# | ^ | +# | | | +# | CAR Globals | +# +-------------+ DCACHE_RAM_BASE +# +# Note that the MRC binary is linked to assume the region marked as "MRC usage" +# starts at DCACHE_RAM_BASE + DCACHE_RAM_SIZE. If those values change then +# a new MRC binary needs to be produced with the updated start and size +# information. + +config DCACHE_RAM_BASE + hex + default 0xfe000000 + +config DCACHE_RAM_SIZE + hex + default 0x8000 + help + The size of the cache-as-ram region required during bootblock + and/or romstage. Note DCACHE_RAM_SIZE and DCACHE_RAM_MRC_VAR_SIZE + must add up to a power of 2. + +config DCACHE_RAM_MRC_VAR_SIZE + hex + default 0x8000 + help + The amount of cache-as-ram region required by the reference code. + +config DCACHE_RAM_ROMSTAGE_STACK_SIZE + hex + default 0x800 + help + The amount of anticipated stack usage from the data cache + during pre-ram rom stage execution. + +config RESET_ON_INVALID_RAMSTAGE_CACHE + bool "Reset the system on S3 wake when ramstage cache invalid." + default n + depends on RELOCATABLE_RAMSTAGE + help + The haswell romstage code caches the loaded ramstage program + in SMM space. On S3 wake the romstage will copy over a fresh + ramstage that was cached in the SMM space. This option determines + the action to take when the ramstage cache is invalid. If selected + the system will reset otherwise the ramstage will be reloaded from + cbfs. + +config CBFS_SIZE + hex "Size of CBFS filesystem in ROM" + default 0x100000 + help + On Bay Trail systems the firmware image has to store a lot more + than just coreboot, including: + - a firmware descriptor + - Intel Management Engine firmware + - MRC cache information + This option allows to limit the size of the CBFS portion in the + firmware image. + +config LOCK_MANAGEMENT_ENGINE + bool "Lock Management Engine section" + default n + help + The Intel Management Engine supports preventing write accesses + from the host to the Management Engine section in the firmware + descriptor. If the ME section is locked, it can only be overwritten + with an external SPI flash programmer. You will want this if you + want to increase security of your ROM image once you are sure + that the ME firmware is no longer going to change. + + If unsure, say N. + +config ENABLE_BUILTIN_COM1 + bool "Enable builtin COM1 Serial Port" + default n + help + The PMC has a legacy COM1 serial port. Choose this option to + configure the pads and enable it. This serial port can be used for + the debug console. + +endif diff --git a/src/soc/intel/baytrail/Makefile.inc b/src/soc/intel/baytrail/Makefile.inc new file mode 100644 index 0000000000..112b5303e4 --- /dev/null +++ b/src/soc/intel/baytrail/Makefile.inc @@ -0,0 +1,93 @@ +subdirs-y += bootblock +subdirs-y += microcode +subdirs-y += romstage +subdirs-y += ../common +subdirs-y += ../../../cpu/x86/lapic +subdirs-y += ../../../cpu/x86/mtrr +subdirs-y += ../../../cpu/x86/smm +subdirs-y += ../../../cpu/x86/tsc +subdirs-y += ../../../cpu/intel/microcode +subdirs-y += ../../../cpu/intel/turbo + +ramstage-y += memmap.c +romstage-y += memmap.c +ramstage-y += tsc_freq.c +romstage-y += tsc_freq.c +smm-y += tsc_freq.c +ramstage-y += spi.c +smm-y += spi.c +ramstage-y += chip.c +ramstage-y += gfx.c +ramstage-y += iosf.c +romstage-y += iosf.c +smm-y += iosf.c +ramstage-y += northcluster.c +ramstage-y += ramstage.c +ramstage-y += gpio.c +romstage-y += reset.c +ramstage-y += reset.c +ramstage-y += cpu.c +ramstage-y += pmutil.c +smm-y += pmutil.c +smm-y += smihandler.c +ramstage-y += smm.c +ramstage-y += ehci.c +ramstage-y += xhci.c +ramstage-y += southcluster.c +ramstage-$(CONFIG_HAVE_REFCODE_BLOB) += refcode.c +ramstage-y += sata.c +ramstage-y += acpi.c +ramstage-y += lpe.c +ramstage-y += scc.c +ramstage-y += emmc.c +ramstage-y += lpss.c +ramstage-y += pcie.c +ramstage-y += sd.c +ramstage-y += dptf.c +ramstage-y += perf_power.c +ramstage-y += stage_cache.c +romstage-y += stage_cache.c +ramstage-$(CONFIG_ELOG) += elog.c +ramstage-y += hda.c +ramstage-$(CONFIG_ALT_CBFS_LOAD_PAYLOAD) += spi_loading.c + +# Remove as ramstage gets fleshed out +ramstage-y += placeholders.c + +INCLUDES += -Isrc/soc/intel/baytrail/include + +# Run an intermediate step when producing coreboot.rom +# that adds additional components to the final firmware +# image outside of CBFS +INTERMEDIATE:=baytrail_add_me + +baytrail_add_me: $(obj)/coreboot.pre $(IFDTOOL) + printf " DD Adding Intel Firmware Descriptor\n" + dd if=3rdparty/mainboard/$(MAINBOARDDIR)/descriptor.bin \ + of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 + printf " IFDTOOL me.bin -> coreboot.pre\n" + $(objutil)/ifdtool/ifdtool \ + -i ME:3rdparty/mainboard/$(MAINBOARDDIR)/me.bin \ + $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +ifeq ($(CONFIG_LOCK_MANAGEMENT_ENGINE),y) + printf " IFDTOOL Locking Management Engine\n" + $(objutil)/ifdtool/ifdtool -l $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +else + printf " IFDTOOL Unlocking Management Engine\n" + $(objutil)/ifdtool/ifdtool -u $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +endif + +# If an MRC file is an ELF file determine the entry address and first loadable +# section offset in the file. Subtract the offset from the entry address to +# determine the final location. +mrcelfoffset = $(shell readelf -S -W $(CONFIG_MRC_FILE) | sed -e 's/\[ /[0/' | awk '$$3 ~ /PROGBITS/ { print "0x"$$5; exit }' ) +mrcelfentry = $(shell readelf -h -W $(CONFIG_MRC_FILE) | grep 'Entry point address' | awk '{print $$NF }') + +# Add memory reference code blob. +cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin +mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE)) +mrc.bin-position := $(if $(findstring elf,$(CONFIG_MRC_FILE)),$(shell printf "0x%x" $$(( $(mrcelfentry) - $(mrcelfoffset) )) ),$(CONFIG_MRC_BIN_ADDRESS)) +mrc.bin-type := 0xab diff --git a/src/soc/intel/baytrail/acpi.c b/src/soc/intel/baytrail/acpi.c new file mode 100644 index 0000000000..940f1f3652 --- /dev/null +++ b/src/soc/intel/baytrail/acpi.c @@ -0,0 +1,511 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MWAIT_RES(state, sub_state) \ + { \ + .addrl = (((state) << 4) | (sub_state)), \ + .space_id = ACPI_ADDRESS_SPACE_FIXED, \ + .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \ + .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \ + .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \ + } + +/* C-state map without S0ix */ +static acpi_cstate_t cstate_map[] = { + { + /* C1 */ + .ctype = 1, /* ACPI C1 */ + .latency = 1, + .power = 1000, + .resource = MWAIT_RES(0, 0), + }, + { + /* C6NS with no L2 shrink */ + /* NOTE: this substate is above CPUID limit */ + .ctype = 2, /* ACPI C2 */ + .latency = 500, + .power = 10, + .resource = MWAIT_RES(5, 1), + }, + { + /* C6FS with full L2 shrink */ + .ctype = 3, /* ACPI C3 */ + .latency = 1500, /* 1.5ms worst case */ + .power = 1, + .resource = MWAIT_RES(5, 2), + } +}; + +void acpi_init_gnvs(global_nvs_t *gnvs) +{ + /* Set unknown wake source */ + gnvs->pm1i = -1; + + /* CPU core count */ + gnvs->pcnt = dev_count_cpu(); + + /* Top of Low Memory (start of resource allocation) */ + gnvs->tolm = nc_read_top_of_low_memory(); + +#if CONFIG_CONSOLE_CBMEM + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); +#endif + +#if CONFIG_CHROMEOS + /* Initialize Verified Boot data */ + chromeos_init_vboot(&(gnvs->chromeos)); +#if CONFIG_EC_GOOGLE_CHROMEEC + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif +#endif +} + +static int acpi_sci_irq(void) +{ + const unsigned long actl = ILB_BASE_ADDRESS + ACTL; + int scis; + static int sci_irq; + + if (sci_irq) + return sci_irq; + + /* Determine how SCI is routed. */ + scis = read32(actl) & SCIS_MASK; + switch (scis) { + case SCIS_IRQ9: + case SCIS_IRQ10: + case SCIS_IRQ11: + sci_irq = scis - SCIS_IRQ9 + 9; + break; + case SCIS_IRQ20: + case SCIS_IRQ21: + case SCIS_IRQ22: + case SCIS_IRQ23: + sci_irq = scis - SCIS_IRQ20 + 20; + break; + default: + printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n"); + sci_irq = 9; + break; + } + + printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq); + return sci_irq; +} + +void acpi_create_intel_hpet(acpi_hpet_t * hpet) +{ + acpi_header_t *header = &(hpet->header); + acpi_addr_t *addr = &(hpet->addr); + + memset((void *) hpet, 0, sizeof(acpi_hpet_t)); + + /* fill out header fields */ + memcpy(header->signature, "HPET", 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + + header->length = sizeof(acpi_hpet_t); + header->revision = 1; + + /* fill out HPET address */ + addr->space_id = 0; /* Memory */ + addr->bit_width = 64; + addr->bit_offset = 0; + addr->addrl = (unsigned long long)HPET_BASE_ADDRESS & 0xffffffff; + addr->addrh = (unsigned long long)HPET_BASE_ADDRESS >> 32; + + hpet->id = 0x8086a201; /* Intel */ + hpet->number = 0x00; + hpet->min_tick = 0x0080; + + header->checksum = + acpi_checksum((void *) hpet, sizeof(acpi_hpet_t)); +} + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, + MCFG_BASE_ADDRESS, 0, 0, 255); + return current; +} + +void acpi_fill_in_fadt(acpi_fadt_t *fadt) +{ + const uint16_t pmbase = ACPI_BASE_ADDRESS; + + fadt->sci_int = acpi_sci_irq(); + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase + PM1_STS; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + PM1_CNT; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + PM2A_CNT_BLK; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->gpe0_blk = pmbase + GPE0_STS; + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 2 * (GPE0_EN - GPE0_STS); + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + fadt->reset_value = 6; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + PM2A_CNT_BLK; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 1; + fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = pmbase + GPE0_STS; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; +} + +static acpi_tstate_t baytrail_tss_table[] = { + { 100, 1000, 0, 0x00, 0 }, + { 88, 875, 0, 0x1e, 0 }, + { 75, 750, 0, 0x1c, 0 }, + { 63, 625, 0, 0x1a, 0 }, + { 50, 500, 0, 0x18, 0 }, + { 38, 375, 0, 0x16, 0 }, + { 25, 250, 0, 0x14, 0 }, + { 13, 125, 0, 0x12, 0 }, +}; + +static int generate_T_state_entries(int core, int cores_per_package) +{ + int len; + + /* Indicate SW_ALL coordination for T-states */ + len = acpigen_write_TSD_package(core, cores_per_package, SW_ALL); + + /* Indicate FFixedHW so OS will use MSR */ + len += acpigen_write_empty_PTC(); + + /* Set NVS controlled T-state limit */ + len += acpigen_write_TPC("\\TLVL"); + + /* Write TSS table for MSR access */ + len += acpigen_write_TSS_package( + ARRAY_SIZE(baytrail_tss_table), baytrail_tss_table); + + return len; +} + +static int calculate_power(int tdp, int p1_ratio, int ratio) +{ + u32 m; + u32 power; + + /* + * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2 + * + * Power = (ratio / p1_ratio) * m * tdp + */ + + m = (110000 - ((p1_ratio - ratio) * 625)) / 11; + m = (m * m) / 1000; + + power = ((ratio * 100000 / p1_ratio) / 100); + power *= (m / 100) * (tdp / 1000); + power /= 1000; + + return (int)power; +} + +static int generate_P_state_entries(int core, int cores_per_package) +{ + int len, len_pss; + int ratio_min, ratio_max, ratio_turbo, ratio_step, ratio_range_2; + int coord_type, power_max, power_unit, num_entries; + int ratio, power, clock, clock_max; + int vid, vid_turbo, vid_min, vid_max, vid_range_2; + u32 control_status; + const struct pattrs *pattrs = pattrs_get(); + msr_t msr; + + /* Inputs from CPU attributes */ + ratio_max = pattrs->iacore_ratios[IACORE_MAX]; + ratio_min = pattrs->iacore_ratios[IACORE_LFM]; + vid_max = pattrs->iacore_vids[IACORE_MAX]; + vid_min = pattrs->iacore_vids[IACORE_LFM]; + + /* Set P-states coordination type based on MSR disable bit */ + coord_type = (pattrs->num_cpus > 2) ? SW_ALL : HW_ALL; + + /* Max Non-Turbo Frequency */ + clock_max = (ratio_max * pattrs->bclk_khz) / 1000; + + /* Calculate CPU TDP in mW */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 1 << (msr.lo & 0xf); + msr = rdmsr(MSR_PKG_POWER_LIMIT); + power_max = ((msr.lo & 0x7fff) / power_unit) * 1000; + + /* Write _PCT indicating use of FFixedHW */ + len = acpigen_write_empty_PCT(); + + /* Write _PPC with NVS specified limit on supported P-state */ + len += acpigen_write_PPC_NVS(); + + /* Write PSD indicating configured coordination type */ + len += acpigen_write_PSD_package(core, 1, coord_type); + + /* Add P-state entries in _PSS table */ + len += acpigen_write_name("_PSS"); + + /* Determine ratio points */ + ratio_step = 1; + num_entries = (ratio_max - ratio_min) / ratio_step; + while (num_entries > 15) { /* ACPI max is 15 ratios */ + ratio_step <<= 1; + num_entries >>= 1; + } + + /* P[T] is Turbo state if enabled */ + if (get_turbo_state() == TURBO_ENABLED) { + /* _PSS package count including Turbo */ + len_pss = acpigen_write_package(num_entries + 2); + + ratio_turbo = pattrs->iacore_ratios[IACORE_TURBO]; + vid_turbo = pattrs->iacore_vids[IACORE_TURBO]; + control_status = (ratio_turbo << 8) | vid_turbo; + + /* Add entry for Turbo ratio */ + len_pss += acpigen_write_PSS_package( + clock_max + 1, /*MHz*/ + power_max, /*mW*/ + 10, /*lat1*/ + 10, /*lat2*/ + control_status, /*control*/ + control_status); /*status*/ + } else { + /* _PSS package count without Turbo */ + len_pss = acpigen_write_package(num_entries + 1); + ratio_turbo = ratio_max; + vid_turbo = vid_max; + } + + /* First regular entry is max non-turbo ratio */ + control_status = (ratio_max << 8) | vid_max; + len_pss += acpigen_write_PSS_package( + clock_max, /*MHz*/ + power_max, /*mW*/ + 10, /*lat1*/ + 10, /*lat2*/ + control_status, /*control */ + control_status); /*status*/ + + /* Set up ratio and vid ranges for VID calculation */ + ratio_range_2 = (ratio_turbo - ratio_min) * 2; + vid_range_2 = (vid_turbo - vid_min) * 2; + + /* Generate the remaining entries */ + for (ratio = ratio_min + ((num_entries - 1) * ratio_step); + ratio >= ratio_min; ratio -= ratio_step) { + + /* Calculate VID for this ratio */ + vid = ((ratio - ratio_min) * vid_range_2) / + ratio_range_2 + vid_min; + /* Round up if remainder */ + if (((ratio - ratio_min) * vid_range_2) % ratio_range_2) + vid++; + + /* Calculate power at this ratio */ + power = calculate_power(power_max, ratio_max, ratio); + clock = (ratio * pattrs->bclk_khz) / 1000; + control_status = (ratio << 8) | (vid & 0xff); + + len_pss += acpigen_write_PSS_package( + clock, /*MHz*/ + power, /*mW*/ + 10, /*lat1*/ + 10, /*lat2*/ + control_status, /*control*/ + control_status); /*status*/ + } + + /* Fix package length */ + len_pss--; + acpigen_patch_len(len_pss); + + return len + len_pss; +} + +void generate_cpu_entries(void) +{ + int len_pr, core; + int pcontrol_blk = get_pmbase(), plen = 6; + const struct pattrs *pattrs = pattrs_get(); + + for (core=0; corenum_cpus; core++) { + if (core > 0) { + pcontrol_blk = 0; + plen = 0; + } + + /* Generate processor \_PR.CPUx */ + len_pr = acpigen_write_processor( + core, pcontrol_blk, plen); + + /* Generate P-state tables */ + len_pr += generate_P_state_entries( + core, pattrs->num_cpus); + + /* Generate C-state tables */ + len_pr += acpigen_write_CST_package( + cstate_map, ARRAY_SIZE(cstate_map)); + + /* Generate T-state tables */ + len_pr += generate_T_state_entries( + core, pattrs->num_cpus); + + len_pr--; + acpigen_patch_len(len_pr); + } +} + +unsigned long acpi_madt_irq_overrides(unsigned long current) +{ + int sci_irq = acpi_sci_irq(); + acpi_madt_irqoverride_t *irqovr; + uint16_t sci_flags = MP_IRQ_TRIGGER_LEVEL; + + /* INT_SRC_OVR */ + irqovr = (void *)current; + current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0); + + if (sci_irq >= 20) + sci_flags |= MP_IRQ_POLARITY_LOW; + else + sci_flags |= MP_IRQ_POLARITY_HIGH; + + irqovr = (void *)current; + current += acpi_create_madt_irqoverride(irqovr, 0, sci_irq, sci_irq, + sci_flags); + + return current; +} diff --git a/src/soc/intel/baytrail/acpi/cpu.asl b/src/soc/intel/baytrail/acpi/cpu.asl new file mode 100644 index 0000000000..16f62ba309 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/cpu.asl @@ -0,0 +1,77 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* These devices are created at runtime */ +External (\_PR.CPU0, DeviceObj) +External (\_PR.CPU1, DeviceObj) +External (\_PR.CPU2, DeviceObj) +External (\_PR.CPU3, DeviceObj) + +/* Notify OS to re-read CPU tables, assuming ^2 CPU count */ +Method (PNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x81) // _CST + Notify (\_PR.CPU1, 0x81) // _CST + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x81) // _CST + Notify (\_PR.CPU3, 0x81) // _CST + } +} + +/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */ +Method (PPCN) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x80) // _PPC + Notify (\_PR.CPU1, 0x80) // _PPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x80) // _PPC + Notify (\_PR.CPU3, 0x80) // _PPC + } +} + +/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */ +Method (TNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x82) // _TPC + Notify (\_PR.CPU1, 0x82) // _TPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x82) // _TPC + Notify (\_PR.CPU3, 0x82) // _TPC + } +} + +/* Return a package containing enabled processor entries */ +Method (PPKG) +{ + If (LGreaterEqual (\PCNT, 4)) { + Return (Package() {\_PR.CPU0, \_PR.CPU1, \_PR.CPU2, \_PR.CPU3}) + } ElseIf (LGreaterEqual (\PCNT, 2)) { + Return (Package() {\_PR.CPU0, \_PR.CPU1}) + } Else { + Return (Package() {\_PR.CPU0}) + } +} diff --git a/src/soc/intel/baytrail/acpi/device_nvs.asl b/src/soc/intel/baytrail/acpi/device_nvs.asl new file mode 100644 index 0000000000..fce7b53054 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/device_nvs.asl @@ -0,0 +1,87 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* Device Enabled in ACPI Mode */ + +S0EN, 8, // SDMA Enable +S1EN, 8, // I2C1 Enable +S2EN, 8, // I2C2 Enable +S3EN, 8, // I2C3 Enable +S4EN, 8, // I2C4 Enable +S5EN, 8, // I2C5 Enable +S6EN, 8, // I2C6 Enable +S7EN, 8, // I2C7 Enable +S8EN, 8, // SDMA2 Enable +S9EN, 8, // SPI Enable +SAEN, 8, // PWM1 Enable +SBEN, 8, // PWM2 Enable +SCEN, 8, // UART2 Enable +SDEN, 8, // UART2 Enable +C0EN, 8, // MMC Enable +C1EN, 8, // SDIO Enable +C2EN, 8, // SD Card Enable +LPEN, 8, // LPE Enable + +/* BAR 0 */ + +S0B0, 32, // SDMA BAR0 +S1B0, 32, // I2C1 BAR0 +S2B0, 32, // I2C2 BAR0 +S3B0, 32, // I2C3 BAR0 +S4B0, 32, // I2C4 BAR0 +S5B0, 32, // I2C5 BAR0 +S6B0, 32, // I2C6 BAR0 +S7B0, 32, // I2C7 BAR0 +S8B0, 32, // SDMA2 BAR0 +S9B0, 32, // SPI BAR0 +SAB0, 32, // PWM1 BAR0 +SBB0, 32, // PWM2 BAR0 +SCB0, 32, // UART1 BAR0 +SDB0, 32, // UART2 BAR0 +C0B0, 32, // MMC BAR0 +C1B0, 32, // SDIO BAR0 +C2B0, 32, // SD Card BAR0 +LPB0, 32, // LPE BAR0 + +/* BAR 1 */ + +S0B1, 32, // SDMA BAR1 +S1B1, 32, // I2C1 BAR1 +S2B1, 32, // I2C2 BAR1 +S3B1, 32, // I2C3 BAR1 +S4B1, 32, // I2C4 BAR1 +S5B1, 32, // I2C5 BAR1 +S6B1, 32, // I2C6 BAR1 +S7B1, 32, // I2C7 BAR1 +S8B1, 32, // SDMA2 BAR1 +S9B1, 32, // SPI BAR1 +SAB1, 32, // PWM1 BAR1 +SBB1, 32, // PWM2 BAR1 +SCB1, 32, // UART1 BAR1 +SDB1, 32, // UART2 BAR1 +C0B1, 32, // MMC BAR1 +C1B1, 32, // SDIO BAR1 +C2B1, 32, // SD Card BAR1 +LPB1, 32, // LPE BAR1 + +/* Extra */ + +LPFW, 32, // LPE BAR2 Firmware diff --git a/src/soc/intel/baytrail/acpi/dptf/charger.asl b/src/soc/intel/baytrail/acpi/dptf/charger.asl new file mode 100644 index 0000000000..7c7f62fb57 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/dptf/charger.asl @@ -0,0 +1,59 @@ +Device (TCHG) +{ + Name (_HID, "INT3403") + Name (_UID, 0) + Name (PTYP, 0x0B) + Name (_STR, Unicode("Battery Charger")) + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Return charger performance states defined by mainboard */ + Method (PPSS) + { + Return (\_SB.CHPS) + } + + /* Return maximum charger current limit */ + Method (PPPC) + { + /* Convert size of PPSS table to index */ + Store (SizeOf (\_SB.CHPS), Local0) + Decrement (Local0) + + /* Check if charging is disabled (AC removed) */ + If (LEqual (\PWRS, Zero)) { + /* Return last power state */ + Return (Local0) + } Else { + /* Return highest power state */ + Return (0) + } + + Return (0) + } + + /* Set charger current limit */ + Method (SPPC, 1) + { + /* Retrieve Control (index 4) for specified PPSS level */ + Store (DeRefOf (Index (DeRefOf (Index + (\_SB.CHPS, ToInteger (Arg0))), 4)), Local0) + + /* Pass Control value to EC to limit charging */ + \_SB.PCI0.LPCB.EC0.CHGS (Local0) + } + + /* Initialize charger participant */ + Method (INIT) + { + /* Disable charge limit */ + \_SB.PCI0.LPCB.EC0.CHGD () + } +} diff --git a/src/soc/intel/baytrail/acpi/dptf/cpu.asl b/src/soc/intel/baytrail/acpi/dptf/cpu.asl new file mode 100644 index 0000000000..3cbfc5f672 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/dptf/cpu.asl @@ -0,0 +1,144 @@ +External (\_PR.CPU0._TSS, MethodObj) +External (\_PR.CPU0._TPC, MethodObj) +External (\_PR.CPU0._PTC, PkgObj) +External (\_PR.CPU0._TSD, PkgObj) +External (\_PR.CPU0._PSS, MethodObj) + +Device (TCPU) +{ + Name (_HID, EISAID ("INT3401")) + Name (_UID, 0) + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* + * Processor Throttling Controls + */ + + Method (_TSS) + { + If (CondRefOf (\_PR.CPU0._TSS)) { + Return (\_PR.CPU0._TSS) + } Else { + Return (Package () + { + Package () { 0, 0, 0, 0, 0 } + }) + } + } + + Method (_TPC) + { + If (CondRefOf (\_PR.CPU0._TPC)) { + Return (\_PR.CPU0._TPC) + } Else { + Return (0) + } + } + + Method (_PTC) + { + If (CondRefOf (\_PR.CPU0._PTC)) { + Return (\_PR.CPU0._PTC) + } Else { + Return (Package () + { + Buffer () { 0 }, + Buffer () { 0 } + }) + } + } + + Method (_TSD) + { + If (CondRefOf (\_PR.CPU0._TSD)) { + Return (\_PR.CPU0._TSD) + } Else { + Return (Package () + { + Package () { 5, 0, 0, 0, 0 } + }) + } + } + + Method (_TDL) + { + If (CondRefOf (\_PR.CPU0._TSS)) { + Store (SizeOf (\_PR.CPU0._TSS ()), Local0) + Decrement (Local0) + Return (Local0) + } Else { + Return (0) + } + } + + /* + * Processor Performance Control + */ + + Method (_PPC) + { + Return (0) + } + + Method (SPPC, 1) + { + Store (Arg0, \PPCM) + + /* Notify OS to re-read _PPC limit on each CPU */ + \PPCN () + } + + Method (_PSS) + { + If (CondRefOf (\_PR.CPU0._PSS)) { + Return (\_PR.CPU0._PSS) + } Else { + Return (Package () + { + Package () { 0, 0, 0, 0, 0, 0 } + }) + } + } + + Method (_PDL) + { + /* Check for mainboard specific _PDL override */ + If (CondRefOf (\_SB.MPDL)) { + Return (\_SB.MPDL) + } ElseIf (CondRefOf (\_PR.CPU0._PSS)) { + Store (SizeOf (\_PR.CPU0._PSS ()), Local0) + Decrement (Local0) + Return (Local0) + } Else { + Return (0) + } + } + + /* Return PPCC table defined by mainboard */ + Method (PPCC) + { + Return (\_SB.MPPC) + } + +#ifdef DPTF_CPU_CRITICAL + Method (_CRT) + { + Return (^^CTOK (DPTF_CPU_CRITICAL)) + } +#endif + +#ifdef DPTF_CPU_PASSIVE + Method (_PSV) + { + Return (^^CTOK (DPTF_CPU_PASSIVE)) + } +#endif +} diff --git a/src/soc/intel/baytrail/acpi/dptf/dptf.asl b/src/soc/intel/baytrail/acpi/dptf/dptf.asl new file mode 100644 index 0000000000..9ebfb8c9ce --- /dev/null +++ b/src/soc/intel/baytrail/acpi/dptf/dptf.asl @@ -0,0 +1,78 @@ +Device (DPTF) +{ + Name (_HID, EISAID ("INT3400")) + Name (_UID, 0) + + Name (IDSP, Package() + { + /* DPPM Passive Policy 1.0 */ + ToUUID ("42A441D6-AE6A-462B-A84B-4A8CE79027D3"), + + /* DPPM Critical Policy */ + ToUUID ("97C68AE7-15FA-499c-B8C9-5DA81D606E0A"), + + /* DPPM Cooling Policy */ + ToUUID ("16CAF1B7-DD38-40ED-B1C1-1B8A1913D531"), + }) + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + /* Arg0: Buffer containing UUID + * Arg1: Integer containing Revision ID of buffer format + * Arg2: Integer containing count of entries in Arg3 + * Arg3: Buffer containing list of DWORD capabilities + * Return: Buffer containing list of DWORD capabilities + */ + Method (_OSC, 4, Serialized) + { + /* Check for Passive Policy UUID */ + If (LEqual (DeRefOf (Index (IDSP, 0)), Arg0)) { + /* Initialize Thermal Devices */ + ^TINI () + +#ifdef DPTF_ENABLE_CHARGER + /* Initialize Charger Device */ + ^TCHG.INIT () +#endif + } + + Return (Arg3) + } + + /* Priority based _TRT */ + Name (TRTR, 1) + + Method (_TRT) + { + Return (\_SB.DTRT) + } + + /* Convert from Degrees C to 1/10 Kelvin for ACPI */ + Method (CTOK, 1) { + /* 10th of Degrees C */ + Multiply (Arg0, 10, Local0) + + /* Convert to Kelvin */ + Add (Local0, 2732, Local0) + + Return (Local0) + } + + /* Include CPU Participant */ + #include "cpu.asl" + + /* Include Thermal Participants */ + #include "thermal.asl" + +#ifdef DPTF_ENABLE_CHARGER + /* Include Charger Participant */ + #include "charger.asl" +#endif +} diff --git a/src/soc/intel/baytrail/acpi/dptf/thermal.asl b/src/soc/intel/baytrail/acpi/dptf/thermal.asl new file mode 100644 index 0000000000..7113215cd3 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/dptf/thermal.asl @@ -0,0 +1,203 @@ +/* Thermal Threshold Event Handler */ +Method (TEVT, 1, NotSerialized) +{ + Store (ToInteger (Arg0), Local0) + +#ifdef DPTF_TSR0_SENSOR_ID + If (LEqual (Local0, DPTF_TSR0_SENSOR_ID)) { + Notify (^TSR0, 0x90) + } +#endif +#ifdef DPTF_TSR1_SENSOR_ID + If (LEqual (Local0, DPTF_TSR1_SENSOR_ID)) { + Notify (^TSR1, 0x90) + } +#endif +#ifdef DPTF_TSR2_SENSOR_ID + If (LEqual (Local0, DPTF_TSR2_SENSOR_ID)) { + Notify (^TSR2, 0x90) + } +#endif +} + +/* Thermal device initialization - Disable Aux Trip Points */ +Method (TINI) +{ +#ifdef DPTF_TSR0_SENSOR_ID + ^TSR0.PATD () +#endif +#ifdef DPTF_TSR1_SENSOR_ID + ^TSR1.PATD () +#endif +#ifdef DPTF_TSR2_SENSOR_ID + ^TSR2.PATD () +#endif +} + +#ifdef DPTF_TSR0_SENSOR_ID +Device (TSR0) +{ + Name (_HID, EISAID ("INT3403")) + Name (_UID, 1) + Name (PTYP, 0x03) + Name (TMPI, DPTF_TSR0_SENSOR_ID) + Name (_STR, Unicode (DPTF_TSR0_SENSOR_NAME)) + Name (GTSH, 20) /* 2 degree hysteresis */ + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Method (_TMP, 0, Serialized) + { + Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI)) + } + + Method (_PSV) + { + Return (^^CTOK (DPTF_TSR0_PASSIVE)) + } + + Method (_CRT) + { + Return (^^CTOK (DPTF_TSR0_CRITICAL)) + } + + Name (PATC, 2) + + /* Set Aux Trip Point */ + Method (PAT0, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0) + } + + /* Set Aux Trip Point */ + Method (PAT1, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0) + } + + /* Disable Aux Trip Point */ + Method (PATD, 0, Serialized) + { + \_SB.PCI0.LPCB.EC0.PATD (TMPI) + } +} +#endif + +#ifdef DPTF_TSR1_SENSOR_ID +Device (TSR1) +{ + Name (_HID, EISAID ("INT3403")) + Name (_UID, 2) + Name (PTYP, 0x03) + Name (TMPI, DPTF_TSR1_SENSOR_ID) + Name (_STR, Unicode (DPTF_TSR1_SENSOR_NAME)) + Name (GTSH, 20) /* 2 degree hysteresis */ + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Method (_TMP, 0, Serialized) + { + Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI)) + } + + Method (_PSV) + { + Return (^^CTOK (DPTF_TSR1_PASSIVE)) + } + + Method (_CRT) + { + Return (^^CTOK (DPTF_TSR1_CRITICAL)) + } + + Name (PATC, 2) + + /* Set Aux Trip Point */ + Method (PAT0, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0) + } + + /* Set Aux Trip Point */ + Method (PAT1, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0) + } + + /* Disable Aux Trip Point */ + Method (PATD, 0, Serialized) + { + \_SB.PCI0.LPCB.EC0.PATD (TMPI) + } +} +#endif + +#ifdef DPTF_TSR2_SENSOR_ID +Device (TSR2) +{ + Name (_HID, EISAID ("INT3403")) + Name (_UID, 3) + Name (PTYP, 0x03) + Name (TMPI, DPTF_TSR2_SENSOR_ID) + Name (_STR, Unicode (DPTF_TSR2_SENSOR_NAME)) + Name (GTSH, 20) /* 2 degree hysteresis */ + + Method (_STA) + { + If (LEqual (\DPTE, One)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + Method (_TMP, 0, Serialized) + { + Return (\_SB.PCI0.LPCB.EC0.TSRD (TMPI)) + } + + Method (_PSV) + { + Return (^^CTOK (DPTF_TSR2_PASSIVE)) + } + + Method (_CRT) + { + Return (^^CTOK (DPTF_TSR2_CRITICAL)) + } + + Name (PATC, 2) + + /* Set Aux Trip Point */ + Method (PAT0, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT0 (TMPI, Arg0) + } + + /* Set Aux Trip Point */ + Method (PAT1, 1, Serialized) + { + \_SB.PCI0.LPCB.EC0.PAT1 (TMPI, Arg0) + } + + /* Disable Aux Trip Point */ + Method (PATD, 0, Serialized) + { + \_SB.PCI0.LPCB.EC0.PATD (TMPI) + } +} +#endif diff --git a/src/soc/intel/baytrail/acpi/globalnvs.asl b/src/soc/intel/baytrail/acpi/globalnvs.asl new file mode 100644 index 0000000000..a201c03d50 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/globalnvs.asl @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* Global Variables */ + +Name(\PICM, 0) // IOAPIC/8259 + +/* Global ACPI memory region. This region is used for passing information + * between coreboot (aka "the system bios"), ACPI, and the SMI handler. + * Since we don't know where this will end up in memory at ACPI compile time, + * we have to fix it up in coreboot's ACPI creation phase. + */ + + +OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0x2000) +Field (GNVS, ByteAcc, NoLock, Preserve) +{ + /* Miscellaneous */ + Offset (0x00), + OSYS, 16, // 0x00 - Operating System + SMIF, 8, // 0x02 - SMI function + PRM0, 8, // 0x03 - SMI function parameter + PRM1, 8, // 0x04 - SMI function parameter + SCIF, 8, // 0x05 - SCI function + PRM2, 8, // 0x06 - SCI function parameter + PRM3, 8, // 0x07 - SCI function parameter + LCKF, 8, // 0x08 - Global Lock function for EC + PRM4, 8, // 0x09 - Lock function parameter + PRM5, 8, // 0x0a - Lock function parameter + P80D, 32, // 0x0b - Debug port (IO 0x80) value + LIDS, 8, // 0x0f - LID state (open = 1) + PWRS, 8, // 0x10 - Power State (AC = 1) + PCNT, 8, // 0x11 - Processor count + TPMP, 8, // 0x12 - TPM Present and Enabled + TLVL, 8, // 0x13 - Throttle Level + PPCM, 8, // 0x14 - Maximum P-state usable by OS + PM1I, 32, // 0x15 - System Wake Source - PM1 Index + + /* Device Config */ + Offset (0x20), + S5U0, 8, // 0x20 - Enable USB0 in S5 + S5U1, 8, // 0x21 - Enable USB1 in S5 + S3U0, 8, // 0x22 - Enable USB0 in S3 + S3U1, 8, // 0x23 - Enable USB1 in S3 + TACT, 8, // 0x24 - Thermal Active trip point + TPSV, 8, // 0x25 - Thermal Passive trip point + TCRT, 8, // 0x26 - Thermal Critical trip point + DPTE, 8, // 0x27 - Enable DPTF + + /* Base addresses */ + Offset (0x30), + CMEM, 32, // 0x30 - CBMEM TOC + TOLM, 32, // 0x34 - Top of Low Memory + CBMC, 32, // 0x38 - coreboot mem console pointer + + /* ChromeOS specific */ + Offset (0x100), + #include + + Offset (0x1000), + #include +} + +/* Set flag to enable USB charging in S3 */ +Method (S3UE) +{ + Store (One, \S3U0) + Store (One, \S3U1) +} + +/* Set flag to disable USB charging in S3 */ +Method (S3UD) +{ + Store (Zero, \S3U0) + Store (Zero, \S3U1) +} + +/* Set flag to enable USB charging in S5 */ +Method (S5UE) +{ + Store (One, \S5U0) + Store (One, \S5U1) +} + +/* Set flag to disable USB charging in S5 */ +Method (S5UD) +{ + Store (Zero, \S5U0) + Store (Zero, \S5U1) +} diff --git a/src/soc/intel/baytrail/acpi/gpio.asl b/src/soc/intel/baytrail/acpi/gpio.asl new file mode 100644 index 0000000000..aa6af717c1 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/gpio.asl @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +/* SouthCluster GPIO */ +Device (GPSC) +{ + Name (_HID, "INT33FC") + Name (_CID, "INT33FC") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, RMEM) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,) + { + GPIO_SC_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^RMEM._BAS, RBAS) + Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSCORE, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + Return (0xF) + } +} + +/* NorthCluster GPIO */ +Device (GPNC) +{ + Name (_HID, "INT33FC") + Name (_CID, "INT33FC") + Name (_UID, 2) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, RMEM) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,) + { + GPIO_NC_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^RMEM._BAS, RBAS) + Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPNCORE, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + Return (0xF) + } +} + +/* SUS GPIO */ +Device (GPSS) +{ + Name (_HID, "INT33FC") + Name (_CID, "INT33FC") + Name (_UID, 3) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, RMEM) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared,,,) + { + GPIO_SUS_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^RMEM._BAS, RBAS) + Add (IO_BASE_ADDRESS, IO_BASE_OFFSET_GPSSUS, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + Return (0xF) + } +} diff --git a/src/soc/intel/baytrail/acpi/irq_helper.h b/src/soc/intel/baytrail/acpi/irq_helper.h new file mode 100644 index 0000000000..b19895b583 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/irq_helper.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#undef PCI_DEV_PIRQ_ROUTES +#undef ACPI_DEV_APIC_IRQ +#undef PCI_DEV_PIRQ_ROUTE +#undef PIRQ_PIC_ROUTES +#undef PIRQ_PIC + +#if defined(PIC_MODE) + +#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \ + Package() { ## dev_ ## ffff, pin_, \_SB.PCI0.LPCB.LNK ## pin_name_, 0 } + +#else /* defined(PIC_MODE) */ + +#define ACPI_DEV_APIC_IRQ(dev_, pin_, pin_name_) \ + Package() { ## dev_ ## ffff, pin_, 0, PIRQ ## pin_name_ ## _APIC_IRQ } + +#endif + +#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \ + ACPI_DEV_APIC_IRQ(dev_, 0, a_), \ + ACPI_DEV_APIC_IRQ(dev_, 1, b_), \ + ACPI_DEV_APIC_IRQ(dev_, 2, c_), \ + ACPI_DEV_APIC_IRQ(dev_, 3, d_) + +/* Empty PIRQ_PIC definition. */ +#define PIRQ_PIC(pirq_, pic_irq_) + +/* Include the mainboard irq route definition. */ +#include "irqroute.h" diff --git a/src/soc/intel/baytrail/acpi/irqlinks.asl b/src/soc/intel/baytrail/acpi/irqlinks.asl new file mode 100644 index 0000000000..5fcee45f29 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/irqlinks.asl @@ -0,0 +1,493 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (LNKA) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 1) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTA) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLA, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLA, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTA + ShiftLeft(1, And(PRTA, 0x0f), IRQ0) + + Return (RTLA) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTA) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTA, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKB) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 2) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTB) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLB, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLB, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTB + ShiftLeft(1, And(PRTB, 0x0f), IRQ0) + + Return (RTLB) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTB) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTB, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKC) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 3) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTC) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLC, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLC, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTC + ShiftLeft(1, And(PRTC, 0x0f), IRQ0) + + Return (RTLC) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTC) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTC, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKD) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 4) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTD) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLD, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLD, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTD + ShiftLeft(1, And(PRTD, 0x0f), IRQ0) + + Return (RTLD) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTD) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTD, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKE) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 5) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTE) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLE, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLE, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTE + ShiftLeft(1, And(PRTE, 0x0f), IRQ0) + + Return (RTLE) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTE) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTE, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKF) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 6) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTF) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLF, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLF, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTF + ShiftLeft(1, And(PRTF, 0x0f), IRQ0) + + Return (RTLF) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTF) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTF, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKG) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 7) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTG) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLG, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLG, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTG + ShiftLeft(1, And(PRTG, 0x0f), IRQ0) + + Return (RTLG) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTG) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTG, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKH) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 8) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTH) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLH, ResourceTemplate() + { + IRQ(Level, ActiveLow, Shared) {} + }) + CreateWordField(RTLH, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTH + ShiftLeft(1, And(PRTH, 0x0f), IRQ0) + + Return (RTLH) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField(Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit(IRQ0, Local0) + + Decrement(Local0) + Store(Local0, PRTH) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And(PRTH, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + diff --git a/src/soc/intel/baytrail/acpi/irqroute.asl b/src/soc/intel/baytrail/acpi/irqroute.asl new file mode 100644 index 0000000000..23987d7d2a --- /dev/null +++ b/src/soc/intel/baytrail/acpi/irqroute.asl @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// PCI Interrupt Routing +Method(_PRT) +{ + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include + PCI_DEV_PIRQ_ROUTES + }) + } Else { + Return (Package() { + #define PIC_MODE + #include + PCI_DEV_PIRQ_ROUTES + }) + } +} diff --git a/src/soc/intel/baytrail/acpi/lpc.asl b/src/soc/intel/baytrail/acpi/lpc.asl new file mode 100644 index 0000000000..408d2b420f --- /dev/null +++ b/src/soc/intel/baytrail/acpi/lpc.asl @@ -0,0 +1,167 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +// Intel LPC Bus Device - 0:1f.0 + +Device (LPCB) +{ + Name(_ADR, 0x001f0000) + + #include "irqlinks.asl" + + #include "acpi/ec.asl" + + Device (DMAC) // DMA Controller + { + Name(_HID, EISAID("PNP0200")) + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x00, 0x00, 0x01, 0x20) + IO (Decode16, 0x81, 0x81, 0x01, 0x11) + IO (Decode16, 0x93, 0x93, 0x01, 0x0d) + IO (Decode16, 0xc0, 0xc0, 0x01, 0x20) + DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 } + }) + } + + Device (FWH) // Firmware Hub + { + Name (_HID, EISAID("INT0800")) + Name (_CRS, ResourceTemplate() + { + Memory32Fixed(ReadOnly, 0xff000000, 0x01000000) + }) + } + + Device (HPET) + { + Name (_HID, EISAID("PNP0103")) + Name (_CID, 0x010CD041) + + Method (_STA, 0) // Device Status + { + Return (0xf) // Enable and show device + } + + Name(_CRS, ResourceTemplate() + { + Memory32Fixed(ReadOnly, 0xfed00000, 0x400) + }) + } + + Device(PIC) // 8259 Interrupt Controller + { + Name(_HID,EISAID("PNP0000")) + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x20, 0x20, 0x01, 0x02) + IO (Decode16, 0x24, 0x24, 0x01, 0x02) + IO (Decode16, 0x28, 0x28, 0x01, 0x02) + IO (Decode16, 0x2c, 0x2c, 0x01, 0x02) + IO (Decode16, 0x30, 0x30, 0x01, 0x02) + IO (Decode16, 0x34, 0x34, 0x01, 0x02) + IO (Decode16, 0x38, 0x38, 0x01, 0x02) + IO (Decode16, 0x3c, 0x3c, 0x01, 0x02) + IO (Decode16, 0xa0, 0xa0, 0x01, 0x02) + IO (Decode16, 0xa4, 0xa4, 0x01, 0x02) + IO (Decode16, 0xa8, 0xa8, 0x01, 0x02) + IO (Decode16, 0xac, 0xac, 0x01, 0x02) + IO (Decode16, 0xb0, 0xb0, 0x01, 0x02) + IO (Decode16, 0xb4, 0xb4, 0x01, 0x02) + IO (Decode16, 0xb8, 0xb8, 0x01, 0x02) + IO (Decode16, 0xbc, 0xbc, 0x01, 0x02) + IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02) + IRQNoFlags () { 2 } + }) + } + + Device(LDRC) // LPC device: Resource consumption + { + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 2) + + Name (RBUF, ResourceTemplate() + { + IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status + IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post + IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI + }) + + Method (_CRS, 0, NotSerialized) + { + Return (RBUF) + } + } + + Device (RTC) // Real Time Clock + { + Name (_HID, EISAID("PNP0B00")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x70, 0x70, 1, 8) +// Disable as Windows doesn't like it, and systems don't seem to use it. +// IRQNoFlags() { 8 } + }) + } + + Device (TIMR) // Intel 8254 timer + { + Name(_HID, EISAID("PNP0100")) + Name(_CRS, ResourceTemplate() + { + IO (Decode16, 0x40, 0x40, 0x01, 0x04) + IO (Decode16, 0x50, 0x50, 0x10, 0x04) + IRQNoFlags() {0} + }) + } + + // Include mainboard's superio.asl file. + #include "acpi/superio.asl" + +#ifdef ENABLE_TPM + Device (TPM) // Trusted Platform Module + { + Name(_HID, EISAID("IFX0102")) + Name(_CID, 0x310cd041) + Name(_UID, 1) + + Method(_STA, 0) + { + If (TPMP) { + Return (0xf) + } + Return (0x0) + } + + Name(_CRS, ResourceTemplate() { + IO (Decode16, 0x2e, 0x2e, 0x01, 0x02) + IO (Decode16, 0x6f0, 0x6f0, 0x01, 0x10) + Memory32Fixed (ReadWrite, 0xfed40000, 0x5000) + IRQ (Edge, Activehigh, Exclusive) { 6 } + }) + } +#endif +} diff --git a/src/soc/intel/baytrail/acpi/lpe.asl b/src/soc/intel/baytrail/acpi/lpe.asl new file mode 100644 index 0000000000..dfa555c834 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/lpe.asl @@ -0,0 +1,119 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (LPEA) +{ + Name (_HID, "80860F28") + Name (_CID, "80860F28") + Name (_UID, 1) + Name (_DDN, "Low Power Audio Controller") + Name (_PR0, Package () { PLPE }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x00200000, BAR0) + Memory32Fixed (ReadWrite, 0, 0x00001000, BAR1) + Memory32Fixed (ReadWrite, 0, 0x00100000, BAR2) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_DMA0_IRQ + } + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_DMA1_IRQ + } + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_SSP0_IRQ + } + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_SSP1_IRQ + } + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_SSP2_IRQ + } + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPE_IPC2HOST_IRQ + } + }) + + Method (_CRS) + { + /* Update BAR0 from NVS */ + CreateDwordField (^RBUF, ^BAR0._BAS, BAS0) + Store (\LPB0, BAS0) + + /* Update BAR1 from NVS */ + CreateDwordField (^RBUF, ^BAR1._BAS, BAS1) + Store (\LPB1, BAS1) + + /* Update LPE FW from NVS */ + CreateDwordField (^RBUF, ^BAR2._BAS, BAS2) + Store (\LPFW, BAS2) + + /* Append any Mainboard defined GPIOs */ + If (CondRefOf (^GBUF, Local0)) { + ConcatenateResTemplate (^RBUF, ^GBUF, Local1) + Return (Local1) + } + + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\LPEN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, LPB1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + PowerResource (PLPE, 0, 0) + { + Method (_STA) + { + Return (1) + } + + Method (_OFF) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_ON) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + } +} diff --git a/src/soc/intel/baytrail/acpi/lpss.asl b/src/soc/intel/baytrail/acpi/lpss.asl new file mode 100644 index 0000000000..0f8f7465f9 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/lpss.asl @@ -0,0 +1,712 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (SDM1) +{ + Name (_HID, "INTL9C60") + Name (_UID, 1) + Name (_DDN, "DMA Controller #1") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_DMA1_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S0B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S0EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } +} + +Device (SDM2) +{ + Name (_HID, "INTL9C60") + Name (_UID, 2) + Name (_DDN, "DMA Controller #2") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_DMA2_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S8B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S8EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } +} + +Device (I2C1) +{ + Name (_HID, "80860F41") + Name (_UID, 1) + Name (_DDN, "I2C Controller #1") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C1_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S1B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S1B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C2) +{ + Name (_HID, "80860F41") + Name (_UID, 2) + Name (_DDN, "I2C Controller #2") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C2_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S2B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S2B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C3) +{ + Name (_HID, "80860F41") + Name (_UID, 3) + Name (_DDN, "I2C Controller #3") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C3_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S3B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S3EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S3B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C4) +{ + Name (_HID, "80860F41") + Name (_UID, 4) + Name (_DDN, "I2C Controller #4") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C4_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S4B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S4EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S4B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C5) +{ + Name (_HID, "80860F41") + Name (_UID, 5) + Name (_DDN, "I2C Controller #5") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C5_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S5B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S5EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S5B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C6) +{ + Name (_HID, "80860F41") + Name (_UID, 6) + Name (_DDN, "I2C Controller #6") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C6_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S6B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S6EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S6B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (I2C7) +{ + Name (_HID, "80860F41") + Name (_UID, 7) + Name (_DDN, "I2C Controller #7") + + /* Standard Mode: HCNT, LCNT, SDA Hold Time */ + Name (SSCN, Package () { 0x200, 0x200, 0x6 }) + + /* Fast Mode: HCNT, LCNT, SDA Hold Time */ + Name (FMCN, Package () { 0x55, 0x99, 0x6 }) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_I2C7_IRQ + } + FixedDMA (0x10, 0x0, Width32Bit, ) + FixedDMA (0x11, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S7B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S7EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S7B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (SPI1) +{ + Name (_HID, "80860F0E") + Name (_UID, 1) + Name (_DDN, "SPI Controller #2") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_SPI_IRQ + } + FixedDMA (0x0, 0x0, Width32Bit, ) + FixedDMA (0x1, 0x1, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\S9B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\S9EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, S9B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (PWM1) +{ + Name (_HID, "80860F09") + Name (_UID, 1) + Name (_DDN, "PWM Controller #1") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\SAB0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\SAEN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } +} + +Device (PWM2) +{ + Name (_HID, "80860F09") + Name (_UID, 2) + Name (_DDN, "PWM Controller #2") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\SBB0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\SBEN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } +} + +Device (UAR1) +{ + Name (_HID, "80860F0A") + Name (_UID, 1) + Name (_DDN, "HS-UART Controller #1") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_HSUART1_IRQ + } + FixedDMA (0x2, 0x2, Width32Bit, ) + FixedDMA (0x3, 0x3, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\SCB0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\SCEN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, SCB1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (UAR2) +{ + Name (_HID, "80860F0A") + Name (_UID, 2) + Name (_DDN, "HS-UART Controller #2") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + LPSS_HSUART2_IRQ + } + FixedDMA (0x4, 0x4, Width32Bit, ) + FixedDMA (0x5, 0x5, Width32Bit, ) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\SDB0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\SDEN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, SDB1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} diff --git a/src/soc/intel/baytrail/acpi/pcie.asl b/src/soc/intel/baytrail/acpi/pcie.asl new file mode 100644 index 0000000000..5ad4e788fc --- /dev/null +++ b/src/soc/intel/baytrail/acpi/pcie.asl @@ -0,0 +1,109 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Intel SOC PCIe support */ + +Device (RP01) +{ + Name (_ADR, 0x001c0000) + + Method (_PRT) + { + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D) + }) + } Else { + Return (Package() { + #define PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, A, B, C, D) + }) + } + } +} + +Device (RP02) +{ + Name (_ADR, 0x001c0001) + + Method (_PRT) + { + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A) + }) + } Else { + Return (Package() { + #define PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, B, C, D, A) + }) + } + } +} + +Device (RP03) +{ + Name (_ADR, 0x001c0002) + + Method (_PRT) + { + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B) + }) + } Else { + Return (Package() { + #define PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, C, D, A, B) + }) + } + } +} + +Device (RP04) +{ + Name (_ADR, 0x001c0003) + + Method (_PRT) + { + If (PICM) { + Return (Package() { + #undef PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C) + }) + } Else { + Return (Package() { + #define PIC_MODE + #include + PCI_DEV_PIRQ_ROUTE(0x0, D, A, B, C) + }) + } + } +} diff --git a/src/soc/intel/baytrail/acpi/platform.asl b/src/soc/intel/baytrail/acpi/platform.asl new file mode 100644 index 0000000000..e32880ef9b --- /dev/null +++ b/src/soc/intel/baytrail/acpi/platform.asl @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method(TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method(_PIC, 1) +{ + // Remember the OS' IRQ routing choice. + Store(Arg0, PICM) +} + +/* The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method(_PTS,1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} + +Method (_SWS) +{ + /* Index into PM1 for device that caused wake */ + Return (\PM1I) +} diff --git a/src/soc/intel/baytrail/acpi/scc.asl b/src/soc/intel/baytrail/acpi/scc.asl new file mode 100644 index 0000000000..7181fb1669 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/scc.asl @@ -0,0 +1,187 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (EMMC) +{ + Name (_HID, "80860F14") + Name (_CID, "PNP0D40") + Name (_UID, 1) + Name (_DDN, "eMMC Controller 4.5") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + SCC_EMMC_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\C0B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\C0EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, C0B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Device (EM45) + { + /* Slot 0, Function 8 */ + Name (_ADR, 0x8) + + Method (_RMV, 0, NotSerialized) + { + Return (0) + } + } +} + +Device (SDIO) +{ + Name (_HID, "INT33BB") + Name (_CID, "PNP0D40") + Name (_UID, 2) + Name (_DDN, "SDIO Controller") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + SCC_SDIO_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\C1B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\C1EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, C1B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} + +Device (SDCD) +{ + Name (_HID, "80860F16") + Name (_CID, "PNP0D40") + Name (_UID, 3) + Name (_DDN, "SD Card Controller") + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0x1000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive,,,) + { + SCC_SD_IRQ + } + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^BAR0._BAS, RBAS) + Store (\C2B0, RBAS) + Return (^RBUF) + } + + Method (_STA) + { + If (LEqual (\C2EN, 1)) { + Return (0xF) + } Else { + Return (0x0) + } + } + + OperationRegion (KEYS, SystemMemory, C2B1, 0x100) + Field (KEYS, DWordAcc, NoLock, WriteAsZeros) + { + Offset (0x84), + PSAT, 32, + } + + Method (_PS3) + { + Or (PSAT, 0x00000003, PSAT) + Or (PSAT, 0x00000000, PSAT) + } + + Method (_PS0) + { + And (PSAT, 0xfffffffc, PSAT) + Or (PSAT, 0x00000000, PSAT) + } +} diff --git a/src/soc/intel/baytrail/acpi/sleepstates.asl b/src/soc/intel/baytrail/acpi/sleepstates.asl new file mode 100644 index 0000000000..06bfcb6a58 --- /dev/null +++ b/src/soc/intel/baytrail/acpi/sleepstates.asl @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Name(\_S0, Package(){0x0,0x0,0x0,0x0}) +// Name(\_S1, Package(){0x1,0x1,0x0,0x0}) +Name(\_S3, Package(){0x5,0x5,0x0,0x0}) +Name(\_S4, Package(){0x6,0x6,0x0,0x0}) +Name(\_S5, Package(){0x7,0x7,0x0,0x0}) + diff --git a/src/soc/intel/baytrail/acpi/southcluster.asl b/src/soc/intel/baytrail/acpi/southcluster.asl new file mode 100644 index 0000000000..47151a30fa --- /dev/null +++ b/src/soc/intel/baytrail/acpi/southcluster.asl @@ -0,0 +1,273 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include + +Scope(\) +{ + // IO-Trap at 0x800. This is the ACPI->SMI communication interface. + + OperationRegion(IO_T, SystemIO, 0x800, 0x10) + Field(IO_T, ByteAcc, NoLock, Preserve) + { + Offset(0x8), + TRP0, 8 // IO-Trap at 0x808 + } + + // Intel Legacy Block + OperationRegion(ILBS, SystemMemory, ILB_BASE_ADDRESS, ILB_BASE_SIZE) + Field (ILBS, AnyAcc, NoLock, Preserve) + { + Offset (0x8), + PRTA, 8, + PRTB, 8, + PRTC, 8, + PRTD, 8, + PRTE, 8, + PRTF, 8, + PRTG, 8, + PRTH, 8, + } +} + +Name(_HID,EISAID("PNP0A08")) // PCIe +Name(_CID,EISAID("PNP0A03")) // PCI + +Name(_ADR, 0) +Name(_BBN, 0) + +Method (_CRS, 0, Serialized) +{ + Name (MCRS, ResourceTemplate() + { + // Bus Numbers + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00) + + // IO Region 0 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00) + + // PCI Config Space + Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008) + + // IO Region 1 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01) + + // VGA memory (0xa0000-0xbffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000a0000, 0x000bffff, 0x00000000, + 0x00020000,,, ASEG) + + // OPROM reserved (0xc0000-0xc3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c0000, 0x000c3fff, 0x00000000, + 0x00004000,,, OPR0) + + // OPROM reserved (0xc4000-0xc7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c4000, 0x000c7fff, 0x00000000, + 0x00004000,,, OPR1) + + // OPROM reserved (0xc8000-0xcbfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c8000, 0x000cbfff, 0x00000000, + 0x00004000,,, OPR2) + + // OPROM reserved (0xcc000-0xcffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000cc000, 0x000cffff, 0x00000000, + 0x00004000,,, OPR3) + + // OPROM reserved (0xd0000-0xd3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d0000, 0x000d3fff, 0x00000000, + 0x00004000,,, OPR4) + + // OPROM reserved (0xd4000-0xd7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d4000, 0x000d7fff, 0x00000000, + 0x00004000,,, OPR5) + + // OPROM reserved (0xd8000-0xdbfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d8000, 0x000dbfff, 0x00000000, + 0x00004000,,, OPR6) + + // OPROM reserved (0xdc000-0xdffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000dc000, 0x000dffff, 0x00000000, + 0x00004000,,, OPR7) + + // BIOS Extension (0xe0000-0xe3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e0000, 0x000e3fff, 0x00000000, + 0x00004000,,, ESG0) + + // BIOS Extension (0xe4000-0xe7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e4000, 0x000e7fff, 0x00000000, + 0x00004000,,, ESG1) + + // BIOS Extension (0xe8000-0xebfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e8000, 0x000ebfff, 0x00000000, + 0x00004000,,, ESG2) + + // BIOS Extension (0xec000-0xeffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000ec000, 0x000effff, 0x00000000, + 0x00004000,,, ESG3) + + // System BIOS (0xf0000-0xfffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000f0000, 0x000fffff, 0x00000000, + 0x00010000,,, FSEG) + + // PCI Memory Region (Top of memory-0xfeafffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0xfea00000, 0xfeafffff, 0x00000000, + 0x00100000,,, PMEM) + + // TPM Area (0xfed40000-0xfed44fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0xfed40000, 0xfed44fff, 0x00000000, + 0x00005000,,, TPMR) + }) + + // Update PCI resource area + CreateDwordField(MCRS, PMEM._MIN, PMIN) + CreateDwordField(MCRS, PMEM._MAX, PMAX) + CreateDwordField(MCRS, PMEM._LEN, PLEN) + + // TOLM is BMBOUND accessible from IOSF so is saved in NVS + Store (\TOLM, PMIN) + Add (Subtract (PMAX, PMIN), 1, PLEN) + + Return (MCRS) +} + +/* Device Resource Consumption */ +Device (PDRC) +{ + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 1) + + Name (PDRS, ResourceTemplate() { + Memory32Fixed(ReadWrite, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE) + Memory32Fixed(ReadWrite, MCFG_BASE_ADDRESS, MCFG_BASE_SIZE) + Memory32Fixed(ReadWrite, PMC_BASE_ADDRESS, PMC_BASE_SIZE) + Memory32Fixed(ReadWrite, ILB_BASE_ADDRESS, ILB_BASE_SIZE) + Memory32Fixed(ReadWrite, SPI_BASE_ADDRESS, SPI_BASE_SIZE) + Memory32Fixed(ReadWrite, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE) + Memory32Fixed(ReadWrite, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE) + Memory32Fixed(ReadWrite, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE) + }) + + // Current Resource Settings + Method (_CRS, 0, Serialized) + { + Return(PDRS) + } +} + +Method (_OSC, 4) +{ + /* Check for proper GUID */ + If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) + { + /* Let OS control everything */ + Return (Arg3) + } + Else + { + /* Unrecognized UUID */ + CreateDWordField (Arg3, 0, CDW1) + Or (CDW1, 4, CDW1) + Return (Arg3) + } +} + +/* IOSF MBI Interface for kernel access */ +Device (IOSF) +{ + Name (_HID, "INT33BD") + Name (_CID, "INT33BD") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate () + { + /* MCR / MDR / MCRX */ + Memory32Fixed (ReadWrite, 0, 12, RBAR) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^RBAR._BAS, RBAS) + Store (Add (MCFG_BASE_ADDRESS, 0xD0), RBAS) + Return (^RBUF) + } +} + +// LPC Bridge 0:1f.0 +#include "lpc.asl" + +// USB XHCI 0:14.0 +#include "xhci.asl" + +// IRQ routing for each PCI device +#include "irqroute.asl" + +// PCI Express Ports 0:1c.x +#include "pcie.asl" + +Scope (\_SB) +{ + // GPIO Devices + #include "gpio.asl" + + // LPSS Devices + #include "lpss.asl" + + // SCC Devices + #include "scc.asl" + + // LPE Device + #include "lpe.asl" +} diff --git a/src/soc/intel/baytrail/acpi/xhci.asl b/src/soc/intel/baytrail/acpi/xhci.asl new file mode 100644 index 0000000000..4d5367acec --- /dev/null +++ b/src/soc/intel/baytrail/acpi/xhci.asl @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device (XHCI) +{ + Name (_ADR, 0x00140000) + Name (_PRW, Package () { 0x0d, 3 }) + Name (_S3D, 3) /* Highest D state in S3 state */ + + Device (RHUB) + { + Name (_ADR, 0x00000000) + Device (PRT1) { Name (_ADR, 1) } + Device (PRT2) { Name (_ADR, 2) } + Device (PRT3) { Name (_ADR, 3) } + Device (PRT4) { Name (_ADR, 4) } + } +} diff --git a/src/soc/intel/baytrail/bootblock/Makefile.inc b/src/soc/intel/baytrail/bootblock/Makefile.inc new file mode 100644 index 0000000000..3a4025198c --- /dev/null +++ b/src/soc/intel/baytrail/bootblock/Makefile.inc @@ -0,0 +1 @@ +chipset_bootblock_inc += $(src)/soc/intel/baytrail/bootblock/timestamp.inc diff --git a/src/soc/intel/baytrail/bootblock/bootblock.c b/src/soc/intel/baytrail/bootblock/bootblock.c new file mode 100644 index 0000000000..6eedbd0372 --- /dev/null +++ b/src/soc/intel/baytrail/bootblock/bootblock.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +static void set_var_mtrr(int reg, uint32_t base, uint32_t size, int type) +{ + msr_t basem, maskm; + basem.lo = base | type; + basem.hi = 0; + wrmsr(MTRRphysBase_MSR(reg), basem); + maskm.lo = ~(size - 1) | MTRRphysMaskValid; + maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; + wrmsr(MTRRphysMask_MSR(reg), maskm); +} + +static void enable_rom_caching(void) +{ + msr_t msr; + + disable_cache(); + /* Why only top 4MiB ? */ + set_var_mtrr(1, 0xffc00000, 4*1024*1024, MTRR_TYPE_WRPROT); + enable_cache(); + + /* Enable Variable MTRRs */ + msr.hi = 0x00000000; + msr.lo = 0x00000800; + wrmsr(MTRRdefType_MSR, msr); +} + +static void setup_mmconfig(void) +{ + uint32_t reg; + + /* Set up the MMCONF range. The register lives in the BUNIT. The + * IO variant of the config access needs to be used initially to + * properly configure as the IOSF access registers live in PCI + * config space. */ + reg = 0; + /* Clear the extended register. */ + pci_io_write_config32(IOSF_PCI_DEV, MCRX_REG, reg); + reg = CONFIG_MMCONF_BASE_ADDRESS | 1; + pci_io_write_config32(IOSF_PCI_DEV, MDR_REG, reg); + reg = IOSF_OPCODE(IOSF_OP_WRITE_BUNIT) | IOSF_PORT(IOSF_PORT_BUNIT) | + IOSF_REG(BUNIT_MMCONF_REG) | IOSF_BYTE_EN; + pci_io_write_config32(IOSF_PCI_DEV, MCR_REG, reg); +} + +static void bootblock_cpu_init(void) +{ + /* Allow memory-mapped PCI config access. */ + setup_mmconfig(); + + /* Load microcode before any caching. */ + intel_update_microcode_from_cbfs(); + enable_rom_caching(); +} diff --git a/src/soc/intel/baytrail/bootblock/timestamp.inc b/src/soc/intel/baytrail/bootblock/timestamp.inc new file mode 100644 index 0000000000..f565775ed8 --- /dev/null +++ b/src/soc/intel/baytrail/bootblock/timestamp.inc @@ -0,0 +1,19 @@ +/* Store the initial timestamp for booting in mmx registers. This works + * because the bootblock isn't being compiled with MMX support so mm0 and + * mm1 will be preserved into romstage. */ + .code32 + +.global stash_timestamp +stash_timestamp: + + /* Save the BIST value */ + movl %eax, %ebp + + finit + rdtsc + movd %eax, %mm0 + movd %edx, %mm1 + + /* Restore the BIST value to %eax */ + movl %ebp, %eax + diff --git a/src/soc/intel/baytrail/chip.c b/src/soc/intel/baytrail/chip.c new file mode 100644 index 0000000000..b842713fbc --- /dev/null +++ b/src/soc/intel/baytrail/chip.c @@ -0,0 +1,94 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include +#include "chip.h" + +static void pci_domain_set_resources(device_t dev) +{ + assign_resources(dev->link_list); +} + +static struct device_operations pci_domain_ops = { + .read_resources = pci_domain_read_resources, + .set_resources = pci_domain_set_resources, + .enable_resources = NULL, + .init = NULL, + .scan_bus = pci_domain_scan_bus, + .ops_pci_bus = &pci_ops_mmconf, +}; + +static void cpu_bus_noop(device_t dev) { } + +static struct device_operations cpu_bus_ops = { + .read_resources = cpu_bus_noop, + .set_resources = cpu_bus_noop, + .enable_resources = cpu_bus_noop, + .init = baytrail_init_cpus, + .scan_bus = NULL, +}; + + +static void enable_dev(device_t dev) +{ + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_DOMAIN) { + dev->ops = &pci_domain_ops; + } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { + dev->ops = &cpu_bus_ops; + } else if (dev->path.type == DEVICE_PATH_PCI) { + /* Handle south cluster enablement. */ + if (PCI_SLOT(dev->path.pci.devfn) > GFX_DEV && + (dev->ops == NULL || dev->ops->enable == NULL)) { + southcluster_enable_dev(dev); + } + } +} + +/* Called at BS_DEV_INIT_CHIPS time -- very early. Just after BS_PRE_DEVICE. */ +static void soc_init(void *chip_info) +{ + baytrail_init_pre_device(chip_info); +} + +struct chip_operations soc_intel_baytrail_ops = { + CHIP_NAME("Intel BayTrail SoC") + .enable_dev = enable_dev, + .init = soc_init, +}; + +static void pci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + } +} + +struct pci_operations soc_pci_ops = { + .set_subsystem = &pci_set_subsystem, +}; diff --git a/src/soc/intel/baytrail/chip.h b/src/soc/intel/baytrail/chip.h new file mode 100644 index 0000000000..97b92efb99 --- /dev/null +++ b/src/soc/intel/baytrail/chip.h @@ -0,0 +1,94 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The devicetree parser expects chip.h to reside directly in the path + * specified by the devicetree. */ + +#ifndef _BAYTRAIL_CHIP_H_ +#define _BAYTRAIL_CHIP_H_ + +#include + +struct soc_intel_baytrail_config { + uint8_t enable_xdp_tap; + uint8_t sata_port_map; + uint8_t sata_ahci; + uint8_t ide_legacy_combined; + uint8_t clkreq_enable; + + /* VR low power settings -- enable PS2 mode for gfx and core */ + int vnn_ps2_enable; + int vcc_ps2_enable; + + /* Disable SLP_X stretching after SUS power well loss. */ + int disable_slp_x_stretch_sus_fail; + + /* USB Port Disable mask */ + uint16_t usb2_port_disable_mask; + uint16_t usb3_port_disable_mask; + + /* USB routing */ + int usb_route_to_xhci; + + /* USB PHY settings specific to the board */ + uint32_t usb2_per_port_lane0; + uint32_t usb2_per_port_rcomp_hs_pullup0; + uint32_t usb2_per_port_lane1; + uint32_t usb2_per_port_rcomp_hs_pullup1; + uint32_t usb2_per_port_lane2; + uint32_t usb2_per_port_rcomp_hs_pullup2; + uint32_t usb2_per_port_lane3; + uint32_t usb2_per_port_rcomp_hs_pullup3; + uint32_t usb2_comp_bg; + + /* LPE Audio Clock configuration. */ + int lpe_codec_clk_freq; /* 19 or 25 are valid. */ + int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */ + + /* Native SD Card controller - override controller capabilities. */ + uint32_t sdcard_cap_low; + uint32_t sdcard_cap_high; + + /* Enable devices in ACPI mode */ + int lpss_acpi_mode; + int scc_acpi_mode; + int lpe_acpi_mode; + + /* Allow PCIe devices to wake system from suspend. */ + int pcie_wake_enable; + + int gpu_pipea_port_select; /* Port select: 1=DP_B 2=DP_C */ + uint16_t gpu_pipea_power_on_delay; + uint16_t gpu_pipea_light_on_delay; + uint16_t gpu_pipea_power_off_delay; + uint16_t gpu_pipea_light_off_delay; + uint16_t gpu_pipea_power_cycle_delay; + int gpu_pipea_pwm_freq_hz; + + int gpu_pipeb_port_select; /* Port select: 1=DP_B 2=DP_C */ + uint16_t gpu_pipeb_power_on_delay; + uint16_t gpu_pipeb_light_on_delay; + uint16_t gpu_pipeb_power_off_delay; + uint16_t gpu_pipeb_light_off_delay; + uint16_t gpu_pipeb_power_cycle_delay; + int gpu_pipeb_pwm_freq_hz; +}; + +extern struct chip_operations soc_intel_baytrail_ops; +#endif /* _BAYTRAIL_CHIP_H_ */ diff --git a/src/soc/intel/baytrail/cpu.c b/src/soc/intel/baytrail/cpu.c new file mode 100644 index 0000000000..f4d752eb94 --- /dev/null +++ b/src/soc/intel/baytrail/cpu.c @@ -0,0 +1,309 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static void smm_relocate(void *unused); +static void enable_smis(void *unused); + +static struct mp_flight_record mp_steps[] = { + MP_FR_BLOCK_APS(smm_relocate, NULL, smm_relocate, NULL), + MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL), + /* Wait for APs to finish initialization before proceeding. */ + MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), +}; + +/* The APIC id space on Bay Trail is sparse. Each id is separated by 2. */ +static int adjust_apic_id(int index, int apic_id) +{ + return 2 * index; +} + +/* Package level MSRs */ +const struct reg_script package_msr_script[] = { + /* Set Package TDP to ~7W */ + REG_MSR_WRITE(MSR_PKG_POWER_LIMIT, 0x3880fa), + REG_MSR_RMW(MSR_PP1_POWER_LIMIT, ~(0x7f << 17), 0), + REG_MSR_WRITE(MSR_PKG_TURBO_CFG1, 0x702), + REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG1, 0x200b), + REG_MSR_WRITE(MSR_CPU_TURBO_WKLD_CFG2, 0), + REG_MSR_WRITE(MSR_CPU_THERM_CFG1, 0x00000305), + REG_MSR_WRITE(MSR_CPU_THERM_CFG2, 0x0405500d), + REG_MSR_WRITE(MSR_CPU_THERM_SENS_CFG, 0x27), + REG_SCRIPT_END +}; + +/* Core level MSRs */ +const struct reg_script core_msr_script[] = { + /* Dynamic L2 shrink enable and threshold, clear SINGLE_PCTL bit 11 */ + REG_MSR_RMW(MSR_PMG_CST_CONFIG_CONTROL, ~0x3f080f, 0xe0008), + REG_MSR_RMW(MSR_POWER_MISC, + ~(ENABLE_ULFM_AUTOCM_MASK | ENABLE_INDP_AUTOCM_MASK), 0), + /* Disable C1E */ + REG_MSR_RMW(MSR_POWER_CTL, ~0x2, 0), + REG_MSR_OR(MSR_POWER_MISC, 0x44), + REG_SCRIPT_END +}; + +void baytrail_init_cpus(device_t dev) +{ + struct bus *cpu_bus = dev->link_list; + const struct pattrs *pattrs = pattrs_get(); + struct mp_params mp_params; + uint32_t bsmrwac; + void *default_smm_area; + + /* Set up MTRRs based on physical address size. */ + x86_setup_fixed_mtrrs(); + x86_setup_var_mtrrs(pattrs->address_bits, 2); + x86_mtrr_check(); + + mp_params.num_cpus = pattrs->num_cpus, + mp_params.parallel_microcode_load = 1, + mp_params.adjust_apic_id = adjust_apic_id; + mp_params.flight_plan = &mp_steps[0]; + mp_params.num_records = ARRAY_SIZE(mp_steps); + mp_params.microcode_pointer = pattrs->microcode_patch; + + default_smm_area = backup_default_smm_area(); + + /* + * Configure the BUNIT to allow dirty cache line evictions in non-SMM + * mode for the lines that were dirtied while in SMM mode. Otherwise + * the writes would be silently dropped. + */ + bsmrwac = iosf_bunit_read(BUNIT_SMRWAC) | SAI_IA_UNTRUSTED; + iosf_bunit_write(BUNIT_SMRWAC, bsmrwac); + + /* Set package MSRs */ + reg_script_run(package_msr_script); + + /* Enable Turbo Mode on BSP and siblings of the BSP's building block. */ + enable_turbo(); + + if (mp_init(cpu_bus, &mp_params)) { + printk(BIOS_ERR, "MP initialization failure.\n"); + } + + restore_default_smm_area(default_smm_area); +} + +static void baytrail_core_init(device_t cpu) +{ + printk(BIOS_DEBUG, "Init BayTrail core.\n"); + + /* On bay trail the turbo disable bit is actually scoped at building + * block level -- not package. For non-bsp cores that are within a + * building block enable turbo. The cores within the BSP's building + * block will just see it already enabled and move on. */ + if (lapicid()) + enable_turbo(); + + /* Set core MSRs */ + reg_script_run(core_msr_script); + + /* Set this core to max frequency ratio */ + set_max_freq(); +} + +static struct device_operations cpu_dev_ops = { + .init = baytrail_core_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_INTEL, 0x30673 }, + { X86_VENDOR_INTEL, 0x30678 }, + { 0, 0 }, +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; + + +/* + * SMM loading and initialization. + */ + +struct smm_relocation_attrs { + uint32_t smbase; + uint32_t smrr_base; + uint32_t smrr_mask; +}; + +static struct smm_relocation_attrs relo_attrs; + +static void adjust_apic_id_map(struct smm_loader_params *smm_params) +{ + int i; + struct smm_runtime *runtime = smm_params->runtime; + + for (i = 0; i < CONFIG_MAX_CPUS; i++) + runtime->apic_id_to_cpu[i] = mp_get_apic_id(i); +} + +static void asmlinkage cpu_smm_do_relocation(void *arg) +{ + msr_t smrr; + em64t100_smm_state_save_area_t *smm_state; + const struct smm_module_params *p; + const struct smm_runtime *runtime; + int cpu; + + p = arg; + runtime = p->runtime; + cpu = p->cpu; + + if (cpu >= CONFIG_MAX_CPUS) { + printk(BIOS_CRIT, + "Invalid CPU number assigned in SMM stub: %d\n", cpu); + return; + } + + /* Set up SMRR. */ + smrr.lo = relo_attrs.smrr_base; + smrr.hi = 0; + wrmsr(SMRRphysBase_MSR, smrr); + smrr.lo = relo_attrs.smrr_mask; + smrr.hi = 0; + wrmsr(SMRRphysMask_MSR, smrr); + + /* The relocated handler runs with all CPUs concurrently. Therefore + * stagger the entry points adjusting SMBASE downwards by save state + * size * CPU num. */ + smm_state = (void *)(SMM_EM64T100_SAVE_STATE_OFFSET + runtime->smbase); + smm_state->smbase = relo_attrs.smbase - cpu * runtime->save_state_size; + printk(BIOS_DEBUG, "New SMBASE 0x%08x\n", smm_state->smbase); +} + +static int install_relocation_handler(int num_cpus) +{ + const int save_state_size = sizeof(em64t100_smm_state_save_area_t); + + struct smm_loader_params smm_params = { + .per_cpu_stack_size = save_state_size, + .num_concurrent_stacks = num_cpus, + .per_cpu_save_state_size = save_state_size, + .num_concurrent_save_states = 1, + .handler = (smm_handler_t)&cpu_smm_do_relocation, + }; + + if (smm_setup_relocation_handler(&smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; +} + +static int install_permanent_handler(int num_cpus) +{ + /* There are num_cpus concurrent stacks and num_cpus concurrent save + * state areas. Lastly, set the stack size to the save state size. */ + int save_state_size = sizeof(em64t100_smm_state_save_area_t); + struct smm_loader_params smm_params = { + .per_cpu_stack_size = save_state_size, + .num_concurrent_stacks = num_cpus, + .per_cpu_save_state_size = save_state_size, + .num_concurrent_save_states = num_cpus, + }; + const int tseg_size = smm_region_size() - CONFIG_SMM_RESERVED_SIZE; + + printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", + relo_attrs.smbase); + + if (smm_load_module((void *)relo_attrs.smbase, tseg_size, &smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; +} + +static int smm_load_handlers(void) +{ + /* All range registers are aligned to 4KiB */ + const uint32_t rmask = ~((1 << 12) - 1); + const struct pattrs *pattrs = pattrs_get(); + + /* Initialize global tracking state. */ + relo_attrs.smbase = (uint32_t)smm_region_start(); + relo_attrs.smrr_base = relo_attrs.smbase | MTRR_TYPE_WRBACK; + relo_attrs.smrr_mask = ~(smm_region_size() - 1) & rmask; + relo_attrs.smrr_mask |= MTRRphysMaskValid; + + /* Install handlers. */ + if (install_relocation_handler(pattrs->num_cpus) < 0) { + printk(BIOS_ERR, "Unable to install SMM relocation handler.\n"); + return -1; + } + + if (install_permanent_handler(pattrs->num_cpus) < 0) { + printk(BIOS_ERR, "Unable to install SMM permanent handler.\n"); + return -1; + } + + /* Ensure the SMM handlers hit DRAM before performing first SMI. */ + wbinvd(); + + return 0; +} + +static void smm_relocate(void *unused) +{ + const struct pattrs *pattrs = pattrs_get(); + + /* Load relocation and permanent handler. */ + if (boot_cpu()) { + if (smm_load_handlers() < 0) { + printk(BIOS_ERR, "Error loading SMM handlers.\n"); + return; + } + southcluster_smm_clear_state(); + } + + /* Relocate SMM space. */ + smm_initiate_relocation(); + + /* Load microcode after SMM relocation. */ + intel_microcode_load_unlocked(pattrs->microcode_patch); +} + +static void enable_smis(void *unused) +{ + southcluster_smm_enable_smi(); +} diff --git a/src/soc/intel/baytrail/dptf.c b/src/soc/intel/baytrail/dptf.c new file mode 100644 index 0000000000..a7274e0933 --- /dev/null +++ b/src/soc/intel/baytrail/dptf.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +static const struct reg_script dptf_init_settings[] = { + /* SocThermInit */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTMC, 0x00030708), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GFXT, 0x0000C000), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_VEDT, 0x00000004), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_ISPT, 0x00000004), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PTPS, 0x00000000), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TE_AUX3, 0x00061029), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRIccMax, 0x00061029), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_VRHot, 0x00061029), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_XXPROCHOT, 0x00061029), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM0, 0x00001029), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_TTE_SLM1, 0x00001029), + /* ratio 11 = 1466mhz for mid and entry celeron */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_POWER_BUDGET, 0x00000B00), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_SOC_ENERGY_CREDIT, 0x00000002), + REG_SCRIPT_END, +}; + +static void dptf_init(void *unused) +{ + printk(BIOS_DEBUG, "Applying SOC Thermal settings for DPTF.\n"); + reg_script_run(dptf_init_settings); +} + +BOOT_STATE_INIT_ENTRIES(dptf_init_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, dptf_init, NULL), +}; diff --git a/src/soc/intel/baytrail/ehci.c b/src/soc/intel/baytrail/ehci.c new file mode 100644 index 0000000000..0c7082c51b --- /dev/null +++ b/src/soc/intel/baytrail/ehci.c @@ -0,0 +1,181 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static const struct reg_script ehci_init_script[] = { + /* Enable S0 PLL shutdown + * D29:F0:7A[12,10,7,6,4,3,2,1]=11111111b */ + REG_PCI_OR16(0x7a, 0x14de), + /* Enable SB local clock gating + * D29:F0:7C[14,3,2]=111b (14 set in clock gating step) */ + REG_PCI_OR32(0x7c, 0x0000000c), + REG_PCI_OR32(0x8c, 0x00000001), + /* Enable dynamic clock gating 0x4001=0xCE */ + REG_IOSF_RMW(IOSF_PORT_USBPHY, 0x4001, 0xFFFFFF00, 0xCE), + /* Magic RCBA register set sequence */ + /* RCBA + 0x200=0x1 */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x200, 0x00000001), + /* RCBA + 0x204=0x2 */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x204, 0x00000002), + /* RCBA + 0x208=0x0 */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x208, 0x00000000), + /* RCBA + 0x240[4,3,2,1,0]=00000b */ + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x240, ~0x0000001f, 0), + /* RCBA + 0x318[9,8,6,5,4,3,2,1,0]=000000111b */ + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x318, ~0x00000378, 0x00000007), + /* RCBA + 0x31c[3,2,1,0]=0011b */ + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x31c, ~0x0000000c, 0x00000003), + REG_SCRIPT_END +}; + +static const struct reg_script ehci_clock_gating_script[] = { + /* Enable SB local clock gating */ + REG_PCI_OR32(0x7c, 0x00004000), + /* RCBA + 0x284=0xbe (step B0+) */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x284, 0x000000be), + REG_SCRIPT_END +}; + +static const struct reg_script ehci_disable_script[] = { + /* Clear Run/Stop Bit */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD, ~USB2CMD_RS, 0), + /* Wait for HC Halted */ + REG_RES_POLL32(PCI_BASE_ADDRESS_0, USB2STS, + USB2STS_HCHALT, USB2STS_HCHALT, 10000), + /* Disable Interrupts */ + REG_PCI_OR32(EHCI_CMD_STS, INTRDIS), + /* Disable Asynchronous and Periodic Scheduler */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, USB2CMD, + ~(USB2CMD_ASE | USB2CMD_PSE), 0), + /* Disable port wake */ + REG_PCI_RMW32(EHCI_SBRN_FLA_PWC, ~(PORTWKIMP | PORTWKCAPMASK), 0), + /* Set Function Disable bit in RCBA */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + RCBA_FUNC_DIS, RCBA_EHCI_DIS), + REG_SCRIPT_END +}; + +static const struct reg_script ehci_hc_reset[] = { + REG_RES_OR16(PCI_BASE_ADDRESS_0, USB2CMD, USB2CMD_HCRESET), + REG_SCRIPT_END +}; + +static void usb2_phy_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + u32 usb2_comp_bg = (config->usb2_comp_bg == 0 ? + 0x4700 : config->usb2_comp_bg); + struct reg_script usb2_phy_script[] = { + /* USB3PHYInit() */ + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_COMPBG, + usb2_comp_bg), + /* Per port phy settings, set in devicetree.cb */ + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE0, + config->usb2_per_port_lane0), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, + USBPHY_PER_PORT_RCOMP_HS_PULLUP0, + config->usb2_per_port_rcomp_hs_pullup0), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE1, + config->usb2_per_port_lane1), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, + USBPHY_PER_PORT_RCOMP_HS_PULLUP1, + config->usb2_per_port_rcomp_hs_pullup1), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE2, + config->usb2_per_port_lane2), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, + USBPHY_PER_PORT_RCOMP_HS_PULLUP2, + config->usb2_per_port_rcomp_hs_pullup2), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, USBPHY_PER_PORT_LANE3, + config->usb2_per_port_lane3), + REG_IOSF_WRITE(IOSF_PORT_USBPHY, + USBPHY_PER_PORT_RCOMP_HS_PULLUP3, + config->usb2_per_port_rcomp_hs_pullup3), + REG_SCRIPT_END + }; + reg_script_run(usb2_phy_script); +} + +static void ehci_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + struct reg_script ehci_hc_init[] = { + /* Controller init */ + REG_SCRIPT_NEXT(ehci_init_script), + /* Enable clock gating */ + REG_SCRIPT_NEXT(ehci_clock_gating_script), + /* + * Disable ports if requested + */ + /* Open per-port disable control override */ + REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN), + REG_PCI_WRITE8(EHCI_USB2PDO, config->usb2_port_disable_mask), + /* Close per-port disable control override */ + REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0), + REG_SCRIPT_END + }; + + /* Don't reset controller in S3 resume path */ + if (acpi_slp_type != 3) + reg_script_run_on_dev(dev, ehci_hc_reset); + + /* Disable controller if ports are routed to XHCI */ + if (config->usb_route_to_xhci) { + /* Disable controller */ + reg_script_run_on_dev(dev, ehci_disable_script); + + /* Hide device with southcluster function */ + dev->enabled = 0; + southcluster_enable_dev(dev); + } else { + /* Initialize EHCI controller */ + reg_script_run_on_dev(dev, ehci_hc_init); + } + + /* Setup USB2 PHY based on board config */ + usb2_phy_init(dev); +} + +static struct device_operations ehci_device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = ehci_init, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver baytrail_ehci __pci_driver = { + .ops = &ehci_device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = EHCI_DEVID +}; diff --git a/src/soc/intel/baytrail/elog.c b/src/soc/intel/baytrail/elog.c new file mode 100644 index 0000000000..d352390e45 --- /dev/null +++ b/src/soc/intel/baytrail/elog.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void log_power_and_resets(const struct chipset_power_state *ps) +{ + if (ps->gen_pmcon1 & PWR_FLR) { + elog_add_event(ELOG_TYPE_POWER_FAIL); + elog_add_event(ELOG_TYPE_PWROK_FAIL); + } + + if (ps->gen_pmcon1 & SUS_PWR_FLR) { + elog_add_event(ELOG_TYPE_SUS_POWER_FAIL); + } + + if (ps->gen_pmcon1 & RPS) { + elog_add_event(ELOG_TYPE_RTC_RESET); + } + + if (ps->tco_sts & SECOND_TO_STS) { + elog_add_event(ELOG_TYPE_TCO_RESET); + } + + if (ps->pm1_sts & PRBTNOR_STS) { + elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE); + } + + if (ps->gen_pmcon1 & SRS) { + elog_add_event(ELOG_TYPE_RESET_BUTTON); + } + + if (ps->gen_pmcon1 & GEN_RST_STS) { + elog_add_event(ELOG_TYPE_SYSTEM_RESET); + } +} + +static void log_wake_events(const struct chipset_power_state *ps) +{ + const uint32_t pcie_wake_mask = PCI_EXP_STS | PCIE_WAKE3_STS | + PCIE_WAKE2_STS | PCIE_WAKE1_STS | + PCIE_WAKE0_STS; + uint32_t gpe0_sts; + uint32_t gpio_mask; + int i; + + /* Mask off disabled events. */ + gpe0_sts = ps->gpe0_sts & ps->gpe0_en; + + if (ps->pm1_sts & WAK_STS) { + elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, + acpi_slp_type == 3 ? 3 : 5); + } + + if (ps->pm1_sts & PWRBTN_STS) { + elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0); + } + + if (ps->pm1_sts & RTC_STS) { + elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0); + } + + if (gpe0_sts & PME_B0_EN) { + elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); + } + + if (gpe0_sts & pcie_wake_mask) { + elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0); + } + + gpio_mask = SUS_GPIO_STS0; + i = 0; + while (gpio_mask) { + if (gpio_mask & gpe0_sts) { + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i); + } + gpio_mask <<= 1; + i++; + } +} + +void southcluster_log_state(void) +{ + struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE); + + if (ps == NULL) { + printk(BIOS_DEBUG, "Not logging power state information. " + "Power state not found in cbmem.\n"); + return; + } + + log_power_and_resets(ps); + log_wake_events(ps); +} diff --git a/src/soc/intel/baytrail/emmc.c b/src/soc/intel/baytrail/emmc.c new file mode 100644 index 0000000000..1708428506 --- /dev/null +++ b/src/soc/intel/baytrail/emmc.c @@ -0,0 +1,77 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "chip.h" + +static const struct reg_script emmc_ops[] = { + /* Enable 2ms card stable feature. */ + REG_PCI_OR32(0xa8, (1 << 24)), + /* Enable HS200 */ + REG_PCI_WRITE32(0xa0, 0x446cc801), + REG_PCI_WRITE32(0xa4, 0x80000807), + /* cfio_regs_score_special_bits.sdio1_dummy_loopback_en=1 */ + REG_IOSF_OR(IOSF_PORT_SCORE, 0x49c0, (1 << 3)), + /* CLKGATE_EN_1 . cr_scc_mipihsi_clkgate_en = 1 */ + REG_IOSF_RMW(IOSF_PORT_CCU, 0x1c, ~(3 << 26), (1 << 26)), + /* Set slew for HS200 */ + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x3c), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x3c), + /* Max timeout */ + REG_RES_WRITE8(PCI_BASE_ADDRESS_0, 0x002e, 0x0e), + REG_SCRIPT_END, +}; + +static void emmc_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + + printk(BIOS_DEBUG, "eMMC init\n"); + reg_script_run_on_dev(dev, emmc_ops); + + if (config->scc_acpi_mode) + scc_enable_acpi_mode(dev, SCC_MMC_CTL, SCC_NVS_MMC); +} + +static struct device_operations device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = emmc_init, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = MMC_DEVID, +}; diff --git a/src/soc/intel/baytrail/gfx.c b/src/soc/intel/baytrail/gfx.c new file mode 100644 index 0000000000..a97dd61c0d --- /dev/null +++ b/src/soc/intel/baytrail/gfx.c @@ -0,0 +1,414 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "chip.h" + +#define GFX_TIMEOUT 100000 /* 100ms */ + +/* + * Lock Power Context Base Register to point to a 24KB block + * of memory in GSM. Power context save data is stored here. + */ +static void gfx_lock_pcbase(device_t dev) +{ + struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0); + const u16 gms_size_map[17] = { 0,32,64,96,128,160,192,224,256, + 288,320,352,384,416,448,480,512 }; + u32 pcsize = 24 << 10; /* 24KB */ + u32 wopcmsz = 0x100000; /* PAVP offset */ + u32 gms, gmsize, pcbase; + + gms = pci_read_config32(dev, GGC) & GGC_GSM_SIZE_MASK; + gms >>= 3; + if (gms > sizeof(gms_size_map)) + return; + gmsize = gms_size_map[gms]; + + /* PcBase = BDSM + GMS Size - WOPCMSZ - PowerContextSize */ + pcbase = pci_read_config32(dev, GSM_BASE) & 0xfff00000; + pcbase += (gmsize-1) * wopcmsz - pcsize; + pcbase |= 1; /* Lock */ + + write32(res->base + 0x182120, pcbase); +} + +static const struct reg_script gfx_init_script[] = { + /* Allow-Wake render/media wells */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x130090, ~1, 1), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130094, 1, 1, GFX_TIMEOUT), + /* Render Force-Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80008000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0x8000, + GFX_TIMEOUT), + /* Media Force-Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80008000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0x8000, + GFX_TIMEOUT), + /* Workaround - X0:261954/A0:261955 */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x182060, ~0xf, 1), + + /* + * PowerMeter Weights + */ + + /* SET1 */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA800, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA804, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA808, 0x0000ff0A), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA80C, 0x1D000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA810, 0xAC004900), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA814, 0x000F0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA818, 0x5A000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA81C, 0x2600001F), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA820, 0x00090000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA824, 0x2000ff00), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA828, 0xff090016), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA82C, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA830, 0x00000100), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA834, 0x00A00F51), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA838, 0x000B0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA83C, 0xcb7D3307), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA840, 0x003C0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA844, 0xFFFF0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA848, 0x00220000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA84c, 0x43000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA850, 0x00000800), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA854, 0x00000F00), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA858, 0x00000021), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA85c, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA860, 0x00190000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA80, 0x00FF00FF), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xAA84, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x1300A4, 0x00000000), + /* SET2 */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA900, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA904, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA908, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa90c, 0x1D000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa910, 0xAC005000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa914, 0x000F0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa918, 0x5A000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa91c, 0x2600001F), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa920, 0x00090000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa924, 0x2000ff00), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa928, 0xff090016), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa92c, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa930, 0x00000100), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa934, 0x00A00F51), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa938, 0x000B0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA93C, 0xcb7D3307), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA940, 0x003C0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA944, 0xFFFF0000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA948, 0x00220000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA94C, 0x43000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA950, 0x00000800), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA954, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA960, 0x00000000), + /* SET3 */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa3c, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa54, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xaa60, 0x00000000), + /* Enable PowerMeter Counters */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA248, 0x00000058), + + /* Program PUNIT_GPU_EC_VIRUS based on DPTF SDP */ + /* SDP Profile 4 == 0x11940, others 0xcf08 */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_GPU_EC_VIRUS, 0xcf08), + + /* GfxPause */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa000, 0x00071388), + + /* Dynamic EU Control Settings */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa080, 0x00000004), + + /* Lock ECO Bit Settings */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x80000000), + + /* DOP Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x00000001), + + /* MBCunit will send the VCR (Fuse) writes as NP-W */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x907c, 0xfffeffff, 0x00010000), + + /* + * RC6 Settings + */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA090, 0x00000000), + /* RC1e - RC6/6p - RC6pp Wake Rate Limits */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA09C, 0x00280000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0A8, 0x0001E848), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0AC, 0x00000019), + /* RC Sleep / RCx Thresholds */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B0, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA0B8, 0x00000557), + + /* + * Turbo Settings + */ + + /* Render/Video/Blitter Idle Max Count */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x2054, 0x0000000A), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000A), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000A), + /* RP Down Timeout */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA010, 0x000F4240), + + /* + * Turbo Control Settings + */ + + /* RP Up/Down Threshold */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA02C, 0x0000E8E8), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA030, 0x0003BD08), + /* RP Up/Down EI */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA068, 0x000101D0), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xA06C, 0x00055730), + + /* RP Idle Hysteresis */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa070, 0x0000000a), + + /* HW RC6 Control Settings */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x11000000), + + /* RP Control */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000592), + + /* Enable PM Interrupts */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x44024, 0x03000000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa168, 0x0000007e), + + /* Aggressive Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0), + + /* Enable Gfx Turbo. */ + REG_IOSF_RMW(IOSF_PORT_PMC, SB_BIOS_CONFIG, + ~SB_BIOS_CONFIG_GFX_TURBO_DIS, 0), + REG_SCRIPT_END +}; + +static const struct reg_script gpu_pre_vbios_script[] = { + /* Make sure GFX is bus master with MMIO access */ + REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY), + /* Display */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xc0, 0xc0, + GFX_TIMEOUT), + /* Tx/Rx Lanes */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfff0c0), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfff0c0, 0xfff0c0, + GFX_TIMEOUT), + /* Common Lane */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xfffcc0), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xfffcc0, + GFX_TIMEOUT), + /* Ungating Tx only */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00cc0), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffcc0, 0xf00cc0, + GFX_TIMEOUT), + /* Ungating Common Lane only */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf000c0), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xffffc0, 0xf000c0, + GFX_TIMEOUT), + /* Ungating Display */ + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xf00000), + REG_IOSF_POLL(IOSF_PORT_PMC, PUNIT_PWRGT_STATUS, 0xfffff0, 0xf00000, + GFX_TIMEOUT), + REG_SCRIPT_END +}; + +static const struct reg_script gfx_post_vbios_script[] = { + /* Deassert Render Force-Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b0, 0x80000000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300b4, 0x8000, 0, GFX_TIMEOUT), + /* Deassert Media Force-Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1300b8, 0x80000000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x1300bc, 0x8000, 0, GFX_TIMEOUT), + /* Set Lock bits */ + REG_PCI_RMW32(GGC, 0xffffffff, 1), + REG_PCI_RMW32(GSM_BASE, 0xffffffff, 1), + REG_PCI_RMW32(GTT_BASE, 0xffffffff, 1), + REG_SCRIPT_END +}; + +static inline void gfx_run_script(device_t dev, const struct reg_script *ops) +{ + reg_script_run_on_dev(dev, ops); +} + +static void gfx_pre_vbios_init(device_t dev) +{ + printk(BIOS_INFO, "GFX: Pre VBIOS Init\n"); + gfx_run_script(dev, gpu_pre_vbios_script); +} + +static void gfx_pm_init(device_t dev) +{ + printk(BIOS_INFO, "GFX: Power Management Init\n"); + gfx_run_script(dev, gfx_init_script); + + /* Lock power context base */ + gfx_lock_pcbase(dev); +} + +static void gfx_post_vbios_init(device_t dev) +{ + printk(BIOS_INFO, "GFX: Post VBIOS Init\n"); + gfx_run_script(dev, gfx_post_vbios_script); +} + +static void set_backlight_pwm(device_t dev, uint32_t bklt_reg, int req_hz) +{ + int divider; + struct resource *res; + + res = find_resource(dev, PCI_BASE_ADDRESS_0); + + if (res == NULL) + return; + + /* Default to 200 Hz if nothing is set. */ + if (req_hz == 0) + req_hz = 200; + + /* Base clock is 25MHz */ + divider = 25 * 1000 * 1000 / (16 * req_hz); + + /* Do not set duty cycle (lower 16 bits). Just set the divider. */ + write32(res->base + bklt_reg, divider << 16); +} + +static void gfx_panel_setup(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + struct reg_script gfx_pipea_init[] = { + /* CONTROL */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_CONTROL), + PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD), + /* POWER ON */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_ON_DELAYS), + (config->gpu_pipea_port_select << 30 | + config->gpu_pipea_power_on_delay << 16 | + config->gpu_pipea_light_on_delay)), + /* POWER OFF */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_OFF_DELAYS), + (config->gpu_pipea_power_off_delay << 16 | + config->gpu_pipea_light_off_delay)), + /* DIVISOR */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEA_REG(PP_DIVISOR), + ~0x1f, config->gpu_pipea_power_cycle_delay), + REG_SCRIPT_END + }; + struct reg_script gfx_pipeb_init[] = { + /* CONTROL */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_CONTROL), + PP_CONTROL_UNLOCK | PP_CONTROL_EDP_FORCE_VDD), + /* POWER ON */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_ON_DELAYS), + (config->gpu_pipeb_port_select << 30 | + config->gpu_pipeb_power_on_delay << 16 | + config->gpu_pipeb_light_on_delay)), + /* POWER OFF */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_OFF_DELAYS), + (config->gpu_pipeb_power_off_delay << 16 | + config->gpu_pipeb_light_off_delay)), + /* DIVISOR */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, PIPEB_REG(PP_DIVISOR), + ~0x1f, config->gpu_pipeb_power_cycle_delay), + REG_SCRIPT_END + }; + + if (config->gpu_pipea_port_select) { + printk(BIOS_INFO, "GFX: Initialize PIPEA\n"); + reg_script_run_on_dev(dev, gfx_pipea_init); + set_backlight_pwm(dev, PIPEA_REG(BACKLIGHT_CTL), + config->gpu_pipea_pwm_freq_hz); + } + + if (config->gpu_pipeb_port_select) { + printk(BIOS_INFO, "GFX: Initialize PIPEB\n"); + reg_script_run_on_dev(dev, gfx_pipeb_init); + set_backlight_pwm(dev, PIPEB_REG(BACKLIGHT_CTL), + config->gpu_pipeb_pwm_freq_hz); + } +} + +static void gfx_init(device_t dev) +{ + /* Pre VBIOS Init */ + gfx_pre_vbios_init(dev); + + /* Power Management Init */ + gfx_pm_init(dev); + + gfx_panel_setup(dev); + + /* Run VBIOS */ + pci_dev_init(dev); + + /* Post VBIOS Init */ + gfx_post_vbios_init(dev); +} + +static void gfx_read_resources(device_t dev) +{ + pci_dev_read_resources(dev); + +#if CONFIG_MARK_GRAPHICS_MEM_WRCOMB + struct resource *res; + + /* Set the graphics memory to write combining. */ + res = find_resource(dev, PCI_BASE_ADDRESS_2); + if (res == NULL) { + printk(BIOS_DEBUG, "GFX: memory resource not found.\n"); + return; + } + res->flags |= IORESOURCE_WRCOMB; +#endif +} + +static struct device_operations gfx_device_ops = { + .read_resources = gfx_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = gfx_init, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver gfx_driver __pci_driver = { + .ops = &gfx_device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = GFX_DEVID, +}; diff --git a/src/soc/intel/baytrail/gpio.c b/src/soc/intel/baytrail/gpio.c new file mode 100644 index 0000000000..6e737d1704 --- /dev/null +++ b/src/soc/intel/baytrail/gpio.c @@ -0,0 +1,245 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +/* GPIO-to-Pad LUTs */ +static const u8 gpncore_gpio_to_pad[GPNCORE_COUNT] = + { 19, 18, 17, 20, 21, 22, 24, 25, /* [ 0: 7] */ + 23, 16, 14, 15, 12, 26, 27, 1, /* [ 8:15] */ + 4, 8, 11, 0, 3, 6, 10, 13, /* [16:23] */ + 2, 5, 9 }; /* [24:26] */ + +static const u8 gpscore_gpio_to_pad[GPSCORE_COUNT] = + { 85, 89, 93, 96, 99, 102, 98, 101, /* [ 0: 7] */ + 34, 37, 36, 38, 39, 35, 40, 84, /* [ 8: 15] */ + 62, 61, 64, 59, 54, 56, 60, 55, /* [16: 23] */ + 63, 57, 51, 50, 53, 47, 52, 49, /* [24: 31] */ + 48, 43, 46, 41, 45, 42, 58, 44, /* [32: 39] */ + 95, 105, 70, 68, 67, 66, 69, 71, /* [40: 47] */ + 65, 72, 86, 90, 88, 92, 103, 77, /* [48: 55] */ + 79, 83, 78, 81, 80, 82, 13, 12, /* [56: 63] */ + 15, 14, 17, 18, 19, 16, 2, 1, /* [64: 71] */ + 0, 4, 6, 7, 9, 8, 33, 32, /* [72: 79] */ + 31, 30, 29, 27, 25, 28, 26, 23, /* [80: 87] */ + 21, 20, 24, 22, 5, 3, 10, 11, /* [88: 95] */ + 106, 87, 91, 104, 97, 100 }; /* [96:101] */ + +static const u8 gpssus_gpio_to_pad[GPSSUS_COUNT] = + { 29, 33, 30, 31, 32, 34, 36, 35, /* [ 0: 7] */ + 38, 37, 18, 7, 11, 20, 17, 1, /* [ 8:15] */ + 8, 10, 19, 12, 0, 2, 23, 39, /* [16:23] */ + 28, 27, 22, 21, 24, 25, 26, 51, /* [24:31] */ + 56, 54, 49, 55, 48, 57, 50, 58, /* [32:39] */ + 52, 53, 59, 40 }; /* [40:43] */ + +/* GPIO bank descriptions */ +static const struct gpio_bank gpncore_bank = { + .gpio_count = GPNCORE_COUNT, + .gpio_to_pad = gpncore_gpio_to_pad, + .legacy_base = GP_LEGACY_BASE_NONE, + .pad_base = GPNCORE_PAD_BASE, + .has_wake_en = 0, + .gpio_f1_range_start = GPNCORE_GPIO_F1_RANGE_START, + .gpio_f1_range_end = GPNCORE_GPIO_F1_RANGE_END, +}; + +static const struct gpio_bank gpscore_bank = { + .gpio_count = GPSCORE_COUNT, + .gpio_to_pad = gpscore_gpio_to_pad, + .legacy_base = GPSCORE_LEGACY_BASE, + .pad_base = GPSCORE_PAD_BASE, + .has_wake_en = 0, + .gpio_f1_range_start = GPSCORE_GPIO_F1_RANGE_START, + .gpio_f1_range_end = GPSCORE_GPIO_F1_RANGE_END, +}; + +static const struct gpio_bank gpssus_bank = { + .gpio_count = GPSSUS_COUNT, + .gpio_to_pad = gpssus_gpio_to_pad, + .legacy_base = GPSSUS_LEGACY_BASE, + .pad_base = GPSSUS_PAD_BASE, + .has_wake_en = 1, + .gpio_f1_range_start = GPSSUS_GPIO_F1_RANGE_START, + .gpio_f1_range_end = GPSSUS_GPIO_F1_RANGE_END, +}; + +static void setup_gpios(const struct soc_gpio_map *gpios, + const struct gpio_bank *bank) +{ + const struct soc_gpio_map *config; + int gpio = 0; + u32 reg, pad_conf0; + u8 set, bit; + + u32 use_sel[4] = {0}; + u32 io_sel[4] = {0}; + u32 gp_lvl[4] = {0}; + u32 tpe[4] = {0}; + u32 tne[4] = {0}; + u32 wake_en[4] = {0}; + + if (!gpios) + return; + + for (config = gpios; config->pad_conf0 != GPIO_LIST_END; + config++, gpio++) { + if (gpio > bank->gpio_count) + break; + + set = gpio >> 5; + bit = gpio % 32; + + if (bank->legacy_base != GP_LEGACY_BASE_NONE) { + /* Legacy IO configuration */ + use_sel[set] |= config->use_sel << bit; + io_sel[set] |= config->io_sel << bit; + gp_lvl[set] |= config->gp_lvl << bit; + tpe[set] |= config->tpe << bit; + tne[set] |= config->tne << bit; + + /* Some banks do not have wake_en ability */ + if (bank->has_wake_en) + wake_en[set] |= config->wake_en << bit; + } + + /* Pad configuration registers */ + reg = bank->pad_base + 16 * bank->gpio_to_pad[gpio]; + + /* Add correct func to GPIO pad config */ + pad_conf0 = config->pad_conf0; + if (config->is_gpio) + { + if (gpio >= bank->gpio_f1_range_start && + gpio <= bank->gpio_f1_range_end) + pad_conf0 |= PAD_FUNC1; + else + pad_conf0 |= PAD_FUNC0; + } + +#ifdef GPIO_DEBUG + printk(BIOS_DEBUG, "Write Pad: Base(%x) - %x %x %x\n", + reg, pad_conf0, config->pad_conf1, config->pad_val); +#endif + + write32(reg + PAD_CONF0_REG, pad_conf0); + write32(reg + PAD_CONF1_REG, config->pad_conf1); + write32(reg + PAD_VAL_REG, config->pad_val); + } + + if (bank->legacy_base != GP_LEGACY_BASE_NONE) + for (set = 0; set <= (bank->gpio_count - 1) / 32; ++set) { + reg = bank->legacy_base + 0x20 * set; + +#ifdef GPIO_DEBUG + printk(BIOS_DEBUG, + "Write GPIO: Reg(%x) - %x %x %x %x %x\n", + reg, use_sel[set], io_sel[set], gp_lvl[set], + tpe[set], tne[set]); +#endif + + outl(use_sel[set], reg + LEGACY_USE_SEL_REG); + outl(io_sel[set], reg + LEGACY_IO_SEL_REG); + outl(gp_lvl[set], reg + LEGACY_GP_LVL_REG); + outl(tpe[set], reg + LEGACY_TPE_REG); + outl(tne[set], reg + LEGACY_TNE_REG); + + /* TS registers are WOC */ + outl(0, reg + LEGACY_TS_REG); + + if (bank->has_wake_en) + outl(wake_en[set], reg + LEGACY_WAKE_EN_REG); + } +} + +static void setup_gpio_route(const struct soc_gpio_map *sus, + const struct soc_gpio_map *core) +{ + uint32_t route_reg = 0; + int i; + + for (i = 0; i < 8; i++) { + /* SMI takes precedence and wake_en implies SCI. */ + if (sus[i].smi) { + route_reg |= ROUTE_SMI << (2 * i); + } else if (sus[i].sci) { + route_reg |= ROUTE_SCI << (2 * i); + } + + if (core[i].smi) { + route_reg |= ROUTE_SMI << (2 * (i + 8)); + } else if (core[i].sci) { + route_reg |= ROUTE_SCI << (2 * (i + 8)); + } + } + southcluster_smm_save_param(SMM_SAVE_PARAM_GPIO_ROUTE, route_reg); +} + +static void setup_dirqs(const u8 dirq[GPIO_MAX_DIRQS], + const struct gpio_bank *bank) +{ + u32 reg = bank->pad_base + PAD_BASE_DIRQ_OFFSET; + u32 val; + int i; + + /* Write all four DIRQ registers */ + for (i=0; i<4; ++i) { + val = dirq[i * 4 + 3] << 24 | dirq[i * 4 + 2] << 16 | + dirq[i * 4 + 1] << 8 | dirq[i * 4]; + write32(reg + i * 4, val); +#ifdef GPIO_DEBUG + printk(BIOS_DEBUG, "Write DIRQ reg(%x) - %x\n", + reg + i * 4, val); +#endif + } +} + +void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap) +{ + if (config) { + setup_gpios(config->ncore, &gpncore_bank); + setup_gpios(config->score, &gpscore_bank); + setup_gpios(config->ssus, &gpssus_bank); + setup_gpio_route(config->ssus, config->score); + + if (config->core_dirq) + setup_dirqs(*config->core_dirq, &gpscore_bank); + if (config->sus_dirq) + setup_dirqs(*config->sus_dirq, &gpssus_bank); + } + + /* Set on die termination feature with pull up value and + * drive the pad high for TAP_TDO and TAP_TMS + */ + if (!enable_xdp_tap) { + printk(BIOS_DEBUG, "Tri-state TDO and TMS\n"); + write32(GPSSUS_PAD_BASE + 0x2fc, 0xc); + write32(GPSSUS_PAD_BASE + 0x2cc, 0xc); + } +} + +struct soc_gpio_config* __attribute__((weak)) mainboard_get_gpios(void) +{ + printk(BIOS_DEBUG, "Default/empty GPIO config\n"); + return NULL; +} diff --git a/src/soc/intel/baytrail/hda.c b/src/soc/intel/baytrail/hda.c new file mode 100644 index 0000000000..2e70e39f30 --- /dev/null +++ b/src/soc/intel/baytrail/hda.c @@ -0,0 +1,116 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static const struct reg_script init_ops[] = { + /* Enable no snoop traffic. */ + REG_PCI_OR16(0x78, 1 << 11), + /* Configure HDMI codec connection. */ + REG_PCI_OR32(0xc4, 1 << 1), + REG_PCI_OR8(0x43, (1 << 3) | (1 << 6)), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0xc0), + REG_IOSF_WRITE(IOSF_PORT_PMC, PUNIT_PWRGT_CONTROL, 0x00), + /* Configure internal settings. */ + REG_PCI_OR32(0xc0, 0x7 << 21), + REG_PCI_OR32(0xc4, (0x3 << 26) | (1 << 13) | (1 << 10)), + REG_PCI_WRITE32(0xc8, 0x82a30000), + REG_PCI_RMW32(0xd0, ~(1 << 31), 0x0), + /* Disable docking. */ + REG_PCI_RMW8(0x4d, ~(1 << 7), 0), + REG_SCRIPT_END, +}; + +static const uint32_t hdmi_codec_verb_table[] = { + /* coreboot specific header */ + 0x80862882, /* vid did for hdmi codec */ + 0x00000000, /* subsystem id */ + 0x00000003, /* number of jacks */ + + /* pin widget 5 - port B */ + 0x20471c10, + 0x20471d00, + 0x20471e56, + 0x20471f18, + + /* pin widget 6 - port C */ + 0x20571c20, + 0x20571d00, + 0x20571e56, + 0x20571f18, + + /* pin widget 7 - port D */ + 0x20671c30, + 0x20671d00, + 0x20671e56, + 0x20671f58, +}; + +static void hda_init(device_t dev) +{ + struct resource *res; + int codec_mask; + int i; + + reg_script_run_on_dev(dev, init_ops); + + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res == NULL) + return; + + codec_mask = hda_codec_detect(res->base); + + printk(BIOS_DEBUG, "codec mask = %x\n", codec_mask); + if (!codec_mask) + return; + + for (i = 3; i >= 0; i--) { + if (!((1 << i) & codec_mask)) + continue; + hda_codec_init(res->base, i, sizeof(hdmi_codec_verb_table), + hdmi_codec_verb_table); + } +} + +static const struct device_operations device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = hda_init, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = HDA_DEVID, +}; diff --git a/src/soc/intel/baytrail/include/soc/acpi.h b/src/soc/intel/baytrail/include/soc/acpi.h new file mode 100644 index 0000000000..f1b571ae2f --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/acpi.h @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_ACPI_H_ +#define _BAYTRAIL_ACPI_H_ + +#include +#include + +void acpi_create_intel_hpet(acpi_hpet_t * hpet); +void acpi_fill_in_fadt(acpi_fadt_t *fadt); +unsigned long acpi_madt_irq_overrides(unsigned long current); +void acpi_init_gnvs(global_nvs_t *gnvs); + +#endif /* _BAYTRAIL_ACPI_H_ */ + diff --git a/src/soc/intel/baytrail/include/soc/device_nvs.h b/src/soc/intel/baytrail/include/soc/device_nvs.h new file mode 100644 index 0000000000..f8f831b735 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/device_nvs.h @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_DEVICE_NVS_H_ +#define _BAYTRAIL_DEVICE_NVS_H_ + +#include + +/* Offset in Global NVS where this structure lives */ +#define DEVICE_NVS_OFFSET 0x1000 + +#define LPSS_NVS_SIO_DMA1 0 +#define LPSS_NVS_I2C1 1 +#define LPSS_NVS_I2C2 2 +#define LPSS_NVS_I2C3 3 +#define LPSS_NVS_I2C4 4 +#define LPSS_NVS_I2C5 5 +#define LPSS_NVS_I2C6 6 +#define LPSS_NVS_I2C7 7 +#define LPSS_NVS_SIO_DMA2 8 +#define LPSS_NVS_SPI 9 +#define LPSS_NVS_PWM1 10 +#define LPSS_NVS_PWM2 11 +#define LPSS_NVS_HSUART1 12 +#define LPSS_NVS_HSUART2 13 + +#define SCC_NVS_MMC 0 +#define SCC_NVS_SDIO 1 +#define SCC_NVS_SD 2 + +typedef struct { + /* Device Enabled in ACPI Mode */ + u8 lpss_en[14]; + u8 scc_en[3]; + u8 lpe_en; + + /* BAR 0 */ + u32 lpss_bar0[14]; + u32 scc_bar0[3]; + u32 lpe_bar0; + + /* BAR 0 */ + u32 lpss_bar1[14]; + u32 scc_bar1[3]; + u32 lpe_bar1; + + /* Extra */ + u32 lpe_fw; /* LPE Firmware */ +} __attribute__((packed)) device_nvs_t; + +#endif diff --git a/src/soc/intel/baytrail/include/soc/efi_wrapper.h b/src/soc/intel/baytrail/include/soc/efi_wrapper.h new file mode 100644 index 0000000000..3304d03451 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/efi_wrapper.h @@ -0,0 +1,52 @@ +/* + * PEI EFI entry point + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __EFI_WRAPPER_H__ +#define __EFI_WRAPPER_H__ + +#define EFI_WRAPPER_VER 2 + +/* Provide generic x86 calling conventions. */ +#define ABI_X86 __attribute((regparm(0))) + +/* Errors returned by the EFI wrapper. */ +enum efi_wrapper_error { + INVALID_VER = -1, +}; + +struct efi_wrapper_params { + /* Mainboard Inputs */ + int version; + + void ABI_X86 (*console_out)(unsigned char byte); + + unsigned int tsc_ticks_per_microsecond; +} __attribute__((packed)); + +typedef int ABI_X86 (*efi_wrapper_entry_t)(struct efi_wrapper_params *); +#endif diff --git a/src/soc/intel/baytrail/include/soc/ehci.h b/src/soc/intel/baytrail/include/soc/ehci.h new file mode 100644 index 0000000000..a1edd6dffe --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/ehci.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BAYTRAIL_EHCI_H +#define BAYTRAIL_EHCI_H + +/* EHCI PCI Registers */ +#define EHCI_CMD_STS 0x04 +# define INTRDIS (1 << 10) +#define EHCI_SBRN_FLA_PWC 0x60 +# define PORTWKIMP (1 << 16) +# define PORTWKCAPMASK (0x3ff << 17) +#define EHCI_USB2PDO 0x64 + +/* EHCI Memory Registers */ +#define USB2CMD 0x20 +# define USB2CMD_ASE (1 << 5) +# define USB2CMD_PSE (1 << 4) +# define USB2CMD_HCRESET (1 << 1) +# define USB2CMD_RS (1 << 0) +#define USB2STS 0x24 +# define USB2STS_HCHALT (1 << 12) + +/* RCBA EHCI Registers */ +#define RCBA_FUNC_DIS 0x220 +# define RCBA_EHCI_DIS (1 << 0) + +#endif /* BAYTRAIL_EHCI_H */ diff --git a/src/soc/intel/baytrail/include/soc/gfx.h b/src/soc/intel/baytrail/include/soc/gfx.h new file mode 100644 index 0000000000..7047dd5a6a --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/gfx.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_GFX_H_ +#define _BAYTRAIL_GFX_H_ + +/* + * PCI config registers. + */ + +#define GGC 0x50 +# define GGC_VGA_DISABLE (1 << 1) +# define GGC_GTT_SIZE_MASK (3 << 8) +# define GGC_GTT_SIZE_0MB (0 << 8) +# define GGC_GTT_SIZE_1MB (1 << 8) +# define GGC_GTT_SIZE_2MB (2 << 8) +# define GGC_GSM_SIZE_MASK (0x1f << 3) +# define GGC_GSM_SIZE_0MB (0 << 3) +# define GGC_GSM_SIZE_32MB (1 << 3) +# define GGC_GSM_SIZE_64MB (2 << 3) +# define GGC_GSM_SIZE_128MB (4 << 3) + +#define GSM_BASE 0x5c +#define GTT_BASE 0x70 + +#define MSAC 0x62 +#define APERTURE_SIZE_MASK (3 << 1) +#define APERTURE_SIZE_128MB (0 << 1) +#define APERTURE_SIZE_256MB (1 << 1) +#define APERTURE_SIZE_512MB (3 << 1) + +#define VLV_DISPLAY_BASE 0x180000 +#define PIPEA_REG(reg) (VLV_DISPLAY_BASE + (reg)) +#define PIPEB_REG(reg) (VLV_DISPLAY_BASE + 0x100 + (reg)) + +/* Panel control registers */ +#define HOTPLUG_CTRL 0x61110 +#define PP_CONTROL 0x61204 +#define PP_CONTROL_UNLOCK 0xabcd0000 +#define PP_CONTROL_EDP_FORCE_VDD (1 << 3) +#define PP_ON_DELAYS 0x61208 +#define PP_OFF_DELAYS 0x6120c +#define PP_DIVISOR 0x61210 +#define BACKLIGHT_CTL2 0x61250 +#define BACKLIGHT_ENABLE (1 << 31) +#define BACKLIGHT_CTL 0x61254 + +#endif /* _BAYTRAIL_GFX_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/gpio.h b/src/soc/intel/baytrail/include/soc/gpio.h new file mode 100644 index 0000000000..70bf1f9239 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/gpio.h @@ -0,0 +1,459 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_GPIO_H_ +#define _BAYTRAIL_GPIO_H_ + +#include +#include +#include + +/* #define GPIO_DEBUG */ + +/* Pad base, ex. PAD_CONF0[n]= PAD_BASE+16*n */ +#define GPSCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSCORE) +#define GPNCORE_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPNCORE) +#define GPSSUS_PAD_BASE (IO_BASE_ADDRESS + IO_BASE_OFFSET_GPSSUS) + +/* DIRQ registers start at pad base + 0x980 */ +#define PAD_BASE_DIRQ_OFFSET 0x980 + +/* Pad register offset */ +#define PAD_CONF0_REG 0x0 +#define PAD_CONF1_REG 0x4 +#define PAD_VAL_REG 0x8 + +/* Legacy IO register base */ +#define GPSCORE_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x00) +#define GPSSUS_LEGACY_BASE (GPIO_BASE_ADDRESS + 0x80) +/* Some banks have no legacy GPIO interface */ +#define GP_LEGACY_BASE_NONE 0xFFFF + +#define LEGACY_USE_SEL_REG 0x00 +#define LEGACY_IO_SEL_REG 0x04 +#define LEGACY_GP_LVL_REG 0x08 +#define LEGACY_TPE_REG 0x0C +#define LEGACY_TNE_REG 0x10 +#define LEGACY_TS_REG 0x14 +#define LEGACY_WAKE_EN_REG 0x18 + +/* Number of GPIOs in each bank */ +#define GPNCORE_COUNT 27 +#define GPSCORE_COUNT 102 +#define GPSSUS_COUNT 44 + +/* GPIO legacy IO register settings */ +#define GPIO_USE_MMIO 0 +#define GPIO_USE_LEGACY 1 + +#define GPIO_DIR_OUTPUT 0 +#define GPIO_DIR_INPUT 1 + +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 + +#define GPIO_PEDGE_DISABLE 0 +#define GPIO_PEDGE_ENABLE 1 + +#define GPIO_NEDGE_DISABLE 0 +#define GPIO_NEDGE_ENABLE 1 + +/* config0[29] - Disable second mask */ +#define PAD_MASK2_DISABLE (1 << 29) + +/* config0[27] - Direct Irq En */ +#define PAD_IRQ_EN (1 << 27) + +/* config0[26] - gd_tne */ +#define PAD_TNE_IRQ (1 << 26) + +/* config0[25] - gd_tpe */ +#define PAD_TPE_IRQ (1 << 25) + +/* config0[24] - Gd Level */ +#define PAD_LEVEL_IRQ (1 << 24) +#define PAD_EDGE_IRQ (0 << 24) + +/* config0[17] - Slow clkgate / glitch filter */ +#define PAD_SLOWGF_ENABLE (1 << 17) + +/* config0[16] - Fast clkgate / glitch filter */ +#define PAD_FASTGF_ENABLE (1 << 16) + +/* config0[15] - Hysteresis enable (inverted) */ +#define PAD_HYST_DISABLE (1 << 15) +#define PAD_HYST_ENABLE (0 << 15) + +/* config0[14:13] - Hysteresis control */ +#define PAD_HYST_CTRL_DEFAULT (2 << 13) + +/* config0[11] - Bypass Flop */ +#define PAD_FLOP_BYPASS (1 << 11) +#define PAD_FLOP_ENABLE (0 << 11) + +/* config0[10:9] - Pull str */ +#define PAD_PU_2K (0 << 9) +#define PAD_PU_10K (1 << 9) +#define PAD_PU_20K (2 << 9) +#define PAD_PU_40K (3 << 9) + +/* config0[8:7] - Pull assign */ +#define PAD_PULL_DISABLE (0 << 7) +#define PAD_PULL_UP (1 << 7) +#define PAD_PULL_DOWN (2 << 7) + +/* config0[2:0] - Func. pin mux */ +#define PAD_FUNC0 0x0 +#define PAD_FUNC1 0x1 +#define PAD_FUNC2 0x2 +#define PAD_FUNC3 0x3 +#define PAD_FUNC4 0x4 +#define PAD_FUNC5 0x5 +#define PAD_FUNC6 0x6 + +/* pad config0 power-on values - We will not often want to change these */ +#define PAD_CONFIG0_DEFAULT (PAD_MASK2_DISABLE | PAD_SLOWGF_ENABLE | \ + PAD_FASTGF_ENABLE | PAD_HYST_DISABLE | \ + PAD_HYST_CTRL_DEFAULT | PAD_FLOP_BYPASS) + +/* pad config1 reg power-on values - Shouldn't need to change this */ +#define PAD_CONFIG1_DEFAULT 0x8000 + +/* pad_val[2] - Iinenb - active low */ +#define PAD_VAL_INPUT_DISABLE (1 << 2) +#define PAD_VAL_INPUT_ENABLE (0 << 2) + +/* pad_val[1] - Ioutenb - active low */ +#define PAD_VAL_OUTPUT_DISABLE (1 << 1) +#define PAD_VAL_OUTPUT_ENABLE (0 << 1) + +/* Input / Output state should usually be mutually exclusive */ +#define PAD_VAL_INPUT (PAD_VAL_INPUT_ENABLE | PAD_VAL_OUTPUT_DISABLE) +#define PAD_VAL_OUTPUT (PAD_VAL_OUTPUT_ENABLE | PAD_VAL_INPUT_DISABLE) + +/* pad_val[0] - Value */ +#define PAD_VAL_HIGH (1 << 0) +#define PAD_VAL_LOW (0 << 0) + +/* pad_val reg power-on default varies by pad, and apparently can cause issues + * if not set correctly, even if the pin isn't configured as GPIO. */ +#define PAD_VAL_DEFAULT PAD_VAL_INPUT + +/* Configure GPIOs as MMIO by default */ +#define GPIO_INPUT_PU_10K \ + { .pad_conf0 = PAD_PU_10K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_MMIO, \ + .is_gpio = 1 } + +#define GPIO_INPUT_PU_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_MMIO, \ + .is_gpio = 1 } + +#define GPIO_INPUT_PD_10K \ + { .pad_conf0 = PAD_PU_10K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_MMIO, \ + .is_gpio = 1 } + +#define GPIO_INPUT_PD_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_MMIO, \ + .is_gpio = 1 } + +#define GPIO_INPUT_NOPU \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_MMIO, \ + .is_gpio = 1 } + +#define GPIO_INPUT_LEGACY_NOPU \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .is_gpio = 1 } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_LEVELHIGH_NO_PULL \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_LEVEL_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_LEVELLOW_PU_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_LEVEL_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_EDGELOW_PU_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_EDGEHIGH_PD_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ | PAD_EDGE_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_EDGELOW_PD_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_DOWN | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TNE_IRQ | PAD_EDGE_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +/* Direct / dedicated IRQ input - pass signal directly to apic */ +#define GPIO_DIRQ_EDGEBOTH_PU_20K \ + { .pad_conf0 = PAD_PU_20K | PAD_PULL_UP | PAD_CONFIG0_DEFAULT \ + | PAD_FUNC0 | PAD_IRQ_EN | PAD_TPE_IRQ| PAD_TNE_IRQ | PAD_EDGE_IRQ, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, } + +#define GPIO_OUT_LOW \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_OUTPUT | PAD_VAL_LOW, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_OUTPUT, \ + .gp_lvl = GPIO_LEVEL_LOW, \ + .is_gpio = 1 } + +#define GPIO_OUT_HIGH \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_OUTPUT | PAD_VAL_HIGH, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_OUTPUT, \ + .gp_lvl = GPIO_LEVEL_HIGH, \ + .is_gpio = 1 } + +/* Define no-pull / PU / PD configs for each functional config option */ +#define GPIO_FUNC(_func, _pudir, _str) \ + { .use_sel = GPIO_USE_MMIO, \ + .pad_conf0 = PAD_FUNC##_func | PAD_##_pudir | PAD_PU_##_str | \ + PAD_CONFIG0_DEFAULT, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_DEFAULT } + +/* Default functional configs -- no PU */ +#define GPIO_FUNC0 GPIO_FUNC(0, PULL_DISABLE, 20K) +#define GPIO_FUNC1 GPIO_FUNC(1, PULL_DISABLE, 20K) +#define GPIO_FUNC2 GPIO_FUNC(2, PULL_DISABLE, 20K) +#define GPIO_FUNC3 GPIO_FUNC(3, PULL_DISABLE, 20K) +#define GPIO_FUNC4 GPIO_FUNC(4, PULL_DISABLE, 20K) +#define GPIO_FUNC5 GPIO_FUNC(5, PULL_DISABLE, 20K) +#define GPIO_FUNC6 GPIO_FUNC(6, PULL_DISABLE, 20K) + +/* ACPI GPIO routing. Assume everything is externally pulled and negative edge + * triggered. SCI implies WAKE, but WAKE doesn't imply SCI. */ +#define GPIO_ACPI_SCI \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .tne = 1, \ + .sci = 1, \ + .wake_en = 1, } +#define GPIO_ACPI_WAKE \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .tne = 1, \ + .wake_en = 1, } +#define GPIO_ACPI_SMI \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .tne = 1, \ + .smi = 1} + +/* End marker */ +#define GPIO_LIST_END 0xffffffff + +#define GPIO_END \ + { .pad_conf0 = GPIO_LIST_END } + +/* Common default GPIO settings */ +#define GPIO_INPUT GPIO_INPUT_NOPU +#define GPIO_INPUT_LEGACY GPIO_INPUT_LEGACY_NOPU +#define GPIO_INPUT_PU GPIO_INPUT_PU_20K +#define GPIO_INPUT_PD GPIO_INPUT_PD_20K +#define GPIO_NC GPIO_INPUT_PU_20K +#define GPIO_DEFAULT GPIO_FUNC0 + +/* 16 DirectIRQs per supported bank */ +#define GPIO_MAX_DIRQS 16 + +/* Most pins are GPIO function 0. Some banks have a range of pins with GPIO + * function 1. Indicate first / last GPIOs with function 1. */ +#define GPIO_NONE 255 +/* All NCORE GPIOs are function 0 */ +#define GPNCORE_GPIO_F1_RANGE_START GPIO_NONE +#define GPNCORE_GPIO_F1_RANGE_END GPIO_NONE +/* SCORE GPIO [92:93] are function 1 */ +#define GPSCORE_GPIO_F1_RANGE_START 92 +#define GPSCORE_GPIO_F1_RANGE_END 93 +/* SSUS GPIO [11:21] are function 1 */ +#define GPSSUS_GPIO_F1_RANGE_START 11 +#define GPSSUS_GPIO_F1_RANGE_END 21 + +struct soc_gpio_map { + u32 pad_conf0; + u32 pad_conf1; + u32 pad_val; + u32 use_sel : 1; + u32 io_sel : 1; + u32 gp_lvl : 1; + u32 tpe : 1; + u32 tne : 1; + u32 wake_en : 1; + u32 smi : 1; + u32 is_gpio : 1; + u32 sci : 1; +} __attribute__ ((packed)); + +struct soc_gpio_config { + const struct soc_gpio_map *ncore; + const struct soc_gpio_map *score; + const struct soc_gpio_map *ssus; + const u8 (*core_dirq)[GPIO_MAX_DIRQS]; + const u8 (*sus_dirq)[GPIO_MAX_DIRQS]; +}; + +/* Description of GPIO 'bank' ex. {ncore, score. ssus} */ +struct gpio_bank { + const int gpio_count; + const u8* gpio_to_pad; + const int legacy_base; + const unsigned long pad_base; + const u8 has_wake_en :1; + const u8 gpio_f1_range_start; + const u8 gpio_f1_range_end; +}; + +void setup_soc_gpios(struct soc_gpio_config *config, u8 enable_xdp_tap); +/* This function is weak and can be overridden by a mainboard function. */ +struct soc_gpio_config* mainboard_get_gpios(void); + +/* Functions / defines for changing GPIOs in romstage */ +/* SCORE Pad definitions. */ +#define UART_RXD_PAD 82 +#define UART_TXD_PAD 83 +#define PCU_SMB_CLK_PAD 88 +#define PCU_SMB_DATA_PAD 90 +#define SOC_DDI1_VDDEN_PAD 16 + +static inline unsigned int ncore_pconf0(int pad_num) +{ + return GPNCORE_PAD_BASE + pad_num * 16; +} + +static inline void ncore_select_func(int pad, int func) +{ + uint32_t reg; + uint32_t pconf0_addr = ncore_pconf0(pad); + + reg = read32(pconf0_addr); + reg &= ~0x7; + reg |= func & 0x7; + write32(pconf0_addr, reg); +} + +static inline unsigned int score_pconf0(int pad_num) +{ + return GPSCORE_PAD_BASE + pad_num * 16; +} + +static inline unsigned int ssus_pconf0(int pad_num) +{ + return GPSSUS_PAD_BASE + pad_num * 16; +} + +static inline void score_select_func(int pad, int func) +{ + uint32_t reg; + uint32_t pconf0_addr = score_pconf0(pad); + + reg = read32(pconf0_addr); + reg &= ~0x7; + reg |= func & 0x7; + write32(pconf0_addr, reg); +} + +static inline void ssus_select_func(int pad, int func) +{ + uint32_t reg; + uint32_t pconf0_addr = ssus_pconf0(pad); + + reg = read32(pconf0_addr); + reg &= ~0x7; + reg |= func & 0x7; + write32(pconf0_addr, reg); +} + +/* These functions require that the input pad be configured as an input GPIO */ +static inline int score_get_gpio(int pad) +{ + uint32_t val_addr = score_pconf0(pad) + PAD_VAL_REG; + + return read32(val_addr) & PAD_VAL_HIGH; +} + +static inline int ssus_get_gpio(int pad) +{ + uint32_t val_addr = ssus_pconf0(pad) + PAD_VAL_REG; + + return read32(val_addr) & PAD_VAL_HIGH; +} + +static inline void ssus_disable_internal_pull(int pad) +{ + const uint32_t pull_mask = ~(0xf << 7); + write32(ssus_pconf0(pad), read32(ssus_pconf0(pad)) & pull_mask); +} + +#endif /* _BAYTRAIL_GPIO_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/iomap.h b/src/soc/intel/baytrail/include/soc/iomap.h new file mode 100644 index 0000000000..867484b178 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/iomap.h @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_IOMAP_H_ +#define _BAYTRAIL_IOMAP_H_ + + +/* + * Memory Mapped IO bases. + */ + +/* PCI Configuration Space */ +#define MCFG_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS +#define MCFG_BASE_SIZE 0x10000000 + +/* Transactions in this range will abort */ +#define ABORT_BASE_ADDRESS 0xfeb00000 +#define ABORT_BASE_SIZE 0x00100000 + +/* Power Management Controller */ +#define PMC_BASE_ADDRESS 0xfed03000 +#define PMC_BASE_SIZE 0x400 + +/* IO Memory */ +#define IO_BASE_ADDRESS 0xfed0c000 +#define IO_BASE_OFFSET_GPSCORE 0x0000 +#define IO_BASE_OFFSET_GPNCORE 0x1000 +#define IO_BASE_OFFSET_GPSSUS 0x2000 +#define IO_BASE_SIZE 0x4000 + +/* Intel Legacy Block */ +#define ILB_BASE_ADDRESS 0xfed08000 +#define ILB_BASE_SIZE 0x400 + +/* SPI Bus */ +#define SPI_BASE_ADDRESS 0xfed01000 +#define SPI_BASE_SIZE 0x400 + +/* MODPHY */ +#define MPHY_BASE_ADDRESS 0xfef00000 +#define MPHY_BASE_SIZE 0x100000 + +/* Power Management Unit */ +#define PUNIT_BASE_ADDRESS 0xfed05000 +#define PUNIT_BASE_SIZE 0x800 + +/* Root Complex Base Address */ +#define RCBA_BASE_ADDRESS 0xfed1c000 +#define RCBA_BASE_SIZE 0x400 + +/* High Performance Event Timer */ +#define HPET_BASE_ADDRESS 0xfed00000 +#define HPET_BASE_SIZE 0x400 + +/* Temporary Base Address */ +#define TEMP_BASE_ADDRESS 0xfd000000 + +/* + * IO Port bases. + */ +#define ACPI_BASE_ADDRESS 0x0400 +#define ACPI_BASE_SIZE 0x80 + +#define GPIO_BASE_ADDRESS 0x0500 +#define GPIO_BASE_SIZE 0x100 + +#define SMBUS_BASE_ADDRESS 0xefa0 + +#ifndef __ACPI__ +/* Read Top of Low Memory (BMBOUND) */ +uint32_t nc_read_top_of_low_memory(void); +#endif + +#endif /* _BAYTRAIL_IOMAP_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/iosf.h b/src/soc/intel/baytrail/include/soc/iosf.h new file mode 100644 index 0000000000..8bda618347 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/iosf.h @@ -0,0 +1,349 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_IOSF_H_ +#define _BAYTRAIL_IOSF_H_ + +#include +#include + +/* + * The Bay Trail SoC has a message network called IOSF Sideband. The access + * routines are through 3 registers in PCI config space of 00:00.0: + * MCR - control register + * MDR - data register + * MCRX - control register extension + * The extension regist is only used for addresses that don't fit into the + * 8 bit register address. + */ + +#ifndef PCI_DEV +#define PCI_DEV(SEGBUS, DEV, FN) ( \ + (((SEGBUS) & 0xFFF) << 20) | \ + (((DEV) & 0x1F) << 15) | \ + (((FN) & 0x07) << 12)) +#endif +#define IOSF_PCI_DEV PCI_DEV(0,SOC_DEV,SOC_FUNC) + +#define MCR_REG 0xd0 +#define IOSF_OPCODE(x) ((x) << 24) +#define IOSF_PORT(x) ((0xff & (x)) << 16) +#define IOSF_REG(x) ((0xff & (x)) << 8) +#define IOSF_REG_UPPER(x) (((~0xff) & (x))) +#define IOSF_BYTE_EN_0 0x10 +#define IOSF_BYTE_EN_1 0x20 +#define IOSF_BYTE_EN_2 0x40 +#define IOSF_BYTE_EN_3 0x80 +#define IOSF_BYTE_EN \ + (IOSF_BYTE_EN_0 | IOSF_BYTE_EN_1 | IOSF_BYTE_EN_2 | IOSF_BYTE_EN_3) +#define MDR_REG 0xd4 +#define MCRX_REG 0xd8 + +uint32_t iosf_aunit_read(int reg); +void iosf_aunit_write(int reg, uint32_t val); +uint32_t iosf_cpu_bus_read(int reg); +void iosf_cpu_bus_write(int reg, uint32_t val); +uint32_t iosf_bunit_read(int reg); +void iosf_bunit_write(int reg, uint32_t val); +uint32_t iosf_dunit_read(int reg); +void iosf_dunit_write(int reg, uint32_t val); +/* Some registers are per channel while the gloals live in dunit 0 */ +uint32_t iosf_dunit_ch0_read(int reg); +uint32_t iosf_dunit_ch1_read(int reg); +uint32_t iosf_punit_read(int reg); +void iosf_punit_write(int reg, uint32_t val); +uint32_t iosf_usbphy_read(int reg); +void iosf_usbphy_write(int reg, uint32_t val); +uint32_t iosf_ushphy_read(int reg); +void iosf_ushphy_write(int reg, uint32_t val); +uint32_t iosf_sec_read(int reg); +void iosf_sec_write(int reg, uint32_t val); +uint32_t iosf_port45_read(int reg); +void iosf_port45_write(int reg, uint32_t val); +uint32_t iosf_port46_read(int reg); +void iosf_port46_write(int reg, uint32_t val); +uint32_t iosf_port47_read(int reg); +void iosf_port47_write(int reg, uint32_t val); +uint32_t iosf_port55_read(int reg); +void iosf_port55_write(int reg, uint32_t val); +uint32_t iosf_port58_read(int reg); +void iosf_port58_write(int reg, uint32_t val); +uint32_t iosf_port59_read(int reg); +void iosf_port59_write(int reg, uint32_t val); +uint32_t iosf_port5a_read(int reg); +void iosf_port5a_write(int reg, uint32_t val); +uint32_t iosf_lpss_read(int reg); +void iosf_lpss_write(int reg, uint32_t val); +uint32_t iosf_ccu_read(int reg); +void iosf_ccu_write(int reg, uint32_t val); +uint32_t iosf_score_read(int reg); +void iosf_score_write(int reg, uint32_t val); +uint32_t iosf_scc_read(int reg); +void iosf_scc_write(int reg, uint32_t val); +uint32_t iosf_porta2_read(int reg); +void iosf_porta2_write(int reg, uint32_t val); +uint32_t iosf_ssus_read(int reg); +void iosf_ssus_write(int reg, uint32_t val); + +/* IOSF ports. */ +#define IOSF_PORT_AUNIT 0x00 /* IO Arbiter unit */ +#define IOSF_PORT_SYSMEMC 0x01 /* System Memory Controller */ +#define IOSF_PORT_DUNIT_CH0 0x07 /* DUNIT Channel 0 */ +#define IOSF_PORT_CPU_BUS 0x02 /* CPU Bus Interface Controller */ +#define IOSF_PORT_BUNIT 0x03 /* System Memroy Arbiter/Bunit */ +#define IOSF_PORT_PMC 0x04 /* Power Management Controller */ +#define IOSF_PORT_GFX 0x06 /* Graphics Adapter */ +#define IOSF_PORT_DUNIT_CH1 0x07 /* DUNIT Channel 1 */ +#define IOSF_PORT_SYSMEMIO 0x0c /* System Memory IO */ +#define IOSF_PORT_USBPHY 0x43 /* USB PHY */ +#define IOSF_PORT_SEC 0x44 /* SEC */ +#define IOSF_PORT_0x45 0x45 +#define IOSF_PORT_0x46 0x46 +#define IOSF_PORT_0x47 0x47 +#define IOSF_PORT_SCORE 0x48 /* SCORE */ +#define IOSF_PORT_0x55 0x55 +#define IOSF_PORT_0x58 0x58 +#define IOSF_PORT_0x59 0x59 +#define IOSF_PORT_0x5a 0x5a +#define IOSF_PORT_USHPHY 0x61 /* USB XHCI PHY */ +#define IOSF_PORT_SCC 0x63 /* Storage Control Cluster */ +#define IOSF_PORT_LPSS 0xa0 /* LPSS - Low Power Subsystem */ +#define IOSF_PORT_0xa2 0xa2 +#define IOSF_PORT_SATAPHY 0xa3 /* SATA PHY */ +#define IOSF_PORT_PCIEPHY 0xa3 /* PCIE PHY */ +#define IOSF_PORT_SSUS 0xa8 /* SUS */ +#define IOSF_PORT_CCU 0xa9 /* Clock control unit. */ + +/* Read and write opcodes differ per port. */ +#define IOSF_OP_READ_AUNIT 0x10 +#define IOSF_OP_WRITE_AUNIT (IOSF_OP_READ_AUNIT | 1) +#define IOSF_OP_READ_SYSMEMC 0x10 +#define IOSF_OP_WRITE_SYSMEMC (IOSF_OP_READ_SYSMEMC | 1) +#define IOSF_OP_READ_CPU_BUS 0x10 +#define IOSF_OP_WRITE_CPU_BUS (IOSF_OP_READ_CPU_BUS | 1) +#define IOSF_OP_READ_BUNIT 0x10 +#define IOSF_OP_WRITE_BUNIT (IOSF_OP_READ_BUNIT | 1) +#define IOSF_OP_READ_PMC 0x06 +#define IOSF_OP_WRITE_PMC (IOSF_OP_READ_PMC | 1) +#define IOSF_OP_READ_GFX 0x00 +#define IOSF_OP_WRITE_GFX (IOSF_OP_READ_GFX | 1) +#define IOSF_OP_READ_SYSMEMIO 0x06 +#define IOSF_OP_WRITE_SYSMEMIO (IOSF_OP_READ_SYSMEMIO | 1) +#define IOSF_OP_READ_USBPHY 0x06 +#define IOSF_OP_WRITE_USBPHY (IOSF_OP_READ_USBPHY | 1) +#define IOSF_OP_READ_SEC 0x04 +#define IOSF_OP_WRITE_SEC (IOSF_OP_READ_SEC | 1) +#define IOSF_OP_READ_0x45 0x06 +#define IOSF_OP_WRITE_0x45 (IOSF_OP_READ_0x45 | 1) +#define IOSF_OP_READ_0x46 0x06 +#define IOSF_OP_WRITE_0x46 (IOSF_OP_READ_0x46 | 1) +#define IOSF_OP_READ_0x47 0x06 +#define IOSF_OP_WRITE_0x47 (IOSF_OP_READ_0x47 | 1) +#define IOSF_OP_READ_SCORE 0x06 +#define IOSF_OP_WRITE_SCORE (IOSF_OP_READ_SCORE | 1) +#define IOSF_OP_READ_0x55 0x04 +#define IOSF_OP_WRITE_0x55 (IOSF_OP_READ_0x55 | 1) +#define IOSF_OP_READ_0x58 0x06 +#define IOSF_OP_WRITE_0x58 (IOSF_OP_READ_0x58 | 1) +#define IOSF_OP_READ_0x59 0x06 +#define IOSF_OP_WRITE_0x59 (IOSF_OP_READ_0x59 | 1) +#define IOSF_OP_READ_0x5a 0x04 +#define IOSF_OP_WRITE_0x5a (IOSF_OP_READ_0x5a | 1) +#define IOSF_OP_READ_USHPHY 0x06 +#define IOSF_OP_WRITE_USHPHY (IOSF_OP_READ_USHPHY | 1) +#define IOSF_OP_READ_SCC 0x06 +#define IOSF_OP_WRITE_SCC (IOSF_OP_READ_SCC | 1) +#define IOSF_OP_READ_LPSS 0x06 +#define IOSF_OP_WRITE_LPSS (IOSF_OP_READ_LPSS | 1) +#define IOSF_OP_READ_0xa2 0x06 +#define IOSF_OP_WRITE_0xa2 (IOSF_OP_READ_0xa2 | 1) +#define IOSF_OP_READ_SATAPHY 0x00 +#define IOSF_OP_WRITE_SATAPHY (IOSF_OP_READ_SATAPHY | 1) +#define IOSF_OP_READ_PCIEPHY 0x00 +#define IOSF_OP_WRITE_PCIEPHY (IOSF_OP_READ_PCIEPHY | 1) +#define IOSF_OP_READ_SSUS 0x10 +#define IOSF_OP_WRITE_SSUS (IOSF_OP_READ_SSUS | 1) +#define IOSF_OP_READ_CCU 0x06 +#define IOSF_OP_WRITE_CCU (IOSF_OP_READ_CCU | 1) + +/* + * BUNIT Registers. + */ + +#define BNOCACHE 0x23 +/* BMBOUND has a 128MiB granularity. Highest address is 0xf8000000. */ +#define BUNIT_BMBOUND 0x25 +/* BMBOUND_HI describes the available ram above 4GiB. It has a + * 256MiB granularity. Physical address bits 35:28 are compared with 31:24 + * bits in the BMBOUND_HI register. Also note that since BMBOUND has 128MiB + * granularity care needs to be taken with the e820 map to account for a hole + * in the ram. */ +#define BUNIT_BMBOUND_HI 0x26 +#define BUNIT_MMCONF_REG 0x27 +/* The SMMRR registers define the SMM region in MiB granularity. */ +#define BUNIT_SMRCP 0x2b +#define BUNIT_SMRRAC 0x2c +#define BUNIT_SMRWAC 0x2d +#define BUNIT_SMRRL 0x2e +#define BUNIT_SMRRH 0x2f +# define BUNIT_SMRR_ENABLE (1 << 31) + +/* SA ID bits. */ +#define SAI_IA_UNTRUSTED (1 << 0) +#define SAI_IA_SMM (1 << 2) +#define SAI_IA_BOOT (1 << 4) + +/* + * DUNIT Registers. + */ + +#define DRP 0x00 +# define DRP_DIMM0_RANK0_EN (0x01 << 0) +# define DRP_DIMM0_RANK1_EN (0x01 << 1) +# define DRP_DIMM1_RANK0_EN (0x01 << 2) +# define DRP_DIMM1_RANK1_EN (0x01 << 3) +# define DRP_RANK_MASK (DRP_DIMM0_RANK0_EN | DRP_DIMM0_RANK1_EN | \ + DRP_DIMM1_RANK0_EN | DRP_DIMM1_RANK1_EN) +#define DTR0 0x01 +# define DTR0_SPEED_MASK 0x03 +# define DTR0_SPEED_800 0x00 +# define DTR0_SPEED_1066 0x01 +# define DTR0_SPEED_1333 0x02 +# define DTR0_SPEED_1600 0x03 + +/* + * PUNIT Registers + */ +#define SB_BIOS_CONFIG 0x06 +# define SB_BIOS_CONFIG_ECC_EN (1 << 31) +# define SB_BIOS_CONFIG_DUAL_CH_DIS (1 << 30) +# define SB_BIOS_CONFIG_EFF_ECC (1 << 29) +# define SB_BIOS_CONFIG_EFF_DUAL_CH_DIS (1 << 28) +# define SB_BIOS_CONFIG_PERF_MODE (1 << 17) +# define SB_BIOS_CONFIG_PDM_MODE (1 << 16) +# define SB_BIOS_CONFIG_DDRIO_PWRGATE (1 << 8) +# define SB_BIOS_CONFIG_GFX_TURBO_DIS (1 << 7) +# define SB_BIOS_CONFIG_PS2_EN_VNN (1 << 3) +# define SB_BIOS_CONFIG_PS2_EN_VCC (1 << 2) +# define SB_BIOS_CONFIG_PCIE_PLLOFFOK (1 << 1) +# define SB_BIOS_CONFIG_USB_CACHING_EN (1 << 0) +#define BIOS_RESET_CPL 0x05 +# define BIOS_RESET_CPL_ALL_DONE (1 << 1) +# define BIOS_RESET_CPL_RESET_DONE (1 << 0) +#define PUNIT_PWRGT_CONTROL 0x60 +#define PUNIT_PWRGT_STATUS 0x61 +#define PUNIT_GPU_EC_VIRUS 0xd2 + +#define PUNIT_SOC_POWER_BUDGET 0x02 +#define PUNIT_SOC_ENERGY_CREDIT 0x03 +#define PUNIT_PTMC 0x80 +#define PUNIT_GFXT 0x88 +#define PUNIT_VEDT 0x89 +#define PUNIT_ISPT 0x8c +#define PUNIT_PTPS 0xb2 +#define PUNIT_TE_AUX0 0xb5 +#define PUNIT_TE_AUX1 0xb6 +#define PUNIT_TE_AUX2 0xb7 +#define PUNIT_TE_AUX3 0xb8 +#define PUNIT_TTE_VRIccMax 0xb9 +#define PUNIT_TTE_VRHot 0xba +#define PUNIT_TTE_XXPROCHOT 0xbb +#define PUNIT_TTE_SLM0 0xbc +#define PUNIT_TTE_SLM1 0xbd +#define PUNIT_TTE_SWT 0xbf + +/* + * LPSS Registers + */ +#define LPSS_SIO_DMA1_CTL 0x280 +#define LPSS_I2C1_CTL 0x288 +#define LPSS_I2C2_CTL 0x290 +#define LPSS_I2C3_CTL 0x298 +#define LPSS_I2C4_CTL 0x2a0 +#define LPSS_I2C5_CTL 0x2a8 +#define LPSS_I2C6_CTL 0x2b0 +#define LPSS_I2C7_CTL 0x2b8 +#define LPSS_SIO_DMA2_CTL 0x240 +#define LPSS_PWM1_CTL 0x248 +#define LPSS_PWM2_CTL 0x250 +#define LPSS_HSUART1_CTL 0x258 +#define LPSS_HSUART2_CTL 0x260 +#define LPSS_SPI_CTL 0x268 +# define LPSS_CTL_ACPI_INT_EN (1 << 21) +# define LPSS_CTL_PCI_CFG_DIS (1 << 20) +# define LPSS_CTL_SNOOP (1 << 18) +# define LPSS_CTL_NOSNOOP (1 << 19) +# define LPSS_CTL_PM_CAP_PRSNT (1 << 1) + +/* + * SCC Registers + */ +#define SCC_SD_CTL 0x504 +#define SCC_SDIO_CTL 0x508 +#define SCC_MMC_CTL 0x50c +# define SCC_CTL_PCI_CFG_DIS (1 << 0) +# define SCC_CTL_ACPI_INT_EN (1 << 1) + +/* + * CCU Registers + */ + +#define PLT_CLK_CTRL_0 0x3c +#define PLT_CLK_CTRL_1 0x40 +#define PLT_CLK_CTRL_2 0x44 +#define PLT_CLK_CTRL_3 0x48 +#define PLT_CLK_CTRL_4 0x4c +#define PLT_CLK_CTRL_5 0x50 +# define PLT_CLK_CTRL_19P2MHZ_FREQ (0 << 1) +# define PLT_CLK_CTRL_25MHZ_FREQ (1 << 1) +# define PLT_CLK_CTRL_SELECT_FREQ (1 << 0) + +/* + * USBPHY Registers + */ +#define USBPHY_COMPBG 0x7f04 +#define USBPHY_PER_PORT_LANE0 0x4100 +#define USBPHY_PER_PORT_RCOMP_HS_PULLUP0 0x4122 +#define USBPHY_PER_PORT_LANE1 0x4200 +#define USBPHY_PER_PORT_RCOMP_HS_PULLUP1 0x4222 +#define USBPHY_PER_PORT_LANE2 0x4300 +#define USBPHY_PER_PORT_RCOMP_HS_PULLUP2 0x4322 +#define USBPHY_PER_PORT_LANE3 0x4400 +#define USBPHY_PER_PORT_RCOMP_HS_PULLUP3 0x4422 + +/* + * USHPHY Registers + */ +#define USHPHY_CDN_PLL_CONTROL 0x03c0 +#define USHPHY_CDN_VCO_START_CAL_POINT 0x0054 +#define USHPHY_CCDRLF 0x8040 +#define USHPHY_PEAKING_AMP_CONFIG_DIAG 0x80a8 +#define USHPHY_OFFSET_COR_CONFIG_DIAG 0x80b0 +#define USHPHY_VGA_GAIN_CONFIG_DIAG 0x8080 +#define USHPHY_REE_DAC_CONTROL 0x80b8 +#define USHPHY_CDN_U1_POWER_STATE_DEF 0x0000 + +/* + * LPE Registers + */ +#define LPE_PCICFGCTR1 0x0500 +# define LPE_PCICFGCTR1_PCI_CFG_DIS (1 << 0) +# define LPE_PCICFGCTR1_ACPI_INT_EN (1 << 1) + +#endif /* _BAYTRAIL_IOSF_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/irq.h b/src/soc/intel/baytrail/include/soc/irq.h new file mode 100644 index 0000000000..e66fab5d0a --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/irq.h @@ -0,0 +1,164 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_IRQ_H_ +#define _BAYTRAIL_IRQ_H_ + +#define PIRQA_APIC_IRQ 16 +#define PIRQB_APIC_IRQ 17 +#define PIRQC_APIC_IRQ 18 +#define PIRQD_APIC_IRQ 19 +#define PIRQE_APIC_IRQ 20 +#define PIRQF_APIC_IRQ 21 +#define PIRQG_APIC_IRQ 22 +#define PIRQH_APIC_IRQ 23 +/* The below IRQs are for when devices are in ACPI mode. Active low. */ +#define LPE_DMA0_IRQ 24 +#define LPE_DMA1_IRQ 25 +#define LPE_SSP0_IRQ 26 +#define LPE_SSP1_IRQ 27 +#define LPE_SSP2_IRQ 28 +#define LPE_IPC2HOST_IRQ 29 +#define LPSS_I2C1_IRQ 32 +#define LPSS_I2C2_IRQ 33 +#define LPSS_I2C3_IRQ 34 +#define LPSS_I2C4_IRQ 35 +#define LPSS_I2C5_IRQ 36 +#define LPSS_I2C6_IRQ 37 +#define LPSS_I2C7_IRQ 38 +#define LPSS_HSUART1_IRQ 39 +#define LPSS_HSUART2_IRQ 40 +#define LPSS_SPI_IRQ 41 +#define LPSS_DMA1_IRQ 42 +#define LPSS_DMA2_IRQ 43 +#define SCC_EMMC_IRQ 44 +#define SCC_SDIO_IRQ 46 +#define SCC_SD_IRQ 47 +#define GPIO_NC_IRQ 48 +#define GPIO_SC_IRQ 49 +#define GPIO_SUS_IRQ 50 +/* GPIO direct / dedicated IRQs. */ +#define GPIO_S0_DED_IRQ_0 51 +#define GPIO_S0_DED_IRQ_1 52 +#define GPIO_S0_DED_IRQ_2 53 +#define GPIO_S0_DED_IRQ_3 54 +#define GPIO_S0_DED_IRQ_4 55 +#define GPIO_S0_DED_IRQ_5 56 +#define GPIO_S0_DED_IRQ_6 57 +#define GPIO_S0_DED_IRQ_7 58 +#define GPIO_S0_DED_IRQ_8 59 +#define GPIO_S0_DED_IRQ_9 60 +#define GPIO_S0_DED_IRQ_10 61 +#define GPIO_S0_DED_IRQ_11 62 +#define GPIO_S0_DED_IRQ_12 63 +#define GPIO_S0_DED_IRQ_13 64 +#define GPIO_S0_DED_IRQ_14 65 +#define GPIO_S0_DED_IRQ_15 66 +#define GPIO_S5_DED_IRQ_0 67 +#define GPIO_S5_DED_IRQ_1 68 +#define GPIO_S5_DED_IRQ_2 69 +#define GPIO_S5_DED_IRQ_3 70 +#define GPIO_S5_DED_IRQ_4 71 +#define GPIO_S5_DED_IRQ_5 72 +#define GPIO_S5_DED_IRQ_6 73 +#define GPIO_S5_DED_IRQ_7 74 +#define GPIO_S5_DED_IRQ_8 75 +#define GPIO_S5_DED_IRQ_9 76 +#define GPIO_S5_DED_IRQ_10 77 +#define GPIO_S5_DED_IRQ_11 78 +#define GPIO_S5_DED_IRQ_12 79 +#define GPIO_S5_DED_IRQ_13 80 +#define GPIO_S5_DED_IRQ_14 81 +#define GPIO_S5_DED_IRQ_15 82 +/* DIRQs - Two levels of expansion to evaluate to numeric constants for ASL. */ +#define _GPIO_S0_DED_IRQ(slot) GPIO_S0_DED_IRQ_##slot +#define _GPIO_S5_DED_IRQ(slot) GPIO_S5_DED_IRQ_##slot +#define GPIO_S0_DED_IRQ(slot) _GPIO_S0_DED_IRQ(slot) +#define GPIO_S5_DED_IRQ(slot) _GPIO_S5_DED_IRQ(slot) + +/* PIC IRQ settings. */ +#define PIRQ_PIC_IRQDISABLE 0x0 +#define PIRQ_PIC_IRQ3 0x3 +#define PIRQ_PIC_IRQ4 0x4 +#define PIRQ_PIC_IRQ5 0x5 +#define PIRQ_PIC_IRQ6 0x6 +#define PIRQ_PIC_IRQ7 0x7 +#define PIRQ_PIC_IRQ9 0x9 +#define PIRQ_PIC_IRQ10 0xa +#define PIRQ_PIC_IRQ11 0xb +#define PIRQ_PIC_IRQ12 0xc +#define PIRQ_PIC_IRQ14 0xe +#define PIRQ_PIC_IRQ15 0xf + +/* Overloaded term, but these values determine the per device route. */ +#define PIRQA 0 +#define PIRQB 1 +#define PIRQC 2 +#define PIRQD 3 +#define PIRQE 4 +#define PIRQF 5 +#define PIRQG 6 +#define PIRQH 7 + +/* These registers live behind the ILB_BASE_ADDRESS */ +#define ACTL 0x00 +# define SCIS_MASK 0x07 +# define SCIS_IRQ9 0x00 +# define SCIS_IRQ10 0x01 +# define SCIS_IRQ11 0x02 +# define SCIS_IRQ20 0x04 +# define SCIS_IRQ21 0x05 +# define SCIS_IRQ22 0x06 +# define SCIS_IRQ23 0x07 + +/* In each mainbaord directory there should exist a header file irqroute.h that + * defines the PCI_DEV_PIRQ_ROUTES and PIRQ_PIC_ROUTES macros which + * consist of PCI_DEV_PIRQ_ROUTE and PIRQ_PIC entries. */ + +#if !defined(__ASSEMBLER__) && !defined(__ACPI__) +#include + +#define NUM_IR_DEVS 32 +#define NUM_PIRQS 8 + +struct baytrail_irq_route { + /* Per device configuration. */ + uint16_t pcidev[NUM_IR_DEVS]; + /* Route path for each internal PIRQx in PIC mode. */ + uint8_t pic[NUM_PIRQS]; +}; + +extern const struct baytrail_irq_route global_baytrail_irq_route; + +#define DEFINE_IRQ_ROUTES \ + const struct baytrail_irq_route global_baytrail_irq_route = { \ + .pcidev = { PCI_DEV_PIRQ_ROUTES, }, \ + .pic = { PIRQ_PIC_ROUTES, }, \ + } + +#define PCI_DEV_PIRQ_ROUTE(dev_, a_, b_, c_, d_) \ + [dev_] = ((PIRQ ## d_) << 12) | ((PIRQ ## c_) << 8) | \ + ((PIRQ ## b_) << 4) | ((PIRQ ## a_) << 0) + +#define PIRQ_PIC(pirq_, pic_irq_) \ + [PIRQ ## pirq_] = PIRQ_PIC_IRQ ## pic_irq_ + +#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */ + +#endif /* _BAYTRAIL_IRQ_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/lpc.h b/src/soc/intel/baytrail/include/soc/lpc.h new file mode 100644 index 0000000000..2f6256cc41 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/lpc.h @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_LPC_H_ +#define _BAYTRAIL_LPC_H_ + +/* PCI config registers in LPC bridge. */ +#define REVID 0x08 +#define ABASE 0x40 +#define PBASE 0x44 +#define GBASE 0x48 +#define IOBASE 0x4c +#define IBASE 0x50 +#define SBASE 0x54 +#define MPBASE 0x58 +#define PUBASE 0x5c +#define UART_CONT 0x80 +#define RCBA 0xf0 + + +#define RID_A_STEPPING_START 1 +#define RID_B_STEPPING_START 5 +#define RID_C_STEPPING_START 0xe +enum baytrail_stepping { + STEP_A0, + STEP_A1, + STEP_B0, + STEP_B1, + STEP_B2, + STEP_B3, + STEP_C0, +}; + +/* Registers behind the RCBA_BASE_ADDRESS bar. */ +#define GCS 0x00 +# define BILD (1 << 0) + +#endif /* _BAYTRAIL_LPC_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/mrc_wrapper.h b/src/soc/intel/baytrail/include/soc/mrc_wrapper.h new file mode 100644 index 0000000000..b5009e4b2d --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/mrc_wrapper.h @@ -0,0 +1,107 @@ +/* + * MRC wrapper definitions + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _MRC_WRAPPER_H_ +#define _MRC_WRAPPER_H_ + +#define MRC_PARAMS_VER 5 + +#define NUM_CHANNELS 2 + +/* Provide generic x86 calling conventions. */ +#define ABI_X86 __attribute((regparm(0))) + +enum { + DRAM_INFO_SPD_SMBUS, /* Use the typical SPD smbus access. */ + DRAM_INFO_SPD_MEM, /* SPD info in memory. */ + DRAM_INFO_DETAILED, /* Timing info not in SPD format. */ +}; + +enum dram_type { + DRAM_DDR3, + DRAM_DDR3L, + DRAM_LPDDR3, +}; + +/* Errors returned by the MRC wrapper. */ +enum mrc_wrapper_error { + INVALID_VER = -1, + INVALID_DRAM_TYPE = -2, + INVALID_SLEEP_MODE = -3, + PLATFORM_SETTINGS_FAIL = -4, + DIMM_DETECTION_FAILURE = -5, + MEMORY_CONFIG_FAILURE = -6, + INVALID_CPU_ODT_SETTING = -7, + INVALID_DRAM_ODT_SETTING = -8, +}; + +struct mrc_mainboard_params { + int dram_type; + int dram_info_location; /* DRAM_INFO_* */ + int dram_is_slotted; /* mobo has DRAM slots. */ + /* + * The below ODT settings are only honored when !dram_is_slotted. + * Aditionally, weaker_odt_settings being non-zero causes + * cpu_odt_value to not be honored as weaker_odt_settings have a + * special training path. + */ + int weaker_odt_settings; + /* Allowed settings: 60, 80, 100, 120, and 150. */ + int cpu_odt_value; + /* Allowed settings: 60 and 120. */ + int dram_odt_value; + int spd_addrs[NUM_CHANNELS]; + void *dram_data[NUM_CHANNELS]; /* SPD or Timing specific data. */ +} __attribute__((packed)); + +struct mrc_params { + /* Mainboard Inputs */ + int version; + + struct mrc_mainboard_params mainboard; + + void ABI_X86 (*console_out)(unsigned char byte); + + int prev_sleep_state; + + int saved_data_size; + const void *saved_data; + + int txe_size_mb; /* TXE memory size in megabytes. */ + int rmt_enabled; /* Enable RMT training + prints. */ + int io_hole_mb; /* Size of IO hole in MiB. */ + + /* Outputs */ + void *txe_base_address; + int data_to_save_size; + void *data_to_save; +} __attribute__((packed)); + +/* Call into wrapper. */ +typedef int ABI_X86 (*mrc_wrapper_entry_t)(struct mrc_params *); + +#endif /* _MRC_WRAPPER_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/msr.h b/src/soc/intel/baytrail/include/soc/msr.h new file mode 100644 index 0000000000..656d26aae7 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/msr.h @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_MSR_H_ +#define _BAYTRAIL_MSR_H_ + +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0xcd +#define MSR_PLATFORM_INFO 0xce +#define MSR_PMG_CST_CONFIG_CONTROL 0xe2 +#define SINGLE_PCTL (1 << 11) +#define MSR_POWER_MISC 0x120 +#define ENABLE_ULFM_AUTOCM_MASK (1 << 2) +#define ENABLE_INDP_AUTOCM_MASK (1 << 3) +#define MSR_IA32_PERF_CTL 0x199 +#define MSR_IA32_MISC_ENABLES 0x1a0 +#define MSR_POWER_CTL 0x1fc +#define MSR_PKG_POWER_SKU_UNIT 0x606 +#define MSR_PKG_POWER_LIMIT 0x610 +#define MSR_PP1_POWER_LIMIT 0x638 +#define MSR_IACORE_RATIOS 0x66a +#define MSR_IACORE_TURBO_RATIOS 0x66c +#define MSR_IACORE_VIDS 0x66b +#define MSR_IACORE_TURBO_VIDS 0x66d +#define MSR_PKG_TURBO_CFG1 0x670 +#define MSR_CPU_TURBO_WKLD_CFG1 0x671 +#define MSR_CPU_TURBO_WKLD_CFG2 0x672 +#define MSR_CPU_THERM_CFG1 0x673 +#define MSR_CPU_THERM_CFG2 0x674 +#define MSR_CPU_THERM_SENS_CFG 0x675 + +/* Read BCLK from MSR */ +unsigned bus_freq_khz(void); + +#endif /* _BAYTRAIL_MSR_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/nvs.h b/src/soc/intel/baytrail/include/soc/nvs.h new file mode 100644 index 0000000000..c909d567e5 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/nvs.h @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_NVS_H_ +#define _BAYTRAIL_NVS_H_ + +#include +#include + +typedef struct { + /* Miscellaneous */ + u16 osys; /* 0x00 - Operating System */ + u8 smif; /* 0x02 - SMI function call ("TRAP") */ + u8 prm0; /* 0x03 - SMI function call parameter */ + u8 prm1; /* 0x04 - SMI function call parameter */ + u8 scif; /* 0x05 - SCI function call (via _L00) */ + u8 prm2; /* 0x06 - SCI function call parameter */ + u8 prm3; /* 0x07 - SCI function call parameter */ + u8 lckf; /* 0x08 - Global Lock function for EC */ + u8 prm4; /* 0x09 - Lock function parameter */ + u8 prm5; /* 0x0a - Lock function parameter */ + u32 p80d; /* 0x0b - Debug port (IO 0x80) value */ + u8 lids; /* 0x0f - LID state (open = 1) */ + u8 pwrs; /* 0x10 - Power state (AC = 1) */ + u8 pcnt; /* 0x11 - Processor Count */ + u8 tpmp; /* 0x12 - TPM Present and Enabled */ + u8 tlvl; /* 0x13 - Throttle Level */ + u8 ppcm; /* 0x14 - Maximum P-state usable by OS */ + u32 pm1i; /* 0x15 - System Wake Source - PM1 Index */ + u8 rsvd1[7]; + + /* Device Config */ + u8 s5u0; /* 0x20 - Enable USB0 in S5 */ + u8 s5u1; /* 0x21 - Enable USB1 in S5 */ + u8 s3u0; /* 0x22 - Enable USB0 in S3 */ + u8 s3u1; /* 0x23 - Enable USB1 in S3 */ + u8 tact; /* 0x24 - Thermal Active trip point */ + u8 tpsv; /* 0x25 - Thermal Passive trip point */ + u8 tcrt; /* 0x26 - Thermal Critical trip point */ + u8 dpte; /* 0x27 - Enable DPTF */ + u8 rsvd2[8]; + + /* Base Addresses */ + u32 cmem; /* 0x30 - CBMEM TOC */ + u32 tolm; /* 0x34 - Top of Low Memory */ + u32 cbmc; /* 0x38 - coreboot memconsole */ + u8 rsvd3[196]; + + /* ChromeOS specific (0x100-0xfff)*/ + chromeos_acpi_t chromeos; + + /* Baytrail LPSS (0x1000) */ + device_nvs_t dev; +} __attribute__((packed)) global_nvs_t; + +#ifdef __SMM__ +/* Used in SMM to find the ACPI GNVS address */ +global_nvs_t *smm_get_gnvs(void); +#endif + +#endif /* _BAYTRAIL_NVS_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/pattrs.h b/src/soc/intel/baytrail/include/soc/pattrs.h new file mode 100644 index 0000000000..d4eb721593 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/pattrs.h @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _PATTRS_H_ +#define _PATTRS_H_ + +#include +#include + +enum { + IACORE_MIN, + IACORE_LFM, + IACORE_MAX, + IACORE_TURBO, + IACORE_END +}; + +/* The pattrs structure is a common place to stash pertinent information + * about the processor or platform. Instead of going to the source (msrs, cpuid) + * every time an attribute is needed use the pattrs structure. + */ +struct pattrs { + msr_t platform_id; + msr_t platform_info; + int iacore_ratios[IACORE_END]; + int iacore_vids[IACORE_END]; + uint32_t cpuid; + int revid; + int stepping; + const void *microcode_patch; + int address_bits; + int num_cpus; + unsigned bclk_khz; +}; + +/* This is just to hide the abstraction w/o relying on how the underlying + * storage is allocated. */ +#define PATTRS_GLOB_NAME __global_pattrs +#define DEFINE_PATTRS struct pattrs PATTRS_GLOB_NAME +extern DEFINE_PATTRS; + +static inline const struct pattrs *pattrs_get(void) +{ + return &PATTRS_GLOB_NAME; +} + + +#endif /* _PATTRS_H_ */ + diff --git a/src/soc/intel/baytrail/include/soc/pci_devs.h b/src/soc/intel/baytrail/include/soc/pci_devs.h new file mode 100644 index 0000000000..b3fdce234a --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/pci_devs.h @@ -0,0 +1,155 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_PCI_DEVS_H_ +#define _BAYTRAIL_PCI_DEVS_H_ + +/* All these devices live on bus 0 with the associated device and function */ + +/* SoC transaction router */ +#define SOC_DEV 0x0 +#define SOC_FUNC 0 +# define SOC_DEVID 0x0f00 + +/* Graphics and Display */ +#define GFX_DEV 0x2 +#define GFX_FUNC 0 +# define GFX_DEVID 0x0f31 + +/* SDIO Port */ +#define SDIO_DEV 0x11 +#define SDIO_FUNC 0 +# define SDIO_DEVID 0x0f15 + +/* SD Port */ +#define SD_DEV 0x12 +#define SD_FUNC 0 +# define SD_DEVID 0x0f16 + +/* SATA */ +#define SATA_DEV 0x13 +#define SATA_FUNC 0 +#define IDE1_DEVID 0x0f20 +#define IDE2_DEVID 0x0f21 +#define AHCI1_DEVID 0x0f22 +#define AHCI2_DEVID 0x0f23 + +/* xHCI */ +#define XHCI_DEV 0x14 +#define XHCI_FUNC 0 +# define XHCI_DEVID 0x0f35 + +/* LPE Audio */ +#define LPE_DEV 0x15 +#define LPE_FUNC 0 +# define LPE_DEVID 0x0f28 + +/* MMC Port */ +#define MMC_DEV 0x17 +#define MMC_FUNC 0 +# define MMC_DEVID 0x0f50 + +/* Serial IO 1 */ +#define SIO1_DEV 0x18 +# define SIO_DMA1_DEV SIO1_DEV +# define SIO_DMA1_FUNC 0 +# define SIO_DMA1_DEVID 0x0f40 +# define I2C1_DEV SIO1_DEV +# define I2C1_FUNC 1 +# define I2C1_DEVID 0x0f41 +# define I2C2_DEV SIO1_DEV +# define I2C2_FUNC 2 +# define I2C2_DEVID 0x0f42 +# define I2C3_DEV SIO1_DEV +# define I2C3_FUNC 3 +# define I2C3_DEVID 0x0f43 +# define I2C4_DEV SIO1_DEV +# define I2C4_FUNC 4 +# define I2C4_DEVID 0x0f44 +# define I2C5_DEV SIO1_DEV +# define I2C5_FUNC 5 +# define I2C5_DEVID 0x0f45 +# define I2C6_DEV SIO1_DEV +# define I2C6_FUNC 6 +# define I2C6_DEVID 0x0f46 +# define I2C7_DEV SIO1_DEV +# define I2C7_FUNC 7 +# define I2C7_DEVID 0x0f47 + +/* Trusted Execution Engine */ +#define TXE_DEV 0x1a +#define TXE_FUNC 0 +# define TXE_DEVID 0x0f18 + +/* HD Audio */ +#define HDA_DEV 0x1b +#define HDA_FUNC 0 +# define HDA_DEVID 0x0f04 + +/* PCIe Ports */ +#define PCIE_DEV 0x1c +# define PCIE_PORT1_DEV PCIE_DEV +# define PCIE_PORT1_FUNC 0 +# define PCIE_PORT1_DEVID 0x0f48 +# define PCIE_PORT2_DEV PCIE_DEV +# define PCIE_PORT2_FUNC 1 +# define PCIE_PORT2_DEVID 0x0f4a +# define PCIE_PORT3_DEV PCIE_DEV +# define PCIE_PORT3_FUNC 2 +# define PCIE_PORT3_DEVID 0x0f4c +# define PCIE_PORT4_DEV PCIE_DEV +# define PCIE_PORT4_FUNC 3 +# define PCIE_PORT4_DEVID 0x0f4e + +/* EHCI */ +#define EHCI_DEV 0x1d +#define EHCI_FUNC 0 +# define EHCI_DEVID 0x0f34 + +/* Serial IO 2 */ +#define SIO2_DEV 0x1e +# define SIO_DMA2_DEV SIO2_DEV +# define SIO_DMA2_FUNC 0 +# define SIO_DMA2_DEVID 0x0f06 +# define PWM1_DEV SIO2_DEV +# define PWM1_FUNC 1 +# define PWM1_DEVID 0x0f08 +# define PWM2_DEV SIO2_DEV +# define PWM2_FUNC 2 +# define PWM2_DEVID 0x0f09 +# define HSUART1_DEV SIO2_DEV +# define HSUART1_FUNC 3 +# define HSUART1_DEVID 0x0f0a +# define HSUART2_DEV SIO2_DEV +# define HSUART2_FUNC 4 +# define HSUART2_DEVID 0x0f0c +# define SPI_DEV SIO2_DEV +# define SPI_FUNC 5 +# define SPI_DEVID 0xf0e + +/* Platform Controller Unit */ +#define PCU_DEV 0x1f +# define LPC_DEV PCU_DEV +# define LPC_FUNC 0 +# define LPC_DEVID 0x0f1c +# define SMBUS_DEV PCU_DEV +# define SMBUS_FUNC 3 +# define SMBUS_DEVID 0x0f12 + +#endif /* _BAYTRAIL_PCI_DEVS_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/pcie.h b/src/soc/intel/baytrail/include/soc/pcie.h new file mode 100644 index 0000000000..a1c0263a74 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/pcie.h @@ -0,0 +1,102 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_PCIE_H_ +#define _BAYTRAIL_PCIE_H_ + +/* PCIe root port config space registers. */ +#define XCAP 0x40 +# define SI (1 << 24) +#define DCAP 0x44 +# define MPS_MASK 0x7 +#define DCTL_DSTS 0x48 +# define URE (1 << 3) +# define FEE (1 << 2) +# define NFE (1 << 1) +# define CEE (1 << 0) +#define LCAP 0x4c +# define L1EXIT_SHIFT 15 +# define L1EXIT_MASK (0x7 << L1EXIT_SHIFT) +#define LCTL 0x50 +# define CCC (1 << 6) +# define RL (1 << 5) +# define LD (1 << 4) +#define LSTS 0x52 +#define SLCAP 0x54 +# define SLN_SHIFT 19 +# define SLS_SHIFT 15 +# define SLV_SHIFT 7 +# define HPC (1 << 6) +# define HPS (1 << 5) +#define SLCTL_SLSTS 0x58 +# define PDS (1 << 22) +#define DCAP2 0x64 +# define OBFFS (0x3 << 18) +# define LTRMS (1 << 11) +#define DSTS2 0x68 +# define OBFFEN (3 << 13) +# define LTRME (1 << 10) +# define CTD (1 << 4) +#define CHCFG 0xd0 +# define UPSD (1 << 24) +# define UNRS (1 << 15) +# define UPRS (1 << 14) +#define MPC2 0xd4 +# define IPF (1 << 11) +# define LSTP (1 << 6) +# define EOIFD (1 << 1) +#define MPC 0xd8 +# define CCEL_SHIFT 15 +# define CCEL_MASK (0x7 << CCEL_SHIFT) +#define RPPGEN 0xe0 +# define RPSCGEN (1 << 15) +# define LCLKREQEN (1 << 13) +# define BBCLKREQEN (1 << 12) +# define SRDLCGEN (1 << 11) +# define SRDBCGEN (1 << 10) +# define RPDLCGEN (1 << 9) +# define RPDBCGEN (1 << 8) +#define PWRCTL 0xe8 +# define RPL1SQPOL (1 << 1) +# define RPDTSQPOL (1 << 0) +#define PHYCTL2_IOSFBCTL 0xf4 +# define PLL_OFF_EN (1 << 8) +# define TDFT (3 << 14) +# define TXCFGCHWAIT (3 << 12) +# define SIID (3 << 26) +#define STRPFUSECFG 0xfc +# define LANECFG_SHIFT 14 +# define LANECFG_MASK (0x3 << LANECFG_SHIFT) +#define AERCH 0x100 +#define NFTS 0x314 +#define L0SC 0x318 +#define CFG2 0x320 +# define CSREN (1 << 22) +# define LATGC_SHIFT 6 +# define LATGC_MASK (0x7 << LATGC_SHIFT) +#define PCIEDBG 0x324 +# define SPCE (1 << 5) +#define PCIESTS1 0x328 +#define PCIEALC 0x338 +#define RTP 0x33c +#define PHYCTL4 0x408 +# define SQDIS (1 << 27) + +#define PCIE_ROOT_PORT_COUNT 4 +#endif /* _BAYTRAIL_PCIE_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/pmc.h b/src/soc/intel/baytrail/include/soc/pmc.h new file mode 100644 index 0000000000..1af7ab86ce --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/pmc.h @@ -0,0 +1,303 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_PMC_H_ +#define _BAYTRAIL_PMC_H_ + + +#define IOCOM1 0x3f8 + +/* Memory mapped IO registers behind PMC_BASE_ADDRESS */ +#define PRSTS 0x00 +# define PMC_WDT_STS (1 << 15) +# define SEC_GBLRST_STS (1 << 7) +# define SEC_WDT_STS (1 << 6) +# define WOL_OVR_WK_STS (1 << 5) +# define PMC_WAKE_STS (1 << 4) +#define PMC_CFG 0x08 +# define SPS (1 << 5) +# define NO_REBOOT (1 << 4) +# define SX_ENT_TO_EN (1 << 3) +# define TIMING_T581_SHIFT (0) +# define TIMING_T581_MASK (3 << TIMING_T581_SHIFT) +# define TIMING_T581_10uS (0 << TIMING_T581_SHIFT) +# define TIMING_T581_100uS (1 << TIMING_T581_SHIFT) +# define TIMING_T581_1mS (2 << TIMING_T581_SHIFT) +# define TIMING_T581_10mS (3 << TIMING_T581_SHIFT) +#define VLV_PM_STS 0x0c +# define PMC_MSG_FULL_STS (1 << 24) +# define PMC_MSG_4_FULL_STS (1 << 23) +# define PMC_MSG_3_FULL_STS (1 << 22) +# define PMC_MSG_2_FULL_STS (1 << 21) +# define PMC_MSG_1_FULL_STS (1 << 20) +# define CODE_REQ (1 << 8) +# define HPR_ENT_TO (1 << 2) +# define SX_ENT_TO (1 << 1) +#define GEN_PMCON1 0x20 +# define UART_EN (1 << 24) +# define DISB (1 << 23) +# define MEM_SR (1 << 21) +# define SRS (1 << 20) +# define CTS (1 << 19) +# define MS4V (1 << 18) +# define PWR_FLR (1 << 16) +# define PME_B0_S5_DIS (1 << 15) +# define SUS_PWR_FLR (1 << 14) +# define WOL_EN_OVRD (1 << 13) +# define DIS_SLP_X_STRCH_SUS_UP (1 << 12) +# define GEN_RST_STS (1 << 9) +# define RPS (1 << 2) +# define AFTERG3_EN (1 << 0) +#define GEN_PMCON2 0x24 +# define SLPSX_STR_POL_LOCK (1 << 18) +# define BIOS_PCI_EXP_EN (1 << 10) +# define PWRBTN_LVL (1 << 9) +# define SMI_LOCK (1 << 4) +#define ETR 0x48 +# define CF9LOCK (1 << 31) +# define LTR_DEF (1 << 22) +# define IGNORE_HPET (1 << 21) +# define CF9GR (1 << 20) +# define CWORWRE (1 << 18) +#define FUNC_DIS 0x34 +# define SIO_DMA2_DIS (1 << 0) +# define PWM1_DIS (1 << 1) +# define PWM2_DIS (1 << 2) +# define HSUART1_DIS (1 << 3) +# define HSUART2_DIS (1 << 4) +# define SPI_DIS (1 << 5) +# define SDIO_DIS (1 << 9) +# define SD_DIS (1 << 10) +# define MMC_DIS (1 << 11) +# define HDA_DIS (1 << 12) +# define LPE_DIS (1 << 13) +# define OTG_DIS (1 << 14) +# define XHCI_DIS (1 << 15) +# define SATA_DIS (1 << 17) +# define EHCI_DIS (1 << 18) +# define TXE_DIS (1 << 19) +# define PCIE_PORT1_DIS (1 << 20) +# define PCIE_PORT2_DIS (1 << 21) +# define PCIE_PORT3_DIS (1 << 22) +# define PCIE_PORT4_DIS (1 << 23) +# define SIO_DMA1_DIS (1 << 24) +# define I2C1_DIS (1 << 25) +# define I2C2_DIS (1 << 26) +# define I2C3_DIS (1 << 27) +# define I2C4_DIS (1 << 28) +# define I2C5_DIS (1 << 29) +# define I2C6_DIS (1 << 30) +# define I2C7_DIS (1 << 31) +#define FUNC_DIS2 0x38 +# define USH_SS_PHY_DIS (1 << 2) +# define OTG_SS_PHY_DIS (1 << 1) +# define SMBUS_DIS (1 << 0) +#define GPIO_ROUT 0x58 +# define ROUTE_MASK 3 +# define ROUTE_NONE 0 +# define ROUTE_SMI 1 +# define ROUTE_SCI 2 +#define PLT_CLK_CTL_0 0x60 +#define PLT_CLK_CTL_1 0x64 +#define PLT_CLK_CTL_2 0x68 +#define PLT_CLK_CTL_3 0x6c +#define PLT_CLK_CTL_4 0x70 +#define PLT_CLK_CTL_5 0x74 +# define CLK_FREQ_25MHZ (0x0 << 2) +# define CLK_FREQ_19P2MHZ (0x1 << 2) +# define CLK_CTL_D3_LPE (0x0 << 0) +# define CLK_CTL_ON (0x1 << 0) +# define CLK_CTL_OFF (0x2 << 0) +#define PME_STS 0xc0 +#define GPE_LEVEL_EDGE 0xc4 +# define GPE_EDGE 0 +# define GPE_LEVEL 1 +#define GPE_POLARITY 0xc8 +# define GPE_ACTIVE_HIGH 1 +# define GPE_ACTIVE_LOW 0 +#define LOCK 0xcc + +/* IO Mapped registers behind ACPI_BASE_ADDRESS */ +#define PM1_STS 0x00 +#define WAK_STS (1 << 15) +#define PCIEXPWAK_STS (1 << 14) +#define USB_STS (1 << 13) +#define PRBTNOR_STS (1 << 11) +#define RTC_STS (1 << 10) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define TMROF_STS (1 << 0) +#define PM1_EN 0x02 +#define PCIEXPWAK_DIS (1 << 14) +#define USB_WAKE_EN (1 << 13) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP_SHIFT 10 +#define SLP_TYP (7 << SLP_TYP_SHIFT) +#define SLP_TYP_S0 0 +#define SLP_TYP_S1 1 +#define SLP_TYP_S3 5 +#define SLP_TYP_S4 6 +#define SLP_TYP_S5 7 +#define GBL_RLS (1 << 2) +#define BM_RLD (1 << 1) +#define SCI_EN (1 << 0) +#define PM1_TMR 0x08 +#define GPE0_STS 0x20 +#define CORE_GPIO_STS7 (1 << 31) +#define CORE_GPIO_STS6 (1 << 30) +#define CORE_GPIO_STS5 (1 << 29) +#define CORE_GPIO_STS4 (1 << 28) +#define CORE_GPIO_STS3 (1 << 27) +#define CORE_GPIO_STS2 (1 << 26) +#define CORE_GPIO_STS1 (1 << 25) +#define CORE_GPIO_STS0 (1 << 24) +#define SUS_GPIO_STS7 (1 << 23) +#define SUS_GPIO_STS6 (1 << 22) +#define SUS_GPIO_STS5 (1 << 21) +#define SUS_GPIO_STS4 (1 << 20) +#define SUS_GPIO_STS3 (1 << 19) +#define SUS_GPIO_STS2 (1 << 18) +#define SUS_GPIO_STS1 (1 << 17) +#define SUS_GPIO_STS0 (1 << 16) +#define PME_B0_STS (1 << 13) +#define BATLOW_STS (1 << 10) +#define PCI_EXP_STS (1 << 9) +#define PCIE_WAKE3_STS (1 << 8) +#define PCIE_WAKE2_STS (1 << 7) +#define PCIE_WAKE1_STS (1 << 6) +#define GUNIT_SCI_STS (1 << 5) +#define PUNIT_SCI_STS (1 << 4) +#define PCIE_WAKE0_STS (1 << 3) +#define SWGPE_STS (1 << 2) +#define HOT_PLUG_STS (1 << 1) +#define GPE0_EN 0x28 +#define CORE_GPIO_EN7 (1 << 31) +#define CORE_GPIO_EN6 (1 << 30) +#define CORE_GPIO_EN5 (1 << 29) +#define CORE_GPIO_EN4 (1 << 28) +#define CORE_GPIO_EN3 (1 << 27) +#define CORE_GPIO_EN2 (1 << 26) +#define CORE_GPIO_EN1 (1 << 25) +#define CORE_GPIO_EN0 (1 << 24) +#define SUS_GPIO_EN7_BIT 23 +#define SUS_GPIO_EN7 (1 << SUS_GPIO_EN7_BIT) +#define SUS_GPIO_EN6_BIT 22 +#define SUS_GPIO_EN6 (1 << SUS_GPIO_EN6_BIT) +#define SUS_GPIO_EN5_BIT 21 +#define SUS_GPIO_EN5 (1 << SUS_GPIO_EN5_BIT) +#define SUS_GPIO_EN4_BIT 20 +#define SUS_GPIO_EN4 (1 << SUS_GPIO_EN4_BIT) +#define SUS_GPIO_EN3_BIT 19 +#define SUS_GPIO_EN3 (1 << SUS_GPIO_EN3_BIT) +#define SUS_GPIO_EN2_BIT 18 +#define SUS_GPIO_EN2 (1 << SUS_GPIO_EN2_BIT) +#define SUS_GPIO_EN1_BIT 17 +#define SUS_GPIO_EN1 (1 << SUS_GPIO_EN1_BIT) +#define SUS_GPIO_EN0_BIT 16 +#define SUS_GPIO_EN0 (1 << SUS_GPIO_EN0_BIT) +#define PME_B0_EN (1 << 13) +#define BATLOW_EN (1 << 10) +#define PCI_EXP_EN (1 << 9) +#define PCIE_WAKE3_EN (1 << 8) +#define PCIE_WAKE2_EN (1 << 7) +#define PCIE_WAKE1_EN (1 << 6) +#define PCIE_WAKE0_EN (1 << 3) +#define SWGPE_EN (1 << 2) +#define HOT_PLUG_EN (1 << 1) +#define _ACPI_ENABLE_WAKE_SUS_GPIO(x) SUS_GPIO_EN##x##_BIT +#define ACPI_ENABLE_WAKE_SUS_GPIO(x) _ACPI_ENABLE_WAKE_SUS_GPIO(x) +#define SMI_EN 0x30 +#define INTEL_USB2_EN (1 << 18) // Intel-Specific USB2 SMI logic +#define USB_EN (1 << 17) // Legacy USB2 SMI logic +#define PERIODIC_EN (1 << 14) // SMI on PERIODIC_STS in SMI_STS +#define TCO_EN (1 << 13) // Enable TCO Logic (BIOSWE et al) +#define BIOS_RLS (1 << 7) // asserts SCI on bit set +#define SWSMI_TMR_EN (1 << 6) // start software smi timer on bit set +#define APMC_EN (1 << 5) // Writes to APM_CNT cause SMI# +#define SLP_SMI_EN (1 << 4) // Write to SLP_EN in PM1_CNT asserts SMI# +#define BIOS_EN (1 << 2) // Assert SMI# on setting GBL_RLS bit +#define EOS (1 << 1) // End of SMI (deassert SMI#) +#define GBL_SMI_EN (1 << 0) // SMI# generation at all? +#define SMI_STS 0x34 +#define ALT_GPIO_SMI 0x38 +#define UPRWC 0x3c +# define UPRWC_WR_EN (1 << 1) // USB Per-Port Registers Write Enable +#define GPE_CTRL 0x40 +#define PM2A_CNT_BLK 0x50 +#define TCO_RLD 0x60 +#define TCO_STS 0x64 +# define SECOND_TO_STS (1 << 17) +# define TCO_TIMEOUT (1 << 3) +#define TCO1_CNT 0x68 +# define TCO_LOCK (1 << 12) +# define TCO_TMR_HALT (1 << 11) +#define TCO_TMR 0x70 + +/* I/O ports */ +#define RST_CNT 0xcf9 +# define FULL_RST (1 << 3) +# define RST_CPU (1 << 2) +# define SYS_RST (1 << 1) + +#if !defined(__ASSEMBLER__) && !defined(__ACPI__) + +/* Track power state from reset to log events. */ +struct chipset_power_state { + uint16_t pm1_sts; + uint16_t pm1_en; + uint32_t pm1_cnt; + uint32_t gpe0_sts; + uint32_t gpe0_en; + uint32_t tco_sts; + uint32_t prsts; + uint32_t gen_pmcon1; + uint32_t gen_pmcon2; +} __attribute__((packed)); + +/* Power Management Utility Functions. */ +uint16_t get_pmbase(void); +uint32_t clear_smi_status(void); +uint16_t clear_pm1_status(void); +uint32_t clear_tco_status(void); +uint32_t clear_gpe_status(void); +uint32_t clear_alt_status(void); +void clear_pmc_status(void); +void enable_smi(uint32_t mask); +void disable_smi(uint32_t mask); +void enable_pm1(uint16_t events); +void enable_pm1_control(uint32_t mask); +void disable_pm1_control(uint32_t mask); +void enable_gpe(uint32_t mask); +void disable_gpe(uint32_t mask); +void disable_all_gpe(void); + +#if CONFIG_ELOG +void southcluster_log_state(void); +#else +static inline void southcluster_log_state(void) {} +#endif + +#endif /* !defined(__ASSEMBLER__) && !defined(__ACPI__) */ + +#endif /* _BAYTRAIL_PMC_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/ramstage.h b/src/soc/intel/baytrail/include/soc/ramstage.h new file mode 100644 index 0000000000..0ed83bd1d4 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/ramstage.h @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_RAMSTAGE_H_ +#define _BAYTRAIL_RAMSTAGE_H_ + +#include +#include + +/* The baytrail_init_pre_device() function is called prior to device + * initialization, but it's after console and cbmem has been reinitialized. */ +void baytrail_init_pre_device(struct soc_intel_baytrail_config *config); +void baytrail_init_cpus(device_t dev); +void set_max_freq(void); +void southcluster_enable_dev(device_t dev); +#if CONFIG_HAVE_REFCODE_BLOB +void baytrail_run_reference_code(void); +#else +static inline void baytrail_run_reference_code(void) {} +#endif +void baytrail_init_scc(void); +void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index); + +extern struct pci_operations soc_pci_ops; + +#endif /* _BAYTRAIL_RAMSTAGE_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/reset.h b/src/soc/intel/baytrail/include/soc/reset.h new file mode 100644 index 0000000000..dbf0fd23cf --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/reset.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_RESET_H_ +#define _BAYTRAIL_RESET_H_ +#include + +/* Bay Trail has the following types of resets: + * - Soft reset (INIT# to cpu) - write 0x1 to I/O 0x92 + * - Soft reset (INIT# to cpu)- write 0x4 to I/0 0xcf9 + * - Cold reset (S0->S5->S0) - write 0xe to I/0 0xcf9 + * - Warm reset (PMC_PLTRST# assertion) - write 0x6 to I/O 0xcf9 + * - Global reset (S0->S5->S0 with TXE reset) - write 0x6 or 0xe to 0xcf9 but + * with ETR[20] set. + */ + +void cold_reset(void); +void warm_reset(void); + +#endif /* _BAYTRAIL_RESET_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/romstage.h b/src/soc/intel/baytrail/include/soc/romstage.h new file mode 100644 index 0000000000..f99a8e28bc --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/romstage.h @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_ROMSTAGE_H_ +#define _BAYTRAIL_ROMSTAGE_H_ + +#if !defined(__PRE_RAM__) +#error "Don't include romstage.h from a ramstage compilation unit!" +#endif + +#include +#include +#include + +struct romstage_params { + unsigned long bist; + struct mrc_params *mrc_params; +}; + +void mainboard_romstage_entry(struct romstage_params *params); +void romstage_common(struct romstage_params *params); +void * asmlinkage romstage_main(unsigned long bist, uint32_t tsc_lo, + uint32_t tsc_high); +void asmlinkage romstage_after_car(void); +void raminit(struct mrc_params *mp, int prev_sleep_state); +void gfx_init(void); +void tco_disable(void); +void punit_init(void); +void set_max_freq(void); +int early_spi_read_wpsr(u8 *sr); + +#if CONFIG_ENABLE_BUILTIN_COM1 +void byt_config_com1_and_enable(void); +#else +static inline void byt_config_com1_and_enable(void) { } +#endif + +#endif /* _BAYTRAIL_ROMSTAGE_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/sata.h b/src/soc/intel/baytrail/include/soc/sata.h new file mode 100644 index 0000000000..7704c18f34 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/sata.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BAYTRAIL_SATA_H +#define BAYTRAIL_SATA_H + +#define SATA_SIRI 0xa0 +#define SATA_SIRD 0xa4 + +#endif diff --git a/src/soc/intel/baytrail/include/soc/smm.h b/src/soc/intel/baytrail/include/soc/smm.h new file mode 100644 index 0000000000..f147f7336e --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/smm.h @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_SMM_H_ +#define _BAYTRAIL_SMM_H_ + +/* There is a bug in the order of Kconfig includes in that arch/x86/Kconfig + * is included after chipset code. This causes the chipset's Kconfig to be + * cloberred by the arch/x86/Kconfig if they have the same name. */ +static inline int smm_region_size(void) +{ + /* Make it 8MiB by default. */ + if (CONFIG_SMM_TSEG_SIZE == 0) + return (8 << 20); + return CONFIG_SMM_TSEG_SIZE; +} + +void *smm_region_start(void); + +#if !defined(__PRE_RAM__) && !defined(__SMM___) +#include +void southcluster_smm_clear_state(void); +void southcluster_smm_enable_smi(void); +void southcluster_smm_save_param(int param, uint32_t data); +#endif + +enum { + SMM_SAVE_PARAM_GPIO_ROUTE = 0, + SMM_SAVE_PARAM_PCIE_WAKE_ENABLE, + SMM_SAVE_PARAM_COUNT +}; + +#endif /* _BAYTRAIL_SMM_H_ */ diff --git a/src/soc/intel/baytrail/include/soc/spi.h b/src/soc/intel/baytrail/include/soc/spi.h new file mode 100644 index 0000000000..4ffb93a918 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/spi.h @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BAYTRAIL_SPI_H_ +#define _BAYTRAIL_SPI_H_ + +#include + +/* These registers live behind SPI_BASE_ADDRESS. */ +#define HSFSTS 0x04 +#define FDATA0 0x10 +# define FLOCKDN (0x1 << 15) +#define SSFS 0x90 +# define CYCLE_DONE_STATUS (0x1 << 2) +# define FLASH_CYCLE_ERROR (0x1 << 3) +#define SSFC 0x91 +# define SPI_CYCLE_GO (0x1 << 1) +# define DATA_CYCLE (0x1 << 14) +#define PREOP 0x94 +#define OPTYPE 0x96 +#define OPMENU0 0x98 +#define OPMENU1 0x9c +#define LVSCC 0xc4 +# define VCL (0x1 << 23) +# define EO(x) (((x) & 0xff) << 8) +# define WG_1_BYTE (0x0 << 2) +# define WG_64_BYTE (0x1 << 2) +# define BES_256_BYTE (0x0 << 0) +# define BES_4_KB (0x1 << 0) +# define BES_8_KB (0x2 << 0) +# define BES_64_KB (0x3 << 0) +#define UVSCC 0xc8 +#define SCS 0xf8 +# define SMIWPEN (0x1 << 7) +#define BCR 0xfc +# define EISS (0x1 << 5) +# define SRC_MASK (0x3 << 2) +# define SRC_CACHE_NO_PREFETCH (0x0 << 2) +# define SRC_NO_CACHE_NO_PREFETCH (0x1 << 2) +# define SRC_CACHE_PREFETCH (0x2 << 2) +# define BCR_LE (0x1 << 1) +# define BCR_WPD (0x1 << 0) + +/* + * SPI lockdown configuration. + */ +struct spi_config { + uint16_t preop; + uint16_t optype; + uint32_t opmenu[2]; + uint32_t lvscc; + uint32_t uvscc; +}; + +/* Return 0 on success < 0 on failure. */ +int mainboard_get_spi_config(struct spi_config *cfg); + +#endif /* _BAYTRAIL_SPI_H_ */ + diff --git a/src/soc/intel/baytrail/include/soc/xhci.h b/src/soc/intel/baytrail/include/soc/xhci.h new file mode 100644 index 0000000000..b317361c08 --- /dev/null +++ b/src/soc/intel/baytrail/include/soc/xhci.h @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BAYTRAIL_XHCI_H +#define BAYTRAIL_XHCI_H + +/* XHCI PCI Registers */ +#define XHCI_PWR_CTL_STS 0x74 +#define XHCI_USB2PR 0xd0 +#define XHCI_USB2PRM 0xd4 +#define XHCI_USB3PR 0xd8 +#define XHCI_USB3PRM 0xdc +#define XHCI_USB2PDO 0xe4 +#define XHCI_USB3PDO 0xe8 + +/* XHCI Memory Registers */ +#define XHCI_USB3_PORTSC(port) (0x4e0 + (port * 0x10)) +# define XHCI_USB3_PORTSC_CHST (0x7f << 17) +# define XHCI_USB3_PORTSC_WCE (1 << 25) /* Wake on Connect */ +# define XHCI_USB3_PORTSC_WDE (1 << 26) /* Wake on Disconnect */ +# define XHCI_USB3_PORTSC_WOE (1 << 27) /* Wake on Overcurrent */ +# define XHCI_USB3_PORTSC_WRC (1 << 19) /* Warm Reset Complete */ +# define XHCI_USB3_PORTSC_LWS (1 << 16) /* Link Write Strobe */ +# define XHCI_USB3_PORTSC_PED (1 << 1) /* Port Enabled/Disabled */ +# define XHCI_USB3_PORTSC_WPR (1 << 31) /* Warm Port Reset */ +# define XHCI_USB3_PORTSC_PLS (0xf << 5) /* Port Link State */ +# define XHCI_PLSR_DISABLED (4 << 5) /* Port is disabled */ +# define XHCI_PLSR_RXDETECT (5 << 5) /* Port is disconnected */ +# define XHCI_PLSR_POLLING (7 << 5) /* Port is polling */ +# define XHCI_PLSW_ENABLE (5 << 5) /* Enable port */ + +/* The Fuse register is incorrect for Baytrail-M so use hardcoded values */ +#define BYTM_USB2_PORT_COUNT 4 +#define BYTM_USB2_PORT_MAP 0xf +#define BYTM_USB3_PORT_COUNT 1 +#define BYTM_USB3_PORT_MAP 0x1 + +#define XHCI_RESET_TIMEOUT 100000 /* 100ms */ + +#endif /* BAYTRAIL_XHCI_H */ diff --git a/src/soc/intel/baytrail/iosf.c b/src/soc/intel/baytrail/iosf.c new file mode 100644 index 0000000000..bcc6f0e30e --- /dev/null +++ b/src/soc/intel/baytrail/iosf.c @@ -0,0 +1,287 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#if !defined(__PRE_RAM__) +#define IOSF_PCI_BASE (CONFIG_MMCONF_BASE_ADDRESS + (IOSF_PCI_DEV << 12)) + +static inline void write_iosf_reg(int reg, uint32_t value) +{ + write32(IOSF_PCI_BASE + reg, value); +} +static inline uint32_t read_iosf_reg(int reg) +{ + return read32(IOSF_PCI_BASE + reg); +} +#else +static inline void write_iosf_reg(int reg, uint32_t value) +{ + pci_write_config32(IOSF_PCI_DEV, reg, value); +} +static inline uint32_t read_iosf_reg(int reg) +{ + return pci_read_config32(IOSF_PCI_DEV, reg); +} +#endif + +/* Common sequences for all the port accesses. */ +static uint32_t iosf_read_port(uint32_t cr, int reg) +{ + cr |= IOSF_REG(reg) | IOSF_BYTE_EN; + write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg)); + write_iosf_reg(MCR_REG, cr); + return read_iosf_reg(MDR_REG); +} + +static void iosf_write_port(uint32_t cr, int reg, uint32_t val) +{ + cr |= IOSF_REG(reg) | IOSF_BYTE_EN; + write_iosf_reg(MDR_REG, val); + write_iosf_reg(MCRX_REG, IOSF_REG_UPPER(reg)); + write_iosf_reg(MCR_REG, cr); +} + +#define IOSF_READ(port) \ + IOSF_OPCODE(IOSF_OP_READ_##port) | IOSF_PORT(IOSF_PORT_##port) +#define IOSF_WRITE(port) \ + IOSF_OPCODE(IOSF_OP_WRITE_##port) | IOSF_PORT(IOSF_PORT_##port) + +uint32_t iosf_bunit_read(int reg) +{ + return iosf_read_port(IOSF_READ(BUNIT), reg); +} + +void iosf_bunit_write(int reg, uint32_t val) +{ + iosf_write_port(IOSF_WRITE(BUNIT), reg, val); +} + +uint32_t iosf_dunit_read(int reg) +{ + return iosf_read_port(IOSF_READ(SYSMEMC), reg); +} + +uint32_t iosf_dunit_ch0_read(int reg) +{ + return iosf_dunit_read(reg); +} + +uint32_t iosf_dunit_ch1_read(int reg) +{ + uint32_t cr = IOSF_OPCODE(IOSF_OP_READ_SYSMEMC) | + IOSF_PORT(IOSF_PORT_DUNIT_CH1); + return iosf_read_port(cr, reg); +} + +void iosf_dunit_write(int reg, uint32_t val) +{ + iosf_write_port(IOSF_WRITE(SYSMEMC), reg, val); +} + +uint32_t iosf_punit_read(int reg) +{ + return iosf_read_port(IOSF_READ(PMC), reg); +} + +void iosf_punit_write(int reg, uint32_t val) +{ + iosf_write_port(IOSF_WRITE(PMC), reg, val); +} + +uint32_t iosf_usbphy_read(int reg) +{ + return iosf_read_port(IOSF_READ(USBPHY), reg); +} + +void iosf_usbphy_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(USBPHY), reg, val); +} + +uint32_t iosf_ushphy_read(int reg) +{ + return iosf_read_port(IOSF_READ(USHPHY), reg); +} + +void iosf_ushphy_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(USHPHY), reg, val); +} + +uint32_t iosf_lpss_read(int reg) +{ + return iosf_read_port(IOSF_READ(LPSS), reg); +} + +void iosf_lpss_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(LPSS), reg, val); +} + +uint32_t iosf_ccu_read(int reg) +{ + return iosf_read_port(IOSF_READ(CCU), reg); +} + +void iosf_ccu_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(CCU), reg, val); +} + +uint32_t iosf_score_read(int reg) +{ + return iosf_read_port(IOSF_READ(SCORE), reg); +} + +void iosf_score_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(SCORE), reg, val); +} + +uint32_t iosf_scc_read(int reg) +{ + return iosf_read_port(IOSF_READ(SCC), reg); +} + +void iosf_scc_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(SCC), reg, val); +} + +uint32_t iosf_aunit_read(int reg) +{ + return iosf_read_port(IOSF_READ(AUNIT), reg); +} + +void iosf_aunit_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(AUNIT), reg, val); +} + +uint32_t iosf_cpu_bus_read(int reg) +{ + return iosf_read_port(IOSF_READ(CPU_BUS), reg); +} + +void iosf_cpu_bus_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(CPU_BUS), reg, val); +} + +uint32_t iosf_sec_read(int reg) +{ + return iosf_read_port(IOSF_READ(SEC), reg); +} + +void iosf_sec_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(SEC), reg, val); +} + +uint32_t iosf_port45_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x45), reg); +} + +void iosf_port45_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x45), reg, val); +} + +uint32_t iosf_port46_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x46), reg); +} + +void iosf_port46_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x46), reg, val); +} + +uint32_t iosf_port47_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x47), reg); +} + +void iosf_port47_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x47), reg, val); +} + +uint32_t iosf_port55_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x55), reg); +} + +void iosf_port55_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x55), reg, val); +} + +uint32_t iosf_port58_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x58), reg); +} + +void iosf_port58_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x58), reg, val); +} + +uint32_t iosf_port59_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x59), reg); +} + +void iosf_port59_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x59), reg, val); +} + +uint32_t iosf_port5a_read(int reg) +{ + return iosf_read_port(IOSF_READ(0x5a), reg); +} + +void iosf_port5a_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0x5a), reg, val); +} + +uint32_t iosf_porta2_read(int reg) +{ + return iosf_read_port(IOSF_READ(0xa2), reg); +} + +void iosf_porta2_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(0xa2), reg, val); +} + +uint32_t iosf_ssus_read(int reg) +{ + return iosf_read_port(IOSF_READ(SSUS), reg); +} + +void iosf_ssus_write(int reg, uint32_t val) +{ + return iosf_write_port(IOSF_WRITE(SSUS), reg, val); +} diff --git a/src/soc/intel/baytrail/lpe.c b/src/soc/intel/baytrail/lpe.c new file mode 100644 index 0000000000..bee9d2ef5d --- /dev/null +++ b/src/soc/intel/baytrail/lpe.c @@ -0,0 +1,187 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" + + +/* The LPE audio devices needs 1MiB of memory reserved aligned to a 512MiB + * address. Just take 1MiB @ 512MiB. */ +#define FIRMWARE_PHYS_BASE (512 << 20) +#define FIRMWARE_PHYS_LENGTH (1 << 20) +#define FIRMWARE_PCI_REG_BASE 0xa8 +#define FIRMWARE_PCI_REG_LENGTH 0xac +#define FIRMWARE_REG_BASE_C0 0x144000 +#define FIRMWARE_REG_LENGTH_C0 (FIRMWARE_REG_BASE_C0 + 4) + +static void assign_device_nvs(device_t dev, u32 *field, unsigned index) +{ + struct resource *res; + + res = find_resource(dev, index); + if (res) + *field = res->base; +} + +static void lpe_enable_acpi_mode(device_t dev) +{ + static const struct reg_script ops[] = { + /* Disable PCI interrupt, enable Memory and Bus Master */ + REG_PCI_OR32(PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)), + /* Enable ACPI mode */ + REG_IOSF_OR(IOSF_PORT_0x58, LPE_PCICFGCTR1, + LPE_PCICFGCTR1_PCI_CFG_DIS | + LPE_PCICFGCTR1_ACPI_INT_EN), + REG_SCRIPT_END + }; + global_nvs_t *gnvs; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0, BAR1, and firmware base to ACPI NVS */ + assign_device_nvs(dev, &gnvs->dev.lpe_bar0, PCI_BASE_ADDRESS_0); + assign_device_nvs(dev, &gnvs->dev.lpe_bar1, PCI_BASE_ADDRESS_1); + assign_device_nvs(dev, &gnvs->dev.lpe_fw, FIRMWARE_PCI_REG_BASE); + + /* Device is enabled in ACPI mode */ + gnvs->dev.lpe_en = 1; + + /* Put device in ACPI mode */ + reg_script_run_on_dev(dev, ops); +} + +static void setup_codec_clock(device_t dev) +{ + uint32_t reg; + int clk_reg; + struct soc_intel_baytrail_config *config; + const char *freq_str; + + config = dev->chip_info; + switch (config->lpe_codec_clk_freq) { + case 19: + freq_str = "19.2"; + reg = CLK_FREQ_19P2MHZ; + break; + case 25: + freq_str = "25"; + reg = CLK_FREQ_25MHZ; + break; + default: + printk(BIOS_DEBUG, "LPE codec clock not required.\n"); + return; + } + + /* Default to always running. */ + reg |= CLK_CTL_ON; + + if (config->lpe_codec_clk_num < 0 || config->lpe_codec_clk_num > 5) { + printk(BIOS_DEBUG, "Invalid LPE codec clock number.\n"); + return; + } + + printk(BIOS_DEBUG, "LPE Audio codec clock set to %sMHz.\n", freq_str); + + clk_reg = PMC_BASE_ADDRESS + PLT_CLK_CTL_0; + clk_reg += 4 * config->lpe_codec_clk_num; + + write32(clk_reg, (read32(clk_reg) & ~0x7) | reg); +} + +static void lpe_stash_firmware_info(device_t dev) +{ + struct resource *res; + struct resource *mmio; + const struct pattrs *pattrs = pattrs_get(); + + res = find_resource(dev, FIRMWARE_PCI_REG_BASE); + if (res == NULL) { + printk(BIOS_DEBUG, "LPE Firmware memory not found.\n"); + return; + } + + /* Continue using old way of informing firmware address / size. */ + pci_write_config32(dev, FIRMWARE_PCI_REG_BASE, res->base); + pci_write_config32(dev, FIRMWARE_PCI_REG_LENGTH, res->size); + + /* C0 and later steppings use an offset in the MMIO space. */ + if (pattrs->stepping >= STEP_C0) { + mmio = find_resource(dev, PCI_BASE_ADDRESS_0); + write32(mmio->base + FIRMWARE_REG_BASE_C0, res->base); + write32(mmio->base + FIRMWARE_REG_LENGTH_C0, res->size); + } +} + +static void lpe_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + + lpe_stash_firmware_info(dev); + + setup_codec_clock(dev); + + if (config->lpe_acpi_mode) + lpe_enable_acpi_mode(dev); +} + +static void lpe_read_resources(device_t dev) +{ + pci_dev_read_resources(dev); + + reserved_ram_resource(dev, FIRMWARE_PCI_REG_BASE, + FIRMWARE_PHYS_BASE >> 10, + FIRMWARE_PHYS_LENGTH >> 10); +} + +static const struct device_operations device_ops = { + .read_resources = lpe_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = lpe_init, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = LPE_DEVID, +}; diff --git a/src/soc/intel/baytrail/lpss.c b/src/soc/intel/baytrail/lpss.c new file mode 100644 index 0000000000..caa945cc31 --- /dev/null +++ b/src/soc/intel/baytrail/lpss.c @@ -0,0 +1,206 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "chip.h" + +static void dev_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index) +{ + struct reg_script ops[] = { + /* Disable PCI interrupt, enable Memory and Bus Master */ + REG_PCI_OR32(PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)), + /* Enable ACPI mode */ + REG_IOSF_OR(IOSF_PORT_LPSS, iosf_reg, + LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN), + REG_SCRIPT_END + }; + struct resource *bar; + global_nvs_t *gnvs; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + bar = find_resource(dev, PCI_BASE_ADDRESS_0); + if (bar) + gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base; + + bar = find_resource(dev, PCI_BASE_ADDRESS_1); + if (bar) + gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base; + + /* Device is enabled in ACPI mode */ + gnvs->dev.lpss_en[nvs_index] = 1; + + /* Put device in ACPI mode */ + reg_script_run_on_dev(dev, ops); +} + +static void dev_enable_snoop_and_pm(device_t dev, int iosf_reg) +{ + struct reg_script ops[] = { + REG_IOSF_RMW(IOSF_PORT_LPSS, iosf_reg, + ~(LPSS_CTL_SNOOP | LPSS_CTL_NOSNOOP), + LPSS_CTL_SNOOP | LPSS_CTL_PM_CAP_PRSNT), + REG_SCRIPT_END, + }; + + reg_script_run_on_dev(dev, ops); +} + +static void dev_ctl_reg(device_t dev, int *iosf_reg, int *nvs_index) +{ + *iosf_reg = -1; + *nvs_index = -1; +#define SET_IOSF_REG(name_) \ + case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \ + *iosf_reg = LPSS_ ## name_ ## _CTL; \ + *nvs_index = LPSS_NVS_ ## name_ + + switch (dev->path.pci.devfn) { + SET_IOSF_REG(SIO_DMA1); + break; + SET_IOSF_REG(I2C1); + break; + SET_IOSF_REG(I2C2); + break; + SET_IOSF_REG(I2C3); + break; + SET_IOSF_REG(I2C4); + break; + SET_IOSF_REG(I2C5); + break; + SET_IOSF_REG(I2C6); + break; + SET_IOSF_REG(I2C7); + break; + SET_IOSF_REG(SIO_DMA2); + break; + SET_IOSF_REG(PWM1); + break; + SET_IOSF_REG(PWM2); + break; + SET_IOSF_REG(HSUART1); + break; + SET_IOSF_REG(HSUART2); + break; + SET_IOSF_REG(SPI); + break; + } +} + +static void i2c_disable_resets(device_t dev) +{ + /* Release the I2C devices from reset. */ + static const struct reg_script ops[] = { + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3), + REG_SCRIPT_END, + }; + +#define CASE_I2C(name_) \ + case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC) + + switch (dev->path.pci.devfn) { + CASE_I2C(I2C1): + CASE_I2C(I2C2): + CASE_I2C(I2C3): + CASE_I2C(I2C4): + CASE_I2C(I2C5): + CASE_I2C(I2C6): + CASE_I2C(I2C7): + printk(BIOS_DEBUG, "Releasing I2C device from reset.\n"); + reg_script_run_on_dev(dev, ops); + break; + default: + return; + } +} + +static void lpss_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + int iosf_reg, nvs_index; + + dev_ctl_reg(dev, &iosf_reg, &nvs_index); + + if (iosf_reg < 0) { + int slot = PCI_SLOT(dev->path.pci.devfn); + int func = PCI_FUNC(dev->path.pci.devfn); + printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", + slot, func); + return; + } + dev_enable_snoop_and_pm(dev, iosf_reg); + i2c_disable_resets(dev); + + if (config->lpss_acpi_mode) + dev_enable_acpi_mode(dev, iosf_reg, nvs_index); +} + +static struct device_operations device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = lpss_init, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + SIO_DMA1_DEVID, + I2C1_DEVID, + I2C2_DEVID, + I2C3_DEVID, + I2C4_DEVID, + I2C5_DEVID, + I2C6_DEVID, + I2C7_DEVID, + SIO_DMA2_DEVID, + PWM1_DEVID, + PWM2_DEVID, + HSUART1_DEVID, + HSUART2_DEVID, + SPI_DEVID, + 0, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/baytrail/memmap.c b/src/soc/intel/baytrail/memmap.c new file mode 100644 index 0000000000..2d6c644be6 --- /dev/null +++ b/src/soc/intel/baytrail/memmap.c @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied wacbmem_entryanty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + + +void *smm_region_start(void) +{ + return (void *)(iosf_bunit_read(BUNIT_SMRRL) << 20); +} + +void *cbmem_top(void) +{ + return smm_region_start(); +} diff --git a/src/soc/intel/baytrail/microcode/M0C30678_0000082D.h b/src/soc/intel/baytrail/microcode/M0C30678_0000082D.h new file mode 100644 index 0000000000..b7200f60f3 --- /dev/null +++ b/src/soc/intel/baytrail/microcode/M0C30678_0000082D.h @@ -0,0 +1,13056 @@ +0x00000001, +0x0000082d, +0x09182014, +0x00030678, +0x71bc26fc, +0x00000001, +0x0000000c, +0x0000cbd0, +0x0000cc00, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x000000a1, +0x00020001, +0x0000082d, +0x00000000, +0x00000000, +0x20140918, +0x00003201, +0x00000001, +0x00030678, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x000032f4, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x617a37ff, +0x5303dba7, +0xb1f97ab5, +0x71ec2257, +0xd80df93f, +0x85ca1a0e, +0x59894a07, +0x6c968b83, +0x156866db, +0xc4bf175a, +0x9d00ca4f, +0xb3e89a09, +0x7d2c8e19, +0xbf5b667c, +0x7a1a7ac0, +0x26eebc7d, +0xb2967286, +0xceb685c8, +0xffba02e6, +0x144b5468, +0x00c428c9, +0x6d15dd3a, +0xf9461953, +0x1632a092, +0x222335da, +0x1fee67d9, +0xa770513c, +0x4e83def6, +0xb3d82e5a, +0x50f0b89f, +0x7fe10d45, +0x70f05efd, +0x5f575449, +0xab71a0a3, +0xfb2a6eb5, +0x0283b4e2, +0x58a95566, +0x38a4c957, +0x8a682f1b, +0xc49b3009, +0x1256e90b, +0x33169c52, +0xd91585c4, +0xdf78eb29, +0x9f403399, +0xa9de58da, +0xfd05c858, +0x5a0f11bc, +0xc00e7840, +0xb39bd56a, +0xb87f38c7, +0x90141c59, +0x325933f9, +0x0b0e1332, +0x963c4bef, +0xf203d9ac, +0x3925365b, +0x2955f8e7, +0x1fc417cb, +0xd840e4e7, +0x25e9f7fa, +0xfb769b96, +0xc7b8da5e, +0xe81200f0, +0x71291c12, +0x5989b1e5, +0xc007fdad, +0xd7c9091f, +0x6a008197, +0x73005539, +0x6d8b436c, +0xbc606f43, +0x00000011, +0x5f813318, +0x6f87a2ce, +0x8f280324, +0x968c8f61, +0xd16e0e73, +0x07b65c72, +0x33cad9f0, +0x23afad77, +0x73463c86, +0x0bbd1459, +0x307fea6c, +0xe5e83ba0, +0x62f82c5d, +0xdf2421e6, +0xebdf5964, +0x27260524, +0x228dd7b0, +0xcbf4158d, +0x703b7611, +0x6be6eecf, +0xcfe520b5, +0x105ed241, +0xeb4fdb1d, +0x68d40ec8, +0x9e8a6465, +0x15932571, +0xf839ef14, +0x32514fca, +0xf966e9d0, +0xbf4e6b5e, +0x22be3144, +0xf737f64e, +0x2ae320ee, +0x7bf9a602, +0x0337261b, +0x8b0b92b9, +0x5f7315e0, +0x6d90f980, +0xc0a52b16, +0x0c1ab213, +0x1a807305, +0x402235b7, +0x5b635a12, +0x277012d3, +0x5001c104, +0x02cb5b6f, +0x1ce7dc3c, +0x88ed3e72, +0x41e35ac1, +0xc10782f7, +0x636bee67, +0x6f46a6c4, +0xc3c75f5d, +0x45f899a5, +0xdc64a2bf, +0x0112aee3, +0x4f2f1a2e, +0x83cd4e02, +0x8b67af93, +0xcec717f4, +0x26a8f8e2, +0x10f99399, +0xf86b934f, +0x9b89db08, +0x2487fef6, +0xbbff7a69, +0x6908c2f3, +0xa045df2a, +0xce65d3ce, +0xd61a9294, +0xfd7b3fdd, +0x42c13d62, +0x7e87e222, +0xed2c5e20, +0x2b19d4ab, +0x874dbeba, +0xc1dd586b, +0xd60bc6e6, +0xd84f5d29, +0xe332dfb3, +0x91f572ed, +0xe151fada, +0x791feda4, +0x9606eee0, +0xc19d813d, +0x757a0a22, +0xf3d601ec, +0xd9175522, +0x656da24e, +0xe253425c, +0xc1d785f8, +0xed1f4d3c, +0x43474b17, +0xfc359c41, +0xc5068790, +0x114e7d58, +0xb1e0693c, +0xd92baade, +0xebc0ec49, +0x2dd672c0, +0x3f9ac6de, +0x2e0a166f, +0x6e8bdaed, +0xda94c30e, +0xcdf02f8c, +0x43d9dda6, +0x4a6baeb0, +0x3f2382d6, +0xbc759da8, +0x2e3601c3, +0x56a4b614, +0xd34d6ef7, +0xe17569fd, +0x1cde4fed, +0xa3c6be73, +0x770919d5, +0x448f24e6, +0xa21c3876, +0x80ff6c48, +0xc8eca7d1, +0xab868eaf, +0x1c7eaa22, +0x8e8c9b6f, +0x37610851, +0xb9052511, +0x2235ec62, +0xf59d30d5, +0xd4f09bc3, +0x2b9bbb39, +0x68965dbb, +0xda36b2d3, +0x659591d2, +0x8b6e60a6, +0x74a7267f, +0xd27cc8ae, +0x2f60d81b, +0x019b506f, +0xf13cd673, +0x7dad58b2, +0x491a0566, +0x42c2418b, +0x0565c74c, +0x53eb363c, +0xa0f9716e, +0x80fc5629, +0xcad03e0e, +0x52eb5e6a, +0x780f26a1, +0x22a22734, +0x135ff60b, +0xf973dbe0, +0x306c9642, +0x2ad4f2c3, +0x698c05bd, +0xcf776cdd, +0xe4f2cf0c, +0xe4afbb1f, +0xac395092, +0xe34f1554, +0x7c964590, +0x833248b7, +0x06a7d950, +0xe2c7373c, +0xaf67d476, +0x5f2a28bc, +0xcb633926, +0xef7c37b8, +0x52964916, +0xb7b70845, +0x441c01ad, +0x6fef39b6, +0x14f3a164, +0x74ef27f6, +0x33c7cbbc, +0xbc88c920, +0xc0a957b3, +0x8b13ce3b, +0xac627edc, +0x869c4120, +0xa2bea077, +0xc063bbb4, +0xf6ef5199, +0xc7ab33e5, +0x5e7a494d, +0xa5d7bc68, +0x6b97dcaf, +0xb4f31d43, +0xf92c221d, +0xab48dec0, +0x4f2260bc, +0x53a35e60, +0xd35dda86, +0x89f1c55a, +0x62e488d4, +0x29a5ce72, +0xe0f1aec8, +0x6b74efa7, +0x2740dd85, +0x2ca2d6b8, +0xf8fb18b8, +0x782d7922, +0xa53dc422, +0xde77a470, +0xf8fbac7d, +0xf25dab61, +0x0329420c, +0xacd56e72, +0xfa13ae4c, +0x6a67685d, +0x3f40d729, +0x14402a95, +0x9234f6e8, +0x6fce09f5, +0x8705e213, +0x6d03c949, +0xb0828afd, +0x1389ea78, +0x8dca0937, +0x5455d973, +0x951d0715, +0xb08c08f7, +0x70318776, +0xa9e131bb, +0xec48ebe6, +0x061306e6, +0xbb83f918, +0x0460e1d6, +0xd421b9bd, +0xe0fbc016, +0x14276fa5, +0x666f05c6, +0xd51598d2, +0x36023730, +0x538ea166, +0x4cd82513, +0x3ce58143, +0xdeab5d51, +0x4adf4666, +0xed01aec8, +0x43572cdb, +0xad1fd1a8, +0x9403d896, +0xe6939490, +0x2b0fafed, +0x7b717957, +0x82170740, +0x886d1273, +0x7ea299f5, +0x3ea5822f, +0x740acaeb, +0xf7f3559a, +0x28bdbedb, +0x5a1aee23, +0x922d9408, +0xe497e405, +0x2bf4489e, +0x108c5627, +0x8bfbff5f, +0x03efb5b7, +0x6c278b95, +0x3702b16e, +0xde8c24d0, +0x586df014, +0x3559ef3b, +0xe772a113, +0x59c50d2e, +0xf177c3e7, +0x027c2247, +0x1747639f, +0x0cec7112, +0x07b034cb, +0xa03df7e7, +0x08021d74, +0xb2d6e4c5, +0xbbe12182, +0x987ee0c9, +0x64d98e2b, +0xd5a91464, +0xa82c4dd5, +0x4cf5a49f, +0x411c64a2, +0x5996cfc3, +0xdc154123, +0x11538973, +0x3f068765, +0x1c96c60c, +0x3704282d, +0x1b123346, +0x806f2ec1, +0x61113000, +0xdd664a36, +0xa3155bc7, +0x324d44dc, +0x2f3f5422, +0xc3c14e70, +0xc8c1fc5b, +0x08ec858e, +0x42ef9e6d, +0xfb999b18, +0x6e2ccfba, +0xd0249407, +0xb037ad7b, +0x7d26d264, +0xd930518d, +0xd3f944f9, +0xe2eb5c42, +0x5ca9d1f4, +0x37e714bc, +0x0ffb8193, +0xf7c7dba5, +0x5fd890d5, +0x51de2121, +0x8015568d, +0x8e282b1e, +0xa28e37de, +0xe73ba1d2, +0x274d907c, +0xf5bb69cc, +0xa28e85d1, +0x71fc848d, +0xf7a2cb4c, +0x905fcc78, +0x608fa566, +0x53e2c930, +0x0aa800f5, +0xdfc6ee1b, +0x92f6cade, +0xea396641, +0x93dd536e, +0xaca85d54, +0x7722eda4, +0x641bc48f, +0xf2d828fe, +0x228ac119, +0x65c23c5e, +0xa030e24e, +0xda6aae2e, +0x31d60bb9, +0xa95a4877, +0xa02aca71, +0x9aeac2db, +0xe89aefc0, +0x7af121ba, +0x1448801f, +0x6829089b, +0x053639d8, +0xc29a2f96, +0x8f052f76, +0x8f7cb9b0, +0xc0822658, +0xfe5eab06, +0x280e5a0d, +0xd8ae059c, +0x03ddb7ce, +0x8acf7126, +0x28c4ad0c, +0x26244649, +0xd5dbb54c, +0xf356af13, +0x4451849b, +0xa7cc27e7, +0x33569104, +0xb243b7d8, +0x998d3666, +0x87dd9328, +0x4620f46f, +0x090fcfb9, +0xa735184e, +0x0207c9ca, +0xd76ca56a, +0x83c468e5, +0x630782d8, +0xd7d8d93f, +0xa57a66d1, +0x585d039b, +0x7e550487, +0x93b2cae1, +0x165ccc1a, +0x565f1e44, +0x4ac2a7c0, +0x55d42c32, +0xbd161c5b, +0xa5cc9637, +0x8118e82a, +0x8128e8d2, +0x7ec983a4, +0x8386ef8f, +0xa41d74a5, +0xdf0472d5, +0xe6057f14, +0x8098b095, +0xadc98f56, +0x2a0bd61b, +0xd9e59816, +0xf559f2dd, +0x4385a18f, +0xb11a23c4, +0xd3bdfe41, +0xade5f7d7, +0x170c831b, +0xd690a32e, +0x76afda76, +0x1454c6c5, +0x455e3470, +0x3de03f85, +0xdb1a884f, +0x7c301eda, +0xf45b8f3d, +0xdf030153, +0x7a4f681b, +0xc6a76457, +0x9109b1e5, +0xd2b591c9, +0x786cca50, +0x55c2f13e, +0x7813da90, +0x1288b665, +0x09d53934, +0x70498ab3, +0xca80cde2, +0xfdefd5c0, +0xeaeedd90, +0x38c38041, +0xaa50286c, +0x57d7233e, +0x4153c14f, +0x3a8009a7, +0xcb2bfc6e, +0x09310e67, +0x4310fa5f, +0xf3c9d420, +0xb91aac3e, +0xdb126f0b, +0x5ddc7f75, +0xbbe6f6ea, +0xc3454ffa, +0x22a1e74d, +0x8e9a2e00, +0x4a5c330e, +0xdf3710eb, +0xcbab5604, +0xfe12d609, +0x529384a0, +0x95baf04e, +0x09a55823, +0xe5f36748, +0xe5b11d2d, +0xc44b2e00, +0x326e4598, +0x3841b84c, +0x491436d9, +0x1580a9ec, +0x7faf5167, +0x92219541, +0xd43e02fa, +0xae42e6c0, +0xb5fe9d0e, +0x65ee6ecb, +0xa3964c43, +0x45f57927, +0xa6373701, +0x900e94fa, +0x189f32b1, +0xc2cb622d, +0xb147bfda, +0x36dcf790, +0x5235e2c0, +0xdba55c90, +0x41c21d92, +0xf6524c2a, +0xf246234c, +0x2eb6a5d9, +0x133a87d4, +0x29e91fb5, +0x38ab56af, +0x150162a1, +0x19d47f2e, +0x1233ac14, +0x2e9174a9, +0xa340152e, +0x8759f86e, +0x59e1f07c, +0x0247f95d, +0x59c3de3e, +0x5e28efa1, +0x7f54be9b, +0x28564ca8, +0xbdc0e2b2, +0xdaab2ec6, +0x63eaa02d, +0x22151871, +0xec6a99cf, +0x90de6a6e, +0x104b1a96, +0x81495f83, +0xbed747aa, +0xa8b327d2, +0xe31aed8f, +0xe35ad40c, +0x12e8a24f, +0xc62180ee, +0x9aec3a5c, +0x43f30053, +0xa631e521, +0x0f2ee065, +0x305b5fbf, +0x8073c437, +0xe7855966, +0x7babee89, +0xe94b331c, +0x243aed2e, +0x9bcacc3b, +0x0d835b50, +0x328dd8b8, +0x329d1623, +0xc6628a55, +0xfa22b75f, +0x3e50b698, +0x64068592, +0x752cf44e, +0xe950447d, +0xde0d264f, +0x645ba8f6, +0xa4ec59d6, +0x1cd1e085, +0xddcdee08, +0x671f3d44, +0x3213a918, +0x384b86f2, +0x1b7ce38d, +0x994c5a1a, +0x5d0e89c4, +0xa9df4390, +0x3dbeea3b, +0xc61be3f2, +0xae23ef6d, +0x9d309f2d, +0x6fc9ae0f, +0xa47c63c2, +0xbfbaf6dd, +0x5dca8ce3, +0xa5c24df7, +0xbe4f6751, +0x50965196, +0x7e01a727, +0x4a44c514, +0x06bcd7e2, +0xaac56abf, +0xf38ef686, +0x368253d0, +0x7a8b8596, +0x9c41e418, +0x5e876f65, +0x609c913b, +0xd38012c3, +0xa89dbb6c, +0x9476a65d, +0x5fad2c83, +0x45940320, +0xc53a5249, +0xd9f081d5, +0xe0065e2f, +0xb769c26e, +0x5d61c026, +0x89d91ee3, +0xc334977d, +0x237e294b, +0x9abf7592, +0x305800c1, +0xba5084a6, +0x90ce6f9d, +0x656a7f38, +0xf2e9076f, +0xc24131c8, +0x7b183623, +0x6d5a7c1e, +0xda7a847b, +0x1961fdb5, +0x4095d72f, +0x165fdd6d, +0xd1c8d390, +0xf5010355, +0x0a47ecea, +0xc8677a8d, +0x7ec70289, +0x7dd1ac4f, +0xb359c6cf, +0x7b8b3fac, +0xecc423b0, +0x097f4e8c, +0x25350063, +0x610f97a7, +0x47546a92, +0x3c815cf7, +0x359432f1, +0x729c7b4d, +0xe1965ae6, +0x3f222f56, +0x23a648c9, +0x875e56e1, +0x5b936815, +0x69da8130, +0x1bfcf858, +0x29c9134c, +0xb3a1d11f, +0xf6de1f6b, +0x9f089f43, +0xa5ccfdcd, +0xbbbec578, +0x1c12c419, +0x5edd44c9, +0x3350d30c, +0xd997e435, +0x7385848c, +0xccc6914c, +0x12fdc31f, +0x1a07f38f, +0x14e88fde, +0xfbdc33d9, +0x6397f021, +0x733d7cac, +0x5d836878, +0x05f7b0bb, +0xe62759e5, +0x98c76bb7, +0xb8baa3fb, +0xc26712be, +0xf50b3a10, +0x041050e0, +0x82f8fd48, +0x29d06b2c, +0xeea22b0c, +0x070d68f5, +0xfa7f2bd8, +0x7ef4cdbd, +0x697054b9, +0x3e500014, +0x720e9ecd, +0x7351efe3, +0x81aa8c49, +0x46eb0528, +0x5bc987ea, +0x6ac299ef, +0xe0a46527, +0xa942935c, +0xcffaaca7, +0x6a0cf6db, +0x8928aa93, +0xafb8e548, +0x0b00efe8, +0x2ac7f1e3, +0xd38516c1, +0x9e31df0c, +0x065cf5fc, +0x22e8c3f3, +0x5c46a153, +0xf208e124, +0xa6239ec2, +0x842f47d2, +0x6f3dd36b, +0xc3a5db5c, +0xebf43097, +0x6fd7139a, +0x286086c3, +0x6135e46b, +0x9f1c0250, +0xd7c3cb90, +0xec0ce072, +0xc454da71, +0x072fa37c, +0x66fee72c, +0x190d9d02, +0xd4dc5290, +0x8b96c2d0, +0xf481767b, +0xabeb4560, +0x7fd67a79, +0x9447b593, +0xfbefb9d6, +0xbbf6507a, +0x932252b7, +0x88385e19, +0x50c2fc7f, +0x108b9828, +0x80dc7773, +0x4412a38b, +0x86770c54, +0x71a2bb4b, +0x26744944, +0x07f60e0e, +0x2b870459, +0x95dd170e, +0x0d07e805, +0x3a20a820, +0x3e7b06d5, +0x35afb60a, +0x93c0a891, +0xb02aec62, +0x5b4feb0b, +0x6886f1e1, +0xdc037b2c, +0xbb1b67aa, +0x1554d640, +0x2c751a2d, +0xefa91d1a, +0x225e3c55, +0x124746e1, +0x03431e23, +0x0a097596, +0x65996e9c, +0xfa6798a5, +0x03fb50c6, +0x7e623f53, +0x069cc309, +0xd5180120, +0x16a3e3da, +0xd50bdc39, +0x7ff9ab3a, +0x76704f3d, +0x5337bb4e, +0x1f8d314b, +0x8272dd1e, +0x72e1badd, +0xb7e3ea55, +0x085a199e, +0x1517fab1, +0x70be848d, +0x109fcb56, +0xa42dbbe4, +0x4ff77c56, +0xf70e13eb, +0x25579238, +0x424b6cce, +0x4a562917, +0x03778a2d, +0x3fb04352, +0xbe69f827, +0x50fa6752, +0x1467809b, +0x51742ce0, +0x764ab8ba, +0x2bb820be, +0x7e7aee8f, +0x60349db7, +0xea01ab0e, +0xb2c57345, +0x5652e241, +0x2414992a, +0x09c152c8, +0xf40a4a3e, +0xa98a4bdc, +0x4c7c0d38, +0x4024feef, +0xfd95e9f4, +0x582fe867, +0x8efe422a, +0x14a8077b, +0xdb4756e8, +0x01835084, +0x534afa75, +0x5eb1907b, +0xf5bb8402, +0xa2795829, +0x493f1d66, +0xce675fcd, +0x1da55071, +0x523cd74c, +0x20cd3ae1, +0x1754bf11, +0x686e62b2, +0x52e2d0e9, +0xe7c54554, +0x0c6a7f78, +0x71caa31f, +0xc4e1ff21, +0x0c449e04, +0xb7f9c1c7, +0xc6dc32d3, +0x06e895ac, +0xd473c1c3, +0x5bbe945a, +0xe8fbe00f, +0x5d739135, +0xc5f7245b, +0xe8695de9, +0x83cc21bf, +0x1af54c3e, +0xcb8dc52e, +0x7b13cc75, +0x51a56023, +0x05b31609, +0x634e0471, +0x4fb1f9e5, +0xbc816bcd, +0xe0e613a2, +0x4f60c697, +0x0e3fd8b7, +0xc6811848, +0x1d60012c, +0xdab8dce4, +0xbc50cf26, +0x7021ef89, +0xd82f6d85, +0x8f6f6e58, +0x8f16d521, +0xd76ee926, +0xfe30dda1, +0x7f86c672, +0x54d5726e, +0x34767655, +0x9da213b0, +0x33cb82cf, +0xa463cb97, +0x1b694bd4, +0xdfbd6ce2, +0xe7a64f99, +0x30359b89, +0x2be3b60d, +0xcf692954, +0xc4677867, +0xcb9afa27, +0xad1a4972, +0x55cd31b9, +0xc2882402, +0x96386824, +0x3007cfab, +0x1d1d31f7, +0x3f73c899, +0xdd684a7a, +0xbf4dd6dc, +0x95a65fec, +0x50b8e6b9, +0xe84995db, +0xdade7ff2, +0xb9d673f3, +0x2dbf5777, +0x274963a5, +0xe55f5788, +0xe94c89ac, +0xd1d20eb1, +0x3293ac42, +0xa172ac40, +0xa8c27b84, +0x16893817, +0xa04a36de, +0x851ce09c, +0xde0d7896, +0xe7b258e5, +0x65c66076, +0x5d12f9d8, +0x577dab29, +0x3e9df102, +0x354af6f5, +0x29d1af79, +0x1dc47f22, +0xc55bea67, +0x5af79d76, +0x3a0fba3e, +0x8c06b657, +0x2270d5c8, +0x0134081a, +0x94e57e8c, +0xbd33965f, +0xa4f0900a, +0x70e8417d, +0x82eb496a, +0x02c354ef, +0xb2900fe8, +0x6bc32df0, +0x933171dc, +0x4734409b, +0xacf53361, +0x7b77aaad, +0x5b0c3176, +0x2a7dc96d, +0x066116b2, +0x781a708f, +0xcebb723b, +0x7b7d7dfe, +0x42440852, +0x82aeb573, +0xbb7d3423, +0xc8d5a94a, +0x1e14d9d2, +0x28ef1807, +0xc8da32c3, +0xd020aefa, +0x59f5744c, +0x8a7d0b36, +0x1ad2e5ab, +0x973d61e3, +0x86172061, +0x2e27eaf7, +0x21f29553, +0xb3ab2973, +0xdea5a361, +0xfed9d651, +0xaaf905d0, +0xc2352b4a, +0x21295d1f, +0x921d9ebe, +0x6aae8a0a, +0xc8089523, +0xd342b957, +0x3edfb932, +0x9ba57ef0, +0x9274aa4a, +0xf41e7425, +0xf17ffe4b, +0x3ccc2c99, +0x1fc495ac, +0xac767483, +0x9fff6974, +0xda55e68b, +0x4c26678f, +0x2f522b15, +0x27b09943, +0x4f40ba24, +0x75f160ce, +0xb5fb3b18, +0x297c3404, +0x2b965a3b, +0xaa44656f, +0xe2b86825, +0x9f32aca4, +0xe453b5b8, +0x1bbddc38, +0x040d28f5, +0xbc5eb23a, +0x4288c03d, +0xe18f2f72, +0x8169ecae, +0xcef466d6, +0x1f68b032, +0xff94a131, +0x0446c82e, +0x3295bd3b, +0xbc605b1c, +0x3d014b14, +0xe817115a, +0x78f04886, +0x06f254fe, +0x44b48d8e, +0x94732c0d, +0x3c7db191, +0xd1c70231, +0xb298d2b5, +0xac57aa25, +0x6ffeb86f, +0xacec435f, +0x8a75ad79, +0x8a2cc5cb, +0x24b3cccd, +0xde475bbf, +0x8e70dabb, +0x2e5fddf2, +0x53bdb21f, +0x0bb49031, +0x4ae69983, +0x263f18cd, +0xa5979975, +0xfab22e86, +0x6a3f3482, +0x4480fd93, +0x4924fa5f, +0x1cb12e49, +0x1c4c185b, +0x12a0cda3, +0xbc709e89, +0x6ee2486e, +0xb76a93a0, +0x21d6ef1a, +0xd98aa10e, +0x4b8d2394, +0xa1a829c4, +0xe120c219, +0xd89d2ca9, +0x4f90dd91, +0x41f93e65, +0x9d386a84, +0xc7ddc29d, +0xd5eaf025, +0xab03821e, +0x3f9b3a42, +0x39669aa6, +0x68fe0e56, +0xd67e24b3, +0x78ad4792, +0x7a3c9fcc, +0x1997f3be, +0xb79c26c6, +0xa34979c1, +0x5beeaa94, +0x337a2fad, +0xcf32db84, +0x87a71e28, +0x7242f8de, +0xcfabacc1, +0x0b557c1c, +0x2f3b6ed0, +0x61574fb9, +0x79dd5d7e, +0x716f924e, +0x9e0a63e5, +0x09ac0bcf, +0x7f3b9e76, +0x62a09271, +0xcbf1eded, +0x049828b0, +0x72352420, +0x2e0b044f, +0x269b9539, +0x1e059e21, +0x508ad396, +0x645c1c45, +0x69b78196, +0xcd8ea8b1, +0xfb02addd, +0x75b2989a, +0x5ccdee4a, +0xabd283a0, +0xa5616de3, +0xaeb7f54a, +0xdd19e6f6, +0xd94699e9, +0x5865cd34, +0x2416dfa0, +0x5b45f99f, +0x7989eb04, +0x266a5546, +0x8aeb734c, +0x57123b86, +0xbf3fdbb1, +0xea72b3d4, +0x89394ca8, +0x72b4eb2e, +0xdf06e48c, +0x8558ea21, +0x3ee3945c, +0x8b54e77c, +0xb3d4c405, +0x53a64ff6, +0x5e2f2f37, +0xa4a8d61a, +0x941bc5f1, +0xc6cdf32f, +0x3972c503, +0x944e6824, +0xae9f1502, +0xd62f9b99, +0xa981e082, +0xcb2cb499, +0xebf83a6d, +0x8baa0c3d, +0xa9a25cc4, +0x851182a6, +0xdde19098, +0x214b7024, +0xb71908c4, +0xf843f17d, +0x5f0bbb62, +0xccd6dc82, +0x09543c90, +0xae54582c, +0x4c4a0005, +0xbab898df, +0xe58b0841, +0x8702e8fe, +0x2d223316, +0xe9585c87, +0x4d201d93, +0x06dc4b2f, +0x9475e659, +0x7fde9102, +0xd345723f, +0xb2655763, +0x2eb59866, +0xedf5f4ea, +0xe501c9d7, +0x7ad661e5, +0x9b3136e4, +0xe25934ac, +0x7422ad4c, +0x9b617d4d, +0x56b0ebf2, +0xb69e3211, +0x9ae8add1, +0x9a89f146, +0x507657c0, +0x2fd2b40f, +0xc12c19b1, +0x55a9731c, +0x5bdb67a5, +0xdc5197a9, +0x550a1b5f, +0x2eedbfb6, +0x69c542e1, +0x990fd178, +0x82b7fb98, +0x4462209a, +0xfb2d7021, +0xf4bfd2a9, +0x9e01ffc5, +0x510767a6, +0x55454ba7, +0xa0190600, +0x63895e26, +0x3eed3e0b, +0xc88ad8a4, +0x403f7ac7, +0xedb7d406, +0x8ec8f594, +0xa32652cf, +0xb9e30f58, +0xaddd6bc8, +0x024baa37, +0x0abc4b8f, +0xd4bbd7e6, +0xd5d1c6c9, +0xbdf93dd2, +0x731a9501, +0xc02fd21a, +0xce45c6c7, +0xc12daead, +0x813933fe, +0x94922f19, +0x8e5353b1, +0x4c6902c1, +0xc88ad962, +0xb356748e, +0x6c46bbc9, +0xe110109f, +0x17ebee08, +0x8620553b, +0x40220d1f, +0xbc283a7b, +0xe6e13815, +0x1e262a27, +0x5addf07a, +0xf153a5eb, +0x076b567c, +0x34e82530, +0xc519569d, +0x42431d10, +0x1a085d7d, +0xee58069b, +0xcaffcb07, +0xa99f532a, +0x79fb39f2, +0xde7ac5ed, +0x5db3b043, +0xa952e064, +0x07f7c2bb, +0x27d38994, +0x271b4b47, +0xfad5465f, +0x9923671a, +0x9ad5de30, +0xaa13ff33, +0xf687d1b1, +0xa6dcb74b, +0x98fedb6a, +0x8093a888, +0xdc491928, +0x58bb5ff2, +0xc4550f9a, +0x4e83aa74, +0x87b72cf3, +0x692927d2, +0xeab11d41, +0xe07d3ba1, +0xabf679ec, +0x238aa49d, +0x620f6146, +0xe3c998cf, +0x1e39268b, +0x44063c3e, +0x5e796d0c, +0x9c3bda47, +0x60cca22e, +0xcdc36456, +0x742690cb, +0x89144785, +0x60950e85, +0xcfdcc165, +0x36c409ca, +0x9786ba50, +0x6ad6af23, +0x4bcaa97b, +0x0f2e3dce, +0xd2ebd83a, +0xcc92df68, +0xa4cf91e4, +0x20a3bee5, +0x1ce487ed, +0x92a4ae70, +0xf1631397, +0xc8e7c35a, +0xc8e74ed1, +0xb6d386a8, +0xc2a60742, +0x593d7a0f, +0xfff0d2bf, +0x42744524, +0x701828dd, +0xc96a471b, +0xdc432aa4, +0xf933cd56, +0x9dd5ed7f, +0xab195400, +0x2f929ffe, +0xc7035a37, +0x4b1260b9, +0x19b6444c, +0x4be8ac18, +0x2778aa3f, +0x7927a778, +0x4e9cbe1b, +0x2f24f8a3, +0xa963fcb1, +0xb1e57bbd, +0x094785de, +0x35183759, +0xeadd86ee, +0xd8cd0f90, +0x9ff4c404, +0x495b27d5, +0x195e5b44, +0x12c2faed, +0xbc72de30, +0xf16d6b4b, +0x563dba43, +0x32dd60bb, +0xde1b52dd, +0xf9f7c735, +0xa4b7c810, +0x2a379685, +0xcbf3bf05, +0x6de6fc81, +0x0fe91ded, +0xaab39d40, +0x90a6acaf, +0x14bb42c7, +0xb37e20e7, +0x2240a600, +0xab6f853f, +0x7c290bb1, +0xdf06f4e9, +0x9c35a83b, +0x6f59fd13, +0x892782bb, +0x71addb98, +0x12405139, +0x4b511edc, +0x57432294, +0x1b61511d, +0xe0b49aa1, +0x0a1f35cb, +0x70284150, +0xb4ff79b3, +0x904ab903, +0x2cb2ed33, +0x5bb7ac9a, +0x6e99ff53, +0x10891968, +0x43af9f26, +0x1c8d1b3f, +0x93c54b34, +0x5bccb8bf, +0x19846a8a, +0x9651441c, +0x31db6f4e, +0x17ddbb16, +0x2381fc02, +0xb7807351, +0x0bca4c7f, +0xcf21a1b9, +0xe93cc8fc, +0xd7115172, +0xd61a3797, +0x690e2514, +0x52710188, +0xa5495827, +0x45891a77, +0x7830887c, +0xb0e070a7, +0x8323f6bf, +0x159c8c67, +0xf89845c9, +0x0b456fdb, +0xf7536b15, +0x76dff6d3, +0x9413535a, +0x88af1d89, +0x07ccd5f0, +0xaf635760, +0xcd7696e8, +0xd043eb7b, +0xd6bb1392, +0xb3ff1987, +0xe6b0f727, +0xdd954ba3, +0xed4e451a, +0xc8fed300, +0xb77a1843, +0x0a21de50, +0xc15c14ca, +0x23d553f7, +0x9e726249, +0x92f72cc1, +0x2319bc62, +0x2959605e, +0xfae0e1e4, +0xdbd99912, +0xf5d4da83, +0x458f7014, +0xe5e87d0d, +0xfb23850d, +0xcdb18d7f, +0x025e7d2a, +0x57d15b61, +0x0997ede8, +0x331d9950, +0xd2a2c68d, +0x1e8bfc09, +0xa2475100, +0x47164597, +0x78cbd6f7, +0x4a9de76c, +0xa4347b0f, +0x6abda86f, +0xed9b5cde, +0xd958ef9e, +0x1d9b1f40, +0xb3d42f3c, +0x366eff83, +0x5e91f50f, +0xaa00c01a, +0xb155a4be, +0xc3723042, +0x9af53783, +0xa1225a5d, +0x659b1fde, +0x8a0ae3c0, +0xaa66c193, +0x05d342cd, +0x88a86bc5, +0x59a7d873, +0x38df2d35, +0xdc9d0465, +0x260bfd42, +0xc2e63d63, +0x0662ea29, +0xf12fb49c, +0x45b3131e, +0xd4d71d60, +0x61d3d787, +0x5e646c3f, +0x9cd16252, +0xe7a8cdaf, +0x53893eae, +0xcf21f30f, +0x45504b48, +0x036d7441, +0x4386bae7, +0x6aa6effa, +0x54b40ca3, +0xf5870ad0, +0x3fa8777c, +0xe2d0ab3d, +0x9d773f4b, +0xd7f15f44, +0x74ffacd1, +0xeb39f3e8, +0x59ab9057, +0x2dbf8901, +0x8e70f59a, +0x4f5c3215, +0x36cbb5be, +0x0333ec30, +0x1a3fb74d, +0xf46d0a19, +0x38ae3ceb, +0x70bfcba3, +0x09c0dcbb, +0x5611e713, +0x2f779fea, +0x58571b1c, +0x82d255a6, +0x569bcad3, +0xcaee271f, +0x7e5e13fe, +0xd812a572, +0x1a9ea89a, +0xb57e0a70, +0x0cad7a17, +0x906c65d1, +0xf6c51387, +0x6b653c8f, +0x16f7ddc5, +0x30db7df4, +0x030e0491, +0x8a789c13, +0xcc1cc33c, +0xf8f6ac62, +0x4748b664, +0xf31554eb, +0x215fe389, +0x922153cf, +0x0e39eb7e, +0xfbaa9644, +0x3ed06c39, +0xc9e8a66d, +0x1106c38c, +0xe0a7bbaf, +0x488abb23, +0x4bd83111, +0xac13dfd3, +0x11e36837, +0x08f1e1a9, +0xfea1fbe5, +0x2d9262ce, +0x657e8a59, +0x1fb6ddac, +0x4998a0d6, +0x865a2335, +0xb352f6dc, +0x1231bb19, +0xed31ea60, +0xb51f7fd7, +0x0d36b616, +0xddf481f4, +0x8307a1b0, +0xbd96d633, +0x0cce8532, +0x151e9750, +0x252c4fd9, +0xf120998f, +0x0876c17a, +0x59306a4d, +0xb1e11292, +0xf06876e1, +0xe316196e, +0x721d9385, +0x70af11c1, +0xe174f52a, +0x65360b00, +0x54d70b47, +0xc7ff7289, +0x3f9daf26, +0xe4e87e48, +0x219e50a1, +0xfc5d22f6, +0x456c2e1b, +0x373475ec, +0x4fe2e50a, +0xce029131, +0x59649fcb, +0x5447f3ef, +0x7f885f20, +0x79370f9c, +0xe53b9bf3, +0x2b626669, +0x7a4ed7dc, +0x1e51d0d8, +0x1664dec9, +0x79a49c1f, +0xbdd7b686, +0x795f0255, +0x057736aa, +0xe49e634a, +0x511f7090, +0x2eaa108c, +0x9ae321b4, +0xa5ae3545, +0x67defa01, +0x506dde4a, +0xed3cbcc9, +0x4c016b29, +0x7c604c71, +0x43720f91, +0xdbfcf099, +0xf4597225, +0xa05039cb, +0xd7aa8678, +0x17c54109, +0x4c993613, +0x8b4d15c1, +0xc034f517, +0xbc75dc15, +0xfadbc8ad, +0x998713f4, +0x1be39282, +0x4c0d2f75, +0xab3f2b39, +0x014e200d, +0xe627e60c, +0x891098c0, +0x9ae9325f, +0xfa1ef42b, +0xd7512565, +0x1b4885cc, +0x2a983aba, +0x1b654ceb, +0x89bd12f2, +0x3e9a5d5f, +0x923095f9, +0x98471631, +0xaa3e28cb, +0x6bade281, +0x861dc63f, +0x4c712e6d, +0x644caf30, +0x5cd282ee, +0x546218f0, +0x1bc00161, +0xcbdb1880, +0x9e7dab53, +0x1514cf54, +0x57297f8a, +0x24f2cd50, +0x7492a1e0, +0x147dfdd3, +0x4030f389, +0x251ea095, +0x855673bd, +0x2db9000e, +0xcbf0735a, +0x6e811038, +0x7546d536, +0x4a38f70e, +0x9f1ba2d9, +0x5db5418b, +0x13804eed, +0xdeeec29b, +0xbc654f28, +0x650463c9, +0x33361ab0, +0x085831d8, +0xbd783ae2, +0x1a85218c, +0x6f244b06, +0xd838fcde, +0x333ca222, +0xa1859b79, +0xde21145b, +0xd0b6c5cd, +0xdb432d27, +0xccb5def7, +0xb503f867, +0x08e01dde, +0x7f745249, +0xc6c4b5ad, +0x826b2547, +0xb7a1a2bd, +0x24a0303d, +0xa371c688, +0xccd84aba, +0xb027d367, +0x51ba461e, +0x212ddf69, +0x93be7b81, +0x0987a880, +0xf4306c59, +0x1d80a0a4, +0x98f0f68b, +0xac0aae7e, +0x9a015f27, +0x4cd0ac5f, +0x600e5dde, +0x3d379f4c, +0x05494040, +0x5b72633b, +0x27c66166, +0xa70ef185, +0x0c85a162, +0x81940fee, +0x186ff972, +0xf1847095, +0x01ae42fc, +0x6c0dfcd4, +0x90278ba0, +0xbc51331d, +0xb900d524, +0x51cf1cfb, +0x27c35f7d, +0x157f0dce, +0x0aac145b, +0xbc77d8ca, +0x956718e0, +0xeead3591, +0x3377ec3c, +0x394d3263, +0x072ec363, +0x8d9b06f1, +0x8e3063c1, +0xcdab70a0, +0xf9c9dab8, +0xa253fb44, +0x4e67d896, +0x1d4536b5, +0x1473cbb7, +0xdb2d1ca6, +0x04b546d0, +0x5d73dcd5, +0x682cb6d3, +0x7474c7ab, +0xb5019d72, +0xfced0640, +0x2640c792, +0x72fb7c30, +0xa2afb7da, +0xc9d4ecf5, +0x763eb11c, +0xe08c0b34, +0xde5b04a6, +0x319216e1, +0x641f70fd, +0xe643f6f5, +0x8a9b25b3, +0x832b85bc, +0x0a0800b8, +0x50a3a5bb, +0x7c3bb671, +0x8a318d7e, +0x969781df, +0xe7129618, +0xd836e271, +0x06c6155c, +0xf89fb8af, +0x30a0f233, +0x7561b151, +0x99e8b84b, +0x0f9b4b81, +0xae3319e7, +0xb2fed8f9, +0x4b83b724, +0xaa816eca, +0xceeb2488, +0x7293468b, +0x91bc3171, +0x6ee95127, +0xc04ceab6, +0x0fefe497, +0xd2417234, +0x74c9392b, +0x5d45dc76, +0x7ae1d16e, +0xb2a00f7e, +0x72640388, +0x67464e9d, +0x0af5afe8, +0xc9b83821, +0x05f4f8d6, +0x16ca64e5, +0xd9840d39, +0x1101f439, +0x3ba670bb, +0x8b79cd2f, +0x0b6558ae, +0x0679f98d, +0x93cd8c7b, +0x2d6f5740, +0x7de62667, +0x32184108, +0x870e166e, +0xb20a95d6, +0x08918260, +0x2e2fef86, +0x60ed5aff, +0xe16b1be5, +0xb2abc75b, +0xacd93de6, +0xc59ffbce, +0xff5cbd06, +0x5456fa3e, +0x4e5cae7e, +0x25d0c292, +0x8f741ebe, +0x472a9663, +0x1e59ad2a, +0x4221cf6f, +0x120f600d, +0x2a9aef29, +0x4faa0301, +0x514b13ee, +0x4184619f, +0x1c729f43, +0x2a3efa8c, +0x88bc4c75, +0x69bb3fd1, +0xabcbbd29, +0xdc23e3f5, +0x30fad2fa, +0x5b1975b6, +0xf85cde5a, +0xeecee496, +0x51ac888b, +0xc48bce9c, +0xc8782058, +0x1694dda2, +0x3b050240, +0x94dceb95, +0x735b3ecc, +0xa9e686e3, +0xc2b659a9, +0xd8415c10, +0xe3d48749, +0xef547def, +0x7c5f156a, +0xb1588364, +0xd87ad49c, +0xb6daa014, +0x6d96de07, +0xcefb8d21, +0x81bb092b, +0xfab64359, +0xd1e24cfc, +0x247df9ab, +0x5c95b095, +0x0c4b858f, +0x42e41f96, +0xc19a8824, +0xb1680107, +0x2edc742b, +0xa3dcb1ed, +0xb75008f6, +0xd00add8b, +0x42f301cf, +0x027b7bce, +0xaefcd0a4, +0xb7ed9ffa, +0xc251e81c, +0xe2da64a4, +0x4926fc3d, +0x0caafcb1, +0x5cfc431c, +0xfc430d3f, +0x015a6327, +0x612899f7, +0x344b5eec, +0xcade9b16, +0xebbf14f5, +0x9922e84e, +0xbd6dedaa, +0x9cb05715, +0xecb5868c, +0x6bedbac1, +0x4af45ff1, +0x7c4061d6, +0x90da8c6b, +0x8c445b64, +0xf4d6183c, +0x2f1fce06, +0x181d8479, +0xd99e5b57, +0x0f6a06ae, +0x13cecf52, +0x12cfa95d, +0x2a2fec1c, +0x2e1366dc, +0xbd465007, +0x91e3b0d5, +0x28a6ec70, +0xf5043b38, +0x9470295d, +0x36f2d03d, +0xb6bc55fc, +0xc8746c46, +0x830a6e9e, +0xb3506ab3, +0x6183976b, +0x73165e5b, +0xf277a519, +0x89c088df, +0x9e727468, +0x3bc79f0c, +0x545a42f1, +0x905fa358, +0x159e3c49, +0xf06e0469, +0xa8372ab6, +0xb0d159bd, +0x63b3898c, +0xdac3adca, +0x81b3fff9, +0x1dd9b98c, +0xc6fd4277, +0x7b2c079a, +0xbec086aa, +0x5280a11c, +0x0ccf74d2, +0xa77ae8e0, +0x892846c7, +0xf6071228, +0x7e52a661, +0xf2f5099c, +0x11cb2c1a, +0xe8c12ad4, +0xd93842d3, +0x18643578, +0x89927831, +0xe6078bbc, +0x0c470fb7, +0x6d948254, +0x08d26156, +0xa12d2c50, +0x0b8cefe6, +0x8cf2db61, +0xb2e4746b, +0x3cb6f324, +0xb8f36b0d, +0x43db72a7, +0x084fce21, +0x163b9a37, +0xd50af7cd, +0x2c9c111b, +0x83f24eb0, +0xcff24f10, +0x30a314b7, +0xb7fb0e1f, +0x78083b79, +0x0b9290e5, +0x660f41cb, +0x621b31dc, +0xde6ad93a, +0x96d28665, +0xfb9387f1, +0x7c71bf8b, +0xc0a098a3, +0x01bafb5b, +0x0bc668bb, +0x95f469d7, +0x761b83ce, +0xb672f285, +0x05374fb3, +0x104bb909, +0x969a216d, +0x86ba234b, +0xd1ac6eb2, +0x37b6cf73, +0x3aaf4759, +0xe4c4a020, +0xdd5f0faa, +0x4ac9b549, +0x96ed5853, +0xbd8849db, +0x1fdbfe17, +0x14554df8, +0xe6b5e5b4, +0x1a01502d, +0x3d3dca3d, +0xba7ba3eb, +0x5c1c73c7, +0x89490173, +0x2dcf2a8c, +0x67d03f6e, +0xd6d0983d, +0x9fe15372, +0x9b85f7eb, +0x5a0b8314, +0x57257bc8, +0x046bc00d, +0x017f8e0a, +0x2917f751, +0xfe6f7a90, +0x8ff3bea4, +0xf97b10b9, +0x415ad376, +0x9556583a, +0x3cd21629, +0x4121f960, +0x5d1759c4, +0x62218599, +0x74f09e97, +0xcbeca1c9, +0x74143a60, +0x487f14fc, +0x6d703836, +0xcf12e352, +0x60caf110, +0x6b884026, +0x72221a7a, +0x8454850b, +0x1c1bdc94, +0xc2946efe, +0xd631147c, +0x011c1547, +0x7303a97f, +0x8ea2691a, +0xce30fdf5, +0x72e357d6, +0x2f4e481e, +0x603bec20, +0xcd68ddc7, +0xec237513, +0x8b61524b, +0xa75fcd6d, +0x880e5ff7, +0xeb18e3d5, +0xf3952b26, +0x647d85ea, +0xe0f32fc4, +0x9f9f101f, +0x467bb92e, +0x425ad309, +0x7ac79b68, +0x44141e1c, +0xdee509dd, +0xf19311fb, +0x42ad7b50, +0xdfffbbec, +0x16f01a27, +0x88716fb5, +0x4a168d33, +0xdab1db57, +0x2168b417, +0x33533794, +0x9c1ce44d, +0xf85edf33, +0xade64994, +0x823f6966, +0x17c88e67, +0x85ce352c, +0xd4c7aae3, +0x34919132, +0xd730bcf4, +0xfc8528b6, +0xb90bded3, +0x72d5374d, +0xc4d91b7d, +0xbc775491, +0x2a0879ae, +0x3c796b47, +0xda2b4ca9, +0x396d0959, +0x8fba7225, +0xdceb83dd, +0xed8dd9c9, +0x07576991, +0x9eaa97bb, +0x4262b53c, +0x4b45eee7, +0x2222aec5, +0x75a23ecf, +0xbcaa72ba, +0x22384675, +0x17124455, +0x8c00f27e, +0xe1ea1bb4, +0xb21bfde1, +0x74330ef2, +0x56ee15d7, +0xd5c7115a, +0xb77dbde4, +0x74b45b68, +0xf9d45a0c, +0x21ead27f, +0x3a97daa9, +0x68b65ace, +0x0fcf59e8, +0x6e676e0e, +0x5663c51d, +0x120cb352, +0x728c32a6, +0x000b8a5a, +0x6d088fe4, +0xdec6c190, +0xc681a3be, +0x67d94fbd, +0xa9129b03, +0x0d4436d1, +0xb03cc465, +0xbcbf7368, +0x2e5274e1, +0xed63a072, +0xffe0a4b8, +0xb42588ea, +0x18e3f012, +0x96bcc486, +0x8635b33e, +0xb917bf17, +0x509aa6d2, +0xc846bc0a, +0x4ae99814, +0x30f5d804, +0xbd27d949, +0xa03b8d43, +0xfc3ead4c, +0xc19d3408, +0x89075a02, +0x106a0c7e, +0xe5fed0ab, +0x783c9ae1, +0x27ec700e, +0xdd19a908, +0x9032db77, +0xeae6b00e, +0x17d0df8e, +0xaa835299, +0x4b878833, +0x8b762bdc, +0x2073bd41, +0x64f7edf6, +0xf0972926, +0xf7ff08ae, +0xfa82abe5, +0xc0d3f5b7, +0xc55e35f1, +0x5bf724b9, +0x8e814cf5, +0x313b3f35, +0x67de3485, +0xb1dc1398, +0x527c59e6, +0x9513b1cb, +0x13746831, +0xfad97757, +0x63a65d63, +0xa28a6047, +0x80713a3b, +0x0711a136, +0x843bbe1c, +0x2cc2f175, +0x942bb350, +0x27ccb27f, +0x31635b94, +0x929974e3, +0xc09453bf, +0xcaf1142d, +0x4e6ecb96, +0xac3d5bbf, +0x9e4b8604, +0x2b7aa80f, +0xf97fef9e, +0xad42f677, +0x317fe753, +0x6820426d, +0xe6922406, +0xe8aacde7, +0x65f9044b, +0x13fa2f21, +0x17748333, +0x1685bf36, +0xe37faefb, +0xd523e0b7, +0x66dc68ff, +0x9061e136, +0x2750adf3, +0xd3620f70, +0xd3837751, +0x72aff8c6, +0x0d70a163, +0x65523a9a, +0x9ac7d7e9, +0xb1eafdd3, +0xdf3b1438, +0x302667c2, +0xa5e3e196, +0xdde40a42, +0xdf21834f, +0x34be121f, +0xf675e77b, +0x96413b9f, +0x1749b48e, +0x9f38bf3d, +0x7a0b7a5c, +0x5846e1b4, +0xbbfb0dcd, +0x401faf99, +0x5a18d546, +0xcc888fed, +0x93424a74, +0x1b9fd559, +0x288e4007, +0x3687bf45, +0xb56f5345, +0x931a41b0, +0x3b2efae0, +0x37e7187c, +0xf39ca728, +0x1902fd57, +0x4d8c404f, +0x9812aa4b, +0x7c4fa669, +0x0d13f3d9, +0x5e112593, +0x70c88729, +0xed61abab, +0xa4474a6c, +0x6792e078, +0x82edc6fe, +0x263206f3, +0xd5463816, +0xced91802, +0xb498c1d1, +0x25acf984, +0xa3f5ed51, +0x86842eb8, +0x670e13f3, +0x1bc47eea, +0x32096349, +0x78f600b7, +0x0a21a191, +0xc7f6f066, +0x83d85562, +0xe5b1a0e9, +0x3d8685f2, +0x6d881949, +0x0898b920, +0xa7acd9f5, +0x873f362d, +0x6667db3e, +0x29616fea, +0x78413c93, +0x0a7c7c91, +0x865e3ec9, +0x5f63c5f1, +0x7da13a8f, +0x40f1e86a, +0xc633b559, +0xf0d3584c, +0x289e6007, +0xeb0b87a2, +0x12f07cea, +0x9d488617, +0xb10bea0a, +0x2fcc8fdb, +0x668aa4f6, +0x16b5ca8e, +0x46162f6f, +0x1a1f8e0f, +0x9ccba0a9, +0x84db2f5b, +0x1f362ed5, +0xc660e800, +0xfbe28f03, +0xad203eef, +0x2b1a815c, +0x85c96916, +0x92492037, +0x637a967a, +0x90ee8dda, +0x3fea1de6, +0x32bb02d6, +0x81d201ae, +0x8b72b800, +0x32444386, +0x1e28dbdd, +0x820ac306, +0x34b2a437, +0xb3add414, +0xca013f1b, +0x2663cd89, +0x5f2affa2, +0xbb0ef3d5, +0x3a0ca117, +0x6174e8fc, +0x66b09d16, +0xdaddbebb, +0x7b4f70e1, +0x5ecf4b21, +0x895c11b9, +0x3bd3c8ca, +0x14ba5c00, +0x0214696a, +0x990916d7, +0x992efaee, +0x7c4ebac8, +0x7da48397, +0xdcdfde04, +0xc2f4fbac, +0x2a49f4c7, +0x3ed92bbe, +0x1a2567a9, +0xe7286df3, +0x38edbe88, +0x3f076952, +0xe7a1b9a5, +0x1ce4f06f, +0x765a9d10, +0xe91f2989, +0x8f6abfd4, +0x822d93aa, +0x9024cb87, +0x359c13e0, +0xa7b6591a, +0xf486c7c0, +0x869cdfe1, +0xc922923f, +0xcce567a4, +0x00207b8b, +0x4bc842bd, +0xc333c464, +0x029b8912, +0x017b146d, +0x0cdafe66, +0xadf2b864, +0x9f9f3523, +0x073dfd81, +0xddd18c6c, +0x04319ba4, +0x4646dc66, +0xdad72fee, +0xd81ed522, +0x1fc7a293, +0xabc8a9db, +0x4b7dd0a2, +0x6912a520, +0x611b52d9, +0xbd90c82c, +0xf029e77c, +0x85b32295, +0x58148f38, +0x29367a27, +0xf0a9d0a4, +0xb724fba0, +0xba2009ab, +0x4a5176d8, +0x91f52cb2, +0x368a7432, +0x6afc878a, +0x1b9b3b69, +0xa67ff022, +0x4a6d53e0, +0xc4c13a6e, +0x14411edc, +0xfb37ebd2, +0xedac5af5, +0xa286d9d4, +0x3abbf02b, +0x38b6e0d9, +0xe626d493, +0x699abf8c, +0xc20c8d06, +0xf14529e3, +0x9ec3bcc6, +0x6ab8082c, +0x582a64a0, +0x8a0120ab, +0x1cf8cb94, +0x367956ee, +0xf3c5c8a9, +0x09c3e844, +0x923c474e, +0xb0f7fad8, +0x1762c6f6, +0xbaa4eb75, +0x9e4104fb, +0x1b359a44, +0x163810fa, +0x5f9ebfa4, +0x6bf7b72c, +0x2ffbede5, +0xe5c013dc, +0xe0ccd47b, +0xd7c5937f, +0x8ff257d9, +0xe0490224, +0x89360deb, +0xadb380d3, +0x192cfb69, +0xb72eba01, +0x68084eee, +0xd66a7ad4, +0xa6243778, +0x825440dc, +0x09c799eb, +0xca1bbe8c, +0xf3c1cc3c, +0xac6e656b, +0x1ebcc6a6, +0xefb8f359, +0x1b10b462, +0x22d353b8, +0xc5df0aaa, +0xa363fbcd, +0xebf312c3, +0x36bd2488, +0x8de36b4c, +0x4f01c74a, +0x82e6d197, +0x3829a84a, +0x9e43954c, +0x31e95827, +0x4a5a20a0, +0x8bc919d8, +0x09a1d073, +0xd0b27952, +0x088a0f24, +0x4cbf4d32, +0xf956f6d1, +0xc934ca96, +0xa784b3d1, +0x20d0a06c, +0xc18c6af1, +0xedbdebb0, +0xa8e06fb9, +0x9020bcfa, +0xc0421afa, +0x21a14b79, +0x4b3b70b8, +0x4e6d9f79, +0x957fda6a, +0x34949d83, +0xc47ab4e6, +0x659a42fd, +0x56848e19, +0xe1a87533, +0x65373e30, +0xa31eff62, +0x212715d8, +0x0ad6a9bc, +0x59b86a17, +0x01e73725, +0x6e3e54fa, +0x719a3c51, +0x598abd05, +0x44b22c59, +0x57b16f4f, +0xaf895d89, +0xf20d4a3e, +0xf5b69fe9, +0x94004a77, +0x66b4e3d6, +0x71825483, +0x25efb098, +0xd5a6a33c, +0x5ff94df1, +0x260d4edd, +0x91b18727, +0x6f3baa70, +0x3dedea64, +0xa642f541, +0x48329694, +0x90505b57, +0x3313d7ba, +0x1701e531, +0x4e959b53, +0xfd3158df, +0xb6796fc8, +0x61ec1cf5, +0x30db600d, +0x652985f2, +0x5d7e9fd1, +0x3e8f769d, +0xdff53b67, +0xb5c12c5f, +0x6fb415b4, +0x5c7785dd, +0x86b944e2, +0xbe78bdd0, +0xf5b01c1f, +0xf2c01b13, +0x14f7b124, +0xfefb5325, +0xda1491fb, +0x6d59d40a, +0x2b731f84, +0x39a7ecb4, +0x732c8c75, +0xd6b754dd, +0x55c93866, +0x88516f12, +0x84c47191, +0x8ac08049, +0x414073ce, +0xe89fac25, +0x1595d8c8, +0x6636787a, +0x2425e4ac, +0xed8b9ed3, +0xf0455fb9, +0x83930536, +0x7ad0e9e7, +0x76509edf, +0xc2e132ed, +0x7547d2f5, +0x61996f9f, +0x8d92d653, +0x618cbf7a, +0xf4391ee4, +0xcf40d368, +0x86905518, +0xd8b86e8a, +0xa302491b, +0x51f361bd, +0x70f3f495, +0x742bdbdd, +0xb50dede2, +0xb9c55d72, +0xf6d766cd, +0xc1d87429, +0x011e01a6, +0xc190bfb8, +0x3e4d5d09, +0x6705fc36, +0x8983d741, +0x2a72f098, +0xd528d7ec, +0x34a4efc1, +0x5840066c, +0x7ad28622, +0xa0e150da, +0x5fc56747, +0x937670e0, +0x657aaf6e, +0x4358e079, +0x05ad4669, +0x16b11767, +0x0dfca4d1, +0x7395def0, +0x44e0c9de, +0xca0dbe3d, +0x7983f813, +0xda69e193, +0x2768606f, +0x0cc96ed2, +0xd11754b6, +0x0c81eacb, +0x1d3e91f8, +0xd6c3bfc0, +0x313fb4cf, +0x10533d2e, +0x40b22280, +0xc934f6f6, +0x18f75b4f, +0x1c728e3d, +0xe5f58061, +0x5e359727, +0x6a624a89, +0x743d0175, +0xb6c1a7ff, +0xc033ee5f, +0x6a9f07d9, +0x4e48125a, +0x77d122a1, +0x353acc03, +0xf0f86c21, +0x484687f7, +0xfe6f74ed, +0xc5a85672, +0x7e518fa1, +0x2b01253b, +0x54d6540d, +0x2a45c5a1, +0x7d22c6f3, +0xed801ed7, +0x5a90a4ec, +0x7624477b, +0x83df6028, +0x3ab6d5c7, +0xe073632d, +0xdd6856b0, +0x9b5fd52b, +0xc325bb7f, +0x9520a04a, +0x5752e896, +0xfe322571, +0xe4bed7a3, +0xbc796900, +0x86231dca, +0xa1032581, +0xc45d172e, +0xa598f63b, +0x3b45dc91, +0xe2927a63, +0xf9d16d9a, +0x4c824cf9, +0x9b789ea8, +0xb88272e7, +0x334e1169, +0x38d515c4, +0xd0632f12, +0x1b83261a, +0x11d374c1, +0x312d6b69, +0x0698d75e, +0x48331afe, +0x2f32bff1, +0x81dc79d7, +0x2d382903, +0x5f896827, +0x9a202192, +0x7f561ec4, +0xd807d340, +0x8e4cebc9, +0x39a0dac2, +0xa9a7b674, +0x62d72c00, +0x7cc0210f, +0x34ad7e5c, +0x3304749d, +0xb3dfb732, +0x6bbcf2b2, +0xbb87f9c0, +0xbee2d7f6, +0x1baf27ed, +0x97fa2177, +0x05dc8295, +0xc59e795e, +0x6b4ea4b5, +0x23e55e16, +0x71a517a2, +0xd0ed383c, +0xff653303, +0xbdc9fdff, +0x43e586ae, +0x25624f65, +0x746613fa, +0x1cd5d9a2, +0x607f5f99, +0x89285355, +0xdff0c9b9, +0x6fc71b79, +0xda14f572, +0xf0ef6d20, +0x89dbeff8, +0x1dde7a25, +0x95dd2225, +0x0f2a587f, +0xbe661576, +0xf8325d85, +0x15828432, +0xf6a9a546, +0xc3ffc812, +0xa78838d0, +0xa236e484, +0xe9863aa8, +0x478aeb1c, +0xdfb8a0e3, +0xf947e3d3, +0xdbdc761d, +0x6372bc94, +0xe442b915, +0x582efb31, +0x147b129b, +0x9264a0d7, +0x89cdb677, +0x89df9232, +0x5860c199, +0x9d365a36, +0xb15571df, +0x7c11c64b, +0x3e698d05, +0xfa5b32e9, +0xd3a934e7, +0x032b3319, +0x62f52af1, +0xbc57874f, +0x9d814a24, +0x03cfcbd7, +0x06ff8cb6, +0x7d10e335, +0xf5e51d19, +0x59834681, +0xe51a2c6c, +0xfa944ee9, +0xc2004ccd, +0x20d2c68b, +0x55449eb3, +0x678f34b3, +0x7ff7de93, +0x0c0f83ff, +0x01a090be, +0x551e438d, +0xa1fef941, +0x9f0c81e6, +0x37221df9, +0xcfafa1a7, +0x21d5f1da, +0xa2ea282a, +0xacf35c77, +0xcb9b2cf9, +0xe9aa1c05, +0xad9b1776, +0xe79444f4, +0xb119b7ba, +0xd9ca864e, +0x3e4a22ce, +0x2032e8cb, +0x99ecccef, +0x93317f4b, +0xf802417c, +0x132097cb, +0xcb87e353, +0x0cda20cf, +0xf30567d6, +0x337f0ab9, +0x9290e380, +0xa635be44, +0x040011e9, +0x0c9fbb08, +0x192292a3, +0x886eaa60, +0x763cd3eb, +0x0ea18e11, +0xb98667d9, +0x6786e7cc, +0xc28534cb, +0x18d8bbaf, +0x384a5508, +0x4a0ec15e, +0x6992cd26, +0x09ed45b2, +0x9e8548fa, +0x5a4b2a2e, +0xfc5af841, +0xa7ba46e5, +0xb62f3ba9, +0xeae04547, +0xb7d94e8a, +0xf484825c, +0xfe8c303a, +0xfcf51d3a, +0x5fa18d23, +0x405f004c, +0x0fec380a, +0x50f364f4, +0x8976cc14, +0x4453496a, +0x67962407, +0x8024395a, +0x6a07c0a2, +0xc32dc631, +0xe9a13e24, +0x57ae5062, +0x79da8181, +0x0448dabc, +0xc80fec60, +0x682f9ff8, +0x9fdeb9a2, +0x95531738, +0xcd5c1d8f, +0xa2d6fcfc, +0xf32ab52c, +0xad277139, +0xe0514fee, +0x6d818e7c, +0x3e182685, +0x5a999909, +0xba19eb46, +0x1f5548a1, +0x07e2b6b8, +0xf2595104, +0x4c85cf95, +0x6fb40795, +0x98e5a93e, +0xbf15dae8, +0xf81d9d5c, +0x773c4e6b, +0x3b3898ea, +0x650618aa, +0xf3960468, +0xacf4f8c6, +0xd733fc21, +0xb7ee0ac5, +0x34a371b9, +0x1d3656e0, +0x75550b34, +0x1f31e92c, +0x5bccbec0, +0x1cd0cd6f, +0x479f6679, +0xee18214a, +0x04329c4a, +0xaf6c1d10, +0xfbb773d9, +0xc39680a0, +0x1cfbd992, +0xa94244b8, +0x25845009, +0x634ac0bf, +0x321df508, +0x3ca52d0d, +0xfd448eff, +0x265f89ea, +0x3909907d, +0x24dd8f20, +0x0dacf408, +0x1ceed46b, +0xbdc03b4b, +0x5758084e, +0x7cbc098a, +0x21f40e13, +0x81bd27e3, +0x73ab7cf4, +0xd03d257c, +0xcfd0d890, +0x131eb4e4, +0xf22283f9, +0xaf984f7c, +0x7b06ba6f, +0x54a2c26c, +0xc3ac5947, +0x279f9015, +0x8240cceb, +0x8c556f41, +0x04299ef0, +0x9940e58b, +0xd24ebe0e, +0x5df9295a, +0x371d04b5, +0x206f8a46, +0x8370548d, +0xdb94a15f, +0xa59081d9, +0x84330212, +0xd088e5c2, +0xb90c31e3, +0x4d8a62a9, +0x2b505194, +0x3573ff0b, +0x41c14d85, +0x6e2abca3, +0xf058502b, +0x38b2be53, +0xf560059b, +0x567e69bb, +0xc19a7826, +0xb5df9333, +0xf97aa942, +0xd3e5f02d, +0x38aab444, +0x8cca23dd, +0xb0a4c85b, +0x3f355d3c, +0x488b836d, +0x8bf5c0cb, +0x5e54efb9, +0x6ba5a413, +0x57f03248, +0x87e9799a, +0xba1a95a9, +0x5d984e22, +0x869864ca, +0xbef2e6df, +0x8810319f, +0xc14b0d24, +0x60a855dd, +0x6d13b3ea, +0x012205d5, +0x3498a99f, +0x38759aba, +0xf1a084b1, +0xc0f12412, +0x6ae7729a, +0xca62e5d0, +0x42c7148b, +0x8c614daa, +0x5496bd1e, +0x1235571c, +0xb36f3778, +0xe9b8e304, +0x593a5272, +0xf6bc0669, +0xd31e7afc, +0x71f4e08e, +0x088910f5, +0xc75a5694, +0x12a56bf9, +0x05d67a5c, +0xcab26cb3, +0x8d5be30d, +0xfdba9dc1, +0xdcbcdfec, +0x973d77c6, +0xb5afaf9b, +0x91e5f235, +0x11956460, +0x8ee4facb, +0x7ca7cbc3, +0x443bb7df, +0x7ad1f7ad, +0xad917dfb, +0xa0ac05df, +0x454ff60c, +0xd7535c3f, +0xd14067a2, +0xb1b8c3ad, +0xdc659c02, +0x8c88cee5, +0x58558e84, +0x55bde4d5, +0xa0cd02db, +0x5fe8781a, +0xced3bfaf, +0x3d1710fc, +0x2d2a6ef8, +0x6bdd17cf, +0x4647e02f, +0x56b3bbad, +0xd7d68343, +0x19e49bb2, +0xb6a420b5, +0xe2f23440, +0x9790bdc0, +0x231b2928, +0xca6c8fd3, +0x59e48321, +0x926ff9a5, +0xa26b5f0e, +0xf607c8fc, +0x227318ab, +0xf279082a, +0xdabf4fa4, +0x7f4bca23, +0x138d9f9d, +0x282caced, +0xde739968, +0xeed8e2fc, +0x7b6475ff, +0xa34fd2d2, +0x8efabd75, +0xe545db81, +0x464aba89, +0x8cc19ec4, +0xf8be439a, +0x9658b729, +0x480dad8b, +0xab96c89a, +0xa8453e19, +0x54e517f2, +0x2db38bd7, +0xa023534c, +0x21fbb92a, +0xc8186c5a, +0x2dbf076b, +0xe7c1f1ef, +0xc1189a77, +0xd7164b9d, +0xca13a321, +0x4ada9404, +0x90e6d5a9, +0x9e514851, +0x23212f39, +0x5a73c539, +0xa248693b, +0x81fda93c, +0xc38b96c2, +0x3fd93617, +0xa24f1045, +0x1bb5b545, +0x8d0b6890, +0xe2a69ef0, +0x6f1fc206, +0xfc954301, +0x0d9ddc57, +0x938a0e41, +0x7ba9604c, +0xc095b8b0, +0xfd3a096e, +0x982c1faa, +0x8bf3e52a, +0x60fcc7fc, +0x6e366b57, +0x06d4e1df, +0xd185507e, +0x1064f486, +0x7bc88177, +0xdc03e7eb, +0x2f0fb706, +0x1ab2096b, +0x65e230a7, +0x898ba2d8, +0x963916a7, +0x66b76977, +0x8f9ee94d, +0x7f6c5d1d, +0x098967c3, +0xabf0ba04, +0xe90d34ed, +0x9b1a1188, +0xaecfa835, +0x26c9db17, +0xe1a13a02, +0xed27875d, +0x2b1d12a7, +0xcd181901, +0xcff206bb, +0xe7b1bb2b, +0x7f9f0c88, +0xd2ee6d23, +0xab88f1fe, +0xbd6b28e0, +0x7b15eaa0, +0x7c379fc8, +0x3ff66bbd, +0x4f754263, +0x68ed2813, +0x59b9d7b9, +0xd429cd1e, +0xba76c62e, +0x8db7e9fc, +0x1baf1119, +0x849b3230, +0x2b56945b, +0x54d5d481, +0x92a75121, +0xf5ec9df1, +0x48d4c9ed, +0xcc651048, +0x0af7c77f, +0xaa6d4660, +0xb41b87f5, +0xac009650, +0xf19dfa85, +0x05a3e656, +0x520bfb39, +0x0fc5d1a9, +0xc04aef8d, +0xdb8d809f, +0x491e43aa, +0xac4dbb4d, +0xb8649db1, +0xff1946be, +0xf698cafa, +0x591597d1, +0x8a9a95ce, +0x975fc9e9, +0x98377175, +0x9e3797f7, +0xbe9d5ee8, +0xa7a566cc, +0x1dbf1b68, +0x6bc2b328, +0xe74e2e26, +0x55088e00, +0xebc53bf8, +0xeb52b398, +0xc46fb7d7, +0xeeb04836, +0x674a6c3c, +0x83cbab03, +0xee21be88, +0xab2576e3, +0xbf707092, +0x9207aac5, +0x51147896, +0x363bd039, +0x8ed31a8c, +0x8a222f57, +0xd4b4d8b7, +0xd9fe60e7, +0xe522842e, +0xa62165c5, +0xf598804b, +0x6385ccff, +0x1773de09, +0x5a117195, +0x2a34d040, +0xb9f5663e, +0xe89d40d6, +0xaacfc44a, +0x53505470, +0xb91648a8, +0x88520788, +0xb31e5cd4, +0xe078dd19, +0x0fa0a103, +0x05a1b79e, +0xebeb1aef, +0xa3239c27, +0x6d1e149e, +0xa9450851, +0x8aeb9207, +0xe4b47d95, +0xc458d031, +0x1111ae2e, +0x9e7f250e, +0x2f21cd64, +0x84862c21, +0xd1d15120, +0xfbe60a45, +0x820d4ec4, +0xa127cc44, +0x58ab65e4, +0xff28cbdc, +0x499756e3, +0x3516019b, +0x4b160a8f, +0x3577f68d, +0xb26c9637, +0x0262f345, +0x4fb10bb0, +0x243a7df6, +0xa66ae991, +0xe0917b81, +0x9094b2cf, +0xeeddbd83, +0xee47c107, +0xc586b6c0, +0x09a284cc, +0x37dc6a11, +0x9162d63b, +0x9cf6cacf, +0xb6566bce, +0xe6d63c1e, +0x803e5da7, +0x96ea2629, +0xe8b58fd8, +0xff42094e, +0xf9d80895, +0xddc747f4, +0xa95b9c1a, +0x403c1268, +0x81738681, +0x30d3581d, +0x63ce35d1, +0xf21b4d2f, +0xa6682bff, +0xbce0acc1, +0x174e6ccd, +0xd3d61c24, +0x595a539b, +0x2f4860c2, +0x6f49dc45, +0xad4b9932, +0xe427676c, +0xc4d02aa0, +0x98ebfb7b, +0xa6deca0c, +0x21e62045, +0xe8e219ef, +0xcc162f7c, +0xb4ec86fa, +0xe92e1687, +0x11700e78, +0xdebb9f99, +0x89b6e439, +0xce628848, +0x7fde04ce, +0x25878e90, +0xeef073a1, +0xacbad4d6, +0x88eb7598, +0x2277eecb, +0x464ea2de, +0x25760214, +0x09a02a5b, +0x85a5dc4f, +0x3cd06568, +0x1f715bc6, +0xfa94228b, +0xc1273f3c, +0x1f0e359a, +0x014f4c7c, +0x407a8232, +0x87373978, +0x456f2282, +0x5bc1b977, +0xd9dbe8d7, +0x559b6d53, +0x124a8be7, +0x666efdd0, +0x3fd26d32, +0x5eb7401c, +0x4ccf9703, +0xb43c2866, +0x2f91ff15, +0x79d71f1b, +0x3a84a546, +0x26ff33f3, +0x043acec1, +0x5b2553d4, +0x718ad290, +0xa8b945b0, +0x1f893ebd, +0x09d45f71, +0xe5d87bcc, +0x21b72fd5, +0x154622ee, +0x2d0de0e1, +0xb76fc27c, +0xcec5c3ce, +0xfa34d52f, +0x9c9754e1, +0xd58e686d, +0xfc3ad506, +0xc487efc4, +0x9f265fa8, +0x43d85900, +0xcdefd059, +0x7de49b73, +0x0b8a2c03, +0xe06ef912, +0xebaa9288, +0x80f9fc32, +0xd8e7533d, +0x308d0e2d, +0xe983256f, +0xbe332808, +0x9e1db863, +0x21c04527, +0x5dfe0010, +0xbbc42ddb, +0xdd405dae, +0x23639b54, +0x45b73e49, +0x52112a3e, +0x73d3f4f8, +0x60e5be73, +0x043f79af, +0xb973b18d, +0x9683efd2, +0x05ff00cd, +0x15057bea, +0x638ef5f3, +0x241b720b, +0x69da3fbb, +0x8c500641, +0xaa48a2fb, +0xcab5a8e8, +0x6764729c, +0xb7da26c2, +0x936a91a3, +0x29f3f29b, +0xbee79033, +0xd31cd65d, +0x28e4f374, +0x87a3a7b4, +0xb2518cff, +0x200904dc, +0xebcdaa73, +0x6fdd992f, +0xca5f7a2e, +0x7250dcde, +0x11e2a55e, +0x52512aac, +0x3f385aba, +0x61a6c348, +0x29673710, +0x3e1356b8, +0x2847d70c, +0x51f919e8, +0x741746c4, +0xa592e5f6, +0x7536f1ea, +0x749f3677, +0xbdf86d75, +0x3136d40d, +0xd961f145, +0x21cf0b00, +0xd7a22bd8, +0xe5d934d5, +0xdab23f47, +0x6b9a5a21, +0x68eb0d40, +0xa4716b19, +0x7adeff87, +0x19d95dd9, +0x4db21d49, +0x3a85e5b8, +0x9ae7c1be, +0xd2004bf6, +0x7e45f606, +0x91a1b046, +0x1d62f56c, +0x05e75f1f, +0x01078864, +0xd8d46308, +0x25446feb, +0x3acb041e, +0x0246fef8, +0x7fa90255, +0xbf32953c, +0xc7beae3c, +0x665c536a, +0x7b410ebe, +0xb7325db1, +0x5db6d97c, +0x0230a9bc, +0x85b82033, +0x90e04bff, +0xd23d17c9, +0x55c594f3, +0xd476cd20, +0xcca07a4f, +0xf9b0c1e2, +0x037c1d25, +0x2ddd4625, +0xf47c23e6, +0x57a6d5d1, +0x189733e7, +0xafb4650a, +0x23fd67b8, +0xdee8fb53, +0x48ffc6c2, +0x9eaab663, +0x82792940, +0x0d908dc1, +0x32c0358b, +0x3b496579, +0x43c7306a, +0xef500637, +0xf83c727f, +0x17c94bc2, +0x8e6994eb, +0x15eeb582, +0x26811329, +0x42137d40, +0x6086615a, +0xd91237f2, +0xbdc32b9e, +0xcc1492d6, +0x507e76f0, +0xaeecfbfa, +0xc2f15f2a, +0x3ed74d42, +0x3e3db281, +0xfeff6c49, +0x4c9da4bc, +0x0463cfdc, +0x17116ebd, +0x13f4f30b, +0xc4bd705f, +0x7023662a, +0xa007bae1, +0xe550260b, +0xd59ecf7e, +0xe1c57c25, +0x10efa4b6, +0xc51c46b1, +0xde97f2e9, +0x8a5cea45, +0x5b8c7e04, +0x0fb6f45d, +0x002e9293, +0xd5e46d97, +0x7b145d00, +0xc96ef9d9, +0x589e75a0, +0x9ed3a200, +0xc90e80d2, +0x47b8b2b2, +0x4032b56a, +0x7bc6bf50, +0xecb9a6f3, +0x85e028f1, +0x5fb8da7e, +0x4788c6dd, +0x4ef6bf5a, +0xb7ca3ed2, +0x6542d5d5, +0x01b2e890, +0x52b87fc8, +0x7144d31e, +0xb4c95f30, +0xd88a4264, +0x1febc3be, +0xc0f0e425, +0x4efccea7, +0x22b50ebb, +0xe808e3e9, +0xb8cb5ecf, +0x557a2db8, +0xb40d4a13, +0xf431723e, +0xbd91d383, +0x5e7971b0, +0xf21cc177, +0xaf848bd0, +0x567116e6, +0x65fe6bae, +0x7a96264c, +0x7c665d55, +0x52e98000, +0x72c0f870, +0x97d8845b, +0x00de710d, +0x822e4e97, +0x8dba9dbd, +0xeacb3519, +0xd708d62b, +0xe775ceaf, +0xa5e154c6, +0x83cafbb8, +0x5783ef48, +0xe9cfff76, +0xc835e837, +0x256a7f02, +0xb92de402, +0x404dd31d, +0x20a98cfa, +0x2640c3d6, +0x46d6675c, +0x119a125f, +0x7239af58, +0x36c00bb8, +0xc8448ab0, +0x0c221dd1, +0xb2728602, +0x9a96fbab, +0x6d1e4845, +0x6913ea2c, +0x7b706c11, +0x831fbbe1, +0xbf8d2270, +0xe417b00f, +0x701cfdc6, +0x64bc311d, +0xdd6faa44, +0x131b6314, +0xcfa4f49d, +0x6cf32d27, +0x817e4530, +0x38c2b558, +0xc4952a51, +0xa2c9d134, +0x4ebfa493, +0xe22fadc9, +0x9dafb322, +0xcc239300, +0xf9f8857c, +0x2c94d435, +0x5e8794f9, +0x2ae93f99, +0xde15f56c, +0xeb25d779, +0xd33c0c53, +0xf3b5c6ad, +0xa05bf100, +0x80d57215, +0x0b88c847, +0x80d3b767, +0xe004d039, +0xf779a438, +0xf3f50ad8, +0x8890b6f7, +0x447f5a97, +0xb10ba322, +0xc049c1c0, +0x6f00b4fe, +0x62a1835e, +0xedf814bf, +0xef7344ff, +0x613b836c, +0xc59b084d, +0x4fecd0fd, +0x652ec05c, +0xb87adabf, +0x639656ae, +0x862f6ebf, +0xd8427588, +0x6300a3c7, +0x95144d0f, +0x3966b128, +0x2b7bb5b6, +0x50185459, +0xc74b9d9f, +0xd9becdcc, +0xf78e96fe, +0x35dfc8d9, +0xc2d88f95, +0x29322376, +0x68c8733e, +0xd6b3f291, +0x9e080b6c, +0x308d01c2, +0x3de20542, +0xfb3e88fe, +0x894aca7d, +0x943bcd45, +0x7b11dff4, +0xb08b9189, +0xa69954ee, +0xa9056382, +0xe78ef595, +0x507c8d38, +0x0caa5713, +0x56661d2a, +0x170453d2, +0xcf7f7c38, +0xc358e262, +0x5bf8d10d, +0x417ba90f, +0x42a312ef, +0xc2019ad8, +0x580882ef, +0x3eae851f, +0x1102390c, +0x2531e798, +0x06897dd7, +0xe85e35fa, +0x75406d8e, +0x9b519988, +0x60667ee6, +0x471b1d7d, +0x13a294cb, +0xb416461b, +0x6777cd0f, +0x0933e525, +0x92ef0d76, +0x98c84f0c, +0x8e6ec8ed, +0x8bf72f01, +0x4f8722ea, +0x75675cf2, +0x48af30c0, +0x93b56bd8, +0x17c666a0, +0x5dab9e74, +0x4d4ea20b, +0x573bc373, +0x6353f34d, +0xe67ef889, +0x8e73af71, +0x19d539a9, +0x2ba3ace7, +0x55a734c0, +0xf6f3593c, +0x7cac710a, +0x1105b441, +0x69813cdb, +0xcc56c14d, +0xd774a905, +0xc00d1371, +0xb290a472, +0x27b34cc8, +0xe5fcec6a, +0xf2d664eb, +0x3ee16d68, +0xb02014a3, +0x420bc06c, +0x9c99a81e, +0xee20bf8e, +0xf9e9e802, +0xb0c511c5, +0x1dab2faa, +0x4449a716, +0xb4d4cae1, +0x2c450b4c, +0xd90893f2, +0xea8abe0f, +0x23fefcec, +0x0175e64f, +0x544df7ce, +0x0bdf5256, +0xbb824c21, +0x3a43beea, +0x11cc59f2, +0x551bb5c2, +0x298a3e9c, +0xa7e657ec, +0x08db09f1, +0x70ea06f1, +0x46a9d205, +0x30509bbd, +0x99774108, +0x502f1d3d, +0x4c8a4243, +0xa51e72b9, +0x161b95c6, +0xe8b8c218, +0x78421709, +0x1af45df7, +0xe060fa90, +0x8c606d8a, +0x4857b9eb, +0xe41597b2, +0xa6147ed3, +0x4a5eb1e7, +0x835cf0c2, +0x991e6d7b, +0x3ed3686c, +0xf91f8b57, +0xcbbeb12a, +0xc2deaf7b, +0x442f2f74, +0x74cd9b3f, +0xd3d18180, +0x64e8c920, +0x0971412f, +0x527f50f5, +0x94b1cdd4, +0x1fdf12e8, +0x900aacc0, +0x9d2f5010, +0x599c1933, +0xbd06a672, +0x337e17e4, +0x589bbc31, +0xc1b05e11, +0x27f21ade, +0xe8fb3299, +0xe1b4fcf3, +0xe772529f, +0x6e78c395, +0x69dce572, +0xc7479140, +0xb83a14ea, +0xdc925d5d, +0x96d9594c, +0xc1e7cb7e, +0x0407438d, +0xb8516169, +0x0af27525, +0x85c137ad, +0x8923f3c8, +0x5e1514b6, +0x2a09b236, +0xd5d00658, +0x159519fa, +0x3ab8b4e2, +0x511cddac, +0xa5a42c05, +0x87974e96, +0x384cdfae, +0x049ee489, +0xa877497e, +0xaf623f8a, +0x01baf942, +0x1cdb68e3, +0x5c9e9781, +0x434abe3a, +0x1292259f, +0xb1f51f81, +0x85417f54, +0xfa58b6d3, +0xa1a2408d, +0x6b069e2c, +0xcbfc01a7, +0xbc9465c0, +0xb627c668, +0x083f377f, +0x46deef97, +0x8d284abd, +0x141d5ee0, +0xfdaa2182, +0x7c8f8309, +0x7fb0fdf4, +0xd3079f5a, +0x8c5cb61e, +0xcad5aede, +0xc8e62f8d, +0xacc93c3c, +0xbefe6720, +0x3d175e27, +0x7958e969, +0x6582726c, +0xe17d125e, +0xe72a230a, +0x8b5e64ff, +0x42dc2694, +0x993fbed5, +0x9e599a8d, +0x9bd17278, +0x53ab5744, +0x8698a577, +0x93f17ae5, +0x475361b8, +0x003773cd, +0x7a72e95f, +0xf26015a4, +0x9c27d923, +0x09b1f96e, +0xb55ca672, +0x99595073, +0x940bee78, +0x2e006741, +0x58024658, +0x25b40046, +0x06c684ae, +0x7cc37d82, +0x25449e5a, +0x9f33c26f, +0x5df331ad, +0xf19d19b9, +0xa05fa67b, +0xfc332bf8, +0x73fb4860, +0x33ecf684, +0xc5f296b2, +0x3ed87fc8, +0xee2b248e, +0x9e2885b9, +0xd4748464, +0xee3b8ca4, +0x2e9095e6, +0x22887806, +0x765a121e, +0xa0dd0fee, +0xc56c7274, +0x1f2db30a, +0x6ef70b4c, +0xdf47fbbd, +0x0f3cb8bd, +0x4f8b5e39, +0x97605e1e, +0x0978f059, +0x1a58f6ae, +0xf0a4a41b, +0x3f47a64f, +0x2ba79456, +0x832d3917, +0xeeee2b3f, +0xe02516d7, +0x9a897c33, +0x3c572c99, +0xba16d6dc, +0x19f4156d, +0x765e8897, +0xeca4e957, +0xf21a077a, +0xd7f03425, +0x01ad773e, +0xd85ae6b3, +0xdb0de7a7, +0x42c54bc0, +0xbfc1d539, +0x302b36d6, +0xb3ac7b8a, +0xf9d86026, +0x2d88673a, +0x61794c98, +0x27cb90c8, +0x3125601b, +0x6deba337, +0xfe721b05, +0xe68a0c8a, +0xa52e540d, +0x66536ec7, +0x9f28a3a8, +0x87acb922, +0x72b36860, +0xb29d89f0, +0xfeff9e9a, +0x48d62bce, +0xcf6f8d17, +0xc4f1ed17, +0x5d805afb, +0xbe18da0c, +0xf6b2553c, +0xdc69b930, +0x4ab77362, +0x01bc547b, +0xe660a3ed, +0x4ac44f5b, +0x687dd5e5, +0xa617ab8b, +0xda2526a5, +0x1b3dffc9, +0x697a8c96, +0xaecc6b96, +0xc2c4eaf1, +0xc439dbcc, +0x914e04b2, +0x78c00fc2, +0x948951b1, +0x576ceddf, +0x31ed1a71, +0xaeec1630, +0x952302fd, +0xaf5c5f0e, +0x2ce78017, +0xa6cb7eca, +0x9e8ec6ba, +0x41d3dbd9, +0x03f53f47, +0xfeeb443c, +0x4fc66636, +0xe83171b5, +0x71623f84, +0xae451ef7, +0x0a16ffdf, +0xb898d551, +0x4f6ac571, +0x97d59fbe, +0x6ce12e07, +0x61e05748, +0xe08b38f9, +0x67d4abe4, +0xce500c73, +0x087d527d, +0xe8190fe5, +0x840a5cf3, +0xd8e13cae, +0x5f0db115, +0x6705944e, +0xf6598f37, +0x56f5f0dd, +0x86842717, +0xe42957ae, +0xc29690ba, +0xbf6e58b8, +0xa024c5ea, +0x161176ae, +0x83ed047f, +0xe5963f8b, +0xbe21871b, +0x893bd9bb, +0x7298fcf6, +0x580ae6a0, +0x7cbd337b, +0x3b560301, +0x1023328f, +0x5adc163b, +0xf90ece9b, +0x944f30f1, +0x76f32711, +0x1e7c6d53, +0xcc9d0b98, +0xd524bcfe, +0xeff52617, +0x69ad01ac, +0xd905cfed, +0xc4447cca, +0xde8f85a9, +0x8bada3cc, +0xb1c75396, +0x06ea98bf, +0x858a12cb, +0xc0710104, +0xa2d93187, +0x05f49818, +0xe8b558a1, +0x95be5aa7, +0xc6bed4bf, +0x8b87888c, +0xa517aadf, +0x4d91b673, +0xf5ee7261, +0x1100b657, +0x60e08c1c, +0x12c6f03c, +0xdf051f0f, +0x0835c2c8, +0xc5e59293, +0xe789d2f4, +0x95170c93, +0x8f9d521a, +0x2e01b620, +0x6872a514, +0x1f0b2a58, +0xe3dd943f, +0xb16073ef, +0x5ffe69a8, +0xf0161a79, +0x78d4dd8a, +0x2da2cf7e, +0xef61a2ad, +0xd5dadb32, +0x4655bf31, +0xb1d3d2c7, +0xa1c07c41, +0xa53fa758, +0x27a6a276, +0xc053f6ff, +0x4eb72cf6, +0x9d165b28, +0xb9dc07bb, +0x5af7f339, +0xf921f13c, +0x9e6b1b67, +0x75470152, +0x3678966f, +0x5a06c940, +0x6de4f203, +0xcc7ab5dd, +0xdafc034b, +0xe4716079, +0x83affc29, +0x8edf3435, +0x889ccb1f, +0xe59a0b60, +0x8a3718fd, +0x69b6ab41, +0x0a29f9cd, +0xb1736e3c, +0xee108d33, +0xc06b53b7, +0x2174bba1, +0x287e9070, +0x3f3d6953, +0xbfde0e83, +0x460c3502, +0x1fae1131, +0xbc1f4290, +0x1f04f2b9, +0xede18ea5, +0xfcabdc03, +0x9cbe21da, +0x245bb5b5, +0xb2b929d1, +0x3e1554f9, +0x2a932e37, +0x412b494b, +0xaacc09a2, +0x8eb57876, +0xac1b32da, +0x868093a0, +0xfcd086ff, +0xe783f8c1, +0xfa0fb196, +0x0d7a2e85, +0x1fafcd2d, +0x96f8b872, +0x19988dca, +0xf9ce3d8f, +0x6554b90a, +0x7d9a6a7e, +0x8b84386f, +0xfa245e83, +0x72759b45, +0x16df249a, +0x05c5eaf5, +0xbb202bff, +0xd2c85722, +0xf356a096, +0x53563f7b, +0x269a32a0, +0x80bdc9b3, +0x2cb80024, +0x2d7c14bc, +0x92f05939, +0xb81479d3, +0x954e319a, +0x84024c2f, +0xe4338a6a, +0x4c756e4e, +0xd60a2369, +0x3738184b, +0x9785bdd3, +0x6b620783, +0xd0e65977, +0x0b1bdd07, +0xb499aeda, +0x0f0ab941, +0x7bfa67a4, +0x8a07dd5c, +0x13e60d1d, +0x672ce73e, +0x220e6f32, +0x58ba9747, +0x59bffe21, +0x6bf12f0b, +0x398353f2, +0x6d75a457, +0x5fe6f8eb, +0xd44ea5f5, +0x7280161d, +0x64e119bf, +0x7874d813, +0xf7359ef4, +0x441c8e65, +0xa08fa618, +0xe1f539cb, +0x4950c8eb, +0xc7087a88, +0x52746e36, +0xefebac69, +0x61930bc4, +0xacd6c8d5, +0x27fbf063, +0x388098fc, +0xea25fd21, +0x40eaa6ee, +0x2c9f3110, +0xe1db5193, +0xb3531de8, +0x6fb331b4, +0xc0948cc5, +0xcd333e73, +0xb3855dc0, +0xfc009d15, +0xc6cd653a, +0xfcddce16, +0x1dbca00c, +0x51a06463, +0x70cede74, +0x625bc8eb, +0x7e344aa7, +0x6481d2e0, +0xb89ddc00, +0x9f093e74, +0x0021541a, +0xf24e939d, +0xcd26e04d, +0x91647141, +0x5513b67e, +0x50f09009, +0x17d3aa91, +0xf7e4dd25, +0xec224e3f, +0x4418b65f, +0x4bcf617e, +0x3a797033, +0x858a1598, +0xfda0f926, +0x14e4452c, +0xdd2f680c, +0x20af678c, +0xa20d3924, +0x0bc84b9e, +0xd1401408, +0x273f3945, +0x2bc0d232, +0x8c454cd7, +0xc95dce15, +0xe78ea8c4, +0x797d0456, +0xcf2ffa94, +0x6dc5843c, +0x39eaf064, +0x6682ac56, +0xb2b50de1, +0x111ccf28, +0xb582f2e3, +0x45aeb94b, +0x437ba1b4, +0xb769c44a, +0xaacd2820, +0x075c291c, +0x3775dc99, +0xdbfd1d78, +0x65955fc3, +0x5b53af8d, +0xc6561e3b, +0xc5459afd, +0xacb4312c, +0xf4c0d66c, +0x8a18e833, +0x76c2ee03, +0xfa5f19c1, +0xb92b8b38, +0x86d26ec7, +0x4f9d97f6, +0x72e5181e, +0x1dd0e89a, +0x36714346, +0xa45763d9, +0xafa694a1, +0xd5ca9ca6, +0xdd60b4c9, +0x7964a8bc, +0x7c5e7122, +0x8a5fde7a, +0x7e4c4c97, +0xbb08ea2d, +0xa6d6c39c, +0x8bb7f627, +0xba6bcd8e, +0x03a65533, +0x62593498, +0x69d395ba, +0x456f56f5, +0x67071787, +0xea238fa0, +0x3d4da513, +0x21b615b6, +0xf36d0322, +0x360d662a, +0x9dc79a1c, +0xb100d265, +0xe8e04dcf, +0xe615dda8, +0x36ca1c7b, +0xa89234db, +0xcec88343, +0xe1231d6d, +0x93ab9374, +0x511f3dc9, +0x1c56d206, +0xf7486214, +0x366bfeda, +0x210f9fea, +0x5700e09b, +0x28f18553, +0xd0047e3b, +0x412c7974, +0x10cf9e20, +0xacfc7f3f, +0xc8ce0d0a, +0xe997abe5, +0x1fd0bf6b, +0xadd83fdd, +0xfb6bdacb, +0x0d8ce1f8, +0x5af780bf, +0x7febb1f5, +0x97d0cce2, +0xd0251b87, +0xc3e33017, +0xc14e802d, +0xdc37e0f5, +0x3bbeee99, +0x1865d14b, +0x3367f2c7, +0x808075c3, +0x4b9d7ce3, +0x78cafcd8, +0x8030b921, +0x1a356936, +0xc8f74455, +0xafdf62fc, +0xcd3bb1b5, +0xf541f724, +0x50841203, +0xfe602b10, +0x6f277bae, +0xdeabc931, +0x997febed, +0xca0bc1f7, +0x4d5295b8, +0x08bb0fba, +0x6462df6b, +0x702b0e62, +0x7d2d0486, +0x7f471740, +0x47c83400, +0x7c4c806e, +0x0ec7df4b, +0x0a9fc106, +0xad221eb9, +0x93c08974, +0x88a1f722, +0x8141aa3e, +0xc9f13253, +0xe29e17dd, +0x8f6f4625, +0x7c106f5f, +0x2f38c713, +0x40de0b46, +0xbf72d44e, +0x538b2fd5, +0xea72101e, +0xc1597f5e, +0x3264af68, +0x51b53392, +0xc1c6dd1b, +0xdfd2a943, +0xa4ef82a9, +0x713ac552, +0x527f02c6, +0xd88d8ab5, +0xcc106aa9, +0x5793ac72, +0x1dc2cbf7, +0x8cfbf0d0, +0x24e13bbd, +0xec4306df, +0x1f0f2af8, +0x43ae0d2a, +0x638a9209, +0x4dd89056, +0x55f6f92c, +0x57a5531a, +0xa0a6a912, +0x7706e03d, +0xe778c9f1, +0x6c71ef4f, +0x388ee29e, +0x98467cc7, +0x36914c5d, +0x8d4c87e6, +0xe151f8ec, +0xc487d524, +0x9671cd5d, +0x802bd8a2, +0x643e19ac, +0x4187d63c, +0xaee4e4c3, +0x7c8eafef, +0x0387307f, +0xab168a04, +0xcaf2a2f4, +0x4807a97c, +0xd0175180, +0xf782c190, +0xe65aa80c, +0xbbd1650c, +0x9a34db96, +0x762c5c77, +0xbb7b99dc, +0x62e59057, +0x2c40d36e, +0x486f0936, +0x15814565, +0xf3205ebd, +0x055e65b6, +0x337a7b0a, +0x33cc833b, +0xf6901bbd, +0x28948026, +0x2313d982, +0x0d882926, +0x2862754e, +0xcbe8f72b, +0x6bcc3ed7, +0x9f510a8b, +0xdd1ac6ed, +0x41efc1ec, +0x1c808b21, +0xacb6e3e0, +0x296f1526, +0x94106d9b, +0xdfa2026c, +0xb80cdb2e, +0xd509aeea, +0x83dee9e6, +0x88b08cb2, +0x9a023e9a, +0xa37d1383, +0xdb2b7359, +0x64aadd86, +0x04a819b1, +0xbd4db988, +0x31574899, +0x30271f5c, +0xe8a222fc, +0x2304eb25, +0x1b05e598, +0xc78b8f7f, +0x75d6e28f, +0x46bf9169, +0x7c4f50ce, +0x1a4616f2, +0x1d32a412, +0xa204736d, +0xe7093069, +0x831ef6f8, +0xa870ec5c, +0x9c173b0b, +0x00ae5314, +0x0284d8fd, +0x755b0b6e, +0xb167e2cf, +0xbc736a57, +0x8a49de7b, +0xa2a5919f, +0x8ea9edd8, +0x699ca76a, +0xe8966af7, +0xc47c8b84, +0x8a6cf78d, +0xb2b0b142, +0x3b879c9f, +0x2ec347f1, +0x7902703a, +0x00ad2905, +0x62a3bafa, +0xbdc5e275, +0x71a28326, +0xa9067e34, +0xae0048e3, +0x5cfaa2cb, +0x17dd6776, +0x3f51742f, +0x614f4ec6, +0x6fa15c8e, +0x41b8dea2, +0x9ffe7fa1, +0x0c12900b, +0x1416bdeb, +0x703d98c0, +0x0807c837, +0x78cdfc0e, +0xaeab92ce, +0xd4b5fcb6, +0x21e44c88, +0x1f282d2c, +0xe835bf0a, +0xfff22fb0, +0x4bd84ffd, +0x31fc4d8c, +0x7c0dd62f, +0xae892a0e, +0x4a5bcf7b, +0x677d03de, +0x1f52ac1a, +0xca4f1786, +0x97c4aa2c, +0x009baf9d, +0x5767f61a, +0xeab973cc, +0x2c0006f2, +0x8f7a59b9, +0x80f73da8, +0xeef70bce, +0xd1979881, +0x132d2680, +0x07349975, +0xd6b88145, +0xa32d4699, +0x435833f4, +0xd9d93bd9, +0x32da5d3c, +0x8f02e1b1, +0x685b469d, +0x60f0d2af, +0xd30f6f86, +0x25c534d3, +0x0408d573, +0xda325d88, +0xc898805a, +0xedb05140, +0xd1156ced, +0x738c83eb, +0xa6fc6c74, +0x5385242b, +0xd4ffeb43, +0x2e05f073, +0x2456889d, +0xff3b851f, +0xa00880d1, +0x9ade8d8f, +0x72bd1d40, +0xe6512b95, +0xe1e23656, +0x67744438, +0x048cf06c, +0x573a0b09, +0xcb35936b, +0x73831f84, +0xfc782ae3, +0xc5325e8e, +0x0b4e9dd7, +0xda956de8, +0xa02cbafb, +0x7d316e66, +0x77d8964d, +0xf5b8c61e, +0x204b16e0, +0xfee079c2, +0xb12ffe16, +0x6941cf58, +0x965602f0, +0x580f7e36, +0x1425f2d9, +0xf305ef2a, +0xdac03a78, +0xe992dfd4, +0x1c39a6bb, +0xfa058f9e, +0xe67c2c8e, +0x8dbe8d46, +0xeb7641d5, +0x4356e910, +0x214f91a8, +0x7bd41f28, +0x9da5de9b, +0x1b5da409, +0x87bf755a, +0x5098509d, +0x21dbb61c, +0x5cfd8320, +0xf5351e3c, +0x31be20df, +0xb93eb473, +0x2f3cab2d, +0x11dc279b, +0xc9bd0440, +0x0d8d053e, +0x18732ac7, +0x8457d823, +0xcc532f72, +0x91868eb1, +0x4afdfd38, +0x529674ec, +0xd194f9b1, +0xf908f422, +0xf1877ced, +0x1e4b237b, +0x00fb760c, +0x75864e77, +0x210dffc9, +0x4ac86b14, +0x099b2bae, +0x6aab1d90, +0xf9d47ba4, +0x6771b858, +0xce895f2f, +0xf54ce316, +0x5aac04e3, +0x5023f8c4, +0x398762a9, +0x75ccc949, +0xfb1eacc8, +0xb972ff0d, +0x70f11997, +0xd8ccd069, +0x10f2e96e, +0x12b80912, +0xecf77b19, +0x4d240416, +0xb24abb5a, +0x9717e18a, +0x0847cf93, +0x7cb76096, +0x8d67b6bc, +0x43b19867, +0xec3b58d6, +0xcc941d79, +0x815258d5, +0x2b54da62, +0xb066ceb4, +0x592301ea, +0x852078ff, +0x49ea06a0, +0x84c8e47c, +0x5302da27, +0xad5d98e8, +0x174f1023, +0xe1f1e9c4, +0x8e41acd5, +0xae69cbc6, +0x39e71d2b, +0xbbcf4b36, +0x55aaf4eb, +0x3d3aa1ad, +0xe57a0d58, +0xd68c797c, +0x09cb8ddd, +0x57054d79, +0x6dc3859e, +0xf4e93f2e, +0x8a5abc50, +0x3181c477, +0x5702b5a8, +0x0c35aa0f, +0x6cb6c815, +0x7aae2cff, +0x7197ae66, +0xa15f8e5e, +0xd2c84aa4, +0x067a85bc, +0x58f9cbec, +0xf51c6904, +0x8928b705, +0xdaa3f586, +0xe0740ddc, +0x8ae5521d, +0x3cf3509d, +0x6d17e04f, +0x48abbe39, +0x1fceca0d, +0x3bcbcb86, +0x1be20e49, +0x1c55c2bf, +0x6a51b5cf, +0x1187dfdf, +0x6ab15a64, +0xf95ed542, +0x20735945, +0x029568a4, +0x0eb08f5d, +0x6c2d58af, +0x606fb594, +0x67705241, +0x06d6672e, +0xa289a5f1, +0xf29e0c25, +0xe5ac6f9d, +0x4edc72b7, +0x984ed1d1, +0x818b22b7, +0xc73cc905, +0xe59d2b78, +0xb780710d, +0x44b51b79, +0x8a3d57fe, +0x3a13e43e, +0x39431e18, +0xe70a9ec2, +0xa570f3cc, +0x08a2a18f, +0xfd7cb7e6, +0xa62c4c13, +0xc87c10eb, +0x954f4822, +0x6bec1b3c, +0x8d275a91, +0xfa9d7112, +0x6c931fbb, +0x0eea4c32, +0x6c1be283, +0xb60d8b4d, +0x2f0b694e, +0x4060956f, +0x3ac543eb, +0x875efe92, +0x7911a89d, +0x9e76d2a0, +0x9f60f6ec, +0x48d53dd3, +0x4ae1bd0f, +0x9e8837f1, +0x95686196, +0x4a5255d3, +0xd476e7d8, +0x99e939de, +0x15a4ebb2, +0xf7f02e89, +0xf09f4af9, +0xbd59e8ff, +0x177c0d28, +0x56bdd493, +0x7ee12045, +0x10251d29, +0x570d64da, +0xd73c0967, +0xb9573907, +0xcaffd35b, +0x5dd1cc4f, +0xbe659e0a, +0xb1876c7d, +0xfefcd210, +0xbb54f849, +0x3d9d22e5, +0xf6330c6b, +0x073bbfff, +0xe50faa36, +0x4cbfc5b5, +0x9dfa889a, +0x0f547311, +0x389be508, +0x4c8fd23c, +0x450847e9, +0x980abffb, +0x4bca8f29, +0x37f39f97, +0x00180ab9, +0x0c2d7872, +0xb039f73b, +0x21a99e8f, +0x0dd5d49d, +0x8293f076, +0x212c5ee5, +0xd376f459, +0xfb0ee35f, +0xc78ab250, +0x2a6cbd90, +0x3f0527c1, +0x8658b4ef, +0xba59be04, +0x3ac68621, +0x3613b39a, +0x6724cf52, +0x0d966813, +0x6d59e7c5, +0x15adac38, +0x36a58b07, +0xc274f732, +0x728b46a9, +0x95d45d40, +0xad295c10, +0x0523a01a, +0x61b094c3, +0x2faa9fa9, +0xee925c8b, +0xade373f1, +0x76701e40, +0xce29931c, +0x7820fa23, +0x379db9e5, +0xa8b98311, +0x4468a009, +0xdc84c1c5, +0xdcdabbc9, +0x0c4bb9cd, +0x2f38fb30, +0x4312f4f4, +0xe98b65b5, +0x5f618a7f, +0xf838266f, +0x5ae71df9, +0x3b6f8c58, +0x78a7c7b7, +0x9136de09, +0x8409bd61, +0xdca84afb, +0xf7d66d71, +0x8663c18b, +0xb5cce00a, +0x661e9653, +0xda4c0f58, +0x8cd6ed66, +0x242c4bf4, +0xaf418766, +0x3328730e, +0x182d8cef, +0x66957672, +0xee487e62, +0x0e6a2cc0, +0x33d2188b, +0x41988869, +0xe63187fb, +0x495c3c75, +0xb2108ebb, +0x20afac20, +0x3baf242d, +0x4a1c04d7, +0x703cbb2e, +0x2e4a73cd, +0xe98ac009, +0x28c0e625, +0x3c119a57, +0xaffbaff4, +0x992c7a44, +0xf6e67503, +0xc045403c, +0xad7e46e1, +0x0ffbc046, +0x6656e86d, +0xa2cafbf6, +0x6e4463d5, +0x99f12583, +0x69861cae, +0x364e0676, +0xcc63ead0, +0x1fd9fef0, +0xc0c5332b, +0x628c92e8, +0x5bf924ef, +0xfc8c6a8a, +0x5a73bcd7, +0x81cb0691, +0xec7ffa6f, +0x4e9a228b, +0x7ddac980, +0x4fe88782, +0x692849da, +0x46758301, +0x2048eed7, +0x3cc34b4c, +0x8262edd6, +0x2c638994, +0x909a936e, +0x0172b418, +0x0890df30, +0xe8557e5a, +0x0d304ac8, +0xf7a64a66, +0xeff71278, +0xa05bd98a, +0x9087e596, +0x838b7bf7, +0x95dac78f, +0x00bdb14f, +0x3b62a85c, +0x4b92673d, +0x99d21242, +0x8b33f8be, +0x7aa8b570, +0xe0ef79ba, +0x8b44b199, +0xf77b8173, +0x6f02f886, +0x3f2e1022, +0xc15965d5, +0x62afd877, +0xa45e0a23, +0x23833307, +0xbf9f786b, +0x144f57fe, +0x4ffef421, +0xf0fc44f2, +0x84747762, +0x0d20457b, +0x3e3f37a1, +0xd7f9a85a, +0xdc96af18, +0x0f5586fa, +0x16b93bf5, +0xf8a74703, +0x06c95dbc, +0xc0d29a33, +0x3c360bfa, +0x90e2c9ad, +0x7352c296, +0x8e8a22e1, +0x3d4a09fa, +0x4f00750f, +0xbdcd5a42, +0xd26cb9b8, +0xdf936db7, +0x1ed1c880, +0xf2b6ed1f, +0x2dee7375, +0xadad6e49, +0xb15e7957, +0xbcaf36d4, +0x43870456, +0x0f6142e1, +0xe055a640, +0xbabeeced, +0x345833ed, +0x9041637b, +0x8e802fc7, +0x519f0f72, +0x3e88bf65, +0xa2ed5e9e, +0x0ddb13f7, +0xca5b7bf3, +0xc4cff843, +0x54272bc0, +0xd831b545, +0x4064a0ad, +0xab4974a4, +0x79e9e85e, +0xc7a4fa5b, +0xf7c9d22a, +0x0305d9ed, +0x13261dbe, +0xd87e8085, +0xbabd3181, +0x4fd2bf2e, +0x233f3646, +0x191d8f3b, +0xe25cc08b, +0xe2b05cec, +0x15ad4280, +0xed61e3ea, +0xdcb1c08b, +0xb110bc47, +0xb54b9903, +0x7f004c91, +0xc0b9941c, +0x1172519b, +0x0871d77c, +0xe4481eea, +0x586eb90e, +0xee1c97d1, +0x5a68c1d4, +0x4b010fa2, +0xc3bca250, +0xb3a85753, +0xedde7b01, +0x68f932a6, +0x399292cc, +0x1dfa7416, +0x3f232ca3, +0xa76c9832, +0xdb96a9a2, +0xf87a123d, +0x1dc738d9, +0x566cb20b, +0x0e90eb0d, +0x4fdfc0b0, +0xa12829b3, +0x37a0f268, +0xa555f63f, +0xc06d2e03, +0x2b2a9f06, +0xe02e58ae, +0x7426b235, +0x3fc6cc82, +0xd026962f, +0x535e05c9, +0x1394649f, +0x8f21c21f, +0xabbd1edf, +0x85b2071e, +0x7b0553a0, +0x120e9b75, +0x1c930560, +0xe2d30284, +0x5736a127, +0xd66f700e, +0x2c6317da, +0x95d45c12, +0x01f953d6, +0x00c38c43, +0x7b78a88b, +0x068aeeff, +0x2b65fa7d, +0x812981f7, +0x6b7ba6b9, +0x16adc019, +0x773262ad, +0xb62752c7, +0x2cce14e7, +0x7fe51c98, +0xfa4b7a07, +0xd27fa651, +0x6ad243e4, +0x36188dac, +0x7c134b31, +0xba8f557e, +0x9a2f5f62, +0xd7ef0746, +0x7ed4118d, +0xcb95f292, +0xf5212d31, +0xbf2d4a60, +0xc5b07c48, +0xd4cde60c, +0xd54dc24d, +0x47fc4775, +0x5f63a5b1, +0x7b9569fd, +0xf2119342, +0x77af8498, +0x11b5db71, +0x3272da0f, +0x04e34457, +0x05a4d13d, +0x233ad8aa, +0x61682eed, +0xa5789056, +0x879f4ef8, +0x9ad1a3fb, +0x48bfe67f, +0x8734effc, +0x805c3802, +0xc5313a70, +0x2d5ea4cd, +0xb68cc014, +0x2ac958b2, +0x217e31e1, +0x019324ab, +0x3af3e24a, +0x48bc0689, +0xbae53088, +0xb50c12ae, +0x9cfd616f, +0xa35729c8, +0x3056914a, +0x17f118b7, +0xf88325b9, +0x841b8f45, +0x5411ca86, +0x20a5f341, +0x22319635, +0x22be9f50, +0xc159f4cd, +0x68f8a491, +0xae047fc9, +0x8bfeb413, +0x2b40b666, +0xf4f43f5d, +0x2efa8c5f, +0x6cc62f02, +0xd883a44a, +0xa81d5a5f, +0x375b0514, +0xc2b53e9b, +0x24938960, +0x79c15a18, +0x403fe76f, +0xeece77de, +0x6a7b7655, +0xc39c9f20, +0x7035efc8, +0xb0b7842e, +0xe317255e, +0x2477f6b9, +0xed6113b3, +0x298fb1a6, +0xaf55ca4d, +0x83710aa4, +0x059258a8, +0x16253276, +0x43e4c97b, +0x129be940, +0x5d436fb0, +0x25c56e38, +0xddd4900d, +0x1a0af503, +0x31114d51, +0x69fab9a8, +0xf93243a5, +0x09697e38, +0xdfe995ed, +0x5c8336b4, +0x080be679, +0x5d6c4af9, +0x62b3b525, +0xb06d5a1e, +0x6b988050, +0x4206fc02, +0x1583a401, +0x64321b49, +0xb79d65e5, +0xef08f59c, +0x192d2092, +0xbb59060e, +0xc5edc445, +0x1adbfbc4, +0x6684d182, +0xd61a9e20, +0x5f5c55eb, +0x739b454f, +0x46022245, +0xfe31446e, +0xf655ba85, +0x99181065, +0x117dcff3, +0x8d3590be, +0x01d5cbf0, +0xa75161c1, +0xbe58c221, +0x575a0196, +0x42658dbd, +0xc66f3e88, +0x02dea5e9, +0xedf8b605, +0xc86b3ce2, +0x74d9af17, +0x3c0cb6f0, +0xa1dfad34, +0xf2f16f2b, +0x509850ee, +0xcaf02e93, +0xad435e5a, +0xb6c50e69, +0xece569ea, +0xfa696b44, +0x0ad8bce5, +0x1808cedd, +0x0a69f1da, +0x1a744fda, +0x91303621, +0xf684b242, +0xd3f782de, +0x055bd13b, +0x3d42152e, +0xd12eb59b, +0xd8cccad6, +0xcbd919d6, +0xc38425e0, +0x1751c854, +0x5171b810, +0xb20fa03e, +0x8bb35d24, +0x17bc1045, +0x236a43a9, +0x43f0c7a4, +0xf3f38486, +0x8b868938, +0xa8f1443d, +0x1f2f789f, +0x70e06f16, +0x6b116c03, +0xfddca9e9, +0x4efba402, +0xee8d1d65, +0x95fbf8bd, +0x774c081c, +0x277d0a97, +0xcbd78eb0, +0xd3e13d0f, +0x60af7d2f, +0x7aa772d3, +0xd1bc8070, +0x0b940539, +0x05747998, +0x5538c9f3, +0x737514b2, +0x385e3d93, +0x3229b91e, +0x2689d490, +0x41cba99a, +0xca1bc2c2, +0x14e0b81e, +0x42948877, +0x00f61254, +0x8326f30b, +0xad5b9b60, +0xd84fc7de, +0xdd734ea6, +0x69926c2b, +0x82f34538, +0x50de6ff1, +0x3e1a3848, +0xc20ac780, +0x9112b7b6, +0x586827c4, +0x5a71a7a9, +0x048dfbeb, +0x1c60e022, +0x668da6e9, +0x53d55ed0, +0x485b1757, +0x3b5c5405, +0xa087ce39, +0xfa2c8a99, +0x3dea680e, +0x19335c3d, +0xadaa860a, +0xcf8a194c, +0x76c04476, +0x7464cfd0, +0xe2eb4bc9, +0xb5e2ffe0, +0x994fb8cd, +0x03561979, +0x8dd7100d, +0x26778dcf, +0x92d55891, +0x98102925, +0x2edc0042, +0x9f5580e6, +0x70d68baa, +0x177db856, +0xd1f4d541, +0xcb268c04, +0x61c95b7b, +0x2e3c473f, +0x4db5abc0, +0x75518f9f, +0x335b2818, +0xed3f98ab, +0xa3ecec37, +0x110f1cc1, +0xd4ef89f6, +0x848e6c50, +0xc33ec661, +0x1887604d, +0x608f9025, +0x106307bc, +0x44acc205, +0xc6d8942a, +0x91d2d080, +0xa53835fd, +0x48d781bf, +0x5cf45b22, +0xc8855f33, +0xe75d1e3c, +0xf2e3981d, +0x473d4b31, +0x9886a590, +0x4db6bd8c, +0x2f4312d0, +0x01fa42ae, +0x2f9f377e, +0x8f16e5ec, +0x1b7740d5, +0x00c7860a, +0x490b34b9, +0x727a6200, +0x8db6efd1, +0x58e8ba5d, +0x91458b69, +0x509581de, +0x12a0590c, +0xf44527a2, +0x5f53f7db, +0xe63e65f7, +0x5566efd3, +0x46052d0b, +0xc3bf192b, +0x3ec514eb, +0xe034f9b6, +0xdafa54e8, +0x72f26a81, +0xff93f0cd, +0xef1823ca, +0x6caaf5c4, +0x06ad2452, +0x38d0cab9, +0x1b0ca241, +0x3c94db10, +0x40775e89, +0xa4391dad, +0x22bc1c6e, +0x81968f13, +0x57279d52, +0xbc61a084, +0xd00fc544, +0x7cced07e, +0xe3f8feb9, +0x1119dad2, +0x0f1217a1, +0x8b4050ef, +0x05285485, +0xc81971ce, +0x36b1b8cd, +0xdb49753e, +0xf1d47820, +0xbba36339, +0xd2d6c1ff, +0xd4175ccf, +0x7b7b46ba, +0x7611c5ed, +0xbdf3d987, +0xa3c611fb, +0xeed38d41, +0xdaeaeec6, +0x8cc119e6, +0x498e7ea3, +0x7d700553, +0xd09462e8, +0xbba0ff1c, +0x5cf83f4b, +0x968e9e97, +0xe9482f2e, +0x92dc765d, +0xff019c4c, +0x62725f0e, +0x3e96e4cb, +0x8930ca1e, +0xfa35a8c9, +0xdbac7728, +0xeba689fb, +0xd5eac991, +0x15f588cd, +0x7338622f, +0x9a136c35, +0x86c86499, +0x540a51e7, +0x4fa64901, +0x13cc5060, +0xb1327c3f, +0xc98bcf17, +0xfd080150, +0xe9658d3e, +0xb3de6340, +0xf1c44f1f, +0x91cbf202, +0x78390f6e, +0x5a40c98e, +0xe2e59968, +0xfbf402f9, +0x074bcd20, +0xc52182ce, +0xc79d8880, +0x56802829, +0x05da8919, +0x7fb9e5d1, +0xba726d27, +0x1fe6a0b2, +0x6155b56f, +0xc1f6e962, +0x4cb32883, +0x9813615f, +0xebe6bfae, +0x2945523e, +0x53514f5c, +0xcfe66b23, +0x484f6ca9, +0xd1c62169, +0xbd601144, +0xa8b70a53, +0x67edf0ba, +0x805972c6, +0x4979e3ea, +0xb17c8a29, +0x2784662b, +0x60ebed0b, +0xd483b044, +0x1acd81d9, +0x509e7089, +0xc71911a9, +0x7a5678fa, +0x0bf56e14, +0x948a173b, +0x4742417c, +0x92b863cc, +0x90da4d37, +0x9609f2c8, +0x4423be08, +0x452a3128, +0x60bc43fa, +0x1f890657, +0x31610a24, +0xa0a52a0e, +0xeaf70e13, +0xf71f0b15, +0x3c3ad9a6, +0xa67f3b7e, +0xa2a112d8, +0x1f3d5c1d, +0x18c38bb7, +0xceab95da, +0x1db1c458, +0x6a098c74, +0x909e2411, +0x5bebd187, +0xbed4fadb, +0x27da48ae, +0x17a88a9e, +0xa4291752, +0xdba752d0, +0x4e53756e, +0xd74f395f, +0xd1410c35, +0x4e9534a3, +0xc5a4c700, +0x6082d388, +0x47355256, +0x2ea81ebf, +0x027cbc6a, +0x6e7d0f79, +0x8145cabc, +0x513207e4, +0x16cefcbf, +0x1904daef, +0xdd29ae1e, +0xc863fece, +0xafd88199, +0x581c763c, +0x76c98a9b, +0xb7ed1952, +0x78845b30, +0x92f4920c, +0x7ad69480, +0xbd419c30, +0x123ce9ed, +0x56ef8454, +0x0200cac5, +0xa3e9c72d, +0x19b35380, +0x97311722, +0x070fbd5f, +0xb7f99669, +0x252e2004, +0x1e6b3b9d, +0xb042298d, +0x2c6e99b2, +0x627dfec6, +0xef349d25, +0x5b8d0ae2, +0x29846fb9, +0xedff735d, +0xfa4f4671, +0x5f801d1d, +0x12e75523, +0x08b2f474, +0x837e7d28, +0x33ee1fae, +0x68c60712, +0xd1069e70, +0x6a8e188b, +0xcf6e24dd, +0xd7c388e4, +0xeabd5e3c, +0x669a22a3, +0x1586e5da, +0x8670dfca, +0xec3120b1, +0x6bf7f88f, +0x8de8207a, +0xcde15755, +0x63d61ecd, +0x9f285c75, +0x2723b395, +0xa86e75b2, +0x079e908f, +0xc34724f0, +0x4fc57442, +0x0dbbd74f, +0x9203a512, +0xaa7aa0fc, +0xf1ecbb03, +0xb323d3d6, +0xa4ff661a, +0x19dbb5e0, +0xfd9c465d, +0x187a0b33, +0x23e17861, +0x01b35944, +0xbacdfd6e, +0x8d254f44, +0x0db5bfd3, +0x2c9235ff, +0xb2af0faa, +0xdbb60068, +0x46e8eba3, +0x208078fb, +0x8b442a99, +0x2d413f5f, +0x72f183f0, +0x04fe1fdb, +0xfecb0961, +0x324f76f9, +0xb1ebbf1a, +0xc78b1757, +0x00e5dd54, +0xdd3cdef5, +0x1d57a2a0, +0xa69b47c5, +0x48c4441a, +0xc48a55df, +0xb8d8e8d7, +0x6b80a7f0, +0xd50e9a6e, +0x9bae6598, +0x2db8ca80, +0x171d5ebc, +0xfb5d13cc, +0x546d338d, +0xc4bf7e8a, +0x0d951461, +0x20d16318, +0x7e094c2d, +0xf5ff6fba, +0xb5d419ac, +0xeaf184dd, +0xbfa1b2b5, +0x4c083c6d, +0x3ad85e87, +0x7c206956, +0xd350b07b, +0x520b3e62, +0x2be9ea6e, +0xf32dc210, +0xd38017e7, +0xebee70d3, +0x9202f12d, +0x1fe37581, +0x0e43db43, +0x263d43cf, +0x0294f4f7, +0x84c4b89b, +0x61f7df94, +0xae973a81, +0xf542601e, +0x70c40905, +0xa85ad8b8, +0x963f7679, +0x0518a7a1, +0x4f327d16, +0x56883c40, +0xa0ff486b, +0xb0c9beea, +0xeaecdd94, +0x70765a08, +0x034000a4, +0x56ba2cfb, +0xdd17ecce, +0x6f14cc87, +0x689b01f0, +0x12f8f651, +0x6612f80e, +0x6543ca62, +0xa570712e, +0x8888fc04, +0x6f585d47, +0x53ab8695, +0xa838e915, +0xb3555b60, +0xcd4a8dd0, +0x257f53b5, +0x241e40ab, +0xbd7691bc, +0xd2303864, +0x0c394dcb, +0xf227810c, +0x4d4bcd56, +0x5aae8a8b, +0x575829bc, +0x5d803e1f, +0xf9d021d7, +0x6cefafde, +0x93c9b098, +0xfbef4b4b, +0xbe22bfbd, +0x1095f139, +0x61d088a0, +0xb4af263e, +0x254f49ed, +0x5c56c32e, +0x62121e48, +0x62869447, +0x575532b2, +0xa321a460, +0xee29e8dd, +0xaf510ab2, +0x49aba018, +0x60ca69b8, +0xa1002348, +0x978f07a4, +0x51752111, +0xf2c2fc46, +0x35a51466, +0x8f91aa79, +0xb8462c4d, +0x256ddbe3, +0xa4cdb0d5, +0xa7100a80, +0x1e5cb893, +0x53c4eed8, +0xcf85df55, +0xe2004f0d, +0xe1e4e7ac, +0x49927de0, +0x73197988, +0x69c554e0, +0xba49b5a5, +0xca77b8fa, +0x023f3e87, +0xe8c788f1, +0x43f73705, +0x0e2e5f3b, +0x2fa99f85, +0xae4bed0b, +0x3ff24a7b, +0x0f91982f, +0x8f5b370b, +0xa41436b1, +0x9d150f81, +0xaa29918c, +0x150d8f5f, +0xe16a07f5, +0x0dd8241c, +0x04e432ac, +0x1d8b670a, +0xb9f9116b, +0x13063baa, +0x2fbe99bc, +0x9e4afb8d, +0x47931bf9, +0xe0e65563, +0x2e6a8a69, +0xb347fcb1, +0x0b940d8c, +0x5f118c11, +0x87a943c1, +0xa864dba1, +0xbf514e58, +0xdfda9f01, +0x4f38eb25, +0x5f2d8648, +0xb5bacb0b, +0x988a364b, +0x30fd92c4, +0x2140ee3a, +0x9405d445, +0xc4effb51, +0xb0cea47a, +0xdcbc0d20, +0xb215d2bf, +0x3fc9532c, +0x9de5411b, +0x2bd20ee4, +0x1d1e8855, +0xa2c47bb7, +0x4616b92b, +0x4bb3c357, +0x9a433890, +0xfaa891d1, +0x5e8c613d, +0x02363e8a, +0x0d89a67a, +0x0ec62d3b, +0x00e28b6c, +0x372340cd, +0xb683da68, +0x328ac533, +0x82f85d14, +0x3dc56452, +0xd607c16a, +0x7235aea3, +0xf508df13, +0x76adeaed, +0x2ede2bf9, +0x2106515a, +0x69cc82d5, +0xbdd0d456, +0xcd6f825b, +0xf2b37fe4, +0xa3f247f6, +0xd28bbbd1, +0xdbea4225, +0x2be715a7, +0xccff47bb, +0x20bb3849, +0x9a77fbb1, +0xa34831fe, +0x53efbb85, +0x24905365, +0xd51426f7, +0x92fdb08b, +0x0c02a513, +0xcd78988a, +0x91596306, +0x99016044, +0x0cda0df6, +0xdffe07db, +0xf6ef607a, +0x83603760, +0x0c352d92, +0xc3b57370, +0x02e4b68d, +0x8d129016, +0xfb5b9e88, +0x4ab13ff8, +0x12d94acc, +0x748512ec, +0xbf3a152f, +0xea3c68e6, +0x8c42a6c9, +0x11aec073, +0x11659735, +0x88fbff81, +0xea03651d, +0x28b50e40, +0x386c74e8, +0x9b0d167a, +0x7ca6c8ed, +0xdc782ed3, +0x10e7be5e, +0x1aa5331d, +0xa1c9b9ae, +0x3e798b9d, +0x770f9be3, +0xac35d9f1, +0xfc45e2a9, +0x0f40c18a, +0xc2650f95, +0x0e120340, +0x6f1b7c99, +0x921724fd, +0xfd2ebdff, +0xc1d9424e, +0x7854d1b7, +0x9443192c, +0x012274fa, +0x1c7d8f4e, +0xea04cd15, +0x598f64f2, +0x1c35f3d3, +0x03f6bb87, +0x81b9f0c8, +0x5b63d04a, +0x370ebcd8, +0x8cb518f3, +0xaf4953f7, +0x0729b68c, +0x255cb23c, +0x78f11cd2, +0x78728ebc, +0x372a2fa6, +0xd7a1a8e2, +0x7066680f, +0x91041dbd, +0xdecd2360, +0xdc952c7d, +0x6215c7cf, +0xf14d7803, +0x78b8745e, +0xf2262484, +0x1c7b4788, +0x83fbda4d, +0x63f66c99, +0xddd77bf5, +0xa8dc5095, +0xe44a855c, +0x721a4621, +0x50deeac1, +0x8af663ab, +0x17b42a9c, +0xfc76b6b8, +0xf4a64384, +0xee39e455, +0x04a56869, +0x247fd553, +0x5d1a133c, +0x058202c4, +0xe2f4aa90, +0xd06540f1, +0xbc3b8549, +0xfb639bc8, +0xa23b8b3c, +0xe140817b, +0x7c1471ed, +0x2827052b, +0xf20ad543, +0x18b069e2, +0x418a8ede, +0x8f34678d, +0x3a83804e, +0xf65f5e11, +0x31c38694, +0x483c03a7, +0x76010a92, +0x1685b032, +0x26f1bcb7, +0x25ccd371, +0xa96ebe47, +0x611db87b, +0x48644246, +0xcebe73f9, +0xd137ab2f, +0xde5b0f5e, +0xf5871475, +0xeb10447d, +0x8accd8f4, +0x530a541a, +0x3bb872be, +0xd8ef50e7, +0x9e2e88c8, +0x523b7b87, +0xb9dd0476, +0x6a810e2e, +0x9be766d7, +0x46bcdfb2, +0x49b2f4f9, +0xa579aae7, +0x1d772ae9, +0x0b072c1b, +0x38a2b581, +0x6b5015d5, +0xb5905239, +0x983e6fc2, +0x8f583133, +0x3e4ffc37, +0x158889ed, +0x8c57e2f1, +0x2626e574, +0xce3322bf, +0xd8cd5281, +0x43e897f0, +0x45d027a0, +0x31d5e520, +0x8ece3ba6, +0xfc22629b, +0xd2dfe268, +0xae0ae6c1, +0x8623f728, +0x30227dd4, +0x372ba38b, +0x6bf12978, +0xf8ae71f6, +0x41b126b2, +0x731bbbda, +0xd2258aa4, +0x7940636d, +0x9acc02ef, +0x61ba0abc, +0x9aef086e, +0x1018b815, +0xc3b623e2, +0xa582d333, +0x3953eaaa, +0x459a68fd, +0xe67847c4, +0x7d564ff4, +0x4822ff54, +0x9f8233c3, +0xcc6be0c8, +0xe343f5c3, +0x1c05fe30, +0x44792d78, +0x33c6d8ba, +0x60b98233, +0x2babe73d, +0x98b2d098, +0xb4b7645d, +0xc1ce1201, +0x59f845ff, +0xf106bbcc, +0x06e04284, +0x439524d9, +0x24a36217, +0x8e8a7a87, +0x5c164dda, +0x80473970, +0xee8e17ff, +0x9fd43aef, +0xc30495cc, +0xd117bf66, +0x67fc3ab3, +0x775f80ab, +0x89e898cb, +0xb5714d11, +0x4ec27179, +0xc3bed1c1, +0xdc4078d2, +0x10b9e59b, +0x5de0f485, +0xef4fde8e, +0x7acf7052, +0xffa266ca, +0x4051f237, +0xa985de3e, +0x7bab2054, +0x3c142d88, +0x59e8ddb1, +0xfd4bc474, +0x7f2d0e7a, +0x751b0bfd, +0xd3f319dc, +0x903a6033, +0xf1e12ab0, +0xafb6ab7f, +0xba5ef716, +0xb3f6c6d9, +0xdb924309, +0x864812ec, +0x9286fa41, +0x944bceb0, +0x0ccd1704, +0xac28825d, +0xd85b7666, +0x2867cffe, +0x49d526d9, +0xa2584d48, +0x597b8d72, +0xd72957c8, +0x2ab9586a, +0x869b8a07, +0xc3b14826, +0x3286d4d1, +0xb772faea, +0xda43fc80, +0x18067037, +0xe4220fd5, +0xc65e9873, +0x80cdf369, +0x4a110009, +0x5c9cbb6d, +0x468bef4c, +0x0c86ba4a, +0x75d8ef6a, +0x41e07ec2, +0xefe5f7ee, +0x91539009, +0xf91ca5ec, +0xfeab9bda, +0x4a48188f, +0x633b1c65, +0x009341d8, +0x5f84bbca, +0x9f318849, +0x56546cca, +0x691ad32a, +0xb2886300, +0x4b97a12e, +0xfb94b6fa, +0x7c52c168, +0x534222e2, +0xf45e2c18, +0x6544487c, +0xd4193039, +0x25f90e57, +0xad11a044, +0x7cd116fb, +0x6c8b914e, +0xcf12da8f, +0x344b3fb2, +0x42f97a1e, +0xa599c2b1, +0xc5dc69ba, +0xa83ee8b8, +0x564507cb, +0x645c0311, +0xed3923d5, +0x59e1b183, +0x03d135c3, +0x0736046c, +0xd57b7379, +0x56fe67b1, +0x53062473, +0xeb4ceb70, +0x815705a2, +0xe26184c3, +0xa0ea75ce, +0x0b08a9c9, +0x127a8f53, +0x4a9a1f8d, +0xb3046954, +0x4c002fa7, +0x647d56f3, +0xb7b66e03, +0xaf9c2044, +0xb1a3dd33, +0x2c65cfeb, +0xc2349517, +0xda90ef06, +0x0b4184f8, +0x3e5e4bc7, +0x940675fc, +0x86e686f0, +0x74971959, +0x4845aee3, +0x436dc863, +0xbbc94df0, +0x40397317, +0x8f20f491, +0x36e45043, +0xed439810, +0xf8dedb50, +0x0cefb5bc, +0xb2733e75, +0xd96c0d19, +0xb34e0912, +0x0e918dd6, +0x6fa82c97, +0x37477782, +0x64631e25, +0xb2c5f068, +0xbfa87ac2, +0xc43270ec, +0x8fb51733, +0xaee4651e, +0xdcea6944, +0xde987e95, +0xa47de65f, +0xfe5dbe42, +0x75699112, +0xe96af073, +0x903950fe, +0xcd529fe8, +0xa1a875e9, +0x93dc1ce8, +0x80799d26, +0xf315be17, +0x33f2724e, +0xaf97e211, +0xda8bf541, +0x3f65ca8e, +0x6555efbf, +0x441669d2, +0x0b43bc37, +0x35e3f6d9, +0x5c663800, +0xd73f57d0, +0xfb1929bf, +0x41d631e7, +0x01f81ac5, +0x32f30825, +0x4c3cb6f2, +0x18189fc4, +0xc128be30, +0xf006c8cf, +0x7083ec87, +0x52109ece, +0xf2b4bebe, +0xe5f38ddc, +0xbd37f9b1, +0xf9fdce78, +0x5eb5c5fe, +0x271a3d31, +0xdbe89db5, +0x666e24aa, +0x3296906c, +0x54ca4046, +0xff7aabc6, +0x60186f3b, +0x0a42ba5c, +0x9df10e13, +0x84abcb0c, +0x024c414a, +0x6c585057, +0x92e6eca9, +0x3306706f, +0x829a6c34, +0x521cd283, +0x861eb9c3, +0xae913585, +0x9a64ae6b, +0x867a0b14, +0xde9f3b81, +0x7b99478a, +0x648c2094, +0x903df62d, +0xca1c8ed0, +0x4d73b7e4, +0x942ab89a, +0x6869771d, +0x3291ef47, +0x46f7c4c3, +0xaafc4dca, +0x7a197a01, +0x4598d437, +0xb4a6d2e4, +0x9b3f5d1f, +0xb750c9a8, +0x80006ec6, +0x6fddd82d, +0x5eacbe43, +0x9b60c6b0, +0x17de166c, +0x0cb7ed0c, +0x5bee2eb2, +0xf8ae34ab, +0x34d030e4, +0xe969222c, +0x119c780c, +0x12bc4b5a, +0xa2fd59dc, +0xa026a833, +0x54098c0c, +0xa763badd, +0xa1c7d2b9, +0xb5132661, +0xef012809, +0x0aa7e326, +0x64480c23, +0xd30edde3, +0x6dd021c8, +0x834120d8, +0x9dd4a295, +0xd30c531d, +0x41bf4cf8, +0x199f52de, +0x3478ab90, +0x6762092c, +0x0d83bc9b, +0x0767d340, +0x8aa64562, +0x93a45934, +0xd85d7193, +0x1750f52b, +0xd4d5173a, +0xa2e0adde, +0x91e89c0d, +0x11d88a46, +0x9afa4aa5, +0x1771a758, +0x7987b518, +0xa56b3b5e, +0x448e122a, +0x60efb7d0, +0xf44b3c9a, +0xcea28417, +0xf061a468, +0xefa3ffe3, +0x16fb6a83, +0x9707fe61, +0x0f429b2e, +0xc0dc174d, +0x2a2819a7, +0x3c28959c, +0x4a4e727f, +0x8c7c5390, +0xcc4e048c, +0x669dc76d, +0x323878dc, +0x86ebabe3, +0x3a513312, +0xac8ea5a6, +0x9c6b441e, +0xb717a176, +0xe2fee4c1, +0xf32134ae, +0xce4c23c4, +0xde35ae51, +0x43e346a6, +0xb3cdcb26, +0x05961ca5, +0xdcacbfdc, +0xee84d4f3, +0x15bc1006, +0x30e1790f, +0x25851dad, +0xdfc81c7e, +0xb9d7980c, +0x84584721, +0xbfe36cf1, +0x7e3b4391, +0xd96087c1, +0x87fd7067, +0x539db1f6, +0xf33cbde3, +0x3490266b, +0xcaa859e7, +0x3df6d6b5, +0x9d472175, +0xcb211d48, +0xe8e41650, +0xff4010f3, +0x628c7009, +0x0b28b3ae, +0x13f576e5, +0x9eabbcb0, +0xdb19973e, +0x8f00e95b, +0xd08cf267, +0xaeb046ff, +0xfe27acb5, +0x792ab73e, +0x2b67d80f, +0x5949e13c, +0x6cb6c1ba, +0xa1bb8894, +0x8a0c5129, +0xc38497b0, +0xadbe064c, +0xe3e2d4ed, +0x45730640, +0x0dbec24d, +0x691c1d36, +0xe86c49aa, +0xeffb4113, +0xb7e1ecb1, +0x93a76a57, +0x453909eb, +0x4002785c, +0x9b144a7b, +0xfe806183, +0x355305a2, +0xba1c0601, +0x32abd6af, +0x3751f9da, +0x4e11ca30, +0xaa6fb941, +0xf907ccd7, +0xa74bcfc5, +0x18c4638e, +0xebae0896, +0x19b0d291, +0x8b440a4e, +0x6f1a3f37, +0x8e536380, +0xead0b5cb, +0xbde30358, +0x27c96dce, +0x8f898e95, +0x23f35674, +0x4b37dc2f, +0x59466dd1, +0xd2717638, +0xbc9ccbbf, +0x5a4d0411, +0x88d93126, +0x815cc46f, +0x59f9eed2, +0x6c69c0b3, +0x4bc39c57, +0xa09c945b, +0xcfbeef87, +0xe63b5ad1, +0xf5f7a7da, +0x1167466b, +0x7b8087ed, +0x6fc2999b, +0x4215b248, +0xae04e6e8, +0xf5c62895, +0x62a265db, +0x6feffb1d, +0xddf821fc, +0x2c04a21b, +0xbe188b87, +0x66ddf99e, +0x5bb6459a, +0xc10a0684, +0xc93360b1, +0x06362683, +0x58007ee9, +0x71f83cf5, +0x753ab0be, +0x9c279866, +0x59838a8d, +0x9645471e, +0x496b94bc, +0x601f2b47, +0x777ff2f5, +0xc54ddda6, +0xa7e63905, +0xc5775e5c, +0x5c4f9f13, +0x9e4b3789, +0x54a5759e, +0x78345bb4, +0xed676b5f, +0x247c1e28, +0x1d7834f1, +0xfe73bcf5, +0xa74a2ca7, +0xb7966853, +0x341b00a4, +0x6ec6707b, +0xa03b3bd9, +0x91b56b7c, +0x407482e3, +0x0875e47a, +0xe1285afb, +0x220bdb6c, +0x41fe7e52, +0x6d1907c9, +0x408912f0, +0x8e79508b, +0xa8c26b4c, +0x5d3ece38, +0x0ea23c6c, +0x4b430b1c, +0xd1bc9bc6, +0xb4081c7e, +0x72077432, +0x69ddd370, +0x0430c392, +0x305e924d, +0x2f8c8951, +0xb35700e4, +0x4165008c, +0xf5abfea9, +0x5bb67522, +0x8826b08b, +0xdfe02fbc, +0x2b8801c2, +0xbaba5e77, +0x340b3d6b, +0x4a15b138, +0xf11900f8, +0x054d4e00, +0xbe402c0c, +0x21d38f81, +0x8d79c08a, +0xfaf68719, +0x536b1ee7, +0xf550445a, +0xdcc71208, +0xdb1c2dad, +0xae838ad1, +0xd60a7e73, +0xc155e56c, +0x52311e41, +0x53cd9afb, +0x04f6574b, +0xf341691a, +0xe2a9a653, +0xe06fbce8, +0xc5905861, +0x04eec9f7, +0x262e89e1, +0xe9a00f97, +0x52f929a7, +0xb0553c11, +0x982351be, +0x053608c1, +0x6284a3da, +0x3d7766d2, +0x0b5255ec, +0x4efaf7e3, +0xf0dd0605, +0x495d5b69, +0x4e600f74, +0x3e90078b, +0x5cdd094f, +0x8ccbfbbc, +0x6e676a46, +0xb947f12c, +0xdfeea2af, +0x46c7adaf, +0x831768e4, +0x00617424, +0x790f437d, +0x9f32b6ed, +0x30ddcd37, +0xcf36700f, +0x6660e87f, +0xfb413cc4, +0x56a6f212, +0x318e0fb6, +0x89124cbb, +0x7753a58d, +0xf2aaa3b6, +0x16f823e9, +0xcf45d9e7, +0x5e8c30e6, +0xbd43b24b, +0x7841d29a, +0x40955cd6, +0xd67c3e22, +0x1aae524d, +0x223cedda, +0x405ca50b, +0xc31ec4b1, +0x035eb941, +0x9d2e16ab, +0xddd8c859, +0x4fa37027, +0x32a6260e, +0xcc4aeeff, +0xe9aadd48, +0x9dcecac3, +0x4db98acd, +0x95b99d28, +0x58aea302, +0x3c5d7005, +0x68d7b224, +0x4e260501, +0x6dd0ad3c, +0x89f2ab5e, +0x722afe30, +0xd7e6221b, +0xb15634ac, +0x8b19bc3d, +0x694d6e16, +0xb5cd9168, +0x5eff1c55, +0xd0abf6e3, +0x8fd6f998, +0xc3e3affb, +0xbb48cc3b, +0xa7678171, +0x6e63087b, +0x7803fdea, +0x180e984f, +0x160d6b8e, +0x896425fe, +0xc80d1fe5, +0xfbee2240, +0xcd3d2c27, +0x67882604, +0xcfe690ba, +0xf9a84d5a, +0x76e25e10, +0xf3e0ed44, +0x08651e13, +0xb9bf4d77, +0xdb0b780b, +0xa0039933, +0x29509513, +0xda37747e, +0xf70bba85, +0xf3906bb1, +0x3c71e2c4, +0x07a2239c, +0xa1e8ef6f, +0xca13ca98, +0xa2d10206, +0xa113f786, +0xaa551894, +0xc13eea49, +0x64c917cb, +0xb4b7cbca, +0xef449ee1, +0xcc2ebb2c, +0x75cf57e2, +0x02f25259, +0x6201d953, +0xbbf30d16, +0xc19cc20e, +0xda4ea705, +0x53e9e5e2, +0xb172fe5b, +0x91c85301, +0x6a7b9fad, +0xd827952a, +0x5ac18396, +0xe589d85b, +0xd6ed56cb, +0x2eb16dc7, +0x653be6da, +0x3a016a3c, +0x16cf2183, +0x6d7bdbe3, +0xbd546bc7, +0x9c6a0749, +0x3f6d6c40, +0x5bfc05ef, +0x365a3abe, +0xc53dccab, +0x1570d96d, +0xfe6c4a21, +0x9e820d2f, +0x509edb9d, +0x561a81a4, +0x8e4e2023, +0x8ab8b51d, +0xa0675719, +0x1ce3cbf8, +0xcef5731d, +0xbb0a1848, +0xe208e40d, +0x71b35cd1, +0xf823ce88, +0xbf8b2dd9, +0x17f94ad1, +0x92af56de, +0x0c9d7811, +0xbea3c997, +0x6f391fb5, +0xf46216f8, +0x208d9a24, +0x10ec2f8d, +0xc02420a0, +0x333ec27d, +0x7ee9f5ff, +0xccd01476, +0xbc5ef707, +0xd4803e9b, +0x5f66b4df, +0xd186bc66, +0xa1d2332e, +0xe2e37696, +0xcddbb979, +0xfea40a46, +0xa3dee032, +0x0bac75b4, +0xd3e15b39, +0xfc1d450c, +0xb99857d2, +0xb348322e, +0xa670110f, +0x1f648302, +0x84c7eb04, +0x0590b0f9, +0xc08f71e6, +0xd6d166d2, +0x060bfa0c, +0x6615feff, +0xafa4b4ed, +0x5975b372, +0xeae2f435, +0x75f38d35, +0xcee6b575, +0xe6dd5639, +0xaac9ce5b, +0xdbf059b3, +0x540fb43d, +0x8404d8a6, +0x1107a3f8, +0x067c46b6, +0xdffc4394, +0x9517836f, +0x2ac3fa6c, +0x2c0dd124, +0x79c04a84, +0x79080f3d, +0xe9c413c9, +0xca289aeb, +0x4a8ff774, +0x898c0ad1, +0xa07736c3, +0x5feb71bc, +0x3e109cd4, +0x8a6b6c80, +0x7cc4cc4e, +0xbf99102c, +0x1e36eb49, +0x276bc49d, +0x8790cd3c, +0x0a1a70dd, +0x026d4723, +0xdae902aa, +0x95477d09, +0xd0267fd1, +0xf79b34b8, +0x3ec244b6, +0x2eac7b40, +0x4a3669b0, +0x69633d56, +0xcecc4570, +0x6875e0ef, +0xc15c3a97, +0x86cb649a, +0x34433086, +0x0e9679d9, +0xd4233204, +0x8c245f44, +0x931ebdb8, +0x0e3ad635, +0xcdc97797, +0xf0e0a894, +0xa8e2558d, +0x12d3f453, +0x63cdebec, +0xdd429e24, +0x3db7aad3, +0xfb0a442f, +0x0d26d617, +0x23050777, +0xb4398134, +0x12cafd8d, +0xb62b29ed, +0xbf455fea, +0xcacff703, +0x51aaab77, +0x468c4e90, +0xe4ef58d3, +0x6f1463f2, +0xac8c6f88, +0x7246472f, +0xaf7b32be, +0x603e6946, +0xe641394f, +0x0c7bf351, +0xf4014ce0, +0xf1da5969, +0x57c4296e, +0xdc542539, +0x13b2788f, +0xa5f54ecc, +0x800d6fa0, +0x08efe5c0, +0xfd38332b, +0x4ad6134d, +0x88a66d3e, +0x429b19aa, +0x71d15f6d, +0x9402971d, +0xd6ec34b1, +0x7bf6a637, +0xb218a286, +0x73a92e0d, +0xac915287, +0xa01267fe, +0x08d329b2, +0x5de23b2b, +0xf69f2985, +0x0a215a51, +0xe649c998, +0xecb97b3f, +0x601cefbb, +0x17ed46e6, +0x96c2aaf8, +0xcb1e2980, +0x0741946b, +0x6a189e60, +0x74d18436, +0x6d1d0946, +0x9bf13a76, +0x50a22ded, +0x366f5164, +0xab0b5264, +0x18d8a243, +0x987122e2, +0xa316cf32, +0xb2d21758, +0x965b5c45, +0xc269f1b7, +0xdb3d34b2, +0xc4a2ef08, +0x21656521, +0xfb8f5e0d, +0x5a3bfaec, +0xdabfa8da, +0x899bd2a3, +0x938e37f7, +0x1197571e, +0x95d0d9c4, +0x54804f3a, +0x588303a0, +0xcad7eda0, +0xb66aeccf, +0xf09adb3e, +0x07ea2be5, +0xb03f3660, +0xf016ddb1, +0xa591ba72, +0xd9ec9461, +0x8a7477b9, +0x799d51ad, +0x864604e4, +0xb6aae8c0, +0x1cd9bcc3, +0x7aefcdd3, +0x1f49dce8, +0x4ab5519f, +0x9f81946e, +0xe468344f, +0xf0050a04, +0x79b6aefc, +0x41d3da7c, +0x717996e0, +0xb5ab6313, +0xcd27e680, +0x0a1e77ed, +0x600b9d53, +0x2cc7cae4, +0x08caf88a, +0x33521ef9, +0xd7c85fa4, +0x6efdbd5a, +0x015879b6, +0x847a5b0f, +0xd5395b4b, +0x74d02559, +0x4fa5e73b, +0x52e75d25, +0x37ab597d, +0x4325e2ca, +0x6d05ea4b, +0xd13c9029, +0x87d960f9, +0x5dc22183, +0x69bd3732, +0xa5f783fe, +0x694c56d7, +0xd044f27d, +0x6132d265, +0xd839b9f0, +0x73493baa, +0xcaf1c770, +0xb246f473, +0xb0ba7e1d, +0x78f2a8ab, +0x6450dd30, +0x60cee083, +0xb4dbe6e2, +0x3ae6747f, +0xd515c9a2, +0xcd972fc6, +0x64bc7ac3, +0xbaf15768, +0x6995a982, +0x9ad2a9f0, +0x737bbf42, +0xbb3c9591, +0x0b34a58e, +0xc94257dc, +0x53a28719, +0x66aa5555, +0xa24016bf, +0x3b8b0c51, +0xfe146f61, +0x3bffb4ba, +0xc36ba734, +0x510ecf07, +0x370a9f47, +0x551aab40, +0xa286c2c3, +0xc520aa2f, +0x919967e5, +0x83fc241e, +0x787f8750, +0x2935bc71, +0xbef0531c, +0xe0f757e0, +0xf63e93cd, +0x28d54a72, +0x142e305f, +0x4359f26e, +0x9f4453ae, +0x72954a05, +0x1bc153d4, +0x983b2aa0, +0x2e22628b, +0x12a53a59, +0xcb147563, +0x8de1bb51, +0x6f2cf871, +0x7253c66b, +0xd1afa902, +0x51ca3717, +0xb03147ff, +0x6ed504de, +0x73d5a43e, +0x1512b235, +0x58f9896e, +0xd5e60caf, +0xa867089d, +0xe159ffdc, +0xb1070110, +0xe33b4da9, +0xe2616634, +0xf371bbf2, +0x3ee50ded, +0xc8567177, +0x396b6be1, +0x3f53a393, +0x584006b7, +0xd47ebce6, +0x82cc8977, +0x2af210e7, +0x54cec73e, +0xfd76c317, +0x099a9aee, +0x451739da, +0x203f6ef9, +0x2c7cabc2, +0xea5b0a08, +0x5ebb35e2, +0xf3e899fc, +0x39f85457, +0xba5cacc6, +0xe578fd7e, +0xe4f1c3f5, +0xf9b29ada, +0x8289d3a0, +0x76ff2c0b, +0xe4b87438, +0x7d6581b7, +0xaacc7e9b, +0x6e9894a8, +0x67c2f968, +0x824e8153, +0x011feb8e, +0xa48c4385, +0xf3f0123d, +0x8ffa8e3c, +0x2dc0d6f5, +0x755f0c8b, +0x9145e369, +0xb51dc644, +0xe43ee4ac, +0xa8eefa1c, +0x3b31110b, +0x3b32bb17, +0x5bf10bf6, +0x43207fc9, +0x2adcddd1, +0xb952baa0, +0xe2ebfa61, +0x9f2ce392, +0xd1893116, +0x3663748e, +0x941b0823, +0x9cc7cf27, +0xf1e5d2f7, +0x8a66c0c6, +0xa0446b35, +0xd7a99926, +0x53354d42, +0xa181041b, +0x6d79dd77, +0x188bb0fa, +0x7af4508f, +0x3dcca9ff, +0x26ef6952, +0x21f0fdc9, +0x93cc0e0c, +0xd251cd11, +0xdf44e310, +0x58b0ba83, +0x475d19cd, +0x35751f78, +0x4ae9aca0, +0x39313db7, +0x2b5865a6, +0x752c065d, +0xa2e5a090, +0xfb4945c7, +0x33c59024, +0x06f7c4a2, +0x7e739368, +0xdc2c3921, +0xb2c68f7b, +0x7e6dc10b, +0xbeafad6d, +0x7b0281a1, +0xdd50c04b, +0xf3c7a85c, +0xf6916f11, +0x311dcc0f, +0x993aeaa9, +0x99cc72ff, +0x48c11e25, +0x9e3437b5, +0xafe967f5, +0xf360f1ae, +0x11d0a48d, +0x2d1ee21a, +0x65e3105f, +0x90d0e82b, +0xdc1dc381, +0x4cc4a025, +0x92dc71d6, +0x799f4f49, +0xe3adf755, +0xb67b8344, +0xf8810dda, +0x02fceb3a, +0xa4e7029e, +0x4da27632, +0x3d3aa74a, +0xa1db7db5, +0xa74a896b, +0xfe2a7490, +0xf9222cb6, +0x819b58a5, +0x81a685b4, +0xb0c27e0f, +0xf9167ff4, +0x2a927355, +0xbd402852, +0xd7e60aa3, +0x2c098797, +0x1887330b, +0xc6e9f671, +0x52ce5caa, +0xb2102e63, +0x86047f7b, +0xe6afe5fc, +0xc27e9649, +0xe9cbc818, +0x81e30efd, +0x59b9b67d, +0x26be1ade, +0x72ee559f, +0xc41fc308, +0xe8ee3151, +0x202cc0e6, +0xcdd38437, +0xae790c22, +0x92a1d64f, +0xb6c76532, +0x36b83346, +0xb25fa1f1, +0x6d226461, +0xa2cc8bdf, +0x34c9ebf4, +0x7841c01d, +0x05c6b17e, +0x134ad299, +0x429e149c, +0x4c31279c, +0x59f5d1dd, +0xcebc430c, +0x0587f45f, +0x277e016c, +0x3671f2a2, +0xb5a6bf33, +0x11b8cc04, +0x53341a6c, +0xe07bddb4, +0x50994e8f, +0xff1e12f7, +0xeb31d227, +0x481d0867, +0x0315c25b, +0x80770ab4, +0x6787afc2, +0x85025fc5, +0xf1c6999e, +0x6882a04b, +0xb195a7e9, +0x56a392fa, +0xb2d916cf, +0x3b571516, +0xfe4e6585, +0x3a2cabde, +0xda2d901e, +0x8d954c56, +0xa77af7d2, +0xe8de256b, +0x3a37b322, +0x6b3826e6, +0x72e4976e, +0x4fd9377c, +0x766f5468, +0x7377b1f5, +0x5ecfd738, +0xddf3315f, +0xd27b8e44, +0xb729de1f, +0x3a914cc4, +0x9499fcc0, +0x10196a52, +0x346deb46, +0xab36dbcc, +0xc91e352e, +0x91283fa7, +0xeb35a35f, +0x7853b5d9, +0x1210aab8, +0xa45f1816, +0x17cd34c1, +0xa8bfb19e, +0xeb1328b2, +0x9bd94119, +0xe5ac5413, +0x1a6c8a20, +0x92cc1c5c, +0xfa293cf6, +0x9f7bd55c, +0xc20120b5, +0x7e4e2925, +0x72006536, +0x65485349, +0x8fda1844, +0x8069932c, +0xc007b660, +0x55c145a0, +0xc9944fdb, +0x97908ca9, +0xf2e800f3, +0x5f0c2053, +0xd17530c1, +0x8ae45185, +0x517e2211, +0xbc5d16e6, +0x32358ee4, +0x07d530df, +0xefedef6f, +0x4ab5b62d, +0x295afac4, +0xb6c4ff83, +0x9a756674, +0x29f24d51, +0x27528152, +0xf147f6e9, +0xe53219fd, +0xf39effd5, +0x4d7c0f1f, +0xaf2ee304, +0x2a85bd9d, +0xee7d9bdd, +0xa12c1f84, +0x0d88b2da, +0xe79d8704, +0xe48e7c9b, +0xa1be3d6c, +0xaa3a5f9e, +0x905a8864, +0xca32acf7, +0x12ebea17, +0x78c0cafe, +0x537b691f, +0x5c0bd809, +0x8d8631a2, +0x215b784e, +0xa4226901, +0x37cf0d57, +0x2db10b4b, +0xcaabf08d, +0xcfe18ca5, +0xce6f879d, +0x8b518c63, +0xcb207464, +0xc1e5faa2, +0x6c7faa71, +0x0721ebc3, +0xd71d789a, +0x2475c917, +0x5aa8e4f2, +0x4cfa2d3f, +0xc99f4992, +0x0c7cfe98, +0x86165739, +0xe0226bbe, +0x978c67fe, +0x1b1ccf18, +0x09a5e824, +0x483bfd69, +0x6f41235d, +0x167d53b3, +0x8096312c, +0xc1cf4cd7, +0x62cfe523, +0x1deef094, +0xce432de7, +0x5e0f7037, +0x8518f8be, +0x30fd052c, +0xe9edb5e7, +0x96ba7987, +0xba404f07, +0x7e5f9294, +0x5ead6037, +0x5e4243ba, +0x243f9937, +0xf8857bf8, +0xa3b6cce4, +0x85b8d1ed, +0x2a6850fd, +0x1cafda30, +0x4153ffa8, +0xfff36caf, +0x8fda1514, +0xec8e3af4, +0x7f6acf1f, +0x237a3c62, +0x01973743, +0x01ae4126, +0x48f56e17, +0x097fa9d8, +0xd43146d6, +0xda7f3440, +0xb5d1cdf7, +0x3db85afb, +0x099a52ff, +0x444a2b2b, +0xbfd01b90, +0x40c6d0d6, +0x545cd3a8, +0x2be35779, +0xda454e20, +0xb344d1da, +0xa78bae7b, +0xdcf1fd0f, +0xbb24240e, +0xfefc8909, +0x720d682f, +0x3b79a14f, +0xd6267ad9, +0x9fe72749, +0x16859f84, +0x35746dde, +0x80babe95, +0x7ae36277, +0xc6e8823b, +0xf9dc7b7b, +0x7672415f, +0xdd460fb9, +0xa766bbd0, +0xe8fd13ec, +0xba840e99, +0xb660d633, +0x4c385e87, +0x0bdd815f, +0x5ea76670, +0xc2dec909, +0xb5ae0993, +0xd93e90c3, +0x12e205b2, +0x3942f8f6, +0xa91e820f, +0x4c7d6142, +0x7d571c5f, +0x8b9086bf, +0x11e21466, +0x9d44bdc2, +0x59a5bb40, +0x6379d63e, +0x96913b84, +0xdd752db0, +0x8457fb06, +0xbacf2fe2, +0xd3f232ab, +0x7d6040ad, +0x8feab24e, +0x0d924d1b, +0x02480fb8, +0x24634f72, +0xf101d07f, +0x59ac400c, +0x4ffa9292, +0x89a9cefe, +0x732403b2, +0xa5911fe4, +0x97002e47, +0xc640bafd, +0xa118d55a, +0xdceb9238, +0x76d7f8f9, +0xd723e3a3, +0x60b5c34b, +0x4ac3d96e, +0x2bf71445, +0xf0f494a7, +0xa0a35d92, +0x44473053, +0xc4530340, +0x9e32a72f, +0x3bb46717, +0xf91b6e26, +0x95114d32, +0x41a6666b, +0x4ac59aae, +0x3f31254e, +0xc26df449, +0xacd8741c, +0xd8a1871c, +0x5e4ba137, +0xac26edd4, +0xb44f165d, +0xfcb9d7f9, +0x1d8bda26, +0x31bfbdb8, +0x425be8a4, +0x210cb36d, +0x1b726b97, +0x5325a15e, +0xf0545abf, +0x50439c90, +0x67f0f8fa, +0x38bf8819, +0x1fbd7547, +0x902af3e0, +0x0fae72b8, +0x0fbde83e, +0x8f805411, +0xe19e9997, +0x63a31011, +0x5df4f381, +0x625bc88b, +0xba328db9, +0x2ff2b58c, +0x17aa67d8, +0x2954f0d2, +0x5f56972d, +0xd4c993b9, +0x33a7f6eb, +0x0d9552ee, +0xe3902950, +0x8c4f7dc6, +0x3cb65995, +0x630572b0, +0xc18806a2, +0x0a6c21cd, +0xca859ac4, +0x0786099f, +0xc9aa4b98, +0x20508b02, +0xec739a0f, +0xb74d654e, +0xcb132bab, +0x9e1530ce, +0x1ade59c5, +0x7bd6582c, +0x02a5bbde, +0x78d3d131, +0xca40e9a4, +0xf2d24d5f, +0x0dd9145f, +0xe5d7029f, +0x02b935a9, +0x797deda8, +0x98b09226, +0xb4f4981a, +0x255f1384, +0x3f92d346, +0x3a525a00, +0xfac54623, +0xcd9e6b85, +0x59c58f50, +0x77911b19, +0xc4204838, +0x9a65005a, +0x4816c002, +0x352e3d09, +0x04b6f42c, +0x38bbd131, +0x3675d59b, +0x0c636b6b, +0xf0841e42, +0x80697fcf, +0xdba71d55, +0xa55f2baf, +0xdfe14970, +0x61ca340c, +0x68c1abbe, +0x06bb9fa1, +0xc3970dc9, +0xd86ac4bf, +0xc746c04e, +0x752b23b6, +0xde08fece, +0xc224f47d, +0x41eb87b9, +0xc8d7a88e, +0xeb37ddaa, +0x4e8f10c0, +0xa74fc2d7, +0xeb1bcea9, +0x28ecad75, +0x07329620, +0xefd2b59d, +0x165ba3ab, +0x335f458a, +0x5d898fa7, +0x86b464a2, +0xa4ec0e35, +0x6c34b81f, +0x3cfef36c, +0x96186f64, +0xa0053546, +0x7960c1f1, +0x585718e1, +0xb04326d8, +0xae46baa3, +0x98302fe8, +0x2954ee09, +0xa019709f, +0x0f1ab45f, +0x35a654d6, +0x1541918c, +0x27408644, +0x231d566c, +0x9a78067c, +0x83d088f3, +0xd495035c, +0x5926c62c, +0x83d0d28f, +0x6137db36, +0xe46c9001, +0x9319411c, +0x3273d51b, +0xce6622dd, +0x2a2af94d, +0x17f740ca, +0xbf467c1d, +0x24e72144, +0x81f1e928, +0xaf536845, +0x7c6fc34b, +0x53c9cf3b, +0x09f4a4d3, +0x13ad0882, +0xfad50c43, +0x5ca80560, +0xa9d18d19, +0x628a29c8, +0x19e7a788, +0xd1360d94, +0x843dba79, +0xb337b385, +0x66e4bbb3, +0x67eaa250, +0x3fe51043, +0x5c5a1508, +0xeaf25491, +0x37852590, +0x216929e0, +0x7c6d49e5, +0xcdb46925, +0x610daa46, +0x85932744, +0x5a5c3084, +0x093aff50, +0xcba56778, +0xa0ef7f0a, +0x9bf44aeb, +0x294e2c84, +0xc1ad3f68, +0xabc8096a, +0xb797d841, +0x58cbb825, +0x4e1f600b, +0xde3829d5, +0xf5d99c91, +0xa9dabf96, +0xe2947c8f, +0x44a9d4c4, +0x4b362074, +0x9ef0a830, +0x2a9569c4, +0xc34a6dcb, +0xa5865fbf, +0x58ea4549, +0xc47a36e2, +0xbb417af9, +0xe1868a02, +0x2993d6fa, +0x535522d8, +0x09bdbf7c, +0x9a4dda84, +0xfe53355e, +0x77aa8c3d, +0x40b98e3c, +0xefa94069, +0xb8608ea8, +0x88363d4c, +0xded38c6c, +0x1ced8226, +0x93a2562e, +0x28cef721, +0xebd0f2ec, +0x9d715e4c, +0x1831df69, +0x736bd1fe, +0x928fb5b6, +0x49a28f10, +0x1e1137c7, +0xa246f5d1, +0x942b932d, +0x5b87ff28, +0xc8781175, +0xb58dae8d, +0x1a830b01, +0xced33a69, +0x7bdb71e8, +0x08e83a7a, +0x46782b34, +0x801deb95, +0xbd5415a6, +0x7d85b659, +0x56b86d0d, +0xa559338c, +0xd4741f6e, +0xaa044616, +0x1668d11c, +0x525447a0, +0x1b3dd038, +0xfd432d2f, +0xc11b9eaf, +0xeb70d719, +0xc6ac2584, +0x0739fae8, +0xa468b257, +0x495630f5, +0x514a37f0, +0xb305924f, +0xfea437c4, +0xb94d62e9, +0x7feee77b, +0x66eed6ae, +0x8cc0d7a4, +0x1b7908f9, +0x464ba8ea, +0xb854251b, +0xe0ba7502, +0xe8530ee0, +0x7ea18b83, +0x4a93fb36, +0x7c1a7b6d, +0xd375e9d5, +0x6f191e44, +0x4dd8a708, +0x392b4ffe, +0x135bdbb7, +0x74899fd1, +0xcc190304, +0x151d8718, +0x7683f4e1, +0x06f8d287, +0x73e6a453, +0x074cb038, +0x3c20ac99, +0xb73551de, +0x6c772603, +0x91101211, +0xc672a879, +0x0b189722, +0x2abed8f6, +0x3252cea5, +0x15fa5cf3, +0x2058f704, +0xceac7a09, +0xcd647d12, +0x37933089, +0xbae5e4b4, +0xde6669e4, +0x1aeb9a5f, +0xfcfd8397, +0x652e73bd, +0x015e64b9, +0xe139feb0, +0x869112b0, +0x3b1d02a6, +0x240e5566, +0xa416e24a, +0xbe4333f2, +0xe6528c29, +0x88baa044, +0xe8032854, +0x30ee7568, +0x5c9eadc1, +0x089b4a35, +0xf060e03e, +0xba360389, +0xb93220e4, +0xc4f89c13, +0x7e4f8fe3, +0x1d8ef2b6, +0x1f6a08c7, +0xf36ee4d4, +0x4f24530f, +0x4b1b351a, +0xe61c8918, +0x9e64ab2f, +0xf6e13955, +0x26ec0495, +0xc01feb10, +0x255eb4c7, +0xe11cb103, +0x761c2201, +0xb45ce42f, +0xe62ec328, +0xe09f557f, +0xf737074e, +0xe28784dd, +0x02787cb9, +0xf75eece2, +0x27d0225e, +0xe92fa4f0, +0x6749f620, +0x16157b23, +0xaf94aa59, +0x11a094a8, +0xb3b4fe0f, +0xb77d38f1, +0x649ae923, +0x24c12b72, +0x3c026120, +0xffdfff40, +0x2999821f, +0x3c22f890, +0x4f5ad56e, +0xc8bda6c9, +0x35fcf5f6, +0x1c75a328, +0xc95cbcd8, +0x2e2403c4, +0x9e5e7c46, +0x5d63169c, +0xfbc8cc19, +0xfd3468bc, +0x3af03541, +0x013a9d0c, +0x74a35a15, +0x6a95f2cf, +0x6846e0d1, +0x092b08e9, +0x0cf60395, +0x82579d8e, +0x3e8234b1, +0x96f0fdad, +0x3067d932, +0xf5c1efb8, +0x13620dfb, +0xf0884fc1, +0xc010279b, +0x0b526eff, +0xa559381c, +0x65f32953, +0xb59564bc, +0x5658723b, +0xbc1ea858, +0xc9636510, +0x0499ea08, +0x399caf1c, +0xe7abbffa, +0x3038171e, +0x92d413a0, +0x92b2fcd5, +0xb0bf54c6, +0x6f0dfec9, +0x453d1964, +0x6f537457, +0x714e6cdf, +0x2c0bb050, +0x84d7a20a, +0x2e3949e6, +0x47ce68d4, +0xb1d89a74, +0xa613bb4d, +0x4951b165, +0x3fc103fd, +0x04f2f72c, +0x08c667db, +0x833ffd83, +0xb1d7a318, +0x19265e3f, +0x9a013494, +0xa4716ed0, +0x538031ed, +0x0ab53d07, +0x6be09d9b, +0x869a8ea9, +0xbaf564f8, +0xe7d3f200, +0x6d3624a6, +0xee4969ca, +0x39203e55, +0x537962b1, +0xc1a8a24d, +0x15e7792b, +0x14e937ea, +0x216b66c6, +0x9fd22159, +0xf1515171, +0x554cf49f, +0x8d12901c, +0x63cdcfe3, +0x97fa66b8, +0x4a398249, +0x374fcc0e, +0x4f73fedf, +0xb2422ea9, +0x29c47c0a, +0x43ec57e2, +0x88abadc8, +0x29a305a9, +0x2d46b9a9, +0xace38e13, +0xb3df96fb, +0x66bac304, +0x451d610a, +0x0dd6f140, +0x16e8dac4, +0x9b992d6f, +0x9d0d0c7e, +0x7cea6dd9, +0xaab9b55b, +0xcb672c75, +0x152db14e, +0x0be97413, +0x5fbc13b6, +0x6c06cb1e, +0x47b589bd, +0x0fccce1f, +0xb62a315c, +0x1ce19234, +0xe0d9801e, +0xc013bc67, +0xe28cd0e2, +0x8c4e60fa, +0xa4b758f9, +0x545e0ff4, +0x6b5cf234, +0x81d20230, +0xdd3c0037, +0xb0ebf8b0, +0xef1a8ca2, +0x1d004e4d, +0xd50f3ca0, +0xcf0389b4, +0xe6f9075c, +0xab1d482d, +0x4200d6b2, +0xf09a1a11, +0x15bf2001, +0xa1519848, +0x8327082f, +0xc1b55806, +0x2795b726, +0x3e745a71, +0x51775ac5, +0xdf78b857, +0xffb24322, +0x569eaeb1, +0x576d0858, +0x560ce47a, +0x056a52a9, +0x31ff8814, +0x54ab2921, +0x94a9d9a4, +0x6e00899b, +0x76a7bacf, +0x6d3020c6, +0x3455c319, +0xcd8ab1e4, +0x027693c8, +0xd8392d72, +0xb2c4e33e, +0x4d74258c, +0xd65bf991, +0xa066acd1, +0xc8523f57, +0x8863dfb9, +0x718d40e5, +0xf68065ea, +0xa0fe1384, +0x345abaa2, +0x59460908, +0xdeedc2b7, +0xb4275dc6, +0xf48c1757, +0x2466b68d, +0xb6d9b0a5, +0x2c1558c5, +0x3e930149, +0xb7e1d3ef, +0x5729adb1, +0x4304817d, +0x40ff38cc, +0x1295c228, +0xbf7684d1, +0x27a342cc, +0x152b306b, +0x561c9cc9, +0x9f7ca7df, +0xe871c179, +0x705bfaa9, +0x3b0facc1, +0xd67b4ba4, +0xf9f7efc3, +0xba91a567, +0xeb67adc3, +0xcc17aeb2, +0x233732c4, +0x689380a1, +0x8050dd36, +0x4dc10831, +0x36f7067e, +0x7181a44b, +0x713da6f9, +0x1f0c41b0, +0x5fccd762, +0xa7fd027b, +0x5091ce5f, +0xf04abb80, +0xb1272355, +0x176a850b, +0x53f5440f, +0x8c5f56ab, +0x29a298b4, +0x42e4f566, +0xd1502104, +0x48d89cc5, +0x3f7543f6, +0x2af4f592, +0x966ed0a4, +0x70444a5f, +0xe35eae1f, +0x7736a913, +0x3d1f8e95, +0xe72bf48d, +0x1a1cda6c, +0xc9621cf9, +0x68832c06, +0x17b69441, +0xfc675950, +0xe9df0c77, +0xa401d71b, +0x975e79da, +0x0714c41c, +0xeeb68319, +0xfef3f1d3, +0x6f1e4ed9, +0x4d0c74db, +0xf3f9d3f4, +0x4d926160, +0x0ef6729e, +0xc4daafae, +0x110f3c8e, +0x415ebd33, +0x95121cae, +0xde4bd6be, +0x014f67b0, +0x6c8fd2d5, +0xa4142844, +0xa7c22d2d, +0x314c1001, +0xb7d9a289, +0x85cec410, +0x9abcb00b, +0xc78bde35, +0xb376d08a, +0x1d5f64a2, +0x48589f40, +0xa7a55745, +0x7c7c55a0, +0x987b146d, +0x6aa8e50e, +0x189a5170, +0xb910942a, +0xaf1d3caf, +0xe2e67e56, +0xc4fcaca6, +0x30dd46be, +0x7c00f5de, +0xf4d30bf1, +0xf1560d45, +0x5b5e019f, +0xfee30768, +0xcb10762c, +0x8d931f51, +0x3b26c223, +0x8efa0d51, +0x91162e74, +0x0e2e3ace, +0x87d8b9a7, +0x0d41681f, +0xe7b3075c, +0x0d83042c, +0xa8bdd0ad, +0x1307ab49, +0x25cbbdb5, +0xd3a55f47, +0x47853317, +0xa5aafa65, +0x7d48f54e, +0xafe9e0a8, +0xeba64275, +0xff1b6def, +0x5dc57f11, +0xd809ee01, +0x28e31b6c, +0x64dcd5a9, +0xd12cb9c2, +0x184093d4, +0xce5b186b, +0x206d6102, +0xd40cf7dd, +0x21f065b6, +0x497454de, +0x5f116c96, +0xd2dcd851, +0xaf6dae78, +0x5d7c4fe8, +0xc32135a3, +0x187ad625, +0x217eac8c, +0x86e4edd6, +0x5542efd7, +0xbc84cf04, +0x63d78bdf, +0xc8bcdc87, +0xfa03f393, +0x3d58d72e, +0xfa4855e0, +0xee8c79ee, +0x42a99a9b, +0x7da2c758, +0x72710a64, +0x64582d97, +0xe7f6ffb2, +0xbd129071, +0x558f45b3, +0xa835e6f4, +0x102e7235, +0x5f4bd1c7, +0xd4029235, +0x190003be, +0xbec0acf5, +0x98eb67e4, +0x4ec90324, +0x0c31f03b, +0x833484fa, +0xa76079e2, +0x36a4da50, +0x5bd4d06a, +0xa2b04916, +0x10547800, +0xa06d2a27, +0x26ae89fe, +0x9c4e2fec, +0x4caed017, +0x3ca4b193, +0x521acae1, +0xf12b10a2, +0x8efcb09f, +0x88361f36, +0x631fbe5c, +0x454ec462, +0xaef49f59, +0xbe34a559, +0xc8c27615, +0xda4670ae, +0x5ae64fea, +0xffca3661, +0x6a7eefe0, +0xc1522519, +0x04cee92c, +0xb7b3869b, +0x1590edd1, +0xac5857de, +0xe5352045, +0x6cda6040, +0x7cbdfb78, +0x29f9ad90, +0x581684c9, +0x21f283fd, +0xba762c00, +0x7e8e974f, +0x9619fcde, +0xbb03ef57, +0xad470d15, +0x5ed71186, +0xfb9e78a3, +0xbe94b05a, +0x7876c157, +0x52864b73, +0x4541a6b7, +0xc0384f17, +0xee338d07, +0xf596bb4e, +0xc4065c75, +0xa64f968b, +0x42a00db5, +0x4fc1688c, +0x68a88a14, +0x22f4b14e, +0x58a9cfab, +0xe4b20df4, +0x091bcd4d, +0x4c918f6c, +0xa9119f74, +0x303dc007, +0x4a4fb78d, +0x672a2601, +0x392d5eb6, +0x0e6567df, +0xbd1fb47f, +0x0724b32b, +0xad2298be, +0x2d246a94, +0x7929a0be, +0x4ccbd587, +0xce17bcec, +0x5ae7d327, +0x5ec17d37, +0x2a0db53c, +0xc6c0d1d6, +0xe780665f, +0x289a8b06, +0xf475db4e, +0xe7713444, +0x657a4abe, +0xb1b36b47, +0x5d240e56, +0x816ef038, +0x934743f7, +0xc895177c, +0x5aa85895, +0xddcaa1e4, +0x315d69d6, +0xdb191573, +0x9562968e, +0x402e75c6, +0x62ec4361, +0x917e0fa7, +0x4f5aaadc, +0xdf497894, +0x3d46fe02, +0x680d942b, +0x7ec803ba, +0x42415c27, +0x382253d2, +0xb55b4613, +0xe195184c, +0x6bb7fc41, +0x97736076, +0x95b7fbbe, +0x9380ba23, +0x02ffd0b5, +0x97529cdc, +0xdd088e9c, +0xee5baafb, +0x9b1c8486, +0xb9e15dbd, +0x1d308fd6, +0x60c4a324, +0x89efe14f, +0x31363d92, +0xc5198c7a, +0x2f536d6b, +0xbbc49c22, +0xa61efa1a, +0xd07b973d, +0xa0d837b9, +0xca0faf64, +0xc84be752, +0xf6a4e5dc, +0xcb3fb3f0, +0xb6ea5035, +0xf09709b8, +0xdbf39e48, +0x3dfe6ff9, +0xe1755df0, +0xee347411, +0x1477b4b4, +0x5289e602, +0x8f231059, +0x53a0f7aa, +0x61703331, +0x29cd8a49, +0x9864a574, +0x37a47cb2, +0xba0aa0fc, +0xe584fd8c, +0x1abfdb6c, +0xc553e7fe, +0x44f8751b, +0x1694c0fc, +0x4e14cb59, +0x7155f91d, +0x81dd6690, +0x28aa9188, +0xd8a1c9bb, +0x4f803c23, +0x671f4d7a, +0xa9089877, +0x04f7f337, +0xccafae33, +0xab59ea54, +0x67403cba, +0x43b4f5d9, +0x9440f3a4, +0xdf3bdcbd, +0xa1bf9b12, +0xcce32186, +0x50b631c5, +0x103f41cf, +0xdd02b29a, +0x15af703a, +0x2b16d394, +0xbd5c06aa, +0x13da92ae, +0xf16577e2, +0x194047fc, +0xa840aeff, +0x1b54138b, +0x55dc2c89, +0xdb7b30c8, +0x7c8aab5b, +0xce6a3044, +0x39b69f37, +0x512d0077, +0x59a1ee54, +0xefe01af5, +0xd0341fa5, +0x8d629bc4, +0x228b095b, +0xf2d7d40f, +0x377fc137, +0x1c5d137f, +0x8c799591, +0x41a6ced2, +0xdc1707a9, +0x970deb72, +0x43a27352, +0xfe3e0e62, +0xbf3cca4c, +0xb8fedec5, +0x66277643, +0x50649e6d, +0xbd99842d, +0x5a9f90bb, +0x84578e53, +0x3e690418, +0x6424e7a1, +0x2bac0fb6, +0x9b98dd58, +0x97e122b3, +0x5036fc49, +0x52155e7a, +0x2b8dedc7, +0xba6c50f7, +0x3a8abf12, +0xd7668786, +0x6905c64e, +0x37b92b17, +0x02c0bfe1, +0x2c85deb3, +0xc20e58e8, +0x537bc9db, +0x44c6e819, +0xb7d64f1b, +0x9157e437, +0x65a9213c, +0x6ca3aea8, +0xa6191a21, +0xf459bc61, +0xd03b7cfb, +0xb1b6f1ee, +0x03c2da6c, +0x7a2ec61e, +0x3fd39ccc, +0x9747c789, +0x0a9dc095, +0x70cad5de, +0x3d55c442, +0xe6b6825a, +0x1a8707ac, +0xc8828dbc, +0x2c753d3e, +0x1b443081, +0x5918f430, +0x1b678551, +0xcec5ce9b, +0xb8ef0d36, +0xcc186d06, +0xb0c33755, +0x018c2a5b, +0x12a9de82, +0x77d8e553, +0x028eb99f, +0xc3991d7f, +0x0f9895f8, +0x19187794, +0x277efeff, +0xc908bf58, +0x7d02b9f4, +0x0972b8d5, +0xb95a5b5b, +0x82a964c8, +0xa1850d5a, +0x4ae2df75, +0xcce31b72, +0x1b9ebcd2, +0x362a39dd, +0x83e1e3a7, +0x618c91ea, +0x5736dc43, +0x05cd4d61, +0x258682fb, +0x2189524d, +0x66229210, +0x8369bdfe, +0xcd4061a3, +0x4e740743, +0x19d8be05, +0x667d085c, +0xd777efc2, +0xad8e19dd, +0x30269815, +0xe73719f0, +0x09331e0e, +0xea806836, +0x7eb90c13, +0x969e4df4, +0x15b1aec3, +0x37ced135, +0x7c931f7c, +0xe80496be, +0x7e22fa06, +0x13ed7de2, +0x3a8361cd, +0x22f8dd80, +0x2a800925, +0x23f77731, +0x25eb1fd7, +0xefeb4b9a, +0xa0e6e444, +0x2f15bf4d, +0x1bc4e9eb, +0x28bb371e, +0x63cce358, +0x2a92babf, +0x7ecf079f, +0x7599914d, +0x9a07aa68, +0x9824a28c, +0xa256ed76, +0x45ef8334, +0xc8e64296, +0xe399f5f3, +0xc876a2e0, +0x9b7be100, +0x49d658ec, +0x748081ae, +0x6d4b64e7, +0x1ea8730c, +0x68ed2c2a, +0x63cc5c0c, +0x86945b79, +0x59cf6617, +0x6ab5d9af, +0x85f9d5c8, +0x54a38841, +0xb07a3eb1, +0x1fc172b8, +0x0861661b, +0x9449accb, +0x6b41bad7, +0x69df6a7a, +0x62584f7a, +0x8fc6ac43, +0xffe0a085, +0x06f67c8e, +0x8c73d2eb, +0xfb5cfa82, +0x28fb752d, +0x0c09a1ae, +0xa0894e89, +0xc3991f43, +0x2376c1ee, +0xe4499f26, +0x9dadb23d, +0xf465bb06, +0xe87ed569, +0x7cf745d3, +0x7ac901e6, +0xd3daa3b1, +0xf165aeeb, +0xa5d5441f, +0xcd3666fb, +0x5741c911, +0x4805754f, +0x3a9a70c2, +0x57b31c91, +0x88553440, +0x16a7364d, +0x79074149, +0x87f271bd, +0xfc397a0c, +0xa2e733a1, +0x2d358599, +0x657e126c, +0xc714ad05, +0x6edb57fb, +0xb6dbecb4, +0xbbf4252c, +0x7e4af601, +0x980cdf3f, +0x3de2bd01, +0x5ce77cee, +0x0e346abf, +0x1a28c067, +0x3db60a61, +0x370cf7dd, +0x64c7b688, +0x65b7d6f1, +0x66eadc4a, +0x6ac2962b, +0x55c43890, +0xe72534c8, +0x75874ff1, +0x3fbddf71, +0x1b9adcda, +0x2e58a290, +0x5dad72df, +0x52032f05, +0x9d50a510, +0x5a70b35f, +0x40612d09, +0xc71279b3, +0x23ef5297, +0x0afa3b7c, +0x8f72c2f6, +0xd55f2b2b, +0x0f160889, +0xf5e264c5, +0xaf426c01, +0xc6dc9e49, +0x0fbbeac8, +0xb9d543d2, +0xf5965bc9, +0x1412e475, +0x5e805d5e, +0xaa514948, +0x09037674, +0x0845faac, +0x77515c23, +0xf6161743, +0xeacf070b, +0x90da566d, +0x88438602, +0x19afdf55, +0xafb0bff3, +0xe8796dff, +0xd99a2f24, +0x75ca8d1a, +0x7515c345, +0x5b01f85a, +0x1aef1656, +0x36ceee23, +0xcac1c3bd, +0x32059360, +0xce2f8f7e, +0xcadbfad0, +0x2672a4e9, +0x4b7e316e, +0x79d6d9f9, +0x1d76fd9b, +0x1102143a, +0x440fca45, +0xec474f1f, +0x6f79f54a, +0x7dba108d, +0xe8de103c, +0x71fbeea9, +0x9f2dbcb2, +0x72706cfd, +0x895fe04e, +0xffe34189, +0x7a00c796, +0xe53cd0aa, +0x9c9fcf5c, +0xa84d857b, +0x57d11265, +0x0799951b, +0xb3d536c4, +0xd8256646, +0x2c473eea, +0x22a58f8e, +0xb3d95089, +0xb90155bc, +0x0eacb779, +0x49d62083, +0x0013a55c, +0x2b878a6d, +0x88707ad9, +0x3e68c9f1, +0x6aaf0fc9, +0x3bf6b87e, +0x2a5f0dc7, +0x6b8b0a1c, +0x535db3ea, +0x403975ce, +0x4be5ff8d, +0x339d046d, +0x2586bd05, +0x4dd4b88e, +0x74233ed5, +0xdad4779d, +0x3b6537e5, +0x4cc8d5d6, +0x9ae8feab, +0x0ac766df, +0x44c7abbe, +0x11adad15, +0x64f216c6, +0x1b9d69d6, +0x86d365e0, +0xaee8d40a, +0xeb66b712, +0xe98cf103, +0x59672ef3, +0xaf0a5b1f, +0x7a65bd05, +0x710797ca, +0x09f81c6f, +0xb522e0e0, +0xa20c2b4f, +0x795d851a, +0xd9ded6cf, +0x59eb8f5a, +0x98eb414b, +0x24b5a1f7, +0x2ad92a6a, +0x51c2d391, +0xff61806b, +0x375351ec, +0x016a02fc, +0x19a433e0, +0x8a75d8a3, +0x99664d24, +0xf2af57bc, +0xfe1373bb, +0x631486c7, +0x874c0454, +0x876b1542, +0xe6bd5b59, +0x8a0f9623, +0xd18b7fe3, +0x26d5bced, +0x6118c953, +0x9d1e8da7, +0x1618dd34, +0xfb980310, +0xc9481f9b, +0xd5cc632f, +0xf9c6778f, +0xc79ea1aa, +0xf7a8c7e0, +0x39649b35, +0x5b9e76f1, +0xc06e6903, +0x637b0128, +0x8839b5e3, +0xf3219b99, +0x4e07c021, +0xbd4698a4, +0x03f530e3, +0xf9381c7f, +0x9fafe30a, +0xf8085cc9, +0xa35deab1, +0x2ef51be0, +0x219c4b3b, +0xc6f3765d, +0xeda13b11, +0xc9050836, +0x316a703a, +0x0b7f4a7f, +0x4a686422, +0x09db92bd, +0xd266b21c, +0xc0c56eb2, +0xb9fcca35, +0x2f6ce26d, +0x921c5468, +0x15ba68cf, +0x45b9fe7e, +0x7fc04611, +0xf7a4085e, +0x3ec96643, +0xeb884cac, +0xb8608cb0, +0x8e75b252, +0x920be75e, +0xb05d3bdf, +0xc7c869c9, +0x48eda80c, +0x8dd59b67, +0x1c671a71, +0x3b976a5e, +0xae8ccc89, +0x44e29737, +0x5db19522, +0xea022188, +0xf06da85f, +0xfb0c3643, +0xdde5b222, +0xb68961f0, +0x135f8e61, +0x1c82e6d3, +0x81a078c1, +0xd8e79e18, +0x3219f874, +0xabcfdcc2, +0xb1c481b1, +0x2ad7ca9c, +0x61639cf1, +0x686c0cf2, +0xf0a433e8, +0xdedf336b, +0xbe8db514, +0x5a4b0c33, +0x5b091301, +0xc3c77f2c, +0xb08af26a, +0x961526ec, +0x23b9f9a5, +0xf0fc99a5, +0x2d77d898, +0xfc1b7586, +0x5674dd71, +0x2dcd3433, +0x18bea8a4, +0xf7bfff05, +0xe21e2803, +0xe638f89e, +0x1646e041, +0xf64b8371, +0x3e5b9846, +0xe6d7dbdf, +0x513a80e3, +0x4e58dea6, +0x3b6c57ff, +0x57458aff, +0x28e2c883, +0x2633c6aa, +0xf52cf945, +0x87724796, +0xf8fc6bcc, +0xf261765b, +0xb5c91d2c, +0x7999c2c5, +0x7630cc6e, +0xfa3e39fd, +0xc7c26617, +0xf4574f43, +0x34c62aee, +0x78165572, +0x1ff46b05, +0x8bd04294, +0x7c8ddc3f, +0x5625bfc9, +0xcfc4f5b6, +0xbea317f8, +0xaa98ccdf, +0x45a7f747, +0x47b4e408, +0xc91bd874, +0xc07d783e, +0x7e603757, +0x8830a63c, +0xd88aad67, +0xc2834259, +0x6f56e7a7, +0x016fca99, +0x91d53899, +0x5524189d, +0x0dedc98e, +0xde714d42, +0x3dd2d27e, +0x60785b11, +0xddc933ef, +0x9090c3dc, +0x0205a4bb, +0xf6da0cfa, +0x308fa8cd, +0x963b92e8, +0xd6869f6e, +0x09de3e73, +0x2cc8f00f, +0xdaef3149, +0xf8ae7fd9, +0x386c7835, +0x4c664811, +0x9b11078a, +0xfd0e46c1, +0x63574b91, +0x40a3c759, +0x72915870, +0x3b77ff4b, +0x9bbca9e7, +0x37e21e87, +0x865ca930, +0xe297e692, +0xf72bac7e, +0x69b33e3a, +0xff828a24, +0x57d0484d, +0x2135251a, +0x1d712c21, +0x3908d4a5, +0x67d6f095, +0x494b2146, +0x7aeae8ea, +0x8c1619ef, +0x97c89b2a, +0x87f6d252, +0x713780f1, +0x77d63b39, +0x3f9fcf3b, +0xfb274a40, +0x5ded0cc3, +0xcefabb30, +0x19134bd8, +0x8b314dea, +0xc12c5889, +0xff704906, +0x17eb8750, +0xceea9299, +0x3554640e, +0x0f28246d, +0xb7389a0d, +0xc8ce910d, +0x3f022108, +0x33d8a8d4, +0x21f9ecd6, +0xf4a5a395, +0xa0b9e977, +0x3590d167, +0x2175e6cd, +0xaa70164e, +0xbebe01f7, +0xe6eb1622, +0x374f7a47, +0xcfa4d01c, +0x38b50e02, +0x4a18f4a8, +0x9b318875, +0x47f35160, +0xad99f82a, +0xf8594ab6, +0x59c16853, +0xc8c97a1b, +0xf0c7b3d3, +0x0b8f6a74, +0x71da87b8, +0x4291ec19, +0x7ccdf558, +0x77145112, +0xa901c03f, +0x37099d99, +0x89cf2f53, +0xc71b0fd3, +0x5aec87e3, +0x463a9bd0, +0x0d6cb8e7, +0x74644003, +0xb918dbf5, +0xb212504f, +0xee286d4a, +0x192a6a4e, +0x23b13dd8, +0x03a1e131, +0xcf0b1ef1, +0xa13b0ce7, +0x2a778750, +0x08768af1, +0x3c178cec, +0x378c971a, +0x8de11121, +0xf7da3983, +0x1865f9ec, +0x60868e0e, +0x1927f155, +0xfd68c205, +0x314b3716, +0x42542b85, +0x4698ecfb, +0xc9503c4e, +0x9cb8d3da, +0x558ee96b, +0x60966c02, +0x4ea0640b, +0x8c2085eb, +0x9a44fc08, +0xd49c2318, +0xa11b8e51, +0x48493150, +0x48028631, +0x45bf81b2, +0x73ec7650, +0xa119e679, +0x405e8de4, +0xad28386f, +0x16fe8865, +0xd0e94b59, +0x3bcb6811, +0xfe11e56d, +0xf049917a, +0xf5bf8c6d, +0x85b3339e, +0xa551325e, +0x368bf869, +0x57ed6d6b, +0x41967dff, +0x5662e06e, +0x7550541f, +0xad6b6af5, +0x15b148b8, +0x12a62105, +0x83cd9528, +0x32dcbd80, +0x502a6d01, +0x64908039, +0x5f5d57d8, +0x8c50331c, +0x167137b1, +0x89b5a931, +0x00dcca63, +0x7a1bedb7, +0xf56ba765, +0x4a689d23, +0xd540b103, +0xb9f9de13, +0x8242e41e, +0xa3c21374, +0xf95fc2c8, +0x272c2349, +0x8b5bce59, +0xbe46d1b7, +0x86c32cec, +0x4716262f, +0xf642cbed, +0xcf5c6f3e, +0x5098e6cf, +0xdae88013, +0xad094dd1, +0x6e96e805, +0xa4ee7adb, +0xa3bef283, +0x248476eb, +0x1d94c878, +0x7c9f44d0, +0x34a8ed71, +0xc20dad1b, +0x5d8f6a53, +0xca02cb32, +0xcdaba38b, +0xd8d1f601, +0xa2a7507b, +0x5d0893b9, +0x7144eb9f, +0xb9be70f7, +0xe36c9071, +0xc7ef31f1, +0x0960a848, +0xc40a42ca, +0x3108442d, +0x7737f56e, +0x3cd4f1de, +0x9a0a5be9, +0xfba24048, +0x5095d21d, +0x587359b4, +0x3bed5d51, +0x1a81d5e8, +0xe2e6c44b, +0x8d56c2d0, +0x1a9979ec, +0x568ef128, +0xd1d3440e, +0x2569dd41, +0x8a8bbc3b, +0xdfea728f, +0x674ebd80, +0x9b2dd7d9, +0x32cb4484, +0xc39c90dc, +0xcf38cf93, +0x4ab9636e, +0xfd94dca2, +0x7191b99e, +0xdefcf811, +0xcef6ca73, +0xdb5eb08c, +0x278f0c50, +0x56b2d0b4, +0xcf68e5ce, +0xed8b1ac1, +0xf28d49d0, +0x77ee39b1, +0x58fc24d8, +0x4cb0bf7a, +0x1366092e, +0xc28ca498, +0x5e3af798, +0x10ecfaba, +0x467ed33a, +0xa6e97ecc, +0xd6734757, +0x252b7a65, +0x1040fb53, +0xa29b1803, +0x58c2cf54, +0xa03e1b80, +0xcf0ebf5d, +0xd065ed56, +0x7d200f91, +0xd8e8b947, +0x44f743c4, +0x42625d09, +0xa9ea35e2, +0xe9d74b5c, +0x155c25e3, +0x734d712a, +0x73bb1c35, +0x8b89e31d, +0x8cda1a6e, +0xc743ced0, +0x83905ede, +0xaf938d79, +0x9245d489, +0x98abd6ef, +0xf0b68bcd, +0x516ce595, +0x7a1f1dc1, +0xddbb2ec7, +0xecc728c6, +0xa00b5248, +0xc6225f30, +0x06834b2f, +0xcea976f7, +0x58648ab3, +0x72e1772d, +0x2adbfa4f, +0xb92e4116, +0x18341450, +0x08a4931e, +0x192101ab, +0x7ab9bea7, +0xd94123cc, +0xf6154416, +0x933f01a8, +0x4bd3d789, +0x56405f32, +0x84556712, +0xa3f72727, +0xe28abaf9, +0x3cb66913, +0x7ce07dfb, +0xb8355845, +0xd19bf353, +0x88198b5b, +0xebc4d474, +0x3929f1ba, +0xc5037eab, +0x00566422, +0x361641f0, +0xb27ea74b, +0xe33d9f64, +0x42210a39, +0x3b376c79, +0x66f7ea5c, +0x059fa03d, +0x6e907cbf, +0xf2e043ef, +0xe2ef486b, +0x50a0ac09, +0xb975e41c, +0x113d0561, +0xe485600c, +0x7bcc8a48, +0x7b5e208a, +0xa4748cdc, +0xb49836d5, +0xc6379928, +0x2d7e647f, +0x946bd398, +0x25f7faf0, +0x25cc3f90, +0x15c9669a, +0x8b3b645e, +0xcf4240a3, +0x8426ddda, +0x24de1254, +0xbe75d553, +0x158b84f6, +0x4af19bf7, +0xf354d2df, +0xd0ac0536, +0x784bcaef, +0xee92bb8f, +0x608d9f42, +0x846eed27, +0xbd66a9c4, +0x287b8f76, +0xe52b9325, +0x1a3b4da2, +0x782a6ae8, +0xdc50e1fa, +0x2c00f771, +0xd7d196f4, +0xac0fff28, +0x60852f0d, +0xf183b73d, +0x632e9f88, +0xeeeb7fd5, +0x9f15d50f, +0x450aa681, +0xe4d575c5, +0x60945b0e, +0x9130b85f, +0x10bdf370, +0x4b209b8b, +0x913d14ca, +0x9cbd8e39, +0xb75485f2, +0x303884c3, +0x44b52c6b, +0xcd2713a2, +0x90ca8d83, +0xc2a86e4c, +0xb3bd3749, +0x96ac4cc7, +0x0e355c8f, +0xc165becd, +0xf1518761, +0xfdbcd5f1, +0xd057e589, +0x3b1220e4, +0xd3b76f6f, +0xcb6fa163, +0x28a61ef8, +0x3fa43d5d, +0xe1d5b794, +0x9df7e2d5, +0x4e2d1292, +0x936f1734, +0x297c0d61, +0xf2f5fc8d, +0x1ab7a14c, +0x95554885, +0xa7b72cfe, +0x1988dfcf, +0x63a04cd2, +0xa95be6d2, +0x87848b50, +0xe01a2089, +0xbbde1b78, +0x107a9c61, +0xef15de6b, +0xf6d6bbe9, +0x3aa1e400, +0xd6d269a4, +0xd357d2fa, +0x497eae52, +0xb916d61d, +0x059081c1, +0xa9066d63, +0xdca9bc5f, +0xdad70d95, +0xc732faa3, +0xcdc483bb, +0x73576f58, +0xd2137f59, +0x5392c48e, +0xb978fae5, +0x0ff6de6b, +0x075dad34, +0x7df161b5, +0xf81b343b, +0x4f169fc1, +0xe7a3aa89, +0x1dfd3d3d, +0x9cbc08cd, +0x540e2ea8, +0xd27a5eb9, +0x43287a0e, +0x81ab4ef9, +0x62488405, +0x99e3dfe1, +0x13620bb4, +0x7d206685, +0x33b838d6, +0x9f7e056e, +0x55b5f994, +0x8596617c, +0x472609bb, +0xd6542fc4, +0x2610e8ce, +0x6affa2a7, +0x0fe40604, +0x2765e10f, +0x684ad904, +0xe175e69e, +0x9c5a4457, +0xae303a41, +0x2070ec33, +0xa5e12467, +0x9ded6b5d, +0x31d335e7, +0x41324ce0, +0x8847cdab, +0xce4f8f2f, +0x9b3a173a, +0x291d1eae, +0xdda1be98, +0xc26bdabc, +0x68e775e2, +0xdd479bcc, +0x78727ba7, +0xa58926ba, +0x56249152, +0xf9fa1e99, +0x5f826d8e, +0xbe2de6b8, +0xb77363ea, +0xaa90fd8b, +0xc18d0fde, +0x30cfdcfe, +0xa7cf9c91, +0x385d1d8b, +0xba86d7d0, +0x3070576d, +0x1d849eda, +0xd955502d, +0x5975c813, +0xc6ed3db6, +0x637e32bf, +0x00520f4e, +0xf3044470, +0x1e4adaa7, +0x0a75cdae, +0x3253ad9f, +0xea5a8c9a, +0xe05cea58, +0xff1eca3f, +0xef10e56b, +0x3d17c10b, +0xe09e06a0, +0xb7bdc593, +0xc3154a4d, +0xca790b52, +0x216b4393, +0x61aba95f, +0x8d76d295, +0x8783b457, +0x0989cb4b, +0xd28315a9, +0x3cc877b5, +0x2803ed09, +0x4d32d2b9, +0x4c38a051, +0xb8c34eaf, +0x953632e9, +0x1461782e, +0x8824b9b0, +0x09cf7ef3, +0x73bfd168, +0xfb5d0fdb, +0x09e438d9, +0x667f9db5, +0xa98f7b6b, +0xb007827f, +0xe45b339e, +0x8dec1a4f, +0x730a7b74, +0x29b22912, +0x73a4b66a, +0x485c3aa9, +0x5014fa2a, +0x12687426, +0xe06312d4, +0x3f95c9c9, +0x02f9c6d6, +0xbdc0af10, +0x7e25c51a, +0x45f545d6, +0xd40f273a, +0x6331a9ff, +0x8f015088, +0xded6e6ad, +0x049345b0, +0xc3fcfae7, +0xbc1a43c0, +0xc326079e, +0xfdacbaf0, +0xfd5d9af7, +0xb9895fa0, +0x36357018, +0x56de0ffe, +0x64714e0b, +0x62279ac2, +0xd1719cb2, +0x61d0e37e, +0x4b12cc55, +0x3edeb2a2, +0x65da216e, +0x4fd3f0fc, +0xdc8fda98, +0x8875e51e, +0x64b42f62, +0xbf49d552, +0x4134f8ad, +0x6d630ee4, +0x1b84bd2e, +0xb5505d29, +0x1dbd4dde, +0x4b6e0f1f, +0x3b5b6ccc, +0xf8c10541, +0x884f3163, +0x72cecc76, +0x64cc8062, +0xeb4bbda4, +0xc773c230, +0x7a1ac5bc, +0x5e6488bf, +0x438a5761, +0x91adbeaa, +0xcead6ad1, +0x65f0c583, +0xe4a84e0c, +0x8e364fa6, +0x905be7af, +0x5a375816, +0xbd204fdd, +0x56cc5b8f, +0x56c8036c, +0x9fa0ed14, +0xb47f1fa7, +0xbdb58354, +0x9d87c06b, +0x248b8130, +0x69601520, +0x6a1ae425, +0x6cd31540, +0xf2b270c9, +0x0cb9a4d2, +0x90423dcb, +0xc8cc8ca1, +0xd72b0ae3, +0x10d3d40c, +0xfeae28fe, +0x2bb50263, +0xa538b00c, +0x3e7f870b, +0x33c31012, +0x43fa8e33, +0x029c2a5a, +0x895c35a2, +0xd83dd428, +0x25756476, +0xa25bbfe1, +0x0634c234, +0xf2d042f9, +0x60202e65, +0x40565dd9, +0xe448015f, +0xb5ec34ad, +0x52c526f2, +0xb60a9661, +0xa65017f6, +0x1a30196b, +0x3e7d696d, +0x331dd94f, +0x77c0d6a2, +0xd15ee1c7, +0x5b8940fe, +0xc49690d8, +0xad13250f, +0x7a716ebf, +0x8f2786ce, +0xacb47cf2, +0x479fb494, +0xd546f60b, +0x3d658c88, +0x522bb6f0, +0x3532d9c8, +0x8223c615, +0x01d7244f, +0x1104bfb5, +0xb6cb189b, +0x8a46b73b, +0x9c9273e8, +0x2a909c51, +0x1e57413c, +0xdedec3be, +0x2599d7a8, +0x6a5f920e, +0xb0c881cb, +0x35187a17, +0xe59f8aea, +0x9e9264b4, +0x7fe40acb, +0x2c2cb1b9, +0xe8fa2504, +0x954e461b, +0x5cccf42d, +0xd3095f52, +0x093f79ab, +0xc00c9618, +0x4acf779b, +0xd21c45c4, +0xdcb513ac, +0x1ad98532, +0xe5c87b42, +0xcc59e0cd, +0x1083b40c, +0xda46a62b, +0x134db1b4, +0x91aa7d60, +0x99df65ff, +0xe4f03e23, +0x66690712, +0x092f2c74, +0x2c0bdba2, +0x37b84cb2, +0xeb7d0d7a, +0x82c49764, +0x152d7e57, +0xc865fb75, +0x1f02a422, +0xe45c4539, +0x1670ef0a, +0x0f73f86b, +0xb2289aa3, +0x3f43673c, +0x7bd1d24c, +0x9927e507, +0x2c3b7f96, +0x02186ebd, +0xe56e7a8f, +0xf61e2ba3, +0xdc6fe231, +0x91c4fe79, +0x5a6bdc20, +0x2d2e785d, +0x0dceeaab, +0x96625e8d, +0xf4b4dfe7, +0x54560918, +0x3cdc42d3, +0xee34e231, +0xc9582eb1, +0xa257a5aa, +0x119b9a05, +0x8505fdfb, +0xb0bd4f78, +0x282ad560, +0x043fd096, +0x7316c3aa, +0xbb22d56e, +0x319fdd1c, +0x9a07ea23, +0xd8461266, +0x7d5aefc2, +0x5f8b6924, +0x5bf985b6, +0xd5107a14, +0x82bc5cde, +0x1ddbf05b, +0x53f95748, +0x51806b90, +0xdd5ccd84, +0x4e29424b, +0x27291397, +0x59b8c351, +0x9d2f27a2, +0x3b8e3bf7, +0xfd263a9f, +0xbdae3332, +0x47857731, +0x4a9d19cd, +0x53afa716, +0xb4f20c53, +0xb6107d03, +0x9677e97e, +0x1d41ad06, +0xa8300017, +0x180da76d, +0xb774367a, +0xdbf1e8e1, +0xaac869ab, +0xa31917b5, +0x7e346c17, +0x8f26eebf, +0x0f191e10, +0x7b2cbb6a, +0x76ed4a5d, +0x7831de23, +0x5ab47c55, +0x0d0055ec, +0x888d09a9, +0x90a1c72b, +0x20a05a20, +0x3dca3f44, +0x3a01894e, +0x40e105e6, +0x428faaa6, +0x5fa2ad55, +0x64b7bf57, +0x17690148, +0x2b1ddb7a, +0x0e16e78b, +0x003f6925, +0x358fdff9, +0xc1004904, +0xff19ff5a, +0xbcc5a3d1, +0x90d0d64e, +0x6e27d080, +0x714ce15f, +0x1d4ae017, +0xcc87f7aa, +0x77acfbf6, +0xe829021c, +0x89eaa239, +0xbcf4c7ba, +0x48c5f165, +0xcaf5f19c, +0x635f9968, +0xedce8e41, +0xf6a4bed5, +0xb529f10b, +0x8dff27aa, +0x8eaee699, +0x99d56af8, +0x3ad7f2f7, +0x2e26f86b, +0x683ffdb9, +0x700d64b3, +0x1db0d66a, +0xac3c108b, +0x91f7397a, +0x0f902efc, +0xb98f6c55, +0x397b9c85, +0xa714f009, +0xca299be4, +0x12972697, +0x05048c1f, +0x8891c5cc, +0xe7229cbe, +0xe286d6f7, +0xfec7b74f, +0xc21f95ea, +0xd914aaf6, +0xb5fe1375, +0xed9a2fa4, +0xa0b45b04, +0xe68439c2, +0xd335fc28, +0xe34b296c, +0xe6114ed9, +0xd51a8696, +0xdce5f1cd, +0x70cc135f, +0x1c8aa61d, +0xf3595636, +0x2405e096, +0xc0627e6c, +0x910109fd, +0x742620dc, +0x8a3552c6, +0x528346ab, +0xfeac34f9, +0xbe73ea29, +0xa3e99478, +0x865aefca, +0x28938b52, +0xefbb4a60, +0x5a8fbc41, +0xb0181723, +0xd977ee86, +0x836561f5, +0xd12995e4, +0x0e67d0ef, +0xd56a5385, +0xe65176aa, +0xa0174119, +0xaf3bf750, +0x226bb56b, +0x8c255741, +0xea477433, +0xa20884a6, +0x280b9a0b, +0xe7d358b5, +0xb03f8865, +0x34c6b004, +0x8b5dca36, +0xcb368bbe, +0xb734d21a, +0x0755df6e, +0x4084979e, +0x1514e0d5, +0xd9aaa7c7, +0x54fd5295, +0x42d9ffb8, +0x99a23e48, +0x750db55b, +0xe9a15976, +0x3f6a8d88, +0x4b87c0ee, +0xc83a3541, +0x1ab6fb73, +0x70b05961, +0x0326d651, +0xceb693f5, +0x4dece988, +0xa2f04ec8, +0xfc4304fc, +0xd1fcb853, +0xc51f62fb, +0xe162f143, +0x63a34b92, +0x79e47c76, +0xa7fc2c65, +0xc05b8ae9, +0xfc99e78b, +0x9d4c9070, +0xe8355310, +0xb53bcc6d, +0x7492049d, +0xf6658cfa, +0xf4ec4fa8, +0x623103ad, +0xa132e9a4, +0xdd58ee92, +0x9a959694, +0xeab54f65, +0xa56a0eb2, +0xd6683509, +0x88c10659, +0x3810b10d, +0xe76ba2ad, +0x411179ed, +0xf3ea1724, +0x49b1f4e4, +0x5eb784fa, +0x69fabc16, +0x8eaf58db, +0x166f0e7a, +0x68d7f5f6, +0x02a804c8, +0x2f6077d3, +0xd28848be, +0x29891b85, +0xb0e8dcb1, +0x7a77d46a, +0x759a0972, +0x97669ef4, +0xe36513ae, +0x88a3d638, +0x72497be1, +0xba8658ce, +0x84593f20, +0x5a17c76a, +0x7deb4f47, +0x76f2483a, +0xd683768b, +0xfd345659, +0x5969f7b2, +0xe70dfbc7, +0x4a1848c4, +0xd6645700, +0xb54d2ebd, +0xf63ea0b6, +0xd20726ab, +0x78618cdb, +0x3b9dd333, +0x3bdc2716, +0x60d73a80, +0x7534a0a9, +0x00432e73, +0x15c23aa2, +0x30031457, +0x0b5622b8, +0x8bbe3314, +0x5ef089ac, +0xc1f15c08, +0xd010dd83, +0xc148e410, +0xf4cf083d, +0x6e9379cf, +0xce241f5c, +0x27c8b95f, +0xb4a8756b, +0x4e1372b9, +0x6ab5fd01, +0xc9b4a6d1, +0xaf4008a3, +0x5af50b27, +0x80e40d2a, +0x005c101e, +0xc373c2f1, +0xbfd21574, +0x2046e2ad, +0x1528a133, +0xee833f70, +0x9b8488b3, +0xb7d20009, +0x77e63a22, +0x057e528b, +0x1e600759, +0x3e0749e8, +0x7f4a958e, +0x3b6b8450, +0x3ffdff06, +0x5fd46620, +0x900e7950, +0x37ded3d1, +0x4801e872, +0x87bfc987, +0xc137a3a1, +0x6c8ca22a, +0x238289d9, +0xcddfe33e, +0x19f5c090, +0xaa270579, +0x5af14fe7, +0xb230370e, +0x7168498b, +0x4ffb7a7b, +0x26baad6a, +0x2d2a8c0b, +0xa904b712, +0xe0b98e2e, +0xa4d168e6, +0xdbefcee6, +0xeb2314e6, +0xf80c66b0, +0x25ad2a83, +0xae45311c, +0xcd31aef6, +0xf69623a8, +0xac0543e2, +0x86ba51be, +0x90302059, +0x1e657740, +0xc530092c, +0xeb843aff, +0x356e00dd, +0xcb3c79ba, +0x23e7f81b, +0x062dc0cd, +0xbe6662b0, +0x4291ff12, +0xb6befdf6, +0xbcebdb03, +0x5ec2881c, +0x88ff1515, +0x95ac5f57, +0xee49a2ce, +0xb7cb6409, +0x7e79022e, +0x958f23f6, +0x917b7b88, +0x58583aee, +0x1f85c777, +0x6208cde7, +0xa4687669, +0xbd17c83c, +0x859d0052, +0x0d2c59ef, +0x84cf3188, +0xab3c34dd, +0xecc48311, +0x635cb72f, +0xb8058233, +0xe9e241ec, +0x0a51064d, +0xad93ce76, +0xa5ceb698, +0xe81b2f5e, +0x62ebae93, +0xe9e4f8b1, +0x8ec571b5, +0x01ee2a92, +0x99b6c0b1, +0xbc053db1, +0x0269e3db, +0xcfe687d6, +0xda525feb, +0x1fc6930d, +0x363de501, +0x22c3ab65, +0xee6225d9, +0x6dafbf93, +0x7a735178, +0x533ded21, +0x6af90f51, +0x72e09fa7, +0x509c4a24, +0x4e1c831f, +0xe9929227, +0x384dd033, +0x0aee5c6b, +0xec5be7ba, +0x81abbc5c, +0x5f188d95, +0xd6de613a, +0x5c4069b6, +0x576b60d0, +0x9c82cfcf, +0xceb5052d, +0x4619ed43, +0x65516cb1, +0xf937c6e0, +0xfe5f5b28, +0x8f2f8531, +0x66a1c30c, +0x9e287799, +0x9ee20c0c, +0x4daf6dc4, +0xd22c8ef6, +0x7e800ec0, +0xefa217e9, +0xc303e071, +0x9254110f, +0x30fcf85a, +0xdc2bbea1, +0xc6f39df7, +0x139a721f, +0x55dc58ec, +0xcd918ea6, +0xc57d19e8, +0x820998f1, +0x9e97b0e0, +0xa219f4e4, +0x8b7fea9b, +0x601ca496, +0x0c89a2e8, +0x08a35bed, +0xf97f7bb2, +0xab344f90, +0x31efe622, +0x17031a5d, +0x8ddf3e5a, +0x96e4df66, +0xc12e952d, +0x420ccc6c, +0x5a8672e2, +0x4c1c2532, +0x591111f2, +0x1c9bbe8e, +0xff39f7da, +0x0ac6f467, +0xb8db78f1, +0x5c8d479c, +0x6d8fff00, +0x855bf3cb, +0xe3924846, +0x632b9e61, +0xeb1e32cb, +0x9e967b95, +0x69376754, +0x96c8ae7b, +0x079fdcb7, +0xd9688ddb, +0xbcb82cd4, +0xf316b258, +0x7395e239, +0xcd991ea5, +0xe0c488aa, +0x3e116d6c, +0x421899c8, +0x6c6648c4, +0x34f39791, +0xf3992c98, +0x27fb2e1a, +0x732e303b, +0xda27a51c, +0x0c8d776c, +0xc00548b6, +0xa09d6a58, +0xb6b53e08, +0x936e20fd, +0x3bff8e77, +0x16f9bcd1, +0x2df8399f, +0x5d56ba24, +0x29e83817, +0x5b127b48, +0x775a8598, +0x876376dc, +0xbf614e3f, +0xd51f8120, +0x6cae19b2, +0x8af4f28c, +0x50ae0e9e, +0x52ef7273, +0x885aadd2, +0xddb6f3e4, +0xa8165424, +0xc7eb2edb, +0x10f59532, +0xfcbb9d92, +0xbe41313a, +0x118650e7, +0x7e411b44, +0xddc150e9, +0x3bd0e313, +0xe57242f4, +0xc0fdc488, +0x67b98074, +0x72ba27f2, +0xabcab22f, +0xabd0e56e, +0x681b05b7, +0xf8550ead, +0x713d9ebb, +0x1c6b5912, +0x11c9e3d6, +0x24061857, +0x0c2a9098, +0x0450716c, +0x674e1772, +0xc62695e4, +0xf59bbdda, +0xcef25912, +0x5c51a3bd, +0x7053acb3, +0x2e5dcc92, +0x873a4a87, +0x6bb4cdeb, +0x99e1fd3e, +0xa38621b0, +0x77c88a51, +0xa4ca84c1, +0x06bb3948, +0x98e4afb8, +0xc14a59e3, +0x5b39bfaf, +0x23f97fda, +0xbc9b3f76, +0x1abbd048, +0x79be16ce, +0x3e4f3df7, +0xdae4bd1c, +0xe09f85f8, +0xb312f6db, +0x4de71c9f, +0x561ab685, +0xe6200e6d, +0xdd4597da, +0xcfcb94cd, +0x8a26f704, +0xa379491d, +0xfd0645d3, +0x591ccbfd, +0x88995eac, +0x3db80cfc, +0x50ab0d4f, +0xb9915137, +0xa73f303b, +0x653ea93d, +0x7fc1f1b6, +0xfe9f29c0, +0xc662eefa, +0xc8a35380, +0x694680e2, +0x620325d4, +0xf8669474, +0x8ae0e80e, +0xea3c97b0, +0x656fd3d6, +0xcba3dcd7, +0x16ef71b0, +0xa23aad03, +0x12e0924a, +0x6168ca59, +0x07fd72ea, +0x39678e87, +0xaf5dc207, +0xa4291d7f, +0x910be08e, +0x7a18c034, +0x0a539fb9, +0x99d822b1, +0x5e91d8d5, +0x6550313d, +0x6a27178a, +0x030f6a17, +0x60001e2b, +0x907a8627, +0xc955b3d2, +0x6aeea34d, +0xc3bc8442, +0x25d57b8d, +0xc3c510fc, +0xf4a16456, +0x4ce67809, +0x56b65ca5, +0x49390d14, +0x9fdd9df4, +0xdeb4b355, +0x9ef4461e, +0xec0407e5, +0x4a543c9c, +0x3cee23ce, +0xe397422e, +0xb330914a, +0x1917ba2c, +0xc785b19f, +0x0137ec76, +0x6222cac4, +0xdea69cb8, +0x4f7a111d, +0x164bc79e, +0xe1b98eb4, +0x7c397961, +0x9a9caad3, +0xedee71eb, +0x2bc330dc, +0x09c89f5a, +0x1ae8d6ae, +0x82ac3ba8, +0x7ef0705f, +0x16dd4165, +0xd9a767cf, +0xf5e61df1, +0xb301ab52, +0x95a2f7ac, +0xcc601fc3, +0x64b0d55c, +0xe3deb17e, +0x11627656, +0xc53fe154, +0x6efbc355, +0x990985d4, +0xe1a38bac, +0xfe616345, +0x9558fe63, +0x06028973, +0xcc70e6ec, +0x88bc77b3, +0xa8350462, +0x71a772be, +0x2108e090, +0xb758c7a7, +0xc8f720ff, +0x43f98fbd, +0xb1d77f42, +0x971cf4b7, +0x0bb310aa, +0xad4c2b32, +0x124f877a, +0x0d21606d, +0xa9464b71, +0x9a68757c, +0x26c1bb42, +0x6e41e0df, +0xd3642904, +0x784fb122, +0x4df28ea8, +0x61f3c935, +0x83aef158, +0x4bbe96e3, +0xdb98a2a7, +0xbabddd85, +0x8c9eea3e, +0x7999e597, +0x6b8659fe, +0x4fdf8bf4, +0x619fb787, +0x01cea891, +0x39adf95f, +0x9e63935e, +0x0374d864, +0xc19856f0, +0xbfdca6bd, +0x21e15e5f, +0xc2bb0c48, +0x61ea401d, +0x73e895eb, +0x0d7090a1, +0x8c6f4cfa, +0xa73eb4b7, +0x43ff4f18, +0x31d1e4eb, +0x9e2a43bd, +0x26d33263, +0xc9658268, +0xd5ac239b, +0x02116421, +0x08e426f4, +0x48610ce4, +0x7471d495, +0x358be7ef, +0xb098fd8a, +0x71b450f9, +0x7106c747, +0x438a4491, +0x75e02aa5, +0x939712fe, +0x2daca1f6, +0x050693d2, +0x9af4cabb, +0x088e73b3, +0xe5ec8e0b, +0x38136dbe, +0x42255569, +0x11656713, +0xd728f03c, +0xb225fd70, +0xebf46fcc, +0x9c56c9d4, +0x37e5c8c4, +0x30e2ffc8, +0x5da27e90, +0xacd3b8f0, +0xda2603ac, +0xf26c7098, +0x0020358f, +0x16988309, +0x509ce18f, +0x2c9385bb, +0x6ccac9e1, +0xa45a1141, +0x01f4f9bc, +0x5276d168, +0x55d59bfd, +0xb1381d60, +0xca241b13, +0xf906b1a8, +0xa120f034, +0x85e67e63, +0x3a3785b1, +0x3a802529, +0xad0db492, +0x715d4705, +0xb3864a44, +0x9c4bd39c, +0x9a4cc24f, +0xa770588c, +0x620acfbc, +0x24c66bbd, +0xb8797568, +0xfe5bf8ee, +0x9d9181e3, +0xfb7e4c6f, +0xe44fe22a, +0x56a8ac31, +0x8bf0b40c, +0x9b92bca6, +0xa8529efd, +0x45990ca5, +0xbef98022, +0xe5cfe715, +0x9edc46a6, +0xf7e97406, +0x1c6c4b0f, +0x45b57877, +0x032757ef, +0x17f3be53, +0xae973e6b, +0xa2d59ab5, +0xae998518, +0x1d279bbe, +0x518369c5, +0x088af5c6, +0x021b5262, +0x054fb96e, +0x52074590, +0xc29a5fd6, +0x7c287658, +0x917396e4, +0xa5180664, +0x1d28f629, +0x1d26ee3d, +0x39b2539e, +0x5f33e62b, +0xe27ebb85, +0x826c6363, +0x6ca77c97, +0x472b0a5d, +0xe8f5200e, +0x3505b3bc, +0x747083d4, +0x00485649, +0x136444c4, +0xbe972575, +0x809457cd, +0x1030e3fb, +0x62708770, +0x539a7ca2, +0x27deafad, +0xec54ce9e, +0x1460b52c, +0xc1fb4f28, +0xe6b8cf53, +0xa6e29603, +0xc4d129a2, +0x8e84a05a, +0x61c11fd6, +0x4ccfc849, +0x3386674a, +0xb3516746, +0x69d1aa94, +0x44bcf352, +0x15c290c3, +0x3c5b2174, +0x4d226fbd, +0x9fddc4a0, +0x73ded96b, +0x9d08a13f, +0x7d185333, +0x33d59f31, +0x7ff0dd99, +0x4bd8b8ec, +0xd5544a49, +0x466b60bf, +0x3fe0e07c, +0x29e5b4c2, +0xdb773e16, +0xca484d1b, +0xdfde039e, +0x8c7ee4f3, +0xc5b367dc, +0xff0341e7, +0x4f1901fa, +0x31d33d6e, +0xb28f07b2, +0x0a51c3bc, +0x40ee9d58, +0x60340e26, +0xc63bedbd, +0xe59a63bc, +0x1686815a, +0x319e89b0, +0x38b901c3, +0xd92da036, +0x0a62f0ab, +0xa25b4955, +0xf330fd6b, +0x04448bc9, +0x214733b6, +0x7508c44d, +0x87d087be, +0xf1404ab0, +0x723314d4, +0xe9579709, +0xe7d4bbeb, +0xd1515aeb, +0x75473bb0, +0x1bf266cb, +0x49153e2a, +0x5454f9d0, +0xfd8174fb, +0x5875c647, +0x516ca60e, +0xe6722b3e, +0x870996c9, +0xd48cc3fb, +0x7ff057a8, +0xc37babb1, +0x768c9791, +0x80797b2b, +0x76240d4c, +0x813ba105, +0x6b825f9a, +0x240d8f12, +0xacff7c74, +0x58e70656, +0x1fb916fa, +0x80198b94, +0x42a2b44e, +0xd47f3248, +0xb3f2826e, +0x6ed66205, +0x3f27d3fe, +0xa953aaca, +0xb6fbfab9, +0x18f69993, +0x7b73fab9, +0x75c54835, +0x9ee83b61, +0xdd4e18e9, +0x76ea5f6b, +0xa498fd31, +0x57750eed, +0x9c05dd73, +0x78949e35, +0xf802eda1, +0x820490f3, +0xadb807ad, +0xbf69b2f9, +0xe6fb6d98, +0x2310f533, +0x6d3e5952, +0x48410799, +0x0b984491, +0x01fc2b2e, +0x8a265d25, +0x1cb9f0e2, +0x3b4098b2, +0xf4227d88, +0x8021c178, +0x5ab30d29, +0x5dc125ff, +0xf947c9e8, +0x215cb41d, +0x5792c8ff, +0x44d9330e, +0x7b93ea15, +0xac4941a7, +0xf7f68b89, +0xb598a873, +0x575e4510, +0x405597d2, +0x808e1831, +0x966d3d2b, +0x73a0a8c5, +0x1b10f6a4, +0x81b5c98e, +0x739f938b, +0x3153d52f, +0xedf3ee6a, +0xf19f2e97, +0x7274777a, +0xe4e2d85e, +0xd79c2933, +0x5534fc24, +0x986bb9c4, +0x2208df8a, +0x36d56ad2, +0x8842c881, +0x85cc14d7, +0xfdc16e52, +0x83c969b7, +0x809a986f, +0x239cd901, +0xb65a3352, +0x052b0d7a, +0x1c26a4c8, +0x7cc95857, +0x11609345, +0x5b155f2b, +0x95583d33, +0x61f18a1b, +0xaa77a439, +0x8bdce024, +0x4f22c5c5, +0x644e5129, +0x1d9e1f63, +0xdd78373a, +0x6e24313b, +0xe72c5a51, +0x1a213b8d, +0x44a91d47, +0x4bfa03ab, +0x1e337544, +0xb50d0826, +0xf0463b4b, +0x5bbcd676, +0x21b5c5eb, +0x8a5c9246, +0xd73c7b0d, +0x6f1ef8cb, +0x06ea2822, +0x322e0fe6, +0xa6d5c23c, +0x6877cf01, +0x4dbaab3a, +0x6eed05e4, +0xfed3a01a, +0xbe0ccb55, +0xbe98a3e2, +0x9a6a89fa, +0xf93bd388, +0x9a5d720d, +0x4822bef5, +0xcce7cf45, +0x9aa53a62, +0xa5f8cff4, +0x61747ab5, +0xfa77c8bc, +0x86c5077a, +0x791c8c9e, +0x4dbf4dfe, +0x5785ee5d, +0xea2b08b8, +0xea3e66f9, +0x5c67ce6c, +0x17ca0f09, +0xb21e83af, +0x22dfebbf, +0xfa979882, +0x12313cd8, +0x61052612, +0xe398fcd4, +0x6925274d, +0x4139bcbc, +0xfb79a5dc, +0xde288ed1, +0x7ee3bd7e, +0x5328ca9d, +0xf5937e42, +0x76c04288, +0x11a8d434, +0x6c147ba8, +0xa8c6bb5a, +0x98898e36, +0x764b56d1, +0xaeb6d9d2, +0x3a12d75e, +0x54520b9d, +0x9fd457e0, +0xd09c1fda, +0xc39b4e0b, +0x9f908c4b, +0xd2b710ed, +0xbeb24521, +0xd042fb72, +0x92ee3925, +0xdcc1ceda, +0xf5f787e3, +0x22d6181a, +0x9628d5d0, +0xd9662210, +0x40141809, +0xb7d53c84, +0xa09b4ba1, +0xa6d6bb7c, +0xe6e65b70, +0x1f21c827, +0x1292feac, +0x3715becb, +0x2c930c90, +0x747fa38d, +0x8de62855, +0x39c19d6a, +0x7688b95a, +0xc0fbe9d0, +0x3f69fe9e, +0x3a2f17f1, +0x610d1ed1, +0x3a313b56, +0x9c77265a, +0x1b2362fc, +0xe6cb8757, +0xb3eca8c8, +0x5fd79328, +0xdf381853, +0xcd8c480a, +0x25ea547c, +0x8ede7cc7, +0x6012805f, +0x9d09bb3c, +0xe9d3fb55, +0x7ec1dc30, +0x428df62e, +0xa5230d38, +0x1211b480, +0x08930f6a, +0xfd7b154a, +0x028d678e, +0xc1fcb5f8, +0xb660f932, +0x99dbb421, +0x78adcf1a, +0xe1a7b797, +0xd2487d83, +0x614208de, +0xa8cef833, +0xead1ba2c, +0xd232cd5f, +0x57fea3e5, +0x5562016f, +0xf95502aa, +0x448b0cf0, +0x6c30ffbb, +0x6ac6d43f, +0xf4f41497, +0x36f2145f, +0x8cdf2cf7, +0xa678dd42, +0xba985234, +0x6d779eda, +0x3b009a27, +0x8f86894b, +0xf52ca02c, +0x36e65aae, +0x372d89cb, +0xac838875, +0x13f30f5c, +0x4af55282, +0x6be5c02d, +0xea609a61, +0x9501dbc7, +0x4d5fe330, +0x6de64b51, +0xae08cc51, +0xd0314772, +0x95d0b85b, +0xd71cdc81, +0x41610312, +0x97b7a564, +0x06727398, +0xbb3fd30b, +0x1b626857, +0xa5cccf6a, +0x53acfa1d, +0xbf461ce9, +0xeab54b9d, +0x5ec133ea, +0x51a46550, +0xd708ebda, +0x9f02dc81, +0x203f4cae, +0xf24f2395, +0xc57b6611, +0x269b4009, +0x7c23090b, +0x204ace32, +0x7907a82d, +0x27bf74a6, +0xacbba782, +0xccf3ccc1, +0x64e89b42, +0x45401522, +0x30840a2f, +0x9487c84c, +0xd48acf8b, +0xf8361f81, +0xb6ebd487, +0x51053a3d, +0x417e3fa7, +0xd7bbc040, +0x8f71d98a, +0x47d711ac, +0xe7fffc4c, +0xe7b78af1, +0xa6646233, +0x066693dc, +0xe6dccf16, +0xacbd7a21, +0x0bab9f12, +0xe19f337a, +0x5adfb119, +0x95300474, +0x8392c0f8, +0x0de6311c, +0x00c8d291, +0xc63523f3, +0x8400489f, +0xd03ff5db, +0x2744aa52, +0x6e5039d2, +0x58e41d0a, +0xbe37cee5, +0xe2411379, +0xad43ef0d, +0xb6d5cccd, +0xd2195da4, +0x34534916, +0xeb86de50, +0xeec10654, +0x4224fbbd, +0x6af4f989, +0x6f8165f7, +0x6aa47899, +0xb9bcb6b8, +0x2c9dec0e, +0xd21a4959, +0xc8229227, +0xc9fdb412, +0xb6ab6696, +0x29e60352, +0x91be6a52, +0xf97ef2bd, +0xf061d628, +0xe4157932, +0x7af956a9, +0x5e9b998b, +0x7e59d90b, +0x75179450, +0xca8df865, +0xe94dd1dd, +0x998c8a14, +0xca8abf47, +0xbdb317d6, +0xc365cdbb, +0xe7b8c3fa, +0x38290d01, +0xae48236b, +0x70ffba9c, +0xa39860ed, +0xe625b792, +0x184ae107, +0xb9087eec, +0x7fb0e464, +0xa79236d8, +0x2023536c, +0x76c9d932, +0x036c3e3c, +0x75e400a3, +0x46a9969e, +0xda7ed44d, +0x1e0756f6, +0x517b2a96, +0xb4b7f389, +0x0578e263, +0x53ecc201, +0xf8d104be, +0xbcee454a, +0x19e8d5f4, +0xd90ace39, +0x3ed2dcfd, +0xdec7702d, +0xc285e96f, +0xdfa18486, +0x2d8f8261, +0x8b721577, +0x413e3e64, +0xbcc4f037, +0x72782601, +0x2967d77a, +0x2047bc3a, +0xdf9bdc71, +0x4c7e97f9, +0xb1624da9, +0x587d7ba9, +0x95607d38, +0x06ae0a73, +0x88c307c6, +0x00642751, +0x2cdbf42c, +0x059527ea, +0xd5cbe384, +0x89d1e711, +0x6f53ed58, +0xb8e3661b, +0xf523b03d, +0xe743b4c5, +0x1925d758, +0x7e570b29, +0x8982be35, +0x49575ea2, +0x151d8037, +0x84ee8704, +0x3784b0f3, +0x50f79728, +0x3485508e, +0xca1c33f7, +0xd7d7928d, +0xb6a612dc, +0x33a89bfb, +0x7c98f51e, +0x39779361, +0x2d0abef8, +0xa82a0a05, +0xe82a12cf, +0x9dca15fa, +0x0bd4fad1, +0xe4c3adcc, +0x44f37d26, +0x77828c27, +0xe3d752ef, +0xe14c5683, +0x7b138fc6, +0x85ccce8c, +0x89a65d5d, +0xc2ceb6a5, +0x3a68a05f, +0x54cde7b7, +0x307cadf2, +0x9ec3fd55, +0xe600ee13, +0x9bf9d73f, +0x6acf383f, +0x8578d28c, +0x8d5993d8, +0x4c2333ed, +0x79d2526e, +0x915714e9, +0xb5cb9602, +0x883a98b0, +0xf27d5829, +0xd29211ad, +0x6a49fe33, +0x5a212152, +0x9d45878f, +0x1d32bf69, +0x0c2b379c, +0x0479d8a7, +0xf6871692, +0x48d6f88c, +0xe994ec95, +0x0a814f15, +0xd0b47df4, +0x7993c34d, +0x35a1f169, +0xc81d109d, +0x100a766c, +0x3b32df7c, +0xee03287f, +0xd982cede, +0x25ad9605, +0xcd99ffa0, +0x0ef41976, +0x216e3d82, +0xda5f7f3b, +0xd55576e1, +0x6c66caf5, +0xa38eed19, +0x4751d57a, +0xc5cbb8c7, +0xee2aa353, +0xf5980a4c, +0x4169dedb, +0x94e2be5f, +0x638a95e2, +0x97f7d42b, +0x5b2c0f95, +0x72ca3ac6, +0xbc123539, +0x06431d5b, +0x062b013e, +0x0fbe7279, +0x59313b78, +0xe5aa8c2a, +0x7a66720b, +0x5f1c3839, +0x1669bc9b, +0x874b5286, +0x53f56c4b, +0x5722a543, +0x54efc928, +0x61dd4f11, +0xda89b33e, +0x14fb711f, +0x62a4d219, +0x4f002425, +0x182c6f61, +0x2e770afe, +0x17b3e603, +0x236d24a9, +0x43e13bcc, +0xe97172e4, +0x845e2742, +0x8ae8e24a, +0x7db5af6d, +0x8d2deb10, +0xfb86ed84, +0x6be2b913, +0x2783283d, +0xbb7473fa, +0x419f77e0, +0xb05a00f0, +0x16e5c55c, +0xd7c832c6, +0x22811596, +0x6e262e4b, +0xc092f9ce, +0x6882ec81, +0x542d7789, +0xc695d174, +0x4817ae0f, +0xf13d73ba, +0xbe8e86de, +0x7237c2fc, +0xdc446447, +0x4417c3c0, +0xb13eacde, +0x387cdef6, +0x6debc894, +0xf09bb2a9, +0x11bd3167, +0xdfcbd1a0, +0xd21b8c4f, +0x9ca1521b, +0xec890dce, +0xeb990844, +0x807edfc3, +0x8b640e78, +0xe270b72d, +0xff745f10, +0xf15b028b, +0x2849c890, +0x04bc2750, +0x320cf622, +0x8fe6313f, +0xcf0b09f1, +0xc8ce8a02, +0xba79a0d5, +0x17072415, +0xf975d50c, +0x57f9137e, +0xe27527b8, +0x7626b362, +0x1055c79a, +0x0d4702a7, +0xf3a0626d, +0x486e5e1a, +0x3e85aecc, +0x6b40a7e6, +0xc234a1df, +0x2b10b7d4, +0x08cd6bd6, +0xb356d5d9, +0x96305542, +0xafec5f5a, +0x720e62c3, +0xb02000d5, +0xe9852092, +0x28b1eb0f, +0x50472b8e, +0xe32eba90, +0x25171914, +0xf2bcba08, +0x46412688, +0x49c15e65, +0xb139fa08, +0xf5c3e728, +0xe0409d34, +0x2c969542, +0x5c3d51e3, +0x54ddb79f, +0x74e83670, +0xba961b37, +0xca6fc608, +0x31328137, +0x0748ebae, +0x65f58a7d, +0xe58ba96c, +0xbf08e011, +0xf44ee9d8, +0xcc7d252f, +0xf4161726, +0x6a385be9, +0x963c3fe4, +0x82942257, +0xf0f1fe4f, +0x97f1be31, +0x91437586, +0x3e8ae44b, +0x57906bcb, +0xba609a0b, +0x2804d942, +0xa17a78eb, +0xa31a1899, +0xc38a06f8, +0xd50884de, +0x9af7a3cb, +0x323cd27e, +0xa97f978d, +0x1155974c, +0xe9117b7c, +0x68c1c618, +0xc37dd0b3, +0x6bc83292, +0xc4765970, +0x769bb495, +0x7103f16d, +0x5d783ecb, +0xa3160e4c, +0xee0337ed, +0xfc173468, +0xfd38e8b0, +0xe5444b70, +0xfecba61d, +0x375e41cf, +0x0d6f9929, +0x024c4865, +0x662010c3, +0x23dcffe3, +0xcad6f4cf, +0xaeec48a1, +0xf729d3c2, +0x1eae9c4f, +0xd8e76342, +0xefb4d356, +0xab3a76b0, +0x458c2077, +0xf4cbf542, +0x2c283ede, +0x3bd2ebaf, +0xc304dd2d, +0xbf510161, +0x3e52f3a7, +0x6f82cfa0, +0x753ec16e, +0xe1176c91, +0xb02b2ff4, +0x3601aee7, +0x949d736f, +0xa9d20831, +0x12ae02a3, +0x0cf112db, +0x01475353, +0x21131837, +0xf7541e33, +0x6a90c901, +0x9d60c7b9, +0x46b4a17a, +0x42f32a3f, +0x0b5f3a87, +0x30ec2557, +0xcb17a856, +0x6980dc11, +0xc79c1abf, +0xc17d7381, +0x03118d1e, +0x672cd393, +0x7869d3a0, +0x3fe0b815, +0x95854502, +0x760336df, +0xb7483dc2, +0xdcd6b12d, +0x10e43d5f, +0x6f57a0c8, +0x655db46e, +0x2463f43a, +0x2c72d9cf, +0x77510148, +0xa3c7455b, +0x60611c75, +0xbb13faa3, +0x4adb0b28, +0xd4e78227, +0x5792343a, +0x2e1056a0, +0xa22b9a1f, +0x9b834d5c, +0x986c7c22, +0xda6c3fd8, +0x25d699d8, +0xd3515282, +0xb72ed3a7, +0x948d75fe, +0x85367fde, +0x6769d645, +0xdd241018, +0x25892f5a, +0xbf068ce2, +0x79a8b03f, +0x8860ea09, +0xa507ad22, +0xac826d5a, +0x07afdc8c, +0xec7e3531, +0xa5c3d81a, +0xae3efd8e, +0x7bc3d87b, +0x52e02ad5, +0x37922655, +0xd9e9fc8c, +0x46dbf22c, +0x8aeb4a62, +0xb95c063b, +0x53e26d13, +0xbc0e24bc, +0x238cf0f6, +0xeda955ad, +0x5741c72b, +0x0af03921, +0x40996c96, +0x656c02b6, +0x73e59d7d, +0x08c612b7, +0xc7a729a7, +0xf9de6d9c, +0xde4f39d9, +0x58afd437, +0xce4aba58, +0x28ee5089, +0xd59a5b49, +0x9986072b, +0xaf783a99, +0x32739ea2, +0xce660a68, +0xc8cb9577, +0x53c47782, +0x6dfcff93, +0xde8db177, +0x543e7733, +0x6169f508, +0x8eb60d98, +0x9532ddab, +0xf400a4a6, +0x27758c84, +0x0c94d472, +0x244a2185, +0x6841c439, +0xe7008c2a, +0xab450cd1, +0x9a867f92, +0x9389b814, +0x5503d041, +0xb8ce3813, +0x3b2b6945, +0x78e1a99d, +0xde19ec4b, +0x5c9f607d, +0x273f0461, +0x2c1c3ebd, +0x532eaa57, +0x70c700cd, +0xd20208c9, +0x523ed52c, +0x91d2bd99, +0x2e2c5c6f, +0x2102c599, +0xb9caaecb, +0x192e1b05, +0x59c508b5, +0x76e7cf53, +0x13fca59e, +0xb96c3b0d, +0x09900ba4, +0x2d7b0e7f, +0x2399b0e5, +0x7dd113f0, +0xb7732328, +0x6d7a21be, +0x4c4efd90, +0x6880f6a7, +0x94ac1e7c, +0x1de040ca, +0x15b62acb, +0xa58e60ea, +0x47b6db70, +0x5ed824d6, +0x8ed41e71, +0xa190df2e, +0x4cde127b, +0x13add98f, +0xde6d0bfb, +0x5c1bd0f2, +0x7461ee4e, +0x6081d103, +0x6a4d7a42, +0xb48d2f2e, +0x2935e3f3, +0xacbff423, +0xc70667b4, +0x2cf43de7, +0x190ebc2e, +0x11925b41, +0xe56a8905, +0x6b7f9d0a, +0xbeb86515, +0x37cb32b7, +0x3b5bf7f6, +0x3b0af610, +0x7c44bdb5, +0x97e7afc0, +0xc27b3264, +0xcb7b86aa, +0x8b1bdfd7, +0xcf4531f1, +0xfa070518, +0xcaf4a802, +0x1d2f541e, +0x82b07753, +0xc5d4a975, +0x32997be4, +0x5e75b690, +0xb8ae2371, +0x680d670d, +0xbb9da2c7, +0xef2e8b34, +0x42d8425f, +0xb15ff774, +0x314b3aa8, +0xb99926ac, +0x92f2caba, +0xc71f8561, +0x5fb81005, +0x6f4bc985, +0x6f3c0c40, +0xa447b8db, +0xe7260de4, +0x3b6ec5a6, +0x3b1529d9, +0xc6875cff, +0xef74b1af, +0x54309eb7, +0x33a009c9, +0x43ea9d1f, +0x4d8b7bb1, +0x41242c68, +0x6915d34a, +0x59572a60, +0x334df1f4, +0x17c5d70a, +0x11262614, +0xdcde4f27, +0xf49f5ba3, +0xf856b0cc, +0xdc7fdb89, +0x251b2446, +0x6a276bd2, +0x382f2781, +0x3c87d791, +0xa01db734, +0x1c95355c, +0x7714bd17, +0x0a91b352, +0x1eb93939, +0x4cc33eb8, +0xc8a4cff5, +0x8f6674d5, +0x5ee5c49e, +0x83425e91, +0x7a5a8502, +0x1f305e18, +0x3c3e0dd0, +0x3b8287dd, +0x9acb46f6, +0x99ae507e, +0xc36b6715, +0xd6ffb75b, +0xf0849d5d, +0x06d4a4c0, +0xd3a31076, +0xa8b60edf, +0x550dbe0e, +0x7048a97c, +0x22e63597, +0xfea5d7ab, +0x2f1bfae1, +0x20e25c38, +0xed5a706c, +0x32e5342c, +0x7c70f4a8, +0xc3228c90, +0xc5244982, +0x16d16e92, +0x8488c65b, +0x1fde16ce, +0xd71f5cc8, +0x61cb100a, +0xa0755b82, +0x7ffe2618, +0x352c4606, +0xe8723977, +0x6bf55e0a, +0x7068ccec, +0x59710a94, +0x29c0d6d1, +0x929815ae, +0xcffbba25, +0xff668a2b, +0xfcdd58ea, +0x1bbb4be9, +0x8e73325a, +0x74a0e190, +0x67c536f3, +0x89b0ae9f, +0xb359a58c, +0x5f573e6f, +0xb128fcd2, +0xda868fef, +0xd0545d89, +0x4eca24d2, +0x349940dc, +0x9d0a2ac8, +0x0a023bc7, +0x330a595d, +0xcfa861b2, +0x57a2c1e4, +0x745cb9e1, +0x0ee52c9f, +0x8ff0451f, +0xffecae99, +0xa5c265a4, +0xd25d6b37, +0xb56cde2c, +0x9501cb1a, +0x00e07a8c, +0xaa6335d8, +0xc6871a50, +0x90e9c4f1, +0x76610ee7, +0xd21d6848, +0xd9d383bf, +0x5ee697f7, +0xedc338b2, +0x68953b00, +0xc6ef060b, +0xa99642cb, +0x568e64c5, +0xfd52385c, +0x4924680b, +0x6826096a, +0x500b3b26, +0x093b1080, +0xb5256b37, +0x0eb2083a, +0x45757399, +0x450d0262, +0xfa31da02, +0x6ef620a7, +0x674d8748, +0xe1432734, +0xb8442228, +0xde06116f, +0xc4b74f5f, +0xbd308848, +0xea2d35cc, +0xe0c58e3c, +0x201e2723, +0xac77f858, +0x06eeabc7, +0x6737e4a6, +0x5618ab0e, +0xb3321688, +0x3fa720b7, +0x6e18dd46, +0x2368cb1d, +0xd4019d7b, +0x4f0052e6, +0xf38c8e48, +0x891682ee, +0x59b5114f, +0x8a209094, +0xcbf84a47, +0x682cb714, +0x051c25ba, +0x17cc8f46, +0xc468e050, +0xfccdf539, +0x5bbf3aa7, +0xaf73b845, +0x56c4baca, +0xd0644777, +0x05ee56a2, +0x7db3c14c, +0x70ec1e96, +0x11e8dfae, +0x63a572d9, +0x09cace90, +0xcb9faf0b, +0x1054b963, +0x9dbdeeba, +0x150f3b29, +0xaa0ed54f, +0x66a90e4e, +0x09ac47a0, +0xfb6d1cc5, +0x27a5b8ba, +0xbe4e6d98, +0x0de05504, +0x73f1c292, +0xac34221e, +0x1d0bba92, +0x731273a1, +0x8e586c04, +0xb650eb2b, +0x99583904, +0x4c1c46c8, +0xd7f8df3b, +0xc835f6f3, +0x7aab2863, +0x7b6f388b, +0x434d60ed, +0x6f4f2429, +0xd0ed569b, +0x136336ad, +0x96d1f8d2, +0x35ce27d0, +0x9e1a7568, +0x28608eb3, +0x35499e97, +0x77d32a21, +0x72385480, +0x18f2946d, +0xd7226d4b, +0x9afc010f, +0x83e85449, +0x021047ec, +0xe3984336, +0xe36dd816, +0x44182242, +0x28639d5e, +0x0a17f347, +0x10a2de7a, +0x3911411a, +0xbfa7ce30, +0xaace7719, +0x414d563c, +0x16bd40e9, +0xbd337a8f, +0xca274c0e, +0x4003f02c, +0x70f5f49d, +0x1e45fa8d, +0xb7ef8abe, +0xfbc7e453, +0xb90aab33, +0xd7e0361d, +0xa7c373b1, +0x380cdc2c, +0x0c62c807, +0x18f8d487, +0xb6f6fc70, +0xeeb98c18, +0x98077493, +0xab060da1, +0x5e76b292, +0xec480938, +0xea051cc1, +0xfa4c28f9, +0xef00fca6, +0x0337c85c, +0xb09caa46, +0x0da956e9, +0xdeea7b42, +0x1e8cc4a4, +0x5f3b25b9, +0xc349f6dc, +0xdca978d2, +0x17962d01, +0x1aa5f3b7, +0x86dbd1bb, +0xef3cec02, +0x6d106c4a, +0x95a79328, +0xeb5a3051, +0x7ef45c13, +0x70558ad3, +0x1d39b7f8, +0xc6732c03, +0xec16cd5d, +0x517c0d32, +0x59ce1232, +0x549d5003, +0xeb952674, +0xc5782f6a, +0x996a664e, +0xd466cd52, +0x9d2da534, +0x6082eef5, +0x5227861b, +0x14952df2, +0x8507bd39, +0xc6f24cbd, +0x1152fbcb, +0x8d91805a, +0x44960da0, +0x912b84ae, +0x2a830453, +0x1e413b10, +0xdcc47701, +0x87b247d0, +0x248a8a5c, +0xc46d3ba6, +0x1737c0bf, +0xd1557802, +0xf610e323, +0xe1d33507, +0x5e7828a7, +0x2d05679d, +0x5d6646f9, +0xa0d9dd1a, +0x74895b75, +0x28f4ef5b, +0xdafeb0cc, +0x9c1dedcb, +0x9df3da98, +0x5ef3c990, +0x7abd261e, +0x7ea945d8, +0xd1f50847, +0x2bd48555, +0x09c80f2b, +0xef363d92, +0xfb385508, +0x04fe26c8, +0xbdde1f67, +0x0bf7c966, +0x4949f3a1, +0xdad10c13, +0xdb267a66, +0xbe6c2206, +0xf822f4d0, +0xe8b4cbfe, +0x1c6a1cda, +0xa1870095, +0xd52f9a21, +0xd05f9e55, +0xee986251, +0x12774efb, +0x815c8b3f, +0x69e4a022, +0x8f82c261, +0xf5e48112, +0x92f26db3, +0x3b0c02fc, +0xead4383d, +0x1fbbfd7b, +0xddbd7b1c, +0xe2dc273b, +0x7d56e533, +0x306dbd94, +0xb1ec3b98, +0xaf6a8bef, +0xb72bd17f, +0x51081e70, +0x6284a5f5, +0x3ca14980, +0xf3707225, +0xc355ba37, +0x1ab62e84, +0xdfd2f221, +0x86cd4ba0, +0x265c047f, +0xbab3fb84, +0x354274ed, +0xd17d6383, +0x5778bba1, +0xc5367926, +0x4871656a, +0x72ac1457, +0xac9d784c, +0xf9b95608, +0xfb1a52f7, +0xd52ce2d2, +0xcf2d8483, +0xd6cddc36, +0xd1eff71e, +0xa0f6b38e, +0xbb9ceb0b, +0x822a995c, +0x33cce8b9, +0x26435910, +0x9f0550df, +0x910adab7, +0xf3b7797e, +0x431190b2, +0x5cf5b5b7, +0x45b9bbb8, +0x41a77618, +0x599ac277, +0x0d781cbf, +0xe4b116ec, +0x0db1d868, +0x72d047d5, +0x609f2062, +0xea1497f4, +0xc103d5d0, +0x1b951fb2, +0x47769c08, +0x3dd66f57, +0xab859e00, +0x8f45a97b, +0xcfe82134, +0x7841227b, +0x0c691b02, +0x581189c9, +0xafc5dcd5, +0x19fa43fe, +0xb4cc7260, +0x72300139, +0x1192ceab, +0x48855cbf, +0xe5c1c2d3, +0xf261a949, +0x376392d3, +0x8c46404b, +0xefbad752, +0xdfa3c066, +0xe8f9f888, +0xbfe5e495, +0xf27883fa, +0xf6772585, +0x17b7d0d0, +0xb45829f7, +0x4eae3e25, +0x1301f259, +0xec6e92ea, +0x8bbd6c12, +0x408eb787, +0x4787fdfc, +0x53b3dc9f, +0x886a4933, +0xe0624729, +0xc429e9aa, +0xaabcd040, +0x9ed9441e, +0xee75aa11, +0x8465e584, +0x8494b837, +0x680c93f9, +0xf14bb0b9, +0xdffa78cc, +0xb0a90675, +0x4ebd79c5, +0x34c214f7, +0xd75e6e7b, +0x34e16725, +0x8ae705ab, +0xea350ec2, +0x41bd010c, +0x26b3916f, +0xb8f3a310, +0x71904724, +0x21696a5d, +0xee4393a7, +0x8304d9df, +0xb00bccbf, +0x8c431860, +0x629bf84d, +0x804475a7, +0x24f22938, +0x616f48fd, +0xd93cc7ce, +0x5dd7342b, +0xe1380e1b, +0xc4a16dca, +0x18c163a6, +0xb2c90c31, +0x9fd57227, +0x8a2b551a, +0x36da8eea, +0x01ea55ff, +0x26a326bf, +0x46f5a3c2, +0xfe507aa3, +0xe5afdb79, +0x213276b5, +0x84511faf, +0x80cff381, +0x209e1b27, +0x2beb22e8, +0x0086d62c, +0x656d7de1, +0xac69ba08, +0xc36bbdd3, +0x4f134e0d, +0xa06c0ce5, +0x3e160ea4, +0x6e3cf124, +0xe496876a, +0x8f9a6396, +0x035c38ec, +0x2902f5e4, +0xd363d826, +0xa36c60c2, +0x563ce70b, +0x484a4c52, +0xa513faad, +0x4d050ad1, +0xf04a996c, +0xcf7e528f, +0x0d2320e1, +0xdd98275b, +0x0033dea2, +0x71241bab, +0x713af745, +0xb71674bd, +0x7b76b32a, +0x3af0d390, +0x1eede1bb, +0xe66707e0, +0x13200b25, +0x4ff73b4e, +0xd3dab6cf, +0xd766e6a5, +0xfb0e93ab, +0x242139b1, +0xe59606d8, +0xa35f0df3, +0xc556c065, +0xc3a86e7f, +0x2427bcaf, +0x1d3d601c, +0xca3ead22, +0x7708f504, +0x2fd3c906, +0xd2238a58, +0xb6843e2c, +0xa1e8090f, +0xda9c1d9d, +0xc21fe6a2, +0xe7642dd2, +0xe008b988, +0xc71e41b8, +0x486631ee, +0xccd56fba, +0xa30dc9fa, +0xce993abd, +0x74ea8a5f, +0x98d7d7e9, +0x458e9010, +0x1503438d, +0xb770eb46, +0x19b89a05, +0xa2cd23a3, +0xbafaafcf, +0xdbc0704e, +0xb9201b87, +0xe361c1c5, +0xce1998cb, +0x90262fae, +0x52071199, +0x2ff2d659, +0xffad91bc, +0x9d509514, +0xa395c960, +0x31866dc7, +0x83aa046f, +0x2897a8ae, +0x60dd4ad1, +0x18be1f25, +0x402e9926, +0x4c518f0f, +0xc9f860b2, +0xf0be249e, +0x783ce6db, +0xd1b57613, +0xc3e64e04, +0xb3cdb5b1, +0x0a119e3c, +0x4f14dc24, +0x5e7cddab, +0x6ef20784, +0x39ab98e1, +0xdc72cb02, +0xe8f13332, +0x5b5e3cc6, +0x3c59f242, +0xacd283ac, +0x0dee1c12, +0x3e560d41, +0xfd9f48e8, +0x92013b18, +0x484eff60, +0x1fcac129, +0x1393018a, +0x38bf44a7, +0x0fc3fe86, +0x091b81c9, +0xa00071b8, +0x8b979b4f, +0x4819ab43, +0x73a39a97, +0x9e418ffa, +0xbac12fae, +0x5e8e4427, +0xb4a2b36e, +0x7586a808, +0xc0935a15, +0xeb4aadde, +0x9c755839, +0x03f2a59a, +0xb16de876, +0x4092ea9b, +0x4dfc0d74, +0x3d067e39, +0xb2d478e3, +0xc58e0d28, +0x463e5c54, +0x477faaf6, +0x9eec3bf5, +0x00e34637, +0xfdb76516, +0xd6fa8ff7, +0x8ea7c0cf, +0xe098ff8f, +0x5076e241, +0x773b245b, +0xb8ac3fbe, +0x56bcc599, +0xfaf5a538, +0x34b9bcf9, +0xa9c08692, +0xebc5f11c, +0x0cb15088, +0x065f9b38, +0x1ab7cecc, +0x3fbe6fcb, +0x06508571, +0x7cbdead2, +0x482a1672, +0x33d70470, +0x70412d99, +0x2d0b4e42, +0x0bf95ca8, +0x43959b93, +0x7d1f14d5, +0x3ad60ae4, +0xb2b0a0b6, +0xd221f059, +0xca588e0e, +0xc35e67a8, +0xc65271e8, +0x2d1c988c, +0x74077b8c, +0x05ad0d20, +0x4517205a, +0x2eec287e, +0xde7335d2, +0x520fc35e, +0xb174f920, +0x306f3d1a, +0x682763e0, +0x007116c5, +0xd1a84077, +0xcd543958, +0x0897d904, +0x17e66cf6, +0xc93c80cf, +0xdccdef55, +0x0fb263fb, +0xec872fdc, +0x2954b1c3, +0x761f3d8e, +0xbf954a50, +0x8fe1931c, +0xf3d546c9, +0x0873d08b, +0x35d2439b, +0xc1305068, +0x314f2d4f, +0x5245e91a, +0xdd1611bd, +0x260df042, +0xe3eaecd5, +0x7bf6f262, +0x65ae3fae, +0x76840a79, +0x737ade91, +0x39ab0b2d, +0x5813fab4, +0x5d201146, +0x176682d6, +0xaa9b503a, +0x974d610a, +0x24eec1ce, +0xb16563b6, +0x7e4accc6, +0xf63d507f, +0x6eb94b6e, +0x6bb0eec8, +0x9937d490, +0xb80cf3c4, +0xcf3f7122, +0x83efa365, +0x3a0aee5a, +0x1ac7a582, +0x58f725d3, +0xaf5f8150, +0x452146d6, +0xfdb77473, +0xc25c2ddf, +0x629e7f00, +0x8df3d826, +0xeb82ec41, +0x9e0ff979, +0x418bac24, +0x09134f9e, +0x55aaba7e, +0x097647bf, +0xfcaebf86, +0x82762f87, +0x74423794, +0x92864fb7, +0xaff98019, +0xffed7437, +0x20d289cd, +0x9d87de61, +0x84edbf15, +0x4c473d7a, +0xd83ecbc8, +0x0bc060ce, +0xfdb7a7a6, +0x1756acb1, +0x88f31ad5, +0xa588d5de, +0x58b6269b, +0xa971fb2b, +0xa646cce4, +0x4581451c, +0xc9208968, +0x573ea5b6, +0x6119f476, +0xdfc9febc, +0xeaaa0c2b, +0xcdc2dd8f, +0x2bf3e4a5, +0x189fa495, +0x2a83c7fe, +0x13a54bf6, +0x041df194, +0x07ed99c6, +0x95a62536, +0x435593ba, +0xbbeda1d6, +0x682634ce, +0x7a9c12cb, +0x8f11e7e3, +0x70282587, +0xe7c56899, +0x41806f54, +0x5f11ea11, +0x5965ead2, +0x9361bdaa, +0x8a5f0199, +0x3d8cb53b, +0x95d0d0f3, +0x71169547, +0xf474c8cf, +0x5b80d2f7, +0x5d1d0472, +0x9b37acd8, +0xdbe0799d, +0x7a32b63a, +0x1be744f8, +0xc8748050, +0x2107f9b1, +0x32dc80e8, +0xa1a2fb11, +0x30fbb2bb, +0xdfafc57c, +0xc8a50043, +0x503db717, +0xafbc78cf, +0x93249a67, +0xd626dfdc, +0x4b0639f9, +0x75cdf147, +0xe5aa9d57, +0xc77c494f, +0x4d808d3a, +0x65bb3932, +0x28a9422e, +0xb258870d, +0x6b47f79f, +0x9c4e06e9, +0xd203dd47, +0xfef388e4, +0x8cc577f1, +0xf0e40aba, +0x039195f1, +0xc8ff3b43, +0x3e32d0ac, +0xc043c8e7, +0xe10ff464, +0x1603ce86, +0x388bc6ff, +0xa0ce9e0a, +0x091b174b, +0x6c199fe9, +0xdd84507d, +0x55aadf77, +0x81755278, +0x6e4ce48b, +0x67e8d2c7, +0x26819a19, +0x232af10b, +0xd10cca1a, +0x5f4a6c7d, +0x3f18d0c5, +0x0f0fb181, +0x0e0890b9, +0x8caa7e95, +0xeefce2d5, +0xd012a07e, +0xd67c9a79, +0x28a2d1b5, +0xe0e5abbb, +0x083f5b2c, +0x43fd3a49, +0x7282122b, +0xfb009899, +0xd9c12399, +0xc9bb2f75, +0xa68645ed, +0x53c630a3, +0x2ee11d05, +0xa3b785be, +0xedc4c52d, +0xb3d48644, +0xf25f0a34, +0xc8cb95bc, +0x0691af33, +0x6033530b, +0x31045a81, +0xf1cbce12, +0xa138ee44, +0xfc2430c5, +0x3561cd95, +0xe7570bdb, +0x5979c48d, +0x7b10b68a, +0x92d573fe, +0x970940f0, +0x31f1377a, +0xe9dc8512, +0x4a842da1, +0x948bf4e6, +0x0b20c268, +0x20dff711, +0x57ed1cf0, +0xac53b7d2, +0xca7103f5, +0x9f6d2d6c, +0x4bc0f9ec, +0xe9dc4068, +0x50542cf3, +0xf11ab80c, +0xb04791de, +0x1fedb194, +0x541aebd3, +0x07ad65b1, +0xec361bc9, +0xa4cdd84a, +0x22e44bf8, +0xaa075e20, +0x8162a800, +0x727a1785, +0x75d0c30d, +0x8ae17afb, +0x8a703c47, +0xc15bce02, +0x3114ae9b, +0xb6e5c990, +0x7b55599e, +0xcb44099f, +0xda84d199, +0x45035c0c, +0xf9c37def, +0x7fdab24e, +0x8e52ea6c, +0x7c529a16, +0xe3f25ae9, +0xcbc3ad44, +0xcad49ff4, +0xa41ea5f9, +0x2ca3f599, +0x9d55c1d5, +0x05d96a72, +0x0fcbe623, +0x3346f102, +0x5a8f224d, +0xe507ff04, +0xa0b32378, +0x71f5f5b2, +0x961d3f0e, +0x51ad227b, +0xb6788959, +0x6e65191d, +0x2bc81842, +0xcc03d45f, +0x37b3ef3a, +0x94ee33c9, +0x45d1c2ba, +0x7618ca85, +0x6211d873, +0xc53d78a8, +0x33b21cba, +0x67929e4d, +0xaeefed8c, +0x2e7478b3, +0x6a4682c6, +0x240f700f, +0xe272b6fa, +0x3e922a56, +0xda3d4992, +0x9c51c776, +0x1ab9e280, +0xb51e8801, +0xb7796e17, +0xe7477de9, +0x520db16f, +0x79dd9954, +0x9abeb60e, +0xaf0b667a, +0x2f53ab20, +0xf3c05bb8, +0xa5112482, +0x7c3f588a, +0x37d152e5, +0x3410200c, +0xd81e4041, +0xb93bbe1c, +0x89da0d47, +0x01e8fa5d, +0x08d5f155, +0xfd1555bb, +0x79c2a40a, +0x5b1082df, +0xb753edbc, +0x8ecf1bf3, +0x112fb4ec, +0xf013a98e, +0x776d730a, +0x754f6d55, +0x5aa4514a, +0xb55190c2, +0x81a8c122, +0x8579c117, +0x521c0944, +0x180498d2, +0xb8c5bf81, +0xd791eba5, +0x0c94c72b, +0xe3a27fb8, +0xca66d2ae, +0x698c3140, +0x9742832b, +0xe84a487c, +0xa811fb05, +0x90395efa, +0x423640df, +0x0f142319, +0x7c94d4d6, +0x5057a508, +0x373a6426, +0x4bc958f5, +0x0c7dec3d, +0x0e446522, +0x5ab9424f, +0x4b92dbac, +0xabf7978e, +0xa418c45f, +0xf612eae0, +0x0a3f7e40, +0x3c1224b9, +0x1674f633, +0x51285f68, +0xefc000a6, +0xbae72622, +0xaa9ad60c, +0x3a44d9ae, +0x9eb9d4f6, +0xc63e4c0b, +0xaddfd2c4, +0xcdd00f78, +0x35a281a0, +0xa8831f4a, +0xd23dc951, +0x598fc254, +0x36302932, +0xd362009f, +0xdeb575f6, +0xe7ade8ee, +0x00332495, +0x2c01ab1d, +0xdf6abc46, +0xaea66f02, +0xe508966d, +0xf766a5ea, +0xe8d443f5, +0x88942732, +0xd9ea6219, +0x68f42c0b, +0xd421b11b, +0x0c5868e0, +0x28b945dc, +0x6285b90c, +0xae13c42f, +0x2eaba948, +0xad121590, +0x07911b92, +0x095f947d, +0x4b6b7455, +0x3c7c14c4, +0x29122ff9, +0x5aea442a, +0xd8ed7523, +0xf45aa606, +0x3d1e6810, +0xc3fc592d, +0xa7ea5860, +0x71af7d5c, +0xea4b66b9, +0x6dc97134, +0x2946a0a9, +0x4de83abe, +0xea60c4da, +0xfc6dee72, +0xe1364431, +0x7a8ef0f3, +0xe2e0637e, +0x4682cc91, +0x7cf01bd1, +0x745d7e69, +0x75ce22f0, +0x74390400, +0xbf3e8c23, +0xfdda7a63, +0xb517f8af, +0x40168beb, +0xd2f475bf, +0x907abd7c, +0x6852f473, +0x2f463099, +0xe0fe21db, +0x98c7f1fe, +0x4bebb460, +0x4457c74f, +0x61c5b2bb, +0x5e51106a, +0x5ceac8df, +0x6ea31271, +0xacd6953f, +0xf9e54b69, +0x0e7a0c28, +0xd1f36527, +0xaef37453, +0x6f21441c, +0x550218e7, +0x316b385e, +0x28d5b914, +0xc11c01d2, +0xd53b1129, +0x867af92c, +0x17fd1d19, +0xbc2e13af, +0x814955eb, +0xd26e977e, +0xece1757c, +0x56a18da9, +0xff36906f, +0xf614fb75, +0xdadeec59, +0xc9be99ed, +0xe8e4f1f2, +0xafb3ccdb, +0x9072f26b, +0xd12311e8, +0xa8093301, +0xd1161865, +0xc3e04c82, +0xc1ce1345, +0x5e132ff2, +0x008d37bd, +0xed33cca9, +0x43214266, +0xece7d3d5, +0xe81a7939, +0x1c5adb4a, +0x10cf800e, +0xc2bfa50d, +0xda77f7e0, +0x12b99d3f, +0x5c403f9e, +0x0ea09663, +0x277e19d7, +0xf7feb737, +0xaa0a18f8, +0x9f15f60c, +0xba91269a, +0x5df0e90f, +0xd172e3f8, +0xbf286c4d, +0x022b655b, +0xe563d666, +0x858f5401, +0x697a9f3b, +0xb86e4145, +0xc3251695, +0xa08cea9b, +0xb59d3686, +0xfd2ca189, +0x2a7d0855, +0x9001a639, +0xc4fb5bab, +0xaeac6db7, +0x92a96244, +0x6f1d453b, +0x66bd50c7, +0x27205a7c, +0x1cb9c005, +0x609df0ba, +0xf23096a7, +0x43f2e5d3, +0x6737418b, +0xd263f4d0, +0x4532e07a, +0xd27cdb23, +0x24019503, +0x8724c090, +0x20a2eb55, +0xf9ae2565, +0x7519b42b, +0xbd96709a, +0x3d9d8ac1, +0x84f0a7af, +0x5a1afdba, +0xf84955d6, +0x71be510d, +0x3eeff861, +0x55da5c2f, +0x03c16f78, +0x1b93e934, +0x2520caaa, +0x41e3bee3, +0x6f0c6aff, +0x8918ccb7, +0xecfc7417, +0xa4466bf8, +0xf33c89db, +0x9f871941, +0x60064aa6, +0x0e77e1ae, +0x8907c213, +0x436ff15b, +0x2bf1bd65, +0x693eea79, +0x96637c3c, +0x211ddaeb, +0x6cadf5bf, +0x4d3b7e30, +0x46e3689c, +0xecca39e5, +0x5dccca36, +0xbad5ae5d, +0xe15a3d64, +0x01d5bd78, +0xbe9de7e3, +0x3c5108df, +0x1d49ae0e, +0x1ed0846d, +0x68376f6d, +0x9adf76f6, +0x49c0fd41, +0x84c35a8b, +0xbfb06c4e, +0x2e8256f1, +0x4bd76a7c, +0x541f60d4, +0xd24de960, +0x8172dfef, +0x94aaad3e, +0x38c94d0f, +0xe104113e, +0xd5c9011c, +0x692ea669, +0xc82baf10, +0x011dea07, +0xfa8d3393, +0x3eb91291, +0x88436266, +0x67953368, +0xddffae38, +0x10b732fa, +0xae9ae1aa, +0xc408db20, +0x82ba61bd, +0xb7d166b1, +0xe0240547, +0x6ed32297, +0x80a0829b, +0x02b9bb27, +0x10a207a5, +0x87e889d1, +0x112832f3, +0x2f75abc8, +0x83ea73d7, +0xff90b880, +0x00f35b84, +0xc5ad80c9, +0xb6e000e6, +0xb7ec19bb, +0xa9f8da6a, +0x4646cdf3, +0x9e217d98, +0xf9dcf238, +0x488da5ce, +0x4dc1e1b8, +0x47aa1f34, +0xa76b7f3f, +0x64dafb10, +0x3ebb9fcd, +0x41a9013f, +0x79243baf, +0x657cbc2c, +0x983b11a0, +0x978a8647, +0x3e24bb67, +0x03c4e7e2, +0x1add24f2, +0x036576a1, +0x30c126f4, +0x3f06874b, +0xd4c7a936, +0xf7f6e58f, +0x758edbb3, +0x8a6cf3d6, +0x86c830bc, +0x0a1f1444, +0xb5b35d0c, +0xa3f56bb4, +0x0c7b5590, +0x8d816ad9, +0x6860ae2d, +0xd667fb36, +0xb5e30c61, +0x90d496e2, +0x91a73702, +0xac695fb9, +0xa3af9e50, +0x654d44af, +0xad532202, +0xbee120ba, +0x555a513a, +0xcab0fe12, +0xf0b77ac3, +0x47cf9708, +0xfd3a40cb, +0x378297a2, +0x66059bb4, +0xafa75c8d, +0xd1fbcc1f, +0x2bf73793, +0x612b3e5c, +0xe6c3f9cc, +0x848175bd, +0x4d88069a, +0xefd7045a, +0x26e87dcd, +0x58157315, +0xa3d576d7, +0xfa840ab3, +0xf2894d01, +0x45fab3a0, +0x0eb48f2d, +0x1edb62d2, +0xe8091204, +0xda2495a0, +0x57d90dd2, +0x15ecdbbc, +0x84eb9447, +0x198b99fc, +0xbfa4cf12, +0xc243c36d, +0xf494e2c4, +0xdfbe83f4, +0x37309651, +0xe49ff21c, +0xd6a7fd16, +0xe0ba8242, +0x2204a4f5, +0x6493d301, +0xb7692249, +0xf9a27736, +0xaa8cfb43, +0xae5aaa8b, +0xfd9b6f1a, +0x0f290434, +0xccf9a0ff, +0xe3ffd7c0, +0x5ddacfd3, +0xa1f37f17, +0x7f41ed15, +0x95d707f2, +0x872fec62, +0x2e645a71, +0xdb3e473f, +0xf5f58b92, +0x2873a1dc, +0x7d1cf43c, +0x0ea3eb29, +0x2c632dd3, +0xbe62f34e, +0x58ea3041, +0xe0062a9f, +0x2b8cbb49, +0x164d4783, +0x90da4eda, +0x8330430a, +0x2e4515a9, +0xee0d7964, +0x552ff7e4, +0xac3c5f8b, +0x280ee056, +0x5dab4536, +0x13309800, +0x0b5a2dd6, +0xb62e09f8, +0x36c765ab, +0x64503da5, +0xad926037, +0xb34041a8, +0xead57da5, +0x0cc0e398, +0x314d409c, +0xafd3a8bc, +0x21f8210d, +0xce5d1d4d, +0x7c6fb2c9, +0x00ff407c, +0x180d436a, +0x6e3dd104, +0xa03bb9e2, +0xad5cdafe, +0x7da46c79, +0x8c5d4867, +0x74bad33d, +0xfbe86ffc, +0xf772e62a, +0x9f67a2b2, +0xb8f2889f, +0xc26454a4, +0x02733a67, +0xd1c0a746, +0x15764dbf, +0xe079f78c, +0x39f2447f, +0xe34d5118, +0xf8dda37c, +0x4a607938, +0x77e3559d, +0x3d03008a, +0x255eb08e, +0xb0127faf, +0xf1a1e499, +0x1e22f1a0, +0xd3a327e1, +0x23c1ac0f, +0x4ee88724, +0x1be53e7b, +0xecbbda4c, +0xcb943d2f, +0x9bba2270, +0xd3e5ed70, +0x0a8f7a74, +0x1259f35d, +0xe5fc43ef, +0xd56d4e41, +0xb3346562, +0xca8770ec, +0xd387e5af, +0x516c5b1c, +0x4c9e3faf, +0x206b724d, +0x653a7b9e, +0xa711ced0, +0x37ec7be9, +0x0bb355e8, +0xecb1dc73, +0x5834b315, +0xd055411e, +0xaeb3f0dd, +0x1d1be8a9, +0x028e0dbe, +0xa322a156, +0xd7ef2316, +0x6b4003a9, +0xff95e6c6, +0x9e83be52, +0x61868439, +0xac0073dc, +0x57fcbb57, +0xea768bb2, +0x6052b8aa, +0x85a13371, +0x30bf778e, +0xa79f335b, +0x802fe9b2, +0x544d53d2, +0x56ab3094, +0x4063e36a, +0x61d82682, +0x9d63a2b6, +0x6e42a5a5, +0x5eaceaea, +0x3f098dc0, +0x998ecdc5, +0x93ed0198, +0x4662860c, +0x7c124d8c, +0x54883038, +0x346759c9, +0xc8095dc0, +0x84beaa3c, +0x1f5bd8e8, +0x7046991c, +0x7a437d2c, +0x24b5940b, +0xe98a2eb7, +0x2169e9af, +0x24ac1864, +0xd0ad084f, +0x396c8ac4, +0x77ae7159, +0x9f5ac240, +0xb86b83f5, +0x5ffc475d, +0x934b4154, +0xf79cad93, +0xa460df57, +0x2ad149fe, +0xd7a9dcb7, +0x7031823c, +0xc3ef9294, +0xb0fa846c, +0x45bc4364, +0x66c2838f, +0x520389f4, +0x65419b65, +0x52d73a12, +0x28787c1c, +0x7c864251, +0x5f3fdd52, +0x0a86809d, +0x75b2069a, +0x032efeb5, +0x3c7fca2f, +0x7aa43f1e, +0xbb0196bd, +0x475db1a0, +0xb6d86920, +0xc2a69bdc, +0x01ab8cfc, +0x775112b4, +0x9538c25f, +0xd01fab48, +0x3c4d6988, +0xfebfd2f8, +0x3aa7581b, +0x122c6ba4, +0x17af97c3, +0x5d4bd5e8, +0x88f48683, +0x7e44d6f1, +0x394df05f, +0x719953d9, +0xa05790c3, +0x8b574f57, +0x8ef606c2, +0x954e659d, +0xaef46b09, +0x3580633f, +0x6f4c5ec8, +0xab44e106, +0x94289ab3, +0x16465620, +0xca95bef2, +0x525ebd5e, +0x0d83f1c6, +0x89e87376, +0x65972b59, +0x641eaac7, +0x1407cbe6, +0xc5245d27, +0xed83f8e0, +0x1ec6f38a, +0x4fd8e130, +0xca3dc369, +0xd3465e24, +0x28183f4a, +0x598c9974, +0x736132c2, +0x4b78994d, +0x3ad889c4, +0x204b09b3, +0x0272d68b, +0xc51ca7fb, +0xe6f5dead, +0xe2040483, +0x5d5964a2, +0x04780145, +0xf6393feb, +0x2db80c9b, +0x8e4fa2d1, +0xed502d10, +0xa53709b4, +0xe056f703, +0x88d887ad, +0x5e8baed0, +0xa948cf04, +0x702d3203, +0x35ada694, +0xfea67b1f, +0x9bc014ec, +0x63b6f48c, +0x88cb394b, +0xcecd7d1f, +0x4408cd88, +0x3acceec7, +0x39b80234, +0x77811184, +0xf44ef467, +0xc81a90dc, +0xff5ee534, +0x6adf997b, +0x3297f8f9, +0xa7172429, +0xe536e983, +0x1558cf60, +0x41df2942, +0x31d5aa4f, +0xf381dbf5, +0x11c6d529, +0x63a0951e, +0x8f85a282, +0x0203987d, +0xaf5cf4eb, +0x59b8f7b1, +0xc889c3df, +0xa20f52fb, +0x44f6fde6, +0xf3d2910e, +0x55c96b94, +0x83a360b5, +0x6ff940c9, +0x3ee59898, +0xe9e6b715, +0x3e55b94d, +0x1b7eafcf, +0xdf50573c, +0x2c943a0e, +0x59e3095d, +0xce064cf0, +0xb412152e, +0x7e965582, +0xb3da8b52, +0x9dc11f3d, +0x5c318ab5, +0xea3f22ab, +0x926c92d9, +0x436c108d, +0xd5a50455, +0xa3d8a9c2, +0xe167dcbe, +0x6a76a4db, +0xb81ebfbf, +0xda75dda4, +0x0c1b5759, +0x9fe297c4, +0x37f5bff5, +0xb4f00819, +0x39a97e1c, +0x7ca8d6e8, +0x968fc69b, +0x8be532ed, +0x7fea3488, +0x37e28c01, +0x84b166f8, +0x1af762ca, +0xc28eac81, +0x9f196892, +0x8b763557, +0xbc01c1a0, +0xf1d3e739, +0x7a8305fa, +0xb20af97e, +0x7f6d66a0, +0xdf1ce2cb, +0xaeba9b84, +0x1009b9e2, +0x3332ee25, +0xc6f59fa1, +0xd08994a0, +0x3308f588, +0xf4c671ac, +0x6845854a, +0x2b7372ae, +0x342c75aa, +0x382c5973, +0x7a1bf655, +0xbe5ab2a7, +0x7db41447, +0x7a333c18, +0x2f63fb62, +0x52ba6010, +0xd70bc7d0, +0x6eaad2f7, +0xe96a2066, +0x40a8df56, +0x92540d1a, +0xae2a9bb6, +0x14b0936c, +0x8d0943da, +0x367f5b50, +0x543435a0, +0x522cd476, +0x8157c886, +0x7bdf9918, +0x1312e9e9, +0xbe994502, +0x2eff46f2, +0x4c8fd7ca, +0xc07be1fd, +0x7e3de052, +0x0729b67e, +0xb9328a97, +0x913127f2, +0x0abf0c86, +0x3f5e6d3a, +0x60d68dab, +0x5c26f1df, +0x15df9aaa, +0x24357d98, +0x95dba3ae, +0x845afa79, +0xd0f7c146, +0x6b361e73, +0xcdb7840c, +0x83bccbc9, +0xa476c112, +0xf1b06bc5, +0xfa682539, +0xf54c3c6a, +0x5bd0e322, +0x454b8632, +0x5c4d3724, +0x24baaf29, +0x4406bbbd, +0x2f5f39aa, +0x37390b26, +0xa75bcbf0, +0x9fcebd60, +0xfe40eaf8, +0xdbec1458, +0x549b196c, +0x97e66522, +0xf2f10274, +0x6c205de1, +0xd198d5ea, +0xae82904c, +0x35f4ab9c, +0xc4ab18fb, +0x669f44e0, +0x6a3943aa, +0xb09c1813, +0xd9289f36, +0x11ea8123, +0x08aafedf, +0x2ef1f251, +0x6d7bd851, +0x237cebbd, +0x1e9af47f, +0xea78c049, +0x232ee16c, +0x6bfb5516, +0x553fcdd6, +0x681d0de7, +0x83b5c741, +0x4538432f, +0xfed938ce, +0xacf0ae8a, +0xac51de1d, +0x9f9004d5, +0x37e1a846, +0x8436e25e, +0x48fee4f8, +0x2c13e77f, +0x92325b51, +0x188c5987, +0xcb360100, +0x5849e125, +0x790c0916, +0x97eca12d, +0xa5ed3c96, +0x36b9122c, +0x210c5487, +0x41064c8f, +0x168b191e, +0xdd790fd7, +0x48814b75, +0x83efb252, +0x3fef63d8, +0x676579fe, +0x454d5fae, +0xe7499484, +0x474dcc94, +0x1afe2c2b, +0x6f343639, +0x4cfa76a6, +0x433472e5, +0x954a49bf, +0x1b894bfc, +0x97afa741, +0x7ac15509, +0x82dba4d8, +0x1d0b101c, +0xef81e8cf, +0x243ba88c, +0xc6a75989, +0x507cf0f6, +0x6dbf2584, +0x1bbe6622, +0xe1c96ecb, +0x43133a2c, +0x3d57d32c, +0xd81e64ea, +0xeac8b9c1, +0x29448c50, +0xca183ab5, +0xbf149d97, +0xb59eb47b, +0xeb5190da, +0xf7b7c006, +0x2a31c99a, +0x6639d08e, +0xdef213ba, +0x177109fa, +0xac6e8cf8, +0xca1ace45, +0x8e5caae0, +0xd313a1e7, +0xcab52ab8, +0xf9f7b1c5, +0x5e8b40e6, +0xbf78d0e3, +0xb53a1616, +0x7717cda9, +0x82938809, +0x0cb07cd6, +0x428c9ded, +0x93ea525b, +0x8030f10e, +0xd9a31590, +0x3be12be5, +0xa375e5d8, +0x473b016e, +0xc84b4fb2, +0x7056de39, +0x0a803468, +0xd3185c6a, +0xced74411, +0x985aabf4, +0x3b39de1e, +0xd269744e, +0xb648a900, +0x542a0aad, +0x3a0af496, +0x550420ed, +0x7f5ef291, +0x66759f06, +0xae8babc9, +0x8fb894fd, +0xd2bcba40, +0x4e4eaef6, +0x69560af8, +0xcc907182, +0xf4505f6d, +0x9ec795af, +0x868a042e, +0x74319136, +0x9a5ab474, +0x2da21400, +0xe95a6642, +0xdd4c60a3, +0xb30d422b, +0x9de86841, +0xb9f50315, +0x2e6e997c, +0x5a549d11, +0x71a71c86, +0xad9df373, +0x192ed789, +0x70651b6b, +0xf1415e24, +0x4ef507b9, +0xd630ea15, +0x2a229b0f, +0x49a9edea, +0x65c9f203, +0xdc80c24c, +0x294e5b34, +0x8a8afcbd, +0x9cce7a87, +0x4998f40e, +0x89638f81, +0xba4007dd, +0x4e2ea32d, +0xb0c30023, +0x35dced96, +0x18a00ffd, +0x98fb6562, +0x043cd1f3, +0xf295d4aa, +0xcd40b4c6, +0x6d56700f, +0x3999c87b, +0xe49cd126, +0xf25b3811, +0x964f3b54, +0x526734d0, +0x7a3479cb, +0xf6f11ad5, +0x79bfdf03, +0xa03e7f71, +0x8eebff7a, +0xdca667e1, +0x90031d44, +0x58684e04, +0x35c6b08c, +0x665685b5, +0x4c196081, +0x810ab6cd, +0xfcc9e392, +0x99d5454c, +0x28705f7f, +0x7d147aa3, +0x3fba76cf, +0x27bc5ba5, +0x1c5ed7e4, +0xa9598559, +0x81e09c20, +0xc44bfd17, +0x876b45df, +0x98a47b57, +0xbc33b541, +0x65cf0b28, +0x5be59efd, +0xbc74798c, +0x3c748f7e, +0x1d4c86c8, +0x1ae90fb6, +0x6bf2f744, +0xd1b09f24, +0xfd782623, +0xf6679ed7, +0x29c118f4, +0xcd6970bf, +0x725df327, +0x882c4852, +0xdccd71e0, +0xe4e08fa4, +0x4c00a4ba, +0x87030850, +0xc19d95fd, +0xaecab820, +0x3598be66, +0xa0e662ec, +0x214cf837, +0x49d77b19, +0x826ac833, +0x40a005c1, +0x67848083, +0x23890c87, +0xc22459cb, +0xdd02df3b, +0x2641fcf3, +0x9bfa605e, +0xd9a39a68, +0x8747d13d, +0x814df76c, +0x0cb97438, +0x08aefd1a, +0x8baa15da, +0x2687ed9c, +0x83e09ebd, +0x9240ed27, +0x4d2ba0af, +0xb72e5a48, +0xd5c582fa, +0x97384095, +0x89c1e46b, +0x63a1ae3a, +0x04b4fdc3, +0x7949ef5e, +0x8f45cc8f, +0x926152f8, +0xab0eaddb, +0xd3ecddb6, +0xac762e8f, +0x27be3b7f, +0x040621bd, +0x8deda5bf, +0x499f9a10, +0xe0951f1f, +0x2f7efcf7, +0x683a26c6, +0x927fc66b, +0x890b7624, +0x750cbeb2, +0xb0a0979c, +0x9ce8d57f, +0x304462c2, +0xe46aa144, +0x52d4455d, +0x31b6dfdb, +0x1b2eae3b, +0x52987022, +0xb4d6d86a, +0xa84372e5, +0x9aa57ce1, +0x17fd2a91, +0x37556dee, +0xc2abe74c, +0xc3a92b98, +0x1ac9fb36, +0xd8272877, +0xc94c5a32, +0xcd964355, +0xe3cbb4a1, +0x4910d6ba, +0xf7177ce9, +0xf279f210, +0xe0bc1120, +0xa96b7063, +0x94dc9eab, +0x1be60955, +0xb9fe8dfb, +0x88f852bf, +0x7f793590, +0xebf92402, +0x0b99c8fd, +0xd450dde6, +0x20b0dd0b, +0xbb992f4c, +0x041a4d87, +0x23f6f164, +0xcf43eb9c, +0xe145e8f6, +0x6b095a7f, +0x0a9dab77, +0x539ef38c, +0xdb869ca7, +0xbf5cdfbf, +0x35db145f, +0x060bd4c5, +0xc034d041, +0x629d29ca, +0x4fe15e81, +0xfd3e91dc, +0x2b113bfe, +0x5dbd69ca, +0xdbfe0e0d, +0x4ca2e6ec, +0x304e92e5, +0x705459b7, +0x68df8988, +0xd492d7be, +0xb18785a7, +0xe248d3d1, +0x9ef220f3, +0x0fedbfb5, +0x76a71f17, +0x35fedbbc, +0x2a38c87c, +0x34e71459, +0x9c613228, +0xf358691d, +0x102d3f9b, +0x9f156438, +0xb4e68ff0, +0x2488fc5d, +0xcc749e4b, +0xb0bfca3f, +0x694a739b, +0x0dc6cf78, +0x2060ef48, +0xa0e570cf, +0x5c8c0c8f, +0xafd43855, +0x42245a2d, +0xd419c478, +0x122ba602, +0x41bfafd3, +0xfba62c6f, +0xcee3e2e3, +0x569299c0, +0x978ce0e7, +0xe2d14cfb, +0xc30eed3b, +0xf3b8a4c6, +0x1672026a, +0xd36f9e56, +0x08007ab6, +0x6107c413, +0x436126a9, +0xb63795f5, +0x035c23c5, +0x5b588ade, +0x4c75d2b6, +0x3a8b1931, +0x5781d7aa, +0xc88505e5, +0x401797aa, +0x0eca8c96, +0x65e53c07, +0xd0eceeac, +0x35b72060, +0x932d72c7, +0xfd0d356a, +0x8f8cbed4, +0x87dbcb72, +0xbcb4db3a, +0xf4b4ab31, +0x9b385eaf, +0x65b3756c, +0x0e5e610c, +0xd7d7a8dc, +0xe9317e47, +0x7f92aca0, +0x15ea2730, +0xa0da2e59, +0xd4381b1f, +0x89695e26, +0x74257d20, +0xbbc59798, +0x1585fcee, +0xcfa1594f, +0x7eeac74b, +0x3fe321a2, +0x00167896, +0x3a103adc, +0x0bf693eb, +0x0705dc7c, +0x6c2ebabb, +0xef5ea090, +0xfb818299, +0x1462e032, +0x268e58d6, +0x5116c318, +0x70aaabb2, +0x87ebae8b, +0x0244aab2, +0x07497479, +0xa4566efd, +0xa17a4462, +0x871a18ef, +0x7ff3ebc7, +0xe9bf73a0, +0x337fb30d, +0xf3e68cb9, +0x95fda1e8, +0x5750b9c5, +0x5a33b699, +0x4410fe22, +0x985ee3f2, +0x27bb27c1, +0x44757f8c, +0xe851a5d3, +0xa03dbb3c, +0x4a3365d3, +0xa6e3ccf5, +0x97ff37eb, +0xd8ea5bc7, +0xad8f2ba8, +0x03d2b93e, +0xffbef924, +0xb56446b6, +0xab726d16, +0xe74c50f3, +0x73de21ed, +0x704cc4f6, +0x1f35dc19, +0xec66b494, +0x4ed3986c, +0x4f424ba9, +0xb31c9dc3, +0xab99b7a8, +0x977c17cc, +0x51a48ee0, +0xba47c56b, +0x95436b46, +0x04d94b19, +0x71d156ed, +0x3ac8964f, +0xd6bae400, +0x967966c5, +0x0453b242, +0x8e11a87d, +0x3569cae2, +0x1b9c99e2, +0x69274776, +0xf9cc0fe2, +0x04650339, +0x1e0e2c4c, +0x4ae1e105, +0x8d035f83, +0xc7b4bdd3, +0x559fcdcc, +0x7bc329c0, +0x545688d6, +0x7ae11de5, +0x44a5b6fd, +0x1ea2597c, +0xe0da25ac, +0x54b20591, +0x1ebf2734, +0x6f5ceab4, +0xaf977e3d, +0x7c2f428f, +0x24ac5b67, +0x027084ab, +0x213a1356, +0xdb1c515e, +0x53861d1c, +0x9c0a86cb, +0xf18d1174, +0x42d6c33d, +0x76679ea6, +0xee45c1be, +0x4e0ba122, +0x9acbec0d, +0x628a0dc6, +0x0446324a, +0x0bb379ea, +0x7900bdbe, +0x58ab45d6, +0x155a12c4, +0xe43c73ac, +0xa5a6f292, +0x43765290, +0x39703b99, +0xfb7e6a88, +0x9f969e82, +0xa1aa65f6, +0x100028e8, +0x181ce2f8, +0x33868a11, +0xcdcf0408, +0x514609bd, +0x16742f83, +0x289d08f5, +0x95d3135a, +0x351d2550, +0x65dc17f6, +0xf52712b9, +0x6c7fd366, +0xae59d5bf, +0xf7d51a31, +0x766e7416, +0xa06920f0, +0xf031c1de, +0xfb3a4976, +0x40a2af48, +0xf5df39d3, +0x67b487f6, +0xe1755089, +0x6831d28e, +0xab744aeb, +0xe70e6833, +0x64c975d7, +0x3ee711ba, +0xfe93e3fe, +0x958b449f, +0x6058a027, +0x495936ce, +0x957e0022, +0xb4068279, +0x200f8c77, +0xd0ddcc21, +0xa43afcd9, +0x55adc2c7, +0x203826a3, +0x57bfc79b, +0x58580229, +0x8a98d2d6, +0x88ea3f08, +0xf67fa34b, +0xeee366a0, +0x010f4972, +0x08a73c36, +0xaa8dd893, +0x5339c0cd, +0x9df9f85f, +0xbbeb2c1d, +0x044e5914, +0x6cc0ab86, +0x30aa4cb9, +0x8ef89a9d, +0xafbf0472, +0x5b4ebbc0, +0xa3508118, +0x44a04aad, +0xd9f8fb66, +0xab5a1ea8, +0x3ac941cb, +0x1aaaece6, +0x1b0812cf, +0x75278158, +0x4b220690, +0x4f330cf0, +0xae155ea7, +0xb5dde032, +0xf2a878eb, +0x24f867e8, +0xdfdeeef7, +0xce2d9f03, +0x51695022, +0x0b18d323, +0x4c417c58, +0xd665bc64, +0x427de71e, +0x48b0a713, +0xcaf023a3, +0x685322f2, +0x78aa9d2f, +0xdbf34911, +0xc1d65a83, +0x101f3ae6, +0xd46ecb54, +0x1a680c81, +0xd02425fe, +0x64c5b69e, +0xfbb8ca68, +0x2ac7ebc2, +0xa0529352, +0x9d28274b, +0x2b84de88, +0x07b053e1, +0x1127f539, +0xab69afda, +0x8840ac73, +0xb4346346, +0x183942ec, +0x1c88f09c, +0xf6e5984c, +0x0296970e, +0xa730203f, +0x1b647133, +0x446e9d21, +0x27c3f376, +0x47e1dd28, +0xd732cc0e, +0x3381083f, +0x3230f37c, +0xf805f37f, +0x348032e4, +0xaa5ca983, +0xb3dd21bc, +0x48c78e23, +0x3330c0dc, +0x1955aeac, +0x0e9ca4c0, +0x9d210113, +0x852cf856, +0x9aa1f2e8, +0x7901f677, +0x359f71a5, +0x96ff5a29, +0xf9c13fea, +0x0ae4bc4a, +0xa93c42e1, +0x94fe2d3b, +0xe83395ee, +0x61a002f4, +0xdbe7af92, +0x67bb34d0, +0x51a9d66f, +0x0375cdd5, +0xb618ceb2, +0x77c9d5f9, +0xa5de79e9, +0x4d23889c, +0x8119cae0, +0xde62a9e7, +0x7bb0326e, +0x79a44dfa, +0xc1e86dba, +0x4ca7e2e6, +0xe149a07c, +0x090691ce, +0xf73a5e14, +0x2c939d4e, +0x2ae4a412, +0x13192f64, +0xd80fff6d, +0xea1b3162, +0xa7056847, +0xf5ae3d79, +0xbb28a344, +0x09cc67f0, +0xc15d4016, +0x59c054e0, +0x3fa74496, +0xd4124c19, +0xaf138730, +0xe47b1a7a, +0x1a884532, +0xd000e9da, +0x471412c1, +0x147502b6, +0x7a1660b6, +0x82534fe0, +0xa8bc4796, +0xfc227932, +0x272c8814, +0x8d6230d1, +0x8394e950, +0x9888bf70, +0x53caa038, +0x236f8409, +0x802b52f7, +0xf9dda17d, +0xd015655d, +0xeda5ac38, +0x34f0aa8a, +0x337941be, +0x888b34f5, +0x72ec3cb4, +0x9e580415, +0xfcd25747, +0x4989b075, +0x18da1688, +0x73f25a46, +0x7687936b, +0x6a3b7c71, +0x42548a80, +0xab6dd98f, +0x8b99037b, +0xc6a479d5, +0x32c193de, +0x2b8c0e2b, +0xcf57aad5, +0x006a512b, +0xa4de6868, +0x6c8cc7b7, +0xe2a7bab7, +0x2a794334, +0x527ef7e1, +0x7e93d62a, +0xadad057c, +0x3db7624b, +0xcad91953, +0xd50eeb52, +0x0af8a442, +0xf059c351, +0x5e3e6e8b, +0xa828492f, +0xa5b3f306, +0xde945e22, +0xfe2e4ec3, +0xe0be07d1, +0x328b47c9, +0x0eb783cb, +0x514c3460, +0xdd6a1786, +0x2e45084f, +0x52e93c02, +0x569e8b2c, +0x8f9d5186, +0xe02a2c69, +0x0d22f496, +0x6a0ecd86, +0x9ddd3272, +0x55d31906, +0x420c3ce4, +0x7d265168, +0xae941340, +0x5efc716b, +0x1ae5807b, +0xc1723e3e, +0xfd13067c, +0x084f6f3d, +0x319f1870, +0x371281e0, +0xcfaa9be9, +0xef6eaf59, +0x5bbef834, +0xca4abd4b, +0x770b42f8, +0x65a0978f, +0xb5c6e5c6, +0xfe3d88c8, +0xfd390094, +0x5edccacd, +0x2a32089c, +0x3e0b75b3, +0x9ed8b43d, +0x902b4841, +0xc93c29b0, +0x5dfdc60c, +0xa5992f7b, +0x3f8e2087, +0x9b020b73, +0xec89b872, +0x62fdb410, +0x93e4f3ea, +0xbac1969f, +0x5741be5c, +0x40d2d37d, +0x8a849248, +0xee3ad934, +0xf6123d83, +0x3a089cc8, +0xca727824, +0x246f0afd, +0x92507ae3, +0x2cc38b87, +0xf987fbf3, +0x495e0b87, +0xf67adcd8, +0xcfe4daa7, +0x56d36fbb, +0x975d2b57, +0x9dc1bd1b, +0x4846eb77, +0xb0138075, +0x4e3319c3, +0x8b9d4fb9, +0xa67a0fe3, +0x141e9eea, +0x492c41d7, +0xe220704d, +0xc0d5d8f1, +0xa8803aeb, +0x17a50b06, +0xcdbd6701, +0x36f7bae9, +0xa6c20c16, +0x65e9bfa0, +0xbfb3d033, +0x992fabb1, +0x6e03d495, +0xf74dfc5f, +0x315b55be, +0xfd64fb56, +0x05e2308a, +0x73d7fc69, +0x4efdde3c, +0x726dadc3, +0xa3f77807, +0xab0e2697, +0x4df964c2, +0x1aeae61b, +0x0c31cac9, +0x59839a03, +0x4e608ffc, +0xfd22613f, +0xc8f5a727, +0x4957c602, +0x0e47be91, +0xc162e167, +0xa1dad6d1, +0x75c71f26, +0xbc753e3f, +0xbbf11df0, +0xd2386c67, +0x9f7a8eeb, +0xcd3caa2d, +0x4f959ab3, +0xde0724f1, +0x5123451b, +0x918cdd38, +0x5e25767c, +0x06c875cd, +0x62a7ee1c, +0xdba3d459, +0x39c40d95, +0xbc5d0d9c, +0x6bf076b3, +0x29dd7162, +0x76b8006c, +0x9f078d38, +0xb5fde1eb, +0xe48d0eae, +0x80e414b9, +0xd317cdc5, +0xa0f6f61e, +0xd4e1397f, +0xd070d5c1, +0xc2e6ef6c, +0x8a409d6c, +0xca351426, +0x201f1296, +0x9e250041, +0xa5dd4609, +0x165d2f3d, +0x0c5c7e6c, +0x3096076b, +0x5ca1bc2d, +0x62cbd77c, +0xee062a5c, +0xc4dcb3a6, +0x1ff42f9d, +0xfb9639fe, +0xed699746, +0x4bd70787, +0xc333570d, +0x9bb9c0fd, +0x7f13858d, +0xf3b1ab3e, +0xd2e507d1, +0x3935a24e, +0xea5dd9f5, +0xdfb8e5be, +0x646989a7, +0x91c37a3a, +0x78d42ed3, +0xb882396f, +0x6fb19e89, +0x4e58576e, +0x69e1ea51, +0x37113de0, +0xad45f1cd, +0x04a4ba1c, +0xdc61f889, +0xeee8392f, +0x6ea06613, +0x704b5793, +0x3dfd7aab, +0xf44d83f3, +0x019796a4, +0xb98b8ce1, +0xdd860175, +0x2a20b503, +0x90764474, +0x8b77f746, +0xe0943ea3, +0x3c0a315c, +0x9fdac5c2, +0x4e139981, diff --git a/src/soc/intel/baytrail/microcode/M0C3067_0000031E.h b/src/soc/intel/baytrail/microcode/M0C3067_0000031E.h new file mode 100644 index 0000000000..021303dfd6 --- /dev/null +++ b/src/soc/intel/baytrail/microcode/M0C3067_0000031E.h @@ -0,0 +1,3264 @@ + 0x00000001, 0x0000031e, 0x11222013, 0x00030673, + 0x74f7a834, 0x00000001, 0x0000000c, 0x0000cbd0, + 0x0000cc00, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000a1, 0x00020001, 0x0000031e, + 0x00000000, 0x00000000, 0x20131122, 0x00003211, + 0x00000001, 0x00030673, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000032f4, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xbf565d55, 0x38258339, 0x8e14da75, 0xcef7e34e, + 0xc193245c, 0x55ecc05b, 0xc9fc0973, 0x4179db61, + 0x156866db, 0xc4bf175a, 0x9d00ca4f, 0xb3e89a09, + 0x7d2c8e19, 0xbf5b667c, 0x7a1a7ac0, 0x26eebc7d, + 0xb2967286, 0xceb685c8, 0xffba02e6, 0x144b5468, + 0x00c428c9, 0x6d15dd3a, 0xf9461953, 0x1632a092, + 0x222335da, 0x1fee67d9, 0xa770513c, 0x4e83def6, + 0xb3d82e5a, 0x50f0b89f, 0x7fe10d45, 0x70f05efd, + 0x5f575449, 0xab71a0a3, 0xfb2a6eb5, 0x0283b4e2, + 0x58a95566, 0x38a4c957, 0x8a682f1b, 0xc49b3009, + 0x1256e90b, 0x33169c52, 0xd91585c4, 0xdf78eb29, + 0x9f403399, 0xa9de58da, 0xfd05c858, 0x5a0f11bc, + 0xc00e7840, 0xb39bd56a, 0xb87f38c7, 0x90141c59, + 0x325933f9, 0x0b0e1332, 0x963c4bef, 0xf203d9ac, + 0x3925365b, 0x2955f8e7, 0x1fc417cb, 0xd840e4e7, + 0x25e9f7fa, 0xfb769b96, 0xc7b8da5e, 0xe81200f0, + 0x71291c12, 0x5989b1e5, 0xc007fdad, 0xd7c9091f, + 0x6a008197, 0x73005539, 0x6d8b436c, 0xbc606f43, + 0x00000011, 0x86993075, 0xa33cfcf4, 0xe2d2093a, + 0xe90654b9, 0xafc52cbf, 0x6fc74f97, 0x7ec453f2, + 0x68ccbefe, 0x3072632e, 0x8a3c8d5e, 0x56e783c7, + 0x80413013, 0xdb88d19f, 0x3eee9c5c, 0x58c22561, + 0xbb8d3c3f, 0xc2986d1e, 0xf0093f8c, 0xa4e7a5c3, + 0x8fc985d3, 0x2ec0ab20, 0x442352b2, 0xc4f77bb6, + 0x0a7b03c5, 0xced18a78, 0xf8e1c50a, 0x0cdc3b59, + 0x2c27a9a2, 0x216806f2, 0xcf8f473c, 0x7055a7e6, + 0x577666e7, 0x1bccfe0a, 0xad5ba35b, 0xc85a588c, + 0x24969d58, 0xa853807c, 0xc772ccd5, 0x23f8d2c6, + 0x3dd86fd1, 0x0a7f79da, 0x48d24f9f, 0x77124fe8, + 0x560f48a3, 0x3c8d81a2, 0x03625f3b, 0x731115cf, + 0x1f1e0bd4, 0xd15c2153, 0xdaad219f, 0xbdd34cfd, + 0x9e3243ef, 0x18a1af49, 0xb0a09da3, 0x6aac90b4, + 0xff81f7de, 0x5ae08902, 0x50266ca0, 0xc49cb4ca, + 0x46800b68, 0x92a53246, 0x09a06ad3, 0x98ef4ee1, + 0x1948db9d, 0xa9d0b2ff, 0x6de1ac47, 0xc046718c, + 0x6c75d258, 0x05f50508, 0xff8bfd9d, 0x9c983218, + 0xe985d80a, 0xd5150d95, 0x849d9f3a, 0x14a0d62c, + 0x910c96b6, 0x28d928fd, 0x588e810d, 0x943e2a5c, + 0x3b708745, 0xab500fa3, 0xc0ba8b55, 0x01cfa928, + 0x44f5b28e, 0x1f5b259b, 0xb23e7f84, 0x6923075e, + 0x7c9fdc17, 0x0a57f37e, 0x25f0bb5a, 0xdf279dfe, + 0x8d7dd592, 0x7912f993, 0xc1230b8e, 0x5c92b024, + 0xfd27e2e0, 0xd97f0c6d, 0xcb1c2eed, 0xd8152ed4, + 0x3e6bad99, 0x89db6805, 0x34bd18fc, 0x5c32216d, + 0xfe576b83, 0xd2cd9ac9, 0x97565c05, 0x86b76584, + 0x717e8c24, 0x06a319bc, 0x6b8cacdc, 0x23c04fb1, + 0x2cbdcd44, 0xd89b5b25, 0xefda5b50, 0xfebb39cf, + 0x63fc7bdf, 0x4fe10275, 0x85ca5ff6, 0xf7d31164, + 0x7a816ce0, 0x95a0cda0, 0x2e52d3c3, 0x6278d12c, + 0xc60214a7, 0xeb8dccdb, 0x32eaa1b1, 0x3f58010f, + 0x4609b2d6, 0x21dae3f5, 0x52f5a2dc, 0xf177d7f6, + 0xe6fc6feb, 0x398452ff, 0xdd2d2e59, 0xd141d83a, + 0x63d668a5, 0xc6699704, 0x29228486, 0x2c6c0735, + 0xf8ec4b50, 0x3c9bbf79, 0xb94358ff, 0xb8f374bc, + 0x69a925a3, 0xc6b63a6f, 0xa1eeac6b, 0x5a095548, + 0x64e192e9, 0xfcea6763, 0x71fa834a, 0xca198982, + 0x3e673a02, 0x334317ba, 0xde290c6d, 0xd6015a36, + 0x0acc939b, 0x2dfd1002, 0xc4801626, 0xf97f402d, + 0xd93d8c86, 0xfbe850a6, 0xc0f63d6e, 0x9063896d, + 0x4f60d190, 0x947b9ad5, 0x30ae46f9, 0xbb853e58, + 0xc37d022f, 0x2943a03e, 0xe3c3f1e1, 0x7b2f1307, + 0x946ed0d9, 0xe4a4332e, 0x6d5cab85, 0xa29a3f68, + 0xe7f03b6a, 0x5cbf1811, 0x7e1de6c5, 0x28ffaa18, + 0xba92f8e2, 0x9980918b, 0x72ddf15b, 0x5964cea2, + 0x1bc3734e, 0xfecee901, 0xeca35041, 0x79407d1e, + 0xb3c9abbc, 0xe17fc624, 0x9aff0689, 0xa27a353e, + 0xa42c890f, 0xa6f9598f, 0xfd2bd5da, 0x576c8b70, + 0xda028ac6, 0x10d7ffc8, 0x8a5d424c, 0x213195ee, + 0x24533e0d, 0x4057825a, 0x0d476585, 0xe15cd557, + 0xf77787e4, 0x682d7bf2, 0x14c08836, 0x51473972, + 0x7f8333df, 0x0f9613b0, 0x1a760778, 0x4dc1b5d1, + 0x06a1a134, 0x788904d8, 0x65e62607, 0xf58b4e41, + 0x2cd54b64, 0x30e0226a, 0x97e39de5, 0x03029535, + 0x298be450, 0x15ba4051, 0xf8d95dbd, 0x90ac7352, + 0x75c126f6, 0x0bd61e6e, 0xc5cf5c44, 0xcc921f68, + 0x89948225, 0xf5adbbff, 0x47472423, 0x3ec39457, + 0xde8bbde1, 0xc4a5f48e, 0xd6c6b31f, 0x6d977d5e, + 0x03a00c06, 0x7ead487b, 0x5e9a5be8, 0xb7d2fee3, + 0x50ae2479, 0x0094f50c, 0x2e1fe01c, 0x60a7e74e, + 0x73ede666, 0x172eb04f, 0x99735f29, 0x045140d7, + 0x51f1d74f, 0x0ba058fc, 0xd043447e, 0xf655353c, + 0xc5667d4d, 0x57e0acc6, 0xc7b01b29, 0xaa867411, + 0x92d759b9, 0xcda67ed4, 0x4b6140c7, 0x19273ea1, + 0x63b03909, 0xc07793ed, 0xde39ec06, 0x316e6070, + 0x1c33f0f5, 0x1d1904ae, 0x1cd7c500, 0x687b30df, + 0xd14d5602, 0x9c02fd14, 0xb75480c1, 0x7002f6b0, + 0x2a6b7e2d, 0x9dc8208f, 0xc1427074, 0x5101e312, + 0x1a346f36, 0x57510e13, 0x155c4b21, 0x2aa942ec, + 0x079bfa9d, 0xdab867a2, 0x9bac8fea, 0x75ec8c01, + 0x50d9cf16, 0x7113908c, 0x79b74b0f, 0xcbeafb52, + 0x337396cf, 0x0a826b1b, 0x59e36435, 0x44680dbc, + 0x6d6c23cb, 0x432d3c7a, 0x57c0fb67, 0xf13f0fe5, + 0xb825a278, 0x664ad9d2, 0x0ec9e15f, 0x93e0a0d5, + 0xc87f0dac, 0xda407a74, 0xf65670ab, 0xcdad17a1, + 0x070cd828, 0x4fc961fa, 0xd732eaed, 0xa1d5832e, + 0xf8100a82, 0x7df6daea, 0x20846dc8, 0xa72a2dff, + 0xf82e1ef6, 0x1ff8bef2, 0x6c80161e, 0x9d5559bb, + 0xb770aeda, 0xd080ff65, 0xe4abd3ef, 0x75583652, + 0x4c14a25c, 0xcca4a73d, 0x0e58bf7d, 0xec3720cd, + 0x1b558e5c, 0xb48ca16c, 0x77b603b3, 0x487a32d1, + 0xf6d041a9, 0x165c6872, 0xc8a08b2a, 0x9fb8edef, + 0xaf096381, 0x02a6f39a, 0x0869a696, 0x8a3cb00a, + 0x851b951f, 0x477568e2, 0x732e6d0f, 0xf356b0d1, + 0x398e48f4, 0x84e44a65, 0xe02b9b01, 0x14b0fc90, + 0x0f09cee2, 0xcfd7ff9a, 0x5da0ed16, 0x4be7d666, + 0x046f24ca, 0x29c92cba, 0x3dd830f7, 0xeef21118, + 0x0c939afa, 0xd2d9ce88, 0xf021a60f, 0x59fd537b, + 0xabef3ae8, 0x9fcd742d, 0x66a44a16, 0xb0f6040c, + 0xd7fb9687, 0x6ce92a37, 0x5730d84f, 0xd766b94d, + 0x2aec6c41, 0x452e4867, 0xe9374196, 0x3cff49f7, + 0x4d2ce871, 0x1f03bb3f, 0x8117859d, 0x5b22b7eb, + 0x327a0daa, 0x2d768d48, 0x543edd6f, 0xc76ceb41, + 0x814430fb, 0xcea0d50d, 0x5fba5606, 0x9465fad2, + 0xc84afa0c, 0x8af94721, 0xded00da4, 0xb8c2a217, + 0xd4329a8b, 0xc6fbff61, 0x8a82ec7e, 0x4ce636d1, + 0x4ba0d496, 0xc2a3bca0, 0xa5c3de9c, 0xd0caddc2, + 0x5d2ff620, 0x7e6a71d1, 0xcb737271, 0xa0e15773, + 0xad2336ab, 0xbcb621d6, 0x5f94ff6f, 0x393389f8, + 0x7cc193ac, 0xcb096988, 0xbe5cf2b4, 0x474a4bd9, + 0x43002571, 0xc4aad175, 0xe158db6d, 0xae279b66, + 0x8f602d13, 0x3a4676bc, 0x32cb5292, 0xb0d10113, + 0x00762103, 0x99c14c73, 0xebb942f5, 0x08a6057d, + 0xf0c627a2, 0xa42b0a0e, 0x142935e7, 0xec8dae9f, + 0xf553ca4d, 0xb9b970c7, 0x79cf447a, 0x1068309f, + 0x33f30b5f, 0x3b48c9ac, 0x4f5532a9, 0x8256a232, + 0x4153b2c9, 0x0bfb6fa7, 0xf61bf515, 0xd6abea3c, + 0x6b173626, 0x48ce76f3, 0x2fcedf48, 0xce1bc025, + 0x42877895, 0xb8a16b22, 0x26f02443, 0x738ccf03, + 0x5d5ffb79, 0x99b16976, 0x66e091a1, 0x8587212c, + 0x00a97256, 0xfd0e0fdc, 0x0723b790, 0xf7f575d4, + 0xb5f7d751, 0x212243f2, 0xa84cd6dd, 0x91522ffe, + 0x20332a82, 0x8f48e87e, 0xa027aefd, 0xc03bd1cb, + 0x5d447f67, 0x7a339206, 0x675bebdf, 0x888b3050, + 0xca347b8d, 0x7b49125c, 0xb07a9d19, 0x7c82ae14, + 0x2207d582, 0x303f0d6d, 0x19b0ff02, 0x1204bd7a, + 0x80194ae2, 0x15837433, 0xd2b75746, 0x48628cc3, + 0xe95b7954, 0xe65d6066, 0x976511bf, 0x71b1a28b, + 0x112327ce, 0x7ab110f1, 0x712a4ae4, 0x8b6579be, + 0xc7e41aaf, 0xec7612fc, 0xd944cf82, 0x71dc2570, + 0xf60d242b, 0x25420024, 0x2bb993d5, 0xac610b44, + 0x69a74965, 0xc35d2cf5, 0xb664579c, 0x12235fc6, + 0xb2add3c6, 0xabf28f79, 0x06d0673d, 0x6115a988, + 0x96bdc9dd, 0x82652c0c, 0x65b46776, 0xf9a092ea, + 0x94a68326, 0xe06cdf2c, 0x3b0b0726, 0x8c6c3155, + 0x5395a32c, 0x264d5df1, 0x2871a700, 0x5db44aa7, + 0x559ec6c6, 0x44239073, 0x2f447ab3, 0x4e653dba, + 0xf8d13b24, 0xbe6876e9, 0xe554f09f, 0x7417038a, + 0x661d180f, 0x28f9bee9, 0xf52554cd, 0xba49438a, + 0x722ded7b, 0x746f9af8, 0x506016ef, 0xbfcc654f, + 0xa0239098, 0x632210ad, 0x736327aa, 0x24fa32fa, + 0x546e11a8, 0x368dce69, 0xc2575152, 0xfa7553f4, + 0x168587d9, 0xf3363136, 0x9b21fdb6, 0x470da9ca, + 0xd966f45a, 0x6005a5c9, 0xfe049c3f, 0x5e046cb1, + 0xc2f7a9d6, 0xe2231756, 0x84b3a264, 0x87465041, + 0xfaad0fa1, 0xd1c7db7e, 0xd3c841bd, 0xb0662cf5, + 0xc55c0a13, 0x96e17ff7, 0x43ad1176, 0xc54a004c, + 0x831ab6cc, 0xb105bcee, 0x6ac775f7, 0x3ce6e9f8, + 0x9ef4be5a, 0x5fb00a50, 0xc1e8fc9d, 0xf2b477b5, + 0x5582ed32, 0x2233589e, 0x89451382, 0x99b90862, + 0x9e723e59, 0x588bd1de, 0x24f14032, 0x717b283f, + 0x50687dfd, 0xf44d0a3b, 0x5f34b24f, 0x7c90c3eb, + 0xab492f12, 0x6c17c5df, 0x3e032a7d, 0x04a7be72, + 0xbbde4b51, 0x75c94238, 0x28bd23b2, 0xbd29ff15, + 0x07c88cd6, 0xcb700a03, 0x8144797b, 0x64dc5773, + 0xeaaaa475, 0x16c067f4, 0xc969dacb, 0xaa44f5e7, + 0xc8d0fb40, 0xd704a0c5, 0x147a0259, 0x41f6f5e4, + 0x2c48783d, 0x128136cd, 0x9f80dc76, 0x5e0361ff, + 0x00c35d51, 0x2e1b514f, 0xde5d5043, 0x18ce853d, + 0xa0d558b1, 0x40097904, 0xdbeaf286, 0x5d0b2f1c, + 0xa7b18014, 0x0ab263c5, 0xd37631f1, 0x3aeac13b, + 0x89df6a10, 0x8ac84f4d, 0x5efb988d, 0x1f4c0268, + 0xa06a0f98, 0x375cd54b, 0x78f055e1, 0x46adb311, + 0xd8873808, 0xd36c1612, 0x827753a5, 0x405bbcb8, + 0xe5d855c8, 0xeb1fabd5, 0x9a08ef70, 0x88b129f0, + 0xd396b665, 0xd86a4dc5, 0x463de483, 0x9ec23564, + 0xeb5837bf, 0x14245ae2, 0xa9371691, 0xcce16dd5, + 0x3add57e6, 0x5cff6cc6, 0x53a5b3ca, 0x006ee895, + 0x277ac692, 0xcc85f79f, 0x4391ff7d, 0xc82a4ef8, + 0xc39a8858, 0x11250b8c, 0xff865fa3, 0xabe983c2, + 0xe42ebe4a, 0x02e602d2, 0xdd97b804, 0x0f02afae, + 0x84ca5924, 0x68e1cad5, 0x9d2917f9, 0x36ab7bfd, + 0x057a6e8f, 0x63f04ac6, 0x734b3414, 0xc0949d4f, + 0x546cd09b, 0x102ae615, 0x34ebf1b7, 0xb480e6dd, + 0x14255ee7, 0xf0ea12d4, 0xad4fe81e, 0xa03d997a, + 0x61d6038e, 0xd5413dd0, 0x2b64fb8b, 0x52a7910a, + 0x3818a0f2, 0x4de176d7, 0xbb96c3c6, 0x126fd9e3, + 0xf307651b, 0x18d29d43, 0xccfb0a65, 0x6c0c1f49, + 0x1c45496b, 0x80ac25f2, 0x70211f14, 0x120ee80a, + 0x7fb2f153, 0xbe15c491, 0x29e14589, 0x4449e0a1, + 0x4edf43fe, 0xc739e609, 0x495e4781, 0x672ed2cb, + 0x0b76fe85, 0x2a0da259, 0x4c7a15d8, 0xb1fe821f, + 0x3bc66bc1, 0x5a70d187, 0xe84b8a49, 0x5b16d3ae, + 0x9c111f6e, 0x0f0e95ef, 0x7d861361, 0xbd3e7547, + 0xdc9a080c, 0x125c96c9, 0xa97aea0a, 0xeb280954, + 0xd7e6db61, 0x265e0fdc, 0x4664c0cd, 0x71f23a6c, + 0xfb9fdca3, 0xd5b39273, 0x5c15d195, 0xf6e6e592, + 0xbdf61fd1, 0xae5913e0, 0x861e93f0, 0xb01225b4, + 0x0ec9115b, 0x9c517296, 0xd265fa8e, 0x86b261e4, + 0xf0692d85, 0x0688a438, 0x06cdebe7, 0xd8e66cdb, + 0x80cbc6a2, 0x7e8cfe67, 0x71dc6fa2, 0xe5d40de7, + 0x7cd1d37b, 0x989156a9, 0x407717f5, 0x5594cd9e, + 0x45a81aa1, 0xfabe3d42, 0x9c2ed10c, 0x1d85491e, + 0x7a9f9133, 0x2b108ef1, 0xe426113d, 0x2068ce7a, + 0xf0ccaef6, 0xc116be90, 0x0fe20781, 0xe9f1ae4e, + 0x1932cd1a, 0xaeaefcf1, 0x3f6f8da5, 0x8233ee4f, + 0xe7718973, 0x47f870e1, 0x723d61ca, 0x49c9f30c, + 0xdf2be261, 0x2f1f8038, 0xdddd41aa, 0x16541423, + 0x9bdd30cd, 0x14decfd4, 0x42c17fc7, 0xb585ebb4, + 0x19a74973, 0x0f95347b, 0x39e2e844, 0x9942a599, + 0x1450d405, 0x598cc42d, 0x13028178, 0xd85b2168, + 0x3388ce9a, 0x063a9580, 0x92565ea5, 0xce1f7243, + 0x33385a51, 0xfc45ffda, 0xf651de2e, 0x1907507a, + 0x4d1d07d5, 0x483b37b7, 0xb94e7a09, 0x08d0907a, + 0x00d1f047, 0xabb97f20, 0x763bda75, 0xcf67244b, + 0xc6678bbd, 0xcbb8446b, 0x3f16dc05, 0x316ab5ef, + 0xf824e089, 0x6947935b, 0x3aee38ca, 0x0446562c, + 0xdde5933e, 0x37f5d64a, 0x4acdee81, 0x2d50aa2a, + 0x61b554ac, 0x7fcbd2ee, 0x8f247ace, 0x37b1cc99, + 0x36d53563, 0xa97ec27e, 0x73acf8b0, 0xe30d7fda, + 0xd3059265, 0x196e0d7f, 0x18376cf8, 0x199f20f6, + 0x311613b3, 0xa5adb2a7, 0xe97d2592, 0xdf8b5cd7, + 0xc9362e9f, 0x23947026, 0x4511b634, 0x68da3d9c, + 0x9b69da16, 0x1f342b1c, 0xf945ded8, 0x1512f7dd, + 0x2fa63569, 0xf7ed00be, 0x0d1a8544, 0xad1d6d74, + 0xc7a858e0, 0xa475b809, 0x1bca5970, 0xccc2c1e2, + 0x6110b605, 0x5c074e63, 0x42c589e6, 0x8f4ca193, + 0xcad9eb5b, 0x9d3d12a7, 0x2f85b623, 0x1bd8adfe, + 0x8cda6742, 0x1467040f, 0x36a1aaab, 0xab3bd9d4, + 0x8c122a00, 0xa066247c, 0x81b517ee, 0x64dc2065, + 0xa3f5aac7, 0xa2eb4193, 0x5ed75da6, 0x1185e863, + 0xb918efc1, 0x618de814, 0xfb3a4287, 0x667e7c54, + 0xdb996d6a, 0xc46017b1, 0x7789c149, 0x1d4ad028, + 0xad503ef7, 0x4531e48a, 0x7616af7a, 0xa142084f, + 0x46bf8d11, 0x44205897, 0x94c267f3, 0x2ab7f510, + 0xa9978502, 0xbc53e506, 0x58659611, 0x57efb750, + 0x7cc65355, 0x9d22f3bc, 0xc42585b1, 0x0140e7c5, + 0x141552e0, 0xefd35097, 0xc17010f7, 0xfb3e1972, + 0x5c341b5e, 0x27a20003, 0xff28cee1, 0x13b06e0a, + 0xd483f674, 0x7fde4210, 0x6e6eb4d3, 0x9b098e6d, + 0x8e12948f, 0xc9a763e1, 0xa46f1c98, 0x52dff147, + 0x6d862dc2, 0xd3828276, 0x9146659f, 0x05fff96a, + 0x73e3872d, 0xa709f27a, 0x2136d8d5, 0xcf77f275, + 0x0cedf6ef, 0xc93b7dba, 0x0e2302c2, 0x6473f453, + 0x8b88bee3, 0xb0baf0b1, 0x2831acec, 0xafa70e75, + 0xecab6817, 0x09e82b17, 0x78ccd8c2, 0x4718e95f, + 0x50b8511d, 0xa491b09d, 0xfd83b844, 0x4cc78ba9, + 0x8bfe99e0, 0xf587318b, 0xdb62b0aa, 0x11f4a06c, + 0x288b02ef, 0xf7c14b8b, 0x143fca2c, 0x0adf7b9b, + 0x538ce33b, 0x5a5e1952, 0xa48cffc5, 0x4a62055d, + 0x38a18dd7, 0x5658c217, 0x4255fe29, 0x2602a634, + 0x68cb5b0f, 0x9b329e26, 0x1bf83981, 0x99d9cb3e, + 0x92d7fc6a, 0xb8191fef, 0xcc1c57a3, 0xf755c1de, + 0x97990946, 0x9e2d6cb9, 0x991941e8, 0x4c37338b, + 0xb79010ed, 0x8cdf39a3, 0x0f88cfbb, 0xdb885644, + 0x409d2721, 0x25c54f27, 0xc3eeeeaf, 0x2bf24bbe, + 0xaececc16, 0x3a82008f, 0xab8b32f7, 0xc29254ce, + 0xf3e7b0af, 0xe94aa114, 0xf85a2d84, 0x58f44736, + 0x4fbe9e56, 0xae35cad4, 0x780c27d2, 0xc6da14a2, + 0x5e26e1e5, 0x37b58819, 0x2cd7c5c1, 0x1d9699ab, + 0x72ec5cca, 0xfca9a49f, 0xf3667835, 0x4fc7d965, + 0xe7e3ed90, 0x205bc031, 0x9b19429a, 0x7cd1c7d9, + 0x4ffea41e, 0x227b953d, 0xc39363db, 0xc62a4f8f, + 0x288716e3, 0xa4d62686, 0xda15e0d4, 0x8ab98e08, + 0x1f1e6c80, 0x93b08433, 0x37ace529, 0x8596988d, + 0xbccb284e, 0x6de275b6, 0xe7bfbff9, 0x500aa98a, + 0xd229e71d, 0x3c4af83e, 0x2e82a123, 0xc7fd6119, + 0xc7818ebe, 0xd5e8430c, 0x47f55f2b, 0xd124f22d, + 0x46478549, 0xb362db78, 0xa4129cc5, 0xd3e114b9, + 0x8e4df6f7, 0x41198dae, 0x8407ca30, 0xea9fc534, + 0xdcc72494, 0x99599608, 0x27b2c746, 0x8626e02d, + 0x7026fb56, 0x1463aafc, 0x707cde60, 0x6df9280b, + 0x3ba65213, 0xb998e450, 0x1dac9110, 0xfccdddb2, + 0x094cc73e, 0xf2f94554, 0x90cb96f6, 0x1ca389ca, + 0x9941f75f, 0x850cd9fc, 0x97b2d2dd, 0xd2291fe4, + 0xe4dec2dc, 0x47aee389, 0xff12240b, 0x0db4c6c9, + 0x0a5ae8a7, 0x5bcba24e, 0x2b01d4b7, 0x6b731967, + 0xb8da5990, 0xc949785f, 0x32100788, 0x7ed8da28, + 0xfe1ab8d1, 0x30b59071, 0x2285ef9d, 0xe3029035, + 0x878e5e90, 0xdea2d6e6, 0x2fb1586a, 0xbc307c9f, + 0x231c7276, 0xc4a1855c, 0x930efb53, 0x1b326944, + 0x04aac196, 0x4454aeca, 0x608ce81e, 0xc9f37572, + 0x88b88493, 0xa09b54df, 0x539adbf0, 0xa01880e2, + 0xac74791b, 0x4322325c, 0xd2bc2364, 0xb27d1575, + 0x2c1b9559, 0x6ba7a6f6, 0x7cd9ae9e, 0x3d675bb4, + 0x379bafea, 0x6937110a, 0xa0d1855e, 0x1c430c95, + 0x339eeb3a, 0x5232ec9c, 0xed3aeb8b, 0x395028af, + 0x7c0eb026, 0x2ad79839, 0x31f82a68, 0x50e47a3b, + 0x89042c57, 0x9134a400, 0x531d82ec, 0x02f2394c, + 0x945c107d, 0x1ac8ccd7, 0x808a9c41, 0x6e748856, + 0xbf0e0dc4, 0xfb0da0ff, 0xe1cef6ef, 0xb20c765e, + 0x0971dbc9, 0x7385e9bc, 0xff31df7b, 0xb102e368, + 0x4277e6e2, 0x10cd8127, 0x89d68846, 0x0f52ac92, + 0xdd2f427b, 0xc57743a9, 0x48cf5fb3, 0xcaad400f, + 0x26ef4057, 0x48228b1b, 0xd56d72f0, 0x1a646667, + 0xcaa87978, 0x53e71f0b, 0x49aca7e6, 0x68ff2a5f, + 0x678d9abe, 0xbbfaeace, 0xca4a048a, 0xaa594ee1, + 0xcf0bb1d0, 0xfeb7bc8e, 0xa857fed9, 0xb3578282, + 0x4fd39f2c, 0xab881286, 0x019ce70c, 0x7896f627, + 0x26191b46, 0xfe3c78f4, 0xa42e692a, 0x4b9018c1, + 0xa4066926, 0xde833f4d, 0xc31a2fd0, 0xea28e969, + 0x5c4a9922, 0x0bf72d6b, 0x59933e6d, 0x01dc943c, + 0x1d374197, 0xd56d5ea2, 0x616d4f8e, 0xd229da83, + 0xb10bccc3, 0x2dd41abb, 0x310cda0d, 0x7610d025, + 0x9887136a, 0x95068a58, 0x41e6ac7d, 0x77137d64, + 0x6fac6ca5, 0xb8552579, 0xbfa3a1da, 0x2bf9011c, + 0x7f73d6d0, 0x851731e8, 0x6fdd72c3, 0x4203d860, + 0xedbdeda2, 0xc545d443, 0x662cf3c8, 0xa8342eb0, + 0x6bde212d, 0xee46381a, 0xa266ab5e, 0xf68e01ba, + 0x9e94324f, 0xe72a6d23, 0x589fe187, 0xc7b9f1ac, + 0x27749e56, 0x1142ad7a, 0x679f17ec, 0x6b7786ad, + 0xaf0776fc, 0xc48a3b00, 0x021e44af, 0xce05cb34, + 0x42b833d1, 0x341a28e8, 0x3bd80897, 0xf503615c, + 0x2835364f, 0x0205bd26, 0xb4437c78, 0x9ad5ddb7, + 0x0bd1d5b9, 0x0ce0f298, 0xc6c8fb58, 0x2c00ed0b, + 0xb81fa7fc, 0xf37c3cf8, 0x254b2e8f, 0xc79843c2, + 0x66cbf695, 0xf880ee7d, 0x58d3165c, 0x32761bb3, + 0x62caf34d, 0xd7110b0d, 0xa9ced7b1, 0xf1e78a6f, + 0xde0f1e3d, 0x1b8559f2, 0x2d1d6b61, 0x1e25a62a, + 0x23890ea5, 0x316851f0, 0xcf81bf63, 0xe432c8ec, + 0xe2670acb, 0x889b716a, 0xf167d8f6, 0xe2ce3ea4, + 0x0fdd6105, 0x3ab98d0e, 0xddb76815, 0x5b50d0d5, + 0x6c72821d, 0x830ec583, 0xd89d44f5, 0xee123312, + 0x936e96d3, 0x17714540, 0x2bee56fa, 0x8b54f390, + 0x9ea2fe49, 0xa261f1e1, 0x5fea57ad, 0x3f981865, + 0x985f3a75, 0xfbc3c0dc, 0xe9a8f17d, 0xea9f23fc, + 0xd4a9bfcf, 0x55789025, 0xa8715ef0, 0x85fda5f6, + 0x3d77b64f, 0x71332e1a, 0x5f0026cc, 0xf940a9df, + 0xd444f5dc, 0x880a4304, 0x2d58ca64, 0xae8f7a5a, + 0x090e46ae, 0x462cfcbe, 0xa1941852, 0x0e767732, + 0x5616c715, 0x54c2acc1, 0xfe6d9be4, 0x42e66d3a, + 0x27c00f86, 0xd3d69e04, 0x1a54bb24, 0xed2552bd, + 0xf7709214, 0xcb178bcf, 0x41cf0563, 0xa76d7626, + 0x65be00b6, 0x31afd6ce, 0x791f585b, 0x5d948793, + 0x20321b9d, 0x976a4abd, 0x8aa576d1, 0xfc286915, + 0x4c29e738, 0x945b943a, 0x336f9564, 0xc75fde9a, + 0x8e35d000, 0xb6caf7da, 0x440f9a9e, 0xf9340566, + 0xdb4a8d36, 0xb92523af, 0x94a359eb, 0xdf4fbffc, + 0xef523d50, 0x2fb05dfe, 0x59841a0a, 0x7db5d9ae, + 0xd21b5fb4, 0x89136b25, 0xd4e70ac5, 0xbe4c54a1, + 0x61224ae2, 0x8c9f1b5c, 0x7b0d3924, 0x2da194ec, + 0x69919006, 0x7ac94822, 0x7cf741b8, 0xa5f80e5d, + 0x25c9d226, 0xc0c5dc88, 0xa1a0c252, 0x827991c5, + 0x8b172a53, 0x9dc39f2f, 0x22379941, 0x042fd018, + 0xa74f669d, 0x0c91d302, 0x3e686f0b, 0x7a2309e3, + 0x5f308bd3, 0xa4bd995c, 0xd10569b6, 0x6ccc8b57, + 0x01e3b622, 0x5ef0ab2b, 0x16578df5, 0x93d3a5fa, + 0xed6b2809, 0x5127b966, 0x21f7fdde, 0x8e5f8374, + 0x7c0efe40, 0x26f7037b, 0x03ce41d7, 0xf4feb35d, + 0xc89b2654, 0x44676ab6, 0x5385fb70, 0x0c6b18ba, + 0x4fd1be37, 0x400b98a0, 0x17339588, 0x73b944a8, + 0x6761afc2, 0x3ad0b9b9, 0xed83ecb8, 0xc0d87835, + 0x94c55e62, 0xebf723e2, 0xa99229eb, 0xcd6939fe, + 0x493e484f, 0x1a875265, 0xa293bdda, 0x3ef3027b, + 0xa1b81af7, 0x656ac6b4, 0x44d45870, 0x2f1a2bb8, + 0xaa2f8c30, 0x6ccc2722, 0x6c9ce089, 0x8a826a74, + 0x79c3801f, 0x2ce3a5b7, 0x49db575b, 0xe1756ae7, + 0x96b90f0d, 0x7db88316, 0xb146be0c, 0xe16e2b37, + 0x79f466b2, 0x0fc9c0f9, 0xd731594a, 0xf4417f11, + 0xd78c5db2, 0x22971a89, 0xdfd46771, 0x33288719, + 0x9ea40d16, 0x24ac0673, 0xdd2ebd1d, 0x60dc770c, + 0x4616fc0a, 0x1851e861, 0xbf1bf5e7, 0x90d2cd44, + 0x4f80074a, 0xe19fe0b3, 0x73bb8109, 0x65b09784, + 0x3ebf3150, 0xde015df6, 0x000a6c09, 0x0664fed0, + 0x35677a0b, 0x9029dfd0, 0xcc7247b6, 0xea52b8f0, + 0xa2efda7e, 0x67ce44a2, 0xf7511014, 0x99d1f014, + 0x20e9f7fd, 0xcb10c51e, 0x30143244, 0xf63abdd8, + 0x7c233587, 0x207ed78e, 0x239b8a29, 0x2562f7ee, + 0x9c520273, 0xfde73326, 0xf47caa50, 0x91405a0b, + 0x3b4df754, 0xce63c39d, 0x1311e0c4, 0x4136b90e, + 0x693e7b04, 0xcfaccd60, 0x15d19062, 0x575c988a, + 0xef93764e, 0x9c83476a, 0xe3091579, 0xa8230f6f, + 0x0bc9041f, 0x40dce4f3, 0xaf6e0b44, 0x85f845fc, + 0xa34e2c96, 0xaf35c5c6, 0x2dc48d78, 0x18df1226, + 0x66520258, 0x967eb4d7, 0xc4f21e5f, 0xeb44471d, + 0xc86420a8, 0x282782fe, 0x1a7d707a, 0x0a268d21, + 0x6828ceb8, 0x33057688, 0xb74039de, 0xf149a8aa, + 0x97dedb10, 0xb11032c9, 0x8b693f65, 0x97acade7, + 0x792df7ca, 0x195429c9, 0xc1e8ec75, 0x5b9110f8, + 0xe11234ea, 0xb4685812, 0xa2c2fb10, 0x80136255, + 0x1effc1a0, 0xc8fc3744, 0xff0103a7, 0xf60187ca, + 0xac960517, 0xfa4a4c0e, 0x5c8dccf0, 0xbe5d2e5a, + 0xe3ac5e6f, 0x0857c37d, 0x6cba5735, 0x8d3dec6f, + 0xe98ec1ec, 0xec49ffeb, 0xd291c4c8, 0x64ed0a94, + 0x8bee800c, 0x0effd327, 0x5885bb11, 0x6c6fa23b, + 0xaa399202, 0x4b1a3310, 0x46bab2e1, 0x9bce015c, + 0xa0455a4d, 0x11a3d593, 0xd667006a, 0xca2241d8, + 0xbe6dc73e, 0xd5461b30, 0x06d38aa5, 0x4bacc1a3, + 0x4002f2f6, 0x6ec05acb, 0x0d7f1720, 0x09983b4c, + 0xd63f9ebc, 0x296be5d4, 0xdf1e40ad, 0xc017636d, + 0xc22ea1e3, 0xa47d8a16, 0xf6eae2a2, 0x58fd07ee, + 0xa346b981, 0x443a70c8, 0xf51d8a7f, 0x0b6a4e5e, + 0x90005b44, 0xd65d20ef, 0xf9c9548b, 0x1b8f670d, + 0x6732c000, 0xc61eae0c, 0xca4dba6c, 0xc57b5f3c, + 0x838412fd, 0x3a64976d, 0x908960bc, 0xe6fc70a6, + 0x23540703, 0x64ad9681, 0xdc99ba25, 0x34302628, + 0x260583ae, 0x1d330877, 0x837d1e3f, 0x17280aaa, + 0x3ad0e4b6, 0xcc4746e7, 0x86c3ada5, 0xb9b50ced, + 0xd1570f3f, 0x5af33a09, 0x05e561e2, 0x42b74345, + 0x2f29f422, 0xe99250dd, 0x3d023347, 0x390d1ac4, + 0x8eb73237, 0xc0ef6a51, 0xf54b5d2a, 0xfb87f00d, + 0x11c9d3ac, 0x73cf0617, 0xdc74cd9f, 0xaa03d91b, + 0x22ff768c, 0xbb5e0a84, 0x54b9bcd6, 0x02bdb8fd, + 0xc365bb43, 0xe8c64d88, 0x5ab95d94, 0x057c8d35, + 0xc62c8a52, 0x1c2c38ac, 0x907e505c, 0x36869f64, + 0x779cd99e, 0x09b91df9, 0x1359ae8e, 0x9910e35a, + 0xf40bdd0e, 0xbfe7c4ab, 0xb810a776, 0x71c8ccbe, + 0x2cf280d7, 0x491c752c, 0x07d0534a, 0xad1be8bb, + 0x01730fa3, 0x0d759a10, 0x75755f5b, 0x3ff564a1, + 0x8b03d3fd, 0xcf2a2a12, 0x4b9e4dea, 0xb4ac64a3, + 0xddc0daee, 0xe8318438, 0x53cf11c8, 0x8ec4ea03, + 0xe8e10d39, 0x70b8a85f, 0x94ccb479, 0xb9f524b5, + 0xd0081dae, 0x4eed46c9, 0xb339612b, 0x4307e5c0, + 0x8aebdc84, 0x07574cc7, 0xd4a6037a, 0xc6ffb6a1, + 0x0c2c43d1, 0x093e79b2, 0xf6a09279, 0x8f38533c, + 0x9fdb1096, 0x76b7b7e1, 0x41e01a6c, 0x8d262b58, + 0xd8dcef0d, 0xf17408f3, 0xfd29abe2, 0xdf40d7ec, + 0x46a54270, 0x97505382, 0x422a468d, 0xd924eb6b, + 0xe22afecd, 0xdd9d4e9c, 0x9909b518, 0x1ec2e4bc, + 0x92d3b2c7, 0x3d51d9b4, 0x7d8af0cd, 0xe41aa28d, + 0x72d2fd01, 0xd06360ca, 0x9520fa85, 0xd5e96f77, + 0x3628906d, 0x16a90354, 0xf4ce3334, 0x5e383904, + 0xd300e05a, 0xe60bcecf, 0x04e4d78a, 0x11c80fe1, + 0x21b8b926, 0x0ac3ab25, 0x58b00c67, 0x4b369e1e, + 0x07b2832f, 0x99a5257d, 0xb47c81dd, 0x8a463df3, + 0x87f1ecd3, 0x8d86d6b2, 0xdd8a61aa, 0x5e5abd11, + 0x0f7c9621, 0x6757b617, 0x166dcea1, 0x3421fc35, + 0xf650dd3c, 0x1c2493f7, 0x5f10c5e9, 0xc23cbd6e, + 0xf381aec3, 0x86f2bd5d, 0xc925f3bb, 0x167d76c7, + 0xd544c23d, 0x3db981e8, 0x4faa24e7, 0xd6d5e5fc, + 0xee252435, 0xc207b120, 0x1532c5dd, 0xc9ae6654, + 0x550d8e87, 0xfc982fc4, 0xca3e1ffb, 0x3cfd73d4, + 0xbfd8a52c, 0x9a675f28, 0xace69af2, 0x934369cd, + 0x2ccee87d, 0x60b6abc5, 0x3e31fdd6, 0x90367e93, + 0x4b1f45a8, 0xee11816b, 0x26aa4e75, 0x31e68a56, + 0x587834b8, 0xb436aa39, 0x60b20bde, 0x740d8bef, + 0x1d0356cc, 0x23cbb474, 0x14e45292, 0xdae455d3, + 0x4ab5ed06, 0x2b34a1b5, 0x4e39243c, 0xa7a019cd, + 0x7ad9e0c7, 0xca551f1d, 0x256318de, 0x0ae0e1c8, + 0x2c94bc45, 0x8a30639c, 0x1243183d, 0x682b91e4, + 0x5d193e08, 0x7d5b9736, 0x7992c858, 0xc7cc6b0b, + 0x35523eb7, 0x06bc5835, 0xb6324673, 0x7679ab7d, + 0x4f520f22, 0x84bf96e6, 0x5f89f846, 0xbc04bce9, + 0x094ea11d, 0xc6bae7f1, 0xdddc8f0d, 0x9aee4aae, + 0x4a43a716, 0xbc0d67cd, 0x6d9b09eb, 0xff971083, + 0xf66611d8, 0x4d6157f0, 0x43b3239b, 0xa82ea565, + 0xeffb5e86, 0xa705cbde, 0x2d7afd0b, 0x80942b2c, + 0x7468e303, 0x9f6b48d1, 0xc28b123b, 0x0dbef60a, + 0x9d0d85e1, 0xbd3357dc, 0xd35a1f77, 0x7b7ee000, + 0xdd224ff1, 0xd46b692a, 0x96467b23, 0x10ca5e31, + 0x8687c144, 0xb04ad7da, 0x5c10bb3e, 0xfd0a7289, + 0xe3617069, 0x150d7480, 0x2e8f9de9, 0x4977e191, + 0x34f24f4b, 0x9700093c, 0x3fe41a74, 0x84ce82d9, + 0x984c34e4, 0xfa344c8b, 0xdb89a561, 0xd202e556, + 0xce60c69e, 0xec16888f, 0x9c3712c3, 0xbdf9f979, + 0x94139ed6, 0x61528928, 0xde87b41c, 0x6a3c245c, + 0xf9774574, 0xad73d53a, 0x876a5fb8, 0xb6413dc5, + 0xdb3e5324, 0x7445cd5e, 0xcd07d031, 0xae1548de, + 0x818409be, 0x503694de, 0xc0f055f1, 0x3b4f791f, + 0xf1a921bf, 0x98447f7f, 0x49a2dab9, 0x582ba48a, + 0x3fa9fe44, 0x51fc0233, 0x41d4bdd3, 0x8c8c2e58, + 0x9e2d3f93, 0xa3037c04, 0xfbe721dc, 0x22bcf9da, + 0x0fb7ffbb, 0x9fd471af, 0xebf97185, 0x2d8543d1, + 0x4477188c, 0xe2a4b44e, 0x31858468, 0x93835021, + 0x4cf8e945, 0x35d3f81b, 0x7be516ab, 0x1b241f76, + 0xe3a11153, 0xb10f7a37, 0x1e630ccb, 0xda847efb, + 0x93d81181, 0x55a83268, 0x21d64d30, 0x1fe02004, + 0x8606d4b2, 0x568c72eb, 0x82b9fc8b, 0xc30528ef, + 0x0c412038, 0xd9960067, 0xe65d945e, 0xee746fbb, + 0x6da22008, 0x6610dacf, 0x9056db07, 0x54167607, + 0xf9c73906, 0xddea5291, 0xbacf5c69, 0xf3df9b69, + 0x11feaff9, 0x0453a8b6, 0x3fe53f61, 0xe29a3dd4, + 0xe7937c1f, 0x760c0e9a, 0x0bc18fe0, 0x95e2946e, + 0x5659ec0d, 0x2827634d, 0x10c94b46, 0x7b9c0e0f, + 0xa76c04af, 0x80311d62, 0xa513fd35, 0xc57dc2eb, + 0x9c6aec8b, 0x6ad02dca, 0x56717e4c, 0x7cd17832, + 0xf38e1886, 0x4b3cfd3e, 0xb0e9c0ce, 0x175e1cea, + 0x9ff1f1c1, 0xff3257a8, 0xb4193253, 0x28165b0f, + 0x167f1fc3, 0xf742786a, 0xe13b7301, 0x479c0959, + 0x1a23c59b, 0xad5c1e7d, 0x97f9bc8a, 0xfc021a74, + 0x79d8e144, 0xcdaaa3a6, 0xd40f2909, 0x534a25e1, + 0xb312f873, 0x3bac337d, 0x727d02b4, 0xa5a20e75, + 0x51101852, 0xf614121a, 0x20fe9116, 0xbed94fe8, + 0x33a0988e, 0xbb2de4ae, 0x63034e39, 0x79d9c3a3, + 0x3840d72b, 0xc2f5654d, 0xe0c5e869, 0x2ed8ad67, + 0xaa1dd829, 0x119d0bb2, 0xd4c40331, 0xc121c991, + 0x40ecbefd, 0x824c4915, 0x9956ea07, 0xcf85eb51, + 0xf0b7bc59, 0xa361494b, 0x4c808069, 0xfdfd0a1d, + 0xd6f966d6, 0x6365fb74, 0xc73c91d2, 0x279e9941, + 0xacac90de, 0x91b5f00b, 0x1711ffb7, 0x2e2f1c2e, + 0x8d0cbbe7, 0x93a07245, 0xa7b623ef, 0x35c87252, + 0x82a4c86a, 0x4f7f36de, 0xcc3a6cb8, 0x88c866d1, + 0xabfdf111, 0xdcc1aeea, 0x702e3253, 0x0d98c7e8, + 0xd21a1cf5, 0x5e7ab282, 0xa2817de4, 0x2a018a1a, + 0x47952cda, 0x1dff27e2, 0x1ff8eec7, 0x8ca93098, + 0xc782faec, 0xef0d00f2, 0x88480c97, 0x8bd9317e, + 0x6149085f, 0xf7af467f, 0x703c2efe, 0x3c351d57, + 0x7d0a702e, 0x6a92b286, 0x1aa9a388, 0xc1a9964f, + 0x2ba28b9b, 0x0a8f604b, 0xb0ebabc8, 0xa55d9957, + 0xcb98cdaa, 0xa0f6f6df, 0x751d03fd, 0x4336044b, + 0x6b9c0b98, 0x8c609a16, 0x29357cb3, 0x26473001, + 0x46124389, 0xd92ba814, 0xc891b904, 0x11e72675, + 0xe43420c7, 0x3b78f29a, 0x2643efcb, 0x06e44cb3, + 0xe68b6aae, 0x350fd91e, 0x6eca3b2e, 0x08fd7f68, + 0x31154efb, 0xdd481cee, 0x0aecd5c3, 0x1df7cc1c, + 0xa7bac7da, 0x0154101c, 0xcb2cd202, 0xa7253a5b, + 0x195bd5d6, 0xc86f712c, 0x781aed1b, 0xe61460a5, + 0x69aaff9f, 0xdad36a76, 0x5d5b6810, 0xa4082fba, + 0x8e5c2880, 0x0a2f109e, 0x4184bdd5, 0xf9e8e63d, + 0x987dc281, 0xb8ecce8f, 0x42f5c73a, 0x1edfd6b8, + 0x5f504024, 0xeaa6bfa2, 0x0e5d4904, 0x04247478, + 0xfbfbf2d6, 0xc8977c6e, 0xff007c56, 0xec950a4c, + 0x29e945b7, 0xab2ea384, 0x80994900, 0x648f17ad, + 0x14a81b41, 0x38dc4013, 0x8e4510a3, 0x458c1b2a, + 0x151f9f76, 0xf244bdc0, 0x6214b024, 0x83171a80, + 0x3227a57a, 0x0b6a183a, 0x05fc6244, 0xae1f9b38, + 0xb8150156, 0x828c7a0d, 0x9aa3fcb6, 0x3653a9de, + 0xd3df54ee, 0xcbe74b3a, 0xad4864cf, 0xe02a96ec, + 0xfa735b79, 0xbb8689da, 0xa9f6144f, 0xa6acae6a, + 0xbf42e674, 0x332248bb, 0x6f17fdc6, 0x747a58c1, + 0x8b38ed4b, 0x5b639be7, 0x045804b7, 0x90d7e58a, + 0x449f8251, 0x61ff0d9a, 0x196d7b18, 0xe1d5f2a1, + 0x6b45a77f, 0x9943e5cc, 0xd1e94039, 0x9ea45ac8, + 0xacef5148, 0xb7304d4d, 0x90a2b367, 0xa3c615a5, + 0xb102e6e3, 0x20b30c55, 0xa9e45e77, 0x012b61e2, + 0xfd4f46fc, 0x11db75b7, 0xcd28b6c4, 0xdd64926b, + 0xff95d8d6, 0x5d3e7c10, 0x8f01d1eb, 0x91db12ec, + 0xb16a9f24, 0x59ede105, 0x05ad4502, 0x766cd29a, + 0x114b7750, 0x7c03893f, 0x746394a9, 0xe4e71094, + 0x4a4f2783, 0xe610aab2, 0x0a7980d6, 0xf0f32758, + 0xfb5cfe04, 0xeb557aae, 0x33972bce, 0xa77728c7, + 0x72ac6056, 0x6ca43233, 0x450a161e, 0x435f2f39, + 0x89161c4e, 0x62b0fb79, 0x4abca503, 0x313c2518, + 0xf13e0b63, 0xe3be6089, 0xd2f3e7e3, 0x8fa0b2a9, + 0xcc674947, 0x5fa1f850, 0x6820f92f, 0x62fd0fd1, + 0xfc66aeff, 0xa94f1417, 0x630e3bc2, 0x3e2eda38, + 0x814907ea, 0x9502e76e, 0x20a4eaec, 0x3f31da60, + 0x33414e93, 0xa9eed304, 0x30358865, 0x1b0c6640, + 0xc07c4b42, 0x50a0f794, 0xa3ab6eab, 0xbd8053ca, + 0x07767977, 0xda49b678, 0x9567e78b, 0x66ca8dd9, + 0xb61b16cb, 0x8c308aa4, 0x49bab603, 0xab414aef, + 0xab13befb, 0x25d9fffe, 0xadc2bacf, 0xd40380a2, + 0x6ceec429, 0xb928c4dd, 0x8353458e, 0xaf9dd0ca, + 0x1dd1e8ff, 0x36b526a3, 0xbc0e5ea7, 0xc43f6f45, + 0x7d6869e8, 0x86bf1842, 0xf4e3697e, 0x13305510, + 0x2613055f, 0x16dff0a6, 0x9343dd1b, 0x0d7af146, + 0x4cd5602b, 0x9096386e, 0xef0c69d9, 0xfc828da3, + 0x3790757b, 0x5a1604be, 0x85ceab33, 0x159cd5c5, + 0x704fefbd, 0x03d2530f, 0xc3ab6110, 0xc152d54b, + 0x4fa7e884, 0xf4da8bb9, 0xf33709d0, 0x7095aeb1, + 0xa4f6aa20, 0xe1715054, 0x0a2859d0, 0xfcd772b8, + 0x26e99e16, 0x2b1004a3, 0xbd6f8586, 0x9008c5ac, + 0xc501917b, 0x461157ef, 0x579a3e4b, 0xce465660, + 0x428d00b9, 0x976d9b22, 0x551bdca5, 0x2fd49d86, + 0x4bf5a7e7, 0x60ebb7e6, 0x981e574d, 0x521fed95, + 0x1d1bcea9, 0x3a571356, 0xbd0b7c1e, 0x3a76fdf8, + 0x5130aa52, 0x40bfe307, 0x4a7536c1, 0x2b5d60f5, + 0xa79ec54e, 0xb8764bdf, 0x4ec60969, 0x55faadfe, + 0x26054b06, 0x212a8287, 0x67621fea, 0x0a3a9f26, + 0xe344972a, 0x9b6eb14b, 0xfa459f61, 0x691f5f25, + 0x2ba9603a, 0x8694065f, 0xc4a6b1f8, 0x14a768ef, + 0x94020d3b, 0x179c90e9, 0x804cd4f2, 0x3b6568b2, + 0x4046c102, 0x73f77d11, 0x488993ee, 0x8e101842, + 0xca8f5762, 0x27417103, 0xc8ce9d40, 0x810dff8b, + 0xea3411c7, 0x4c046e03, 0x6c9ed316, 0x7fa9211d, + 0x7706a2a6, 0x506f311f, 0x7e1bb46f, 0x314fac6a, + 0xc0835554, 0xe65db5d8, 0xc8583ec8, 0x7ca9cc21, + 0x30f57d22, 0x750599a3, 0xf520e2d5, 0x14f07732, + 0x055adad0, 0x33fc9f95, 0x79405cb8, 0xaf635c26, + 0xc5051fa4, 0x01f91f77, 0xbea106fd, 0x3228f638, + 0x8884a5ed, 0xd723ea43, 0xdd110d7d, 0x194785ae, + 0xe60c56d2, 0x5241c47e, 0x7f3b3fa7, 0xb2934078, + 0x3591414f, 0x70d7ae55, 0x4df9591b, 0x566c47df, + 0x7a38adfe, 0xe3f90853, 0x772ac0b6, 0x72e49654, + 0x011268ab, 0x89c22a92, 0xcf5d30da, 0xd0d3dd8f, + 0x596bac9c, 0x1ff07d1c, 0xd8f35b74, 0x109812e7, + 0xdfecb705, 0x39f47be0, 0x9f2d8b3c, 0x6d78bba0, + 0x67cf8859, 0x4a852d4d, 0xeda1d0e4, 0xa29398a8, + 0x96d0b639, 0xc560fb2f, 0x5628c057, 0x59bd87ad, + 0xc2775969, 0x280deb38, 0x1e24e99a, 0x3f044836, + 0x58adf2d7, 0xf7325dd4, 0x405ec8a9, 0xba64d004, + 0xdc83a0b4, 0x93dba248, 0xf5bbfcf1, 0x988dc0e8, + 0x477001ae, 0x0eceaf1c, 0x59a50b5b, 0xf47cdd05, + 0x9b506014, 0x92b08da5, 0x76d58f5b, 0x201e9185, + 0xad3ae16c, 0x97d45939, 0x92a76bff, 0x4b603b13, + 0x6578dd6a, 0x9e7fe47d, 0xeaa8f87e, 0x6e914b28, + 0x95ed4994, 0x873f7ea9, 0xe2271d9d, 0x3639ce14, + 0xd66f875e, 0x50f0664b, 0x1b6c66e5, 0x1d5df7f6, + 0xcd8e6dd0, 0xc32c30ad, 0x00eb7d98, 0x99b14966, + 0x24a1dfb2, 0xa0ce4250, 0xaf04424f, 0x551b960d, + 0xf984af3c, 0xf879c6b9, 0xdeab23d1, 0xe69a1c7f, + 0x333c2628, 0xedc8ebe7, 0x2b820e22, 0x1a0301fc, + 0xdab21431, 0xe26dcf84, 0xe077f727, 0xbee936dc, + 0xe17794a0, 0x7ca79071, 0x5b78a8e8, 0x6f6162d7, + 0x16c478d2, 0x9c38a40b, 0xd8036e50, 0xc7c79ec3, + 0xd421dae8, 0x40f5ae17, 0x2f1b3a7e, 0x0c7547fd, + 0x6596a461, 0x37b6faff, 0x9f50e7a7, 0xd0ca4941, + 0xfd0fd1a0, 0xf7b5e454, 0xfa7e694d, 0x2c9d12d1, + 0x523e9198, 0xa43ce6ab, 0x754debed, 0x6c329ffd, + 0x8cb464d3, 0x9296bd07, 0xb0c94b13, 0x8b79edbd, + 0x3ae66ff8, 0x7a6f73bd, 0x4c94ad17, 0xede21412, + 0x6a521970, 0xc92ba31e, 0x0d2c2ffa, 0x91508bda, + 0x6467d7ea, 0x44528e5c, 0xa50857ac, 0x8a7a3cc9, + 0xef2577f2, 0x00ad2b4d, 0x69adaf79, 0x6724dc4e, + 0xb7fefc9f, 0xc269eeb4, 0x22841b78, 0x275d52ab, + 0x1c29a934, 0x30467267, 0xf3d6fe26, 0xe7182bda, + 0xec81ca38, 0x752f34c8, 0xadf3cb46, 0x4eeccdc1, + 0x1d667c1c, 0xcb53ebb2, 0x2103002a, 0x625dcc6a, + 0x350641ec, 0x7819d810, 0x7c31af20, 0xbeb6f5b2, + 0x310fc860, 0xfa40b5fb, 0x90620956, 0x2153ca3f, + 0x924c79c8, 0x4e1a41ad, 0xd5c20603, 0x9f8a04c0, + 0x743d2987, 0x1dd34953, 0x242b9ef6, 0x1babe9ee, + 0x051d54b8, 0xf9498686, 0xe4a3d732, 0x42cdfeef, + 0xc7afb586, 0x91da5279, 0xf1a8023d, 0x32571823, + 0xdf112fac, 0xd5621774, 0x3de1598d, 0x586a3b88, + 0x60af3b94, 0x0a88850e, 0x85ee67b0, 0xfca8c39c, + 0xefc74b0a, 0x7103177b, 0xd3b65ba3, 0x368d5ecd, + 0x5f99a46c, 0xb63ca199, 0xc144b0f6, 0x7dd42db7, + 0x8767b74c, 0x023bdfac, 0x05256360, 0x194ad34c, + 0xec7b2dcb, 0x9c6d10c7, 0xef5d0342, 0x1d6c2693, + 0xa7de7b55, 0x92727976, 0xfe47e32d, 0xe56ab49b, + 0xb8d0db47, 0x640ea6fa, 0x1f8eed5a, 0xb824bf88, + 0x323677c4, 0xe4bbdb9e, 0xfeddc30c, 0x604dd61e, + 0x87bc873a, 0xbd09fa6e, 0x241dc2ef, 0x905a52e7, + 0xdb6d2135, 0x3cf21fe4, 0xaa40a791, 0xa2471859, + 0x7317bb46, 0x3c12ce9f, 0x18f369b1, 0x030cb559, + 0x442f37fb, 0x1fcf9814, 0x2217de64, 0xe2e68bdf, + 0x943d8001, 0x1f1b8d8a, 0x576a886b, 0x96ead16c, + 0xdb5e7caa, 0xc97d1c50, 0x0e6bb8ce, 0x6d082c04, + 0x37a72738, 0x4d2ced35, 0xdcc6165b, 0xd50aa40b, + 0xf1aba32a, 0x276000a8, 0xd6fc6901, 0x7f568c49, + 0xc39160ab, 0xbaf88b7f, 0x0d3f7a24, 0x6e3f0dd0, + 0x396f0ac4, 0x4fa1d091, 0x81f11830, 0xba59fcdd, + 0xba8b74c9, 0x1d0fef4b, 0x07c4214b, 0x18dcd17e, + 0x27619858, 0x62b7681c, 0x6a5fa01a, 0x25740bcb, + 0x054419ba, 0x83dc3500, 0x38d1845f, 0xfcbe5436, + 0x7aebaceb, 0xf18778ab, 0x511a5509, 0x05752e02, + 0xa748b75f, 0xb9070941, 0x8b303eef, 0x192dba37, + 0x919261f2, 0x78aeecb8, 0x04d24bec, 0x7b8460d5, + 0x2cc387ca, 0xb94a2126, 0xb3f1f858, 0x384ada5b, + 0x14fd4d78, 0x2fd7eeff, 0x4f73bcf2, 0x7895086c, + 0xaf8b1b74, 0x5d7f9c27, 0xeb86aaf8, 0xe5ad98b9, + 0x89081a19, 0x5344e545, 0x35a37b65, 0xd20b11ec, + 0x34cb42b0, 0x7e5cbfea, 0x5836ce81, 0x2ed1bf98, + 0x94c7fa73, 0x854d4090, 0x87488648, 0x357cfcd0, + 0xa6949ca0, 0x4b1cbb7f, 0x0ead7bc3, 0x2a5d2f7d, + 0xea3607d3, 0xbdd9a813, 0x715d55ae, 0x744d03fa, + 0x23195439, 0x70faca06, 0xbb56c127, 0x30face9e, + 0xecf00ec7, 0x8657185d, 0x453dcca6, 0xb3c28f0c, + 0xeeaa6dec, 0x2596a28d, 0x7df3ec0e, 0x934f524e, + 0xc7e4634b, 0xd778afec, 0x5c266a32, 0x8f5ffa83, + 0xa95875d7, 0x46b6db48, 0xdbc1dca9, 0x19feecaf, + 0xb5a05313, 0x1e73bb8b, 0xe74a2b88, 0x64656697, + 0x9a36ed16, 0x282896d3, 0x697bca85, 0xb8b19d12, + 0xe6bfc885, 0xca082fcb, 0xfec085f6, 0x54dee6ec, + 0xf2837748, 0x1b1614f5, 0x63feba0c, 0x7a30024c, + 0x2324905b, 0xf92c5bd2, 0x97dee61e, 0x04a916c6, + 0x9c539aab, 0xe631118c, 0x4b14734a, 0x6d45208b, + 0x66bbdfeb, 0xf12f50c5, 0x6901a54b, 0xa98ff372, + 0xe34f310e, 0xb5031e84, 0x51dfcaf9, 0x67a71328, + 0x41d50333, 0x363d3bce, 0x70386666, 0x69e73680, + 0xbe1510f9, 0xa97d6780, 0xd79bbb72, 0x7f53cb8c, + 0x6f8ec113, 0x0d1e7f23, 0x96dcdbc3, 0xb9558972, + 0x7bf2b701, 0xaa02d861, 0x7bd7af1d, 0x6e093900, + 0x9bfe9bc3, 0xe63eb914, 0x5d8c1275, 0x5bfc16f2, + 0x33c86297, 0x5963f82e, 0xb901b15b, 0x6aef7879, + 0x47436021, 0xbdbbf65b, 0x88011d3a, 0xa1bfc87c, + 0x849033dc, 0x2a7c6a87, 0x43683723, 0x7126a39e, + 0xc555f29e, 0x64836b66, 0x6fcfb8ff, 0x7bfebf43, + 0x5f3c1971, 0x62d8f502, 0x0b0b6d9c, 0xa4dc3239, + 0xedcee9eb, 0xbd8625ba, 0xb93543e6, 0xe4236428, + 0x265b26a9, 0x0527cf2f, 0x39754033, 0x5c7973a2, + 0x6fc21215, 0x57d033bb, 0xc60c3a72, 0xd78cdaf9, + 0xdf7f808a, 0x905790ab, 0xd0f3134a, 0xcad29f56, + 0x0a253c5f, 0xe2497090, 0x8b3bcc01, 0x98c8f66a, + 0x5cea1937, 0x51e6e60b, 0x26aa3f7e, 0xdd84c770, + 0x7731659a, 0xdb739572, 0x7c368ca9, 0xadf5a90d, + 0xd4979acf, 0x6a5e5d36, 0x144c7881, 0x22ec1a06, + 0xa8ef8edd, 0xb36ece19, 0xde73a8a8, 0xc6e58692, + 0x83b1cb2e, 0x96e4169f, 0x5a5bb39c, 0xf77bbead, + 0x89ddf55f, 0x0d28bc3f, 0xf7b0736b, 0x6e7d20c3, + 0x59424289, 0x90f33454, 0x734af829, 0x4b93d588, + 0x9dbc4eb3, 0x5bba339a, 0xeab22cbf, 0x5d2c5851, + 0x131f804d, 0x6bb7bb7c, 0x6d515e30, 0xe12876e6, + 0xcac64d1b, 0x80f4b263, 0xced14977, 0xe488f851, + 0x71961454, 0x20ea4b91, 0xe2d3ab46, 0xd13c9bf4, + 0x8b0575f7, 0x4ac25ea7, 0x1562be37, 0x4575f6ce, + 0xf4784a4f, 0x418d8591, 0x2abc704c, 0xccdd4dd7, + 0x61163204, 0x63173896, 0xe69773ea, 0xc39b7588, + 0x02e82b7f, 0x030c5e96, 0x52d9c6fd, 0xa7450061, + 0x7369e92d, 0xde041ecf, 0x6b028969, 0xfa40cfc5, + 0x9069bafb, 0x7364c892, 0x074a1bc9, 0x7f335ef1, + 0x1b3ae737, 0xf5afed4f, 0x3c29b4e9, 0xaf2cedeb, + 0xa09cab6f, 0xfbbc9bb5, 0x1aa480d9, 0x9b18f1dc, + 0x4a7725f8, 0x58d8e4ba, 0xdfac4731, 0xce6e8312, + 0x6e2d21df, 0x05755bdd, 0x01abaf23, 0xa07d3769, + 0x8cfa0ef0, 0x18e64860, 0x11fa10a4, 0x8818af44, + 0x6bbb67fe, 0x4b74e96a, 0x8d910c9f, 0x82cba49e, + 0x96681fac, 0xcd86e1e6, 0x4ee3e707, 0xf1c80e7b, + 0xc92d7ffa, 0x43e03916, 0x4b87ca87, 0xad9f197d, + 0x76e639d0, 0xc5633334, 0xe01cec33, 0xd5a55934, + 0x4e5ba40a, 0x5925eab2, 0x72383326, 0xa2da4449, + 0x128f2fc3, 0x4bc2f943, 0x815c1fa3, 0xeac488ba, + 0xd1c3cd34, 0x006f3a63, 0x784c579d, 0x87818cac, + 0x726364d1, 0xd6f5272d, 0x1f12538a, 0x8ce8b860, + 0xb8b34f4e, 0xc6953e3c, 0x594bb1a0, 0x252c5587, + 0x751186e1, 0xc744925e, 0xd50699e3, 0x85c88ca8, + 0xd46b079e, 0x604e6557, 0xbcf489d1, 0xfaeb606c, + 0x24c02cd1, 0x01869224, 0x12099284, 0x93fdc86f, + 0xba3a4a24, 0xbb527125, 0xb4ffe340, 0xb42e90dd, + 0x8ad65ac8, 0x1cecd5fd, 0x5dedca6c, 0xc20d5b01, + 0xa0cf6aa9, 0x3d2915cf, 0x87c026b8, 0x4222a93c, + 0x63fb05e2, 0x1248fbef, 0xdcfd4995, 0x7b3b96e5, + 0x16819f78, 0x772d423e, 0x3c951590, 0x62a56f1c, + 0xee0edc86, 0xcbc8c40a, 0xe3416f77, 0x12750cc7, + 0xbc4678a3, 0xcdfdd877, 0x622fdbd9, 0x344151ac, + 0x1e4c1f6b, 0x00d1d6ca, 0x9c3a381e, 0xb0eb9703, + 0xa1db3943, 0xab1b2958, 0xa2a15582, 0xfd6063a2, + 0xa3c4cfc8, 0xdf75852a, 0x5da747a6, 0x486a0e57, + 0x9de47ca8, 0x08d2fd4f, 0x9666bc2a, 0x4d19c9d3, + 0xbf524cae, 0xc6b27b99, 0x7aa44853, 0x8f66e1dc, + 0xf5584f3a, 0x013ad42a, 0xe9c7c7f7, 0xf2a86626, + 0xbd0a7728, 0x57156e15, 0xd6a000be, 0xef40e261, + 0xf798d6f6, 0xa5f6967f, 0x64a010b8, 0xdea52623, + 0x8c1aa73d, 0xd68ba687, 0x6a77b1ee, 0x1df83d5c, + 0xdea9bc81, 0x5c154c70, 0x03ac675c, 0xdaedce0a, + 0xadbb3215, 0x12fe81de, 0x6166798f, 0x8d5f89e7, + 0x03b35c7e, 0xe3185635, 0x50ae5550, 0x2e835a0a, + 0x288d560b, 0x029e79ec, 0x0f8a8937, 0x762ea0ad, + 0xa9bc36fd, 0xe72901d8, 0xc67e8421, 0xe79d4b7b, + 0x38b846b6, 0x0c1e0447, 0xef55bd28, 0x5d544024, + 0x18f68b54, 0xe0b41294, 0xefdbe81d, 0x1b905cab, + 0x71d21bf8, 0xdb2f276e, 0x79f5787d, 0xe509ee76, + 0xfd38142e, 0x79e9f52d, 0x7bcab8e2, 0x1ec78269, + 0xe90a374d, 0x249b1223, 0x2874281a, 0xa1bcfa6d, + 0x8505f39c, 0x871492a1, 0x68643ecc, 0xfdee5a1d, + 0xf71c0e59, 0x1c4c7b03, 0xbc223c3c, 0x69902c28, + 0x58078012, 0xd3d0d1cc, 0x8ad5e993, 0x260e3944, + 0x91b707ba, 0xb8e6db01, 0xf207be39, 0x61e2ac75, + 0xddabab4f, 0x048e9bb4, 0x409eb891, 0x9b2860b8, + 0x9983c366, 0x3bf51556, 0x02cf74d7, 0xdb9da7f7, + 0x90c59550, 0x3ec14eba, 0xb3da42ae, 0xa1678ee3, + 0xf5b3171a, 0xc4891311, 0x3956f0f1, 0x1c1e6198, + 0xe10489ad, 0xe4af795a, 0x6ce359bc, 0x92db2c47, + 0xb29d0bbe, 0xdcfc073f, 0xef8e0c56, 0x016e5c10, + 0x55d28640, 0x23a73397, 0x63463e4f, 0xd05e7e5e, + 0x33317dd6, 0xdfd4ee25, 0x8abb1147, 0x07920ad9, + 0xe9ce1eb1, 0x4c563761, 0xb25af483, 0x833fc686, + 0xfa26f8d8, 0xfc6d9706, 0xce287235, 0x1a4dedb3, + 0x9e7e2244, 0xbc6d76ad, 0x454244dd, 0x1fa6f791, + 0xd68d5d44, 0xd575c107, 0xa29f363f, 0xa4d82a2e, + 0x54807dd8, 0x834288a7, 0x1bb3c0cf, 0xdf14c691, + 0xf948a1dc, 0xe8f36e29, 0x995b9ddc, 0x285cfe79, + 0xae873e12, 0x24512b6b, 0x2b5a7536, 0x12ed1f02, + 0xfa33f1fe, 0xf8ae1287, 0x2d198673, 0x305f4bc0, + 0x04e81749, 0x2ee39d5a, 0x9fb3ad43, 0xffa79dd9, + 0x6e7552dc, 0xafd3b9a9, 0xe77a27e4, 0x3389861c, + 0x88875f99, 0x6c3fb970, 0x1dd33d87, 0xad2da30b, + 0xed61353d, 0x159b0258, 0x289afc18, 0x4d2f5a8b, + 0x3e60b265, 0x289016c6, 0xc5e5126d, 0x70ecface, + 0x1e8ca90a, 0x981b7bb2, 0xbe6cb8d4, 0x950b2832, + 0x3ce849fa, 0x8605fece, 0x6f725305, 0x34749033, + 0x45e47071, 0xf03b3fc3, 0xb01376f7, 0xf0fc9650, + 0xe1479c89, 0x7f1e7f3f, 0xb444276a, 0x3daa38d6, + 0x83b58e2c, 0x0b01c0f9, 0x057e6fee, 0xadae5a22, + 0x2662781e, 0xf00dd6aa, 0x90a8af3b, 0xeaa7d3b4, + 0x307a1bed, 0xa078467a, 0x2b6ec7e8, 0x5afecab1, + 0x79dd1397, 0xfd7894e9, 0x936c2bf3, 0xb4cb94c8, + 0xfbf88987, 0x5bc4a881, 0xf96c5691, 0x0775ac8b, + 0x8d29216c, 0x4205bb21, 0x87227749, 0x77b45968, + 0x2bc64816, 0xa8bd9961, 0x3406cf85, 0xf8bdd876, + 0x95d22fbf, 0xfd3ffa19, 0x11370663, 0xfc444051, + 0xf8ea818a, 0xd8316c19, 0xca863792, 0xf7da216c, + 0x46949cca, 0xafb6749f, 0xa6ccd651, 0x3ba7ec03, + 0x20be1947, 0x293b9573, 0x230c5ce6, 0x2190e64c, + 0x24fb7c77, 0x5455e549, 0xf24ef784, 0xfd6ee2e3, + 0x5135d6f7, 0x5a75c2ef, 0xf93a5e4e, 0xd7c27523, + 0x047d2c00, 0x925b92ce, 0x8b8dbd5a, 0xd1a8851f, + 0x3c36e267, 0x77e1d04a, 0x04ffbc6a, 0xe4372737, + 0x25437178, 0xc219c406, 0x3b704354, 0x06529726, + 0xc4d31af6, 0x8670d91d, 0xd6aea080, 0xef0816f0, + 0x47a5f6e1, 0x96a9f010, 0x3718b52d, 0xf2b95c2f, + 0xfcb10d89, 0x9930f255, 0x3725e7e4, 0x8031eeec, + 0x7b1d3530, 0xc19bc696, 0x57e18b66, 0x9ca51015, + 0x0359392b, 0x65bba057, 0xb3ae19d4, 0xfc80f9e3, + 0x4216f017, 0x857c2552, 0x595afd26, 0x15a911e1, + 0x4804e926, 0xdbce02f6, 0x96a66f55, 0x2d925a8d, + 0x1c9ea6f7, 0xbd78e3ad, 0xcf074656, 0x32eb5a1c, + 0x82c06e4b, 0xc9febae6, 0x28879bc5, 0xad5f3420, + 0xe5628497, 0x27153186, 0xff595698, 0x8c1fad00, + 0x3ffb627b, 0x9b080b87, 0xb1137fe3, 0x02bed087, + 0x286780a2, 0xb8757a4a, 0xf801f348, 0xc48f3e72, + 0x67418bd9, 0x7f612a53, 0xd7db1928, 0x800b0269, + 0x8c0d57ff, 0xfcb68d2d, 0x7208ef04, 0x81bbc9f5, + 0x855eeb1c, 0x45a57ee1, 0x6c40c1e0, 0x735a0b5b, + 0xf4b38a8c, 0x2ac2c2f5, 0x0d14f9e1, 0xf02044f3, + 0xbdb55030, 0x3d71fbff, 0x42dd1271, 0x3d311abb, + 0x933ce178, 0x74a04d2c, 0x9a898c1b, 0x104325e3, + 0x78615383, 0x7ce7f4e2, 0x64a054f6, 0xadceac90, + 0x4ed286c5, 0x1af06c1a, 0x612f00e1, 0x868c8ed0, + 0xa9daeea3, 0x6b98dcdf, 0xd8800984, 0xca1e88fd, + 0x08e749f4, 0xc0496222, 0xffe27b59, 0xc499d775, + 0x7ffc317f, 0xbeb3ecbf, 0xb6e9e56b, 0x77f0591b, + 0xaa7faa6c, 0x59fa9f88, 0xf34c1c66, 0x3669b364, + 0xa86e75ac, 0x1bdfe98e, 0xb91c7dca, 0x0c44ded5, + 0xfcde4390, 0x741fc3ed, 0x69a37953, 0x3abc03e1, + 0x2d23ce32, 0x7f12cb5d, 0x10869fae, 0xe08df47d, + 0xb80c67eb, 0x841be480, 0x5c401872, 0xe7678c67, + 0x82f70eb7, 0xa56aa21b, 0x176f381a, 0x04de078a, + 0x5c43a8b5, 0xe46ed7ca, 0xf7bb9d1d, 0xe5f31be9, + 0xfe0ebfce, 0x711c928f, 0x36a2bee9, 0xcdb69225, + 0x6a7ffcea, 0xf6e763e5, 0xf1e1a209, 0x3aeebd5b, + 0xaba20b8a, 0x5810a1ee, 0x6b545432, 0x5e2c21b8, + 0x09585b25, 0xe3a11ced, 0x27846cf8, 0x76b22712, + 0x2ec5e6d0, 0x18541334, 0x9bab9995, 0xc59b3a57, + 0x207b1eb3, 0x29ae92fd, 0x87427c88, 0xc42654d9, + 0x66072a41, 0x9738fa39, 0xbea0c2a2, 0xa93f9df5, + 0xda2eb8f5, 0x3d51fffe, 0x78529632, 0x79cdb8ab, + 0x2c704cf3, 0x94a263cc, 0xf621dcab, 0xd5e01733, + 0xb0e58c76, 0xb909aae9, 0x49aba69b, 0x3b4b50b9, + 0x6fc63bf3, 0xf3c1e17c, 0xe7664b06, 0xa50f40e3, + 0x2b95da6e, 0x56ce065b, 0x9158df9e, 0xa86ebedb, + 0x2a7edb43, 0x34c0645e, 0x524fa131, 0xab634ea2, + 0x3c7128ae, 0x87051714, 0xb35f48f4, 0xa72d93e0, + 0x65194924, 0x5c13657f, 0xcfc4d7bf, 0xef3f233b, + 0xcc4c39c9, 0x751c7b6a, 0x4df76062, 0x2737a37b, + 0x3dce16c9, 0x752b321c, 0x2ea9c22f, 0x670f44a8, + 0x1ce3e4d6, 0x86f1e24a, 0xf68716e8, 0x03be1150, + 0xe50c11e8, 0xdb88bd7e, 0x5d4d1806, 0xfd680781, + 0xe6c89686, 0xdf2b301c, 0x8a547767, 0xe648917d, + 0x1b02d1fb, 0x4cbec1a5, 0xad134e62, 0x3c5458e2, + 0x80f1dbf6, 0x2d81d799, 0x3792881f, 0xeedf5aeb, + 0x5ddf4505, 0x5ceaa231, 0x467cef8f, 0xf5885e21, + 0x4ad7a22e, 0x82e064bf, 0xea77c2d4, 0x87cfc25a, + 0x25abdf7c, 0x553ec8f0, 0x64a9c184, 0x8e25684b, + 0xd1f9d1ef, 0xabb52b96, 0x03ab9d5b, 0x7f89d083, + 0x50c4c292, 0x47e78a96, 0x456cc58c, 0xa0cf8aad, + 0x545c8e36, 0x4586eefd, 0x298a750b, 0xef697975, + 0x4dce0624, 0x119048cc, 0x84a5677b, 0x74f53d72, + 0xa8ccf01a, 0x7375f0fc, 0xfe039200, 0x04b81b66, + 0xcee20aa1, 0x398d32fa, 0xbf1611a8, 0x20f6ec20, + 0xad535511, 0x77b38173, 0xb2eb6de4, 0x09723ab0, + 0x201167f3, 0x4d8ed77d, 0xb19207ac, 0x2433a83f, + 0x235d1a50, 0x136725d3, 0x91d2759f, 0xba128133, + 0xa0234f53, 0x07be8967, 0xb88f5bf5, 0xc2985341, + 0x7577ca64, 0x341f86d3, 0x7b5dce75, 0x9aa93835, + 0x560ec5e0, 0x3d5d1a1e, 0x5bd41f29, 0x537c083c, + 0x58efe68f, 0x9ba12bcf, 0x12333b34, 0xc40f1b00, + 0xf5056370, 0x2aeda8c3, 0x4adb9c53, 0xfaa69efa, + 0xa19557ca, 0x2bc25873, 0x740d4413, 0xfdc96ec5, + 0x8c85d634, 0x58f03d23, 0xad45f948, 0x322bbf4c, + 0x21b4552d, 0xd944f686, 0xe01a9db9, 0x8812e76c, + 0x6bae3dd9, 0x692133bf, 0x987579e2, 0x96cf7ffe, + 0xf3f0112d, 0xd7cfef00, 0x6e35e31f, 0xf61b96b5, + 0x1645d2ea, 0x9a6d54e0, 0xbefd1245, 0xdae87f14, + 0x56eb83de, 0xec5e7d1f, 0x9c023853, 0x771fe4ab, + 0xece4538e, 0xacda1d06, 0x9fbaa127, 0xf717f714, + 0x4e1a3df1, 0x4b1f58d4, 0x1c7c69ae, 0xf7aa8cc1, + 0x48c5795d, 0x2b4a7839, 0x2f549eb3, 0xb17deeae, + 0xb70c9639, 0xce18be08, 0x29cc7d87, 0x7dbebd98, + 0x3708b02b, 0x580c175d, 0x61fe14c2, 0xedef9ebe, + 0x6ab07642, 0x61e59251, 0xc2c6cd63, 0x5b44a72d, + 0xa1d934dc, 0x4bba8f16, 0xd6bed796, 0x9ed4635c, + 0x4bc7f0e3, 0xc9e84a74, 0x36cb3224, 0x71349c43, + 0xfc216dc7, 0xa1f0e269, 0x921813c2, 0x6dfd38a4, + 0xa160d1f9, 0xd0013ba2, 0xb01cb55e, 0x7fb06ae2, + 0x6d060a20, 0xf321e0f3, 0x7b2bd14f, 0x57ff444f, + 0x71561500, 0xf1d50771, 0xa30f2a0e, 0xf91ae7e5, + 0xe46b561f, 0xd123ea4f, 0x0485bdbe, 0x26427e50, + 0x0398399d, 0xb68cff28, 0x93ae74c6, 0x99bd6359, + 0xd1a116f1, 0x87d464ad, 0xfb62112a, 0xddf2b528, + 0x244cdc6e, 0x946bad29, 0xd24db484, 0xe0db5b0a, + 0x23f15645, 0x581dde3f, 0x5ead934b, 0x0a4e768b, + 0xca4b7134, 0x54eea26d, 0x3ac2fc6d, 0x1cfdacdc, + 0x2b72db1d, 0xaf346626, 0x2cf087f9, 0x49f70c8b, + 0x6115cc03, 0x190a6658, 0x9c5d23e0, 0xe49f8106, + 0x8e7df080, 0x9d7c42a6, 0x5fd7212b, 0x5e4a732f, + 0x38968ae9, 0xef65bea1, 0xd71ed34f, 0x7dd287df, + 0x25fae5cb, 0xbf98a2e5, 0xbe196a29, 0xe7ff1c36, + 0xce06477f, 0x5bc5defe, 0x281cedf4, 0xad3f6523, + 0x74dba05f, 0xbc665231, 0xd467cd4f, 0x91f8962f, + 0x33af9d7d, 0x04489e82, 0x8ae649a0, 0x9600f2c0, + 0xb92341aa, 0x7f4cada0, 0xf9bb8dce, 0xb8e2ab84, + 0x6a204931, 0xcd847483, 0xc1955877, 0xd680c1f7, + 0xb331bc5e, 0x8f8b4b88, 0xdd339331, 0xfd745177, + 0x8f05796e, 0xf3744f1e, 0x15936e1a, 0xb63269af, + 0xaa5c9429, 0xd140fea5, 0xfeca6e63, 0x5b3d3df5, + 0x188cd709, 0x1b31fbf7, 0x6fa460f3, 0xfe5a8d6a, + 0x7d7357f9, 0xe024a932, 0xafce671e, 0x5c4a1ab3, + 0xf28526ed, 0xccb7f64f, 0x4affef38, 0xa71bb42d, + 0xb570f6df, 0x1cf39e4a, 0xa36edc29, 0x7863d050, + 0x7cd4cacb, 0x98edea74, 0xdbba6a1c, 0xb4b368b6, + 0x2417280b, 0x88713157, 0x2431dad4, 0xd7bfcd43, + 0x226a5a63, 0xc41861aa, 0x31ab4635, 0x90ecc7b3, + 0x6e32d2f8, 0x62b31865, 0x3a0a4560, 0x1b5873e1, + 0x825983f7, 0x66d48f0f, 0xccccaa51, 0x06521343, + 0xf2f0820e, 0xdb97a2fe, 0x9876f69b, 0x53a2c1c5, + 0x22055f01, 0x554e5b14, 0x9707975c, 0x9f67825c, + 0xa7641a4d, 0x31f66056, 0xc4b60c05, 0xf5975ead, + 0xd37c4c98, 0x1b4ee33a, 0x24d0e94e, 0x25526b51, + 0x58dd0968, 0xb7ce30e1, 0x1904f14a, 0xdb5d5738, + 0x68a1e735, 0xc107dfe4, 0x6dcfb718, 0x85d0ed4f, + 0xb9f7e5f2, 0x82d238c8, 0x29352162, 0xa77a3522, + 0xa079166d, 0xa3bb9275, 0x2903169d, 0x61c980f4, + 0xddc91413, 0xf010ba6a, 0x31c0b54e, 0xb8c96662, + 0x095c0d76, 0xd8cec25d, 0xdeaa554a, 0xa4de2784, + 0x0dd03033, 0x971ef5f5, 0x1c45995e, 0x9b363baf, + 0xafdfa811, 0xc7ff05eb, 0xd2d7dbd9, 0x4bc1b145, + 0xd2397d2d, 0xa279d171, 0x4e956b1f, 0xb2f7673f, + 0x8e8ea35e, 0x7642504c, 0xb739ad78, 0x0a88c121, + 0x4d8c27b5, 0x8a7ece52, 0x93fd2121, 0x8d923062, + 0x26c234d2, 0xf140034c, 0x717c472c, 0x2e26ed56, + 0x7adb8be0, 0x710b5063, 0x2ccaa6e1, 0xd617eff3, + 0x8e48c710, 0x75091c92, 0xdf38967e, 0x9fcee5c3, + 0x7c7c85a3, 0x8459301f, 0x2ab73b95, 0x10a220c8, + 0x954da298, 0x0d3d765c, 0xc1cf5234, 0x83a209d2, + 0x62fd8a04, 0x866d5c9a, 0xeebf64cd, 0xc16ad5cc, + 0x0c318444, 0x2e853253, 0xb018e4bf, 0x23d70987, + 0x6d577c67, 0x48baeb3d, 0x5d12bd44, 0x452679b5, + 0xede886e4, 0x60d75e53, 0xfaeacd65, 0x956c3293, + 0xc2c3e0f4, 0x6a614952, 0x85bfc57b, 0x2adc641f, + 0x27bafb9f, 0x85453c9d, 0x8a0bf885, 0x54813714, + 0x8c2da9ce, 0x9862e196, 0x53608eb9, 0x50cb1cce, + 0x2e5fde04, 0x6001c4e3, 0xe7afb6e5, 0x35a1d538, + 0xe5965475, 0x71550518, 0x25624264, 0x24b85892, + 0x1f46861a, 0x5902ff04, 0xba886bdf, 0xaf6b111f, + 0xe702147b, 0xb868b219, 0x5450e53d, 0x26400643, + 0xc7cc3b00, 0xfe4a7f61, 0xcd0cec5d, 0x55fa74e5, + 0xab4aece6, 0x594801f7, 0xa4c700b0, 0x263eafd2, + 0xca5157c2, 0x87cbed00, 0x3fa19c0d, 0x30d1583b, + 0x774a1bc2, 0x7ab8728b, 0x51b9da00, 0x11e7b913, + 0xb621d527, 0x20e15cb5, 0x468ada88, 0x22cf6e59, + 0x272f671f, 0xb7c6e619, 0x0cde1a07, 0x4b1040a6, + 0x06ce0c54, 0x445887ea, 0x3497265f, 0xc57b1d5b, + 0xcc28db4e, 0x142326cd, 0x269ec4c0, 0xda176039, + 0x29387952, 0x00819916, 0x44bf30ce, 0x16682b6c, + 0xcefb02de, 0x0a8f1c1c, 0xf329ccc6, 0xb7254388, + 0xc0adbd5a, 0xa73db62d, 0xcf007f8f, 0x2193c371, + 0x878bf5a4, 0x40133190, 0xed4e6469, 0xfd548f7a, + 0x6de3ee2f, 0x7482390c, 0x7686cda4, 0xf0968c8a, + 0xbd884ca3, 0xbe9f759a, 0x5e847e97, 0xb5751c67, + 0x80164301, 0xaed7f727, 0xd64b6214, 0x54d4056c, + 0x209bacdb, 0xf7a1dd4d, 0x373425b4, 0x220f5e83, + 0x94619726, 0x9199b9ff, 0x7ca4009e, 0x3a9f4df3, + 0x043091df, 0x598f1b88, 0x8e541a7b, 0x9993f3cc, + 0xa7a32036, 0xc92d145f, 0x1c7710b7, 0xe844402b, + 0x4db7621e, 0x5ad0026d, 0xbf78fc6b, 0xd864c7bf, + 0x5511cf7f, 0xd1cf34ed, 0x3fd39550, 0xe9a1d9d0, + 0xa5357ffa, 0x6cbb33bf, 0x9dc1eb2e, 0x6f187cb8, + 0x5004e814, 0xedc31d16, 0xee64e9d2, 0x950a8aa5, + 0x97262d0a, 0xc9e6db62, 0xad18ffbc, 0xc817ee0e, + 0xc7e10ceb, 0xd41b86e4, 0x561ef40b, 0x9883c061, + 0x25805f56, 0xa2627be3, 0xeff8c394, 0xb62fa8c0, + 0x3d1f2f44, 0xcf84fce7, 0xb43e9a4e, 0x66ad46ac, + 0x3fa2f210, 0x838fe161, 0x8e56451a, 0x06a906c2, + 0xe8840faf, 0x5ac47e9b, 0x6a71b661, 0x2ec8cd2e, + 0xe6e0e8f8, 0x9707b6ef, 0x99cc54fc, 0x81e846c5, + 0x814eeb22, 0x8ada0add, 0x7d19266a, 0x69f7a703, + 0x9aac18aa, 0x5b9cfc8c, 0xf919dfb4, 0xa94e43f1, + 0xbb74a48a, 0x6cf705a7, 0x8f3e6307, 0x9794e695, + 0x1651e6c8, 0xe89b31fa, 0x43f7ba10, 0x2a514f1c, + 0x1e7bfed9, 0xa93bce47, 0x3a6e4532, 0x9e374769, + 0x9c536590, 0x90b0b81e, 0xefbfdfe5, 0x69ca533c, + 0x4ecbf634, 0x1b8c8263, 0x0374ec8f, 0xf702dbc7, + 0xd045ec79, 0x192b0095, 0x5829de23, 0x881e4918, + 0xbbdf15fd, 0x3f32a538, 0x288366e6, 0xcfb220b9, + 0x3ab3180f, 0xa4bf51fd, 0xf4e01603, 0x713d18fc, + 0xb909f63c, 0xdae85bc1, 0xd9b969ab, 0x0b2538f6, + 0x2dd34ba7, 0xddd6e0ae, 0xc96bba5e, 0x7c9f4215, + 0xf1f09f73, 0x6e7fc99f, 0x81f44af7, 0x13f118c5, + 0xfa44cf12, 0x8b5e93c4, 0x6f707ee9, 0x4c81e0b4, + 0x60969387, 0x8081f7e7, 0x05f90a32, 0x327f334a, + 0xb0bc3d5d, 0x347b402d, 0xe7b67c17, 0x94ab5369, + 0x47ceb456, 0xf22facf0, 0x4234359b, 0x54953e7a, + 0xd2bb1870, 0xe223c3ba, 0x7b0ff382, 0x61963879, + 0x5eb4e268, 0xd4bce3f8, 0x573a4335, 0x9c9979eb, + 0xa2a9b2ee, 0xe86c6e4a, 0xefb9fbb5, 0x2b5759f0, + 0x04c2b2b2, 0x4192fc64, 0x3ffbecb1, 0xf7308321, + 0x2a8c4ffe, 0xc5f17893, 0xe83dddef, 0xc19b9577, + 0x0bd28f37, 0x2135b42a, 0x7ecbc7ed, 0x972340c1, + 0x0c576383, 0x17433c6a, 0x42ed452f, 0xb884852c, + 0x1b584cd7, 0x165b59c0, 0xedae4aa0, 0xe4398ea1, + 0xc40cdd64, 0x709d9c48, 0x24898031, 0x8b9bff2b, + 0x6c024eaa, 0xe6fe9c19, 0xfcb23fc7, 0x6c0b4208, + 0x3e111e68, 0xfa8f70bd, 0xd9ffdacc, 0x3a2ef4b7, + 0xdf2037cd, 0x75d43850, 0x9e879700, 0xae1316e8, + 0x9c7ffb47, 0xeaa9d230, 0xf9480bc0, 0xc69ca1c3, + 0x9abf7e78, 0x8a4c9c38, 0xd8b4dd75, 0x83131c68, + 0xcd2ffebb, 0xfde3d386, 0x51d9950c, 0x5a35007b, + 0x73d4edc7, 0x7a3947ab, 0xc07ecb2a, 0xf9f7a977, + 0x731a8c62, 0xc2ee4ddd, 0xa41b5e38, 0x18c3967b, + 0xbeef769b, 0x27f78249, 0x44cd1694, 0x12624897, + 0xfd2ed164, 0x60de1fa7, 0xcc7063c0, 0x1e5ffb83, + 0x1cfac0d0, 0x386b1121, 0x22adc69d, 0xd406eb21, + 0xde5959e3, 0xf053ad2b, 0x7798db5b, 0xf99cfa5d, + 0x7b5391d0, 0xc982d53a, 0xc63e25bc, 0xa607c935, + 0x554a53ba, 0x55dd374b, 0x610b228e, 0x975af7ba, + 0x58abf083, 0x1bbb059d, 0xa210322e, 0xc9ac4c66, + 0xd54aeb4d, 0x79ea4b22, 0x28fc7933, 0x578c8d15, + 0x6510f9d5, 0x218213d6, 0xfb9d7a05, 0x49beb8dd, + 0xf8a08a0a, 0x880fe164, 0xc41f266c, 0x830ff8a5, + 0xb29e2611, 0x302f3065, 0x6ba9affc, 0xc0467ed2, + 0xef11ac86, 0xc11edf26, 0xb7b23c2f, 0x608ca952, + 0x032e2b74, 0x4dd90e3b, 0x181638df, 0x116a7204, + 0xc43e188a, 0x882f6729, 0xf72658ab, 0xcb1a34d3, + 0xab040797, 0xbf073fd3, 0x869f28ec, 0xbb56384c, + 0x5c3586e3, 0x3adcb5bf, 0xfe52aa43, 0xb1c90e8a, + 0x3da63282, 0x96de578b, 0x5a87e849, 0x407f540a, + 0x489b4576, 0xc867c3bf, 0xec270d1b, 0x2681cd54, + 0x0b58c35e, 0x31bda6f8, 0xa8a53574, 0xd72c5c17, + 0xce4ae157, 0xd37a8963, 0xd19f1f67, 0x4adae3b6, + 0xefed933c, 0x6109b0ff, 0x0678fec6, 0x8c4d0710, + 0xcf427bf2, 0x99929120, 0x3b4be2ac, 0x6156ce40, + 0xd82c7c0a, 0x45031039, 0x87aaf12c, 0x7fe780e2, + 0x5bd1641a, 0x4a652116, 0xcbb0282c, 0x4cc6422d, + 0x455b1ffb, 0x269b9ed0, 0x40154c8e, 0x858b5d90, + 0x288b74a0, 0x93db3461, 0x0e8fcba0, 0xb5e229eb, + 0x78f0b895, 0xf912c2b2, 0x1909c95a, 0x1977e7b5, + 0x6790e9d4, 0x346aa36f, 0x8f746b89, 0x871e3209, + 0x8d39520e, 0x3e1bd336, 0xdb9e1551, 0xf2397c8f, + 0x3aadcec4, 0x78e3e450, 0xf3a3282f, 0x5d5f0097, + 0xa4b0b527, 0x5ae0e620, 0x75d11fa7, 0xc26d3ca8, + 0x1c346346, 0xae9995f5, 0xff82ac22, 0x88adb589, + 0xf7cd6606, 0xa9f700bb, 0xbbbda493, 0x5ce3a134, + 0x0b5bcdd2, 0xd08ebdbc, 0xb8f3aed9, 0x0bb5bbc6, + 0xbd1b3cc8, 0xc0157f5c, 0xc3c1a169, 0x74f37092, + 0xa47ceeb4, 0x8adb10ca, 0x728dd1c0, 0x7ae3da24, + 0x4db77331, 0xc9672bd1, 0xe1dff5d2, 0x02dc7586, + 0xd84b722e, 0x8a9a9785, 0x0573f800, 0x70ec48bd, + 0x9b9e0dfb, 0x0023ddd0, 0x2865b11d, 0x4d94744f, + 0x1511a892, 0xb8870149, 0xfae7b22e, 0xaf62fb18, + 0x5bc02cdc, 0x3c141e07, 0x7b20f75c, 0xd23a008c, + 0x3e44f105, 0xd70075a8, 0xf41a37d0, 0x173548c4, + 0x650aebc1, 0x03a2fe59, 0x46d34565, 0x67844700, + 0xb93672e4, 0x0b17aebd, 0x7e3b080c, 0x5d3a4468, + 0x1bba2fcc, 0x33976b5c, 0xe53839a1, 0x58aff6ee, + 0xbf254846, 0xd5a134fe, 0x534e36be, 0x90207d1a, + 0xefdef4f2, 0x81237fb9, 0x26a0388b, 0x6be9f6f1, + 0x79b05ddf, 0xd28d8216, 0xc44632d5, 0x6d947d94, + 0x9182a6b8, 0x9c1700f6, 0x5d4cd8e3, 0xb98b66bd, + 0x43c5d447, 0x468ec70e, 0x2f733f48, 0xa15cbf77, + 0x7a1229bf, 0x25bac348, 0x1666e4d5, 0x112656ab, + 0xa70a776b, 0x9442fd97, 0x99369f89, 0xdd584396, + 0x584b3ead, 0xef970e3f, 0xc8f094c5, 0x2338430b, + 0xf9741b19, 0x46cbf552, 0x7e44da18, 0x997fac2f, + 0xc9728915, 0x166271b2, 0x25944ecd, 0xafd32f0b, + 0x5a2aa891, 0xd173fc4f, 0xeeeb9841, 0x6355237c, + 0xdec80496, 0x0b17fad9, 0x8a98cf2f, 0xb9e0b54d, + 0xadd4629c, 0x190a9dbe, 0xbff95d93, 0xc395409f, + 0xe32d0202, 0xe11ccbfa, 0xa9b9d56d, 0x19df6eed, + 0x553e522d, 0xa5150e7c, 0x7cdd2477, 0xd5e50f71, + 0x867dceb4, 0x5ad6001f, 0xf88f5e73, 0x1548cc85, + 0xee19bb69, 0x723b54db, 0x7182737a, 0x2637ef3d, + 0x0d07b151, 0xaab82782, 0x1a67f480, 0x427cbfd0, + 0x76bafa88, 0x2201b5ea, 0xcd476d93, 0x6621fe11, + 0xe71632e2, 0xf2babb88, 0x4751dfe0, 0x65ae2697, + 0x715e35c9, 0xb4c68b5c, 0x4ea5d76d, 0x7964e9f5, + 0x5d41f041, 0x9545f953, 0x3aeabf4a, 0x1e686a87, + 0x4466e931, 0x1b085197, 0x3fd99ec6, 0x16d9ee38, + 0x3b443801, 0x0c62be56, 0xde6a506e, 0x70248e0c, + 0xd43fc5fa, 0xffcbbf1f, 0x0597777d, 0xc4d757e0, + 0x2c3863a3, 0x406c484e, 0x5c93ccd2, 0xa1915b85, + 0x5cef9263, 0xae54c85c, 0x80ab4b36, 0x5601ae18, + 0x9d4b3896, 0x4bf6daab, 0xc9a1d31b, 0x3cdd788a, + 0xd68a1f8e, 0x963eca4f, 0xcfacc55f, 0x5bf01c2a, + 0xb8095201, 0x1b243c11, 0xe0be3993, 0x92dc9ee2, + 0xdcb7a9fc, 0x1e297a5f, 0xb955d798, 0x7720ec7e, + 0xbed66060, 0x406bcd05, 0xf07df4c8, 0x0f15fb66, + 0x4cc4bc87, 0xf7fa2ff4, 0xf9df4483, 0x96ed18a1, + 0x17684906, 0x50437e25, 0x2732ad5a, 0x090dc7ec, + 0xd35e9357, 0xcd80ee47, 0xb2246342, 0x7c7cf4e3, + 0xa6113203, 0xda27c828, 0xb5c6052c, 0xc88236b2, + 0xb9717be3, 0x1dce1918, 0xc61d96ee, 0xdad16f5b, + 0xa4edaa73, 0x09b62bbb, 0x6ad57010, 0xd5439798, + 0x928d2ff7, 0xa77cbccd, 0xd1a74104, 0xd391b849, + 0x582f4930, 0x987718f0, 0x9ce39f53, 0x30b123a3, + 0x25fd3e8f, 0x53020467, 0x1b64a6ac, 0xe3348470, + 0x1f78ea67, 0xc0f8d448, 0x5f27532a, 0x0fadce33, + 0xcdbc62a7, 0x6c0d76ec, 0x9d7bb6e7, 0xd0540d19, + 0x8d7ca1ed, 0x215a87b3, 0x5d5781c4, 0x692bd8c3, + 0xf3378f13, 0xcd30e3af, 0x69404c11, 0x6eca1552, + 0x0c259cd2, 0xb3ee39a7, 0xe8891fd1, 0xa175a5e8, + 0xd9df300d, 0xd08f5352, 0x603ed07c, 0x99f600e3, + 0xc930a060, 0x799719e0, 0x088f4e20, 0x7c1ddd7d, + 0xf4b3a502, 0xd3c55950, 0x84a79d2c, 0xafc5c205, + 0xa3b054ff, 0x1b95436a, 0x35d7e834, 0x7dba2f8a, + 0x4fcd13d0, 0x73a066b5, 0x3e953765, 0x502968f0, + 0x48685f18, 0x40d75838, 0x146de6fa, 0xf740666e, + 0xcf192aa7, 0x12d75036, 0x54a1bd85, 0xf0b5ba44, + 0x566525c3, 0x0b09fa0b, 0x1b13cb17, 0xffa7ac52, + 0x6d3cb7fe, 0x664e7783, 0xce2c070c, 0x5a4620b0, + 0x2885b271, 0x7b65bf03, 0x9b0d39d4, 0x3a7014e5, + 0x08b92c70, 0xed569496, 0xb4c52a10, 0x7112b539, + 0x17aa1a9f, 0xcb6e1e6b, 0x516eae6d, 0x4ef0f35c, + 0x3c8c0d44, 0xbb9bd760, 0xe643da0e, 0xc9cface0, + 0xf1011dfb, 0xb281e276, 0xa87f200e, 0x15e1d187, + 0x823cb7da, 0x252b6fac, 0x0bfcf155, 0x008f7fea, + 0xad82caf7, 0x1e5c40ad, 0xbf3b9a11, 0x4246331a, + 0x803154e5, 0x0ffd9e62, 0x3e5d4acc, 0xd9ce46c7, + 0x3e5a621a, 0x462d1772, 0x5d7cb636, 0x3bf8d751, + 0xc0f09ff1, 0xd5d47ebe, 0x19d80c9c, 0x679f69ed, + 0x72e6e407, 0x200029e1, 0x2c64f391, 0x643cda60, + 0x5a5bfb05, 0xa904a860, 0xcdfb83a8, 0xa85208ac, + 0x9f681117, 0xe5e4e0f4, 0x6905d4b1, 0x9fe6a725, + 0xdbb8207a, 0xe2e0f1fd, 0xa8244e4d, 0x7cea2179, + 0x9570026c, 0x93412c43, 0xd907c02a, 0xaaf792bb, + 0x0e0936f9, 0xacebd3d4, 0x013c7b7b, 0x2b2bf6b0, + 0x50cab382, 0x8ca022be, 0x7b6abbb5, 0x3de76e3b, + 0xa5c5c4a0, 0x19cff42c, 0x5cdc0cf9, 0x063ed260, + 0x6f5f9d21, 0x450617d5, 0x52ef21a3, 0x5b77bb8c, + 0x2ca46d8f, 0x79006971, 0x00329d75, 0xa8d79c3a, + 0x63603db1, 0x6c655820, 0x52402d3a, 0x78db9e76, + 0x5bcc235c, 0xda5a72ed, 0xaa3b4490, 0x7578b248, + 0xb8c0a56f, 0xc235b082, 0x22a49a70, 0x857540c7, + 0xdf31602d, 0x85fb2110, 0x15dcadbf, 0x02983291, + 0x344be753, 0x5304430e, 0xd19cfa2e, 0x851cdcd2, + 0x3fa09c0c, 0xc26b2584, 0xaf620389, 0xce6775df, + 0x347a74f5, 0xe433e672, 0xf14892f1, 0x4cc98dc4, + 0xe280f3fc, 0x8feaee9d, 0x20dbacc0, 0x441250e2, + 0x1b6097c8, 0xa2f2f494, 0x19f7234a, 0x24940434, + 0x5465b1a8, 0xc5662a79, 0x4f31d1f4, 0x249ea959, + 0x881b0f31, 0xb5762ca9, 0xc3af5796, 0x80608359, + 0x8981a871, 0xfbe2cd9e, 0x7a1da627, 0xa4dfeb2c, + 0x07f5da7e, 0x4a621101, 0x86d5fc65, 0x8b01d35c, + 0x6ee3ec81, 0xd7c70c56, 0x13549171, 0x0dbb64be, + 0x2fdadb74, 0xc1e1c1ef, 0x540a102e, 0xef635b56, + 0xd28fb2e6, 0xe4ce6815, 0x8bc07adb, 0xd22226e7, + 0xea5452e8, 0x0d636a22, 0x3f36e416, 0x65924428, + 0xc689edc1, 0xec96af4e, 0x14d8bc2d, 0x0e77541b, + 0x89c9722d, 0x10b56804, 0xb2d38782, 0x79ea1ea6, + 0x2e861537, 0xfa167b5c, 0x364049a2, 0x59219c57, + 0x69f573fe, 0xc6c2d492, 0x09f4230a, 0x24d926eb, + 0xe4a045fa, 0x282fd868, 0x06d0d112, 0xa32ef962, + 0x6d8ddf0d, 0x64e4bb75, 0xe2daf8b5, 0xfad8c656, + 0x5b6213b6, 0x564867de, 0x7f396777, 0xba003008, + 0xdcbce73b, 0x0276742c, 0xd1798208, 0xa73a9b0b, + 0x3a3453d6, 0xbf0ab4b7, 0xb8f386d2, 0xb482f58e, + 0x010c34a2, 0x5ab9ae11, 0x084342a1, 0x4de229d9, + 0x7eb0019d, 0x6f9c48d1, 0x9b7c7254, 0xe72fe7f4, + 0x61d3c6d0, 0x5f325f9d, 0x2c0dd201, 0x4e88ae87, + 0xead0a615, 0x77377e76, 0xdec9367d, 0x7176424d, + 0x8948bab3, 0xaecd7619, 0xa542cfad, 0xe114c986, + 0x45a89d9b, 0xd65caf42, 0x959cc728, 0x8c46bc72, + 0xee82cb66, 0xb74b127f, 0x888043ee, 0x45f215dc, + 0x31757661, 0x954cc945, 0xa8d8fc3e, 0x89d7cc0e, + 0x05fb1850, 0xbf55a4e0, 0x9d07b5d2, 0x8ed19aa7, + 0xbd213124, 0x871dcadd, 0x88f3583c, 0xc533e4e8, + 0xa193e265, 0x9184dfc8, 0x076fb6b8, 0x0c988f7f, + 0x09aa99c2, 0x0202e9b4, 0x6089972e, 0x04683e2b, + 0xeb162f9c, 0x4575cfe4, 0xe14e5bb6, 0x5536cc7f, + 0x3e325a0c, 0xdf6ea889, 0xbe12bf6a, 0x8c270854, + 0x823faf43, 0x1e190166, 0x4bf5f2ba, 0x1a0eec2e, + 0xacf0b04b, 0x36b28a5f, 0xfa152239, 0x0a220498, + 0x799202d3, 0xb9679758, 0xcfea054f, 0x559a74cd, + 0x0c3b6b9f, 0xe5b176d3, 0xc861a763, 0x96a0a5f9, + 0x9c2a76f0, 0x51c40c7b, 0xaec7424f, 0xec483091, + 0xcf173270, 0x5e645d94, 0xd55fe28e, 0x3c7bd81a, + 0xdef2414c, 0x6609653b, 0xd783e959, 0x5eecfa89, + 0x17c428a2, 0xe04470e1, 0xeb0fdf02, 0xa1049ca5, + 0x29a1a12b, 0x5421341c, 0x28173e87, 0xd0bbc827, + 0x3ec3e501, 0x6a4585b0, 0x25bb6bfc, 0x377b41f0, + 0xc73415ac, 0x19c84967, 0x34dacefb, 0x095677f7, + 0xedaa36ac, 0x327c7594, 0x6f23fd0a, 0x69c351ca, + 0xe8001214, 0xd8396899, 0x13da8cc6, 0x39a31562, + 0x20c87663, 0x8d3059ae, 0x69d8bc6f, 0xd8b5f3f4, + 0xf9601dca, 0x6f77676d, 0xc1b56c2f, 0x771e2935, + 0xbf4ae95c, 0x23718ca7, 0x0c765f79, 0xd45e2d00, + 0xb0d04243, 0x5f5feaf6, 0xf0460fd3, 0x7b7056c1, + 0x899d8e9e, 0xed52bb18, 0x52685147, 0xf1dde703, + 0x7d5be459, 0x294106fd, 0xd1645027, 0x20df9a18, + 0xa20e6dce, 0x188c901e, 0xc5185655, 0xd57af73d, + 0x4cce7042, 0x1717b7c8, 0x98ea58c2, 0x25877371, + 0xa8d4a700, 0xa2352903, 0x490926aa, 0xbdde05b4, + 0xc7399b70, 0x70947833, 0xf049aaf9, 0x71eedb1a, + 0x61bfa5c9, 0x4b5c6202, 0xb02d0e70, 0x555dcf28, + 0x10aead7e, 0x0cdcde62, 0x790ee757, 0xf19bcee1, + 0x671af1c2, 0xc1e9a032, 0x10a1ec98, 0xfe276456, + 0xae468a82, 0x4ffad70f, 0xe5bc85c5, 0x94ac79fc, + 0xc6cb0e54, 0xe377d805, 0xdda376f6, 0x617fae47, + 0x67bfcef5, 0x0cbdb05e, 0xc527ec76, 0x7ce4e25b, + 0xdbd522e5, 0x01015c63, 0xc2f88b4d, 0x763516bc, + 0xa6e3d01b, 0x11cf5fbf, 0xae998260, 0xa8bbc7fa, + 0xa3a71f1d, 0xbe3c66b1, 0x7f01fc61, 0x7c76b159, + 0x0a818527, 0x947fc14d, 0xd506d85d, 0x00fa3d7d, + 0xb2559817, 0xab8fbb90, 0x1512e524, 0x9862b966, + 0x2211ea00, 0x3655c2c2, 0xfe68365d, 0xaf4f4922, + 0x93e4c4d3, 0x9ccf0e43, 0x519737b2, 0x012a1a4d, + 0x3102ad44, 0x39cb3d83, 0xe25c92ff, 0x90803cd8, + 0x82e8a160, 0x0df879f9, 0x172e2e59, 0x4555531c, + 0xaa90ffaf, 0xaaa7551d, 0x8854dbff, 0x8d506eec, + 0x554f911f, 0x75681d0d, 0xd81358c6, 0x9a4374e3, + 0x07262862, 0x020d1289, 0x60a5d925, 0xe0a9da60, + 0xab05f8ea, 0x5c1a6ddc, 0x520669df, 0x776c2e01, + 0xe2d7eb1d, 0x1533d7d5, 0xd7ec9e1c, 0x8998bd4e, + 0x1eaea14d, 0xf824320e, 0xd650bfc7, 0xe03e581d, + 0xbb7811fb, 0xc06d47f1, 0xb016ffe2, 0x6ef636d6, + 0x084bcbfc, 0x1c2931ac, 0x4b1d6d23, 0x5b52df0c, + 0x6722deff, 0x6637ec34, 0x50d7cac4, 0xe93acf27, + 0x0a5f1c96, 0x6691baa8, 0x196ac6c7, 0xde02c7d1, + 0xc6654cc3, 0x92fc77ad, 0xcbddc53d, 0x8812077c, + 0x2c24e386, 0x5dc3ae0d, 0x288ade1e, 0xa7b2980a, + 0x9e074d68, 0xf56ebd28, 0xdc7407df, 0xf739962d, + 0x4265150d, 0x67547248, 0xdba6123d, 0x9d901e31, + 0xb5f7371f, 0x902a417a, 0xa5461e34, 0x8f95942d, + 0xf9128b96, 0x246c3b84, 0xdbe723c8, 0x33af8832, + 0x07947cd0, 0x3120ae67, 0xe2cb3f25, 0x561fd013, + 0xec94aa93, 0x30d544a0, 0xb6146e73, 0x5f9eb72e, + 0x4ef4974c, 0x7388faa8, 0x80ccd000, 0x1645ba2a, + 0xc1931822, 0x5a8a90c4, 0x671a7821, 0x45cde72c, + 0xcdf00e3e, 0x110e4534, 0x871b3a8a, 0x92871932, + 0x389c033e, 0x518d3d39, 0x730bacdc, 0x224e87b8, + 0x91a69e62, 0x67392c22, 0xc00fdc01, 0x7b4695ab, + 0xac24e03b, 0x8b8b1c20, 0xa668ad83, 0xffd0c5f6, + 0xf113ebe7, 0xeec07974, 0xd067e345, 0x30f784a4, + 0x31dec475, 0xe7dc5b8c, 0x17fa9595, 0x6ed0f63f, + 0x3b9e89d6, 0xee95b6d0, 0x09519cf1, 0x894685b1, + 0x1a4f5783, 0xcd0c7c3a, 0x4a29d4a6, 0xa6297b75, + 0x3113e482, 0x7d7c6671, 0xce65e003, 0x2961622e, + 0x9de0f171, 0xd81bec53, 0xfe3337d4, 0x6a41a1a2, + 0xdaf4c822, 0x35b83ec7, 0xbd65ba4a, 0x97712528, + 0x04965784, 0x0ff7c2c2, 0xbadcd742, 0xa825284b, + 0x034e703c, 0xae374dc4, 0x9c62ab4d, 0x49240dad, + 0x3df6d1e9, 0x2671ba57, 0x284d6257, 0x8195e532, + 0x81250fc5, 0x1cdfd75c, 0xd6018cd9, 0x55fac417, + 0x95273244, 0x0882b932, 0xfba4a7c6, 0x3e3f7d12, + 0xe02b2500, 0x28142bc2, 0x86b771c1, 0x76479eb7, + 0x54189bf8, 0xd8098873, 0x1074c551, 0x11476fe8, + 0xd7e328b0, 0xdfcd1c8e, 0x657861fa, 0x80644d26, + 0x6e9995f5, 0x8e3d70f4, 0x1872816b, 0x950ca6ee, + 0x8a4521ea, 0xeba371fe, 0x02320c81, 0x626a3d66, + 0x3c71ce24, 0x11a6e15d, 0xb97efbb4, 0x60ffc428, + 0x851831b4, 0x12283e5d, 0xc2be679a, 0x59737083, + 0xc69d2df8, 0x29efd7ea, 0xd14e844b, 0xd723830a, + 0x533dc25d, 0xdbedd2b4, 0x7fb501dd, 0x4a0dd00a, + 0x264dc555, 0x6fd4a058, 0xcb4db177, 0xafd67e51, + 0x6ff5bac1, 0x33f1af1b, 0x14c157e1, 0x2d11d0c1, + 0xe15f5e13, 0xb43cd253, 0x88b86a2c, 0xa3fed30e, + 0x9584f524, 0x5edf52c3, 0xe4983055, 0x37d01498, + 0xd0275470, 0xdd2d0838, 0x05a6dc9e, 0xb448283a, + 0x3e813cd5, 0x9d72aaad, 0x66d017ec, 0x1e55e244, + 0xdec93a6e, 0xe514ccdf, 0xea794b51, 0x5f6e0aed, + 0x9c99551d, 0xcc4949c3, 0xa35ba73a, 0x84cd2359, + 0x3866e22a, 0x5409a77f, 0x573882a3, 0xcc31dbad, + 0xa0268411, 0x40d8c5c2, 0xaab0d780, 0x3e52a338, + 0x8030015a, 0xf6ecd2d5, 0x770d4674, 0x55b8f09f, + 0xaf390b78, 0xe043eac3, 0x1fce72bc, 0x5c0a037c, + 0x697e08aa, 0xd85bd8a9, 0x57481efa, 0x4916f2e9, + 0x456ed05a, 0xae8cb722, 0x8f507d70, 0x76f6f39e, + 0x2bdf5259, 0xf1f8d541, 0x2b50c778, 0xe5f9490e, + 0x9d8b788e, 0x2baea68b, 0x34ba2d1e, 0x828cb929, + 0x0f842b49, 0x76e0dde0, 0x5682f568, 0x66d1c5de, + 0x634ef696, 0x212a8f6b, 0xa29756b8, 0x156219b6, + 0x09a9fc7a, 0xb9249216, 0x4a7ae8b7, 0x53d14148, + 0x13510bdb, 0x2131a2f7, 0x7df45c3e, 0xd50d3a2a, + 0xae382656, 0x809eeddb, 0x78ddf724, 0x6edce7e5, + 0xbb21c1f6, 0x081fc73e, 0x76869eea, 0xe06a86a5, + 0xe4a2bd9c, 0xb78e5c40, 0x32ee8493, 0x7888aad3, + 0x669131c8, 0x9a2c05a4, 0xbcf3d9c4, 0x3b412dde, + 0x3cae2f74, 0x0744867d, 0xb7538ee3, 0xa520207c, + 0x41289631, 0xe46e4aab, 0x1848e0d2, 0x19aad620, + 0x30b327d8, 0x40c6f681, 0xae8dc046, 0x589dc9c7, + 0xaa17e28f, 0x6dc85c0e, 0x74488e82, 0xc4208a25, + 0x64d4617a, 0x5ee46a77, 0xffca0693, 0x5007f221, + 0xcc4bf790, 0xe515c241, 0x27e79ffb, 0x1e38aa9b, + 0x56197e79, 0xb435c115, 0x70e6ea5c, 0xe0a130b3, + 0x77b85ff6, 0x85751cf9, 0x80e61f0d, 0xdd3868d7, + 0x163e44b6, 0xfe3acca3, 0x1936a81d, 0xa1507e76, + 0x04a15dcb, 0x624aa874, 0x388c1b87, 0x15360f93, + 0x2e4a0833, 0xfd01216f, 0xe1ccb3dc, 0xd8f3105b, + 0x6c07b2a3, 0x51ba0953, 0xe5400c7e, 0xcd086f8c, + 0xfcc33cea, 0xd6035c96, 0x0eb2b33f, 0x1b265721, + 0xfc44123f, 0x5bb66566, 0x74544487, 0x30ce8ed3, + 0x557bb62e, 0x7e37f9ae, 0xce0cf72d, 0xe40b9628, + 0xbd2cad80, 0x3c47fb99, 0x86c3716b, 0x14f19c64, + 0xbfd75a2a, 0x6e6ebaaf, 0x5146233a, 0x0c574398, + 0x2adeb48e, 0x1255340a, 0x1224d979, 0x647ab6c4, + 0x7399aa83, 0x8ba6bab7, 0xb11f481d, 0x9a07a663, + 0x12f4b1aa, 0x9dc75926, 0x10f33d85, 0xd147fd4b, + 0xede5ad53, 0x5a7dc8bb, 0xd5e90467, 0x4cf132aa, + 0x9198ea59, 0x21111e32, 0x01ef3a92, 0xb8e0e023, + 0xb6353bcc, 0xd4833107, 0xa1625c21, 0xb6953811, + 0x3f4d839c, 0x1001ca44, 0x65fdb0a2, 0x264ddffd, + 0x6ffa6f31, 0x16b8e87d, 0x36462bcb, 0x48fcc93b, + 0xa343a8b8, 0x8775ae4c, 0x9d99f458, 0x09ffe777, + 0x35a61897, 0x92ef4fad, 0x73115358, 0x30e8b909, + 0xe63b96cf, 0xbfe8eb51, 0x3f8ab778, 0xea8b03dc, + 0xbe2260c6, 0x7f7cc442, 0x6cb62967, 0x4c35323c, + 0x19f393da, 0x32c5e70a, 0x5e06843b, 0xef87551c, + 0x13d9e5a7, 0x03ccc3bc, 0x6e69bd8e, 0xf9f06521, + 0x684d9b89, 0xaaca7531, 0xadb35910, 0xcd89effb, + 0x764761f9, 0x12351b73, 0xffc5dd64, 0x21210bc9, + 0x640aa59a, 0xf2dfec09, 0x36d92a72, 0x07362c2b, + 0xd1b9f122, 0xb54b00ce, 0xc05eaf0c, 0x61f9e747, + 0x9b6cc9bb, 0x361a99e6, 0x2ea28616, 0x92b51282, + 0x66a965dc, 0x93999800, 0x1bc8020c, 0xe5e9acd0, + 0xb426c154, 0xd217569b, 0x489e1447, 0x9a066913, + 0x671ed9e0, 0xd2cb03a1, 0x7b4d0ddb, 0xd3795f58, + 0x768e4a58, 0x2279850f, 0xeeaed07c, 0xeb3e5af7, + 0x3694bd4c, 0xad595170, 0x462f9ba2, 0xa37c9ea5, + 0x2bb80262, 0x4fa7e8ed, 0xfae3d648, 0x3db9b455, + 0x4518b3df, 0xcfecaf84, 0xfb4fc40f, 0x08e90140, + 0xc89c4c7e, 0xfe94b9a1, 0x9513af4b, 0x1d90c5ee, + 0x3d5d6a21, 0x56be9e74, 0xc7bfefdc, 0x61d41c68, + 0x2dc29d7d, 0x46f5be73, 0x091ac556, 0xc1f10a05, + 0x87d9e54b, 0xf83e8653, 0x17e28262, 0xeed60ac1, + 0xc997e7df, 0xce95a43d, 0x1c033f7d, 0x642b6582, + 0x61892ca7, 0x49a088d3, 0x936be1c9, 0x11d1486f, + 0x782a6705, 0xe483befc, 0x8f476e91, 0x45b84525, + 0xe2048cf9, 0x01d38134, 0x14c47aca, 0xacddb09c, + 0xde347663, 0x115f90d4, 0x95672716, 0x0bd4f4c4, + 0x36477877, 0xc14a78d8, 0xb14b4b4b, 0x6af2e0bf, + 0xf313c909, 0x2f731e15, 0x5426fa60, 0x2d76cf6a, + 0x47ffda79, 0x953d464a, 0x05768d14, 0x0f81f835, + 0x98a06e6f, 0xd5a8b453, 0xc35f2c07, 0x15da054a, + 0x584e2bb6, 0xd6126787, 0xf335c3a6, 0x070f1430, + 0x02efef35, 0x4350f6f6, 0x2f1302eb, 0x888c76c0, + 0x1fad1876, 0x3b284e92, 0x8ac49eac, 0x1c9116b8, + 0x91ca04c0, 0x18f392b9, 0xe6b8f734, 0x6b1cc99d, + 0x61649305, 0x8d14d72b, 0x6173c5d9, 0xaaf8e7fa, + 0x16500d34, 0xe27bfb3e, 0xe6bf35c4, 0x386b8e30, + 0x9fc1e9a4, 0x9f44bfb1, 0x37c899ed, 0x8235ea1f, + 0x3044f5c4, 0x715e6b19, 0x638a2dfa, 0xc804120c, + 0x045bd63f, 0x3c322ab6, 0xf6222404, 0xab4a2b6f, + 0x0e8071b5, 0x5d0bd6d1, 0x84059106, 0xb581a9c9, + 0x659c4796, 0x6eeb3f00, 0x5fafad87, 0xdeedc11d, + 0x100cb39f, 0x405c0b2e, 0x24b08c9f, 0xa8fa5848, + 0x342ec500, 0x18e8089e, 0xbec2f19d, 0xae085900, + 0x5a2ac4b6, 0xdf23ea33, 0xd5cfda21, 0x0ade6068, + 0xd5c41ba1, 0x184a9975, 0x35e1d998, 0xf015aa99, + 0x730b911c, 0x658b33a8, 0x1a86c0b3, 0xce7496df, + 0x7d234d7b, 0xa2e92853, 0x94fada37, 0x5c9161e0, + 0xf4674e71, 0x0d842f6e, 0xf2065d2c, 0x1d72502b, + 0xf5039fce, 0x484775b6, 0x1973bf73, 0xc4ba227f, + 0xd65edf8b, 0x59463591, 0xd239638e, 0x96cf33a6, + 0xd9197b41, 0xb8721cd0, 0x9eeca52c, 0x92a06327, + 0x08f48d62, 0x18d0c9b6, 0xcad7d343, 0xfb072f8a, + 0xb0c97b2b, 0xd88db393, 0xe72c5da2, 0x1c389579, + 0x9adb7e4e, 0xd2cb1dbf, 0x209a9c94, 0x4220c981, + 0x5bdc6ca5, 0xe3b078fe, 0xccf9dcf4, 0x6228bbd5, + 0xcb7294c2, 0xc186fb0f, 0x27be619a, 0x4cf71d90, + 0x4f2d1c45, 0x179f97c3, 0xf97727fd, 0x4c8cb801, + 0x5a48ab57, 0x3b8db3be, 0x9b9932e8, 0x3727d15b, + 0xd43e7d34, 0x59aab323, 0x78c972a8, 0x070e2f22, + 0x91bbeee1, 0xf3112532, 0xfd43659e, 0xf51316e2, + 0x6754e948, 0x58ce9072, 0x803d8f48, 0x4b32cf04, + 0xeb4fe96f, 0x48ecfbf3, 0x0348e941, 0x74cd52c2, + 0x669d7288, 0xaa17dacd, 0xc18283ed, 0xb2a046e6, + 0x5926644e, 0xe3f4f200, 0xa88ce3e1, 0x1c9f67a8, + 0x5e4a4d75, 0xd6a95fdd, 0x560a4bdf, 0xb986b661, + 0x52a3cf3a, 0x9c341a96, 0xfc0d687a, 0xac1c9ccd, + 0x5597940f, 0xc364389a, 0xc753eea0, 0x888a039b, + 0x6835a25f, 0x337155c2, 0x28fefb3d, 0xf0b667d6, + 0xc1966b48, 0xb0e458b1, 0x6b5c014c, 0x3df57166, + 0x28b7de4b, 0x28cf6fc7, 0x8a99d5f6, 0x61f742e1, + 0xce8896c7, 0x520de06d, 0xc98195a3, 0xfb79f11e, + 0x83333890, 0x46a0b9ff, 0x987027b1, 0x5a99b9a2, + 0x733abc25, 0x9df25e2f, 0xbb15d34a, 0xf79d19c0, + 0x59453ee7, 0x3b46dc0a, 0x21aa97a5, 0x5be1073b, + 0x6255a69c, 0x168f3960, 0x0b922f09, 0xcfb9b4f9, + 0xeb85a443, 0x20538182, 0x40e6e529, 0x3da23239, + 0xc4484958, 0x953533d8, 0xd5d6c7f2, 0xc5df7450, + 0xbefa38da, 0x8c7935de, 0xbc7db0b9, 0x4847b56e, + 0x50cd38b6, 0x4f886e38, 0x1efc2fc2, 0xf79b7eaa, + 0xfdd91ea5, 0xcc26bfcd, 0x41b7947c, 0x50e172a9, + 0x3aabc88b, 0x74891436, 0xd268ff36, 0xa3c4ca06, + 0x0bb16d18, 0x717cd9bc, 0xec56c692, 0xdecfd1fb, + 0x38c0e224, 0x96e9328f, 0x9d8b3c7e, 0x98f52ffd, + 0x68a6d960, 0x73c5c885, 0xf25114e9, 0x58fa684a, + 0xa072c8cd, 0x39062209, 0xd5b837ad, 0xc1282787, + 0x806f7c5b, 0x69e239b7, 0xc828588a, 0xef590ebd, + 0x8a1907a6, 0x5f6d2c0c, 0x2d2b5677, 0xd2cca905, + 0x73ff0c85, 0xb65d45ce, 0x4ef87869, 0x7816f934, + 0xc026bb7e, 0xfd1ce6a0, 0x5c853805, 0x71b1b312, + 0xa6e0219c, 0xed4e89bd, 0xc42ec4f0, 0xe351c2be, + 0x61af1ef5, 0xdaa0e9e0, 0x21e7672c, 0xd5deb556, + 0xc90b54a2, 0x11eaa18c, 0xbad09356, 0xb1865003, + 0x16367bfb, 0xfe849827, 0x07adb77b, 0xf6e9f366, + 0x9a21fd47, 0x4f381abb, 0xd23bcaa8, 0x00d7a8d9, + 0xfedf4ee7, 0x23ad6a8b, 0x0368ab53, 0x38141b62, + 0x91e39b21, 0x3a3ee194, 0x88721894, 0xfb8b07ba, + 0x89a47db7, 0x351d4a41, 0x4778ddac, 0x28352134, + 0x499b8228, 0xca36d401, 0x660fbec1, 0xb7a041f0, + 0x9d7191ce, 0xea22d95d, 0xc2653e09, 0xe85652af, + 0x6a021612, 0xff66462e, 0x67b760df, 0xe7ef5c83, + 0x6fe036a5, 0xcc4a2a0f, 0xcf9ee593, 0xfed06d4e, + 0xc166e72c, 0x2638fe8c, 0xbd759388, 0x87bb1a0e, + 0x99bb92cf, 0xbab768cb, 0xf171d306, 0x4b41fbb9, + 0x9466a9d7, 0x1f1da28f, 0x88f021f0, 0xe97e8adf, + 0x4c4edf26, 0x973121c4, 0x976eca75, 0x62603f28, + 0x98455b1a, 0x22856a35, 0xc26d4ca9, 0x0878679b, + 0x4d3cffc6, 0xba4bfdd3, 0x6b338d41, 0x75fd3040, + 0xaa0b90f4, 0x0bfb49f2, 0xca63ea6c, 0xd5b9a617, + 0x9fb3640f, 0x7121c54c, 0x0abd708a, 0xbea70041, + 0x3798755c, 0xc01f4752, 0x4b6e1acc, 0x57371f21, + 0x88cec024, 0x98239d76, 0x6885ae35, 0x36562a21, + 0xb52722c9, 0xc6b8f152, 0x96706f5c, 0x309ca6d6, + 0x4cd0662b, 0x9b859f81, 0x1f949629, 0x4561b934, + 0x92af0e05, 0x2c4e9ce2, 0xa25e5651, 0xba8441f2, + 0x41767331, 0x0e865959, 0x1088a032, 0x0b5056e6, + 0xe545b255, 0xe4325357, 0x5d831ddb, 0xd9c25c02, + 0x1fb917bc, 0xc04bb88f, 0x20e6b587, 0x363a7c6a, + 0xacc4b3e4, 0xf96d4feb, 0x7773f96a, 0x2cf262c3, + 0x924a8638, 0x16312b2a, 0x3451e718, 0xf02cde76, + 0x8cab0a60, 0x3960442d, 0xde22a36f, 0xc52b2a50, + 0x288fa4ac, 0xb21c5d47, 0xfad683b6, 0x4ce3ab14, + 0x579d0ae3, 0x5250c865, 0x8fe443f8, 0x5e57b37f, + 0xffdb9fdc, 0x743c99a9, 0x2fc52649, 0x89c5355c, + 0x40bd2667, 0xde656547, 0x741cee38, 0x91fe7295, + 0xfa1383cf, 0x3c8c70b5, 0x2b2b0115, 0xee377a3c, + 0x3f024fdc, 0xabdeb5c7, 0x63c5ac1e, 0x614728e5, + 0x4c9ac0d1, 0xcd714050, 0x4cd76c4c, 0x8b0ac295, + 0x3f0a23d4, 0x26b1a5cf, 0x97101e38, 0x60444232, + 0x37b82517, 0x80c22d78, 0x33c550a1, 0xc02c71ce, + 0xfcc8b1de, 0x4e9941d0, 0xf7528b01, 0x46b648b7, + 0x886d4e31, 0xc4149487, 0xa0c370a5, 0x970016d0, + 0x43e3e5d6, 0x8afbdb95, 0x305841e6, 0x8555ecb7, + 0xe5ebbdf4, 0xe1ab19bc, 0xb8324559, 0xa94abc7b, + 0xd7b570e7, 0x71e5e62f, 0x87f14382, 0xaf8e300d, + 0x5e1e4242, 0x493b0e69, 0xcaa1b1f8, 0xcee82bf7, + 0x1b9a0c19, 0xdac3641f, 0x1f0fefb9, 0x5e180035, + 0x691acda1, 0x58aa7efd, 0x36e3773f, 0xd41641ef, + 0x7090766a, 0xcb133eea, 0xc618881f, 0x1b60ec4f, + 0x8c8d67a2, 0xe87cfeeb, 0x2ba826ae, 0xd9d80c56, + 0xb5f6d248, 0x7077eecd, 0xe67ac236, 0xe2ef605a, + 0x76ac0fe2, 0x4c0ec422, 0xf3f106e3, 0xc9b82a12, + 0xea68b3a6, 0x87ebaef7, 0x3ed418a2, 0x6cf05a07, + 0x7b474f07, 0x5463726c, 0x49677735, 0x85a16624, + 0x6b086835, 0x04a7c692, 0x3054ea16, 0xf32835d2, + 0x9719ee3d, 0x4c7f59b2, 0xacc62188, 0x4441d359, + 0x2193514e, 0x517ba9cd, 0x84534168, 0x3a02297b, + 0x5b260b45, 0x210c0b34, 0x8ab2f13b, 0x3d31e7f8, + 0xa2fb4747, 0xfdbe2d04, 0x75410c0b, 0x1c1b13b9, + 0x5ccb85f3, 0xa06a64ed, 0x6969a796, 0x42c69e43, + 0x45ca59fb, 0x5903c1de, 0x87bc3adf, 0x59a5ed56, + 0xf9df0890, 0x55c423d0, 0x898c01e7, 0x3351b50a, + 0x466763e5, 0x403e0fc1, 0xf9d45622, 0x8a123cc0, + 0xdefef6e0, 0x7e4e1261, 0x5876aa8d, 0xebc0f276, + 0x645fb389, 0xfb81b51a, 0xa4cf6279, 0xaf75dda7, + 0x6d5b3633, 0x2805b0be, 0xaa95723b, 0x53fdea33, + 0x4822c4cc, 0xe07b2e9b, 0xb04d1aa3, 0x24b068e5, + 0x9c587a1c, 0xbf8cb9fe, 0x5776508c, 0x1b6228e6, + 0x95029174, 0x68599aff, 0x72d279f5, 0x2df7b472, + 0x1b6ce0ff, 0xccb87c5b, 0x28b34cb6, 0x351a8784, + 0xd96ae788, 0x813f7058, 0x004c51c7, 0x3e0ec4fa, + 0x7bd9e172, 0x7bb60516, 0x2c4ed5ca, 0x0bd7708a, + 0xd8004287, 0xb847766d, 0xcc72ef13, 0x88b8abc8, + 0x780bb9ec, 0x584fe787, 0x35a76a93, 0xe6f90a84, + 0x02fe93e9, 0xfc548ef1, 0xa884ea83, 0xd06fc4ec, + 0xc454a49f, 0x9e33fb40, 0x3455fd8f, 0x0324b606, + 0x81626d9e, 0x209dae75, 0x075b4bcc, 0x14f1b18e, + 0x36e13565, 0x4ae60c11, 0x6e9f5f7b, 0xceb6d6a9, + 0xb31f7ab1, 0x7b10baa4, 0x2ee8d52b, 0x082ea035, + 0x46cc75a9, 0xe6765cf9, 0x3021e399, 0xc4f50a44, + 0xd2393f57, 0xb4a7346d, 0x298c5794, 0x3f1c3fe2, + 0xf37fde93, 0x0830d435, 0x1868bc03, 0xda7d4049, + 0xf4ed9427, 0xa8ee63cc, 0x46db896b, 0x0cb55b25, + 0x022cfbf0, 0x920031c3, 0xf7be5666, 0x93e707c7, + 0x77d3e86e, 0xb502bd11, 0xe18def05, 0x58075890, + 0xb3299f8f, 0x978d158a, 0x3f3f7d71, 0x992f0ed6, + 0x54e4baac, 0x9af31103, 0x7f23ae1e, 0xcddfb1c5, + 0x8f1c5ee8, 0xc47d21fd, 0x2acab7b4, 0xab51ccb0, + 0x3151c9cb, 0x069c3f8a, 0xf8fb54d8, 0x6c1ab4b3, + 0xe1d00b2d, 0xdcfba085, 0x4e812ad9, 0xfbeb54f8, + 0x3842c409, 0x08360642, 0x04d373d8, 0x43934023, + 0xd0e6a96c, 0xcc9b6608, 0xd53e8a2f, 0xd72791f0, + 0x2b61f2b6, 0x47684643, 0x753999af, 0x3487ef6b, + 0x59d80818, 0x30a87a45, 0x431ad752, 0x61aab04b, + 0xa6c28ed8, 0x6c1e72da, 0x88f934d7, 0x90f19f95, + 0x4c182f6f, 0xe3859acf, 0x786903f2, 0xe8b43b69, + 0x6f2f25f0, 0xe0430f68, 0xea6a24dc, 0xe21d8653, + 0xf0a1ac3a, 0xa533e1fd, 0x134cff32, 0x643370b1, + 0xfe3419c8, 0xae943ca3, 0x1bb832b9, 0x3ebd70fb, + 0xb54dfbf4, 0xec790fa2, 0x914b96a7, 0x350c2864, + 0x69599462, 0x2c5e120b, 0x2ab4ed44, 0x449c381c, + 0x1c4d4719, 0xc34c6197, 0xbe5f7566, 0x6b8cc646, + 0x7eaa2b57, 0xbdc78fa5, 0x021a4f2f, 0xcad3471d, + 0xd491acd3, 0x841d54a7, 0x6e293eea, 0xdc33fe0b, + 0x28bec482, 0xb9cdd43a, 0x3645b417, 0x68cf8f0e, + 0x0c77c88b, 0x87ea3366, 0x6297fdfa, 0x0a2a6edd, + 0x76266ae5, 0xd5ab5315, 0x1c160b01, 0x6d06e0e0, + 0xbe5adaae, 0x4da3aad5, 0x87a88a0e, 0x65c548b1, + 0xa0c4b311, 0x9de26c22, 0x71286bd5, 0xebce60e1, + 0x07cb4bdf, 0x81bd0699, 0x585f919e, 0x3360c9dc, + 0x3ad13e68, 0xad3e046b, 0x33fe4432, 0x47eae5d3, + 0x6019e2e8, 0xfb6e850e, 0xec140d70, 0xe96cb516, + 0x143c17bd, 0x1c69cf2d, 0x752e762d, 0x91025a6b, + 0xd27da360, 0x949f4340, 0xdfefc075, 0x200e7194, + 0x88456b3c, 0xf873d255, 0x6e659be1, 0x07f75e8d, + 0x86f98e7c, 0x791b5790, 0x7e313f52, 0xf40e51b8, + 0x06ea23e8, 0x212b47c5, 0x04aaa082, 0x967037ba, + 0x1aadc12e, 0x872219b9, 0x6dfc9edb, 0x665114ef, + 0xfce6888d, 0x84674668, 0xa2d99014, 0x7eba0ea9, + 0xec04c21b, 0x6043e9da, 0x23b75ac6, 0xbd819ec7, + 0x4a980613, 0xa8519f81, 0xf47fb1ea, 0xf202a67b, + 0xcfae2b25, 0x243b9640, 0x3cdc2ae2, 0xc9694189, + 0xd4f78ae6, 0xe8f3c9e1, 0x0ad19a6f, 0xe685185a, + 0x237db448, 0x372611c8, 0x83461646, 0xf5960af0, + 0x3caa0770, 0xd12f2300, 0x74d38edf, 0x1ca4bde3, + 0x41b65454, 0xe994dad5, 0x0cb51473, 0x9595cec0, + 0x0a161905, 0x77ad322b, 0x0cca0ab8, 0xe55fac68, + 0xfd741f6f, 0xcd496a10, 0xef3ef74c, 0xdce0f9a2, + 0x974f1d65, 0x7fbe6f8d, 0x1f397983, 0x65b190da, + 0xf8ad60dc, 0x3afe5937, 0x38125cf6, 0xfa99804c, + 0x55ad851b, 0x6b011e2c, 0xaf063d6b, 0xc625d28b, + 0xe8d52c06, 0x240af361, 0xf3cd155c, 0x4c43e3df, + 0x53517351, 0xbff2b3a9, 0x76de55ec, 0x717b945d, + 0x9ca46159, 0x76b94177, 0x544f21c6, 0xfc0554f6, + 0x1e255637, 0xfa2648a5, 0x66175b23, 0x4221ba09, + 0x27b7ca0d, 0x40a41d36, 0xb576b6f2, 0xc058b379, + 0x9d12c12e, 0xafb22112, 0x0b4efb38, 0x9fc4db0d, + 0x1e5106d8, 0x008bf43a, 0x36d5a261, 0x0390d4c1, + 0x58814521, 0xf0360311, 0x788fb46c, 0xd20083ee, + 0xa6471124, 0x4957c104, 0x3696900d, 0x7b4bcdf8, + 0xa6c33df3, 0xc59a4f0d, 0x31cf3ef2, 0x9f56e8f1, + 0x6fbd1153, 0xcc133da6, 0x06dc4f70, 0xdc87ebe7, + 0xd7769103, 0xdb1b6fa7, 0x4d27a4ce, 0x5aa2df8d, + 0xb5c45cdd, 0xec5378de, 0x931a72ca, 0x4a8103fe, + 0xfb9b2c86, 0x7f0002aa, 0x1103e5fd, 0xc2e0b472, + 0x05e406b1, 0x53a3b2bc, 0x4074cf3a, 0x6c2d6159, + 0xe0c9d51b, 0xa58f21d7, 0x951e5211, 0x7da68df2, + 0x33f3f8c8, 0xfcf9835b, 0x416be47e, 0xa8fead8b, + 0xf7a9c6a4, 0x09a503e1, 0x02582596, 0x3f3f9635, + 0xd8b8ef32, 0xc79ad413, 0xa4535d47, 0x199fd36e, + 0x96c2cdf7, 0x25014d3d, 0x8332ac03, 0xa8d03b58, + 0xddb610d2, 0xc969e97e, 0xb6d6fe0b, 0xdff28770, + 0x691361a7, 0xf1e352ac, 0xbe6e8632, 0x79406980, + 0xe40fcdc3, 0xf2ad5d41, 0xa18fec2d, 0xea0a2ec0, + 0x6881a1b2, 0xe37adae4, 0xd8394139, 0x6a7166c9, + 0x14d7ed51, 0x0783746e, 0x907f78e7, 0xf67b4120, + 0x9ea2b13e, 0x66c2f9d3, 0x44b4def4, 0x530797ed, + 0x2eaac065, 0x0ba94033, 0x6c8888fa, 0x77bfb22f, + 0xa44aa777, 0x2b501179, 0x2d8d5ad7, 0xfbe55696, + 0xfd28297b, 0xd8ff3553, 0x3a71575e, 0x8e178194, + 0xdd4c41d0, 0x58e83bf1, 0x476d321a, 0xc3e870e9, + 0x26d1b852, 0xb4a65120, 0x5a26d46b, 0xff038f01, + 0x22470eda, 0x6a8d53dd, 0x65bbb1a9, 0xd7b0dc3b, + 0x6c9c8017, 0x9438fec1, 0xedac193e, 0xfe2f5d5e, + 0xed73e772, 0x4019f1a3, 0xc157ae51, 0x54122040, + 0xb04045f5, 0x882d4530, 0x29ebf3c1, 0x76ed099d, + 0x6ff6366d, 0xe7f8ab16, 0xa5f2ceb3, 0x0f63476e, + 0xaae5cd38, 0x07b5246a, 0xb8e1b30e, 0xa05d7d9f, + 0x5fa1e2a1, 0x68cc00e6, 0x13588e6d, 0x598cf752, + 0xee2c5036, 0x3d177f5a, 0xc2369ab8, 0x77a2c162, + 0xc326d32b, 0x7a9d8e42, 0x0b96fd57, 0x14a40dbc, + 0x9bc0df7d, 0x72d7166e, 0xbcb5cb57, 0x2d3ee27c, + 0xaba25eab, 0xa681b901, 0xd41d5c36, 0xfd6a968d, + 0x0180b3e4, 0x865d2607, 0x06aaf49a, 0x8e9147d5, + 0xcbe9d8df, 0x1bbf0e56, 0xbc20597b, 0x1d4378cd, + 0xb685366f, 0x69e2af37, 0x54d809bd, 0x58641336, + 0xbfc8c751, 0xe69c39ea, 0x222988a6, 0xc8cb3e45, + 0x9ee0c8ca, 0xf8cf88c2, 0x91fe1df6, 0x4375fa8f, + 0xdda1d3d4, 0x794996e0, 0x1aac3b80, 0x8ccdf057, + 0xf5604278, 0x0dee7181, 0x11c8602d, 0x033bc43d, + 0x2668e498, 0x0c836135, 0xbc450504, 0x1f03c1d3, + 0x7dbf90d0, 0x46d6fd92, 0xd18d3244, 0x2df2b77b, + 0x76567ef8, 0x283703ab, 0xf8cec4cd, 0x42bed101, + 0x5c263ecd, 0x9f7b6365, 0xc8f695cb, 0x4a73e653, + 0x2a550c6e, 0xbbef5aa6, 0xd07bfa4c, 0x3320536d, + 0xcce2966c, 0x2dc8eb11, 0x6ad8f142, 0x4df0dbc7, + 0x3d7589e3, 0x47ad718c, 0x30ace76c, 0xc49e40d5, + 0x1db0ee99, 0xd323fcaa, 0x5a417f22, 0x2762cc41, + 0x2dfb790c, 0x48516f5a, 0x8d93b79b, 0x16350384, + 0x244e1eb7, 0x4ae0fa65, 0x5b5affaf, 0xf9094b7d, + 0x73ebb6fb, 0x0c3e674a, 0x22916b90, 0xb4057006, + 0x9d9846fb, 0x1e5de062, 0xe985b8e0, 0x4f54bfb2, + 0x6c91c808, 0x2e1261dc, 0x03384bc6, 0x12c4aa40, + 0x82a18ca2, 0xdfcfa565, 0x678deb28, 0x21171665, + 0xce842777, 0x4f013255, 0xf4facca2, 0x727a5484, + 0x90b83dd4, 0x2fa958bf, 0x16b261c8, 0x2b7ad3a8, + 0x778201c5, 0x09e6a61e, 0xb2065b13, 0x8382058f, + 0x06227c2f, 0x6b231e58, 0x03f5914d, 0xe5ad5103, + 0xf5181b85, 0x43832a61, 0xef3d0651, 0x80b0b55f, + 0xaaee1078, 0xbfddbe9b, 0x5c1d25de, 0xdc7f0b6d, + 0x681d4562, 0x589da81f, 0xc85d61d4, 0x945c0d4b, + 0x675f91fc, 0xa9a1d887, 0x9ad99e05, 0x0c59c80a, + 0x8d9faa09, 0x32bd3d7d, 0xa51b5de1, 0x453075c2, + 0xf9068920, 0x4f3bd245, 0xb0c236a2, 0xdc97875f, + 0x6c2a9456, 0xf13b77b2, 0xea43279c, 0x6c45f00e, + 0xe23b335c, 0x7d9b4fa8, 0x13ed73e0, 0xb14ddc40, + 0x267d60c7, 0xcc63a983, 0x326df747, 0x95e577f6, + 0x15f9b759, 0xc740ae4f, 0xcb0534b4, 0x933fd825, + 0xbfff11ad, 0x9b8a6b0f, 0xb7088acc, 0x7e36e7f4, + 0xdcc26afd, 0x2d3d61a2, 0xf9d3641d, 0xe7b2af7c, + 0x08fcfde6, 0x96d02518, 0x959eae0c, 0xf1ddea1c, + 0x4e9b5561, 0x35ebd9a4, 0xef869bc5, 0xc2f01c99, + 0x7fcfeb79, 0xec47fc6e, 0x1d35c0b5, 0x5a6f5b9b, + 0x72759023, 0x426cb485, 0x4aa04781, 0x2297eac6, + 0x46aade0f, 0x0252649e, 0x83ecc2d1, 0xff238309, + 0x2311a9c1, 0x6e22ec43, 0x86952ab8, 0x2956c070, + 0x1a346fa1, 0x9a31d8a3, 0xf00dc70b, 0x7ce30b3c, + 0xb360f620, 0xccf8af9d, 0xdf2868f1, 0xb88a63dd, + 0x8c30945a, 0xecb82b87, 0xbba3fafc, 0x736c3782, + 0x870bfb60, 0x9e9e78e7, 0x4266d68d, 0x789636bf, + 0xd1be37d7, 0x92177b7e, 0xcc9d14f5, 0x4b708af2, + 0xf05bab5c, 0x25d45db0, 0x3391f049, 0x2525bbb9, + 0xa075c6c7, 0xf7d709bd, 0x2ed5b6f3, 0xc9680cbb, + 0x0ecd2b1a, 0x329c77b8, 0x4b49f433, 0x0df8084c, + 0x0703b8bb, 0xa604d4dc, 0x73bf2ab3, 0xd841b3c2, + 0x2ab1c007, 0x93f8f328, 0x2630b835, 0x59a9ed50, + 0xba7cb3ae, 0xcf384031, 0x0ba90109, 0x8b474c42, + 0x008aa928, 0x0db2a81c, 0x8927bb1a, 0x3f61249d, + 0x179a4259, 0xf9b07f25, 0xa7e1a06f, 0xfd3b93b3, + 0x8f1c5b03, 0x169d3859, 0x38ec8b45, 0x498f70cc, + 0xcd463c8c, 0x6c242b10, 0xfaa0c1c9, 0x7dd5a746, + 0x8c381258, 0xe0f8d70f, 0x5123e0e0, 0x9eec1595, + 0x7c37f4c6, 0xed95de11, 0xa2a39413, 0x6a46e2ae, + 0x64fa6577, 0xbe0e3305, 0xec061108, 0x98479bf6, + 0x2d534b86, 0x58f1f0dd, 0xbc174919, 0x0e9e641b, + 0x45631014, 0xdaaa85fe, 0xa567d7b5, 0xe5461e27, + 0x5eb6a45d, 0xad8cb177, 0x3491d710, 0xe4121186, + 0xea34e115, 0xfc4cf825, 0x8e9f0bdd, 0xdb76c575, + 0x51b37455, 0x4e2e9cd7, 0xbbef23b2, 0x041cba06, + 0x35a90ae0, 0xa4e44676, 0xf46eab94, 0xe1295be0, + 0xe168f06c, 0xbd4a0741, 0xb178fc8d, 0xeb8d2690, + 0xa788be7a, 0xb57a1f8d, 0xdb6737c4, 0xedd3d0b5, + 0xa570e600, 0xce9fcca9, 0x567456ef, 0x86a5f81f, + 0xdccce0ce, 0xa80dfe75, 0xcf0b0e0c, 0x328d2de5, + 0x2e6b4cbd, 0x0b3784a7, 0x26e47d4a, 0x2e168e0e, + 0x3b07380c, 0xe0f9dce4, 0x190dc0f3, 0xf39530de, + 0xc809d681, 0x7849b877, 0x2548145c, 0x51d90b30, + 0x08279197, 0x9e9e461c, 0x48f5f4f9, 0x9721b313, + 0x7a98f550, 0xac92badd, 0xfc593d36, 0x296ae070, + 0x607a6ecf, 0xd94d7b1e, 0xc9922a2d, 0x2b8d388f, + 0xfdcc598f, 0xbde4df95, 0x11a4515c, 0xca3d6d95, + 0x2eca17a3, 0x70034421, 0xb2e66a94, 0x8631db33, + 0x28ce3e8b, 0xe3b1b545, 0x3c0a787d, 0xe11be074, + 0x75a6a07e, 0x44e8a15e, 0xc8daff15, 0x9437b827, + 0x5129caf1, 0x5766103c, 0x42e9a369, 0xbbeb2e3b, + 0x83b45ee4, 0x25771500, 0x94156687, 0xb8633ce5, + 0x389648f5, 0xd0415eb3, 0xc57e5b4e, 0xb550cc4b, + 0xb5b40b88, 0xb2c96923, 0x2cbc20df, 0xf6c38102, + 0x396c71c5, 0xbd165b6d, 0x78e3c566, 0x8e27145e, + 0xa88f8863, 0x0edac0ef, 0x3dfadc83, 0xdae2eb68, + 0xbc590603, 0xfa1ba9f7, 0x72bea0c9, 0x66adbfa7, + 0xe541f5e0, 0x7c9713bd, 0x8a69ce69, 0x0213fe52, + 0x132950ec, 0x3124fb49, 0xf9050bd3, 0xb13b6299, + 0x060e94ac, 0x6662a4e5, 0x59df69ad, 0x093cb3ad, + 0xd5a73a58, 0x81d62900, 0xf67ce182, 0x5f2a26d6, + 0xf5bd27ae, 0x5756f504, 0xd2864100, 0xa065982a, + 0x6b857bfb, 0x91fd0316, 0xb1ea68b1, 0x0311214a, + 0x02e6e860, 0x8dc774d8, 0xab4fd4d4, 0x12182cf3, + 0x3486ed5e, 0x5d021848, 0x45bd18d8, 0xa5367197, + 0x63678ae3, 0xe3584740, 0x2409abc5, 0x09f77957, + 0x8afb83fc, 0xbb71e7d4, 0xa388247d, 0xfd129f78, + 0x50479631, 0x040ec490, 0x77ffa567, 0x3c357c14, + 0xbe770316, 0x95e8489b, 0x8e1313f7, 0x577f1442, + 0xb9b279ba, 0x7c8b0de0, 0x3b00be04, 0x8d0a326c, + 0x7b0b26d9, 0xd013e93d, 0x83b0480c, 0x0ccfb8ed, + 0x8df346b5, 0x1524b8bd, 0xe6622ff4, 0xcadd3b94, + 0x461813f4, 0x2e86d7f0, 0x1ff70e7b, 0x9ade3726, + 0xd86c7a4d, 0xc2de43d8, 0xaa987172, 0x4e7e91e2, + 0x11e4a337, 0x3aaeabf6, 0x6366a917, 0x68caebbb, + 0x23817841, 0x972e706a, 0xe7936a36, 0x45432399, + 0x5916009c, 0x44dfd211, 0xdd10adf1, 0x5987da29, + 0x6229335d, 0xd3ef7ab5, 0xdcfa4083, 0x851fde4a, + 0x4f41fb0e, 0xd9088e95, 0xf16d87c1, 0xcfe96b84, + 0xddd65fad, 0xdb7a2e4d, 0xa9b4267f, 0xefd34cee, + 0xf9bc811b, 0xb24b0e13, 0x074aefe7, 0x8fa8f3fa, + 0xf5e38560, 0xa760fc88, 0x71040551, 0x8db0159a, + 0x22a61a14, 0xfbc68caf, 0x9d6c9004, 0xe9a15c30, + 0x7b1af507, 0xff3a5466, 0x5cd984e0, 0x7ec401ba, + 0x08b195d2, 0x21b70042, 0x4c78a8b6, 0x5abdc257, + 0x848a85d2, 0x916aa39a, 0x4a068dc7, 0x8f6001eb, + 0xdb976975, 0x7a82c00b, 0x84f3a7fd, 0x25113227, + 0x1733e740, 0xa7caa954, 0x951afb03, 0x8bb953fc, + 0xbf3d87d5, 0x21087dde, 0xbde02339, 0x6e8d7f3a, + 0x64d03fd5, 0xbdbbe3b5, 0xb900a058, 0xae3d8886, + 0x69314648, 0x103c8595, 0x313389d9, 0x43fdb183, + 0xf62b152b, 0x0e7ad491, 0xcde6457f, 0xb491e524, + 0x37ef01e4, 0x152404ff, 0x8d2e5104, 0xdf80cc41, + 0xba8cc9a1, 0x6137e3e2, 0x761f7690, 0x9e74a543, + 0x8eda924d, 0x106eda16, 0x2a25f095, 0xbab87e4a, + 0x4ebed965, 0xcefdd142, 0x46b2bf33, 0x129581a8, + 0x30bdd840, 0x13523957, 0x3f7eefe5, 0x866f131b, + 0xb7c8ede1, 0xfed3e6a0, 0x9012d187, 0x553dad3c, + 0x8ce8531c, 0xb2b37c76, 0x8616e40e, 0x15878517, + 0xd3cdbee1, 0x64bb6e3f, 0x02621e58, 0x5a8c4508, + 0xb4d628e5, 0x98782b01, 0xab6378d7, 0xc18746f4, + 0xe94eb24d, 0x69a3c17d, 0xd09c60e1, 0xbbd5d12c, + 0xa3eb73ee, 0x5d202d32, 0xac5a7e25, 0xe428776e, + 0x5bd54f36, 0xbb4209ee, 0x65a02032, 0x243365c8, + 0x4b2a311f, 0xf10646dd, 0x748ba36c, 0xc15c4a08, + 0xf33280ff, 0x2dc7ee89, 0x8837292b, 0x82b96d0e, + 0xd6b24d2c, 0x82028cd7, 0x71c33029, 0xe59d5794, + 0x1927a33d, 0xef0de697, 0x0ea37a87, 0xa01dea8f, + 0x74ed792f, 0xfe71cdf9, 0xc3f8740c, 0xbc51013e, + 0xb23a95f4, 0x314ec964, 0x857ff2a9, 0x20095b84, + 0xf2eb1c0b, 0x7fb93c27, 0x37a0c686, 0x61c33c64, + 0xdb6a0d4a, 0x2e85cd51, 0x7b7701e8, 0x1b3c7e16, + 0xe0a383b8, 0xd8e32a62, 0xa11696ab, 0xc680a360, + 0x76fa369a, 0x6d881899, 0x9a2700fc, 0xde0fd12b, + 0xaa2bdbf9, 0x4afa6594, 0x3133064a, 0xbe9d3a50, + 0x4347b08e, 0xd9c930bc, 0x8472acb4, 0x05c395be, + 0x5b14d602, 0x2b46c26e, 0xa9f4fdf2, 0x993e924a, + 0x808e39f4, 0x0d1f434f, 0xe28ff969, 0x88443a65, + 0x034f5d22, 0x1a142ff4, 0xf4200ff2, 0x01c2f2ab, + 0x7589fe4a, 0x1d17bc63, 0x49218dc5, 0x6aa90dbf, + 0x98e1ec14, 0x9fa62368, 0xd0625457, 0x0c69960f, + 0x947952db, 0x33361207, 0x5f981397, 0x328bdf4a, + 0x8deb0fcf, 0xa5f7f117, 0x2e4ffc18, 0x6ce21500, + 0x4c0c4a6a, 0xd4a66fd2, 0x390c306c, 0x607ad605, + 0xbc587215, 0xf6d8b97b, 0xfdcf559b, 0x5ea7224d, + 0x1854779f, 0xe670a933, 0x4b196714, 0x279da541, + 0xb495f829, 0x866cd554, 0xfcf460c3, 0x90bb440a, + 0xb6f7b383, 0x25f9ce03, 0x29ae54a3, 0x22a43ca8, + 0x987b77a9, 0xf7d2d536, 0x4dfe20b9, 0x0752789d, + 0xb281049e, 0x28eec305, 0x33089e0d, 0x175b4b52, + 0x5fdf4c3e, 0xc43b48a8, 0x18699c1d, 0x2aa1b570, + 0x82666120, 0x7f70b94a, 0xaed37d0d, 0xf3b1b8a0, + 0x7332fafb, 0x0ee9cef8, 0xebef9ccd, 0x651b4978, + 0xe266f4d5, 0x4e2a2bf4, 0x691c313e, 0x94690b66, + 0x94fd3199, 0x5bf98420, 0x9daa8413, 0x245183b8, + 0xa80b653d, 0x301568be, 0xbef07a28, 0xbb4ba293, + 0xff9f8d6c, 0x83176907, 0x699d2ec9, 0x77176048, + 0xa4653568, 0x17741396, 0xf2b5aab1, 0xd9d4f1f9, + 0xe5575096, 0x17a83fd4, 0x6f047711, 0x54f0411e, + 0x9d672a58, 0x546ae427, 0x7277a067, 0x3752e180, + 0x52d25d3f, 0x1e73a1f7, 0x683da477, 0x3fa1ce38, + 0x9c3b6261, 0x1568a423, 0x5a327b48, 0x731a3f9d, + 0x2987df6a, 0x52289e5a, 0x79338183, 0x69c8d017, + 0xc0a3207a, 0xf8a90d3b, 0x6869622d, 0x439faf65, + 0x28be5b52, 0x066d473d, 0x7561347c, 0xb885ff4b, + 0x577c0e3d, 0xfb0ff41f, 0x478bd4e3, 0x313d51d7, + 0xcb694173, 0xed1724fa, 0x64bbfa53, 0x9b27b810, + 0xc6c12019, 0x9a0280a1, 0xef45c1ed, 0xe3ecf3ce, + 0xa21ca237, 0x7a2f2d53, 0x1508a3ea, 0x6bb41fa9, + 0x8b4016da, 0xb91c9b64, 0x3d7be421, 0x35ecb54a, + 0x94dd3b52, 0x51234fed, 0xfc653faf, 0xf81ddca4, + 0xa41ca592, 0x5de55bde, 0x23667674, 0x19671a5a, + 0x1f8145ee, 0x353ae3c6, 0x6e011a6d, 0x50f93a52, + 0xf361b6ae, 0x844b4e2a, 0x9e21ab21, 0x317c8828, + 0x5ee67d13, 0x428b4bf7, 0xdb383a52, 0xcdaaecdf, + 0x197af85f, 0x53fd1816, 0x4357fca9, 0xdffacbd0, + 0xc8c1bca5, 0x8f4a4f2a, 0xe1a7c95e, 0x988bdf87, + 0xc964b82d, 0x58ace38a, 0x0af343c2, 0xf2260a28, + 0x79c884df, 0x44d3194d, 0xeb80d539, 0xe6d4519c, + 0x17fc8176, 0x6072c359, 0xd06fac2e, 0x20d9fddf, + 0xf8923abd, 0x48eb957b, 0xeb039f3b, 0x325b7032, + 0xf384092b, 0x03940ac9, 0xa5eb34e7, 0x5cd0480c, + 0x385270ec, 0x2cc6331b, 0x25dc15de, 0xe6b6b6d9, + 0x70c7c581, 0xa21d09cd, 0xbda580b8, 0xbc028df1, + 0xf831aa89, 0x7b3c07d6, 0x4de89b10, 0xba8968e6, + 0x69f01f38, 0xf02b2c30, 0x7ad867e1, 0xbbf4b70a, + 0xe2c8f388, 0x341f4477, 0x7778befc, 0x5d39b16a, + 0x4db909fd, 0x61d4087c, 0x8f7dff65, 0x3eb26a1d, + 0xbc909a4f, 0x73bb689c, 0xfe9d83b5, 0xc97e6c2d, + 0x154e0f07, 0x6c6ae1c6, 0x12065966, 0x84d7297d, + 0x2f42b976, 0x42ee5c92, 0x838e790c, 0x769f57b1, + 0x5456f8ac, 0xfbea0e3d, 0xf5cfbf82, 0x313c427e, + 0xe7fc478a, 0x909fbb69, 0xb427ae48, 0xae59cd2f, + 0xb42adb37, 0xa3f334f6, 0x6aa1868e, 0x71cc9a8e, + 0xc0839134, 0xea7726a6, 0xdc424d63, 0xf0a22233, + 0x5c6a147d, 0x3ea57359, 0xd96c228c, 0x1e6101cc, + 0x5da64fdd, 0xab7015e2, 0x94367c91, 0x6e3a2be4, + 0xe2a99359, 0xbe3256a7, 0x38314426, 0x681e081e, + 0xeb2a4a9f, 0xf373f054, 0x449de5de, 0x8b2931e5, + 0x62ebd455, 0xd23e681e, 0x77f06d0f, 0xaa42c9b3, + 0xf82046ac, 0x00aef2fc, 0xb5d1c8ff, 0xf725199e, + 0x81baab74, 0x98c5c8ca, 0x13c43ec6, 0x00399be0, + 0x497d5e8c, 0x99b9776b, 0x491039d9, 0x3101efa4, + 0xb05cb290, 0x78f33530, 0x51d58579, 0xd79aae15, + 0x5e194b9c, 0x8b59d65d, 0xe90d08b2, 0x35e060aa, + 0x806fc41e, 0xf4d8053c, 0xd5aaeb30, 0x7dceb5db, + 0xf028f0bf, 0xf83f3e2d, 0x70ff717f, 0xb2097935, + 0xdbd52e41, 0x08bac03e, 0xa46f26a2, 0x73f83bb8, + 0x2c0837ab, 0x3bacfdf5, 0xd5e76578, 0xc2a25576, + 0xa25603eb, 0x9c532f96, 0x8a2424d1, 0xe96c3a01, + 0x308132ea, 0xad280691, 0x560987d1, 0x18d0b431, + 0x943ae1b3, 0x81f276be, 0x9f8dc385, 0x971e5ac7, + 0x78d939f7, 0xbf375116, 0x16165c5e, 0x7da00a01, + 0xb64d1d34, 0x04c9b7a4, 0xd4f01865, 0xb86c7327, + 0x26236daf, 0x7cd6c1aa, 0x5973da89, 0x2153eed7, + 0xaf565d59, 0x106e8c07, 0x22c31257, 0xed0eaac2, + 0x9fd83bd2, 0x125efc59, 0x868c3eb1, 0xe8c7e651, + 0x50901f05, 0x3a9471af, 0xcc4dbd36, 0xe92c83ff, + 0x9f0eade8, 0x5eed5785, 0xbb2a402c, 0x107fb1ba, + 0xdd437725, 0xa85c7831, 0x65bb6263, 0xb236a316, + 0x73059fb4, 0x2374a6e2, 0x2c9a150a, 0xf31325fa, + 0x094e9425, 0x1d04e097, 0x77ec8dda, 0x50f472eb, + 0x6939e58b, 0xdc733aee, 0x61391354, 0xa03050b0, + 0xa88cc609, 0x8137a48c, 0xcfcd6ad0, 0xc90fdbc1, + 0xcbee5317, 0x527f2901, 0x361fd7f3, 0x66e64531, + 0x9ac686d9, 0xa58bdb4f, 0xca82e3bd, 0x10c1947b, + 0xf4e9d1b2, 0x1885268f, 0x602cffa2, 0x799e5146, + 0x84769f28, 0xb9cd1299, 0x891a3759, 0x4ec906b6, + 0xfddc037c, 0x9ce051ce, 0x4d10b62b, 0x093089ba, + 0xd6c21e98, 0xa49dcb58, 0x85a7b837, 0x34be9773, + 0x3f1c498e, 0xd23f2ca1, 0x4a675d6e, 0x3719657d, + 0x2ff1f3b4, 0x3c5edfcf, 0x63eff1d8, 0x09acfbd5, + 0x13e22b87, 0x5261f199, 0x6a352411, 0x6969bf65, + 0xb8c135e9, 0x2d72024b, 0x20d13872, 0xe722f640, + 0x12f874e4, 0x2db31b4b, 0x3ad3b491, 0xd841f695, + 0x5aefd87b, 0xc6e95f4d, 0x540891fb, 0x000d660c, + 0x23edbb8c, 0xe6522558, 0x65d88e35, 0x67faa0b5, + 0x10f4fdf9, 0xfc87f7a6, 0xbe525b5e, 0x27ae652c, + 0x7b0d2161, 0x729e6a99, 0x18cc9d55, 0xf0aea3e9, + 0x0e626e47, 0x46583cfb, 0xd8cce253, 0x67562c4b, + 0x89829b7a, 0x33d7e3fe, 0x57d6fcb5, 0x50970180, + 0x7a63daa8, 0xc1b7e56e, 0x39a00303, 0x4e227d7e, + 0xf9622dec, 0xb3d07f85, 0x4f104315, 0xcaff68cf, + 0x459a7677, 0x3aa229a2, 0xf568e721, 0xcd018f24, + 0x407760dd, 0x00eef9ea, 0x9a0ec730, 0xb54c6317, + 0xa8972df2, 0xb5e77069, 0x1d195ecb, 0x3a65baad, + 0xeed89a3a, 0xa35f2433, 0xead206da, 0x1acc8c7e, + 0xba8d334a, 0xbf5aa074, 0xe8079d73, 0x04c36483, + 0x1add8231, 0xb41e328b, 0xe25b343e, 0xb8e501fd, + 0x9efb0484, 0xf23dd20c, 0x3448b1c4, 0x7ae5cf23, + 0x8dbf5656, 0xa3f80e83, 0x3ef49d96, 0x0cea453a, + 0xd9a36da8, 0x30673183, 0x6f88edba, 0xfcd7f66f, + 0x8b65f9cb, 0xc2e3df02, 0x77f55a79, 0x55d72a8a, + 0x76f0cc47, 0x3945c588, 0x3c9eabbe, 0x03a844d8, + 0x7faf85c7, 0x4a99e62c, 0x715205bf, 0x3418c6c9, + 0xe14ec1cf, 0x2586cf74, 0xa8205398, 0x2b5c19ed, + 0x0cd804a4, 0xbad1b2ee, 0x3fcc48f8, 0xb91e3e27, + 0x61faf3f2, 0xd9f1dbf1, 0xe67fb084, 0x70eeea0f, + 0x48640cb9, 0x2b2a1819, 0xa0bdf40c, 0x1e4e138b, + 0x726b3456, 0x5b575876, 0x385b2c7f, 0x119399ac, + 0x92b94568, 0x830d128e, 0x03730036, 0x9b16626f, + 0x3b1f0cc2, 0x04522fd3, 0xefe3799e, 0x757425ef, + 0x41ba50f2, 0xf78c72d8, 0x82c24b2d, 0x9e4edc85, + 0x4e0f8492, 0x632c8df1, 0xeb04c7a0, 0x3109643e, + 0xa247d84a, 0x97de8486, 0xba275339, 0x2a71e81f, + 0xe597d51c, 0x14953010, 0x202859e7, 0xb6d22732, + 0xfe767835, 0xa3123fe9, 0x7bb93b69, 0xfc36be6a, + 0x5c12c3da, 0x766f13c8, 0xa8eeacaa, 0xd896a751, + 0x4d3bbeaf, 0x433119bd, 0xa4c9dd1f, 0x74765a8c, + 0x408daa3e, 0x6a29b045, 0x36f05585, 0x3f20654b, + 0xc5cac73e, 0xd8dce56f, 0x1b7b0538, 0xb9323d5c, + 0x68721bc2, 0x423eb318, 0x793ea010, 0x2e8ddb34, + 0x8c849ffc, 0x083469cf, 0x9b63354b, 0x5fea6204, + 0x548bd058, 0xa88dafab, 0x4aa25a26, 0xa0a3bb87, + 0xf1151f67, 0x2ef2ee48, 0x31e8e536, 0xca03cb97, + 0x359f3aca, 0xcf187893, 0x0f376665, 0xcf0410c1, + 0x25ede881, 0x20e37c72, 0xea988167, 0x77e1a294, + 0x0f1581bf, 0xba27355b, 0xa643b909, 0xc5116f7a, + 0xbfb230df, 0xfe475308, 0x3b94db9a, 0x9f5484fe, + 0xf4a3952d, 0x32164194, 0xe9e55961, 0xa31292fa, + 0x0607b801, 0x664abe7e, 0x18cfaa9c, 0x2a31ee99, + 0xe6a9215b, 0x8551f3f1, 0x526ff97b, 0x0960fcfe, + 0x081c76e4, 0x630d44ea, 0x02d59cf4, 0x00d70687, + 0xa01348c4, 0x9c363fd8, 0xf52f2923, 0x3b978878, + 0x32993df3, 0xb483f634, 0xbe3b793b, 0x318ad606, + 0xcba532b3, 0xbb3ce420, 0x2ddce772, 0x6bd68cb7, + 0x827b3b37, 0x59fc0819, 0x27821286, 0x15b18414, + 0xc20b4eba, 0x949f522a, 0x09917dbe, 0x55b13e68, + 0x1addbe6e, 0x02c996c8, 0xf9e7ac62, 0x542b4512, + 0x079b0bec, 0xfc6a34ae, 0xf36c2179, 0x77188093, + 0x35b667fb, 0x500be259, 0x4aaa482f, 0xcc6d62c6, + 0xd4821506, 0x5a3a4a32, 0xb7b83c98, 0xed9202e2, + 0xbbd03d52, 0x7fc10dc7, 0x685d7ce7, 0x2fe580b7, + 0xa710a5b3, 0xd19955d6, 0xacc44881, 0xab4f239e, + 0x75bf9e8b, 0x0501d606, 0x4e7bc981, 0x944846e7, + 0x2360ea73, 0x7132a075, 0x30647ee1, 0x9b21da9e, + 0x3173492a, 0x0a287e96, 0xaea5814e, 0x6fb9ede3, + 0xf814d671, 0x85936648, 0xa3452e2b, 0x880b329a, + 0x55594d06, 0x9f361752, 0xbdfb7ee4, 0xd8433132, + 0x4c4a2c2a, 0x5656a72d, 0xe6db6e83, 0xd2189605, + 0xe5fbeb91, 0xf0322e53, 0x6bcc58b1, 0xc49f0f48, + 0x9b28ee72, 0xa8f58028, 0x6636c0ba, 0xa0307c12, + 0x6d791ecf, 0x04dea8b5, 0xb4e18e27, 0x16700624, + 0xf96d3606, 0xc75bac1f, 0x527ed907, 0xd127a44c, + 0x52d54e09, 0x66594cb1, 0x03c55a97, 0xd25743f2, + 0xa9c716de, 0xef8a56e0, 0x99bc103c, 0x53e8f42b, + 0xac1ef337, 0x5abe3c67, 0x57d3e5d6, 0xc17ff9eb, + 0xaf205e42, 0x8e733182, 0x275b53c2, 0x7c8c80bf, + 0xe6428065, 0xf896878e, 0xda058744, 0x10fa6ec6, + 0xfbec08a0, 0xb2ac39de, 0x7624585b, 0x1de913c5, + 0x49dac70c, 0xaac77cfe, 0xa11ea00a, 0xbe70550f, + 0xdf207b41, 0xf65d944e, 0x5013c2f8, 0x5614774b, + 0x2cee2f83, 0xf404245b, 0x15b2669d, 0x90c5f2ca, + 0x908cdd49, 0x3319008c, 0xb1a2f008, 0x9697e9db, + 0x045e19db, 0x4b3a5cc6, 0x2ac2f153, 0xf211a10f, + 0x6c9ced3a, 0x3ee4c758, 0xd817c408, 0x4f5a9126, + 0xca18de83, 0xd88e041e, 0x016e7eaa, 0x5b780a5e, + 0x5f997043, 0x171cf478, 0xb58f4781, 0x5baa936e, + 0x2134eb3f, 0x41c97a25, 0x361a417f, 0x1161f55f, + 0x070f7913, 0xaeac2ec1, 0x816520df, 0x1db225e7, + 0xdfdd68d1, 0xf19a404c, 0x9caafd95, 0x182b8bf2, + 0xa7c927e2, 0x26effee3, 0x06e34c19, 0x34eb7c71, + 0xa707f1b7, 0xa86bb217, 0xf65223fa, 0x1150f15b, + 0x8638fd58, 0x833e9b0c, 0x2be67143, 0x85244ef4, + 0x264739f0, 0x06432cff, 0xa2ed6105, 0x5ac4be62, + 0x981a255c, 0x97a5bb3e, 0xcec77ef3, 0x66bf320b, + 0x75caf7ce, 0x85648346, 0xb3ea007a, 0x3c6f1e18, + 0x5815f504, 0xf7b671da, 0x4442b943, 0xdf202a71, + 0xec0d4356, 0x50d08f00, 0x911beb22, 0x33d00671, + 0x71d46490, 0xf6c53dfc, 0x5525a3b6, 0x6a996168, + 0x0ab2ad1f, 0xe8fbdfe3, 0x90fc4f22, 0xecfdc89c, + 0x34eb1eba, 0x5f06cd50, 0x6afdb438, 0x7a0b8f1c, + 0x862ecfed, 0x72802e59, 0xb7c97758, 0x90da65b4, + 0xe1e3155a, 0x97a22dd4, 0xcbfdc0b8, 0x0b6a8ced, + 0x7a4de14e, 0xee0b8c6e, 0x8cac47ac, 0x66557264, + 0x87ebaa6c, 0x85cf1694, 0xbbd2b291, 0x3f65d911, + 0xe12d4cdf, 0x1a63229a, 0xbff41172, 0xb5dad0b0, + 0x573cefd7, 0x6f44f1a7, 0x9e7620c3, 0xf4c6ec29, + 0xdc17294b, 0x57b9470c, 0x58463dbe, 0xedfcf1f9, + 0xf1df4662, 0xc31796ed, 0xbe42d9d6, 0x8ca98426, + 0x67e4de96, 0x31f8bc96, 0x88009a46, 0x500c111a, + 0x968b209b, 0x0a6f0a85, 0x150b97ad, 0x90ac8eb3, + 0x69e3d43e, 0x76002a1c, 0xc25f709d, 0xe09d0b76, + 0x995a3f6d, 0xa9f5f35f, 0x82e7b678, 0x8f36fd7f, + 0xc8c6303a, 0xac375598, 0x2e4d374f, 0x96157f0f, + 0xb1fbb183, 0xc972be35, 0xf1f2184b, 0xf7dd9b10, + 0x8f96f16a, 0x4d4e5bac, 0x4c98517d, 0x230a9372, + 0x77431cf6, 0xe8f8a3f4, 0xdffce373, 0x184e6b01, + 0x4f65855a, 0xf80c22b9, 0x62cf5f4f, 0x18272cf1, + 0xb2c6e98c, 0xe72cfb69, 0xce52a3f2, 0x5ec853ce, + 0xc5eb3d48, 0xfd3236fc, 0xde2d53aa, 0x5a51ce3b, + 0x29caa98e, 0x5acff2e9, 0x2471d01f, 0x1b0eba32, + 0xef026ea5, 0x9b5c71e4, 0x11163cea, 0x1886b2b7, + 0x46064ce2, 0x50573fa2, 0x2b0f1a6e, 0xb0a5c4e4, + 0x80a0dfad, 0x99df6a98, 0xbc094030, 0xe2d1914e, + 0x0dbc1930, 0xe1dc8888, 0xe05e9171, 0x42ea777a, + 0x46b19499, 0xd6190530, 0x348236ec, 0xbe0b93b8, + 0x334fca62, 0xa31fedc5, 0xb17e84bb, 0x458f524c, + 0xe236367c, 0xad6ddffc, 0x6fa3b705, 0x2457dd4f, + 0xacb206bf, 0x33c6d7f0, 0x22a232ca, 0x372bb1c4, + 0x92057e84, 0x14b02358, 0x90d3dea5, 0x941fca1e, + 0x39668874, 0x29f8ccf1, 0x7ee0a47b, 0x0d025525, + 0x3f1c0f4f, 0xf61124c5, 0xd3ff45f1, 0xf5115ddf, + 0x7a32b730, 0x66d640d3, 0xceb4cd89, 0x294be9e9, + 0x628d7eb6, 0x573093fd, 0x5e5fd116, 0x654c4313, + 0x4ac06396, 0x679d8e6c, 0xf8385637, 0x882ee0c1, + 0x82c95bc6, 0xb5e5699f, 0x1927b099, 0x2d024059, + 0x511aa76d, 0xf7a652c4, 0xcc41d63f, 0x36957ef1, + 0x326f88dc, 0x45eceb0a, 0xbfeb3cd0, 0xf4dae814, + 0x95630d1f, 0xdaf300d3, 0xfdae1bb0, 0xa318210d, + 0xdd69c157, 0xacd4e4fd, 0x7ea7a724, 0xe8db397d, + 0xb8dfa5ca, 0x766cb107, 0x0e91d417, 0x39d28748, + 0x4453d103, 0x894693b6, 0xc2f56cd3, 0x2d3b6cfb, + 0x96820fdc, 0x53da38e5, 0x42af9dfc, 0x3fe10dd4, + 0x1a97a9d1, 0x40bccd1a, 0x8f106193, 0x9d70b3e9, + 0x71fdd31d, 0x11dc84cb, 0x01b2f90a, 0x712a8ddc, + 0xc295091e, 0x42a6a761, 0x87ae3ee2, 0x426e84ee, + 0xbaaedcbb, 0xf96a59a0, 0x815c5372, 0x2e0351f3, + 0x09544cef, 0x25a9027a, 0x8b8341ab, 0x97976151, + 0x7c328e31, 0x4e88f933, 0xd31e6de3, 0x21141597, + 0x2849aec8, 0xecaecc4e, 0x57154cb6, 0x725d9f44, + 0xba56aaee, 0x7d619ae7, 0x0c09fac9, 0xd81236bd, + 0x667fc710, 0x033ae5f9, 0x50f745fc, 0x85e34787, + 0x538cda7f, 0xd503dd16, 0x04da3c04, 0xeb3a8154, + 0x62d9764c, 0x6b086500, 0x04a33f27, 0xfabaabe0, + 0xdc280910, 0xba26391c, 0x1f31dc24, 0x2ed869cc, + 0x14978055, 0xd6e9f23d, 0x79ba1932, 0xb8263187, + 0x3c287053, 0x5813171d, 0xa20e5805, 0x1bf39bb5, + 0x9c9caf7c, 0x8f0763a0, 0x88fc2538, 0x8ed5405e, + 0x53fb37b7, 0x4e5e0f65, 0x59c1cb79, 0xf03df570, + 0xccb6a599, 0x5ea4bf58, 0x5ea2e12a, 0x95bbc637, + 0x08133508, 0x8b7194a5, 0x033182a4, 0xe5ad3e22, + 0x12126d46, 0x335aded5, 0x4ee628dd, 0x090fbab1, + 0x2e67e3ea, 0xa132d8fc, 0x1bb6ed44, 0xb2705a58, + 0x2b7e751c, 0xe15ffcae, 0x62627cfe, 0xd5a498f8, + 0x143c2b46, 0x844457ac, 0x7d4000b1, 0x2ecacfb3, + 0x143c472c, 0xa0420c4f, 0x47833e22, 0x9f74eb78, + 0x79dc5cc3, 0xd5e1b45d, 0x3bb00f31, 0x702739ca, + 0x0a4c6c8c, 0xd627e632, 0x289c2b69, 0x1633d18d, + 0x61d761af, 0x59c4182a, 0x4a9b111a, 0x4a52c8e9, + 0x4708ad90, 0xdbd03373, 0x835b8a04, 0x05db663d, + 0xe6ca7f1f, 0x2a08b5ac, 0x28583a42, 0x9ae3e9b3, + 0x150b7d3f, 0x1842347b, 0x709a1f93, 0xaeda1fbf, + 0x3bce401f, 0x8a1baa9f, 0x01290c32, 0x20647880, + 0x6052019c, 0x7d186543, 0xcf304e84, 0xd3f7318e, + 0x116d366b, 0xfaa3565e, 0x2e00cae6, 0x8438ca03, + 0xf8522fa0, 0xb3357dcb, 0xf45193f8, 0x04508fe6, + 0xc3a60001, 0x547aed43, 0xbe31030a, 0x357a2385, + 0x4a77958a, 0x1d133ce4, 0xdf24e601, 0xba0db6a0, + 0x702b799e, 0x643bcb34, 0xe33af8e0, 0xb90fbae5, + 0x65571140, 0xd4bea20b, 0xe58b7cb2, 0xcd5e7c3d, + 0x7153f7d7, 0x747ed174, 0xe6471dda, 0xd9e46017, + 0x62de25c5, 0xece16d33, 0x36f5a1a0, 0xd82c503b, + 0x9d472d1e, 0x34f3d3e6, 0x3e0fe08e, 0xe9a5f240, + 0xd528ea27, 0xf6c1e417, 0x0ba5ea4e, 0xf7474725, + 0x113c0c1f, 0xea4e468b, 0x4450efb9, 0xf6fe6ad6, + 0xe399031d, 0xa3fc24f3, 0x9f1950a1, 0xc08196ff, + 0x116ca5ec, 0x4786af82, 0x01e032de, 0xd04dc3f6, + 0x0c9b90d0, 0x1ad17953, 0x7627ac6f, 0x59f5574c, + 0xe1bc651c, 0xbca29c8b, 0x01450503, 0x8fd48513, + 0x341bcbe0, 0x4b0126a8, 0x0a87cc95, 0xb8824433, + 0x8578e83d, 0xba5acc14, 0xc80b9b2c, 0xb6e97cd9, + 0xb649f23f, 0x3729b1f2, 0x38f54386, 0xf878b7a8, + 0x33d407af, 0x741f5b8e, 0x075d7c35, 0xe1473094, + 0xb3def3dc, 0x554c46ec, 0xed6c4bad, 0x21ee1788, + 0xd99f10f0, 0x9bea4e3a, 0xc1aa7284, 0xf4a7f3d4, + 0xecaed392, 0x3a50e2b1, 0xd341d311, 0x95f7af1f, + 0xa8a4bc2d, 0x3c0a17d4, 0x647a847f, 0x1b85d21f, + 0xc742629c, 0xb454877e, 0xc3714bdf, 0x1b4af075, + 0x100dce7b, 0x4eea8191, 0x5f5dcfe1, 0xfb08b083, + 0xdc3bb74a, 0x7904387d, 0x17120a99, 0xe18cb06c, + 0x6f62f650, 0x79502b10, 0x2353b516, 0xc3f55109, + 0x7825ab36, 0xe7cae711, 0xd47c9b20, 0x18c4066a, + 0x1ecb5c39, 0x89388d3d, 0xcd5e1e7e, 0x22e09d54, + 0x23573c6f, 0x531db85b, 0x6ccee43e, 0xc15cf1b5, + 0x7d452fb4, 0x83fe1174, 0x47b32970, 0xcd9540bd, + 0xa19e4d96, 0x2bc5a44d, 0x7bac4d43, 0x65be88f1, + 0x1a3a73a2, 0xa4333b7c, 0x39875df5, 0x04b1055c, + 0x167ef24c, 0x88a2dc6c, 0x7ccae5d1, 0x8780c88c, + 0x157c40d6, 0x5abb3003, 0xd3fcf545, 0x984b3434, + 0xed21e58a, 0x3ab1a5ff, 0x743770ba, 0x60f64534, + 0xbee7070e, 0x7d890ff5, 0xda4e1665, 0x670e67bb, + 0x63e7ec85, 0xf6e313c1, 0x79cf3b00, 0x7a92a4db, + 0x9da0dc95, 0x2aa2faaf, 0x6dbf37a8, 0x128faf9e, + 0x73fc7ae1, 0x3c17ba6f, 0xa39b42b4, 0xc187bdfe, + 0x3f107194, 0xaeb79cef, 0x3c00fd96, 0x369ee475, + 0x703304ee, 0xd9e48e46, 0xf15adda4, 0x82fcbc7b, + 0xeef851dc, 0xd880a41a, 0xcbfc0ee7, 0x02c4fe03, + 0x8c34a979, 0xa1ce5216, 0x60243594, 0x9bb078c6, + 0x5fb87abc, 0xda3a8b9a, 0x7fd4b726, 0xf5cac6b3, + 0xbe65fd2f, 0xeb76cb4b, 0x5aacdd07, 0x528d2ea4, + 0x773c014d, 0x3b2bc521, 0x729011fd, 0x047d28a3, + 0x7cee0602, 0xcbb6d384, 0x7c75e483, 0x88a2d2f3, + 0x62fbbc54, 0x05df5ca3, 0x9f57ae1f, 0x9374ac97, + 0x9ac7a900, 0x445c8ee8, 0x609ea023, 0xf33be914, + 0xbbdfb7f5, 0x23713816, 0x600ca7d9, 0xd74c4b5c, + 0xeeb82a27, 0x656ce577, 0x50ac829a, 0xed1a49fc, + 0x8ab39272, 0xc5b82955, 0x740ff715, 0xa1692b0a, + 0x9dd67528, 0x0d1f0071, 0x84a5464c, 0x955dccad, + 0x96ca68a9, 0xc69f2148, 0xcc2fda23, 0xfca7f8fa, + 0xa33f03d3, 0x48ca8480, 0x7e32a71b, 0x8f91a2c7, + 0xa976a470, 0x8c5394a8, 0x764b0ac5, 0x8884f106, + 0xbe5c8f61, 0xf07c911d, 0xe8c57ad7, 0x2e613171, + 0x4a6ddbec, 0xdaa4761d, 0x82aa91e1, 0xd9725405, + 0x92f3f354, 0x0bec2278, 0x66608c01, 0xa04099c5, + 0x0f1825d1, 0x9cefb5e4, 0xd8ed966b, 0xf83e386c, + 0x9bbd5026, 0xc3c0b291, 0x2f69486f, 0x85624022, + 0x45b84bbd, 0xa1f91d90, 0x1e1efa94, 0x8a75d193, + 0x9507b716, 0xa96976f9, 0x8359a6ea, 0x72aeeb28, + 0xb1d4b727, 0xaea1c2b1, 0x61d3cbbe, 0x65ae2218, + 0x7f724420, 0x3cac4251, 0x93ee0c1c, 0x64010c67, + 0xab88919a, 0x0c10d388, 0xdf3daa06, 0x4a4b0997, + 0x465a8813, 0x3f6c33db, 0xcbcf6a48, 0x4e33c2d6, + 0xc79b5905, 0x6e3793aa, 0xe9ebce19, 0x5a849a33, + 0x0490f96c, 0x808af010, 0xe9f617ca, 0xcc6d4602, + 0x3d877302, 0x61a4129e, 0x432e46ab, 0xfdb64bc8, + 0x4f317ebe, 0xf6848bbc, 0xff3bae1a, 0x9d70fb8a, + 0x66df6ac7, 0x8a7f2aea, 0x59878b1e, 0x988a871d, + 0x02d349c9, 0xec0d72c6, 0x73291262, 0xd955eded, + 0xb02fff43, 0xaa2d723f, 0xaf73b857, 0xd074e773, + 0xe696557c, 0xf6f6d303, 0x9ba2c0de, 0x90165398, + 0xd382bc24, 0x4f902051, 0xcb761448, 0x73aa9756, + 0x554ed1f5, 0x6c28d933, 0xa3ed9268, 0xbb09317d, + 0xd001cee2, 0xd7ffe0cc, 0x59e04eb1, 0xd78e1b6b, + 0x66e4392e, 0xa68f9f6f, 0x27f971d7, 0x211ce38f, + 0x28f787fb, 0xbdc7b9dd, 0x22ad3abc, 0x7b7079db, + 0x7b4298fc, 0x5ce79d65, 0xa7870345, 0x295f88ce, + 0xfdce14ad, 0x122f7075, 0xaf27d4f6, 0xda2b1924, + 0x9f5dfb98, 0x64405332, 0x0dd7e2bf, 0x31e7c1a0, + 0x67959231, 0x2f0c1197, 0xe3846345, 0x55fc2aec, + 0xd9f6e7a1, 0x4b68f5b0, 0x22c527d5, 0x3a10a5dc, + 0x8f088ab2, 0xb8aeaa4a, 0x5d92c52d, 0xaf4d81b9, + 0x3c550f85, 0x4b9c6eb0, 0xb25ee7f7, 0x345e3dbd, + 0x721841af, 0xa0195140, 0xd3281d4c, 0x77f8b657, + 0x6c2248da, 0xd29d40cf, 0x1b1c7201, 0x37d89a61, + 0x90796492, 0xf15f6138, 0x38f4682a, 0xa1b6a5bc, + 0x2b3ec6c7, 0x9f799827, 0x668f51f5, 0x960ae646, + 0x8edac805, 0x1fe326bd, 0x4fdb8553, 0x240b3a41, + 0xd57a8343, 0xaa77d835, 0xe773d2cf, 0xcd4c9311, + 0x8f83e2aa, 0x41503f62, 0xd16e6afc, 0x72a8ee46, + 0x85a50ea6, 0xb188874d, 0xa58fe21d, 0x984b3ad5, + 0x676872bd, 0xc9785d88, 0x93b129e0, 0xf6dd66aa, + 0x5f46d7db, 0x915bbbe4, 0xd5bb7a68, 0xdcffb9e5, + 0xb2822f2e, 0x78337743, 0x122f446a, 0xf28389f7, + 0x5c55061d, 0x9a965f10, 0xd1cdbf80, 0xbb1afeaf, + 0xf9e58885, 0xeb0c6538, 0xe766d40b, 0x9a052186, + 0xe468feca, 0xad66cb11, 0xc37252bf, 0xb6a22475, + 0x56c3aac4, 0xb6e832e0, 0x5093fc20, 0xed827f33, + 0x4f7d3149, 0xbf7637e8, 0x01065f64, 0xde875144, + 0x7605fcaf, 0x6174a7e2, 0xeee5b92e, 0x942a7b17, + 0xd6092543, 0xc9d42372, 0x2bf59900, 0x0b8360a1, + 0x1157cedc, 0x5517c6ca, 0x06cf6c10, 0x5520ef08, + 0x8fe1d847, 0x123bc0dc, 0xfd7d101d, 0x46f7c7bd, + 0x69ebfab8, 0x02c05e70, 0x497b884c, 0x25038d06, + 0x2f6488cb, 0x184f0cbf, 0x568580fe, 0x0addbcee, + 0xc9836be8, 0x33d25f94, 0xfaf57137, 0xc1329b74, + 0x2398f70a, 0x1af8d6b5, 0xc3b0b215, 0x4096b7cd, + 0x6ff7eae3, 0xa7fbe0f9, 0x9063016f, 0x25b13428, + 0xc14fc8b4, 0xe9162886, 0xd8a8af8b, 0xa3e82eb1, + 0x922b7a7d, 0x2fbfbff7, 0xce7e5134, 0xa7d2592b, + 0xa31d7b3b, 0xe35b479a, 0xddaf042f, 0x84a4e9a6, + 0xccd9127f, 0xb4569f69, 0x6c0c2be2, 0x07b85dbe, + 0x940ec892, 0x01d53d55, 0x33c7c773, 0xc741a6ee, + 0x1ad4b26e, 0x84de8eeb, 0xc006e3ab, 0xebe7d0c1, + 0x11b2ae46, 0xff569ef6, 0x023681c3, 0xff1786ca, + 0xf34cf604, 0x381e282b, 0x882efa21, 0x9b8e1fb9, + 0xa7c1a1a6, 0xbba7833b, 0xa041dae2, 0x2bd40bc8, + 0x77836a98, 0x92b2b00c, 0xec94bbbf, 0x1eab3570, + 0xd6cdb94f, 0x1a50e7be, 0x9f1f8065, 0x0c3d0124, + 0xf58db470, 0xa9e2fd15, 0x534c9ae7, 0x48968a0f, + 0x83f3c2fd, 0x4b3b1bd2, 0x5bde47b6, 0x86a06b48, + 0x11934039, 0xbaa6067d, 0x7d75a2e2, 0x7da7e096, + 0xb5b171c1, 0x0bf53cf9, 0x9cdec8de, 0x9551acdb, + 0xc530438b, 0xbd671e7a, 0x1280842d, 0xf5d88af9, + 0x1245df3e, 0xdf6b048b, 0x53edbcfe, 0x40ff2ed1, + 0xe2cb8d61, 0x309e7e99, 0x1b6be416, 0xde3f6dd6, + 0x3e13356f, 0x0fd0f8e5, 0x4906c31d, 0xbaf5a269, + 0xa868c874, 0x73fcd3d7, 0xd7fde17f, 0x9ae13f32, + 0x862f9c74, 0x30b5d589, 0xa62971f2, 0xacd23b52, + 0x1fadf615, 0xe969e6a1, 0x58925d95, 0x26d9110b, + 0x94282383, 0xdb7e87b4, 0x61f2dd84, 0x1ace18fa, + 0x6e50e5c2, 0x8570c4b3, 0x4bb8132d, 0xbb1ec149, + 0x434eeea0, 0x9010fbdf, 0x513baff4, 0xe18c2240, + 0x6ad59662, 0xec453e06, 0x5abef1fb, 0x8bea5393, + 0xa65537d3, 0xb418d400, 0x1304cf30, 0x372e758a, + 0x9f02eb97, 0xd80c99ca, 0xb02edd9f, 0x73d9f559, + 0x91260500, 0x16ec2d68, 0xf4950f12, 0x41bdb11a, + 0x1f7f9a2f, 0xd1ccc1bf, 0xb6e38114, 0xada41bc8, + 0xc6c877ca, 0x3d84ac90, 0xf2ff6f97, 0xf4db55b8, + 0xb3dd1ca9, 0x0f95e403, 0xaf7aa610, 0xb778cbea, + 0xd38c3729, 0x19445e31, 0x373971dc, 0xfd9dbdda, + 0x4ee0fc8c, 0xa2831d78, 0x023379b4, 0xff7b5aaa, + 0xd2fe9b62, 0x5ac6d8ab, 0x68bdd29c, 0xc5126f8b, + 0x739e9f16, 0xe7b9e7b1, 0x26b4f5e7, 0xdd8d7179, + 0xbfd97c58, 0x5dd2c6e7, 0x7b161782, 0xf04b2855, + 0x3c644c2b, 0x24f6d67b, 0x9774e6ef, 0x15e138f8, + 0x27095205, 0x72f60dab, 0xdf419dc3, 0xd0e8547f, + 0x9e550ef9, 0xebf59032, 0x7aac934e, 0x4cf229ae, + 0x68d40429, 0x52da6dce, 0x7633c388, 0x5991a40c, + 0x9094a217, 0xceb564bb, 0xa470565b, 0x0c25cf95, + 0xfbd5a738, 0x788154db, 0xdb99181c, 0x1f4b6c88, + 0x595967d9, 0x15593c46, 0xe697197e, 0xdd423fa0, + 0x8fa9750b, 0xbf1a16b5, 0xcbc93675, 0x2a160d35, + 0x957aabf4, 0xc5d0f510, 0x56bf0671, 0xb369aaad, + 0x2182b995, 0x0724c93a, 0xeacea072, 0x5c9c09bc, + 0x9923e4d2, 0x09c0446d, 0xe84d7071, 0xaba523fe, + 0x61b8db6f, 0x59de0329, 0x4fa29e20, 0x461a7cf5, + 0xbc01f300, 0x76ed4e61, 0xf8eab270, 0x990eaed5, + 0xdcc93fd7, 0x1ea665ae, 0xb19decc7, 0xb72c1b66, + 0x6688b343, 0xe006019f, 0x099544a0, 0xdd3a530c, + 0xf5e83f0d, 0x2c60d0c8, 0x88e01e7e, 0x9a19b32d, + 0xc0ad1896, 0xc5fea7ce, 0x94017684, 0x2ac1ea84, + 0xf51c37e3, 0x1c715b66, 0x69e4bc62, 0x71283993, + 0x1c2f4e97, 0xf6d5e0e5, 0x0f05e60d, 0x4ec27480, + 0x8b55c122, 0x3a188f9f, 0x74e3ade3, 0x23acfccb, + 0x6b91d884, 0x21764b24, 0x1d985f2b, 0xf7250a48, + 0x39e3a568, 0x18e90d0c, 0x2fb81478, 0x4a0b413c, + 0x88b31e83, 0x11aebf51, 0xe2306214, 0x7c6a6ba3, + 0xce73828d, 0x4254fd56, 0xc9f8df24, 0x676e1294, + 0xb885f8c8, 0x88abb4b7, 0xb7396e2d, 0x1a1a390a, + 0xc51220e5, 0x8a7cb695, 0x36086502, 0x1d82cc88, + 0x1aab1b06, 0x1f134f4b, 0x77a734cf, 0xab22564f, + 0x4eb87d47, 0x50e8dfa9, 0x11df8078, 0x18fd070d, + 0xbef37f01, 0xa15afe65, 0xa52471d1, 0xa63ee5d3, + 0x5be1cfb6, 0x23671d28, 0x117ad254, 0xd1b01766, + 0xe30b8a65, 0x1cdddf83, 0x1bd7ebeb, 0xece2f6dd, + 0x481cf4d1, 0x177f425e, 0x4a4f01bd, 0x2e010338, + 0x61d0295b, 0x0416841e, 0xd5c746af, 0x52b4d0d5, + 0x189b878b, 0xd308f655, 0x6897377f, 0xe2e15941, + 0x5399bcec, 0x3fd3f5ff, 0xfdbf1836, 0x17806622, + 0xc5d31e25, 0x3a1f55e3, 0x8f813296, 0x071b6bf7, + 0x47a0808c, 0x365b7b8b, 0xa548aced, 0x21cbb8f0, + 0xa18088d4, 0xfeb793e0, 0x01b69a2e, 0xecde0ac9, + 0x0b433707, 0xe0b418d9, 0x134b8b72, 0x6a540fee, + 0x126dab96, 0x21e11b8d, 0x67322574, 0x4594e729, + 0x2963313b, 0x354596e3, 0x3b416341, 0x5df82051, + 0x7865d8d2, 0x6c6649cd, 0x6761989c, 0x1c252b8c, + 0x76220e24, 0x7db9b968, 0x60a889d6, 0xc9726070, + 0xe289905e, 0x64445cb4, 0x7c37b688, 0x166b9f06, + 0x431700fb, 0x48794bcd, 0xc9300724, 0x6b2f4aed, + 0x1c98b16b, 0x19f61c61, 0xbd230ae7, 0x2e065918, + 0xde69ad3b, 0xcff99480, 0xb2f9bae2, 0x801207a0, + 0x030e5ae2, 0x623d9b3d, 0xc2156695, 0x2c0d53fa, + 0x94fd0bd1, 0xf4cf45e9, 0x42597ea0, 0x59a49589, + 0x87d27d6a, 0x8a66488f, 0xcc07048e, 0x06d6a76f, + 0x89481e0f, 0x25dcdc68, 0x3e3c268d, 0x967d1b3b, + 0x1e17a8ec, 0x3c32080d, 0xeff3600a, 0x7f0e224a, + 0xad850f59, 0x0f2a4133, 0xaf1808c6, 0x1c6eb8a2, + 0xfba7572b, 0xbb8ec03d, 0x4256627c, 0xf089ae59, + 0xb9fd6230, 0xd03648a8, 0xb0c63f78, 0x54bc7913, + 0x0bbc2bac, 0x0a94e32f, 0xdfec6161, 0x887f4dae, + 0x465dd2a5, 0x0fa8dc1e, 0x4d1984da, 0x3356f309, + 0x15f423e2, 0xc2a07e5a, 0xc19265bd, 0xf3c2ae0b, + 0x8d86ef00, 0x81ce94af, 0x323a982f, 0xea38e1b8, + 0xa36a3e8f, 0x5ef1518b, 0x5692a84f, 0xdd66efce, + 0xb8a4c5f5, 0x0689776a, 0x295d73a5, 0x0ae6785d, + 0x62f1ab65, 0xa9181f50, 0x3a4c6f3d, 0x0b9ab84e, + 0x83a2a195, 0x919553d3, 0x4e7d43c6, 0xf0bf5d18, + 0xce876130, 0x773caba7, 0x02f71c2f, 0x9b8eb6d8, + 0x30c5db13, 0x2fda78a4, 0x9a358df7, 0xac3d9c3a, + 0xf2a25ef7, 0xa7e710d0, 0x0986ac72, 0x98d73ef6, + 0x4d1ac3ca, 0x7579abf6, 0xfda5f3db, 0xc040d8e1, + 0x8a1cf285, 0xfc9960b7, 0x9c7dcd59, 0xdc78ff0d, + 0xc5876405, 0xc2fb9c7f, 0xa6e9624f, 0xaca0f295, + 0xb0eeccb0, 0x8f61b056, 0x1398a934, 0x52868c9c, + 0x824d9994, 0x6cb08beb, 0x275136fd, 0x64978a31, + 0xa879c151, 0x7c3ca445, 0xc6a16fae, 0xc18cdbfb, + 0x2806bef0, 0xcaf9766c, 0xbac35157, 0x4a68238e, + 0xd7a61559, 0xcdda9b45, 0x1eeaaeb7, 0xe9a7d37a, + 0x37d676a3, 0xed994073, 0x085c6c91, 0x6f488598, + 0x7f1a6a56, 0x574c8915, 0x9cff6c11, 0x52647cee, + 0x67856ea2, 0xcc3a658a, 0x1979f070, 0x8201cf56, + 0x40556f2c, 0x7848710b, 0x471e8559, 0xee1d6373, + 0x3cd276db, 0x15760135, 0x8c2292b3, 0x087b5d32, + 0x5c96ab0c, 0xe3b4d850, 0x3048501f, 0xa39df353, + 0xd6a690cf, 0x56a9f6af, 0xa410ca91, 0xadfc674c, + 0x91f2f212, 0xe565a922, 0x2ad441a0, 0x70f2dbbe, + 0xb7ef1856, 0x5b39b7ce, 0x061dac3a, 0x95a60250, + 0x032669f8, 0x75c7eca8, 0x918b90b7, 0x8afa15ba, + 0x5f02eb32, 0xec4b53ca, 0x2ad61e09, 0xe663b16f, + 0x453bbe0f, 0x4b52ad67, 0x704e835d, 0xb110aa6b, + 0x6f80f344, 0xbd33126a, 0x3d730676, 0x61274d4b, + 0x366f4ab7, 0x76b4fd92, 0x0cab4b03, 0xf08e91ae, + 0x9a805c87, 0x9693d06d, 0x541332c7, 0xace1b771, + 0xe450f25f, 0x08f15fde, 0x1d46af92, 0x38f1b34b, + 0xdda5f95b, 0x42867f2a, 0x351ba162, 0x649dce1c, + 0x647e0a6c, 0xe096fbc7, 0x1a4f214b, 0x052a167e, + 0xa23c0c71, 0xef96e22d, 0x73adb4de, 0xb88d43e8, + 0x37aed369, 0x51be874b, 0x0131999e, 0x6c4c3595, + 0xd192977e, 0x6175c3fd, 0x01f6ca19, 0xa9575222, + 0xd5d7f2d2, 0x0da0e86c, 0xaf2ca907, 0x0f912ecc, + 0x11e3bb36, 0x807bcd4b, 0x16386d78, 0xe8eff9de, + 0x39b84743, 0x198b7d0d, 0xa1cb0889, 0xbcf19a93, + 0xfc9f8ffe, 0x013536e9, 0x4f2d060c, 0xa894b0a4, + 0x7d1a0f45, 0xb73219cb, 0xf1abd7a3, 0x4192d3d0, + 0xf66a8e04, 0x5ba565db, 0xf192eed0, 0x9de8fdd4, + 0x80da2920, 0xae34b9cf, 0x7f27a72d, 0xc831d71a, + 0x4d2a1ddb, 0x5c1fcadd, 0x7de9efab, 0xb5500cb9, + 0x57d5e486, 0x5c76b5ad, 0xf462a1a8, 0xe8c98e95, + 0xb48b3acd, 0xbeb35b86, 0x71df3948, 0x9d97d8f1, + 0x4f5f549a, 0x85a3473e, 0xeef99b25, 0xb6c28677, + 0x499445c9, 0xef8d708f, 0x928535f3, 0x827abf63, + 0x8431726f, 0x8b561869, 0x802f4b7b, 0x50d11349, + 0xa3eae78f, 0x109e8f42, 0xb31b2c45, 0x0041ab72, + 0xea5dac3e, 0xe3692b0e, 0x371b5492, 0x4eebba99, + 0xba1b85be, 0x5460a48f, 0x7b336263, 0x9ca28a9b, + 0x153b3bbe, 0xff46bff0, 0x10367d0e, 0xc29a2a60, + 0xb1d8caff, 0xc16c3aaa, 0x76f91830, 0x25a1fca7, + 0x72dbf7a7, 0x44bc4924, 0xa42b11de, 0x24230012, + 0x449d3abd, 0x64705b5d, 0x9a62ef85, 0xfcdd549e, + 0x2df78089, 0x3a43088a, 0xb0f51665, 0x2e42cf5d, + 0x53c68400, 0x6014dcc1, 0xca4863bf, 0x24f50528, + 0x81a7dc99, 0x488f5d57, 0x59b97b41, 0x1a83808f, + 0xa9723897, 0x10f66c26, 0xed9c7c6f, 0x921f0993, + 0xd52c67d2, 0xb67a7765, 0xb987ea64, 0x991da05f, + 0xfeb1e64f, 0x75000143, 0xd0efee3f, 0x69835455, + 0xcca5874a, 0x4276c9a3, 0x938fbb52, 0xd2237864, + 0x19afe2d8, 0x23ecca87, 0xeb640180, 0xe7755000, + 0xc4a56e03, 0xa21121b9, 0xf3b043cf, 0x8e47e3a3, + 0xc4121407, 0x8e8dadf8, 0xd5e26e64, 0xc2846083, + 0x85293aa0, 0xd7affc50, 0x5fc89502, 0x459681b5, + 0x3a554842, 0x64dadb74, 0x1e89aa6b, 0x2edf4555, + 0x133f28ef, 0x5d4ee4f6, 0xa9cb2b84, 0x246f9078, + 0xb2327a29, 0xa2e9f935, 0xaae618b2, 0xb5fc3e42, + 0x5861276f, 0x82c619ac, 0x871d9434, 0x01d46376, + 0xb9f5e432, 0x45267ba1, 0x655b9e50, 0x0394f543, + 0xe1d5d3fa, 0xbed9d5a4, 0x028fb630, 0x4af00271, + 0x924d203f, 0xc99a9522, 0x27b7480f, 0xa44f0bc3, + 0xd775bad1, 0xcd812a88, 0x8de50e58, 0x67b8c119, + 0x1b3ac68e, 0x201da61c, 0x90203805, 0xbf707db0, + 0x71e19f2b, 0x531533d3, 0x5ba07475, 0xf0e0eec4, + 0xd670f59e, 0x3e103ef6, 0x3c650bcd, 0x42d4e272, + 0x25f4f1b6, 0xd60dcf77, 0xa1d51a81, 0x9a6de436, + 0xea8fc06a, 0xe531316f, 0x7ce26a21, 0xc526af2e, + 0x54e6ad81, 0x4377e550, 0xc506529f, 0x471d35fb, + 0x4d238c39, 0x67917265, 0x4880982c, 0x0efb4af8, + 0xbfa8d0f4, 0xdce08927, 0x1b74b544, 0x60cabce1, + 0x20aef17d, 0xf743c1d7, 0x57a9ce5c, 0x76d4050c, + 0x56f5e0ae, 0xc0b34226, 0x12c4c20c, 0xf824597b, + 0xaa2050e5, 0x2ab4e1db, 0x3d5cdfa5, 0x58280f73, + 0xe27495a6, 0x9d27f65c, 0xcaaf6bd6, 0x3b1811fd, + 0xf82a33c3, 0xb8d15201, 0x8ec73ef4, 0x99ab20d5, + 0x8f095885, 0xbdf47f05, 0xa4214b5a, 0x2e6f827d, + 0x4592c3c0, 0x2dd3be25, 0x30a67d2a, 0xfedfdb14, + 0xc111b856, 0xc61ff666, 0x76c1f441, 0xf55944f3, + 0x4740b7c0, 0xdfbd6f4f, 0xd400a3f7, 0xbdbeb5f3, + 0x4038ddb8, 0x0be66965, 0x2bf69e7f, 0x1c3d996e, + 0xd7fe7a88, 0x8ee7e8fd, 0xc678056e, 0x111e4a47, + 0x68cf2ae9, 0xd29d7245, 0x5b5dd367, 0xe6b2ab3f, + 0x7111a7ab, 0xf2a21c5c, 0xd5435a9e, 0x86401cb9, + 0x9a288246, 0xd4f9ea27, 0xd07da772, 0x1d5719ed, + 0x8d8b5a88, 0x3f4191c2, 0x56cc0c1d, 0x549a79d6, + 0xc3251a24, 0x614309f3, 0x99394b0a, 0x0a1c988e, + 0xaa8bc076, 0xe4c8505e, 0x7d4dfa95, 0xb1a97f00, + 0xfac7d971, 0xea8e2d74, 0x261ad1a4, 0x4fb37ea5, + 0x1a106b19, 0xa281ee48, 0x5eebe79e, 0x9d9a08c3, + 0xf4979b06, 0x5c3e5781, 0x017cebc9, 0x36402dbd, + 0xaae8df09, 0xd7a0a6fa, 0xa4fd8bdb, 0x769b72ec, + 0x93ba256b, 0x597b1b72, 0x8cb223d9, 0x45b105e4, + 0x6ce12ab2, 0x4a4a6dc9, 0x69a68302, 0xa3ab0377, + 0xf4026526, 0xd7c06d01, 0x86c99511, 0xbb487cef, + 0x7305999e, 0x9ce8b2d9, 0x7baccd31, 0x9e6db792, + 0x541fd437, 0x7102a4fd, 0x2cfd2af8, 0xe3fd541a, + 0xc76717a5, 0x0e30fc09, 0x8f6de52b, 0x001a3062, + 0xb645ac39, 0x2ec826c2, 0x20c04713, 0x7fe88da0, + 0x0d37b0ab, 0x51719f08, 0xa9bbbeaf, 0xba657a73, + 0x54804a7a, 0x1799c329, 0x41bd0c20, 0x13bd65ad, + 0xc491ad3b, 0xb34e2edc, 0xb73d7c19, 0x604d1ad0, + 0x161bf036, 0xd8515015, 0xcbf3f705, 0x3a880873, + 0x6847b4de, 0x6f486a3a, 0xfdf96ca4, 0xcc0bb9bb, + 0x32e51e25, 0x29e18480, 0x558c6689, 0xbe835c8b, + 0xb431e806, 0x73db1d47, 0xd740ab4d, 0xafa0ad06, + 0xce905d70, 0x67be6f62, 0x5b7770d5, 0x71c48671, + 0x34b5fcd1, 0x68c914db, 0xa2c651f8, 0xe2d9a3e5, + 0x27540d0b, 0xe49b84e5, 0x135d9648, 0xe3913a70, + 0x677f3258, 0x50225f1b, 0x559e943e, 0x7557afe9, + 0x25d663ac, 0x3f0444cb, 0xf6ea805a, 0x93917af6, + 0x727e44b1, 0xcd50e43c, 0x0c319d01, 0x69a84d57, + 0x1148a05a, 0xdd610d18, 0x31c5ebaa, 0xcfb9bc46, + 0x4e91db57, 0x705d2475, 0xd9fc9519, 0xe350fbd2, + 0x3368c7a5, 0xc9a8ee0d, 0x73e12c1a, 0xb4a755ff, + 0xb6aa8968, 0x9af7ed1d, 0xbbca18e3, 0xf8268aa0, + 0x5fb1a6bd, 0x0b8ec594, 0x8954f363, 0xdf113f29, + 0x05635d61, 0x534b28ae, 0xed75117b, 0xdeff6cc2, + 0x9e33a2f9, 0xa1a4299d, 0xc18e6840, 0x7f81ec41, + 0x733d457f, 0x9c620573, 0x03d65d24, 0xafb2a17c, + 0x906dbd63, 0xb800eee3, 0xf25df8c1, 0xcace4190, + 0x80837262, 0xa7c477de, 0xa7dc3200, 0x7d13cf9c, + 0x4b10e82e, 0xf8282d4d, 0x0c4a1521, 0x41c1f1d1, + 0xa816fdac, 0x50894c29, 0xbf96e6e1, 0x15f37687, + 0xd1f0c529, 0x5e8d445e, 0xc96157e3, 0x35bc6a4b, + 0x17ab1d44, 0x4b32c7d4, 0xad07b3a6, 0xf57f72df, + 0x222eedf8, 0x198ee973, 0xcdea7151, 0x0b558e7c, + 0x5eae4c95, 0x4e035ee1, 0x80d1dd40, 0xe121f92a, + 0xc9755a36, 0xf5cfeb7d, 0xc9fc70a3, 0x84771eba, + 0x7b491be4, 0x0bc9927a, 0x70d1c4f9, 0x6169ed7c, + 0x57eaa667, 0x265a5d02, 0xab8a9ab3, 0x66bcf428, + 0x363a9f21, 0x8915d408, 0x8a4feb0a, 0x32df9e3f, + 0xca0d330d, 0x299a8f5c, 0x6b04a1b1, 0xd58a7605, + 0x557c5d7f, 0xf402d6dc, 0x3af34632, 0x3ebdcc80, + 0x82842684, 0xde5662c2, 0x7c6ac0fb, 0xe7d92ee8, + 0xce5abdba, 0x56806b13, 0x01b9095d, 0x9e20b335, + 0xecb5420e, 0x2014aeb3, 0x6c6c21f2, 0x16137540, + 0x2c74e373, 0x981e65e2, 0xdbf439ce, 0x2ce6414f, + 0xbffc40d8, 0x5da3b06d, 0x3f122a5b, 0x2eb469ca, + 0x2223ff44, 0x2d4dc939, 0x45dcd66a, 0x674a89c1, + 0x34780db5, 0x69b18919, 0x0b03c2ae, 0xef8e95fd, + 0xbcff533d, 0x25802d08, 0x5c5e98be, 0xd2d86627, + 0xc36a8db0, 0xb7037871, 0x927764ff, 0x8f4486df, + 0xdbc25d8b, 0xd7e45e48, 0x4368cedf, 0x4e1ab6c3, + 0x01a13217, 0xb7a6a7d0, 0x80b476a7, 0xcc769d12, + 0xd6a2e19e, 0xf1fa8984, 0xe9dd6f57, 0xfd51184f, + 0x4127cf16, 0x93434013, 0xeaa14b68, 0xafda06d8, + 0x24c50b72, 0xa8f4ac62, 0x925c050f, 0x24216919, + 0x3e536e55, 0xb1ec1d2b, 0x025a17b6, 0xde102883, + 0x1b1d43e9, 0x6db046f1, 0x60ad4400, 0xfa29891c, + 0x0fa073d3, 0x2b8764c8, 0x6e7d5d67, 0x0583a1bc, + 0x1cdfa417, 0xfecac7bb, 0xe4da5157, 0x8fa6e28f, + 0x31f8ec29, 0x97faca9c, 0xd83ec2e7, 0x7af7c43e, + 0x6843df73, 0xc94a901a, 0x3459cede, 0x66fe9d05, + 0x101dbc3b, 0xb6f5077b, 0x3001478b, 0xaf0bb014, + 0xb36e8113, 0x34deb613, 0xa0c2ea3a, 0x0016501c, + 0xfaefe974, 0x351882b9, 0x54ed87da, 0xaf07d4a0, + 0xcfa0bfac, 0xdede7ac0, 0x389ad36d, 0x70e20e49, + 0x66d151dc, 0x04b3f189, 0x1f3e82a5, 0xf4f6dd3a, + 0xc5dd1095, 0xb5c66d12, 0x127c8885, 0x91d11e89, + 0xf7f78341, 0xe0479da8, 0x356a32fc, 0x6a08c056, + 0xb084b999, 0x345215cc, 0xe0a0c381, 0xa2557263, + 0xfb3740f8, 0x41b3a613, 0x015a4c2f, 0xa31586ee, + 0xaf25d79a, 0xb5706d24, 0xe7d1f84f, 0xf7020c69, + 0x1dda209c, 0xf544df92, 0xce713bdc, 0xc519d3c2, + 0x22b85f04, 0xf4cfc44b, 0xa0b22bf7, 0x26d1b449, + 0x23bf9d59, 0xb859c110, 0xd54dae1a, 0x36849959, + 0x3fb1ee39, 0x4aa6f970, 0xeec7a300, 0x892069b8, + 0x27229bf5, 0x7ce5ff86, 0x8f2001b1, 0x8880f8f1, + 0xa4dfed1b, 0xd3a9f8a9, 0xb0e5128b, 0x7aaa96c8, + 0x0763b52a, 0xab7ecd5d, 0x83f921df, 0x29d9092f, + 0x81bb7b3f, 0x250f581d, 0xc84d593b, 0x17839bd2, + 0x3363fe94, 0xc43193a0, 0x54422b16, 0xacbcd70e, + 0x22ed0c08, 0x695daf74, 0x4a94c6f7, 0xe75eb314, + 0x72406d5c, 0x85a582bb, 0x62e71d90, 0xa3602b62, + 0x3e5bdcdd, 0xa3b2526e, 0x2aa86f25, 0x6985258e, + 0x0ef6f163, 0xd39cbf76, 0x25e068e7, 0x2e821045, + 0xff43de07, 0x53c28fa2, 0x9cd33c06, 0x08eab9ff, + 0x5cbec3d6, 0x741b0d4c, 0xf3e9f2af, 0xb0c9ebcf, + 0xd2fa5516, 0x6aceca4d, 0xb7aa170b, 0x91064556, + 0x8c3a2725, 0x8a9cf497, 0x0bda8884, 0x5091f5dd, + 0xc21a2b4c, 0x848bf319, 0xfb224655, 0x379c22ef, + 0x73506767, 0x1e1131ba, 0x66db3867, 0x8c69bb23, + 0x449f03d2, 0x267a0a8e, 0xfdd33f8d, 0x3d6384ba, + 0xb3deef14, 0x1b592989, 0x6fc8693f, 0xb89b680f, + 0x2a0ddd58, 0xd91a7dbd, 0x16dd9115, 0x2483fde8, + 0x90cf607c, 0x35c059f5, 0x74006062, 0x52e379a9, + 0x23183842, 0x1f1eef2c, 0x708e608b, 0xa50d19c0, + 0x1f8ee404, 0x775c971e, 0x9d9e41a1, 0xe314268b, + 0x34349f28, 0x5f6e1582, 0x26c53780, 0xc4d58acf, + 0x0ee78d20, 0x2058cbca, 0xf3e2b6f3, 0x3ca00e9d, + 0x5434f03e, 0x4a2daeca, 0xa5c1122c, 0xcc0da679, + 0x2816db83, 0x2c590558, 0x78df041c, 0xf786c7c9, + 0x0de08a99, 0x9aba69e0, 0xb37b43c6, 0xc0ed75c5, + 0x19d1e903, 0x298b4329, 0x4ad528c4, 0x30c23938, + 0xb59658bf, 0x5672c5a0, 0x4804924d, 0x405db429, + 0x1b681fef, 0x74be288a, 0xf0c57c29, 0xd83f17c5, + 0xfccc14c9, 0xd9b8872e, 0x6e5a55a6, 0x75624258, + 0x537baa29, 0xbc7ca096, 0xfc9dae88, 0x17615045, + 0xfd6ffbed, 0xc1c06167, 0x863c3739, 0x9af2ab8f, + 0xc04373d3, 0x3ded464b, 0x17cd43dc, 0x6b3f48a5, + 0x3bef12e7, 0x1a0d8bdc, 0xc484978d, 0x22dd16df, + 0x1ad2f7a7, 0xb2778fb5, 0x25c5098d, 0x93df97b8, + 0xc8c8d1f6, 0xce4fe7b6, 0x7d19ae1f, 0xf24e4d50, + 0x145fe372, 0x33d3a8c2, 0x4530a371, 0xc0fb1ed9, + 0x22438bac, 0x6bf2dc2c, 0xb4529cbe, 0xab3a2bc2, + 0xd2018531, 0xb78f9c3f, 0x4af9304e, 0xef42eba7, + 0xc2fc9af2, 0x07e22827, 0x995f32f9, 0xd091349a, + 0xed1cca93, 0xf6bfdbe7, 0x950fe757, 0xae81983b, + 0x27b3d01e, 0x0f7cbe7b, 0x4522467d, 0x155d82c8, + 0xa4591670, 0xb19f2b93, 0x891ff2f1, 0x600a3376, + 0x2158c825, 0x2281f93c, 0x7f2b80c2, 0x212c15bc, + 0xeecbdebf, 0xf316e255, 0x1a2fee4c, 0x93f536ce, + 0xe3b66d7d, 0x993c5641, 0xf3ef38e1, 0x98cb4502, + 0xa8436dd0, 0x11c8bedf, 0xc2041795, 0x3c8fc217, + 0xe279bcd6, 0x522df4b6, 0x303e987e, 0x2c46590f, + 0x6149ec6f, 0xcd6307f8, 0xc4c47585, 0xfd6e778b, + 0x94a2fc01, 0x004b032b, 0x1599a274, 0xac62aeef, + 0x67654b19, 0x10139b48, 0x0a751aef, 0x454a0ce1, + 0xdc7eee44, 0xa828a9ee, 0x4200680d, 0x354e8bbb, + 0xe81e3765, 0xdd0b827b, 0x641cec43, 0x5e09ae5f, + 0x238d61ad, 0x40dc7d08, 0x73430fb2, 0x4069f058, + 0x06d575f5, 0x0f908ec0, 0xae16e61d, 0x6178e3ec, + 0xfb5efebd, 0x9b493a1e, 0xf7530d2c, 0x439d6686, + 0xbe1f1fe4, 0x1028bf71, 0x0c46a51c, 0x1a92019f, + 0xd241495a, 0x2cd2621e, 0xc611292c, 0x21ca45aa, + 0xc66549e4, 0x894069bc, 0x3e4d8e40, 0x9face010, + 0x28d73480, 0x6ae84a2e, 0xe59c2acf, 0xa968d69a, + 0x2fd9aeea, 0x9b220751, 0xadb65eaa, 0xdde40d3f, + 0x32123e03, 0x6a5f0c91, 0x2da3f8f2, 0x47b617d3, + 0x091dd2b1, 0xc3be1b66, 0x5ad4898e, 0xeabd5276, + 0x83f177f3, 0x9bbcd47b, 0xf1fe41cb, 0x832e1e0b, + 0xf4670093, 0x4ec4bef0, 0x28b575f1, 0x73d3f83b, + 0x44a53523, 0xfe2427ba, 0x008e9b5e, 0x9032a368, + 0x32ec0699, 0x56190075, 0xf2e8c746, 0xd4329896, + 0x43609223, 0x0c63a187, 0xe2470ef9, 0x0e0a3ce2, + 0x057443af, 0x87650c3c, 0xa914e81d, 0x1d0bc597, + 0x1ce0d42b, 0xf3c346b4, 0x199d199e, 0xf776515c, + 0x9a4b4fb8, 0x9eb770ec, 0xfd6377af, 0x557c6624, + 0x6d1f4edf, 0x3c2bcde7, 0x169943a3, 0x416588be, + 0xaee7a8bd, 0x30a466fd, 0x858c7909, 0xaddc0c95, + 0x724f271c, 0xb98781d5, 0xf61d4eaf, 0x56b21720, + 0xfecd34e9, 0xf702263d, 0x3f7c1cdc, 0x3be5ecd7, + 0x1041f78b, 0xf555dcc1, 0x7f48d9c9, 0x9688b5b0, + 0x0204a63f, 0xf722bb6f, 0x4c05653f, 0xb629c57c, + 0x5e24fbe9, 0x0cfca8bb, 0xe9e2818f, 0x840130c1, + 0x24e3daeb, 0xff164046, 0x870c0568, 0x4b468b3f, + 0xa3278c9a, 0x2a51e673, 0xadc01ede, 0x49f11116, + 0xed03001b, 0x7d648161, 0x0a1869a0, 0x77fbb639, + 0x24574dbf, 0x021d75cd, 0x1b9c32e3, 0x5451ca22, + 0x56ef408e, 0x3f6deb25, 0x3a03fa8c, 0xbdb2a173, + 0xd5ea1c3a, 0xaed24134, 0xeb95299d, 0x0dc484dc, + 0x2f194d75, 0x4464745e, 0x29e6a715, 0x62f4534a, + 0x530f9cd8, 0x45f9b058, 0x7254909b, 0x1b25f5b1, + 0x932cb503, 0x8ec1b821, 0x06a0198b, 0x229113b0, + 0xd8a79b7c, 0x7ac11c1b, 0x5e591096, 0x602a0828, + 0x4e30a8d2, 0x5b7f0c4b, 0x0a65c794, 0xff6b0735, + 0x5f80c5cd, 0x441b895f, 0xc248b09e, 0x6ad068a6, + 0xc78d9df6, 0x01ee5a2f, 0x373aa716, 0x30952950, + 0x39e38d39, 0xfd8b8e4c, 0x972d2535, 0x4e7bf47a, + 0xf71c92c3, 0xb95fa1b8, 0x1b3bb029, 0xdfdef2c2, + 0x9e38562a, 0x16225a49, 0xc687ddce, 0xeffde1b1, + 0x08f6c409, 0xbe2893db, 0x947655e0, 0x781053e1, + 0x5b91ff4a, 0x2db8bb8e, 0xef3b1bc7, 0xe22a181e, + 0xf358bec5, 0x99200e07, 0x179f5a3b, 0x0646ca17, + 0x99e56253, 0xd2af0dd9, 0xfef16672, 0xb5a8763b, + 0x565cfdbd, 0x963a853f, 0xd410b7bc, 0x6b7a9cf1, + 0x52619189, 0x05297999, 0x54cf082c, 0x4b63e050, + 0x0ddb5000, 0xedb72b99, 0x1684f632, 0xa1461542, + 0xb852d7bb, 0xe202e66c, 0x1870f3e8, 0xd62a4aa9, + 0x61d954d2, 0x807a26c1, 0x4a2318b0, 0xabed0549, + 0xe9d15c0a, 0xbfebc9eb, 0x17034731, 0x2f145506, + 0x04dca828, 0x6ed9bf3a, 0xe6694be1, 0x34e301d9, + 0x75072c05, 0x8f254e29, 0xaa073c1a, 0x5efe2252, + 0x20354141, 0xe332cbaf, 0x501c7ff4, 0x873a506b, + 0x0e3a80ae, 0xa35312e0, 0x4c6d9043, 0xcfd1aae9, + 0xecc5ff93, 0x53f9cbdc, 0xb09e5f6f, 0x1f124041, + 0xde0e748e, 0x3dc34e66, 0xb0c7f92a, 0x3a405efa, + 0x4463c275, 0xc2066be4, 0x60215c73, 0xc6a5af5b, + 0x3d4f0e63, 0x52f1dd71, 0xc4cbad36, 0x7d763fc6, + 0xe8eb4e11, 0xaa23d45a, 0xb7506628, 0x2d080baf, + 0x2e36de40, 0x6db864ba, 0x7ee9b5fd, 0x5f8a55d7, + 0x0d6e6b63, 0xb1ebda74, 0xd5fc5f93, 0x15488af6, + 0x507b72b4, 0xced11fe2, 0xab92335e, 0x29a7e9c8, + 0x0982831a, 0xa8ad1b05, 0x55dcdd06, 0x831689b0, + 0x95341a59, 0x6b23a0b3, 0x7718d7bf, 0xa10e5cdf, + 0x360a4200, 0xd524d2c3, 0xf625d8d7, 0x18dbf6e6, + 0x829959b6, 0x8afb2c0a, 0x12e5df41, 0x8f7fca96, + 0x61f0b8ae, 0x6d7f0f6d, 0x70a1e426, 0xb967a26b, + 0xb7f9702d, 0x23d4e064, 0x16faf685, 0xb529ad50, + 0xe5d12ffd, 0xb55ed3e6, 0xd13a3566, 0x569080ff, + 0x8f847118, 0x6792123a, 0x227b5cd7, 0xba1b7e52, + 0xcefedb78, 0x4ba524f3, 0xc09a5744, 0x2a073ed9, + 0x33cb801a, 0x4051564c, 0xcdb61ae4, 0x7cea0ee0, + 0x232ee349, 0xf46c7082, 0x801767ad, 0x8327b57b, + 0xf28ece2b, 0x83a0a104, 0xf736b3ad, 0x193ccc93, + 0x645323bb, 0xa0db66b6, 0xcefeb7d2, 0xd5a9404c, + 0x7dce4a4d, 0x6ff71b5f, 0x5d79a9d9, 0xfc7e9049, + 0x7e92c2d4, 0x38beca5b, 0xb672e4d7, 0xaf77c9ab, + 0x861da8be, 0xdb01fecb, 0xf359b649, 0x582e7e7b, + 0x6b3647d0, 0x8f8fb920, 0xee432235, 0x01af6455, + 0x795fcf81, 0x793bf7fe, 0xa3ab8d51, 0xdeda8400, + 0xf9f0a6a8, 0x9153d4ad, 0x2fd49f38, 0x406b7ec8, + 0x8ab8473f, 0x08cb392e, 0x2b23d770, 0x315c5b7c, + 0x57991715, 0xc4323c1f, 0x9659ea00, 0x584b00b3, + 0x24b63a45, 0x250dd391, 0xa0a3c6c7, 0x3bf9e2a7, + 0xe6381c38, 0xd06dbb44, 0xf50f38fd, 0x9ac2d746, + 0x3820e0ca, 0x9308e312, 0x18cf0ff4, 0xf29f8246, + 0x9991a358, 0x9b463405, 0x45fc42a4, 0xbf7a2843, + 0xdedf2111, 0xcae6bfff, 0x78d19852, 0x993e220e, + 0x344ceb92, 0xfae92b90, 0x00252090, 0x9d33a743, + 0xb7143bf7, 0x155fbdad, 0xb06a6ee9, 0x7af6d4be, + 0xca5741cd, 0x4a92fef2, 0x68faa852, 0xcf59e7cc, + 0xa94cc063, 0xc92d70bf, 0x147e4c64, 0x8fc4f233, + 0xb2b00225, 0x5f9b1073, 0x7368cbef, 0x1043c7ae, + 0x5cba9f79, 0x31081635, 0xa4b09da2, 0x7bcc8aff, + 0xbac4ad20, 0xb4bcfca1, 0x7780423b, 0xd70be548, + 0xaadede85, 0x380ffc61, 0xa4a15064, 0xe7da99e4, + 0x3b9b8dd5, 0x06fdc414, 0x7a72b76c, 0x8c1e9e9b, + 0xe256670c, 0x7c0cb5bb, 0x3f638228, 0x24e39288, + 0xad9214a0, 0xbf7f4be7, 0x48263398, 0x4520d5f4, + 0xb81e4d5b, 0x4d57f30d, 0x4cdaa3a3, 0xc1be33b7, + 0x8c77df28, 0xc4ff528b, 0xc51d4a57, 0x61bac598, + 0x068a1bc0, 0x08a3ab44, 0xff262f66, 0x2ce177ae, + 0x2ddd2f4b, 0xf3af55b7, 0x5f404ee3, 0x7b84dc8d, + 0xaee842d7, 0x873ab41f, 0x90cbf2d0, 0xc876837f, + 0x0da4e2ff, 0x9d44095c, 0xdacce369, 0x9df9d0be, + 0xe594d5d9, 0x2e6ccefd, 0xaff59267, 0x88e63a97, + 0xa2357c12, 0xbd96fe28, 0x1a79ef99, 0xface1d96, + 0x15d88dc9, 0x60f22207, 0xfa95fe9e, 0x8cc8c144, + 0x5957697c, 0x09501826, 0x1a7d9d71, 0xcd436092, + 0xd6186af4, 0x755adf03, 0x63bdacec, 0x82c05cff, + 0x671d5b8c, 0x2c659340, 0xa1da6cec, 0x8b232a30, + 0x93eb820c, 0x41dbd71a, 0x8d96b5b0, 0xa2b0aa87, + 0xa424b92e, 0xeda18dc2, 0x6facc0d1, 0x7a4135d3, + 0x63843f35, 0x1c1920ba, 0x0433c37b, 0x06ad0db4, + 0xf2b2e542, 0xf75df8ab, 0xbe706538, 0xd6029090, + 0x91be4136, 0xb2394f18, 0x50ac7fb9, 0x04291d6e, + 0xd7e56ab8, 0xda9ab692, 0xadf8f639, 0x2fbb17eb, + 0xdf6d9b49, 0xb3758ef4, 0xc5615d52, 0xdfb79291, + 0xe79b6c90, 0x43134d92, 0xfa34f822, 0x54a6f3f9, + 0xae83894a, 0x0d7f7a83, 0x3f8824a8, 0x811353b7, + 0x4a1f0fda, 0x547bb62b, 0x58f80bf4, 0x698f01d0, + 0xb04a2fe6, 0x849cda6e, 0x4f2dc4c7, 0x6afdeedd, + 0x6f4de756, 0xa9db007f, 0xb72dbdde, 0x56e31d4c, + 0x276c0b92, 0x01429f8c, 0x982b92c8, 0x098f9281, + 0xb016d86a, 0x64b0a733, 0x51d34aa1, 0x045ff5a5, + 0x2878930d, 0xd2b6bf6f, 0x0184984d, 0x34ad84e7, + 0xcfad67b1, 0x2f70cfd0, 0xf15f50da, 0xe3fd724c, + 0x3b7b7588, 0x1b1940a5, 0x18e19c9b, 0x32f98d71, + 0x7cb73e7d, 0x1154d745, 0x30ee268e, 0x5a5963c8, + 0xb36e03ad, 0x052b4052, 0x57c10ae8, 0xfa833fd2, + 0x040b25ab, 0x29d8de83, 0x91a9873f, 0xa0ad57a3, + 0x8207a261, 0x3e60991c, 0x26410027, 0x32c5f604, + 0xc9cd7cfa, 0x3bb24d2a, 0xfc7e6e7d, 0x44c82073, + 0x504c8075, 0xbfaad041, 0xbb383ecb, 0x3fa88697, + 0xfa08e265, 0xbfd92e12, 0xbb9dad80, 0xc7bb99e8, + 0x8baea4f4, 0xf4b97217, 0x50b1e1c4, 0xa0560930, + 0xd8089bda, 0x885d2e6b, 0x36a83f3b, 0x7edbe6c6, + 0xa114bd37, 0x08dee9d3, 0x47278a67, 0x5bb55ef4, + 0x17dc684a, 0x82c4344f, 0x2ebbafa1, 0x84b2325d, + 0x951ac6a4, 0x3f50aae2, 0x4695a8ab, 0xebe61f22, + 0xcc25e519, 0x62c91794, 0x3dc2872b, 0xdd5e4028, + 0xe2dbfd35, 0xfc695391, 0x2a296e0c, 0x7c4a2ef9, + 0x1d2f21cb, 0x03b79895, 0x6fd00773, 0x7b18e2e1, + 0xe077c139, 0x80cb9583, 0x7e10e92d, 0x449703d6, + 0x2adfcfa9, 0xe9444e49, 0xdb5df4aa, 0xa44f9f53, + 0x48de1027, 0xdc68e587, 0x60b484f6, 0x6af828ad, + 0xe2c6ef72, 0x77078867, 0xc660a832, 0x284710bd, + 0x92786a18, 0xfb875ad4, 0x5400fe2a, 0xf0935b3b, + 0x944cf0e4, 0xeec31e5b, 0xbe21f73b, 0x6a5c9da3, + 0x68558062, 0xb219e125, 0x4b816339, 0x78dff006, + 0x41ca6bc1, 0x0213b064, 0xccfba3df, 0xaa368951, + 0xb2c5545d, 0x734badcb, 0x49167c7a, 0xcb39d780, + 0xe5bffdfe, 0x62fcc725, 0x34c41ac8, 0x29c02273, + 0x18731b2a, 0x5cb59ee8, 0x98a7d516, 0x4be46385, + 0x7ef73714, 0x7b06697d, 0x32ff6e67, 0xd51f2042, + 0xfc80722f, 0x3928b00e, 0x519dc535, 0xbead4eef, + 0x68d047df, 0xc8b3d613, 0xcccdbd99, 0xb1fd7198, + 0x11760138, 0x03fa355a, 0xfd693654, 0xd52fb67b, + 0x117d29ef, 0xcf2ed83b, 0xc59e18e0, 0x541ed6c1, + 0x6f9e892f, 0x2a6d5e92, 0xdab5f564, 0xa42f9832, + 0xd998d3ce, 0x52bebc95, 0x821e782b, 0x9b797830, + 0xe4e538dc, 0x4e18482a, 0x56d31f75, 0x6e246fc9, + 0x33980c08, 0x119e2aa9, 0x0539a394, 0xfc12cab8, + 0xc94c5e5f, 0x0e5413a5, 0xa7059709, 0x6b6c08cc, + 0xc6a1dc49, 0x3df4f03e, 0xab777160, 0x4a12ce2a, + 0xab1be938, 0x590b7f4b, 0xeb5325c1, 0x410418de, + 0x1b3b34f4, 0x56b1d7cf, 0xbed0d3d1, 0xd23f70ec, + 0xdb77531c, 0xec014217, 0xcbfa9635, 0x34200b99, + 0x7bce0824, 0xb3a7bf0f, 0xb4797072, 0x287d1aa5, + 0x1ba51af7, 0x770b984f, 0xc512e19e, 0x36cd12ac, + 0x8270040e, 0x517ea552, 0x536f11d6, 0x5abae263, + 0x89dbcf36, 0xcac374c2, 0xecebb3f3, 0x2084c3ab, + 0xd4205b8b, 0xc2712830, 0xd2726ad3, 0xbbce34d5, + 0x4c4e54c0, 0x8e7a6b9b, 0x93eb7db5, 0x30474f80, + 0x41c48e0f, 0xc6ae5782, 0x5dc50dcf, 0x6d5da72c, + 0x81eb1216, 0xbfc39e46, 0x528a1e62, 0xed374d8f, + 0x1cbc4964, 0x02639707, 0xf601ded7, 0x3eb74e60, + 0x2503df24, 0x09b3b716, 0x50f3b88a, 0xa511d1ab, + 0xfe9138d9, 0x39c045ba, 0xd8b179ed, 0x9bd9de57, + 0x49744017, 0x71ec0f05, 0xb6f3052f, 0x60991783, + 0x95eb27ec, 0xa88ddc41, 0xd8ad08d3, 0x39eda54a, + 0xeccf6d70, 0x3f47a952, 0x45fa957e, 0xb9f9e871, + 0x94eb0c45, 0xc44dbac3, 0xbcefdd3e, 0xa02df323, + 0x464eeea4, 0x5b37d7f9, 0xeec4c72f, 0xcbfa165a, + 0x9a936039, 0xe66ad709, 0x72014620, 0xf5954cfe, + 0x0618b2df, 0x0897d33c, 0x0da561d4, 0x606f5fb6, + 0xdf5b4d3f, 0xe51a32ec, 0xfe41db23, 0x43479cad, + 0xa6721ef6, 0xc1275942, 0x4fe70582, 0x4905566a, + 0x71b57164, 0x46fc5c01, 0x649fa9f0, 0x69abaae0, + 0x1e682afd, 0xd88c1bec, 0x67428b4e, 0x4b2f4f5e, + 0x70b949fb, 0x0565e15c, 0xc3a91062, 0xe8cdd08f, + 0x3bc7616c, 0xcdd83023, 0x007b117a, 0x298fb227, + 0x88b5dd83, 0x741bbac4, 0xc6b91fa7, 0x654613b9, + 0x6d6dc52e, 0xade83da4, 0xda7916d5, 0x8831d936, + 0x87c6525e, 0xff29ea1e, 0xfb82b16d, 0x1b41b11e, + 0x74c87921, 0x9fc4ddb4, 0x67008435, 0x8b15f3b6, + 0x1a24e07a, 0x843e9fcd, 0x24119c24, 0xec576060, + 0x9e1d3ad1, 0x99e29e8c, 0x1b304d4f, 0xca9eb591, + 0x81defb41, 0x48c897ff, 0xdc879292, 0xc02a5607, + 0x0f5fd451, 0x1b4ad7ff, 0x57afe60a, 0x8248b114, + 0x7168870d, 0xde0a4953, 0xacf1ee95, 0x027330f3, + 0x2dad966f, 0x26deb796, 0xbc55ac34, 0x4d499fc1, + 0x6d83bbad, 0xbe606c98, 0xbbdaf046, 0x2c18465f, + 0x6c4c67a0, 0x4b6aa92a, 0x9feaed42, 0x674bd7e2, + 0x008bf80f, 0x1ab8c005, 0xf46c4f30, 0x9928438d, + 0x8c133b47, 0xc86a2ca1, 0xaeadb664, 0xc7fecf71, + 0xb13c882e, 0xafc3e937, 0xc809dadb, 0x31138a33, + 0x785a0ea6, 0xbf038dea, 0xa3bd1fbd, 0xcb910d7e, + 0x5c69974f, 0x19bc46b2, 0xa70a1efc, 0xc1b6e888, + 0xf3baea63, 0x81dde9bf, 0xfa2c0793, 0x600f7bfb, + 0xbae1624a, 0x88455ccc, 0xda07fe34, 0x0433d474, + 0x5d3c1fbe, 0xfccc6222, 0x55cb08e0, 0x70393e11, + 0x00c07a2e, 0xb2776182, 0x1e48407d, 0xa0c48c8e, + 0x4b962829, 0x83934059, 0xcf47f5da, 0x75a15ceb, + 0x36145150, 0xb9fa6ea0, 0x1a0a0371, 0x372f5741, + 0x3ba286e1, 0x8098930f, 0xb1df967f, 0x9821903b, + 0x47837056, 0xd90fde0e, 0x10673c63, 0xd75ce044, + 0xcaf12a48, 0x2f7eba5c, 0x0998614f, 0xeeb9bfe0, + 0xca429611, 0x9f4bf1d4, 0xbbff1d94, 0xc0c8c425, + 0x1d924e41, 0xd662097b, 0x121fbb0f, 0xed364b46, + 0x3c4e75a0, 0xd0c7d6de, 0xb6350e15, 0xd9b36910, + 0xb31f727d, 0x7f440afa, 0xde78141f, 0x408a689b, + 0x60cb0f61, 0x7b32ff1c, 0x443e72ab, 0x0e104b19, + 0xbcca3deb, 0xaa043b3c, 0x2fe2a5e7, 0x6e71d66e, + 0x250c6229, 0x8cb3c62e, 0x55fcf8ba, 0x0057d7e1, + 0x5bf9b0fe, 0x3a4a4572, 0x88462068, 0x7d08f489, + 0x82573e8e, 0xe970164e, 0x9cdc75cf, 0x86c7674b, + 0xf54878e1, 0xc457c328, 0x366e4f2b, 0xac3dcc01, + 0x1451846e, 0x8f5a5da1, 0x80ce2857, 0x6a0917bd, + 0x12d35a2b, 0x4f2767f4, 0xe120462c, 0x99be17ff, + 0x98d18df3, 0xa8f65dca, 0xff17bc24, 0xbf0e33c7, + 0x250c27bb, 0x87e9dd6e, 0x34295aae, 0x346b7502, + 0x7aaae55e, 0x2687ccf1, 0xdbf85c57, 0x5b8dbdd2, + 0x52d1ed81, 0x614326ff, 0x439186f2, 0x02c6fd2c, + 0xd99ffa67, 0x2ddd6e9a, 0x8ca86a6a, 0xbc686bbf, + 0x641b265e, 0x8965d6cc, 0xe7305b90, 0xe205f84b, + 0xa2e55022, 0xd4417cb3, 0x60cbedb6, 0xb7850271, + 0xae24e27a, 0xc89499b1, 0xadccb280, 0xa3cd5e54, + 0x1ec56c11, 0xa75d036c, 0x82d482a0, 0x09be52c1, + 0xf0a1437c, 0x767d72d4, 0x49dafece, 0x0d0569d6, + 0x9087bcab, 0x55de9b7e, 0x3f8ffa4d, 0x2589337e, + 0xc0a6ec1a, 0xf13297ad, 0x7142df74, 0x318db6f6, + 0xc60db447, 0x75864ea7, 0x731a931d, 0x37e7b9eb, + 0x1e8e7260, 0x18bd245e, 0xc7d51eeb, 0xfb44e5f6, + 0x9ae91cff, 0x780a3652, 0x4d49bb5e, 0x05ef4254, + 0x96de67ea, 0xdc0e465d, 0xd18f5659, 0xfcc37e33, + 0x25ffa1f2, 0xaae6c32e, 0x1dc94f67, 0x11859efc, + 0xe11b5187, 0x6609bfec, 0x16474b47, 0x60a072e0, + 0xd0acbbff, 0xd6fb9a59, 0xa78275b4, 0x35b09bb2, + 0x0cd059b1, 0x661f1832, 0xc090d909, 0x14cc039c, + 0x51997e7c, 0xc0f5aea8, 0x19153f78, 0xafc13431, + 0xa4539bf3, 0x35b6647d, 0x577c0e56, 0x7466c128, + 0xa8456d1c, 0xb700705e, 0x6c42811a, 0x091188da, + 0x5821927e, 0x72caf44d, 0xe3bdd149, 0x24ac233c, + 0xd64ca297, 0x4d321544, 0xd4d30672, 0x4a802fed, + 0x24ef382a, 0x85e0dc03, 0x46336bfa, 0x98f2b240, + 0xc441a234, 0x03c32613, 0x98de1c75, 0xdca8449e, + 0x953761a5, 0xc4418567, 0x84ae35f6, 0xdfdac145, + 0x405acb3d, 0x5b43adc2, 0xbd55fdfb, 0xccf5e096, + 0x4932689a, 0x2775ff7b, 0x15fdb541, 0x428d0f1e, + 0xd73830ec, 0x46b22482, 0x50f51c34, 0x278a5a20, + 0xd32e8353, 0xa81aa6e0, 0x458d9d33, 0x6f90f679, + 0x55649d22, 0x18ef9c74, 0xaf26b7a3, 0x8e8cae4f, + 0xba029121, 0x99ead662, 0x5fb4f67c, 0xe31b73c1, + 0xd15f0842, 0x4306905d, 0xfc879c78, 0xaa419d14, + 0xd4889d38, 0xcd9c1d2e, 0x0a6c9f75, 0xcc72458f, + 0x73e472ee, 0x4ad36515, 0xb559b4db, 0x0f12c440, + 0xa883ac0c, 0xfd66d02b, 0x14d83fd2, 0x8b6463c5, + 0x0b25da40, 0xa0b0c954, 0x070a0f3c, 0xbbade711, + 0x248802e9, 0xe04f27f5, 0xfe00a72e, 0x1d1924aa, + 0x82cd2f8b, 0x39a33d2f, 0xce4cab92, 0x7833e3a4, + 0xed28d3fe, 0xc142c484, 0x3c4e3e0a, 0x2f03bdfb, + 0x731c15cb, 0x3d834acc, 0x40cf17c4, 0x591db783, + 0x71f3d7bf, 0x7910e9bf, 0xbc0efc7d, 0x95154836, + 0x6a1a5725, 0x07e9403e, 0x9893569a, 0x5d560194, + 0x0ed6eff5, 0x5f1dfa95, 0x603b0120, 0x178b35ab, + 0xa37e8319, 0x3259ac25, 0x55d915eb, 0xf308b4ca, + 0xfdbdd917, 0x207588f0, 0xdcfcaf21, 0xe08100b8, + 0xd076fc4d, 0xa1d7b1f6, 0x36f437d2, 0x4c20303c, + 0x9c25b595, 0xd503804b, 0xcd7473ff, 0x979ae295, + 0x6b23dbe1, 0x93db002b, 0xfef090d5, 0x9fe9bbff, + 0x5a23e174, 0x3132e20c, 0x556a4f46, 0x09cdfc66, + 0xac401d82, 0x083b6f75, 0xa13f9e80, 0xf8ac02e0, + 0x2f6b4195, 0x89029396, 0xf171b17e, 0x780ea561, + 0x064d8fe3, 0x3183a4e1, 0xe4c1de43, 0x24757e0a, + 0xd3b3562b, 0x60b35423, 0xbf3c8332, 0x72c08be9, + 0x2823b6f6, 0x5968b3db, 0xcc689e6e, 0xc16b9f39, + 0xc10e7dd5, 0xbf23fe26, 0x14f00e5c, 0x623b1324, + 0x1e0910c4, 0x2d446981, 0x1759b03e, 0xfc07794c, + 0xa1dffb05, 0x482062d0, 0x778bc506, 0xdd0061eb, + 0xc7180c23, 0xd1f9e8fe, 0xae6fd816, 0xd052ae4c, + 0xe7f7d983, 0x343e002a, 0xe8cd1bcb, 0x4c03afcd, + 0x4e59bd1d, 0x390b41b3, 0xb9e414c9, 0x512ada78, + 0xeba620d0, 0x6e9860dc, 0x2d29b23c, 0x98e52a71, + 0xf7d38090, 0x21b214f0, 0x28bd6437, 0xf36d6c33, + 0x12cf2a4d, 0x2519ac4a, 0x6eb25348, 0x6ede7a41, + 0xfa176448, 0x512dd66a, 0x567a9ff5, 0xd11b65b3, + 0x23f02e73, 0x325ccd7d, 0x34b9d579, 0x5db2150d, + 0x12962623, 0xb185734c, 0x1f19ecda, 0x189df290, + 0x699b71df, 0x54b37fd4, 0xc29e26e5, 0xa3677da7, + 0xd02a23e9, 0xfaf73805, 0xfa8cabd0, 0x173b4c45, + 0x53fb4e90, 0x1af38ee8, 0x3a9dcc15, 0x892f5fbf, + 0xfd069c90, 0x22a3e682, 0x8e3450c2, 0x1a381218, + 0xf4eb91db, 0xa01194c2, 0x0f9b5883, 0xf252dcdd, + 0x56848fc7, 0x0a639c8e, 0xf54944b3, 0x799efd0c, + 0x6d5d73f1, 0x911d3e69, 0x189e17a1, 0xfd2540ea, + 0x601dbfba, 0x012e1011, 0xb336a96d, 0x8f043e71, + 0xa451540d, 0x4af1ffce, 0x3de462dc, 0x72df9e88, + 0x992f5631, 0x69110047, 0xc0d82a30, 0x50e5501b, + 0x9a5a09d0, 0x3fdfbbff, 0x18eabfb3, 0x3f85edf7, + 0x0122e30a, 0x3d46fc32, 0x9232a571, 0xcdb483d4, + 0xfbee9430, 0x29fde39a, 0xb011cb09, 0x370ede2e, + 0x8acf620e, 0x77959d82, 0x0bad2ba2, 0x54d4456f, + 0xda4baa48, 0x90072258, 0x7456eb77, 0x0fc190a8, + 0xfdf03fbd, 0x4bff110f, 0xce530a25, 0x6e59af1a, + 0x0b8728cf, 0x2027276f, 0x7642e9d0, 0x71144999, + 0xb2ad0f34, 0x1701d10e, 0x9c16f7e8, 0xd6b9a361, + 0xb50a8b17, 0x9531badb, 0x1285dac5, 0xc5b6699a, + 0x674482b4, 0xe37330d3, 0x22b64833, 0xeb8449f2, + 0xea7f5b21, 0xc513fd28, 0x0425a578, 0xdf571d18, + 0x2ee7e152, 0x1117300b, 0x1727c46c, 0x2d623554, + 0xb0bb96ef, 0x546cbf44, 0x44b4cd17, 0x9580dceb, + 0x1cefdbbe, 0x0ee3a9fe, 0x680d5a09, 0x8748de04, + 0xba2d019d, 0x03d198be, 0x437bef46, 0x08a8158b, + 0x666d01da, 0xd2b47790, 0xa929fb15, 0x649f4909, + 0x021d59c1, 0x1a0cb4f1, 0xc32b00b9, 0x2193aa55, + 0x655b49af, 0x7deb3084, 0xbbf22ec7, 0xdbd81b2c, + 0x017a1835, 0x546f1d18, 0x53ef80c2, 0x4d3a0450, + 0x31883045, 0x72f982f8, 0xb834f079, 0xbef44740, + 0x5c822669, 0x14a57059, 0x2e5a4941, 0xe7b58287, + 0xff9b7add, 0x0f1d8344, 0x7c26f7dc, 0x37b79b89, + 0x77306fce, 0xe8d2978f, 0xd3ff01bc, 0x803eb0f9, + 0x41df8a8d, 0x572b43c8, 0x077ce9b0, 0x4f6d8f73, + 0x9db2f5e4, 0x0d36c068, 0x07f9bf4b, 0x0533da1c, + 0x33313080, 0xe0b31dd4, 0x92467d67, 0x6c112966, + 0x2d5c618b, 0x8745c04b, 0x9ce2ed1c, 0x92358b6c, + 0xedd1d249, 0x2a16d0e2, 0x47640e5f, 0x7c21f7a9, + 0x70d314cd, 0xd7c9be04, 0x19705097, 0xfbe8cb95, + 0x4c730fee, 0xe5f5ec1c, 0x1b175e4d, 0xc0fbcf7d, + 0x7e49b64a, 0x6c052a74, 0xf55d6188, 0x755fe007, + 0x63dc2741, 0xfef82e88, 0xf9059d00, 0xfdf02f43, + 0x4c530b39, 0xea345985, 0xfd97cc2b, 0x8ebae058, + 0xf18d660b, 0x93d3f934, 0x353eb2e5, 0xc6e2b281, + 0x51053e1c, 0x81e95136, 0xd6860530, 0x2b65f1ab, + 0x92875153, 0x48a67186, 0xfc431047, 0xfb3b6394, + 0x1ee13b4b, 0xd05cb927, 0x9fbaf824, 0x7b83ed92, + 0x32fe6318, 0x23c28e43, 0x6dcb7621, 0x9df62220, + 0x95f79b3e, 0xa785bf2e, 0xacbad3a4, 0xb79250e1, + 0x293a177a, 0x5e952e4a, 0xed8b03a9, 0x3f414020, + 0x41637692, 0x3e03de46, 0x201be444, 0x22d0bb98, + 0x2898992a, 0x39e0ee43, 0x12353eb6, 0x53b92dbb, + 0xf009f2ea, 0x3a609aef, 0xf40e6d67, 0xac2ff183, + 0x6db24c8c, 0x816e2769, 0x7a9fc0b9, 0x9b9bde51, + 0x03aa8efa, 0xbcd9a470, 0x41d64576, 0x10574d69, + 0x1dcb0486, 0xc779307f, 0xc06c72be, 0x0072a2cf, + 0x52520bf8, 0x59c7415c, 0x951956c4, 0x219fb6e7, + 0x7f01864e, 0x77f188d5, 0xd9e0c040, 0x9440e98e, + 0x2e4c0cd6, 0xa1be2cfa, 0xfbda86ab, 0x1247cd36, + 0x6dbcaf7f, 0x9590a798, 0x2ad3c9ce, 0x9f29c807, + 0x03513724, 0x5e6ee402, 0xdffe7c7f, 0x650168ec, + 0xa9202eb6, 0xe32f3820, 0xbcfe9143, 0xfe35e6f0, + 0x91f54ec5, 0x8aa67218, 0x22deab2c, 0xd47efd50, + 0xc15df555, 0xa223f7ff, 0xaa6d7f8d, 0x296a2855, + 0xf9668963, 0xdbf45ad8, 0xa982ccba, 0x11c16aee, + 0xf7ec363c, 0x31c1d1b1, 0x8e27f2ae, 0xd5c3c48b, + 0x4bd61cd4, 0xb751741a, 0x7ea97dfb, 0x4254b8db, + 0x8ab783b2, 0xd11a46fc, 0xaf2419b4, 0x1f62e2ea, + 0xfc69cc0a, 0x5c4d15a1, 0xa0424256, 0xc760dfa5, + 0xbe3df54f, 0x7ac9d2e1, 0x65b0b968, 0x42fb846c, + 0xd1359f4f, 0x4d022cce, 0x2beb80e4, 0x3282f10a, + 0xb1a7225b, 0xa90c9c37, 0x757762e4, 0x31408bbb, + 0xd9a40cb7, 0x61580b4c, 0xc6ff2ffc, 0xd3526e62, + 0x7125f1d3, 0xf3189dda, 0x67d11f87, 0x648f45f5, + 0xc5810520, 0x347920ff, 0x039e14fb, 0x97a42122, + 0x4df6b4b3, 0xee851af3, 0x43acfad0, 0x9c9cd84b, + 0x40b45baf, 0x362cf829, 0xd6cac8b4, 0x934a1376, + 0x87cd42cd, 0x8e808070, 0x4fecdbd2, 0x071409bd, + 0x7a5d6355, 0x2c67de3e, 0xd56606a1, 0x95d2e76c, + 0x69e172f3, 0x856f9d05, 0x99e3a80e, 0x969ff6ab, + 0x32dc03bc, 0x902d5997, 0xe9e088d6, 0xf6e8ea21, + 0x3e71f23c, 0x987f783f, 0x2ed0e84f, 0x06735107, + 0x1284430c, 0x3e75ab9e, 0x31ea53e0, 0xfbf26ca9, + 0x0accdde8, 0x39b63851, 0xc5889929, 0x47cd276e, + 0xb0b6cdcc, 0x9267af2e, 0x0b90c15b, 0x32516cd8, + 0xf43f785a, 0x2854f889, 0xbca0e433, 0xd1708789, + 0x2a3f9a80, 0x18f6b988, 0xba0f2ea6, 0x328e3a13, + 0xead807e5, 0x6268894e, 0x6da5c47f, 0xe4ed9155, + 0xe3b3aaa4, 0x8b7ed969, 0x0982d3cf, 0xae370314, + 0x0c583276, 0x88bc65f2, 0x07e3cd24, 0x7991f209, + 0x4e132010, 0xa5f1b475, 0x1f9a2e1d, 0x626b90ca, + 0x36de636f, 0x892b837a, 0xb93f1016, 0x5c1be235, + 0x48a90273, 0x5e83d92a, 0x5a5d0253, 0xc1b05ca7, + 0x0365632a, 0x96c0d50e, 0x3e73af65, 0x77a6a728, + 0xb788e908, 0xf3816701, 0xcb82095a, 0x67bdefa6, + 0x012bf484, 0x7050ad6e, 0x9c917bc8, 0xbcbb9381, + 0x48279c9d, 0xc60c898c, 0xbd6d0b52, 0x53a793e0, + 0x07fb79bf, 0x9e3e81b1, 0x29c8ad2e, 0x06443670, + 0x69b3e56d, 0x646ffada, 0xf4ba092d, 0xf2ababc3, + 0x18d765f4, 0x26e7ea3c, 0x90cc6dda, 0xbc3caeef, + 0x71fde7ed, 0x3d0bfb36, 0xa7eed78b, 0x0792f6c8, + 0x4e24c346, 0xf1c0d50c, 0x22092fe1, 0xb67638c9, + 0xa4c39abb, 0x1f6d4d49, 0x2db33879, 0x8719b757, + 0x0cf9af3b, 0x05f6f20d, 0x397cd808, 0x9b2efff4, + 0x090a5ab8, 0xe0e9f1bd, 0x8ad8d72d, 0xf615f757, + 0x0ea6b24b, 0x22a7e4f5, 0x9a6ae841, 0x47f0eaed, + 0xd733ba4a, 0x40acbfd6, 0x61e0c808, 0x69c3bbd9, + 0xc82bd02f, 0x90b4249f, 0xc6acdb4e, 0x27108f86, + 0xabb44e6b, 0x0afabefe, 0x69844572, 0x5da3199f, + 0xdb29d3e9, 0x7fa1806b, 0xc5aa260d, 0x32747067, + 0x93c1ce40, 0x429c6164, 0x0f5305cf, 0xd877ec14, + 0x48607397, 0x5ca10fa7, 0x0ce1c5c6, 0x9439ca38, + 0x8a94181f, 0xf4c9dcfc, 0x4a5b75ab, 0xdbd33a59, + 0xb3e514ae, 0x5190445a, 0xa737a66e, 0x50caa538, + 0x16b685c7, 0x77d24ba0, 0xdffe2cd5, 0x7e5faaf1, + 0x74536a84, 0x7504d7ae, 0x5c841e22, 0xc0e8b92a, + 0x6c693ae5, 0x8849c83f, 0xc7e663c8, 0xfa53d78a, + 0x2c83ee85, 0x8beb903b, 0x5d25a8e3, 0x24ddc8cf, + 0xd23d228f, 0x67284ff3, 0x7b008d51, 0x028ef6cf, + 0xd5de32da, 0x4f767144, 0xda883262, 0x3fd69b08, + 0x789fbb8c, 0xfeecf919, 0x86e69e4a, 0xb23af044, + 0x92054c6e, 0x8744a5df, 0xf8ebb53a, 0xe28abc6e, + 0x3c62ef29, 0x87651253, 0x4238e2fc, 0x85089dd3, + 0xda531023, 0x2d2cb952, 0x61583808, 0xdb8cab2a, + 0x9528e21f, 0xf01558ff, 0xbfb0ef31, 0xf66ace91, + 0x0de8edc2, 0x726f75c2, 0xe9a6d88c, 0x08566d9e, + 0x78747d76, 0x3b59f5af, 0x712e0495, 0xe69a31ad, + 0xb8b2219e, 0xe8fb400c, 0x0a563156, 0x2e4719be, + 0x145d6ec6, 0x2db7e400, 0x5b98599b, 0xcbd7b30d, + 0xf317dac3, 0xc8a4dda3, 0x4578b8d4, 0x2f3d011a, + 0x86f30242, 0x0c40b79b, 0x8bf4d12f, 0x07f1dfe3, + 0x2573e8a0, 0x9ed44780, 0xe73ab2ad, 0x5bc1ff82, + 0xa93d8c10, 0x2c53f221, 0x6bdcc01c, 0x64660fc5, + 0x80539eea, 0x302bb3bf, 0xdfa7b28a, 0x122a5316, + 0x6715b038, 0x23b7a887, 0x8d479bfb, 0x54ca95f3, + 0x85d8283b, 0x38704f26, 0xcb6d30e2, 0x766075f5, + 0x7b134605, 0xbed5389f, 0x20116bb8, 0xbbaa72ea, + 0xf4cdd9ab, 0xa5c5d829, 0x02c79931, 0xc513cf6d, + 0x078af118, 0x003986ef, 0xfb046b02, 0x8056e960, + 0x35fcf612, 0xbc4f1480, 0xb25a81a8, 0x13adc516, + 0xe3d57e06, 0x6e17904f, 0x8579e150, 0x5be5335e, + 0x91e51add, 0x6472d95f, 0x1855f3a5, 0xfe87f775, + 0x3e697fe7, 0x16a74175, 0xf33f4931, 0x72ede223, + 0xa0ce98c7, 0x87c0fe9a, 0x3828c479, 0x2bc55330, + 0xcb2e8cb7, 0x11775a0c, 0x0f99242d, 0x620258d5, + 0x6e5704c7, 0x1f821f51, 0x2d52d551, 0x6dbe4c20, + 0x63547624, 0x3662c46e, 0x5c84fe0d, 0x37e1ecdb, + 0xd4f543b3, 0xa5e0b6a0, 0xd8acca14, 0x0ed788df, + 0x145d9193, 0x00589986, 0x6bfa6c85, 0x721816ff, + 0xd148e0d9, 0x3180b903, 0x9d1b99f2, 0x348946db, + 0xf0a605c5, 0xf85044af, 0x5f07a66e, 0x05aadf49, + 0x3e09d30d, 0xe9d8f881, 0x6b5ebb38, 0xcd8db1ae, + 0xda24e06f, 0xf5fe635c, 0x4f0f56d8, 0x5893db64, + 0x58d2f27d, 0xa562ca4d, 0xf158c9c8, 0x90262f46, + 0x483d253a, 0xc83d8136, 0xb015f31a, 0xaf03425d, + 0xde6010cc, 0x11fddefe, 0x1c64cf78, 0xfa5294bb, + 0x0be3c5da, 0xd7514771, 0x69e2b4cf, 0x680b14e5, + 0x19284641, 0xf0a17660, 0xbf782cee, 0xc718a7e5, + 0xa7c245df, 0x48f444f3, 0xdf20562c, 0x19e68b1e, + 0x2c8781b4, 0xc55c4e09, 0x75325b6c, 0xc7778332, + 0x329c46a9, 0x19a377fd, 0xa129af6f, 0x583baa01, + 0x2175a652, 0x84ae7a30, 0x460978e5, 0x2f65c7bd, + 0x767e1f24, 0xd64e558d, 0x65ca2b8f, 0xc1497e1e, + 0xfc796a68, 0xb9857c92, 0xb258a87e, 0x26521920, + 0xeceddbd3, 0x9b601aa4, 0x64d93518, 0xe9b4fb00, + 0xbbe81710, 0x250ec14a, 0x5372b49b, 0x31569029, + 0x7ca2ace1, 0x22ada7bf, 0x020e482d, 0xdc372db5, + 0x14a98db2, 0x38444921, 0x42fb59d5, 0xb5488716, + 0x3b1281fd, 0x8e2dc654, 0xef55acc6, 0x3125db61, + 0xbf600343, 0x50e76b36, 0x8f381c2b, 0x0e6f2172, + 0xcc0e0219, 0x1b61210a, 0xa6a918b3, 0x3b1dff2e, + 0xd1f23995, 0x9d00a692, 0x179a4d1f, 0x0e816ae1, + 0x51dc48e2, 0xceeb5aba, 0x948511c0, 0x6b5ff1d9, + 0x6a4abdc2, 0x34e9c74d, 0x65e3cf6f, 0xb86f1228, + 0x7405f671, 0xea9af0ac, 0x8b955b4e, 0x7e52d8e7, + 0x5948e9d2, 0x588693a0, 0x56bce808, 0x79d97095, + 0x8c20f6b4, 0xb248f0bf, 0x49ada670, 0x02aaa2e4, + 0xd0c27ecc, 0x1eb646c4, 0x8cb75096, 0xc16ab826, + 0x6fe1e039, 0xce22b587, 0x41a83917, 0x278e33b0, + 0x0df9670b, 0x4bdbb7ec, 0xe7abd1a3, 0xa535ea14, + 0x8b6d53c3, 0xb6da14d4, 0xea91c661, 0xa1693463, + 0x48e7b511, 0x28333684, 0x7255dd77, 0x036fc870, + 0x6fa6e4c9, 0x509fee27, 0xc8ba0209, 0x01382fcc, + 0x0c366f52, 0x072ef751, 0x835726bc, 0xeefc8f06, + 0x4e543204, 0x822551c5, 0x647a534e, 0x0259cc37, + 0x9e6a90f7, 0xdf09430a, 0x3a93206f, 0xf08860c6, + 0x7f1a2440, 0x5835201d, 0x8dd0819a, 0x6688f7cb, + 0x1f65d5ed, 0x81af9f50, 0x37341627, 0x80444f4e, + 0x4b1b0ce3, 0x570901b9, 0x1164f900, 0x55bd4bd8, + 0x05be2d51, 0x9c7229dd, 0x245abf2b, 0x1e8f50ca, + 0x0cc58442, 0x55bdb522, 0xf39a5444, 0x1856d135, + 0xb99b4cd6, 0x2409ffd0, 0x588ddf1c, 0x0bdf5202, + 0x8e7b7dac, 0x9e0d2e24, 0x7c519b18, 0xb60f5839, + 0x5bf4604c, 0x4144566a, 0x0f1ff011, 0xeea8165b, + 0xa9f62d45, 0x9813a593, 0xe9a60409, 0x1d355581, + 0x99354f2a, 0x0167c44f, 0x0fb8231a, 0x2140f3da, + 0x2339db93, 0x91fa4511, 0x9e9e8ddf, 0xb4b43f1f, + 0x4e915b6a, 0xce05c220, 0x77ba118f, 0xa9c0bd44, + 0x3ff6ef33, 0x7c6cbd93, 0xd1d3071a, 0xe62e0eb5, + 0x4b1baab8, 0xd5905210, 0x959b3b78, 0x8e808e87, + 0x197650f3, 0x36f5b821, 0x8c1b7992, 0x1e2ee053, + 0x074f57db, 0xb0004ec4, 0x6ae1d4ff, 0xdf10430c, + 0xdab93503, 0x60c25839, 0x9636d4ac, 0xa92bfd3c, + 0x65ee27b3, 0x8d30f047, 0x445d627c, 0x48e0e0d8, + 0xde3c6596, 0xff4be906, 0xd689497b, 0x2bd0ef38, + 0xa47e2d02, 0x0ad34c28, 0x21cbb74a, 0xc06ffebc, + 0x7b8b844d, 0x4249381a, 0x0e019cd2, 0x70f47378, + 0x37d1d969, 0x119ea3bf, 0xd48c6f2f, 0xb07cbb95, + 0x5fdf6e50, 0x3c811846, 0x51584b9d, 0xe21ac784, + 0xb9bee497, 0xfd4e44cf, 0xfdd14526, 0xdaffba37, + 0x664089b9, 0x810054dd, 0x4196d34b, 0x7673e608, + 0x8de2a38f, 0xb2513f03, 0xed2d064c, 0x927853ce, + 0x05646afc, 0x75935f03, 0x772a59c1, 0x237e85a0, + 0x2770cc2e, 0x335b1e63, 0x24610dc4, 0x8658a909, + 0xf53bc839, 0x89b36a82, 0xfe6227bd, 0x7765fa68, + 0x61c6c1f2, 0xdf5c28f2, 0x7bf6ac4f, 0x5f422e01, + 0xee6d2660, 0x05c15302, 0xf99b82b6, 0x7d591269, + 0x52fb0b79, 0x299bd507, 0xf696db80, 0xc83360e2, + 0xfdca2ab8, 0x891b244b, 0xd4836793, 0x4044ab47, + 0x77c6c06b, 0x64447b6d, 0xce8a026f, 0xa6a5ebcf, + 0x8675f469, 0x3e91c935, 0x36318f4e, 0xb3596bdd, + 0x28c0a114, 0x9d0b1da5, 0xf37837df, 0x792dcf74, + 0x590e9fd1, 0x301493c0, 0x87ba74ca, 0x384bc17f, + 0x5c259022, 0x9816c8ba, 0xd0e2b1aa, 0x88c885c6, + 0xa3119272, 0x91822f5d, 0xcc775eb1, 0x73627504, + 0xa0d61b38, 0x0eaeb4eb, 0x7523a3cb, 0x5a358200, + 0xba247986, 0x31dc19f9, 0x87371fc1, 0x6c255530, + 0x854cbab0, 0x6d061778, 0x63853aac, 0x61d2798d, + 0x1b14ed4f, 0xe680f141, 0xccbde100, 0xaf97feff, + 0xae1620b4, 0x7520b7ca, 0xd4864612, 0xb6e97e97, + 0x390f7c3c, 0x8393de45, 0x7dfbb090, 0xa62b4e79, + 0x89d4ff79, 0x7f6cb41c, 0x8c3d045b, 0xad13e0be, + 0xc941ce86, 0xba2b48dd, 0x683239a9, 0x21bcad12, + 0x5d92afa1, 0x1927068e, 0x83bfcc55, 0x813e9730, + 0xe3d9ddb9, 0xf08b1f2b, 0xa9402271, 0xf61768ec, + 0xe158e1d9, 0xedb72e85, 0xd8692051, 0xb9a6f89b, + 0xdff617c2, 0x5701c322, 0x9f839e1c, 0x8acb8e16, + 0x9d4b8870, 0xfb9a5b25, 0x62b45032, 0x79ccac62, + 0xf6ae3428, 0x93df34c8, 0xf04fc1e8, 0xed3ee96c, + 0xc910d298, 0x86456ca3, 0x1bd77c25, 0xfa1ee14c, + 0xe0b41ee2, 0xc98a0039, 0xedf4740a, 0xaa3b09c2, + 0x418bb017, 0x08b19648, 0x3764b08b, 0x5b6253c4, + 0xfd7dee90, 0xd5f3c0ae, 0x1fb452d8, 0x76937c5f, + 0x86a7602e, 0x5f6297ba, 0x418646c5, 0x4a44baae, + 0xf291d068, 0x484e1284, 0xd499cfc9, 0x1a6c821c, + 0xef31f9ce, 0x67afce23, 0x2d5ec400, 0x57bf4203, + 0x54fe7df2, 0x549bf043, 0xe54a6b9f, 0xd7b9c718, + 0x2ff04b4f, 0xd57a44d8, 0xe46a33aa, 0x01a15a80, + 0x87f99bcb, 0x61731b51, 0x9a40183c, 0x94dddddf, + 0xa64bf9c1, 0xbdd83c20, 0x3124ba09, 0x3cfece51, + 0xe3096575, 0xf51ca11b, 0xd8b01462, 0x684ecfaa, + 0xc88fcd28, 0x3c2c9222, 0xaf656df4, 0xb9b2ccd8, + 0x4f11d16f, 0xe640e0fa, 0x08a4bcb3, 0x9159768a, + 0x1cbc6291, 0x61741dc8, 0x67bfc84a, 0x13d2f920, + 0x2f9e3a67, 0x3a052fad, 0x8586c74b, 0x4830fc8d, + 0xe0325e0d, 0x56d34524, 0x85710ff3, 0x5c2e368c, + 0xef165e27, 0x099bc507, 0x29e2a5d3, 0x1e03e4be, + 0x552aa444, 0xc56cd34c, 0xee54ad1d, 0x15212944, + 0x73b839d5, 0x5eb06362, 0x1fe82278, 0x4edd9784, + 0x12047386, 0xa46defd8, 0x98975ed0, 0x5b7843f1, + 0x76770324, 0x8ac36c50, 0x9c103dea, 0x7bc77f4c, + 0xe57cb4c0, 0xbcdd4b78, 0x86e0c93a, 0xe416f211, + 0xd529c7d2, 0x7688e7be, 0xa3445436, 0x8444e75c, + 0x3de7f15b, 0x419bdccd, 0x7e93e2ea, 0x98dc95ac, + 0xb7e9abd8, 0x30c5d5b8, 0xdc603ff7, 0x4e62563c, + 0xc9a31230, 0x7dadd663, 0x566f85f4, 0x2de500d6, + 0x506bc0b7, 0x13e1d310, 0x19cc041d, 0x848ef8b5, + 0x14ae1696, 0xdfb2cf6e, 0x86a68d7c, 0x3b25c484, + 0xfcf2367c, 0x0f99d40a, 0xac1eb1dd, 0x5c58e31c, + 0xf9552270, 0x4bead251, 0xa51ba300, 0x47d9df78, + 0xebc1fd0d, 0x2b4ef26f, 0x510046f2, 0xcaefd6ed, + 0xbc49c9a2, 0x72995df5, 0x68f86878, 0x13d324f3, + 0x9c30e08f, 0x4c553357, 0x403fcc91, 0x53a7a7fa, + 0x751afe50, 0x9629e32e, 0x807e9cbc, 0x61f205b0, + 0x67f32794, 0x7feb361c, 0x2dc24e39, 0xea0ce153, + 0x4d0edd08, 0x281d41ec, 0x5f780de1, 0x66f5a54f, + 0x438d66f9, 0x312233a8, 0x3f1e9847, 0xd67f75c9, + 0x49d1b403, 0x8ab4bf04, 0x20707827, 0xd75bf764, + 0x3db0d945, 0xddb48bea, 0x33b5b22b, 0x9dc9d872, + 0x125aaa11, 0x23016e90, 0xb3db1977, 0x067cb9c0, + 0x608cf93a, 0xf4347d6e, 0x937f2d9e, 0xdcb1a008, + 0x913cd8ed, 0x54a55ab3, 0xf6ee9fb3, 0xb2be1711, + 0x82e33f91, 0x228dc8e3, 0x2c8dda07, 0x6a14cb0b, + 0x37cba2ff, 0x387e12e9, 0x34c600d7, 0x5b517118, + 0x14a0801c, 0x64e9882b, 0xa33bd7ae, 0x34f67231, + 0x9018d47b, 0x6afef0e1, 0xe55ab101, 0x13ab579b, + 0x5cae1482, 0xdfa2be20, 0x6c0116c4, 0xb60110b1, + 0x31ea72d0, 0xc501e008, 0x4893864e, 0x21ae1415, + 0x476087fc, 0xe4d3a6b1, 0xf3c651ab, 0xd0f8407b, + 0x75147d86, 0xbc473f0d, 0xf6fb5abd, 0x06cfda8c, + 0xd113fa66, 0xb1726f00, 0x5e7d6a7a, 0x4e240a77, + 0xd542b170, 0xc1791134, 0x36611e91, 0x9f3265e1, + 0x429ff7ff, 0xfc8d6c18, 0x7ea29b45, 0x6ed89d8c, + 0x99023f7a, 0x8fde3a83, 0x95c6c6e5, 0x027b7d9a, + 0x9b3eaeff, 0x73ddeeea, 0xe9739512, 0x8e35626a, + 0x048c535f, 0x8dfb5e76, 0x102580d3, 0x40d1c76d, + 0x4ede7540, 0x2f045db3, 0x6f1f2ff6, 0x5e5c6936, + 0x633d070c, 0xbc91762b, 0x2e5be68d, 0x1623b35a, + 0x687dc993, 0xa3f63efe, 0xa6564723, 0x84fe7eac, + 0x52f01836, 0xcac1838a, 0xad28e22d, 0x80b6ebc5, + 0x44611fe6, 0xbd77a2b3, 0xbe887160, 0x0bc91072, + 0x36f3771c, 0x119c644e, 0xa86ae2e4, 0x9cb9705a, + 0x66c78689, 0xbfc8f95f, 0xcb978dd6, 0xd2d13205, + 0xfdbc2313, 0xec6698f9, 0xcc8edd14, 0x908ad80c, + 0x48a3b200, 0x9febfd7f, 0xfbde5b86, 0xf3378495, + 0xe2b872f2, 0x7487a751, 0x62e485ab, 0x614a4be5, + 0x031c4d79, 0xe4b7736d, 0x82a23999, 0x1be8151d, + 0x422e7431, 0x116029e0, 0x876bd40c, 0xb77200cd, + 0x78f73058, 0x2c9d85ca, 0xcc9d781b, 0xa24a2518, + 0x6afd5cd2, 0x6a403d39, 0xa0380dfb, 0xd096d5c5, + 0x14134136, 0x1b645458, 0xa3edb6bc, 0x2c4df9f7, + 0x462d7abe, 0xdc30cc65, 0xb0c7c363, 0x633cc318, + 0x7330fb01, 0xa9459131, 0xf7ed26ac, 0x70afc670, + 0x4ecda1ad, 0xcf25e69b, 0x780eca0d, 0x3ae26f4c, + 0x2b2fcd70, 0xa76e02b3, 0x0d366a36, 0x380a2800, + 0x1970c343, 0xc9754277, 0x6d0d1295, 0xd065ce3a, + 0x38a13c55, 0x4c23345b, 0xa8390d65, 0x50ef33f7, + 0x64aee72a, 0x6e594a73, 0x4d900d3d, 0xe61abab8, + 0x91738cc9, 0x50188457, 0x0d6071de, 0xbe4bd672, + 0xaa3ebda3, 0x3090cb7d, 0x8f74422a, 0x7aa680e7, + 0x92a9fee2, 0x13471252, 0xe16eeb97, 0xd516918e, + 0x03d2cad4, 0x34ef9338, 0x3c6b99a0, 0x51039a63, + 0x7b935775, 0xb38f12c0, 0xbe641a55, 0xaf253e07, + 0xe3d2d033, 0xf958b031, 0x6357238d, 0xadbe6eb7, + 0xdc380f54, 0xf000ca83, 0xeeb0778d, 0x66aa9263, + 0x20641cf1, 0x61ba52d2, 0xb4935ed2, 0x3ccc973f, + 0x2191f19c, 0x7eb97d03, 0x3ff1649d, 0xb511296e, + 0xdf01ae1f, 0x66b07ca0, 0x7f1d65a8, 0x49de6561, + 0x7176c65e, 0x99fbae8c, 0x194d8822, 0xf2709b59, + 0xc9eb3952, 0x81fd0775, 0x75cd8c06, 0x8a053e1e, + 0x067531cb, 0xd586dade, 0xe1c50505, 0xe5c814a7, + 0x5225bff1, 0x7ad3e55c, 0xc839956e, 0x5ff8cad2, + 0x8b2c17fb, 0xa8aeca4e, 0xbb420e26, 0x8778629c, + 0x609ba6b7, 0x9095646a, 0x2a5b6b94, 0x83269b82, + 0x0125c515, 0xc7921089, 0x118c8972, 0xce192d6b, + 0x745964d7, 0x22aea96c, 0x5dd81fda, 0x22b9c926, + 0x3372cd87, 0xf18f3504, 0x27a1d46c, 0x68c36ebc, + 0xe31489a6, 0xde1d9da0, 0x3864c0e2, 0x1f828a1a, + 0x067cedda, 0x42e4b0c8, 0xad811266, 0x7dc5019e, + 0x8323bcd6, 0x3a2dca21, 0x12cc2427, 0x18c0eed0, + 0x50344423, 0x2723890f, 0x58316b91, 0xc3ecd0b6, + 0x3f23794c, 0x31e326fa, 0x9c894c83, 0x2b051e59, + 0xdffa05be, 0x934f1ca6, 0x992a3056, 0x64744f25, + 0xf917da6d, 0x3ff73ad5, 0x1b192c25, 0x1fa4861b, + 0x99f7319b, 0xd7f14c0d, 0x3a59d0be, 0xd00faef3, + 0x920234d8, 0xc358666d, 0x1209b81c, 0x922b826e, + 0xe420227a, 0xe935fa1b, 0xc720c105, 0x4d2b24ae, + 0x1ba29c2c, 0xd9dea5f1, 0xaac12ee9, 0x5b9995ad, + 0xfee12188, 0x330a2e8a, 0xcae4c659, 0x3db1daa8, + 0x93e01f23, 0x1806d738, 0xf85b17c2, 0xd5000fc8, + 0x7f999185, 0x90f84116, 0x12bc69d2, 0xa427b36d, + 0x52706ad7, 0x6554e7eb, 0x656f04cd, 0xb732fa55, + 0x1e001fb6, 0x9515c121, 0x991746a0, 0xbfd8698d, + 0x0a4b6311, 0x3eea4504, 0x7da833c5, 0xb85ff51e, + 0xcb0d7c8f, 0xf9f2ed9d, 0xdf5b6980, 0x809e4200, + 0x34ebc9b8, 0xc9884fc5, 0x5546af40, 0x7aa82e84, + 0xf30e074f, 0x4686763e, 0x26e09a50, 0x9e81c298, + 0x157e3306, 0xa3aa13c4, 0xb14fbe0b, 0x06e3340c, + 0xe4addcdb, 0x647a2278, 0x74f3536d, 0x09891339, + 0xd4cdd43a, 0x04dc1e26, 0xf349802c, 0x4cd759a3, + 0xccfac681, 0x38671571, 0xe4b736d6, 0x6b9cde99, + 0x98d6315f, 0x97b521ac, 0x00e6a544, 0xb9b7e5b8, + 0x2f622b1f, 0x46c0833e, 0x977631e1, 0x918fe584, + 0x358ada54, 0x22b9145c, 0x599b1c00, 0xce04a2e6, + 0xdc25c77f, 0xfe36b8ee, 0x4ee6e51f, 0x26d79fa4, + 0xf2eba569, 0x9d44ec06, 0xe391d6a3, 0x60267abc, + 0x037582c8, 0xfb71db7a, 0xc7ebdaf7, 0x3f77de9f, + 0xa2791ef6, 0x7692cf99, 0x1d42d301, 0xe57ecfde, + 0x6b14a1b5, 0xf4e7f842, 0x9b1cd83f, 0x1e1425d1, + 0x791e2f88, 0x60be64e6, 0xbc0f34a1, 0x435bb965, + 0x981c911c, 0x5d0a1803, 0xfe495d2a, 0xcd5d61ca, + 0xf970cf41, 0xedae50c5, 0xf7172a4b, 0xab0563a1, + 0x457f9b9a, 0xa8e9bf24, 0x6ba86586, 0x8b86b043, + 0x0e30d985, 0x42aff4b8, 0xcf4defbf, 0xf32824c7, + 0x7589e433, 0x45a06efb, 0xfa83bca8, 0xc0817868, + 0x20a34ab0, 0xb9637ff7, 0x8aa9ba88, 0xac799c8d, + 0x9862097a, 0xdec64a5d, 0xeeacdc0f, 0xc13a24ee, + 0x8885e0e9, 0x3cacb882, 0x09957561, 0xfbf43039, + 0xf949e1fe, 0xa79ab300, 0x0118dbbb, 0x6f53833c, + 0xa88db1e4, 0x94108270, 0xaa3bd807, 0x8170c5f6, + 0xc2f3019d, 0xc1d5c85c, 0xcf565ab9, 0xfabba490, + 0x8ff287df, 0x5683d997, 0xe8455d79, 0xa86d9b71, + 0x1178099d, 0x184f70fd, 0xd0885393, 0x7b429e4a, + 0x00212574, 0x3b1ec7c6, 0xa8713e0e, 0x6d719ec5, + 0xcc9a1210, 0x8a5bb3e4, 0xd96fabc1, 0x8cc4b975, + 0x71dc05d7, 0x0026b122, 0x4a985f80, 0xc0319094, + 0xf28d7710, 0x47c8b4b8, 0x01f02a5f, 0x1f5aeae0, + 0xc9591f3d, 0xfce70216, 0x51aee39d, 0xb4f12359, + 0x327f1d53, 0x6d6b7b27, 0x2d5763bd, 0x65058235, + 0x8763e4c4, 0xb58110de, 0xfea2d06d, 0x55b0e6bf, + 0x94490e27, 0xeb056cde, 0x739dac88, 0x1e9bd42c, + 0xd1312fc0, 0xc78807b5, 0x6d1cc64c, 0xb1ec7b47, + 0x69ed55b5, 0x5e377672, 0x052763b1, 0x441c5ad2, + 0xa19b308f, 0xdf50835e, 0x826a07f0, 0xe237ba75, + 0x373328d0, 0xab1567be, 0xfcf090e8, 0x01b08f61, + 0x6c6cff71, 0x55ff8530, 0x4fca2fac, 0xd8026b81, + 0xbe5dc2fa, 0x7a045eb4, 0xa33affdf, 0x515359ae, + 0xb2a5970d, 0x79cac5b8, 0xab7d508a, 0x6a9cfdba, + 0xab891994, 0x03031abd, 0x5a386953, 0xb0d1400a, + 0x7a067e6a, 0xa215992c, 0xa37f3634, 0xa864c69f, + 0xd7d5f6f3, 0x7105b091, 0xdda56d97, 0x46693f32, + 0x76f6ac3a, 0x277613a9, 0x684ffe3a, 0xc8ffc0cc, + 0x44cb45ab, 0x0b6d1684, 0x1c929e9e, 0xfa375422, + 0xb0fd3ba6, 0x01ac3322, 0x2ff3da35, 0x5b1d5c81, + 0xe43d65e7, 0x0677b2d0, 0x9eb688d0, 0xf16b0c76, + 0x8d631991, 0x66e970f6, 0xbea1b969, 0xa69b23ae, + 0x0d4d1ee8, 0xeab5153d, 0x13cbd99d, 0xdba6a20f, + 0x79c15708, 0x36d70762, 0xaea5be83, 0xf9d1f9d2, + 0x289261e3, 0x42e78643, 0x4978ba45, 0x62973804, + 0x943ae9c1, 0x720a74cc, 0x73b83f39, 0x29023556, + 0xc1fca75f, 0x49f6402b, 0xc379c97c, 0x8d16a538, + 0xc6a6807a, 0x49fd563b, 0xb8e07e56, 0xb56718e3, + 0xa32753f2, 0x9368d9a5, 0xbe964ed3, 0xd0887abf, + 0x68ff1701, 0x2eb03c4c, 0xa9033a35, 0xa1975045, + 0x22398290, 0xdb5f88f8, 0x7ad83735, 0xfebc5905, + 0x392d2bf6, 0xb28fd56e, 0xa42d3f39, 0x8cbb1bd7, + 0x94f2da15, 0x6e1113ef, 0x01a79537, 0x34a61fc2, + 0x2d34bcdb, 0x92a89b1a, 0x4d8e13b0, 0x679179e6, + 0xcee7846e, 0x0635fa0b, 0xad431819, 0x18dfe09f, + 0x98b59646, 0x5b530a3d, 0x501a351d, 0xa5dda362, + 0x02f96e2f, 0x2f02304c, 0x4b5f5683, 0x035ce77f, + 0x5152e01d, 0x814b554a, 0x0cc9b824, 0x6cbe65e7, + 0x6d7c55aa, 0x2f2f230b, 0xa3961541, 0xb7e1fb47, + 0x36cdaac2, 0xa3549fa1, 0x6e843a72, 0x885c6e5a, + 0xe4d830bf, 0xecc4ef0f, 0x49ec6778, 0xfa473918, + 0x6fbd52df, 0x2d601bac, 0x1927d18e, 0x9767d10f, + 0x33455911, 0x39f4a11c, 0x5da36f3a, 0x3a6acb8c, + 0x26dfe109, 0x75534f3d, 0xf9f524a6, 0x11621948, + 0xafa3b70a, 0xc6e95bb5, 0x09ea9691, 0x86422021, + 0x8abd8ae7, 0xd4a9257e, 0x63fcfd26, 0x62af01a0, + 0x9a522121, 0x6035d404, 0x71dec5e5, 0xf52d7713, + 0xab274c7d, 0xfa1f4cf9, 0x3590f75c, 0x2b21b464, + 0xc5fb887b, 0x68930c16, 0x711f5ee2, 0xeeca896a, + 0x3f4e4748, 0xd6ebcede, 0x46861136, 0xbfde5f95, + 0x84475d44, 0x86c51fa4, 0xfba7e0fe, 0x2821131e, + 0xb88099dc, 0x17c1c804, 0xf3928b6c, 0xfb12730f, + 0x7bebef29, 0x77533cc2, 0xf61d53e3, 0x97c52679, + 0x70b92c59, 0x0c52f0c8, 0x1c868739, 0x72fb8a61, + 0x5dfeb379, 0xa3ddb8ae, 0x304540ad, 0xb9027ae8, + 0xb118e925, 0x4af447ab, 0x1f08fabf, 0x6bf871cd, + 0x4dd58222, 0xb3e99379, 0xc50f7ad3, 0xdc6e9981, + 0xf8c54345, 0x04cc38f5, 0xbc339ca3, 0xd00643dc, + 0x2fdaa410, 0x1fb648a0, 0x8d263f0d, 0xe0ccd7db, + 0x0e8b4739, 0x948c1ce1, 0x6517dc67, 0x84360745, + 0x15264166, 0x122930c4, 0x63889fff, 0xf86d6142, + 0x0070abf1, 0xf9c2aa3c, 0x2ebf80db, 0x4bbcfb46, + 0x1bca082f, 0x44cf8e0d, 0x80c2bf73, 0xb040fd58, + 0xa014d4e4, 0x752d74f1, 0xd60c6daa, 0x22450372, + 0x7ae80ec7, 0x9395e303, 0x6bac84cd, 0x7cdfb04b, + 0x5056b882, 0xa3b015a7, 0xb3752d38, 0x11bebcce, + 0xfe330827, 0x28f010ca, 0x2c1ec0e1, 0xe921a365, + 0x0af770b7, 0xc1b5cf65, 0x3694b44e, 0x5d3e9718, + 0x18c1fcf3, 0x6a81c8f4, 0x542a0afe, 0x5ef7acf5, + 0x3fed458c, 0xbd0e32f6, 0xb5175fb2, 0x4c83dc6b, + 0x1f238675, 0x8df4a26b, 0xe114ad19, 0x7359e392, + 0x44ce1986, 0x7ce3f831, 0x7a064d48, 0xe1309c21, + 0x343d2763, 0x9ac22765, 0xa9d39781, 0x0e771707, + 0x2094dcf2, 0x83b214cf, 0x29e8bb49, 0xd5eb9775, + 0xca9fa814, 0xa0d05e76, 0x8cbaff57, 0x7ba1279d, + 0x8cb413d7, 0x81e9c63c, 0x4b67553e, 0xc5be4306, + 0x9404f216, 0x7d98c4a0, 0x30ad3d03, 0x44cf2f12, + 0x5a58c278, 0xec414c18, 0x7729b2b0, 0xc9686d46, + 0x9d9a743d, 0x6fafe79a, 0x2ba77086, 0x91797abb, + 0x34463a5a, 0x868ce6aa, 0xd0c3b0c4, 0x2ec6842a, + 0xfdf9beb7, 0x21aec0ec, 0x50651501, 0x4ddca1da, + 0x62a501c2, 0x65c86a4a, 0x2002be91, 0xdf1e15bf, + 0x4ef3d79c, 0x0957a1f7, 0x869ce566, 0x64c21b6a, + 0xbf46deb6, 0x0474ce95, 0xf98515e6, 0x4a46e10b, + 0xc73e334e, 0xd3064659, 0x2314f759, 0x9eaf1885, + 0x355703c1, 0x7fdcffe1, 0xa5262c9e, 0x7fa191d3, + 0xc4eb661a, 0x4d5fbbb5, 0x169670a8, 0x2ddf976a, + 0xa3edd956, 0x1a55b25a, 0x8552872c, 0x4feaca6a, + 0xfc5e69aa, 0xab345774, 0x829c8f58, 0xb6c74537, + 0xe8556b02, 0x96d39f1b, 0x7bed65bc, 0xc79f8d9a, + 0xdacc2b32, 0x41b3698d, 0xe734d16a, 0x4aea7d43, + 0xa164f1d7, 0x8cb73414, 0x084586b8, 0x481530d2, + 0x6a3be457, 0xb2a8cc87, 0xa552ce0e, 0x00210190, + 0x19fb8b78, 0x3716a7dc, 0xe4c1ab30, 0x6828a064, + 0xf2ec97f1, 0x653bb883, 0x1d64afc1, 0xb4a8db3e, + 0xcf1551c9, 0x9e07b3fc, 0x2fe26f69, 0xb231dccd, + 0x4bb1c02d, 0x68dc3567, 0xc90e9214, 0xed98f214, + 0x8cee4720, 0x2b1bf6fd, 0xda748ba4, 0x7e33659b, + 0xa5423ad1, 0xf4a1b910, 0xcf02cc8f, 0xc351d2fa, + 0x15213c25, 0xe375ae89, 0xa0ad4705, 0x099d0255, + 0x5e560837, 0x4f7975b1, 0x4226fd39, 0x0f150f84, + 0xb35053e7, 0x66ec2593, 0x8b3d2a9f, 0x500df7fd, + 0x8d807ec3, 0x1546c058, 0xf1b36953, 0xf641b4ab, + 0xa2c4eee7, 0x80874554, 0xa4cffb4a, 0x47bb038b, + 0xdc85bc48, 0xf264af42, 0xfed4a8c8, 0x4545f078, + 0xb48cbb08, 0xb38cb4d8, 0xa5d2f87f, 0x7afc6080, + 0xdad36053, 0xb2cb85d7, 0x435601c3, 0x5fcd6c46, + 0x4ff290f9, 0x28fe52a4, 0xa8d2953c, 0x969717d8, + 0x111a060c, 0x81275f6c, 0x3ba503c0, 0x5d1b8f00, + 0x8ed424bd, 0xa7aa2a6a, 0xe8b077b1, 0x7360c3c1, + 0xe4cfea1e, 0xc9175efe, 0x31652f35, 0xa4ba80b4, + 0xdef58c18, 0x3f50a8b5, 0xb3069a46, 0xb59c812a, + 0x9d01a0d8, 0x5195e7cd, 0xd5cddca7, 0xf584fdd3, + 0x7c37aecf, 0xf724feda, 0x517b5369, 0x5a242396, + 0x7f897c75, 0xaa43aaa9, 0x1e0d3a27, 0x17d3530b, + 0x9684c496, 0x9b177e63, 0x89b0c002, 0x2762754a, + 0x1ce24045, 0xe9d3f9f5, 0x0b9c9008, 0x53d8ff66, + 0xa432f4aa, 0x3b0ef1a0, 0x0cb09e9e, 0xb141e6da, + 0x1abaef24, 0xbc4527fb, 0x6d64663e, 0xb81f07db, + 0xc57f0569, 0xb3ccb323, 0x37c5ccb6, 0x5a48a5a3, + 0x5f202e66, 0x249f5c48, 0x3ba3d909, 0x6775b383, + 0xafffe78a, 0xe3b9a058, 0x4a173160, 0x80a37ce0, + 0x1fb5d953, 0xba234f01, 0x650b070b, 0xab0e08f0, + 0x12f58c9e, 0xd3adfca6, 0x7e7aa5e9, 0x4c8d3e40, + 0x645381ac, 0xc80b92b7, 0x52824b6a, 0xfc6650fa, + 0xe9875875, 0x00e440e4, 0x7e7a385b, 0x1d036de1, + 0xc229f901, 0x1cdfe89a, 0x36b31fc3, 0xa409daf5, + 0x1ffec98a, 0x34f2d356, 0xe39323f5, 0xcfd0edc4, + 0x544dff14, 0x96561b29, 0x7e318225, 0xca283e56, + 0x30e6f445, 0x98e1a40d, 0xbb9cdb9e, 0x61ef64ac, + 0x36b93117, 0xb6d8db51, 0xf56ebaf0, 0x15fc55d0, + 0x9f336d3d, 0xf04ba9c1, 0x45718234, 0xa5361c6a, + 0x08c955df, 0xd1911bf1, 0x79515ea6, 0x39072fd5, + 0x72503e65, 0x299b3b0f, 0x5ac12cda, 0x086413a2, + 0x3c212316, 0x9a0a67dc, 0x478067ad, 0x03263094, + 0x191f832f, 0xb0574027, 0x3c1c4b37, 0xae76fef6, + 0x35119743, 0x246bae44, 0x43714400, 0xdc73a15b, + 0x58fc478c, 0x2e853900, 0xb4349195, 0x525ff5ab, + 0x816504da, 0xa3410190, 0xc518b2d4, 0xc200e979, + 0x2da345fa, 0xaa1e13db, 0xc74ac107, 0xb40085b2, + 0xaaacea2b, 0x6fdfc4b2, 0xc65b4e27, 0x2263ac78, + 0xbf122069, 0x2b9ad054, 0x63daa966, 0x8b84eb31, + 0x68f9b24c, 0x2a56c2d8, 0x842c9c42, 0x371509da, + 0xd261b01b, 0x5a8ceacc, 0xc96ec155, 0x400d2767, + 0x3b087aec, 0xfdf4ada0, 0xe8608529, 0xb7a63a4a, + 0x5a8f086c, 0xbd578c4f, 0x9ab4b028, 0xdeacb315, + 0xa8eafb1a, 0x576b7db0, 0x513a0804, 0x03cec626, + 0x0e2fc89d, 0x88ee7af0, 0xcfbc25b8, 0x0ebe884d, + 0xb61da6fb, 0x997631bf, 0x8b9e0c66, 0x2141918c, + 0x2731586f, 0x2db3c681, 0xfd6d5c37, 0x00873fac, + 0x480e2c71, 0x9d23681a, 0x150f2b98, 0x2a61f9d6, + 0xb172abd5, 0x0e652dcb, 0xa7369fdf, 0x9336fd0c, + 0x862164aa, 0x0aad4e83, 0xfa484dc3, 0x0ac9407d, + 0x0d652975, 0x0e1c3834, 0x8fe438a5, 0x2f30e7ac, + 0x7821d6b1, 0xd7dd6497, 0xe79bf71b, 0xa69c7f70, + 0x8b935026, 0xe263ffd4, 0x3eb911cd, 0x11b4e9b1, + 0x682ae6da, 0x791a8c98, 0x3ffa20ea, 0xc9bc62e1, + 0x462ab761, 0x5668a7f5, 0x2db17b75, 0x06cf7333, + 0xccfecf2c, 0x91ece6a3, 0x4fb67a8f, 0x7bc3e477, + 0x9d6606a3, 0xec2c7c02, 0x5600620e, 0xcea8fca3, + 0xc1dd7cb7, 0x3232f262, 0xeff6ee7a, 0x95dd43f7, + 0xfc017fb0, 0x88dfb2fa, 0x0fb857cc, 0xab2704b4, + 0x50c16dd9, 0xecd37325, 0x2fe34706, 0xb76d7960, + 0xc892b7da, 0x1943d334, 0x79b4cbf5, 0xd2d8459f, + 0x1418ad70, 0x5516926f, 0xd879cf48, 0xf68b5c6f, + 0xa8d71c2b, 0x5b25b2aa, 0xdea9cc34, 0xc63eddf1, + 0xf4ef0709, 0xaf7ebcef, 0xe025cbdd, 0xe958bd96, + 0x7bfedc85, 0x38ef0fad, 0xcc75abcc, 0xc46b28af, diff --git a/src/soc/intel/baytrail/microcode/Makefile.inc b/src/soc/intel/baytrail/microcode/Makefile.inc new file mode 100644 index 0000000000..bf9e345dbd --- /dev/null +++ b/src/soc/intel/baytrail/microcode/Makefile.inc @@ -0,0 +1 @@ +cpu_microcode-y += microcode_blob.c diff --git a/src/soc/intel/baytrail/microcode/microcode_blob.c b/src/soc/intel/baytrail/microcode/microcode_blob.c new file mode 100644 index 0000000000..496e1a6133 --- /dev/null +++ b/src/soc/intel/baytrail/microcode/microcode_blob.c @@ -0,0 +1,4 @@ +unsigned microcode[] = { +#include "M0C3067_0000031E.h" +#include "M0C30678_0000082D.h" +}; diff --git a/src/soc/intel/baytrail/northcluster.c b/src/soc/intel/baytrail/northcluster.c new file mode 100644 index 0000000000..35f1d13ad1 --- /dev/null +++ b/src/soc/intel/baytrail/northcluster.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Host Memory Map: + * + * +--------------------------+ BMBOUND_HI + * | Usable DRAM | + * +--------------------------+ 4GiB + * | PCI Address Space | + * +--------------------------+ BMBOUND + * | TPM | + * +--------------------------+ IMR2 + * | TXE | + * +--------------------------+ IMR1 + * | iGD | + * +--------------------------+ + * | GTT | + * +--------------------------+ SMMRRH, IRM0 + * | TSEG | + * +--------------------------+ SMMRRL + * | Usable DRAM | + * +--------------------------+ 0 + * + * Note that there are really only a few regions that need to enumerated w.r.t. + * coreboot's resrouce model: + * + * +--------------------------+ BMBOUND_HI + * | Cacheable/Usable | + * +--------------------------+ 4GiB + * + * +--------------------------+ BMBOUND + * | Uncacheable/Reserved | + * +--------------------------+ SMMRRH + * | Cacheable/Reserved | + * +--------------------------+ SMMRRL + * | Cacheable/Usable | + * +--------------------------+ 0 + */ +#define RES_IN_KiB(r) ((r) >> 10) + +uint32_t nc_read_top_of_low_memory(void) +{ + return iosf_bunit_read(BUNIT_BMBOUND) & ~((1 << 27) - 1); +} + +static void nc_read_resources(device_t dev) +{ + unsigned long mmconf; + unsigned long bmbound; + unsigned long bmbound_hi; + unsigned long smmrrh; + unsigned long smmrrl; + unsigned long base_k, size_k; + const unsigned long four_gig_kib = (4 << (30 - 10)); + int index = 0; + + /* Read standard PCI resources. */ + pci_dev_read_resources(dev); + + /* PCIe memory-mapped config space access - 256 MiB. */ + mmconf = iosf_bunit_read(BUNIT_MMCONF_REG) & ~((1 << 28) - 1); + mmio_resource(dev, BUNIT_MMCONF_REG, RES_IN_KiB(mmconf), 256 * 1024); + + /* 0 -> 0xa0000 */ + base_k = RES_IN_KiB(0); + size_k = RES_IN_KiB(0xa0000) - base_k; + ram_resource(dev, index++, base_k, size_k); + + /* The SMMRR registers are 1MiB granularity with smmrrh being + * inclusive of the SMM region. */ + smmrrl = (iosf_bunit_read(BUNIT_SMRRL) & 0xffff) << 10; + smmrrh = ((iosf_bunit_read(BUNIT_SMRRH) & 0xffff) + 1) << 10; + + /* 0xc0000 -> smrrl - cacheable and usable */ + base_k = RES_IN_KiB(0xc0000); + size_k = smmrrl - base_k; + ram_resource(dev, index++, base_k, size_k); + + if (smmrrh > smmrrl) + reserved_ram_resource(dev, index++, smmrrl, smmrrh - smmrrl); + + /* All address space between bmbound and smmrrh is unusable. */ + bmbound = RES_IN_KiB(nc_read_top_of_low_memory()); + mmio_resource(dev, index++, smmrrh, bmbound - smmrrh); + + /* The BMBOUND_HI register matches register bits of 31:24 with address + * bits of 35:28. Therefore, shift register to align properly. */ + bmbound_hi = iosf_bunit_read(BUNIT_BMBOUND_HI) & ~((1 << 24) - 1); + bmbound_hi = RES_IN_KiB(bmbound_hi) << 4; + if (bmbound_hi > four_gig_kib) + ram_resource(dev, index++, four_gig_kib, + bmbound_hi - four_gig_kib); + + /* Reserve everything between A segment and 1MB: + * + * 0xa0000 - 0xbffff: legacy VGA + * 0xc0000 - 0xfffff: RAM + */ + mmio_resource(dev, index++, (0xa0000 >> 10), (0xc0000 - 0xa0000) >> 10); + reserved_ram_resource(dev, index++, (0xc0000 >> 10), + (0x100000 - 0xc0000) >> 10); + + chromeos_reserve_ram_oops(dev, index++); +} + +static struct device_operations nc_ops = { + .read_resources = nc_read_resources, + .set_resources = NULL, + .enable_resources = NULL, + .init = NULL, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver nc_driver __pci_driver = { + .ops = &nc_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = SOC_DEVID, +}; + diff --git a/src/soc/intel/baytrail/pcie.c b/src/soc/intel/baytrail/pcie.c new file mode 100644 index 0000000000..1a2c1ef1dd --- /dev/null +++ b/src/soc/intel/baytrail/pcie.c @@ -0,0 +1,278 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "chip.h" + +static int pll_en_off; +static uint32_t strpfusecfg; + +static inline int root_port_offset(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn); +} + +static inline int is_first_port(device_t dev) +{ + return root_port_offset(dev) == PCIE_PORT1_FUNC; +} + +static const struct reg_script init_static_before_exit_latency[] = { + /* Disable optimized buffer flush fill and latency tolerant reporting */ + REG_PCI_RMW32(DCAP2, ~(OBFFS | LTRMS), 0), + REG_PCI_RMW32(DSTS2, ~(OBFFEN| LTRME), 0), + /* Set maximum payload size. */ + REG_PCI_RMW32(DCAP, ~MPS_MASK, 0), + /* Disable transmit datapath flush timer, clear transmit config change + * wait time, clear sideband interface idle counter. */ + REG_PCI_RMW32(PHYCTL2_IOSFBCTL, ~(TDFT | TXCFGCHWAIT | SIID), 0), + REG_SCRIPT_END, +}; + +static const struct reg_script init_static_after_exit_latency[] = { + /* Set common clock configuration. */ + REG_PCI_OR16(LCTL, CCC), + /* Set NFTS to 0x743a361b */ + REG_PCI_WRITE32(NFTS, 0x743a361b), + /* Set common clock latency to 0x3 */ + REG_PCI_RMW32(MPC, ~CCEL_MASK, (0x3 << CCEL_SHIFT)), + /* Set relay timer policy. */ + REG_PCI_RMW32(RTP, 0xff000000, 0x854c74), + /* Set IOSF packet fast transmit mode and link speed training policy. */ + REG_PCI_OR16(MPC2, IPF | LSTP), + /* Channel configuration - enable upstream posted split, set non-posted + * and posted request size */ + REG_PCI_RMW32(CHCFG, ~UPSD, UNRS | UPRS), + /* Completion status replay enable and set TLP grant count */ + REG_PCI_RMW32(CFG2, ~(LATGC_MASK), CSREN | (3 << LATGC_SHIFT)), + /* Assume no IOAPIC behind root port -- disable EOI forwarding. */ + REG_PCI_OR16(MPC2, EOIFD), + /* Expose AER */ + REG_PCI_RMW32(AERCH, ~0, (1 << 16) | (1 << 0)), + /* set completion timeout to 160ms to 170ms */ + REG_PCI_RMW16(DSTS2, ~CTD, 0x6), + /* Enable AER */ + REG_PCI_OR16(DCTL_DSTS, URE | FEE | NFE | CEE), + /* Read and write back capabaility registers. */ + REG_PCI_OR32(0x34, 0), + REG_PCI_OR32(0x80, 0), + /* Retrain the link. */ + REG_PCI_OR16(LCTL, RL), + REG_SCRIPT_END, +}; + +static void byt_pcie_init(device_t dev) +{ + struct reg_script init_script[] = { + REG_SCRIPT_NEXT(init_static_before_exit_latency), + /* Exit latency configuration based on + * PHYCTL2_IOSFBCTL[PLL_OFF_EN] set in root port 1*/ + REG_PCI_RMW32(LCAP, ~L1EXIT_MASK, + 2 << (L1EXIT_MASK + pll_en_off)), + REG_SCRIPT_NEXT(init_static_after_exit_latency), + /* Disable hot plug, set power to 10W, set slot number. */ + REG_PCI_RMW32(SLCAP, ~(HPC | HPS), + (1 << SLS_SHIFT) | (100 << SLV_SHIFT) | + (root_port_offset(dev) << SLN_SHIFT)), + /* Dynamic clock gating. */ + REG_PCI_OR32(RPPGEN, RPDLCGEN | RPDBCGEN | RPSCGEN), + REG_PCI_OR32(PWRCTL, RPL1SQPOL | RPDTSQPOL), + REG_PCI_OR32(PCIEDBG, SPCE), + REG_SCRIPT_END, + }; + + reg_script_run_on_dev(dev, init_script); + + if (is_first_port(dev)) { + struct soc_intel_baytrail_config *config = dev->chip_info; + uint32_t reg = pci_read_config32(dev, RPPGEN); + reg |= SRDLCGEN | SRDBCGEN; + + if (config && config->clkreq_enable) + reg |= LCLKREQEN | BBCLKREQEN; + + pci_write_config32(dev, RPPGEN, reg); + } +} + +static const struct reg_script no_dev_behind_port[] = { + REG_PCI_OR32(PCIEALC, (1 << 26)), + REG_PCI_POLL32(PCIESTS1, 0x1f000000, (1 << 24), 50000), + REG_PCI_OR32(PHYCTL4, SQDIS), + REG_SCRIPT_END, +}; + +static void check_port_enabled(device_t dev) +{ + int rp_config = (strpfusecfg & LANECFG_MASK) >> LANECFG_SHIFT; + + switch (root_port_offset(dev)) { + case PCIE_PORT1_FUNC: + /* Port 1 cannot be disabled from strapping config. */ + break; + case PCIE_PORT2_FUNC: + /* Port 2 disabled in all configs but 4x1. */ + if (rp_config != 0x0) + dev->enabled = 0; + break; + case PCIE_PORT3_FUNC: + /* Port 3 disabled only in 1x4 config. */ + if (rp_config == 0x3) + dev->enabled = 0; + break; + case PCIE_PORT4_FUNC: + /* Port 4 disabled in 1x4 and 2x2 config. */ + if (rp_config >= 0x2) + dev->enabled = 0; + break; + } +} + +static u8 all_ports_no_dev_present(device_t dev) +{ + u8 func; + u8 temp = dev->path.pci.devfn; + u8 device_not_present = 1; + u8 data; + + for (func = 1; func < PCIE_ROOT_PORT_COUNT; func++) { + dev->path.pci.devfn &= ~0x7; + dev->path.pci.devfn |= func; + + /* is pcie device there */ + if (pci_read_config32(dev, 0) == 0xFFFFFFFF) + continue; + + data = pci_read_config8(dev, XCAP + 3) | (SI >> 24); + pci_write_config8(dev, XCAP + 3, data); + + /* is any device present */ + if ((pci_read_config32(dev, SLCTL_SLSTS) & PDS)) { + device_not_present = 0; + break; + } + } + + dev->path.pci.devfn = temp; + return device_not_present; +} + +static void check_device_present(device_t dev) +{ + /* Set slot implemented. */ + pci_write_config32(dev, XCAP, pci_read_config32(dev, XCAP) | SI); + + /* No device present. */ + if (!(pci_read_config32(dev, SLCTL_SLSTS) & PDS)) { + printk(BIOS_DEBUG, "No PCIe device present.\n"); + if (is_first_port(dev)) { + if (all_ports_no_dev_present(dev)) { + reg_script_run_on_dev(dev, no_dev_behind_port); + dev->enabled = 0; + } + } else { + reg_script_run_on_dev(dev, no_dev_behind_port); + dev->enabled = 0; + } + } else if(!dev->enabled) { + /* Port is disabled, but device present. Disable link. */ + pci_write_config32(dev, LCTL, + pci_read_config32(dev, LCTL) | LD); + } +} + +static void byt_pcie_enable(device_t dev) +{ + if (is_first_port(dev)) { + struct soc_intel_baytrail_config *config = dev->chip_info; + uint32_t reg = pci_read_config32(dev, PHYCTL2_IOSFBCTL); + pll_en_off = !!(reg & PLL_OFF_EN); + + strpfusecfg = pci_read_config32(dev, STRPFUSECFG); + + if (config && config->pcie_wake_enable) + southcluster_smm_save_param( + SMM_SAVE_PARAM_PCIE_WAKE_ENABLE, 1); + } + + /* Check if device is enabled in strapping. */ + check_port_enabled(dev); + /* Determine if device is behind port. */ + check_device_present(dev); + + southcluster_enable_dev(dev); +} + +static unsigned int byt_pciexp_scan_bridge(device_t dev, unsigned int max) +{ + static const struct reg_script wait_for_link_active[] = { + REG_PCI_POLL32(LCTL, (1 << 29) , (1 << 29), 50000), + REG_SCRIPT_END, + }; + + /* wait for Link Active with 50ms timeout */ + reg_script_run_on_dev(dev, wait_for_link_active); + + return do_pci_scan_bridge(dev, max, pciexp_scan_bus); +} + +static void pcie_root_set_subsystem(device_t dev, unsigned vid, unsigned did) +{ + uint32_t didvid = ((did & 0xffff) << 16) | (vid & 0xffff); + + if (!didvid) + didvid = pci_read_config32(dev, PCI_VENDOR_ID); + pci_write_config32(dev, 0x94, didvid); +} + +static struct pci_operations pcie_root_ops = { + .set_subsystem = &pcie_root_set_subsystem, +}; + +static struct device_operations device_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = byt_pcie_init, + .scan_bus = byt_pciexp_scan_bridge, + .enable = byt_pcie_enable, + .ops_pci = &pcie_root_ops, +}; + +static const unsigned short pci_device_ids[] = { + PCIE_PORT1_DEVID, PCIE_PORT2_DEVID, PCIE_PORT3_DEVID, PCIE_PORT4_DEVID, + 0 +}; + +static const struct pci_driver pcie_root_ports __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/baytrail/perf_power.c b/src/soc/intel/baytrail/perf_power.c new file mode 100644 index 0000000000..467e586506 --- /dev/null +++ b/src/soc/intel/baytrail/perf_power.c @@ -0,0 +1,294 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define MAKE_MASK_INCLUSIVE(msb) \ + ((1ULL << (1 + (msb))) - 1) +#define MAKE_MASK(msb) \ + ((1ULL << (msb)) - 1) +#define MASK_VAL(msb, lsb, val) \ + ~(MAKE_MASK_INCLUSIVE(msb) & ~MAKE_MASK(lsb)), (val) << (lsb) + +#define E(arg1, arg2, args) \ + REG_IOSF_RMW(IOSF_PORT_##arg1, arg2, args) + +static const struct reg_script perf_power_settings[] = { +E(AUNIT, 0x18, MASK_VAL(22, 22, 0x1)), // ACKGATE.AMESSAGE_MSGIF +E(AUNIT, 0x18, MASK_VAL(21, 21, 0x1)), // ACKGATE.AREQDOWN_SCL0_ARB +E(AUNIT, 0x18, MASK_VAL(20, 20, 0x1)), // ACKGATE.AREQUP_MIRROR +E(AUNIT, 0x18, MASK_VAL(19, 19, 0x1)), // ACKGATE.AREQTAHACK +E(AUNIT, 0x18, MASK_VAL(18, 18, 0x1)), // ACKGATE.AREQDOWN_TAREQQ +E(AUNIT, 0x18, MASK_VAL(17, 17, 0x1)), // ACKGATE.AREQDOWN_CREDIT +E(AUNIT, 0x18, MASK_VAL(16, 16, 0x1)), // ACKGATE.ASCLUP_FAIR_ARBITER +E(AUNIT, 0x18, MASK_VAL(15, 15, 0x1)), // ACKGATE.AIOSFDOWN_DATA +E(AUNIT, 0x18, MASK_VAL(14, 14, 0x1)), // ACKGATE.ASCLUP_IOSF_ADAPTER +E(AUNIT, 0x18, MASK_VAL(12, 12, 0x1)), // ACKGATE.ASCLUP_CMD_QUEUE +E(AUNIT, 0x18, MASK_VAL(11, 11, 0x1)), // ACKGATE.ASCLUP_DATA_QUEUE +E(AUNIT, 0x18, MASK_VAL(10, 10, 0x1)), // ACKGATE.AREQUP_CMD_QUEUE +E(AUNIT, 0x18, MASK_VAL(9, 9, 0x1)), // ACKGATE.AREQUP_DATA_QUEUE +E(AUNIT, 0x18, MASK_VAL(8, 8, 0x1)), // ACKGATE.AREQDOWN_RSP_QUEUE +E(AUNIT, 0x18, MASK_VAL(7, 7, 0x1)), // ACKGATE.AREQDOWN_DATA_QUEUE +E(AUNIT, 0x18, MASK_VAL(6, 6, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DRVR +E(AUNIT, 0x18, MASK_VAL(5, 5, 0x1)), // ACKGATE.AIOSFDOWN_CMD_DATA_BUFF +E(AUNIT, 0x18, MASK_VAL(4, 4, 0x1)), // ACKGATE.AT_REQ_QUEUE +E(AUNIT, 0x18, MASK_VAL(3, 3, 0x1)), // ACKGATE.AT_DATA_QUEUE +E(AUNIT, 0x18, MASK_VAL(2, 2, 0x1)), // ACKGATE.TA_REQ_QUEUE +E(AUNIT, 0x18, MASK_VAL(1, 1, 0x1)), // ACKGATE.TA_DATA_QUEUE +E(AUNIT, 0x18, MASK_VAL(0, 0, 0x1)), // ACKGATE.CONFIG_REGS +E(AUNIT, 0x20, MASK_VAL(26, 24, 0x2)), // AISOCHCTL.CHANNEL_AB_DEADLINE_EN +E(AUNIT, 0x20, MASK_VAL(8, 0, 0x1)), // AISOCHCTL.VC1_ISOC_CH_DEFAULT_DDLINE_DLY +E(AUNIT, 0x21, MASK_VAL(31, 31, 0x1)), // AVCCTL.EFFICIENT_PERF_UP_EN +E(AUNIT, 0x21, MASK_VAL(8, 8, 0x0)), // AVCCTL.VC_EN_PRIORITY_DNARB +E(AUNIT, 0x0C0, MASK_VAL(11, 8, 0x4)), // AARBCTL0.IOSF0VC2_WGT +E(AUNIT, 0x0C0, MASK_VAL(7, 4, 0x4)), // AARBCTL0.IOSF0VC1_WGT +E(AUNIT, 0x0C0, MASK_VAL(3, 0, 0x4)), // AARBCTL0.IOSF0VC0_WGT +E(BUNIT, 0x3, MASK_VAL(29, 24, 0x4)), // BARBCTRL0.AGENT3_WEIGHT +E(BUNIT, 0x3, MASK_VAL(21, 16, 0x4)), // BARBCTRL0.AGENT2_WEIGHT +E(BUNIT, 0x3, MASK_VAL(13, 8, 0x4)), // BARBCTRL0.AGENT1_WEIGHT +E(BUNIT, 0x3, MASK_VAL(5, 0, 0x4)), // BARBCTRL0.AGENT0_WEIGHT +E(BUNIT, 0x4, MASK_VAL(29, 24, 0x4)), // BARBCTRL1.AGENT7_WEIGHT +E(BUNIT, 0x4, MASK_VAL(21, 16, 0x4)), // BARBCTRL1.AGENT6_WEIGHT +E(BUNIT, 0x4, MASK_VAL(13, 8, 0x4)), // BARBCTRL1.AGENT5_WEIGHT +E(BUNIT, 0x4, MASK_VAL(5, 0, 0x4)), // BARBCTRL1.AGENT4_WEIGHT +E(BUNIT, 0x5, MASK_VAL(21, 16, 0x4)), // BARBCTRL2.AGENT10_WEIGHT +E(BUNIT, 0x5, MASK_VAL(13, 8, 0x4)), // BARBCTRL2.AGENT9_WEIGHT +E(BUNIT, 0x5, MASK_VAL(5, 0, 0x8)), // BARBCTRL2.AGENT8_WEIGHT +E(BUNIT, 0x7, MASK_VAL(31, 24, 0x20)), // BWFLUSH.FLUSH_THRSHOLD +E(BUNIT, 0x7, MASK_VAL(15, 8, 0x0A)), // BWFLUSH.DIRTY_LWM +E(BUNIT, 0x7, MASK_VAL(7, 0, 0x10)), // BWFLUSH.DIRTY_HWM +E(BUNIT, 0x8, MASK_VAL(23, 0, 0x0)), // BBANKMASK.BANK_MASK +E(BUNIT, 0x9, MASK_VAL(23, 0, 0x3FFFFC)), // BROWMASK.ROW_MASK +E(BUNIT, 0x0A, MASK_VAL(9, 0, 0x080)), // BRANKMASK.RANK_MASK +E(BUNIT, 0x0B, MASK_VAL(29, 24, 0x1F)), // BALIMIT0.AGENT3_LIMIT +E(BUNIT, 0x0B, MASK_VAL(21, 16, 0x2F)), // BALIMIT0.AGENT2_LIMIT +E(BUNIT, 0x0B, MASK_VAL(13, 8, 0x2F)), // BALIMIT0.AGENT1_LIMIT +E(BUNIT, 0x0B, MASK_VAL(5, 0, 0x2F)), // BALIMIT0.AGENT0_LIMIT +E(BUNIT, 0x0C, MASK_VAL(29, 24, 0x2F)), // BALIMIT1.AGENT7_LIMIT +E(BUNIT, 0x0C, MASK_VAL(21, 16, 0x2F)), // BALIMIT1.AGENT6_LIMIT +E(BUNIT, 0x0C, MASK_VAL(13, 8, 0x2F)), // BALIMIT1.AGENT5_LIMIT +E(BUNIT, 0x0C, MASK_VAL(5, 0, 0x2B)), // BALIMIT1.AGENT4_LIMIT +E(BUNIT, 0x0D, MASK_VAL(21, 16, 0x2F)), // BALIMIT2.AGENT10_LIMIT +E(BUNIT, 0x0D, MASK_VAL(13, 8, 0x2F)), // BALIMIT2.AGENT9_LIMIT +E(BUNIT, 0x0D, MASK_VAL(5, 0, 0x2F)), // BALIMIT2.AGENT8_LIMIT +E(BUNIT, 0x0F, MASK_VAL(29, 28, 0x0)), // BARES0.AGENT7_RSVD +E(BUNIT, 0x0F, MASK_VAL(25, 24, 0x0)), // BARES0.AGENT6_RSVD +E(BUNIT, 0x0F, MASK_VAL(21, 20, 0x0)), // BARES0.AGENT5_RSVD +E(BUNIT, 0x0F, MASK_VAL(17, 16, 0x0)), // BARES0.AGENT4_RSVD +E(BUNIT, 0x0F, MASK_VAL(13, 12, 0x0)), // BARES0.AGENT3_RSVD +E(BUNIT, 0x0F, MASK_VAL(9, 8, 0x0)), // BARES0.AGENT2_RSVD +E(BUNIT, 0x0F, MASK_VAL(5, 4, 0x0)), // BARES0.AGENT1_RSVD +E(BUNIT, 0x0F, MASK_VAL(1, 0, 0x0)), // BARES0.AGENT0_RSVD +E(BUNIT, 0x10, MASK_VAL(9, 8, 0x0)), // BARES1.AGENT10_RSVD +E(BUNIT, 0x10, MASK_VAL(5, 4, 0x0)), // BARES1.AGENT9_RSVD +E(BUNIT, 0x10, MASK_VAL(1, 0, 0x0)), // BARES1.AGENT8_RSVD +E(BUNIT, 0x11, MASK_VAL(31, 22, 0x20)), // BISOC.ENTER_SELF_REFRESH_THRSH +E(BUNIT, 0x11, MASK_VAL(18, 18, 0x1)), // BISOC.SR_EXIT_SYNC_EN +E(BUNIT, 0x11, MASK_VAL(17, 12, 0x4)), // BISOC.ENTER_SELF_REFRESH_DLY +E(BUNIT, 0x11, MASK_VAL(11, 8, 0x8)), // BISOC.SCHEDULER_LATENCY +E(BUNIT, 0x12, MASK_VAL(31, 30, 0x0)), // BCOSCAT.COS_CAT_AGENT15 and BCOSCAT.BUS_LOCK_THROTTLE_ENABLE +E(BUNIT, 0x12, MASK_VAL(29, 28, 0x0)), // BCOSCAT.COS_CAT_AGENT14 +E(BUNIT, 0x12, MASK_VAL(27, 26, 0x0)), // BCOSCAT.COS_CAT_AGENT13 +E(BUNIT, 0x12, MASK_VAL(25, 24, 0x0)), // BCOSCAT.COS_CAT_AGENT12 +E(BUNIT, 0x12, MASK_VAL(23, 22, 0x0)), // BCOSCAT.COS_CAT_AGENT11 +E(BUNIT, 0x12, MASK_VAL(21, 20, 0x0)), // BCOSCAT.COS_CAT_AGENT10 +E(BUNIT, 0x12, MASK_VAL(19, 18, 0x0)), // BCOSCAT.COS_CAT_AGENT9 +E(BUNIT, 0x12, MASK_VAL(17, 16, 0x1)), // BCOSCAT.COS_CAT_AGENT8 +E(BUNIT, 0x12, MASK_VAL(15, 14, 0x0)), // BCOSCAT.COS_CAT_AGENT7 +E(BUNIT, 0x12, MASK_VAL(13, 12, 0x0)), // BCOSCAT.COS_CAT_AGENT6 +E(BUNIT, 0x12, MASK_VAL(11, 10, 0x1)), // BCOSCAT.COS_CAT_AGENT5 +E(BUNIT, 0x12, MASK_VAL(9, 8, 0x1)), // BCOSCAT.COS_CAT_AGENT4 +E(BUNIT, 0x12, MASK_VAL(7, 6, 0x0)), // BCOSCAT.COS_CAT_AGENT3 +E(BUNIT, 0x12, MASK_VAL(5, 4, 0x0)), // BCOSCAT.COS_CAT_AGENT2 +E(BUNIT, 0x12, MASK_VAL(3, 2, 0x0)), // BCOSCAT.COS_CAT_AGENT1 +E(BUNIT, 0x12, MASK_VAL(1, 0, 0x0)), // BCOSCAT.COS_CAT_AGENT0 +E(BUNIT, 0x14, MASK_VAL(31, 31, 0x0)), // BFLWT.DISABLE_FLUSH_WEIGHTS +E(BUNIT, 0x14, MASK_VAL(30, 30, 0x0)), // BFLWT.ENABLE_READ_INVALIDATE_TIMER +E(BUNIT, 0x14, MASK_VAL(13, 8, 0x8)), // BFLWT.WRITE_WEIGHTS +E(BUNIT, 0x14, MASK_VAL(5, 0, 0x10)), // BFLWT.READ_WEIGHTS +E(BUNIT, 0x16, MASK_VAL(31, 31, 0x0)), // BISOCWT.ENABLE_ISOC_WEIGHTS +E(BUNIT, 0x16, MASK_VAL(13, 8, 0x3F)), // BISOCWT.ISOC_REQUEST_WEIGHTS +E(BUNIT, 0x16, MASK_VAL(5, 0, 0x8)), // BISOCWT.NON_ISOC_REQUEST_WEIGHTS +E(BUNIT, 0x18, MASK_VAL(31, 24, 0x20)), // BSCHCTRL0.BEST_EFFORT_MAX_LATENCY +E(BUNIT, 0x18, MASK_VAL(23, 21, 0x6)), // BSCHCTRL0.PAGE_HIT_DELAY +E(BUNIT, 0x18, MASK_VAL(13, 7, 0x0)), // BSCHCTRL0.ISOC_BANK_PREFETCH +E(BUNIT, 0x18, MASK_VAL(6, 0, 0x20)), // BSCHCTRL0.BEST_EFFORT_BANK_PREFETCH +E(BUNIT, 0x3B, MASK_VAL(23, 16, 0x4)), // BDEBUG0.CASUAL_TIMER +E(BUNIT, 0x3B, MASK_VAL(9, 9, 0x0)), // BDEBUG0.DISABLE_BADMIT_URGENT_ISOC +E(BUNIT, 0x3B, MASK_VAL(7, 0, 0x0A)), // BDEBUG0.CASUAL_WATER_MARK +E(BUNIT, 0x3C, MASK_VAL(31, 16, 0x0FFFF)), // BDEBUG1.AGENT_WEIGHT_ENABLE +E(BUNIT, 0x3C, MASK_VAL(2, 2, 0x0)), // BDEBUG1.EXIT_SR_FOR_CASUAL_FLUSH +E(BUNIT, 0x3C, MASK_VAL(1, 1, 0x0)), // BDEBUG1.ENABLE_DRAM_SELF_RFRSH +E(BUNIT, 0x3D, MASK_VAL(14, 14, 0x1)), // BCTRL.BANK_STATUS_ENABLE +E(BUNIT, 0x3D, MASK_VAL(13, 13, 0x0)), // BCTRL.DISABLE_OWNED +E(BUNIT, 0x3D, MASK_VAL(12, 12, 0x0)), // BCTRL.INORDER_READ_ENABLE +E(BUNIT, 0x3D, MASK_VAL(11, 11, 0x0)), // BCTRL.INORDER_FLUSH_ENABLE +E(BUNIT, 0x3D, MASK_VAL(8, 8, 0x0)), // BCTRL.MISS_VALID_ENTRIES +E(BUNIT, 0x3D, MASK_VAL(7, 7, 0x0)), // BCTRL.DIRTY_STALL +E(BUNIT, 0x3D, MASK_VAL(6, 6, 0x0)), // BCTRL.SINGLE_TAG_ACCESS +E(BUNIT, 0x3D, MASK_VAL(5, 5, 0x0)), // BCTRL.SINGLE_CHUNK_ACCESS +E(BUNIT, 0x3D, MASK_VAL(2, 2, 0x1)), // BCTRL.BECLK_GATE_EN +E(BUNIT, 0x3D, MASK_VAL(1, 1, 0x1)), // BCTRL.MASTERCLK_GATE_EN +E(BUNIT, 0x3D, MASK_VAL(0, 0, 0x1)), // BCTRL.REQUESTCLK_GATE_EN +E(BUNIT, 0x3E, MASK_VAL(31, 16, 0x0)), // BTHCTRL.AGENT_THROTTLING_ENABLE +E(BUNIT, 0x3E, MASK_VAL(7, 0, 0x0)), // BTHCTRL.RANK_SELECTION_MASK +E(BUNIT, 0x3F, MASK_VAL(31, 24, 0x0FF)), // BTHMASK.ORWRITE_MASK +E(BUNIT, 0x3F, MASK_VAL(23, 16, 0x0FF)), // BTHMASK.ORREAD_MASK +E(BUNIT, 0x3F, MASK_VAL(15, 8, 0x0FF)), // BTHMASK.ERWRITE_MASK +E(BUNIT, 0x3F, MASK_VAL(7, 0, 0x0FF)), // BTHMASK.ERREAD_MASK + //0x02, 0x0, 2, 0, 0x1, //T_INTR_REDIR_CTL.REDIR_MODE_SEL +E(CPU_BUS, 0x3, MASK_VAL(20, 20, 0x1)), // T_CTL.SPLIT_GOIWP_MODE +E(CPU_BUS, 0x3, MASK_VAL(19, 19, 0x0)), // T_CTL.DISABLE_TRDY_RDGO +E(CPU_BUS, 0x3, MASK_VAL(18, 18, 0x0)), // T_CTL.DISABLE_ISOC_HIGHPRI_RDDATA_RETURN +E(CPU_BUS, 0x3, MASK_VAL(17, 17, 0x0)), // T_CTL.ENABLE_NPC_COLLECTOR +E(CPU_BUS, 0x3, MASK_VAL(16, 16, 0x1)), // T_CTL.ENABLE_IN_ORDER_APIC +E(CPU_BUS, 0x3, MASK_VAL(15, 15, 0x0)), // T_CTL.TG_HIGHPRI_WRITE_PULLS + //0x02, 0x3, 12, 12, 0x1, // T_CTL.TG_NDRAMSNP +E(CPU_BUS, 0x3, MASK_VAL(10, 10, 0x1)), // T_CTL.TG_DW_POST_PUSH_LOG +E(CPU_BUS, 0x3, MASK_VAL(3, 3, 0x0)), // T_CTL.ALWAYS_SNP_IDI +E(CPU_BUS, 0x3, MASK_VAL(2, 2, 0x0)), // T_CTL.DIS_LIVE_BRAM_BYP_IDI +E(CPU_BUS, 0x4, MASK_VAL(18, 18, 0x1)), // T_MISC_CTL.DISABLE_IOSF_OUTBOUND_THROTTLE +E(CPU_BUS, 0x4, MASK_VAL(4, 1, 0x8)), // T_MISC_CTL.DPTE_CNT +E(CPU_BUS, 0x4, MASK_VAL(0, 0, 0x0)), // T_MISC_CTL.DPTE_EN +E(CPU_BUS, 0x5, MASK_VAL(27, 27, 0x1)), // T_CLKGATE_CTL.XUNIT_4_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(26, 26, 0x1)), // T_CLKGATE_CTL.XUNIT_3_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(25, 25, 0x1)), // T_CLKGATE_CTL.XUNIT_2_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(24, 24, 0x1)), // T_CLKGATE_CTL.XUNIT_1_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(23, 23, 0x1)), // T_CLKGATE_CTL.MON_LOG_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(22, 22, 0x1)), // T_CLKGATE_CTL.A2T_Q_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(21, 21, 0x1)), // T_CLKGATE_CTL.T2A_Q_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(20, 20, 0x1)), // T_CLKGATE_CTL.A2TAPIC_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(19, 19, 0x1)), // T_CLKGATE_CTL.B2X_DATSEL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(18, 18, 0x1)), // T_CLKGATE_CTL.X2B_DATSEL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(17, 17, 0x1)), // T_CLKGATE_CTL.S2C_RESP_SEL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(16, 16, 0x1)), // T_CLKGATE_CTL.T2A_REQ_SEL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(15, 15, 0x1)), // T_CLKGATE_CTL.C2APIC_FIFO_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(14, 14, 0x1)), // T_CLKGATE_CTL.S2C_REQ_FIFO_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(13, 13, 0x1)), // T_CLKGATE_CTL.S2C_REQ_SEL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(12, 12, 0x1)), // T_CLKGATE_CTL.TRKR_SB_LLST_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(11, 11, 0x1)), // T_CLKGATE_CTL.TRKR_SB_OLDST_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(10, 10, 0x1)), // T_CLKGATE_CTL.TRKR_SB_S2C_RESP_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(9, 9, 0x1)), // T_CLKGATE_CTL.TRKR_SB_T2A_REQSTAT_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(8, 8, 0x1)), // T_CLKGATE_CTL.TRKR_SB_B2X_DATSTAT_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(7, 7, 0x1)), // T_CLKGATE_CTL.TRKR_SB_WRSTAT_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(6, 6, 0x1)), // T_CLKGATE_CTL.TRKR_SB_SNP_STAT_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(5, 5, 0x1)), // T_CLKGATE_CTL.TRKR_SB_REQ_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(4, 4, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VIOL_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(3, 3, 0x1)), // T_CLKGATE_CTL.TRKR_SB_VALID_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(2, 2, 0x1)), // T_CLKGATE_CTL.TRKR_SB_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(1, 1, 0x1)), // T_CLKGATE_CTL.IOSF_SB_CFG_REG_CLK_GATE_EN +E(CPU_BUS, 0x5, MASK_VAL(0, 0, 0x1)), // T_CLKGATE_CTL.IOSF_SB_MSG_CLK_GATE_EN +E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN +E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN +E(0x58, 0x40, MASK_VAL(4, 4, 0x0)), // SSCR2.ACG_EN +E(0x55, 0x54, MASK_VAL(1, 0, 0x0)), // SMB_Config_PMCSR.PS +E(0x55, 0x0FC, MASK_VAL(17, 17, 0x0)), // SMB_Config_CGC.FUNC_CLK_CGD +E(0x55, 0x0FC, MASK_VAL(9, 9, 0x0)), // SMB_Config_CGC.SB_LOCAL_CGD +E(0xa2, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable +E(0x47, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable +E(0x45, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable +E(0x46, 0x0C000, MASK_VAL(0, 0, 0x0)), // power_options.clkgate_disable +E(PMC, 0x0, MASK_VAL(11, 11, 0x1)), // PUNIT_CONTROL.MODE_DEMOTE_EN +E(PMC, 0x0, MASK_VAL(10, 10, 0x1)), // PUNIT_CONTROL.CORE_DEMOTE_EN + + // + //s0ix_PnP_Settings + // +E(0x58, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfprim_trunk_gate_en +E(0x58, 0x1e0, MASK_VAL(0, 0, 0x0)), //vlv.audio.lpe.bridge.pmctl.iosfprimclk_gate_en +E(0x58, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.audio.lpe.bridge.pmctl.iosfsb_trunk_gate_en +E(0x58, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.audio.lpe.bridge.pmctl.pmctl.iosfsbclk_gate_en +E(0x58, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_gate_en +E(0x58, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.audio.lpe.bridge.pmctl.ocpclk_trunk_gate_en +E(CCU, 0x28, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate +E(CCU, 0x38, MASK_VAL(31, 0, 0x0)), //vlv.ccu.ccu_trunk_clkgate_2 +E(CCU, 0x1c, MASK_VAL(29, 28, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_pri_clkgate_en +E(CCU, 0x1c, MASK_VAL(25, 24, 0x0)), //vlv.ccu.clkgate_en_1.cr_lpe_sb_clkgate_en +E(CCU, 0x1c, MASK_VAL( 1, 0, 0x0)), //vlv.ccu.clkgate_en_1.lps_free_clkgate_en +E(CCU, 0x54, MASK_VAL(17, 16, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_func_ip_clkgate_en +E(CCU, 0x54, MASK_VAL(13, 12, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_osc_ip_clk_en +E(CCU, 0x54, MASK_VAL(15, 14, 0x0)), //vlv.ccu.clkgate_en_3.cr_lpe_xtal_ip_clkgate_en +E(CCU, 0x54, MASK_VAL(26, 24, 0x0)), //vlv.ccu.clkgate_en_3.psf_pri_clkgate_en +E(CCU, 0x24, MASK_VAL(24, 20, 0x0)), //vlv.ccu.iclk_clkgate_ctrl.iopcibuffen_force_on +E(0x59, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprim_trunk_gate_en +E(0x59, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfprimclk_gate_en +E(0x59, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsb_trunk_gate_en +E(0x59, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.iosfsbclk_gate_en +E(0x59, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_gate_en +E(0x59, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.usb.xdci_otg.controller.pmctl.ocpclk_trunk_gate_en +E(0x5a, 0xd0, MASK_VAL(8, 0, 0x3f)), //vlv.usb.xhci.controller.usb2pr.usb2hcsel +E(0x5a, 0x40, MASK_VAL(21, 19, 0x6)), //vlv.usb.xhci.controller.xhcc1.iil1e +E(0x5a, 0x40, MASK_VAL(10, 8, 0x1)), //vlv.usb.xhci.controller.xhcc1.l23hrawc +E(0x5a, 0x40, MASK_VAL(18, 18, 0x1)), //vlv.usb.xhci.controller.xhcc1.xhcil1e +E(0x5a, 0x50, MASK_VAL(3, 3, 0x1)), //vlv.usb.xhci.controller.xhclkgten.hsltcge +E(0x5a, 0x50, MASK_VAL(0, 0, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfblcge +E(0x5a, 0x50, MASK_VAL(1, 1, 0x1)), //vlv.usb.xhci.controller.xhclkgten.iosfbtcge +E(0x5a, 0x50, MASK_VAL(2, 2, 0x1)), //vlv.usb.xhci.controller.xhclkgten.ssltcge +E(0x5a, 0x50, MASK_VAL(7, 5, 0x2)), //vlv.usb.xhci.controller.xhclkgten.sspllsue +E(0x5a, 0x50, MASK_VAL(13, 13, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcbbtcgipiso +E(0x5a, 0x50, MASK_VAL(4, 4, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcblcge +E(0x5a, 0x50, MASK_VAL(14, 14, 0x1)), //vlv.usb.xhci.controller.xhclkgten.xhcftclkse +E(0x5a, 0x50, MASK_VAL(12, 12, 0x0)), //vlv.usb.xhci.controller.xhclkgten.xhchstcgu2nrwe +E(0x5a, 0x50, MASK_VAL(11, 10, 0x3)), //vlv.usb.xhci.controller.xhclkgten.xhcusb2pllsdle +E(SCORE, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpscore.cfio_regs_com_cfg_score_pb_config.sb_clkgaten +E(SSUS, 0x4900, MASK_VAL(16, 16, 0x1)), //vlv.gpio.gpssus.cfio_regs_com_cfg_ssus_pb_config.sb_clkgaten +E(LPSS, 0x180, MASK_VAL(1, 1, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_clk_gate_en +E(LPSS, 0x180, MASK_VAL(4, 4, 0x1)), //vlv.lpss.iosf2ahb.pmctl.ahb_trunk_gate_enable +E(LPSS, 0x180, MASK_VAL(0, 0, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosf_clk_gate_enable +E(LPSS, 0x180, MASK_VAL(3, 3, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfprim_trunk_gate_enable +E(LPSS, 0x180, MASK_VAL(5, 5, 0x1)), //vlv.lpss.iosf2ahb.pmctl.iosfsb_trunk_gate_enable +E(LPSS, 0x180, MASK_VAL(2, 2, 0x1)), //vlv.lpss.iosf2ahb.pmctl.side_clk_gate_enable + //0x54, 0xfc, 31, 0, 0x0, //vlv.pcu.iosfahbep.clock_gating_control + //0x55, 0xfc, 1, 1, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_local_cgd + //0x55, 0xfc, 0, 0, 0x0, //vlv.pcu.smbus.smb_config_cgc.pri_trunk_cgd + //0x55, 0xfc, 8, 8, 0x0, //vlv.pcu.smbus.smb_config_cgc.sb_trunk_cgd +E(SCC, 0x600, MASK_VAL(31, 15, 0x5)), //vlv.scc.iosf2ocp.gen_regrw1.gen_reg_rw1 +E(SCC, 0x1e0, MASK_VAL(4, 4, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprim_trunk_gate_en +E(SCC, 0x1e0, MASK_VAL(0, 0, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfprimclk_gate_en +E(SCC, 0x1e0, MASK_VAL(5, 5, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsb_trunk_gate_en +E(SCC, 0x1e0, MASK_VAL(3, 3, 0x1)), //vlv.scc.iosf2ocp.pmctl.iosfsbclk_gate_en +E(SCC, 0x1e0, MASK_VAL(1, 1, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_gate_en +E(SCC, 0x1e0, MASK_VAL(2, 2, 0x1)), //vlv.scc.iosf2ocp.pmctl.ocpclk_trunk_gate_en +E(SEC, 0x88, MASK_VAL(7, 7, 0x0)), //vlv.sec.clk_gate_dis.nfc_cg_dis +E(SEC, 0x88, MASK_VAL(1, 1, 0x0)), //vlv.sec.clk_gate_dis.prim_cg_dis +E(SEC, 0x88, MASK_VAL(2, 2, 0x0)), //vlv.sec.clk_gate_dis.prim_clkreq_dis +E(SEC, 0x88, MASK_VAL(3, 3, 0x0)), //vlv.sec.clk_gate_dis.prim_xsm_clkreq_dis +E(SEC, 0x88, MASK_VAL(4, 4, 0x0)), //vlv.sec.clk_gate_dis.sap_cg_dis +E(SEC, 0x88, MASK_VAL(6, 6, 0x0)), //vlv.sec.clk_gate_dis.sap_clkidle_dis +E(SEC, 0x88, MASK_VAL(5, 5, 0x0)), //vlv.sec.clk_gate_dis.sap_ip_cg_dis +E(SEC, 0x88, MASK_VAL(0, 0, 0x0)), //vlv.sec.clk_gate_dis.sb_cg_dis +REG_SCRIPT_END, +}; + + +static void perf_power(void *unused) +{ + printk(BIOS_DEBUG, "Applying perf/power settings.\n"); + reg_script_run(perf_power_settings); +} + +BOOT_STATE_INIT_ENTRIES(disable_rom_cache_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, perf_power, NULL), + BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, perf_power, NULL), +}; diff --git a/src/soc/intel/baytrail/placeholders.c b/src/soc/intel/baytrail/placeholders.c new file mode 100644 index 0000000000..3495c30c72 --- /dev/null +++ b/src/soc/intel/baytrail/placeholders.c @@ -0,0 +1,11 @@ + +#include +#include +#include +#include + + +void smm_init(void) {} + +/* Rmodules don't like weak symbols. */ +u32 map_oprom_vendev(u32 vendev) { return vendev; } diff --git a/src/soc/intel/baytrail/pmutil.c b/src/soc/intel/baytrail/pmutil.c new file mode 100644 index 0000000000..2b0bc455a6 --- /dev/null +++ b/src/soc/intel/baytrail/pmutil.c @@ -0,0 +1,364 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(__SMM__) + +static const device_t pcu_dev = PCI_DEV(0, PCU_DEV, 0); + +static inline device_t get_pcu_dev(void) +{ + return pcu_dev; +} + +#else /* !__SMM__ */ +#include +#include + +static device_t pcu_dev; +static device_t get_pcu_dev(void) +{ + if (pcu_dev == NULL) + pcu_dev = dev_find_slot(0, PCI_DEVFN(PCU_DEV, 0)); + return pcu_dev; +} +#endif + +uint16_t get_pmbase(void) +{ + return pci_read_config16(get_pcu_dev(), ABASE) & 0xfff8; +} + +static void print_num_status_bits(int num_bits, uint32_t status, + const char *bit_names[]) +{ + int i; + + if (!status) + return; + + for (i = num_bits - 1; i >= 0; i--) { + if (status & (1 << i)) { + if (bit_names[i]) + printk(BIOS_DEBUG, "%s ", bit_names[i]); + else + printk(BIOS_DEBUG, "BIT%d ", i); + } + } +} + +static void print_status_bits(uint32_t status, const char *bit_names[]) +{ + print_num_status_bits(32, status, bit_names); +} + +static uint32_t print_smi_status(uint32_t smi_sts) +{ + static const char *smi_sts_bits[] = { + [2] = "BIOS", + [4] = "SLP_SMI", + [5] = "APM", + [6] = "SWSMI_TMR", + [8] = "PM1", + [9] = "GPE0", + [12] = "DEVMON", + [13] = "TCO", + [14] = "PERIODIC", + [15] = "ILB", + [16] = "SMBUS_SMI", + [17] = "LEGACY_USB2", + [18] = "INTEL_USB2", + [20] = "PCI_EXP_SMI", + [26] = "SPI", + [28] = "PUNIT", + [29] = "GUNIT", + }; + + if (!smi_sts) + return 0; + + printk(BIOS_DEBUG, "SMI_STS: "); + print_status_bits(smi_sts, smi_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return smi_sts; +} + +static uint32_t reset_smi_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint32_t smi_sts = inl(pmbase + SMI_STS); + outl(smi_sts, pmbase + SMI_STS); + return smi_sts; +} + +uint32_t clear_smi_status(void) +{ + return print_smi_status(reset_smi_status()); +} + +void enable_smi(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t smi_en = inl(pmbase + SMI_EN); + smi_en |= mask; + outl(smi_en, pmbase + SMI_EN); +} + +void disable_smi(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t smi_en = inl(pmbase + SMI_EN); + smi_en &= ~mask; + outl(smi_en, pmbase + SMI_EN); +} + +void enable_pm1_control(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t pm1_cnt = inl(pmbase + PM1_CNT); + pm1_cnt |= mask; + outl(pm1_cnt, pmbase + PM1_CNT); +} + +void disable_pm1_control(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t pm1_cnt = inl(pmbase + PM1_CNT); + pm1_cnt &= ~mask; + outl(pm1_cnt, pmbase + PM1_CNT); +} + +static uint16_t reset_pm1_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint16_t pm1_sts = inw(pmbase + PM1_STS); + outw(pm1_sts, pmbase + PM1_STS); + return pm1_sts; +} + +static uint16_t print_pm1_status(uint16_t pm1_sts) +{ + static const char *pm1_sts_bits[] = { + [0] = "TMROF", + [5] = "GBL", + [8] = "PWRBTN", + [10] = "RTC", + [11] = "PRBTNOR", + [13] = "USB", + [14] = "PCIEXPWAK", + [15] = "WAK", + }; + + if (!pm1_sts) + return 0; + + printk(BIOS_SPEW, "PM1_STS: "); + print_status_bits(pm1_sts, pm1_sts_bits); + printk(BIOS_SPEW, "\n"); + + return pm1_sts; +} + +uint16_t clear_pm1_status(void) +{ + return print_pm1_status(reset_pm1_status()); +} + +void enable_pm1(uint16_t events) +{ + outw(events, get_pmbase() + PM1_EN); +} + +static uint32_t print_tco_status(uint32_t tco_sts) +{ + static const char *tco_sts_bits[] = { + [3] = "TIMEOUT", + [17] = "SECOND_TO", + }; + + if (!tco_sts) + return 0; + + printk(BIOS_DEBUG, "TCO_STS: "); + print_status_bits(tco_sts, tco_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return tco_sts; +} + +static uint32_t reset_tco_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint32_t tco_sts = inl(pmbase + TCO_STS); + uint32_t tco_en = inl(pmbase + TCO1_CNT); + + outl(tco_sts, pmbase + TCO_STS); + return tco_sts & tco_en; +} + +uint32_t clear_tco_status(void) +{ + return print_tco_status(reset_tco_status()); +} + +void enable_gpe(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t gpe0_en = inl(pmbase + GPE0_EN); + gpe0_en |= mask; + outl(gpe0_en, pmbase + GPE0_EN); +} + +void disable_gpe(uint32_t mask) +{ + uint16_t pmbase = get_pmbase(); + uint32_t gpe0_en = inl(pmbase + GPE0_EN); + gpe0_en &= ~mask; + outl(gpe0_en, pmbase + GPE0_EN); +} + +void disable_all_gpe(void) +{ + disable_gpe(~0); +} + + +static uint32_t reset_gpe_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint32_t gpe_sts = inl(pmbase + GPE0_STS); + outl(gpe_sts, pmbase + GPE0_STS); + return gpe_sts; +} + +static uint32_t print_gpe_sts(uint32_t gpe_sts) +{ + static const char *gpe_sts_bits[] = { + [1] = "HOTPLUG", + [2] = "SWGPE", + [3] = "PCIE_WAKE0", + [4] = "PUNIT", + [5] = "GUNIT", + [6] = "PCIE_WAKE1", + [7] = "PCIE_WAKE2", + [8] = "PCIE_WAKE3", + [9] = "PCI_EXP", + [10] = "BATLOW", + [13] = "PME_B0", + [16] = "SUS_GPIO_0", + [17] = "SUS_GPIO_1", + [18] = "SUS_GPIO_2", + [19] = "SUS_GPIO_3", + [20] = "SUS_GPIO_4", + [21] = "SUS_GPIO_5", + [22] = "SUS_GPIO_6", + [23] = "SUS_GPIO_7", + [24] = "CORE_GPIO_0", + [25] = "CORE_GPIO_1", + [26] = "CORE_GPIO_2", + [27] = "CORE_GPIO_3", + [28] = "CORE_GPIO_4", + [29] = "CORE_GPIO_5", + [30] = "CORE_GPIO_6", + [31] = "CORE_GPIO_7", + }; + + if (!gpe_sts) + return gpe_sts; + + printk(BIOS_DEBUG, "GPE0a_STS: "); + print_status_bits(gpe_sts, gpe_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return gpe_sts; +} + +uint32_t clear_gpe_status(void) +{ + return print_gpe_sts(reset_gpe_status()); +} + +static uint32_t reset_alt_status(void) +{ + uint16_t pmbase = get_pmbase(); + uint32_t alt_gpio_smi = inl(pmbase + ALT_GPIO_SMI); + outl(alt_gpio_smi, pmbase + ALT_GPIO_SMI); + return alt_gpio_smi; +} + +static uint32_t print_alt_sts(uint32_t alt_gpio_smi) +{ + uint32_t alt_gpio_sts; + static const char *alt_gpio_smi_sts_bits[] = { + [0] = "SUS_GPIO_0", + [1] = "SUS_GPIO_1", + [2] = "SUS_GPIO_2", + [3] = "SUS_GPIO_3", + [4] = "SUS_GPIO_4", + [5] = "SUS_GPIO_5", + [6] = "SUS_GPIO_6", + [7] = "SUS_GPIO_7", + [8] = "CORE_GPIO_0", + [9] = "CORE_GPIO_1", + [10] = "CORE_GPIO_2", + [11] = "CORE_GPIO_3", + [12] = "CORE_GPIO_4", + [13] = "CORE_GPIO_5", + [14] = "CORE_GPIO_6", + [15] = "CORE_GPIO_7", + }; + + /* Status bits are in the upper 16 bits. */ + alt_gpio_sts = alt_gpio_smi >> 16; + if (!alt_gpio_sts) + return alt_gpio_smi; + + printk(BIOS_DEBUG, "ALT_GPIO_SMI: "); + print_num_status_bits(16, alt_gpio_sts, alt_gpio_smi_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return alt_gpio_smi; +} + +uint32_t clear_alt_status(void) +{ + return print_alt_sts(reset_alt_status()); +} + +void clear_pmc_status(void) +{ + uint32_t prsts; + uint32_t gen_pmcon1; + + prsts = read32(PMC_BASE_ADDRESS + PRSTS); + gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1); + + /* Clear the status bits. The RPS field is cleared on a 0 write. */ + write32(PMC_BASE_ADDRESS + GEN_PMCON1, gen_pmcon1 & ~RPS); + write32(PMC_BASE_ADDRESS + PRSTS, prsts); +} diff --git a/src/soc/intel/baytrail/ramstage.c b/src/soc/intel/baytrail/ramstage.c new file mode 100644 index 0000000000..b172ade020 --- /dev/null +++ b/src/soc/intel/baytrail/ramstage.c @@ -0,0 +1,207 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global PATTRS */ +DEFINE_PATTRS; + +#define SHOW_PATTRS 1 + +static void detect_num_cpus(struct pattrs *attrs) +{ + int ecx = 0; + + 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) { + attrs->num_cpus = leaf_b.ebx & 0xffff; + break; + } + ecx++; + } +} + +static inline void fill_in_msr(msr_t *msr, int idx) +{ + *msr = rdmsr(idx); + if (SHOW_PATTRS) { + printk(BIOS_DEBUG, "msr(%x) = %08x%08x\n", + idx, msr->hi, msr->lo); + } +} + +static const char *stepping_str[] = { + "A0", "A1", "B0", "B1", "B2", "B3", "C0" +}; + +static void fill_in_pattrs(void) +{ + device_t dev; + msr_t msr; + struct pattrs *attrs = (struct pattrs *)pattrs_get(); + + attrs->cpuid = cpuid_eax(1); + dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC)); + attrs->revid = pci_read_config8(dev, REVID); + /* The revision to stepping IDs have two values per metal stepping. */ + if (attrs->revid >= RID_C_STEPPING_START) { + attrs->stepping = (attrs->revid - RID_C_STEPPING_START) / 2; + attrs->stepping += STEP_C0; + } else if (attrs->revid >= RID_B_STEPPING_START) { + attrs->stepping = (attrs->revid - RID_B_STEPPING_START) / 2; + attrs->stepping += STEP_B0; + } else { + attrs->stepping = (attrs->revid - RID_A_STEPPING_START) / 2; + attrs->stepping += STEP_A0; + } + + attrs->microcode_patch = intel_microcode_find(); + attrs->address_bits = cpuid_eax(0x80000008) & 0xff; + detect_num_cpus(attrs); + + if (SHOW_PATTRS) { + printk(BIOS_DEBUG, "BYT: cpuid %08x cpus %d rid %02x step %s\n", + attrs->cpuid, attrs->num_cpus, attrs->revid, + (attrs->stepping >= ARRAY_SIZE(stepping_str)) ? "??" : + stepping_str[attrs->stepping]); + } + + fill_in_msr(&attrs->platform_id, MSR_IA32_PLATFORM_ID); + fill_in_msr(&attrs->platform_info, MSR_PLATFORM_INFO); + + /* Set IA core speed ratio and voltages */ + msr = rdmsr(MSR_IACORE_RATIOS); + attrs->iacore_ratios[IACORE_MIN] = msr.lo & 0x7f; + attrs->iacore_ratios[IACORE_LFM] = (msr.lo >> 8) & 0x7f; + attrs->iacore_ratios[IACORE_MAX] = (msr.lo >> 16) & 0x7f; + msr = rdmsr(MSR_IACORE_TURBO_RATIOS); + attrs->iacore_ratios[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */ + + msr = rdmsr(MSR_IACORE_VIDS); + attrs->iacore_vids[IACORE_MIN] = msr.lo & 0x7f; + attrs->iacore_vids[IACORE_LFM] = (msr.lo >> 8) & 0x7f; + attrs->iacore_vids[IACORE_MAX] = (msr.lo >> 16) & 0x7f; + msr = rdmsr(MSR_IACORE_TURBO_VIDS); + attrs->iacore_vids[IACORE_TURBO] = (msr.lo & 0xff); /* 1 core max */ + + /* Set bus clock speed */ + attrs->bclk_khz = bus_freq_khz(); +} + +static inline void set_acpi_sleep_type(int val) +{ +#if CONFIG_HAVE_ACPI_RESUME + acpi_slp_type = val; +#endif +} + +/* Save bit index for first enabled event in PM1_STS for \_SB._SWS */ +static void s3_save_acpi_wake_source(global_nvs_t *gnvs) +{ + struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE); + uint16_t pm1; + + if (!ps) + return; + + pm1 = ps->pm1_sts & ps->pm1_en; + + /* Scan for first set bit in PM1 */ + for (gnvs->pm1i = 0; gnvs->pm1i < 16; gnvs->pm1i++) { + if (pm1 & 1) + break; + pm1 >>= 1; + } + + /* If unable to determine then return -1 */ + if (gnvs->pm1i >= 16) + gnvs->pm1i = -1; + + printk(BIOS_DEBUG, "ACPI System Wake Source is PM1 Index %d\n", + gnvs->pm1i); +} + +static void s3_resume_prepare(void) +{ + global_nvs_t *gnvs; + struct romstage_handoff *romstage_handoff; + + gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t)); + + romstage_handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO); + if (romstage_handoff == NULL || romstage_handoff->s3_resume == 0) { + if (gnvs != NULL) { + memset(gnvs, 0, sizeof(global_nvs_t)); + } + set_acpi_sleep_type(0); + return; + } + + set_acpi_sleep_type(3); + + s3_save_acpi_wake_source(gnvs); +} + +void baytrail_init_pre_device(struct soc_intel_baytrail_config *config) +{ + struct soc_gpio_config *gpio_config; + + fill_in_pattrs(); + + /* Allow for SSE instructions to be executed. */ + write_cr4(read_cr4() | CR4_OSFXSR | CR4_OSXMMEXCPT); + + /* Indicate S3 resume to rest of ramstage. */ + s3_resume_prepare(); + + /* Run reference code. */ + baytrail_run_reference_code(); + + /* Get GPIO initial states from mainboard */ + gpio_config = mainboard_get_gpios(); + setup_soc_gpios(gpio_config, config->enable_xdp_tap); + + baytrail_init_scc(); +} diff --git a/src/soc/intel/baytrail/refcode.c b/src/soc/intel/baytrail/refcode.c new file mode 100644 index 0000000000..50eb084014 --- /dev/null +++ b/src/soc/intel/baytrail/refcode.c @@ -0,0 +1,195 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static inline int is_s3_resume(void) +{ +#if CONFIG_HAVE_ACPI_RESUME + return acpi_slp_type == 3; +#else + return 0; +#endif +} + +static inline struct ramstage_cache *next_cache(struct ramstage_cache *c) +{ + return (struct ramstage_cache *)&c->program[c->size]; +} + +static void ABI_X86 send_to_console(unsigned char b) +{ + console_tx_byte(b); +} + +static efi_wrapper_entry_t load_refcode_from_cache(void) +{ + struct ramstage_cache *c; + long cache_size; + + printk(BIOS_DEBUG, "refcode loading from cache.\n"); + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid ramstage cache descriptor.\n"); + return NULL; + } + + c = next_cache(c); + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid refcode cache descriptor.\n"); + return NULL; + } + + printk(BIOS_DEBUG, "Loading cached reference code from 0x%08x(%x)\n", + c->load_address, c->size); + memcpy((void *)c->load_address, &c->program[0], c->size); + + return (efi_wrapper_entry_t)c->entry_point; +} + +static void cache_refcode(const struct rmod_stage_load *rsl) +{ + struct ramstage_cache *c; + long cache_size; + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "No place to cache reference code.\n"); + return; + } + + /* Determine how much remaining cache available. */ + cache_size -= c->size + sizeof(*c); + + if (cache_size < (sizeof(*c) + cbmem_entry_size(rsl->cbmem_entry))) { + printk(BIOS_DEBUG, "Not enough cache space for ref code.\n"); + return; + } + + c = next_cache(c); + c->magic = RAMSTAGE_CACHE_MAGIC; + c->entry_point = (uint32_t)rsl->entry; + c->load_address = (uint32_t)cbmem_entry_start(rsl->cbmem_entry); + c->size = cbmem_entry_size(rsl->cbmem_entry);; + + printk(BIOS_DEBUG, "Caching refcode at 0x%p(%x)\n", + &c->program[0], c->size); + memcpy(&c->program[0], (void *)c->load_address, c->size); +} + +static int load_refcode_from_vboot(struct rmod_stage_load *refcode, + struct cbfs_stage *stage) +{ + printk(BIOS_DEBUG, "refcode loading from vboot rw area.\n"); + + if (rmodule_stage_load(refcode, stage) || refcode->entry == NULL) { + printk(BIOS_DEBUG, "Error loading reference code.\n"); + return -1; + } + return 0; +} + +static int load_refcode_from_cbfs(struct rmod_stage_load *refcode) +{ + printk(BIOS_DEBUG, "refcode loading from cbfs.\n"); + + if (rmodule_stage_load_from_cbfs(refcode) || refcode->entry == NULL) { + printk(BIOS_DEBUG, "Error loading reference code.\n"); + return -1; + } + + return 0; +} + +static efi_wrapper_entry_t load_reference_code(void) +{ + struct vboot_handoff *vboot_handoff; + const struct firmware_component *fwc; + struct rmod_stage_load refcode = { + .cbmem_id = CBMEM_ID_REFCODE, + .name = CONFIG_CBFS_PREFIX "/refcode", + }; + int ret; + + if (is_s3_resume()) { + return load_refcode_from_cache(); + } + + vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + fwc = &vboot_handoff->components[CONFIG_VBOOT_REFCODE_INDEX]; + + if (vboot_handoff == NULL || + vboot_handoff->selected_firmware == VB_SELECT_FIRMWARE_READONLY || + CONFIG_VBOOT_REFCODE_INDEX >= MAX_PARSED_FW_COMPONENTS || + fwc->size == 0 || fwc->address == 0) { + ret = load_refcode_from_cbfs(&refcode); + } else { + ret = load_refcode_from_vboot(&refcode, (void *)fwc->address); + + if (ret < 0) + ret = load_refcode_from_cbfs(&refcode); + } + + if (ret < 0) + return NULL; + + /* Cache loaded reference code. */ + cache_refcode(&refcode); + + return refcode.entry; +} + +void baytrail_run_reference_code(void) +{ + int ret; + efi_wrapper_entry_t entry; + struct efi_wrapper_params wrp = { + .version = EFI_WRAPPER_VER, + .console_out = send_to_console, + }; + + entry = load_reference_code(); + + if (entry == NULL) + return; + + wrp.tsc_ticks_per_microsecond = tsc_freq_mhz(); + + /* Call into reference code. */ + ret = entry(&wrp); + + if (ret != 0) { + printk(BIOS_DEBUG, "Reference code returned %d\n", ret); + return; + } +} + diff --git a/src/soc/intel/baytrail/reset.c b/src/soc/intel/baytrail/reset.c new file mode 100644 index 0000000000..c4cb2abfb7 --- /dev/null +++ b/src/soc/intel/baytrail/reset.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void cold_reset(void) +{ + /* S0->S5->S0 trip. */ + outb(RST_CPU | SYS_RST | FULL_RST, RST_CNT); +} + +void warm_reset(void) +{ + /* PMC_PLTRST# asserted. */ + outb(RST_CPU | SYS_RST, RST_CNT); +} + +void soft_reset(void) +{ + /* Sends INIT# to CPU */ + outb(RST_CPU, RST_CNT); +} + +void hard_reset(void) +{ + /* Don't power cycle on hard_reset(). It's not really clear what the + * semantics should be for the meaning of hard_reset(). */ + warm_reset(); +} diff --git a/src/soc/intel/baytrail/romstage/Makefile.inc b/src/soc/intel/baytrail/romstage/Makefile.inc new file mode 100644 index 0000000000..dbca9763d1 --- /dev/null +++ b/src/soc/intel/baytrail/romstage/Makefile.inc @@ -0,0 +1,7 @@ +cpu_incs += $(src)/soc/intel/baytrail/romstage/cache_as_ram.inc +romstage-y += romstage.c +romstage-y += raminit.c +romstage-y += gfx.c +romstage-y += pmc.c +romstage-y += early_spi.c +romstage-$(CONFIG_ENABLE_BUILTIN_COM1) += com1.c diff --git a/src/soc/intel/baytrail/romstage/cache_as_ram.inc b/src/soc/intel/baytrail/romstage/cache_as_ram.inc new file mode 100644 index 0000000000..1d49af58cd --- /dev/null +++ b/src/soc/intel/baytrail/romstage/cache_as_ram.inc @@ -0,0 +1,286 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2007-2008 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +/* The full cache-as-ram size includes the cache-as-ram portion from coreboot + * and the space used by the reference code. These 2 values combined should + * be a power of 2 because the MTRR setup assumes that. */ +#define CACHE_AS_RAM_SIZE \ + (CONFIG_DCACHE_RAM_SIZE + CONFIG_DCACHE_RAM_MRC_VAR_SIZE) +#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE + +/* Cache all of CBFS just below 4GiB as Write-Protect type. */ +#define CODE_CACHE_SIZE (CONFIG_CBFS_SIZE) +#define CODE_CACHE_BASE (-CODE_CACHE_SIZE) +#define CODE_CACHE_MASK (~(CODE_CACHE_SIZE - 1)) +#define CPU_PHYSMASK_HI ((1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1) + +#define NoEvictMod_MSR 0x2e0 +#define BBL_CR_CTL3_MSR 0x11e +#define MCG_CAP_MSR 0x179 + + /* Save the BIST result. */ + movl %eax, %ebp + +cache_as_ram: + post_code(0x20) + + /* Send INIT IPI to all excluding ourself. */ + movl $0x000C4500, %eax + movl $0xFEE00300, %esi + movl %eax, (%esi) + + /* All CPUs need to be in Wait for SIPI state */ +wait_for_sipi: + movl (%esi), %eax + bt $12, %eax + jc wait_for_sipi + + post_code(0x21) + /* Configure the default memory type to uncacheable as well as disable + * fixed and variable range mtrrs. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + andl $(~0x00000cff), %eax + wrmsr + + post_code(0x22) + /* Zero the variable MTRRs. */ + movl $MCG_CAP_MSR, %ecx + rdmsr + movzx %al, %ebx + /* First variable MTRR. */ + movl $0x200, %ecx + xorl %eax, %eax + xorl %edx, %edx + 1: + wrmsr + inc %ecx + dec %ebx + jnz 1b + + /* Zero out all fixed range and variable range MTRRs. */ + movl $fixed_mtrr_table, %esi + movl $((fixed_mtrr_table_end - fixed_mtrr_table) / 2), %edi + xorl %eax, %eax + xorl %edx, %edx + 1: + movw (%esi), %bx + movzx %bx, %ecx + wrmsr + add $2, %esi + dec %edi + jnz 1b + + post_code(0x23) + /* Set Cache-as-RAM base address. */ + movl $(MTRRphysBase_MSR(0)), %ecx + movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax + xorl %edx, %edx + wrmsr + + post_code(0x24) + /* Set Cache-as-RAM mask. */ + movl $(MTRRphysMask_MSR(0)), %ecx + movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $CPU_PHYSMASK_HI, %edx + wrmsr + + post_code(0x25) + /* Set code caching up for romstage. */ + movl $(MTRRphysBase_MSR(1)), %ecx + movl $(CODE_CACHE_BASE | MTRR_TYPE_WRPROT), %eax + xorl %edx, %edx + wrmsr + + movl $(MTRRphysMask_MSR(1)), %ecx + movl $(CODE_CACHE_MASK | MTRRphysMaskValid), %eax + movl $CPU_PHYSMASK_HI, %edx + wrmsr + + /* Enable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + post_code(0x26) + + /* Enable the L2 cache. */ + movl $BBL_CR_CTL3_MSR, %ecx + rdmsr + orl $0x100, %eax + wrmsr + + post_code(0x27) + + /* Enable cache (CR0.CD = 0, CR0.NW = 0). */ + movl %cr0, %eax + andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax + invd + movl %eax, %cr0 + + /* enable the 'no eviction' mode */ + movl $NoEvictMod_MSR, %ecx + rdmsr + orl $1, %eax + wrmsr + + post_code(0x28) + + /* Clear the cache memory region. This will also fill up the cache */ + movl $CACHE_AS_RAM_BASE, %esi + movl %esi, %edi + movl $(CACHE_AS_RAM_SIZE / 4), %ecx + xorl %eax, %eax + rep stosl + + /* enable no evict mode */ + movl $NoEvictMod_MSR, %ecx + rdmsr + orl $2, %eax + wrmsr + + post_code(0x29) + + /* Setup the stack. */ + movl $(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE), %eax + movl %eax, %esp + + /* Push the initial TSC value from boot block. The low 32 bits are + * in mm0, and the high 32 bits are in mm1. */ + movd %mm1, %eax + pushl %eax + movd %mm0, %eax + pushl %eax + /* Restore the BIST result. */ + movl %ebp, %eax + movl %esp, %ebp + pushl %eax + +before_romstage: + post_code(0x2a) + /* Call romstage.c main function. */ + call romstage_main + /* Save return value from romstage_main. It contains the stack to use + * after cache-as-ram is torn down. It also contains the information + * for setting up MTTRs. */ + movl %eax, %ebx + + post_code(0x2b) + + /* Disable cache. */ + movl %cr0, %eax + orl $CR0_CacheDisable, %eax + movl %eax, %cr0 + + post_code(0x2c) + + /* Disable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + andl $(~MTRRdefTypeEn), %eax + wrmsr + + invd + + post_code(0x2d) + + /* Disable the no eviction run state */ + movl $NoEvictMod_MSR, %ecx + rdmsr + andl $~2, %eax + wrmsr + + /* Disable the no eviction mode */ + rdmsr + andl $~1, %eax + wrmsr + + post_code(0x2e) + + /* Setup stack as indicated by return value from ramstage_main(). */ + movl %ebx, %esp + + /* Get number of MTTRs. */ + popl %ebx + movl $MTRRphysBase_MSR(0), %ecx +1: + testl %ebx, %ebx + jz 1f + + /* Low 32 bits of MTTR base. */ + popl %eax + /* Upper 32 bits of MTTR base. */ + popl %edx + /* Write MTRR base. */ + wrmsr + inc %ecx + /* Low 32 bits of MTTR mask. */ + popl %eax + /* Upper 32 bits of MTTR mask. */ + popl %edx + /* Write MTRR mask. */ + wrmsr + inc %ecx + + dec %ebx + jmp 1b +1: + post_code(0x2f) + + /* And enable cache again after setting MTRRs. */ + movl %cr0, %eax + andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax + movl %eax, %cr0 + + post_code(0x30) + + /* Enable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + post_code(0x31) + +__main: + post_code(POST_PREPARE_RAMSTAGE) + cld /* Clear direction flag. */ + call romstage_after_car + +.Lhlt: + post_code(POST_DEAD_CODE) + hlt + jmp .Lhlt + +/* Fixed MTRRs */ +fixed_mtrr_table: + .word 0x250, 0x258, 0x259 + .word 0x268, 0x269, 0x26A + .word 0x26B, 0x26C, 0x26D + .word 0x26E, 0x26F +fixed_mtrr_table_end: + diff --git a/src/soc/intel/baytrail/romstage/com1.c b/src/soc/intel/baytrail/romstage/com1.c new file mode 100644 index 0000000000..7705746b9e --- /dev/null +++ b/src/soc/intel/baytrail/romstage/com1.c @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +void byt_config_com1_and_enable(void) +{ + uint32_t reg; + + /* Enable the UART hardware for COM1. */ + reg = 1; + pci_write_config32(PCI_DEV(0, LPC_DEV, 0), UART_CONT, reg); + + /* Set up the pads to select the UART function */ + score_select_func(UART_RXD_PAD, 1); + score_select_func(UART_TXD_PAD, 1); +} diff --git a/src/soc/intel/baytrail/romstage/early_spi.c b/src/soc/intel/baytrail/romstage/early_spi.c new file mode 100644 index 0000000000..2c48af1698 --- /dev/null +++ b/src/soc/intel/baytrail/romstage/early_spi.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include +#include + +#define SPI_CYCLE_DELAY 10 /* 10us */ +#define SPI_CYCLE_TIMEOUT 400000 / SPI_CYCLE_DELAY /* 400ms */ + +#define SPI8(x) *((volatile u8 *)(SPI_BASE_ADDRESS + x)) +#define SPI16(x) *((volatile u16 *)(SPI_BASE_ADDRESS + x)) +#define SPI32(x) *((volatile u32 *)(SPI_BASE_ADDRESS + x)) + +/* Minimal set of commands to read wpsr from SPI. Don't use this code outside + * romstage -- it trashes the opmenu table. + * Returns 0 on success, < 0 on failure. */ +int early_spi_read_wpsr(u8 *sr) +{ + int timeout = SPI_CYCLE_TIMEOUT; + + /* No address associated with rdsr */ + SPI8(OPTYPE) = 0x0; + /* Setup opcode[0] = read wpsr */ + SPI8(OPMENU0) = 0x5; + + /* Start transaction */ + SPI16(SSFC) = DATA_CYCLE | SPI_CYCLE_GO; + + /* Wait for error / complete status */ + while(timeout--) { + u16 status = SPI16(SSFS); + if (status & FLASH_CYCLE_ERROR) { + printk(BIOS_ERR, "SPI rdsr failed\n"); + return -1; + } else if (status & CYCLE_DONE_STATUS) + break; + + udelay(SPI_CYCLE_DELAY); + } + + *sr = SPI32(FDATA0) & 0xff; + return 0; +} diff --git a/src/soc/intel/baytrail/romstage/gfx.c b/src/soc/intel/baytrail/romstage/gfx.c new file mode 100644 index 0000000000..f9bb9c9e8f --- /dev/null +++ b/src/soc/intel/baytrail/romstage/gfx.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void gfx_init(void) +{ + uint32_t ggc; + uint8_t msac; + const unsigned int gfx_dev = PCI_DEV(0, GFX_DEV, GFX_FUNC); + + /* The GFX device needs to set the aperture, gtt stolen size, and + * graphics stolen memory stolen size before running MRC. For now + * just hard code the defaults. Options can be added to the device + * tree if needed. */ + + ggc = pci_read_config32(gfx_dev, GGC); + msac = pci_read_config8(gfx_dev, MSAC); + + ggc &= ~(GGC_GTT_SIZE_MASK | GGC_GSM_SIZE_MASK); + /* 32MB GSM is not supported with +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../chip.h" + +void tco_disable(void) +{ + uint32_t reg; + + reg = inl(ACPI_BASE_ADDRESS + TCO1_CNT); + reg |= TCO_TMR_HALT; + outl(reg, ACPI_BASE_ADDRESS + TCO1_CNT); +} + +/* This sequence signals the PUNIT to start running. */ +void punit_init(void) +{ + uint32_t reg; + uint8_t rid; + const struct device *dev; + const struct soc_intel_baytrail_config *cfg = NULL; + + rid = pci_read_config8(IOSF_PCI_DEV, REVID); + dev = dev_find_slot(0, PCI_DEVFN(SOC_DEV, SOC_FUNC)); + + if (dev) + cfg = dev->chip_info; + + reg = iosf_punit_read(SB_BIOS_CONFIG); + /* Write bits 17:16 of SB_BIOS_CONFIG in the PUNIT. */ + reg |= SB_BIOS_CONFIG_PERF_MODE | SB_BIOS_CONFIG_PDM_MODE; + /* Configure VR low power mode for C0 and above. */ + if (rid >= RID_C_STEPPING_START && cfg != NULL && + (cfg->vnn_ps2_enable || cfg->vcc_ps2_enable)) { + printk(BIOS_DEBUG, "Enabling VR PS2 mode: "); + if (cfg->vnn_ps2_enable) { + reg |= SB_BIOS_CONFIG_PS2_EN_VNN; + printk(BIOS_DEBUG, "VNN "); + } + if (cfg->vcc_ps2_enable) { + reg |= SB_BIOS_CONFIG_PS2_EN_VCC; + printk(BIOS_DEBUG, "VCC "); + } + printk(BIOS_DEBUG, "\n"); + } + iosf_punit_write(SB_BIOS_CONFIG, reg); + + /* Write bits 1:0 of BIOS_RESET_CPL in the PUNIT. */ + reg = BIOS_RESET_CPL_ALL_DONE | BIOS_RESET_CPL_RESET_DONE; + pci_write_config32(IOSF_PCI_DEV, MDR_REG, reg); + reg = IOSF_OPCODE(IOSF_OP_WRITE_PMC) | IOSF_PORT(IOSF_PORT_PMC) | + IOSF_REG(BIOS_RESET_CPL) | IOSF_BYTE_EN_0; + pci_write_config32(IOSF_PCI_DEV, MCR_REG, reg); +} + diff --git a/src/soc/intel/baytrail/romstage/raminit.c b/src/soc/intel/baytrail/romstage/raminit.c new file mode 100644 index 0000000000..d9354dbc99 --- /dev/null +++ b/src/soc/intel/baytrail/romstage/raminit.c @@ -0,0 +1,193 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_CHROMEOS +#include +#else +#define recovery_mode_enabled(x) 0 +#endif + +static void reset_system(void) +{ + warm_reset(); + while(1) { hlt(); } +} + +static void enable_smbus(void) +{ + uint32_t reg; + const uint32_t smbus_dev = PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC); + + /* SMBus I/O BAR */ + reg = SMBUS_BASE_ADDRESS | 2; + pci_write_config32(smbus_dev, PCI_BASE_ADDRESS_4, reg); + /* Enable decode of I/O space. */ + reg = pci_read_config16(smbus_dev, PCI_COMMAND); + reg |= 0x1; + pci_write_config16(smbus_dev, PCI_COMMAND, reg); + /* Enable Host Controller */ + reg = pci_read_config8(smbus_dev, 0x40); + reg |= 1; + pci_write_config8(smbus_dev, 0x40, reg); + + /* Configure pads to be used for SMBus */ + score_select_func(PCU_SMB_CLK_PAD, 1); + score_select_func(PCU_SMB_DATA_PAD, 1); +} + +static void ABI_X86 send_to_console(unsigned char b) +{ + console_tx_byte(b); +} + +static void print_dram_info(void) +{ + const int mrc_ver_reg = 0xf0; + const uint32_t soc_dev = PCI_DEV(0, SOC_DEV, SOC_FUNC); + uint32_t reg; + int num_channels; + int speed; + uint32_t ch0; + uint32_t ch1; + + reg = pci_read_config32(soc_dev, mrc_ver_reg); + + printk(BIOS_INFO, "MRC v%d.%02d\n", (reg >> 8) & 0xff, reg & 0xff); + + /* Number of channels enabled and DDR3 type. Determine number of + * channels by keying of the rank enable bits [3:0]. * */ + ch0 = iosf_dunit_ch0_read(DRP); + ch1 = iosf_dunit_ch1_read(DRP); + num_channels = 0; + if (ch0 & DRP_RANK_MASK) + num_channels++; + if (ch1 & DRP_RANK_MASK) + num_channels++; + + printk(BIOS_INFO, "%d channels of %sDDR3 @ ", num_channels, + (reg & (1 << 22)) ? "LP" : ""); + + /* DRAM frequency -- all channels run at same frequency. */ + reg = iosf_dunit_read(DTR0); + switch (reg & 0x3) { + case 0: + speed = 800; break; + case 1: + speed = 1066; break; + case 2: + speed = 1333; break; + case 3: + speed = 1600; break; + } + printk(BIOS_INFO, "%dMHz\n", speed); +} + +void raminit(struct mrc_params *mp, int prev_sleep_state) +{ + int ret; + mrc_wrapper_entry_t mrc_entry; + const struct mrc_saved_data *cache; + + /* Fill in default entries. */ + mp->version = MRC_PARAMS_VER; + mp->console_out = &send_to_console; + mp->prev_sleep_state = prev_sleep_state; +#if CONFIG_MRC_RMT + mp->rmt_enabled = 1; +#endif + + /* Default to 2GiB IO hole. */ + if (!mp->io_hole_mb) + mp->io_hole_mb = 2048; + + if (recovery_mode_enabled()) { + printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n"); + } else if (!mrc_cache_get_current(&cache)) { + mp->saved_data_size = cache->size; + mp->saved_data = &cache->data[0]; + } else if (prev_sleep_state == 3) { + /* If waking from S3 and no cache then. */ + printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n"); + post_code(POST_RESUME_FAILURE); + reset_system(); + } else { + printk(BIOS_DEBUG, "No MRC cache found.\n"); +#if CONFIG_EC_GOOGLE_CHROMEEC + if (prev_sleep_state == 0) { + /* Ensure EC is running RO firmware. */ + google_chromeec_check_ec_image(EC_IMAGE_RO); + } +#endif + } + + /* Determine if mrc.bin is in the cbfs. */ + if (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", 0xab) == + NULL) { + printk(BIOS_DEBUG, "Couldn't find mrc.bin\n"); + return; + } + + /* + * The entry point is currently the first instruction. Handle the + * case of an ELF file being put in the cbfs by setting the entry + * to the CONFIG_MRC_BIN_ADDRESS. + */ + mrc_entry = (void *)(uintptr_t)CONFIG_MRC_BIN_ADDRESS; + + if (mp->mainboard.dram_info_location == DRAM_INFO_SPD_SMBUS) + enable_smbus(); + + ret = mrc_entry(mp); + + print_dram_info(); + + if (prev_sleep_state != 3) { + cbmem_initialize_empty(); + } else if (cbmem_initialize()) { + #if CONFIG_HAVE_ACPI_RESUME + printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n"); + /* Failed S3 resume, reset to come up cleanly */ + reset_system(); + #endif + } + + printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret); + printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save, + mp->data_to_save_size); + + if (mp->data_to_save != NULL && mp->data_to_save_size > 0) + mrc_cache_stash_data(mp->data_to_save, mp->data_to_save_size); +} diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c new file mode 100644 index 0000000000..f4e084a89a --- /dev/null +++ b/src/soc/intel/baytrail/romstage/romstage.c @@ -0,0 +1,376 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_EC_GOOGLE_CHROMEEC +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The cache-as-ram assembly file calls romstage_main() after setting up + * cache-as-ram. romstage_main() will then call the mainboards's + * mainboard_romstage_entry() function. That function then calls + * romstage_common() below. The reason for the back and forth is to provide + * common entry point from cache-as-ram while still allowing for code sharing. + * Because we can't use global variables the stack is used for allocations -- + * thus the need to call back and forth. */ + +static void *setup_stack_and_mttrs(void); + +static void program_base_addresses(void) +{ + uint32_t reg; + const uint32_t lpc_dev = PCI_DEV(0, LPC_DEV, LPC_FUNC); + + /* Memory Mapped IO registers. */ + reg = PMC_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, PBASE, reg); + reg = IO_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, IOBASE, reg); + reg = ILB_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, IBASE, reg); + reg = SPI_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, SBASE, reg); + reg = MPHY_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, MPBASE, reg); + reg = PUNIT_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, PUBASE, reg); + reg = RCBA_BASE_ADDRESS | 1; + pci_write_config32(lpc_dev, RCBA, reg); + + /* IO Port Registers. */ + reg = ACPI_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, ABASE, reg); + reg = GPIO_BASE_ADDRESS | 2; + pci_write_config32(lpc_dev, GBASE, reg); +} + +static void spi_init(void) +{ + const unsigned long scs = SPI_BASE_ADDRESS + SCS; + const unsigned long bcr = SPI_BASE_ADDRESS + BCR; + uint32_t reg; + + /* Disable generating SMI when setting WPD bit. */ + write32(scs, read32(scs) & ~SMIWPEN); + /* + * Enable caching and prefetching in the SPI controller. Disable + * the SMM-only BIOS write and set WPD bit. + */ + reg = (read32(bcr) & ~SRC_MASK) | SRC_CACHE_PREFETCH | BCR_WPD; + reg &= ~EISS; + write32(bcr, reg); +} + +/* Entry from cache-as-ram.inc. */ +void * asmlinkage romstage_main(unsigned long bist, + uint32_t tsc_low, uint32_t tsc_hi) +{ + struct romstage_params rp = { + .bist = bist, + .mrc_params = NULL, + }; + + timestamp_early_init((((uint64_t)tsc_hi) << 32) | (uint64_t)tsc_low); + timestamp_add_now(TS_START_ROMSTAGE); + + program_base_addresses(); + + tco_disable(); + + byt_config_com1_and_enable(); + + console_init(); + + spi_init(); + + set_max_freq(); + + punit_init(); + + gfx_init(); + +#if CONFIG_EC_GOOGLE_CHROMEEC + /* Ensure the EC is in the right mode for recovery */ + google_chromeec_early_init(); +#endif + + /* Call into mainboard. */ + mainboard_romstage_entry(&rp); + + return setup_stack_and_mttrs(); +} + +static struct chipset_power_state power_state CAR_GLOBAL; + +static void migrate_power_state(void) +{ + struct chipset_power_state *ps_cbmem; + struct chipset_power_state *ps_car; + + ps_car = car_get_var_ptr(&power_state); + ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem)); + + if (ps_cbmem == NULL) { + printk(BIOS_DEBUG, "Not adding power state to cbmem!\n"); + return; + } + memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem)); +} +ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state) + +static struct chipset_power_state *fill_power_state(void) +{ + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + + ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS); + ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN); + ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + ps->gpe0_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS); + ps->gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN); + ps->tco_sts = inl(ACPI_BASE_ADDRESS + TCO_STS); + ps->prsts = read32(PMC_BASE_ADDRESS + PRSTS); + ps->gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1); + ps->gen_pmcon2 = read32(PMC_BASE_ADDRESS + GEN_PMCON2); + + printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n", + ps->pm1_sts, ps->pm1_en, ps->pm1_cnt); + printk(BIOS_DEBUG, "gpe0_sts: %08x gpe0_en: %08x tco_sts: %08x\n", + ps->gpe0_sts, ps->gpe0_en, ps->tco_sts); + printk(BIOS_DEBUG, "prsts: %08x gen_pmcon1: %08x gen_pmcon2: %08x\n", + ps->prsts, ps->gen_pmcon1, ps->gen_pmcon2); + + return ps; +} + +/* Return 0, 3, or 5 to indicate the previous sleep state. */ +static int chipset_prev_sleep_state(struct chipset_power_state *ps) +{ + /* Default to S0. */ + int prev_sleep_state = 0; + + if (ps->pm1_sts & WAK_STS) { + switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) { + #if CONFIG_HAVE_ACPI_RESUME + case SLP_TYP_S3: + prev_sleep_state = 3; + break; + #endif + case SLP_TYP_S5: + prev_sleep_state = 5; + break; + } + /* Clear SLP_TYP. */ + outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT); + } + + if (ps->gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) { + prev_sleep_state = 5; + } + + return prev_sleep_state; +} + +static inline void chromeos_init(int prev_sleep_state) +{ +#if CONFIG_CHROMEOS + /* Normalize the sleep state to what init_chromeos() wants for S3: 2. */ + init_chromeos(prev_sleep_state == 3 ? 2 : 0); +#endif +} + +/* Entry from the mainboard. */ +void romstage_common(struct romstage_params *params) +{ + struct romstage_handoff *handoff; + struct chipset_power_state *ps; + int prev_sleep_state; + + timestamp_add_now(TS_BEFORE_INITRAM); + + ps = fill_power_state(); + prev_sleep_state = chipset_prev_sleep_state(ps); + + printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state); + +#if CONFIG_ELOG_BOOT_COUNT + if (prev_sleep_state != 3) + boot_count_increment(); +#endif + + /* Initialize RAM */ + raminit(params->mrc_params, prev_sleep_state); + + timestamp_add_now(TS_AFTER_INITRAM); + + handoff = romstage_handoff_find_or_add(); + if (handoff != NULL) + handoff->s3_resume = (prev_sleep_state == 3); + else + printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); + + chromeos_init(prev_sleep_state); +} + +void asmlinkage romstage_after_car(void) +{ + timestamp_add_now(TS_END_ROMSTAGE); + + /* Run vboot verification if configured. */ + vboot_verify_firmware(romstage_handoff_find_or_add()); + + /* Load the ramstage. */ + copy_and_run(); + while (1); +} + +static inline uint32_t *stack_push(u32 *stack, u32 value) +{ + stack = &stack[-1]; + *stack = value; + return stack; +} + +/* Romstage needs quite a bit of stack for decompressing images since the lzma + * lib keeps its state on the stack during romstage. */ +static unsigned long choose_top_of_stack(void) +{ + unsigned long stack_top; + const unsigned long romstage_ram_stack_size = 0x5000; + + /* cbmem_add() does a find() before add(). */ + stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, + romstage_ram_stack_size); + stack_top += romstage_ram_stack_size; + return stack_top; +} + +/* setup_stack_and_mttrs() determines the stack to use after + * cache-as-ram is torn down as well as the MTRR settings to use. */ +static void *setup_stack_and_mttrs(void) +{ + unsigned long top_of_stack; + int num_mtrrs; + uint32_t *slot; + uint32_t mtrr_mask_upper; + uint32_t top_of_ram; + + /* Top of stack needs to be aligned to a 4-byte boundary. */ + top_of_stack = choose_top_of_stack() & ~3; + slot = (void *)top_of_stack; + num_mtrrs = 0; + + /* The upper bits of the MTRR mask need to set according to the number + * of physical address bits. */ + mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1; + + /* The order for each MTTR is value then base with upper 32-bits of + * each value coming before the lower 32-bits. The reasoning for + * this ordering is to create a stack layout like the following: + * +0: Number of MTRRs + * +4: MTTR base 0 31:0 + * +8: MTTR base 0 63:32 + * +12: MTTR mask 0 31:0 + * +16: MTTR mask 0 63:32 + * +20: MTTR base 1 31:0 + * +24: MTTR base 1 63:32 + * +28: MTTR mask 1 31:0 + * +32: MTTR mask 1 63:32 + */ + + /* Cache the ROM as WP just below 4GiB. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT); + num_mtrrs++; + + /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK); + num_mtrrs++; + + top_of_ram = (uint32_t)cbmem_top(); + /* Cache 8MiB below the top of ram. The top of ram under 4GiB is the + * start of the TSEG region. It is required to be 8MiB aligned. Set + * this area as cacheable so it can be used later for ramstage before + * setting up the entire RAM as cacheable. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK); + num_mtrrs++; + + /* Cache 8MiB at the top of ram. Top of ram is where the TSEG + * region resides. However, it is not restricted to SMM mode until + * SMM has been relocated. By setting the region to cacheable it + * provides faster access when relocating the SMM handler as well + * as using the TSEG region for other purposes. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK); + num_mtrrs++; + + /* Save the number of MTTRs to setup. Return the stack location + * pointing to the number of MTRRs. */ + slot = stack_push(slot, num_mtrrs); + + return slot; +} + +void ramstage_cache_invalid(struct ramstage_cache *cache) +{ +#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE + /* Perform cold reset on invalid ramstage cache. */ + cold_reset(); +#endif +} + +#if CONFIG_CHROMEOS +int vboot_get_sw_write_protect(void) +{ + u8 status; + /* Return unprotected status if status read fails. */ + return (early_spi_read_wpsr(&status) ? 0 : !!(status & 0x80)); +} +#endif diff --git a/src/soc/intel/baytrail/sata.c b/src/soc/intel/baytrail/sata.c new file mode 100644 index 0000000000..7021b98a18 --- /dev/null +++ b/src/soc/intel/baytrail/sata.c @@ -0,0 +1,240 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +typedef struct soc_intel_baytrail_config config_t; + +static inline void sir_write(struct device *dev, int idx, u32 value) +{ + pci_write_config32(dev, SATA_SIRI, idx); + pci_write_config32(dev, SATA_SIRD, value); +} + +static void sata_init(struct device *dev) +{ + config_t *config = dev->chip_info; + u32 reg32; + u16 reg16; + u8 reg8; + + printk(BIOS_DEBUG, "SATA: Initializing...\n"); + + if (config == NULL) { + printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n"); + return; + } + + if (!config->sata_ahci) { + /* Set legacy or native decoding mode */ + if (config->ide_legacy_combined) { + reg8 = pci_read_config8(dev, 0x09); + reg8 &= ~0x5; + pci_write_config8(dev, 0x09, reg8); + } else { + reg8 = pci_read_config8(dev, 0x09); + reg8 |= 0x5; + pci_write_config8(dev, 0x09, reg8); + } + + /* Set capabilities pointer */ + pci_write_config8(dev, 0x34, 0x70); + reg16 = pci_read_config16(dev, 0x70); + reg16 &= ~0xFF00; + pci_write_config16(dev, 0x70, reg16); + } + + /* Primary timing - decode enable */ + reg16 = pci_read_config16(dev, 0x40); + reg16 |= 1 << 15; + pci_write_config16(dev, 0x40, reg16); + + /* Secondary timing - decode enable */ + reg16 = pci_read_config16(dev, 0x42); + reg16 |= 1 << 15; + pci_write_config16(dev, 0x42, reg16); + + /* Port mapping enables */ + reg16 = pci_read_config16(dev, 0x90); + reg16 |= (config->sata_port_map ^ 0x3) << 8; + pci_write_config16(dev, 0x90, reg16); + + /* Port control enables */ + reg16 = pci_read_config16(dev, 0x92); + reg16 &= ~0x003f; + reg16 |= config->sata_port_map; + pci_write_config16(dev, 0x92, reg16); + + if (config->sata_ahci) { + u32 abar = pci_read_config32(dev, PCI_BASE_ADDRESS_5); + + /* Enable CR memory space decoding */ + reg16 = pci_read_config16(dev, 0x04); + reg16 |= 0x2; + pci_write_config16(dev, 0x04, reg16); + + /* Set capibility register */ + reg32 = read32(abar + 0x00); + reg32 |= 0x0c046000; // set PSC+SSC+SALP+SSS+SAM + reg32 &= ~0x00f20060; // clear SXS+EMS+PMS+gen bits + reg32 |= (0x3 << 20); // Gen3 SATA + write32(abar + 0x00, reg32); + + /* Ports enabled */ + reg32 = read32(abar + 0x0c); + reg32 &= (u32)(~0x3f); + reg32 |= config->sata_port_map; + write32(abar + 0xc, reg32); + /* Two extra reads to latch */ + read32(abar + 0x0c); + read32(abar + 0x0c); + + /* Set cap2 - Support devslp */ + reg32 = (1 << 5) | (1 << 4) | (1 << 3); + write32(abar + 0x24, reg32); + + /* Set PxCMD registers */ + reg32 = read32(abar + 0x118); + reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) | + (1 << 19) | (1 << 18) | (1 << 1)); + reg32 |= 2; + write32(abar + 0x118, reg32); + + reg32 = read32(abar + 0x198); + reg32 &= ~((1 << 27) | (1 << 26) | (1 << 22) | (1 << 21) | + (1 << 19) | (1 << 18) | (1 << 1)); + reg32 |= 2; + write32(abar + 0x198, reg32); + + /* Clear reset features */ + write32(abar + 0xc8, 0); + + /* Enable interrupts */ + reg8 = read8(abar + 0x04); + reg8 |= 0x02; + write8(abar + 0x04, reg8); + + } else { + /* TODO(shawnn): Configure IDE SATA speed regs */ + } + + /* 1.4 us delay after configuring port / enable bits */ + udelay(2); + + /* Enable clock for ports */ + reg32 = pci_read_config32(dev, 0x94); + reg32 |= 0x3f << 24; + pci_write_config32(dev, 0x94, reg32); + reg32 &= (config->sata_port_map ^ 0x3) << 24; + pci_write_config32(dev, 0x94, reg32); + + /* Lock SataGc register */ + reg32 = (0x1 << 31) | (0x7 << 12); + pci_write_config32(dev, 0x98, reg32); +} + +static void sata_enable(device_t dev) +{ + config_t *config = dev->chip_info; + u8 reg8; + u16 reg16; + u32 reg32; + + southcluster_enable_dev(dev); + if (!config) + return; + + /* Port mapping -- mask off SPD + SMS + SC bits, then re-set */ + reg16 = pci_read_config16(dev, 0x90); + reg16 &= ~0x03e0; + reg16 |= (config->sata_port_map ^ 0x3) << 8; + if(config->sata_ahci) + reg16 |= 0x60; + pci_write_config16(dev, 0x90, reg16); + + /* Set reg 0x94 before starting configuration */ + reg32 = pci_read_config32(dev, 0x94); + reg32 &= (u32)(~0x1ff); + reg32 |= 0x183; + pci_write_config32(dev, 0x94, reg32); + + /* Set ORM bit */ + reg16 = pci_read_config16(dev, 0x92); + reg16 |= (1 << 15); + pci_write_config16(dev, 0x92, reg16); + + /* R_PCH_SATA_TM2 - Undocumented in EDS, set according to ref. code */ + reg32 = pci_read_config32(dev, 0x98); + reg32 &= (u32)~(0x1f80 | (1 << 6) | (1 << 5)); + reg32 |= (1 << 29) | (1 << 25) | (1 << 23) | (1 << 22) | + (1 << 20) | (1 << 19) | (1 << 18) | (1 << 9) | (1 << 5); + pci_write_config32(dev, 0x98, reg32); + + /* CMD reg - set bus master enable (BME) */ + reg8 = pci_read_config8(dev, 0x04); + reg8 |= (1 << 2); + pci_write_config8(dev, 0x04, reg8); + + /* "Test mode registers" */ + sir_write(dev, 0x70, 0x00288301); + sir_write(dev, 0x54, 0x00000300); + sir_write(dev, 0x58, 0x50000000); + /* "OOB Detection Margin */ + sir_write(dev, 0x6c, 0x130C0603); + /* "Gasket Control" */ + sir_write(dev, 0xf4, 0); + + /* PCS - Enable requested SATA ports */ + reg8 = pci_read_config8(dev, 0x92); + reg8 &= ~0x03; + reg8 |= config->sata_port_map; + pci_write_config8(dev, 0x92, reg8); +} + +static struct device_operations sata_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sata_init, + .enable = sata_enable, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + IDE1_DEVID, IDE2_DEVID, /* IDE */ + AHCI1_DEVID, AHCI2_DEVID, /* AHCI */ + 0, +}; + +static const struct pci_driver baytrail_sata __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/baytrail/scc.c b/src/soc/intel/baytrail/scc.c new file mode 100644 index 0000000000..6400996ace --- /dev/null +++ b/src/soc/intel/baytrail/scc.c @@ -0,0 +1,125 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const struct reg_script scc_start_dll[] = { + /* Configure master DLL. */ + REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4964, 0x00078000), + /* Configure Swing,FSM for Master DLL */ + REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00000133), + /* Run+Local Reset on Master DLL */ + REG_IOSF_WRITE(IOSF_PORT_SCORE, 0x4970, 0x00001933), + REG_SCRIPT_END, +}; + +static const struct reg_script scc_after_dll[] = { + /* Configure Write Path */ + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4954, ~0x7fff, 0x35ad), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4958, ~0x7fff, 0x35ad), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x495c, ~0x7fff, 0x35ad), + /* Configure Read Path */ + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x43e4, ~0x7fff, 0x35ad), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x4324, ~0x7fff, 0x35ad), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x42b4, ~0x7fff, 0x35ad), + /* eMMC 4.5 TX and RX DLL */ + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a4, ~0x1f001f, 0xa000d), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49a8, ~0x1f001f, 0xd000d), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49ac, ~0x1f001f, 0xd000d), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b0, ~0x1f001f, 0xd000d), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b4, ~0x1f001f, 0xd000d), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x49b8, ~0x1, 0x0), + /* cfio_regs_mmc1_ELECTRICAL.nslew/pslew */ + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c0, ~0x3c, 0x0), + REG_IOSF_RMW(IOSF_PORT_SCORE, 0x48c4, ~0x3c, 0x0), + /* + * iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_ocp = 01 + * iosf2ocp_private.GENREGRW1.cr_clock_enable_clk_xin = 01 + */ + REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0xf, 0x5), + /* Enable IOSF Snoop */ + REG_IOSF_OR(IOSF_PORT_SCC, 0x00, (1 << 7)), + /* SDIO 3V Support. */ + REG_IOSF_RMW(IOSF_PORT_SCC, 0x600, ~0x30, 0x30), + REG_SCRIPT_END, +}; + +void baytrail_init_scc(void) +{ + uint32_t dll_values; + + printk(BIOS_DEBUG, "Initializing sideband SCC registers.\n"); + + /* Common Sideband Initialization for SCC */ + reg_script_run(scc_start_dll); + + /* Override Slave Path - populate DLL settings. */ + dll_values = iosf_score_read(0x496c) & 0x7ffff; + dll_values |= iosf_score_read(0x4950) & ~0xfffff; + iosf_score_write(0x4950, dll_values | (1 << 19)); + + reg_script_run(scc_after_dll); +} + +void scc_enable_acpi_mode(device_t dev, int iosf_reg, int nvs_index) +{ + struct reg_script ops[] = { + /* Disable PCI interrupt, enable Memory and Bus Master */ + REG_PCI_OR32(PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1<<10)), + /* Enable ACPI mode */ + REG_IOSF_OR(IOSF_PORT_SCC, iosf_reg, + SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN), + REG_SCRIPT_END + }; + struct resource *bar; + global_nvs_t *gnvs; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + bar = find_resource(dev, PCI_BASE_ADDRESS_0); + if (bar) + gnvs->dev.scc_bar0[nvs_index] = (u32)bar->base; + + bar = find_resource(dev, PCI_BASE_ADDRESS_1); + if (bar) + gnvs->dev.scc_bar1[nvs_index] = (u32)bar->base; + + /* Device is enabled in ACPI mode */ + gnvs->dev.scc_en[nvs_index] = 1; + + /* Put device in ACPI mode */ + reg_script_run_on_dev(dev, ops); +} diff --git a/src/soc/intel/baytrail/sd.c b/src/soc/intel/baytrail/sd.c new file mode 100644 index 0000000000..577469d3aa --- /dev/null +++ b/src/soc/intel/baytrail/sd.c @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "chip.h" + +#define CAP_OVERRIDE_LOW 0xa0 +#define CAP_OVERRIDE_HIGH 0xa4 +# define USE_CAP_OVERRIDES (1 << 31) + +static void sd_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + + if (config == NULL) + return; + + if (config->sdcard_cap_low != 0 || config->sdcard_cap_high != 0) { + printk(BIOS_DEBUG, "Overriding SD Card controller caps.\n"); + pci_write_config32(dev, CAP_OVERRIDE_LOW, + config->sdcard_cap_low); + pci_write_config32(dev, CAP_OVERRIDE_HIGH, + config->sdcard_cap_high | USE_CAP_OVERRIDES); + } + + if (config->scc_acpi_mode) + scc_enable_acpi_mode(dev, SCC_SD_CTL, SCC_NVS_SD); +} + +static const struct device_operations device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sd_init, + .enable = NULL, + .scan_bus = NULL, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = SD_DEVID, +}; diff --git a/src/soc/intel/baytrail/smihandler.c b/src/soc/intel/baytrail/smihandler.c new file mode 100644 index 0000000000..aa1ee68811 --- /dev/null +++ b/src/soc/intel/baytrail/smihandler.c @@ -0,0 +1,483 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* GNVS needs to be set by coreboot initiating a software SMI. */ +static global_nvs_t *gnvs; +static int smm_initialized; + +int southbridge_io_trap_handler(int smif) +{ + switch (smif) { + case 0x32: + printk(BIOS_DEBUG, "OS Init\n"); + /* gnvs->smif: + * On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + */ + gnvs->smif = 0; + return 1; /* IO trap handled */ + } + + /* Not handled */ + return 0; +} + +void southbridge_smi_set_eos(void) +{ + enable_smi(EOS); +} + +global_nvs_t *smm_get_gnvs(void) +{ + return gnvs; +} + +static void busmaster_disable_on_bus(int bus) +{ + int slot, func; + unsigned int val; + unsigned char hdr; + + for (slot = 0; slot < 0x20; slot++) { + for (func = 0; func < 8; func++) { + u32 reg32; + device_t dev = PCI_DEV(bus, slot, func); + + val = pci_read_config32(dev, PCI_VENDOR_ID); + + if (val == 0xffffffff || val == 0x00000000 || + val == 0x0000ffff || val == 0xffff0000) + continue; + + /* Disable Bus Mastering for this one device */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~PCI_COMMAND_MASTER; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* If this is a bridge, then follow it. */ + hdr = pci_read_config8(dev, PCI_HEADER_TYPE); + hdr &= 0x7f; + if (hdr == PCI_HEADER_TYPE_BRIDGE || + hdr == PCI_HEADER_TYPE_CARDBUS) { + unsigned int buses; + buses = pci_read_config32(dev, PCI_PRIMARY_BUS); + busmaster_disable_on_bus((buses >> 8) & 0xff); + } + } + } +} + +static void southbridge_smi_sleep(void) +{ + uint32_t reg32; + uint8_t slp_typ; + uint16_t pmbase = get_pmbase(); + + /* First, disable further SMIs */ + disable_smi(SLP_SMI_EN); + + /* Figure out SLP_TYP */ + reg32 = inl(pmbase + PM1_CNT); + printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32); + slp_typ = (reg32 >> 10) & 7; + + /* Do any mainboard sleep handling */ + mainboard_smi_sleep(slp_typ-2); + +#if CONFIG_ELOG_GSMI + /* Log S3, S4, and S5 entry */ + if (slp_typ >= 5) + elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2); +#endif + + /* Next, do the deed. + */ + + switch (slp_typ) { + case SLP_TYP_S0: + printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); + break; + case SLP_TYP_S1: + printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n"); + break; + case SLP_TYP_S3: + printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n"); + + /* Invalidate the cache before going to S3 */ + wbinvd(); + break; + case SLP_TYP_S4: + printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); + break; + case SLP_TYP_S5: + printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n"); + + /* Disable all GPE */ + disable_all_gpe(); + + /* also iterates over all bridges on bus 0 */ + busmaster_disable_on_bus(0); + break; + default: + printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); + break; + } + + /* Write back to the SLP register to cause the originally intended + * event again. We need to set BIT13 (SLP_EN) though to make the + * sleep happen. + */ + enable_pm1_control(SLP_EN); + + /* Make sure to stop executing code here for S3/S4/S5 */ + if (slp_typ > 1) + hlt(); + + /* In most sleep states, the code flow of this function ends at + * the line above. However, if we entered sleep state S1 and wake + * up again, we will continue to execute code in this function. + */ + reg32 = inl(pmbase + PM1_CNT); + if (reg32 & SCI_EN) { + /* The OS is not an ACPI OS, so we set the state to S0 */ + disable_pm1_control(SLP_EN | SLP_TYP); + } +} + +/* + * Look for Synchronous IO SMI and use save state from that + * core in case we are not running on the same core that + * initiated the IO transaction. + */ +static em64t100_smm_state_save_area_t *smi_apmc_find_state_save(uint8_t cmd) +{ + em64t100_smm_state_save_area_t *state; + int node; + + /* Check all nodes looking for the one that issued the IO */ + for (node = 0; node < CONFIG_MAX_CPUS; node++) { + state = smm_get_save_state(node); + + /* Check for Synchronous IO (bit0==1) */ + if (!(state->io_misc_info & (1 << 0))) + continue; + + /* Make sure it was a write (bit4==0) */ + if (state->io_misc_info & (1 << 4)) + continue; + + /* Check for APMC IO port */ + if (((state->io_misc_info >> 16) & 0xff) != APM_CNT) + continue; + + /* Check AX against the requested command */ + if ((state->rax & 0xff) != cmd) + continue; + + return state; + } + + return NULL; +} + +#if CONFIG_ELOG_GSMI +static void southbridge_smi_gsmi(void) +{ + u32 *ret, *param; + uint8_t sub_command; + em64t100_smm_state_save_area_t *io_smi = + smi_apmc_find_state_save(ELOG_GSMI_APM_CNT); + + if (!io_smi) + return; + + /* Command and return value in EAX */ + ret = (u32*)&io_smi->rax; + sub_command = (uint8_t)(*ret >> 8); + + /* Parameter buffer in EBX */ + param = (u32*)&io_smi->rbx; + + /* drivers/elog/gsmi.c */ + *ret = gsmi_exec(sub_command, param); +} +#endif + +static void finalize(void) +{ + static int finalize_done; + + if (finalize_done) { + printk(BIOS_DEBUG, "SMM already finalized.\n"); + return; + } + finalize_done = 1; + +#if CONFIG_SPI_FLASH_SMM + /* Re-init SPI driver to handle locked BAR */ + spi_init(); +#endif +} + +/* + * soc_legacy: A payload (Depthcharge) has indicated that the + * legacy payload (SeaBIOS) is being loaded. Switch devices that are + * in ACPI mode to PCI mode so that non-ACPI drivers may work. + * + */ +static void soc_legacy(void) +{ + u32 reg32; + + /* LPE Device */ + if (gnvs->dev.lpe_en) { + reg32 = iosf_port58_read(LPE_PCICFGCTR1); + reg32 &= + ~(LPE_PCICFGCTR1_PCI_CFG_DIS | LPE_PCICFGCTR1_ACPI_INT_EN); + iosf_port58_write(LPE_PCICFGCTR1, reg32); + } + + /* SCC Devices */ +#define SCC_ACPI_MODE_DISABLE(name_) \ + do { if (gnvs->dev.scc_en[SCC_NVS_ ## name_]) { \ + reg32 = iosf_scc_read(SCC_ ## name_ ## _CTL); \ + reg32 &= ~(SCC_CTL_PCI_CFG_DIS | SCC_CTL_ACPI_INT_EN); \ + iosf_scc_write(SCC_ ## name_ ## _CTL, reg32); \ + } } while (0) + + SCC_ACPI_MODE_DISABLE(MMC); + SCC_ACPI_MODE_DISABLE(SD); + SCC_ACPI_MODE_DISABLE(SDIO); + + /* LPSS Devices */ +#define LPSS_ACPI_MODE_DISABLE(name_) \ + do { if (gnvs->dev.lpss_en[LPSS_NVS_ ## name_]) { \ + reg32 = iosf_lpss_read(LPSS_ ## name_ ## _CTL); \ + reg32 &= ~LPSS_CTL_PCI_CFG_DIS | ~LPSS_CTL_ACPI_INT_EN; \ + iosf_lpss_write(LPSS_ ## name_ ## _CTL, reg32); \ + } } while (0) + + LPSS_ACPI_MODE_DISABLE(SIO_DMA1); + LPSS_ACPI_MODE_DISABLE(I2C1); + LPSS_ACPI_MODE_DISABLE(I2C2); + LPSS_ACPI_MODE_DISABLE(I2C3); + LPSS_ACPI_MODE_DISABLE(I2C4); + LPSS_ACPI_MODE_DISABLE(I2C5); + LPSS_ACPI_MODE_DISABLE(I2C6); + LPSS_ACPI_MODE_DISABLE(I2C7); + LPSS_ACPI_MODE_DISABLE(SIO_DMA2); + LPSS_ACPI_MODE_DISABLE(PWM1); + LPSS_ACPI_MODE_DISABLE(PWM2); + LPSS_ACPI_MODE_DISABLE(HSUART1); + LPSS_ACPI_MODE_DISABLE(HSUART2); + LPSS_ACPI_MODE_DISABLE(SPI); +} + +static void southbridge_smi_apmc(void) +{ + uint8_t reg8; + em64t100_smm_state_save_area_t *state; + + /* Emulate B2 register as the FADT / Linux expects it */ + + reg8 = inb(APM_CNT); + switch (reg8) { + case APM_CNT_CST_CONTROL: + /* Calling this function seems to cause + * some kind of race condition in Linux + * and causes a kernel oops + */ + printk(BIOS_DEBUG, "C-state control\n"); + break; + case APM_CNT_PST_CONTROL: + /* Calling this function seems to cause + * some kind of race condition in Linux + * and causes a kernel oops + */ + printk(BIOS_DEBUG, "P-state control\n"); + break; + case APM_CNT_ACPI_DISABLE: + disable_pm1_control(SCI_EN); + printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n"); + break; + case APM_CNT_ACPI_ENABLE: + enable_pm1_control(SCI_EN); + printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n"); + break; + case APM_CNT_GNVS_UPDATE: + if (smm_initialized) { + printk(BIOS_DEBUG, + "SMI#: SMM structures already initialized!\n"); + return; + } + state = smi_apmc_find_state_save(reg8); + if (state) { + /* EBX in the state save contains the GNVS pointer */ + gnvs = (global_nvs_t *)((uint32_t)state->rbx); + smm_initialized = 1; + printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs); + } + break; +#if CONFIG_ELOG_GSMI + case ELOG_GSMI_APM_CNT: + southbridge_smi_gsmi(); + break; +#endif + case APM_CNT_FINALIZE: + finalize(); + break; + + case APM_CNT_LEGACY: + soc_legacy(); + break; + } + + mainboard_smi_apmc(reg8); +} + +static void southbridge_smi_pm1(void) +{ + uint16_t pm1_sts = clear_pm1_status(); + + /* While OSPM is not active, poweroff immediately + * on a power button event. + */ + if (pm1_sts & PWRBTN_STS) { + // power button pressed +#if CONFIG_ELOG_GSMI + elog_add_event(ELOG_TYPE_POWER_BUTTON); +#endif + disable_pm1_control(-1UL); + enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT)); + } +} + +static void southbridge_smi_gpe0(void) +{ + clear_gpe_status(); +} + +static void southbridge_smi_tco(void) +{ + uint32_t tco_sts = clear_tco_status(); + + /* Any TCO event? */ + if (!tco_sts) + return; + + if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */ + /* Handle TCO timeout */ + printk(BIOS_DEBUG, "TCO Timeout.\n"); + } +} + +static void southbridge_smi_periodic(void) +{ + uint32_t reg32; + + reg32 = inl(get_pmbase() + SMI_EN); + + /* Are periodic SMIs enabled? */ + if ((reg32 & PERIODIC_EN) == 0) + return; + + printk(BIOS_DEBUG, "Periodic SMI.\n"); +} + +typedef void (*smi_handler_t)(void); + +static const smi_handler_t southbridge_smi[32] = { + NULL, // [0] reserved + NULL, // [1] reserved + NULL, // [2] BIOS_STS + NULL, // [3] LEGACY_USB_STS + southbridge_smi_sleep, // [4] SLP_SMI_STS + southbridge_smi_apmc, // [5] APM_STS + NULL, // [6] SWSMI_TMR_STS + NULL, // [7] reserved + southbridge_smi_pm1, // [8] PM1_STS + southbridge_smi_gpe0, // [9] GPE0_STS + NULL, // [10] reserved + NULL, // [11] reserved + NULL, // [12] reserved + southbridge_smi_tco, // [13] TCO_STS + southbridge_smi_periodic, // [14] PERIODIC_STS + NULL, // [15] SERIRQ_SMI_STS + NULL, // [16] SMBUS_SMI_STS + NULL, // [17] LEGACY_USB2_STS + NULL, // [18] INTEL_USB2_STS + NULL, // [19] reserved + NULL, // [20] PCI_EXP_SMI_STS + NULL, // [21] reserved + NULL, // [22] reserved + NULL, // [23] reserved + NULL, // [24] reserved + NULL, // [25] reserved + NULL, // [26] SPI_STS + NULL, // [27] reserved + NULL, // [28] PUNIT + NULL, // [29] GUNIT + NULL, // [30] reserved + NULL // [31] reserved +}; + +void southbridge_smi_handler(void) +{ + int i; + uint32_t smi_sts; + + /* We need to clear the SMI status registers, or we won't see what's + * happening in the following calls. + */ + smi_sts = clear_smi_status(); + + /* Call SMI sub handler for each of the status bits */ + for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) { + if (!(smi_sts & (1 << i))) + continue; + + if (southbridge_smi[i] != NULL) { + southbridge_smi[i](); + } else { + printk(BIOS_DEBUG, + "SMI_STS[%d] occured, but no " + "handler available.\n", i); + } + } + + /* The GPIO SMI events do not have a status bit in SMI_STS. Therefore, + * these events need to be cleared and checked unconditionally. */ + mainboard_smi_gpi(clear_alt_status()); +} diff --git a/src/soc/intel/baytrail/smm.c b/src/soc/intel/baytrail/smm.c new file mode 100644 index 0000000000..be13617d7d --- /dev/null +++ b/src/soc/intel/baytrail/smm.c @@ -0,0 +1,133 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Save settings which will be committed in SMI functions. */ +static uint32_t smm_save_params[SMM_SAVE_PARAM_COUNT]; + +void southcluster_smm_save_param(int param, uint32_t data) +{ + smm_save_params[param] = data; +} + +void southcluster_smm_clear_state(void) +{ + uint32_t smi_en; + + /* Log events from chipset before clearing */ + southcluster_log_state(); + + printk(BIOS_DEBUG, "Initializing Southbridge SMI..."); + printk(BIOS_SPEW, " pmbase = 0x%04x\n", get_pmbase()); + + smi_en = inl(get_pmbase() + SMI_EN); + if (smi_en & APMC_EN) { + printk(BIOS_INFO, "SMI# handler already enabled?\n"); + return; + } + + /* Dump and clear status registers */ + clear_smi_status(); + clear_pm1_status(); + clear_tco_status(); + clear_gpe_status(); + clear_alt_status(); + clear_pmc_status(); +} + +static void southcluster_smm_route_gpios(void) +{ + const unsigned long gpio_rout = PMC_BASE_ADDRESS + GPIO_ROUT; + const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI; + uint32_t alt_gpio_reg = 0; + uint32_t route_reg = smm_save_params[SMM_SAVE_PARAM_GPIO_ROUTE]; + int i; + + printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg); + + /* Start the routing for the specific gpios. */ + write32(gpio_rout, route_reg); + + /* Enable SMIs for the gpios that are set to trigger the SMI. */ + for (i = 0; i < 16; i++) { + if ((route_reg & ROUTE_MASK) == ROUTE_SMI) { + alt_gpio_reg |= (1 << i); + } + route_reg >>= 2; + } + printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg); + + outl(alt_gpio_reg, alt_gpio_smi); +} + +void southcluster_smm_enable_smi(void) +{ + uint16_t pm1_events = PWRBTN_EN | GBL_EN; + + printk(BIOS_DEBUG, "Enabling SMIs.\n"); + if (!smm_save_params[SMM_SAVE_PARAM_PCIE_WAKE_ENABLE]) + pm1_events |= PCIEXPWAK_DIS; + enable_pm1(pm1_events); + disable_gpe(PME_B0_EN); + + /* Set up the GPIO route. */ + southcluster_smm_route_gpios(); + + /* Enable SMI generation: + * - on APMC writes (io 0xb2) + * - on writes to SLP_EN (sleep states) + * - on writes to GBL_RLS (bios commands) + * No SMIs: + * - on TCO events + * - on microcontroller writes (io 0x62/0x66) + */ + enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS); +} + +void smm_setup_structures(void *gnvs, void *tcg, void *smi1) +{ + /* + * Issue SMI to set the gnvs pointer in SMM. + * tcg and smi1 are unused. + * + * EAX = APM_CNT_GNVS_UPDATE + * EBX = gnvs pointer + * EDX = APM_CNT + */ + asm volatile ( + "outb %%al, %%dx\n\t" + : /* ignore result */ + : "a" (APM_CNT_GNVS_UPDATE), + "b" ((uint32_t)gnvs), + "d" (APM_CNT) + ); +} diff --git a/src/soc/intel/baytrail/southcluster.c b/src/soc/intel/baytrail/southcluster.c new file mode 100644 index 0000000000..e651439f72 --- /dev/null +++ b/src/soc/intel/baytrail/southcluster.c @@ -0,0 +1,514 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" + +static inline void +add_mmio_resource(device_t dev, int i, unsigned long addr, unsigned long size) +{ + mmio_resource(dev, i, addr >> 10, size >> 10); +} + +static void sc_add_mmio_resources(device_t dev) +{ + add_mmio_resource(dev, 0xfeb, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE); + add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, PMC_BASE_SIZE); + add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, IO_BASE_SIZE); + add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, ILB_BASE_SIZE); + add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, SPI_BASE_SIZE); + add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE); + add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE); + add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE); +} + +/* Default IO range claimed by the LPC device. The upper bound is exclusive. */ +#define LPC_DEFAULT_IO_RANGE_LOWER 0 +#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000 + +static inline int io_range_in_default(int base, int size) +{ + /* Does it start above the range? */ + if (base >= LPC_DEFAULT_IO_RANGE_UPPER) + return 0; + + /* Is it entirely contained? */ + if (base >= LPC_DEFAULT_IO_RANGE_LOWER && + (base + size) < LPC_DEFAULT_IO_RANGE_UPPER) + return 1; + + /* This will return not in range for partial overlaps. */ + return 0; +} + +/* + * Note: this function assumes there is no overlap with the default LPC device's + * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER. + */ +static void sc_add_io_resource(device_t dev, int base, int size, int index) +{ + struct resource *res; + + if (io_range_in_default(base, size)) + return; + + res = new_resource(dev, index); + res->base = base; + res->size = size; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void sc_add_io_resources(device_t dev) +{ + struct resource *res; + + /* Add the default claimed IO range for the LPC device. */ + res = new_resource(dev, 0); + res->base = LPC_DEFAULT_IO_RANGE_LOWER; + res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + /* GPIO */ + sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE); + + /* ACPI */ + sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE); +} + +static void sc_read_resources(device_t dev) +{ + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* Add non-standard MMIO resources. */ + sc_add_mmio_resources(dev); + + /* Add IO resources. */ + sc_add_io_resources(dev); +} + +static void sc_rtc_init(void) +{ + uint32_t gen_pmcon1; + int rtc_fail; + struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE); + + if (ps != NULL) { + gen_pmcon1 = ps->gen_pmcon1; + } else { + gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1); + } + + rtc_fail = !!(gen_pmcon1 & RPS); + + if (rtc_fail) { + printk(BIOS_DEBUG, "RTC failure.\n"); + } + + cmos_init(rtc_fail); +} + +/* + * The UART hardware loses power while in suspend. Because of this the kernel + * can hang because it doesn't re-initialize serial ports it is using for + * consoles at resume time. The following function configures the UART + * if the hardware is enabled though it may not be the correct baud rate + * or configuration. This is definitely a hack, but it helps the kernel + * along. + */ +static void com1_configure_resume(device_t dev) +{ + const uint16_t port = 0x3f8; + + /* Is the UART I/O port eanbled? */ + if (!(pci_read_config32(dev, UART_CONT) & 1)) + return; + + /* Disable interrupts */ + outb(0x0, port + UART8250_IER); + + /* Enable FIFOs */ + outb(UART8250_FCR_FIFO_EN, port + UART8250_FCR); + + /* assert DTR and RTS so the other end is happy */ + outb(UART8250_MCR_DTR | UART8250_MCR_RTS, port + UART8250_MCR); + + /* DLAB on */ + outb(UART8250_LCR_DLAB | 3, port + UART8250_LCR); + + /* Set Baud Rate Divisor. 1 ==> 115200 Baud */ + outb(1, port + UART8250_DLL); + outb(0, port + UART8250_DLM); + + /* Set to 3 for 8N1 */ + outb(3, port + UART8250_LCR); +} + +static void sc_init(device_t dev) +{ + int i; + const unsigned long pr_base = ILB_BASE_ADDRESS + 0x08; + const unsigned long ir_base = ILB_BASE_ADDRESS + 0x20; + const unsigned long gen_pmcon1 = PMC_BASE_ADDRESS + GEN_PMCON1; + const unsigned long actl = ILB_BASE_ADDRESS + ACTL; + const struct baytrail_irq_route *ir = &global_baytrail_irq_route; + struct soc_intel_baytrail_config *config = dev->chip_info; + + /* Set up the PIRQ PIC routing based on static config. */ + for (i = 0; i < NUM_PIRQS; i++) { + write8(pr_base + i*sizeof(ir->pic[i]), ir->pic[i]); + } + /* Set up the per device PIRQ routing base on static config. */ + for (i = 0; i < NUM_IR_DEVS; i++) { + write16(ir_base + i*sizeof(ir->pcidev[i]), ir->pcidev[i]); + } + + /* Route SCI to IRQ9 */ + write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9); + + sc_rtc_init(); + + if (config->disable_slp_x_stretch_sus_fail) { + printk(BIOS_DEBUG, "Disabling slp_x stretching.\n"); + write32(gen_pmcon1, + read32(gen_pmcon1) | DIS_SLP_X_STRCH_SUS_UP); + } else { + write32(gen_pmcon1, + read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP); + } + + if (acpi_slp_type == 3) + com1_configure_resume(dev); +} + +/* + * Common code for the south cluster devices. + */ + +/* Set bit in function disble register to hide this device. */ +static void sc_disable_devfn(device_t dev) +{ + const unsigned long func_dis = PMC_BASE_ADDRESS + FUNC_DIS; + const unsigned long func_dis2 = PMC_BASE_ADDRESS + FUNC_DIS2; + uint32_t mask = 0; + uint32_t mask2 = 0; + +#define SET_DIS_MASK(name_) \ + case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \ + mask |= name_ ## _DIS +#define SET_DIS_MASK2(name_) \ + case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \ + mask2 |= name_ ## _DIS + + switch (dev->path.pci.devfn) { + SET_DIS_MASK(SDIO); + break; + SET_DIS_MASK(SD); + break; + SET_DIS_MASK(SATA); + break; + SET_DIS_MASK(XHCI); + /* Disable super speed PHY when XHCI is not available. */ + mask2 |= USH_SS_PHY_DIS; + break; + SET_DIS_MASK(LPE); + break; + SET_DIS_MASK(MMC); + break; + SET_DIS_MASK(SIO_DMA1); + break; + SET_DIS_MASK(I2C1); + break; + SET_DIS_MASK(I2C2); + break; + SET_DIS_MASK(I2C3); + break; + SET_DIS_MASK(I2C4); + break; + SET_DIS_MASK(I2C5); + break; + SET_DIS_MASK(I2C6); + break; + SET_DIS_MASK(I2C7); + break; + SET_DIS_MASK(TXE); + break; + SET_DIS_MASK(HDA); + break; + SET_DIS_MASK(PCIE_PORT1); + break; + SET_DIS_MASK(PCIE_PORT2); + break; + SET_DIS_MASK(PCIE_PORT3); + break; + SET_DIS_MASK(PCIE_PORT4); + break; + SET_DIS_MASK(EHCI); + break; + SET_DIS_MASK(SIO_DMA2); + break; + SET_DIS_MASK(PWM1); + break; + SET_DIS_MASK(PWM2); + break; + SET_DIS_MASK(HSUART1); + break; + SET_DIS_MASK(HSUART2); + break; + SET_DIS_MASK(SPI); + break; + SET_DIS_MASK2(SMBUS); + break; + } + + if (mask != 0) { + write32(func_dis, read32(func_dis) | mask); + /* Ensure posted write hits. */ + read32(func_dis); + } + + if (mask2 != 0) { + write32(func_dis2, read32(func_dis2) | mask2); + /* Ensure posted write hits. */ + read32(func_dis2); + } +} + +static inline void set_d3hot_bits(device_t dev, int offset) +{ + uint32_t reg8; + printk(BIOS_DEBUG, "Power management CAP offset 0x%x.\n", offset); + reg8 = pci_read_config8(dev, offset + 4); + reg8 |= 0x3; + pci_write_config8(dev, offset + 4, reg8); +} + +/* Parts of the audio subsystem are powered by the HDA device. Therefore, one + * cannot put HDA into D3Hot. Instead perform this workaround to make some of + * the audio paths work for LPE audio. */ +static void hda_work_around(device_t dev) +{ + unsigned long gctl = TEMP_BASE_ADDRESS + 0x8; + + /* Need to set magic register 0x43 to 0xd7 in config space. */ + pci_write_config8(dev, 0x43, 0xd7); + + /* Need to set bit 0 of GCTL to take the device out of reset. However, + * that requires setting up the 64-bit BAR. */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, TEMP_BASE_ADDRESS); + pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0); + pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); + write32(gctl, read32(gctl) | 0x1); + pci_write_config8(dev, PCI_COMMAND, 0); + pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0); +} + +static int place_device_in_d3hot(device_t dev) +{ + unsigned offset; + + /* Parts of the HDA block are used for LPE audio as well. + * Therefore assume the HDA will never be put into D3Hot. */ + if (dev->path.pci.devfn == PCI_DEVFN(HDA_DEV, HDA_FUNC)) { + hda_work_around(dev); + return 0; + } + + offset = pci_find_capability(dev, PCI_CAP_ID_PM); + + if (offset != 0) { + set_d3hot_bits(dev, offset); + return 0; + } + + /* For some reason some of the devices don't have the capability + * pointer set correctly. Work around this by hard coding the offset. */ +#define DEV_CASE(name_) \ + case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC) + + switch (dev->path.pci.devfn) { + DEV_CASE(SDIO): + DEV_CASE(SD): + DEV_CASE(MMC): + DEV_CASE(LPE): + DEV_CASE(SIO_DMA1): + DEV_CASE(I2C1): + DEV_CASE(I2C2): + DEV_CASE(I2C3): + DEV_CASE(I2C4): + DEV_CASE(I2C5): + DEV_CASE(I2C6): + DEV_CASE(I2C7): + DEV_CASE(SIO_DMA2): + DEV_CASE(PWM1): + DEV_CASE(PWM2): + DEV_CASE(HSUART1): + DEV_CASE(HSUART2): + DEV_CASE(SPI): + offset = 0x80; + break; + DEV_CASE(SATA): + DEV_CASE(XHCI): + DEV_CASE(EHCI): + offset = 0x70; + break; + DEV_CASE(HDA): + DEV_CASE(SMBUS): + offset = 0x50; + break; + DEV_CASE(TXE): + /* TXE cannot be placed in D3Hot. */ + return 0; + break; + DEV_CASE(PCIE_PORT1): + DEV_CASE(PCIE_PORT2): + DEV_CASE(PCIE_PORT3): + DEV_CASE(PCIE_PORT4): + offset = 0xa0; + break; + } + + if (offset != 0) { + set_d3hot_bits(dev, offset); + return 0; + } + + return -1; +} + +/* Common PCI device function disable. */ +void southcluster_enable_dev(device_t dev) +{ + uint32_t reg32; + + if (!dev->enabled) { + int slot = PCI_SLOT(dev->path.pci.devfn); + int func = PCI_FUNC(dev->path.pci.devfn); + printk(BIOS_DEBUG, "%s: Disabling device: %02x.%01x\n", + dev_path(dev), slot, func); + + /* Ensure memory, io, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Place device in D3Hot */ + if (place_device_in_d3hot(dev) < 0) { + printk(BIOS_WARNING, + "Could not place %02x.%01x into D3Hot. " + "Keeping device visible.\n", slot, func); + return; + } + /* Disable this device if possible */ + sc_disable_devfn(dev); + } else { + /* Enable SERR */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_SERR; + pci_write_config32(dev, PCI_COMMAND, reg32); + } +} + +static struct device_operations device_ops = { + .read_resources = sc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = NULL, + .init = sc_init, + .enable = southcluster_enable_dev, + .scan_bus = scan_static_bus, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver southcluster __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = LPC_DEVID, +}; + +int __attribute__((weak)) mainboard_get_spi_config(struct spi_config *cfg) +{ + return -1; +} + +static void finalize_chipset(void *unused) +{ + const unsigned long bcr = SPI_BASE_ADDRESS + BCR; + const unsigned long gcs = RCBA_BASE_ADDRESS + GCS; + const unsigned long gen_pmcon2 = PMC_BASE_ADDRESS + GEN_PMCON2; + const unsigned long etr = PMC_BASE_ADDRESS + ETR; + const unsigned long spi = SPI_BASE_ADDRESS; + struct spi_config cfg; + + /* Set the lock enable on the BIOS control register. */ + write32(bcr, read32(bcr) | BCR_LE); + + /* Set BIOS lock down bit controlling boot block size and swapping. */ + write32(gcs, read32(gcs) | BILD); + + /* Lock sleep stretching policy and set SMI lock. */ + write32(gen_pmcon2, read32(gen_pmcon2) | SLPSX_STR_POL_LOCK | SMI_LOCK); + + /* Set the CF9 lock. */ + write32(etr, read32(etr) | CF9LOCK); + + if (mainboard_get_spi_config(&cfg) < 0) { + printk(BIOS_DEBUG, "No SPI lockdown configuration.\n"); + } else { + write16(spi + PREOP, cfg.preop); + write16(spi + OPTYPE, cfg.optype); + write32(spi + OPMENU0, cfg.opmenu[0]); + write32(spi + OPMENU1, cfg.opmenu[1]); + write16(spi + HSFSTS, read16(spi + HSFSTS) | FLOCKDN); + write32(spi + UVSCC, cfg.uvscc); + write32(spi + LVSCC, cfg.lvscc | VCL); + } + + printk(BIOS_DEBUG, "Finalizing SMM.\n"); + outb(APM_CNT_FINALIZE, APM_CNT); +} + +BOOT_STATE_INIT_ENTRIES(finalize_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, + finalize_chipset, NULL), + BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, + finalize_chipset, NULL), +}; diff --git a/src/soc/intel/baytrail/spi.c b/src/soc/intel/baytrail/spi.c new file mode 100644 index 0000000000..0cff010625 --- /dev/null +++ b/src/soc/intel/baytrail/spi.c @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2013 Google Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This file is derived from the flashrom project. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __SMM__ +#define pci_read_config_byte(dev, reg, targ)\ + *(targ) = pci_read_config8(dev, reg) +#define pci_read_config_word(dev, reg, targ)\ + *(targ) = pci_read_config16(dev, reg) +#define pci_read_config_dword(dev, reg, targ)\ + *(targ) = pci_read_config32(dev, reg) +#define pci_write_config_byte(dev, reg, val)\ + pci_write_config8(dev, reg, val) +#define pci_write_config_word(dev, reg, val)\ + pci_write_config16(dev, reg, val) +#define pci_write_config_dword(dev, reg, val)\ + pci_write_config32(dev, reg, val) +#else /* !__SMM__ */ +#include +#include +#define pci_read_config_byte(dev, reg, targ)\ + *(targ) = pci_read_config8(dev, reg) +#define pci_read_config_word(dev, reg, targ)\ + *(targ) = pci_read_config16(dev, reg) +#define pci_read_config_dword(dev, reg, targ)\ + *(targ) = pci_read_config32(dev, reg) +#define pci_write_config_byte(dev, reg, val)\ + pci_write_config8(dev, reg, val) +#define pci_write_config_word(dev, reg, val)\ + pci_write_config16(dev, reg, val) +#define pci_write_config_dword(dev, reg, val)\ + pci_write_config32(dev, reg, val) +#endif /* !__SMM__ */ + +typedef struct spi_slave ich_spi_slave; + +static int ichspi_lock = 0; + +typedef struct ich9_spi_regs { + uint32_t bfpr; + uint16_t hsfs; + uint16_t hsfc; + uint32_t faddr; + uint32_t _reserved0; + uint32_t fdata[16]; + uint32_t frap; + uint32_t freg[5]; + uint32_t _reserved1[3]; + uint32_t pr[5]; + uint32_t _reserved2[2]; + uint8_t ssfs; + uint8_t ssfc[3]; + uint16_t preop; + uint16_t optype; + uint8_t opmenu[8]; + uint32_t bbar; + uint8_t _reserved3[12]; + uint32_t fdoc; + uint32_t fdod; + uint8_t _reserved4[8]; + uint32_t afc; + uint32_t lvscc; + uint32_t uvscc; + uint8_t _reserved5[4]; + uint32_t fpb; + uint8_t _reserved6[28]; + uint32_t srdl; + uint32_t srdc; + uint32_t srd; +} __attribute__((packed)) ich9_spi_regs; + +typedef struct ich_spi_controller { + int locked; + + uint8_t *opmenu; + int menubytes; + uint16_t *preop; + uint16_t *optype; + uint32_t *addr; + uint8_t *data; + unsigned databytes; + uint8_t *status; + uint16_t *control; + uint32_t *bbar; +} ich_spi_controller; + +static ich_spi_controller cntlr; + +enum { + SPIS_SCIP = 0x0001, + SPIS_GRANT = 0x0002, + SPIS_CDS = 0x0004, + SPIS_FCERR = 0x0008, + SSFS_AEL = 0x0010, + SPIS_LOCK = 0x8000, + SPIS_RESERVED_MASK = 0x7ff0, + SSFS_RESERVED_MASK = 0x7fe2 +}; + +enum { + SPIC_SCGO = 0x000002, + SPIC_ACS = 0x000004, + SPIC_SPOP = 0x000008, + SPIC_DBC = 0x003f00, + SPIC_DS = 0x004000, + SPIC_SME = 0x008000, + SSFC_SCF_MASK = 0x070000, + SSFC_RESERVED = 0xf80000 +}; + +enum { + HSFS_FDONE = 0x0001, + HSFS_FCERR = 0x0002, + HSFS_AEL = 0x0004, + HSFS_BERASE_MASK = 0x0018, + HSFS_BERASE_SHIFT = 3, + HSFS_SCIP = 0x0020, + HSFS_FDOPSS = 0x2000, + HSFS_FDV = 0x4000, + HSFS_FLOCKDN = 0x8000 +}; + +enum { + HSFC_FGO = 0x0001, + HSFC_FCYCLE_MASK = 0x0006, + HSFC_FCYCLE_SHIFT = 1, + HSFC_FDBC_MASK = 0x3f00, + HSFC_FDBC_SHIFT = 8, + HSFC_FSMIE = 0x8000 +}; + +enum { + SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0, + SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1, + SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2, + SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3 +}; + +#if CONFIG_DEBUG_SPI_FLASH + +static u8 readb_(const void *addr) +{ + u8 v = read8((unsigned long)addr); + printk(BIOS_DEBUG, "read %2.2x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static u16 readw_(const void *addr) +{ + u16 v = read16((unsigned long)addr); + printk(BIOS_DEBUG, "read %4.4x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static u32 readl_(const void *addr) +{ + u32 v = read32((unsigned long)addr); + printk(BIOS_DEBUG, "read %8.8x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static void writeb_(u8 b, const void *addr) +{ + write8((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %2.2x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +static void writew_(u16 b, const void *addr) +{ + write16((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %4.4x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +static void writel_(u32 b, const void *addr) +{ + write32((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %8.8x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +#else /* CONFIG_DEBUG_SPI_FLASH ^^^ enabled vvv NOT enabled */ + +#define readb_(a) read8((uint32_t)a) +#define readw_(a) read16((uint32_t)a) +#define readl_(a) read32((uint32_t)a) +#define writeb_(val, addr) write8((uint32_t)addr, val) +#define writew_(val, addr) write16((uint32_t)addr, val) +#define writel_(val, addr) write32((uint32_t)addr, val) + +#endif /* CONFIG_DEBUG_SPI_FLASH ^^^ NOT enabled */ + +static void write_reg(const void *value, void *dest, uint32_t size) +{ + const uint8_t *bvalue = value; + uint8_t *bdest = dest; + + while (size >= 4) { + writel_(*(const uint32_t *)bvalue, bdest); + bdest += 4; bvalue += 4; size -= 4; + } + while (size) { + writeb_(*bvalue, bdest); + bdest++; bvalue++; size--; + } +} + +static void read_reg(const void *src, void *value, uint32_t size) +{ + const uint8_t *bsrc = src; + uint8_t *bvalue = value; + + while (size >= 4) { + *(uint32_t *)bvalue = readl_(bsrc); + bsrc += 4; bvalue += 4; size -= 4; + } + while (size) { + *bvalue = readb_(bsrc); + bsrc++; bvalue++; size--; + } +} + +static void ich_set_bbar(uint32_t minaddr) +{ + const uint32_t bbar_mask = 0x00ffff00; + uint32_t ichspi_bbar; + + minaddr &= bbar_mask; + ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask; + ichspi_bbar |= minaddr; + writel_(ichspi_bbar, cntlr.bbar); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + ich_spi_slave *slave = malloc(sizeof(*slave)); + + if (!slave) { + printk(BIOS_DEBUG, "ICH SPI: Bad allocation\n"); + return NULL; + } + + memset(slave, 0, sizeof(*slave)); + + slave->bus = bus; + slave->cs = cs; + return slave; +} + +static ich9_spi_regs *spi_regs(void) +{ + device_t dev; + uint32_t sbase; + +#ifdef __SMM__ + dev = PCI_DEV(0, LPC_DEV, LPC_FUNC); +#else + dev = dev_find_slot(0, PCI_DEVFN(LPC_DEV, LPC_FUNC)); +#endif + pci_read_config_dword(dev, SBASE, &sbase); + sbase &= ~0x1ff; + + return (void *)sbase; +} + +void spi_init(void) +{ + ich9_spi_regs *ich9_spi = spi_regs(); + + ichspi_lock = readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN; + cntlr.opmenu = ich9_spi->opmenu; + cntlr.menubytes = sizeof(ich9_spi->opmenu); + cntlr.optype = &ich9_spi->optype; + cntlr.addr = &ich9_spi->faddr; + cntlr.data = (uint8_t *)ich9_spi->fdata; + cntlr.databytes = sizeof(ich9_spi->fdata); + cntlr.status = &ich9_spi->ssfs; + cntlr.control = (uint16_t *)ich9_spi->ssfc; + cntlr.bbar = &ich9_spi->bbar; + cntlr.preop = &ich9_spi->preop; + ich_set_bbar(0); +} + + +static void spi_init_cb(void *unused) +{ + spi_init(); +} + +BOOT_STATE_INIT_ENTRIES(spi_init_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL), +}; + +int spi_claim_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ +} + +typedef struct spi_transaction { + const uint8_t *out; + uint32_t bytesout; + uint8_t *in; + uint32_t bytesin; + uint8_t type; + uint8_t opcode; + uint32_t offset; +} spi_transaction; + +static inline void spi_use_out(spi_transaction *trans, unsigned bytes) +{ + trans->out += bytes; + trans->bytesout -= bytes; +} + +static inline void spi_use_in(spi_transaction *trans, unsigned bytes) +{ + trans->in += bytes; + trans->bytesin -= bytes; +} + +static void spi_setup_type(spi_transaction *trans) +{ + trans->type = 0xFF; + + /* Try to guess spi type from read/write sizes. */ + if (trans->bytesin == 0) { + if (trans->bytesout > 4) + /* + * If bytesin = 0 and bytesout > 4, we presume this is + * a write data operation, which is accompanied by an + * address. + */ + trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; + else + trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; + return; + } + + if (trans->bytesout == 1) { /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; + return; + } + + if (trans->bytesout == 4) { /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + } + + /* Fast read command is called with 5 bytes instead of 4 */ + if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) { + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + --trans->bytesout; + } +} + +static int spi_setup_opcode(spi_transaction *trans) +{ + uint16_t optypes; + uint8_t opmenu[cntlr.menubytes]; + + trans->opcode = trans->out[0]; + spi_use_out(trans, 1); + if (!ichspi_lock) { + /* The lock is off, so just use index 0. */ + writeb_(trans->opcode, cntlr.opmenu); + optypes = readw_(cntlr.optype); + optypes = (optypes & 0xfffc) | (trans->type & 0x3); + writew_(optypes, cntlr.optype); + return 0; + } else { + /* The lock is on. See if what we need is on the menu. */ + uint8_t optype; + uint16_t opcode_index; + + /* Write Enable is handled as atomic prefix */ + if (trans->opcode == SPI_OPCODE_WREN) + return 0; + + read_reg(cntlr.opmenu, opmenu, sizeof(opmenu)); + for (opcode_index = 0; opcode_index < cntlr.menubytes; + opcode_index++) { + if (opmenu[opcode_index] == trans->opcode) + break; + } + + if (opcode_index == cntlr.menubytes) { + printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n", + trans->opcode); + return -1; + } + + optypes = readw_(cntlr.optype); + optype = (optypes >> (opcode_index * 2)) & 0x3; + if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS && + optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS && + trans->bytesout >= 3) { + /* We guessed wrong earlier. Fix it up. */ + trans->type = optype; + } + if (optype != trans->type) { + printk(BIOS_DEBUG, "ICH SPI: Transaction doesn't fit type %d\n", + optype); + return -1; + } + return opcode_index; + } +} + +static int spi_setup_offset(spi_transaction *trans) +{ + /* Separate the SPI address and data. */ + switch (trans->type) { + case SPI_OPCODE_TYPE_READ_NO_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS: + return 0; + case SPI_OPCODE_TYPE_READ_WITH_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS: + trans->offset = ((uint32_t)trans->out[0] << 16) | + ((uint32_t)trans->out[1] << 8) | + ((uint32_t)trans->out[2] << 0); + spi_use_out(trans, 3); + return 1; + default: + printk(BIOS_DEBUG, "Unrecognized SPI transaction type %#x\n", trans->type); + return -1; + } +} + +/* + * Wait for up to 60ms til status register bit(s) turn 1 (in case wait_til_set + * below is True) or 0. In case the wait was for the bit(s) to set - write + * those bits back, which would cause resetting them. + * + * Return the last read status value on success or -1 on failure. + */ +static int ich_status_poll(u16 bitmask, int wait_til_set) +{ + int timeout = 40000; /* This will result in 400 ms */ + u16 status = 0; + + while (timeout--) { + status = readw_(cntlr.status); + if (wait_til_set ^ ((status & bitmask) == 0)) { + if (wait_til_set) + writew_((status & bitmask), cntlr.status); + return status; + } + udelay(10); + } + + printk(BIOS_DEBUG, "ICH SPI: SCIP timeout, read %x, expected %x\n", + status, bitmask); + return -1; +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int bytesout, void *din, unsigned int bytesin) +{ + uint16_t control; + int16_t opcode_index; + int with_address; + int status; + + spi_transaction trans = { + dout, bytesout, + din, bytesin, + 0xff, 0xff, 0 + }; + + /* There has to always at least be an opcode. */ + if (!bytesout || !dout) { + printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n"); + return -1; + } + /* Make sure if we read something we have a place to put it. */ + if (bytesin != 0 && !din) { + printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n"); + return -1; + } + + if (ich_status_poll(SPIS_SCIP, 0) == -1) + return -1; + + writew_(SPIS_CDS | SPIS_FCERR, cntlr.status); + + spi_setup_type(&trans); + if ((opcode_index = spi_setup_opcode(&trans)) < 0) + return -1; + if ((with_address = spi_setup_offset(&trans)) < 0) + return -1; + + if (trans.opcode == SPI_OPCODE_WREN) { + /* + * Treat Write Enable as Atomic Pre-Op if possible + * in order to prevent the Management Engine from + * issuing a transaction between WREN and DATA. + */ + if (!ichspi_lock) + writew_(trans.opcode, cntlr.preop); + return 0; + } + + /* Preset control fields */ + control = SPIC_SCGO | ((opcode_index & 0x07) << 4); + + /* Issue atomic preop cycle if needed */ + if (readw_(cntlr.preop)) + control |= SPIC_ACS; + + if (!trans.bytesout && !trans.bytesin) { + /* SPI addresses are 24 bit only */ + if (with_address) + writel_(trans.offset & 0x00FFFFFF, cntlr.addr); + + /* + * This is a 'no data' command (like Write Enable), its + * bitesout size was 1, decremented to zero while executing + * spi_setup_opcode() above. Tell the chip to send the + * command. + */ + writew_(control, cntlr.control); + + /* wait for the result */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + printk(BIOS_DEBUG, "ICH SPI: Command transaction error\n"); + return -1; + } + + return 0; + } + + /* + * Check if this is a write command atempting to transfer more bytes + * than the controller can handle. Iterations for writes are not + * supported here because each SPI write command needs to be preceded + * and followed by other SPI commands, and this sequence is controlled + * by the SPI chip driver. + */ + if (trans.bytesout > cntlr.databytes) { + printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use" + " CONTROLLER_PAGE_LIMIT?\n"); + return -1; + } + + /* + * Read or write up to databytes bytes at a time until everything has + * been sent. + */ + while (trans.bytesout || trans.bytesin) { + uint32_t data_length; + + /* SPI addresses are 24 bit only */ + writel_(trans.offset & 0x00FFFFFF, cntlr.addr); + + if (trans.bytesout) + data_length = min(trans.bytesout, cntlr.databytes); + else + data_length = min(trans.bytesin, cntlr.databytes); + + /* Program data into FDATA0 to N */ + if (trans.bytesout) { + write_reg(trans.out, cntlr.data, data_length); + spi_use_out(&trans, data_length); + if (with_address) + trans.offset += data_length; + } + + /* Add proper control fields' values */ + control &= ~((cntlr.databytes - 1) << 8); + control |= SPIC_DS; + control |= (data_length - 1) << 8; + + /* write it */ + writew_(control, cntlr.control); + + /* Wait for Cycle Done Status or Flash Cycle Error. */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + printk(BIOS_DEBUG, "ICH SPI: Data transaction error\n"); + return -1; + } + + if (trans.bytesin) { + read_reg(cntlr.data, trans.in, data_length); + spi_use_in(&trans, data_length); + if (with_address) + trans.offset += data_length; + } + } + + /* Clear atomic preop now that xfer is done */ + writew_(0, cntlr.preop); + + return 0; +} diff --git a/src/soc/intel/baytrail/spi_loading.c b/src/soc/intel/baytrail/spi_loading.c new file mode 100644 index 0000000000..674fe6180d --- /dev/null +++ b/src/soc/intel/baytrail/spi_loading.c @@ -0,0 +1,153 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CACHELINE_SIZE 64 +#define INTRA_CACHELINE_MASK (CACHELINE_SIZE - 1) +#define CACHELINE_MASK (~INTRA_CACHELINE_MASK) + +static void *find_mirror_buffer(int len) +{ + int nentries; + int i; + struct lb_memory *mem; + void *buffer; + + len = ALIGN(len, 4096); + + mem = get_lb_mem(); + nentries = (mem->size - sizeof(*mem)) / sizeof(mem->map[0]); + + /* + * Find the highest RAM entry that accommodates the lenth provide + * while falling below 4GiB. + */ + buffer = NULL; + for (i = 0; i < nentries; i++) { + const uint64_t max_addr = 1ULL << 32; + uint64_t start; + uint64_t size; + struct lb_memory_range *r; + + r = &mem->map[i]; + + if (r->type != LB_MEM_RAM) + continue; + + start = unpack_lb64(r->start); + if (start >= max_addr) + continue; + + size = unpack_lb64(r->size); + if (size < len) + continue; + + /* Adjust size of buffer if range exceeds max address. */ + if (start + size > max_addr) + size = max_addr - start; + + if (size < len) + continue; + + buffer = (void *)(uintptr_t)(start + size - len); + } + + return buffer; +} + +/* + * Mirror the payload file to the default SMM location if it is small enough. + * The default SMM region can be used since no one is using the memory at this + * location at this stage in the boot. + */ +static void *spi_mirror(void *file_start, int file_len) +{ + int alignment_diff; + char *src; + char *dest; + + alignment_diff = (INTRA_CACHELINE_MASK & (long)file_start); + + /* + * Adjust file length so that the start and end points are aligned to a + * cacheline. Coupled with the ROM caching in the CPU the SPI hardware + * will read and cache full length cachelines. It will also prefetch + * data as well. Once things are mirrored in memory all accesses should + * hit the CPUs cache. + */ + file_len += alignment_diff; + file_len = ALIGN(file_len, CACHELINE_SIZE); + + printk(BIOS_DEBUG, "Payload aligned size: 0x%x\n", file_len); + + dest = find_mirror_buffer(file_len); + + /* + * Just pass back the pointer to ROM space if a buffer could not + * be found to mirror into. + */ + if (dest == NULL) + return file_start; + + src = (void *)(CACHELINE_MASK & (long)file_start); + /* + * Note that if mempcy is not using 32-bit moves the performance will + * degrade because the SPI hardware prefetchers look for + * cacheline-aligned 32-bit accesses to kick in. + */ + memcpy(dest, src, file_len); + + /* Provide pointer into mirrored space. */ + return &dest[alignment_diff]; +} + +void *cbfs_load_payload(struct cbfs_media *media, const char *name) +{ + int file_len; + void *file_start; + struct cbfs_file *file; + + file_start = vboot_get_payload(&file_len); + + if (file_start != NULL) + return spi_mirror(file_start, file_len); + + file = cbfs_get_file(media, name); + + if (file == NULL) + return NULL; + + if (ntohl(file->type) != CBFS_TYPE_PAYLOAD) + return NULL; + + file_len = ntohl(file->len); + + file_start = CBFS_SUBHEADER(file); + + return spi_mirror(file_start, file_len); +} diff --git a/src/soc/intel/baytrail/stage_cache.c b/src/soc/intel/baytrail/stage_cache.c new file mode 100644 index 0000000000..d51746fbd1 --- /dev/null +++ b/src/soc/intel/baytrail/stage_cache.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +struct ramstage_cache *ramstage_cache_location(long *size) +{ + char *smm_base; + /* 1MiB cache size */ + const long cache_size = CONFIG_SMM_RESERVED_SIZE; + + /* Ramstage cache lives in TSEG region which is the definition of + * cbmem_top(). */ + smm_base = cbmem_top(); + *size = cache_size; + return (void *)&smm_base[smm_region_size() - cache_size]; +} diff --git a/src/soc/intel/baytrail/tsc_freq.c b/src/soc/intel/baytrail/tsc_freq.c new file mode 100644 index 0000000000..c506818d00 --- /dev/null +++ b/src/soc/intel/baytrail/tsc_freq.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#if !defined(__PRE_RAM__) +#include +#else +#include +#endif + +unsigned bus_freq_khz(void) +{ + msr_t clk_info = rdmsr(MSR_BSEL_CR_OVERCLOCK_CONTROL); + switch (clk_info.lo & 0x3) { + case 0: return 83333; + case 1: return 100000; + case 2: return 133333; + case 3: return 116666; + default: return 0; + } +} + +unsigned long tsc_freq_mhz(void) +{ + msr_t platform_info; + unsigned bclk_khz = bus_freq_khz(); + + if (!bclk_khz) + return 0; + + platform_info = rdmsr(MSR_PLATFORM_INFO); + return (bclk_khz * ((platform_info.lo >> 8) & 0xff)) / 1000; +} + +#if !defined(__SMM__) + +void set_max_freq(void) +{ + msr_t perf_ctl; + msr_t msr; + + /* Enable speed step. */ + msr = rdmsr(MSR_IA32_MISC_ENABLES); + msr.lo |= (1 << 16); + wrmsr(MSR_IA32_MISC_ENABLES, msr); + + /* Set guranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of + * the PERF_CTL. */ + msr = rdmsr(MSR_IACORE_RATIOS); + perf_ctl.lo = (msr.lo & 0x3f0000) >> 8; + /* Set guranteed vid [21:16] from IACORE_VIDS to bits [7:0] of + * the PERF_CTL. */ + msr = rdmsr(MSR_IACORE_VIDS); + perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16; + perf_ctl.hi = 0; + + wrmsr(MSR_IA32_PERF_CTL, perf_ctl); +} + +#endif /* __SMM__ */ diff --git a/src/soc/intel/baytrail/xhci.c b/src/soc/intel/baytrail/xhci.c new file mode 100644 index 0000000000..f48c1995f4 --- /dev/null +++ b/src/soc/intel/baytrail/xhci.c @@ -0,0 +1,259 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +struct reg_script usb3_phy_script[] = { + /* USB3PHYInit() */ + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_PLL_CONTROL, + ~0x00700000, 0x00500000), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_VCO_START_CAL_POINT, + ~0x001f0000, 0x000A0000), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CCDRLF, + ~0x0000000f, 0x0000000b), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_PEAKING_AMP_CONFIG_DIAG, + ~0x000000f0, 0x000000f0), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_OFFSET_COR_CONFIG_DIAG, + ~0x000001c0, 0x00000000), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_VGA_GAIN_CONFIG_DIAG, + ~0x00000070, 0x00000020), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_REE_DAC_CONTROL, + ~0x00000002, 0x00000002), + REG_IOSF_RMW(IOSF_PORT_USHPHY, USHPHY_CDN_U1_POWER_STATE_DEF, + ~0x00000000, 0x00040000), + REG_SCRIPT_END +}; + +const struct reg_script xhci_init_script[] = { + /* CommonXhciHcInit() */ + /* BAR + 0x0c[31:16] = 0x0200 */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0x0000ffff, 0x02000000), + /* BAR + 0x0c[7:0] = 0x0a */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x000c, 0xffffff00, 0x0000000a), + /* BAR + 0x8094[23,21,14]=111b */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8094, 0x00a04000), + /* BAR + 0x8110[20,11,8,2]=1100b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8110, ~0x00000104, 0x00100800), + /* BAR + 0x8144[8,7,6]=111b */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8144, 0x000001c0), + /* BAR + 0x8154[21,13,3]=010b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8154, ~0x00200008, 0x80002000), + /* BAR + 0x816c[19:0]=1110x100000000111100b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x816c, 0xfff08000, 0x000e0030), + /* BAR + 0x8188[26,24]=11b */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8188, 0x05000000), + /* BAR + 0x8174=0x1000c0a*/ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8174, 0xfe000000, 0x01000c0a), + /* BAR + 0x854c[29]=0b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x854c, ~0x20000000, 0), + /* BAR + 0x8178[12:0]=0b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8178, ~0xffffe000, 0), + /* BAR + 0x8164[7:0]=0xff */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8164, 0x000000ff), + /* BAR + 0x0010[10,9,5]=110b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0010, ~0x00000020, 0x00000600), + /* BAR + 0x8058[20,16,8]=110b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8058, ~0x00000100, 0x00110000), + /* BAR + 0x8060[25]=1b */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8060, 0x02000000), + /* BAR + 0x80f0[20]=0b */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80f0, ~0x00100000, 0), + /* BAR + 0x8008[19]=1b (to enable LPM) */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x8008, 0x00080000), + /* BAR + 0x80fc[25]=1b */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x80fc, 0x02000000), + /* 0x40/0x44 are written as bytes to avoid touching bit31 */ + /* D20:F0:40[21,20,18,10,9,8]=111001b (don't write byte3) */ + REG_PCI_RMW8(0x41, ~0x06, 0x01), + /* Except [21,20,19,18]=0001b USB wake W/A is disable IIL1E */ + REG_PCI_RMW8(0x42, 0x3c, 0x04), + /* D20:F0:44[19:14,10,9,7,3:0]=1 (don't write byte3) */ + REG_PCI_RMW8(0x44, 0x00, 0x8f), + REG_PCI_RMW8(0x45, ~0xcf, 0xc6), + REG_PCI_RMW8(0x46, ~0x0f, 0x0f), + /* BAR + 0x8140 = 0xff00f03c */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x8140, 0, 0xff00f03c), + REG_SCRIPT_END +}; + +const struct reg_script xhci_init_boot_script[] = { + /* Setup USB3 phy */ + REG_SCRIPT_NEXT(usb3_phy_script), + /* Initialize host controller */ + REG_SCRIPT_NEXT(xhci_init_script), + /* BAR + 0x80e0[16,9,6]=001b, toggle bit 24=1 */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x00010200, 0x01000040), + /* BAR + 0x80e0 toggle bit 24=0 */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01000000, 0), + REG_SCRIPT_END +}; + +const struct reg_script xhci_init_resume_script[] = { + /* Setup USB3 phy */ + REG_SCRIPT_NEXT(usb3_phy_script), + /* Initialize host controller */ + REG_SCRIPT_NEXT(xhci_init_script), + /* BAR + 0x80e0[16,9,6]=001b, leave bit 24=0 to prevent HC reset */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x80e0, ~0x01010200, 0x00000040), + REG_SCRIPT_END +}; + +const struct reg_script xhci_clock_gating_script[] = { + /* ConfigureXhciClockGating() */ + /* D20:F0:40[21:19,18,10:8]=000,1,001 (don't write byte 3) */ + REG_PCI_RMW16(0x40, ~0x0600, 0x0100), + REG_PCI_RMW8(0x42, ~0x38, 0x04), + /* D20:F0:44[5:3]=001b */ + REG_PCI_RMW16(0x44, ~0x0030, 0x0008), + /* D20:F0:A0[19:18]=01b */ + REG_PCI_RMW32(0xa0, ~0x00080000, 0x00040000), + /* D20:F0:A4[15:0]=0x00 */ + REG_PCI_WRITE16(0xa4, 0x0000), + /* D20:F0:B0[21:17,14:13]=0000000b */ + REG_PCI_RMW32(0xb0, ~0x00376000, 0x00000000), + /* D20:F0:50[31:0]=0x0bce6e5f */ + REG_PCI_WRITE32(0x50, 0x0bce6e5f), + REG_SCRIPT_END +}; + +/* Warm Reset a USB3 port */ +static void xhci_reset_port_usb3(device_t dev, int port) +{ + struct reg_script reset_port_usb3_script[] = { + /* Issue Warm Port Rest to the port */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port), + XHCI_USB3_PORTSC_WPR), + /* Wait up to 100ms for it to complete */ + REG_RES_POLL32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port), + XHCI_USB3_PORTSC_WRC, XHCI_USB3_PORTSC_WRC, + XHCI_RESET_TIMEOUT), + /* Clear change status bits, do not set PED */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, XHCI_USB3_PORTSC(port), + ~XHCI_USB3_PORTSC_PED, XHCI_USB3_PORTSC_CHST), + REG_SCRIPT_END + }; + reg_script_run_on_dev(dev, reset_port_usb3_script); +} + +/* Prepare ports to be routed to EHCI or XHCI */ +static void xhci_route_all(device_t dev) +{ + static const struct reg_script xhci_route_all_script[] = { + /* USB3 SuperSpeed Enable */ + REG_PCI_WRITE32(XHCI_USB3PR, BYTM_USB3_PORT_MAP), + /* USB2 Port Route to XHCI */ + REG_PCI_WRITE32(XHCI_USB2PR, BYTM_USB2_PORT_MAP), + REG_SCRIPT_END + }; + u32 port_disabled; + int port; + + printk(BIOS_INFO, "USB: Route ports to XHCI controller\n"); + + /* Route ports to XHCI controller */ + reg_script_run_on_dev(dev, xhci_route_all_script); + + if (acpi_slp_type == 3) + return; + + /* Reset enabled USB3 ports */ + port_disabled = pci_read_config32(dev, XHCI_USB3PDO); + for (port = 0; port < BYTM_USB3_PORT_COUNT; port++) { + if (port_disabled & (1 << port)) + continue; + xhci_reset_port_usb3(dev, port); + } +} + +static void xhci_init(device_t dev) +{ + struct soc_intel_baytrail_config *config = dev->chip_info; + struct reg_script xhci_hc_init[] = { + /* Initialize clock gating */ + REG_SCRIPT_NEXT(xhci_clock_gating_script), + /* Finalize XHCCI1 and XHCCI2 */ + REG_PCI_RMW32(0x44, ~0x00000000, 0x83c00000), + REG_PCI_RMW32(0x40, ~0x00800000, 0x80000000), + /* Set USB2 Port Routing Mask */ + REG_PCI_WRITE32(XHCI_USB2PRM, BYTM_USB2_PORT_MAP), + /* Set USB3 Port Routing Mask */ + REG_PCI_WRITE32(XHCI_USB3PRM, BYTM_USB3_PORT_MAP), + /* + * Disable ports if requested + */ + /* Open per-port disable control override */ + REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~0, UPRWC_WR_EN), + REG_PCI_WRITE32(XHCI_USB2PDO, config->usb2_port_disable_mask), + REG_PCI_WRITE32(XHCI_USB3PDO, config->usb3_port_disable_mask), + /* Close per-port disable control override */ + REG_IO_RMW16(ACPI_BASE_ADDRESS + UPRWC, ~UPRWC_WR_EN, 0), + REG_SCRIPT_END + }; + + /* Initialize XHCI controller for boot or resume path */ + if (acpi_slp_type == 3) + reg_script_run_on_dev(dev, xhci_init_resume_script); + else + reg_script_run_on_dev(dev, xhci_init_boot_script); + + /* C0 steppings change iCLK/USB PLL VCO settings from 5 to 7 */ + if (pattrs_get()->stepping == STEP_C0) { + uint32_t reg = iosf_ushphy_read(USHPHY_CDN_PLL_CONTROL); + reg |= 0x00700000; + iosf_ushphy_write(USHPHY_CDN_PLL_CONTROL, reg); + } + + /* Finalize Initialization */ + reg_script_run_on_dev(dev, xhci_hc_init); + + /* Route all ports to XHCI if requested */ + if (config->usb_route_to_xhci) + xhci_route_all(dev); +} + +static struct device_operations xhci_device_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = xhci_init, + .ops_pci = &soc_pci_ops, +}; + +static const struct pci_driver baytrail_xhci __pci_driver = { + .ops = &xhci_device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .device = XHCI_DEVID +}; diff --git a/src/soc/intel/broadwell/Kconfig b/src/soc/intel/broadwell/Kconfig new file mode 100644 index 0000000000..fffef0beed --- /dev/null +++ b/src/soc/intel/broadwell/Kconfig @@ -0,0 +1,227 @@ +config SOC_INTEL_BROADWELL + bool + help + Intel Broadwell and Haswell ULT support. + +if SOC_INTEL_BROADWELL + +config CPU_SPECIFIC_OPTIONS + def_bool y + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 + select ALT_CBFS_LOAD_PAYLOAD + select ALWAYS_LOAD_OPROM + select BACKUP_DEFAULT_SMM_REGION + select CACHE_MRC_BIN + select CACHE_MRC_SETTINGS + select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM + select CACHE_ROM + select CAR_MIGRATION + select COLLECT_TIMESTAMPS + select CPU_INTEL_FIRMWARE_INTERFACE_TABLE + select CPU_MICROCODE_IN_CBFS + select DYNAMIC_CBMEM + select HAS_PRECBMEM_TIMESTAMP_REGION + select HAVE_MONOTONIC_TIMER + select HAVE_SMI_HANDLER + select HAVE_HARD_RESET + select HAVE_USBDEBUG + select IOAPIC + select MMCONF_SUPPORT + select MMCONF_SUPPORT_DEFAULT + select RELOCATABLE_MODULES + select REG_SCRIPT + select PARALLEL_MP + select PCIEXP_ASPM + select PCIEXP_COMMON_CLOCK + select PCIEXP_CLK_PM + select PCIEXP_L1_SUB_STATE + select SMM_MODULES + select SMM_TSEG + select SMP + select SPI_FLASH + select SSE2 + select TSC_CONSTANT_RATE + select TSC_SYNC_MFENCE + select UDELAY_TSC + +config BOOTBLOCK_CPU_INIT + string + default "soc/intel/broadwell/bootblock/cpu.c" + +config BOOTBLOCK_NORTHBRIDGE_INIT + string + default "soc/intel/broadwell/bootblock/systemagent.c" + +config BOOTBLOCK_SOUTHBRIDGE_INIT + string + default "soc/intel/broadwell/bootblock/pch.c" + +config MICROCODE_INCLUDE_PATH + string + default "src/soc/intel/broadwell/microcode" + +config MMCONF_BASE_ADDRESS + hex "MMIO Base Address" + default 0xf0000000 + +config SERIAL_CPU_INIT + bool + default n + +config SMM_TSEG_SIZE + hex + default 0x800000 + +config IED_REGION_SIZE + hex + default 0x400000 + +config SMM_RESERVED_SIZE + hex + default 0x100000 + +config VGA_BIOS_ID + string + default "8086,0406" + +config CACHE_MRC_SIZE_KB + int + default 512 + +config DCACHE_RAM_BASE + hex "Base address of cache-as-RAM" + default 0xff7c0000 + +config DCACHE_RAM_SIZE + hex "Length in bytes of cache-as-RAM" + default 0x10000 + help + The size of the cache-as-ram region required during bootblock + and/or romstage. Note DCACHE_RAM_SIZE and DCACHE_RAM_MRC_VAR_SIZE + must add up to a power of 2. + +config DCACHE_RAM_MRC_VAR_SIZE + hex + default 0x30000 + help + The amount of cache-as-ram region required by the reference code. + +config DCACHE_RAM_ROMSTAGE_STACK_SIZE + hex + default 0x2000 + help + The amount of anticipated stack usage from the data cache + during pre-ram rom stage execution. + +config HAVE_MRC + bool "Add a Memory Reference Code binary" + help + Select this option to add a Memory Reference Code binary to + the resulting coreboot image. + + Note: Without this binary coreboot will not work + +if HAVE_MRC + +config MRC_FILE + string "Intel Memory Reference Code path and filename" + depends on HAVE_MRC + default "mrc.bin" + help + The filename of the file to use as Memory Reference Code binary. + +config MRC_BIN_ADDRESS + hex + default 0xfffa0000 + +config CACHE_MRC_SETTINGS + bool "Save cached MRC settings" + default y + +endif # HAVE_MRC + +config CBFS_SIZE + hex "Size of CBFS filesystem in ROM" + default 0x100000 + help + The firmware image has to store more than just coreboot, including: + - a firmware descriptor + - Intel Management Engine firmware + - MRC cache information + This option allows to limit the size of the CBFS portion in the + firmware image. + +config PRE_GRAPHICS_DELAY + int "Graphics initialization delay in ms" + default 0 + help + On some systems, coreboot boots so fast that connected monitors + (mostly TVs) won't be able to wake up fast enough to talk to the + VBIOS. On those systems we need to wait for a bit before executing + the VBIOS. + +config RESET_ON_INVALID_RAMSTAGE_CACHE + bool "Reset the system on S3 wake when ramstage cache invalid." + default n + depends on RELOCATABLE_RAMSTAGE + help + The romstage code caches the loaded ramstage program in SMM space. + On S3 wake the romstage will copy over a fresh ramstage that was + cached in the SMM space. This option determines the action to take + when the ramstage cache is invalid. If selected the system will + reset otherwise the ramstage will be reloaded from cbfs. + +config MONOTONIC_TIMER_MSR + def_bool y + select HAVE_MONOTONIC_TIMER + help + Provide a monotonic timer using the 24MHz MSR counter. + +config INTEL_PCH_UART_CONSOLE + bool "Use Serial IO UART for console" + default n + select HAVE_UART_MEMORY_MAPPED + select CONSOLE_SERIAL8250MEM + depends on !CONFIG_DRIVERS_OXFORD_OXPCIE + +config INTEL_PCH_UART_CONSOLE_NUMBER + hex "Serial IO UART number to use for console" + default "0x0" + depends on INTEL_PCH_UART_CONSOLE + +config TTYS0_BASE + hex + default 0xd6000000 + depends on INTEL_PCH_UART_CONSOLE + +config EHCI_BAR + hex + default 0xd8000000 + +config EHCI_DEBUG_OFFSET + hex + default 0xa0 + +config SERIRQ_CONTINUOUS_MODE + bool + default y + help + If you set this option to y, the serial IRQ machine will be + operated in continuous mode. + +config LOCK_MANAGEMENT_ENGINE + bool "Lock Management Engine section" + default n + help + The Intel Management Engine supports preventing write accesses + from the host to the Management Engine section in the firmware + descriptor. If the ME section is locked, it can only be overwritten + with an external SPI flash programmer. You will want this if you + want to increase security of your ROM image once you are sure + that the ME firmware is no longer going to change. + + If unsure, say N. + +endif diff --git a/src/soc/intel/broadwell/Makefile.inc b/src/soc/intel/broadwell/Makefile.inc new file mode 100644 index 0000000000..d2aa4a3c13 --- /dev/null +++ b/src/soc/intel/broadwell/Makefile.inc @@ -0,0 +1,120 @@ +subdirs-y += bootblock +subdirs-y += microcode +subdirs-y += romstage +subdirs-y += ../common +subdirs-y += ../../../cpu/x86/lapic +subdirs-y += ../../../cpu/x86/mtrr +subdirs-y += ../../../cpu/x86/smm +subdirs-y += ../../../cpu/x86/tsc +subdirs-y += ../../../cpu/intel/microcode +subdirs-y += ../../../cpu/intel/turbo + +ramstage-y += acpi.c +ramstage-y += adsp.c +ramstage-y += chip.c +ramstage-y += cpu.c +ramstage-y += cpu_info.c +smm-y += cpu_info.c +ramstage-y += elog.c +ramstage-y += finalize.c +ramstage-y += gpio.c +romstage-y += gpio.c +smm-y += gpio.c +ramstage-y += hda.c +ramstage-y += igd.c +ramstage-y += iobp.c +romstage-y += iobp.c +ramstage-y += lpc.c +ramstage-y += me.c +ramstage-y += me_status.c +romstage-y += me_status.c +ramstage-y += memmap.c +romstage-y += memmap.c +ramstage-y += minihd.c +ramstage-y += monotonic_timer.c +ramstage-y += pch.c +romstage-y += pch.c +ramstage-y += pcie.c +ramstage-y += pei_data.c +romstage-y += pei_data.c +ramstage-y += pmutil.c +romstage-y += pmutil.c +smm-y += pmutil.c +ramstage-y += ramstage.c +ramstage-$(CONFIG_HAVE_REFCODE_BLOB) += refcode.c +ramstage-y += reset.c +romstage-y += reset.c +ramstage-y += sata.c +ramstage-y += serialio.c +ramstage-y += smbus.c +ramstage-y += smbus_common.c +romstage-y += smbus_common.c +ramstage-y += smi.c +smm-y += smihandler.c +ramstage-y += smmrelocate.c +ramstage-y += spi.c +smm-$(CONFIG_SPI_FLASH_SMM) += spi.c +ramstage-y += spi_loading.c +ramstage-y += stage_cache.c +romstage-y += stage_cache.c +ramstage-y += systemagent.c +ramstage-y += tsc_freq.c +romstage-y += tsc_freq.c +smm-y += tsc_freq.c +ramstage-y += ehci.c +ramstage-y += xhci.c +smm-y += xhci.c + +ifeq ($(CONFIG_USBDEBUG),y) +ramstage-y += usbdebug.c +romstage-y += usbdebug.c +smm-y += usbdebug.c +endif + +INCLUDES += -Isrc/soc/intel/broadwell/include +ifeq ($(CONFIG_PLATFORM_USES_FSP),y) +INCLUDES += -Isrc/drivers/intel/fsp +INCLUDES += -Isrc/vendorcode/intel/fsp/fsp_1_1 +INCLUDES += -Isrc/vendorcode/intel/edk2/uefi_2.4 +INCLUDES += -Isrc/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include +INCLUDES += -Isrc/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Ia32 +INCLUDES += -I$(CONFIG_FSP_INCLUDE_PATH) +endif + +# Run an intermediate step when producing coreboot.rom +# that adds additional components to the final firmware +# image outside of CBFS +INTERMEDIATE := pch_add_me + +pch_add_me: $(obj)/coreboot.pre $(IFDTOOL) + printf " DD Adding Intel Firmware Descriptor\n" + dd if=3rdparty/mainboard/$(MAINBOARDDIR)/descriptor.bin \ + of=$(obj)/coreboot.pre conv=notrunc >/dev/null 2>&1 + printf " IFDTOOL me.bin -> coreboot.pre\n" + $(objutil)/ifdtool/ifdtool \ + -i ME:3rdparty/mainboard/$(MAINBOARDDIR)/me.bin \ + $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +ifeq ($(CONFIG_LOCK_MANAGEMENT_ENGINE),y) + printf " IFDTOOL Locking Management Engine\n" + $(objutil)/ifdtool/ifdtool -l $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +else + printf " IFDTOOL Unlocking Management Engine\n" + $(objutil)/ifdtool/ifdtool -u $(obj)/coreboot.pre + mv $(obj)/coreboot.pre.new $(obj)/coreboot.pre +endif + +PHONY += pch_add_me + +# If an MRC file is an ELF file determine the entry address and first loadable +# section offset in the file. Subtract the offset from the entry address to +# determine the final location. +mrcelfoffset = $(shell readelf -S -W $(CONFIG_MRC_FILE) | sed -e 's/\[ /[0/' | awk '$$3 ~ /PROGBITS/ { print "0x"$$5; exit }' ) +mrcelfentry = $(shell readelf -h -W $(CONFIG_MRC_FILE) | grep 'Entry point address' | awk '{print $$NF }') + +# Add memory reference code blob. +cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin +mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE)) +mrc.bin-position := $(if $(findstring elf,$(CONFIG_MRC_FILE)),$(shell printf "0x%x" $$(( $(mrcelfentry) - $(mrcelfoffset) )) ),$(CONFIG_MRC_BIN_ADDRESS)) +mrc.bin-type := 0xab diff --git a/src/soc/intel/broadwell/acpi.c b/src/soc/intel/broadwell/acpi.c new file mode 100644 index 0000000000..2560515e98 --- /dev/null +++ b/src/soc/intel/broadwell/acpi.c @@ -0,0 +1,608 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * List of suported C-states in this processor. Only the ULT parts support C8, + * C9, and C10. + */ +enum { + C_STATE_C0, /* 0 */ + C_STATE_C1, /* 1 */ + C_STATE_C1E, /* 2 */ + C_STATE_C3, /* 3 */ + C_STATE_C6_SHORT_LAT, /* 4 */ + C_STATE_C6_LONG_LAT, /* 5 */ + C_STATE_C7_SHORT_LAT, /* 6 */ + C_STATE_C7_LONG_LAT, /* 7 */ + C_STATE_C7S_SHORT_LAT, /* 8 */ + C_STATE_C7S_LONG_LAT, /* 9 */ + C_STATE_C8, /* 10 */ + C_STATE_C9, /* 11 */ + C_STATE_C10, /* 12 */ + NUM_C_STATES +}; + +#define MWAIT_RES(state, sub_state) \ + { \ + .addrl = (((state) << 4) | (sub_state)), \ + .space_id = ACPI_ADDRESS_SPACE_FIXED, \ + .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL, \ + .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT, \ + .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \ + } + +static acpi_cstate_t cstate_map[NUM_C_STATES] = { + [C_STATE_C0] = { }, + [C_STATE_C1] = { + .latency = 0, + .power = 1000, + .resource = MWAIT_RES(0,0), + }, + [C_STATE_C1E] = { + .latency = 0, + .power = 1000, + .resource = MWAIT_RES(0,1), + }, + [C_STATE_C3] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(0), + .power = 900, + .resource = MWAIT_RES(1, 0), + }, + [C_STATE_C6_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 800, + .resource = MWAIT_RES(2, 0), + }, + [C_STATE_C6_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 800, + .resource = MWAIT_RES(2, 1), + }, + [C_STATE_C7_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 700, + .resource = MWAIT_RES(3, 0), + }, + [C_STATE_C7_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 700, + .resource = MWAIT_RES(3, 1), + }, + [C_STATE_C7S_SHORT_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(1), + .power = 700, + .resource = MWAIT_RES(3, 2), + }, + [C_STATE_C7S_LONG_LAT] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(2), + .power = 700, + .resource = MWAIT_RES(3, 3), + }, + [C_STATE_C8] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(3), + .power = 600, + .resource = MWAIT_RES(4, 0), + }, + [C_STATE_C9] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(4), + .power = 500, + .resource = MWAIT_RES(5, 0), + }, + [C_STATE_C10] = { + .latency = C_STATE_LATENCY_FROM_LAT_REG(5), + .power = 400, + .resource = MWAIT_RES(6, 0), + }, +}; + +static int cstate_set_s0ix[3] = { + C_STATE_C1E, + C_STATE_C7S_LONG_LAT, + C_STATE_C10 +}; + +static int cstate_set_non_s0ix[3] = { + C_STATE_C1E, + C_STATE_C3, + C_STATE_C7S_LONG_LAT +}; + +static int get_cores_per_package(void) +{ + struct cpuinfo_x86 c; + struct cpuid_result result; + int cores = 1; + + get_fms(&c, cpuid_eax(1)); + if (c.x86 != 6) + return 1; + + result = cpuid_ext(0xb, 1); + cores = result.ebx & 0xff; + + return cores; +} + +void acpi_init_gnvs(global_nvs_t *gnvs) +{ + /* Set unknown wake source */ + gnvs->pm1i = -1; + + /* CPU core count */ + gnvs->pcnt = dev_count_cpu(); + +#if CONFIG_CONSOLE_CBMEM + /* Update the mem console pointer. */ + gnvs->cbmc = (u32)cbmem_find(CBMEM_ID_CONSOLE); +#endif + +#if CONFIG_CHROMEOS + /* Initialize Verified Boot data */ + chromeos_init_vboot(&(gnvs->chromeos)); +#if CONFIG_EC_GOOGLE_CHROMEEC + gnvs->chromeos.vbt2 = google_ec_running_ro() ? + ACTIVE_ECFW_RO : ACTIVE_ECFW_RW; +#endif + gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO; +#endif +} + +void acpi_create_intel_hpet(acpi_hpet_t * hpet) +{ + acpi_header_t *header = &(hpet->header); + acpi_addr_t *addr = &(hpet->addr); + + memset((void *) hpet, 0, sizeof(acpi_hpet_t)); + + /* fill out header fields */ + memcpy(header->signature, "HPET", 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + + header->length = sizeof(acpi_hpet_t); + header->revision = 1; + + /* fill out HPET address */ + addr->space_id = 0; /* Memory */ + addr->bit_width = 64; + addr->bit_offset = 0; + addr->addrl = (unsigned long long)HPET_BASE_ADDRESS & 0xffffffff; + addr->addrh = (unsigned long long)HPET_BASE_ADDRESS >> 32; + + hpet->id = 0x8086a201; /* Intel */ + hpet->number = 0x00; + hpet->min_tick = 0x0080; + + header->checksum = + acpi_checksum((void *) hpet, sizeof(acpi_hpet_t)); +} + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, + MCFG_BASE_ADDRESS, 0, 0, 255); + return current; +} + +void acpi_fill_in_fadt(acpi_fadt_t *fadt) +{ + const uint16_t pmbase = ACPI_BASE_ADDRESS; + + fadt->sci_int = acpi_sci_irq(); + fadt->smi_cmd = APM_CNT; + fadt->acpi_enable = APM_CNT_ACPI_ENABLE; + fadt->acpi_disable = APM_CNT_ACPI_DISABLE; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0; + + fadt->pm1a_evt_blk = pmbase + PM1_STS; + fadt->pm1b_evt_blk = 0x0; + fadt->pm1a_cnt_blk = pmbase + PM1_CNT; + fadt->pm1b_cnt_blk = 0x0; + fadt->pm2_cnt_blk = pmbase + PM2_CNT; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->gpe0_blk = pmbase + GPE0_STS(0); + fadt->gpe1_blk = 0; + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 32; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + fadt->cst_cnt = 0; + fadt->p_lvl2_lat = 1; + fadt->p_lvl3_lat = 87; + fadt->flush_size = 1024; + fadt->flush_stride = 16; + fadt->duty_offset = 1; + fadt->duty_width = 0; + fadt->day_alrm = 0xd; + fadt->mon_alrm = 0x00; + fadt->century = 0x00; + fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042; + + fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | + ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON | + ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE | + ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0; + fadt->reset_value = 6; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 0; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 0; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = pmbase + PM2_CNT; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 0; + fadt->x_gpe0_blk.bit_width = 0; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = 0; + fadt->x_gpe0_blk.addrh = 0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0x0; + fadt->x_gpe1_blk.addrh = 0x0; +} + +static acpi_tstate_t tss_table_fine[] = { + { 100, 1000, 0, 0x00, 0 }, + { 94, 940, 0, 0x1f, 0 }, + { 88, 880, 0, 0x1e, 0 }, + { 82, 820, 0, 0x1d, 0 }, + { 75, 760, 0, 0x1c, 0 }, + { 69, 700, 0, 0x1b, 0 }, + { 63, 640, 0, 0x1a, 0 }, + { 57, 580, 0, 0x19, 0 }, + { 50, 520, 0, 0x18, 0 }, + { 44, 460, 0, 0x17, 0 }, + { 38, 400, 0, 0x16, 0 }, + { 32, 340, 0, 0x15, 0 }, + { 25, 280, 0, 0x14, 0 }, + { 19, 220, 0, 0x13, 0 }, + { 13, 160, 0, 0x12, 0 }, +}; + +static acpi_tstate_t tss_table_coarse[] = { + { 100, 1000, 0, 0x00, 0 }, + { 88, 875, 0, 0x1f, 0 }, + { 75, 750, 0, 0x1e, 0 }, + { 63, 625, 0, 0x1d, 0 }, + { 50, 500, 0, 0x1c, 0 }, + { 38, 375, 0, 0x1b, 0 }, + { 25, 250, 0, 0x1a, 0 }, + { 13, 125, 0, 0x19, 0 }, +}; + +static int generate_T_state_entries(int core, int cores_per_package) +{ + int len; + + /* Indicate SW_ALL coordination for T-states */ + len = acpigen_write_TSD_package(core, cores_per_package, SW_ALL); + + /* Indicate FFixedHW so OS will use MSR */ + len += acpigen_write_empty_PTC(); + + /* Set a T-state limit that can be modified in NVS */ + len += acpigen_write_TPC("\\TLVL"); + + /* + * CPUID.(EAX=6):EAX[5] indicates support + * for extended throttle levels. + */ + if (cpuid_eax(6) & (1 << 5)) + len += acpigen_write_TSS_package( + ARRAY_SIZE(tss_table_fine), tss_table_fine); + else + len += acpigen_write_TSS_package( + ARRAY_SIZE(tss_table_coarse), tss_table_coarse); + + return len; +} + +static int generate_C_state_entries(void) +{ + device_t dev = SA_DEV_ROOT; + config_t *config = dev->chip_info; + acpi_cstate_t map[3]; + int *set; + int i; + + if (config->s0ix_enable) + set = cstate_set_s0ix; + else + set = cstate_set_non_s0ix; + + for (i = 0; i < 3; i++) { + memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t)); + map[i].ctype = i + 1; + } + + /* Generate C-state tables */ + return acpigen_write_CST_package(map, ARRAY_SIZE(map)); +} + +static int calculate_power(int tdp, int p1_ratio, int ratio) +{ + u32 m; + u32 power; + + /* + * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2 + * + * Power = (ratio / p1_ratio) * m * tdp + */ + + m = (110000 - ((p1_ratio - ratio) * 625)) / 11; + m = (m * m) / 1000; + + power = ((ratio * 100000 / p1_ratio) / 100); + power *= (m / 100) * (tdp / 1000); + power /= 1000; + + return (int)power; +} + +static int generate_P_state_entries(int core, int cores_per_package) +{ + int len, len_pss; + int ratio_min, ratio_max, ratio_turbo, ratio_step; + int coord_type, power_max, power_unit, num_entries; + int ratio, power, clock, clock_max; + msr_t msr; + + /* Determine P-state coordination type from MISC_PWR_MGMT[0] */ + msr = rdmsr(MSR_MISC_PWR_MGMT); + if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS) + coord_type = SW_ANY; + else + coord_type = HW_ALL; + + /* Get bus ratio limits and calculate clock speeds */ + msr = rdmsr(MSR_PLATFORM_INFO); + ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */ + + /* Determine if this CPU has configurable TDP */ + if (cpu_config_tdp_levels()) { + /* Set max ratio to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + ratio_max = msr.lo & 0xff; + } else { + /* Max Non-Turbo Ratio */ + ratio_max = (msr.lo >> 8) & 0xff; + } + clock_max = ratio_max * CPU_BCLK; + + /* Calculate CPU TDP in mW */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 2 << ((msr.lo & 0xf) - 1); + msr = rdmsr(MSR_PKG_POWER_SKU); + power_max = ((msr.lo & 0x7fff) / power_unit) * 1000; + + /* Write _PCT indicating use of FFixedHW */ + len = acpigen_write_empty_PCT(); + + /* Write _PPC with no limit on supported P-state */ + len += acpigen_write_PPC_NVS(); + + /* Write PSD indicating configured coordination type */ + len += acpigen_write_PSD_package(core, 1, coord_type); + + /* Add P-state entries in _PSS table */ + len += acpigen_write_name("_PSS"); + + /* Determine ratio points */ + ratio_step = PSS_RATIO_STEP; + num_entries = (ratio_max - ratio_min) / ratio_step; + while (num_entries > PSS_MAX_ENTRIES-1) { + ratio_step <<= 1; + num_entries >>= 1; + } + + /* P[T] is Turbo state if enabled */ + if (get_turbo_state() == TURBO_ENABLED) { + /* _PSS package count including Turbo */ + len_pss = acpigen_write_package(num_entries + 2); + + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + ratio_turbo = msr.lo & 0xff; + + /* Add entry for Turbo ratio */ + len_pss += acpigen_write_PSS_package( + clock_max + 1, /*MHz*/ + power_max, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio_turbo << 8, /*control*/ + ratio_turbo << 8); /*status*/ + } else { + /* _PSS package count without Turbo */ + len_pss = acpigen_write_package(num_entries + 1); + } + + /* First regular entry is max non-turbo ratio */ + len_pss += acpigen_write_PSS_package( + clock_max, /*MHz*/ + power_max, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio_max << 8, /*control*/ + ratio_max << 8); /*status*/ + + /* Generate the remaining entries */ + for (ratio = ratio_min + ((num_entries - 1) * ratio_step); + ratio >= ratio_min; ratio -= ratio_step) { + + /* Calculate power at this ratio */ + power = calculate_power(power_max, ratio_max, ratio); + clock = ratio * CPU_BCLK; + + len_pss += acpigen_write_PSS_package( + clock, /*MHz*/ + power, /*mW*/ + PSS_LATENCY_TRANSITION, /*lat1*/ + PSS_LATENCY_BUSMASTER, /*lat2*/ + ratio << 8, /*control*/ + ratio << 8); /*status*/ + } + + /* Fix package length */ + len_pss--; + acpigen_patch_len(len_pss); + + return len + len_pss; +} + +void generate_cpu_entries(void) +{ + int len_pr; + int coreID, cpuID, pcontrol_blk = ACPI_BASE_ADDRESS, plen = 6; + int totalcores = dev_count_cpu(); + int cores_per_package = get_cores_per_package(); + int numcpus = totalcores/cores_per_package; + + printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n", + numcpus, cores_per_package); + + for (cpuID=1; cpuID <=numcpus; cpuID++) { + for (coreID=1; coreID<=cores_per_package; coreID++) { + if (coreID>1) { + pcontrol_blk = 0; + plen = 0; + } + + /* Generate processor \_PR.CPUx */ + len_pr = acpigen_write_processor( + (cpuID-1)*cores_per_package+coreID-1, + pcontrol_blk, plen); + + /* Generate P-state tables */ + len_pr += generate_P_state_entries( + coreID-1, cores_per_package); + + /* Generate C-state tables */ + len_pr += generate_C_state_entries(); + + /* Generate T-state tables */ + len_pr += generate_T_state_entries( + cpuID-1, cores_per_package); + + len_pr--; + acpigen_patch_len(len_pr); + } + } +} + +unsigned long acpi_madt_irq_overrides(unsigned long current) +{ + int sci = acpi_sci_irq(); + acpi_madt_irqoverride_t *irqovr; + uint16_t flags = MP_IRQ_TRIGGER_LEVEL; + + /* INT_SRC_OVR */ + irqovr = (void *)current; + current += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0); + + if (sci >= 20) + flags |= MP_IRQ_POLARITY_LOW; + else + flags |= MP_IRQ_POLARITY_HIGH; + + /* SCI */ + irqovr = (void *)current; + current += acpi_create_madt_irqoverride(irqovr, 0, sci, sci, flags); + + return current; +} diff --git a/src/soc/intel/broadwell/acpi/adsp.asl b/src/soc/intel/broadwell/acpi/adsp.asl new file mode 100644 index 0000000000..cb10d9a9ad --- /dev/null +++ b/src/soc/intel/broadwell/acpi/adsp.asl @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device (ADSP) +{ + Method (_HID, 0, Serialized) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3438") + } + + // LynxPoint-LP + Return ("INT33C8") + } + Name (_UID, 1) + Name (_DDN, "Intel Smart Sound Technology") + + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00100000, BAR0) + Memory32Fixed (ReadWrite, 0x00000000, 0x00001000, BAR1) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, , , ) {3} + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR address and length if set in NVS + If (LNotEqual (\S8B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B8A0) + CreateDwordField (^RBUF, ^BAR1._BAS, B8A1) + Store (\S8B0, B8A0) + Store (\S8B1, B8A1) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S8EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Device (I2S0) + { + Name (_ADR, 0) + } + + Device (I2S1) + { + Name (_ADR, 1) + } +} diff --git a/src/soc/intel/broadwell/acpi/cpu.asl b/src/soc/intel/broadwell/acpi/cpu.asl new file mode 100644 index 0000000000..f0da2dedd6 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/cpu.asl @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* These devices are created at runtime */ +External (\_PR.CPU0, DeviceObj) +External (\_PR.CPU1, DeviceObj) +External (\_PR.CPU2, DeviceObj) +External (\_PR.CPU3, DeviceObj) +External (\_PR.CPU4, DeviceObj) +External (\_PR.CPU5, DeviceObj) +External (\_PR.CPU6, DeviceObj) +External (\_PR.CPU7, DeviceObj) + +/* Notify OS to re-read CPU tables, assuming ^2 CPU count */ +Method (PNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x81) // _CST + Notify (\_PR.CPU1, 0x81) // _CST + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x81) // _CST + Notify (\_PR.CPU3, 0x81) // _CST + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CPU4, 0x81) // _CST + Notify (\_PR.CPU5, 0x81) // _CST + Notify (\_PR.CPU6, 0x81) // _CST + Notify (\_PR.CPU7, 0x81) // _CST + } +} + +/* Notify OS to re-read CPU _PPC limit, assuming ^2 CPU count */ +Method (PPCN) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x80) // _PPC + Notify (\_PR.CPU1, 0x80) // _PPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x80) // _PPC + Notify (\_PR.CPU3, 0x80) // _PPC + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CPU4, 0x80) // _PPC + Notify (\_PR.CPU5, 0x80) // _PPC + Notify (\_PR.CPU6, 0x80) // _PPC + Notify (\_PR.CPU7, 0x80) // _PPC + } +} + +/* Notify OS to re-read Throttle Limit tables, assuming ^2 CPU count */ +Method (TNOT) +{ + If (LGreaterEqual (\PCNT, 2)) { + Notify (\_PR.CPU0, 0x82) // _TPC + Notify (\_PR.CPU1, 0x82) // _TPC + } + If (LGreaterEqual (\PCNT, 4)) { + Notify (\_PR.CPU2, 0x82) // _TPC + Notify (\_PR.CPU3, 0x82) // _TPC + } + If (LGreaterEqual (\PCNT, 8)) { + Notify (\_PR.CPU4, 0x82) // _TPC + Notify (\_PR.CPU5, 0x82) // _TPC + Notify (\_PR.CPU6, 0x82) // _TPC + Notify (\_PR.CPU7, 0x82) // _TPC + } +} + +/* Return a package containing enabled processor entries */ +Method (PPKG) +{ + If (LGreaterEqual (\PCNT, 8)) { + Return (Package() + { + \_PR.CPU0, + \_PR.CPU1, + \_PR.CPU2, + \_PR.CPU3, + \_PR.CPU4, + \_PR.CPU5, + \_PR.CPU6, + \_PR.CPU7 + }) + } ElseIf (LGreaterEqual (\PCNT, 4)) { + Return (Package () + { + \_PR.CPU0, + \_PR.CPU1, + \_PR.CPU2, + \_PR.CPU3 + }) + } ElseIf (LGreaterEqual (\PCNT, 2)) { + Return (Package () + { + \_PR.CPU0, + \_PR.CPU1 + }) + } Else { + Return (Package () + { + \_PR.CPU0 + }) + } +} diff --git a/src/soc/intel/broadwell/acpi/ctdp.asl b/src/soc/intel/broadwell/acpi/ctdp.asl new file mode 100644 index 0000000000..2aefda979d --- /dev/null +++ b/src/soc/intel/broadwell/acpi/ctdp.asl @@ -0,0 +1,237 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Scope (\_SB.PCI0.MCHC) +{ + Mutex (CTCM, 1) /* CTDP Switch Mutex (sync level 1) */ + Name (CTCC, 0) /* CTDP Current Selection */ + Name (CTCN, 0) /* CTDP Nominal Select */ + Name (CTCD, 1) /* CTDP Down Select */ + Name (CTCU, 2) /* CTDP Up Select */ + Name (SPL1, 0) /* Saved PL1 value */ + + OperationRegion (MCHB, SystemMemory, + Add (MCH_BASE_ADDRESS, 0x5000), 0x1000) + Field (MCHB, DWordAcc, Lock, Preserve) + { + Offset (0x930), /* PACKAGE_POWER_SKU */ + CTDN, 15, /* CTDP Nominal PL1 */ + Offset (0x938), /* PACKAGE_POWER_SKU_UNIT */ + PUNI, 4, /* Power Units */ + , 4, + EUNI, 5, /* Energy Units */ + , 3, + TUNI, 4, /* Time Units */ + Offset (0x958), /* PLATFORM_INFO */ + , 40, + LFM_, 8, /* Maximum Efficiency Ratio (LFM) */ + Offset (0x9a0), /* TURBO_POWER_LIMIT1 */ + PL1V, 15, /* Power Limit 1 Value */ + PL1E, 1, /* Power Limit 1 Enable */ + PL1C, 1, /* Power Limit 1 Clamp */ + PL1T, 7, /* Power Limit 1 Time */ + Offset (0x9a4), /* TURBO_POWER_LIMIT2 */ + PL2V, 15, /* Power Limit 2 Value */ + PL2E, 1, /* Power Limit 2 Enable */ + PL2C, 1, /* Power Limit 2 Clamp */ + PL2T, 7, /* Power Limit 2 Time */ + Offset (0xf3c), /* CONFIG_TDP_NOMINAL */ + TARN, 8, /* CTDP Nominal Turbo Activation Ratio */ + Offset (0xf40), /* CONFIG_TDP_LEVEL1 */ + CTDD, 15, /* CTDP Down PL1 */ + , 1, + TARD, 8, /* CTDP Down Turbo Activation Ratio */ + Offset (0xf48), /* MSR_CONFIG_TDP_LEVEL2 */ + CTDU, 15, /* CTDP Up PL1 */ + , 1, + TARU, 8, /* CTDP Up Turbo Activation Ratio */ + Offset (0xf50), /* CONFIG_TDP_CONTROL */ + CTCS, 2, /* CTDP Select */ + Offset (0xf54), /* TURBO_ACTIVATION_RATIO */ + TARS, 8, /* Turbo Activation Ratio Select */ + } + + /* + * Search CPU0 _PSS looking for control=arg0 and then + * return previous P-state entry number for new _PPC + * + * Format of _PSS: + * Name (_PSS, Package () { + * Package (6) { freq, power, tlat, blat, control, status } + * } + */ + External (\_PR.CPU0._PSS) + Method (PSSS, 1, NotSerialized) + { + Store (One, Local0) /* Start at P1 */ + Store (SizeOf (\_PR.CPU0._PSS), Local1) + + While (LLess (Local0, Local1)) { + /* Store _PSS entry Control value to Local2 */ + ShiftRight (DeRefOf (Index (DeRefOf (Index + (\_PR.CPU0._PSS, Local0)), 4)), 8, Local2) + If (LEqual (Local2, Arg0)) { + Return (Subtract (Local0, 1)) + } + Increment (Local0) + } + + Return (0) + } + + /* Calculate PL2 based on chip type */ + Method (CPL2, 1, NotSerialized) + { + /* Haswell ULT PL2 = 25W */ + /* FIXME: update for broadwell */ + Return (Multiply (25, 8)) + } + + /* Set Config TDP Down */ + Method (STND, 0, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + If (LEqual (CTCD, CTCC)) { + Release (CTCM) + Return (0) + } + + Store ("Set TDP Down", Debug) + + /* Set CTC */ + Store (CTCD, CTCS) + + /* Set TAR */ + Store (TARD, TARS) + + /* Set PPC limit and notify OS */ + Store (PSSS (TARD), PPCM) + PPCN () + + /* Set PL2 */ + Store (CPL2 (CTDD), PL2V) + + /* Set PL1 */ + Store (CTDD, PL1V) + + /* Store the new TDP Down setting */ + Store (CTCD, CTCC) + + Release (CTCM) + Return (1) + } + + /* Set Config TDP Nominal from Down */ + Method (STDN, 0, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + If (LEqual (CTCN, CTCC)) { + Release (CTCM) + Return (0) + } + + Store ("Set TDP Nominal", Debug) + + /* Set PL1 */ + Store (CTDN, PL1V) + + /* Set PL2 */ + Store (CPL2 (CTDN), PL2V) + + /* Set PPC limit and notify OS */ + Store (PSSS (TARN), PPCM) + PPCN () + + /* Set TAR */ + Store (TARN, TARS) + + /* Set CTC */ + Store (CTCN, CTCS) + + /* Store the new TDP Nominal setting */ + Store (CTCN, CTCC) + + Release (CTCM) + Return (1) + } + + /* Calculate PL1 value based on requested TDP */ + Method (TDPP, 1, NotSerialized) + { + Return (Multiply (ShiftLeft (Subtract (PUNI, 1), 2), Arg0)) + } + + /* Enable Controllable TDP to limit PL1 to requested value */ + Method (CTLE, 1, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + + Store ("Enable PL1 Limit", Debug) + + /* Set _PPC to LFM */ + Store (PSSS (LFM_), Local0) + Add (Local0, 1, PPCM) + \PPCN () + + /* Set TAR to LFM-1 */ + Subtract (LFM_, 1, TARS) + + /* Set PL1 to desired value */ + Store (PL1V, SPL1) + Store (TDPP (Arg0), PL1V) + + /* Set PL1 CLAMP bit */ + Store (One, PL1C) + + Release (CTCM) + Return (1) + } + + /* Disable Controllable TDP */ + Method (CTLD, 0, Serialized) + { + If (Acquire (CTCM, 100)) { + Return (0) + } + + Store ("Disable PL1 Limit", Debug) + + /* Clear PL1 CLAMP bit */ + Store (Zero, PL1C) + + /* Set PL1 to normal value */ + Store (SPL1, PL1V) + + /* Set TAR to 0 */ + Store (Zero, TARS) + + /* Set _PPC to 0 */ + Store (Zero, PPCM) + \PPCN () + + Release (CTCM) + Return (1) + } +} diff --git a/src/soc/intel/broadwell/acpi/device_nvs.asl b/src/soc/intel/broadwell/acpi/device_nvs.asl new file mode 100644 index 0000000000..1d2aa78edb --- /dev/null +++ b/src/soc/intel/broadwell/acpi/device_nvs.asl @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Device Enabled in ACPI Mode */ + +S0EN, 8, // DMA Enable +S1EN, 8, // I2C0 Enable +S2EN, 8, // I2C1 Enable +S3EN, 8, // SPI0 Enable +S4EN, 8, // SPI1 Enable +S5EN, 8, // UART0 Enable +S6EN, 8, // UART1 Enable +S7EN, 8, // SDIO Enable +S8EN, 8, // ADSP Enable + +/* BAR 0 */ + +S0B0, 32, // DMA BAR0 +S1B0, 32, // I2C0 BAR0 +S2B0, 32, // I2C1 BAR0 +S3B0, 32, // SPI0 BAR0 +S4B0, 32, // SPI1 BAR0 +S5B0, 32, // UART0 BAR0 +S6B0, 32, // UART1 BAR0 +S7B0, 32, // SDIO BAR0 +S8B0, 32, // ADSP BAR0 + +/* BAR 1 */ + +S0B1, 32, // DMA BAR1 +S1B1, 32, // I2C0 BAR1 +S2B1, 32, // I2C1 BAR1 +S3B1, 32, // SPI0 BAR1 +S4B1, 32, // SPI1 BAR1 +S5B1, 32, // UART0 BAR1 +S6B1, 32, // UART1 BAR1 +S7B1, 32, // SDIO BAR1 +S8B1, 32, // ADSP BAR1 diff --git a/src/soc/intel/broadwell/acpi/ehci.asl b/src/soc/intel/broadwell/acpi/ehci.asl new file mode 100644 index 0000000000..a2e704fccf --- /dev/null +++ b/src/soc/intel/broadwell/acpi/ehci.asl @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// EHCI Controller 0:1d.0 + +Device (EHCI) +{ + Name(_ADR, 0x001d0000) + Name (_PRW, Package(){ 0x6d, 3 }) + + // Leave USB ports on for to allow Wake from USB + + Method(_S3D,0) // Highest D State in S3 State + { + Return (2) + } + + Method(_S4D,0) // Highest D State in S4 State + { + Return (2) + } + + Device (HUB7) + { + Name (_ADR, 0x00000000) + + // How many are there? + Device (PRT1) { Name (_ADR, 1) } // USB Port 0 + Device (PRT2) { Name (_ADR, 2) } // USB Port 1 + Device (PRT3) { Name (_ADR, 3) } // USB Port 2 + Device (PRT4) { Name (_ADR, 4) } // USB Port 3 + Device (PRT5) { Name (_ADR, 5) } // USB Port 4 + Device (PRT6) { Name (_ADR, 6) } // USB Port 5 + } +} diff --git a/src/soc/intel/broadwell/acpi/globalnvs.asl b/src/soc/intel/broadwell/acpi/globalnvs.asl new file mode 100644 index 0000000000..351461e337 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/globalnvs.asl @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Global Variables */ + +Name (\PICM, 0) // IOAPIC/8259 + +/* + * Global ACPI memory region. This region is used for passing information + * between coreboot (aka "the system bios"), ACPI, and the SMI handler. + * Since we don't know where this will end up in memory at ACPI compile time, + * we have to fix it up in coreboot's ACPI creation phase. + */ + +OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0x2000) +Field (GNVS, ByteAcc, NoLock, Preserve) +{ + /* Miscellaneous */ + Offset (0x00), + OSYS, 16, // 0x00 - Operating System + SMIF, 8, // 0x02 - SMI function + PRM0, 8, // 0x03 - SMI function parameter + PRM1, 8, // 0x04 - SMI function parameter + SCIF, 8, // 0x05 - SCI function + PRM2, 8, // 0x06 - SCI function parameter + PRM3, 8, // 0x07 - SCI function parameter + LCKF, 8, // 0x08 - Global Lock function for EC + PRM4, 8, // 0x09 - Lock function parameter + PRM5, 8, // 0x0a - Lock function parameter + PCNT, 8, // 0x0b - Processor Count + PPCM, 8, // 0x0c - Max PPC State + TMPS, 8, // 0x0d - Temperature Sensor ID + TLVL, 8, // 0x0e - Throttle Level Limit + FLVL, 8, // 0x0f - Current FAN Level + TCRT, 8, // 0x10 - Critical Threshold + TPSV, 8, // 0x11 - Passive Threshold + TMAX, 8, // 0x12 - CPU Tj_max + S5U0, 8, // 0x13 - Enable USB in S5 + S3U0, 8, // 0x14 - Enable USB in S3 + S33G, 8, // 0x15 - Enable 3G in S3 + LIDS, 8, // 0x16 - LID State + PWRS, 8, // 0x17 - AC Power State + CMEM, 32, // 0x18 - 0x1b - CBMEM TOC + CBMC, 32, // 0x1c - 0x1f - Coreboot Memory Console + PM1I, 64, // 0x20 - 0x27 - PM1 wake status bit + GPEI, 64, // 0x28 - 0x2f - GPE wake status bit + + /* ChromeOS specific */ + Offset (0x100), + #include + + /* Device specific */ + Offset (0x1000), + #include "device_nvs.asl" +} + +/* Set flag to enable USB charging in S3 */ +Method (S3UE) +{ + Store (One, \S3U0) +} + +/* Set flag to disable USB charging in S3 */ +Method (S3UD) +{ + Store (Zero, \S3U0) +} + +/* Set flag to enable USB charging in S5 */ +Method (S5UE) +{ + Store (One, \S5U0) +} + +/* Set flag to disable USB charging in S5 */ +Method (S5UD) +{ + Store (Zero, \S5U0) +} + +/* Set flag to enable 3G module in S3 */ +Method (S3GE) +{ + Store (One, \S33G) +} + +/* Set flag to disable 3G module in S3 */ +Method (S3GD) +{ + Store (Zero, \S33G) +} diff --git a/src/soc/intel/broadwell/acpi/gpio.asl b/src/soc/intel/broadwell/acpi/gpio.asl new file mode 100644 index 0000000000..c6d8753975 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/gpio.asl @@ -0,0 +1,142 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device (GPIO) +{ + // GPIO Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3437") + } + + // LynxPoint-LP + Return ("INT33C7") + } + Name (_UID, 1) + + Name (RBUF, ResourceTemplate() + { + DWordIo (ResourceProducer, + MinFixed, // IsMinFixed + MaxFixed, // IsMaxFixed + PosDecode, // Decode + EntireRange, // ISARanges + 0x00000000, // AddressGranularity + 0x00000000, // AddressMinimum + 0x00000000, // AddressMaximum + 0x00000000, // AddressTranslation + 0x00000000, // RangeLength + , // ResourceSourceIndex + , // ResourceSource + BAR0) + // Disabled due to IRQ storm: http://crosbug.com/p/29548 + //Interrupt (ResourceConsumer, + // Level, ActiveHigh, Shared, , , ) {14} + }) + + Method (_CRS, 0, NotSerialized) + { + CreateDwordField (^RBUF, ^BAR0._MIN, BMIN) + CreateDwordField (^RBUF, ^BAR0._MAX, BMAX) + CreateDwordField (^RBUF, ^BAR0._LEN, BLEN) + + Store (GPIO_BASE_SIZE, BLEN) + Store (GPIO_BASE_ADDRESS, BMIN) + Store (Subtract (Add (GPIO_BASE_ADDRESS, + GPIO_BASE_SIZE), 1), BMAX) + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + Return (0xF) + } + + // GWAK: Setup GPIO as ACPI GPE for Wake + // Arg0: GPIO Number + Method (GWAK, 1, NotSerialized) + { + // Local0 = GPIO Base Address + Store (And (GPBS, Not(0x1)), Local0) + + // Local1 = BANK, Local2 = OFFSET + Divide (Arg0, 32, Local2, Local1) + + // + // Set OWNER to ACPI + // + + // Local3 = GPIOBASE + GPIO_OWN(BANK) + Store (Add (Local0, Multiply (Local1, 0x4)), Local3) + + // GPIO_OWN(BANK) + OperationRegion (IOWN, SystemIO, Local3, 4) + Field (IOWN, AnyAcc, NoLock, Preserve) { + GOWN, 32, + } + + // GPIO_OWN[GPIO] = 0 (ACPI) + Store (And (GOWN, Not (ShiftLeft (0x1, Local2))), GOWN) + + // + // Set ROUTE to SCI + // + + // Local3 = GPIOBASE + GPIO_ROUTE(BANK) + Store (Add (Add (Local0, 0x30), Multiply (Local1, 0x4)), Local3) + + // GPIO_ROUTE(BANK) + OperationRegion (IROU, SystemIO, Local3, 4) + Field (IROU, AnyAcc, NoLock, Preserve) { + GROU, 32, + } + + // GPIO_ROUTE[GPIO] = 0 (SCI) + Store (And (GROU, Not (ShiftLeft (0x1, Local2))), GROU) + + // + // Set GPnCONFIG to GPIO|INPUT|INVERT + // + + // Local3 = GPIOBASE + GPnCONFIG0(GPIO) + Store (Add (Add (Local0, 0x100), Multiply (Arg0, 0x8)), Local3) + + // GPnCONFIG(GPIO) + OperationRegion (GPNC, SystemIO, Local3, 8) + Field (GPNC, AnyAcc, NoLock, Preserve) { + GMOD, 1, // MODE: 0=NATIVE 1=GPIO + , 1, + GIOS, 1, // IO_SEL: 0=OUTPUT 1=INPUT + GINV, 1, // INVERT: 0=NORMAL 1=INVERT + GLES, 1, // LxEB: 0=EDGE 1=LEVEL + , 24, + ILVL, 1, // INPUT: 0=LOW 1=HIGH + OLVL, 1, // OUTPUT: 0=LOW 1=HIGH + GPWP, 2, // PULLUP: 00=NONE 01=DOWN 10=UP 11=INVALID + ISEN, 1, // SENSE: 0=ENABLE 1=DISABLE + } + + Store (0x1, GMOD) // GPIO + Store (0x1, GIOS) // INPUT + Store (0x1, GINV) // INVERT + } +} diff --git a/src/soc/intel/broadwell/acpi/hda.asl b/src/soc/intel/broadwell/acpi/hda.asl new file mode 100644 index 0000000000..21736615ac --- /dev/null +++ b/src/soc/intel/broadwell/acpi/hda.asl @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Intel PCH HDA */ + +// Intel High Definition Audio (Azalia) 0:1b.0 + +Device (HDEF) +{ + Name (_ADR, 0x001b0000) + Name (_PRW, Package () { 0x6d, 3 }) +} diff --git a/src/soc/intel/broadwell/acpi/irqlinks.asl b/src/soc/intel/broadwell/acpi/irqlinks.asl new file mode 100644 index 0000000000..fee400e6d7 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/irqlinks.asl @@ -0,0 +1,492 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device (LNKA) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 1) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTA) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLA, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLA, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTA + ShiftLeft (1, And (PRTA, 0x0f), IRQ0) + + Return (RTLA) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTA) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTA, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKB) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 2) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTB) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLB, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLB, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTB + ShiftLeft (1, And (PRTB, 0x0f), IRQ0) + + Return (RTLB) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTB) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTB, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKC) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 3) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTC) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLC, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLC, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTC + ShiftLeft (1, And (PRTC, 0x0f), IRQ0) + + Return (RTLC) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTC) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTC, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKD) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 4) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTD) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLD, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLD, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTD + ShiftLeft (1, And (PRTD, 0x0f), IRQ0) + + Return (RTLD) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTD) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTD, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKE) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 5) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTE) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLE, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLE, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTE + ShiftLeft (1, And (PRTE, 0x0f), IRQ0) + + Return (RTLE) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTE) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTE, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKF) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 6) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTF) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLF, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLF, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTF + ShiftLeft (1, And (PRTF, 0x0f), IRQ0) + + Return (RTLF) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTF) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTF, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKG) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 7) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTG) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLG, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLG, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTG + ShiftLeft (1, And (PRTG, 0x0f), IRQ0) + + Return (RTLG) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTG) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTG, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + +Device (LNKH) +{ + Name (_HID, EISAID("PNP0C0F")) + Name (_UID, 8) + + // Disable method + Method (_DIS, 0, Serialized) + { + Store (0x80, PRTH) + } + + // Possible Resource Settings for this Link + Name (_PRS, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) + { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 } + }) + + // Current Resource Settings for this link + Method (_CRS, 0, Serialized) + { + Name (RTLH, ResourceTemplate() + { + IRQ (Level, ActiveLow, Shared) {} + }) + CreateWordField (RTLH, 1, IRQ0) + + // Clear the WordField + Store (Zero, IRQ0) + + // Set the bit from PRTH + ShiftLeft (1, And (PRTH, 0x0f), IRQ0) + + Return (RTLH) + } + + // Set Resource Setting for this IRQ link + Method (_SRS, 1, Serialized) + { + CreateWordField (Arg0, 1, IRQ0) + + // Which bit is set? + FindSetRightBit (IRQ0, Local0) + + Decrement(Local0) + Store (Local0, PRTH) + } + + // Status + Method (_STA, 0, Serialized) + { + If(And (PRTH, 0x80)) { + Return (0x9) + } Else { + Return (0xb) + } + } +} + diff --git a/src/soc/intel/broadwell/acpi/lpc.asl b/src/soc/intel/broadwell/acpi/lpc.asl new file mode 100644 index 0000000000..2b574f756d --- /dev/null +++ b/src/soc/intel/broadwell/acpi/lpc.asl @@ -0,0 +1,208 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Intel LPC Bus Device - 0:1f.0 + +Device (LPCB) +{ + Name (_ADR, 0x001f0000) + + OperationRegion(LPC0, PCI_Config, 0x00, 0x100) + Field (LPC0, AnyAcc, NoLock, Preserve) + { + Offset (0x02), + PDID, 16, // Device ID + Offset (0x40), + PMBS, 16, // PMBASE + Offset (0x48), + GPBS, 16, // GPIOBASE + Offset (0x60), // Interrupt Routing Registers + PRTA, 8, + PRTB, 8, + PRTC, 8, + PRTD, 8, + Offset (0x68), + PRTE, 8, + PRTF, 8, + PRTG, 8, + PRTH, 8, + + Offset (0x80), // IO Decode Ranges + IOD0, 8, + IOD1, 8, + } + + Device (DMAC) // DMA Controller + { + Name (_HID, EISAID("PNP0200")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x00, 0x00, 0x01, 0x20) + IO (Decode16, 0x81, 0x81, 0x01, 0x11) + IO (Decode16, 0x93, 0x93, 0x01, 0x0d) + IO (Decode16, 0xc0, 0xc0, 0x01, 0x20) + DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 } + }) + } + + Device (FWH) // Firmware Hub + { + Name (_HID, EISAID("INT0800")) + Name (_CRS, ResourceTemplate() + { + Memory32Fixed(ReadOnly, 0xff000000, 0x01000000) + }) + } + + Device (HPET) + { + Name (_HID, EISAID("PNP0103")) + Name (_CID, 0x010CD041) + + Name (BUF0, ResourceTemplate() + { + Memory32Fixed(ReadOnly, 0xfed00000, 0x400, FED0) + }) + + Method (_STA, 0) // Device Status + { + If (HPTE) { + // Note: Ancient versions of Windows don't want + // to see the HPET in order to work right + If (LGreaterEqual(OSYS, 2001)) { + Return (0xf) // Enable and show device + } Else { + Return (0xb) // Enable and don't show device + } + } + + Return (0x0) // Not enabled, don't show. + } + + Method (_CRS, 0, Serialized) // Current resources + { + If (HPTE) { + CreateDWordField (BUF0, + \_SB.PCI0.LPCB.HPET.FED0._BAS, HPT0) + + If (Lequal(HPAS, 1)) { + Store(0xfed01000, HPT0) + } + + If (Lequal(HPAS, 2)) { + Store(0xfed02000, HPT0) + } + + If (Lequal(HPAS, 3)) { + Store(0xfed03000, HPT0) + } + } + + Return (BUF0) + } + } + + Device(PIC) // 8259 Interrupt Controller + { + Name (_HID,EISAID("PNP0000")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x20, 0x20, 0x01, 0x02) + IO (Decode16, 0x24, 0x24, 0x01, 0x02) + IO (Decode16, 0x28, 0x28, 0x01, 0x02) + IO (Decode16, 0x2c, 0x2c, 0x01, 0x02) + IO (Decode16, 0x30, 0x30, 0x01, 0x02) + IO (Decode16, 0x34, 0x34, 0x01, 0x02) + IO (Decode16, 0x38, 0x38, 0x01, 0x02) + IO (Decode16, 0x3c, 0x3c, 0x01, 0x02) + IO (Decode16, 0xa0, 0xa0, 0x01, 0x02) + IO (Decode16, 0xa4, 0xa4, 0x01, 0x02) + IO (Decode16, 0xa8, 0xa8, 0x01, 0x02) + IO (Decode16, 0xac, 0xac, 0x01, 0x02) + IO (Decode16, 0xb0, 0xb0, 0x01, 0x02) + IO (Decode16, 0xb4, 0xb4, 0x01, 0x02) + IO (Decode16, 0xb8, 0xb8, 0x01, 0x02) + IO (Decode16, 0xbc, 0xbc, 0x01, 0x02) + IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02) + IRQNoFlags () { 2 } + }) + } + + Device(MATH) // FPU + { + Name (_HID, EISAID("PNP0C04")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0xf0, 0xf0, 0x01, 0x01) + IRQNoFlags() { 13 } + }) + } + + Device(LDRC) // LPC device: Resource consumption + { + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 2) + + Name (RBUF, ResourceTemplate() + { + IO (Decode16, 0x2e, 0x2e, 0x1, 0x02) // First SuperIO + IO (Decode16, 0x4e, 0x4e, 0x1, 0x02) // Second SuperIO + IO (Decode16, 0x61, 0x61, 0x1, 0x01) // NMI Status + IO (Decode16, 0x63, 0x63, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x65, 0x65, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x67, 0x67, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0x80, 0x80, 0x1, 0x01) // Port 80 Post + IO (Decode16, 0x92, 0x92, 0x1, 0x01) // CPU Reserved + IO (Decode16, 0xb2, 0xb2, 0x1, 0x02) // SWSMI + IO (Decode16, ACPI_BASE_ADDRESS, ACPI_BASE_ADDRESS, + 0x1, 0xff) + }) + + Method (_CRS, 0, NotSerialized) + { + Return (RBUF) + } + } + + Device (RTC) // Real Time Clock + { + Name (_HID, EISAID("PNP0B00")) + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x70, 0x70, 1, 8) + //IRQNoFlags() { 8 } + }) + } + + Device (TIMR) // Intel 8254 timer + { + Name (_HID, EISAID("PNP0100")) + Name (_CRS, ResourceTemplate() { + IO (Decode16, 0x40, 0x40, 0x01, 0x04) + IO (Decode16, 0x50, 0x50, 0x10, 0x04) + IRQNoFlags() {0} + }) + } + + #include "gpio.asl" + #include "irqlinks.asl" + #include + #include +} diff --git a/src/soc/intel/broadwell/acpi/pch.asl b/src/soc/intel/broadwell/acpi/pch.asl new file mode 100644 index 0000000000..998133d9d9 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/pch.asl @@ -0,0 +1,101 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +Scope (\) +{ + // IO-Trap at 0x800. This is the ACPI->SMI communication interface. + OperationRegion (IO_T, SystemIO, 0x800, 0x10) + Field (IO_T, ByteAcc, NoLock, Preserve) + { + Offset (0x8), + TRP0, 8 // IO-Trap at 0x808 + } + + // Root Complex Register Block + OperationRegion (RCRB, SystemMemory, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE) + Field (RCRB, DWordAcc, Lock, Preserve) + { + Offset (0x3404), // High Performance Timer Configuration + HPAS, 2, // Address Select + , 5, + HPTE, 1, // Address Enable + } + + /* + * Check PCH type + * Return 1 if PCH is WildcatPoint + * Return 0 if PCH is LynxPoint + */ + Method (ISWP) + { + And (\_SB.PCI0.LPCB.PDID, 0xfff0, Local0) + If (LEqual (Local0, 0x9cc0)) { + Return (1) + } Else { + Return (0) + } + } +} + +// High Definition Audio (Azalia) 0:1b.0 +#include "hda.asl" + +// ADSP/SST 0:13.0 +#include "adsp.asl" + +// PCI Express Ports 0:1c.x +#include "pcie.asl" + +// USB EHCI 0:1d.0 +#include "ehci.asl" + +// USB XHCI 0:14.0 +#include "xhci.asl" + +// LPC Bridge 0:1f.0 +#include "lpc.asl" + +// SATA 0:1f.2 +#include "sata.asl" + +// SMBus 0:1f.3 +#include "smbus.asl" + +// Serial IO +#include "serialio.asl" + +Method (_OSC, 4) +{ + /* Check for proper GUID */ + If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) + { + /* Let OS control everything */ + Return (Arg3) + } + Else + { + /* Unrecognized UUID */ + CreateDWordField (Arg3, 0, CDW1) + Or (CDW1, 4, CDW1) + Return (Arg3) + } +} diff --git a/src/soc/intel/broadwell/acpi/pci_irqs.asl b/src/soc/intel/broadwell/acpi/pci_irqs.asl new file mode 100644 index 0000000000..0c23e10a51 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/pci_irqs.asl @@ -0,0 +1,89 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Method(_PRT) +{ + If (PICM) { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, 0, 16 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, 0, 16 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, 0, 22 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, 0, 16 }, + Package() { 0x001cffff, 1, 0, 17 }, + Package() { 0x001cffff, 2, 0, 18 }, + Package() { 0x001cffff, 3, 0, 19 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, 0, 19 }, + // Audio DSP (Smart Sound) 0:13.0 + Package() { 0x0013ffff, 0, 0, 23 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, 0, 18 }, + // LPC devices 0:1f.0 + Package() { 0x001fffff, 0, 0, 22 }, + Package() { 0x001fffff, 1, 0, 18 }, + Package() { 0x001fffff, 2, 0, 17 }, + Package() { 0x001fffff, 3, 0, 16 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, 0, 20 }, + Package() { 0x0015ffff, 1, 0, 21 }, + Package() { 0x0015ffff, 2, 0, 21 }, + Package() { 0x0015ffff, 3, 0, 21 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, 0, 23 }, + }) + } Else { + Return (Package() { + // Onboard graphics (IGD) 0:2.0 + Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // Mini-HD Audio 0:3.0 + Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + // High Definition Audio 0:1b.0 + Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + // PCIe Root Ports 0:1c.x + Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + // EHCI 0:1d.0 + Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + // Audio DSP (Smart Sound) 0:13.0 + Package() { 0x0013ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + // XHCI 0:14.0 + Package() { 0x0014ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + // LPC device 0:1f.0 + Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKG, 0 }, + Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x001fffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x001fffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }, + // Serial IO 0:15.0 + Package() { 0x0015ffff, 0, \_SB.PCI0.LPCB.LNKE, 0 }, + Package() { 0x0015ffff, 1, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 2, \_SB.PCI0.LPCB.LNKF, 0 }, + Package() { 0x0015ffff, 3, \_SB.PCI0.LPCB.LNKF, 0 }, + // SDIO 0:17.0 + Package() { 0x0017ffff, 0, \_SB.PCI0.LPCB.LNKH, 0 }, + }) + } +} + diff --git a/src/soc/intel/broadwell/acpi/pcie.asl b/src/soc/intel/broadwell/acpi/pcie.asl new file mode 100644 index 0000000000..a48bdde0e3 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/pcie.asl @@ -0,0 +1,214 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Intel PCH PCIe support */ + +Method (IRQM, 1, Serialized) { + + /* Interrupt Map INTA->INTA, INTB->INTB, INTC->INTC, INTD->INTD */ + Name (IQAA, Package() { + Package() { 0x0000ffff, 0, 0, 16 }, + Package() { 0x0000ffff, 1, 0, 17 }, + Package() { 0x0000ffff, 2, 0, 18 }, + Package() { 0x0000ffff, 3, 0, 19 } }) + Name (IQAP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 } }) + + /* Interrupt Map INTA->INTB, INTB->INTC, INTC->INTD, INTD->INTA */ + Name (IQBA, Package() { + Package() { 0x0000ffff, 0, 0, 17 }, + Package() { 0x0000ffff, 1, 0, 18 }, + Package() { 0x0000ffff, 2, 0, 19 }, + Package() { 0x0000ffff, 3, 0, 16 } }) + Name (IQBP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKA, 0 } }) + + /* Interrupt Map INTA->INTC, INTB->INTD, INTC->INTA, INTD->INTB */ + Name (IQCA, Package() { + Package() { 0x0000ffff, 0, 0, 18 }, + Package() { 0x0000ffff, 1, 0, 19 }, + Package() { 0x0000ffff, 2, 0, 16 }, + Package() { 0x0000ffff, 3, 0, 17 } }) + Name (IQCP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKB, 0 } }) + + /* Interrupt Map INTA->INTD, INTB->INTA, INTC->INTB, INTD->INTC */ + Name (IQDA, Package() { + Package() { 0x0000ffff, 0, 0, 19 }, + Package() { 0x0000ffff, 1, 0, 16 }, + Package() { 0x0000ffff, 2, 0, 17 }, + Package() { 0x0000ffff, 3, 0, 18 } }) + Name (IQDP, Package() { + Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 }, + Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKC, 0 } }) + + Switch (ToInteger (Arg0)) { + /* PCIe Root Port 1 and 5 */ + Case (Package() { 1, 5 }) { + If (PICM) { + Return (IQAA) + } Else { + Return (IQAP) + } + } + + /* PCIe Root Port 2 and 6 */ + Case (Package() { 2, 6 }) { + If (PICM) { + Return (IQBA) + } Else { + Return (IQBP) + } + } + + /* PCIe Root Port 3 and 7 */ + Case (Package() { 3, 7 }) { + If (PICM) { + Return (IQCA) + } Else { + Return (IQCP) + } + } + + /* PCIe Root Port 4 and 8 */ + Case (Package() { 4, 8 }) { + If (PICM) { + Return (IQDA) + } Else { + Return (IQDP) + } + } + + Default { + If (PICM) { + Return (IQDA) + } Else { + Return (IQDP) + } + } + } +} + +Device (RP01) +{ + Name (_ADR, 0x001c0000) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP02) +{ + Name (_ADR, 0x001c0001) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP03) +{ + Name (_ADR, 0x001c0002) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP04) +{ + Name (_ADR, 0x001c0003) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP05) +{ + Name (_ADR, 0x001c0004) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP06) +{ + Name (_ADR, 0x001c0005) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP07) +{ + Name (_ADR, 0x001c0006) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} + +Device (RP08) +{ + Name (_ADR, 0x001c0007) + + #include "pcie_port.asl" + + Method (_PRT) + { + Return (IRQM (RPPN)) + } +} diff --git a/src/soc/intel/broadwell/acpi/pcie_port.asl b/src/soc/intel/broadwell/acpi/pcie_port.asl new file mode 100644 index 0000000000..32267461b7 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/pcie_port.asl @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Included in each PCIe Root Port device */ + +OperationRegion (RPCS, PCI_Config, 0x00, 0xFF) +Field (RPCS, AnyAcc, NoLock, Preserve) +{ + Offset (0x4c), // Link Capabilities + , 24, + RPPN, 8, // Root Port Number +} diff --git a/src/soc/intel/broadwell/acpi/platform.asl b/src/soc/intel/broadwell/acpi/platform.asl new file mode 100644 index 0000000000..f63168a745 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/platform.asl @@ -0,0 +1,91 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* The APM port can be used for generating software SMIs */ + +OperationRegion (APMP, SystemIO, 0xb2, 2) +Field (APMP, ByteAcc, NoLock, Preserve) +{ + APMC, 8, // APM command + APMS, 8 // APM status +} + +/* Port 80 POST */ + +OperationRegion (POST, SystemIO, 0x80, 1) +Field (POST, ByteAcc, Lock, Preserve) +{ + DBG0, 8 +} + +/* SMI I/O Trap */ +Method (TRAP, 1, Serialized) +{ + Store (Arg0, SMIF) // SMI Function + Store (0, TRP0) // Generate trap + Return (SMIF) // Return value of SMI handler +} + +/* The _PIC method is called by the OS to choose between interrupt + * routing via the i8259 interrupt controller or the APIC. + * + * _PIC is called with a parameter of 0 for i8259 configuration and + * with a parameter of 1 for Local Apic/IOAPIC configuration. + */ + +Method (_PIC, 1) +{ + /* Remember the OS' IRQ routing choice. */ + Store (Arg0, PICM) +} + +/* + * The _PTS method (Prepare To Sleep) is called before the OS is + * entering a sleep state. The sleep state number is passed in Arg0 + */ + +Method (_PTS, 1) +{ +} + +/* The _WAK method is called on system wakeup */ + +Method (_WAK, 1) +{ + Return (Package (){ 0, 0 }) +} + +Scope (\_SB) +{ + Method (_SWS) + { + /* Index into PM1 for device that caused wake */ + Return (\PM1I) + } +} + +Scope (\_GPE) +{ + Method (_SWS) + { + /* Index into GPE for device that caused wake */ + Return (\GPEI) + } +} diff --git a/src/soc/intel/broadwell/acpi/sata.asl b/src/soc/intel/broadwell/acpi/sata.asl new file mode 100644 index 0000000000..0af2a3f3f5 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/sata.asl @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Intel SATA Controller 0:1f.2 +Device (SATA) +{ + Name (_ADR, 0x001f0002) +} diff --git a/src/soc/intel/broadwell/acpi/serialio.asl b/src/soc/intel/broadwell/acpi/serialio.asl new file mode 100644 index 0000000000..7ffc671a74 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/serialio.asl @@ -0,0 +1,627 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Intel Serial IO Devices in ACPI Mode + +// Serial IO Device BAR0 and BAR1 is 4KB +#define SIO_BAR_LEN 0x1000 + +// Put SerialIO device in D0 state +// Arg0 - BAR1 of device +// Arg1 - Set if device is in ACPI mode +Method (LPD0, 2, Serialized) +{ + // PCI mode devices will be handled by OS PCI bus driver + If (LEqual (Arg1, 0)) { + Return + } + + OperationRegion (SPRT, SystemMemory, Add (Arg0, 0x84), 4) + Field (SPRT, DWordAcc, NoLock, Preserve) + { + SPCS, 32 + } + + And (SPCS, 0xFFFFFFFC, SPCS) + Store (SPCS, Local0) // Read back after writing +} + +// Put SerialIO device in D3 state +// Arg0 - BAR1 of device +// Arg1 - Set if device is in ACPI mode +Method (LPD3, 2, Serialized) +{ + // PCI mode devices will be handled by OS PCI bus driver + If (LEqual (Arg1, 0)) { + Return + } + + OperationRegion (SPRT, SystemMemory, Add (Arg0, 0x84), 4) + Field (SPRT, DWordAcc, NoLock, Preserve) + { + SPCS, 32 + } + + Or (SPCS, 0x3, SPCS) + Store (SPCS, Local0) // Read back after writing +} + +// Serial IO Resource Consumption for BAR1 +Device (SIOR) +{ + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 4) + + Name (RBUF, ResourceTemplate() + { + // Serial IO BAR1 (PCI config space) resources + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D0) // SDMA + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D1) // I2C0 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D2) // I2C1 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D3) // SPI0 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D4) // SPI1 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D5) // UART0 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D6) // UART1 + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, B1D7) // SDIO + }) + + // Update BAR1 address and length if set in NVS + Method (_CRS, 0, NotSerialized) + { + // SDMA + If (LNotEqual (\S0B1, Zero)) { + CreateDwordField (^RBUF, ^B1D0._BAS, B0AD) + CreateDwordField (^RBUF, ^B1D0._LEN, B0LN) + Store (\S0B1, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + // I2C0 + If (LNotEqual (\S1B1, Zero)) { + CreateDwordField (^RBUF, ^B1D1._BAS, B1AD) + CreateDwordField (^RBUF, ^B1D1._LEN, B1LN) + Store (\S1B1, B1AD) + Store (SIO_BAR_LEN, B1LN) + } + + // I2C1 + If (LNotEqual (\S2B1, Zero)) { + CreateDwordField (^RBUF, ^B1D2._BAS, B2AD) + CreateDwordField (^RBUF, ^B1D2._LEN, B2LN) + Store (\S2B1, B2AD) + Store (SIO_BAR_LEN, B2LN) + } + + // SPI0 + If (LNotEqual (\S3B1, Zero)) { + CreateDwordField (^RBUF, ^B1D3._BAS, B3AD) + CreateDwordField (^RBUF, ^B1D3._LEN, B3LN) + Store (\S3B1, B3AD) + Store (SIO_BAR_LEN, B3LN) + } + + // SPI1 + If (LNotEqual (\S4B1, Zero)) { + CreateDwordField (^RBUF, ^B1D4._BAS, B4AD) + CreateDwordField (^RBUF, ^B1D4._LEN, B4LN) + Store (\S4B1, B4AD) + Store (SIO_BAR_LEN, B4LN) + } + + // UART0 + If (LNotEqual (\S5B1, Zero)) { + CreateDwordField (^RBUF, ^B1D5._BAS, B5AD) + CreateDwordField (^RBUF, ^B1D5._LEN, B5LN) + Store (\S5B1, B5AD) + Store (SIO_BAR_LEN, B5LN) + } + + // UART1 + If (LNotEqual (\S6B1, Zero)) { + CreateDwordField (^RBUF, ^B1D6._BAS, B6AD) + CreateDwordField (^RBUF, ^B1D6._LEN, B6LN) + Store (\S6B1, B6AD) + Store (SIO_BAR_LEN, B6LN) + } + + // SDIO + If (LNotEqual (\S7B1, Zero)) { + CreateDwordField (^RBUF, ^B1D7._BAS, B7AD) + CreateDwordField (^RBUF, ^B1D7._LEN, B7LN) + Store (\S7B1, B7AD) + Store (SIO_BAR_LEN, B7LN) + } + + Return (RBUF) + } +} + +Device (SDMA) +{ + // Serial IO DMA Controller + Name (_HID, "INTL9C60") + Name (_UID, 1) + Name (_ADR, 0x00150000) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7} + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S0B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S0B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S0EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } +} + +Device (I2C0) +{ + // Serial IO I2C0 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3432") + } + + // LynxPoint-LP + Return ("INT33C2") + } + Name (_UID, 1) + Name (_ADR, 0x00150001) + + Name (SSCN, Package () { 432, 507, 30 }) + Name (FMCN, Package () { 72, 160, 30 }) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7} + }) + + // DMA channels are only used if Serial IO DMA controller is enabled + Name (DBUF, ResourceTemplate () + { + FixedDMA (0x18, 4, Width32Bit, DMA1) // Tx + FixedDMA (0x19, 5, Width32Bit, DMA2) // Rx + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S1B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S1B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + // Check if Serial IO DMA Controller is enabled + If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) { + Return (ConcatenateResTemplate (RBUF, DBUF)) + } Else { + Return (RBUF) + } + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S1EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S1B1, \S1EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S1B1, \S1EN) + } +} + +Device (I2C1) +{ + // Serial IO I2C1 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3433") + } + + // LynxPoint-LP + Return ("INT33C3") + } + Name (_UID, 1) + Name (_ADR, 0x00150002) + + Name (SSCN, Package () { 432, 507, 30 }) + Name (FMCN, Package () { 72, 160, 30 }) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7} + }) + + // DMA channels are only used if Serial IO DMA controller is enabled + Name (DBUF, ResourceTemplate () + { + FixedDMA (0x1A, 6, Width32Bit, DMA1) // Tx + FixedDMA (0x1B, 7, Width32Bit, DMA2) // Rx + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S2B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S2B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + // Check if Serial IO DMA Controller is enabled + If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) { + Return (ConcatenateResTemplate (RBUF, DBUF)) + } Else { + Return (RBUF) + } + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S2EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S2B1, \S2EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S2B1, \S2EN) + } +} + +Device (SPI0) +{ + // Serial IO SPI0 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3430") + } + + // LynxPoint-LP + Return ("INT33C0") + } + Name (_UID, 1) + Name (_ADR, 0x00150003) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7} + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S3B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S3B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S3EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S3B1, \S3EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S3B1, \S3EN) + } +} + +Device (SPI1) +{ + // Serial IO SPI1 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3431") + } + + // LynxPoint-LP + Return ("INT33C1") + } + Name (_UID, 1) + Name (_ADR, 0x00150004) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {7} + }) + + // DMA channels are only used if Serial IO DMA controller is enabled + Name (DBUF, ResourceTemplate () + { + FixedDMA (0x10, 0, Width32Bit, DMA1) // Tx + FixedDMA (0x11, 1, Width32Bit, DMA2) // Rx + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S4B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S4B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + // Check if Serial IO DMA Controller is enabled + If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) { + Return (ConcatenateResTemplate (RBUF, DBUF)) + } Else { + Return (RBUF) + } + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S4EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S4B1, \S4EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S4B1, \S4EN) + } +} + +Device (UAR0) +{ + // Serial IO UART0 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3434") + } + + // LynxPoint-LP + Return ("INT33C4") + } + Name (_UID, 1) + Name (_ADR, 0x00150005) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {13} + }) + + // DMA channels are only used if Serial IO DMA controller is enabled + Name (DBUF, ResourceTemplate () + { + FixedDMA (0x16, 2, Width32Bit, DMA1) // Tx + FixedDMA (0x17, 3, Width32Bit, DMA2) // Rx + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S5B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S5B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + // Check if Serial IO DMA Controller is enabled + If (LNotEqual (\_SB.PCI0.SDMA._STA, Zero)) { + Return (ConcatenateResTemplate (RBUF, DBUF)) + } Else { + Return (RBUF) + } + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S5EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S5B1, \S5EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S5B1, \S5EN) + } +} + +Device (UAR1) +{ + // Serial IO UART1 Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3435") + } + + // LynxPoint-LP + Return ("INT33C5") + } + Name (_UID, 1) + Name (_ADR, 0x00150006) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {13} + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S6B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S6B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S6EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } + + Method (_PS0, 0, Serialized) + { + ^^LPD0 (\S6B1, \S6EN) + } + + Method (_PS3, 0, Serialized) + { + ^^LPD3 (\S6B1, \S6EN) + } +} + +Device (SDIO) +{ + // Serial IO SDIO Controller + Method (_HID) + { + If (\ISWP ()) { + // WildcatPoint + Return ("INT3436") + } + + // LynxPoint-LP + Return ("INT33C6") + } + Name (_CID, "PNP0D40") + Name (_UID, 1) + Name (_ADR, 0x00170000) + + // BAR0 is assigned during PCI enumeration and saved into NVS + Name (RBUF, ResourceTemplate () + { + Memory32Fixed (ReadWrite, 0x00000000, 0x00000000, BAR0) + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, , , ) {5} + }) + + Method (_CRS, 0, NotSerialized) + { + // Update BAR0 address and length if set in NVS + If (LNotEqual (\S7B0, Zero)) { + CreateDwordField (^RBUF, ^BAR0._BAS, B0AD) + CreateDwordField (^RBUF, ^BAR0._LEN, B0LN) + Store (\S7B0, B0AD) + Store (SIO_BAR_LEN, B0LN) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (LEqual (\S7EN, 0)) { + Return (0x0) + } Else { + Return (0xF) + } + } +} diff --git a/src/soc/intel/broadwell/acpi/sleepstates.asl b/src/soc/intel/broadwell/acpi/sleepstates.asl new file mode 100644 index 0000000000..6fea862d86 --- /dev/null +++ b/src/soc/intel/broadwell/acpi/sleepstates.asl @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Name (\_S0, Package () { 0x0, 0x0, 0x0, 0x0 }) +Name (\_S1, Package () { 0x1, 0x1, 0x0, 0x0 }) +Name (\_S2, Package () { 0x1, 0x1, 0x0, 0x0 }) +Name (\_S3, Package () { 0x5, 0x5, 0x0, 0x0 }) +Name (\_S4, Package () { 0x6, 0x6, 0x0, 0x0 }) +Name (\_S5, Package () { 0x7, 0x7, 0x0, 0x0 }) diff --git a/src/soc/intel/broadwell/acpi/smbus.asl b/src/soc/intel/broadwell/acpi/smbus.asl new file mode 100644 index 0000000000..15bcfde69a --- /dev/null +++ b/src/soc/intel/broadwell/acpi/smbus.asl @@ -0,0 +1,241 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Intel SMBus Controller 0:1f.3 + +Device (SBUS) +{ + Name (_ADR, 0x001f0003) + +#ifdef ENABLE_SMBUS_METHODS + OperationRegion (SMBP, PCI_Config, 0x00, 0x100) + Field(SMBP, DWordAcc, NoLock, Preserve) + { + Offset(0x40), + , 2, + I2CE, 1 + } + + OperationRegion (SMBI, SystemIO, SMBUS_IO_BASE, 0x20) + Field (SMBI, ByteAcc, NoLock, Preserve) + { + HSTS, 8, // Host Status + , 8, + HCNT, 8, // Host Control + HCMD, 8, // Host Command + TXSA, 8, // Transmit Slave Address + DAT0, 8, // Host Data 0 + DAT1, 8, // Host Data 1 + HBDB, 8, // Host Block Data Byte + PECK, 8, // Packet Error Check + RXSA, 8, // Receive Slave Address + RXDA, 16, // Receive Slave Data + AUXS, 8, // Auxiliary Status + AUXC, 8, // Auxiliary Control + SLPC, 8, // SMLink Pin Control + SBPC, 8, // SMBus Pin Control + SSTS, 8, // Slave Status + SCMD, 8, // Slave Command + NADR, 8, // Notify Device Address + NDLB, 8, // Notify Data Low Byte + NDLH, 8, // Notify Data High Byte + } + + // Kill all SMBus communication + Method (KILL, 0, Serialized) + { + Or (HCNT, 0x02, HCNT) // Send Kill + Or (HSTS, 0xff, HSTS) // Clean Status + } + + // Check if last operation completed + // return Failure = 0, Success = 1 + Method (CMPL, 0, Serialized) + { + Store (4000, Local0) // Timeout 200ms in 50us steps + While (Local0) { + If (And(HSTS, 0x02)) { // Completion Status? + Return (1) // Operation Completed + } Else { + Stall (50) + Decrement (Local0) + If (LEqual(Local0, 0)) { + KILL() + } + } + } + + Return (0) // Failure + } + + + // Wait for SMBus to become ready + Method (SRDY, 0, Serialized) + { + Store (200, Local0) // Timeout 200ms + While (Local0) { + If (And(HSTS, 0x40)) { // IN_USE? + Sleep(1) // Wait 1ms + Decrement(Local0) // timeout-- + If (LEqual(Local0, 0)) { + Return (1) + } + } Else { + Store (0, Local0) // We're ready + } + } + + Store (4000, Local0) // Timeout 200ms (50us * 4000) + While (Local0) { + If (And (HSTS, 0x01)) { // Host Busy? + Stall(50) // Wait 50us + Decrement(Local0) // timeout-- + If (LEqual(Local0, 0)) { + KILL() + } + } Else { + Return (0) // Success + } + } + + Return (1) // Failure + } + + // SMBus Send Byte + // Arg0: Address + // Arg1: Data + // Return: 1 = Success, 0=Failure + + Method (SSXB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0) + } + + // Send Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Arg0, TXSA) // Write Address + Store (Arg1, HCMD) // Write Data + + Store (0x48, HCNT) // Start + Byte Data Protocol + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (1) // Success + } + + Return (0) + } + + + // SMBus Receive Byte + // Arg0: Address + // Return: 0xffff = Failure, Data (8bit) = Success + + Method (SRXB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0xffff) + } + + // Receive Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Or (Arg0, 1), TXSA) // Write Address + + Store (0x44, HCNT) // Start + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (DAT0) // Success + } + + Return (0xffff) + } + + + // SMBus Write Byte + // Arg0: Address + // Arg1: Command + // Arg2: Data + // Return: 1 = Success, 0=Failure + + Method (SWRB, 3, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0) + } + + // Send Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Arg0, TXSA) // Write Address + Store (Arg1, HCMD) // Write Command + Store (Arg2, DAT0) // Write Data + + Store (0x48, HCNT) // Start + Byte Protocol + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (1) // Success + } + + Return (0) + } + + + // SMBus Read Byte + // Arg0: Address + // Arg1: Command + // Return: 0xffff = Failure, Data (8bit) = Success + + Method (SRDB, 2, Serialized) + { + + // Is the SMBus Controller Ready? + If (SRDY()) { + Return (0xffff) + } + + // Receive Byte + Store (0, I2CE) // SMBus Enable + Store (0xbf, HSTS) + Store (Or (Arg0, 1), TXSA) // Write Address + Store (Arg1, HCMD) // Command + + Store (0x48, HCNT) // Start + + If (CMPL()) { + Or (HSTS, 0xff, HSTS) // Clean up + Return (DAT0) // Success + } + + Return (0xffff) + } +#endif +} + diff --git a/src/soc/intel/broadwell/acpi/systemagent.asl b/src/soc/intel/broadwell/acpi/systemagent.asl new file mode 100644 index 0000000000..8fcd0b77ed --- /dev/null +++ b/src/soc/intel/broadwell/acpi/systemagent.asl @@ -0,0 +1,212 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +Name (_HID, EISAID ("PNP0A08")) // PCIe +Name (_CID, EISAID ("PNP0A03")) // PCI + +Name (_ADR, 0) +Name (_BBN, 0) + +Device (MCHC) +{ + Name (_ADR, 0x00000000) // 0:0.0 + + OperationRegion (MCHP, PCI_Config, 0x00, 0x100) + Field (MCHP, DWordAcc, NoLock, Preserve) + { + Offset (0x70), // ME Base Address + MEBA, 64, + Offset (0xa0), // Top of Used Memory + TOM, 64, + Offset (0xbc), // Top of Low Used Memory + TLUD, 32, + } +} + +// Current Resource Settings + +Method (_CRS, 0, Serialized) +{ + Name (MCRS, ResourceTemplate() + { + // Bus Numbers + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00) + + // IO Region 0 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00) + + // PCI Config Space + Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008) + + // IO Region 1 + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01) + + // VGA memory (0xa0000-0xbffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000a0000, 0x000bffff, 0x00000000, + 0x00020000,,, ASEG) + + // OPROM reserved (0xc0000-0xc3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c0000, 0x000c3fff, 0x00000000, + 0x00004000,,, OPR0) + + // OPROM reserved (0xc4000-0xc7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c4000, 0x000c7fff, 0x00000000, + 0x00004000,,, OPR1) + + // OPROM reserved (0xc8000-0xcbfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000c8000, 0x000cbfff, 0x00000000, + 0x00004000,,, OPR2) + + // OPROM reserved (0xcc000-0xcffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000cc000, 0x000cffff, 0x00000000, + 0x00004000,,, OPR3) + + // OPROM reserved (0xd0000-0xd3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d0000, 0x000d3fff, 0x00000000, + 0x00004000,,, OPR4) + + // OPROM reserved (0xd4000-0xd7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d4000, 0x000d7fff, 0x00000000, + 0x00004000,,, OPR5) + + // OPROM reserved (0xd8000-0xdbfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000d8000, 0x000dbfff, 0x00000000, + 0x00004000,,, OPR6) + + // OPROM reserved (0xdc000-0xdffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000dc000, 0x000dffff, 0x00000000, + 0x00004000,,, OPR7) + + // BIOS Extension (0xe0000-0xe3fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e0000, 0x000e3fff, 0x00000000, + 0x00004000,,, ESG0) + + // BIOS Extension (0xe4000-0xe7fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e4000, 0x000e7fff, 0x00000000, + 0x00004000,,, ESG1) + + // BIOS Extension (0xe8000-0xebfff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000e8000, 0x000ebfff, 0x00000000, + 0x00004000,,, ESG2) + + // BIOS Extension (0xec000-0xeffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000ec000, 0x000effff, 0x00000000, + 0x00004000,,, ESG3) + + // System BIOS (0xf0000-0xfffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x000f0000, 0x000fffff, 0x00000000, + 0x00010000,,, FSEG) + + // PCI Memory Region (Top of memory-0xfebfffff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0x00000000, 0xfebfffff, 0x00000000, + 0xfec00000,,, PM01) + + // TPM Area (0xfed40000-0xfed44fff) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, + Cacheable, ReadWrite, + 0x00000000, 0xfed40000, 0xfed44fff, 0x00000000, + 0x00005000,,, TPMR) + }) + + // Find PCI resource area in MCRS + CreateDwordField(MCRS, PM01._MIN, PMIN) + CreateDwordField(MCRS, PM01._MAX, PMAX) + CreateDwordField(MCRS, PM01._LEN, PLEN) + + // Fix up PCI memory region + // Start with Top of Lower Usable DRAM + Store (^MCHC.TLUD, Local0) + Store (^MCHC.MEBA, Local1) + + // Check if ME base is equal + If (LEqual (Local0, Local1)) { + // Use Top Of Memory instead + Store (^MCHC.TOM, Local0) + } + + Store (Local0, PMIN) + Add(Subtract(PMAX, PMIN), 1, PLEN) + + Return (MCRS) +} + +/* PCI Device Resource Consumption */ +Device (PDRC) +{ + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 1) + + Name (PDRS, ResourceTemplate() { + Memory32Fixed (ReadWrite, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE) + Memory32Fixed (ReadWrite, MCH_BASE_ADDRESS, MCH_BASE_SIZE) + Memory32Fixed (ReadWrite, DMI_BASE_ADDRESS, DMI_BASE_SIZE) + Memory32Fixed (ReadWrite, EP_BASE_ADDRESS, EP_BASE_SIZE) + Memory32Fixed (ReadWrite, MCFG_BASE_ADDRESS, MCFG_BASE_SIZE) + Memory32Fixed (ReadWrite, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE) + Memory32Fixed (ReadWrite, GDXC_BASE_ADDRESS, GDXC_BASE_SIZE) + }) + + // Current Resource Settings + Method (_CRS, 0, Serialized) + { + Return (PDRS) + } +} + +/* PCI IRQ assignment */ +#include "pci_irqs.asl" + +/* Configurable TDP */ +#include "ctdp.asl" diff --git a/src/soc/intel/broadwell/acpi/xhci.asl b/src/soc/intel/broadwell/acpi/xhci.asl new file mode 100644 index 0000000000..9d870e578c --- /dev/null +++ b/src/soc/intel/broadwell/acpi/xhci.asl @@ -0,0 +1,347 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// XHCI Controller 0:14.0 + +Device (XHCI) +{ + Name (_ADR, 0x00140000) + + Name (PLSD, 5) // Port Link State - RxDetect + Name (PLSP, 7) // Port Link State - Polling + + OperationRegion (XPRT, PCI_Config, 0x00, 0x100) + Field (XPRT, AnyAcc, NoLock, Preserve) + { + Offset (0x0), + DVID, 16, + Offset (0x10), + , 16, + XMEM, 16, // MEM_BASE + Offset (0x74), + D0D3, 2, + , 6, + PMEE, 1, // PME_EN + , 6, + PMES, 1, // PME_STS + Offset (0xb0), + , 13, + MB13, 1, + MB14, 1, + Offset (0xd0), + PR2R, 32, // USB2PR + PR2M, 32, // USB2PRM + PR3R, 32, // USB3PR + PR3M, 32, // USB3PRM + } + + // Clear status bits + Method (LPCL, 0, Serialized) + { + OperationRegion (XREG, SystemMemory, + ShiftLeft (^XMEM, 16), 0x600) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x510), // PORTSCNUSB3[0] + PSC0, 32, + Offset (0x520), // PORTSCNUSB3[1] + PSC1, 32, + Offset (0x530), // PORTSCNUSB3[2] + PSC2, 32, + Offset (0x540), // PORTSCNUSB3[3] + PSC3, 32, + } + + // Port Enabled/Disabled (Bit 1) + Name (PEDB, ShiftLeft (1, 1)) + + // Change Status (Bits 23:17) + Name (CHST, ShiftLeft (0x7f, 17)) + + // Port 0 + And (PSC0, Not (PEDB), Local0) + Or (Local0, CHST, PSC0) + + // Port 1 + And (PSC1, Not (PEDB), Local0) + Or (Local0, CHST, PSC1) + + // Port 2 + And (PSC2, Not (PEDB), Local0) + Or (Local0, CHST, PSC2) + + // Port 3 + And (PSC3, Not (PEDB), Local0) + Or (Local0, CHST, PSC3) + } + + Method (LPS0, 0, Serialized) + { + OperationRegion (XREG, SystemMemory, + ShiftLeft (^XMEM, 16), 0x600) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x510), // PORTSCNUSB3 + , 5, + PLS1, 4, // [8:5] Port Link State + PPR1, 1, // [9] Port Power + , 7, + CSC1, 1, // [17] Connect Status Change + , 1, + WRC1, 1, // [19] Warm Port Reset Change + , 11, + WPR1, 1, // [31] Warm Port Reset + Offset (0x520), // PORTSCNUSB3 + , 5, + PLS2, 4, // [8:5] Port Link State + PPR2, 1, // [9] Port Power + , 7, + CSC2, 1, // [17] Connect Status Change + , 1, + WRC2, 1, // [19] Warm Port Reset Change + , 11, + WPR2, 1, // [31] Warm Port Reset + Offset (0x530), // PORTSCNUSB3 + , 5, + PLS3, 4, // [8:5] Port Link State + PPR3, 1, // [9] Port Power + , 7, + CSC3, 1, // [17] Connect Status Change + , 1, + WRC3, 1, // [19] Warm Port Reset Change + , 11, + WPR3, 1, // [31] Warm Port Reset + Offset (0x540), // PORTSCNUSB3 + , 5, + PLS4, 4, // [8:5] Port Link State + PPR4, 1, // [9] Port Power + , 7, + CSC4, 1, // [17] Connect Status Change + , 1, + WRC4, 1, // [19] Warm Port Reset Change + , 11, + WPR4, 1, // [31] Warm Port Reset + } + + // Wait for all powered ports to finish polling + Store (10, Local0) + While (LOr (LOr (LAnd (LEqual (PPR1, 1), LEqual (PLS1, PLSP)), + LAnd (LEqual (PPR2, 1), LEqual (PLS2, PLSP))), + LOr (LAnd (LEqual (PPR3, 1), LEqual (PLS3, PLSP)), + LAnd (LEqual (PPR4, 1), LEqual (PLS4, PLSP))))) + { + If (LEqual (Local0, 0)) { + Break + } + Decrement (Local0) + Stall (10) + } + + // For each USB3 Port: + // If port is disconnected (PLS=5 PP=1 CSC=0) + // 1) Issue warm reset (WPR=1) + // 2) Poll for warm reset complete (WRC=0) + // 3) Write 1 to port status to clear + + // Local# indicate if port is reset + Store (0, Local1) + Store (0, Local2) + Store (0, Local3) + Store (0, Local4) + + If (LAnd (LEqual (PLS1, PLSD), + LAnd (LEqual (CSC1, 0), LEqual (PPR1, 1)))) { + Store (1, WPR1) // Issue warm reset + Store (1, Local1) + } + If (LAnd (LEqual (PLS2, PLSD), + LAnd (LEqual (CSC2, 0), LEqual (PPR2, 1)))) { + Store (1, WPR2) // Issue warm reset + Store (1, Local2) + } + If (LAnd (LEqual (PLS3, PLSD), + LAnd (LEqual (CSC3, 0), LEqual (PPR3, 1)))) { + Store (1, WPR3) // Issue warm reset + Store (1, Local3) + } + If (LAnd (LEqual (PLS4, PLSD), + LAnd (LEqual (CSC4, 0), LEqual (PPR4, 1)))) { + Store (1, WPR4) // Issue warm reset + Store (1, Local4) + } + + // Poll for warm reset complete on all ports that were reset + Store (10, Local0) + While (LOr (LOr (LAnd (LEqual (Local1, 1), LEqual (WRC1, 0)), + LAnd (LEqual (Local2, 1), LEqual (WRC2, 0))), + LOr (LAnd (LEqual (Local3, 1), LEqual (WRC3, 0)), + LAnd (LEqual (Local4, 1), LEqual (WRC4, 0))))) + { + If (LEqual (Local0, 0)) { + Break + } + Decrement (Local0) + Stall (10) + } + + // Clear status bits in all ports + LPCL () + } + + Method (_PSC, 0, NotSerialized) + { + Return (^D0D3) + } + + Method (_PS0, 0, Serialized) + { + If (LEqual (^DVID, 0xFFFF)) { + Return () + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return () + } + + OperationRegion (XREG, SystemMemory, + Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x0e0), // AUX Reset Control 1 + , 15, + AX15, 1, + Offset (0x154), // AUX Domain PM Control Register 2 + , 31, + CLK2, 1, + Offset (0x16c), // AUX Clock Control + , 2, + CLK0, 1, + , 11, + CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable + } + + // If device is in D3, set back to D0 + Store (^D0D3, Local0) + if (LEqual (Local0, 3)) { + Store (0, ^D0D3) + } + + // Clear PCI 0xB0[14:13] + Store (0, ^MB13) + Store (0, ^MB14) + + // Clear MMIO 0x816C[14,2] + Store (0, CLK0) + Store (0, CLK1) + + // Set MMIO 0x8154[31] + Store (1, CLK2) + + // Handle per-port reset if needed + LPS0 () + + // Set MMIO 0x80e0[15] + Store (1, AX15) + + Return () + } + + Method (_PS3, 0, Serialized) + { + If (LEqual (^DVID, 0xFFFF)) { + Return () + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return () + } + + OperationRegion (XREG, SystemMemory, + Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x0e0), // AUX Reset Control 1 + , 15, + AX15, 1, + Offset (0x154), // AUX Domain PM Control Register 2 + , 31, + CLK2, 1, + Offset (0x16c), // AUX Clock Control + , 2, + CLK0, 1, + , 11, + CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable + } + + Store (1, ^PMES) // Clear PME Status + Store (1, ^PMEE) // Enable PME + + // If device is in D3, set back to D0 + Store (^D0D3, Local0) + if (LEqual (Local0, 3)) { + Store (0, ^D0D3) + } + + // Set PCI 0xB0[14:13] + Store (1, ^MB13) + Store (1, ^MB14) + + // Set MMIO 0x816C[14,2] + Store (1, CLK0) + Store (1, CLK1) + + // Clear MMIO 0x8154[31] + Store (0, CLK2) + + // Clear MMIO 0x80e0[15] + Store (0, AX15) + + // Put device in D3 + Store (3, ^D0D3) + + Return () + } + + Name (_PRW, Package(){ 0x6d, 3 }) + + // Leave USB ports on for to allow Wake from USB + + Method(_S3D,0) // Highest D State in S3 State + { + Return (3) + } + + Method(_S4D,0) // Highest D State in S4 State + { + Return (3) + } + + Device (HUB7) + { + Name (_ADR, 0x00000000) + + // How many are there? + Device (PRT1) { Name (_ADR, 1) } // USB Port 0 + Device (PRT2) { Name (_ADR, 2) } // USB Port 1 + Device (PRT3) { Name (_ADR, 3) } // USB Port 2 + Device (PRT4) { Name (_ADR, 4) } // USB Port 3 + Device (PRT5) { Name (_ADR, 5) } // USB Port 4 + Device (PRT6) { Name (_ADR, 6) } // USB Port 5 + } +} + diff --git a/src/soc/intel/broadwell/adsp.c b/src/soc/intel/broadwell/adsp.c new file mode 100644 index 0000000000..11688fb35f --- /dev/null +++ b/src/soc/intel/broadwell/adsp.c @@ -0,0 +1,166 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void adsp_init(struct device *dev) +{ + config_t *config = dev->chip_info; + struct resource *bar0, *bar1; + u32 tmp32; + + /* Ensure memory and bus master are enabled */ + tmp32 = pci_read_config32(dev, PCI_COMMAND); + tmp32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(dev, PCI_COMMAND, tmp32); + + /* Find BAR0 and BAR1 */ + bar0 = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!bar0) + return; + bar1 = find_resource(dev, PCI_BASE_ADDRESS_1); + if (!bar1) + return; + + /* + * Set LTR value in DSP shim LTR control register to 3ms + * SNOOP_REQ[13]=1b SNOOP_SCALE[12:10]=100b (1ms) SNOOP_VAL[9:0]=3h + */ + tmp32 = pch_is_wpt() ? ADSP_SHIM_BASE_WPT : ADSP_SHIM_BASE_LPT; + write32(bar0->base + tmp32 + ADSP_SHIM_LTRC, ADSP_SHIM_LTRC_VALUE); + + /* Program VDRTCTL2 D19:F0:A8[31:0] = 0x00000fff */ + pci_write_config32(dev, ADSP_PCI_VDRTCTL2, ADSP_VDRTCTL2_VALUE); + + /* Program ADSP IOBP VDLDAT1 to 0x040100 */ + pch_iobp_write(ADSP_IOBP_VDLDAT1, ADSP_VDLDAT1_VALUE); + + /* Set D3 Power Gating Enable in D19:F0:A0 based on PCH type */ + tmp32 = pci_read_config32(dev, ADSP_PCI_VDRTCTL0); + if (pch_is_wpt()) { + if (config->adsp_d3_pg_enable) { + tmp32 &= ~ADSP_VDRTCTL0_D3PGD_WPT; + if (config->adsp_sram_pg_enable) + tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_WPT; + else + tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_WPT; + } else { + tmp32 |= ADSP_VDRTCTL0_D3PGD_WPT; + } + } else { + if (config->adsp_d3_pg_enable) { + tmp32 &= ~ADSP_VDRTCTL0_D3PGD_LPT; + if (config->adsp_sram_pg_enable) + tmp32 &= ~ADSP_VDRTCTL0_D3SRAMPGD_LPT; + else + tmp32 |= ADSP_VDRTCTL0_D3SRAMPGD_LPT; + } else { + tmp32 |= ADSP_VDRTCTL0_D3PGD_LPT; + } + } + pci_write_config32(dev, ADSP_PCI_VDRTCTL0, tmp32); + + /* Set PSF Snoop to SA, RCBA+0x3350[10]=1b */ + RCBA32_OR(0x3350, (1 << 10)); + + /* Set DSP IOBP PMCTL 0x1e0=0x3f */ + pch_iobp_write(ADSP_IOBP_PMCTL, ADSP_PMCTL_VALUE); + + if (config->sio_acpi_mode) { + /* Configure for ACPI mode */ + global_nvs_t *gnvs; + + printk(BIOS_INFO, "ADSP: Enable ACPI Mode IRQ3\n"); + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + gnvs->dev.bar0[SIO_NVS_ADSP] = (u32)bar0->base; + gnvs->dev.bar1[SIO_NVS_ADSP] = (u32)bar1->base; + gnvs->dev.enable[SIO_NVS_ADSP] = 1; + + /* Set PCI Config Disable Bit */ + pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~0, ADSP_PCICFGCTL_PCICD); + + /* Set interrupt de-assert/assert opcode override to IRQ3 */ + pch_iobp_write(ADSP_IOBP_VDLDAT2, ADSP_IOBP_ACPI_IRQ3); + + /* Enable IRQ3 in RCBA */ + RCBA32_OR(ACPIIRQEN, ADSP_ACPI_IRQEN); + + /* Set ACPI Interrupt Enable Bit */ + pch_iobp_update(ADSP_IOBP_PCICFGCTL, ~ADSP_PCICFGCTL_SPCBAD, + ADSP_PCICFGCTL_ACPIIE); + + /* Put ADSP in D3hot */ + tmp32 = read32(bar1->base + PCH_PCS); + tmp32 |= PCH_PCS_PS_D3HOT; + write32(bar1->base + PCH_PCS, tmp32); + } else { + printk(BIOS_INFO, "ADSP: Enable PCI Mode IRQ23\n"); + + /* Configure for PCI mode */ + pci_write_config32(dev, PCI_INTERRUPT_LINE, ADSP_PCI_IRQ); + + /* Clear ACPI Interrupt Enable Bit */ + pch_iobp_update(ADSP_IOBP_PCICFGCTL, + ~(ADSP_PCICFGCTL_SPCBAD | ADSP_PCICFGCTL_ACPIIE), 0); + } +} + +static struct device_operations adsp_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &adsp_init, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c36, /* LynxPoint */ + 0x9cb6, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_adsp __pci_driver = { + .ops = &adsp_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; + diff --git a/src/soc/intel/broadwell/bootblock/Makefile.inc b/src/soc/intel/broadwell/bootblock/Makefile.inc new file mode 100644 index 0000000000..2ca5a4569f --- /dev/null +++ b/src/soc/intel/broadwell/bootblock/Makefile.inc @@ -0,0 +1 @@ +chipset_bootblock_inc += $(src)/soc/intel/broadwell/bootblock/timestamp.inc diff --git a/src/soc/intel/broadwell/bootblock/cpu.c b/src/soc/intel/broadwell/bootblock/cpu.c new file mode 100644 index 0000000000..38f6d78240 --- /dev/null +++ b/src/soc/intel/broadwell/bootblock/cpu.c @@ -0,0 +1,145 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void set_var_mtrr( + unsigned reg, unsigned base, unsigned size, unsigned type) + +{ + /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ + msr_t basem, maskm; + basem.lo = base | type; + basem.hi = 0; + wrmsr(MTRRphysBase_MSR(reg), basem); + maskm.lo = ~(size - 1) | MTRRphysMaskValid; + maskm.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1; + wrmsr(MTRRphysMask_MSR(reg), maskm); +} + +static void enable_rom_caching(void) +{ + msr_t msr; + + disable_cache(); + /* Why only top 4MiB ? */ + set_var_mtrr(1, CACHE_ROM_BASE, CONFIG_CACHE_ROM_SIZE, MTRR_TYPE_WRPROT); + enable_cache(); + + /* Enable Variable MTRRs */ + msr.hi = 0x00000000; + msr.lo = 0x00000800; + wrmsr(MTRRdefType_MSR, msr); +} + +static void bootblock_mdelay(int ms) +{ + u32 target = ms * 24 * 1000; + msr_t current; + msr_t start = rdmsr(MSR_COUNTER_24_MHZ); + + do { + current = rdmsr(MSR_COUNTER_24_MHZ); + } while ((current.lo - start.lo) < target); +} + +static void set_flex_ratio_to_tdp_nominal(void) +{ + msr_t flex_ratio, msr; + u32 soft_reset; + u8 nominal_ratio; + + /* Check for Flex Ratio support */ + flex_ratio = rdmsr(MSR_FLEX_RATIO); + if (!(flex_ratio.lo & FLEX_RATIO_EN)) + return; + + /* Check for >0 configurable TDPs */ + msr = rdmsr(MSR_PLATFORM_INFO); + if (((msr.hi >> 1) & 3) == 0) + return; + + /* Use nominal TDP ratio for flex ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + nominal_ratio = msr.lo & 0xff; + + /* See if flex ratio is already set to nominal TDP ratio */ + if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio) + return; + + /* Set flex ratio to nominal TDP ratio */ + flex_ratio.lo &= ~0xff00; + flex_ratio.lo |= nominal_ratio << 8; + flex_ratio.lo |= FLEX_RATIO_LOCK; + wrmsr(MSR_FLEX_RATIO, flex_ratio); + + /* Set flex ratio in soft reset data register bits 11:6. + * RCBA region is enabled in southbridge bootblock */ + soft_reset = RCBA32(SOFT_RESET_DATA); + soft_reset &= ~(0x3f << 6); + soft_reset |= (nominal_ratio & 0x3f) << 6; + RCBA32(SOFT_RESET_DATA) = soft_reset; + + /* Set soft reset control to use register value */ + RCBA32_OR(SOFT_RESET_CTRL, 1); + + /* Delay before reset to avoid potential TPM lockout */ + bootblock_mdelay(30); + + /* Issue warm reset, will be "CPU only" due to soft reset data */ + outb(0x0, 0xcf9); + outb(0x6, 0xcf9); + while (1) { + asm("hlt"); + } +} + +static void check_for_clean_reset(void) +{ + msr_t msr; + msr = rdmsr(MTRRdefType_MSR); + + /* Use the MTRR default type MSR as a proxy for detecting INIT#. + * Reset the system if any known bits are set in that MSR. That is + * an indication of the CPU not being properly reset. */ + if (msr.lo & (MTRRdefTypeEn | MTRRdefTypeFixEn)) { + outb(0x0, 0xcf9); + outb(0x6, 0xcf9); + while (1) { + asm("hlt"); + } + } +} + +static void bootblock_cpu_init(void) +{ + /* Set flex ratio and reset if needed */ + set_flex_ratio_to_tdp_nominal(); + check_for_clean_reset(); + enable_rom_caching(); + intel_update_microcode_from_cbfs(); +} diff --git a/src/soc/intel/broadwell/bootblock/pch.c b/src/soc/intel/broadwell/bootblock/pch.c new file mode 100644 index 0000000000..c0576f7cdb --- /dev/null +++ b/src/soc/intel/broadwell/bootblock/pch.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +/* + * Enable Prefetching and Caching. + */ +static void enable_spi_prefetch(void) +{ + u8 reg8 = pci_read_config8(PCH_DEV_LPC, 0xdc); + reg8 &= ~(3 << 2); + reg8 |= (2 << 2); /* Prefetching and Caching Enabled */ + pci_write_config8(PCH_DEV_LPC, 0xdc, reg8); +} + + +static void map_rcba(void) +{ + pci_write_config32(PCH_DEV_LPC, RCBA, RCBA_BASE_ADDRESS | 1); +} + +static void enable_port80_on_lpc(void) +{ + /* Enable port 80 POST on LPC. The chipset does this by deafult, + * but it doesn't appear to hurt anything. */ + u32 gcs = RCBA32(GCS); + gcs = gcs & ~0x4; + RCBA32(GCS) = gcs; +} + +static void set_spi_speed(void) +{ + u32 fdod; + u8 ssfc; + + /* Observe SPI Descriptor Component Section 0 */ + SPIBAR32(SPIBAR_FDOC) = 0x1000; + + /* Extract the Write/Erase SPI Frequency from descriptor */ + fdod = SPIBAR32(SPIBAR_FDOD); + fdod >>= 24; + fdod &= 7; + + /* Set Software Sequence frequency to match */ + ssfc = SPIBAR8(SPIBAR_SSFC + 2); + ssfc &= ~7; + ssfc |= fdod; + SPIBAR8(SPIBAR_SSFC + 2) = ssfc; +} + +static void bootblock_southbridge_init(void) +{ + map_rcba(); + enable_spi_prefetch(); + enable_port80_on_lpc(); + set_spi_speed(); +} diff --git a/src/soc/intel/broadwell/bootblock/systemagent.c b/src/soc/intel/broadwell/bootblock/systemagent.c new file mode 100644 index 0000000000..a6a34e777e --- /dev/null +++ b/src/soc/intel/broadwell/bootblock/systemagent.c @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static void bootblock_northbridge_init(void) +{ + uint32_t reg; + + /* + * The "io" variant of the config access is explicitly used to + * setup the PCIEXBAR because CONFIG_MMCONF_SUPPORT_DEFAULT is set to + * to true. That way all subsequent non-explicit config accesses use + * MCFG. This code also assumes that bootblock_northbridge_init() is + * the first thing called in the non-asm boot block code. The final + * assumption is that no assembly code is using the + * CONFIG_MMCONF_SUPPORT_DEFAULT option to do PCI config acceses. + * + * The PCIEXBAR is assumed to live in the memory mapped IO space under + * 4GiB. + */ + reg = 0; + pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR + 4, reg); + reg = CONFIG_MMCONF_BASE_ADDRESS | 4 | 1; /* 64MiB - 0-63 buses. */ + pci_io_write_config32(SA_DEV_ROOT, PCIEXBAR, reg); +} diff --git a/src/soc/intel/broadwell/bootblock/timestamp.inc b/src/soc/intel/broadwell/bootblock/timestamp.inc new file mode 100644 index 0000000000..f565775ed8 --- /dev/null +++ b/src/soc/intel/broadwell/bootblock/timestamp.inc @@ -0,0 +1,19 @@ +/* Store the initial timestamp for booting in mmx registers. This works + * because the bootblock isn't being compiled with MMX support so mm0 and + * mm1 will be preserved into romstage. */ + .code32 + +.global stash_timestamp +stash_timestamp: + + /* Save the BIST value */ + movl %eax, %ebp + + finit + rdtsc + movd %eax, %mm0 + movd %edx, %mm1 + + /* Restore the BIST value to %eax */ + movl %ebp, %eax + diff --git a/src/soc/intel/broadwell/chip.c b/src/soc/intel/broadwell/chip.c new file mode 100644 index 0000000000..124b52a192 --- /dev/null +++ b/src/soc/intel/broadwell/chip.c @@ -0,0 +1,101 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) +#include +#endif /* CONFIG_PLATFORM_USES_FSP */ +#include +#include +#include + +static void pci_domain_set_resources(device_t dev) +{ + assign_resources(dev->link_list); +} + +static struct device_operations pci_domain_ops = { + .read_resources = &pci_domain_read_resources, + .set_resources = &pci_domain_set_resources, + .scan_bus = &pci_domain_scan_bus, + .ops_pci_bus = &pci_ops_mmconf, +}; + +static void cpu_bus_noop(device_t dev) { } + +static void broadwell_final(device_t dev) +{ +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + /* Notify FSP done device setup */ + printk(BIOS_DEBUG, + "Calling FspNotify(EnumInitPhaseAfterPciEnumeration)\n"); + fsp_notify(EnumInitPhaseAfterPciEnumeration); + + printk(BIOS_DEBUG, "Calling FspNotify(EnumInitPhaseReadyToBoot)\n"); + fsp_notify(EnumInitPhaseReadyToBoot); + + printk(BIOS_DEBUG, "FspNotify Returned\n"); +#endif /* CONFIG_PLATFORM_USES_FSP */ +} + +static struct device_operations cpu_bus_ops = { + .read_resources = &cpu_bus_noop, + .set_resources = &cpu_bus_noop, + .enable_resources = &cpu_bus_noop, + .init = &broadwell_init_cpus, + .final = &broadwell_final, +}; + +static void broadwell_enable(device_t dev) +{ + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_DOMAIN) { + dev->ops = &pci_domain_ops; + } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { + dev->ops = &cpu_bus_ops; + } else if (dev->path.type == DEVICE_PATH_PCI) { + /* Handle PCH device enable */ + if (PCI_SLOT(dev->path.pci.devfn) > SA_DEV_SLOT_MINIHD && + (dev->ops == NULL || dev->ops->enable == NULL)) { + broadwell_pch_enable_dev(dev); + } + } +} + +struct chip_operations soc_intel_broadwell_ops = { + CHIP_NAME("Intel Broadwell") + .enable_dev = &broadwell_enable, + .init = &broadwell_init_pre_device, +}; + +static void pci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + else + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + (device << 16) | vendor); +} + +struct pci_operations broadwell_pci_ops = { + .set_subsystem = &pci_set_subsystem +}; diff --git a/src/soc/intel/broadwell/chip.h b/src/soc/intel/broadwell/chip.h new file mode 100644 index 0000000000..703c865a8f --- /dev/null +++ b/src/soc/intel/broadwell/chip.h @@ -0,0 +1,145 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _SOC_INTEL_BROADWELL_CHIP_H_ +#define _SOC_INTEL_BROADWELL_CHIP_H_ + +struct soc_intel_broadwell_config { + /* + * Interrupt Routing configuration + * If bit7 is 1, the interrupt is disabled. + */ + uint8_t pirqa_routing; + uint8_t pirqb_routing; + uint8_t pirqc_routing; + uint8_t pirqd_routing; + uint8_t pirqe_routing; + uint8_t pirqf_routing; + uint8_t pirqg_routing; + uint8_t pirqh_routing; + + /* GPE configuration */ + uint32_t gpe0_en_1; + uint32_t gpe0_en_2; + uint32_t gpe0_en_3; + uint32_t gpe0_en_4; + + /* GPIO SMI configuration */ + uint32_t alt_gp_smi_en; + + /* IDE configuration */ + uint8_t sata_port_map; + uint32_t sata_port0_gen3_tx; + uint32_t sata_port1_gen3_tx; + uint32_t sata_port0_gen3_dtle; + uint32_t sata_port1_gen3_dtle; + + /* + * SATA DEVSLP Mux + * 0 = port 0 DEVSLP on DEVSLP0/GPIO33 + * 1 = port 3 DEVSLP on DEVSLP0/GPIO33 + */ + uint8_t sata_devslp_mux; + + /* + * DEVSLP Disable + * 0: DEVSLP is enabled + * 1: DEVSLP is disabled + */ + uint8_t sata_devslp_disable; + + /* Generic IO decode ranges */ + uint32_t gen1_dec; + uint32_t gen2_dec; + uint32_t gen3_dec; + uint32_t gen4_dec; + + /* Enable linear PCIe Root Port function numbers starting at zero */ + uint8_t pcie_port_coalesce; + + /* Force root port ASPM configuration with port bitmap */ + uint8_t pcie_port_force_aspm; + + /* Put SerialIO devices into ACPI mode instead of a PCI device */ + uint8_t sio_acpi_mode; + + /* I2C voltage select: 0=3.3V 1=1.8V */ + uint8_t sio_i2c0_voltage; + uint8_t sio_i2c1_voltage; + + /* Enable ADSP power gating features */ + uint8_t adsp_d3_pg_enable; + uint8_t adsp_sram_pg_enable; + + /* + * Clock Disable Map: + * [21:16] = CLKOUT_PCIE# 5-0 + * [24] = CLKOUT_ITPXDP + */ + uint32_t icc_clock_disable; + + /* + * Digital Port Hotplug Enable: + * 0x04 = Enabled, 2ms short pulse + * 0x05 = Enabled, 4.5ms short pulse + * 0x06 = Enabled, 6ms short pulse + * 0x07 = Enabled, 100ms short pulse + */ + u8 gpu_dp_b_hotplug; + u8 gpu_dp_c_hotplug; + u8 gpu_dp_d_hotplug; + + /* Panel power sequence timings */ + u8 gpu_panel_port_select; + u8 gpu_panel_power_cycle_delay; + u16 gpu_panel_power_up_delay; + u16 gpu_panel_power_down_delay; + u16 gpu_panel_power_backlight_on_delay; + u16 gpu_panel_power_backlight_off_delay; + + /* Panel backlight settings */ + u32 gpu_cpu_backlight; + u32 gpu_pch_backlight; + + /* + * Graphics CD Clock Frequency + * 0 = 337.5MHz + * 1 = 450MHz + * 2 = 540MHz + * 3 = 675MHz + */ + int cdclk; + + /* Enable S0iX support */ + int s0ix_enable; + + /* Deep SX enable */ + int deep_sx_enable_ac; + int deep_sx_enable_dc; + + /* TCC activation offset */ + int tcc_offset; +}; + +typedef struct soc_intel_broadwell_config config_t; + +extern struct chip_operations soc_ops; + +#endif diff --git a/src/soc/intel/broadwell/cpu.c b/src/soc/intel/broadwell/cpu.c new file mode 100644 index 0000000000..84ced0bed0 --- /dev/null +++ b/src/soc/intel/broadwell/cpu.c @@ -0,0 +1,704 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ +static const u8 power_limit_time_sec_to_msr[] = { + [0] = 0x00, + [1] = 0x0a, + [2] = 0x0b, + [3] = 0x4b, + [4] = 0x0c, + [5] = 0x2c, + [6] = 0x4c, + [7] = 0x6c, + [8] = 0x0d, + [10] = 0x2d, + [12] = 0x4d, + [14] = 0x6d, + [16] = 0x0e, + [20] = 0x2e, + [24] = 0x4e, + [28] = 0x6e, + [32] = 0x0f, + [40] = 0x2f, + [48] = 0x4f, + [56] = 0x6f, + [64] = 0x10, + [80] = 0x30, + [96] = 0x50, + [112] = 0x70, + [128] = 0x11, +}; + +/* Convert POWER_LIMIT_1_TIME MSR value to seconds */ +static const u8 power_limit_time_msr_to_sec[] = { + [0x00] = 0, + [0x0a] = 1, + [0x0b] = 2, + [0x4b] = 3, + [0x0c] = 4, + [0x2c] = 5, + [0x4c] = 6, + [0x6c] = 7, + [0x0d] = 8, + [0x2d] = 10, + [0x4d] = 12, + [0x6d] = 14, + [0x0e] = 16, + [0x2e] = 20, + [0x4e] = 24, + [0x6e] = 28, + [0x0f] = 32, + [0x2f] = 40, + [0x4f] = 48, + [0x6f] = 56, + [0x10] = 64, + [0x30] = 80, + [0x50] = 96, + [0x70] = 112, + [0x11] = 128, +}; + +/* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate + * the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly + * when a core is woken up. */ +static int pcode_ready(void) +{ + int wait_count; + const int delay_step = 10; + + wait_count = 0; + do { + if (!(MCHBAR32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY)) + return 0; + wait_count += delay_step; + udelay(delay_step); + } while (wait_count < 1000); + + return -1; +} + +static void calibrate_24mhz_bclk(void) +{ + int err_code; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return; + } + + /* A non-zero value initiates the PCODE calibration. */ + MCHBAR32(BIOS_MAILBOX_DATA) = ~0; + MCHBAR32(BIOS_MAILBOX_INTERFACE) = + MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return; + } + + err_code = MCHBAR32(BIOS_MAILBOX_INTERFACE) & 0xff; + + printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration response: %d\n", + err_code); + + /* Read the calibrated value. */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = + MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on read.\n"); + return; + } + + printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration value: 0x%08x\n", + MCHBAR32(BIOS_MAILBOX_DATA)); +} + +static u32 pcode_mailbox_read(u32 command) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return 0; + } + + /* Send command and start transaction */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return 0; + } + + /* Read mailbox */ + return MCHBAR32(BIOS_MAILBOX_DATA); +} + +static void initialize_vr_config(void) +{ + msr_t msr; + + printk(BIOS_DEBUG, "Initializing VR config.\n"); + + /* Configure VR_CURRENT_CONFIG. */ + msr = rdmsr(MSR_VR_CURRENT_CONFIG); + /* Preserve bits 63 and 62. Bit 62 is PSI4 enable, but it is only valid + * on ULT systems. */ + msr.hi &= 0xc0000000; + msr.hi |= (0x01 << (52 - 32)); /* PSI3 threshold - 1A. */ + msr.hi |= (0x05 << (42 - 32)); /* PSI2 threshold - 5A. */ + msr.hi |= (0x14 << (32 - 32)); /* PSI1 threshold - 20A. */ + msr.hi |= (1 << (62 - 32)); /* Enable PSI4 */ + /* Leave the max instantaneous current limit (12:0) to default. */ + wrmsr(MSR_VR_CURRENT_CONFIG, msr); + + /* Configure VR_MISC_CONFIG MSR. */ + msr = rdmsr(MSR_VR_MISC_CONFIG); + /* Set the IOUT_SLOPE scalar applied to dIout in U10.1.9 format. */ + msr.hi &= ~(0x3ff << (40 - 32)); + msr.hi |= (0x200 << (40 - 32)); /* 1.0 */ + /* Set IOUT_OFFSET to 0. */ + msr.hi &= ~0xff; + /* Set exit ramp rate to fast. */ + msr.hi |= (1 << (50 - 32)); + /* Set entry ramp rate to slow. */ + msr.hi &= ~(1 << (51 - 32)); + /* Enable decay mode on C-state entry. */ + msr.hi |= (1 << (52 - 32)); + /* Set the slow ramp rate to be fast ramp rate / 4 */ + msr.hi &= ~(0x3 << (53 - 32)); + msr.hi |= (0x01 << (53 - 32)); + /* Set MIN_VID (31:24) to allow CPU to have full control. */ + msr.lo &= ~0xff000000; + wrmsr(MSR_VR_MISC_CONFIG, msr); + + /* Configure VR_MISC_CONFIG2 MSR. */ + msr = rdmsr(MSR_VR_MISC_CONFIG2); + msr.lo &= ~0xffff; + /* Allow CPU to control minimum voltage completely (15:8) and + * set the fast ramp voltage in 10mV steps. */ + if (cpu_family_model() == BROADWELL_FAMILY_ULT) + msr.lo |= 0x006a; /* 1.56V */ + else + msr.lo |= 0x006f; /* 1.60V */ + wrmsr(MSR_VR_MISC_CONFIG2, msr); +} + +static void configure_pch_power_sharing(void) +{ + u32 pch_power, pch_power_ext, pmsync, pmsync2; + int i; + + /* Read PCH Power levels from PCODE */ + pch_power = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER); + pch_power_ext = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT); + + printk(BIOS_INFO, "PCH Power: PCODE Levels 0x%08x 0x%08x\n", + pch_power, pch_power_ext); + + pmsync = RCBA32(PMSYNC_CONFIG); + pmsync2 = RCBA32(PMSYNC_CONFIG2); + + /* Program PMSYNC_TPR_CONFIG PCH power limit values + * pmsync[0:4] = mailbox[0:5] + * pmsync[8:12] = mailbox[6:11] + * pmsync[16:20] = mailbox[12:17] + */ + for (i = 0; i < 3; i++) { + u32 level = pch_power & 0x3f; + pch_power >>= 6; + pmsync &= ~(0x1f << (i * 8)); + pmsync |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG) = pmsync; + + /* Program PMSYNC_TPR_CONFIG2 Extended PCH power limit values + * pmsync2[0:4] = mailbox[23:18] + * pmsync2[8:12] = mailbox_ext[6:11] + * pmsync2[16:20] = mailbox_ext[12:17] + * pmsync2[24:28] = mailbox_ext[18:22] + */ + pmsync2 &= ~0x1f; + pmsync2 |= pch_power & 0x1f; + + for (i = 1; i < 4; i++) { + u32 level = pch_power_ext & 0x3f; + pch_power_ext >>= 6; + pmsync2 &= ~(0x1f << (i * 8)); + pmsync2 |= (level & 0x1f) << (i * 8); + } + RCBA32(PMSYNC_CONFIG2) = pmsync2; +} + +int cpu_config_tdp_levels(void) +{ + msr_t platform_info; + + /* Bits 34:33 indicate how many levels supported */ + platform_info = rdmsr(MSR_PLATFORM_INFO); + return (platform_info.hi >> 1) & 3; +} + +/* + * Configure processor power limits if possible + * This must be done AFTER set of BIOS_RESET_CPL + */ +void set_power_limits(u8 power_limit_1_time) +{ + msr_t msr = rdmsr(MSR_PLATFORM_INFO); + msr_t limit; + unsigned power_unit; + unsigned tdp, min_power, max_power, max_time; + u8 power_limit_1_val; + + if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr)) + power_limit_1_time = 28; + + if (!(msr.lo & PLATFORM_INFO_SET_TDP)) + return; + + /* Get units */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 2 << ((msr.lo & 0xf) - 1); + + /* Get power defaults for this SKU */ + msr = rdmsr(MSR_PKG_POWER_SKU); + tdp = msr.lo & 0x7fff; + min_power = (msr.lo >> 16) & 0x7fff; + max_power = msr.hi & 0x7fff; + max_time = (msr.hi >> 16) & 0x7f; + + printk(BIOS_DEBUG, "CPU TDP: %u Watts\n", tdp / power_unit); + + if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time) + power_limit_1_time = power_limit_time_msr_to_sec[max_time]; + + if (min_power > 0 && tdp < min_power) + tdp = min_power; + + if (max_power > 0 && tdp > max_power) + tdp = max_power; + + power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time]; + + /* Set long term power limit to TDP */ + limit.lo = 0; + limit.lo |= tdp & PKG_POWER_LIMIT_MASK; + limit.lo |= PKG_POWER_LIMIT_EN; + limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) << + PKG_POWER_LIMIT_TIME_SHIFT; + + /* Set short term power limit to 1.25 * TDP */ + limit.hi = 0; + limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK; + limit.hi |= PKG_POWER_LIMIT_EN; + /* Power limit 2 time is only programmable on server SKU */ + + wrmsr(MSR_PKG_POWER_LIMIT, limit); + + /* Set power limit values in MCHBAR as well */ + MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo; + MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi; + + /* Set DDR RAPL power limit by copying from MMIO to MSR */ + msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO); + msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI); + wrmsr(MSR_DDR_RAPL_LIMIT, msr); + + /* Use nominal TDP values for CPUs with configurable TDP */ + if (cpu_config_tdp_levels()) { + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + limit.hi = 0; + limit.lo = msr.lo & 0xff; + wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit); + } +} + +static void configure_c_states(void) +{ + msr_t msr; + + msr = rdmsr(MSR_PMG_CST_CONFIG_CONTROL); + msr.lo |= (1 << 31); // Timed MWAIT Enable + msr.lo |= (1 << 30); // Package c-state Undemotion Enable + msr.lo |= (1 << 29); // Package c-state Demotion Enable + msr.lo |= (1 << 28); // C1 Auto Undemotion Enable + msr.lo |= (1 << 27); // C3 Auto Undemotion Enable + msr.lo |= (1 << 26); // C1 Auto Demotion Enable + msr.lo |= (1 << 25); // C3 Auto Demotion Enable + msr.lo &= ~(1 << 10); // Disable IO MWAIT redirection + /* The deepest package c-state defaults to factory-configured value. */ + wrmsr(MSR_PMG_CST_CONFIG_CONTROL, msr); + + msr = rdmsr(MSR_MISC_PWR_MGMT); + msr.lo &= ~(1 << 0); // Enable P-state HW_ALL coordination + wrmsr(MSR_MISC_PWR_MGMT, msr); + + msr = rdmsr(MSR_POWER_CTL); + msr.lo |= (1 << 18); // Enable Energy Perf Bias MSR 0x1b0 + msr.lo |= (1 << 1); // C1E Enable + msr.lo |= (1 << 0); // Bi-directional PROCHOT# + wrmsr(MSR_POWER_CTL, msr); + + /* C-state Interrupt Response Latency Control 0 - package C3 latency */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_0, msr); + + /* C-state Interrupt Response Latency Control 1 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_1, msr); + + /* C-state Interrupt Response Latency Control 2 - package C6/C7 short */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr); + + /* C-state Interrupt Response Latency Control 3 - package C8 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_3_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr); + + /* C-state Interrupt Response Latency Control 4 - package C9 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_4_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr); + + /* C-state Interrupt Response Latency Control 5 - package C10 */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | + C_STATE_LATENCY_CONTROL_5_LIMIT; + wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr); +} + +static void configure_thermal_target(void) +{ + device_t dev = SA_DEV_ROOT; + config_t *conf = dev->chip_info; + msr_t msr; + + /* Set TCC activaiton offset if supported */ + msr = rdmsr(MSR_PLATFORM_INFO); + if ((msr.lo & (1 << 30)) && conf->tcc_offset) { + msr = rdmsr(MSR_TEMPERATURE_TARGET); + msr.lo &= ~(0xf << 24); /* Bits 27:24 */ + msr.lo |= (conf->tcc_offset & 0xf) << 24; + wrmsr(MSR_TEMPERATURE_TARGET, msr); + } +} + +static void configure_misc(void) +{ + msr_t msr; + + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= (1 << 0); /* Fast String enable */ + msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */ + msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */ + wrmsr(IA32_MISC_ENABLE, msr); + + /* Disable Thermal interrupts */ + msr.lo = 0; + msr.hi = 0; + wrmsr(IA32_THERM_INTERRUPT, msr); + + /* Enable package critical interrupt only */ + msr.lo = 1 << 4; + msr.hi = 0; + wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr); +} + +static void enable_lapic_tpr(void) +{ + msr_t msr; + + msr = rdmsr(MSR_PIC_MSG_CONTROL); + msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */ + wrmsr(MSR_PIC_MSG_CONTROL, msr); +} + +static void configure_dca_cap(void) +{ + struct cpuid_result cpuid_regs; + msr_t msr; + + /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */ + cpuid_regs = cpuid(1); + if (cpuid_regs.ecx & (1 << 18)) { + msr = rdmsr(IA32_PLATFORM_DCA_CAP); + msr.lo |= 1; + wrmsr(IA32_PLATFORM_DCA_CAP, msr); + } +} + +static void set_max_ratio(void) +{ + msr_t msr, perf_ctl; + + perf_ctl.hi = 0; + + /* Check for configurable TDP option */ + if (get_turbo_state() == TURBO_ENABLED) { + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else if (cpu_config_tdp_levels()) { + /* Set to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = rdmsr(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + wrmsr(IA32_PERF_CTL, perf_ctl); + + printk(BIOS_DEBUG, "cpu: frequency set to %d\n", + ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); +} + +static void set_energy_perf_bias(u8 policy) +{ + msr_t msr; + int ecx; + + /* Determine if energy efficient policy is supported. */ + ecx = cpuid_ecx(0x6); + if (!(ecx & (1 << 3))) + return; + + /* Energy Policy is bits 3:0 */ + msr = rdmsr(IA32_ENERGY_PERFORMANCE_BIAS); + msr.lo &= ~0xf; + msr.lo |= policy & 0xf; + wrmsr(IA32_ENERGY_PERFORMANCE_BIAS, msr); + + printk(BIOS_DEBUG, "cpu: energy policy set to %u\n", policy); +} + +static void configure_mca(void) +{ + msr_t msr; + const unsigned int mcg_cap_msr = 0x179; + int i; + int num_banks; + + msr = rdmsr(mcg_cap_msr); + num_banks = msr.lo & 0xff; + msr.lo = msr.hi = 0; + /* TODO(adurbin): This should only be done on a cold boot. Also, some + * of these banks are core vs package scope. For now every CPU clears + * every bank. */ + for (i = 0; i < num_banks; i++) + wrmsr(IA32_MC0_STATUS + (i * 4), msr); +} + +#if CONFIG_USBDEBUG +static unsigned ehci_debug_addr; +#endif + +static void bsp_init_before_ap_bringup(struct bus *cpu_bus) +{ +#if CONFIG_USBDEBUG + if(!ehci_debug_addr) + ehci_debug_addr = get_ehci_debug(); + set_ehci_debug(0); +#endif + + /* Setup MTRRs based on physical address size. */ + x86_setup_fixed_mtrrs(); + x86_setup_var_mtrrs(cpuid_eax(0x80000008) & 0xff, 2); + x86_mtrr_check(); + +#if CONFIG_USBDEBUG + set_ehci_debug(ehci_debug_addr); +#endif + + initialize_vr_config(); + calibrate_24mhz_bclk(); + configure_pch_power_sharing(); +} + +/* All CPUs including BSP will run the following function. */ +static void cpu_core_init(device_t cpu) +{ + /* Clear out pending MCEs */ + configure_mca(); + + /* Enable the local cpu apics */ + enable_lapic_tpr(); + setup_lapic(); + + /* Configure C States */ + configure_c_states(); + + /* Configure Enhanced SpeedStep and Thermal Sensors */ + configure_misc(); + + /* Thermal throttle activation offset */ + configure_thermal_target(); + + /* Enable Direct Cache Access */ + configure_dca_cap(); + + /* Set energy policy */ + set_energy_perf_bias(ENERGY_POLICY_NORMAL); + + /* Enable Turbo */ + enable_turbo(); +} + +/* MP initialization support. */ +static const void *microcode_patch; +int ht_disabled; + +static int adjust_apic_id_ht_disabled(int index, int apic_id) +{ + return 2 * index; +} + +static void relocate_and_load_microcode(void *unused) +{ + /* Relocate the SMM handler. */ + smm_relocate(); + + /* After SMM relocation a 2nd microcode load is required. */ + intel_microcode_load_unlocked(microcode_patch); +} + +static void enable_smis(void *unused) +{ + /* Now that all APs have been relocated as well as the BSP let SMIs + * start flowing. */ + southbridge_smm_enable_smi(); + + /* Lock down the SMRAM space. */ + smm_lock(); +} + +static struct mp_flight_record mp_steps[] = { + MP_FR_NOBLOCK_APS(relocate_and_load_microcode, NULL, + relocate_and_load_microcode, NULL), + MP_FR_BLOCK_APS(mp_initialize_cpu, NULL, mp_initialize_cpu, NULL), + /* Wait for APs to finish initialization before proceeding. */ + MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), +}; + +static struct device_operations cpu_dev_ops = { + .init = cpu_core_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_INTEL, CPUID_HASWELL_ULT }, + { X86_VENDOR_INTEL, CPUID_BROADWELL_C0 }, + { X86_VENDOR_INTEL, CPUID_BROADWELL_D0 }, + { X86_VENDOR_INTEL, CPUID_BROADWELL_E0 }, + { 0, 0 }, +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; + +void broadwell_init_cpus(device_t dev) +{ + struct bus *cpu_bus = dev->link_list; + int num_threads; + int num_cores; + msr_t msr; + struct mp_params mp_params; + void *smm_save_area; + + msr = rdmsr(CORE_THREAD_COUNT_MSR); + num_threads = (msr.lo >> 0) & 0xffff; + num_cores = (msr.lo >> 16) & 0xffff; + printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", + num_cores, num_threads); + + ht_disabled = num_threads == num_cores; + + /* Perform any necesarry BSP initialization before APs are brought up. + * This call alos allows the BSP to prepare for any secondary effects + * from calling cpu_initialize() such as smm_init(). */ + bsp_init_before_ap_bringup(cpu_bus); + + microcode_patch = intel_microcode_find(); + + /* Save default SMM area before relocation occurs. */ + smm_save_area = backup_default_smm_area(); + + mp_params.num_cpus = num_threads; + mp_params.parallel_microcode_load = 1; + if (ht_disabled) + mp_params.adjust_apic_id = adjust_apic_id_ht_disabled; + else + mp_params.adjust_apic_id = NULL; + mp_params.flight_plan = &mp_steps[0]; + mp_params.num_records = ARRAY_SIZE(mp_steps); + mp_params.microcode_pointer = microcode_patch; + + /* Load relocation and permeanent handlers. Then initiate relocation. */ + if (smm_initialize()) + printk(BIOS_CRIT, "SMM Initialiazation failed...\n"); + + if (mp_init(cpu_bus, &mp_params)) { + printk(BIOS_ERR, "MP initialization failure.\n"); + } + + /* Set Max Ratio */ + set_max_ratio(); + + /* Restore the default SMM region. */ + restore_default_smm_area(smm_save_area); + + /* Enable ROM caching if option was selected. */ + x86_mtrr_enable_rom_caching(); +} diff --git a/src/soc/intel/broadwell/cpu_info.c b/src/soc/intel/broadwell/cpu_info.c new file mode 100644 index 0000000000..7e9ad9710d --- /dev/null +++ b/src/soc/intel/broadwell/cpu_info.c @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +u32 cpu_family_model(void) +{ + return cpuid_eax(1) & 0x0fff0ff0; +} + +u32 cpu_stepping(void) +{ + return cpuid_eax(1) & 0xf; +} + +/* Dynamically determine if the part is ULT. */ +int cpu_is_ult(void) +{ + static int ult = -1; + + if (ult < 0) { + u32 fm = cpu_family_model(); + if (fm == BROADWELL_FAMILY_ULT || fm == HASWELL_FAMILY_ULT) + ult = 1; + else + ult = 0; + } + + return ult; +} diff --git a/src/soc/intel/broadwell/ehci.c b/src/soc/intel/broadwell/ehci.c new file mode 100644 index 0000000000..f50c7ba221 --- /dev/null +++ b/src/soc/intel/broadwell/ehci.c @@ -0,0 +1,104 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + u8 access_cntl; + + access_cntl = pci_read_config8(dev, 0x80); + + /* Enable writes to protected registers. */ + pci_write_config8(dev, 0x80, access_cntl | 1); + + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + } + + /* Restore protection. */ + pci_write_config8(dev, 0x80, access_cntl); +} + +static void usb_ehci_set_resources(struct device *dev) +{ +#if CONFIG_USBDEBUG + struct resource *res; + u32 base; + u32 usb_debug; + + usb_debug = get_ehci_debug(); + set_ehci_debug(0); +#endif + pci_dev_set_resources(dev); + +#if CONFIG_USBDEBUG + res = find_resource(dev, 0x10); + set_ehci_debug(usb_debug); + if (!res) return; + base = res->base; + set_ehci_base(base); + report_resource_stored(dev, res, ""); +#endif +} + +static void ehci_enable(struct device *dev) +{ + if (CONFIG_USBDEBUG) + dev->enabled = 1; + else + pch_disable_devfn(dev); +} + +static struct pci_operations ehci_ops_pci = { + .set_subsystem = &usb_ehci_set_subsystem, +}; + +static struct device_operations usb_ehci_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &usb_ehci_set_resources, + .enable_resources = &pci_dev_enable_resources, + .ops_pci = &ehci_ops_pci, + .enable = &ehci_enable, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c26, /* LynxPoint-LP */ + 0x9ca6, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_usb_ehci __pci_driver = { + .ops = &usb_ehci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/elog.c b/src/soc/intel/broadwell/elog.c new file mode 100644 index 0000000000..af76db1ee6 --- /dev/null +++ b/src/soc/intel/broadwell/elog.c @@ -0,0 +1,143 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start) +{ + int i; + + gpe0_sts &= gpe0_en; + + for (i = 0; i <= 31; i++) { + if (gpe0_sts & (1 << i)) + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start); + } +} + +static void pch_log_wake_source(struct chipset_power_state *ps) +{ + /* Power Button */ + if (ps->pm1_sts & PWRBTN_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0); + + /* RTC */ + if (ps->pm1_sts & RTC_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0); + + /* PCI Express (TODO: determine wake device) */ + if (ps->pm1_sts & PCIEXPWAK_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0); + + /* PME (TODO: determine wake device) */ + if (ps->gpe0_sts[GPE_STD] & PME_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); + + /* Internal PME (TODO: determine wake device) */ + if (ps->gpe0_sts[GPE_STD] & PME_B0_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); + + /* SMBUS Wake */ + if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0); + + /* GPIO27 */ + if (ps->gpe0_sts[GPE_STD] & GP27_STS) + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, 27); + + /* Log GPIO events in set 1-3 */ + pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0); + pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32); + pch_log_gpio_gpe(ps->gpe0_sts[GPE_94_64], ps->gpe0_en[GPE_94_64], 64); +} + +static void pch_log_power_and_resets(struct chipset_power_state *ps) +{ + /* Thermal Trip Status */ + if (ps->gen_pmcon2 & THERMTRIP_STS) + elog_add_event(ELOG_TYPE_THERM_TRIP); + + /* PWR_FLR Power Failure */ + if (ps->gen_pmcon2 & PWROK_FLR) + elog_add_event(ELOG_TYPE_POWER_FAIL); + + /* SUS Well Power Failure */ + if (ps->gen_pmcon3 & SUS_PWR_FLR) + elog_add_event(ELOG_TYPE_SUS_POWER_FAIL); + + /* SYS_PWROK Failure */ + if (ps->gen_pmcon2 & SYSPWR_FLR) + elog_add_event(ELOG_TYPE_SYS_PWROK_FAIL); + + /* PWROK Failure */ + if (ps->gen_pmcon2 & PWROK_FLR) + elog_add_event(ELOG_TYPE_PWROK_FAIL); + + /* TCO Timeout */ + if (ps->prev_sleep_state != 3 && + ps->tco2_sts & TCO2_STS_SECOND_TO) + elog_add_event(ELOG_TYPE_TCO_RESET); + + /* Power Button Override */ + if (ps->pm1_sts & PRBTNOR_STS) + elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE); + + /* RTC reset */ + if (ps->gen_pmcon3 & RTC_BATTERY_DEAD) + elog_add_event(ELOG_TYPE_RTC_RESET); + + /* System Reset Status (reset button pushed) */ + if (ps->gen_pmcon2 & SYSTEM_RESET_STS) + elog_add_event(ELOG_TYPE_RESET_BUTTON); + + /* General Reset Status */ + if (ps->gen_pmcon3 & GEN_RST_STS) + elog_add_event(ELOG_TYPE_SYSTEM_RESET); + + /* ACPI Wake Event */ + if (ps->prev_sleep_state != SLEEP_STATE_S0) + elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state); +} + +static void pch_log_state(void *unused) +{ + struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE); + + if (ps == NULL) { + printk(BIOS_ERR, "Not logging power state information. " + "Power state not found in cbmem.\n"); + return; + } + + /* Power and Reset */ + pch_log_power_and_resets(ps); + + /* Wake Sources */ + pch_log_wake_source(ps); +} + +BOOT_STATE_INIT_ENTRIES(pch_log) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, pch_log_state, NULL) +}; diff --git a/src/soc/intel/broadwell/finalize.c b/src/soc/intel/broadwell/finalize.c new file mode 100644 index 0000000000..96ffbdc80d --- /dev/null +++ b/src/soc/intel/broadwell/finalize.c @@ -0,0 +1,127 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct reg_script system_agent_finalize_script[] = { + REG_PCI_OR16(0x50, 1 << 0), /* GGC */ + REG_PCI_OR32(0x5c, 1 << 0), /* DPR */ + REG_PCI_OR32(0x78, 1 << 10), /* ME */ + REG_PCI_OR32(0x90, 1 << 0), /* REMAPBASE */ + REG_PCI_OR32(0x98, 1 << 0), /* REMAPLIMIT */ + REG_PCI_OR32(0xa0, 1 << 0), /* TOM */ + REG_PCI_OR32(0xa8, 1 << 0), /* TOUUD */ + REG_PCI_OR32(0xb0, 1 << 0), /* BDSM */ + REG_PCI_OR32(0xb4, 1 << 0), /* BGSM */ + REG_PCI_OR32(0xb8, 1 << 0), /* TSEGMB */ + REG_PCI_OR32(0xbc, 1 << 0), /* TOLUD */ + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x5500, 1 << 0), /* PAVP */ + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x5f00, 1 << 31), /* SA PM */ + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x6020, 1 << 0), /* UMA GFX */ + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x63fc, 1 << 0), /* VTDTRK */ + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x6800, 1 << 31), + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x7000, 1 << 31), + REG_MMIO_OR32(MCH_BASE_ADDRESS + 0x77fc, 1 << 0), + REG_MMIO_WRITE8(MCH_BASE_ADDRESS + 0x50fc, 0x8f), /* MC */ + + REG_SCRIPT_END +}; + +const struct reg_script pch_finalize_script[] = { + /* Set SPI opcode menu */ + REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_PREOP, + SPI_OPPREFIX), + REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_OPTYPE, + SPI_OPTYPE), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + + SPIBAR_OPMENU_LOWER, SPI_OPMENU_LOWER), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + + SPIBAR_OPMENU_UPPER, SPI_OPMENU_UPPER), + + /* Lock SPIBAR */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + SPIBAR_OFFSET + SPIBAR_HSFS, + SPIBAR_HSFS_FLOCKDN), + + /* TC Lockdown */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x0050, (1 << 31)), + + /* BIOS Interface Lockdown */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + GCS, (1 << 0)), + + /* Function Disable SUS Well Lockdown */ + REG_MMIO_OR8(RCBA_BASE_ADDRESS + FDSW, (1 << 7)), + + /* Global SMI Lock */ + REG_PCI_OR16(GEN_PMCON_1, SMI_LOCK), + + /* GEN_PMCON Lock */ + REG_PCI_OR8(GEN_PMCON_LOCK, SLP_STR_POL_LOCK | ACPI_BASE_LOCK), + + /* PMSYNC */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + PMSYNC_CONFIG, (1 << 31)), + + + REG_SCRIPT_END +}; + +static void broadwell_finalize(void *unused) +{ + printk(BIOS_DEBUG, "Finalizing chipset.\n"); + + reg_script_run_on_dev(SA_DEV_ROOT, system_agent_finalize_script); + reg_script_run_on_dev(PCH_DEV_LPC, pch_finalize_script); + + /* Lock */ + RCBA32_OR(0x3a6c, 0x00000001); + + /* Read+Write the following registers */ + MCHBAR32(0x6030) = MCHBAR32(0x6030); + MCHBAR32(0x6034) = MCHBAR32(0x6034); + MCHBAR32(0x6008) = MCHBAR32(0x6008); + RCBA32(0x21a4) = RCBA32(0x21a4); + + /* Re-init SPI after lockdown */ + spi_init(); + + printk(BIOS_DEBUG, "Finalizing SMM.\n"); + outb(APM_CNT_FINALIZE, APM_CNT); + + /* Indicate finalize step with post code */ + post_code(POST_OS_BOOT); +} + +BOOT_STATE_INIT_ENTRIES(finalize) = { + BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, + broadwell_finalize, NULL), + BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, + broadwell_finalize, NULL), +}; diff --git a/src/soc/intel/broadwell/gpio.c b/src/soc/intel/broadwell/gpio.c new file mode 100644 index 0000000000..dc7d71371c --- /dev/null +++ b/src/soc/intel/broadwell/gpio.c @@ -0,0 +1,199 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This function will return a number that indicates which PIRQ + * this GPIO maps to. If this is not a PIRQ capable GPIO then + * it will return -1. The GPIO to PIRQ mapping is not linear. + */ +static int gpio_to_pirq(int gpio) +{ + switch (gpio) { + case 8: return 0; /* PIRQI */ + case 9: return 1; /* PIRQJ */ + case 10: return 2; /* PIRQK */ + case 13: return 3; /* PIRQL */ + case 14: return 4; /* PIRQM */ + case 45: return 5; /* PIRQN */ + case 46: return 6; /* PIRQO */ + case 47: return 7; /* PIRQP */ + case 48: return 8; /* PIRQQ */ + case 49: return 9; /* PIRQR */ + case 50: return 10; /* PIRQS */ + case 51: return 11; /* PIRQT */ + case 52: return 12; /* PIRQU */ + case 53: return 13; /* PIRQV */ + case 54: return 14; /* PIRQW */ + case 55: return 15; /* PIRQX */ + default: return -1; + }; +} + +void init_one_gpio(int gpio_num, struct gpio_config *config) +{ + u32 owner, route, irqen, reset; + int set, bit; + + if (gpio_num > MAX_GPIO_NUMBER || !config) + return; + + outl(config->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)); + outl(config->conf1, GPIO_BASE_ADDRESS + GPIO_CONFIG1(gpio_num)); + + /* Determine set and bit based on GPIO number */ + set = gpio_num >> 5; + bit = gpio_num % 32; + + /* Save settings from current GPIO config */ + owner = inl(GPIO_BASE_ADDRESS + GPIO_OWNER(set)); + route = inl(GPIO_BASE_ADDRESS + GPIO_ROUTE(set)); + irqen = inl(GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set)); + reset = inl(GPIO_BASE_ADDRESS + GPIO_RESET(set)); + + owner |= config->owner << bit; + route |= config->route << bit; + irqen |= config->irqen << bit; + reset |= config->reset << bit; + + outl(owner, GPIO_BASE_ADDRESS + GPIO_OWNER(set)); + outl(route, GPIO_BASE_ADDRESS + GPIO_ROUTE(set)); + outl(irqen, GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set)); + outl(reset, GPIO_BASE_ADDRESS + GPIO_RESET(set)); + + if (set == 0) { + u32 blink = inl(GPIO_BASE_ADDRESS + GPIO_BLINK); + blink |= config->blink << bit; + outl(blink, GPIO_BASE_ADDRESS + GPIO_BLINK); + } + + /* PIRQ to IO-APIC map */ + if (config->pirq == GPIO_PIRQ_APIC_ROUTE) { + u32 pirq2apic = inl(GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN); + set = gpio_to_pirq(gpio_num); + if (set >= 0) { + pirq2apic |= 1 << set; + outl(pirq2apic, GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN); + } + } +} + +void init_gpios(const struct gpio_config config[]) +{ + const struct gpio_config *entry; + u32 owner[3] = {0}; + u32 route[3] = {0}; + u32 irqen[3] = {0}; + u32 reset[3] = {0}; + u32 blink = 0; + u16 pirq2apic = 0; + int set, bit, gpio = 0; + + for (entry = config; entry->conf0 != GPIO_LIST_END; entry++, gpio++) { + if (gpio > MAX_GPIO_NUMBER) + break; + + /* Setup Configuration registers 1 and 2 */ + outl(entry->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio)); + outl(entry->conf1, GPIO_BASE_ADDRESS + GPIO_CONFIG1(gpio)); + + /* Determine set and bit based on GPIO number */ + set = gpio >> 5; + bit = gpio % 32; + + /* Apply settings to set specific bits */ + owner[set] |= entry->owner << bit; + route[set] |= entry->route << bit; + irqen[set] |= entry->irqen << bit; + reset[set] |= entry->reset << bit; + + if (set == 0) + blink |= entry->blink << bit; + + /* PIRQ to IO-APIC map */ + if (entry->pirq == GPIO_PIRQ_APIC_ROUTE) { + set = gpio_to_pirq(gpio); + if (set >= 0) + pirq2apic |= 1 << set; + } + } + + for (set = 0; set <= 2; set++) { + outl(owner[set], GPIO_BASE_ADDRESS + GPIO_OWNER(set)); + outl(route[set], GPIO_BASE_ADDRESS + GPIO_ROUTE(set)); + outl(irqen[set], GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set)); + outl(reset[set], GPIO_BASE_ADDRESS + GPIO_RESET(set)); + } + + outl(blink, GPIO_BASE_ADDRESS + GPIO_BLINK); + outl(pirq2apic, GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN); +} + +int get_gpio(int gpio_num) +{ + if (gpio_num > MAX_GPIO_NUMBER) + return 0; + + return !!(inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)) & GPI_LEVEL); +} + +/* + * get a number comprised of multiple GPIO values. gpio_num_array points to + * the array of gpio pin numbers to scan, terminated by -1. + */ +unsigned get_gpios(const int *gpio_num_array) +{ + int gpio; + unsigned bitmask = 1; + unsigned vector = 0; + + while (bitmask && + ((gpio = *gpio_num_array++) != -1)) { + if (get_gpio(gpio)) + vector |= bitmask; + bitmask <<= 1; + } + return vector; +} + +void set_gpio(int gpio_num, int value) +{ + u32 conf0; + + if (gpio_num > MAX_GPIO_NUMBER) + return; + + conf0 = inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)); + conf0 &= ~GPO_LEVEL_MASK; + conf0 |= value << GPO_LEVEL_SHIFT; + outl(conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)); +} + +int gpio_is_native(int gpio_num) +{ + return !(inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)) & 1); +} diff --git a/src/soc/intel/broadwell/hda.c b/src/soc/intel/broadwell/hda.c new file mode 100644 index 0000000000..b705e96f6e --- /dev/null +++ b/src/soc/intel/broadwell/hda.c @@ -0,0 +1,181 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const u32 * cim_verb_data = NULL; +u32 cim_verb_data_size = 0; +const u32 * pc_beep_verbs = NULL; +u32 pc_beep_verbs_size = 0; + +static void codecs_init(u32 base, u32 codec_mask) +{ + int i; + + /* Can support up to 4 codecs */ + for (i = 3; i >= 0; i--) { + if (codec_mask & (1 << i)) + hda_codec_init(base, i, + cim_verb_data_size, + cim_verb_data); + } + + if (pc_beep_verbs_size && pc_beep_verbs) + hda_codec_write(base, pc_beep_verbs_size, pc_beep_verbs); +} + +static void hda_pch_init(struct device *dev, u32 base) +{ + u8 reg8; + u16 reg16; + u32 reg32; + + if (RCBA32(0x2030) & (1 << 31)) { + reg32 = pci_read_config32(dev, 0x120); + reg32 &= 0xf8ffff01; + reg32 |= (1 << 25); + reg32 |= RCBA32(0x2030) & 0xfe; + pci_write_config32(dev, 0x120, reg32); + } else + printk(BIOS_DEBUG, "HDA: V1CTL disabled.\n"); + + reg32 = pci_read_config32(dev, 0x114); + reg32 &= ~0xfe; + pci_write_config32(dev, 0x114, reg32); + + // Set VCi enable bit + if (pci_read_config32(dev, 0x120) & ((1 << 24) | + (1 << 25) | (1 << 26))) { + reg32 = pci_read_config32(dev, 0x120); + reg32 &= ~(1 << 31); + pci_write_config32(dev, 0x120, reg32); + } + + /* Additional programming steps */ + reg32 = pci_read_config32(dev, 0xc4); + reg32 |= (1 << 24); + pci_write_config32(dev, 0xc4, reg32); + + reg8 = pci_read_config8(dev, 0x40); // Audio Control + reg8 |= 1; // Select HDA mode + pci_write_config8(dev, 0x40, reg8); + + reg8 = pci_read_config8(dev, 0x4d); // Docking Status + reg8 &= ~(1 << 7); // Docking not supported + pci_write_config8(dev, 0x4d, reg8); + + reg16 = read32(base + 0x0012); + reg16 |= (1 << 0); + write32(base + 0x0012, reg16); + + /* disable Auto Voltage Detector */ + reg8 = pci_read_config8(dev, 0x42); + reg8 |= (1 << 2); + pci_write_config8(dev, 0x42, reg8); +} + +static void hda_init(struct device *dev) +{ + u32 base; + struct resource *res; + u32 codec_mask; + u32 reg32; + + /* Find base address */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "HDA: base = %08x\n", (u32)base); + + /* Set Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER); + + hda_pch_init(dev, base); + + codec_mask = hda_codec_detect(base); + + if (codec_mask) { + printk(BIOS_DEBUG, "HDA: codec_mask = %02x\n", codec_mask); + codecs_init(base, codec_mask); + } +} + +static void hda_enable(struct device *dev) +{ + u32 reg32; + u8 reg8; + + reg8 = pci_read_config8(dev, 0x43); + reg8 |= 0x6f; + pci_write_config8(dev, 0x43, reg8); + + if (!dev->enabled) { + /* Route I/O buffers to ADSP function */ + reg8 = pci_read_config8(dev, 0x42); + reg8 |= (1 << 7) | (1 << 6); + pci_write_config8(dev, 0x42, reg8); + + printk(BIOS_INFO, "HDA disabled, I/O buffers routed to ADSP\n"); + + /* Ensure memory, io, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Disable this device */ + pch_disable_devfn(dev); + } +} + +static struct device_operations hda_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &hda_init, + .enable = &hda_enable, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c20, /* LynxPoint-LP */ + 0x9ca0, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_hda __pci_driver = { + .ops = &hda_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/igd.c b/src/soc/intel/broadwell/igd.c new file mode 100644 index 0000000000..0999cc1467 --- /dev/null +++ b/src/soc/intel/broadwell/igd.c @@ -0,0 +1,597 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GT_RETRY 1000 +#define GT_CDCLK_337 0 +#define GT_CDCLK_450 1 +#define GT_CDCLK_540 2 +#define GT_CDCLK_675 3 + +struct reg_script haswell_early_init_script[] = { + /* Enable Force Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x00000020), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010001), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130044, 1, 1, GT_RETRY), + + /* Enable Counters */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa248, 0x00000016), + + /* GFXPAUSE settings */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa000, 0x00070020), + + /* ECO Settings */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0xa180, 0xff3fffff, 0x15000000), + + /* Enable DOP Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x000003fd), + + /* Enable Unit Level Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0x00000080), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0x40401000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0x00000000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0x02000001), + + /* + * RC6 Settings + */ + + /* Wake Rate Limits */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa090, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa098, 0x03e80000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa09c, 0x00280000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0a8, 0x0001e848), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0ac, 0x00000019), + + /* Render/Video/Blitter Idle Max Count */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x02054, 0x0000000a), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000a), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000a), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1a054, 0x0000000a), + + /* RC Sleep / RCx Thresholds */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b0, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b4, 0x000003e8), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa0b8, 0x0000c350), + + /* RP Settings */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa010, 0x000f4240), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa014, 0x12060000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa02c, 0x0000e808), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa030, 0x0003bd08), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa068, 0x000101d0), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa06c, 0x00055730), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0xa070, 0x0000000a), + + /* RP Control */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000b92), + + /* HW RC6 Control */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x88040000), + + /* Video Frequency Request */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa00c, 0x08000000), + + /* Set RC6 VIDs */ + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138128, 0), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138124, 0x80000004), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY), + + /* Enable PM Interrupts */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076), + + /* Enable RC6 in idle */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa094, 0x00040000), + + REG_SCRIPT_END +}; + +static const struct reg_script haswell_late_init_script[] = { + /* Lock settings */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a248, (1 << 31)), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a004, (1 << 4)), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a080, (1 << 2)), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a180, (1 << 31)), + + /* Disable Force Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130044, 1, 0, GT_RETRY), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00000001), + + /* Enable power well for DP and Audio */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x45400, (1 << 31)), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x45400, + (1 << 30), (1 << 30), GT_RETRY), + + REG_SCRIPT_END +}; + +static const struct reg_script broadwell_early_init_script[] = { + /* Enable Force Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010001), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130044, 1, 1, GT_RETRY), + + /* Enable push bus metric control and shift */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa248, 0x00000004), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa250, 0x000000ff), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa25c, 0x00000010), + + /* GFXPAUSE settings (set based on stepping) */ + + /* ECO Settings */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa180, 0x45200000), + + /* Enable DOP Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9424, 0x000000fd), + + /* Enable Unit Level Clock Gating */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9400, 0x00000000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9404, 0x40401000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x9408, 0x00000000), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x940c, 0x02000001), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x1a054, 0x0000000a), + + /* Video Frequency Request */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa00c, 0x08000000), + + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138158, 0x00000009), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x13815c, 0x0000000d), + + /* + * RC6 Settings + */ + + /* Wake Rate Limits */ + REG_RES_RMW32(PCI_BASE_ADDRESS_0, 0x0a090, 0, 0), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a098, 0x03e80000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a09c, 0x00280000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0a8, 0x0001e848), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0ac, 0x00000019), + + /* Render/Video/Blitter Idle Max Count */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x02054, 0x0000000a), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x12054, 0x0000000a), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x22054, 0x0000000a), + + /* RC Sleep / RCx Thresholds */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0b0, 0x00000000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a0b8, 0x00000271), + + /* RP Settings */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a010, 0x000f4240), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a014, 0x12060000), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a02c, 0x0000e808), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a030, 0x0003bd08), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a068, 0x000101d0), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a06c, 0x00055730), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a070, 0x0000000a), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a168, 0x00000006), + + /* RP Control */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa024, 0x00000b92), + + /* HW RC6 Control */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa090, 0x90040000), + + /* Set RC6 VIDs */ + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138128, 0), + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x138124, 0x80000004), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x138124, (1 << 31), 0, GT_RETRY), + + /* Enable PM Interrupts */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x4402c, 0x03000076), + + /* Enable RC6 in idle */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa094, 0x00040000), + + REG_SCRIPT_END +}; + +static const struct reg_script broadwell_late_init_script[] = { + /* Lock settings */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a248, (1 << 31)), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a000, (1 << 18)), + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x0a180, (1 << 31)), + + /* Disable Force Wake */ + REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0xa188, 0x00010000), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x130044, 1, 0, GT_RETRY), + + /* Enable power well for DP and Audio */ + REG_RES_OR32(PCI_BASE_ADDRESS_0, 0x45400, (1 << 31)), + REG_RES_POLL32(PCI_BASE_ADDRESS_0, 0x45400, + (1 << 30), (1 << 30), GT_RETRY), + + REG_SCRIPT_END +}; + +u32 map_oprom_vendev(u32 vendev) +{ + return SA_IGD_OPROM_VENDEV; +} + +static struct resource *gtt_res = NULL; + +static unsigned long gtt_read(unsigned long reg) +{ + u32 val; + val = read32(gtt_res->base + reg); + return val; + +} + +static void gtt_write(unsigned long reg, unsigned long data) +{ + write32(gtt_res->base + reg, data); +} + +static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask) +{ + u32 val = gtt_read(reg); + val &= andmask; + val |= ormask; + gtt_write(reg, val); +} + +static int gtt_poll(u32 reg, u32 mask, u32 value) +{ + unsigned try = GT_RETRY; + u32 data; + + while (try--) { + data = gtt_read(reg); + if ((data & mask) == value) + return 1; + udelay(10); + } + + printk(BIOS_ERR, "GT init timeout\n"); + return 0; +} + +static void igd_setup_panel(struct device *dev) +{ + config_t *conf = dev->chip_info; + u32 reg32; + + /* Setup Digital Port Hotplug */ + reg32 = gtt_read(PCH_PORT_HOTPLUG); + if (!reg32) { + reg32 = (conf->gpu_dp_b_hotplug & 0x7) << 2; + reg32 |= (conf->gpu_dp_c_hotplug & 0x7) << 10; + reg32 |= (conf->gpu_dp_d_hotplug & 0x7) << 18; + gtt_write(PCH_PORT_HOTPLUG, reg32); + } + + /* Setup Panel Power On Delays */ + reg32 = gtt_read(PCH_PP_ON_DELAYS); + if (!reg32) { + reg32 = (conf->gpu_panel_port_select & 0x3) << 30; + reg32 |= (conf->gpu_panel_power_up_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff); + gtt_write(PCH_PP_ON_DELAYS, reg32); + } + + /* Setup Panel Power Off Delays */ + reg32 = gtt_read(PCH_PP_OFF_DELAYS); + if (!reg32) { + reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff); + gtt_write(PCH_PP_OFF_DELAYS, reg32); + } + + /* Setup Panel Power Cycle Delay */ + if (conf->gpu_panel_power_cycle_delay) { + reg32 = gtt_read(PCH_PP_DIVISOR); + reg32 &= ~0xff; + reg32 |= conf->gpu_panel_power_cycle_delay & 0xff; + gtt_write(PCH_PP_DIVISOR, reg32); + } + + /* Enable Backlight if needed */ + if (conf->gpu_cpu_backlight) { + gtt_write(BLC_PWM_CPU_CTL2, BLC_PWM2_ENABLE); + gtt_write(BLC_PWM_CPU_CTL, conf->gpu_cpu_backlight); + } + if (conf->gpu_pch_backlight) { + gtt_write(BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE); + gtt_write(BLC_PWM_PCH_CTL2, conf->gpu_pch_backlight); + } +} + +static void igd_cdclk_init_haswell(struct device *dev) +{ + config_t *conf = dev->chip_info; + int cdclk = conf->cdclk; + int devid = pci_read_config16(dev, PCI_DEVICE_ID); + int gpu_is_ulx = 0; + u32 dpdiv, lpcll; + + /* Check for ULX GT1 or GT2 */ + if (devid == 0x0a0e || devid == 0x0a1e) + gpu_is_ulx = 1; + + /* 675MHz is not supported on haswell */ + if (cdclk == GT_CDCLK_675) + cdclk = GT_CDCLK_337; + + /* If CD clock is fixed or ULT then set to 450MHz */ + if ((gtt_read(0x42014) & 0x1000000) || cpu_is_ult()) + cdclk = GT_CDCLK_450; + + /* 540MHz is not supported on ULX */ + if (gpu_is_ulx && cdclk == GT_CDCLK_540) + cdclk = GT_CDCLK_337; + + /* 337.5MHz is not supported on non-ULT/ULX */ + if (!gpu_is_ulx && !cpu_is_ult() && cdclk == GT_CDCLK_337) + cdclk = GT_CDCLK_450; + + /* Set variables based on CD Clock setting */ + switch (cdclk) { + case GT_CDCLK_337: + dpdiv = 169; + lpcll = (1 << 26); + break; + case GT_CDCLK_450: + dpdiv = 225; + lpcll = 0; + break; + case GT_CDCLK_540: + dpdiv = 270; + lpcll = (1 << 26); + break; + default: + return; + } + + /* Set LPCLL_CTL CD Clock Frequency Select */ + gtt_rmw(0x130040, 0xf3ffffff, lpcll); + + /* ULX: Inform power controller of selected frequency */ + if (gpu_is_ulx) { + if (cdclk == GT_CDCLK_450) + gtt_write(0x138128, 0x00000000); /* 450MHz */ + else + gtt_write(0x138128, 0x00000001); /* 337.5MHz */ + gtt_write(0x13812c, 0x00000000); + gtt_write(0x138124, 0x80000017); + } + + /* Set CPU DP AUX 2X bit clock dividers */ + gtt_rmw(0x64010, 0xfffff800, dpdiv); + gtt_rmw(0x64810, 0xfffff800, dpdiv); +} + +static void igd_cdclk_init_broadwell(struct device *dev) +{ + config_t *conf = dev->chip_info; + int cdclk = conf->cdclk; + u32 dpdiv, lpcll, pwctl, cdset; + + /* Inform power controller of upcoming frequency change */ + gtt_write(0x138128, 0); + gtt_write(0x13812c, 0); + gtt_write(0x138124, 0x80000018); + + /* Poll GT driver mailbox for run/busy clear */ + if (!gtt_poll(0x138124, (1 << 31), (0 << 31))) + cdclk = GT_CDCLK_450; + + if (gtt_read(0x42014) & 0x1000000) { + /* If CD clock is fixed then set to 450MHz */ + cdclk = GT_CDCLK_450; + } else { + /* Program CD clock to highest supported freq */ + if (cpu_is_ult()) + cdclk = GT_CDCLK_540; + else + cdclk = GT_CDCLK_675; + } + + /* CD clock frequency 675MHz not supported on ULT */ + if (cpu_is_ult() && cdclk == GT_CDCLK_675) + cdclk = GT_CDCLK_540; + + /* Set variables based on CD Clock setting */ + switch (cdclk) { + case GT_CDCLK_337: + cdset = 337; + lpcll = (1 << 27); + pwctl = 2; + dpdiv = 169; + break; + case GT_CDCLK_450: + cdset = 449; + lpcll = 0; + pwctl = 0; + dpdiv = 225; + break; + case GT_CDCLK_540: + cdset = 539; + lpcll = (1 << 26); + pwctl = 1; + dpdiv = 270; + break; + case GT_CDCLK_675: + cdset = 674; + lpcll = (1 << 26) | (1 << 27); + pwctl = 3; + dpdiv = 338; + default: + return; + } + + /* Set LPCLL_CTL CD Clock Frequency Select */ + gtt_rmw(0x130040, 0xf3ffffff, lpcll); + + /* Inform power controller of selected frequency */ + gtt_write(0x138128, pwctl); + gtt_write(0x13812c, 0); + gtt_write(0x138124, 0x80000017); + + /* Program CD Clock Frequency */ + gtt_rmw(0x46200, 0xfffffc00, cdset); + + /* Set CPU DP AUX 2X bit clock dividers */ + gtt_rmw(0x64010, 0xfffff800, dpdiv); + gtt_rmw(0x64810, 0xfffff800, dpdiv); +} + +static void igd_init(struct device *dev) +{ + int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT); + u32 rp1_gfx_freq; + + /* IGD needs to be Bus Master */ + u32 reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + pci_write_config32(dev, PCI_COMMAND, reg32); + + gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!gtt_res || !gtt_res->base) + return; + + /* Wait for any configured pre-graphics delay */ +#if IS_ENABLED(CONFIG_CHROMEOS) + if (developer_mode_enabled() || recovery_mode_enabled() || + vboot_wants_oprom()) + mdelay(CONFIG_PRE_GRAPHICS_DELAY); +#else + mdelay(CONFIG_PRE_GRAPHICS_DELAY); +#endif + + /* Early init steps */ + if (is_broadwell) { + reg_script_run_on_dev(dev, broadwell_early_init_script); + + /* Set GFXPAUSE based on stepping */ + if (cpu_stepping() <= (CPUID_BROADWELL_E0 & 0xf) && + systemagent_revision() <= 9) { + gtt_write(0xa000, 0x300ff); + } else { + gtt_write(0xa000, 0x30020); + } + } else { + reg_script_run_on_dev(dev, haswell_early_init_script); + } + + /* Set RP1 graphics frequency */ + rp1_gfx_freq = (MCHBAR32(0x5998) >> 8) & 0xff; + gtt_write(0xa008, rp1_gfx_freq << 24); + + /* Post VBIOS panel setup */ + igd_setup_panel(dev); + + /* Initialize PCI device, load/execute BIOS Option ROM */ + pci_dev_init(dev); + + /* Late init steps */ + if (is_broadwell) { + igd_cdclk_init_broadwell(dev); + reg_script_run_on_dev(dev, broadwell_late_init_script); + } else { + igd_cdclk_init_haswell(dev); + reg_script_run_on_dev(dev, haswell_late_init_script); + } + + if (oprom_is_loaded) { + /* + * Work around VBIOS issue that is not clearing first 64 + * bytes of the framebuffer during VBE mode set. + */ + struct resource *fb = find_resource(dev, PCI_BASE_ADDRESS_2); + memset((void *)((u32)fb->base), 0, 64); + } + + if (!oprom_is_loaded && acpi_slp_type != 3) { + /* + * Enable DDI-A if the Option ROM did not execute: + * + * bit 0: Display detected (RO) + * bit 4: DDI A supports 4 lanes and DDI E is not used + * bit 7: DDI buffer is idle + */ + gtt_write(DDI_BUF_CTL_A, DDI_BUF_IS_IDLE | DDI_A_4_LANES | + DDI_INIT_DISPLAY_DETECTED); + } +} + +static void igd_read_resources(struct device *dev) +{ + pci_dev_read_resources(dev); + +#if CONFIG_MARK_GRAPHICS_MEM_WRCOMB + struct resource *res; + + /* Set the graphics memory to write combining. */ + res = find_resource(dev, PCI_BASE_ADDRESS_2); + if (res == NULL) { + printk(BIOS_DEBUG, "gma: memory resource not found.\n"); + return; + } + res->flags |= IORESOURCE_WRCOMB; +#endif +} + +static struct device_operations igd_ops = { + .read_resources = &igd_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &igd_init, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + IGD_HASWELL_ULT_GT1, + IGD_HASWELL_ULT_GT2, + IGD_HASWELL_ULT_GT3, + IGD_BROADWELL_U_GT1, + IGD_BROADWELL_U_GT2, + IGD_BROADWELL_U_GT3_15W, + IGD_BROADWELL_U_GT3_28W, + IGD_BROADWELL_Y_GT2, + IGD_BROADWELL_H_GT2, + IGD_BROADWELL_H_GT3, + 0, +}; + +static const struct pci_driver igd_driver __pci_driver = { + .ops = &igd_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/include/chipset_fsp_util.h b/src/soc/intel/broadwell/include/chipset_fsp_util.h new file mode 100644 index 0000000000..4eac4c496f --- /dev/null +++ b/src/soc/intel/broadwell/include/chipset_fsp_util.h @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CHIPSET_FSP_UTIL_H + +#define CHIPSET_FSP_UTIL_H + +/* + * Include the FSP binary interface files + * + * These files include the necessary UEFI constants and data structures + * that are used to interface to the FSP binary. + */ + +#include /* UEFI data types */ +#include /* FSP API definitions */ +#include /* FSP binary layout */ +#include /* UEFI boot mode definitions */ +#include /* UEFI file definitions */ +#include /* UEFI file system defs */ +#include /* UEFI memory types */ +#include /* Hand off block definitions */ +#include /* HOB routine declarations */ +#include /* Vital/updatable product data definitions*/ + +#endif /* CHIPSET_FSP_UTIL_H */ diff --git a/src/soc/intel/broadwell/include/soc/acpi.h b/src/soc/intel/broadwell/include/soc/acpi.h new file mode 100644 index 0000000000..2b1e77eea0 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/acpi.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_ACPI_H_ +#define _BROADWELL_ACPI_H_ + +#include +#include + +/* P-state configuration */ +#define PSS_MAX_ENTRIES 8 +#define PSS_RATIO_STEP 2 +#define PSS_LATENCY_TRANSITION 10 +#define PSS_LATENCY_BUSMASTER 10 + +void acpi_create_intel_hpet(acpi_hpet_t *hpet); +void acpi_fill_in_fadt(acpi_fadt_t *fadt); +unsigned long acpi_madt_irq_overrides(unsigned long current); +void acpi_init_gnvs(global_nvs_t *gnvs); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/adsp.h b/src/soc/intel/broadwell/include/soc/adsp.h new file mode 100644 index 0000000000..747a123579 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/adsp.h @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_ADSP_H_ +#define _BROADWELL_ADSP_H_ + +#define ADSP_PCI_IRQ 23 +#define ADSP_ACPI_IRQ 3 +#define ADSP_ACPI_IRQEN (1 << 3) + +#define ADSP_SHIM_BASE_LPT 0xe7000 +#define ADSP_SHIM_BASE_WPT 0xfb000 +#define ADSP_SHIM_LTRC 0xe0 +#define ADSP_SHIM_LTRC_VALUE 0x3003 +#define ADSP_SHIM_IMC 0x28 +#define ADSP_SHIM_IPCD 0x40 + +#define ADSP_PCI_VDRTCTL0 0xa0 +#define ADSP_VDRTCTL0_D3PGD_LPT (1 << 1) +#define ADSP_VDRTCTL0_D3PGD_WPT (1 << 0) +#define ADSP_VDRTCTL0_D3SRAMPGD_LPT (1 << 2) +#define ADSP_VDRTCTL0_D3SRAMPGD_WPT (1 << 1) +#define ADSP_PCI_VDRTCTL1 0xa4 +#define ADSP_PCI_VDRTCTL2 0xa8 +#define ADSP_VDRTCTL2_VALUE 0x00000fff + +#define ADSP_IOBP_VDLDAT1 0xd7000624 +#define ADSP_VDLDAT1_VALUE 0x00040100 +#define ADSP_IOBP_VDLDAT2 0xd7000628 +#define ADSP_IOBP_ACPI_IRQ3 0xd9d8 +#define ADSP_IOBP_ACPI_IRQ3I 0xd8d9 +#define ADSP_IOBP_ACPI_IRQ4 0xdbda +#define ADSP_IOBP_PMCTL 0xd70001e0 +#define ADSP_PMCTL_VALUE 0x3f +#define ADSP_IOBP_PCICFGCTL 0xd7000500 +#define ADSP_PCICFGCTL_PCICD (1 << 0) +#define ADSP_PCICFGCTL_ACPIIE (1 << 1) +#define ADSP_PCICFGCTL_SPCBAD (1 << 7) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/cpu.h b/src/soc/intel/broadwell/include/soc/cpu.h new file mode 100644 index 0000000000..312532d68a --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/cpu.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_CPU_H_ +#define _BROADWELL_CPU_H_ + +#include +#include + +/* CPU types */ +#define HASWELL_FAMILY_ULT 0x40650 +#define BROADWELL_FAMILY_ULT 0x306d0 + +/* Supported CPUIDs */ +#define CPUID_HASWELL_A0 0x306c1 +#define CPUID_HASWELL_B0 0x306c2 +#define CPUID_HASWELL_C0 0x306c3 +#define CPUID_HASWELL_ULT_B0 0x40650 +#define CPUID_HASWELL_ULT 0x40651 +#define CPUID_HASWELL_HALO 0x40661 +#define CPUID_BROADWELL_C0 0x306d2 +#define CPUID_BROADWELL_D0 0x306d3 +#define CPUID_BROADWELL_E0 0x306d4 + +/* CPU bus clock is fixed at 100MHz */ +#define CPU_BCLK 100 + +/* Latency times in units of 1024ns. */ +#define C_STATE_LATENCY_CONTROL_0_LIMIT 0x42 +#define C_STATE_LATENCY_CONTROL_1_LIMIT 0x73 +#define C_STATE_LATENCY_CONTROL_2_LIMIT 0x91 +#define C_STATE_LATENCY_CONTROL_3_LIMIT 0xe4 +#define C_STATE_LATENCY_CONTROL_4_LIMIT 0x145 +#define C_STATE_LATENCY_CONTROL_5_LIMIT 0x1ef + +#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \ + (((1 << ((base)*5)) * (limit)) / 1000) +#define C_STATE_LATENCY_FROM_LAT_REG(reg) \ + C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \ + (IRTL_1024_NS >> 10)) + +/* Configure power limits for turbo mode */ +void set_power_limits(u8 power_limit_1_time); +int cpu_config_tdp_levels(void); + +/* + * Determine if HyperThreading is disabled. + * The variable is not valid until setup_ap_init() has been called. + */ +extern int ht_disabled; + +/* CPU identification */ +u32 cpu_family_model(void); +u32 cpu_stepping(void); +int cpu_is_ult(void); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/device_nvs.h b/src/soc/intel/broadwell/include/soc/device_nvs.h new file mode 100644 index 0000000000..7dab40da6a --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/device_nvs.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_DEVICE_NVS_H_ +#define _BROADWELL_DEVICE_NVS_H_ + +#include + +/* Offset in Global NVS where this structure lives */ +#define DEVICE_NVS_OFFSET 0x1000 + +#define SIO_NVS_DMA 0 +#define SIO_NVS_I2C0 1 +#define SIO_NVS_I2C1 2 +#define SIO_NVS_SPI0 3 +#define SIO_NVS_SPI1 4 +#define SIO_NVS_UART0 5 +#define SIO_NVS_UART1 6 +#define SIO_NVS_SDIO 7 +#define SIO_NVS_ADSP 8 + +typedef struct { + u8 enable[9]; + u32 bar0[9]; + u32 bar1[9]; +} __attribute__((packed)) device_nvs_t; + +#endif diff --git a/src/soc/intel/broadwell/include/soc/ehci.h b/src/soc/intel/broadwell/include/soc/ehci.h new file mode 100644 index 0000000000..44d51ef311 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/ehci.h @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_EHCI_H_ +#define _BROADWELL_EHCI_H_ + +/* EHCI Memory Registers */ +#define EHCI_USB_CMD 0x20 +#define EHCI_USB_CMD_RUN (1 << 0) +#define EHCI_USB_CMD_PSE (1 << 4) +#define EHCI_USB_CMD_ASE (1 << 5) +#define EHCI_PORTSC(port) (0x64 + (port * 4)) +#define EHCI_PORTSC_ENABLED (1 << 2) +#define EHCI_PORTSC_SUSPEND (1 << 7) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/gpio.h b/src/soc/intel/broadwell/include/soc/gpio.h new file mode 100644 index 0000000000..a0359755d2 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/gpio.h @@ -0,0 +1,192 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_GPIO_H_ +#define _BROADWELL_GPIO_H_ + +#include + +/* PCH-LP GPIOBASE Registers */ +#define GPIO_OWNER(set) (0x00 + ((set) * 4)) +#define GPIO_PIRQ_APIC_EN 0x10 +#define GPIO_BLINK 0x18 +#define GPIO_SER_BLINK 0x1c +#define GPIO_SER_BLINK_CS 0x20 +#define GPIO_SER_BLINK_DATA 0x24 +#define GPIO_ROUTE(set) (0x30 + ((set) * 4)) +#define GPIO_ALT_GPI_SMI_STS 0x50 +#define GPIO_ALT_GPI_SMI_EN 0x54 +#define GPIO_RESET(set) (0x60 + ((set) * 4)) +#define GPIO_GLOBAL_CONFIG 0x7c +#define GPIO_IRQ_IS(set) (0x80 + ((set) * 4)) +#define GPIO_IRQ_IE(set) (0x90 + ((set) * 4)) +#define GPIO_CONFIG0(gpio) (0x100 + ((gpio) * 8)) +#define GPIO_CONFIG1(gpio) (0x104 + ((gpio) * 8)) + +#define MAX_GPIO_NUMBER 94 /* zero based */ +#define GPIO_LIST_END 0xffffffff + +/* conf0 */ + +#define GPIO_MODE_NATIVE (0 << 0) +#define GPIO_MODE_GPIO (1 << 0) + +#define GPIO_DIR_OUTPUT (0 << 2) +#define GPIO_DIR_INPUT (1 << 2) + +#define GPIO_NO_INVERT (0 << 3) +#define GPIO_INVERT (1 << 3) + +#define GPIO_IRQ_EDGE (0 << 4) +#define GPIO_IRQ_LEVEL (1 << 4) + +#define GPI_LEVEL (1 << 30) + +#define GPIO_OUT_LOW 0 +#define GPIO_OUT_HIGH 1 +#define GPO_LEVEL_SHIFT 31 +#define GPO_LEVEL_MASK (1 << GPO_LEVEL_SHIFT) +#define GPO_LEVEL_LOW (GPIO_OUT_LOW << GPO_LEVEL_SHIFT) +#define GPO_LEVEL_HIGH (GPIO_OUT_HIGH << GPO_LEVEL_SHIFT) + +/* conf1 */ + +#define GPIO_PULL_NONE (0 << 0) +#define GPIO_PULL_DOWN (1 << 0) +#define GPIO_PULL_UP (2 << 0) + +#define GPIO_SENSE_ENABLE (0 << 2) +#define GPIO_SENSE_DISABLE (1 << 2) + +/* owner */ + +#define GPIO_OWNER_ACPI 0 +#define GPIO_OWNER_GPIO 1 + +/* route */ + +#define GPIO_ROUTE_SCI 0 +#define GPIO_ROUTE_SMI 1 + +/* irqen */ + +#define GPIO_IRQ_DISABLE 0 +#define GPIO_IRQ_ENABLE 1 + +/* blink */ + +#define GPO_NO_BLINK 0 +#define GPO_BLINK 1 + +/* reset */ + +#define GPIO_RESET_PWROK 0 +#define GPIO_RESET_RSMRST 1 + +/* pirq route to io-apic */ + +#define GPIO_PIRQ_APIC_MASK 0 +#define GPIO_PIRQ_APIC_ROUTE 1 + +#define PCH_GPIO_END \ + { .conf0 = GPIO_LIST_END } + +#define PCH_GPIO_NATIVE \ + { .conf0 = GPIO_MODE_NATIVE } + +#define PCH_GPIO_UNUSED \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + +#define PCH_GPIO_ACPI_SCI \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_ACPI, \ + .route = GPIO_ROUTE_SCI } + +#define PCH_GPIO_ACPI_SMI \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_ACPI, \ + .route = GPIO_ROUTE_SMI } + +#define PCH_GPIO_INPUT \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO } + +#define PCH_GPIO_INPUT_INVERT \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_GPIO } + +#define PCH_GPIO_IRQ_EDGE \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, \ + .owner = GPIO_OWNER_GPIO, \ + .irqen = GPIO_IRQ_ENABLE } + +#define PCH_GPIO_IRQ_LEVEL \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_LEVEL, \ + .owner = GPIO_OWNER_GPIO, \ + .irqen = GPIO_IRQ_ENABLE } + +#define PCH_GPIO_PIRQ \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO, \ + .pirq = GPIO_PIRQ_APIC_ROUTE } + +#define PCH_GPIO_OUT_HIGH \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + +#define PCH_GPIO_OUT_LOW \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + +struct gpio_config { + u8 gpio; + u32 conf0; + u32 conf1; + u8 owner; + u8 route; + u8 irqen; + u8 reset; + u8 blink; + u8 pirq; +} __attribute__ ((packed)); + +/* Configure GPIOs with mainboard provided settings */ +void init_one_gpio(int gpio_num, struct gpio_config *config); +void init_gpios(const struct gpio_config config[]); + +/* Get GPIO pin value */ +int get_gpio(int gpio_num); + +/* Set GPIO pin value */ +void set_gpio(int gpio_num, int value); + +/* Return non-zero if gpio is set to native function. 0 otherwise. */ +int gpio_is_native(int gpio_num); + +/* + * Get a number comprised of multiple GPIO values. gpio_num_array points to + * the array of gpio pin numbers to scan, terminated by -1. + */ +unsigned get_gpios(const int *gpio_num_array); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/iobp.h b/src/soc/intel/broadwell/include/soc/iobp.h new file mode 100644 index 0000000000..9f17692508 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/iobp.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_IOBP_H_ +#define _BROADWELL_IOBP_H_ + +u32 pch_iobp_read(u32 address); +void pch_iobp_write(u32 address, u32 data); +void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue); +void pch_iobp_exec(u32 addr, u16 op_dcode, u8 route_id, u32 *data, u8 *resp); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/iomap.h b/src/soc/intel/broadwell/include/soc/iomap.h new file mode 100644 index 0000000000..bb98975d85 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/iomap.h @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_IOMAP_H_ +#define _BROADWELL_IOMAP_H_ + +#define MCFG_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS +#define MCFG_BASE_SIZE 0x4000000 + +#define MCH_BASE_ADDRESS 0xfed10000 +#define MCH_BASE_SIZE 0x8000 + +#define DMI_BASE_ADDRESS 0xfed18000 +#define DMI_BASE_SIZE 0x1000 + +#define EP_BASE_ADDRESS 0xfed19000 +#define EP_BASE_SIZE 0x1000 + +#define EDRAM_BASE_ADDRESS 0xfed80000 +#define EDRAM_BASE_SIZE 0x4000 + +#define GDXC_BASE_ADDRESS 0xfed84000 +#define GDXC_BASE_SIZE 0x1000 + +#define RCBA_BASE_ADDRESS 0xfed1c000 +#define RCBA_BASE_SIZE 0x4000 + +#define HPET_BASE_ADDRESS 0xfed00000 + +#define ACPI_BASE_ADDRESS 0x1000 +#define ACPI_BASE_SIZE 0x100 + +#define GPIO_BASE_ADDRESS 0x1400 +#define GPIO_BASE_SIZE 0x400 + +#define SMBUS_BASE_ADDRESS 0x0400 +#define SMBUS_BASE_SIZE 0x10 + +/* Temporary addresses used in romstage */ +#define EARLY_GTT_BAR 0xe0000000 +#define EARLY_XHCI_BAR 0xd7000000 +#define EARLY_EHCI_BAR CONFIG_EHCI_BAR +#define EARLY_UART_BAR CONFIG_TTYS0_BASE +#define EARLY_TEMP_MMIO 0xfed08000 + +#endif diff --git a/src/soc/intel/broadwell/include/soc/lpc.h b/src/soc/intel/broadwell/include/soc/lpc.h new file mode 100644 index 0000000000..180e527c9e --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/lpc.h @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_LPC_H_ +#define _BROADWELL_LPC_H_ + +/* PCI Configuration Space (D31:F0): LPC */ +#define SERIRQ_CNTL 0x64 +#define PMBASE 0x40 +#define ACPI_CNTL 0x44 +#define ACPI_EN (1 << 7) +#define SCI_IRQ_SEL (7 << 0) +#define SCIS_IRQ9 0 +#define SCIS_IRQ10 1 +#define SCIS_IRQ11 2 +#define SCIS_IRQ20 4 +#define SCIS_IRQ21 5 +#define SCIS_IRQ22 6 +#define SCIS_IRQ23 7 +#define GPIOBASE 0x48 +#define BIOS_CNTL 0xdc +#define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ +#define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ +#define GPIO_EN (1 << 4) +#define GPIO_ROUT 0xb8 + +#define PIRQA_ROUT 0x60 +#define PIRQB_ROUT 0x61 +#define PIRQC_ROUT 0x62 +#define PIRQD_ROUT 0x63 +#define PIRQE_ROUT 0x68 +#define PIRQF_ROUT 0x69 +#define PIRQG_ROUT 0x6A +#define PIRQH_ROUT 0x6B + +#define LPC_IO_DEC 0x80 /* IO Decode Ranges Register */ +#define LPC_EN 0x82 /* LPC IF Enables Register */ +#define CNF2_LPC_EN (1 << 13) /* 0x4e/0x4f */ +#define CNF1_LPC_EN (1 << 12) /* 0x2e/0x2f */ +#define MC_LPC_EN (1 << 11) /* 0x62/0x66 */ +#define KBC_LPC_EN (1 << 10) /* 0x60/0x64 */ +#define GAMEH_LPC_EN (1 << 9) /* 0x208/0x20f */ +#define GAMEL_LPC_EN (1 << 8) /* 0x200/0x207 */ +#define FDD_LPC_EN (1 << 3) /* LPC_IO_DEC[12] */ +#define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */ +#define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */ +#define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[2:0] */ +#define LPC_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */ +#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */ +#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */ +#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ +#define LGMR 0x98 /* LPC Generic Memory Range */ +#define RCBA 0xf0 /* Root Complex Register Block */ + +/* Power Management */ + +#define GEN_PMCON_1 0xa0 +#define SMI_LOCK (1 << 4) +#define GEN_PMCON_2 0xa2 +#define SYSTEM_RESET_STS (1 << 4) +#define THERMTRIP_STS (1 << 3) +#define SYSPWR_FLR (1 << 1) +#define PWROK_FLR (1 << 0) +#define GEN_PMCON_3 0xa4 +#define SUS_PWR_FLR (1 << 14) +#define GEN_RST_STS (1 << 9) +#define RTC_BATTERY_DEAD (1 << 2) +#define PWR_FLR (1 << 1) +#define SLEEP_AFTER_POWER_FAIL (1 << 0) +#define GEN_PMCON_LOCK 0xa6 +#define SLP_STR_POL_LOCK (1 << 2) +#define ACPI_BASE_LOCK (1 << 1) +#define PMIR 0xac +#define PMIR_CF9LOCK (1 << 31) +#define PMIR_CF9GR (1 << 20) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/me.h b/src/soc/intel/broadwell/include/soc/me.h new file mode 100644 index 0000000000..3973fc85bf --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/me.h @@ -0,0 +1,507 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_ME_H_ +#define _BROADWELL_ME_H_ + +#include + +#define ME_RETRY 100000 /* 1 second */ +#define ME_DELAY 10 /* 10 us */ + +/* + * Management Engine PCI registers + */ + +#define PCI_CPU_MEBASE_L 0x70 /* Set by MRC */ +#define PCI_CPU_MEBASE_H 0x74 /* Set by MRC */ + +#define PCI_ME_HFS 0x40 +#define ME_HFS_CWS_RESET 0 +#define ME_HFS_CWS_INIT 1 +#define ME_HFS_CWS_REC 2 +#define ME_HFS_CWS_NORMAL 5 +#define ME_HFS_CWS_WAIT 6 +#define ME_HFS_CWS_TRANS 7 +#define ME_HFS_CWS_INVALID 8 +#define ME_HFS_STATE_PREBOOT 0 +#define ME_HFS_STATE_M0_UMA 1 +#define ME_HFS_STATE_M3 4 +#define ME_HFS_STATE_M0 5 +#define ME_HFS_STATE_BRINGUP 6 +#define ME_HFS_STATE_ERROR 7 +#define ME_HFS_ERROR_NONE 0 +#define ME_HFS_ERROR_UNCAT 1 +#define ME_HFS_ERROR_IMAGE 3 +#define ME_HFS_ERROR_DEBUG 4 +#define ME_HFS_MODE_NORMAL 0 +#define ME_HFS_MODE_DEBUG 2 +#define ME_HFS_MODE_DIS 3 +#define ME_HFS_MODE_OVER_JMPR 4 +#define ME_HFS_MODE_OVER_MEI 5 +#define ME_HFS_BIOS_DRAM_ACK 1 +#define ME_HFS_ACK_NO_DID 0 +#define ME_HFS_ACK_RESET 1 +#define ME_HFS_ACK_PWR_CYCLE 2 +#define ME_HFS_ACK_S3 3 +#define ME_HFS_ACK_S4 4 +#define ME_HFS_ACK_S5 5 +#define ME_HFS_ACK_GBL_RESET 6 +#define ME_HFS_ACK_CONTINUE 7 + +struct me_hfs { + u32 working_state: 4; + u32 mfg_mode: 1; + u32 fpt_bad: 1; + u32 operation_state: 3; + u32 fw_init_complete: 1; + u32 ft_bup_ld_flr: 1; + u32 update_in_progress: 1; + u32 error_code: 4; + u32 operation_mode: 4; + u32 reserved: 4; + u32 boot_options_present: 1; + u32 ack_data: 3; + u32 bios_msg_ack: 4; +} __attribute__ ((packed)); + +#define PCI_ME_UMA 0x44 + +struct me_uma { + u32 size: 6; + u32 reserved_1: 10; + u32 valid: 1; + u32 reserved_0: 14; + u32 set_to_one: 1; +} __attribute__ ((packed)); + +#define PCI_ME_H_GS 0x4c +#define ME_INIT_DONE 1 +#define ME_INIT_STATUS_SUCCESS 0 +#define ME_INIT_STATUS_NOMEM 1 +#define ME_INIT_STATUS_ERROR 2 +#define ME_INIT_STATUS_SUCCESS_OTHER 3 /* SEE ME9 BWG */ + +#define ME_HSIO_MESSAGE (7 << 28) +#define ME_HSIO_CMD_GETHSIOVER 1 +#define ME_HSIO_CMD_CLOSE 0 + +struct me_did { + u32 uma_base: 16; + u32 reserved: 7; + u32 rapid_start: 1; + u32 status: 4; + u32 init_done: 4; +} __attribute__ ((packed)); + +/* + * Apparently the GMES register is renamed to HFS2 (or HFSTS2 according + * to ME9 BWG). Sadly the PCH EDS and the ME BWG do not match on nomenclature. + */ +#define PCI_ME_HFS2 0x48 +/* Infrastructure Progress Values */ +#define ME_HFS2_PHASE_ROM 0 +#define ME_HFS2_PHASE_BUP 1 +#define ME_HFS2_PHASE_UKERNEL 2 +#define ME_HFS2_PHASE_POLICY 3 +#define ME_HFS2_PHASE_MODULE_LOAD 4 +#define ME_HFS2_PHASE_UNKNOWN 5 +#define ME_HFS2_PHASE_HOST_COMM 6 +/* Current State - Based on Infra Progress values. */ +/* ROM State */ +#define ME_HFS2_STATE_ROM_BEGIN 0 +#define ME_HFS2_STATE_ROM_DISABLE 6 +/* BUP State */ +#define ME_HFS2_STATE_BUP_INIT 0 +#define ME_HFS2_STATE_BUP_DIS_HOST_WAKE 1 +#define ME_HFS2_STATE_BUP_FLOW_DET 4 +#define ME_HFS2_STATE_BUP_VSCC_ERR 8 +#define ME_HFS2_STATE_BUP_CHECK_STRAP 0xa +#define ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT 0xb +#define ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP 0xd +#define ME_HFS2_STATE_BUP_M3 0x11 +#define ME_HFS2_STATE_BUP_M0 0x12 +#define ME_HFS2_STATE_BUP_FLOW_DET_ERR 0x13 +#define ME_HFS2_STATE_BUP_M3_CLK_ERR 0x15 +#define ME_HFS2_STATE_BUP_CPU_RESET_DID_TIMEOUT_MEM_MISSING 0x17 +#define ME_HFS2_STATE_BUP_M3_KERN_LOAD 0x18 +#define ME_HFS2_STATE_BUP_T32_MISSING 0x1c +#define ME_HFS2_STATE_BUP_WAIT_DID 0x1f +#define ME_HFS2_STATE_BUP_WAIT_DID_FAIL 0x20 +#define ME_HFS2_STATE_BUP_DID_NO_FAIL 0x21 +#define ME_HFS2_STATE_BUP_ENABLE_UMA 0x22 +#define ME_HFS2_STATE_BUP_ENABLE_UMA_ERR 0x23 +#define ME_HFS2_STATE_BUP_SEND_DID_ACK 0x24 +#define ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR 0x25 +#define ME_HFS2_STATE_BUP_M0_CLK 0x26 +#define ME_HFS2_STATE_BUP_M0_CLK_ERR 0x27 +#define ME_HFS2_STATE_BUP_TEMP_DIS 0x28 +#define ME_HFS2_STATE_BUP_M0_KERN_LOAD 0x32 +/* Policy Module State */ +#define ME_HFS2_STATE_POLICY_ENTRY 0 +#define ME_HFS2_STATE_POLICY_RCVD_S3 3 +#define ME_HFS2_STATE_POLICY_RCVD_S4 4 +#define ME_HFS2_STATE_POLICY_RCVD_S5 5 +#define ME_HFS2_STATE_POLICY_RCVD_UPD 6 +#define ME_HFS2_STATE_POLICY_RCVD_PCR 7 +#define ME_HFS2_STATE_POLICY_RCVD_NPCR 8 +#define ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE 9 +#define ME_HFS2_STATE_POLICY_RCVD_AC_DC 0xa +#define ME_HFS2_STATE_POLICY_RCVD_DID 0xb +#define ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND 0xc +#define ME_HFS2_STATE_POLICY_VSCC_INVALID 0xd +#define ME_HFS2_STATE_POLICY_FPB_ERR 0xe +#define ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR 0xf +#define ME_HFS2_STATE_POLICY_VSCC_NO_MATCH 0x10 +/* Current PM Event Values */ +#define ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE 0 +#define ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR 1 +#define ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET 2 +#define ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR 3 +#define ME_HFS2_PMEVENT_CLEAN_ME_RESET 4 +#define ME_HFS2_PMEVENT_ME_RESET_EXCEPTION 5 +#define ME_HFS2_PMEVENT_PSEUDO_ME_RESET 6 +#define ME_HFS2_PMEVENT_S0MO_SXM3 7 +#define ME_HFS2_PMEVENT_SXM3_S0M0 8 +#define ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET 9 +#define ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3 0xa +#define ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF 0xb +#define ME_HFS2_PMEVENT_SXMX_SXMOFF 0xc + +struct me_hfs2 { + u32 bist_in_progress: 1; + u32 reserved1: 2; + u32 invoke_mebx: 1; + u32 cpu_replaced_sts: 1; + u32 mbp_rdy: 1; + u32 mfs_failure: 1; + u32 warm_reset_request: 1; + u32 cpu_replaced_valid: 1; + u32 reserved2: 4; + u32 mbp_cleared: 1; + u32 reserved3: 2; + u32 current_state: 8; + u32 current_pmevent: 4; + u32 progress_code: 4; +} __attribute__ ((packed)); + +#define PCI_ME_HFS5 0x68 + +#define PCI_ME_H_GS2 0x70 +#define PCI_ME_MBP_GIVE_UP 0x01 + +#define PCI_ME_HERES 0xbc +#define PCI_ME_EXT_SHA1 0x00 +#define PCI_ME_EXT_SHA256 0x02 +#define PCI_ME_HER(x) (0xc0+(4*(x))) + +struct me_heres { + u32 extend_reg_algorithm: 4; + u32 reserved: 26; + u32 extend_feature_present: 1; + u32 extend_reg_valid: 1; +} __attribute__ ((packed)); + +/* + * Management Engine MEI registers + */ + +#define MEI_H_CB_WW 0x00 +#define MEI_H_CSR 0x04 +#define MEI_ME_CB_RW 0x08 +#define MEI_ME_CSR_HA 0x0c + +struct mei_csr { + u32 interrupt_enable: 1; + u32 interrupt_status: 1; + u32 interrupt_generate: 1; + u32 ready: 1; + u32 reset: 1; + u32 reserved: 3; + u32 buffer_read_ptr: 8; + u32 buffer_write_ptr: 8; + u32 buffer_depth: 8; +} __attribute__ ((packed)); + +#define MEI_ADDRESS_CORE 0x01 +#define MEI_ADDRESS_AMT 0x02 +#define MEI_ADDRESS_RESERVED 0x03 +#define MEI_ADDRESS_WDT 0x04 +#define MEI_ADDRESS_MKHI 0x07 +#define MEI_ADDRESS_ICC 0x08 +#define MEI_ADDRESS_THERMAL 0x09 + +#define MEI_HOST_ADDRESS 0 + +struct mei_header { + u32 client_address: 8; + u32 host_address: 8; + u32 length: 9; + u32 reserved: 6; + u32 is_complete: 1; +} __attribute__ ((packed)); + +#define MKHI_GROUP_ID_CBM 0x00 +#define MKHI_GLOBAL_RESET 0x0b +#define MKHI_GROUP_ID_FWCAPS 0x03 +#define MKHI_FWCAPS_GET_RULE 0x02 +#define MKHI_GROUP_ID_HMRFPO 0x05 +#define MKHI_HMRFPO_LOCK 0x02 +#define MKHI_HMRFPO_LOCK_NOACK 0x05 +#define MKHI_GROUP_ID_MDES 0x08 +#define MKHI_MDES_ENABLE 0x09 +#define MKHI_GROUP_ID_GEN 0xff +#define MKHI_GET_FW_VERSION 0x02 +#define MKHI_END_OF_POST 0x0c +#define MKHI_FEATURE_OVERRIDE 0x14 +#define MKHI_END_OF_POST_NOACK 0x1a + +struct mkhi_header { + u32 group_id: 8; + u32 command: 7; + u32 is_response: 1; + u32 reserved: 8; + u32 result: 8; +} __attribute__ ((packed)); + +struct me_fw_version { + u16 code_minor; + u16 code_major; + u16 code_build_number; + u16 code_hot_fix; + u16 recovery_minor; + u16 recovery_major; + u16 recovery_build_number; + u16 recovery_hot_fix; +} __attribute__ ((packed)); + +/* ICC Messages */ +#define ICC_SET_CLOCK_ENABLES 0x3 +#define ICC_API_VERSION_LYNXPOINT 0x00030000 + +struct icc_header { + u32 api_version; + u32 icc_command; + u32 icc_status; + u32 length; + u32 reserved; +} __attribute__ ((packed)); + +struct icc_clock_enables_msg { + u32 clock_enables; + u32 clock_mask; + u32 no_response: 1; + u32 reserved: 31; +} __attribute__ ((packed)); + +#define HECI_EOP_STATUS_SUCCESS 0x0 +#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1 + +#define CBM_RR_GLOBAL_RESET 0x01 + +#define GLOBAL_RESET_BIOS_MRC 0x01 +#define GLOBAL_RESET_BIOS_POST 0x02 +#define GLOBAL_RESET_MEBX 0x03 + +struct me_global_reset { + u8 request_origin; + u8 reset_type; +} __attribute__ ((packed)); + +typedef enum { + ME_NORMAL_BIOS_PATH, + ME_S3WAKE_BIOS_PATH, + ME_ERROR_BIOS_PATH, + ME_RECOVERY_BIOS_PATH, + ME_DISABLE_BIOS_PATH, + ME_FIRMWARE_UPDATE_BIOS_PATH, +} me_bios_path; + +/* + * ME to BIOS Payload Datastructures and definitions. The ordering of the + * structures follows the ordering in the ME9 BWG. + */ + +#define MBP_APPID_KERNEL 1 +#define MBP_APPID_INTEL_AT 3 +#define MBP_APPID_HWA 4 +#define MBP_APPID_ICC 5 +#define MBP_APPID_NFC 6 +/* Kernel items: */ +#define MBP_KERNEL_FW_VER_ITEM 1 +#define MBP_KERNEL_FW_CAP_ITEM 2 +#define MBP_KERNEL_ROM_BIST_ITEM 3 +#define MBP_KERNEL_PLAT_KEY_ITEM 4 +#define MBP_KERNEL_FW_TYPE_ITEM 5 +#define MBP_KERNEL_MFS_FAILURE_ITEM 6 +#define MBP_KERNEL_PLAT_TIME_ITEM 7 +/* Intel AT items: */ +#define MBP_INTEL_AT_STATE_ITEM 1 +/* ICC Items: */ +#define MBP_ICC_PROFILE_ITEM 1 +/* HWA Items: */ +#define MBP_HWA_REQUEST_ITEM 1 +/* NFC Items: */ +#define MBP_NFC_SUPPORT_DATA_ITEM 1 + +#define MBP_MAKE_IDENT(appid, item) ((appid << 8) | item) +#define MBP_IDENT(appid, item) \ + MBP_MAKE_IDENT(MBP_APPID_##appid, MBP_##appid##_##item##_ITEM) + +typedef struct { + u32 mbp_size : 8; + u32 num_entries : 8; + u32 rsvd : 16; +} __attribute__ ((packed)) mbp_header; + +typedef struct { + u32 app_id : 8; + u32 item_id : 8; + u32 length : 8; + u32 rsvd : 8; +} __attribute__ ((packed)) mbp_item_header; + +typedef struct { + u32 major_version : 16; + u32 minor_version : 16; + u32 hotfix_version : 16; + u32 build_version : 16; +} __attribute__ ((packed)) mbp_fw_version_name; + +typedef struct { + u32 full_net : 1; + u32 std_net : 1; + u32 manageability : 1; + u32 reserved_2 : 2; + u32 intel_at : 1; + u32 intel_cls : 1; + u32 reserved : 3; + u32 intel_mpc : 1; + u32 icc_over_clocking : 1; + u32 pavp : 1; + u32 reserved_1 : 4; + u32 ipv6 : 1; + u32 kvm : 1; + u32 och : 1; + u32 vlan : 1; + u32 tls : 1; + u32 reserved_4 : 1; + u32 wlan : 1; + u32 reserved_5 : 8; +} __attribute__ ((packed)) mbp_mefwcaps; + +typedef struct { + u16 device_id; + u16 fuse_test_flags; + u32 umchid[4]; +} __attribute__ ((packed)) mbp_rom_bist_data; + +typedef struct { + u32 key[8]; +} mbp_platform_key; + +typedef struct { + u32 mobile: 1; + u32 desktop: 1; + u32 server: 1; + u32 workstation: 1; + u32 corporate: 1; + u32 consumer: 1; + u32 regular_super_sku: 1; + u32 rsvd: 1; + u32 image_type: 4; + u32 brand: 4; + u32 rsvd1: 16; +} __attribute__ ((packed)) mbp_me_firmware_type; + +typedef struct { + mbp_me_firmware_type rule_data; + u8 available; +} mbp_plat_type; + +typedef struct { + u16 icc_start_address; + u16 mask; +} __attribute__ ((packed)) icc_address_mask; + +typedef struct { + u8 num_icc_profiles; + u8 icc_profile_soft_strap; + u8 icc_profile_index; + u8 reserved; + u32 icc_reg_bundles; + icc_address_mask icc_address_mask[0]; +} __attribute__ ((packed)) mbp_icc_profile; + +typedef struct { + u16 lock_state : 1; + u16 authenticate_module : 1; + u16 s3authentication : 1; + u16 flash_wear_out : 1; + u16 flash_variable_security : 1; + u16 reserved : 11; +} __attribute__ ((packed)) tdt_state_flag; + +typedef struct { + u8 state; + u8 last_theft_trigger; + tdt_state_flag flags; +} __attribute__ ((packed)) mbp_at_state; + +typedef struct { + u32 wake_event_mrst_time_ms; + u32 mrst_pltrst_time_ms; + u32 pltrst_cpurst_time_ms; +} __attribute__ ((packed)) mbp_plat_time; + +typedef struct { + u32 device_type : 2; + u32 reserved : 30; +} __attribute__ ((packed)) mbp_nfc_data; + +typedef struct { + mbp_fw_version_name *fw_version_name; + mbp_mefwcaps *fw_capabilities; + mbp_rom_bist_data *rom_bist_data; + mbp_platform_key *platform_key; + mbp_plat_type *fw_plat_type; + mbp_icc_profile *icc_profile; + mbp_at_state *at_state; + u32 *mfsintegrity; + mbp_plat_time *plat_time; + mbp_nfc_data *nfc_data; +} me_bios_payload; + +struct me_fwcaps { + u32 id; + u8 length; + mbp_mefwcaps caps_sku; + u8 reserved[3]; +} __attribute__ ((packed)); + +void intel_me_hsio_version(uint16_t *version, uint16_t *checksum); + +#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) +/* Defined in me_status.c for both romstage and ramstage */ +void intel_me_status(void); +#else +static inline void intel_me_status(void) { } +#endif + +#endif diff --git a/src/soc/intel/broadwell/include/soc/msr.h b/src/soc/intel/broadwell/include/soc/msr.h new file mode 100644 index 0000000000..707041a161 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/msr.h @@ -0,0 +1,109 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_MSR_H_ +#define _BROADWELL_MSR_H_ + +#define MSR_PIC_MSG_CONTROL 0x2e +#define CORE_THREAD_COUNT_MSR 0x35 +#define IA32_FEATURE_CONTROL 0x3a +#define CPUID_VMX (1 << 5) +#define CPUID_SMX (1 << 6) +#define MSR_PLATFORM_INFO 0xce +#define PLATFORM_INFO_SET_TDP (1 << 29) +#define MSR_PMG_CST_CONFIG_CONTROL 0xe2 +#define MSR_PMG_IO_CAPTURE_BASE 0xe4 +#define MSR_FEATURE_CONFIG 0x13c +#define SMM_MCA_CAP_MSR 0x17d +#define SMM_CPU_SVRSTR_BIT 57 +#define SMM_CPU_SVRSTR_MASK (1 << (SMM_CPU_SVRSTR_BIT - 32)) +#define MSR_FLEX_RATIO 0x194 +#define FLEX_RATIO_LOCK (1 << 20) +#define FLEX_RATIO_EN (1 << 16) +#define IA32_MISC_ENABLE 0x1a0 +#define MSR_MISC_PWR_MGMT 0x1aa +#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) +#define MSR_TURBO_RATIO_LIMIT 0x1ad +#define MSR_TEMPERATURE_TARGET 0x1a2 +#define IA32_PERF_CTL 0x199 +#define IA32_THERM_INTERRUPT 0x19b +#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0 +#define ENERGY_POLICY_PERFORMANCE 0 +#define ENERGY_POLICY_NORMAL 6 +#define ENERGY_POLICY_POWERSAVE 15 +#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2 +#define EMRRphysBase_MSR 0x1f4 +#define EMRRphysMask_MSR 0x1f5 +#define IA32_PLATFORM_DCA_CAP 0x1f8 +#define MSR_POWER_CTL 0x1fc +#define MSR_LT_LOCK_MEMORY 0x2e7 +#define UNCORE_EMRRphysBase_MSR 0x2f4 +#define UNCORE_EMRRphysMask_MSR 0x2f5 +#define IA32_MC0_STATUS 0x401 +#define SMM_FEATURE_CONTROL_MSR 0x4e0 +#define SMM_CPU_SAVE_EN (1 << 1) + +#define MSR_C_STATE_LATENCY_CONTROL_0 0x60a +#define MSR_C_STATE_LATENCY_CONTROL_1 0x60b +#define MSR_C_STATE_LATENCY_CONTROL_2 0x60c +#define MSR_C_STATE_LATENCY_CONTROL_3 0x633 +#define MSR_C_STATE_LATENCY_CONTROL_4 0x634 +#define MSR_C_STATE_LATENCY_CONTROL_5 0x635 +#define IRTL_VALID (1 << 15) +#define IRTL_1_NS (0 << 10) +#define IRTL_32_NS (1 << 10) +#define IRTL_1024_NS (2 << 10) +#define IRTL_32768_NS (3 << 10) +#define IRTL_1048576_NS (4 << 10) +#define IRTL_33554432_NS (5 << 10) +#define IRTL_RESPONSE_MASK (0x3ff) +#define MSR_COUNTER_24_MHZ 0x637 + +/* long duration in low dword, short duration in high dword */ +#define MSR_PKG_POWER_LIMIT 0x610 +#define PKG_POWER_LIMIT_MASK 0x7fff +#define PKG_POWER_LIMIT_EN (1 << 15) +#define PKG_POWER_LIMIT_CLAMP (1 << 16) +#define PKG_POWER_LIMIT_TIME_SHIFT 17 +#define PKG_POWER_LIMIT_TIME_MASK 0x7f + +#define MSR_VR_CURRENT_CONFIG 0x601 +#define MSR_VR_MISC_CONFIG 0x603 +#define MSR_PKG_POWER_SKU_UNIT 0x606 +#define MSR_PKG_POWER_SKU 0x614 +#define MSR_DDR_RAPL_LIMIT 0x618 +#define MSR_VR_MISC_CONFIG2 0x636 +#define MSR_PP0_POWER_LIMIT 0x638 +#define MSR_PP1_POWER_LIMIT 0x640 + +#define MSR_CONFIG_TDP_NOMINAL 0x648 +#define MSR_CONFIG_TDP_LEVEL1 0x649 +#define MSR_CONFIG_TDP_LEVEL2 0x64a +#define MSR_CONFIG_TDP_CONTROL 0x64b +#define MSR_TURBO_ACTIVATION_RATIO 0x64c + +/* SMM save state MSRs */ +#define SMBASE_MSR 0xc20 +#define IEDBASE_MSR 0xc22 + +/* MTRRcap_MSR bits */ +#define SMRR_SUPPORTED (1<<11) +#define EMRR_SUPPORTED (1<<12) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/nvs.h b/src/soc/intel/broadwell/include/soc/nvs.h new file mode 100644 index 0000000000..6dcd9ba224 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/nvs.h @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_NVS_H_ +#define _BROADWELL_NVS_H_ + +#include +#include + +typedef struct { + /* Miscellaneous */ + u16 osys; /* 0x00 - Operating System */ + u8 smif; /* 0x02 - SMI function call ("TRAP") */ + u8 prm0; /* 0x03 - SMI function call parameter */ + u8 prm1; /* 0x04 - SMI function call parameter */ + u8 scif; /* 0x05 - SCI function call (via _L00) */ + u8 prm2; /* 0x06 - SCI function call parameter */ + u8 prm3; /* 0x07 - SCI function call parameter */ + u8 lckf; /* 0x08 - Global Lock function for EC */ + u8 prm4; /* 0x09 - Lock function parameter */ + u8 prm5; /* 0x0a - Lock function parameter */ + u8 pcnt; /* 0x0b - Processor Count */ + u8 ppcm; /* 0x0c - Max PPC State */ + u8 tmps; /* 0x0d - Temperature Sensor ID */ + u8 tlvl; /* 0x0e - Throttle Level Limit */ + u8 flvl; /* 0x0f - Current FAN Level */ + u8 tcrt; /* 0x10 - Critical Threshold */ + u8 tpsv; /* 0x11 - Passive Threshold */ + u8 tmax; /* 0x12 - CPU Tj_max */ + u8 s5u0; /* 0x13 - Enable USB in S5 */ + u8 s3u0; /* 0x14 - Enable USB in S3 */ + u8 s33g; /* 0x15 - Enable 3G in S3 */ + u8 lids; /* 0x16 - LID State */ + u8 pwrs; /* 0x17 - AC Power State */ + u32 cmem; /* 0x18 - 0x1b - CBMEM TOC */ + u32 cbmc; /* 0x1c - 0x1f - Coreboot Memory Console */ + u64 pm1i; /* 0x20 - 0x27 - PM1 wake status bit */ + u64 gpei; /* 0x28 - 0x2f - GPE wake status bit */ + u8 unused[208]; + + /* ChromeOS specific (0x100 - 0xfff) */ + chromeos_acpi_t chromeos; + + /* Device specific (0x1000) */ + device_nvs_t dev; +} __attribute__((packed)) global_nvs_t; + +#ifdef __SMM__ +/* Used in SMM to find the ACPI GNVS address */ +global_nvs_t *smm_get_gnvs(void); +#endif + +#endif diff --git a/src/soc/intel/broadwell/include/soc/pch.h b/src/soc/intel/broadwell/include/soc/pch.h new file mode 100644 index 0000000000..e677215c7f --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/pch.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_PCH_H_ +#define _BROADWELL_PCH_H_ + +/* Haswell ULT Pch (LynxPoint-LP) */ +#define PCH_LPT_LP_SAMPLE 0x9c41 +#define PCH_LPT_LP_PREMIUM 0x9c43 +#define PCH_LPT_LP_MAINSTREAM 0x9c45 +#define PCH_LPT_LP_VALUE 0x9c47 + +/* Broadwell PCH (WildatPoint) */ +#define PCH_WPT_HSW_U_SAMPLE 0x9cc1 +#define PCH_WPT_BDW_U_SAMPLE 0x9cc2 +#define PCH_WPT_BDW_U_PREMIUM 0x9cc3 +#define PCH_WPT_BDW_U_BASE 0x9cc5 +#define PCH_WPT_BDW_Y_SAMPLE 0x9cc6 +#define PCH_WPT_BDW_Y_PREMIUM 0x9cc7 +#define PCH_WPT_BDW_Y_BASE 0x9cc9 +#define PCH_WPT_BDW_H 0x9ccb + +/* Power Management Control and Status */ +#define PCH_PCS 0x84 +#define PCH_PCS_PS_D3HOT 3 + +u8 pch_revision(void); +u16 pch_type(void); +int pch_is_wpt(void); +int pch_is_wpt_ulx(void); +u32 pch_read_soft_strap(int id); +void pch_log_state(void); +void pch_disable_devfn(device_t dev); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/pci_devs.h b/src/soc/intel/broadwell/include/soc/pci_devs.h new file mode 100644 index 0000000000..76e3a688ed --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/pci_devs.h @@ -0,0 +1,119 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_PCI_DEVS_H_ +#define _BROADWELL_PCI_DEVS_H_ + +#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_ ## slot, 0) +#define _PCH_DEVFN(slot,func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func) + +#if defined(__PRE_RAM__) || defined(__SMM__) || defined(__ROMCC__) +#include +#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_ ## slot, 0) +#define _PCH_DEV(slot,func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func) +#else +#include +#include +#define _SA_DEV(slot) dev_find_slot(0, _SA_DEVFN(slot)) +#define _PCH_DEV(slot,func) dev_find_slot(0, _PCH_DEVFN(slot, func)) +#endif + +/* System Agent Devices */ + +#define SA_DEV_SLOT_ROOT 0x00 +#define SA_DEVFN_ROOT _SA_DEVFN(ROOT) +#define SA_DEV_ROOT _SA_DEV(ROOT) + +#define SA_DEV_SLOT_IGD 0x02 +#define SA_DEVFN_IGD _SA_DEVFN(IGD) +#define SA_DEV_IGD _SA_DEV(IGD) + +#define SA_DEV_SLOT_MINIHD 0x03 +#define SA_DEVFN_MINIHD _SA_DEVFN(MINIHD) +#define SA_DEV_MINIHD _SA_DEV(MINIHD) + +/* PCH Devices */ + +#define PCH_DEV_SLOT_ADSP 0x13 +#define PCH_DEVFN_ADSP _PCH_DEVFN(ADSP, 0) +#define PCH_DEV_ADSP _PCH_DEV(ADSP, 0) + +#define PCH_DEV_SLOT_XHCI 0x14 +#define PCH_DEVFN_XHCI _PCH_DEVFN(XHCI, 0) +#define PCH_DEV_XHCI _PCH_DEV(XHCI, 0) + +#define PCH_DEV_SLOT_SIO 0x15 +#define PCH_DEV_SDMA _PCH_DEV(SIO, 0) +#define PCH_DEV_I2C0 _PCH_DEV(SIO, 1) +#define PCH_DEV_I2C1 _PCH_DEV(SIO, 2) +#define PCH_DEV_SPI0 _PCH_DEV(SIO, 3) +#define PCH_DEV_SPI1 _PCH_DEV(SIO, 4) +#define PCH_DEV_UART0 _PCH_DEV(SIO, 5) +#define PCH_DEV_UART1 _PCH_DEV(SIO, 6) +#define PCH_DEVFN_SDMA _PCH_DEVFN(SIO, 0) +#define PCH_DEVFN_I2C0 _PCH_DEVFN(SIO, 1) +#define PCH_DEVFN_I2C1 _PCH_DEVFN(SIO, 2) +#define PCH_DEVFN_SPI0 _PCH_DEVFN(SIO, 3) +#define PCH_DEVFN_SPI1 _PCH_DEVFN(SIO, 4) +#define PCH_DEVFN_UART0 _PCH_DEVFN(SIO, 5) +#define PCH_DEVFN_UART1 _PCH_DEVFN(SIO, 6) + +#define PCH_DEV_SLOT_ME 0x16 +#define PCH_DEVFN_ME _PCH_DEVFN(ME, 0) +#define PCH_DEVFN_ME_2 _PCH_DEVFN(ME, 1) +#define PCH_DEVFN_ME_IDER _PCH_DEVFN(ME, 2) +#define PCH_DEVFN_ME_KT _PCH_DEVFN(ME, 3) +#define PCH_DEV_ME _PCH_DEV(ME, 0) +#define PCH_DEV_ME_2 _PCH_DEV(ME, 1) +#define PCH_DEV_ME_IDER _PCH_DEV(ME, 2) +#define PCH_DEV_ME_KT _PCH_DEV(ME, 3) + +#define PCH_DEV_SLOT_SDIO 0x17 +#define PCH_DEVFN_SDIO _PCH_DEVFN(SDIO, 0) +#define PCH_DEV_SDIO _PCH_DEV(SDIO, 0) + +#define PCH_DEV_SLOT_GBE 0x19 +#define PCH_DEVFN_GBE _PCH_DEVFN(GBE, 0) +#define PCH_DEV_GBE _PCH_DEV(GBE, 0) + +#define PCH_DEV_SLOT_HDA 0x1b +#define PCH_DEVFN_HDA _PCH_DEVFN(HDA, 0) +#define PCH_DEV_HDA _PCH_DEV(HDA, 0) + +#define PCH_DEV_SLOT_PCIE 0x1c + +#define PCH_DEV_SLOT_EHCI 0x1d +#define PCH_DEVFN_EHCI _PCH_DEVFN(EHCI, 0) +#define PCH_DEV_EHCI _PCH_DEV(EHCI, 0) + +#define PCH_DEV_SLOT_LPC 0x1f +#define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0) +#define PCH_DEVFN_IDE _PCH_DEVFN(LPC, 1) +#define PCH_DEVFN_SATA _PCH_DEVFN(LPC, 2) +#define PCH_DEVFN_SMBUS _PCH_DEVFN(LPC, 3) +#define PCH_DEVFN_SATA2 _PCH_DEVFN(LPC, 5) +#define PCH_DEVFN_THERMAL _PCH_DEVFN(LPC, 6) +#define PCH_DEV_LPC _PCH_DEV(LPC, 0) +#define PCH_DEV_IDE _PCH_DEV(LPC, 1) +#define PCH_DEV_SATA _PCH_DEV(LPC, 2) +#define PCH_DEV_SMBUS _PCH_DEV(LPC, 3) +#define PCH_DEV_SATA2 _PCH_DEV(LPC, 5) +#define PCH_DEV_THERMAL _PCH_DEV(LPC, 6) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/pei_data.h b/src/soc/intel/broadwell/include/soc/pei_data.h new file mode 100644 index 0000000000..e6147181f7 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/pei_data.h @@ -0,0 +1,199 @@ +/* + * Broadwell UEFI PEI wrapper + * + * Copyright (C) 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PEI_DATA_H +#define PEI_DATA_H + +#include +#include + +#define PEI_VERSION 22 + +#define ABI_X86 __attribute__((regparm(0))) + +typedef void ABI_X86 (*tx_byte_func)(unsigned char byte); + +enum board_type { + BOARD_TYPE_CRB_MOBILE = 0, /* CRB Mobile */ + BOARD_TYPE_CRB_DESKTOP, /* CRB Desktop */ + BOARD_TYPE_USER1, /* SV mobile */ + BOARD_TYPE_USER2, /* SV desktop */ + BOARD_TYPE_USER3, /* SV server */ + BOARD_TYPE_ULT, /* ULT */ + BOARD_TYPE_CRB_EMBDEDDED, /* CRB Embedded */ + BOARD_TYPE_UNKNOWN, +}; + +#define MAX_USB2_PORTS 14 +#define MAX_USB3_PORTS 6 +#define USB_OC_PIN_SKIP 8 + +enum usb2_port_location { + USB_PORT_BACK_PANEL = 0, + USB_PORT_FRONT_PANEL, + USB_PORT_DOCK, + USB_PORT_MINI_PCIE, + USB_PORT_FLEX, + USB_PORT_INTERNAL, + USB_PORT_SKIP, + USB_PORT_NGFF_DEVICE_DOWN, +}; + +struct usb2_port_setting { + /* + * Usb Port Length: + * [16:4] = length in inches in octal format + * [3:0] = decimal point + */ + uint16_t length; + uint8_t enable; + uint8_t oc_pin; + uint8_t location; +} __attribute__((packed)); + +struct usb3_port_setting { + uint8_t enable; + uint8_t oc_pin; + /* + * Set to 0 if trace length is > 5 inches + * Set to 1 if trace length is <= 5 inches + */ + uint8_t fixed_eq; +} __attribute__((packed)); + +struct pei_data +{ + uint32_t pei_version; + + enum board_type board_type; + int boot_mode; + int ec_present; + int usbdebug; + + /* Base addresses */ + uint32_t pciexbar; + uint16_t smbusbar; + uint32_t xhcibar; + uint32_t ehcibar; + uint32_t gttbar; + uint32_t rcba; + uint32_t pmbase; + uint32_t gpiobase; + uint32_t temp_mmio_base; + uint32_t tseg_size; + + /* + * 0 = leave channel enabled + * 1 = disable dimm 0 on channel + * 2 = disable dimm 1 on channel + * 3 = disable dimm 0+1 on channel + */ + int dimm_channel0_disabled; + int dimm_channel1_disabled; + /* Set to 0 for memory down */ + uint8_t spd_addresses[4]; + /* Enable 2x Refresh Mode */ + int ddr_refresh_2x; + /* DQ pins are interleaved on board */ + int dq_pins_interleaved; + /* Limit DDR3 frequency */ + int max_ddr3_freq; + /* Disable self refresh */ + int disable_self_refresh; + /* Disable cmd power/CKEPD */ + int disable_cmd_pwr; + + /* USB port configuration */ + struct usb2_port_setting usb2_ports[MAX_USB2_PORTS]; + struct usb3_port_setting usb3_ports[MAX_USB3_PORTS]; + + /* + * USB3 board specific PHY tuning + */ + + /* Valid range: 0x69 - 0x80 */ + uint8_t usb3_txout_volt_dn_amp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x80 - 0x9c */ + uint8_t usb3_txout_imp_sc_volt_amp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x39 - 0x80 */ + uint8_t usb3_txout_de_emp_adj[MAX_USB3_PORTS]; + /* Valid range: 0x3d - 0x4a */ + uint8_t usb3_txout_imp_adj_volt_amp[MAX_USB3_PORTS]; + + /* Console output function */ + tx_byte_func tx_byte; + + /* + * DIMM SPD data for memory down configurations + * [CHANNEL][SLOT][SPD] + */ + uint8_t spd_data[2][2][512]; + + /* + * LPDDR3 DQ byte map + * [CHANNEL][ITERATION][2] + * + * Maps which PI clocks are used by what LPDDR DQ Bytes (from CPU side) + * DQByteMap[0] - ClkDQByteMap: + * - If clock is per rank, program to [0xFF, 0xFF] + * - If clock is shared by 2 ranks, program to [0xFF, 0] or [0, 0xFF] + * - If clock is shared by 2 ranks but does not go to all bytes, + * Entry[i] defines which DQ bytes Group i services + * DQByteMap[1] - CmdNDQByteMap: [0] is CmdN/CAA and [1] is CmdN/CAB + * DQByteMap[2] - CmdSDQByteMap: [0] is CmdS/CAA and [1] is CmdS/CAB + * DQByteMap[3] - CkeDQByteMap : [0] is CKE /CAA and [1] is CKE /CAB + * For DDR, DQByteMap[3:1] = [0xFF, 0] + * DQByteMap[4] - CtlDQByteMap : Always program to [0xFF, 0] + * since we have 1 CTL / rank + * DQByteMap[5] - CmdVDQByteMap: Always program to [0xFF, 0] + * since we have 1 CA Vref + */ + uint8_t dq_map[2][6][2]; + + /* + * LPDDR3 Map from CPU DQS pins to SDRAM DQS pins + * [CHANNEL][MAX_BYTES] + */ + uint8_t dqs_map[2][8]; + + /* Data read from flash and passed into MRC */ + const void *saved_data; + int saved_data_size; + + /* Disable use of saved data (can be set by mainboard) */ + int disable_saved_data; + + /* Data from MRC that should be saved to flash */ + void *data_to_save; + int data_to_save_size; + struct memory_info meminfo; +} __attribute__((packed)); + +typedef struct pei_data PEI_DATA; + +#endif diff --git a/src/soc/intel/broadwell/include/soc/pei_wrapper.h b/src/soc/intel/broadwell/include/soc/pei_wrapper.h new file mode 100644 index 0000000000..3ade4ffff7 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/pei_wrapper.h @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_PEI_WRAPPER_H_ +#define _BROADWELL_PEI_WRAPPER_H_ + +#include + +typedef int ABI_X86 (*pei_wrapper_entry_t)(struct pei_data *pei_data); + +static inline void pei_data_usb2_port(struct pei_data *pei_data, int port, + uint16_t length, uint8_t enable, + uint8_t oc_pin, uint8_t location) +{ + pei_data->usb2_ports[port].length = length; + pei_data->usb2_ports[port].enable = enable; + pei_data->usb2_ports[port].oc_pin = oc_pin; + pei_data->usb2_ports[port].location = location; +} + +static inline void pei_data_usb3_port(struct pei_data *pei_data, int port, + uint8_t enable, uint8_t oc_pin, + uint8_t fixed_eq) +{ + pei_data->usb3_ports[port].enable = enable; + pei_data->usb3_ports[port].oc_pin = oc_pin; + pei_data->usb3_ports[port].fixed_eq = fixed_eq; +} + +void broadwell_fill_pei_data(struct pei_data *pei_data); +void mainboard_fill_pei_data(struct pei_data *pei_data); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/pm.h b/src/soc/intel/broadwell/include/soc/pm.h new file mode 100644 index 0000000000..54fc4a7f1d --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/pm.h @@ -0,0 +1,172 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_PM_H_ +#define _BROADWELL_PM_H_ + +/* ACPI_BASE_ADDRESS / PMBASE */ + +#define PM1_STS 0x00 +#define WAK_STS (1 << 15) +#define PCIEXPWAK_STS (1 << 14) +#define PRBTNOR_STS (1 << 11) +#define RTC_STS (1 << 10) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) +#define PM1_EN 0x02 +#define PCIEXPWAK_DIS (1 << 14) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_SHIFT 10 +#define SLP_TYP_S0 0 +#define SLP_TYP_S1 1 +#define SLP_TYP_S3 5 +#define SLP_TYP_S4 6 +#define SLP_TYP_S5 7 +#define GBL_RLS (1 << 2) +#define BM_RLD (1 << 1) +#define SCI_EN (1 << 0) +#define PM1_TMR 0x08 +#define SMI_EN 0x30 +#define XHCI_SMI_EN (1 << 31) +#define ME_SMI_EN (1 << 30) +#define GPIO_UNLOCK_SMI_EN (1 << 27) +#define INTEL_USB2_EN (1 << 18) +#define LEGACY_USB2_EN (1 << 17) +#define PERIODIC_EN (1 << 14) +#define TCO_EN (1 << 13) +#define MCSMI_EN (1 << 11) +#define BIOS_RLS (1 << 7) +#define SWSMI_TMR_EN (1 << 6) +#define APMC_EN (1 << 5) +#define SLP_SMI_EN (1 << 4) +#define LEGACY_USB_EN (1 << 3) +#define BIOS_EN (1 << 2) +#define EOS (1 << 1) +#define GBL_SMI_EN (1 << 0) +#define SMI_STS 0x34 +#define UPWRC 0x3c +#define UPWRC_WS (1 << 8) +#define UPWRC_WE (1 << 1) +#define UPWRC_SMI (1 << 0) +#define GPE_CNTL 0x42 +#define SWGPE_CTRL (1 << 1) +#define DEVACT_STS 0x44 +#define PM2_CNT 0x50 +#define TCO1_CNT 0x60 +#define TCO_TMR_HLT (1 << 11) +#define TCO1_STS 0x64 +#define DMISCI_STS (1 << 9) +#define TCO2_STS 0x66 +#define TCO2_STS_SECOND_TO (1 << 1) + +#define GPE0_REG_MAX 4 +#define GPE0_REG_SIZE 32 +#define GPE0_STS(x) (0x80 + (x * 4)) +#define GPE_31_0 0 /* 0x80/0x90 = GPE[31:0] */ +#define GPE_63_32 1 /* 0x84/0x94 = GPE[63:32] */ +#define GPE_94_64 2 /* 0x88/0x98 = GPE[94:64] */ +#define GPE_STD 3 /* 0x8c/0x9c = Standard GPE */ +#define WADT_STS (1 << 18) +#define GP27_STS (1 << 16) +#define PME_B0_STS (1 << 13) +#define ME_SCI_STS (1 << 12) +#define PME_STS (1 << 11) +#define BATLOW_STS (1 << 10) +#define PCI_EXP_STS (1 << 9) +#define SMB_WAK_STS (1 << 7) +#define TCOSCI_STS (1 << 6) +#define SWGPE_STS (1 << 2) +#define HOT_PLUG_STS (1 << 1) +#define GPE0_EN(x) (0x90 + (x * 4)) +#define WADT_en (1 << 18) +#define GP27_EN (1 << 16) +#define PME_B0_EN (1 << 13) +#define ME_SCI_EN (1 << 12) +#define PME_EN (1 << 11) +#define BATLOW_EN (1 << 10) +#define PCI_EXP_EN (1 << 9) +#define TCOSCI_EN (1 << 6) +#define SWGPE_EN (1 << 2) +#define HOT_PLUG_EN (1 << 1) + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define MAINBOARD_POWER_KEEP 2 + +#define SLEEP_STATE_S0 0 +#define SLEEP_STATE_S3 3 +#define SLEEP_STATE_S5 5 + +struct chipset_power_state { + uint16_t pm1_sts; + uint16_t pm1_en; + uint32_t pm1_cnt; + uint16_t tco1_sts; + uint16_t tco2_sts; + uint32_t gpe0_sts[4]; + uint32_t gpe0_en[4]; + uint16_t gen_pmcon1; + uint16_t gen_pmcon2; + uint16_t gen_pmcon3; + int prev_sleep_state; + uint16_t hsio_version; + uint16_t hsio_checksum; +}; + +/* PM1_CNT */ +void enable_pm1_control(uint32_t mask); +void disable_pm1_control(uint32_t mask); + +/* PM1 */ +uint16_t clear_pm1_status(void); +void enable_pm1(uint16_t events); +uint32_t clear_smi_status(void); + +/* SMI */ +void enable_smi(uint32_t mask); +void disable_smi(uint32_t mask); + +/* ALT_GP_SMI */ +uint32_t clear_alt_smi_status(void); +void enable_alt_smi(uint32_t mask); + +/* TCO */ +uint32_t clear_tco_status(void); +void enable_tco_sci(void); + +/* GPE0 */ +uint32_t clear_gpe_status(void); +void clear_gpe_enable(void); +void enable_all_gpe(uint32_t set1, uint32_t set2, uint32_t set3, uint32_t set4); +void disable_all_gpe(void); +void enable_gpe(uint32_t mask); +void disable_gpe(uint32_t mask); + +/* Return the selected ACPI SCI IRQ */ +int acpi_sci_irq(void); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/ramstage.h b/src/soc/intel/broadwell/include/soc/ramstage.h new file mode 100644 index 0000000000..9242aa9ea3 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/ramstage.h @@ -0,0 +1,38 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_RAMSTAGE_H_ +#define _BROADWELL_RAMSTAGE_H_ + +#include +#include + +void broadwell_init_pre_device(void *chip_info); +void broadwell_init_cpus(device_t dev); +void broadwell_pch_enable_dev(device_t dev); + +#if CONFIG_HAVE_REFCODE_BLOB +void broadwell_run_reference_code(void); +#else +static inline void broadwell_run_reference_code(void) { } +#endif + +extern struct pci_operations broadwell_pci_ops; + +#endif diff --git a/src/soc/intel/broadwell/include/soc/rcba.h b/src/soc/intel/broadwell/include/soc/rcba.h new file mode 100644 index 0000000000..eb854525e8 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/rcba.h @@ -0,0 +1,178 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_RCBA_H_ +#define _BROADWELL_RCBA_H_ + +#include + +#define RCBA8(x) *((volatile u8 *)(RCBA_BASE_ADDRESS + x)) +#define RCBA16(x) *((volatile u16 *)(RCBA_BASE_ADDRESS + x)) +#define RCBA32(x) *((volatile u32 *)(RCBA_BASE_ADDRESS + x)) + +#define RCBA_AND_OR(bits, x, and, or) \ + RCBA##bits(x) = ((RCBA##bits(x) & (and)) | (or)) +#define RCBA8_AND_OR(x, and, or) RCBA_AND_OR(8, x, and, or) +#define RCBA16_AND_OR(x, and, or) RCBA_AND_OR(16, x, and, or) +#define RCBA32_AND_OR(x, and, or) RCBA_AND_OR(32, x, and, or) +#define RCBA32_OR(x, or) RCBA_AND_OR(32, x, ~0UL, or) + +#define RPC 0x0400 /* 32bit */ +#define RPFN 0x0404 /* 32bit */ + +/* Root Port configuratinon space hide */ +#define RPFN_HIDE(port) (1 << (((port) * 4) + 3)) +/* Get the function number assigned to a Root Port */ +#define RPFN_FNGET(reg,port) (((reg) >> ((port) * 4)) & 7) +/* Set the function number for a Root Port */ +#define RPFN_FNSET(port,func) (((func) & 7) << ((port) * 4)) +/* Root Port function number mask */ +#define RPFN_FNMASK(port) (7 << ((port) * 4)) + +#define NOINT 0 +#define INTA 1 +#define INTB 2 +#define INTC 3 +#define INTD 4 + +#define DIR_IDR 12 /* Interrupt D Pin Offset */ +#define DIR_ICR 8 /* Interrupt C Pin Offset */ +#define DIR_IBR 4 /* Interrupt B Pin Offset */ +#define DIR_IAR 0 /* Interrupt A Pin Offset */ + +#define PIRQA 0 +#define PIRQB 1 +#define PIRQC 2 +#define PIRQD 3 +#define PIRQE 4 +#define PIRQF 5 +#define PIRQG 6 +#define PIRQH 7 + +/* IO Buffer Programming */ +#define IOBPIRI 0x2330 +#define IOBPD 0x2334 +#define IOBPS 0x2338 +#define IOBPS_READY 0x0001 +#define IOBPS_TX_MASK 0x0006 +#define IOBPS_MASK 0xff00 +#define IOBPS_READ 0x0600 +#define IOBPS_WRITE 0x0700 +#define IOBPU 0x233a +#define IOBPU_MAGIC 0xf000 +#define IOBP_PCICFG_READ 0x0400 +#define IOBP_PCICFG_WRITE 0x0500 + +#define D31IP 0x3100 /* 32bit */ +#define D31IP_TTIP 24 /* Thermal Throttle Pin */ +#define D31IP_SIP2 20 /* SATA Pin 2 */ +#define D31IP_SMIP 12 /* SMBUS Pin */ +#define D31IP_SIP 8 /* SATA Pin */ +#define D30IP 0x3104 /* 32bit */ +#define D30IP_PIP 0 /* PCI Bridge Pin */ +#define D29IP 0x3108 /* 32bit */ +#define D29IP_E1P 0 /* EHCI #1 Pin */ +#define D28IP 0x310c /* 32bit */ +#define D28IP_P8IP 28 /* PCI Express Port 8 */ +#define D28IP_P7IP 24 /* PCI Express Port 7 */ +#define D28IP_P6IP 20 /* PCI Express Port 6 */ +#define D28IP_P5IP 16 /* PCI Express Port 5 */ +#define D28IP_P4IP 12 /* PCI Express Port 4 */ +#define D28IP_P3IP 8 /* PCI Express Port 3 */ +#define D28IP_P2IP 4 /* PCI Express Port 2 */ +#define D28IP_P1IP 0 /* PCI Express Port 1 */ +#define D27IP 0x3110 /* 32bit */ +#define D27IP_ZIP 0 /* HD Audio Pin */ +#define D26IP 0x3114 /* 32bit */ +#define D26IP_E2P 0 /* EHCI #2 Pin */ +#define D25IP 0x3118 /* 32bit */ +#define D25IP_LIP 0 /* GbE LAN Pin */ +#define D22IP 0x3124 /* 32bit */ +#define D22IP_KTIP 12 /* KT Pin */ +#define D22IP_IDERIP 8 /* IDE-R Pin */ +#define D22IP_MEI2IP 4 /* MEI #2 Pin */ +#define D22IP_MEI1IP 0 /* MEI #1 Pin */ +#define D20IP 0x3128 /* 32bit */ +#define D20IP_XHCI 0 /* XHCI Pin */ +#define D31IR 0x3140 /* 16bit */ +#define D30IR 0x3142 /* 16bit */ +#define D29IR 0x3144 /* 16bit */ +#define D28IR 0x3146 /* 16bit */ +#define D27IR 0x3148 /* 16bit */ +#define D26IR 0x314c /* 16bit */ +#define D25IR 0x3150 /* 16bit */ +#define D23IR 0x3158 /* 16bit */ +#define D22IR 0x315c /* 16bit */ +#define D20IR 0x3160 /* 16bit */ +#define D21IR 0x3164 /* 16bit */ +#define D19IR 0x3168 /* 16bit */ +#define ACPIIRQEN 0x31e0 /* 32bit */ +#define OIC 0x31fe /* 16bit */ +#define DEEP_S3_POL 0x3328 /* 32bit */ +#define DEEP_S3_EN_AC (1 << 0) +#define DEEP_S3_EN_DC (1 << 1) +#define DEEP_S5_POL 0x3330 /* 32bit */ +#define DEEP_S5_EN_AC (1 << 14) +#define DEEP_S5_EN_DC (1 << 15) +#define DEEP_SX_CONFIG 0x3334 /* 32bit */ +#define DEEP_SX_WAKE_PIN_EN (1 << 2) +#define DEEP_SX_ACPRESENT_PD (1 << 1) +#define DEEP_SX_GP27_PIN_EN (1 << 0) +#define PMSYNC_CONFIG 0x33c4 /* 32bit */ +#define PMSYNC_CONFIG2 0x33cc /* 32bit */ +#define SOFT_RESET_CTRL 0x38f4 +#define SOFT_RESET_DATA 0x38f8 + +#define DIR_ROUTE(a,b,c,d) \ + (((d) << DIR_IDR) | ((c) << DIR_ICR) | \ + ((b) << DIR_IBR) | ((a) << DIR_IAR)) + +#define RC 0x3400 /* 32bit */ +#define HPTC 0x3404 /* 32bit */ +#define GCS 0x3410 /* 32bit */ +#define BUC 0x3414 /* 32bit */ +#define PCH_DISABLE_GBE (1 << 5) +#define FD 0x3418 /* 32bit */ +#define FDSW 0x3420 /* 8bit */ +#define DISPBDF 0x3424 /* 16bit */ +#define FD2 0x3428 /* 32bit */ +#define CG 0x341c /* 32bit */ + +/* Function Disable 1 RCBA 0x3418 */ +#define PCH_DISABLE_ALWAYS (1 << 0) +#define PCH_DISABLE_ADSPD (1 << 1) +#define PCH_DISABLE_SATA1 (1 << 2) +#define PCH_DISABLE_SMBUS (1 << 3) +#define PCH_DISABLE_HD_AUDIO (1 << 4) +#define PCH_DISABLE_EHCI2 (1 << 13) +#define PCH_DISABLE_LPC (1 << 14) +#define PCH_DISABLE_EHCI1 (1 << 15) +#define PCH_DISABLE_PCIE(x) (1 << (16 + x)) +#define PCH_DISABLE_THERMAL (1 << 24) +#define PCH_DISABLE_SATA2 (1 << 25) +#define PCH_DISABLE_XHCI (1 << 27) + +/* Function Disable 2 RCBA 0x3428 */ +#define PCH_DISABLE_KT (1 << 4) +#define PCH_DISABLE_IDER (1 << 3) +#define PCH_DISABLE_MEI2 (1 << 2) +#define PCH_DISABLE_MEI1 (1 << 1) +#define PCH_ENABLE_DBDF (1 << 0) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/reset.h b/src/soc/intel/broadwell/include/soc/reset.h new file mode 100644 index 0000000000..6f21181a0c --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/reset.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_RESET_H_ +#define _BROADWELL_RESET_H_ + +void reset_system(void); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/romstage.h b/src/soc/intel/broadwell/include/soc/romstage.h new file mode 100644 index 0000000000..0c0e6b8c7a --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/romstage.h @@ -0,0 +1,117 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_ROMSTAGE_H_ +#define _BROADWELL_ROMSTAGE_H_ + +#include +#include +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) +#include +#endif /* CONFIG_PLATFORM_USES_FSP */ +#include +#include + +struct romstage_params { + unsigned long bist; + struct chipset_power_state *power_state; + struct pei_data *pei_data; +}; + +/* + * FSP Boot Flow: + * 1. src/cpu/x86/16bit/reset.inc + * 2. src/cpu/x86/16bit/entry.inc + * 3. other modules + * 4. src/soc/intel/broadwell/romstage/fsp_1_1.inc + * 5. src/drivers/intel/fsp/fsp_util.c/find_fsp + * 6. FSP binary/TempRamInit + * 7. src/soc/intel/broadwell/romstage/fsp_1_1.inc - return + * 8. src/soc/intel/broadwell/romstage/romstage.c/romstage_main + * 9. src/mainboard/.../romstage.c/mainboard_romstage_entry + * 10. src/soc/intel/broadwell/romstage/romstage.c/romstage_common + * 11. src/mainboard/.../fsp.c/board_fsp_memory_init_params + * 12. FSP binary/MemoryInit + * 13. src/soc/intel/broadwell/romstage/romstage.c/romstage_common - return + * 14. src/mainboard/.../romstage.c/mainboard_romstage_entry - return + * 15. src/soc/intel/broadwell/romstage/romstage.c/romstage_main - return + * 16. src/soc/intel/broadwell/stack.c/setup_stack_and_mttrs + * 17. src/soc/intel/broadwell/romstage/fsp_1_1.inc - return, cleanup + * after call to romstage_main + * 18. FSP binary/TempRamExit + * 19. src/soc/intel/broadwell/romstage.c/romstage_after_car + * 20. FSP binary/SiliconInit + * 21. src/soc/intel/broadwell/romstage.c/romstage_after_car - return + * 22. src/soc/intel/broadwell/chip.c/broadwell_final + * 23. src/drivers/intel/fsp/fsp_util.c/fsp_notify + * 24. FSP binary/FspNotify + * + * + * MRC Boot Flow: + * 1. src/cpu/x86/16bit/reset.inc + * 2. src/cpu/x86/16bit/entry.inc + * 3. other modules + * 4. src/soc/intel/broadwell/romstage/cache_as_ram.inc + * 5. src/soc/intel/broadwell/romstage/romstage.c/romstage_main + * 6. src/mainboard/.../romstage.c/mainboard_romstage_entry + * 7. src/soc/intel/broadwell/romstage/romstage.c/romstage_common + * 8. src/soc/intel/broadwell/ram_init.c/ram_init + * 9. src/soc/intel/broadwell/romstage/romstage.c/romstage_common - return + * 10. src/mainboard/.../romstage.c/mainboard_romstage_entry - return + * 11. src/soc/intel/broadwell/romstage/romstage.c/romstage_main - return + * 12. src/soc/intel/broadwell/stack.c/setup_stack_and_mttrs + * 13. src/soc/intel/broadwell/romstage/cache_as_ram.inc - return, cleanup + * after call to romstage_main + * 14. src/soc/intel/broadwell/romstage.c/romstage_after_car + */ + +asmlinkage void *romstage_main(unsigned int bist, uint32_t tsc_lo, + uint32_t tsc_high); +void mainboard_romstage_entry(struct romstage_params *params); +void romstage_common(struct romstage_params *params); +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) +void board_fsp_memory_init_params( + struct romstage_params *params, + FSP_INFO_HEADER *fsp_header, + FSP_MEMORY_INIT_PARAMS *fsp_memory_init_params); +#endif /* CONFIG_PLATFORM_USES_FSP */ +void asmlinkage romstage_after_car(void); +void raminit(struct romstage_params *params, struct pei_data *pei_data); +void *setup_stack_and_mttrs(void); + +struct chipset_power_state; +struct chipset_power_state *fill_power_state(void); +void report_platform_info(void); +void report_memory_config(void); + +void set_max_freq(void); + +void systemagent_early_init(void); +void pch_early_init(void); +void pch_uart_init(void); +void intel_early_me_status(void); + +void enable_smbus(void); +int smbus_read_byte(unsigned device, unsigned address); + +int early_spi_read(u32 offset, u32 size, u8 *buffer); +int early_spi_read_wpsr(u8 *sr); + +void mainboard_pre_console_init(void); +#endif diff --git a/src/soc/intel/broadwell/include/soc/sata.h b/src/soc/intel/broadwell/include/soc/sata.h new file mode 100644 index 0000000000..357fe584af --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/sata.h @@ -0,0 +1,85 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SATA_H_ +#define _BROADWELL_SATA_H_ + +#define SATA_SIRI 0xa0 /* SATA Indexed Register Index */ +#define SATA_SIRD 0xa4 /* SATA Indexed Register Data */ +#define SATA_SP 0xd0 /* Scratchpad */ + +/* SATA IOBP Registers */ +#define SATA_IOBP_SP0G3IR 0xea000151 +#define SATA_IOBP_SP1G3IR 0xea000051 +#define SATA_IOBP_SP0DTLE_DATA 0xea002550 +#define SATA_IOBP_SP0DTLE_EDGE 0xea002554 +#define SATA_IOBP_SP1DTLE_DATA 0xea002750 +#define SATA_IOBP_SP1DTLE_EDGE 0xea002754 + +#define SATA_DTLE_MASK 0xF +#define SATA_DTLE_DATA_SHIFT 24 +#define SATA_DTLE_EDGE_SHIFT 16 + +/* PCI Configuration Space (D31:F1): IDE */ +#define INTR_LN 0x3c +#define IDE_TIM_PRI 0x40 /* IDE timings, primary */ +#define IDE_DECODE_ENABLE (1 << 15) +#define IDE_SITRE (1 << 14) +#define IDE_ISP_5_CLOCKS (0 << 12) +#define IDE_ISP_4_CLOCKS (1 << 12) +#define IDE_ISP_3_CLOCKS (2 << 12) +#define IDE_RCT_4_CLOCKS (0 << 8) +#define IDE_RCT_3_CLOCKS (1 << 8) +#define IDE_RCT_2_CLOCKS (2 << 8) +#define IDE_RCT_1_CLOCKS (3 << 8) +#define IDE_DTE1 (1 << 7) +#define IDE_PPE1 (1 << 6) +#define IDE_IE1 (1 << 5) +#define IDE_TIME1 (1 << 4) +#define IDE_DTE0 (1 << 3) +#define IDE_PPE0 (1 << 2) +#define IDE_IE0 (1 << 1) +#define IDE_TIME0 (1 << 0) +#define IDE_TIM_SEC 0x42 /* IDE timings, secondary */ + +#define IDE_SDMA_CNT 0x48 /* Synchronous DMA control */ +#define IDE_SSDE1 (1 << 3) +#define IDE_SSDE0 (1 << 2) +#define IDE_PSDE1 (1 << 1) +#define IDE_PSDE0 (1 << 0) + +#define IDE_SDMA_TIM 0x4a + +#define IDE_CONFIG 0x54 /* IDE I/O Configuration Register */ +#define SIG_MODE_SEC_NORMAL (0 << 18) +#define SIG_MODE_SEC_TRISTATE (1 << 18) +#define SIG_MODE_SEC_DRIVELOW (2 << 18) +#define SIG_MODE_PRI_NORMAL (0 << 16) +#define SIG_MODE_PRI_TRISTATE (1 << 16) +#define SIG_MODE_PRI_DRIVELOW (2 << 16) +#define FAST_SCB1 (1 << 15) +#define FAST_SCB0 (1 << 14) +#define FAST_PCB1 (1 << 13) +#define FAST_PCB0 (1 << 12) +#define SCB1 (1 << 3) +#define SCB0 (1 << 2) +#define PCB1 (1 << 1) +#define PCB0 (1 << 0) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/serialio.h b/src/soc/intel/broadwell/include/soc/serialio.h new file mode 100644 index 0000000000..2fd6dca973 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/serialio.h @@ -0,0 +1,94 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SERIALIO_H_ +#define _BROADWELL_SERIALIO_H_ + +/* Serial IO IOBP Registers */ +#define SIO_IOBP_PORTCTRL0 0xcb000000 /* SDIO D23:F0 */ +#define SIO_IOBP_PORTCTRL0_ACPI_IRQ_EN (1 << 5) +#define SIO_IOBP_PORTCTRL0_PCI_CONF_DIS (1 << 4) +#define SIO_IOBP_PORTCTRL1 0xcb000014 /* SDIO D23:F0 */ +#define SIO_IOBP_PORTCTRL1_SNOOP_SELECT(x) (((x) & 3) << 13) +#define SIO_IOBP_GPIODF 0xcb000154 +#define SIO_IOBP_GPIODF_SDIO_IDLE_DET_EN (1 << 4) +#define SIO_IOBP_GPIODF_DMA_IDLE_DET_EN (1 << 3) +#define SIO_IOBP_GPIODF_UART_IDLE_DET_EN (1 << 2) +#define SIO_IOBP_GPIODF_I2C_IDLE_DET_EN (1 << 1) +#define SIO_IOBP_GPIODF_SPI_IDLE_DET_EN (1 << 0) +#define SIO_IOBP_GPIODF_UART0_BYTE_ACCESS (1 << 10) +#define SIO_IOBP_GPIODF_UART1_BYTE_ACCESS (1 << 11) +#define SIO_IOBP_PORTCTRL2 0xcb000240 /* DMA D21:F0 */ +#define SIO_IOBP_PORTCTRL3 0xcb000248 /* I2C0 D21:F1 */ +#define SIO_IOBP_PORTCTRL4 0xcb000250 /* I2C1 D21:F2 */ +#define SIO_IOBP_PORTCTRL5 0xcb000258 /* SPI0 D21:F3 */ +#define SIO_IOBP_PORTCTRL6 0xcb000260 /* SPI1 D21:F4 */ +#define SIO_IOBP_PORTCTRL7 0xcb000268 /* UART0 D21:F5 */ +#define SIO_IOBP_PORTCTRL8 0xcb000270 /* UART1 D21:F6 */ +#define SIO_IOBP_PORTCTRLX(x) (0xcb000240 + ((x) * 8)) +/* PORTCTRL 2-8 have the same layout */ +#define SIO_IOBP_PORTCTRL_ACPI_IRQ_EN (1 << 21) +#define SIO_IOBP_PORTCTRL_PCI_CONF_DIS (1 << 20) +#define SIO_IOBP_PORTCTRL_SNOOP_SELECT(x) (((x) & 3) << 18) +#define SIO_IOBP_PORTCTRL_INT_PIN(x) (((x) & 0xf) << 2) +#define SIO_IOBP_PORTCTRL_PM_CAP_PRSNT (1 << 1) +#define SIO_IOBP_FUNCDIS0 0xce00aa07 /* DMA D21:F0 */ +#define SIO_IOBP_FUNCDIS1 0xce00aa47 /* I2C0 D21:F1 */ +#define SIO_IOBP_FUNCDIS2 0xce00aa87 /* I2C1 D21:F2 */ +#define SIO_IOBP_FUNCDIS3 0xce00aac7 /* SPI0 D21:F3 */ +#define SIO_IOBP_FUNCDIS4 0xce00ab07 /* SPI1 D21:F4 */ +#define SIO_IOBP_FUNCDIS5 0xce00ab47 /* UART0 D21:F5 */ +#define SIO_IOBP_FUNCDIS6 0xce00ab87 /* UART1 D21:F6 */ +#define SIO_IOBP_FUNCDIS7 0xce00ae07 /* SDIO D23:F0 */ +#define SIO_IOBP_FUNCDIS_DIS (1 << 8) + +/* Serial IO Devices */ +#define SIO_ID_SDMA 0 /* D21:F0 */ +#define SIO_ID_I2C0 1 /* D21:F1 */ +#define SIO_ID_I2C1 2 /* D21:F2 */ +#define SIO_ID_SPI0 3 /* D21:F3 */ +#define SIO_ID_SPI1 4 /* D21:F4 */ +#define SIO_ID_UART0 5 /* D21:F5 */ +#define SIO_ID_UART1 6 /* D21:F6 */ +#define SIO_ID_SDIO 7 /* D23:F0 */ + +#define SIO_REG_PPR_CLOCK 0x800 +#define SIO_REG_PPR_CLOCK_EN (1 << 0) +#define SIO_REG_PPR_CLOCK_UPDATE (1 << 31) +#define SIO_REG_PPR_CLOCK_M_DIV 0x25a +#define SIO_REG_PPR_CLOCK_N_DIV 0x7fff +#define SIO_REG_PPR_RST 0x804 +#define SIO_REG_PPR_RST_ASSERT 0x3 +#define SIO_REG_PPR_GEN 0x808 +#define SIO_REG_PPR_GEN_LTR_MODE_MASK (1 << 2) +#define SIO_REG_PPR_GEN_VOLTAGE_MASK (1 << 3) +#define SIO_REG_PPR_GEN_VOLTAGE(x) ((x & 1) << 3) +#define SIO_REG_AUTO_LTR 0x814 + +#define SIO_REG_SDIO_PPR_GEN 0x1008 +#define SIO_REG_SDIO_PPR_SW_LTR 0x1010 +#define SIO_REG_SDIO_PPR_CMD12 0x3c +#define SIO_REG_SDIO_PPR_CMD12_B30 (1 << 30) + +#define SIO_PIN_INTA 1 /* IRQ5 in ACPI mode */ +#define SIO_PIN_INTB 2 /* IRQ6 in ACPI mode */ +#define SIO_PIN_INTC 3 /* IRQ7 in ACPI mode */ +#define SIO_PIN_INTD 4 /* IRQ13 in ACPI mode */ + +#endif diff --git a/src/soc/intel/broadwell/include/soc/smbus.h b/src/soc/intel/broadwell/include/soc/smbus.h new file mode 100644 index 0000000000..fb13c2d8a9 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/smbus.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2005 Yinghai Lu + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SMBUS_H_ +#define _BROADWELL_SMBUS_H_ + +/* PCI Configuration Space (D31:F3): SMBus */ +#define SMB_BASE 0x20 +#define HOSTC 0x40 +#define HST_EN (1 << 0) +#define SMB_RCV_SLVA 0x09 + +/* SMBus I/O bits. */ +#define SMBHSTSTAT 0x0 +#define SMBHSTCTL 0x2 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBBLKDAT 0x7 +#define SMBTRNSADD 0x9 +#define SMBSLVDATA 0xa +#define SMLINK_PIN_CTL 0xe +#define SMBUS_PIN_CTL 0xf + +#define SMBUS_TIMEOUT (10 * 1000 * 100) +#define SMBUS_SLAVE_ADDR 0x24 + +int do_smbus_read_byte(unsigned smbus_base, unsigned device, + unsigned address); +int do_smbus_write_byte(unsigned smbus_base, unsigned device, + unsigned address, unsigned data); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/smm.h b/src/soc/intel/broadwell/include/soc/smm.h new file mode 100644 index 0000000000..a6d896f042 --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/smm.h @@ -0,0 +1,73 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SMM_H_ +#define _BROADWELL_SMM_H_ + +#include +#include + +struct ied_header { + char signature[10]; + u32 size; + u8 reserved[34]; +} __attribute__ ((packed)); + +struct smm_relocation_params { + u32 smram_base; + u32 smram_size; + u32 ied_base; + u32 ied_size; + msr_t smrr_base; + msr_t smrr_mask; + msr_t emrr_base; + msr_t emrr_mask; + msr_t uncore_emrr_base; + msr_t uncore_emrr_mask; + /* The smm_save_state_in_msrs field indicates if SMM save state + * locations live in MSRs. This indicates to the CPUs how to adjust + * the SMMBASE and IEDBASE */ + int smm_save_state_in_msrs; +}; + +/* There is a bug in the order of Kconfig includes in that arch/x86/Kconfig + * is included after chipset code. This causes the chipset's Kconfig to be + * cloberred by the arch/x86/Kconfig if they have the same name. */ +static inline int smm_region_size(void) +{ + /* Make it 8MiB by default. */ + if (CONFIG_SMM_TSEG_SIZE == 0) + return (8 << 20); + return CONFIG_SMM_TSEG_SIZE; +} + +int smm_initialize(void); +void smm_relocate(void); + +/* These helpers are for performing SMM relocation. */ +void southbridge_trigger_smi(void); +void southbridge_clear_smi_status(void); + +/* The initialization of the southbridge is split into 2 compoments. One is + * for clearing the state in the SMM registers. The other is for enabling + * SMIs. They are split so that other work between the 2 actions. */ +void southbridge_smm_clear_state(void); +void southbridge_smm_enable_smi(void); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/spi.h b/src/soc/intel/broadwell/include/soc/spi.h new file mode 100644 index 0000000000..888452547e --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/spi.h @@ -0,0 +1,100 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SPI_H_ +#define _BROADWELL_SPI_H_ + +/* + * SPI Opcode Menu setup for SPIBAR lockdown + * should support most common flash chips. + */ + +#define SPIBAR_OFFSET 0x3800 +#define SPIBAR8(x) RCBA8(x + SPIBAR_OFFSET) +#define SPIBAR16(x) RCBA16(x + SPIBAR_OFFSET) +#define SPIBAR32(x) RCBA32(x + SPIBAR_OFFSET) + +/* Reigsters within the SPIBAR */ +#define SPIBAR_SSFC 0x91 +#define SPIBAR_FDOC 0xb0 +#define SPIBAR_FDOD 0xb4 + +#define SPIBAR_PREOP 0x94 +#define SPIBAR_OPTYPE 0x96 +#define SPIBAR_OPMENU_LOWER 0x98 +#define SPIBAR_OPMENU_UPPER 0x9c + +#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */ +#define SPI_OPTYPE_0 0x01 /* Write, no address */ + +#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */ +#define SPI_OPTYPE_1 0x03 /* Write, address required */ + +#define SPI_OPMENU_2 0x03 /* READ: Read Data */ +#define SPI_OPTYPE_2 0x02 /* Read, address required */ + +#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */ +#define SPI_OPTYPE_3 0x00 /* Read, no address */ + +#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */ +#define SPI_OPTYPE_4 0x03 /* Write, address required */ + +#define SPI_OPMENU_5 0x9f /* RDID: Read ID */ +#define SPI_OPTYPE_5 0x00 /* Read, no address */ + +#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */ +#define SPI_OPTYPE_6 0x03 /* Write, address required */ + +#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */ +#define SPI_OPTYPE_7 0x02 /* Read, address required */ + +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | SPI_OPMENU_4) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | SPI_OPMENU_0) + +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0)) + +#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */ + +#define SPIBAR_HSFS 0x04 /* SPI hardware sequence status */ +#define SPIBAR_HSFS_FLOCKDN (1 << 15)/* Flash Configuration Lock-Down */ +#define SPIBAR_HSFS_SCIP (1 << 5) /* SPI Cycle In Progress */ +#define SPIBAR_HSFS_AEL (1 << 2) /* SPI Access Error Log */ +#define SPIBAR_HSFS_FCERR (1 << 1) /* SPI Flash Cycle Error */ +#define SPIBAR_HSFS_FDONE (1 << 0) /* SPI Flash Cycle Done */ +#define SPIBAR_HSFC 0x06 /* SPI hardware sequence control */ +#define SPIBAR_HSFC_BYTE_COUNT(c) (((c - 1) & 0x3f) << 8) +#define SPIBAR_HSFC_CYCLE_READ (0 << 1) /* Read cycle */ +#define SPIBAR_HSFC_CYCLE_WRITE (2 << 1) /* Write cycle */ +#define SPIBAR_HSFC_CYCLE_ERASE (3 << 1) /* Erase cycle */ +#define SPIBAR_HSFC_GO (1 << 0) /* GO: start SPI transaction */ +#define SPIBAR_FADDR 0x08 /* SPI flash address */ +#define SPIBAR_FDATA(n) (0x10 + (4 * n)) /* SPI flash data */ +#define SPIBAR_SSFS 0x90 +#define SPIBAR_SSFS_ERROR (1 << 3) +#define SPIBAR_SSFS_DONE (1 << 2) +#define SPIBAR_SSFC 0x91 +#define SPIBAR_SSFC_DATA (1 << 14) +#define SPIBAR_SSFC_GO (1 << 1) + +#endif diff --git a/src/soc/intel/broadwell/include/soc/systemagent.h b/src/soc/intel/broadwell/include/soc/systemagent.h new file mode 100644 index 0000000000..5142b09e0a --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/systemagent.h @@ -0,0 +1,133 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_SYSTEMAGENT_H_ +#define _BROADWELL_SYSTEMAGENT_H_ + +#include + +#define SA_IGD_OPROM_VENDEV 0x80860406 + +#define IGD_HASWELL_ULT_GT1 0x0a06 +#define IGD_HASWELL_ULT_GT2 0x0a16 +#define IGD_HASWELL_ULT_GT3 0x0a26 +#define IGD_BROADWELL_U_GT1 0x1606 +#define IGD_BROADWELL_U_GT2 0x1616 +#define IGD_BROADWELL_U_GT3_15W 0x1626 +#define IGD_BROADWELL_U_GT3_28W 0x162b +#define IGD_BROADWELL_Y_GT2 0x161e +#define IGD_BROADWELL_H_GT2 0x1612 +#define IGD_BROADWELL_H_GT3 0x1622 + +#define MCH_BROADWELL_ID_U_Y 0x1604 +#define MCH_BROADWELL_REV_D0 0x06 +#define MCH_BROADWELL_REV_E0 0x08 +#define MCH_BROADWELL_REV_F0 0x09 + +/* Device 0:0.0 PCI configuration space */ + +#define EPBAR 0x40 +#define MCHBAR 0x48 +#define PCIEXBAR 0x60 +#define DMIBAR 0x68 +#define GGC 0x50 /* GMCH Graphics Control */ +#define DEVEN 0x54 /* Device Enable */ +#define DEVEN_D7EN (1 << 14) +#define DEVEN_D4EN (1 << 7) +#define DEVEN_D3EN (1 << 5) +#define DEVEN_D2EN (1 << 4) +#define DEVEN_D1F0EN (1 << 3) +#define DEVEN_D1F1EN (1 << 2) +#define DEVEN_D1F2EN (1 << 1) +#define DEVEN_D0EN (1 << 0) +#define DPR 0x5c +#define DPR_EPM (1 << 2) +#define DPR_PRS (1 << 1) +#define DPR_SIZE_MASK 0xff0 + +#define PAM0 0x80 +#define PAM1 0x81 +#define PAM2 0x82 +#define PAM3 0x83 +#define PAM4 0x84 +#define PAM5 0x85 +#define PAM6 0x86 + +#define SMRAM 0x88 /* System Management RAM Control */ +#define D_OPEN (1 << 6) +#define D_CLS (1 << 5) +#define D_LCK (1 << 4) +#define G_SMRAME (1 << 3) +#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) + +#define MESEG_BASE 0x70 /* Management Engine Base. */ +#define MESEG_LIMIT 0x78 /* Management Engine Limit. */ +#define REMAPBASE 0x90 /* Remap base. */ +#define REMAPLIMIT 0x98 /* Remap limit. */ +#define TOM 0xa0 /* Top of DRAM in memory controller space. */ +#define TOUUD 0xa8 /* Top of Upper Usable DRAM */ +#define BDSM 0xb0 /* Base Data Stolen Memory */ +#define BGSM 0xb4 /* Base GTT Stolen Memory */ +#define TSEG 0xb8 /* TSEG base */ +#define TOLUD 0xbc /* Top of Low Used Memory */ +#define SKPAD 0xdc /* Scratchpad Data */ + +/* MCHBAR */ + +#define MCHBAR8(x) *((volatile u8 *)(MCH_BASE_ADDRESS + x)) +#define MCHBAR16(x) *((volatile u16 *)(MCH_BASE_ADDRESS + x)) +#define MCHBAR32(x) *((volatile u32 *)(MCH_BASE_ADDRESS + x)) + +#define MCHBAR_PEI_VERSION 0x5034 +#define BIOS_RESET_CPL 0x5da8 +#define EDRAMBAR 0x5408 +#define MCH_PAIR 0x5418 +#define GDXCBAR 0x5420 + +#define MCH_PKG_POWER_LIMIT_LO 0x59a0 +#define MCH_PKG_POWER_LIMIT_HI 0x59a4 +#define MCH_DDR_POWER_LIMIT_LO 0x58e0 +#define MCH_DDR_POWER_LIMIT_HI 0x58e4 + +/* PCODE MMIO communications live in the MCHBAR. */ +#define BIOS_MAILBOX_INTERFACE 0x5da4 +#define MAILBOX_RUN_BUSY (1 << 31) +#define MAILBOX_BIOS_CMD_READ_PCS 1 +#define MAILBOX_BIOS_CMD_WRITE_PCS 2 +#define MAILBOX_BIOS_CMD_READ_CALIBRATION 0x509 +#define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909 +#define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa +#define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb +/* Errors are returned back in bits 7:0. */ +#define MAILBOX_BIOS_ERROR_NONE 0 +#define MAILBOX_BIOS_ERROR_INVALID_COMMAND 1 +#define MAILBOX_BIOS_ERROR_TIMEOUT 2 +#define MAILBOX_BIOS_ERROR_ILLEGAL_DATA 3 +#define MAILBOX_BIOS_ERROR_RESERVED 4 +#define MAILBOX_BIOS_ERROR_ILLEGAL_VR_ID 5 +#define MAILBOX_BIOS_ERROR_VR_INTERFACE_LOCKED 6 +#define MAILBOX_BIOS_ERROR_VR_ERROR 7 +/* Data is passed through bits 31:0 of the data register. */ +#define BIOS_MAILBOX_DATA 0x5da0 + +/* System Agent identification */ +u8 systemagent_revision(void); + +#endif diff --git a/src/soc/intel/broadwell/include/soc/xhci.h b/src/soc/intel/broadwell/include/soc/xhci.h new file mode 100644 index 0000000000..3f4fb4e52d --- /dev/null +++ b/src/soc/intel/broadwell/include/soc/xhci.h @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BROADWELL_XHCI_H_ +#define _BROADWELL_XHCI_H_ + +/* XHCI PCI Registers */ +#define XHCI_PWR_CTL_STS 0x74 +#define XHCI_PWR_CTL_SET_MASK 0x3 +#define XHCI_PWR_CTL_SET_D0 0x0 +#define XHCI_PWR_CTL_SET_D3 0x3 +#define XHCI_PWR_CTL_ENABLE_PME (1 << 8) +#define XHCI_PWR_CTL_STATUS_PME (1 << 15) +#define XHCI_USB2PR 0xd0 +#define XHCI_USB2PRM 0xd4 +#define XHCI_USB2PR_HCSEL 0x7fff +#define XHCI_USB3PR 0xd8 +#define XHCI_USB3PR_SSEN 0x3f +#define XHCI_USB3PRM 0xdc +#define XHCI_USB3FUS 0xe0 +#define XHCI_USB3FUS_SS_MASK 3 +#define XHCI_USB3FUS_SS_SHIFT 3 +#define XHCI_USB3PDO 0xe8 + +/* XHCI Memory Registers */ +#define XHCI_USB3_PORTSC(port) (0x510 + (port * 0x10)) +#define XHCI_USB3_PORTSC_CHST (0x7f << 17) +#define XHCI_USB3_PORTSC_WCE (1 << 25) /* Wake on Connect */ +#define XHCI_USB3_PORTSC_WDE (1 << 26) /* Wake on Disconnect */ +#define XHCI_USB3_PORTSC_WOE (1 << 27) /* Wake on Overcurrent */ +#define XHCI_USB3_PORTSC_WRC (1 << 19) /* Warm Reset Complete */ +#define XHCI_USB3_PORTSC_LWS (1 << 16) /* Link Write Strobe */ +#define XHCI_USB3_PORTSC_PED (1 << 1) /* Port Enabled/Disabled */ +#define XHCI_USB3_PORTSC_WPR (1 << 31) /* Warm Port Reset */ +#define XHCI_USB3_PORTSC_PLS (0xf << 5) /* Port Link State */ +#define XHCI_PLSR_DISABLED (4 << 5) /* Port is disabled */ +#define XHCI_PLSR_RXDETECT (5 << 5) /* Port is disconnected */ +#define XHCI_PLSR_POLLING (7 << 5) /* Port is polling */ +#define XHCI_PLSW_ENABLE (5 << 5) /* Transition from disabled */ + +#ifdef __SMM__ +void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ); +#endif + +#endif diff --git a/src/soc/intel/broadwell/iobp.c b/src/soc/intel/broadwell/iobp.c new file mode 100644 index 0000000000..870f6af597 --- /dev/null +++ b/src/soc/intel/broadwell/iobp.c @@ -0,0 +1,152 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#define IOBP_RETRY 1000 + +static inline int iobp_poll(void) +{ + unsigned try; + + for (try = IOBP_RETRY; try > 0; try--) { + u16 status = RCBA16(IOBPS); + if ((status & IOBPS_READY) == 0) + return 1; + udelay(10); + } + + printk(BIOS_ERR, "IOBP: timeout waiting for transaction to complete\n"); + return 0; +} + +u32 pch_iobp_read(u32 address) +{ + u16 status; + + if (!iobp_poll()) + return 0; + + /* Set the address */ + RCBA32(IOBPIRI) = address; + + /* READ OPCODE */ + status = RCBA16(IOBPS); + status &= ~IOBPS_MASK; + status |= IOBPS_READ; + RCBA16(IOBPS) = status; + + /* Undocumented magic */ + RCBA16(IOBPU) = IOBPU_MAGIC; + + /* Set ready bit */ + status = RCBA16(IOBPS); + status |= IOBPS_READY; + RCBA16(IOBPS) = status; + + if (!iobp_poll()) + return 0; + + /* Check for successful transaction */ + status = RCBA16(IOBPS); + if (status & IOBPS_TX_MASK) { + printk(BIOS_ERR, "IOBP: read 0x%08x failed\n", address); + return 0; + } + + /* Read IOBP data */ + return RCBA32(IOBPD); +} + +void pch_iobp_write(u32 address, u32 data) +{ + u16 status; + + if (!iobp_poll()) + return; + + /* Set the address */ + RCBA32(IOBPIRI) = address; + + /* WRITE OPCODE */ + status = RCBA16(IOBPS); + status &= ~IOBPS_MASK; + status |= IOBPS_WRITE; + RCBA16(IOBPS) = status; + + RCBA32(IOBPD) = data; + + /* Undocumented magic */ + RCBA16(IOBPU) = IOBPU_MAGIC; + + /* Set ready bit */ + status = RCBA16(IOBPS); + status |= IOBPS_READY; + RCBA16(IOBPS) = status; + + if (!iobp_poll()) + return; + + /* Check for successful transaction */ + status = RCBA16(IOBPS); + if (status & IOBPS_TX_MASK) + printk(BIOS_ERR, "IOBP: write 0x%08x failed\n", address); +} + +void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) +{ + u32 data = pch_iobp_read(address); + + /* Update the data */ + data &= andvalue; + data |= orvalue; + + pch_iobp_write(address, data); +} + +void pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp) +{ + if (!data || !resp) + return; + + *resp = -1; + if (!iobp_poll()) + return; + + /* RCBA2330[31:0] = Address */ + RCBA32(IOBPIRI) = addr; + /* RCBA2338[15:8] = opcode */ + RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x00ff) | op_code; + /* RCBA233A[15:8] = 0xf0 RCBA233A[7:0] = Route ID */ + RCBA16(IOBPU) = IOBPU_MAGIC | route_id; + + RCBA32(IOBPD) = *data; + /* Set RCBA2338[0] to trigger IOBP transaction*/ + RCBA16(IOBPS) = RCBA16(IOBPS) | 0x1; + + if (!iobp_poll()) + return; + + *resp = (RCBA16(IOBPS) & IOBPS_TX_MASK) >> 1; + *data = RCBA32(IOBPD); +} diff --git a/src/soc/intel/broadwell/lpc.c b/src/soc/intel/broadwell/lpc.c new file mode 100644 index 0000000000..04fba80604 --- /dev/null +++ b/src/soc/intel/broadwell/lpc.c @@ -0,0 +1,613 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void pch_enable_ioapic(struct device *dev) +{ + u32 reg32; + + set_ioapic_id(IO_APIC_ADDR, 0x02); + + /* affirm full set of redirection table entries ("write once") */ + reg32 = io_apic_read(IO_APIC_ADDR, 0x01); + + /* PCH-LP has 39 redirection entries */ + reg32 &= ~0x00ff0000; + reg32 |= 0x00270000; + + io_apic_write(IO_APIC_ADDR, 0x01, reg32); + + /* + * Select Boot Configuration register (0x03) and + * use Processor System Bus (0x01) to deliver interrupts. + */ + io_apic_write(IO_APIC_ADDR, 0x03, 0x01); +} + +/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control + * 0x00 - 0000 = Reserved + * 0x01 - 0001 = Reserved + * 0x02 - 0010 = Reserved + * 0x03 - 0011 = IRQ3 + * 0x04 - 0100 = IRQ4 + * 0x05 - 0101 = IRQ5 + * 0x06 - 0110 = IRQ6 + * 0x07 - 0111 = IRQ7 + * 0x08 - 1000 = Reserved + * 0x09 - 1001 = IRQ9 + * 0x0A - 1010 = IRQ10 + * 0x0B - 1011 = IRQ11 + * 0x0C - 1100 = IRQ12 + * 0x0D - 1101 = Reserved + * 0x0E - 1110 = IRQ14 + * 0x0F - 1111 = IRQ15 + * PIRQ[n]_ROUT[7] - PIRQ Routing Control + * 0x80 - The PIRQ is not routed. + */ + +static void pch_pirq_init(device_t dev) +{ + device_t irq_dev; + config_t *config = dev->chip_info; + + pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing); + pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing); + pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing); + pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing); + + pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing); + pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing); + pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing); + pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing); + + for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) { + u8 int_pin=0, int_line=0; + + if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI) + continue; + + int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN); + + switch (int_pin) { + case 1: /* INTA# */ int_line = config->pirqa_routing; break; + case 2: /* INTB# */ int_line = config->pirqb_routing; break; + case 3: /* INTC# */ int_line = config->pirqc_routing; break; + case 4: /* INTD# */ int_line = config->pirqd_routing; break; + } + + if (!int_line) + continue; + + pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line); + } +} + +static void pch_power_options(device_t dev) +{ + u16 reg16; + const char *state; + /* Get the chip configuration */ + config_t *config = dev->chip_info; + int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + + /* Which state do we want to goto after g3 (power restored)? + * 0 == S0 Full On + * 1 == S5 Soft Off + * + * If the option is not existent (Laptops), use Kconfig setting. + */ + get_option(&pwr_on, "power_on_after_fail"); + + reg16 = pci_read_config16(dev, GEN_PMCON_3); + reg16 &= 0xfffe; + switch (pwr_on) { + case MAINBOARD_POWER_OFF: + reg16 |= 1; + state = "off"; + break; + case MAINBOARD_POWER_ON: + reg16 &= ~1; + state = "on"; + break; + case MAINBOARD_POWER_KEEP: + reg16 &= ~1; + state = "state keep"; + break; + default: + state = "undefined"; + } + pci_write_config16(dev, GEN_PMCON_3, reg16); + printk(BIOS_INFO, "Set power %s after power failure.\n", state); + + /* GPE setup based on device tree configuration */ + enable_all_gpe(config->gpe0_en_1, config->gpe0_en_2, + config->gpe0_en_3, config->gpe0_en_4); + + /* SMI setup based on device tree configuration */ + enable_alt_smi(config->alt_gp_smi_en); +} + +static void pch_rtc_init(struct device *dev) +{ + u8 reg8; + int rtc_failed; + + reg8 = pci_read_config8(dev, GEN_PMCON_3); + rtc_failed = reg8 & RTC_BATTERY_DEAD; + if (rtc_failed) { + reg8 &= ~RTC_BATTERY_DEAD; + pci_write_config8(dev, GEN_PMCON_3, reg8); + printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); + } + + cmos_init(rtc_failed); +} + +static const struct reg_script pch_misc_init_script[] = { + /* Setup SLP signal assertion, SLP_S4=4s, SLP_S3=50ms */ + REG_PCI_RMW16(GEN_PMCON_3, ~((3 << 4)|(1 << 10)), + (1 << 3)|(1 << 11)|(1 << 12)), + /* Prepare sleep mode */ + REG_IO_RMW32(ACPI_BASE_ADDRESS + PM1_CNT, ~SLP_TYP, SCI_EN), + /* Setup NMI on errors, disable SERR */ + REG_IO_RMW8(0x61, ~0xf0, (1 << 2)), + /* Disable NMI sources */ + REG_IO_OR8(0x70, (1 << 7)), + /* Indicate DRAM init done for MRC */ + REG_PCI_OR8(GEN_PMCON_2, (1 << 7)), + /* Enable BIOS updates outside of SMM */ + REG_PCI_RMW8(0xdc, ~(1 << 5), 0), + /* Clear status bits to prevent unexpected wake */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x3310, 0x0000002f), + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x3f02, ~0x0000000f, 0), + /* Enable PCIe Releaxed Order */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2314, (1 << 31) | (1 << 7)), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x1114, (1 << 15) | (1 << 14)), + /* Setup SERIRQ, enable continuous mode */ + REG_PCI_OR8(SERIRQ_CNTL, (1 << 7) | (1 << 6)), +#if !CONFIG_SERIRQ_CONTINUOUS_MODE + REG_PCI_RMW8(SERIRQ_CNTL, ~(1 << 6), 0), +#endif + REG_SCRIPT_END +}; + +/* Magic register settings for power management */ +static const struct reg_script pch_pm_init_script[] = { + REG_PCI_WRITE8(0xa9, 0x46), + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x232c, ~1, 0), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x1100, 0x0000c13f), + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x2320, ~0x60, 0x10), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3314, 0x00012fff), + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + 0x3318, ~0x000f0330, 0x0dcf0400), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3324, 0x04000000), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3368, 0x00041400), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3388, 0x3f8ddbff), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33ac, 0x00007001), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33b0, 0x00181900), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33c0, 0x00060A00), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33d0, 0x06200840), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a28, 0x01010101), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a2c, 0x040c0404), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a9c, 0x9000000a), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b1c, 0x03808033), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b34, 0x80000009), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3348, 0x022ddfff), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x334c, 0x00000001), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3358, 0x0001c000), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3380, 0x3f8ddbff), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3384, 0x0001c7e1), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x338c, 0x0001c7e1), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3398, 0x0001c000), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33a8, 0x00181900), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33dc, 0x00080000), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33e0, 0x00000001), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a20, 0x0000040c), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a24, 0x01010101), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a30, 0x01010101), + REG_PCI_RMW32(0xac, ~0x00200000, 0), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x0410, 0x00000003), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2618, 0x08000000), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2300, 0x00000002), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x2600, 0x00000008), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x33b4, 0x00007001), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3350, 0x022ddfff), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3354, 0x00000001), + /* Power Optimizer */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33d4, 0x08000000), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33c8, 0x08000080), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b10, 0x0000883c), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b14, 0x1e0a4616), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b24, 0x40000005), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x2b20, 0x0005db01), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a80, 0x05145005), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + 0x3a84, 0x00001005), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33d4, 0x2fff2fb1), + REG_MMIO_OR32(RCBA_BASE_ADDRESS + 0x33c8, 0x00008000), + REG_SCRIPT_END +}; + +static void pch_enable_mphy(void) +{ + u32 gpio71_native = gpio_is_native(71); + u32 data_and = 0xffffffff; + u32 data_or = (1 << 14) | (1 << 13) | (1 << 12); + + if (gpio71_native) { + data_or |= (1 << 0); + if (pch_is_wpt()) { + data_and &= ~((1 << 7) | (1 << 6) | (1 << 3)); + data_or |= (1 << 5) | (1 << 4); + + if (pch_is_wpt_ulx()) { + /* Check if SATA and USB3 MPHY are enabled */ + u32 strap19 = pch_read_soft_strap(19); + strap19 &= ((1 << 31) | (1 << 30)); + strap19 >>= 30; + if (strap19 == 3) { + data_or |= (1 << 3); + printk(BIOS_DEBUG, "Enable ULX MPHY PG " + "control in single domain\n"); + } else if (strap19 == 0) { + printk(BIOS_DEBUG, "Enable ULX MPHY PG " + "control in split domains\n"); + } else { + printk(BIOS_DEBUG, "Invalid PCH Soft " + "Strap 19 configuration\n"); + } + } else { + data_or |= (1 << 3); + } + } + } + + pch_iobp_update(0xCF000000, data_and, data_or); +} + +static void pch_init_deep_sx(struct device *dev) +{ + config_t *config = dev->chip_info; + + if (config->deep_sx_enable_ac) { + RCBA32_OR(DEEP_S3_POL, DEEP_S3_EN_AC); + RCBA32_OR(DEEP_S5_POL, DEEP_S5_EN_AC); + } + + if (config->deep_sx_enable_dc) { + RCBA32_OR(DEEP_S3_POL, DEEP_S3_EN_DC); + RCBA32_OR(DEEP_S5_POL, DEEP_S5_EN_DC); + } + + if (config->deep_sx_enable_ac || config->deep_sx_enable_dc) + RCBA32_OR(DEEP_SX_CONFIG, + DEEP_SX_WAKE_PIN_EN | DEEP_SX_GP27_PIN_EN); +} + +/* Power Management init */ +static void pch_pm_init(struct device *dev) +{ + printk(BIOS_DEBUG, "PCH PM init\n"); + + pch_init_deep_sx(dev); + + pch_enable_mphy(); + + reg_script_run_on_dev(dev, pch_pm_init_script); + + if (pch_is_wpt()) { + RCBA32_OR(0x33e0, (1 << 4) | (1 << 1)); + RCBA32_OR(0x2b1c, (1 << 22) | (1 << 14) | (1 << 13)); + RCBA32(0x33e4) = 0x16bf0002; + RCBA32_OR(0x33e4, 0x1); + } + + pch_iobp_update(0xCA000000, ~0UL, 0x00000009); + + /* Set RCBA 0x2b1c[29]=1 if DSP disabled */ + if (RCBA32(FD) & PCH_DISABLE_ADSPD) + RCBA32_OR(0x2b1c, (1 << 29)); + +} + +static void pch_cg_init(device_t dev) +{ + u32 reg32; + u16 reg16; + + /* DMI */ + RCBA32_OR(0x2234, 0xf); + + reg16 = pci_read_config16(dev, GEN_PMCON_1); + reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */ + if (pch_is_wpt()) + reg16 &= ~(1 << 11); + else + reg16 |= (1 << 11); + reg16 |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 12); + reg16 |= (1 << 2); // PCI CLKRUN# Enable + pci_write_config16(dev, GEN_PMCON_1, reg16); + + /* + * RCBA + 0x2614[27:25,14:13,10,8] = 101,11,1,1 + * RCBA + 0x2614[23:16] = 0x20 + * RCBA + 0x2614[30:28] = 0x0 + * RCBA + 0x2614[26] = 1 (IF 0:2.0@0x08 >= 0x0b) + */ + RCBA32_AND_OR(0x2614, ~0x64ff0000, 0x0a206500); + + /* Check for 0:2.0@0x08 >= 0x0b */ + if (pch_is_wpt() || pci_read_config8(SA_DEV_IGD, 0x8) >= 0x0b) + RCBA32_OR(0x2614, (1 << 26)); + + RCBA32_OR(0x900, 0x0000031f); + + reg32 = RCBA32(CG); + if (RCBA32(0x3454) & (1 << 4)) + reg32 &= ~(1 << 29); // LPC Dynamic + else + reg32 |= (1 << 29); // LPC Dynamic + reg32 |= (1 << 31); // LP LPC + reg32 |= (1 << 30); // LP BLA + if (RCBA32(0x3454) & (1 << 4)) + reg32 &= ~(1 << 29); + else + reg32 |= (1 << 29); + reg32 |= (1 << 28); // GPIO Dynamic + reg32 |= (1 << 27); // HPET Dynamic + reg32 |= (1 << 26); // Generic Platform Event Clock + if (RCBA32(BUC) & PCH_DISABLE_GBE) + reg32 |= (1 << 23); // GbE Static + if (RCBA32(FD) & PCH_DISABLE_HD_AUDIO) + reg32 |= (1 << 21); // HDA Static + reg32 |= (1 << 22); // HDA Dynamic + RCBA32(CG) = reg32; + + /* PCH-LP LPC */ + if (pch_is_wpt()) + RCBA32_AND_OR(0x3434, ~0x1f, 0x17); + else + RCBA32_OR(0x3434, 0x7); + + /* SPI */ + RCBA32_OR(0x38c0, 0x3c07); + + pch_iobp_update(0xCE00C000, ~1UL, 0x00000000); +} + +static void pch_set_acpi_mode(void) +{ +#if CONFIG_HAVE_SMI_HANDLER + if (acpi_slp_type != 3) { + printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n"); + outb(APM_CNT_ACPI_DISABLE, APM_CNT); + printk(BIOS_DEBUG, "done.\n"); + } +#endif /* CONFIG_HAVE_SMI_HANDLER */ +} + +static void lpc_init(struct device *dev) +{ + /* Legacy initialization */ + isa_dma_init(); + pch_rtc_init(dev); + reg_script_run_on_dev(dev, pch_misc_init_script); + + /* Interrupt configuration */ + pch_enable_ioapic(dev); + pch_pirq_init(dev); + setup_i8259(); + i8259_configure_irq_trigger(9, 1); + + /* Initialize power management */ + pch_power_options(dev); + pch_pm_init(dev); + pch_cg_init(dev); + + pch_set_acpi_mode(); +} + +static void pch_lpc_add_mmio_resources(device_t dev) +{ + u32 reg; + struct resource *res; + const u32 default_decode_base = IO_APIC_ADDR; + + /* + * Just report all resources from IO-APIC base to 4GiB. Don't mark + * them reserved as that may upset the OS if this range is marked + * as reserved in the e820. + */ + res = new_resource(dev, OIC); + res->base = default_decode_base; + res->size = 0 - default_decode_base; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + /* RCBA */ + if (RCBA_BASE_ADDRESS < default_decode_base) { + res = new_resource(dev, RCBA); + res->base = RCBA_BASE_ADDRESS; + res->size = 16 * 1024; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | + IORESOURCE_FIXED | IORESOURCE_RESERVE; + } + + /* Check LPC Memory Decode register. */ + reg = pci_read_config32(dev, LGMR); + if (reg & 1) { + reg &= ~0xffff; + if (reg < default_decode_base) { + res = new_resource(dev, LGMR); + res->base = reg; + res->size = 16 * 1024; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | + IORESOURCE_FIXED | IORESOURCE_RESERVE; + } + } +} + +/* Default IO range claimed by the LPC device. The upper bound is exclusive. */ +#define LPC_DEFAULT_IO_RANGE_LOWER 0 +#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000 + +static inline int pch_io_range_in_default(u16 base, u16 size) +{ + /* Does it start above the range? */ + if (base >= LPC_DEFAULT_IO_RANGE_UPPER) + return 0; + + /* Is it entirely contained? */ + if (base >= LPC_DEFAULT_IO_RANGE_LOWER && + (base + size) < LPC_DEFAULT_IO_RANGE_UPPER) + return 1; + + /* This will return not in range for partial overlaps. */ + return 0; +} + +/* + * Note: this function assumes there is no overlap with the default LPC device's + * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER. + */ +static void pch_lpc_add_io_resource(device_t dev, u16 base, u16 size, int index) +{ + struct resource *res; + + if (pch_io_range_in_default(base, size)) + return; + + res = new_resource(dev, index); + res->base = base; + res->size = size; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void pch_lpc_add_gen_io_resources(device_t dev, int reg_value, int index) +{ + /* + * Check if the register is enabled. If so and the base exceeds the + * device's deafult claim range add the resoure. + */ + if (reg_value & 1) { + u16 base = reg_value & 0xfffc; + u16 size = (0x3 | ((reg_value >> 16) & 0xfc)) + 1; + pch_lpc_add_io_resource(dev, base, size, index); + } +} + +static void pch_lpc_add_io_resources(device_t dev) +{ + struct resource *res; + config_t *config = dev->chip_info; + + /* Add the default claimed IO range for the LPC device. */ + res = new_resource(dev, 0); + res->base = LPC_DEFAULT_IO_RANGE_LOWER; + res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + /* GPIOBASE */ + pch_lpc_add_io_resource(dev, GPIO_BASE_ADDRESS, + GPIO_BASE_SIZE, GPIO_BASE); + + /* PMBASE */ + pch_lpc_add_io_resource(dev, ACPI_BASE_ADDRESS, ACPI_BASE_SIZE, PMBASE); + + /* LPC Generic IO Decode range. */ + pch_lpc_add_gen_io_resources(dev, config->gen1_dec, LPC_GEN1_DEC); + pch_lpc_add_gen_io_resources(dev, config->gen2_dec, LPC_GEN2_DEC); + pch_lpc_add_gen_io_resources(dev, config->gen3_dec, LPC_GEN3_DEC); + pch_lpc_add_gen_io_resources(dev, config->gen4_dec, LPC_GEN4_DEC); +} + +static void pch_lpc_read_resources(device_t dev) +{ + global_nvs_t *gnvs; + + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* Add non-standard MMIO resources. */ + pch_lpc_add_mmio_resources(dev); + + /* Add IO resources. */ + pch_lpc_add_io_resources(dev); + + /* Allocate ACPI NVS in CBMEM */ + gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t)); + if (acpi_slp_type != 3 && gnvs) + memset(gnvs, 0, sizeof(global_nvs_t)); +} + +static struct device_operations device_ops = { + .read_resources = &pch_lpc_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &lpc_init, + .scan_bus = &scan_static_bus, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + PCH_LPT_LP_SAMPLE, + PCH_LPT_LP_PREMIUM, + PCH_LPT_LP_MAINSTREAM, + PCH_LPT_LP_VALUE, + PCH_WPT_HSW_U_SAMPLE, + PCH_WPT_BDW_U_SAMPLE, + PCH_WPT_BDW_U_PREMIUM, + PCH_WPT_BDW_U_BASE, + PCH_WPT_BDW_Y_SAMPLE, + PCH_WPT_BDW_Y_PREMIUM, + PCH_WPT_BDW_Y_BASE, + PCH_WPT_BDW_H, + 0 +}; + +static const struct pci_driver pch_lpc __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/me.c b/src/soc/intel/broadwell/me.c new file mode 100644 index 0000000000..e83f84f82f --- /dev/null +++ b/src/soc/intel/broadwell/me.c @@ -0,0 +1,1086 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a ramstage driver for the Intel Management Engine found in the + * southbridge. It handles the required boot-time messages over the + * MMIO-based Management Engine Interface to tell the ME that the BIOS is + * finished with POST. Additional messages are defined for debug but are + * not used unless the console loglevel is high enough. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_CHROMEOS +#include +#include +#endif + +/* Path that the BIOS should take based on ME state */ +static const char *me_bios_path_values[] = { + [ME_NORMAL_BIOS_PATH] = "Normal", + [ME_S3WAKE_BIOS_PATH] = "S3 Wake", + [ME_ERROR_BIOS_PATH] = "Error", + [ME_RECOVERY_BIOS_PATH] = "Recovery", + [ME_DISABLE_BIOS_PATH] = "Disable", + [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update", +}; + +/* MMIO base address for MEI interface */ +static u32 mei_base_address; + +#if CONFIG_DEBUG_INTEL_ME +static void mei_dump(void *ptr, int dword, int offset, const char *type) +{ + struct mei_csr *csr; + + printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset); + + switch (offset) { + case MEI_H_CSR: + case MEI_ME_CSR_HA: + csr = ptr; + if (!csr) { + printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword); + break; + } + printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u " + "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth, + csr->buffer_read_ptr, csr->buffer_write_ptr, + csr->ready, csr->reset, csr->interrupt_generate, + csr->interrupt_status, csr->interrupt_enable); + break; + case MEI_ME_CB_RW: + case MEI_H_CB_WW: + printk(BIOS_SPEW, "CB: 0x%08x\n", dword); + break; + default: + printk(BIOS_SPEW, "0x%08x\n", offset); + break; + } +} +#else +# define mei_dump(ptr,dword,offset,type) do {} while (0) +#endif + +/* + * ME/MEI access helpers using memcpy to avoid aliasing. + */ + +static inline void mei_read_dword_ptr(void *ptr, int offset) +{ + u32 dword = read32(mei_base_address + offset); + memcpy(ptr, &dword, sizeof(dword)); + mei_dump(ptr, dword, offset, "READ"); +} + +static inline void mei_write_dword_ptr(void *ptr, int offset) +{ + u32 dword = 0; + memcpy(&dword, ptr, sizeof(dword)); + write32(mei_base_address + offset, dword); + mei_dump(ptr, dword, offset, "WRITE"); +} + +static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset) +{ + u32 dword = pci_read_config32(dev, offset); + memcpy(ptr, &dword, sizeof(dword)); + mei_dump(ptr, dword, offset, "PCI READ"); +} + +static inline void read_host_csr(struct mei_csr *csr) +{ + mei_read_dword_ptr(csr, MEI_H_CSR); +} + +static inline void write_host_csr(struct mei_csr *csr) +{ + mei_write_dword_ptr(csr, MEI_H_CSR); +} + +static inline void read_me_csr(struct mei_csr *csr) +{ + mei_read_dword_ptr(csr, MEI_ME_CSR_HA); +} + +static inline void write_cb(u32 dword) +{ + write32(mei_base_address + MEI_H_CB_WW, dword); + mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE"); +} + +static inline u32 read_cb(void) +{ + u32 dword = read32(mei_base_address + MEI_ME_CB_RW); + mei_dump(NULL, dword, MEI_ME_CB_RW, "READ"); + return dword; +} + +/* Wait for ME ready bit to be asserted */ +static int mei_wait_for_me_ready(void) +{ + struct mei_csr me; + unsigned try = ME_RETRY; + + while (try--) { + read_me_csr(&me); + if (me.ready) + return 0; + udelay(ME_DELAY); + } + + printk(BIOS_ERR, "ME: failed to become ready\n"); + return -1; +} + +static void mei_reset(void) +{ + struct mei_csr host; + + if (mei_wait_for_me_ready() < 0) + return; + + /* Reset host and ME circular buffers for next message */ + read_host_csr(&host); + host.reset = 1; + host.interrupt_generate = 1; + write_host_csr(&host); + + if (mei_wait_for_me_ready() < 0) + return; + + /* Re-init and indicate host is ready */ + read_host_csr(&host); + host.interrupt_generate = 1; + host.ready = 1; + host.reset = 0; + write_host_csr(&host); +} + +static int mei_send_packet(struct mei_header *mei, void *req_data) +{ + struct mei_csr host; + unsigned ndata, n; + u32 *data; + + /* Number of dwords to write */ + ndata = mei->length >> 2; + + /* Pad non-dword aligned request message length */ + if (mei->length & 3) + ndata++; + if (!ndata) { + printk(BIOS_DEBUG, "ME: request has no data\n"); + return -1; + } + ndata++; /* Add MEI header */ + + /* + * Make sure there is still room left in the circular buffer. + * Reset the buffer pointers if the requested message will not fit. + */ + read_host_csr(&host); + if ((host.buffer_depth - host.buffer_write_ptr) < ndata) { + printk(BIOS_ERR, "ME: circular buffer full, resetting...\n"); + mei_reset(); + read_host_csr(&host); + } + + /* Ensure the requested length will fit in the circular buffer. */ + if ((host.buffer_depth - host.buffer_write_ptr) < ndata) { + printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n", + ndata + 2, host.buffer_depth); + return -1; + } + + /* Write MEI header */ + mei_write_dword_ptr(mei, MEI_H_CB_WW); + ndata--; + + /* Write message data */ + data = req_data; + for (n = 0; n < ndata; ++n) + write_cb(*data++); + + /* Generate interrupt to the ME */ + read_host_csr(&host); + host.interrupt_generate = 1; + write_host_csr(&host); + + /* Make sure ME is ready after sending request data */ + return mei_wait_for_me_ready(); +} + +static int mei_send_data(u8 me_address, u8 host_address, + void *req_data, int req_bytes) +{ + struct mei_header header = { + .client_address = me_address, + .host_address = host_address, + }; + struct mei_csr host; + int current = 0; + u8 *req_ptr = req_data; + + while (!header.is_complete) { + int remain = req_bytes - current; + int buf_len; + + read_host_csr(&host); + buf_len = host.buffer_depth - host.buffer_write_ptr; + + if (buf_len > remain) { + /* Send all remaining data as final message */ + header.length = req_bytes - current; + header.is_complete = 1; + } else { + /* Send as much data as the buffer can hold */ + header.length = buf_len; + } + + mei_send_packet(&header, req_ptr); + + req_ptr += header.length; + current += header.length; + } + + return 0; +} + +static int mei_send_header(u8 me_address, u8 host_address, + void *header, int header_len, int complete) +{ + struct mei_header mei = { + .client_address = me_address, + .host_address = host_address, + .length = header_len, + .is_complete = complete, + }; + return mei_send_packet(&mei, header); +} + +static int mei_recv_msg(void *header, int header_bytes, + void *rsp_data, int rsp_bytes) +{ + struct mei_header mei_rsp; + struct mei_csr me, host; + unsigned ndata, n; + unsigned expected; + u32 *data; + + /* Total number of dwords to read from circular buffer */ + expected = (rsp_bytes + sizeof(mei_rsp) + header_bytes) >> 2; + if (rsp_bytes & 3) + expected++; + + if (mei_wait_for_me_ready() < 0) + return -1; + + /* + * The interrupt status bit does not appear to indicate that the + * message has actually been received. Instead we wait until the + * expected number of dwords are present in the circular buffer. + */ + for (n = ME_RETRY; n; --n) { + read_me_csr(&me); + if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected) + break; + udelay(ME_DELAY); + } + if (!n) { + printk(BIOS_ERR, "ME: timeout waiting for data: expected " + "%u, available %u\n", expected, + me.buffer_write_ptr - me.buffer_read_ptr); + return -1; + } + + /* Read and verify MEI response header from the ME */ + mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW); + if (!mei_rsp.is_complete) { + printk(BIOS_ERR, "ME: response is not complete\n"); + return -1; + } + + /* Handle non-dword responses and expect at least the header */ + ndata = mei_rsp.length >> 2; + if (mei_rsp.length & 3) + ndata++; + if (ndata != (expected - 1)) { + printk(BIOS_ERR, "ME: response is missing data %d != %d\n", + ndata, (expected - 1)); + return -1; + } + + /* Read response header from the ME */ + data = header; + for (n = 0; n < (header_bytes >> 2); ++n) + *data++ = read_cb(); + ndata -= header_bytes >> 2; + + /* Make sure caller passed a buffer with enough space */ + if (ndata != (rsp_bytes >> 2)) { + printk(BIOS_ERR, "ME: not enough room in response buffer: " + "%u != %u\n", ndata, rsp_bytes >> 2); + return -1; + } + + /* Read response data from the circular buffer */ + data = rsp_data; + for (n = 0; n < ndata; ++n) + *data++ = read_cb(); + + /* Tell the ME that we have consumed the response */ + read_host_csr(&host); + host.interrupt_status = 1; + host.interrupt_generate = 1; + write_host_csr(&host); + + return mei_wait_for_me_ready(); +} + +static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi, + void *req_data, int req_bytes, + void *rsp_data, int rsp_bytes) +{ + struct mkhi_header mkhi_rsp; + + /* Send header */ + if (mei_send_header(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS, + mkhi, sizeof(*mkhi), req_bytes ? 0 : 1) < 0) + return -1; + + /* Send data if available */ + if (req_bytes && mei_send_data(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS, + req_data, req_bytes) < 0) + return -1; + + /* Return now if no response expected */ + if (!rsp_bytes) + return 0; + + /* Read header and data */ + if (mei_recv_msg(&mkhi_rsp, sizeof(mkhi_rsp), + rsp_data, rsp_bytes) < 0) + return -1; + + if (!mkhi_rsp.is_response || + mkhi->group_id != mkhi_rsp.group_id || + mkhi->command != mkhi_rsp.command) { + printk(BIOS_ERR, "ME: invalid response, group %u ?= %u," + "command %u ?= %u, is_response %u\n", mkhi->group_id, + mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command, + mkhi_rsp.is_response); + return -1; + } + + return 0; +} + +static inline int mei_sendrecv_icc(struct icc_header *icc, + void *req_data, int req_bytes, + void *rsp_data, int rsp_bytes) +{ + struct icc_header icc_rsp; + + /* Send header */ + if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS, + icc, sizeof(*icc), req_bytes ? 0 : 1) < 0) + return -1; + + /* Send data if available */ + if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS, + req_data, req_bytes) < 0) + return -1; + + /* Read header and data, if needed */ + if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp), + rsp_data, rsp_bytes) < 0) + return -1; + + return 0; +} + +/* + * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read + * state machine on the BIOS end doesn't match the ME's state machine. + */ +static void intel_me_mbp_give_up(device_t dev) +{ + struct mei_csr csr; + + pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP); + + read_host_csr(&csr); + csr.reset = 1; + csr.interrupt_generate = 1; + write_host_csr(&csr); +} + +/* + * mbp clear routine. This will wait for the ME to indicate that + * the MBP has been read and cleared. + */ +static void intel_me_mbp_clear(device_t dev) +{ + int count; + struct me_hfs2 hfs2; + + /* Wait for the mbp_cleared indicator */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); + if (hfs2.mbp_cleared) + break; + udelay(ME_DELAY); + } + + if (count == 0) { + printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n"); + intel_me_mbp_give_up(dev); + } else { + printk(BIOS_INFO, "ME: MBP cleared\n"); + } +} + +static void me_print_fw_version(mbp_fw_version_name *vers_name) +{ + if (!vers_name) { + printk(BIOS_ERR, "ME: mbp missing version report\n"); + return; + } + + printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n", + vers_name->major_version, vers_name->minor_version, + vers_name->hotfix_version, vers_name->build_version); +} + +#if CONFIG_DEBUG_INTEL_ME +/* Get ME Firmware Capabilities */ +static int mkhi_get_fwcaps(mbp_mefwcaps *cap) +{ + u32 rule_id = 0; + struct me_fwcaps cap_msg; + struct mkhi_header mkhi = { + .group_id = MKHI_GROUP_ID_FWCAPS, + .command = MKHI_FWCAPS_GET_RULE, + }; + + /* Send request and wait for response */ + if (mei_sendrecv_mkhi(&mkhi, &rule_id, sizeof(u32), + &cap_msg, sizeof(cap_msg)) < 0) { + printk(BIOS_ERR, "ME: GET FWCAPS message failed\n"); + return -1; + } + *cap = cap_msg.caps_sku; + return 0; +} + +static inline void print_cap(const char *name, int state) +{ + printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n", + name, state ? " en" : "dis"); +} + +/* Get ME Firmware Capabilities */ +static void me_print_fwcaps(mbp_mefwcaps *cap) +{ + mbp_mefwcaps local_caps; + if (!cap) { + cap = &local_caps; + printk(BIOS_ERR, "ME: mbp missing fwcaps report\n"); + if (mkhi_get_fwcaps(cap)) + return; + } + + print_cap("Full Network manageability", cap->full_net); + print_cap("Regular Network manageability", cap->std_net); + print_cap("Manageability", cap->manageability); + print_cap("IntelR Anti-Theft (AT)", cap->intel_at); + print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls); + print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc); + print_cap("ICC Over Clocking", cap->icc_over_clocking); + print_cap("Protected Audio Video Path (PAVP)", cap->pavp); + print_cap("IPV6", cap->ipv6); + print_cap("KVM Remote Control (KVM)", cap->kvm); + print_cap("Outbreak Containment Heuristic (OCH)", cap->och); + print_cap("Virtual LAN (VLAN)", cap->vlan); + print_cap("TLS", cap->tls); + print_cap("Wireless LAN (WLAN)", cap->wlan); +} +#endif + +/* Send END OF POST message to the ME */ +static int mkhi_end_of_post(void) +{ + struct mkhi_header mkhi = { + .group_id = MKHI_GROUP_ID_GEN, + .command = MKHI_END_OF_POST, + }; + u32 eop_ack; + + /* Send request and wait for response */ + if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &eop_ack, sizeof(eop_ack)) < 0) { + printk(BIOS_ERR, "ME: END OF POST message failed\n"); + return -1; + } + + printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack); + return 0; +} + +/* Send END OF POST message to the ME */ +static int mkhi_end_of_post_noack(void) +{ + struct mkhi_header mkhi = { + .group_id = MKHI_GROUP_ID_GEN, + .command = MKHI_END_OF_POST_NOACK, + }; + + /* Send request, do not wait for response */ + if (mei_sendrecv_mkhi(&mkhi, NULL, 0, NULL, 0) < 0) { + printk(BIOS_ERR, "ME: END OF POST NOACK message failed\n"); + return -1; + } + + printk(BIOS_INFO, "ME: END OF POST NOACK message successful\n"); + return 0; +} + +/* Send HMRFPO LOCK message to the ME */ +static int mkhi_hmrfpo_lock(void) +{ + struct mkhi_header mkhi = { + .group_id = MKHI_GROUP_ID_HMRFPO, + .command = MKHI_HMRFPO_LOCK, + }; + u32 ack; + + /* Send request and wait for response */ + if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &ack, sizeof(ack)) < 0) { + printk(BIOS_ERR, "ME: HMRFPO LOCK message failed\n"); + return -1; + } + + printk(BIOS_INFO, "ME: HMRPFO LOCK message successful (%d)\n", ack); + return 0; +} + +/* Send HMRFPO LOCK message to the ME, do not wait for response */ +static int mkhi_hmrfpo_lock_noack(void) +{ + struct mkhi_header mkhi = { + .group_id = MKHI_GROUP_ID_HMRFPO, + .command = MKHI_HMRFPO_LOCK_NOACK, + }; + + /* Send request, do not wait for response */ + if (mei_sendrecv_mkhi(&mkhi, NULL, 0, NULL, 0) < 0) { + printk(BIOS_ERR, "ME: HMRFPO LOCK NOACK message failed\n"); + return -1; + } + + printk(BIOS_INFO, "ME: HMRPFO LOCK NOACK message successful\n"); + return 0; +} + +static void intel_me_finalize(device_t dev) +{ + u32 reg32; + + /* S3 path will have hidden this device already */ + if (!mei_base_address || mei_base_address == 0xfffffff0) + return; + + /* Make sure IO is disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Hide the PCI device */ + RCBA32_OR(FD2, PCH_DISABLE_MEI1); + RCBA32(FD2); +} + +static int me_icc_set_clock_enables(u32 mask) +{ + struct icc_clock_enables_msg clk = { + .clock_enables = 0, /* Turn off specified clocks */ + .clock_mask = mask, + .no_response = 1, /* Do not expect response */ + }; + struct icc_header icc = { + .api_version = ICC_API_VERSION_LYNXPOINT, + .icc_command = ICC_SET_CLOCK_ENABLES, + .length = sizeof(clk), + }; + + /* Send request and wait for response */ + if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) { + printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n"); + return -1; + } else { + printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask); + } + + return 0; +} + +/* Determine the path that we should take based on ME status */ +static me_bios_path intel_me_path(device_t dev) +{ + me_bios_path path = ME_DISABLE_BIOS_PATH; + struct me_hfs hfs; + struct me_hfs2 hfs2; + + /* Check and dump status */ + intel_me_status(); + + pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS); + pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); + + /* Check Current Working State */ + switch (hfs.working_state) { + case ME_HFS_CWS_NORMAL: + path = ME_NORMAL_BIOS_PATH; + break; + case ME_HFS_CWS_REC: + path = ME_RECOVERY_BIOS_PATH; + break; + default: + path = ME_DISABLE_BIOS_PATH; + break; + } + + /* Check Current Operation Mode */ + switch (hfs.operation_mode) { + case ME_HFS_MODE_NORMAL: + break; + case ME_HFS_MODE_DEBUG: + case ME_HFS_MODE_DIS: + case ME_HFS_MODE_OVER_JMPR: + case ME_HFS_MODE_OVER_MEI: + default: + path = ME_DISABLE_BIOS_PATH; + break; + } + + /* Check for any error code and valid firmware and MBP */ + if (hfs.error_code || hfs.fpt_bad) + path = ME_ERROR_BIOS_PATH; + + /* Check if the MBP is ready */ + if (!hfs2.mbp_rdy) { + printk(BIOS_CRIT, "%s: mbp is not ready!\n", + __FUNCTION__); + path = ME_ERROR_BIOS_PATH; + } + +#if CONFIG_ELOG + if (path != ME_NORMAL_BIOS_PATH) { + struct elog_event_data_me_extended data = { + .current_working_state = hfs.working_state, + .operation_state = hfs.operation_state, + .operation_mode = hfs.operation_mode, + .error_code = hfs.error_code, + .progress_code = hfs2.progress_code, + .current_pmevent = hfs2.current_pmevent, + .current_state = hfs2.current_state, + }; + elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path); + elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT, + &data, sizeof(data)); + } +#endif + + return path; +} + +/* Prepare ME for MEI messages */ +static int intel_mei_setup(device_t dev) +{ + struct resource *res; + struct mei_csr host; + u32 reg32; + + /* Find the MMIO base for the ME interface */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res || res->base == 0 || res->size == 0) { + printk(BIOS_DEBUG, "ME: MEI resource not present!\n"); + return -1; + } + mei_base_address = res->base; + + /* Ensure Memory and Bus Master bits are set */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Clean up status for next message */ + read_host_csr(&host); + host.interrupt_generate = 1; + host.ready = 1; + host.reset = 0; + write_host_csr(&host); + + return 0; +} + +/* Read the Extend register hash of ME firmware */ +static int intel_me_extend_valid(device_t dev) +{ + struct me_heres status; + u32 extend[8] = {0}; + int i, count = 0; + + pci_read_dword_ptr(dev, &status, PCI_ME_HERES); + if (!status.extend_feature_present) { + printk(BIOS_ERR, "ME: Extend Feature not present\n"); + return -1; + } + + if (!status.extend_reg_valid) { + printk(BIOS_ERR, "ME: Extend Register not valid\n"); + return -1; + } + + switch (status.extend_reg_algorithm) { + case PCI_ME_EXT_SHA1: + count = 5; + printk(BIOS_DEBUG, "ME: Extend SHA-1: "); + break; + case PCI_ME_EXT_SHA256: + count = 8; + printk(BIOS_DEBUG, "ME: Extend SHA-256: "); + break; + default: + printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n", + status.extend_reg_algorithm); + return -1; + } + + for (i = 0; i < count; ++i) { + extend[i] = pci_read_config32(dev, PCI_ME_HER(i)); + printk(BIOS_DEBUG, "%08x", extend[i]); + } + printk(BIOS_DEBUG, "\n"); + +#if CONFIG_CHROMEOS + /* Save hash in NVS for the OS to verify */ + chromeos_set_me_hash(extend, count); +#endif + + return 0; +} + +static void intel_me_print_mbp(me_bios_payload *mbp_data) +{ + me_print_fw_version(mbp_data->fw_version_name); + +#if CONFIG_DEBUG_INTEL_ME + me_print_fwcaps(mbp_data->fw_capabilities); +#endif + + if (mbp_data->plat_time) { + printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n", + mbp_data->plat_time->wake_event_mrst_time_ms); + printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n", + mbp_data->plat_time->mrst_pltrst_time_ms); + printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n", + mbp_data->plat_time->pltrst_cpurst_time_ms); + } +} + +static u32 me_to_host_words_pending(void) +{ + struct mei_csr me; + read_me_csr(&me); + if (!me.ready) + return 0; + return (me.buffer_write_ptr - me.buffer_read_ptr) & + (me.buffer_depth - 1); +} + +struct mbp_payload { + mbp_header header; + u32 data[0]; +}; + +/* + * Read and print ME MBP data + * + * Return -1 to indicate a problem (give up) + * Return 0 to indicate success (send LOCK+EOP) + * Return 1 to indicate success (send LOCK+EOP with NOACK) + */ +static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) +{ + mbp_header mbp_hdr; + u32 me2host_pending; + struct mei_csr host; + struct me_hfs2 hfs2; + struct mbp_payload *mbp; + int i; + int ret = 0; + + pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); + + if (!hfs2.mbp_rdy) { + printk(BIOS_ERR, "ME: MBP not ready\n"); + intel_me_mbp_give_up(dev); + return -1; + } + + me2host_pending = me_to_host_words_pending(); + if (!me2host_pending) { + printk(BIOS_ERR, "ME: no mbp data!\n"); + intel_me_mbp_give_up(dev); + return -1; + } + + /* we know for sure that at least the header is there */ + mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW); + + if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) || + (me2host_pending < mbp_hdr.mbp_size)) { + printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words" + " buffer contains %d words\n", + mbp_hdr.num_entries, mbp_hdr.mbp_size, + me2host_pending); + intel_me_mbp_give_up(dev); + return -1; + } + mbp = malloc(mbp_hdr.mbp_size * sizeof(u32)); + if (!mbp) { + intel_me_mbp_give_up(dev); + return -1; + } + + mbp->header = mbp_hdr; + me2host_pending--; + + i = 0; + while (i != me2host_pending) { + mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW); + i++; + } + + read_host_csr(&host); + + /* Check that read and write pointers are equal. */ + if (host.buffer_read_ptr != host.buffer_write_ptr) { + printk(BIOS_INFO, "ME: MBP Read/Write pointer mismatch\n"); + printk(BIOS_INFO, "ME: MBP Waiting for MBP cleared flag\n"); + + /* Tell ME that the host has finished reading the MBP. */ + host.interrupt_generate = 1; + host.reset = 0; + write_host_csr(&host); + + /* Wait for the mbp_cleared indicator. */ + intel_me_mbp_clear(dev); + } else { + /* Indicate NOACK messages should be used. */ + ret = 1; + } + + /* Dump out the MBP contents. */ +#if CONFIG_DEBUG_INTEL_ME + printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n", + mbp->header.num_entries, mbp->header.mbp_size); + for (i = 0; i < mbp->header.mbp_size - 1; i++) { + printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]); + } +#endif + +#define ASSIGN_FIELD_PTR(field_,val_) \ + { \ + mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \ + break; \ + } + + /* Setup the pointers in the me_bios_payload structure. */ + for (i = 0; i < mbp->header.mbp_size - 1;) { + mbp_item_header *item = (void *)&mbp->data[i]; + + switch(MBP_MAKE_IDENT(item->app_id, item->item_id)) { + case MBP_IDENT(KERNEL, FW_VER): + ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]); + + case MBP_IDENT(ICC, PROFILE): + ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]); + + case MBP_IDENT(INTEL_AT, STATE): + ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, FW_CAP): + ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, ROM_BIST): + ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, PLAT_KEY): + ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, FW_TYPE): + ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, MFS_FAILURE): + ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, PLAT_TIME): + ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]); + + case MBP_IDENT(NFC, SUPPORT_DATA): + ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]); + } + i += item->length; + } + #undef ASSIGN_FIELD_PTR + + return ret; +} + +/* Check whether ME is present and do basic init */ +static void intel_me_init(device_t dev) +{ + config_t *config = dev->chip_info; + me_bios_path path = intel_me_path(dev); + me_bios_payload mbp_data; + int mbp_ret; + struct me_hfs hfs; + struct mei_csr csr; + + /* Do initial setup and determine the BIOS path */ + printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]); + + if (path == ME_NORMAL_BIOS_PATH) { + /* Validate the extend register */ + intel_me_extend_valid(dev); + } + + memset(&mbp_data, 0, sizeof(mbp_data)); + + /* + * According to the ME9 BWG, BIOS is required to fetch MBP data in + * all boot flows except S3 Resume. + */ + + /* Prepare MEI MMIO interface */ + if (intel_mei_setup(dev) < 0) + return; + + /* Read ME MBP data */ + mbp_ret = intel_me_read_mbp(&mbp_data, dev); + if (mbp_ret < 0) + return; + intel_me_print_mbp(&mbp_data); + + /* Set clock enables according to devicetree */ + if (config && config->icc_clock_disable) + me_icc_set_clock_enables(config->icc_clock_disable); + + /* Make sure ME is in a mode that expects EOP */ + pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS); + + /* Abort and leave device alone if not normal mode */ + if (hfs.fpt_bad || + hfs.working_state != ME_HFS_CWS_NORMAL || + hfs.operation_mode != ME_HFS_MODE_NORMAL) + return; + + if (mbp_ret) { + /* + * MBP Cleared wait is skipped, + * Do not expect ACK and reset when complete. + */ + + /* Send HMRFPO Lock command, no response */ + mkhi_hmrfpo_lock_noack(); + + /* Send END OF POST command, no response */ + mkhi_end_of_post_noack(); + + /* Assert reset and interrupt */ + read_host_csr(&csr); + csr.interrupt_generate = 1; + csr.reset = 1; + write_host_csr(&csr); + } else { + /* + * MBP Cleared wait was not skipped + */ + + /* Send HMRFPO LOCK command */ + mkhi_hmrfpo_lock(); + + /* Send EOP command so ME stops accepting other commands */ + mkhi_end_of_post(); + } +} + +static void intel_me_enable(device_t dev) +{ +#if CONFIG_HAVE_ACPI_RESUME + /* Avoid talking to the device in S3 path */ + if (acpi_slp_type == 3) { + dev->enabled = 0; + pch_disable_devfn(dev); + } +#endif +} + +static struct device_operations device_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .enable = &intel_me_enable, + .init = &intel_me_init, + .final = &intel_me_finalize, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c3a, /* Low Power */ + 0x9cba, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver intel_me __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/me_status.c b/src/soc/intel/broadwell/me_status.c new file mode 100644 index 0000000000..18d4825d2c --- /dev/null +++ b/src/soc/intel/broadwell/me_status.c @@ -0,0 +1,321 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void me_read_dword_ptr(void *ptr, int offset) +{ + u32 dword = pci_read_config32(PCH_DEV_ME, offset); + memcpy(ptr, &dword, sizeof(dword)); +} + +#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) + +/* HFS1[3:0] Current Working State Values */ +static const char *me_cws_values[] = { + [ME_HFS_CWS_RESET] = "Reset", + [ME_HFS_CWS_INIT] = "Initializing", + [ME_HFS_CWS_REC] = "Recovery", + [3] = "Unknown (3)", + [4] = "Unknown (4)", + [ME_HFS_CWS_NORMAL] = "Normal", + [ME_HFS_CWS_WAIT] = "Platform Disable Wait", + [ME_HFS_CWS_TRANS] = "OP State Transition", + [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In", + [9] = "Unknown (9)", + [10] = "Unknown (10)", + [11] = "Unknown (11)", + [12] = "Unknown (12)", + [13] = "Unknown (13)", + [14] = "Unknown (14)", + [15] = "Unknown (15)", +}; + +/* HFS1[8:6] Current Operation State Values */ +static const char *me_opstate_values[] = { + [ME_HFS_STATE_PREBOOT] = "Preboot", + [ME_HFS_STATE_M0_UMA] = "M0 with UMA", + [ME_HFS_STATE_M3] = "M3 without UMA", + [ME_HFS_STATE_M0] = "M0 without UMA", + [ME_HFS_STATE_BRINGUP] = "Bring up", + [ME_HFS_STATE_ERROR] = "M0 without UMA but with error" +}; + +/* HFS[19:16] Current Operation Mode Values */ +static const char *me_opmode_values[] = { + [ME_HFS_MODE_NORMAL] = "Normal", + [ME_HFS_MODE_DEBUG] = "Debug", + [ME_HFS_MODE_DIS] = "Soft Temporary Disable", + [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper", + [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message" +}; + +/* HFS[15:12] Error Code Values */ +static const char *me_error_values[] = { + [ME_HFS_ERROR_NONE] = "No Error", + [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure", + [ME_HFS_ERROR_IMAGE] = "Image Failure", + [ME_HFS_ERROR_DEBUG] = "Debug Failure" +}; + +/* HFS2[31:28] ME Progress Code */ +static const char *me_progress_values[] = { + [ME_HFS2_PHASE_ROM] = "ROM Phase", + [ME_HFS2_PHASE_BUP] = "BUP Phase", + [ME_HFS2_PHASE_UKERNEL] = "uKernel Phase", + [ME_HFS2_PHASE_POLICY] = "Policy Module", + [ME_HFS2_PHASE_MODULE_LOAD] = "Module Loading", + [ME_HFS2_PHASE_UNKNOWN] = "Unknown", + [ME_HFS2_PHASE_HOST_COMM] = "Host Communication" +}; + +/* HFS2[27:24] Power Management Event */ +static const char *me_pmevent_values[] = { + [ME_HFS2_PMEVENT_CLEAN_MOFF_MX_WAKE] = + "Clean Moff->Mx wake", + [ME_HFS2_PMEVENT_MOFF_MX_WAKE_ERROR] = + "Moff->Mx wake after an error", + [ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET] = + "Clean global reset", + [ME_HFS2_PMEVENT_CLEAN_GLOBAL_RESET_ERROR] = + "Global reset after an error", + [ME_HFS2_PMEVENT_CLEAN_ME_RESET] = + "Clean Intel ME reset", + [ME_HFS2_PMEVENT_ME_RESET_EXCEPTION] = + "Intel ME reset due to exception", + [ME_HFS2_PMEVENT_PSEUDO_ME_RESET] = + "Pseudo-global reset", + [ME_HFS2_PMEVENT_S0MO_SXM3] = + "S0/M0->Sx/M3", + [ME_HFS2_PMEVENT_SXM3_S0M0] = + "Sx/M3->S0/M0", + [ME_HFS2_PMEVENT_NON_PWR_CYCLE_RESET] = + "Non-power cycle reset", + [ME_HFS2_PMEVENT_PWR_CYCLE_RESET_M3] = + "Power cycle reset through M3", + [ME_HFS2_PMEVENT_PWR_CYCLE_RESET_MOFF] = + "Power cycle reset through Moff", + [ME_HFS2_PMEVENT_SXMX_SXMOFF] = + "Sx/Mx->Sx/Moff" +}; + +/* Progress Code 0 states */ +static const char *me_progress_rom_values[] = { + [ME_HFS2_STATE_ROM_BEGIN] = "BEGIN", + [ME_HFS2_STATE_ROM_DISABLE] = "DISABLE" +}; + +/* Progress Code 1 states */ +static const char *me_progress_bup_values[] = { + [ME_HFS2_STATE_BUP_INIT] = + "Initialization starts", + [ME_HFS2_STATE_BUP_DIS_HOST_WAKE] = + "Disable the host wake event", + [ME_HFS2_STATE_BUP_FLOW_DET] = + "Flow determination start process", + [ME_HFS2_STATE_BUP_VSCC_ERR] = + "Error reading/matching the VSCC table in the descriptor", + [ME_HFS2_STATE_BUP_CHECK_STRAP] = + "Check to see if straps say ME DISABLED", + [ME_HFS2_STATE_BUP_PWR_OK_TIMEOUT] = + "Timeout waiting for PWROK", + [ME_HFS2_STATE_BUP_MANUF_OVRD_STRAP] = + "Possibly handle BUP manufacturing override strap", + [ME_HFS2_STATE_BUP_M3] = + "Bringup in M3", + [ME_HFS2_STATE_BUP_M0] = + "Bringup in M0", + [ME_HFS2_STATE_BUP_FLOW_DET_ERR] = + "Flow detection error", + [ME_HFS2_STATE_BUP_M3_CLK_ERR] = + "M3 clock switching error", + [ME_HFS2_STATE_BUP_CPU_RESET_DID_TIMEOUT_MEM_MISSING] = + "Host error - CPU reset timeout, DID timeout, memory missing", + [ME_HFS2_STATE_BUP_M3_KERN_LOAD] = + "M3 kernel load", + [ME_HFS2_STATE_BUP_T32_MISSING] = + "T34 missing - cannot program ICC", + [ME_HFS2_STATE_BUP_WAIT_DID] = + "Waiting for DID BIOS message", + [ME_HFS2_STATE_BUP_WAIT_DID_FAIL] = + "Waiting for DID BIOS message failure", + [ME_HFS2_STATE_BUP_DID_NO_FAIL] = + "DID reported no error", + [ME_HFS2_STATE_BUP_ENABLE_UMA] = + "Enabling UMA", + [ME_HFS2_STATE_BUP_ENABLE_UMA_ERR] = + "Enabling UMA error", + [ME_HFS2_STATE_BUP_SEND_DID_ACK] = + "Sending DID Ack to BIOS", + [ME_HFS2_STATE_BUP_SEND_DID_ACK_ERR] = + "Sending DID Ack to BIOS error", + [ME_HFS2_STATE_BUP_M0_CLK] = + "Switching clocks in M0", + [ME_HFS2_STATE_BUP_M0_CLK_ERR] = + "Switching clocks in M0 error", + [ME_HFS2_STATE_BUP_TEMP_DIS] = + "ME in temp disable", + [ME_HFS2_STATE_BUP_M0_KERN_LOAD] = + "M0 kernel load", +}; + +/* Progress Code 3 states */ +static const char *me_progress_policy_values[] = { + [ME_HFS2_STATE_POLICY_ENTRY] = "Entery into Policy Module", + [ME_HFS2_STATE_POLICY_RCVD_S3] = "Received S3 entry", + [ME_HFS2_STATE_POLICY_RCVD_S4] = "Received S4 entry", + [ME_HFS2_STATE_POLICY_RCVD_S5] = "Received S5 entry", + [ME_HFS2_STATE_POLICY_RCVD_UPD] = "Received UPD entry", + [ME_HFS2_STATE_POLICY_RCVD_PCR] = "Received PCR entry", + [ME_HFS2_STATE_POLICY_RCVD_NPCR] = "Received NPCR entry", + [ME_HFS2_STATE_POLICY_RCVD_HOST_WAKE] = "Received host wake", + [ME_HFS2_STATE_POLICY_RCVD_AC_DC] = "Received AC<>DC switch", + [ME_HFS2_STATE_POLICY_RCVD_DID] = "Received DRAM Init Done", + [ME_HFS2_STATE_POLICY_VSCC_NOT_FOUND] = + "VSCC Data not found for flash device", + [ME_HFS2_STATE_POLICY_VSCC_INVALID] = + "VSCC Table is not valid", + [ME_HFS2_STATE_POLICY_FPB_ERR] = + "Flash Partition Boundary is outside address space", + [ME_HFS2_STATE_POLICY_DESCRIPTOR_ERR] = + "ME cannot access the chipset descriptor region", + [ME_HFS2_STATE_POLICY_VSCC_NO_MATCH] = + "Required VSCC values for flash parts do not match", +}; + +void intel_me_status(void) +{ + struct me_hfs _hfs, *hfs = &_hfs; + struct me_hfs2 _hfs2, *hfs2 = &_hfs2; + + me_read_dword_ptr(hfs, PCI_ME_HFS); + me_read_dword_ptr(hfs2, PCI_ME_HFS2); + + /* Check Current States */ + printk(BIOS_DEBUG, "ME: FW Partition Table : %s\n", + hfs->fpt_bad ? "BAD" : "OK"); + printk(BIOS_DEBUG, "ME: Bringup Loader Failure : %s\n", + hfs->ft_bup_ld_flr ? "YES" : "NO"); + printk(BIOS_DEBUG, "ME: Firmware Init Complete : %s\n", + hfs->fw_init_complete ? "YES" : "NO"); + printk(BIOS_DEBUG, "ME: Manufacturing Mode : %s\n", + hfs->mfg_mode ? "YES" : "NO"); + printk(BIOS_DEBUG, "ME: Boot Options Present : %s\n", + hfs->boot_options_present ? "YES" : "NO"); + printk(BIOS_DEBUG, "ME: Update In Progress : %s\n", + hfs->update_in_progress ? "YES" : "NO"); + printk(BIOS_DEBUG, "ME: Current Working State : %s\n", + me_cws_values[hfs->working_state]); + printk(BIOS_DEBUG, "ME: Current Operation State : %s\n", + me_opstate_values[hfs->operation_state]); + printk(BIOS_DEBUG, "ME: Current Operation Mode : %s\n", + me_opmode_values[hfs->operation_mode]); + printk(BIOS_DEBUG, "ME: Error Code : %s\n", + me_error_values[hfs->error_code]); + printk(BIOS_DEBUG, "ME: Progress Phase : %s\n", + me_progress_values[hfs2->progress_code]); + printk(BIOS_DEBUG, "ME: Power Management Event : %s\n", + me_pmevent_values[hfs2->current_pmevent]); + + printk(BIOS_DEBUG, "ME: Progress Phase State : "); + switch (hfs2->progress_code) { + case ME_HFS2_PHASE_ROM: /* ROM Phase */ + printk(BIOS_DEBUG, "%s", + me_progress_rom_values[hfs2->current_state]); + break; + + case ME_HFS2_PHASE_UKERNEL: /* uKernel Phase */ + printk(BIOS_DEBUG, "0x%02x", hfs2->current_state); + break; + + case ME_HFS2_PHASE_BUP: /* Bringup Phase */ + if (hfs2->current_state < ARRAY_SIZE(me_progress_bup_values) + && me_progress_bup_values[hfs2->current_state]) + printk(BIOS_DEBUG, "%s", + me_progress_bup_values[hfs2->current_state]); + else + printk(BIOS_DEBUG, "0x%02x", hfs2->current_state); + break; + + case ME_HFS2_PHASE_POLICY: /* Policy Module Phase */ + if (hfs2->current_state < ARRAY_SIZE(me_progress_policy_values) + && me_progress_policy_values[hfs2->current_state]) + printk(BIOS_DEBUG, "%s", + me_progress_policy_values[hfs2->current_state]); + else + printk(BIOS_DEBUG, "0x%02x", hfs2->current_state); + break; + + case ME_HFS2_PHASE_HOST_COMM: /* Host Communication Phase */ + if (!hfs2->current_state) + printk(BIOS_DEBUG, "Host communication established"); + else + printk(BIOS_DEBUG, "0x%02x", hfs2->current_state); + break; + + default: + printk(BIOS_DEBUG, "Unknown phase: 0x%02x state: 0x%02x", + hfs2->progress_code, hfs2->current_state); + } + printk(BIOS_DEBUG, "\n"); +} +#endif + +void intel_me_hsio_version(uint16_t *version, uint16_t *checksum) +{ + int count; + u32 hsiover; + struct me_hfs hfs; + + /* Query for HSIO version, overloads H_GS and HFS */ + pci_write_config32(PCH_DEV_ME, PCI_ME_H_GS, + ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER); + + /* Must wait for ME acknowledgement */ + for (count = ME_RETRY; count > 0; --count) { + me_read_dword_ptr(&hfs, PCI_ME_HFS); + if (hfs.bios_msg_ack) + break; + udelay(ME_DELAY); + } + if (!count) { + printk(BIOS_ERR, "ERROR: ME failed to respond\n"); + return; + } + + /* HSIO version should be in HFS_5 */ + hsiover = pci_read_config32(PCH_DEV_ME, PCI_ME_HFS5); + *version = hsiover >> 16; + *checksum = hsiover & 0xffff; + + printk(BIOS_DEBUG, "ME: HSIO Version : %d (CRC 0x%04x)\n", + *version, *checksum); + + /* Reset registers to normal behavior */ + pci_write_config32(PCH_DEV_ME, PCI_ME_H_GS, + ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER); +} diff --git a/src/soc/intel/broadwell/memmap.c b/src/soc/intel/broadwell/memmap.c new file mode 100644 index 0000000000..dd4856575a --- /dev/null +++ b/src/soc/intel/broadwell/memmap.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static unsigned long get_top_of_ram(void) +{ + /* + * Base of DPR is top of usable DRAM below 4GiB. The register has + * 1 MiB alignment and reports the TOP of the range, the base + * must be calculated from the size in MiB in bits 11:4. + */ + u32 dpr = pci_read_config32(SA_DEV_ROOT, DPR); + u32 tom = dpr & ~((1 << 20) - 1); + + /* Subtract DMA Protected Range size if enabled */ + if (dpr & DPR_EPM) + tom -= (dpr & DPR_SIZE_MASK) << 16; + +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + /* Allocate some space for FSP */ + tom -= CONFIG_FSP_RESERVED_MEM_SIZE; +#endif /* CONFIG_PLATFORM_USES_FSP */ + + return (unsigned long)tom; +} + +void *cbmem_top(void) +{ + return (void *)get_top_of_ram(); +} diff --git a/src/soc/intel/broadwell/microcode/Makefile.inc b/src/soc/intel/broadwell/microcode/Makefile.inc new file mode 100644 index 0000000000..bf9e345dbd --- /dev/null +++ b/src/soc/intel/broadwell/microcode/Makefile.inc @@ -0,0 +1 @@ +cpu_microcode-y += microcode_blob.c diff --git a/src/soc/intel/broadwell/microcode/microcode-M7240651_0000001C.h b/src/soc/intel/broadwell/microcode/microcode-M7240651_0000001C.h new file mode 100644 index 0000000000..df7fc77d72 --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode-M7240651_0000001C.h @@ -0,0 +1,1280 @@ + 0x00000001, 0x0000001c, 0x07032014, 0x00040651, + 0x4f9aa4c4, 0x00000001, 0x00000072, 0x00004fd0, + 0x00005000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000a1, 0x00020001, 0x0000001c, + 0x00000002, 0x00001331, 0x20140702, 0x00001331, + 0x00000001, 0x00040651, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54803536, 0x5b42092a, 0x9f337d90, 0x538e6ae5, + 0xee797c87, 0x40b34be7, 0x2058da4a, 0x02665b1f, + 0xa19308a3, 0x5b19c4b7, 0x4a1b425b, 0x7d6a74f6, + 0x81624193, 0x3a559605, 0x5475280b, 0xe7319d58, + 0x48624ca7, 0x507af030, 0x3b32d96a, 0x30164068, + 0x5284d2f5, 0x725b2915, 0xf63c9280, 0x44b7c142, + 0xe67ca7b3, 0xd6f163e7, 0xcdf51f3c, 0x41d180a1, + 0xcc3931b1, 0xf7a544a9, 0x7f6bf77d, 0xfc45a45f, + 0xf0985836, 0x652d7e2e, 0x0324b1f3, 0x24b9548c, + 0x7bcae7a5, 0xdcdebf79, 0x27015922, 0x0c83c606, + 0x3d2ceeb7, 0x61c5eec8, 0x6b6899c6, 0x3e500531, + 0xf08bfa44, 0xb304a8f4, 0xcee8f713, 0x2912c786, + 0xfae6c34c, 0xa5292960, 0x7d63e389, 0xaa257a01, + 0x1fb25054, 0x963fc676, 0x5bcb9fd3, 0x58f369a4, + 0xf6e3beb2, 0xa58b5eb0, 0x33c7eba4, 0x37fe8b66, + 0x00714403, 0xf0fd0c4e, 0xaa122996, 0x9a55b184, + 0x00201507, 0xc9fb6e3a, 0x11ab60c8, 0x80ff6e84, + 0xc37aabdd, 0x0fc23175, 0xb0b18c34, 0xf1ec806c, + 0x00000011, 0x93ec6a8e, 0xe7e59e0e, 0x8354a863, + 0x6532cc70, 0x6b941f6e, 0xe6efb015, 0x813a0672, + 0x4bd6a134, 0xe7d2ae2e, 0xb801fd17, 0xc6730db1, + 0xffaf70c6, 0x99963a56, 0x552b2448, 0x06da244f, + 0xbddb7094, 0xc41bbd43, 0x8566bdda, 0x8730b02b, + 0x0ffc1836, 0x57f083f5, 0xbc7eb4f9, 0x93720c90, + 0xb948e082, 0x646a29c2, 0xab785ca6, 0x22d6de29, + 0xad6632ee, 0xf781c405, 0xab8c189f, 0xe9f84888, + 0xdfc91edd, 0x7c42229e, 0x713f0b2e, 0xbfec8862, + 0xd7041476, 0x30cdc9df, 0x6a884797, 0x4df51550, + 0xe6e3d09a, 0x2b63aff3, 0xbe437a9a, 0x2bbc6a7e, + 0x36cd4cac, 0x4c3a5d83, 0x22e35ba1, 0x2602cf9d, + 0x90506b16, 0xad5e4dae, 0xfd02e76c, 0x41ecfaf1, + 0x5885656a, 0xf1da2947, 0x9a6e02ea, 0x338ab563, + 0x73de7a3e, 0x80131004, 0xd82962c5, 0x8e8c88ef, + 0x7ae0d2fa, 0x3420c82a, 0x202e795c, 0x3a0d9404, + 0x3d337908, 0xc1c8f56d, 0x1a9d5f9a, 0x8d294c4d, + 0x054fa4f0, 0x1feb3cba, 0x1fcaf41f, 0x36ce8dfa, + 0x15765644, 0x5741c08d, 0xd258e716, 0x67d51f76, + 0xe16efcf6, 0x53877ae9, 0x5632053f, 0x3efc3569, + 0x21202e38, 0x59367def, 0x73e8c31b, 0x5558b394, + 0x3801fe26, 0xa291f1ad, 0xb853571c, 0x43d8845b, + 0x919a9ede, 0x5eaf4d90, 0x986cb6b6, 0x822a630b, + 0x0904e79e, 0xa20dcab6, 0x05470b25, 0x62dc1169, + 0x0de7ce15, 0xd4cafd8a, 0x2216b4fa, 0x3ba658df, + 0xf84db879, 0x94365ec0, 0xffd76c6b, 0xcf5003d0, + 0x2ab8d6dd, 0xb87ce90c, 0x77b341c4, 0xe9bdd2d1, + 0x05343cca, 0x0d0a7813, 0xcc23da22, 0xbbaef3c9, + 0x82bb35d0, 0xc8d97e27, 0x062c07f0, 0x31fc6743, + 0xa5d7b86e, 0xfb399a4a, 0xea0ca298, 0x45c56f0c, + 0x9de334e0, 0x2b808722, 0xdcb90fee, 0x86880439, + 0x4bb5520f, 0x2f8ccd3f, 0xb31154f5, 0x76b037c1, + 0xc8cf720d, 0x9e53125e, 0x495ab1d6, 0xdc09098f, + 0x90ff69e5, 0x4fb52efa, 0xe07dbe04, 0x505dce0e, + 0x9930358e, 0xc7243a95, 0xacae76b3, 0x23702ced, + 0x36ba2ba8, 0x12f6a4d6, 0x6291a5df, 0x43e09751, + 0xd86e8606, 0xe5b8d173, 0x84cf7f38, 0x5a2a732d, + 0xea8dec57, 0x075ab4bd, 0x3093ea05, 0x7ddc4623, + 0x9eeac07d, 0x0bae6c5e, 0x1170d85f, 0x54585ce5, + 0x424b5930, 0x6f962ed0, 0x6291c170, 0xda9a243b, + 0x7a1aa460, 0x07fe426b, 0x3e0fbcef, 0xe6f65e2e, + 0x16a76698, 0x2ee2c974, 0xd42dd042, 0x60b2d4c2, + 0x84ca0de9, 0x1b321482, 0xd80847e7, 0x97cf9fc9, + 0xabad4e62, 0x4c5e7534, 0xba474a3d, 0x4b386fe1, + 0xb1d3bd4a, 0x66f2e748, 0xff997d29, 0x7f9a5ecb, + 0x08b74697, 0xd5ff51e3, 0xf0e80f08, 0xbc8a3750, + 0x96c2b150, 0x993ddd82, 0xb1fcad1a, 0x39c457ed, + 0x8e7887a9, 0x951385c2, 0x5e192577, 0x5ece4be6, + 0xd8aa0cce, 0xda9db0dd, 0xf0a65605, 0xcbe133fb, + 0xd62d187c, 0x43d65c21, 0xd9ff512b, 0x2c1e670f, + 0x94862f11, 0x2ad5876f, 0x0347f479, 0x837c9d9a, + 0xd588cfb5, 0x3184bcbe, 0x4d29209d, 0xb11531fa, + 0xcf60605f, 0x8582c22e, 0xf80aec84, 0x56770992, + 0xb008270e, 0xe61f0247, 0x5b96ca82, 0xddf6a6d7, + 0xa8fd309f, 0x5a37ebf0, 0x89c55922, 0xa1d3e943, + 0xc7437f57, 0x8767c3b9, 0x2aace409, 0xd3ffea65, + 0x01673382, 0x3062cc4d, 0xdc3ca70e, 0x72ec823f, + 0x013dfcf0, 0x3cea3c0f, 0x5c6f9892, 0x0401238b, + 0xd0f5c9a9, 0x83d5363a, 0x20594afe, 0xf31625f7, + 0x36d9bf4d, 0x979d10e2, 0x82ec9621, 0x1575da7e, + 0x1e48b107, 0xcf273476, 0x8f6bc6ce, 0xc468a1f1, + 0x19304de2, 0x8a514ade, 0x0da8ed49, 0x89bba358, + 0x4fcde67f, 0x1b236a87, 0xbd9c34c4, 0xc31e7624, + 0x8d4e1b94, 0xca715a48, 0x57aab513, 0xdc01097a, + 0x61536abc, 0x9ab66e22, 0xc3e9acac, 0xf9793dc1, + 0x01d27d3e, 0xec783b0a, 0x7f8a7b0a, 0x8952bd32, + 0x78f97900, 0xea165074, 0x6a3b9b4f, 0x6994be45, + 0x97b278db, 0x2d7a1059, 0x2a9a584d, 0x3102f971, + 0x3dd2edfd, 0x75d40781, 0xbd8bb3f7, 0x69c9e2ad, + 0x2924453d, 0xf971a611, 0xc44c6a20, 0x6458ddf0, + 0x344e948d, 0x99861094, 0xffc216ce, 0x46a544ac, + 0xa0e12280, 0x2342bdd0, 0xd264153a, 0xef7c5510, + 0x982fdb4b, 0xaa8061e1, 0xeeb4cb06, 0x1c4e24bb, + 0x35137ad0, 0xd383e7b0, 0xb3515b98, 0x34ab789c, + 0xc6677101, 0x3a179ec6, 0x8e1b7f83, 0xbc952258, + 0x528cc506, 0xbb0ee496, 0x041a20c7, 0x435c1764, + 0xc5ffbfe5, 0x7aadad66, 0xba7c49b5, 0x16961f55, + 0x53a973b0, 0x82b7c322, 0x6108d300, 0x1e465f56, + 0xde5b0cdf, 0x1db4c843, 0xdc84068d, 0x746b86a8, + 0xe18bb690, 0x9c31e6c3, 0x3fbe45db, 0x9fcd70bc, + 0xebf1e3bb, 0xf293ed6a, 0x9acc3c5f, 0xc2d8d4a7, + 0xb4f10f0e, 0x8f08aade, 0x7ff658e3, 0x571f87e4, + 0x53911020, 0x8eabc16c, 0x66de43e6, 0x86313e1d, + 0x091638f2, 0x4fabd2cf, 0xf64a8806, 0x34a9f3c4, + 0x342eb98c, 0x6da221f8, 0x5dc9ad3d, 0x3f235ca4, + 0xf13aae29, 0xe58aae0d, 0xbb0f06b0, 0x0146ce07, + 0xdb82eed1, 0xb8a5b35e, 0x5ad2f1af, 0xc904facd, + 0x9cb2684d, 0x664cdcc1, 0x8b83058c, 0x3a144bad, + 0xd818e9fb, 0x1a4378e3, 0x087ee2c7, 0xc45812e8, + 0xd10705f1, 0x040bdc37, 0x24dcced6, 0x5d917109, + 0x6544b517, 0x321bea6d, 0xb4c74b5a, 0x93b11971, + 0xdbd04da0, 0x9180fdad, 0x9b5c205b, 0x8e123be0, + 0x2752e398, 0x74ab49b4, 0x3b8090ae, 0x8e564f95, + 0xae58ebb9, 0x7c2ab771, 0x8d8b4559, 0x4aae59b0, + 0x3d57724b, 0x5324f318, 0x3f6b4f5b, 0xa7c2dd69, + 0x75cc2f3e, 0x58d81e09, 0x724a5ddd, 0x00373586, + 0xfe1bfc27, 0xebeed8c4, 0x9f4df4dd, 0xa3d7150f, + 0xd4cf1d99, 0x77663800, 0xba7326ee, 0xf799bb1d, + 0x17f711a1, 0x0b683496, 0x16734362, 0x1c1ec0fa, + 0xbd7606d5, 0xde0ecfaa, 0x4fa3d7e1, 0x18b5cafe, + 0x86ded1cb, 0x84eb26a4, 0xe15ad21b, 0x6222135a, + 0x4813612b, 0xf435160d, 0x8bb9cdef, 0xc0febebc, + 0x908ea268, 0x6114ec6d, 0xde72772c, 0x2de363f2, + 0xac07caff, 0x4d1367d2, 0x5ccb4e20, 0xb8c2480c, + 0xd40a88f1, 0x4c8aaf04, 0xec69eadf, 0x08d603d4, + 0x1d6b72c2, 0x45cb2279, 0x9c18a457, 0xb1eefcd5, + 0x6f5bbe8a, 0x8656da63, 0x5abd01ef, 0xbd3a0fa9, + 0x07f8b848, 0x4723e8da, 0x1c8a7404, 0x0ee2c60d, + 0xf4d73710, 0x2e98dd50, 0x42265393, 0x607cae51, + 0x5ad2d65a, 0x443fae0a, 0x212bdac1, 0x94eff1e7, + 0x8fd0d83d, 0xf3f48729, 0xaa613eeb, 0x532716af, + 0x22f67b55, 0x197dd562, 0x30bbc619, 0x452ca5b8, + 0x69125584, 0xbe8ffd8f, 0xcdc33841, 0x1afadf4f, + 0x6c327b0a, 0x1ffee636, 0xbc3e313d, 0x2274f02f, + 0x1d4bd1ab, 0xadf7f661, 0xc6ae5dba, 0x65c67cce, + 0xd8ba01b4, 0x067ec15e, 0xcdd98197, 0xf63a814d, + 0xa63ef3b1, 0x3a0f7ab7, 0x0b141297, 0xbd16dffd, + 0x80de07c9, 0x5b855491, 0x775d7917, 0x79039980, + 0xc4f0b5a2, 0x7ad189f3, 0x5b808e2c, 0x6e6c48f8, + 0xea4b291a, 0x244153fb, 0xd866387a, 0x0fbad87f, + 0x37fd2697, 0xe38d68cc, 0xd56bb9be, 0x0fe9183c, + 0xfe4286c7, 0xa9238f4e, 0x57c6bafe, 0x7e7c64da, + 0xf5f0b3c6, 0xf2174839, 0x9622aabd, 0xbfb9add1, + 0x7a9d83f3, 0x22cdc940, 0xd0aed140, 0xb2842a1c, + 0x19350ede, 0x844cea83, 0x03f824b6, 0x2d6a80d1, + 0xcc7234f5, 0x64e522f9, 0x68463ec1, 0xc22ca25a, + 0xf6fb480b, 0x92df3534, 0xcd143a85, 0xcba797d1, + 0xab3040eb, 0xaa862cda, 0xeb8dbb5a, 0x72f87be7, + 0x0574be93, 0x7967a4e8, 0xc43d5618, 0x95f48b0f, + 0x605384f1, 0x49d7bbd0, 0x20e6ff24, 0x8891ad61, + 0xbe37fb81, 0xa14cc9ac, 0x1737a15d, 0x0d8c64c8, + 0xf31ed8cd, 0xaeba1a38, 0x99b73598, 0xfb58e711, + 0xe2cd0a2a, 0xba3ae60f, 0x53874128, 0xca6bd9f6, + 0xdaa3865a, 0xdf558d1e, 0x69c074ea, 0xd2d74d88, + 0xd7924cfa, 0x9cfbba04, 0x560eb2ac, 0xb58eb3fb, + 0xac0f471a, 0x8b9775a6, 0x04f93abd, 0x71830a7b, + 0xabece5a2, 0x7d0b9603, 0x447e0437, 0x9b19fdf0, + 0x2aeb904f, 0xb6c581ab, 0x69c4a6e6, 0x9e996bf9, + 0x28345395, 0x8797c013, 0xab770f48, 0x02414cb3, + 0xf1400aa8, 0x77b85d38, 0x6c1519d4, 0x68aa8d18, + 0x4ad589f6, 0xde108567, 0x26ce3cc8, 0x855d739d, + 0x4123b448, 0x0acfaf11, 0x3d1d706e, 0xcf6dfbc2, + 0x02869b0e, 0x8ad4c4b5, 0xb118ed06, 0x19defc29, + 0x955de3e2, 0x4246d3bb, 0x20d55907, 0x9263ee1a, + 0xe3b1a896, 0x2aa64af6, 0xac652be4, 0xc319f5db, + 0x1f87bdbc, 0x5d35a264, 0x915af64d, 0xa63f8b9d, + 0x8b596f71, 0xb289a637, 0xbf4df8f4, 0x637223dd, + 0x1c7b17aa, 0xb73cff48, 0x490b6e3b, 0xfb9cc770, + 0xbdddc085, 0xf61b9342, 0xf632cb9c, 0x7a1273c8, + 0xe12e5792, 0xc8874fda, 0xbac1a2cb, 0x2525df42, + 0x14735a6b, 0x48b123d4, 0xbf80739f, 0xa5acac23, + 0xe509b461, 0xd72e2e2c, 0x94553b2d, 0x61274a8a, + 0xbad8722a, 0x9cde98cb, 0x497a8db7, 0x84bca500, + 0x85ddf493, 0xcb5717a7, 0xdbada31f, 0x34e9d14e, + 0xc23d20d7, 0xf3a32825, 0x688ea606, 0xecbc1379, + 0xf7cc7e17, 0x98826691, 0x0a2fc103, 0xfa891b0d, + 0x6031f829, 0x3d93a25c, 0x45ebed73, 0xd5e938b5, + 0xb3a8e0cb, 0xd271fb09, 0x6c01ec65, 0x26528bfb, + 0x358e2521, 0xde0ea304, 0x3aa0e26d, 0x06bbe682, + 0x0e141d87, 0x80f84192, 0xd2ca916c, 0x38193f29, + 0x1f26fcb8, 0x48b0f72c, 0xa9e5b9d4, 0x757b1925, + 0x2171c824, 0x7a5cdb28, 0x67a9cd39, 0x58e682cf, + 0xfe773460, 0x54f56488, 0x4fab4a18, 0xd5d62f56, + 0xaa1ff73c, 0x663a3adc, 0x5b28b030, 0xcf7c2fae, + 0xe86c08aa, 0x675ecdf9, 0x6c54904e, 0x59bac9cd, + 0xe830b6b5, 0x9c72f3c8, 0xc2d2dfc2, 0x7eea1860, + 0x3e68956e, 0xcabee365, 0x2abecc3f, 0xf5584efd, + 0x97494ab2, 0x4547de19, 0x23b75177, 0xf5158de7, + 0x8f887368, 0x82aa37f9, 0x45edb6b6, 0x8cd4567e, + 0x35a853f1, 0xabdfdde1, 0x126a775d, 0x74971303, + 0x92965554, 0x884af013, 0x01678e07, 0x5ce5e949, + 0x0e92a0b7, 0xb4ae83b3, 0xb33f17e1, 0xc1eaae2c, + 0xf4d8a373, 0x7aaa8222, 0xbdf9d56b, 0x4b34135f, + 0x5ec53983, 0xd79506ad, 0x48931578, 0x907b2609, + 0x129ca0e3, 0xd1fd7d15, 0xd6cff42e, 0xe91542cc, + 0x006dd750, 0xd45db570, 0x0d6787cb, 0x41fac008, + 0xa14abb50, 0xe3836ddb, 0xa08d7c2a, 0x0c42081e, + 0x99231ac9, 0xc572a6d2, 0xedd8f7c7, 0x299a0245, + 0x1dd8dc9d, 0x67f43cff, 0xe59c0063, 0xb53706a5, + 0x4779de2e, 0x01d4ae62, 0xf1b3af1f, 0x04fe1683, + 0xa6ae95d2, 0xc049f706, 0x35da73f9, 0x786c55fe, + 0x45541fe0, 0x0b712835, 0x0ba80808, 0xfbfa8301, + 0xf243658e, 0x3fa0a207, 0xf1ad361a, 0x1022cd47, + 0x9931194a, 0x458118ba, 0x65b01c42, 0x9eaed094, + 0xea3c1c7d, 0x1f54744a, 0x3a93c482, 0xb624d29f, + 0x78015089, 0x0a68782b, 0xf5497256, 0x0d9422b2, + 0xf79ca89c, 0xd0a62c46, 0xf6bfb279, 0x87639d4f, + 0x853431ca, 0x7cbf82ce, 0xb0b8579f, 0x91dbf9ca, + 0xa4b41a8d, 0x6cc03669, 0x0a8459aa, 0xa84998ee, + 0xb0e5442d, 0xc1206664, 0x1d66b29c, 0x2aa662fe, + 0x3ff230f5, 0xb3b9ea5e, 0x28d59572, 0x071a2784, + 0x48ad8df4, 0xb672a99d, 0x431837c5, 0x312da9d2, + 0x552f1f1e, 0xba76bf31, 0x0fde86fc, 0x3a4b0e5b, + 0x27767132, 0x3207cd66, 0x7acd2d75, 0xa04c2b7a, + 0xbeb5576e, 0xe69396d7, 0xdb471676, 0xc1155dd9, + 0xedeff438, 0xad1fac56, 0x2bdd6c24, 0x1b6a29ed, + 0x3150d31f, 0xfef32ddc, 0x4478c8cf, 0xe291fdb3, + 0xbff85812, 0x07f945a0, 0x2be5471e, 0xcc38f9f9, + 0x2372ce7c, 0x8a9ffc48, 0x4e76ee7a, 0x6f6edd41, + 0x192c0cc1, 0xe2edaa52, 0x455a388c, 0x33f1129e, + 0x3a0db93d, 0x3182e227, 0xd751be55, 0x8f36e600, + 0x3cfdd41f, 0x4b9aef6d, 0x2f7793dc, 0xc53a7f45, + 0x8fc9ed8e, 0x515715ae, 0x0fd65cf7, 0xd9a798e8, + 0x515ac27f, 0xd45cbc76, 0x8bde099b, 0xff9917b9, + 0x8aafd3e3, 0x5fa447d1, 0x7dcff5a9, 0xbba90ca7, + 0x306066d0, 0xd8ce22e7, 0x9b82e925, 0x1878501a, + 0x3c04683c, 0x8178343c, 0x2bf7e5ee, 0xe9e47825, + 0x3b7e90d9, 0x4e702270, 0x66092537, 0x8c499ea6, + 0xfa7d1ac9, 0x08ca5fe7, 0xcaf8de79, 0x1fed7575, + 0xc0878a9c, 0xe4c7df3b, 0xd1192e90, 0xae1c68d1, + 0x8ae43a18, 0x378c02d4, 0xbcfa07c2, 0xc9f916d7, + 0x0e219276, 0xf56251a5, 0xfa7a412a, 0x34cf60f7, + 0x518c5a65, 0x8bd147a9, 0x51043034, 0xb63867c8, + 0x0ef93a61, 0x5913a6ab, 0x5f6fe3d4, 0x2ea3d257, + 0x720d761d, 0x4b5c0dff, 0xa9a9067a, 0x3576ccf3, + 0x52a971d7, 0xeba0bc8a, 0x609de37d, 0xe6cc6920, + 0xf5a5622e, 0xd0c42306, 0xf9d9eca2, 0xc24b0b89, + 0x317c001f, 0x99f19460, 0xeab46ee8, 0x14af43e9, + 0xa56855a2, 0x335f45cd, 0xfc976335, 0x7fa14450, + 0x36a6f269, 0xe6b4a19c, 0xb702c383, 0x3e161b8b, + 0xcdf62b5e, 0xc79e2106, 0x11f6c5f3, 0x0528cf91, + 0x76c17fda, 0x2092699f, 0xed122ee1, 0xd0442e54, + 0xf533a93a, 0xc1dddb81, 0x4c48e8a9, 0x517fba08, + 0xc05af246, 0x19ea1e1a, 0x7a53892b, 0xf81e9376, + 0xa50e2b38, 0x3f269768, 0xd0d29924, 0x51e6eed6, + 0xc4c07b1f, 0x1c5b173e, 0x80cbaab2, 0x8ba8b11e, + 0xdc2b9580, 0xa5d279d3, 0xf264d55e, 0x5e0eb0ad, + 0xae46c12b, 0xe1dde70b, 0x47f68516, 0x68dab0ba, + 0xe978b014, 0xa0e24cc6, 0x961da73d, 0x60662676, + 0x185f3c24, 0xd7da33ce, 0xe37e39b2, 0x64ee0f85, + 0x53208460, 0x09262285, 0x165ef996, 0x66df340d, + 0xd07ad742, 0x10423944, 0x5f72f0b7, 0xbb6389ed, + 0xcba698f1, 0xa1b0f049, 0x800dc191, 0xb44316c1, + 0x202e479d, 0x6ee045e5, 0x75250bdc, 0x703ca7c5, + 0x4995125e, 0x3b14ec5f, 0x6b4ba5f4, 0x98d07673, + 0x46098994, 0x6891156b, 0x59d5f5db, 0xc5d2152d, + 0x84edbe62, 0x35e66a49, 0xa58b0a83, 0x1ad08594, + 0x330f0018, 0x563a7d22, 0xa39da757, 0xa8eefd78, + 0xb6d24f9a, 0x0b646c4c, 0x74c16db6, 0x8c91aed5, + 0xad4dd608, 0x4e0dc1b5, 0xc8cf6685, 0xa617c47f, + 0x9797a48e, 0xa60bdc57, 0x57423988, 0x573924b2, + 0xd26d99bd, 0x1ea54b51, 0x4335e39c, 0x5f57c59e, + 0xa2026ad0, 0xbe251997, 0xe782f773, 0xe825f32e, + 0x23efe8d9, 0xd193811f, 0xb43a94ed, 0x0604c7b6, + 0x015a8da6, 0xfde229c1, 0xe4a43b08, 0x404b8388, + 0x6dfec830, 0x66eb6b3e, 0x02cd278d, 0x7b2a3b47, + 0x53d2f2ec, 0x2d82c0f3, 0xb8156542, 0x8cb4e600, + 0xc2b720b3, 0xa16af285, 0xb377d3cd, 0x4abb191b, + 0x88c66fa6, 0x4a821c50, 0xb6a4bf28, 0xc09c062d, + 0xfb856cf7, 0xa41125f7, 0x219c807f, 0x6f8bd4ac, + 0xd6276165, 0x3f9ed781, 0x49ff1c61, 0xe3854da0, + 0xba0e472f, 0xeae9f81b, 0xdab793d4, 0x573ad66c, + 0x6ba2bf0f, 0x3ee93044, 0x399db579, 0x5626bcac, + 0x25baa925, 0xc5ca7ab8, 0x2f630a5f, 0xeacb1efb, + 0x435c8db1, 0xd8bb68fa, 0xd41b1fb3, 0x06434a60, + 0xba285e40, 0xedab6511, 0xe265b9b0, 0x383fada9, + 0xb908e96c, 0x6baaa59f, 0x0b327507, 0x1773282d, + 0x4e9fbd60, 0xc701cd31, 0x62896b62, 0xed700f5f, + 0x38df9e58, 0x97eaf308, 0xe707fdd1, 0xcc0e1c62, + 0x2cdc90d5, 0x6fc314d5, 0x258b7893, 0x303a2879, + 0x9559982c, 0xeed7400d, 0xc91c91f5, 0x9a56a47d, + 0x27482786, 0x2b7a6e5f, 0xd1a6a9d8, 0xc2349e62, + 0xe2f94d62, 0x891135cb, 0x9760ea82, 0xdd2c8d9f, + 0x00b4cf61, 0x453b6c9d, 0x6c3619ff, 0x58096979, + 0xf3ddd46e, 0xe9e4334b, 0x2f0b3f65, 0xcc91a583, + 0xc42c72e1, 0xd8206185, 0x2cc5007b, 0x794967f7, + 0x351d7c59, 0xc1836803, 0x96ef084d, 0xf7f2c8a0, + 0x06e384f3, 0xf4e50073, 0xf99e8383, 0x511dad20, + 0xa3181f7e, 0x76dd9820, 0x9056b6e6, 0x5e2eef9b, + 0x1b708db3, 0x61cd4520, 0x21fb54a9, 0x8df6dfc4, + 0x66768bc2, 0x84419abb, 0xb57efcaa, 0x666e4545, + 0x5474db67, 0x3e25059a, 0x06221228, 0xa7395d62, + 0xaa2f5904, 0x402ca4db, 0x93493a9a, 0xbfc2d6d3, + 0x2a98403c, 0x7fb63164, 0xdfcea70e, 0xf7c90a2b, + 0xd6d4a59e, 0xf0d591e7, 0x2307ddaa, 0x439cfbe4, + 0xa81b20c8, 0x012393e1, 0x523ae00c, 0x6e249634, + 0x12bc37f1, 0xc523a326, 0xc7580939, 0xab063148, + 0xe1c7866b, 0xc9b1667a, 0x2fad1f24, 0xee522d95, + 0x2fe92e48, 0x813c9a5c, 0x0b226aaf, 0x009d00e4, + 0x42abf72d, 0x44f2133b, 0x3e898e0a, 0x78a512f2, + 0x1c105e72, 0x08951b8a, 0x1e5a35de, 0x0e28e856, + 0x5dcf985a, 0x63ff27b3, 0x5c0d4a53, 0x7c18da96, + 0x11cddd39, 0xb29505c7, 0x41462446, 0x0ef1e2f4, + 0x249f8562, 0xd178666d, 0xd98daa34, 0x561ac04f, + 0x4de3646a, 0x16d77ee1, 0xc36a9c24, 0xde1f7dd4, + 0x8a633eaf, 0x7ae16e67, 0xf1af0e65, 0x25287e88, + 0x5c606845, 0x9439fdda, 0x6f5138aa, 0xdf97c6bf, + 0x639a9ce9, 0xf41a89bd, 0xcedb500a, 0x3cf37ecf, + 0x5bb9d77a, 0x34b8853e, 0x849b1429, 0x54653682, + 0x6a020ed3, 0xf3b91a11, 0x6068efd5, 0xddb5289a, + 0x02b64c69, 0x1eb2ba97, 0xa6c46e47, 0x2a4c1ecf, + 0xa71712b4, 0x40895499, 0x4f37fcf1, 0x5cbc9ced, + 0xc662b1cc, 0xac535570, 0x27ed6ca1, 0x2177a3d8, + 0x675ce22b, 0xe3095c95, 0x688a52d6, 0x57f1fce6, + 0x32ab2e87, 0x45c135b8, 0xf64859e0, 0xbbcdd921, + 0x8b4075f5, 0x1b50ec22, 0xbba41e3c, 0x78307f4b, + 0xcaafef45, 0xc8645a4b, 0xeb743b8c, 0x326f87d9, + 0xe4448780, 0x4da186b4, 0x65e21fe9, 0x7894e394, + 0xf9a430b7, 0x216908bc, 0x06856be1, 0xaaee6daa, + 0x50c7d590, 0x6e6d448e, 0x0cc8679d, 0xb55a6229, + 0x92ad5319, 0x85ad9493, 0x36163b75, 0xa84f841f, + 0xa468af85, 0x51788616, 0x437ecc5c, 0x7603fe0a, + 0xc94ee734, 0xe610511d, 0x881d2657, 0x620a2f81, + 0x69b7c4d7, 0x490af3b2, 0x570d9ec8, 0xed541f39, + 0x90573fc4, 0x11e8cb9d, 0xadaf811e, 0x54d4b616, + 0xd5fccef5, 0x0b3d7e70, 0x66fe5859, 0xcb3c38ba, + 0xe2917270, 0x2f0a5ac6, 0x60957f74, 0xa616db51, + 0x492d4689, 0x4ead8e43, 0x26b31363, 0x19a57294, + 0x48fc2866, 0xe4d3951f, 0xd959ac06, 0x5d754901, + 0xfd996d94, 0x5abee864, 0x78dd567c, 0x9a2dbe1e, + 0x7ac44435, 0xa7582eb0, 0x5999cb1f, 0x4206c12e, + 0x9859660a, 0x248f194f, 0xa4dac482, 0x6ba3ad4c, + 0x5f1cbc3c, 0x5485b5b4, 0xca4030be, 0x71f7e0a5, + 0xdb0bf1d6, 0x5bc7b8e8, 0xb2285178, 0xaa4eba2d, + 0x201a2ac2, 0x6617ca57, 0xadeb0c95, 0x5a256471, + 0xc5bfa51c, 0xfd79f832, 0xc3153463, 0x6aa87186, + 0x1e23d197, 0xc7b02eb4, 0xdd4875dc, 0x5c3c0776, + 0xd9b6a2ff, 0x6a82f1cc, 0x0a5ee213, 0x72d5f081, + 0x56ee7208, 0xb7b7b0d7, 0x28b52266, 0x6deeaf2e, + 0x4fe1bd3f, 0xcd4af160, 0x3b31e610, 0x4bc8d92f, + 0xd75853e9, 0x04a3662a, 0x50d193de, 0x363a900b, + 0x7b04fe66, 0x99072e5e, 0x2daa5fb7, 0x011ab301, + 0x565e6ab8, 0xbfa88876, 0x1073ddad, 0x19a942d8, + 0xb5a45742, 0x43ce67d3, 0x880d6790, 0x6d09683d, + 0x2bba28b3, 0x9e30b5d3, 0xa5e094b5, 0xbffb1f54, + 0xda2866cf, 0x170061d2, 0x087bbd9d, 0xe9147714, + 0xccf75aad, 0x5980ed14, 0xb9b54e0e, 0xb370cfce, + 0xd4477c79, 0x29569a2e, 0xee03c3ff, 0x8db1ad92, + 0x6b62fc38, 0x280fd928, 0x93e906e4, 0xc0fc86f7, + 0x66ea89b0, 0x9585292b, 0xee3678b5, 0xf57ee940, + 0x7113e57e, 0x68c6a0ea, 0x83f0ab09, 0xab5d7d82, + 0xaa7c6d28, 0x7fbe8a3b, 0xabec0792, 0x101cfdbc, + 0xa0772cf3, 0x9b1179b4, 0x720bb88f, 0x37780004, + 0x6c92eada, 0xfaf5450a, 0xfd4c8f89, 0x240857d6, + 0x64134ce9, 0xbabddc85, 0x7ccc36a8, 0x00b3fb82, + 0xd494018f, 0x4b0c4ecc, 0xc51edeec, 0x7e94fe64, + 0xe8071a49, 0x4e27faf2, 0x2acc3b75, 0xddefacf8, + 0x5ac7088c, 0x93a44eff, 0x0b95d285, 0x53e5ddf0, + 0xbd491bc8, 0xa18d7961, 0x730e2f58, 0x799e89ac, + 0x861e1337, 0x94b7b76f, 0xb29b3ea9, 0x2b053a54, + 0xd745754f, 0x3e597c54, 0x97b5e51a, 0xdd21897e, + 0xcb3877af, 0x35cf2417, 0x1d6b6638, 0x6dd0be45, + 0x5ab82db0, 0x2446a5eb, 0x70a6826e, 0xe326b14e, + 0xa3658c00, 0x60c39ff8, 0x7c655475, 0x0ca4fdd0, + 0x7315b3cd, 0x91ef3632, 0x917dcc35, 0x32dbda46, + 0x66583842, 0xb5b5e9c7, 0x07bb1f42, 0xb7e1c698, + 0x5b0f6474, 0xa14d16a1, 0xf7c69623, 0x240c07fc, + 0x6edac9d1, 0xcb28d545, 0xdbbfa1e7, 0xe5b5ccfc, + 0xc1421833, 0x8c06525e, 0x99f00d70, 0x41f1756a, + 0x014b6db1, 0x0b0e4c9d, 0x7ba19462, 0x7ed7bdf2, + 0x58460b8e, 0xa6ce6448, 0x1a1b2b90, 0xe43ada40, + 0x3fc41eb2, 0xcb1faab6, 0x259ec598, 0xf221d105, + 0x447ddf12, 0x784fa66e, 0x3896fbbf, 0xd607bd56, + 0x5d1e9547, 0x075bffdc, 0xfd39e000, 0x8cd067f3, + 0xdc91037f, 0x1cd74bf4, 0xfdae556e, 0xe9e56868, + 0x06abe229, 0x72ecaf0d, 0x3dd95d46, 0x50655092, + 0x8c6be8b4, 0x5882c6a0, 0x48ca02e6, 0xddd72bed, + 0x81efbbc0, 0x50b69a75, 0xb29e4220, 0x3b2bb967, + 0xb8600874, 0x7e4d9fa8, 0xf4af1198, 0x230409c5, + 0x1dedeade, 0x0eb89456, 0x2dab1b30, 0x670e764e, + 0x1b04935f, 0x7c2322f9, 0x1a509a7e, 0x994f97ff, + 0x3c49c170, 0x446dde7a, 0x7e4c9251, 0x17663c09, + 0x41d6c8cd, 0x928cceaf, 0xb65ddf36, 0x369fec92, + 0x21d1bc44, 0x2d3f693c, 0x103fdafd, 0x37f61a5e, + 0xd9c957c4, 0xd83f085c, 0x4faeb03f, 0x11d010ed, + 0x3e40ddcc, 0x55f637e3, 0xe7a0c55c, 0x19959083, + 0x7601f29d, 0x84240811, 0x2664346b, 0xa0ffb322, + 0xcb360ff8, 0x9faa514e, 0xc7662f40, 0xc2a7cb3f, + 0x56817170, 0xeb0fc302, 0x20b1fae4, 0x8117ef36, + 0x160c02c7, 0x68308405, 0x5eb5a567, 0x870effb3, + 0xdb0cd956, 0x41fa5f19, 0x6324c713, 0x6e776daf, + 0x51e9d794, 0x57d7681a, 0xd6f6a968, 0xe7307598, + 0xae05ac2b, 0x53294cfd, 0xdbfa3706, 0xac8d9743, + 0x6fbfd6db, 0x3f4ea73a, 0x91c1059b, 0xf66e20d5, + 0x8f53988e, 0xa0c4a0e3, 0x3d969b28, 0x7bfa0ff2, + 0xe92c21d9, 0xe9537559, 0x539b62f7, 0xc33bd95b, + 0x4de2a8bf, 0x85da648d, 0x670148c1, 0x4af7a7e5, + 0xc8f69af3, 0x277cba64, 0xc316448a, 0x73e7f8be, + 0x1b703345, 0x93c376e0, 0x0f53fd44, 0xe62bf3ba, + 0x6f8ec391, 0x3c972ca9, 0x091ca3c6, 0x713e1e60, + 0x9646b17a, 0x1c8d733a, 0x476f523a, 0xf78c4236, + 0x35a9422d, 0x8a3bc243, 0xed1797a1, 0xc39d0fde, + 0x82d4e0e2, 0x1a571aa6, 0xcb37073b, 0x8ce8b583, + 0x0e46b21b, 0x8be5edfc, 0xc3264126, 0x6de50885, + 0x3154140b, 0xeb03524f, 0x42907386, 0xf28eacbc, + 0xd5babd2e, 0xb100d6bd, 0x709f76a3, 0x13b1642b, + 0xd4560451, 0x148b14c2, 0xf2b7d130, 0x958baf5b, + 0x722fb85f, 0x6ad8c4d7, 0xa050553c, 0x73952ded, + 0x02a5cfc9, 0x02d778af, 0x81d56fd7, 0xabd587ee, + 0x228e0dd7, 0xbb299ac8, 0x69a11126, 0xcc516bed, + 0xe21a4b27, 0xfa888cb4, 0x58623b79, 0x6b408e00, + 0xf629abcf, 0x21d9e338, 0x70027401, 0x6a09706e, + 0xc3fdaec7, 0xe6450cd8, 0x6b36442e, 0x2604c9e1, + 0x77cf42c0, 0x9b1e0522, 0x79340f54, 0xbf357f9f, + 0xa7e01d5d, 0x1e998ad9, 0x6b62ec55, 0x2cc8ffd9, + 0xca7262f1, 0x29759fc0, 0x3fb1e23f, 0x407b7e8b, + 0x395d7b38, 0x7fc7cb0d, 0x4948cdd5, 0xac1cd1d1, + 0x4bdb813a, 0x4b718f91, 0xacaa36fd, 0xa7c7997d, + 0xcd147af1, 0x76993ad2, 0xd7119077, 0x237b6926, + 0x6a8dfc22, 0x17f9ec46, 0x0b00917c, 0x9aae66c1, + 0x2da74bca, 0x2f86482a, 0x6b721e26, 0x021553d7, + 0x1754bf78, 0x569b3825, 0x5c00e561, 0x703103c8, + 0x18e0004e, 0xd4f68c70, 0x96b64cf0, 0x200f3dcb, + 0x18e446b0, 0x8f249d20, 0xbb66d4de, 0x8a7f6d01, + 0x7ab85979, 0xadea84f7, 0x1d96548d, 0x6121759b, + 0x669911e0, 0xdb91abd7, 0x52c1db11, 0x1d58473e, + 0x81840d89, 0xb4723b6f, 0x2a6e48be, 0x7957eb22, + 0x8bdfe7fd, 0x70e922f3, 0xaaf702c0, 0xfeed26cf, + 0xe3cc0244, 0x2507c5b2, 0x7bb59f03, 0x8c3a76b4, + 0xa03388da, 0x2f2b627c, 0xe8f29601, 0x20a1dfcf, + 0x6c46841d, 0x10487f61, 0xb9e954a5, 0x3e21654a, + 0x7a44e6a8, 0x034045dd, 0x8f1f192a, 0xe78808e9, + 0x1e1ebb0c, 0x3e4e01c0, 0x1051faf8, 0x9f1ebf14, + 0x1dcc581f, 0xdeb51e40, 0x93fc89d3, 0x38415c2e, + 0x4d7c8e9f, 0x0042112a, 0x230348a8, 0x3afe6855, + 0x7fa8aa29, 0xf11e0de0, 0x80b32965, 0xabda25bb, + 0x32ab8cd8, 0x11bb816b, 0x3f8c8a40, 0xb99b9603, + 0xe92ee1f4, 0x3d42efe9, 0x5cf83e52, 0xe9aba8fe, + 0x5b0d3dd0, 0x162bf5d7, 0x23409250, 0x21df5d9f, + 0x282d7c07, 0xbae82d2d, 0x204a34fb, 0x73c8cbda, + 0x4ab2d458, 0xd33dc9c5, 0x3104d92f, 0x89e1ad5f, + 0xd4ec1ebf, 0xece6e880, 0x2cc54cc3, 0xf50979aa, + 0x08ab292b, 0xba7a1ba1, 0x42900cef, 0xb239e70e, + 0x75438b52, 0x9fce69a4, 0x7aeac599, 0xc479a7ad, + 0x95f4b513, 0xa4ad8fed, 0xe1381482, 0xfdb4f70e, + 0xb7ddad0d, 0x6e12b0f7, 0x70aa2201, 0x93035ce8, + 0xfe87d943, 0x6a7e80cb, 0xbe0c643d, 0xd3ab55b4, + 0x4d3ffb16, 0x0dff6e18, 0xee2e77ed, 0xa3f0244b, + 0x590474c7, 0x798d5547, 0x59ffa16a, 0x38df5e5b, + 0x7aa158c4, 0x751e5482, 0xaaeba39e, 0x2ccd1221, + 0x9bf44535, 0xf936f2fb, 0x34a9de69, 0x33ca175c, + 0x0485855e, 0xc6c0aa01, 0xf633ef11, 0xf6c65488, + 0xcfd4eb34, 0xe7452351, 0x74e63c2d, 0x43b23730, + 0x3e6371ba, 0x16e216d4, 0x1bbd985d, 0x3d479c16, + 0x4e8f0427, 0x283e2970, 0x44260f1e, 0x7c45e38e, + 0x702bf17a, 0x1e629106, 0xfeeb31fc, 0xfe5a3c3b, + 0x727dc41a, 0x3442e1e9, 0xfd3b7735, 0x85b0efd8, + 0x250b13e9, 0x4a9766ff, 0x95ce8407, 0xbfb894ea, + 0x97a5195e, 0xa6654a73, 0xec4faa90, 0x0b65e10a, + 0xfb928cc9, 0x494b456b, 0xe7fa2204, 0x95373d0b, + 0xd24b972d, 0x457ddac1, 0x7a747b27, 0xf318eb4b, + 0x24e4a65d, 0xa3f0749a, 0xe717abe8, 0xba8c80bd, + 0x7d52be30, 0x12c93c4e, 0x126f17ca, 0x905ade24, + 0x72fd1b30, 0x86f10948, 0xde05d53a, 0x40c2d9e1, + 0x3d29c294, 0x0205e0e1, 0x782e184f, 0x38e19d96, + 0xc23e1505, 0xb0a3ee7b, 0xa629fc94, 0x67a0be1d, + 0xf19c4cb3, 0x43663bf0, 0xc2d0be9f, 0x5f55643b, + 0xdbceb2fe, 0x5dd84fc8, 0x5daa48fb, 0x4cf735b4, + 0x0509a91d, 0xf349fff4, 0x5eb0f0ae, 0x4bc02c37, + 0x0a7775f2, 0xe82c4183, 0xf3f68ecc, 0x911af63c, + 0x4758828f, 0x8449f80f, 0x4c421119, 0x14647f5f, + 0x779e2b9d, 0xe4ab1a44, 0x439fa920, 0x4bd8b75b, + 0xf94c0001, 0xef2d4d79, 0x786942c2, 0x5e4aee3a, + 0x81ce2390, 0xbfc706ba, 0x721c3386, 0xe404ed97, + 0x574daa9d, 0x32470dd8, 0x3de30cef, 0xf334b67b, + 0x06c3b886, 0xbcc51791, 0x343a49d2, 0x4c2805f7, + 0x4bcd1e08, 0xb5ba4c59, 0xa38ad1f1, 0xb265705f, + 0x164cf5c9, 0x5597e64c, 0xdbc173d6, 0x34cdc9ba, + 0xbceb9e14, 0xc8fa1932, 0x89888990, 0xd8668a04, + 0x3838d309, 0x74b87ec7, 0xabf16a63, 0xf2f31139, + 0xf6e381b0, 0x1dcfb650, 0x312c061b, 0x63189215, + 0x113d4d64, 0x949c8dca, 0x92d49315, 0x9329863d, + 0x00dd9240, 0x6a932887, 0x311f620c, 0x76e0c797, + 0x982d6768, 0x86c7a327, 0xc6e436c5, 0x0fa88a62, + 0xb142307e, 0x313998ba, 0x6f973392, 0xeefee1d3, + 0xecda4d45, 0x45beba7c, 0x80566f62, 0x2524d686, + 0x3e294737, 0x1c54be7b, 0x12aba319, 0x055a50f2, + 0x16df2b2c, 0x3f0197f1, 0x17c9d836, 0x5aa26984, + 0x85354a95, 0xc1067d56, 0x59041931, 0x6967cfa9, + 0xecd856ee, 0x795da2b2, 0xbe22954e, 0x46b3535c, + 0x58f89824, 0xb6563ab5, 0xb5d81dbf, 0x34e0ca07, + 0xcf31b877, 0xd225d056, 0x5d1f9423, 0x3046c941, + 0x97f9c884, 0x803f7a49, 0xda51486f, 0x221e1ee1, + 0xda39cba9, 0x06345732, 0xfe24ddd2, 0x232c7b09, + 0x4bf1fc10, 0x3c8b1076, 0xc59a1e79, 0xeee28815, + 0xfb516ed7, 0xd9c583ed, 0xa3d02109, 0x4122ede6, + 0x0221b118, 0xf161c9ce, 0x98eb8c01, 0x00f25590, + 0xb239c1b8, 0xa28e6a0c, 0x983e1180, 0xac518016, + 0xb2275327, 0x862b2a0c, 0xebbcda8f, 0xfb3963b9, + 0x7a2403ac, 0x696f018d, 0x255c9052, 0xf66330d4, + 0xcb9a8503, 0x1928b8b0, 0xc4392666, 0x875bf29d, + 0x93845c90, 0xd3ce822f, 0xafa84cdc, 0x34fee83b, + 0x2e3704ca, 0x11d3dc2b, 0xe7b1c421, 0xcf6a02a2, + 0xb9c16c95, 0xa8e012cb, 0xc1df0e21, 0x60fe0340, + 0x91d01576, 0x99dbd24a, 0xc3da782b, 0x4b8ba245, + 0x8ec7a2fa, 0x1b85f893, 0x76f719e8, 0xa5a81b30, + 0xf411c6e8, 0xa0867ab5, 0xd084ba22, 0x91ca34e5, + 0x809a3d35, 0x47b55eba, 0x0d447b76, 0x0105aaa0, + 0x511ce927, 0xdb3e8fce, 0xdf281fec, 0x45c3511d, + 0x14e70135, 0x3aac5c53, 0xde304341, 0x984e8b79, + 0xfb51a149, 0x082abb5d, 0xd7c11288, 0x4706bd6d, + 0x6de99f22, 0xcf0e88f8, 0x4869b59f, 0xfb1228a4, + 0xeaeabbb3, 0x941c307e, 0x0858cb3f, 0xb0b8aab7, + 0x2997fc2c, 0x08dc2ac6, 0xdaee8a9f, 0x009a2879, + 0xe09227ee, 0xe760fa27, 0x808c753b, 0xed645a2a, + 0xe7b35294, 0x875da6d5, 0x91a7d0f5, 0xa7e27bf9, + 0x13d79171, 0xddc7ea8d, 0x871119f8, 0x05782f05, + 0x1367dbda, 0x61abcf83, 0x6bf9962b, 0x0855c17a, + 0x98d6b65c, 0x8b3e3bc1, 0xcd9f07c0, 0x5a8aacdd, + 0x56de51e4, 0x633f7171, 0x618406bc, 0x26ad3679, + 0xb78dd7b9, 0x9d6e1a11, 0x90860397, 0x2f778605, + 0xa3ae2bbf, 0x77ab097a, 0x259e74e9, 0x49d0697c, + 0x34ebe8b4, 0x8af23270, 0xe0cb58a5, 0xf42813a0, + 0x2ab40d08, 0x45c38f5b, 0xe40768fc, 0xa00a7e81, + 0xcb1622cb, 0x76932bbb, 0x380bbd03, 0x4e888e14, + 0x57748f95, 0xebb3a9a2, 0x15268ab0, 0x5f0ca109, + 0x197ed3fb, 0xa396cbc7, 0xdd4544d3, 0x72bcad87, + 0x9bacf1c5, 0xc29a2586, 0xafff138a, 0x06ae187e, + 0xfa09b8a1, 0xce61d82c, 0xe1cf706d, 0xb4b386c8, + 0xd1e7a92f, 0xd8cf6f74, 0x8e04c16c, 0xbebc903a, + 0x6daa28e1, 0x80609217, 0x566f0132, 0x0ced94da, + 0xc578937e, 0xe9aa4250, 0x2b91dca3, 0x97e92316, + 0xcd4cb9c4, 0x47e27a30, 0x7c7b2403, 0x08016d6c, + 0x0bbe10d4, 0x1ed123b6, 0x06c96396, 0xf8a5bf6b, + 0xad1072c2, 0xba941cc4, 0xe037e205, 0x83f168a6, + 0xec6560ec, 0xfa40ca26, 0xd65cfc94, 0x1bdc826a, + 0x6bd9c11d, 0xff5b007c, 0x266536f8, 0xfdcec273, + 0x43f228e5, 0x90b4df14, 0x8a0af815, 0x5b094b39, + 0x81557772, 0xa299eab7, 0x36c9f544, 0x20ac0b41, + 0x98b35d1f, 0xa9257811, 0x8b139c37, 0xabe02e60, + 0x09013c2d, 0x928f431f, 0xdfed27df, 0xf39322b0, + 0x7afa38fb, 0x6be0a4a7, 0xd1e29fdd, 0x7d0ae420, + 0x03a07c22, 0xcd4fb717, 0xba8dea2c, 0xe5eb6967, + 0x4c6749c9, 0x1291af8e, 0xab638bff, 0x30bc3540, + 0x4d87aac0, 0x8b05c47a, 0x5eefd021, 0x54f12af6, + 0xc2b4058b, 0xf34cc743, 0x32c52d84, 0x5f3e8a3c, + 0xbd01d895, 0x103da8b5, 0xa7a8c1ad, 0xda260c67, + 0x7e50f04b, 0xfb8b5e03, 0xcce6b146, 0xd3c2c47f, + 0x87a122ed, 0x2b993551, 0xfd71137d, 0x8a6053c9, + 0x4856a2ea, 0x09c81bc3, 0x0bbc0386, 0x916dadc8, + 0x5644c85f, 0x25e0b999, 0x8f9429e8, 0xee3ebc5c, + 0xb7598fae, 0xd37bc93e, 0x45e2bc3a, 0x81d68b22, + 0xa9adb1b2, 0x11e4d6ea, 0x54e2d2ab, 0xdcdb457e, + 0x7eec508a, 0xf08f2924, 0x1d0f9df0, 0x51454db7, + 0x877b20ac, 0x2b765a9f, 0x7ce268d6, 0xbc4ee5e7, + 0xcf568649, 0xffb05d1e, 0x558af352, 0xca04227d, + 0x2dee1df3, 0x78e75939, 0x84cda769, 0x235e7fc3, + 0x034cbdc1, 0x4e9ce87e, 0x55bbfcba, 0x32e99c12, + 0x8ddc91af, 0xabb90ee0, 0x0991018b, 0xcda3b110, + 0x5c817e68, 0x5023abfd, 0x9c812b0a, 0x9b57eb07, + 0xa18782db, 0xa0f91c06, 0x9bde0572, 0x3bb6fd14, + 0x97e5111e, 0xd5c883fa, 0x8628514a, 0x001e90fc, + 0xf3ba4bb8, 0x8e4e01c4, 0xce5afd59, 0x36b26bcb, + 0xb7407dc9, 0xd5f49f87, 0x8a0cff32, 0x56505350, + 0xb303dcca, 0xc971e593, 0xa4a51ee1, 0xd25f811b, + 0x77f138e1, 0x35825a3c, 0x21568e0d, 0xcc6226a0, + 0x1874d2c9, 0x164076a4, 0x5fd825a7, 0xcbc3bd4a, + 0x4c7eb6b3, 0x67293518, 0x57c68c88, 0x8d3d80b5, + 0xfaaf0fa1, 0x6e19db43, 0x0ff03a9e, 0xc90f8c44, + 0xea5e4a53, 0xf57612df, 0x64153938, 0xea843b3a, + 0xa32e589e, 0x86563c63, 0x0f2d8e96, 0xa9cf8cf5, + 0x0c2f9151, 0xc0937d75, 0x5023556a, 0x254369bc, + 0x19c8e66a, 0xd6dc36af, 0x508db6bc, 0xa56322f9, + 0x3dd77c1e, 0x01137d6b, 0xcf1a44ac, 0x0e031252, + 0xd2cd440b, 0x0fc5ef56, 0x59753f8b, 0xbaf85623, + 0x85eb6dc3, 0xe5aee9d0, 0x4e0cc6a6, 0x1e68bdb0, + 0x6708eec2, 0xc1f18bf9, 0x403cc612, 0x982e78e5, + 0xd41a90b9, 0x3f73bacc, 0xf14c5c04, 0x421e5bcb, + 0x670feaaa, 0x3f730685, 0x725bc072, 0xb756a547, + 0xb4c4e653, 0xa77d83cf, 0x7a76b097, 0x30fc210d, + 0x228d2cac, 0x41ee4179, 0x333422dc, 0x058604ee, + 0x01138532, 0xbf028a4a, 0x0e9b8bb7, 0x9e4fefbc, + 0x389ea6f8, 0x7bbb969d, 0x1a0ea648, 0x94a1378c, + 0xf63df085, 0xce5865f9, 0xcde59d20, 0x31394f39, + 0x342eeaf4, 0x6922775a, 0x3305a9d0, 0x0d5eda70, + 0xc146f9e6, 0x5c5b8eb6, 0xa8ec5a3a, 0xf7271c8b, + 0x1da14ba3, 0x12429600, 0x51f9021e, 0x6a64c06b, + 0xb7be5176, 0x5c1ea01e, 0xc527a763, 0xd319b4e9, + 0x2fdfb539, 0x304f0ab5, 0xab03e3a6, 0x7bdb9eb3, + 0x64654823, 0x903577d3, 0xb78d0207, 0x98091543, + 0x86a0d06a, 0xb908c1d3, 0x4200d06e, 0xae1d81d3, + 0xf84b17a7, 0xfd873b86, 0xd573f9c7, 0x3cbbd2aa, + 0xdca2b53c, 0xe4863a75, 0xd671623b, 0x80b5ed85, + 0x02df2232, 0x55cb02a4, 0x52d44db3, 0x39bb74e9, + 0x9b5f07af, 0x9b59fc4e, 0xe03360b5, 0xbe5a727c, + 0x62985b5f, 0xf4054d9b, 0x0ef889dd, 0xeca27a0d, + 0xd75e9a4a, 0x8475121e, 0x42969e5b, 0x92fc387b, + 0xac5b3eea, 0xbeaecf23, 0xe41c3415, 0x1166550a, + 0x91897285, 0x515d78eb, 0xb999b01b, 0x3270e601, + 0x9925929f, 0x297a659d, 0x9a7542d8, 0x2fe3c326, + 0x90434988, 0x49c09eb3, 0x8d959433, 0x851d5190, + 0xb355ae5f, 0xc905b570, 0xdef48766, 0x3e1aef0f, + 0xdd2d97b0, 0xda4d88c4, 0xaf4e3984, 0x03d1379a, + 0x19d40f8d, 0x9c104c2f, 0x6969fe11, 0x37e274a3, + 0xf971a5c5, 0x26ad6b15, 0x9f7f3ed0, 0xb8801c58, + 0xc90b8ce5, 0x0e06de8f, 0xb38a51d5, 0x7507741e, + 0xa5ca22ff, 0x92a4c7bd, 0xfacf82bf, 0xc8237ea8, + 0x274b5ee3, 0xa00a735f, 0xe4b0a18d, 0x1654f1a8, + 0x49d72f81, 0x427514c4, 0xd527afbc, 0x2b828199, + 0xf2bce884, 0xa3ac6544, 0xef2feee1, 0x8a35a000, + 0x76f75d2e, 0x8e9f3c56, 0x836c90dd, 0xe2171aaa, + 0xd741bd23, 0xba1dfe6b, 0xe929a3f4, 0x93193cfc, + 0xa1780246, 0xe08ebc81, 0xf201a38e, 0xeaa33380, + 0xa0ad7bcb, 0xc55f1dbf, 0x3cad3d37, 0x343ef6c2, + 0x2aba3d58, 0x8aee352a, 0x4d000028, 0x40aba8d7, + 0x9e526b1e, 0xea0ca587, 0x43b5310d, 0x06a180b1, + 0x4c7ef4d1, 0x1509e884, 0xbfe7434c, 0xd355a073, + 0xc46dfca3, 0x87ae84ec, 0x547254e5, 0x07e76bcb, + 0x0ab64ecc, 0x9d1b38d8, 0x2c0d037a, 0x2157e51b, + 0x4ff2d37b, 0x82749dce, 0x5ed4035e, 0x10ba9087, + 0xfcaf1e32, 0x904c84e0, 0x8f7fa1a4, 0x7c521be0, + 0x14638166, 0xe190363e, 0x4406c3b1, 0x70cf4c95, + 0xfd6f6d5f, 0xef3a82c6, 0x2b8ad973, 0xa18b8f83, + 0x98df1272, 0xddfc2663, 0xccb3d374, 0x50200417, + 0x24e5e9cd, 0x8e5bdb29, 0xf0e7d30c, 0x044e2365, + 0x5aa3752c, 0x962903fa, 0x08096d80, 0x6ccc5019, + 0x980d9276, 0xab06a0aa, 0x2c184dea, 0xd030d051, + 0xfa2c286c, 0xc5ee6752, 0x0d01c775, 0x08dc0b9d, + 0xe0e80e92, 0x07c3ae5a, 0x0afd83f3, 0xc75a5e13, + 0x43aa4abf, 0x4fc573e3, 0xd5fef3f9, 0xc925bed0, + 0x3dcd545a, 0x9c38a04a, 0xe76596c2, 0x58417a77, + 0x5d41575b, 0xfe22a4e6, 0xf01166db, 0xfdec546f, + 0xf68dc228, 0x8d98f2d6, 0xb9df8917, 0xcb77df27, + 0xd96ea21f, 0x9ad30fae, 0xc14b4cf9, 0xd042d065, + 0x7ef8a588, 0xe1290b57, 0xb63013dc, 0x2d8e3706, + 0xc7b8b020, 0x269531ff, 0xf542b017, 0x3bffadbb, + 0xf10befb8, 0x83d64aa6, 0xf249db6b, 0x5cb20a76, + 0x77b917b4, 0x75b1928d, 0x54f9656b, 0x378d0b22, + 0x1fddbaa6, 0x4fdfe289, 0x25d3a70a, 0x742aa440, + 0x23d4dac0, 0x09f87b6e, 0x6cae4aac, 0x69cbddd9, + 0xdae5c53c, 0xb3334174, 0xb9b286ec, 0xd00a2f16, + 0xf85b0415, 0x6d940d46, 0x8dc206a5, 0x7934abfb, + 0xff924615, 0x0ab97330, 0x534f3892, 0x5ccc3fb3, + 0x8319bc0a, 0xe6aa2d53, 0x0c969180, 0xa8cef536, + 0x1d47940c, 0x8f6d6b81, 0xea993c5d, 0x7b62cb80, + 0xd3d8afa4, 0x41f69f3a, 0x0105c930, 0x1076a1ae, + 0xfc1c513b, 0x934b3023, 0x6038edb9, 0x51547854, + 0x70df12db, 0x5f80064e, 0xa3b849a8, 0x816f2ae4, + 0x2fbfc976, 0xf9778cfa, 0x0dfcfd6b, 0x5cad2b8a, + 0x6dba494e, 0xbcb2d6cb, 0x7411183b, 0x089609b4, + 0x1108420d, 0xfb2fff13, 0xffe09b7d, 0x0448553f, + 0x66b94fc8, 0xe57662aa, 0x5ae14576, 0x1ac17a3e, + 0xda0af6a0, 0xcaad8b23, 0x2c2d5e25, 0xb5b838f2, + 0x1c9f7373, 0x16aa1d98, 0x4974fec4, 0xa8f57a26, + 0x45cbb8c6, 0x0a384ba3, 0x73c7a5a6, 0x8b7701e3, + 0x04e94edc, 0xb23baf28, 0xd72ba468, 0xbd567619, + 0x794dd424, 0x715f9d1d, 0x1d5aa5ca, 0xe6d1b5c2, + 0xc4454ff9, 0x77a51c7c, 0x4563a2cc, 0x2de4a847, + 0x759fbe2d, 0x26582948, 0x7e1f7c85, 0x2c02f945, + 0x0cb38f9d, 0x730cc1b9, 0x4381e953, 0xac61b20c, + 0xbaecb4ec, 0x2d60afae, 0x9ec1ddc8, 0x1e22d6ca, + 0x6db5cdda, 0x389d72d0, 0x2f9f0126, 0x3e628849, + 0x09b00e4d, 0x37ce1b77, 0xa45e7e32, 0xf32ece6b, + 0xf1295641, 0x4b7f3e8c, 0xb0f32abe, 0x147fe08e, + 0xd21d5fe9, 0x5dad1765, 0x68944f69, 0x4ca7b0fd, + 0xdec6ed99, 0xce0fd6e5, 0x5a76053e, 0xff52d641, + 0x7ba14a03, 0x12e9ac8e, 0x5da27afb, 0x9a178be3, + 0x6383c4db, 0xc4997272, 0x14bd9ff5, 0x9a54d4fd, + 0x62152ae1, 0xad16f69c, 0x70fca056, 0xdffe7858, + 0x17ed0670, 0x94a7b667, 0x25086946, 0xaf8cdf34, + 0xf0e2e989, 0x10c4fa9b, 0xcc6be9b9, 0xa7d41319, + 0x5153504a, 0x5e60c244, 0x5e2bba45, 0x4f6837a4, + 0x0514781c, 0xfb10bec6, 0x58fe9b40, 0x3f01b063, + 0x99e20ba9, 0x7a9f08b4, 0x9153ef3f, 0x1c87637a, + 0xc768ca0f, 0x6a005b91, 0xd81ec648, 0xa562b4f8, + 0xf181de29, 0xed1e009d, 0x5caa39c8, 0x3f081868, + 0xb1a7bfe9, 0xd911beb1, 0x6009bd89, 0xb6a6c69b, + 0xc2b5b817, 0x57c51571, 0x50c2e0d9, 0x87a3244d, + 0x5174f395, 0xe3928633, 0x6b5c7f64, 0x9499e8c4, + 0xc42d555f, 0x119a0789, 0xdfbf0c46, 0x472f65d2, + 0x68ff57dd, 0xe4ffd20d, 0xaa25a50b, 0x25e2e231, + 0x37a2fbc1, 0xc14724ba, 0xee54f5b9, 0x617038d9, + 0xa5513954, 0x679608b6, 0xb5011dcb, 0x11da66ec, + 0xf9c03956, 0xf40e3d37, 0x5d1b5853, 0x2aa74bc2, + 0xd6cd2c0e, 0x6f9e7f5e, 0x071520e0, 0xb859ee8a, + 0x685ac308, 0x802cae93, 0x59a7321a, 0x733485eb, + 0x72ba637e, 0xb47d7c18, 0x128b696f, 0xd2cebfec, + 0xc7158d0d, 0xb4064407, 0xe536dd9d, 0xe9829009, + 0x97dfaae4, 0x8c3d7201, 0x99610659, 0xd4718253, + 0x9625f17a, 0x43fab7f2, 0x2621ca0e, 0x254319f6, + 0x5a02e2b3, 0xddc9f52f, 0x2fe2779a, 0x4f6e0852, + 0x4dbde8b7, 0x532cc790, 0x8c92d82b, 0x5d85a58c, + 0x1589899f, 0xe9433e17, 0x123dbe9b, 0xeff94e38, + 0xb7192345, 0xd10c04bc, 0x0a653c70, 0x27da65cb, + 0x724c0366, 0x8660d570, 0x6f752fb1, 0x7a2f4925, + 0x7433591c, 0x8698573a, 0x98d882f0, 0x7a03dcf8, + 0x9bda5ed4, 0xa2a2a2b1, 0xe43ef0c5, 0x3b1dd256, + 0x1761b2b2, 0x6e1e56dc, 0x5dd19888, 0xa2dae55d, + 0xc575ee0b, 0x78453bac, 0x7b5da7f3, 0x47830f4e, + 0xfd24ebe0, 0x709146a9, 0x5c0cce35, 0x529b2174, + 0xf7c8d08b, 0xdd84cdb5, 0xe1c3ba98, 0x4b92ba9a, + 0x9eeee319, 0x14f53b0d, 0x28d32f2b, 0x4b08c647, + 0x6698fed7, 0xcdb26787, 0xb314b3ab, 0x376efcde, + 0x345b5531, 0xb0ea7f68, 0x18ef8315, 0x3320c970, + 0x6c75bfe6, 0x0ff165f7, 0x327eb8b7, 0xbe05f679, + 0x79e8424c, 0x4dfa8aff, 0x1a29ad36, 0x6db0ff7c, + 0x36d6c97e, 0xec2ddfdc, 0x2e43a8d3, 0x8375b77e, + 0xbd3dd5ee, 0xd4b978a1, 0xcb0c6885, 0x28b7cb15, + 0xb15cd265, 0xc61c5f1e, 0xd3add732, 0x41892c0d, + 0x9a9d04b7, 0xb3e4cd6a, 0xfb7ab190, 0x51611b48, + 0xe181f9a6, 0xac6b46cd, 0x81a68dd2, 0xade51f0e, + 0xafea158c, 0xc66cca82, 0x843a4fd9, 0xcbcfba0a, + 0xa06f84d8, 0x09ac26b0, 0x347494fc, 0x23a78093, + 0x0a00ab9c, 0xfc305057, 0x194e6310, 0x62ced9c0, + 0x03833b0b, 0x8afd5943, 0xbbc1dcf5, 0x0073973e, + 0xdbac1e68, 0xb71ec7b6, 0xd91e0971, 0xcc7d4e64, + 0x03da7794, 0x13c9636c, 0x032609e0, 0xbcd89537, + 0x1eeba1e0, 0x750bb7d2, 0xb7338ac8, 0x947f7f6a, + 0x95a8b1b3, 0xcdfd324a, 0x10e658da, 0x172e3dff, + 0x93b2d8a7, 0x236a650e, 0x1f1b67ae, 0x224505bb, + 0x3a73417e, 0xd74df883, 0x2a6e33a5, 0x9fb954f8, + 0xd6ad9566, 0x2ddfa1c9, 0xab12586d, 0x9c6da60b, + 0xc3ddbaba, 0x6d41b748, 0xaba9bf16, 0x7c224cc8, + 0x4e39e5c0, 0x4aebe559, 0xc26fd2ee, 0x1f811a6e, + 0xb73be5f7, 0x004010d3, 0xfceec8de, 0xbfb7f67f, + 0x457967d2, 0x59a3b253, 0xec18b1dd, 0xcde0e0cf, + 0x6d7bcddc, 0x5d1bd7b3, 0x8b51f8ce, 0x94e19b51, + 0x83818da5, 0xa8fe8c7f, 0xf118acc8, 0x90d31135, + 0x74576c4c, 0x86c9c5e9, 0xc72a8cdd, 0x59a2d7e6, + 0x6806b96e, 0x50265477, 0x0a3d34ba, 0x41854d99, + 0x8cf43e3d, 0x2711aed6, 0xe881c39b, 0x41a8830a, + 0x6b846bc5, 0x9d5ab0d2, 0xf2149be7, 0x360a1df5, + 0x26117995, 0x02b4aa7b, 0xe1950d6b, 0xdb5d271a, + 0x9f3bf539, 0x88ffe82c, 0xc4ea1ac0, 0x5f5e53ec, + 0xaad42738, 0x8c262ef6, 0xaf9b066a, 0xf0872d1c, + 0x178cf011, 0xa18dabdf, 0x4acb6249, 0xaef7af0f, + 0x86e1730a, 0x529de70c, 0x94d55aa3, 0xed4ca43c, + 0x96d935ad, 0xd1e6904e, 0xc70aaf68, 0x65a666a8, + 0xfe2054ba, 0xc8360f44, 0xd15ca0f3, 0xd225d942, + 0x164d5a35, 0x9061be3c, 0xd93a0aeb, 0xbe3d28b0, + 0xcf876a6e, 0x24ee344f, 0x663df9fd, 0x497cd718, + 0x73c5d0ce, 0xaf6a540e, 0x1e517b55, 0xb64c3c08, + 0x79ef0d4a, 0xa103f384, 0x6d89d6d8, 0xba9d484f, + 0xe7a077bb, 0x374b7b13, 0xf6c34e4d, 0x6797d667, + 0x595a49ca, 0x7e4ad667, 0x04c50855, 0x618c7a60, + 0x32448985, 0xf6599a67, 0xcdbb0b5e, 0x69ab2030, + 0x3cd5825f, 0xa94cdc5e, 0x4d2de10d, 0x8d941061, + 0x6525b319, 0x398a6f78, 0xdaa5ee1d, 0xa8c5763c, + 0xc6d0eccd, 0x42daa2d4, 0x46195a19, 0xadeb3676, + 0x380335c8, 0x25aa588e, 0x7a0b88c1, 0xcb0034cc, + 0x0b39d916, 0x4a86bb4e, 0x7466c566, 0xc1216dbe, + 0xe0b939a5, 0xc0b27f60, 0x11fac0e9, 0x9d1648fc, + 0x6d8ebe7f, 0x3646602a, 0xd75ff20a, 0x8eb4ac6b, + 0x06bcb6a1, 0x7c0514fa, 0x76cccdc7, 0x3ecbfc25, + 0x1d477a2c, 0x847c167a, 0x55f195a0, 0xe62708e7, + 0x36b15203, 0x834b3209, 0xff0232ad, 0xe72e9662, + 0x3dfd0370, 0x45f96511, 0x06caef0c, 0x1916d679, + 0x48547dce, 0xdd2ac4aa, 0x056b9f0b, 0x025ece56, + 0x2bacceb0, 0x16be23e1, 0x5a22b391, 0x69c870b2, + 0x6e9612e0, 0x3f6d79ff, 0x2c8842f3, 0x08fe63ed, + 0xeef07eac, 0x86fb2b9e, 0xf28000a3, 0x423bf4c2, + 0x6dac5f60, 0xa3438d58, 0x221c5f0f, 0x82746b39, + 0xe4d02d8a, 0xe1c52284, 0xfc5786b0, 0x16d31e93, + 0x91d130cc, 0x05e3c67f, 0xd3851827, 0xfe1282c8, + 0x7c3d8e8e, 0x102b79c1, 0x3d30a541, 0xb0f390b6, + 0xb6e39ec3, 0x0bdece96, 0xc62e38c1, 0xc77f2649, + 0xdf382702, 0x671f70d1, 0x02aad865, 0x1fb88588, + 0xab6e9a72, 0x994a53a9, 0x33091d86, 0x00967d27, + 0xab055a9a, 0xd10bebb9, 0xe06067ad, 0x2eefc272, + 0x507b4f63, 0xa6776dc2, 0xd354b1e9, 0xf5333bde, + 0xdc643d21, 0x5837246c, 0xf789b20b, 0x36817b21, + 0xdd9500dc, 0xc7ee8e18, 0x318cceb6, 0xce7410f9, + 0x80c25e64, 0xfb250ab8, 0x990d6ea8, 0x6a6d28e6, + 0xf2b6d65d, 0x86d64352, 0x4a63f9b3, 0xaafdd365, + 0xa48a865e, 0x24d13930, 0xa38880bb, 0x960f8796, + 0xd37412c6, 0xd317c335, 0x648bc505, 0x2f447276, + 0x1b2ac702, 0x318d25ac, 0x8f28a886, 0xb4121e07, + 0xeb8b039d, 0x2bbbfbf6, 0xf3b5d76e, 0xdcfcf9c4, + 0xeb49eff5, 0xaebe5efc, 0xffc4e443, 0xd383cc5a, + 0xedff96fc, 0xc81c6590, 0x03112218, 0xd8f1a3e6, + 0x2aa347df, 0xbb357bb2, 0x32ae2a23, 0x2be30bd0, + 0x0fab4908, 0x28ca5809, 0x97cab691, 0x43b384f9, + 0x5d53faaf, 0xe7773e12, 0xea09e2f7, 0x7e4d1759, + 0x175eee68, 0x955f79a8, 0x9a19a259, 0xa01e0918, + 0xd506b767, 0xb9edd62b, 0x5f96cc35, 0x23a9f9e0, + 0x6c7a5f49, 0x1d11adac, 0x69abc8a0, 0xbb7a0e30, + 0x01b98373, 0x4594385f, 0x2dceab59, 0xf0690368, + 0x95c44885, 0x14c52e57, 0x9412d71d, 0x6b2eb5af, + 0x7e17c99e, 0x443facdb, 0x47a5121a, 0x781825d6, + 0xa7773fcf, 0x2bc971a5, 0xad314dbd, 0xda1f792a, + 0x1cbe7bb5, 0x78c73ddf, 0xfb1084e6, 0x1520f3bf, + 0xcbe64972, 0x6af27ff5, 0x78fa499c, 0x56e78809, + 0xf157f62d, 0xd79cd556, 0xb3630d74, 0x0fe193f1, + 0x3a525f15, 0xb8360770, 0xb9fc79eb, 0xc119c465, + 0x9c4e6cea, 0x796ed2e0, 0x7ea5bf3a, 0xbbc96092, + 0x7fab2abb, 0x51db14bb, 0x396fb289, 0x9bb1fe7f, + 0xb78bc587, 0xa11e824a, 0x0e7ec7d0, 0x935ea888, + 0xcd31816e, 0xe6ffad19, 0x25f4eefa, 0xcd85de99, + 0xc4df9cf2, 0x325f2ba4, 0x30e92f74, 0x3228afaf, + 0x1db42f19, 0x863d460c, 0x49f01598, 0x394dc72e, + 0xf34c8102, 0x9bf324a7, 0x20bae348, 0x8ba1ef96, + 0x7f83c9e1, 0xc872d3a2, 0xa2bf5a6b, 0x3ace9565, + 0x93c1cfeb, 0x68da7bd0, 0xf66ffcc3, 0x7c615af3, + 0x9d4a45f6, 0x7a767a88, 0x831963c6, 0x7da2017f, + 0xb26a7c81, 0x763f4ca3, 0x3178f4d8, 0xfa65e5c2, + 0xecfcd393, 0xfbe6c388, 0xa343179d, 0xd58f3c83, + 0x7e2da10f, 0x53636d18, 0xed27af74, 0x6c576292, + 0x374c90b4, 0x3bf07fe9, 0xa6519017, 0xe7e36ae7, + 0x23cc0c0c, 0x86f11bb5, 0xe6faec68, 0x066d82d7, + 0x0f74f757, 0xf4b15293, 0x80c69421, 0x77efed20, + 0xbd25faf8, 0xd20be300, 0x03d66481, 0x99026974, + 0x348674b6, 0xe745097e, 0x4cc1948f, 0x3901b58a, + 0xba4cbe7b, 0xc7841132, 0x60eaeef6, 0xa21aee74, + 0x471f2713, 0x4eedc729, 0xeb940a32, 0x9edb4cd7, + 0x6ab917d6, 0x883a3380, 0x0cdaf1b1, 0x17c327b2, + 0xed59beb2, 0x2817a78a, 0xad0fb637, 0x8af25604, + 0x8377e0c9, 0x8153fcc6, 0x4dd06f5b, 0xc53460f8, + 0x4613d1f8, 0x881ecb2b, 0x61635800, 0x3161f625, + 0x2a514279, 0x3a979459, 0x80816f2e, 0xa43a2b79, + 0xbe0b57d3, 0x88c380b9, 0xd6c1ba6b, 0xbb58c9c2, + 0x0015479a, 0xa2d74dbb, 0xf6a12a17, 0x7f026911, + 0x1b7b2c6e, 0x872776a2, 0xd229a1d7, 0xa8a18ad4, + 0x92d4cae4, 0xed92ce50, 0x89c6940d, 0x532b136e, + 0xd1d0a913, 0x768bc2b9, 0xa07c19a1, 0xd0114ab4, + 0x3830fb81, 0xeefb1da4, 0xb82e25ff, 0x62dfe06c, + 0x15171cd7, 0x3d0f7796, 0x36779b17, 0xec1bac6c, + 0xa08ecfc7, 0x2a26390f, 0x11be1de5, 0x388c9834, + 0xbb756fd5, 0x28a9ef0a, 0x82c55faf, 0x02106d73, + 0xcfba07bc, 0xdfdae27f, 0x5189a7de, 0x1c0ed0b8, + 0xb3cca2b2, 0x19054ab5, 0x49a89575, 0x9aeeb656, + 0xc31b9b38, 0x954744f4, 0x8fc22bf6, 0xd8f39f19, + 0xb7bd824d, 0xfafabb8e, 0x22e4d9b4, 0xdb0b426b, + 0x661e1903, 0x36f24730, 0x14e23d23, 0x7d87c8cd, + 0x9eb76c23, 0xe539b20f, 0x46ae2013, 0x76a59666, + 0xbb2560c2, 0xc594b08b, 0xb050cc85, 0x467690fa, + 0xa951958c, 0x1ffa21aa, 0x18c40d61, 0x39434b6c, + 0x4b107901, 0x6256e70e, 0x70342211, 0xc552aa46, + 0xda90d164, 0x9ca9210d, 0xaa32e33d, 0x211e3d00, + 0x4e9b16c7, 0x186f92fa, 0xfd95c0a4, 0xea9bb1a9, + 0x1d6288d3, 0x19d9277c, 0x8ee3a02f, 0x39457299, + 0x6b8ea5d6, 0xebcc2af8, 0x3f1fb107, 0xf23e3e98, + 0xa1c40be5, 0xc9459d51, 0xa48cf93c, 0x3571d2f9, + 0x7c4dbf5a, 0xf77757c2, 0xaad01e4a, 0x970db9d9, + 0x3ac71c1d, 0x78fad179, 0x4fb8bb3c, 0x70bba938, + 0x83ede56f, 0x6161e971, 0x8d7c830d, 0x829bad0d, + 0x0a21b8e6, 0x393d7463, 0x2c2076ab, 0xa74dd0e5, + 0x94376e60, 0x1cd50531, 0x1aef6c72, 0x449868a7, + 0x927ff54f, 0xbd5248f7, 0x32647753, 0xbaaa180c, + 0xa2a45164, 0xdade9fd7, 0x6e4f3ee9, 0x42b79f19, + 0x3fc2969a, 0x8d7b5000, 0x14fb647d, 0xb1c40e7e, + 0x5488b76b, 0x74136e02, 0x351e40e2, 0x8306f650, + 0xbdb35e09, 0xe561a0b2, 0xc0f53956, 0xd8d4590e, + 0x410aa007, 0xc85562fb, 0x29bc516a, 0xf41ff6cb, + 0x2368a2ec, 0x068684d3, 0xdfa5afff, 0x9b9c58df, + 0xec1eb8db, 0x3a061b42, 0x8be5890a, 0x41900e66, + 0xaa285397, 0xa068ea9c, 0xa193dcbe, 0x9f7ffb2e, + 0x80aa5197, 0xe473d1c7, 0x801bccbc, 0xc435ef45, + 0x582a76cb, 0x65283821, 0x8d4f1552, 0x4369a4b0, + 0x6ffb58b6, 0x9d69709f, 0xc4989d21, 0x3c1ab5ff, + 0xebad12db, 0xac330967, 0x3467f89f, 0x264f7e5c, + 0x04be69ad, 0x4b3174d8, 0x3746242b, 0xc299d5b7, + 0xc134a601, 0x7a9f5294, 0x4aecd319, 0x51154234, + 0x0a5a7180, 0xadefbdb2, 0xfb3bf137, 0x55c839ad, + 0x333ae081, 0xac7239b8, 0x96de5477, 0x3c562516, + 0x819a43f7, 0xf0a93b64, 0x9017c9cf, 0xd90a96be, + 0x956abd6b, 0xbe14d92d, 0xbff0b51d, 0x54bc4fbd, + 0x7b582d3c, 0xd016ad18, 0xb9ea92e9, 0x404a1825, + 0x96ad48c4, 0x01c30b60, 0xb71b764a, 0xc5e83022, + 0x6bd6a3df, 0x99d752ed, 0xdba50160, 0x8ae6ae76, + 0x974834b9, 0x7b43f985, 0x5930337a, 0x637da8a3, + 0x498d3b46, 0xff545989, 0x636e4bbf, 0x36f5bd68, + 0xab22e0e8, 0x5ba13795, 0x338b92bb, 0x8bfd201e, + 0xd7cf5375, 0xe0f52c6b, 0x27811ca0, 0xa1420d9f, + 0x6e594c9e, 0xc5f505a8, 0x08ffc79d, 0xed20c941, + 0xb9428101, 0x064b4c52, 0x5eaadb2f, 0x1af0551f, + 0x61f8af78, 0xf5e112f4, 0xb9e84b63, 0xcf725bb3, + 0xa02a2e65, 0xc07babfa, 0x3f70eb00, 0x06d3f569, + 0xc8284125, 0xa6619823, 0x729244b4, 0xd20ffaa6, + 0x025af246, 0x2772f59c, 0xed130a74, 0x8d1ad807, + 0x602f3466, 0x4c483502, 0xa984517c, 0xaf889784, + 0x181f076c, 0xc2e7db4e, 0x21beddd1, 0x4f30741f, + 0xf7569779, 0xec6d74bf, 0x8c6f878f, 0x28058e49, + 0x3b6ae1fa, 0x016154a4, 0xd89b3eaf, 0x67893386, + 0x4948c802, 0x72359f2d, 0xbd586e7c, 0xefade558, + 0x66f5ebd7, 0x4d903956, 0xb7c7573a, 0x98bf67f0, + 0xa9c6a6b5, 0x31652d15, 0xc71a8f90, 0x747cc66d, + 0x0ca883d4, 0xb47a5b85, 0x7b3f7a41, 0x63655254, + 0x61b86ffb, 0x85c20b37, 0xe2f8ac44, 0x2a23083e, + 0xe611c93d, 0x542036b7, 0x3082a731, 0xdbc5fe01, + 0xd7a03fe2, 0xfb351402, 0xaa21517b, 0x958a55b4, + 0x868b20b2, 0xa9f4ff87, 0xaafde28e, 0x090917f7, + 0x90fc5886, 0x89ffc27c, 0x135846c0, 0x5157ffff, + 0xaddfe6e0, 0x420de05f, 0x4c4ff192, 0x501b2d8f, + 0xeb0b326b, 0x57ab5ded, 0xdb1086e8, 0xab76fbe9, + 0x170991f0, 0x3dbfe9f3, 0x1cc24909, 0xdb2e3aea, + 0xff55a932, 0xfb9ea5c5, 0xb5d7ab5b, 0xd1f06c5f, + 0x1f190a72, 0xbaa1792d, 0xe96c8d78, 0x575b58e6, + 0x06d241bf, 0x8844c3bb, 0x4e3016b2, 0x32fd4d0e, + 0x45f69dcd, 0x2d1ac976, 0xca23164a, 0xebf0d020, + 0x01b45f50, 0xe387be3b, 0x10851359, 0xb0e532a0, + 0xfdd14b4c, 0x06c09ba1, 0x6ff3fa57, 0x7bb3ae24, + 0x392efe9d, 0x288291a3, 0x763fed12, 0x6878dc1a, + 0x6f4bd552, 0x7eb83b3b, 0x38702104, 0x10a0cc2c, + 0x327dfe3d, 0xab265a51, 0xa8ed1d06, 0x31ec5087, + 0xdbae25da, 0x30006363, 0x6b3445fc, 0xc5a1ab21, + 0x984990b4, 0x6b2e9d74, 0xd309190f, 0x62682a13, + 0xceab4e75, 0x18065ca5, 0x7681d95c, 0xff3767b9, + 0x7951b0d8, 0xa43d8e9c, 0xe3e2f297, 0xff2914b6, + 0x9c93dcbb, 0xd961ec4a, 0x890eaf4f, 0xf4d16c4f, + 0x82f4b510, 0x8c669bd9, 0x144fece7, 0xf6814ed7, + 0xdef133cd, 0x9d4df9d0, 0x19f610c8, 0x7eccfbd8, + 0xa70e28b6, 0x9129380d, 0x15b1c5db, 0xf0f0d86f, + 0xe74153f5, 0x5313e291, 0x9bdcf917, 0xb775a537, + 0x8850c86f, 0x96790a6d, 0x5e382798, 0x153d624f, + 0xbf1211c9, 0xf39ba580, 0x6698bba9, 0x9d0b3816, + 0xbcbfb5f8, 0xd4654d05, 0xae53ae6a, 0x409b5cb2, + 0x8fbdcb5d, 0x9edbf86f, 0x2f8a1515, 0x0901c1cd, + 0xed2de425, 0x68a3de2f, 0xcc3cbeb7, 0x65ca347b, + 0x2927ad97, 0x18c232cd, 0x2a3bf2ed, 0x00346946, + 0xca3d4eb8, 0xd571e640, 0xe77c0f5e, 0xe67a4ba9, + 0xd1d535be, 0x0b210d76, 0x0956d69f, 0xa5da366e, + 0x54266ae5, 0xf5411644, 0xfe133067, 0xf67f5fa6, + 0xa90f5006, 0x9120820b, 0x1e85d6a1, 0xdf497a0b, + 0x820f2b5c, 0xd19fe47e, 0x7a5ee8b4, 0x6f9c999d, + 0xac580753, 0xbc7608d4, 0x78c48ee6, 0x7e39844a, + 0x21df5f29, 0xea7dcffa, 0x9ce59f50, 0x8baec77b, + 0xf758e8e7, 0x7e0a0568, 0x38058ec8, 0x9bcda57d, + 0xff4af641, 0xe62cb5c4, 0x94a42d0f, 0x7808c674, + 0x914e3f26, 0x9c7f08c6, 0x89b0fae3, 0x61f9152e, + 0x36424903, 0xda042fa9, 0x0481c199, 0x06d71286, + 0xa4aeac50, 0xc0bd99d4, 0xa6e2cb34, 0xc4e5cfc9, + 0xc6ca7c48, 0xb7616475, 0x365449dd, 0x79d9d5ad, + 0x24329b9a, 0x65e7095b, 0xaa3e336d, 0x06749e1f, + 0x04a5963c, 0xe507cd8f, 0xd278050c, 0x7360cecd, + 0x2c4abfa4, 0x0b612f7d, 0xb655108b, 0xdb3bb735, + 0xc0fdb880, 0x34b3e5c5, 0xc2952b93, 0xc99b3aa7, + 0xe7051d39, 0xe3344f7b, 0x31241fe5, 0x8c958ee5, + 0xdde4cc87, 0x880130f3, 0xfd28d5b3, 0xb15d852b, + 0x83d7cb4a, 0x7bf26fc0, 0x2d9e3c36, 0xab0304f3, + 0x435c930b, 0xc5ebc70d, 0x08416b31, 0x89acdfeb, + 0x12c9e83e, 0xaa05968c, 0x9e5a67d8, 0x3bac1b48, + 0x5d32c0ab, 0x330309a8, 0x4b99deaa, 0x8f1ecd35, + 0x80d1d798, 0x6707bf8f, 0x25bb560c, 0xb9145b28, + 0x47e43b2e, 0x9dea75b6, 0x95fe6f30, 0x9fb167b7, + 0x7aef02dd, 0xabf4b3d1, 0x98d09d41, 0x62031949, + 0x1ed7a5d2, 0x3a9a8588, 0x17f98a61, 0x4709c106, + 0x4f176243, 0x38231698, 0x45351109, 0xe1a1fe25, + 0xa20ec597, 0xf82f221c, 0xa2bd42c1, 0x774e0012, + 0xc33a0a5b, 0xd05da439, 0xdfd64aa2, 0x2f548ef4, + 0x56ab9995, 0x2b7a856f, 0xd403cc27, 0x80ccd469, + 0x44b4868c, 0x642f9dbd, 0x5ceab8c0, 0xa4066663, + 0x6889d201, 0x13df6b3f, 0x483b67e1, 0x5af914cb, + 0x136c2bc2, 0x916dbd9a, 0xb510adb8, 0xe2144042, + 0xb657206b, 0xd528fb40, 0xa5de9ecf, 0xb72a58d5, + 0xff8ddfd2, 0xf5d5192d, 0xabbd5164, 0xf17238ad, + 0xda3417df, 0xc76d7271, 0x1eb6138c, 0xfb7bd846, + 0xa3b8c4f0, 0x3e91b6e1, 0x4de3ea12, 0x3198bebf, + 0xe57471e5, 0x1861ff72, 0x102c0ed3, 0xb303d5fd, + 0x6e5e307b, 0x5d90e1e1, 0x3e880a5e, 0xc308cd29, + 0x58785225, 0xa706f09a, 0x9954d5f4, 0xb2d05edb, + 0x836a8223, 0xf0209294, 0xca8dff3d, 0x663e840e, + 0x97a9d7f7, 0x197978c3, 0xb96a6943, 0x47649766, + 0x9f3c9f85, 0x4678ed6c, 0xd359a4f7, 0x20d56684, + 0xccf6f6ce, 0xa420d806, 0x0203bf82, 0x93d31115, + 0x90e9f008, 0xcaa788eb, 0xda2a558c, 0xbe0ded55, + 0xc987b6c8, 0x471b16d6, 0x3cec879b, 0xaf4fe676, + 0x559afe9b, 0x27e3b79a, 0x5be24aef, 0x8b085772, + 0x9e147677, 0x0de2cc8a, 0x23a132f8, 0x31ee16c5, + 0x86c707ca, 0x1db85924, 0x0d0c0e14, 0x5db87d36, + 0x4cabff3b, 0x6d947820, 0x0ff434c9, 0xc5c5760d, + 0x2a88448d, 0xcdf0b1c6, 0xb3d86c54, 0x80ae749c, + 0x49410a98, 0x1851caf8, 0x6350e1a0, 0x504c1297, + 0x09a88652, 0xf3506173, 0xb85689a4, 0x5a799576, + 0xbf0c2ce0, 0xf0d5538a, 0x28f214f7, 0x8643b5df, + 0x20819c7d, 0x71cd2bb7, 0xbdb27657, 0x72dd4ed4, + 0xc84545c2, 0x9a08eaee, 0x16326fce, 0x2d4342c2, + 0xab008c9c, 0x00204ceb, 0xa993c9ef, 0xb7c3c076, + 0x75218534, 0xb14eb69d, 0xf718cccf, 0xb81e5e67, + 0xff55fc53, 0x970bbbad, 0xda2f1a45, 0x256f333d, + 0x1ff0f5a8, 0x2eb661a5, 0x0337ef90, 0x57e1656e, + 0x4a9b07ee, 0xacf54f2e, 0x9717abea, 0xb5bb714c, + 0x1792f7a6, 0x81cdd7e8, 0x62a12406, 0x761f99f7, + 0x072a3a97, 0xe22bd93e, 0xf100ec03, 0xc8e0a791, + 0x361145f7, 0x36e15247, 0x2ee9386a, 0x1d439e0d, + 0xea8b8df7, 0x674afbe1, 0xe33b5da1, 0x23690868, + 0x9fd72a8c, 0xf7dd3c7a, 0xed75f0e8, 0xaf8c3031, + 0x198afbff, 0x92010eba, 0x7748e906, 0xdd8844cc, + 0x00affff6, 0x24d46ac1, 0x90df95f0, 0xdd0c2aa4, + 0xce2104aa, 0xe23e4620, 0x142b9215, 0x769d8186, + 0x6ec121a8, 0xdd309c46, 0x7fb0b89b, 0x8016afdc, + 0xf3708954, 0xce3d39be, 0x52476650, 0x9e827030, + 0x0ca77a29, 0x7df3a31e, 0x4fca9715, 0xc59ad4a2, + 0xbb26442d, 0x3f8a3cce, 0x81e09ea3, 0x94919687, + 0x958c6a31, 0x06508982, 0x32988dab, 0x3a276ce9, + 0x0208f157, 0xcf8367d3, 0x163ba3bf, 0x17159607, + 0xf265d581, 0xaad84b54, 0x63a9365d, 0x80af00dc, + 0x257f8001, 0x772dfd0d, 0x367eecf1, 0xdaa6aa96, + 0x0f6a5c10, 0xd5acf51d, 0x7872c2e5, 0x79708bf6, + 0xc40f652b, 0xf62bc7ca, 0x22952a96, 0x5cffcdfa, + 0xfab55a3f, 0xcf5256b9, 0x27de0e02, 0xdace9547, + 0x92db78cf, 0xfa005e20, 0x3ec98153, 0x1647c3e5, + 0xe386397a, 0x039b0510, 0xb02c2fee, 0x0428ecb9, + 0x7e889fff, 0xc39d8bf9, 0xadfacddc, 0x64f2ca0b, + 0xa82acc83, 0xbacf9264, 0x656e28d5, 0x53014b7b, + 0x014a593c, 0x43ae7d08, 0x4e5e660f, 0x6b548f42, + 0xbd1c298c, 0xfae46cb0, 0xb2983391, 0x5461c49e, + 0xc4d0be21, 0xae949561, 0xe719d444, 0xb9e88874, + 0xae19b604, 0xc8df3646, 0x1354ab60, 0xe47f58ab, + 0x4f827aac, 0x83344c8c, 0xc0233ae0, 0x2118c6ec, + 0x93e3f597, 0x1b5b0281, 0x0ddc480f, 0xfb7c17b6, + 0x6fad8d4e, 0x1dae9191, 0x09d78e21, 0x53ca75ee, + 0xb9c4f84d, 0x610154ce, 0x7f113f51, 0x33332eff, + 0x2e8bf6ed, 0x9a960f02, 0xf4287ef4, 0x494b8b99, + 0x8bd01fe5, 0xe0baa3b7, 0x39cd90ff, 0x12fd7ef8, + 0xf41687dd, 0x62bff535, 0x7e8b1b36, 0x0bda14b7, + 0x7d179fce, 0x9faf161d, 0x03b14666, 0xb356ecb0, + 0x3f2b190d, 0x38846643, 0xb9a3442a, 0x4c56f86a, + 0x05ad857a, 0x54789c95, 0x3ad47233, 0x392744bc, + 0x0b7f7d75, 0x28a7ed56, 0x15a84f5a, 0x1b02dfc6, + 0xbc8df094, 0x82690988, 0x7a390885, 0xa1bbe4a9, + 0xdc71d353, 0x6d26f0e0, 0x86660dd5, 0x23248a1c, + 0xb1517a0c, 0xd9d8d09f, 0x63fc6034, 0x65b2e78c, + 0xf9633cf0, 0x97db9ebb, 0x7b9aaafd, 0x351328d8, + 0x8c9d13b8, 0x78b7a2b0, 0xfd60f60b, 0xf98e9794, + 0x159071ab, 0x85c5654c, 0x9fb0bf2d, 0xf870e501, + 0x52474957, 0xe2f03cc7, 0x9f966cc9, 0x390a72a3, + 0x5096b069, 0xd616565e, 0xcc98c4cf, 0x84998bed, + 0xe76237ef, 0xa7be56ab, 0x8a050904, 0x2eedcd6d, + 0x033a7054, 0x95a0eecd, 0xc952457a, 0x490e57ff, + 0x0a93414f, 0x7ee5be6b, 0x31b637d6, 0xa4a09d0e, + 0x00cd2ed0, 0x9a106b5e, 0xb56d3501, 0xf4fea131, + 0xa05f6692, 0x50a4d745, 0x53aefb25, 0xefa92b0d, + 0x81513e81, 0x2d1bb9cc, 0x664d4f1e, 0x9a4314a4, + 0xeaca641d, 0xa91ad134, 0xadf4747a, 0x143b7cd3, + 0x7dad81ce, 0xf5f9e604, 0x79853b12, 0x69789d1e, + 0x30428e5e, 0xca324ec5, 0x0fcc78e5, 0xc53e6fca, + 0x4d35b7b3, 0x3197723e, 0x6875a6d3, 0xd4e337b0, + 0x306810cf, 0xeb665343, 0x7a87f334, 0x54b48e76, + 0xbcca9639, 0x97015ef7, 0xf7489ffb, 0x51137556, + 0x3a00e23a, 0x1601a20a, 0xa56142e9, 0xcf3f6686, + 0xe011d298, 0x12040cce, 0xc35370a9, 0xf0334d1c, + 0xf3ad5d2c, 0x0e8b90f9, 0xa3e960c4, 0x4594364c, + 0xb2c67fab, 0xb9fde2ea, 0x14c177c0, 0xff37d1d1, + 0x9caff287, 0x9ff37fec, 0x65ddd0e0, 0xa3af5640, + 0xe58b14af, 0x20eb11f2, 0x92bbee51, 0xea08071f, + 0xa7307967, 0x40c64879, 0xcd048a82, 0xc67bcb55, + 0x796d61d0, 0x2f64447c, 0x363bfe30, 0x9471cc2d, + 0xffc9abdc, 0xadd4ae51, 0x69f84501, 0xa00f2dd8, + 0x41ba0692, 0x086ae228, 0x399c227a, 0xf5857bb9, + 0x81c407e6, 0xfb89d225, 0xbe135bda, 0x4628c85e, + 0x16075b1e, 0xbd4e9bff, 0x10d56cf4, 0x7b8324ad, + 0x107bc662, 0x145a6ac4, 0xbb843ce2, 0xc3b2ee37, + 0x32e46fdd, 0xebfbff21, 0xf7f879ef, 0xe9120cf8, + 0x07a8692b, 0xdb3178f9, 0x252ab16e, 0xa1a18aae, + 0x5ffd978c, 0x0c930ad0, 0xb9c5ab5c, 0xf313f14a, + 0x0a263adf, 0x4a9e5ce5, 0x200cbf81, 0x51760e33, + 0xdc46fc9b, 0xbc4074f8, 0x457c18fe, 0xa4b32e67, + 0x6b1ddef7, 0xc7a43160, 0x7401a555, 0x121ff4af, + 0xd570ca26, 0x96834b82, 0x22708c95, 0xe03ca738, + 0x0dbe1c49, 0x3ddadd32, 0x7ccc33ff, 0xe6901061, + 0xb1d60fdc, 0x0da12ead, 0x6b127930, 0xa8a1b7a6, + 0x5874d1b0, 0x4dc510a8, 0x10ccdaca, 0xc6261fd7, + 0x9a1f640d, 0x0830fb74, 0x88d32e04, 0xa423cb97, + 0xab47c146, 0x9622a2aa, 0x645cb863, 0xdee11ddf, + 0xa86e42bd, 0xf9abfe02, 0xe90a884e, 0xd8f7c9e3, + 0x0e00e7ac, 0x974bd00b, 0x2ae3ae6f, 0xb3769668, + 0x12af4a65, 0x8168fcb9, 0xd2347009, 0x6eb7cb98, + 0x3d7ded18, 0xa992905b, 0xcc639b5b, 0x070f435c, + 0xd7975257, 0x9a14b13d, 0x60a83c28, 0x3f75d649, + 0x8e4c0293, 0x36fae022, 0x016f50c6, 0xd1a11a06, + 0x37565aec, 0xf013fdf4, 0x573f3c06, 0x6143253c, + 0xe476aa9d, 0x5fb1f168, 0xdb947737, 0x8ecb1d59, + 0x078034ec, 0x34de29ba, 0xa6355e48, 0x26d200dd, + 0x5ed91fa4, 0xfe209ec2, 0xf07f0e96, 0x0c85decd, + 0xdc4826aa, 0xbcd6160e, 0x58fae767, 0x3abc4cb7, + 0x3e53766c, 0x454f65e6, 0x8e6d022b, 0xcd19b787, + 0x290f55af, 0x1fd62d64, 0x8acd2656, 0xca329872, + 0xec09529a, 0x532ea97c, 0x83779692, 0x2330688b, + 0x83e13072, 0x7da1462b, 0x629bed72, 0xd553318c, + 0xa5274b10, 0x5251883a, 0xbca83ba4, 0x66f4380e, + 0xc6bf0e55, 0xb4f7af61, 0x2e22487a, 0xf9b51c4b, + 0x4edb1462, 0x254d1810, 0x6855fdff, 0xbf652c08, + 0xb475e20d, 0x49d2b19d, 0x75869421, 0x342a175a, + 0x4911a63b, 0xfecb43c8, 0xa173e5f6, 0x599ea60a, + 0xad383364, 0x4b414fd1, 0xc73cd9f0, 0xc1bae2b2, + 0xff3421ee, 0x0ef8dcd2, 0x516a1b2f, 0xb35d9270, + 0x78fad230, 0x64753c9d, 0x4ee0c049, 0x3efae84f, + 0x332a450f, 0x5df8fe97, 0x697565d6, 0x5ef8c9b1, + 0xa6fbae64, 0x128ac0e1, 0xf95129a6, 0x1cf53bcd, + 0x04435183, 0xb058ca3f, 0x1a3a086e, 0x9562c50f, + 0x8c90e9ea, 0xa0df4f23, 0x5334155b, 0x16c62826, + 0x680f3213, 0xecd3e8f7, 0xb3836f13, 0xfbb84b82, + 0x3e45ca63, 0x39ce4c83, 0x39bc92e7, 0xa1a067a5, + 0x9dc60770, 0x9b32e09f, 0x78a7cb2b, 0xcd1f68ef, + 0x8cdd261d, 0xa88f0fac, 0xb3ce9949, 0x83471661, + 0x33383459, 0x44246d99, 0xcc9c4fcc, 0x1f8d89ed, + 0xbc75b0b6, 0xd15b7a15, 0x0516ab7f, 0xecf3553d, + 0x64ab1dfb, 0x431ec543, 0x35d4ffdd, 0xbe1d1dce, + 0x3cec9a68, 0xc9f5fe6b, 0x48f216ad, 0x21d5458c, + 0xb4e89c33, 0xdf6fc2a1, 0x75a82ce8, 0x9772d2b8, + 0x50f0ee84, 0xf89dd66c, 0x1af93b95, 0xc82bdb01, + 0x4241204a, 0x38a0852a, 0x83a563e2, 0xcc579e3f, + 0x64c3ff4a, 0x55a489db, 0x09f3e441, 0x47e6f47c, + 0x0ebc9ed3, 0x65a93ed6, 0xbd282038, 0x3a84f7ca, + 0xe9aea1cb, 0xba382a96, 0x0b7f4464, 0x82c2da22, + 0x08cd24d7, 0x1f7c415b, 0x08592b5b, 0x1fd07e86, + 0x866322ef, 0x0c13e720, 0xab129b1f, 0xad307bb0, + 0x9dd275dd, 0x4736eb09, 0x56472906, 0xa06de3ef, + 0x051f600d, 0x788bf911, 0xe84b13c8, 0xc69eb604, + 0x2a7ef36d, 0x35930deb, 0x277db8f7, 0x324b23ff, + 0xc99f7ddc, 0x022fb9e0, 0x376faa11, 0x880d3142, + 0xe0364be6, 0x3d736920, 0xfe801b4c, 0xc79e26b6, + 0xb15bc802, 0x7a203cc6, 0x2e41cee3, 0xaf4ecc90, + 0xf00b3388, 0x472e4cba, 0xf5c5fa9e, 0x499282ea, + 0xae3c37d4, 0x9c4dc51d, 0x4447b018, 0x96f3c04e, + 0xdbf895ad, 0x78277314, 0xc8322681, 0x4799a312, + 0xa1f59724, 0xcdbd0a94, 0xaf0e344b, 0xfce052bb, + 0xdebb9269, 0x5b708031, 0xa6dd155f, 0x28a8e97e, + 0x47a4d35d, 0xbca41db8, 0xd44e8c89, 0x8ea4cfd4, + 0x2087643e, 0x5c5361a0, 0x19d5b038, 0xe1a44e71, + 0xbaaa5865, 0x32985d2e, 0xb30cb132, 0x8346f712, + 0x72122d8a, 0x9da8fe8b, 0x8ad3b0b9, 0xb86020c6, + 0x96076c4d, 0xaf15e5dd, 0x4eb7694e, 0xcb66e0f9, + 0xc0cc7811, 0x9f62498c, 0xf7628eb1, 0xb40f5782, + 0xe3909967, 0x5268c0ea, 0x5ed85a84, 0xeddcfc66, + 0x2aab8bcc, 0x67d9cc4c, 0xdad309a9, 0x4fb8f216, + 0x87b670ff, 0x8046968e, 0x1005493e, 0x7aff15cc, + 0x18a3b0ff, 0x275e0830, 0xe794620c, 0x84ff92f0, + 0xefe38a1e, 0x5f13f4d9, 0x5b65eb4e, 0x0e3b130b, + 0x28c7a40d, 0xd2e79e8a, 0xa979057b, 0x865238ac, + 0x11c29a5c, 0x9c4a67b0, 0x3a4033e5, 0x5cd9ce4d, + 0x446f5f03, 0x3eb976ec, 0x0db06dfb, 0x7d91aba4, + 0xfe5a51ae, 0xaa1fc1aa, 0x84faba78, 0x74e7675a, + 0xb8b6c3d2, 0x2bf10867, 0x372e7c86, 0xe41e6e82, + 0xa4a14b4b, 0xccd7934d, 0x9dfd2ab8, 0xf85e71fa, + 0x0b03de17, 0xab711a2e, 0x0c3667b5, 0xc1168ffd, + 0x8f136051, 0x404a38d9, 0x4b1c5b34, 0xea938905, + 0xd7e8ca3f, 0x76e7c24d, 0xd12d7b32, 0x83d3d1e7, + 0xcbdf10fa, 0x56c9a35b, 0x487ddb54, 0x2625fb37, + 0x58115a05, 0xd7ba9677, 0x32485abd, 0x7f1cf033, + 0x1363fcf5, 0x498429a7, 0xcee7b643, 0x4a143dfd, + 0xc7277108, 0x540a1db1, 0x8f382d79, 0xe6d57a47, + 0x7573ff7c, 0xab24a417, 0x038c794e, 0x3d554bae, + 0x7701c302, 0x7503f382, 0xd78eb998, 0x981f748f, + 0x8674777e, 0x50d1d36a, 0x720d2a1c, 0x5a73a23e, + 0x6c11d5d5, 0x5a50129d, 0xb102a470, 0xa7725c61, + 0x50367f63, 0xb40cb199, 0x36e40d6a, 0x351e6215, + 0x844a1961, 0xd7e04ed3, 0x840dd7fd, 0x6d1cca8a, + 0x8e87c6fa, 0x71577bfa, 0x0f332230, 0xee23eda7, + 0x693f76e9, 0x3c8ed3c4, 0x6a72fca5, 0x91bc7dde, + 0x8353ad65, 0x7fd77a7f, 0xc9fb1685, 0x63d52396, + 0xc58586cf, 0x1513f259, 0xd0b1b6c1, 0x50ccee15, + 0x4bf40990, 0xd78a2a7a, 0x4e356a76, 0x9db0a659, + 0x8472ca4c, 0xc74eeff6, 0xe5548c38, 0x4ca3343d, + 0xa380a749, 0xfcbba8c7, 0xec8b5df2, 0xf290a3f6, + 0xda4fc91c, 0x4e037ff3, 0x369ee32b, 0x1e4f0d76, + 0xe771cddf, 0x165aed55, 0x28b0b90b, 0x67d033e5, + 0xbd763f03, 0x5bd5e38e, 0x4295e5a3, 0xa293db4f, + 0x5f607ab4, 0x5322a0d0, 0xc94c8c94, 0xeceded4d, + 0x73785c71, 0x17e0bf88, 0x7f5c0911, 0x98d8710f, + 0x567d8325, 0x4761278a, 0xb8f49fd0, 0x22ae4f2c, + 0x5b913027, 0x31da1fbb, 0xa859ccd5, 0xf628dcd8, + 0x0c08f212, 0x757dd74a, 0xa3483622, 0xa4afab73, + 0xf85495fc, 0x79aeba4c, 0xf760fedf, 0x37e9980a, + 0x70afa8a8, 0x771fccd3, 0xabe409ae, 0xa3caf014, + 0xc61bb263, 0xdf6f080a, 0xa1b1a7a1, 0xd4cb1433, + 0x772173b1, 0x127e2a84, 0x6078ed37, 0xe9ae0d72, + 0x068deb2e, 0x538509b0, 0x3745ca8c, 0x80411c2a, + 0xdc0af1f1, 0xbf1bd266, 0xddb1e7da, 0xe58b0f03, + 0x8cf24e18, 0xb082104a, 0x3f3bf7f5, 0xbc52c82b, + 0x7c289318, 0x91621c7e, 0x61ba7282, 0xe057ef2a, + 0x2c7490ec, 0x636ed4f9, 0xef4ee885, 0xc2102cd3, + 0x03b096fa, 0xa721a20f, 0xe2e2de9b, 0xdf99ee9c, + 0x63e87140, 0x98f04a3b, 0x998a1415, 0x47d425d5, + 0x81e18b1e, 0xfd75cd73, 0xda911e2f, 0xa131759c, + 0xe609c123, 0x8bcf7251, 0xa062ca69, 0xf1254c75, + 0xca0c3afa, 0x2b620162, 0x8f05cdc7, 0xf5e35e5d, + 0x694d0ada, 0x9c30edcd, 0x91fcd15b, 0x7c4da71f, + 0x8133bb65, 0x60c41108, 0xc8fe6ebe, 0x24baed41, + 0x327b23e2, 0x3823edbd, 0x77a223e9, 0xeb2d7390, + 0x16068273, 0xe63bfd53, 0x0f29df30, 0x27d62905, + 0xf0ac1652, 0xe6f5f20d, 0xfee7aab7, 0x6e6aa877, + 0xb61f6c21, 0xca0b9dde, 0x16b8384c, 0x8eab3c80, + 0x0de85346, 0x3d3d32e5, 0x58663398, 0x0b0b33e9, + 0xd154d1f5, 0x5c747425, 0xe4228b0b, 0x856dcb01, + 0xa716d47f, 0x805c4ca7, 0x1d815217, 0xd8a0cf3f, + 0x42f34017, 0xba088929, 0x80a2cd8a, 0x517ffe63, + 0x20aa7c69, 0xa72d7746, 0x165e2f6a, 0x93e5568d, + 0xf8f31ded, 0xd1598f8a, 0x2fda6076, 0xa31b5c80, + 0x8d43b7f2, 0x7d2375c1, 0x2a00e4b7, 0x1040cf38, + 0x264e88d7, 0xc8abe360, 0xdfe13c3e, 0x3b750fb9, + 0x406183c3, 0x78bc2427, 0x334b01d1, 0xc26cad7a, + 0x88b72b50, 0x1bc1d63c, 0x32810eca, 0x80f6a523, + 0xa141a57f, 0x32ce732c, 0x68556d26, 0x72a0dc26, + 0xdd25e4c0, 0xa61f2404, 0xe1592e10, 0x4698acc1, + 0x7d80e659, 0x0913ddf7, 0xda82f04b, 0xb788cd43, + 0x3de72856, 0x8bc444d2, 0x1d3dc87b, 0x2380fbc0, + 0x434fd2d0, 0xa37cc127, 0xa5806f48, 0x2bbd90ae, + 0x0c4d4ebe, 0x6a9306ba, 0xac3254d9, 0xd7cefc84, + 0xc98c0ca7, 0xea8bb1c6, 0x16851fe0, 0x02c28a65, + 0x76324463, 0xac6c62c3, 0x9bb2ce0d, 0xe7f220ba, + 0x59a250af, 0xf432731f, 0x555c8843, 0xb0fbdbf5, + 0xc4f37431, 0x64d68150, 0xb9da0993, 0x9321efd2, + 0x67e301bf, 0xf6c6ea44, 0x3092635a, 0xd1ebed53, + 0x02115815, 0x22815a78, 0x74c011ea, 0x303b0004, + 0x317bc945, 0x79fffdb5, 0x0f5aed16, 0xaf6eabb2, + 0x93624d52, 0x8d9cdf73, 0xd5656d1a, 0xbc7a2d44, + 0x880f264f, 0x1db87830, 0x2db5e687, 0x89d6bac3, + 0x7d3e0955, 0xb3b5db9f, 0x0d9405b8, 0x22f818be, + 0x292e26fd, 0xb461ebc9, 0xa6b5ddab, 0xa6e4f23e, + 0x2a088cfb, 0x9fc5b8d6, 0x59b210a7, 0x1498dd36, + 0xe4e9feaf, 0x1a47f3b7, 0xfc5693bb, 0x52076044, + 0xe2074937, 0x9762fcfa, 0x0700fd20, 0xc324f305, + 0x3a7e03a2, 0xc766ab10, 0xa17541e4, 0xbce64eaa, + 0xe68c5ae4, 0x5bf60a02, 0xf89f055e, 0xf13ccc98, + 0x969b0106, 0x22191c6d, 0x8d2e0add, 0x33738386, + 0xd3363e1a, 0xf2e5e217, 0x6bf72eb3, 0xa2159955, + 0x322bc2f9, 0xdce59e07, 0x1a403d7a, 0xd40da160, + 0xce583705, 0x705b002e, 0x53e38536, 0x0b46b6f4, + 0xc889d7c7, 0xf282eac8, 0x864fc78f, 0x2de9689f, + 0xed001e5a, 0xdafae8d0, 0xc3407619, 0x2ae6a6ea, + 0x69713a02, 0x7bb17fcc, 0xfec1da98, 0xa607c8e6, + 0x99e36005, 0x11e5b59f, 0x8ec18208, 0xf067d7f4, + 0xe8a608b5, 0x26207dd2, 0xc7cb8146, 0xbaf6d7ad, + 0xf47df435, 0xc54522c7, 0x748a8b8e, 0x99e794eb, + 0xf2bf9683, 0x52f62b6c, 0x82b46215, 0x572d1d5e, + 0x04c0f1df, 0xe6509ba2, 0x970a88ff, 0x152fc27f, + 0xb93c6389, 0x0146abd0, 0x871834e7, 0x5eb57bc0, + 0xaa0aeb71, 0xa52b0f4c, 0x241780a7, 0x64793af4, + 0x5aaf4d43, 0x3cdbee68, 0x3dca4e19, 0xbaeebf0b, + 0x320a8567, 0xe11a3bd2, 0x9b1d91a6, 0x810d70ce, + 0xd1283978, 0x0d125cae, 0xb013fa71, 0x2bc20620, + 0x3d5d2ff7, 0xde44d71c, 0x7fc69f0d, 0x4ad2e8af, + 0x2f14b582, 0x6853bf2b, 0x68919517, 0x9d5f6509, + 0xd9fab7ca, 0x7a6ce651, 0x8f982024, 0xb5547784, + 0xae74490a, 0x714065fa, 0x405372cc, 0x3a58a46f, + 0xe78230ca, 0x55cef9c0, 0xdbcad2d7, 0x962ea979, + 0x33832922, 0x9673c257, 0xe2a54fc7, 0x758afe4a, + 0x697c69cf, 0x1d03764f, 0x3c472146, 0x11bf0aad, + 0x07d02cc8, 0x61d2ba2b, 0x1c8b3139, 0xa8e1b0dc, + 0x2c90ea31, 0x6103556e, 0xd0e94b78, 0xe3314ab1, + 0xd2cf23ca, 0x04763ea4, 0x4cffeb72, 0x25ec80ed, + 0x63aaba43, 0xaa340488, 0x85e9a636, 0xfcdd73c1, + 0x14ddf111, 0xec29eec7, 0x8acfbdae, 0xd545844c, + 0x222077aa, 0xb3914d02, 0xd0828004, 0x3dfbaecb, + 0xa9b3094b, 0xef71cf12, 0x553fb47d, 0xc1d0cd93, + 0xd7ba76a0, 0xfae66db4, 0x18c47d41, 0x3aa84d32, + 0x175836ff, 0xdd3c5f15, 0xe45bc3da, 0x2cc8d22f, + 0x33bcf111, 0x1318ceed, 0x859f7c6d, 0x5346115c, + 0xae7ac501, 0x7d10961b, 0x6df6c9e1, 0x07a9a3ae, + 0x13e284a8, 0x658ef9f8, 0x20245391, 0x9822ef01, + 0xc1457049, 0x4cdb8fce, 0xf466eb27, 0xf0e3554f, + 0x644780ba, 0x4fa1bd26, 0x82f5f7c9, 0x367fbc36, + 0x75aac234, 0x8950f1e4, 0x73eef9b8, 0x106b26d4, + 0x154ac50f, 0xc928a55a, 0x8aecdff8, 0x6bea8c50, + 0xf819b422, 0x4dde53cf, 0x83e2d7bb, 0x711b4da1, + 0x8c63329c, 0x0117361e, 0xbdf6b395, 0x3ce2ad71, + 0x13afbd7d, 0xd9363170, 0xc07606b5, 0xb3e57512, + 0x34eeef15, 0x9d308933, 0x5d1f96ab, 0x6bdc81f3, + 0x74e0ad20, 0x436731ce, 0x924dd479, 0x39e04f1d, + 0x15e3fc6c, 0x89c73eb1, 0x56d7a3f1, 0x6d90ae82, + 0x1b85ef26, 0x328fcad2, 0x28acd6ad, 0x221ece3b, + 0x918ee52d, 0x869de6a0, 0x8e67660a, 0x57a65605, + 0xc16e2019, 0x5b1a8b07, 0xbb76a606, 0xb864e189, + 0xb42f7ec3, 0xddd14d1a, 0x2d9b60ea, 0x06ab5c4a, + 0x3a5f0e8a, 0xd8a2925f, 0x69c60a15, 0x31aacc3d, + 0xb696029e, 0xf1db51f3, 0xf5a2fc5c, 0xf865e873, + 0x12838c07, 0xac5402f5, 0x4a4d06c9, 0xd376714f, + 0x99afff3e, 0x8faa34e1, 0xc41d60b4, 0x9771a02b, + 0xf054ae7b, 0xedf372df, 0x825d7c86, 0xe3072c73, + 0x0005e224, 0x31c57f28, 0xc16a1696, 0xf53e5497, + 0x7ef862ed, 0x7c6aa7fa, 0x78a74bed, 0xf95a114e, + 0xaa361ba1, 0xa191f3cf, 0xed1a7af2, 0x2f551a17, diff --git a/src/soc/intel/broadwell/microcode/microcode-MC0306D3_FFFF0010.h b/src/soc/intel/broadwell/microcode/microcode-MC0306D3_FFFF0010.h new file mode 100644 index 0000000000..2b954afcfd --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode-MC0306D3_FFFF0010.h @@ -0,0 +1,1088 @@ + 0x00000001, 0xffff0010, 0x07022014, 0x000306d3, + 0x6a251c3a, 0x00000001, 0x000000c0, 0x000043d0, + 0x00004400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000a1, 0x00020001, 0xffff0010, + 0x00000000, 0x00001061, 0x20140702, 0x00001061, + 0x00000001, 0x000306d3, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x10d33c84, 0x5135f3ea, 0xaad3b9ce, 0x370732ff, + 0xb3187746, 0x9ac2b4e1, 0x5b38db95, 0xfb09ed26, + 0xe1d4113f, 0xc3085503, 0x1367060c, 0x9bf7efea, + 0x2b756eb6, 0x2ee07b69, 0x7cfd1dc4, 0x9811c8b2, + 0x86cf4036, 0x20534caf, 0x37046580, 0x432b4e6c, + 0x6a3a2e54, 0x88a74dfc, 0x81a503f6, 0x67736b51, + 0xbc2b11b7, 0xbcf3adc9, 0x96c8eefe, 0x688bcc49, + 0x16c4f996, 0xe0175cd2, 0x454d7a58, 0xa67afd13, + 0x098d9e42, 0xf86d2ec2, 0x738a67a6, 0x26c4ad17, + 0x08666776, 0x050d971d, 0x68998a7c, 0x21ac9cf9, + 0x29e27b61, 0xd61cfd7d, 0x3500ff83, 0xd4123687, + 0x27b72496, 0xe9b867f6, 0x62920d71, 0xe159dd34, + 0x3991c6ba, 0x367a5719, 0x7af5e9df, 0x5cb9fd11, + 0xf5988469, 0x4153f210, 0x24b194a9, 0x8c563988, + 0xac5bfd38, 0xd271e693, 0x16e9b292, 0x0c6583d0, + 0xd2501a4f, 0x9896af00, 0x6665aa9f, 0x0f3a8de9, + 0xc8f0db5f, 0x60b7a546, 0xe3a52963, 0x0ea3eb39, + 0x0d8c08ab, 0x2f5faa26, 0x1d3cbd56, 0xa8596256, + 0x00000011, 0x55ccefcd, 0xadcfd53d, 0xa8b54e10, + 0x43ce01b2, 0xcddf2a5a, 0x1b3de1b2, 0x024efb41, + 0x7815f12a, 0x77bd8a6a, 0x3b853e85, 0x0a2cb8d2, + 0xdf5d38d3, 0xbf01f605, 0x0b6f6cf2, 0xa5400746, + 0x938f8e2c, 0x511d7d89, 0xe2aa03ba, 0xc2ab558d, + 0xa577801f, 0xfe99cd6b, 0xdeaf4c7b, 0x4d3343ae, + 0xecd56e0c, 0x3ce1d096, 0x03744bfc, 0x3b933173, + 0xe519759d, 0x2d5ea8be, 0xb455f95a, 0x5e04f852, + 0x5b7093d5, 0xc634ad91, 0xcd8839f5, 0x1ea77bc4, + 0x2f3e3523, 0x6b132b7e, 0xbe48e6fb, 0x65626813, + 0x54131f92, 0x8b710dff, 0x9e603646, 0x784bff2b, + 0xd90293b8, 0x334b5436, 0x0280fb5f, 0x2dd41e29, + 0xc3bdbd20, 0x756f9144, 0x8cf467f4, 0xd045b0c0, + 0xd89694bd, 0xe7e01b0d, 0xa7665360, 0xb7f67329, + 0x20139111, 0x66863efa, 0xda2a4f79, 0xa8a129e0, + 0xbb6f4436, 0x16f63f6b, 0xe4ef4446, 0x1024e8c9, + 0x1150673c, 0x169781bc, 0x10c922bf, 0xc803b59f, + 0x514fce0d, 0x31f4ea31, 0x9443e843, 0xd289b519, + 0xd1d12dc7, 0x430e94ce, 0x8880f260, 0x8053c217, + 0x4e58c08a, 0x25bfa0ee, 0xe0545f0f, 0x31dd536f, + 0xcf94c10f, 0x7714dad2, 0xc1a687ce, 0x43a6aefc, + 0x9dfaf699, 0xc1b5007d, 0xb7dbaafd, 0xf0680d80, + 0x6fce66c2, 0x222ebaff, 0x37f1f82e, 0xc1f7c230, + 0x35247939, 0xee9e70ff, 0x5b539a2d, 0x0216a521, + 0x4e0fb986, 0x797d1a9d, 0x88e46c0a, 0x53fde70e, + 0xa410dec2, 0x24c9e1ba, 0x4fb95a39, 0xaa21a4f2, + 0x0d047ec2, 0x95f21514, 0x60e342e7, 0xc9c8eb5e, + 0x55a8b4b3, 0x338b3a34, 0x3a0c5517, 0xd2c1d19c, + 0xaaab932f, 0xa71af859, 0x596b6b2e, 0x2dc5e1d3, + 0xcbc950bd, 0x1134ec77, 0xecaf4543, 0x57b8bc7f, + 0x4bc66253, 0x79f1b994, 0x69e29c55, 0x18276356, + 0x037ac5a9, 0x728eab6b, 0xdd21d51a, 0x738cef32, + 0x9599722d, 0x1dd05ae4, 0x22d06e6a, 0x75c1cde0, + 0x949f1edd, 0xe0909f7c, 0x50e439b4, 0x32516b66, + 0xc3784a24, 0xa49cb178, 0x11679610, 0xcf3e5332, + 0x3d03804b, 0x224a88ed, 0x08a98efe, 0xaf7d3eae, + 0xba14c582, 0x13f0cf93, 0x65fff6c0, 0xbe4c9a3e, + 0x34309345, 0x2f4b479a, 0x4be410fb, 0x73bd9f5c, + 0x9ade520a, 0x6095c916, 0x2c9b8493, 0x9ce27151, + 0xef84c6f2, 0x02536213, 0xc69c2e48, 0x7a1b0593, + 0x0fa823c9, 0x57ff8a8b, 0xcb5120d8, 0x73d1e49e, + 0x38fcb16d, 0x93165cb4, 0x7207d21a, 0x2cfca2b5, + 0x8922d17f, 0x65b65fd2, 0x39e1cd83, 0xd307bd67, + 0xf3e4175c, 0xdb7fb4ce, 0x5ed09e9d, 0x5a20d551, + 0xcefdd7fd, 0xa2e25611, 0x52936e79, 0xe62d494c, + 0x4a4f8e7e, 0x103a04b5, 0xe0806adc, 0x466c7211, + 0x4a58a157, 0x718ccb3f, 0x429a1996, 0x09f73a66, + 0xdaf53eec, 0x40c466ec, 0xe6f7ca2a, 0x9a8293e2, + 0x1ab20525, 0x6800f236, 0xadf9110e, 0xdeef284d, + 0xf4ff2567, 0x3875cefe, 0x144bcc23, 0xe85500f6, + 0x7cf1aa2a, 0xa079dbc8, 0xaf7ae1c8, 0x3835e85b, + 0xa5e8cd78, 0x8133d26b, 0xbc8f90e8, 0x418f4ff0, + 0x3ba8053e, 0x02abe8d0, 0xfc6f5caf, 0xbb3ff41e, + 0xa33f1688, 0x4577ac37, 0x17f6c481, 0xf84d6e33, + 0x3755530f, 0x54ef96b0, 0xa8ad852b, 0x7ceb8490, + 0x01a058c8, 0x2abbd4a6, 0xd26fc2b8, 0x1a863296, + 0xef96105f, 0xdecd5842, 0x6eddd540, 0xc8b72419, + 0xb725ece2, 0x031f73f4, 0x1394ed68, 0x044433f5, + 0xe228bc8d, 0xe6653122, 0xcb1b1ea7, 0x91814a0f, + 0x2c4e0203, 0xf4df992f, 0x748ad83e, 0x4955353a, + 0x27b8ed38, 0xf09074f9, 0xb5fc059f, 0xc8c87753, + 0xc5275550, 0xc545ced3, 0xa7760521, 0x01296e85, + 0xfef10f59, 0xbbcb0540, 0x524e1197, 0x2947eb03, + 0xb114aa3a, 0x66f3f4f6, 0x2a943e9b, 0xcf5db2a5, + 0x27d2dc0c, 0x0d188883, 0x44e6f0e7, 0x89efa185, + 0x4c74a64b, 0x273b4f7a, 0xe71afefc, 0x84ecb07f, + 0x67ddaa2f, 0x0a169262, 0xcba03750, 0x64987add, + 0x3edbd52a, 0x8abdc1cd, 0x3d7a2ece, 0x8a189e49, + 0x6eb34b8a, 0xd9e0d994, 0xdaa53746, 0xbd64678d, + 0x6d362592, 0xa3f42f6b, 0xc35633c3, 0x398eab3d, + 0x208c1c8c, 0xc4a88f12, 0xd4010d72, 0x956d911e, + 0xf043ee49, 0x00f2f510, 0xb0f0e1c0, 0x82ceafc4, + 0x05bfbdb2, 0x88b2b297, 0xb6cea039, 0x0472393c, + 0xf0117f38, 0x5ed230c9, 0x2f5ab638, 0xe0ae275f, + 0x0d6eae29, 0xc0dbbddb, 0x01bd8795, 0x7162e3ae, + 0x049a5093, 0x0519151f, 0x98dfe9b5, 0x947144d9, + 0xb61d350c, 0xd190ed78, 0x63ea0bb4, 0x90531193, + 0xde5fb76e, 0xe7e2c9d8, 0x4f6bbe26, 0xb7c39864, + 0xe686f905, 0x28165288, 0x89e6bd60, 0x5888366f, + 0x03ed7eac, 0x31018c8d, 0x2da4c464, 0xf5fe04ed, + 0x35ccd1b1, 0x33b5860b, 0x1a233fa7, 0xed0c0be2, + 0x64c81a38, 0x36b5a905, 0xf9a4a5ff, 0x4bef53fc, + 0x122585ab, 0xd2a470b1, 0xa5d593dd, 0x1d1e745f, + 0x0ce02120, 0xf839e98a, 0xc7269c02, 0x37ad8033, + 0xc675a3b1, 0xcccad7c6, 0x55acb3ed, 0xac8a9bab, + 0x88ba90bf, 0x925991f7, 0xf3537254, 0xfc433115, + 0xfac9d769, 0x0f69cec2, 0x98e8d84a, 0x6909981c, + 0xd8e37e3c, 0x32e14387, 0xfd26207d, 0xe4dbd085, + 0x2304770f, 0xb405a419, 0xb8ab8623, 0xe85ede17, + 0xc4454b30, 0xb0ec30ce, 0x5bf12fde, 0x1abdcbad, + 0x02afba83, 0x9e76905f, 0x0d7768d5, 0xd662eb0c, + 0xc586ed78, 0xd710b92f, 0x29aedb61, 0xaf2f9eba, + 0xde50ffef, 0xbedecf32, 0x95ff9374, 0xac224939, + 0x3f257efd, 0x21c477b7, 0x1dfb7ecb, 0x157c0629, + 0xcc94a695, 0xc709518e, 0x72496bbf, 0x44d68580, + 0xd651cd9d, 0x5b36446c, 0x6efa1bac, 0xc9dc5f4a, + 0xfde12946, 0x2a177fc6, 0x4f8a1d49, 0x16c3ece3, + 0x5e322dd4, 0x78524cf8, 0xf284706c, 0xe8f256da, + 0x6e0bdd15, 0xace40e74, 0x98cac740, 0xdda92247, + 0x2ada3978, 0x8fd65aa6, 0x0db18f0f, 0xc2599d66, + 0xe4ffdaf9, 0xa47df3cd, 0x00709bf9, 0x67c0f182, + 0x5fd455c4, 0xd272c62c, 0x986afe10, 0x1d63f3d5, + 0x68eb7a3a, 0xe54002e3, 0x0af49799, 0x0fc40648, + 0x57d2c82d, 0x5ff7e5eb, 0x9b758838, 0x67d0cebd, + 0xf9f160b5, 0x3d61ccde, 0xef95235f, 0x4ace9d1f, + 0x43cecb48, 0x21412059, 0x4fecb5e4, 0xa49c24b4, + 0xff47e365, 0xd866d529, 0xdb7af13f, 0x5eceda69, + 0x88e317e1, 0xa5543fdd, 0x623b7131, 0x2513d152, + 0x0ade96ff, 0xa24800ed, 0x2ad63ee3, 0x13eb076d, + 0xa9c49ad2, 0xbc60ecae, 0x8aaac34a, 0xcdcbaecf, + 0xabfa7a22, 0x76b24ca3, 0x3d1bb6a6, 0x747edc02, + 0x3a6adaef, 0xa8928b91, 0x2ec84487, 0x86515744, + 0x91ca4f0d, 0x82e63bc7, 0xc8ab4c35, 0xdcbd34dd, + 0x533f6aa0, 0x39e1c634, 0x2b0dfb99, 0x6c3bbe56, + 0xd222adae, 0xdee35ce7, 0xefaa1066, 0x46c0d664, + 0x88eae4b0, 0x84e1c6dd, 0x56fac635, 0x154f6692, + 0xd59be802, 0xf0cafa82, 0x4be2696a, 0x3557d651, + 0x8db33c87, 0xcc35b197, 0x5e96ef0c, 0x3a06428b, + 0xf958ba99, 0xe1887cad, 0x684c0073, 0x182ee4a2, + 0x13cdf247, 0xb3c264f7, 0x89a4c204, 0x9a76bbe5, + 0x12721e84, 0xa548a555, 0xc249df28, 0xe827f8be, + 0x1f13beac, 0x9b4ce727, 0xe1e414b4, 0x54ad8b18, + 0xd8720232, 0x2422aa17, 0xab0e1ce3, 0x223027e9, + 0xd497456a, 0xa55dcedc, 0x6cba766b, 0x82a3ff29, + 0xd410cadc, 0xb8995c4f, 0xd6674af7, 0xc6adb0ec, + 0x1d0256fb, 0x051743d5, 0xf0e6d11d, 0x142bbb74, + 0x800a9d15, 0x047fa9fe, 0xa042d28a, 0xa6161c1d, + 0xbb7c4f40, 0xadb00bbe, 0x1ed84f3e, 0x39c7038d, + 0xdcfb0a76, 0x2d77d72b, 0x0b9fd2fa, 0x7d87e7c4, + 0xcd11a212, 0xf9e93d98, 0x13761993, 0x7ef74b96, + 0xc74b3f78, 0x1b521f5c, 0x97720416, 0xae7e7d42, + 0xd57d5a19, 0x19ae9a3b, 0x81f7ff27, 0x5514060a, + 0xae3af4da, 0xfe9ec101, 0x4be4b53b, 0x60bc35d9, + 0x81bf45af, 0xe8e04d7f, 0x822ea223, 0x568d83e9, + 0x4e394abc, 0x9c68e5db, 0xec09c483, 0xfc96b322, + 0xac374303, 0x0022dc2e, 0x45be810c, 0x3ce1e42f, + 0xfc044ea4, 0x09d7d077, 0x6b5a4353, 0x143e2f42, + 0x4f023155, 0x5d89766b, 0x223f041c, 0x742b5196, + 0x008b12c1, 0x5f4a2293, 0x9e36affe, 0x9758315d, + 0xd5a19407, 0xa2445725, 0x5da6eb65, 0x665a20aa, + 0xec4b0408, 0x4d2efaf1, 0x7c49337f, 0x4e909c1f, + 0xf7c9ba0a, 0x2ec89b45, 0xc97d08e7, 0xe8575949, + 0xc405a9b1, 0x68536a39, 0x5b95dda4, 0x3c55af8d, + 0xd41245b7, 0x114e2695, 0xba9fd11a, 0xa7b9c9a6, + 0x4410c1e8, 0x1f907bc4, 0x09e7cd91, 0x11b6c1fc, + 0xf96914ef, 0xeb17a336, 0xb9e45590, 0x3884f9a4, + 0x94c2fb97, 0xb6f1065a, 0x32e43826, 0x84349de2, + 0x758e23b3, 0xa6e2d866, 0x0f657d77, 0x514d7ccc, + 0x45f29354, 0x2b094c7d, 0x033071f2, 0x183dd640, + 0x357fa091, 0xe5c803ef, 0x94e4d6d8, 0x25c53c3a, + 0xae5c1d24, 0x5be804be, 0x895d7dc9, 0x17b18011, + 0x02cbf8c1, 0xf8436767, 0x2b6dd76e, 0x744fed43, + 0xc19a95f8, 0x5268d7bf, 0xc96f81d3, 0x6c363f06, + 0xaa2b72c8, 0x91b36f54, 0x8faf845d, 0x83c8e65d, + 0xdb134ad1, 0x32d9611c, 0x0d220246, 0x678ca138, + 0xbf9a28f4, 0x3992c27d, 0x4eeed1ac, 0x23cdcf25, + 0x6b9bfd39, 0x371ac7ff, 0x0341c56a, 0x2bd70c26, + 0xf843569a, 0x2890d0fd, 0x4ef4ccd4, 0xa78055ca, + 0x6066e3b2, 0x948087dc, 0xe5403f07, 0x3b0eacd7, + 0xa0cd963c, 0xf8e804b8, 0xb1f21634, 0xe60089ec, + 0xb43c80ea, 0xccc9c94c, 0x3a4c2fcf, 0x1bd9d4e3, + 0x5abcc14c, 0x508f1211, 0xb066a748, 0x839d8ee8, + 0x5636646f, 0x62cc41f1, 0xd5413b31, 0xaff999a1, + 0x9b8347a2, 0x4ee8e520, 0x66551fa5, 0x2e82aea6, + 0x81167f0e, 0xfe8b421b, 0x224febee, 0x60c9a920, + 0x98e76f3b, 0xef8b75fd, 0x41c7db3a, 0x7869cf73, + 0x3ca3a4ce, 0x2606867a, 0x252da693, 0x4bebf089, + 0x7bdec4be, 0x174f293c, 0x6a165360, 0x46d16037, + 0x8d484d2c, 0x9ce71782, 0xb62541e7, 0x69f01344, + 0x6da46cb1, 0xd9c223b1, 0xe7ede905, 0x8715b76f, + 0x64d03cd1, 0x38d956fb, 0x2955d5a2, 0x415dcd22, + 0xd3951748, 0xed521795, 0xc7fae97d, 0xb44532ad, + 0x87c042fe, 0x5f57e097, 0x2124e1c7, 0x04601c12, + 0x8e7bc307, 0xf8c7abe8, 0xd3fe7a86, 0xb947a6d3, + 0xd6b7c3f1, 0xe18e577a, 0xbeadf83f, 0x9dfcce0c, + 0xe4ab27d3, 0xaa12fd13, 0x9084c2a7, 0xd322d3c0, + 0x7783aa68, 0x303fdad5, 0x7972b988, 0x46bfbd49, + 0x06970d90, 0x05d7ff8f, 0x5bc8b497, 0x927b0e9d, + 0x91be9f61, 0x0a47fb93, 0xc35ab4c1, 0x74495add, + 0x05939e04, 0xd9cde83f, 0x8140d31f, 0xcb11ef31, + 0x903035eb, 0x5e4b8d88, 0xaa6f58cc, 0xd218f09c, + 0x68bb102b, 0x4644208b, 0xd040244e, 0x20f3bd67, + 0xfc90da66, 0xd209cef7, 0x38513a95, 0x60740af5, + 0xeeb881d4, 0x9d5bc23b, 0xc63d912e, 0x2e6d4f77, + 0xd2268a82, 0x64580675, 0x02e83ca2, 0xf9ca5993, + 0xcf6afde1, 0xcbb9edfc, 0x383e65fd, 0x64da6644, + 0x1e9051cf, 0xc4ae5d56, 0xfdeb0e81, 0x939423b3, + 0xe8a36294, 0x885c09ff, 0x562ac9d0, 0xffd43f93, + 0xcf9d91f9, 0x33c41332, 0xb262188a, 0x625efa3e, + 0x61f57fff, 0x8dcb5476, 0x64d98389, 0xe2d11efa, + 0xf270c812, 0x05cbc288, 0x6bd74a37, 0xd4a90421, + 0xaf9a2777, 0xf0238bd1, 0x8268cf4e, 0x3535398e, + 0xa2badbba, 0x3012db8f, 0x650fddd4, 0x005a5253, + 0x657c524b, 0x444add60, 0x539a373e, 0x63c13972, + 0x4dd0b633, 0x2f7c594b, 0x3950abbd, 0xa310aca7, + 0x93a07313, 0xdf8b5330, 0x5689c541, 0x4b050799, + 0x0d2d9ed5, 0xe2666fbb, 0x1a1471e9, 0xd0d790b5, + 0x77892416, 0xbb89b281, 0x01e0313b, 0x17e07fa7, + 0x67484345, 0xa7c967e7, 0x33827881, 0x04ef77fd, + 0xb6d42200, 0x14337042, 0x3e9a1ac3, 0x46e0ddb3, + 0x46dd06ec, 0xcf363261, 0x2b72270e, 0x65445dbe, + 0x4f42b725, 0xb6075b41, 0x2b4f6d5b, 0xa70a47b9, + 0xa6387c36, 0xb34750e1, 0x6e0f9a3b, 0x758db076, + 0x8b6c88a1, 0x9934ca5e, 0xee945ac0, 0x7f63c6e5, + 0x1a694049, 0x37b66f96, 0x1d8f3bf0, 0xccd33847, + 0x73940bb4, 0x698c4d75, 0x9d842ac2, 0x397e539d, + 0x148b8c02, 0xb85f87a5, 0x36810368, 0xc5b27787, + 0x3da33072, 0xcd6e1fd9, 0xbcd54d59, 0x0e1c87f6, + 0x4ea36f01, 0x8cc28c04, 0xca4998ed, 0x67d64949, + 0x32f49d4b, 0x7af05681, 0xa17f2357, 0x87c5029b, + 0x5e239a5e, 0xfdc70bb4, 0x7917a33f, 0x359d31ce, + 0xe5e8bf40, 0x7dbb54dc, 0x1e5c4652, 0x96f23e80, + 0x94ff3afc, 0x1916db6e, 0xb8abc275, 0xc6ed8f06, + 0xb7989c1a, 0x132ce865, 0x7dbdb589, 0x9fc28b63, + 0x0496a52f, 0x041ab62c, 0x8b91a1f4, 0x0c4718fe, + 0xb989eb5a, 0xc6f4da1d, 0x07bd8a6f, 0x156c779a, + 0xfcfcc49b, 0x3dc0c9f9, 0xa63a717d, 0x60b280da, + 0x2619d67d, 0x9c42d7ab, 0x28bac19f, 0xa7fcd8d3, + 0x77ce0653, 0xf0e87136, 0x0df2d37a, 0xeb36ef90, + 0x34178dec, 0x5a593c74, 0x16f0ce31, 0xae2aefb7, + 0x87629f44, 0x6225461b, 0x189d5e4b, 0x04359e7b, + 0x09c71ef0, 0xe8bd52ab, 0x4009689c, 0x4aec1256, + 0x1c8d80f0, 0x423ac0e6, 0x0b7984c2, 0xdcfc7642, + 0xca2fba79, 0x25004586, 0x2ff3a382, 0xe19d687c, + 0x4d71509e, 0xfbb9bcf9, 0xc4d4a64a, 0x12170978, + 0x8ce36cc9, 0x690d46da, 0xb843a793, 0xcb1dc1a5, + 0xea03efd7, 0x26ed8d9c, 0xb1e3a724, 0x91449a45, + 0x9eb5cdc2, 0xd1200da6, 0x4b9405a2, 0x0144b568, + 0x34bcf685, 0xdc01660f, 0xffc974da, 0xf1022adf, + 0x2bc91732, 0x2126dfee, 0xee4f0a33, 0xe53a5bbf, + 0xe27a2a61, 0xf6113864, 0xc8170279, 0x3b429d50, + 0x54990a68, 0x5f41033d, 0xd84dc58e, 0x5abb14ce, + 0x8e91f11e, 0x276957bf, 0x2cd4ac18, 0xaffdc797, + 0x044e88fe, 0xdc139d65, 0x8f882e2b, 0x1940d468, + 0xdca778f0, 0xac0639f7, 0x4a5fe861, 0x54624e9d, + 0x48452787, 0x1dddc714, 0x960055c3, 0xef3e4197, + 0x7710b495, 0x0f10362a, 0xba397277, 0x48933e1c, + 0xb82866e7, 0xe1b0f95d, 0x07c61bee, 0x9af9ca30, + 0x890b8bfc, 0xdaa9ee78, 0x5d78dae6, 0x81045e7b, + 0x4f0bdb65, 0x0843f506, 0xa24805cc, 0x03fd1f98, + 0xd017a642, 0x2c225675, 0x8712a634, 0x72c27638, + 0x32f918fa, 0x6da9f658, 0xabc713fd, 0x54409efd, + 0x6e8d7f68, 0x2fd462dd, 0xc78142f1, 0x03617103, + 0xcf90cb8b, 0x8cc4db7d, 0xfd77350c, 0xc5760c58, + 0x3355daae, 0xcfd298a3, 0x250b5b95, 0x2c0a797a, + 0xe47f062e, 0x207e942e, 0x68a85554, 0x8f8bec88, + 0x6cf2b3a7, 0xdd9cfbcf, 0x77da56c0, 0x395c9ff3, + 0xddc948bb, 0xeeb7cc43, 0x2d5a9eb9, 0xd76e7cf0, + 0x949f8863, 0x66a92e3f, 0x091a3dca, 0xa7a71e58, + 0xff133c74, 0xaf1ca6da, 0x2cd31b81, 0x322bfc48, + 0xeac5d142, 0x3aa10c21, 0x129a0677, 0xcf5e813d, + 0x1fd76bfb, 0x83c241ef, 0x2b752e0e, 0x7ce561c7, + 0xe620b75b, 0x8cb5e5ae, 0x7fe55c9c, 0xf336d027, + 0x6830d9d6, 0xc86f788a, 0x04aa903c, 0x226fb45e, + 0x25569ab5, 0x14db3db6, 0xfdca2f52, 0xd7ae0845, + 0xd3ddf63d, 0xaa991b19, 0x0deae63b, 0x4b8c0b80, + 0x88fe96ff, 0xfa4015d1, 0xd64a7737, 0x8cde2001, + 0x52c5c953, 0x60bec37c, 0xb57f919a, 0xecf33633, + 0xd65bb5f7, 0x9bf7e9ba, 0x0213b159, 0xd9f2daff, + 0xe10acf39, 0x416e47f6, 0xdb8a2ac8, 0x484d1ec8, + 0x5acd305f, 0x9772c681, 0x51965a2a, 0xc50ba8fc, + 0x35b99226, 0xb2f4dfdb, 0x97cbe0f9, 0x76a83466, + 0x301b2743, 0x662b1879, 0xf14466f7, 0x3c512ba4, + 0x90d8e115, 0x3ca12cb2, 0xb4deef8d, 0xf55c0cff, + 0xb30b5bcf, 0xa1e61027, 0x9f2cb3e2, 0xa7d5fde3, + 0xc2d7c33a, 0x17a12ee4, 0x623bbd8b, 0xb0c141f9, + 0x1ac187b1, 0xe84bb26a, 0x08729228, 0xb1bda5d7, + 0xda659696, 0xb58881ea, 0x8abd56b2, 0xcb34ba6b, + 0x3a822d13, 0x02cb8c92, 0xc8937fb1, 0xd01c7e1b, + 0x67314272, 0xd4d5feca, 0x96d155ce, 0x9183f463, + 0xddbcd4fd, 0x8a762683, 0x872d3f68, 0x318e932f, + 0xd892328b, 0x82cfe110, 0x111a21d7, 0x58892a8a, + 0xd887a412, 0x8bea7729, 0x64e809c2, 0x08abad30, + 0x857dd565, 0x413a4f14, 0xae98836b, 0x05fdd2bd, + 0xfc1b5b02, 0xf6d0b5c4, 0x7530b97d, 0xf6cd028d, + 0xc9e32039, 0xcd5646ab, 0xa97987d2, 0x9c9c8ca9, + 0xcfacedcf, 0x9fb5607f, 0xf5576f53, 0xce7ebd36, + 0xbe793f13, 0x068e7b1d, 0x75a874bd, 0x715531af, + 0x3b280dc3, 0x45b7acdf, 0x91f6ad57, 0x00b0e0d8, + 0xa82ff53a, 0x028f60f5, 0x48b899a1, 0xc6d53be4, + 0x95c5ed6f, 0xc92b626c, 0xdb187659, 0xd8e645d5, + 0xa101d6ac, 0x00f03a15, 0xf33ec522, 0x5fbd3223, + 0x5798d88c, 0xcdf36fd2, 0xe8d623c5, 0x23c2b8a4, + 0x9b166c7e, 0x837339c7, 0xf8203c1b, 0xcc5ef7c7, + 0x790d7f17, 0x32e4b040, 0x5d39f17a, 0xea444171, + 0x8f324f77, 0x654b6fc1, 0xd558de10, 0xf62c9d57, + 0x65698326, 0x7543f60a, 0x25068be6, 0x2dcbd222, + 0x2cef9550, 0x96ba75a5, 0xb2420ef4, 0xdb9fdc15, + 0x7db73207, 0x57f66346, 0xc78ca728, 0x17719eb4, + 0xfe03090c, 0xb6b5ac15, 0x9adc5d05, 0x3cc4bf44, + 0x1ea2d4d8, 0x3200f937, 0xe465150a, 0xc159f8a0, + 0x0489b80e, 0x90f36892, 0xe05c2d2c, 0xf77e7ebe, + 0x6e10240c, 0x4ba24295, 0x2a79a0ff, 0xf5bd438e, + 0xe6d71c00, 0x46a9d067, 0x85863380, 0x2371615d, + 0x6f4ebfb2, 0xbefb93e0, 0xad6f695f, 0x11350894, + 0xb1bc15b5, 0x9725c7b8, 0x7987288a, 0x6ec83510, + 0x6e109032, 0x92eb2e3c, 0x1d6067ac, 0x6e1b04cf, + 0xa0017e5d, 0xdf928cba, 0x1a1f41f6, 0x06eef9f9, + 0x7d867a2f, 0x8ed9265a, 0xc2404273, 0xe5e31b7e, + 0x0dee39a6, 0xb5a70cca, 0xcd0f6126, 0x62a56d8f, + 0x8a9fa2bf, 0x18944541, 0x0b02a7be, 0xcdc85420, + 0x5f2e415b, 0xf2f17235, 0x7c5926d7, 0xd9a50651, + 0xfa7665fb, 0x2e845bc4, 0x2a220038, 0x845b59f6, + 0xfe08b04a, 0x0edc57ee, 0x58437c79, 0x8e6300a2, + 0xdbbb71bf, 0x510d6535, 0x1e2e0b1d, 0x7da58caa, + 0x5dc40f86, 0x6d5b74b8, 0x8f25d682, 0x61a622c5, + 0x6cda283f, 0x531f08d5, 0x6dbb5606, 0x7cead721, + 0x98d2cf24, 0x76aefc4a, 0x6830aa08, 0xa0d5863a, + 0x3e1d5385, 0xde975d50, 0x0f915cf4, 0x55cfec36, + 0x62d7f21c, 0x7f8953d7, 0xf435d53b, 0x856ccd42, + 0xf9eacd65, 0x0357dde3, 0x861fd0d1, 0x482ea553, + 0xe0d88833, 0x6ed59c4a, 0xbac6a4d3, 0x800b4fe5, + 0xbaf2318c, 0xa8e93a41, 0x9659b284, 0xfb1c517c, + 0xe626bc6a, 0xe12f1718, 0x76d49717, 0x1eb4108c, + 0xf29f93f3, 0xa57ba3f8, 0xb05b8736, 0x7df3615c, + 0xd9f08b1e, 0x3c45e27e, 0xedcd46d8, 0x389a0a47, + 0xa78f7923, 0xbf651e84, 0x32f77752, 0xc1976135, + 0x05d4a266, 0x6743ade9, 0xd87dc149, 0x9aefed2d, + 0x8483fb8c, 0xc52a098d, 0xb4503985, 0x0ecbbe7e, + 0x03a139d3, 0x4dc22002, 0xa753f6e0, 0xb7f87a68, + 0x2226a478, 0xe7bf5e09, 0xd10dc25c, 0xa0f2cfc0, + 0x0162ce9a, 0x0a32326a, 0x58af600c, 0xc2f974d4, + 0x18afe983, 0x5a4d2952, 0x26c1cdf3, 0x0e2ee561, + 0xd4fed0a5, 0x7ea64ab4, 0xdff4b74c, 0x4a43a19d, + 0xecbeac15, 0x08badb12, 0x21227b2d, 0xaad49bd5, + 0x5c334c94, 0x913fd0fe, 0x0bb973a9, 0xd3c41534, + 0x6b563134, 0x2a4ccd98, 0xb2424e3f, 0xcd4730b4, + 0x6c47887b, 0xbd883773, 0xa9d9aaca, 0xb3572d39, + 0x514639fd, 0x06b9849a, 0x7472ac59, 0x1919b2ac, + 0xe0f31bb0, 0x41d51e08, 0xe596b4f7, 0x9739d4dc, + 0x6a6271c9, 0xa9ad95d7, 0xd2a34c1a, 0x81eb269c, + 0x3093f028, 0x4f0e3bd8, 0x5a985a05, 0x3b587592, + 0x0cd7fe42, 0x0d98d31d, 0x0c8078fe, 0x886af0fa, + 0xf8a7268f, 0xf7add825, 0x13c17d80, 0xfb022420, + 0x6b2a360a, 0x68efe7ad, 0xce7203f9, 0xd852d18d, + 0xc680f399, 0xb8fb6f39, 0x2aa7f1ce, 0x7111437f, + 0x355f6b06, 0x038e21ad, 0x8e5e5ad1, 0x4f902cc7, + 0x880af0b4, 0xfdf55706, 0xc0cd99b8, 0xd75675b0, + 0xff7e2b7a, 0xc46bd7b2, 0x22f5da68, 0x6b182e8d, + 0x88cc245d, 0x37142d55, 0x53890b72, 0xe58d82f2, + 0xa534209a, 0x2045d3a9, 0x4955fd9f, 0x8d933654, + 0xd9cd95d7, 0xf00302c2, 0xa48fab0b, 0xaf573c59, + 0x82b014d6, 0xb42e1b06, 0x43b4d2a4, 0xe90c1961, + 0xd67ee71b, 0x9ef78d9a, 0xb5b75930, 0x2b6f16ed, + 0x15c658f7, 0xc585308f, 0x52ee622d, 0x868896cc, + 0x37711c62, 0x67f50b9a, 0xb656f779, 0xdc9bf2b2, + 0xe4023bc4, 0x1e46b333, 0xc310085e, 0xd530fdd6, + 0xf16a3ff2, 0x91556caa, 0xf9ddb1a5, 0xc181a993, + 0x5b34c859, 0x92dba0d7, 0xccaf1b5e, 0x99751cdc, + 0xecafa0a2, 0x7c3898d7, 0x7a3753a8, 0xe876ba1e, + 0xcb34099f, 0xea7ad693, 0xf2a00507, 0xbaa2e9b8, + 0x4f8ff4ed, 0x54e0ec2c, 0xd2f28383, 0x84745e51, + 0xab789db0, 0x8481b924, 0x4adb38ef, 0x27967c28, + 0x77aa9df4, 0x25e3fec5, 0xb0d82d65, 0x5bff868d, + 0x2e1601cd, 0xfd6dfa28, 0xec0defcc, 0x1433527f, + 0xe3607d72, 0x3b213681, 0x0cb9b758, 0x5e8230b5, + 0xa5fe2938, 0x03aeb9c2, 0xa141ff8b, 0xb7b8c5e4, + 0xbd0aaef9, 0xbf99ac9c, 0xbd0a75c2, 0xa6e04389, + 0x27b09e23, 0x4e174887, 0x92582645, 0x3ded2071, + 0x4780cd7a, 0x2203ded2, 0xf912e069, 0x97b20678, + 0x68606eb8, 0xeed60cb8, 0x9d1123c5, 0x7d4ae12b, + 0xf9d368e6, 0xe5010a37, 0xe2aaf18c, 0xc1fa1e70, + 0xc52a00af, 0xb7d0da93, 0x6f5baa28, 0xdb676e79, + 0x7e2144ba, 0x1467e2f4, 0x0ce16dca, 0xbb5344f7, + 0x94b0d824, 0x566c8f33, 0x4a4ca95c, 0xab5b99b8, + 0x1ac7c0c1, 0xd054edfb, 0xec19c505, 0xe446a37b, + 0xff63da78, 0xf4b7fb94, 0x3980bd01, 0x8301e9bb, + 0x969cd5cb, 0x348bb9d4, 0xb1b5c97d, 0xbe6ea5f7, + 0x592640dd, 0x4f75be6f, 0x5eee2f4e, 0x6f93c2f1, + 0xce35e206, 0xad0fa9ce, 0xa3b88c44, 0xfc4cec63, + 0xd642fa11, 0xc4f11ac9, 0x219affba, 0x68973568, + 0x80a40920, 0xb5fdb551, 0xad01947a, 0x628e6eb7, + 0xfd6e7b36, 0x270dfa7c, 0xf0de1a20, 0xed913037, + 0x279867a5, 0x368e482e, 0xe1f616fd, 0x4b915684, + 0xa07bc997, 0x52e0e886, 0xa14cbe55, 0xdc81d053, + 0xe56bcc0e, 0xd3afad48, 0x26a24e3d, 0xbf7e8587, + 0xc0bdeb35, 0x27c7baaf, 0x9b83e7c0, 0xa3b84599, + 0x75fce158, 0xf46d3bd3, 0x85a17bbe, 0xe51c7a1e, + 0x9f227e2c, 0x87a891d8, 0xcc99a702, 0x96bc4343, + 0x3cfad23b, 0x5b4f8b27, 0x7a6b5c72, 0x8735f319, + 0xe00dc6c1, 0x0b70d649, 0x1df426fd, 0x034807c3, + 0x91360e4d, 0x9346f4a0, 0x391b3e66, 0x8c8f783d, + 0x7b78edba, 0x54233daf, 0x4cbb8b19, 0xfa3aee3d, + 0xd4b6d81b, 0x290b834d, 0x53fdc7b0, 0x8c533bae, + 0xc1bc3df9, 0xc29cc74a, 0x9e95057f, 0x94ca33ef, + 0x02beea6d, 0x9e8788c0, 0x34364ae4, 0x6340413d, + 0x15c7e26c, 0xf56fc185, 0x99ff16a6, 0x7c41afa8, + 0x7ac9e02e, 0xa80280c7, 0xb57c19c1, 0x5790f684, + 0x72962892, 0x215a64bd, 0xddad1697, 0x115d02d1, + 0xbaa37fcc, 0x9f2a2d59, 0x0f4b4972, 0x5a98b654, + 0xf0367916, 0x4236c046, 0x198aac7a, 0x0b93e5e6, + 0x1da2f313, 0x993fc934, 0xca3cf006, 0xe19e707d, + 0xe40f8fa0, 0x5d66219f, 0x57fd2765, 0x2b004b0b, + 0xfb1a1ec3, 0x09f68cbe, 0x41131e48, 0x4f8207b7, + 0x9ec36dd0, 0x4a42f678, 0x90045769, 0x83d73cfb, + 0xae976eb5, 0x5bd21372, 0x94e4148f, 0x4667d52b, + 0x20c62f43, 0xf02e21dd, 0x9f29b5d0, 0x1c712655, + 0xd96ab699, 0x9177f5b3, 0x3e66d06b, 0xccc746a9, + 0xb8daf417, 0x4527de48, 0x09571384, 0x6c2ab355, + 0x975050af, 0x6fc7ef4d, 0xba97b08c, 0x3167bcda, + 0x05bd65f9, 0xc044f2ba, 0x247f8929, 0x2377c208, + 0x56061fb2, 0xfe1da794, 0x9b2204d1, 0x20628814, + 0xe241f3bf, 0xdc09bd1b, 0x84c2ad0c, 0x92ae64f9, + 0x2847e1f8, 0xee9bffc7, 0x4661550c, 0xa6452037, + 0x2137c192, 0xd0c93189, 0x4d9598f0, 0x6259cdc6, + 0xd215e916, 0xed7da493, 0x6a08d008, 0x28c6cbb6, + 0xcb96f629, 0xdf4eb175, 0xc162f73e, 0x1c101e82, + 0x3a7685fc, 0xceb08248, 0x649145ae, 0x3e8c55a6, + 0xdd78e0dd, 0x214f109b, 0x39a3f05c, 0xbd4bfcdb, + 0x5a38bb03, 0x7b078686, 0x552a6eb0, 0x47215841, + 0xc6a9fe2b, 0x4de24654, 0xd3758a32, 0x44031c86, + 0xe5df0b4e, 0x4be04fc1, 0x2ba37995, 0xe15b7d94, + 0x24cf9d1e, 0x32fed11d, 0x7f79cb0c, 0x943ff977, + 0x65e31c7a, 0x0475c5f5, 0xf25c8cb3, 0xaf94d63b, + 0x35afc594, 0xcad6806d, 0x21eee184, 0xaeb906a3, + 0xd45e1c48, 0x7a55b641, 0xb338600c, 0xe49bf241, + 0x4d31d141, 0x348d87aa, 0x43a88576, 0xd448e017, + 0xa6b3bef5, 0x17905f8f, 0x3d6b2b0d, 0xe981a973, + 0x931cb674, 0x3d4b796f, 0x1f1225e9, 0x99b3b9d1, + 0xda4557c4, 0x61e49e8e, 0x8f89991e, 0x52997e1a, + 0x4f8b6940, 0x21ebf073, 0x3684b73c, 0x6a68337f, + 0x77c61045, 0xeea1be5d, 0xb4ba0488, 0xbbb363bc, + 0xb324735c, 0x61e51637, 0x42ce6c47, 0x1ee3dba0, + 0x523d3cfc, 0x9bf50984, 0xe581ed76, 0x76c502ee, + 0xba48acf1, 0x3005daed, 0xe641ee9e, 0x050b4099, + 0x9d89205c, 0xbd91d15b, 0x2831f59f, 0xc5a2b7e2, + 0xd26b7c12, 0x79a2dc86, 0x27fd7534, 0x7f07f0ef, + 0x959216f5, 0x880c3353, 0x485cdad9, 0xb8e4263f, + 0x88ed4fc3, 0x681d195c, 0xbe67150a, 0x0247c919, + 0xa6271625, 0xd2c048a9, 0x37431776, 0x6c0494c0, + 0xae094608, 0x00e7f6cf, 0x76b051e4, 0x339509c1, + 0xa130c889, 0x046403b7, 0x9d6265b8, 0x7718e9d9, + 0x93f22ad6, 0x2d04bbba, 0x0333763f, 0x48cd8dc7, + 0x11715310, 0xf3c5c212, 0xc24df77a, 0x5c15091a, + 0x72615448, 0xe8a20621, 0xec95fe38, 0xf92bdda4, + 0x0edb3fde, 0xf0e2fdb8, 0xa88e89a5, 0xfc4a6f67, + 0xe6b29f3b, 0x02f4cfea, 0x0a29bd35, 0x33e8b91c, + 0x5fa6adbe, 0x23c14f59, 0x7b522c9a, 0x9ac96564, + 0x0ab2e161, 0x847ad31f, 0x3a329f2c, 0xfead5e7e, + 0x5d816e1f, 0x42a08562, 0xc71d11f3, 0x9359ae94, + 0x19b49e5f, 0x6a506bde, 0xa558f9ee, 0xcd09ff72, + 0x157dc995, 0x75797e8b, 0x8cb24880, 0x6905e66e, + 0xafbb162f, 0x739a3183, 0x976bebdb, 0xb84ec55d, + 0xb351d21d, 0x806125ca, 0x5262268f, 0xac837b94, + 0xef042c59, 0x26b976e0, 0x699d3a84, 0x899b1629, + 0x4b6adc2b, 0x75ff6ebd, 0x1508627b, 0x12b7dbc6, + 0xf9023f32, 0x03c41833, 0xae930d99, 0x0c68a202, + 0xbcc11466, 0x02ad7ef2, 0x4a18a876, 0xd7daba0c, + 0x6d3e2d24, 0x6cfd2fb8, 0x62846356, 0x8f6effd7, + 0x1a887d78, 0x8f8696d2, 0x3dbf1731, 0x2118af8a, + 0x0a3f96f8, 0xa554e8de, 0xa12dd3f3, 0xc31abbc2, + 0xfad4385e, 0x7753a186, 0x2d107ecb, 0xca21b86f, + 0x0ebde088, 0xa2f25476, 0x9d7c50fc, 0x0e53ed0d, + 0xabaeb7dc, 0xe85b514a, 0x4d1f8e49, 0x4f3ace76, + 0x86dd8dc2, 0x311effc0, 0xb2cfea1f, 0x86c2ccba, + 0x3d493036, 0x061e7e0a, 0xd84ed9c1, 0xcd438c68, + 0xd96cc506, 0xe8682312, 0x502d7cc1, 0x1f074f87, + 0xfe412442, 0x8cf0bfe4, 0xb57535c3, 0x53ad7bd5, + 0x06caa806, 0x23cd7fb2, 0x44632988, 0x2961f19e, + 0x67385209, 0xbeb2e966, 0xbd42b308, 0x5c1d7fb3, + 0x2d1c9316, 0x2923eead, 0x0ded12bd, 0x70b0ef36, + 0xa2c84cd9, 0x4d231e4c, 0x7851a1a7, 0x4de53278, + 0x2f588d90, 0x6659aab5, 0x5807365d, 0x2db999c0, + 0xc1f0010f, 0x66f30649, 0x085058a4, 0x393bed10, + 0x67f027f1, 0x541ccda1, 0x4ef5a73b, 0xca6bb4ff, + 0xe59895e9, 0x81e236d7, 0x76b8e104, 0x6fb180f2, + 0x0e9cd557, 0x00b47910, 0xa981f200, 0x2637db4a, + 0xe339c583, 0xaa0051e7, 0x7747e5b4, 0x5f8724d0, + 0x0d0ccb2a, 0xb5c55bc0, 0x0c2d24bb, 0x158af140, + 0xae9db863, 0xc670e1b9, 0xcafb6285, 0xb1940fd8, + 0xd2e2f4d9, 0x8f4f9d3a, 0x0fb44cbb, 0x7e12d699, + 0x2b2bd044, 0xba6d03a4, 0x37b0468b, 0x98bbf3b5, + 0xfbb8d8f9, 0x9f248319, 0x19abe32a, 0xda9c40f7, + 0x216701ba, 0x49526ac7, 0xf2be6f36, 0x3891b905, + 0xcd42c6b7, 0x6e03730c, 0xc6c0e3a7, 0xa1987492, + 0xc811b616, 0x7e3d88a9, 0x753e56f7, 0x91a90018, + 0x15c447c0, 0x3b17dbed, 0x2a11ad60, 0x9477b9fb, + 0x75094c02, 0x58c31045, 0x63b22748, 0x47af54d4, + 0x9d6583d1, 0xb602db16, 0x27a0088e, 0xd41c80bd, + 0x078c1e75, 0xa697bef8, 0x8126d26e, 0xbfae878e, + 0x3f6efae1, 0x2cc1d1d5, 0x1ad71563, 0x96df253a, + 0x3e3358e0, 0x0f178855, 0xcd2dab65, 0xcc269e96, + 0xefd1a4f9, 0x539477a8, 0xbf3d7f01, 0xa3c1ac35, + 0x754a3d96, 0x669ffc9e, 0xc60c2a59, 0xbb16477b, + 0x52ecac02, 0x47f35403, 0xac4627cf, 0x574a29f5, + 0x97bde744, 0xaabbc29c, 0x7b2e83aa, 0xfdd17949, + 0x12cef292, 0x031d2880, 0xc101a334, 0x1ceb6942, + 0xeaa8581b, 0xe0c14a51, 0x6846b66e, 0x1bd398bd, + 0xddacc1bd, 0xf05f3027, 0xfff6f727, 0xcf55f258, + 0x43257fa4, 0xde22356e, 0xbb72d4b7, 0xc3e401ce, + 0x2364cd19, 0x1769a9b5, 0xac8a6042, 0xea0d431b, + 0x5923d993, 0xcc6b7c23, 0x39307964, 0x5bc4aaa5, + 0x7b144413, 0x107ca5d4, 0xe10192f7, 0x4b1d0063, + 0x0e571f27, 0x5d7dba93, 0x26db4e18, 0x3b51caca, + 0x577cac3c, 0xa480f83f, 0x37f6f5f1, 0xba7c938e, + 0xd860a731, 0xf226b906, 0x3d1c4992, 0xa980bfeb, + 0x8faf6536, 0xf27cebc8, 0x823891f7, 0x8d877151, + 0x0331e01e, 0xf5cc95e8, 0xb2b29419, 0xde83667d, + 0x68ce0b80, 0xc69dc9a5, 0x9fdd7c29, 0xf8fba2e9, + 0x77abe86b, 0x0c5dfdd0, 0x26cbfe84, 0x35d2a52e, + 0xef7db5c3, 0x9cb81617, 0xb52d9441, 0x817bdd86, + 0x2ae4f409, 0xb879e322, 0x5661174e, 0xa5a18de3, + 0xc3ade438, 0x78ec5960, 0x7b103c7b, 0x2193d878, + 0x32f08c7c, 0x42976e82, 0xab0867cf, 0x104677cb, + 0x8329e315, 0x2a368ee7, 0xbf9e6c3f, 0x7cdf896d, + 0x63f828e0, 0x2ab272f1, 0xb26ea341, 0x9b7e2629, + 0x6e9bd833, 0xb3854af4, 0x96b1ef6a, 0xea9b6592, + 0xe6e013e6, 0xc3820c5b, 0x6f5a6220, 0xb75b3567, + 0xa42cb0b9, 0x8fb548bb, 0xcfff5979, 0x979d91ce, + 0xb13bc9b8, 0x673e79cd, 0x492fe687, 0xb7ba2648, + 0x64ccb212, 0xfb543f88, 0x277ff01e, 0xec20a52e, + 0xb2296fa0, 0x322e74f3, 0x24d0d4d1, 0x03505df8, + 0x69dc3a7d, 0xa566599d, 0x20c31f7d, 0xee5bd1f0, + 0x67330476, 0xaed8d573, 0x9b62c233, 0x20cefda4, + 0x2e33256f, 0x46508926, 0xd3320a20, 0x76cdca63, + 0xa91ba331, 0x25e93993, 0x4b0e0132, 0x29c837bc, + 0x9bd487b2, 0xbcd8c521, 0x782b0e0c, 0xd848a100, + 0x5f26ef2f, 0x94f30206, 0xef66e0c8, 0xed53c059, + 0x93554cb6, 0x9625cb5a, 0x41fe144a, 0x96c67865, + 0xea11e45c, 0x6888c5da, 0xaa1dc3ba, 0x29a10939, + 0x0e4ad56f, 0xb2980a6e, 0x14d07a68, 0x43202e29, + 0x63c99bb1, 0x479837e7, 0xa3e51598, 0x1b10d440, + 0xe12d60f0, 0xfdeaa393, 0x751205da, 0xb831d092, + 0x26833df4, 0x2ae55a7f, 0x231be6e7, 0x3bd668ce, + 0x848352cf, 0x62bbab65, 0x95ebfdda, 0x88f20a57, + 0xe74a86ef, 0x251927e4, 0x8b99fccf, 0x332ebee6, + 0x634411c1, 0x15666f72, 0x4ddc73d4, 0x7997bbf5, + 0x96e8fa5a, 0x0ad45882, 0x1d1f7c24, 0xa25f7fee, + 0x95ee1751, 0xa3b656ec, 0x2021eb73, 0xb3bb3693, + 0xa97c2283, 0x38633213, 0x80b81cc0, 0x334ce9a0, + 0x41375ee5, 0x24347b99, 0x98d2ddb3, 0x9e1726d3, + 0xf0a8022f, 0x0f134ede, 0x44be9e28, 0xf827f5b0, + 0x6df48bf2, 0x8d9d9bc2, 0x4fd15f07, 0xbdc157e0, + 0x118428ab, 0xbc2d8e0d, 0x0b604386, 0xc6f180e9, + 0x3f474089, 0x54de30ce, 0x0d0da374, 0x1792dc7c, + 0xb9a271cd, 0x17e98274, 0x8725e4d8, 0x0d169712, + 0xa1518c7f, 0x253096ad, 0x51d7f233, 0x5e8faddc, + 0x2808be53, 0x174a6e0c, 0xba86a1c2, 0x98cca2fa, + 0x417383f8, 0xe5978b57, 0x99f43641, 0x4d293d51, + 0x450141fe, 0x6a96f3c8, 0xc8c8677d, 0xbda2ec04, + 0x12be20cd, 0xa7cda086, 0xda21d3a5, 0x0e8be9bb, + 0xf40631b7, 0x91467e23, 0xc6f09312, 0x83613b12, + 0x81da9c4f, 0x80198116, 0xdad19494, 0xc5d3e635, + 0x1e5cfaf5, 0x850f173b, 0x2cca4022, 0xfc757d5b, + 0x07fc9103, 0x12cc2c45, 0xd7f3c464, 0x26c90d7e, + 0xa04e750c, 0xe1cca271, 0x3dda9264, 0xda567d38, + 0x9e3066f5, 0xf7fd5999, 0x08111fd8, 0xfc76580c, + 0x8a13f16a, 0xf7e1b476, 0x5f3434d5, 0xa52c965a, + 0x42e8ad99, 0x249a6347, 0x1d13a355, 0x6b17701d, + 0x901185a4, 0xc50b6462, 0x2c4dbd61, 0xc74f4735, + 0x3d1dde43, 0x84f7b921, 0xc3060704, 0x250b28e2, + 0x036f3bf9, 0xd1f023a2, 0xda40aec8, 0x6140ef41, + 0x58d87fe8, 0x039891e2, 0xbd187a0e, 0xa4ff16d7, + 0x43e1b111, 0x6a3f4d6d, 0x9d028c10, 0x9ce3fd6b, + 0x0896ac1d, 0xa3606262, 0x6a9c65f3, 0x8b1d295d, + 0xc059e027, 0x7a4b67ad, 0xcab0bd44, 0xe43d1486, + 0x078c5830, 0x89de4c18, 0xaad1992a, 0xd38258c6, + 0x26cef574, 0xf42e5861, 0x09727140, 0x08d78503, + 0x5bcc7b38, 0x8763f064, 0xb45c10a9, 0x53aea628, + 0xbd6ba731, 0x1ebb1f73, 0x2b4e9529, 0x85a6ede6, + 0x89bded7c, 0xbf12a8ac, 0x3bb46e44, 0x41a589a8, + 0x6b7861b1, 0x490613d7, 0x3e06226d, 0x688ae488, + 0xf58119af, 0x2e03925c, 0x2ee2756f, 0xb3dc7a40, + 0x9c4dbdc3, 0x5a1d921c, 0xe2d446bd, 0xd9b6ec17, + 0xa47d74d1, 0xed231a1c, 0x1a592a1a, 0x1e9b3e1a, + 0xea8df403, 0x5f9fb0c5, 0xa99640b1, 0xb2a2ce58, + 0x5883712d, 0x06a844e3, 0xeb26f8e0, 0xaaf17987, + 0x5667fdcb, 0x5b7dfe6f, 0x1a0e7c78, 0xdad14f2c, + 0xf228fb4d, 0x24ca0bfa, 0x17e07709, 0xcbd545b0, + 0xe20e3134, 0x96ca6f27, 0x24d8e4a2, 0xcfb48e24, + 0xdcc1b9ce, 0xd50b1dfd, 0x6dfaa2ff, 0x2cb8fc64, + 0x5228eef8, 0xacfe8a2f, 0x1fbce9ef, 0x9fa74d73, + 0x0cca7cde, 0x5d4e021b, 0x9f06871b, 0x36107093, + 0xa1f28059, 0x6dbafa9d, 0xb9346ec7, 0x2c39cdfc, + 0x4c3ffa51, 0x7426d72d, 0xea66b084, 0x1278c08c, + 0xdd8c1a8b, 0x88ada48c, 0xb50eafca, 0x63e4c8b3, + 0x4c0d5bc4, 0x142222e7, 0x4b5ad5f3, 0x946e5401, + 0xe562686c, 0x36fc6be9, 0x342e0063, 0x811bbb2d, + 0x5b0d15e2, 0x31ff5c36, 0x0b317779, 0x305fdf94, + 0xe9549d9c, 0x2ce6e673, 0xfa149eba, 0xfdb871b0, + 0xcaf9eb52, 0xcc285a64, 0xd77bdd15, 0x69c4e71e, + 0xf6f38ff3, 0xe2d1cab4, 0x060e46eb, 0xd74f7a52, + 0x927334c7, 0x59e6eeb5, 0xd0298c01, 0x634a8c8a, + 0xd5c9a783, 0x3156b7e4, 0x483058c8, 0xf1d53f86, + 0x7c400e07, 0xbb84382a, 0x6b17403c, 0xdceecacf, + 0xb6833efb, 0x452fd3e7, 0x9b8aa623, 0x8792e8c5, + 0xdb23b93d, 0x6dcf4cd9, 0x540980fd, 0x791ad937, + 0xee441f41, 0x2bf6c8bd, 0xba80f8e4, 0x2d8e02c6, + 0xa28aaab3, 0x7fc745ab, 0x1e24e3af, 0xcf895e07, + 0x2cd347a5, 0x0ac67408, 0xcbae54ee, 0xb3b76622, + 0xd72dd7b3, 0xab23f09c, 0x8cd5f504, 0x60ac551d, + 0xe74349de, 0x908b326f, 0xa0936377, 0x52d27d68, + 0x0dca3eab, 0x70600b2f, 0x4df41c92, 0xfa4177bf, + 0xab625810, 0x35952e0a, 0x78347f40, 0x9accbad6, + 0x80e76601, 0x333f2693, 0x88cb1641, 0x4c73988d, + 0x6e36bec6, 0x1e59adbf, 0xd38dfee8, 0xd372ba32, + 0x0c4143a2, 0x2cff48ca, 0x0b9848a7, 0x7f9c324b, + 0x7a546bf2, 0xb8bd8b7f, 0x31c86d93, 0x631f8064, + 0xaa3c6382, 0x23d4e9f6, 0x3649fbc1, 0x5ce228c9, + 0x3f1d1399, 0x94a2baaf, 0x77d4b540, 0xa5c893a9, + 0xf1551a49, 0x7eda3387, 0xc0f554bf, 0x6b8e889e, + 0x89b285b6, 0x843d7d76, 0x26759d8a, 0x31e6a48a, + 0xc8f910a9, 0x9e09646d, 0x1bf0887b, 0x8a42e516, + 0x69eb6219, 0xd67b39f1, 0x1bf54242, 0xe2898566, + 0xacfb9abe, 0xf9ec45cc, 0xb3fc5810, 0x747370e2, + 0x18abe2b9, 0xe8887c2d, 0xd9c04e9d, 0xc2dc1417, + 0xb0dbd1c8, 0xa29d7412, 0x545dabc6, 0x7b2b2c5c, + 0x3131b60b, 0x4d13aee6, 0xb345a81c, 0x5d91b7d9, + 0x19389f66, 0x53d66ab6, 0xe16e9b88, 0xe9319c62, + 0xc8d61b90, 0xffcff3ce, 0x85fa37c5, 0xdb4d940f, + 0xaf4d39ad, 0xa4d32aaf, 0xfec47d58, 0x1df1b6ac, + 0xd6a4736b, 0x7caf5969, 0x22bb3f33, 0x2bc42080, + 0xd2ddc678, 0x8671b635, 0x6463885d, 0xb0bc987c, + 0x2a3bec77, 0x6f467f2f, 0xb688c138, 0xecf1d0cd, + 0xd42a491d, 0x43ee9900, 0x1a050f3d, 0x626ad115, + 0x11cb944c, 0xd12c0ada, 0xe642c2f0, 0x09868c76, + 0xd625232e, 0xb57ed534, 0xa52b37e3, 0x599e2713, + 0x9dcddf43, 0x15908f44, 0x618c34ec, 0x12346d74, + 0x0fd5f43d, 0xcc8a749a, 0x28c7ce51, 0xab790e85, + 0x241c49d8, 0x6353c8b3, 0xab084bee, 0x033c7851, + 0xfe24e4bd, 0xec5df3ec, 0x7b7a97af, 0x4cb958a5, + 0x2e0acbe3, 0x3a456be5, 0x2246b352, 0x237cfbc8, + 0x9239a212, 0xf769e35c, 0x1e0ced3c, 0xbec19260, + 0x1a3971b5, 0xf7fad8d8, 0x7f315804, 0xa1f20a52, + 0x3531ca5a, 0xd69562c5, 0x61b1b8c7, 0xb2966d64, + 0x2a86880e, 0x1dad2183, 0x0f124f55, 0x4d8f95c5, + 0x48f22f68, 0x86108de0, 0x6818256b, 0xfb49b17b, + 0x9162c1e0, 0xcceaa00c, 0x1b70bcab, 0x90cc8cf7, + 0x5112d0ea, 0x738695b2, 0x74967e89, 0x45422f79, + 0xab1f8142, 0xc6a9e328, 0xb405ead1, 0x72d9f13c, + 0xb1132163, 0x8441bbc3, 0x1dca37f5, 0xbbfa84ad, + 0x7fd9dae5, 0x868aa1ed, 0xc0d214eb, 0x52b94954, + 0x042a49c3, 0x67d6aba2, 0xb04a10b9, 0x12626778, + 0xedbc5b58, 0x26fe7db6, 0x05cc02ff, 0xf05b93c0, + 0xdd28c5dd, 0xc0e8f7b6, 0xd1952270, 0x492e86d9, + 0x733a6ab8, 0x97f0e762, 0xc277b315, 0x207bae30, + 0x62b18576, 0xa87be383, 0x75b47de7, 0x71654cf6, + 0xebe5c393, 0x0146a66e, 0xc229d8e9, 0x4ce9aec2, + 0xc0835dea, 0x26e68ed8, 0x169c5341, 0xa5dd2853, + 0xb5b476e8, 0x8389b44f, 0xda71bb79, 0x41c66619, + 0x4e52798e, 0x6da84880, 0x0ce5c0cd, 0xdd4da889, + 0x34ef641b, 0x27b020f5, 0xaf2b67db, 0x9de4debd, + 0x37427915, 0x0f25feb4, 0x0c0ee7cc, 0x1b324d9e, + 0x307f2c6e, 0x5771871e, 0x72e817a6, 0xcf02b6ae, + 0x1d0b6ddd, 0x560f5a25, 0xbd857dc8, 0xfb27e4f0, + 0x4073bd31, 0xd2f5e3e3, 0x02c13db4, 0xd3abbb67, + 0xfa354973, 0x6b103da5, 0xd5f422d9, 0xb96fba74, + 0x54a6af06, 0x92ab7c27, 0x8cf506f5, 0xf32eae35, + 0x52804927, 0xe342df32, 0x9a830e5c, 0x0f29282a, + 0x76a84159, 0x1d67bb5a, 0x9eace297, 0x22ecce99, + 0x5a50534c, 0x23742e83, 0x879802fc, 0x4fb14dc3, + 0x08578e23, 0x6e07d913, 0x2b7f04b5, 0x7143695d, + 0xe3c00675, 0x4ffe12ab, 0xfcf239e7, 0x07988646, + 0x3e028808, 0xffa92b70, 0xe0a4983c, 0xba725578, + 0xd5b9a6f8, 0x98d02235, 0x30586d81, 0x4ff955b6, + 0xbd6311bf, 0xd01ef581, 0x8ca3ff9b, 0x85addcab, + 0x7853db0c, 0xdba09b60, 0xe5f0b23b, 0x0b717755, + 0xc975322a, 0xa2788d2e, 0xb64a06da, 0x440ed7aa, + 0x527508b5, 0xbb640570, 0xbdd40c8c, 0xa382f705, + 0x868a3913, 0x0ae11e7a, 0xec7d6d02, 0x85ea41ff, + 0xd1048c6b, 0xda870fda, 0x2ae6f815, 0x5d24e26f, + 0xafa72760, 0x61b56160, 0x4a75dc9d, 0xed8a7c83, + 0xfdb05b07, 0x65478a75, 0x14e557fc, 0x7588350b, + 0xf40ad263, 0x4cb831f5, 0x90388d9a, 0xf5056b8c, + 0xa2673bd9, 0x490ae87c, 0x7557280f, 0x5cf607ad, + 0xf0a7bd77, 0xf1e64efa, 0x2a3aec2a, 0x70d951ee, + 0xe58fe6e8, 0xa11f32a4, 0x4beb6f2b, 0xa3725110, + 0x6db2a091, 0x8a698858, 0x5299df97, 0x0ae5e62c, + 0xa9fdec89, 0xb1838f15, 0x8b3995d7, 0x43963418, + 0xe4a6c30d, 0x41520619, 0x1d18b481, 0x5cb3e2fd, + 0x3f081874, 0x57269d09, 0xa0b5a54f, 0xdf7bdb42, + 0x7cc4b50f, 0xef414e39, 0x2e0f249c, 0xed1b661e, + 0x7901649a, 0x0bc75b9e, 0x936b26b3, 0x8ff40e47, + 0xc4fa1eb2, 0x7a64f2f4, 0x875bd077, 0x88ead711, + 0x68959297, 0x07204abc, 0xad011e59, 0x24a0cd7e, + 0x2fdcb26b, 0x2574f0d9, 0x0dbd3897, 0x3aa08fae, + 0x99bcf015, 0xa3b80f2c, 0xa4db9ec0, 0xa68dd712, + 0xf20d89cd, 0x36f782dd, 0xcb5d3cf5, 0x6c3a2bab, + 0x6730b232, 0xe6c0aa64, 0xb037a8b8, 0x9e01ee30, + 0x51e45ba5, 0x493a0e33, 0x7f9fcd83, 0x9d34cf75, + 0x71480cc7, 0xc90de6c8, 0x1f3a527b, 0x45ff2042, + 0x8d6be405, 0x7f73ae0c, 0xba765c64, 0x0ad0647a, + 0x50dd487a, 0x36587af2, 0xbe3544ca, 0x03f087ca, + 0x3ac4d749, 0x2cfc99df, 0x3e36578d, 0xa4ee1e34, + 0xb8d5edfa, 0x6a3c56fa, 0x08595b58, 0x3641449f, + 0x83cb63f4, 0xe21d781b, 0x3f7376d1, 0x3e5519bc, + 0x83098eaa, 0x2629aed6, 0xaecab3bd, 0x3a35bd86, + 0x9c94f388, 0x149d6563, 0x3f55d385, 0x11e36afa, + 0xd4537bc0, 0xd8c41d95, 0x05be0728, 0x7c89b3b8, + 0x0d6105c7, 0xa7a9d20d, 0xb6b715e8, 0xa8ae3f80, + 0x4de79620, 0x09eacbad, 0xee3398a9, 0x17df9df5, + 0x17be1459, 0x1d36a3ec, 0x39dbbe9c, 0x398713e2, + 0xedbc6b52, 0x1269d55a, 0xf164fcbf, 0xf39b9303, + 0xda4d5bac, 0x383c6300, 0xfe67d07e, 0xd7ab2d49, + 0x05cab919, 0x829e73d4, 0x997539d4, 0x87335625, + 0x7d806858, 0xf1fbf4f0, 0xb52db2ef, 0xe559bc41, + 0x0e5f4124, 0x74f4a7b0, 0x5df8786c, 0x7426ab33, + 0x3b6309f7, 0xc01ce056, 0x6fa398a9, 0x9281106f, + 0x79b7efff, 0xd2d53fdc, 0x58573c60, 0x23e3bcf1, + 0x4b6802df, 0x861928a9, 0x136c43e4, 0xb4d2b83f, + 0xb9cdfd3b, 0xf6ebc551, 0x94a58373, 0xba8b08c2, + 0x3dfbd4dc, 0x81ec9639, 0x2400ae39, 0xd57634c4, + 0xf1909bb4, 0x35211e33, 0xf90c1a95, 0xede63fc2, + 0xa6ff6a8a, 0x03019f57, 0x638fedaf, 0x3f08c32a, + 0xef44c2fe, 0x192be636, 0x65065249, 0xd92ed3ca, + 0xb01b4d0c, 0xedbc892d, 0xe254f592, 0x5fa231f0, + 0xef67678a, 0xcf9af85f, 0x49fb312b, 0x7a034dcc, + 0x26774c4d, 0x83ad53f8, 0xc589fa48, 0x70467c0c, + 0x90d7ba83, 0x7364b446, 0x670a28c1, 0x9c413fd8, + 0x029c7b7b, 0x56202d80, 0xa921b3b9, 0xe81420ae, + 0xb6f4a79a, 0x740ae45d, 0xad61b781, 0xb430bd0e, + 0x003c8536, 0x3d766704, 0xb3d3ab22, 0x7e7c5c70, + 0xf80fc991, 0x9f64f222, 0x2d915c44, 0x4f6193f9, + 0xe1abb1a3, 0x7b82cf39, 0x135d486a, 0x88fe5af5, + 0x2f9779e1, 0xd2fdc972, 0xd1811806, 0x9c83722e, + 0xc60086ea, 0xaf84f962, 0x36e6fb7f, 0xa61aa4dd, + 0x01e1bb77, 0x1c751390, 0x1b77e7f4, 0xe2be36d6, + 0xb8292297, 0xb2f054b8, 0x1e701bfc, 0x25170bdd, + 0x6c2c6d1a, 0xcc657a4f, 0x9ee5dc50, 0x0b155065, + 0x1780e086, 0x78534504, 0xa9d28d97, 0x63ff34c4, + 0x2d6fc0ac, 0x37c7c572, 0x2454d67a, 0x2077773a, + 0xeecadc25, 0x82bf1048, 0xe85205c2, 0x2c0139ea, + 0xe3c16534, 0x870f0910, 0x2b7df30e, 0x689e3adb, + 0x920f3f94, 0x8a092202, 0xb622606c, 0xf95ca422, + 0x56e2c6b4, 0xd9772b5b, 0x142a693d, 0x28a6fe17, + 0xc304b8c5, 0x64aaf0e8, 0x326ac610, 0xc9ef14e8, + 0x7db4e199, 0x8fa80dba, 0x186f9a1c, 0xed139c43, + 0xbc1a02ca, 0xd2622d7b, 0xd5785197, 0x67532359, + 0xe6251f7f, 0x24791a01, 0xa6f9617a, 0x068f379a, + 0x9658702f, 0xcd15c86e, 0xeb63c3d1, 0xbf1faba7, + 0xfaa82239, 0x60ec95b8, 0x75f32268, 0x607586c3, + 0x67e9bbc7, 0xf83ab0e5, 0xc8c424b3, 0x8e0e625d, + 0x7a76425e, 0x9688584c, 0xcf1191b9, 0xacb7af01, + 0x8fc7effa, 0x9b06e815, 0x9ae32587, 0x335871e6, + 0x5598bd8d, 0x5103eb01, 0x945be170, 0x910c7e25, + 0x43977685, 0x4283ee84, 0x544a0378, 0x862609db, + 0x3e362679, 0x00da3609, 0xae9e717d, 0x864fbda0, + 0xc9e7306d, 0x0a9fcffa, 0x2005ca99, 0xa9fea274, + 0xb46fe47a, 0x2bbfa8f6, 0xbc008fab, 0xcf0c2db9, + 0x8ad12948, 0x8a1937cc, 0x2624d4d2, 0x78450219, + 0x7f342366, 0xf96aa90b, 0x4470d76e, 0x3e720ccc, + 0x591f445e, 0x27af4cdc, 0x3d14c836, 0x0a6ab01e, + 0xb57c960a, 0x1d537c4c, 0x18a74c89, 0x95604e16, + 0xe755f0b9, 0x422baebd, 0x65faf8f4, 0x6a6df86a, + 0xc882aaf9, 0x684f6855, 0x3929a889, 0x41691397, + 0x9ea53159, 0x32d4dbc0, 0x93847a41, 0x2c1d393c, + 0x80020c5f, 0x259339b0, 0x8cd51f9f, 0x6838e9a8, + 0x166840aa, 0x61f979dd, 0x40343536, 0xb1fd9a47, + 0x8bf2cd23, 0xb68b9c6a, 0x7b698187, 0x9816802c, + 0x98bb39fa, 0x3ceb6d39, 0x17acbdca, 0x74ae92e4, + 0xc9f546ae, 0xa624d60e, 0x7dfacb4e, 0x89cd454a, + 0x20a3a0a4, 0x3ff1abc7, 0x5bef9982, 0xe0049752, + 0xd2d85fd7, 0xfcd880f3, 0xd8a7009a, 0x4877e331, + 0xa0a84f42, 0x05561b0c, 0xa5b1f278, 0x41463fd8, + 0x6c6ff170, 0x57a3af47, 0x0640bc5d, 0xc844af89, + 0xa0605721, 0x5f8cc946, 0x6dbc2cde, 0xc28b804c, + 0x6f04314d, 0x63d21346, 0x9bcde6a7, 0x17719258, + 0xc51ac26d, 0x466fc45b, 0x6174dc34, 0x19d6b3df, + 0xc7ff264b, 0xf877cdda, 0xa8a600a3, 0x202d1fb7, + 0x4b8e090f, 0xd39358f8, 0x1ee17661, 0x1e40ffca, + 0x75e35ba4, 0xe59a0c4d, 0x0a61adf4, 0x14d1e00c, + 0xbbc93b14, 0xc303b2b3, 0xb20be9a3, 0x7af82e0e, + 0xfc8d41d4, 0xd9a9f2c7, 0xf12b6eeb, 0xcaa4f967, + 0x0553b2ec, 0xec31a51d, 0x53fa5204, 0x3b8056e9, + 0xd7ec1934, 0xbb939a0b, 0x45ca5cdb, 0xa984404e, + 0xbf5d8c7b, 0xab13bd09, 0x71edce02, 0x1e20f68c, + 0xb9512246, 0x9810f0f3, 0x5aece9a4, 0x0d23fd0d, + 0xd317aac2, 0xdf39c8d8, 0x90afcf4d, 0x3dcbdaa4, + 0xeddbf868, 0x2bcc028d, 0xf9df9b58, 0x27c0fbde, + 0xb020139f, 0x0972a6a2, 0xea8a27b3, 0x3c2d9baf, + 0xb300c74e, 0x5fe2906f, 0xf84bb184, 0xb9645b29, + 0xa8005104, 0x60851a9c, 0xfef0aaa1, 0x169e2106, + 0x443853f8, 0xbbf653cf, 0x7689b59f, 0x6a920bc4, + 0x74ca6239, 0xef0e08a5, 0x4ff0dd2a, 0xf8135e14, + 0x8cf91335, 0x31cf4ac3, 0xd8f42205, 0xf205d095, + 0x23823bd6, 0xa1d39214, 0x364a5a2e, 0x3a2ff48c, + 0x7c0d90ef, 0x5955bc5b, 0xcdf49a80, 0x7862500b, + 0x75505049, 0x9930060b, 0x64cf68fa, 0x6d06afae, + 0x7259bde3, 0x38493f2e, 0xf9a89c54, 0xec8c1a6d, + 0xf38d50fb, 0xe4ab264a, 0x9c5d5122, 0xa82e8b35, + 0xcdf07db8, 0xa74e7e27, 0x5dd6d0cd, 0xbf5cbb8f, + 0x8162b9f7, 0x6bddaedf, 0x090b3ef2, 0x9b025c4d, + 0x2bf26547, 0x86caa384, 0xa8259276, 0xf989d33a, + 0x5488f614, 0x31fcf03b, 0x52a3132f, 0xc2837991, + 0x83509a0b, 0x2c3fcdee, 0x0537ae30, 0x8bc1ba60, + 0xcb16f1bd, 0xf5460c9c, 0x8a166a55, 0xc9f88c22, + 0x2e718e3b, 0xe454a0a0, 0x99df8eeb, 0xfe4e7adc, + 0x6e36e222, 0xe5bb9d47, 0x3a419c64, 0xfeb5694d, + 0x2e196303, 0x53b8d25b, 0x14928e84, 0x8fda33b9, + 0x247eaf10, 0x3edd371b, 0x8b4ca1c2, 0xe7ca3d0d, + 0xec2bb908, 0x1c7dd6a5, 0xd3d1468a, 0x8d2834d0, + 0x7e41df91, 0xd89c37b4, 0x737dfca8, 0x3c566c9c, + 0x46c7cb03, 0x5cd71a59, 0xac854ccc, 0x1597a611, + 0x652f5f4e, 0x005dd848, 0xb7aa8966, 0xa155d075, + 0x0a87d1fd, 0x546d265d, 0xbb33b450, 0xb492d8e0, + 0xf9a1694e, 0xd4244a92, 0xc7c26f5c, 0x225f6159, + 0xf49f3afd, 0x776ff30f, 0x704f26fd, 0x1b1f560c, + 0x6a87e915, 0x0d7cdeb7, 0x3aeb9a4d, 0xf4ed2c52, + 0xd13efa01, 0x3ec1eced, 0x0a130d64, 0x71b6a3ae, + 0xeee3bfa1, 0xa7d77964, 0xac3d2d56, 0xc1d2aa3c, + 0x25055366, 0x724b29d1, 0x2ce9de7b, 0x2bd603da, + 0x28a341f2, 0x36e57918, 0xf0c0c0cd, 0x25de9990, + 0x372f6e73, 0xd5393f89, 0xd5dad0b4, 0x30743212, + 0x6f4f7843, 0x456f16a2, 0xc85e73df, 0xc20c95e9, + 0x030f90f7, 0x98b37b3a, 0x7e8f3bb9, 0x4fe285c9, + 0xc7765899, 0x6f4dbf22, 0x15c60881, 0x62e5d001, + 0x74d7822a, 0x815a7a25, 0x80f1ebd7, 0xcc9b102b, + 0xb7b4ad55, 0x6f65878d, 0x69c4d9dc, 0xdebae9b7, + 0xc3c2ec6a, 0x857c1e76, 0x31f559b3, 0x7942abb4, + 0x90d183a5, 0x4fa03963, 0x84bcea25, 0xad93d50c, + 0x94da5ff3, 0x229373aa, 0x46900b70, 0xa3745b60, + 0x22a3b687, 0x8a0a8412, 0x028ad475, 0x51332404, + 0x91280c7e, 0x0f686770, 0xd50a8e90, 0xc7dc1520, + 0x1b163c11, 0xc10b2636, 0xb7c5233a, 0x146b3459, + 0x01e08e6d, 0x88a89dd7, 0xa6e2f988, 0x55591de7, + 0x20ae60c3, 0x23bf3334, 0xea09a5a8, 0x3226d181, + 0x4ebfbafc, 0x21ceb10a, 0x984174a4, 0x610904dc, + 0x1624edfd, 0xc91fc912, 0x48ff79be, 0xed3d16d0, + 0x8232721c, 0xc1ed594a, 0x0778ccc6, 0x7f161551, + 0xcd9ae8ba, 0xe53dac03, 0x96e9b8fb, 0xb7088571, + 0xb80974ea, 0x8b8a0338, 0xaa3809f0, 0x72e7da59, + 0xd9fd5685, 0x8ed0048c, 0x953be388, 0x753408dd, + 0xae94085b, 0x94abadb7, 0x52ba35e8, 0x127e02e1, + 0x639fbde9, 0xaf650d0d, 0x04f9c1f3, 0xddec0f69, + 0xef92d0ff, 0xfdb2a0bb, 0x78c31f55, 0xdfcd1253, + 0x21f9b437, 0x6d96b9ae, 0x9ab508bc, 0x2a843675, + 0x836c9a99, 0x7c7933ee, 0x9af932b9, 0xbfa49cd6, + 0xb1f7c2f3, 0x953cead5, 0x90bee0e2, 0xda99315d, + 0x62140637, 0xdcdf410c, 0xc3751d69, 0xfc75bc7c, + 0xfbeabdfb, 0xe0f67c5e, 0x8ac9d95f, 0x07870825, + 0x8484278b, 0x3a559cf3, 0x3264049f, 0x295974c6, + 0xc5a808e1, 0xd5d6e802, 0x701cbe5b, 0x7e9245f6, + 0x49644d13, 0x92457586, 0x2f145d1f, 0xc5670497, + 0x210fc22a, 0xf09026f9, 0x9b3675c0, 0xb5d99a50, + 0x9f8b5bf7, 0x6e737ca0, 0x0794339a, 0xd2746376, + 0xcf24ffc3, 0x6aaaf9d1, 0xb96c0ce5, 0x91e61488, + 0x954539ef, 0x513fa42b, 0xd66203ee, 0x2e09f57a, + 0xe47207a6, 0xad33d43f, 0xf99924fd, 0x30ceb1c7, + 0x5ebaad14, 0xd7ce7d0a, 0x771c2104, 0x6f3597b7, + 0x2648ec14, 0x84059481, 0x02da1467, 0x6004b004, + 0xc156e54f, 0xdb1d5a66, 0x398f291f, 0x6cf58bd6, + 0x71faa784, 0x9b38720a, 0xbe0622bb, 0xcf5b38ff, + 0xc404b47a, 0xdcdcb0c1, 0xef1efa54, 0xb60eed45, + 0x4d443f41, 0x58e51159, 0x1d253fb2, 0xaba2c5c3, + 0x11872665, 0x9e513c97, 0x0d493f56, 0x2bf87766, + 0x69f6e4fd, 0x1e91a4ae, 0x4b61f4ec, 0x2e5e0626, + 0x6e6ace05, 0xc43b98db, 0xac8e8669, 0xf95ec0d8, + 0xad89ff8e, 0x88f90972, 0xf9b05589, 0x3c13846d, + 0x4448316c, 0xcc4800c2, 0x8f01c44f, 0x1f28885e, + 0x29136dcf, 0x14ee9bda, 0x183400c9, 0x0f8eec65, + 0xf01a70c0, 0xefcd882b, 0x28089a41, 0xf1960283, + 0x6a304282, 0x4e1846a5, 0xd97d243a, 0xb6aba532, + 0x68cf2bc0, 0xc1b511cb, 0x2bc1f3f5, 0x5659f855, + 0x6687b98e, 0x79b48a18, 0x72682b2d, 0x66f75745, + 0x333d9d9c, 0x7624f823, 0x43152327, 0xc913c367, + 0x694db566, 0x2cf3faf6, 0xde4ee783, 0xf54fd25f, + 0x92eb9984, 0x62f71803, 0x5c3ec0c0, 0x3e1d4a05, + 0xbcfd6911, 0x1756d97e, 0xee11b924, 0xf9a803d2, + 0x63fc94c8, 0x458b2f0f, 0xfb2ae45d, 0x067cd6cd, + 0x45fc990b, 0xe1403710, 0xaceb4834, 0x3a76ccd4, + 0xc340814a, 0xadb1cc38, 0x96a1ae39, 0xe81ea938, + 0x6435318f, 0x6a0180aa, 0x6b2f20b6, 0x61df9ef2, + 0xbf941e53, 0x79f5ddb9, 0x0d848c5a, 0x3fc2fc47, + 0x5cff32d4, 0x95d49bf5, 0x65b05a2c, 0x4a6c7418, + 0x08f9a25d, 0xe36a10ee, 0x445fbb8d, 0x69749917, + 0x1f0902d3, 0x7941330a, 0x0abf18b8, 0xdb28171b, + 0x02640aef, 0xe560a1c5, 0x73d720be, 0x5da8b445, + 0xeadc4577, 0x02682b95, 0xcc302e8f, 0x37634591, + 0x5a1e5645, 0x8ad209d4, 0x6b99432a, 0x3718ce84, + 0xccea20b1, 0x0cec519c, 0x2ae37495, 0x010ca622, + 0x93b1667b, 0x839be883, 0xb096407d, 0x6bdc582b, + 0x405beef9, 0x6811023c, 0x580359c5, 0xbed39e8f, + 0x4f0937e7, 0xb586624f, 0xb52b4cea, 0xdcaf93b0, + 0xcb833f5d, 0x157f06ca, 0x3d54dba9, 0xe1af3819, + 0x605e8d3b, 0xa4e5cb9d, 0x05ac943a, 0x7724d8a0, + 0x633fb407, 0xc86c2326, 0x81c77ac0, 0xc52769e8, + 0xf84a2a36, 0xe2a70a00, 0x196bd072, 0x35fd95c4, + 0x6c7d3276, 0x3464ba66, 0x0bd21489, 0x984b1c10, + 0xb794524b, 0x7c8a4e7d, 0x703eb5ca, 0x053eb7a6, + 0x48c3c863, 0xe7cd55ee, 0x6a108a96, 0xa7f28770, + 0xe68890ae, 0x598c0913, 0xd85d8d18, 0x0cb27cf1, + 0x08055f9e, 0x412433d3, 0x8b015149, 0x968b4075, + 0xaf7df070, 0x9ee63edf, 0x792a72ce, 0x992c0d00, + 0x9779df2a, 0xce170353, 0x78c5cbae, 0xbf2464b0, + 0x977bf73b, 0xdb452bb4, 0x6fe55359, 0xd3c129f9, + 0x1f8500fe, 0xe378b969, 0xa9995fdc, 0xb4d10467, + 0x38856651, 0x019ca81d, 0x7eac2d66, 0x61101584, + 0x0e5e2380, 0xd1bfbd8e, 0xcdb75ce9, 0xc4f91f6d, + 0xf9334a14, 0x2bba6273, 0x21222d99, 0x91832118, + 0xf8223c69, 0x5aeb1319, 0x57fe1ccf, 0x0d14f39b, + 0x9f4109c8, 0x062397cb, 0x8a061fa4, 0x92ca82d1, + 0xd17c8373, 0xb0540892, 0x2e60ec53, 0x628127f0, + 0x2dfa2fe5, 0x7421e577, 0x35996217, 0x05ca69be, + 0x4f3ae334, 0x0c9b9154, 0x379adfd2, 0xed84bef1, + 0xb948de03, 0xcd869ae6, 0x8da93fea, 0x5181c335, + 0xe14e2dff, 0xcd3fa00c, 0xfcf62e2c, 0x5f10d3c2, + 0xe86d2227, 0x1a4171c9, 0x951cf0cb, 0xa4f60f3c, + 0x4256bef6, 0x3e44737a, 0xfba4e163, 0x2e2d16c6, + 0x45c50d5a, 0x96a8c08d, 0xda3753ae, 0x0bbc18db, + 0x6af63d90, 0x15e1506c, 0xecc48116, 0x5f2c1881, + 0xe20c9719, 0x18b3ace3, 0xb71ed8ae, 0xdd99d2cf, + 0xd46a33f8, 0x6d825283, 0x00eacaab, 0x5784c8ad, + 0x3442727e, 0x2fb8c3e0, 0x1b527761, 0x23b57599, + 0xb572276e, 0x3ce4ac6b, 0xbc76a6c5, 0xe115f85c, + 0xa101ebf1, 0xd362e78b, 0x6f755bb4, 0x9a516124, + 0xee8bbbd7, 0xbf2b453e, 0xfa0ee0ee, 0x6bdf2401, + 0xca60b393, 0xcba69624, 0xddf381a4, 0xa0851e9b, + 0x0c33c7a1, 0x8db2b7dd, 0xe100bcab, 0x793ddf15, + 0x02206774, 0x2bd4c624, 0xf45b10be, 0xb87a3e59, + 0xf1bb9661, 0x5a63a609, 0x16c50fb6, 0xa1094c43, + 0xe96fd079, 0x6c4344b2, 0xb49e47f6, 0xe38292a2, + 0x27179eb7, 0x2b2bf898, 0x7893b536, 0x82dfe5ca, + 0x3a3b8201, 0x65b63392, 0x7ccf9846, 0xa0c95525, + 0x142c18cd, 0x4cba26e8, 0x51b58007, 0x233b0bbe, + 0x0ab86635, 0x7cbe802e, 0x62541116, 0xb1670d7b, + 0x1405b57f, 0xf9a6826f, 0x8c84cea7, 0x2c034a26, + 0x82590047, 0x510ad1d4, 0x317f2e44, 0x624856c7, + 0x0d53db3f, 0xdeee6f08, 0x95ddedf7, 0x660abc20, + 0xd01feeeb, 0x6ea13ccc, 0x1a158967, 0x9d67c0c9, + 0x3c62fbd3, 0x851dc52a, 0x2da0d838, 0x460e571d, + 0x09c4527a, 0x0020de5b, 0x3c6a90a7, 0xf4dbdebb, + 0x975313f7, 0xb3ff5265, 0x7fed63c7, 0x81fbed1d, + 0x1cdcb185, 0x69d78b29, 0x9d5b813a, 0x4e340dce, + 0x138d7f1a, 0x6bd01d9c, 0x38847ee7, 0x4f6e82cb, + 0xe5f115b9, 0x681c7306, 0xc2290e84, 0x66083fc5, + 0x1ea902bc, 0xa3942b4f, 0x8d2095ce, 0x0874aef4, + 0xd8aa225e, 0x5f18181a, 0x66a00ce6, 0xca7415e2, + 0xa1e6de21, 0x2d00cbef, 0x2f312795, 0xec4bfaee, + 0x9c77978a, 0x75da7ffb, 0x4fb0f02a, 0x787a8e03, + 0x2f7938e9, 0xdf53314b, 0x75c7c3ed, 0x5f74cc87, + 0x677dc857, 0x25b593c7, 0x892531dd, 0x5b6c2f9a, + 0xdb81e45d, 0x4e566ef1, 0x7e700ddd, 0xae578f9e, + 0xcd22b7ac, 0x68dccf95, 0xf9ad9f1d, 0x5fd1907f, + 0x5fbac465, 0x2dd2f353, 0x4fb4a194, 0x98ebba9c, + 0x8ef8e873, 0x0d83e5a2, 0x9ad91cd9, 0x31d67aba, + 0x37f567cd, 0xf6608dd8, 0xc9f15dbd, 0x7ca27d0d, + 0x51f47bbb, 0xf4dc049c, 0xb2218cde, 0x83e8bc32, + 0x4dcfe51e, 0xa7e9f9ce, 0x20fb6160, 0x9cb01b7a, + 0x02299fb9, 0x1bee3b19, 0x21e81857, 0x32221d31, + 0xe313bb11, 0x81a1efb6, 0xe3f1e910, 0x43aaab21, + 0xb0f9bd0c, 0x14bdf9a2, 0x5e2358e1, 0xd755bfe0, + 0xe41c6f5a, 0x4e534e12, 0x01ff6b4a, 0x087f7f6a, + 0xb19668f0, 0x179a7afb, 0x0c3209d9, 0xbe1e3186, + 0xecc8955b, 0x7647a8f6, 0x49de5280, 0xb7ff2ddf, + 0x893d79a2, 0x0c2791af, 0x689b0921, 0x1881fa6d, + 0x7e367597, 0xc30f9f15, 0x92bb2d5a, 0x3d98f1da, + 0xb7a57e1d, 0x4228c798, 0xa2ab6b7b, 0x5778fa8b, + 0x83a6918f, 0xa55f1b54, 0xea9fb5f6, 0x43fab0d4, + 0xfbb2fb03, 0x69158efd, 0x53e8e345, 0x8065c2b4, + 0xd86a812b, 0x87aa6e4d, 0x7647f3ba, 0xc2d3761d, + 0xe67bdb2f, 0xec9f077f, 0x2f8b6942, 0x9222bf72, + 0x1889c995, 0x69e0b6b0, 0x875cc3e3, 0xa926b149, + 0xa72a34ac, 0x7099062f, 0x66bef7e4, 0xd0fe6331, + 0xdbd7443e, 0x395ca345, 0xba700698, 0x8978262e, + 0xbf61ed0e, 0x43b2d11f, 0xdaf77d24, 0x52232cf9, + 0x113e7536, 0x88b154ab, 0x3083af78, 0x97ae40dd, + 0x608313d9, 0x5ab463f2, 0xe4803a5c, 0xd77c6af0, + 0xdab6eb37, 0x5c333bca, 0xe40bbbc2, 0xd41fed76, + 0x1423e422, 0x8479f31f, 0x4cbd356c, 0x25100886, + 0xad84e18f, 0x19e54ac1, 0x2a99f004, 0x2a878779, + 0x5fc42d6a, 0x5a6a10b4, 0xb0f4c833, 0xae778649, + 0x7128537f, 0xadad2c5e, 0x24f91fc4, 0xf2514b0f, + 0xe7fa42c7, 0xb20d35b7, 0x49ac5e1f, 0x440c2c22, + 0xd81b34db, 0x5309de25, 0x340c4f22, 0x62350846, + 0x62ea039d, 0xc9e0f959, 0xcb56d744, 0x0fc6b5ca, + 0xe240581d, 0x187d9829, 0xa1373631, 0xcafd4540, + 0x34d0afa0, 0x5e2608f8, 0x2ca08662, 0x3c916f89, + 0x5e7274b6, 0xf83e58b9, 0xfb834192, 0xfe11b4b5, + 0x21dde53d, 0x782e7c84, 0xca247bdf, 0x7bcd5338, + 0x49f83851, 0x95b096d6, 0x0dd866cd, 0x685724ca, + 0xc8aa3773, 0x9018e216, 0xf4190695, 0x8c4b6e94, + 0x3a0671d4, 0xd8997592, 0x222fe7c9, 0x2623c9d3, + 0x327aa0d7, 0x9e1794c2, 0x0a0bb3c3, 0x6cd3671b, + 0x1bb3bb4e, 0xd139d797, 0xa3adc4a7, 0xf4246d67, + 0x230cb774, 0x553b0638, 0xbc8bbc56, 0x5397e9d5, + 0xc26ed341, 0xb81bdd0a, 0xc1176e19, 0x45e60e50, + 0xa26ee624, 0xd5fa3aef, 0xa28794c8, 0xaf1993ac, + 0xede7170c, 0x3ccd0a47, 0x733faa6c, 0xaec8cca3, + 0x1d7e74d4, 0xa48de0f8, 0xbfc008f1, 0xbf9c6005, + 0x8506a8a7, 0xc04d704e, 0x67065415, 0xa32886fa, + 0xe37aa2ec, 0xbc089645, 0x03af6c14, 0x794e6834, + 0xf87012ea, 0x4f385ce0, 0x39f73c05, 0xc3d75b08, + 0x1674cedf, 0x43d1e2a5, 0xebf1b7be, 0x5b3b4b3a, + 0x7e6df1ce, 0x0613b3fd, 0xa5db6978, 0xc7caff53, + 0x96b0108f, 0x601cb4bf, 0xde46d211, 0x828b6b32, + 0x52e78553, 0x743aaf80, 0xf2d8cfc2, 0x5be370f9, + 0x7ef4cc3c, 0x772fd625, 0x41e5658c, 0x44cd5c1b, + 0x71c5dcae, 0x9017d706, 0x729e334c, 0xb292c990, + 0x51e82a17, 0xa2840cad, 0xc7e9518f, 0xa181096d, + 0xc01c988e, 0x8691c806, 0x92cd7033, 0xfcbc81ce, + 0xae250082, 0x285194ef, 0x4c5e7800, 0x4855ac18, + 0x06acf515, 0x8ed6d93f, 0xf583a62d, 0x1d8d9f11, + 0x94d8ef69, 0x326f449d, 0x1ba2f7d6, 0x1b055014, + 0x09db36f3, 0x2e2430a6, 0x5d905cac, 0x938948a6, + 0x40905cd4, 0x665fc374, 0xbfa87fd2, 0x1ee766e7, + 0xd393dcf6, 0x601ef0ce, 0xc0ed3f09, 0x280181c4, + 0xdd848627, 0xf85685c8, 0x356c8a83, 0x7eff287b, + 0x779899db, 0x9ddffad7, 0x21d647dd, 0x907c4483, + 0x1e3f8e4f, 0x02ce2291, 0xce169039, 0x92cf5562, + 0x74653c8e, 0xbd2838ff, 0x57302c63, 0x0d616605, + 0x025fd5bc, 0xbf88ca95, 0x8198871b, 0xf4b0192c, + 0x25d4b65f, 0xcf012782, 0x0918b438, 0x28789115, + 0x21dc1471, 0x382e9106, 0x6bafff6b, 0xb8fa48ad, + 0x04b0d4bb, 0x2b0513d5, 0x52223233, 0x5d008f5c, + 0x6d5e167d, 0x3d87f2bd, 0xd2204033, 0xfa946278, + 0x8b5cafb8, 0xafe0e0c6, 0xdb45282e, 0x353e194e, + 0x29970feb, 0xc130dc37, 0x43f6d2b0, 0x566585fe, + 0x9f51d2b8, 0xb8b032ad, 0xace2370f, 0x7249ddf7, + 0x16b3ee7a, 0x6d23855b, 0x33c737d9, 0xa7bb0e23, + 0x2a9cef4b, 0x21f1ea76, 0x863eaeb4, 0xdc076ab6, + 0x23a45f8f, 0x700a0817, 0xf3fabdad, 0xb1302b38, + 0xe3616d6d, 0xd92bb66b, 0x2d5c661d, 0x4b8aadb2, + 0x18ee2329, 0x05df0b20, 0x4b96d565, 0x6da42df0, + 0xec2f38b2, 0xfc11b440, 0x6e66a8ec, 0xd923723e, + 0x8fe0f722, 0x0721702d, 0x099a5300, 0x2ec8aea1, + 0x8cf80bc1, 0xca6e9152, 0x113953dd, 0xc31cf9a3, + 0x86ac6d95, 0x84dbd20d, 0x213a941e, 0xcfe09297, + 0x9fa5080e, 0x4c983621, 0xbac2658f, 0x33a3c43c, + 0xfef8ce4a, 0xdc543d7c, 0x9d97bb9e, 0xceea4e8c, + 0x4bd4b509, 0x14400852, 0x2b64bacd, 0xe27af680, + 0x9a09f9bd, 0x0d2f1f77, 0xae5a85de, 0x62eb7e3b, + 0xb5dd97c6, 0x7c1458ac, 0x753492be, 0x7aeb2ae7, + 0x720d12b2, 0x80fb6196, 0x2fc7b5e5, 0x3725d575, + 0x38e8439d, 0x8049c832, 0x5a708bb1, 0xd5418802, + 0x26990359, 0x31cd28bc, 0x349afc0e, 0x26b7b0ac, + 0xba9af5eb, 0x44427299, 0x6e99771d, 0xd5ffdd7e, + 0x603f66b9, 0xaaa83d07, 0x035d0219, 0xaf5992a0, + 0x7e55e337, 0x855c960d, 0x0a5bab07, 0x6552279b, + 0xb5b7bff7, 0xc44f4b0e, 0x5a66d81e, 0x739c09c9, + 0xdf9ab639, 0xe72d00df, 0x528a7682, 0x12ce8d13, + 0x2d3f86e9, 0xd7b5671c, 0x58ac53d9, 0x553686a7, + 0x64c45914, 0xf43f7e47, 0xd5799470, 0xa8456e42, + 0xb140dfa1, 0x65aaa452, 0x1c66edf7, 0x0f7802d9, + 0x578d2c7f, 0x49271f89, 0xfdd58d15, 0x6ed577b1, + 0xa47df9a3, 0x0b9f2c14, 0xb8a6525b, 0x245cff48, + 0x94421a7d, 0x91b2247d, 0x9fb8614e, 0x00fa2183, + 0x0661bab7, 0x6c7b39ee, 0x0f2ed28f, 0x6ae9ab1a, + 0xcc6a097c, 0x68a6551a, 0x3c79b86d, 0x147f2c2d, + 0x8542f28f, 0x3a832502, 0x03768b4e, 0x3be7ec6d, + 0x01df90d8, 0xe7161507, 0x122a81c1, 0xd93bf36c, + 0xe3921860, 0xcf5bdffb, 0xbbe44e3b, 0x79f043cc, + 0x3f620fba, 0xf045ba2b, 0x4bce3ab5, 0xc9a9b085, + 0x550bd359, 0xff169881, 0xe63da0bb, 0xf1c6c36f, + 0xd39b8767, 0x872aef49, 0xe7414aa0, 0x0a4f04c2, + 0xb8cdcefc, 0x135a5f34, 0x344760ed, 0xd00f9340, + 0x9391d9e8, 0xba782b9a, 0x25d42530, 0xb4fe6539, + 0xd56c9c5c, 0x1b9e0128, 0x859ee1cd, 0x2954ba9f, + 0xe9944e22, 0xf448886a, 0x9c9c247b, 0xacdc40d4, + 0xfbfaa144, 0xff767be9, 0x73c08f78, 0xd16028ef, + 0xb5a17a43, 0xba4d7dc1, 0x397b4bb8, 0xd850f99c, + 0xb6fc563b, 0xfff2b4fd, 0x35486c91, 0xfef035e0, + 0x442ff5a1, 0x2b9e4f04, 0xd1d0639a, 0xddb80a4c, + 0x6a5c5470, 0x95185df1, 0x0d65f9d2, 0x78b11287, + 0xe07972f3, 0xc91e30a6, 0x0fee2147, 0xbff4f124, + 0x0943f488, 0xd46c2de6, 0xbc7d58b7, 0x489ce432, + 0xc73d23f7, 0x55666fd5, 0xd4314902, 0xf7cab902, + 0x46f67f53, 0xcd8dd99f, 0xa709ba57, 0x329c8202, + 0x7ee68771, 0xd953252c, 0x5edbfd6f, 0xe71a39bd, + 0xe79d3164, 0x89e9731c, 0xa7a06b56, 0x6b910e4b, + 0xda2f029a, 0x1a203b71, 0xd79aac7a, 0xc2e368ca, + 0x15fc9285, 0x9c8019ae, 0xc13e0e09, 0x4da2e4b4, diff --git a/src/soc/intel/broadwell/microcode/microcode-MC0306D4_00000018.h b/src/soc/intel/broadwell/microcode/microcode-MC0306D4_00000018.h new file mode 100644 index 0000000000..97500c0f1c --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode-MC0306D4_00000018.h @@ -0,0 +1,896 @@ + 0x00000001, 0x00000018, 0x12052014, 0x000306d4, + 0xc839f43b, 0x00000001, 0x000000c0, 0x000037d0, + 0x00003800, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000a1, 0x00020001, 0x00000018, + 0x00000000, 0x00000de1, 0x20141205, 0x00000de1, + 0x00000001, 0x000306d4, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x662aa2db, 0x9bd70abe, 0x2e996509, 0x2f1084ad, + 0x39092abf, 0xe28807cb, 0x6f1e0bea, 0x3f586e35, + 0xe1d4113f, 0xc3085503, 0x1367060c, 0x9bf7efea, + 0x2b756eb6, 0x2ee07b69, 0x7cfd1dc4, 0x9811c8b2, + 0x86cf4036, 0x20534caf, 0x37046580, 0x432b4e6c, + 0x6a3a2e54, 0x88a74dfc, 0x81a503f6, 0x67736b51, + 0xbc2b11b7, 0xbcf3adc9, 0x96c8eefe, 0x688bcc49, + 0x16c4f996, 0xe0175cd2, 0x454d7a58, 0xa67afd13, + 0x098d9e42, 0xf86d2ec2, 0x738a67a6, 0x26c4ad17, + 0x08666776, 0x050d971d, 0x68998a7c, 0x21ac9cf9, + 0x29e27b61, 0xd61cfd7d, 0x3500ff83, 0xd4123687, + 0x27b72496, 0xe9b867f6, 0x62920d71, 0xe159dd34, + 0x3991c6ba, 0x367a5719, 0x7af5e9df, 0x5cb9fd11, + 0xf5988469, 0x4153f210, 0x24b194a9, 0x8c563988, + 0xac5bfd38, 0xd271e693, 0x16e9b292, 0x0c6583d0, + 0xd2501a4f, 0x9896af00, 0x6665aa9f, 0x0f3a8de9, + 0xc8f0db5f, 0x60b7a546, 0xe3a52963, 0x0ea3eb39, + 0x0d8c08ab, 0x2f5faa26, 0x1d3cbd56, 0xa8596256, + 0x00000011, 0x2c3ce270, 0x66847d1b, 0xd784f7a2, + 0xe53cb6ce, 0x4b238890, 0x32d4b123, 0xefa8ee84, + 0xe988189d, 0x17822bfb, 0x69aca74f, 0xa629c507, + 0xd194068b, 0x002837ba, 0x25ada84d, 0xb9e2fd3c, + 0x834655a7, 0xe20ff78d, 0xb8f5b793, 0x46e89a45, + 0x3b173716, 0x393fcab8, 0xd3fb9d6a, 0x04e126e2, + 0xb294d1b9, 0x764ed602, 0x660231dd, 0x2a8989cc, + 0xbeaa8a44, 0x5c40294c, 0x33280b4c, 0xad39580f, + 0x3f4f207a, 0x2e296b4a, 0x82afd132, 0xa1e9b695, + 0xf1fb5f49, 0xb6ebeef7, 0x67b71aac, 0x4c27f843, + 0xadab79c5, 0xaaa6a1d4, 0x250eb151, 0x30f50f48, + 0xb038ec49, 0xc6f447a6, 0x865abc65, 0x4e893197, + 0x5888be29, 0x881dce1f, 0x011a90cb, 0x06d224a9, + 0xd4d539b5, 0x33ca7475, 0x2dc151fa, 0xb4f68ce9, + 0x5313600a, 0xb049dbec, 0xad905847, 0xb5d05bd7, + 0x68e94d54, 0x1c24075c, 0x8a66ca35, 0x85fa5082, + 0x375ba9e5, 0x85c6717c, 0x8883a382, 0x16fdfca7, + 0x4acb597a, 0x5524f20d, 0x2c859907, 0x13681548, + 0x9a6dd3ba, 0xaf6df31f, 0x2ffad1dc, 0xbde00f33, + 0xb0918a12, 0x39802645, 0xf26d4804, 0x8907f576, + 0xf988a124, 0x34338e24, 0x528dad8e, 0x15c80958, + 0x5a4a710e, 0xe9895fd7, 0x34abb8f8, 0x17f5d8c4, + 0x93837696, 0x9195ab85, 0x7ce159d4, 0xcff5cdd9, + 0x2948ab18, 0x982bd3ff, 0x0453663e, 0xd335b119, + 0xa983ab50, 0xf474d3f2, 0xbeace8f6, 0x78443d00, + 0xd5161e92, 0xe0a47ac8, 0x9390b0a9, 0xf1fcdf55, + 0x0ebfcf07, 0xf22ac8b3, 0x16b7a70f, 0x4beac3ab, + 0xfab5d679, 0xa1b26a02, 0x59193107, 0x59ffcfd7, + 0x871c067f, 0x254507ca, 0x1500eebc, 0xe18752e2, + 0xc151f2a1, 0x42c34277, 0x62d9232f, 0x9ae97918, + 0x2a87c016, 0x4b14608c, 0x0cad1735, 0xbec026a5, + 0x3ae6e427, 0x0c2d6688, 0x289bf8a1, 0xb170feaa, + 0x363b4e7e, 0x40938152, 0x3c51073e, 0x19e6acb6, + 0xf62cd42f, 0x826cea38, 0x66edfe03, 0x233dce1c, + 0xdbd0fd9c, 0x2b7c65c6, 0xd6db8eb5, 0x07c7ffd7, + 0x834f5a60, 0x32c04949, 0xd6725577, 0x723da5ad, + 0x5caefe12, 0x352ea044, 0x739a5570, 0x91ff4528, + 0x5d07384b, 0x3a4ca7bd, 0x6506ec31, 0x52bb45c1, + 0xd07423dc, 0x9c4fd4db, 0x725abf3c, 0xbbcb0ff6, + 0xa98434a2, 0x5b7901f7, 0x69a3408a, 0x466dc30e, + 0x8a7c26c0, 0xc0501939, 0x137aaac3, 0xe0ddfcef, + 0x38df1389, 0xa5939a35, 0x8409f770, 0x8a068ccf, + 0xacf2da8e, 0x2ae63831, 0xa1e2b7e6, 0x906ad62e, + 0x530d6ad1, 0x61739194, 0xed3fd893, 0xfe7937fa, + 0x93d23b5e, 0x3e6f3c68, 0x1c7a91f7, 0xc78450c4, + 0x9c93d980, 0xd3efac37, 0xc7ac6668, 0x462a7219, + 0x0be8b59e, 0x07a24bea, 0xb8fce9b8, 0x0fdc9998, + 0x21235f1b, 0x7b952674, 0xdf7b8173, 0x62002cb4, + 0xdcc82387, 0x4e8651bc, 0x1c1f0de2, 0x16485adf, + 0x01147737, 0x0789fb5d, 0xcd960299, 0x0bc10d96, + 0x16ddc9c3, 0xbd0cd119, 0x580d7de5, 0xdc362ed8, + 0x72535ef0, 0x8ca11477, 0x0cdeb3b3, 0x9381dd74, + 0xda540b26, 0xd0fb1d3e, 0xc55fdfce, 0xe6c780e1, + 0x39ef5a76, 0xd186686d, 0x24d98330, 0xd3c08798, + 0x34bf296b, 0x57439225, 0x9e27f067, 0xd1ba7292, + 0x303dea9e, 0xfd6ba631, 0xa841c147, 0xe73fc348, + 0x5d5cafe1, 0x3fa6793d, 0x916a92ee, 0x903acdcb, + 0x5e59ae3f, 0xd3ff905b, 0x947812c9, 0x5260180f, + 0xedf1ccd4, 0x6ea69428, 0x7fb0dbc5, 0x6c71828a, + 0xe7d97aa5, 0x632f205d, 0x2761d362, 0x62e9ac24, + 0x0f36400a, 0x41a27157, 0xc157080c, 0xd3f1b63f, + 0x2f47aec3, 0x72d64571, 0x2b8ded48, 0x341342f8, + 0x807a1c56, 0xfc1f0545, 0x86428f14, 0x8cfbaa3d, + 0xf3e9d3d1, 0x884dda5f, 0x58be2047, 0x8fd6ac28, + 0x1590b8e2, 0xbb1af27c, 0x550477a5, 0x210bcd88, + 0x5c01611f, 0x6737c985, 0x337eb8ba, 0x6a012431, + 0xe2c63732, 0xe7f1a3d0, 0x794708a8, 0x8a1ccd20, + 0x23b6374b, 0x54ed5873, 0xd9c6ea5a, 0xc8122b75, + 0xf7bba1ae, 0x4eb5f01a, 0xe7ebd25d, 0x7ce44acb, + 0xe6b06fda, 0x179b05e3, 0xb22439d0, 0xd9924d44, + 0xf005d779, 0x995313ff, 0xee223524, 0xd4df738f, + 0xfb49a1ac, 0x528a9581, 0x817bbdfe, 0xef68d7e3, + 0xb4bfe753, 0x139a57a4, 0xe440e377, 0x9e5a1830, + 0xd718aa0d, 0xe98fc60b, 0x271f1695, 0xe43e9cce, + 0x54571691, 0xa4f7891a, 0x468b05c4, 0xd6fbd11c, + 0x7a1f2525, 0xfd78e5f9, 0xc7221376, 0x7f72349c, + 0x89e24ce6, 0xf54895a1, 0x4fb67ba4, 0xd1fcab71, + 0x93e81596, 0x150f1d18, 0x34029fb0, 0x081ff064, + 0x88b28d74, 0xc03351e2, 0x95f5655a, 0xf0c6369f, + 0xd9119ab1, 0x48ddcec9, 0xbb6ed62a, 0x8da8e465, + 0xc599732c, 0x8743e8c4, 0xd65c0979, 0x0cb7fd52, + 0x72e21adc, 0x54e71cb4, 0x1e6af413, 0xaeceb23f, + 0x1390ea5a, 0xb8f60183, 0x651a1341, 0xecc7f2f7, + 0x62287cfa, 0xe8246d3e, 0xd3e75275, 0xa2d84777, + 0x68b794ff, 0x881264b8, 0xd56126c4, 0xedef447f, + 0x459e5c57, 0xb7759ecd, 0x44bb0210, 0xe91eff97, + 0x38507f2e, 0x0b8e2b19, 0x0c61870e, 0xb8441fb1, + 0xf08e130a, 0xae56095a, 0xa23e0162, 0x1a8b4a83, + 0x3b48a861, 0x902e3fc3, 0x9bcc5c7c, 0x00fee59a, + 0x3ba13deb, 0x902f3c3f, 0xff113ae1, 0xf4268ec3, + 0xc9086f84, 0x958ce3e0, 0x5c2f3aa1, 0x471658a3, + 0xc06835c9, 0xc62957f8, 0x02229585, 0x0faa7f72, + 0xc6b45dcd, 0xd79e1acb, 0x4fe4d4f2, 0x5852ff40, + 0xf646da4c, 0x67f84997, 0x38a7f24c, 0xe02a7924, + 0x213d3c26, 0xf990e630, 0x8463e29c, 0xcfaf0c9a, + 0x6c5e64e2, 0x9e30acea, 0x18a2c084, 0xc0e2dc2c, + 0x12c085b7, 0x5c133410, 0xe3654aa6, 0x10ad333c, + 0x4fb85eae, 0xef4355fd, 0xfee1a612, 0x9022ffff, + 0xc407fd45, 0x1064ca70, 0x7c46f117, 0x8fa358a2, + 0xb15ae862, 0x1a44bdba, 0x3b8daff8, 0x2b85f0ab, + 0xa660ad11, 0xa2d61460, 0xdb66bfc8, 0xe44cec45, + 0xaf876098, 0x7f4e9782, 0x512d56ab, 0x028cf772, + 0x57382a12, 0x692dfc51, 0x190e77c2, 0x93771f8e, + 0xa29048d5, 0xcc782f54, 0xc276042c, 0xca8d08c6, + 0xfe467546, 0x8a79ab7b, 0xc00d62f6, 0x415bae42, + 0x962751d3, 0x5835e29c, 0x0dafec02, 0xddf3f49c, + 0x81f63105, 0x7e676e3b, 0xbae6dceb, 0xa74b614f, + 0xf4a32d45, 0xf82d6d8a, 0x9ca70345, 0x59b4feb3, + 0xadf456e6, 0xdfa810da, 0x09c8845b, 0x61c36b62, + 0x502bbeaa, 0xfe7ea1b5, 0x55c77255, 0xe036688e, + 0xc8737c36, 0x2f06e05b, 0xc3a9b2e2, 0x4bbf8462, + 0xc1158659, 0x10a6ba71, 0x1c2be381, 0x94cf2e08, + 0x745854b3, 0x4a032cc2, 0x7c2e70da, 0x0d2b0ab8, + 0x02a05795, 0xe0aab76c, 0xba425051, 0xc3082702, + 0x3b20d4b2, 0x33bd5ab4, 0x11b93134, 0x606b15e6, + 0x506cb749, 0x6cecb681, 0x0b0cdd71, 0xb9a77573, + 0x6b90810a, 0x3e79e37a, 0x29121c8e, 0x9b4b65f8, + 0x61185bab, 0xe49f55bd, 0xe711d009, 0xa57f65a6, + 0xe083daaf, 0xe5a1c36a, 0xe73dfaed, 0x9c14ccb5, + 0x610e1684, 0x4603a14d, 0x8b9a903d, 0xaa2138aa, + 0xb5b0427d, 0xbf9f42e6, 0xd79181ef, 0x7cca195f, + 0x81dc00f0, 0x2e04b6e1, 0x22dd5e69, 0xaf9f6ff6, + 0x145ff194, 0xcadb3766, 0x38d36d3f, 0x51dc71c1, + 0x498ae41d, 0x2e4b1906, 0x5eab2f01, 0x6a219097, + 0x3ac71473, 0x7786d624, 0x640cc22b, 0x9a54b460, + 0x44786abb, 0x4efe3346, 0x2da05ec2, 0x1d632d71, + 0x37ff8c65, 0x453a2e38, 0x41fc0bbc, 0x2e5d6269, + 0x652d9b77, 0xe9cd509e, 0x0c2c0b68, 0x7ced216f, + 0xde7d1b2c, 0x2b51d5ed, 0xe450b2f4, 0xe79b7003, + 0x9e1b5c24, 0x722dc8ed, 0x817bf45e, 0xde875547, + 0xc2d25b54, 0xd3949c6c, 0xf1f4f6d5, 0x5865f07f, + 0x152ea62d, 0xb820dba9, 0x4b240b17, 0x097f05f7, + 0xd5ee7575, 0xbe33e0af, 0x94af257b, 0xfd6421c4, + 0xc549bc5e, 0x1420235d, 0xec12a237, 0xdc7a880d, + 0x28770263, 0x9726be49, 0x08bc7342, 0x6e46e2be, + 0xedab20c1, 0x44abfb82, 0x9b14903f, 0xb4e07677, + 0x7f1de461, 0x2f4ab286, 0x1fb2a1a8, 0x041fef3d, + 0xc1d30754, 0xddb0e502, 0xa195e292, 0x8aece460, + 0x4ac40380, 0x421d0598, 0x9e9a00ac, 0xb3d13c4f, + 0x7f8b2161, 0xb136bbfd, 0x25bd6556, 0xa8d5ed4a, + 0xa6fb394d, 0x31f68cb6, 0x08e0ab6b, 0x86e33ccd, + 0x6d05a56a, 0x7db28cff, 0xd79b0e8f, 0xc3175ce4, + 0xd98aa5d0, 0xdcd55c86, 0x3cb0f0f2, 0x2161d4f4, + 0xf1f7f3fe, 0xe06c57fb, 0x098397c7, 0xa3a47889, + 0xc5c053c7, 0x9bc617cf, 0xc1806b75, 0xdeaad3b4, + 0xa1ec6f43, 0x17f605d0, 0x0fb08e0f, 0x3d4fb550, + 0x5094d440, 0xaa5bf94d, 0x525ce05a, 0x79a52524, + 0x24d1ad31, 0x366aac08, 0x60355031, 0x639f2476, + 0xda69bfaa, 0x6b65da4c, 0x0f5556b2, 0xe9c9130e, + 0x1eb43a82, 0x01114736, 0x655bb179, 0xd6e623fc, + 0x54290648, 0x676e76ba, 0x040698eb, 0xe1b4863b, + 0x12cbe132, 0x8a88fa49, 0x86102b27, 0x28a0c924, + 0x746ee475, 0xd7f413ee, 0xe38a7bd3, 0x2f15c841, + 0xbc0591f6, 0x10dc7059, 0xf457afa8, 0x1f530fc5, + 0x314bb94f, 0x4e15185b, 0x4ffc6b3c, 0x0b6cf4fd, + 0x536112dc, 0x88074ee8, 0xb6de758b, 0x31567f6a, + 0xeedcd975, 0x28f20c30, 0x0feb1a17, 0x9b3aa1e3, + 0x25341a16, 0x1a3a98fa, 0xed7b6ea6, 0x9d5d10b2, + 0x11e7e8ec, 0x215cae03, 0x45852467, 0x76a0cd07, + 0xa9fcf98c, 0x35dfbee8, 0xe7350554, 0xc12d24f6, + 0x83c60d6a, 0x017cf4d3, 0xeed39975, 0x4e925199, + 0x50834a0c, 0xc123cdd0, 0x48e906e0, 0xa66f76cc, + 0x018ce145, 0xb7572de2, 0xfe51617a, 0x1d14913b, + 0x07c75a4d, 0xccdccd8d, 0x5d0e511e, 0xc2d9e9f6, + 0xac6d6691, 0xb4d1a2d0, 0x6caca3ea, 0x160ee0a2, + 0xf04632a6, 0xfa132f26, 0xf82378a5, 0x2fde955c, + 0x3946ee65, 0x295005b4, 0x8f65de31, 0x3975d15c, + 0x3e447e7e, 0x44b731b1, 0x164762cb, 0x83f42cba, + 0xdfb20d05, 0xbd0060f6, 0x268ff84a, 0x91588079, + 0x9d920ed6, 0x0a5ae2f4, 0x14bcbfb3, 0x92398e16, + 0xd380cb23, 0x31992167, 0xff6ce104, 0xad3c504a, + 0x1d6c99dd, 0x3feca130, 0x97562368, 0x6dc93713, + 0x6a9d0e6f, 0xb4027d2a, 0x20cd2ca4, 0xf2c74429, + 0xdddad84b, 0x1ed3fe5b, 0xf4f64c36, 0xb093af95, + 0x52e1d7a0, 0x9d3647b3, 0x6baba121, 0xaa09671f, + 0xe4f61d07, 0x1e007714, 0xfcc0b3c4, 0xc7f2740e, + 0x98013759, 0xd0d69485, 0x27b7fb2b, 0x894c71f2, + 0xf1ef1206, 0x08f0582e, 0x534e0362, 0x764f86ac, + 0x8f582aa8, 0xcb35d2c0, 0x8f99817f, 0x38877fda, + 0xe7437014, 0xb495ab1f, 0x52919b5a, 0x34ff0d2a, + 0x95f302ad, 0xc6afea2a, 0xe280b935, 0xb347c6e3, + 0x954761a6, 0x1dec2d03, 0xf581365d, 0xaf461b33, + 0xd7391d07, 0x00254baa, 0xf9a3ac1a, 0x0447e2a6, + 0xf8e54089, 0xa9050fe5, 0x5b3651a9, 0x38ac2ab4, + 0x23281664, 0xb36d62a1, 0xe17990f4, 0xb6bce6b9, + 0x935be280, 0x5301be02, 0xc0bae1f5, 0xe9f75bf9, + 0x3f8546a9, 0x96d7f9c4, 0xf51b7bf0, 0x8d0e9929, + 0x1d2d35d2, 0x2ed9b905, 0x8a14e8c5, 0xd57c8d56, + 0x3111b05a, 0xcacd5550, 0xdd8c309f, 0xa589c057, + 0xc025de04, 0x1ad6fc0c, 0x59c92933, 0x2fa82ee2, + 0x8d00b4d8, 0x9ca5c4c5, 0x0ac7a279, 0x06e98962, + 0x71ede488, 0x5fd3fc35, 0xa308cd3c, 0x798a20c8, + 0xe386dfbd, 0x179c5c7f, 0x7de366cd, 0x3471e0f9, + 0xdfe551c5, 0x1a9942fa, 0x3c8071da, 0x09beac8e, + 0x260d3455, 0xb4ccf8fb, 0xc5455499, 0x7d05f0d8, + 0xb778cfaa, 0x3454edc2, 0x8e8c9c41, 0x7cdc0d19, + 0x19b0a6b0, 0x816402e5, 0xb803e136, 0x12be7611, + 0x2edd7dcd, 0x652d4bf7, 0xf24ec38a, 0xda210607, + 0xdd5ff486, 0xcd9192a8, 0x40931fee, 0xd5ff78eb, + 0x76921b79, 0x238a0826, 0x0ffdaf75, 0x54a44747, + 0x7fc96ed0, 0xf28323e0, 0x27f8c2ce, 0x3fde0615, + 0x9d2ba10a, 0x7cb2b9f6, 0x54a25fb2, 0x4bff6f36, + 0xa3988812, 0x231fc35a, 0xfed93210, 0x2753bb21, + 0x0ee467f2, 0x6bf8e50f, 0x5d64c3a1, 0x183736b5, + 0x8f5b1127, 0xb2c7782f, 0x295bacbf, 0x60ee59bc, + 0x41c7e02a, 0x355236eb, 0x2db83919, 0x5127dc6f, + 0x4c21a635, 0x5171c116, 0xc475d0e0, 0xbeb0263e, + 0xa91abab2, 0xabbe478c, 0xa9b010fc, 0x422e0c84, + 0x7ac80407, 0xdfac01c2, 0x4a1cd024, 0xfa8ea1f1, + 0xf541cbe7, 0x40447697, 0x1c4ad84c, 0x64676b50, + 0x2b33012a, 0x5042d373, 0x2a015a0c, 0x5c5235da, + 0x1073511e, 0xdc23d33c, 0x79dbc3ee, 0xc3f9f0aa, + 0x8b998183, 0x5e371818, 0xf7cd900c, 0x93e11f54, + 0xffba1a7e, 0x3b02ca93, 0x581c611c, 0x920cca85, + 0x620d9f6e, 0x346f8c67, 0xaf7223cf, 0xcfeb0240, + 0xbf7d0f4c, 0x54e56916, 0xd3107792, 0x50b3cc5d, + 0x0e898955, 0xe3c24551, 0xff0fef85, 0xaa47ce41, + 0x29633015, 0xa894f6d6, 0xbd2bee74, 0xcc0e131b, + 0xbd4d2f1f, 0x3d86f2ad, 0x2b663847, 0x5da35d6e, + 0xfdea5619, 0xe2911506, 0xe8854164, 0x62044dd3, + 0xb1a05f77, 0xf4b4717d, 0xce75ea85, 0x641e7d50, + 0x19641a41, 0x39b6f487, 0x75d75d18, 0x71437766, + 0x2370f881, 0xc461ad76, 0x67674261, 0xedfe4288, + 0x86d48d5a, 0x328b6281, 0xa75405cf, 0xa6b235ec, + 0x1b21f1a6, 0xaa0f533a, 0x5ab9f2b8, 0xae5f1646, + 0x5ad8b684, 0x4a6a1234, 0x49691db7, 0xf73c30d5, + 0x4a931bc8, 0xaddaab23, 0x65de384e, 0xb540bce4, + 0x30edfdf9, 0x0f220c60, 0x88a954e4, 0x4d88bf44, + 0xbf7abe8e, 0x3c32e749, 0xf4f037c3, 0xb4a615c9, + 0x6f0f84ad, 0x9ce30429, 0x5c80136e, 0x99ab0514, + 0xf8d0b365, 0x7e4efa46, 0x7df70146, 0xa767aa83, + 0xf77bc3d5, 0xe77aa259, 0x7544a644, 0xf2b6ac08, + 0x1c238505, 0x62e3b7ba, 0x67d0061c, 0xebbb0851, + 0x21108ea3, 0xc17d7387, 0x5d748587, 0x1a7d46f4, + 0x7e1f55bc, 0xdc6aee79, 0x700cb3c2, 0x3ed77ac8, + 0xbfb0d6bc, 0x5267a833, 0x66416352, 0x0ef1d589, + 0x34d1e291, 0x4d37f757, 0x3ba4c7e1, 0x6c690729, + 0xcb55d200, 0xa19e26b0, 0xc6aa61b8, 0x362a07f7, + 0x4ec6906d, 0x458eca1b, 0x534268d1, 0x877308fc, + 0x694efa7d, 0x43dcdfbd, 0x2bec9f0d, 0x82bc731e, + 0x9da19651, 0xa6c0088f, 0x1ccfe9cc, 0x37f30b3f, + 0x384c7a33, 0x169b8e12, 0xbe9961d5, 0x5a3b205a, + 0xcdebb00f, 0xd74e90eb, 0xfb1b4060, 0x013d6be8, + 0xd95548c4, 0xf3d2823c, 0x3eb85474, 0x19e2a7cd, + 0xf8401946, 0xbbb05fab, 0x36eca41f, 0xab27b89e, + 0x877abca2, 0x14104c8b, 0xc215cfd5, 0x32fba199, + 0xe5f0ea8e, 0x9a9e59f8, 0x338dc0cb, 0x2e628b16, + 0x5ef0abda, 0x00435dc8, 0x5f67e362, 0x27db6d61, + 0xb727ffe6, 0xd8f2fcb1, 0x53504529, 0xae48a0c2, + 0x990e154a, 0xf7b062e7, 0x13577ea0, 0x7892b4f4, + 0x6563d550, 0xe0e75fc0, 0xd0c85fe2, 0x7acc8c66, + 0xc064c7db, 0x9a7015a1, 0x67ef15d1, 0x425c17fb, + 0x10dfe28b, 0x42aa5702, 0x62edddea, 0x65c8a37f, + 0x042976a8, 0x0de73e0d, 0xc67cd300, 0x878a628f, + 0xd342fab1, 0x25b293f9, 0x8946bdf6, 0x06422810, + 0xa4caf0ce, 0x997870a7, 0x1e598931, 0x53330d3a, + 0xe702054c, 0x5ec46e5a, 0x3261c160, 0x3b787a61, + 0xd607578b, 0xee2582eb, 0x35d4c00e, 0xeb9a3ba0, + 0x2a499eb4, 0x21ed62da, 0xf92209c8, 0xfe0fe262, + 0x6b25ba94, 0xada7c0cd, 0xdf9490ed, 0x962416f1, + 0x41845cbe, 0xa7d25610, 0xf1bdcea5, 0x80fe102a, + 0x68601e3e, 0xdf9fdc79, 0xc866195c, 0xba460ff4, + 0x2338a601, 0xbe911737, 0x0fb6e41e, 0x7a88341e, + 0x946454b2, 0x7e8e4d93, 0x7560cecc, 0x55916343, + 0xc067415b, 0x9803982e, 0x620e24d9, 0xc15d85d3, + 0x5bc65264, 0xd1e0c117, 0xe970058f, 0x247ca672, + 0xf7e49693, 0x3b0dcaaa, 0x68d17470, 0xcca0bc93, + 0x19984d15, 0x968a2e86, 0x89085b26, 0x96816448, + 0x9a7c7558, 0xde34446c, 0x92c0949a, 0x2007b32b, + 0x9e28f27b, 0x8fe0f3cb, 0xc5f48f19, 0xe1635ab8, + 0xfd32854f, 0x14f5049a, 0xbbe9015d, 0x69da2822, + 0x1994836a, 0xa4540864, 0x3cc5391e, 0x7f44a321, + 0x7c4b6ac0, 0x83976317, 0xd27fbb0e, 0x0c130890, + 0x32afa351, 0xb5fbe87b, 0xe474d792, 0x73f28c81, + 0xba9d1814, 0x1f9164e4, 0x563279df, 0x40af307b, + 0x76d9f7cd, 0xab3518fb, 0x6674af9b, 0xf0f81d35, + 0xb36619b2, 0x778a5d09, 0x9cf12b41, 0x1316446a, + 0x9b95effb, 0x260c5d83, 0xcd34f010, 0xcf1ba879, + 0xeca8942d, 0x288b951d, 0xb29da723, 0xbe251390, + 0x0d8539d5, 0x7e0b6542, 0xcf0a8904, 0xb1adab98, + 0x2d714e18, 0x729a3efa, 0xe04f891f, 0x24ed7c07, + 0x9a9a5a69, 0xfe0f5063, 0x600a987a, 0xc6b5e041, + 0xf156252d, 0xb9a52ee8, 0x41fb70c9, 0x9a0b2454, + 0xb28442cb, 0x979a8653, 0x78f8223c, 0x400bf5bd, + 0xbc963a4a, 0xbbdbb155, 0xc31de841, 0xcfdc5f01, + 0x10cf52da, 0x67bcbdc4, 0x71cb2921, 0x5a0d2a09, + 0xd0c42797, 0x6a361f61, 0xe51bb269, 0x645eb280, + 0x7826b211, 0xc292d2a2, 0xa893f586, 0x17722f24, + 0xb4b6118c, 0x8d4a4f77, 0x6b584a33, 0x7d19ee39, + 0x7123a113, 0x1a825d9f, 0x790c8b53, 0xe169b461, + 0xc7219c70, 0x6579c3bb, 0xc483d926, 0x2585713d, + 0x5396e753, 0x2a5f736b, 0xd862fd92, 0xcd8cd5e0, + 0xf156501f, 0x8bfdd588, 0x738548fe, 0x1c2e1905, + 0x3738d588, 0x6323c4e4, 0x52743965, 0xab30e986, + 0xf60403fc, 0x139130ba, 0xf493fb97, 0x2e947de0, + 0x82b04f24, 0x09ea5c60, 0x4bfc0766, 0x5c0c9e55, + 0x9b186fb4, 0xd98e976e, 0x84cae75c, 0xa46ed348, + 0xd312a4d8, 0x5b635794, 0xc6fb6dc4, 0x30003268, + 0x6fca7b3d, 0x2e1a0fbb, 0xc5a4d826, 0x2ab1e2fa, + 0xe600b64c, 0x9c987d71, 0xe2b4e451, 0x7088b4a6, + 0xedfb4024, 0x33cfd12c, 0x1c6139c2, 0x2f001e3a, + 0xdc156c47, 0x07b37cee, 0x42e9ec98, 0x1e4acbcf, + 0x46f7ea02, 0x34f6bd8c, 0x945bce03, 0x9f25787f, + 0x7af13a61, 0x6966cc7b, 0x00cbc0d3, 0x176e5558, + 0x2cf5a7ab, 0x0ccfcb9c, 0xdd27563d, 0x6e6b744b, + 0xbeb09adb, 0x3ef35c88, 0x8ed49bb9, 0x7797b3ad, + 0x6221323c, 0xefaf2021, 0x980152ec, 0x632efb5c, + 0x5dd188be, 0x8e5c109a, 0x630ed398, 0x1011d974, + 0x7c5e9d1d, 0x289a7102, 0x4ed89099, 0x446d8bc2, + 0x169a16be, 0x89bec003, 0xc087ebe4, 0x170edb46, + 0xdeda0895, 0xa3099667, 0x9cd00e87, 0x468de89a, + 0x86703cca, 0x164c25d7, 0x98affbf2, 0x57355e6c, + 0x6ecb4626, 0x0ac8508f, 0x00cf927c, 0x1a279fb1, + 0x2160c9b6, 0xd47422c3, 0xa9ea06ec, 0x8e7737d5, + 0x192f8e4c, 0xf7d0d367, 0x002c77fe, 0xdb526e26, + 0x51c35520, 0x3f09863f, 0xb5b98f4c, 0x145f4f07, + 0xc284559b, 0x94b92608, 0xf176d8f7, 0xceb3fd9f, + 0x1c16f416, 0x98fe09aa, 0xa1014a36, 0x114403a9, + 0xffccf91c, 0x56bcbdf8, 0xd4343216, 0xccdf72d4, + 0x054f98c5, 0x9afb8a09, 0xd8ef3bd8, 0x0207aeee, + 0xa70ae6a3, 0x0dd59e8d, 0xab20f208, 0xddcab016, + 0xdd3dc3ba, 0xac60063c, 0x2447fc4f, 0x70351659, + 0x2106e121, 0xb88d71da, 0xa828c62a, 0xe1c965e2, + 0xd4e57980, 0x49f63107, 0x55a330e2, 0xd2833753, + 0xce582646, 0x699a6c07, 0x90314ebe, 0xf14b7d2a, + 0xdf5b26d6, 0xb32c6c1c, 0xff04d44d, 0x7caa37d6, + 0x6960295d, 0xdacb71c4, 0x2b15d12d, 0xad5a2faa, + 0xb09a56d5, 0x1f05911b, 0x28e5d51b, 0x005ea42c, + 0x7c2a36f4, 0x1c8507b0, 0x8c37ef53, 0xa76de3ff, + 0xa5dd3649, 0x4c717c28, 0x9cd5ba0e, 0x69a01bd1, + 0x0e3913ab, 0x7184213b, 0x1e50602b, 0x5b5cec02, + 0xdd1011ca, 0xe1fdbc31, 0x1b8d6f47, 0x5d81292f, + 0xdb85b09c, 0x51e638eb, 0xb8920a06, 0x4d9ff4a4, + 0x50cac0c7, 0x97f0d32c, 0x267fc1e3, 0x41998227, + 0xaae726a9, 0xe305fb5c, 0xa58aa3dd, 0xd5a6fb12, + 0x0680d3f5, 0x02c6dca4, 0xcd19fa90, 0x21a00852, + 0x950b6e4e, 0x5668694c, 0xe8224179, 0x43778b65, + 0xad00b72a, 0x2be02c7f, 0x2996259e, 0x088783ee, + 0xf84509bf, 0xd8f05b52, 0xf6cce63c, 0xc02cd267, + 0x7420a324, 0x28cfab54, 0x9d8ccbab, 0x6adfb330, + 0x9f951825, 0xe71bf2a5, 0xbe9af05a, 0x9067bb91, + 0x0ee474b4, 0xe6a17fb6, 0xbeff8937, 0x4b8a804f, + 0xb0fa702d, 0x74b05854, 0x85df3f3e, 0x70e01e09, + 0xe288d0e5, 0x216d6a50, 0x1a0928a3, 0x7037a4be, + 0x2855a09c, 0xa9340265, 0x1bc93259, 0x8b1cb57a, + 0x138166d4, 0xc3e8a649, 0x1376803a, 0x042eb6d4, + 0xb98b0bab, 0xe34b3ca2, 0x46f1bca7, 0x7742a36e, + 0x4bd1c963, 0x264e6eae, 0x04e36a4a, 0x3bd83e19, + 0xe3509520, 0xbbd00ec7, 0x61a3ea3a, 0x88a10756, + 0x63239aed, 0xf4c11cdd, 0xec9809d6, 0xd0e19f45, + 0x8ad5b616, 0x75339b7f, 0x8ac94df7, 0x401fe357, + 0x3400d2ef, 0xb4768d60, 0xd4068c33, 0x57557105, + 0x9c41683d, 0xc23b02ec, 0x9c8015fa, 0x65070e6f, + 0x94c57188, 0x63a67e44, 0x2c748ac0, 0x6e27e94d, + 0xd6209376, 0x8f6e1f6a, 0x78b4d3e9, 0x1b1dd9c1, + 0x37a5f312, 0x91b105a3, 0x5476043d, 0xa06162de, + 0xbb846cda, 0xe762bb73, 0xf4e67524, 0xb1bcec16, + 0x500b5210, 0x42f8a7c6, 0x7db27d8d, 0x52a9b378, + 0x9f26c02c, 0x66ef794f, 0xc2ca0495, 0xeceaaf60, + 0xad43492d, 0x0f168211, 0xb3b21054, 0x0f7c3274, + 0x8add7f47, 0xb4626746, 0x44b8e4f8, 0xd6936b92, + 0x623e6dbc, 0xee75c333, 0xe0f9120e, 0x8d1aca3a, + 0x75e10bf5, 0xc9b8e2d6, 0x92b99647, 0x0472e5af, + 0xfbb7df0f, 0x925e017e, 0x5599979d, 0xc3a9034b, + 0x0fb91e92, 0x7de1f5ef, 0x4b054778, 0xa564ecc0, + 0x8f00e163, 0xf0c4caac, 0x78b05487, 0x2725f57f, + 0xb6cc0235, 0x9a99f964, 0x9eff7bad, 0xbe1240d8, + 0xb62d53a4, 0xa3e687db, 0x16e70773, 0xe78c596d, + 0xa90572a8, 0xa9d9476d, 0x74ab56d7, 0x9cc001f7, + 0x583681c0, 0x32c70ad8, 0xbecf6a5c, 0x2374c382, + 0x966bafbd, 0x70537c86, 0xe5c99a40, 0x11d04c54, + 0x1b479a47, 0xe271b9b2, 0xf95a1244, 0x919dd654, + 0x155b2617, 0xc2ba4bd4, 0xf4659f10, 0xf250904a, + 0x9d8c21da, 0x185d278f, 0xcb7cffea, 0x5be759d4, + 0x6a91d94b, 0xc9d9e428, 0x18d45435, 0xb1e80cd6, + 0x74b77aef, 0x0d632cb0, 0x94cb28e7, 0xd7bdff56, + 0x4f601195, 0x5dd1007e, 0x7ea4f89f, 0xa44eb77f, + 0x4f02e6e3, 0x6ff3ff5c, 0x4405397c, 0x4d39cc85, + 0x2677cd52, 0x0257f4fb, 0x77460d51, 0x1167c4e8, + 0xbba1e679, 0xd7ec61b4, 0xe6fa6fe1, 0xd172b1f1, + 0xbaa4b1b3, 0x0fb0bf2e, 0xaceca579, 0x345d668f, + 0x36e9b974, 0x1b9ea07b, 0xbcab70fb, 0xf998bb0e, + 0x8f72672c, 0x8e1674b7, 0xe7950496, 0x02dad6ec, + 0x94f92c5d, 0x4ac29f72, 0x80893ee8, 0x6eee74e7, + 0x63b51277, 0x8091bbeb, 0xd60dc302, 0x1de620aa, + 0x7433fec0, 0x2ad7afd0, 0x362e9df1, 0x8e79480a, + 0x66926824, 0x407c3052, 0x57e4e2a1, 0x45ac4e01, + 0xad15fd49, 0xb6c7b530, 0x6a42cd2d, 0xfb33a5fa, + 0xb5ed88f4, 0xfc1dd7de, 0x06f4e21a, 0x153b0035, + 0x4fbfd5e6, 0xaab1c726, 0xd5947f82, 0x69e10035, + 0x40cfbcf8, 0x25923bb8, 0xef5cc57b, 0xf576805d, + 0xd39b6a0e, 0xe1accfb2, 0x76923038, 0x8015cc77, + 0x6d1e07a4, 0xd03e7bd4, 0x46aebf03, 0x2a6ef8ee, + 0xf7da1fe5, 0x2dc8bccb, 0x734495f5, 0xd32e0a15, + 0xb8e0c1cb, 0x94dc587d, 0x557dd013, 0xa32e3a3a, + 0x0fbfa25c, 0x8f2c9a31, 0x562e2738, 0x217d3b7f, + 0x0f6ee652, 0xd1ba2c6b, 0xa7619d94, 0x8435d88a, + 0x146cca48, 0x9fe50d9e, 0x83451999, 0x512c628e, + 0x3b9f3c85, 0xf17b0f2c, 0xbcd68b79, 0x1c99ad4b, + 0x2a2d89a1, 0xfbb208de, 0xb76a870e, 0x482ba8f7, + 0x55e83ff8, 0xcf18ac1a, 0x900684f8, 0x2aa58e1c, + 0xf4c7b72d, 0x6472c9ad, 0x98ab6db8, 0x75ae0fec, + 0x4c4452bf, 0x11c52d40, 0xc1225fea, 0xd7fcce77, + 0xb149dbaf, 0x6887c1a4, 0x2fbeff29, 0x84fa0cc9, + 0xe9b92986, 0xa0e9419b, 0x420286e2, 0x7f70beb9, + 0x36dfd2ff, 0x824f356c, 0x3b930a22, 0xef6c3f80, + 0x625c87f2, 0x9d0a7a2b, 0xbe74224a, 0x46f0e8bf, + 0x717419c6, 0x91c1b2d1, 0x19f03a75, 0xd263f1ba, + 0x4ddf9383, 0x12785c30, 0x5f7cd1f5, 0x4b1ba9de, + 0xfe65d8bd, 0xd82a03c8, 0x9a68efe8, 0x160617ae, + 0xe7454122, 0x8a988464, 0xde5a629e, 0xf605c71e, + 0x162cda2f, 0xcb7c8c14, 0x755de949, 0xa754200e, + 0x3273cb29, 0xea148883, 0x9822ef85, 0x1efea739, + 0x15d9218b, 0xb5525231, 0x6bc2603b, 0xe7bf08b3, + 0x3cd90b72, 0xc0e06d3a, 0x687a1cd7, 0x15944120, + 0x1b5631f8, 0x630e3294, 0x0efe4a45, 0xac70ccb2, + 0x1727c194, 0x6868691b, 0x2f8c1abe, 0xcbb3afac, + 0x934720c7, 0x5f3ef2ea, 0x8fe96fab, 0x2cea8325, + 0xada1f217, 0x625a8db2, 0xe5ea7c81, 0x7460bfc2, + 0x41a28932, 0xc9fc67f7, 0x6069c515, 0x33f953da, + 0x0460c884, 0xe7fc6755, 0x86561b5d, 0x4ae6c1f8, + 0xc6bdfec2, 0xe6be4164, 0xa5383201, 0x7d69be09, + 0x288210e6, 0x90f6fde6, 0x80e6373a, 0x074868bf, + 0x1b186e7d, 0x6001f8e2, 0x42b806a4, 0x04c37222, + 0x8b8485a6, 0xf770b52a, 0xf790da6c, 0x04ba9bbd, + 0xeb916c68, 0x3821e25a, 0x5190a82f, 0x219cdd07, + 0x4b3afc6d, 0xcfe73acc, 0x5c69209e, 0x24cf5afa, + 0xf6873cee, 0x04e136c7, 0x87fd9dcb, 0xbc593e24, + 0x8f3681be, 0x317a4a66, 0xc2c5bbb7, 0xdf1a03a3, + 0x8010629f, 0x6bd8524e, 0xc9581d78, 0x70f4cc0b, + 0xb7b3a727, 0x0284f7ee, 0xcbe40348, 0x37f7fa02, + 0x2d73e3d8, 0xaa5f5dcf, 0x7082de2e, 0x38d05ff4, + 0x211f2e71, 0xcde4f8b0, 0x7be45fa6, 0xf24a4e57, + 0x9d29f782, 0xdd92723c, 0x47668f02, 0x2a72abf5, + 0x52ae0105, 0x045fd871, 0x1a6f87b8, 0x9a4e1d04, + 0xa83b2a5f, 0x7c87cc4d, 0xd8b22e3b, 0x3ebaf15a, + 0x5e154f52, 0x7b50cd4b, 0x5d410a74, 0x840a8fbe, + 0xbf162479, 0x44604f50, 0xe4943769, 0x5c37af05, + 0xdd1c825a, 0xdef70c9d, 0x8073ee2d, 0x5869ccfd, + 0x77c13ceb, 0x354a2145, 0x571c860d, 0xb5b28e97, + 0xcd4ce949, 0x0798d2b7, 0xa32ae4bb, 0xb867819e, + 0xec662e1b, 0x5825851a, 0x7d662086, 0x44571b92, + 0xb1760a60, 0x19268b9e, 0x26b08121, 0x21908910, + 0x72f1c513, 0x830b35bb, 0x86e9f12b, 0xe904bb1e, + 0xa50e6258, 0xa0decf23, 0xbe4d2865, 0xc72e9906, + 0x2f534b7f, 0x8f09b220, 0x81ae4c45, 0x1188ed70, + 0xcaeb2aa4, 0x435e86cd, 0x8423b946, 0x6a59eff8, + 0x63928d50, 0xcde24b62, 0xc8abbe64, 0x0b60e5e5, + 0x2ae16f0b, 0xeeecd23b, 0xb96c1dcb, 0x74c099aa, + 0x7ffb2c60, 0x52fa282a, 0xba74651c, 0x9995009a, + 0x449a0a83, 0x0eddf376, 0xfa8ad7a2, 0x3c88b6f0, + 0xe2bd3445, 0xadb5e747, 0x45c2b033, 0x7c1223b4, + 0xc6bcc311, 0xfc0d03c5, 0x281a60fa, 0x740be5d6, + 0x219431ec, 0x91cbb4d7, 0x9cc27a18, 0x34b51059, + 0xbefaf7b6, 0x958059f1, 0xd66f6913, 0xc061f472, + 0xb6c129c8, 0xe0827e30, 0x56423806, 0xed68ce96, + 0xdccce3ad, 0x23431036, 0x2d1b8dc3, 0x6fce4e45, + 0xd878320b, 0x471d4845, 0x90198311, 0x760a203c, + 0x28e6d15b, 0x3b820db6, 0x100db7cb, 0xed86eb09, + 0xdde1db71, 0xdd79665e, 0xd4e700ef, 0x631bb290, + 0x5dd65a01, 0x30cbba18, 0xc3a8d098, 0xf1638754, + 0xd1b9499e, 0x8f0f4cf4, 0x54333437, 0x19a1aee6, + 0x64d2b4e2, 0xe2d10121, 0x40fc74a6, 0x1904be60, + 0x6dc59519, 0x921e236a, 0x08e73fd8, 0x0bfb7031, + 0xe1d6d14d, 0x9edd2acf, 0xf10974cc, 0xedd17cea, + 0xc7f13f98, 0xd061e4ba, 0x966e7aa5, 0xf9aa14ca, + 0x68fe0793, 0xd0b4b674, 0x49a9b824, 0xd68cd520, + 0x717896ef, 0x254386a1, 0xa03a3b8d, 0x97c5c034, + 0x62d03359, 0x36ac4954, 0xc2ec87bf, 0xa2439bcd, + 0x4e5aacba, 0x1a843e21, 0x575d4a92, 0x32f37d42, + 0xfa9fbc58, 0x43b0e147, 0x39fb1053, 0xff8b5a1a, + 0xd3e160a9, 0x630e928d, 0x94739451, 0x8669ceff, + 0x75fc1912, 0x5ba125d5, 0x1dcd5449, 0x8cac0d09, + 0xf87ad6e7, 0x0065fa61, 0x5ace0d58, 0x9203b2d8, + 0xd5babaeb, 0xce612290, 0x5fc40947, 0x93f0f563, + 0xc4fe7f0c, 0x6223c4d9, 0xee356626, 0x7feed8b4, + 0xacf6ab4b, 0x80be2f14, 0x1e36948c, 0x2ef041b4, + 0xabee78c9, 0x6f652c4e, 0x502c452a, 0x56dbbe00, + 0x335ef338, 0x75c82c49, 0x8960425e, 0xcc9109e2, + 0x7697cb05, 0xca2af880, 0x207b703e, 0x68d721e7, + 0x211de1b9, 0x9741b0c7, 0xa5ff2d70, 0x8b27d5b5, + 0x5bf5ddf7, 0x2546cb34, 0x6fccd772, 0x838b6801, + 0x7b04d78d, 0xf2286c13, 0x68f2b3f6, 0x9048aa86, + 0x8cb8795b, 0xc39b746a, 0x5629e752, 0xce1d68e4, + 0x9494c89e, 0x128a226b, 0xf4b0f407, 0x2726b3f9, + 0xb0778463, 0x26970367, 0x762066f7, 0xcbed792f, + 0x67df91f6, 0xdff613ca, 0x11c0cc57, 0x242396ec, + 0x4ac28cef, 0xe725809d, 0xc3bba72c, 0x2eb7d275, + 0x07155545, 0x2dd4af13, 0xaa03502e, 0xb96f3f02, + 0xa54f8645, 0x3f0b8be4, 0x234fa9e3, 0x6873fbd8, + 0x507c131c, 0xd75d1d17, 0xa0a56182, 0x3631a61b, + 0xe05d5b5d, 0x1bea25e1, 0xdd2fccf7, 0x1fd02cf7, + 0x82f6011c, 0x42c8fc1e, 0xefc3860c, 0x0877958e, + 0xe44ef2ef, 0x6cda8b6d, 0xeb338af9, 0x4826de86, + 0xdfc7b7fe, 0xe4a0c93f, 0x5d11d7ae, 0x35ab1293, + 0xeb19d80b, 0xd7f8bd7f, 0xb2b64548, 0xa9686a7b, + 0xa3d48d85, 0xce81f68a, 0x8911b046, 0x8dd67f54, + 0x4f8d0468, 0xdb688d91, 0x8a79bfea, 0x3ddb75e3, + 0x49331c2c, 0x2a74d257, 0x80354ece, 0xe4e7d6f1, + 0xf1fc1306, 0x8c7b59ca, 0x835497e2, 0x0b1e9137, + 0x236df42d, 0x35f544fb, 0x70f1916f, 0xc62bbb61, + 0x63e7ab40, 0xed0008ca, 0x32ff3668, 0x5ca9cad7, + 0x71e6b3d4, 0x37d399a1, 0xfb508f50, 0xb5156d23, + 0x6b51a56b, 0xc22c3d5a, 0xa33a7772, 0x00012ec0, + 0xa23c692d, 0xce97718c, 0xc537f24f, 0x25545ffe, + 0xd4fa816c, 0xff5bed37, 0xf4156f4e, 0xe63266b9, + 0xf6b450a3, 0x56f194b7, 0x94efa9f1, 0x0649b3b8, + 0xcff86f79, 0x474a0018, 0x1c887528, 0x180faa08, + 0x68dbdf0b, 0xe7e1b537, 0xeadf069a, 0x6e39c389, + 0xcd23a6b9, 0xe01d29c5, 0x16813d39, 0x9c6f4589, + 0xff406332, 0x62065adc, 0xfd6cb2c2, 0x6d1e69da, + 0xa6c565e2, 0xf9b9d563, 0x704b27b6, 0xb3e1bfb6, + 0xe76e9a75, 0xf70fba74, 0xd3fedf0c, 0x32aa9ee7, + 0xaea3376d, 0x6166659e, 0x183f0599, 0xf276c092, + 0x1a1cd985, 0x78aef6e5, 0x4c6861c7, 0xc458eda2, + 0xd24e96c5, 0x625ce025, 0x6ede7e4a, 0x4a606ecd, + 0x5d622faf, 0x1c8514c5, 0x22c4a823, 0x42ce5fd2, + 0xddc52365, 0x4df6e528, 0xdfc3e3ee, 0x71a26ff8, + 0x5eb68575, 0xf36a8cf1, 0x7723a3bb, 0x696bc3d6, + 0x8baf064f, 0xfd7084b9, 0x8b16c78a, 0xaa8c7ea4, + 0x1ba071d5, 0xa2a796f3, 0xcab16e94, 0x4c59419e, + 0x2588d957, 0x986a26fa, 0xd4ea51c5, 0xb009200e, + 0xa914628f, 0x078b2fc6, 0xaea27b04, 0x737f99cf, + 0x7dd74f46, 0x5d486cbe, 0xe6743c1e, 0x2b648547, + 0x2da4e9c9, 0x69810176, 0xa75eda93, 0x6fd263a0, + 0x0000fbae, 0x299bbdc1, 0xd2d75efd, 0x4ba65150, + 0x93f91262, 0x10ef87df, 0x58d80544, 0x52bb1069, + 0x714eb405, 0xd342881d, 0x178e9bab, 0x2c237fe1, + 0x89cf1f64, 0xd9f01623, 0x2374ff2b, 0xa2594d9b, + 0xb7fe95f2, 0x4b02b13c, 0x28d3d082, 0xf9be19b2, + 0xb45f4ee0, 0xc721cdd0, 0xd9a3c564, 0x4cb4f45d, + 0x01ca007c, 0x8e4d7ad7, 0x036b814e, 0x4c5784f4, + 0xd5095f11, 0x8f365815, 0x9ef2859b, 0xc4f9ce0e, + 0x91ceeaee, 0xf1e3323a, 0xb4d96fad, 0x47842120, + 0xdb5eaaa8, 0x9668101e, 0xbf81de55, 0x0ddea74b, + 0x47779aa2, 0x8f71cff0, 0xc20f1824, 0x2b9f47d3, + 0x15a759f6, 0x81a4c801, 0x5a56bd5e, 0x05eee0e3, + 0x929aa1d4, 0x83aea08d, 0x3c584609, 0xdec476f4, + 0x0f2c0473, 0xb3ab1038, 0x78911fe7, 0x7d6e21d6, + 0x4151e1a2, 0x5961e160, 0x11bedc38, 0xa5947ddc, + 0x02ca8aca, 0x1a5ca2f5, 0xe190eedc, 0x33c607cc, + 0xcd5e3327, 0x2b0d5b11, 0xae0cdf9a, 0x1ddc1752, + 0x6c8e323a, 0x25a3e3e7, 0xa162b4cd, 0x40f96d5c, + 0xb4851bff, 0xdf768e14, 0xf519f0f0, 0x8fd05e5b, + 0x95321581, 0xf9f55585, 0xdc7f4b76, 0x791ebb9d, + 0x8e8a1bd8, 0x2453e131, 0xd4b9b2f2, 0xfeb60f25, + 0x86c44b02, 0xe5cb390a, 0x019e004a, 0xf39a033d, + 0x954b5876, 0x6cc484f9, 0x855bb5da, 0xcc09f9fa, + 0x8b64dda4, 0xe3d4c404, 0x21d92c87, 0x1ed11d99, + 0xde8c4e7c, 0xf2ab7d47, 0x4cc53ba1, 0xd8bc2d4e, + 0x543465ea, 0xc058be01, 0xed816beb, 0xc9d5e4b8, + 0xc12a3a2e, 0x1bc558ff, 0x75485ca3, 0x9cf0a642, + 0x7d7a99bd, 0x816d9a3c, 0x24c8756d, 0x43e1fdc2, + 0x42de0d26, 0xb7581b11, 0x5196255f, 0x057752f5, + 0x8fcada43, 0x4592fef4, 0x67ccad1f, 0x804b4cd5, + 0xe59daafc, 0x0c4307a2, 0xae922ca5, 0x5a4fe01a, + 0x633199f3, 0x5c8e4620, 0x3d9025b3, 0x27e560fe, + 0xd44733eb, 0x2e07ad66, 0xeae6fbbd, 0x1e17f0c6, + 0xec59ea4d, 0xffe1014a, 0x1d69b7ab, 0xcee8db89, + 0x5c51f9e9, 0xd3aedc85, 0x02b868e8, 0x186406e6, + 0x94d1d43a, 0xec459b8a, 0x588466ec, 0x978d9899, + 0x095d2d8a, 0xff1be5a5, 0x59aba24b, 0xccf9d049, + 0x55a7d432, 0x3fa551e5, 0x3333ede2, 0x75f39a47, + 0xe29495d5, 0xe5a21a5b, 0x97d5a9cd, 0x23afaf4e, + 0xcb1fa6e2, 0x100278f1, 0xd6110dc6, 0xa8a2256a, + 0x415330e6, 0xa0cd3163, 0x5ba1b3e6, 0xf7dacc81, + 0x3946e570, 0x4d644701, 0x685acab5, 0xf868613c, + 0xc974e04c, 0x51339528, 0x3a9ed3aa, 0x6d28240c, + 0x53f8befb, 0x8e476fbd, 0xa4c17a62, 0x4ed4b7bb, + 0xc97836ad, 0xb9b70d6d, 0x24c7a556, 0x2f303ee6, + 0x282aa0e2, 0x7f3a00db, 0x8d818ac8, 0xe9579034, + 0x1984a2e7, 0xac279d67, 0x5a21619a, 0x3aed8749, + 0x2f08d084, 0x7197557d, 0x3a25abd3, 0x84b3833d, + 0x9dd586ad, 0xa35f8b47, 0xd3110d1d, 0xb46e9061, + 0x91884cfb, 0x21f847e4, 0x533ed0f4, 0x05421916, + 0x46bf5375, 0x96f64f87, 0x619151b7, 0xde889a35, + 0x218f7635, 0x05521ac1, 0xc91eac25, 0xee4b2f56, + 0x2d88b5f8, 0xc0a2d9ac, 0x5878b157, 0xfbac8564, + 0x73986806, 0x3f039e2a, 0x2ab33fe8, 0x8ebdc77d, + 0xc9bd2967, 0x9fcdcedf, 0x95a764f4, 0x63f73309, + 0x1a388454, 0x0853e5fd, 0x423787d5, 0x70e51528, + 0xcb3c68d5, 0xbc132062, 0x198144d6, 0x31a039fb, + 0x28cbdd17, 0xd6253cfa, 0xd35be889, 0x10eada6d, + 0xa669f072, 0xbd1000fa, 0x7eb09b59, 0xdd10cace, + 0xbe01f5bf, 0x9eedc696, 0x5e78d7a9, 0x4dc777e3, + 0xb6e77579, 0x3772cd60, 0x53579b31, 0x8a19b0a4, + 0xfd38f5b3, 0x57cc4fdb, 0x07b57c47, 0x40654213, + 0xaaa6db10, 0x8c4db1c9, 0x71977fcb, 0x0a083a77, + 0x98c3677a, 0xe2e85304, 0x2b6b1b48, 0x3d793d9b, + 0x009388e6, 0xcc537ed4, 0xe61d3578, 0x093928f1, + 0xce542c13, 0x2190c0fb, 0xe10742f6, 0xbcba78ec, + 0x33b37453, 0x6811a166, 0x71846b00, 0x23bc9279, + 0xbda42e3e, 0x24352af0, 0x44f4a225, 0x1f084f1b, + 0xa94effde, 0x80211c06, 0x83e05d6c, 0x87dbf180, + 0x2aaf9644, 0x3834c882, 0x5622fc34, 0xc3b993c3, + 0x3200de64, 0xb315ec9f, 0xe3e381e9, 0x016b1c25, + 0x294dbcfc, 0x52635697, 0x93285790, 0xe4f181a8, + 0x49a1fe17, 0x2e99cf1d, 0x190bebf4, 0xd8a35e54, + 0x30c64f5d, 0xe5e364f5, 0x5a138a03, 0x7e426978, + 0x3ef68639, 0x15bc3a82, 0xffecc942, 0xc4f85686, + 0xfa3a51a3, 0x0f2cc094, 0x87e6cbe2, 0xc9b22bb5, + 0xed89d641, 0xe0e70930, 0xfb31120e, 0xec0886c1, + 0xc830cf9e, 0x57cf2a4f, 0xab6664b9, 0x5dcb1d77, + 0x2cb00462, 0x4c468c9c, 0x8a4f263e, 0x3a8ac7a7, + 0x223fa7ea, 0x591d17bd, 0xebab74d1, 0x0ba7b3a3, + 0xdd9d2c31, 0x9047ffa5, 0x92a44c0a, 0x0dac8391, + 0xca5d63a8, 0x717237dd, 0xcef96cd4, 0x5c09b490, + 0xd582c938, 0x3d70fb85, 0x37815616, 0x525d6595, + 0x351d5735, 0x32235115, 0x34812979, 0xda3b304d, + 0xdc5da37c, 0x39d28e7c, 0x138333c9, 0x791844f0, + 0xad4de5bd, 0x07c82491, 0x68204731, 0xc74ede4c, + 0x93548d2d, 0x63f569f8, 0x4cdcdf54, 0xaff48ba9, + 0xb32983a9, 0x0daf247b, 0x74a53a84, 0x5df2c404, + 0xd740070c, 0x09366f96, 0x9310da06, 0x630f259a, + 0x5057afd3, 0x8dd307dd, 0xc7c67c28, 0x0c340363, + 0x19ed046d, 0x811ca64e, 0xc99d573c, 0x039524ee, + 0x68cd6009, 0x8bddcb93, 0x5b5e27d5, 0xf2e2c115, + 0x5850fafb, 0xc5400f3d, 0x716e24b1, 0x1b1f2378, + 0xb92126da, 0x750be0b5, 0x67bc98e9, 0x279d3022, + 0x244770e9, 0x4484b62f, 0xaf6b24f9, 0x83cf98a9, + 0xf5052a16, 0xcdffc32e, 0xb2dfee2a, 0x7ec83ec1, + 0xd5c3fc45, 0x5d704103, 0xc96808ad, 0xf48474a0, + 0xc22f6e7c, 0x9f82bdf5, 0x7b043fa2, 0x16fd2cc7, + 0x42d6146f, 0x59a9d1f6, 0xac64f184, 0x1d02f622, + 0x9baacbc3, 0x81cf2fac, 0x76d210c0, 0x83a7667f, + 0x62d9d299, 0x6da55346, 0xa217449e, 0x8b75dfc5, + 0x7df1b981, 0xdfc99380, 0x7cba1012, 0xb39d4774, + 0x2e2b0570, 0xd11526f4, 0xe6bbdda9, 0xb2f774b4, + 0x567795ff, 0x2cf2b25d, 0x0059a3fc, 0xf667073e, + 0xcedfaf3e, 0x539cc3ad, 0x2d0d0d8f, 0x6df565fc, + 0x35e24c8d, 0x99b4e0a0, 0xc9c544ef, 0x17e990a2, + 0xd5f404cd, 0x596936b2, 0x3129abfb, 0x62c1dab8, + 0xbbe7baf4, 0x0c179074, 0xb17ea778, 0xda3bd304, + 0x9d465b5c, 0x038245d3, 0x45368ebc, 0xef6abd9d, + 0x0a20a13e, 0xa5dfb3dc, 0xa65392f7, 0x23988796, + 0x53d3367a, 0xa8d86ce1, 0xbc9b9f49, 0x6e9d09c4, + 0x6f57aa74, 0xa5988ca4, 0x04a025ed, 0xfd5b4f32, + 0x4bce9351, 0x28d56b95, 0x24b9a938, 0x48937698, + 0x8ca45318, 0x61e23a9b, 0x951d1cd7, 0x5f6dfbe3, + 0x1c0809f3, 0xca53abc5, 0xb63f0c88, 0x160efaa0, + 0x706da1bd, 0x0b715637, 0xe772eee8, 0xafaea68d, + 0x0e48a749, 0x88710459, 0xfc67582d, 0x3af8e118, + 0xd4c78fb9, 0xdf05237e, 0x23ac3c99, 0xc6195e5f, + 0xc8f4aea8, 0x31b1ecc9, 0x39a340a0, 0x855d94b3, + 0x999c42eb, 0xd7617d52, 0x65d695a1, 0xb281b6d1, + 0xb03a4842, 0xbe5b5689, 0x8588fe44, 0xe4815625, + 0xf4841603, 0x6082ce01, 0xc15af269, 0xf44161fd, + 0x3c549c16, 0x8637adde, 0x6e223661, 0xb88eb81f, + 0x393cc5ac, 0xc3599978, 0x268efa6d, 0x37942749, + 0x35154c63, 0xa3dc7501, 0x3e9d39da, 0x9d9432cd, + 0x8b9809cf, 0x050c019a, 0x3eac43d2, 0xb65341e7, + 0x1a9ef52a, 0xfc4f5d11, 0xa4af95d3, 0x461718d4, + 0xd7608e5b, 0x14ca46b3, 0x35a21eac, 0x1a8a9552, + 0xf2155111, 0x5eac5f45, 0x60f2bbc2, 0xacb164a8, + 0xa488fc13, 0x5d33919d, 0x9278ccb1, 0xadeec129, + 0x84afe973, 0xf82176da, 0xd4cfb384, 0xff11259e, + 0x01fdc36d, 0xcf3216ba, 0x79247f14, 0x32c87f83, + 0x3c2e20e7, 0x330e932e, 0x82d4a89e, 0x50d35d9f, + 0x80226fb0, 0x287dbfdf, 0x46901de3, 0x9974cd5c, + 0xc48823a6, 0xb7fd3154, 0x086141d3, 0x04c6b8cf, + 0xb22d2f66, 0x3b6da5d7, 0x569afde8, 0x4679e5e4, + 0x42114853, 0x22639124, 0xa90f256c, 0xf351c824, + 0x4ccf09e6, 0x06eea0f7, 0x80d5cbaf, 0x79739ecd, + 0xdd64e2cf, 0xe1c12687, 0xe1df3ddb, 0x3e3e47e7, + 0x7679fd20, 0x11c1a2ad, 0xbdad0df8, 0xc4ced0ce, + 0x24f62c91, 0x8bf4ae2e, 0xe834c00f, 0xd319266f, + 0x7e69fe03, 0x1fb8040c, 0xe47cd138, 0x606ba278, + 0x3293d0f9, 0x18e7efdf, 0x31110404, 0x00811e9e, + 0x70e8d898, 0xaf721521, 0x374b6cf5, 0x441e0bc7, + 0x79657ed7, 0x166b7433, 0xe8a7118c, 0x7822ec9e, + 0xae3cbcc7, 0x7628614c, 0x7c325dfc, 0x9b114cbb, + 0x1a7e2d0c, 0x50e7928a, 0x8c54060b, 0x8088eeee, + 0x28ba54a7, 0xf2dc7f54, 0xcdb9187b, 0x150a3aa9, + 0x1a078025, 0xd1749f15, 0x7167d948, 0x41ee0a3a, + 0xe516c0cf, 0x07580c12, 0x5c36bb86, 0xc7243f6f, + 0x631f630d, 0x170b1b7d, 0x2956c535, 0x26be9e7d, + 0x0e294ff4, 0x6d236b76, 0x3f3b1a59, 0xce215499, + 0x569d345a, 0x9bee172d, 0xe393c5b6, 0xaeb93ad4, + 0x475a487f, 0x92f6a8b9, 0x013129c8, 0x3e1311ff, + 0xd2b6e1b3, 0x9d0813a4, 0x8126bb7d, 0x5400abfa, + 0x01f12feb, 0x66f7c204, 0x8ab18ab1, 0x803fc4a1, + 0x924d22d4, 0x413d9a11, 0x70ee86ee, 0x80a241ae, + 0x57eeb717, 0x54c60d09, 0xef844ec7, 0xaf495995, + 0x42c33303, 0x6db8f3ad, 0xd2c47162, 0x53d23f3c, + 0x28634bc2, 0xa34fa351, 0xfc8a890d, 0xa8ba40d8, + 0x1d6d7839, 0xeb0d6f20, 0x7fe0e3ec, 0xc57e3438, + 0x8ee7d91c, 0x2639cff2, 0xca495a4b, 0x3aa8c6dd, + 0xb444e070, 0x19e0fd18, 0xe5911271, 0xfa1b47a5, + 0x9904480e, 0x6a2814f3, 0xe2ec89a8, 0xba83a817, + 0xc3b6e55c, 0xa9984643, 0x8a2f94b5, 0x6e5297e9, + 0x8664192e, 0x6e6e240b, 0xb0f7f9a6, 0x49bf7851, + 0xbf671e95, 0xa33c1665, 0x0fb6ee0c, 0xca969361, + 0xe59b0e7b, 0x96748a01, 0x403ce45f, 0x5bb246dc, + 0x5c751b7c, 0xf9c169e1, 0x94c1b960, 0xd7f334c0, + 0xc648ba71, 0xb7341e19, 0x99667f96, 0xbbf3d687, + 0x422eea4f, 0x06688026, 0xb94395f2, 0x205caeb7, + 0xd5fd742d, 0xbe30aef7, 0xec575d87, 0x681ce40e, + 0x530b2edc, 0x25d32875, 0x154f66f3, 0x3e288412, + 0xc65dcf52, 0x716bdee0, 0x3efdd4a1, 0xbfbfff6b, + 0x50c2935d, 0x69d60929, 0x6c402bad, 0xad4e31af, + 0x37b62d85, 0xaaaf0d6f, 0x9c2ebaf0, 0x6604ab5f, + 0xa3533a29, 0xba840915, 0x3dac0dc8, 0x3cd37d0b, + 0x49b9aa15, 0x0eaf3331, 0x96cfb3bb, 0x7ef39da3, + 0x9e3a3611, 0xaea72610, 0xe5a23abe, 0x67239e77, + 0x8fb2858c, 0x44c64f5f, 0xe33f4cc5, 0x14d1efc1, + 0x463c3b49, 0x20caab57, 0x01d9b5ab, 0x2e1b22f5, + 0xe1085cfe, 0x5f6d84b4, 0xbf19c53c, 0x41d3cd65, + 0xfc22171e, 0x60f0e158, 0x3b71f467, 0x705d3e3c, + 0xef13e76a, 0x4b2c23ae, 0x3e8b9ad1, 0x70fea23e, + 0x74bfcb69, 0x6bb4fb84, 0xb6ba0c53, 0x3b52126c, + 0xb1eba5e6, 0xe8d4152c, 0xf829f8a9, 0xdf111f06, + 0x97c8d13d, 0x2eb0e540, 0xe92bbdf1, 0xef5837de, + 0x08484ce7, 0x587c6450, 0x240e3073, 0x672be09b, + 0xc591db93, 0xbe948393, 0xaff709e3, 0xb72f02bb, + 0x34239ab0, 0x10ebd24d, 0x8c415a20, 0xbe8afcd4, + 0x0474a305, 0x94598725, 0x6a0011f8, 0x60795d6a, + 0x07745c2e, 0x525b6e1e, 0x0da68e6c, 0xc9b0c410, + 0x35fa6c6c, 0x09cc8f98, 0x2f0a3851, 0x97595c4d, + 0x30e72ae2, 0x6bfa05a1, 0xb70fe27f, 0x406b7f14, + 0xd2a18170, 0x607b9ab0, 0xd5505d2d, 0xb046c579, + 0x3d5237b7, 0xd121ed7e, 0x376bf696, 0x27bac8d8, + 0x58f5167d, 0x587cfd48, 0x696868b5, 0x04b46a78, + 0x4949d5c9, 0x8497348c, 0xc3a46d21, 0xf1a06259, + 0xdca640b1, 0x8d329253, 0x237aa4b3, 0x9755583b, + 0x97d1175a, 0x38104d1e, 0x6148ec0d, 0xd7ccd1b8, + 0xb286be43, 0x5992b121, 0x49424d25, 0xab43bbb9, + 0x0c128f94, 0x67cebcb3, 0xbad48269, 0x6c71997c, + 0x7bc678d6, 0x5e5c8ab6, 0x0faa10f2, 0xcacfcbb3, + 0x3f9fcc50, 0x63164179, 0x0c0c6475, 0x38c68b21, + 0x6bcb3b5d, 0x71047d39, 0xd30d237e, 0xe15d1c41, + 0xc2326eaa, 0x4b337dfb, 0x40a76de2, 0x10731708, + 0x51fa4f61, 0xeff87dd9, 0x2720a83d, 0xc406451d, + 0xba720e37, 0x4f3ac5e8, 0x61e6985e, 0x04b962f8, + 0x0efa5474, 0xa672cd55, 0x1c9825c3, 0x93439686, + 0x4a99a4c5, 0x06c0eb6f, 0x496dd43a, 0xdd7a8807, + 0xf07c4685, 0x6be1a4d5, 0x6be16322, 0x1fb99e40, + 0x08078516, 0x0442a859, 0xaeeea02c, 0x97829f1d, + 0x918b795a, 0x35babaea, 0xd548ec3e, 0xac83ab38, + 0x00e8a454, 0xcf9d631a, 0x2ebefc97, 0xeaeab437, + 0xb3976833, 0xd46b8b1f, 0x5952e7e8, 0x1fe684cb, + 0xf6ef4754, 0xa0791a2d, 0xeadfedd4, 0xe1510ad0, + 0x2b9be03f, 0x1c622d08, 0xa8f43e80, 0x68d07f90, + 0xa24c000f, 0x326b5806, 0x2b064f11, 0xb1db9586, + 0x934bd02c, 0x11665f8b, 0xd60be244, 0xed57b1cd, + 0x21b10c46, 0xeb782a9d, 0xec515644, 0x8c8ee2b7, + 0xda3e87e7, 0x23b84b1c, 0x30fe8739, 0x87db6092, + 0x41f9489e, 0x69c68384, 0xf97dc599, 0x3370e8af, + 0x8b000e1a, 0xb9c365a3, 0x66279c1b, 0xd59bf577, + 0x99f8baee, 0x57e158dc, 0x976c8feb, 0x2fdd91d3, + 0x17575843, 0xdeddc952, 0x56c4756f, 0x7c5e8756, + 0xe99e2aa6, 0xaf1285db, 0xe49adffa, 0xdb2266b0, + 0xf07428ce, 0x2510f772, 0x3cb530fd, 0xc2803436, + 0xde49d973, 0x1da5b4b4, 0xf97773d4, 0xd4601c7f, + 0x191db761, 0xa0694191, 0x64667290, 0x565bdfbd, + 0x4d402eca, 0xd411d983, 0xee8a9e8b, 0xf656de93, + 0xb5a1d8ef, 0x23a13d06, 0xa92523c3, 0x0b07f4df, + 0xca32d3f8, 0xe73156bb, 0x95d8720d, 0xcf3665ae, + 0x2edc20b7, 0x0fa26732, 0x1355a6b3, 0xde5902ef, + 0x4cf47360, 0x97a128fe, 0x414e3544, 0x1e7d87f3, + 0x9a9831be, 0x109d7bad, 0x4d09e9ef, 0x3c20f16c, + 0xb86c83fd, 0x3ae9722d, 0x05d086d5, 0xf84b5447, + 0xe436ba6e, 0x00edf1fa, 0x7f1ab370, 0x20e01df6, + 0x5e0594b3, 0x93a16b8f, 0xe27c11ff, 0x3bf75daa, + 0xb7f2f77e, 0xeb942889, 0x58370dcf, 0x6acdb340, + 0xebe26a73, 0x1044704e, 0x0a12e0f1, 0x2cb9e9ee, + 0x9588d951, 0xfd907ddf, 0x67bb64d9, 0x54846094, + 0x1ca0f2d3, 0x2d319165, 0x2eb2109c, 0x7c78cde2, + 0x7c327121, 0x681acf9c, 0x381c631c, 0xc8dd8f38, + 0x8c12da23, 0x0381afac, 0xdad840e7, 0x8b8b196f, + 0x1dfbd4db, 0x08f96849, 0x89e1611d, 0x5eb7470d, + 0x3985d7d7, 0xcafd736c, 0x7b444ba0, 0x75a6683f, + 0xe644f2ed, 0xaad0687a, 0x16972007, 0x30ad1c21, + 0xef312335, 0x022a9363, 0x9fafc5c1, 0x202a93ce, + 0x3c8073ee, 0xcface946, 0x2aadd74b, 0x6116bb54, + 0xd7d410db, 0xe0034f91, 0x4ef00b8b, 0x7c56b724, + 0x1546f69e, 0x6f71dd70, 0xae98f2f5, 0x73f31822, + 0xbbaad2a1, 0xe6212ab7, 0x91d01a11, 0x8871a5ff, + 0xf9fe2e96, 0x34b0e7dc, 0x216a2de1, 0xe6a790d2, + 0xb86aeea6, 0x7066d474, 0x7862ea5a, 0xd3fadf14, + 0x58993260, 0x8cd6956d, 0x9a99596b, 0x161fea80, + 0x1e6c817b, 0xe0aa3e05, 0xe7778880, 0xe619e4dc, + 0xfa283a40, 0x42ed7f47, 0x7c778024, 0x395778b7, + 0x24c9591d, 0x42e1e8a7, 0xd5c2fb9e, 0xe80828b8, + 0xcf546d80, 0x082c4de6, 0xd6b09494, 0xfdf078ec, + 0x08babec3, 0xf3dfdfeb, 0xabe34f92, 0xad35e58e, + 0x71872501, 0xaee49253, 0x600e5f82, 0xd61cf43b, + 0x80b4e9b4, 0x080ecd89, 0xba5d685b, 0x100cde4f, + 0x3e91fd19, 0xbb85de54, 0x47ec1a5d, 0xd0c25367, + 0x4672c9aa, 0xca75f350, 0x1658670a, 0xd87c114e, + 0x0f6a3b34, 0x73df9856, 0x479653d0, 0x01aa5f5c, + 0x262af3db, 0x823a253a, 0x466e1854, 0x5f0d3c58, + 0x6ed32a1a, 0x14fb45d6, 0xec196a70, 0xba404c13, + 0x9ec37588, 0x193b588b, 0x6c62aac8, 0x7ff01860, + 0xbfcfa7f4, 0x7ffb62de, 0x93be599c, 0xcc0204e0, + 0xc555df30, 0x1b00f32e, 0x88f2cdcb, 0xfa9d0a77, + 0x63b58618, 0x681e9716, 0x0fa9df49, 0xeab0ddb9, + 0x6e42a0ee, 0x29082d7d, 0x153eb1fc, 0xc918e6a6, + 0x86d624b0, 0x95f39ce1, 0x9414c896, 0x30e1759f, + 0xd51e38cf, 0x224705ae, 0x823f6199, 0x892fcb5c, + 0x6ca35fca, 0xe84857c3, 0xfec77cfb, 0xb75f3b9e, + 0x6ce94f22, 0xab3777b6, 0xc9c0a161, 0xb3399b5a, + 0xd75e8b84, 0xab395f6a, 0x1b48d213, 0x2f61ead0, + 0x8578d1c5, 0xcd8977e5, 0x18a3a8cb, 0xacd33fe4, + 0xe254b413, 0x18261050, 0x146004cf, 0x90106069, + 0x471aeca0, 0x599edba7, 0xf5d3ad88, 0x1622b8b2, + 0x7f6a2a3c, 0x0aa6ee15, 0x90d0009a, 0x3c7363ea, + 0x247b317d, 0xde14a908, 0xbecf179b, 0x7527d0fe, + 0xa89bf059, 0x9dcf7480, 0xb622ab57, 0x8c86e414, + 0xd14f85b5, 0xec532c4d, 0xf42f627b, 0x7b0729fc, + 0x60e2f7a2, 0x248f97fa, 0xbd97783b, 0xb3cb5df4, + 0x95ae72cc, 0x7528bfdf, 0x544bbaee, 0x10eb4f2a, + 0x8413ae0b, 0x5676d09b, 0xb2f62e25, 0x6743b79d, + 0x6d21b051, 0xda3b485c, 0xeb8e8e0f, 0xf8b39dc6, + 0x2215cc32, 0xdc9b8a9d, 0xc2314aaa, 0xb8bdb1e0, + 0x23e84cf2, 0x6aa2443a, 0xf57d7d26, 0xf22ff14d, + 0xcaf58294, 0xd2787b14, 0x284d5cc2, 0x35f71712, + 0xc6632cf2, 0xfd11b887, 0x9ce81cd4, 0x84b8908c, + 0xc2cd5741, 0x9e434217, 0xa75688ab, 0x2d941918, + 0xd7708a5d, 0x7e20b51f, 0x8ad55890, 0x4b788bc7, + 0x1ea0fd20, 0xc26c817f, 0x5b551c9f, 0x7b474917, + 0xaf8b118a, 0xf1ad33a1, 0xe0c2e19d, 0x029878d7, + 0x794b13d3, 0x9349f5d3, 0xe9fdab6e, 0xfd743e66, + 0xed73d0ea, 0xb3fc516e, 0xc7bda0e2, 0x455f4834, + 0xfab054e1, 0x9a1681dd, 0x26469721, 0xe8adfa4e, + 0xe1377972, 0x87747a24, 0x39dc3615, 0xc35f3222, + 0x57e0567e, 0xb1f14bf3, 0xe0be776b, 0x71b38b11, + 0xa514a120, 0xd1e10207, 0x0ae729a3, 0x19efe583, + 0x52f7f110, 0xc845aee0, 0xaf75c46a, 0x39e847cb, + 0x1ed05964, 0x2275a4e8, 0xd90f481f, 0x11660c6e, + 0x7a63a9d6, 0x385fb3f1, 0xa728a66b, 0x146b41f4, + 0xfc677249, 0xdd7dad76, 0xd0e4ef16, 0xb0f033d2, + 0x9715a5fa, 0xa797369d, 0x889b90b6, 0xdfa991c9, + 0xc616c1dd, 0x2ba5c64c, 0x126d5ed1, 0x553b56b1, + 0x399db93b, 0xab1e3712, 0x3b5875a6, 0x8b7e2853, + 0xec7040e7, 0x6f4d0b34, 0xb0b63ef3, 0xd63a8c8e, + 0x6b57b435, 0x5cd0a143, 0x43b69891, 0x2e629a15, + 0xd73c1cde, 0xed7f64d4, 0x947ebd84, 0x7ad6d0a4, + 0xe67b1014, 0xa6759f5d, 0xd56b1dad, 0x614bc759, + 0x11222117, 0x79c4d55c, 0x417aba9a, 0xe2f2809c, + 0xc47bff1d, 0x9e816605, 0xfc1302f5, 0x460c35d0, + 0xb5b095f4, 0xf0007a8c, 0xbf1c88fa, 0x1e57cfb7, + 0x1f23590e, 0xfdf559b7, 0xf347ef91, 0xdd41ee58, + 0xd2c3659e, 0xda4a9da6, 0xfee4fdca, 0xb7e99850, + 0x8892050f, 0x4a1f5d60, 0xe01449bd, 0xbea6fa6a, + 0x2a626136, 0x709530e9, 0xba02f008, 0xda73eee9, + 0x0af852c2, 0x1ab16336, 0xd09787a2, 0xd58a9588, + 0x1a5d8e1d, 0xa26c4e9c, 0x41151f43, 0xfb163c59, + 0xfd625b9d, 0xb6aef1cc, 0x26befc23, 0x44b5569a, + 0xaa2cf46c, 0x4625fed3, 0xc30fc8cb, 0x4a07cad9, + 0x944a2cfb, 0xf56cbc6e, 0x0f617375, 0x48033439, + 0x5ee56d4c, 0xecc9f389, 0x034d615f, 0xc0c19798, + 0x017ed93e, 0x59722b52, 0xcf64024d, 0x4a12a514, + 0xb5bd0b29, 0x259deebb, 0x449d7bf7, 0x12e0c51e, + 0x16dc8c0c, 0xffa45539, 0x5f51971d, 0x0f30382e, + 0xeec33f8e, 0x45857cc7, 0x0cc74a86, 0x3444288d, + 0x221b5a36, 0xa359dabc, 0x4aa70f77, 0xa26f05a0, + 0xd89aaedb, 0x38ddeee8, 0x6e58315e, 0xf6341e0a, + 0x79dc8db4, 0xe3f879df, 0xf44b05b2, 0xbc6311ba, + 0xe8803e30, 0x6ca5e8d2, 0xd8c197de, 0x992a2bfa, + 0x90706fe8, 0xb9aa8873, 0xf982f2a8, 0xedda0078, + 0x174ee171, 0x4442b6c9, 0xd7dc5fa8, 0x1a299346, + 0xe56cf780, 0x6a080160, 0x010b58cc, 0x6e1ec7b8, + 0xb396f01a, 0x67e58dc4, 0xfc332eaa, 0xba7fcb5b, + 0x12007ba7, 0x1960171f, 0xaae9c135, 0xbefb75e1, + 0xdd9f70c4, 0xdcf5cc5a, 0x19262613, 0xd9570ce1, + 0x44e938f5, 0x545b1738, 0xae81cf1e, 0xeb6d6041, + 0x9c893d7c, 0x6bdaad58, 0x82c7911a, 0x471d2004, + 0x9eb4991e, 0x73d3f32d, 0x67d92ec3, 0x2e04d3f0, + 0x443bcb74, 0x2b588d29, 0x7311c4a2, 0x1c03043c, diff --git a/src/soc/intel/broadwell/microcode/microcode-MF2306D2_FFFF0009.h b/src/soc/intel/broadwell/microcode/microcode-MF2306D2_FFFF0009.h new file mode 100644 index 0000000000..775a064453 --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode-MF2306D2_FFFF0009.h @@ -0,0 +1,1088 @@ + 0x00000001, 0xffff0009, 0x12192013, 0x000306d2, + 0x4218a30f, 0x00000001, 0x000000f2, 0x000043d0, + 0x00004400, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x000000a1, 0x00020001, 0xffff0009, + 0x00000000, 0x00001011, 0x20131219, 0x00001011, + 0x00000001, 0x000306d2, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x60dcadd9, 0xa4e450f7, 0xa10e9ad8, 0x056947aa, + 0x6c53d792, 0x100ed262, 0x0e01ba87, 0x72e1b0a2, + 0xe1d4113f, 0xc3085503, 0x1367060c, 0x9bf7efea, + 0x2b756eb6, 0x2ee07b69, 0x7cfd1dc4, 0x9811c8b2, + 0x86cf4036, 0x20534caf, 0x37046580, 0x432b4e6c, + 0x6a3a2e54, 0x88a74dfc, 0x81a503f6, 0x67736b51, + 0xbc2b11b7, 0xbcf3adc9, 0x96c8eefe, 0x688bcc49, + 0x16c4f996, 0xe0175cd2, 0x454d7a58, 0xa67afd13, + 0x098d9e42, 0xf86d2ec2, 0x738a67a6, 0x26c4ad17, + 0x08666776, 0x050d971d, 0x68998a7c, 0x21ac9cf9, + 0x29e27b61, 0xd61cfd7d, 0x3500ff83, 0xd4123687, + 0x27b72496, 0xe9b867f6, 0x62920d71, 0xe159dd34, + 0x3991c6ba, 0x367a5719, 0x7af5e9df, 0x5cb9fd11, + 0xf5988469, 0x4153f210, 0x24b194a9, 0x8c563988, + 0xac5bfd38, 0xd271e693, 0x16e9b292, 0x0c6583d0, + 0xd2501a4f, 0x9896af00, 0x6665aa9f, 0x0f3a8de9, + 0xc8f0db5f, 0x60b7a546, 0xe3a52963, 0x0ea3eb39, + 0x0d8c08ab, 0x2f5faa26, 0x1d3cbd56, 0xa8596256, + 0x00000011, 0x90cab116, 0x0e040e30, 0xd347b746, + 0x60a21d1a, 0xd6be9b2c, 0x4b45f3f8, 0x4c9f9895, + 0x71624dde, 0xc9c2d232, 0x2c3e4884, 0xd50de558, + 0xb2215b04, 0xea8e09bf, 0x51d7cfd4, 0xd288b7cd, + 0xc56200cd, 0x7b35c8b7, 0x7efb18fc, 0x8ccc42b7, + 0x308b55da, 0xc91a08b3, 0x7d122c6e, 0xbd62a0aa, + 0x65c1171c, 0xa485a771, 0x03a8f12c, 0xe90e07fa, + 0x55fdbf8a, 0x8e479b93, 0x3ed879ac, 0x17aa3978, + 0xcf82b042, 0x22bcb074, 0xaddb3933, 0x32fd00b1, + 0x347ab750, 0x6d2142fa, 0x046ae713, 0x2e2bfa45, + 0xb597e339, 0x70d86bc7, 0x6f0fd994, 0x57b225f6, + 0x12a0db1a, 0x475b29df, 0xa5a56fdc, 0x74da2980, + 0x901db0e3, 0xc574be49, 0xfb71d343, 0x1dad8d1b, + 0x82de7760, 0x92eb14aa, 0xe1b0f244, 0x73d4f475, + 0x4d8598a6, 0xea08353b, 0xe491af06, 0x4d0402e0, + 0xc5a719e7, 0x06ee0e61, 0xc300bdf8, 0xe929060f, + 0x422d6721, 0xdb2e2923, 0x849977e1, 0xb721f8d8, + 0x1489a38a, 0x4ea362e1, 0xb5544404, 0x29b7b6b5, + 0xb9467e1e, 0xb6a573ee, 0xa197f784, 0x3d8a563d, + 0x3021a920, 0x228d2a9d, 0x42ad7645, 0xa5a41a0e, + 0x64afa2b5, 0xaa7de848, 0xf8749a8f, 0xe0e93b95, + 0xc9033385, 0xac9abe32, 0x0511c7f5, 0x48ed3483, + 0x37cdcaa3, 0x44f857b7, 0x8f0d8931, 0x87531352, + 0x792265db, 0x978c9f15, 0x70d04944, 0xfcf1c5f5, + 0x2bf9391b, 0x944e902b, 0xe2ea9bcf, 0x5e8443cc, + 0x08d91892, 0x9cbfcc80, 0x49317133, 0xec45a8e3, + 0xa13f80d8, 0xaa718e22, 0x2ba22e08, 0x2ab3aece, + 0xe6e47fb9, 0x89a2a54a, 0xad5c63fc, 0xde5d1791, + 0x95c2f6cc, 0x651f0b35, 0x2d3712c0, 0x37a3b34e, + 0x366c5ff7, 0xff2f1373, 0x73fd3f21, 0x883dcc99, + 0x723a5552, 0x82ad9770, 0xb962ad18, 0x99e02541, + 0x38dbfbaa, 0xe8ac0a04, 0xc8de2eb3, 0x8b3526b6, + 0x860ee4d6, 0x18d5abbf, 0x44ab0a68, 0x17b2491c, + 0x16745351, 0x01219370, 0x441c7a6f, 0x5abed659, + 0x1de122cf, 0x9272e352, 0x0d41ec76, 0x1a814149, + 0xb77e6086, 0xdbca84ee, 0x3836808f, 0x0013eeed, + 0xe6a8fa02, 0x4967bf1c, 0x9aa60708, 0xbffb9bdb, + 0x0f9a1e2a, 0xb6ad6fd5, 0xf80e5a06, 0xc5c02e14, + 0xa97f7853, 0xd1313de0, 0xce6d086e, 0x2b84fd27, + 0xcf946267, 0x2592a173, 0x31461442, 0x9f916969, + 0x0a82297a, 0x2662bfb3, 0xdea00742, 0xdc7dc6f3, + 0xa4169ea3, 0x18367c67, 0x5b32a88b, 0xa5c49b29, + 0x1dc6d4c2, 0xc7bbb15d, 0x763efa0f, 0x86bcb021, + 0xe342da14, 0xc1f524e6, 0x3fb25d07, 0xc95facb5, + 0xbac2e017, 0xb46425e4, 0x0e4ed37c, 0x3e2e0643, + 0x0e4923d5, 0x0808d43d, 0xb8290fed, 0x9c13b38f, + 0x5af54b12, 0xe52c28f9, 0x4f0e7520, 0x31d23033, + 0x7ffd77d6, 0x3fd6a6ec, 0xa240c9f6, 0xc0d2e7d0, + 0xf21322f5, 0x9a11ce94, 0x0dea1e5d, 0x54195ec4, + 0x131902ed, 0xbe9d2fac, 0x6e2fe66c, 0x77ba266c, + 0x60fff3c1, 0x26423e88, 0xa1113c26, 0x04e4b990, + 0x6f377b8e, 0x19ad39c3, 0x48e73dfd, 0x70224deb, + 0xb58c15f5, 0x2dd6ab84, 0xa341d89d, 0x94a1f39f, + 0xdcdc46d6, 0x2bd6ec0e, 0x54c549a3, 0x9050b2ba, + 0x2eb0dbe7, 0xace8bf18, 0xdf56ecf4, 0x8893fc94, + 0x6432e94f, 0x35376b1d, 0x134c4258, 0xe94bfed0, + 0x14d3b85c, 0x57bbb532, 0x1e9684db, 0x9807ea4f, + 0xc6b43292, 0xd7f59cae, 0xfb5883cf, 0x725ba2cb, + 0xc6f02596, 0x538a8e81, 0xa5136f90, 0x497459c4, + 0xba645c2e, 0x23218d30, 0xb775bc86, 0xd0e34625, + 0xfd1065ae, 0x3f0bbb0f, 0x6004224b, 0xf6a6ae86, + 0x37dea01c, 0x9a368723, 0xda4a7a86, 0x6f7582f8, + 0xd528c630, 0xd74842c0, 0xae825db4, 0x41426f8e, + 0x60cd01a9, 0xf0982f32, 0xa8d0f194, 0xfd1a2924, + 0x85297030, 0x993747a1, 0x5900e9a4, 0xb806c570, + 0x6665a0e7, 0x5c5c606c, 0xa482052e, 0x3586ceb7, + 0xbe34a09a, 0x6d58da9c, 0x9c16214a, 0x77ca2413, + 0xeff1c03d, 0x26bdb02b, 0x7e92c547, 0x7d1c9ccc, + 0x901781bf, 0xe06ca3ec, 0x0068f014, 0x4f037a36, + 0x66f1e220, 0xe932bbc7, 0x35f71129, 0x491299d5, + 0x96dd255d, 0x56140c48, 0xb9d9e9d8, 0x5887b654, + 0xb4f00c09, 0xcac8a128, 0x08061536, 0x156d0a53, + 0x58fd722c, 0xf8ccae65, 0x4c423ed6, 0x5085dcb6, + 0x8d0a4c58, 0x5118e592, 0x720d0e07, 0x32695cf4, + 0xf47583cc, 0xf5a360b9, 0xec68c6b3, 0xdb0b23bd, + 0x63dd835b, 0xb46e45d6, 0xa26e3679, 0x882d0205, + 0xfd1e47a4, 0x5e8f4fe2, 0x2394c20a, 0x5bce06ce, + 0xe0652d89, 0x1638aa4a, 0x5863895f, 0xdb7e13df, + 0x0baeb5c0, 0xb28bb54d, 0xdaacd6e9, 0xf90ac314, + 0x6add6021, 0xed119aac, 0xdc6d04a1, 0x471ead10, + 0x962c88c9, 0xfdc72b61, 0x0e22af57, 0x146a42c3, + 0x34822bae, 0xd83b4b11, 0x1c3a2415, 0x0e0727a2, + 0x566e88a3, 0x4b47cf5e, 0x853639c7, 0x215b716c, + 0xee2e2600, 0xaf2f7ba8, 0x090ff22c, 0x34392116, + 0xa6b296ac, 0x55e79700, 0x35246cf5, 0x086ddb6b, + 0xc01e8683, 0xf6e013f0, 0xe792446b, 0x86ff93eb, + 0x05aa2844, 0xaebc8787, 0x1593f6d0, 0x604b0cea, + 0x69b5616f, 0xdda86324, 0x7ba648ca, 0xf33a5c5f, + 0xa0aef658, 0x1bc7f6c2, 0xb2ce4a17, 0xc83e3e90, + 0x1d3471ab, 0xaa361ce2, 0x33f2fca3, 0x0105f18f, + 0xc27017fd, 0xf3416a6a, 0xfa21e77d, 0x6a889e68, + 0xb31c3c49, 0x532f9608, 0x78a9b0f4, 0xf7a0720e, + 0x1d387e41, 0x882da2d0, 0x400753f4, 0x9343c148, + 0xda9f747c, 0x9b988343, 0x69ece870, 0x8e45b698, + 0xa1e885bb, 0xb1d2f776, 0x8bdf9fbc, 0x988675b8, + 0x6c3800df, 0xedfe4ea2, 0xed70c58e, 0x129307cf, + 0xdcbdde56, 0x7d603fa3, 0xc1ddaf53, 0xf566a221, + 0x611af0b7, 0x491709a6, 0xf6796c46, 0x03c2dd09, + 0x20086a5d, 0xa56d3c4e, 0x21838c3e, 0x741bf887, + 0xc47d1e10, 0x197d7b3f, 0x19abae48, 0x8abffda8, + 0x94435b72, 0xa11b897a, 0x6ec815ac, 0x4c6b3739, + 0x0f4d4593, 0x0dc528b1, 0x9ea4eafc, 0xe3af5be4, + 0xa09856b0, 0x4bb60468, 0x34fce4fb, 0x34cd957d, + 0x20cdc911, 0x7f9fe9df, 0xe2391995, 0x1a2321d7, + 0xa34c246b, 0x79a899ee, 0xd52abee4, 0x9a846264, + 0xc0b4fbf4, 0x3a632892, 0x9c27c222, 0x1420cf14, + 0x9cf93d04, 0x86fb1630, 0x968387c7, 0x0d112814, + 0x43aece1a, 0xef85dc1a, 0x203a9857, 0xd1003708, + 0xb39d7773, 0x7e5779f1, 0x508b45d4, 0xa405466b, + 0xe57343c6, 0x940fac2a, 0xb7a50d24, 0xe0fab30c, + 0x3576bb69, 0x1aaf0431, 0x2d15232e, 0x303fdc31, + 0xe13f2053, 0xfb33e941, 0x4e2b238b, 0xd4ec4f24, + 0xe63f9c36, 0x6e4f9a38, 0x540def86, 0x06266f87, + 0xce6b1e32, 0x8e0b9478, 0x26b2d339, 0x9ff9b40b, + 0x204575b8, 0x946a0473, 0xb78a9ebe, 0x3a5309dd, + 0x9f0eb17c, 0x1a064211, 0x85f47105, 0x0cb89d9f, + 0xebd7b379, 0xd5c975a8, 0x9d52f464, 0x592a5bf4, + 0x6f501956, 0x77578fdb, 0xa0e62c23, 0x6e3dd1e3, + 0xc8774186, 0xe053f68f, 0xece83dc5, 0xc38d39f9, + 0x18f92077, 0x343d3efb, 0xb35d2c11, 0xdb5cde6b, + 0xdfcaf3ec, 0x218e1dc5, 0x686ca7be, 0x97b191be, + 0xea2008e9, 0x32c1fefc, 0x0cffe063, 0xf7bb6146, + 0x08b326e0, 0x2357455d, 0xa0dbebfe, 0x3cdb6cd3, + 0x1e9f5ef6, 0xc51c7891, 0xd8d1fad7, 0x990bc89e, + 0x273ec572, 0xfca8183a, 0x43bcca27, 0x99d670f9, + 0x4eaea6f1, 0x927e1c1d, 0x0ae4b5ab, 0x346b589e, + 0x0bf98ede, 0x47941bd5, 0x5da1b808, 0x7aadcba5, + 0x17123c86, 0x3d58244b, 0xfecdb4ab, 0xe9c9f379, + 0xf6ed0fde, 0x48ce0701, 0x15031801, 0x6dc08d12, + 0xe2b0fefd, 0xfa919920, 0x2be7b549, 0xa0690325, + 0xf4423306, 0x0291c221, 0x99e3f0f4, 0x2a0213b7, + 0x652b0769, 0x461e57c6, 0x9cf49672, 0x1b8bc086, + 0x88c7410c, 0x85129bf0, 0x536ae506, 0x60ff4af5, + 0x134acbe9, 0x413c6069, 0xf12375e2, 0xcdfcc5a9, + 0x36969c82, 0xd77fb84a, 0x3b1cc035, 0x6449616f, + 0x9c350286, 0x4570139a, 0xe54e3afd, 0x52675e36, + 0x4d53c27e, 0x9744c74e, 0xaa66ba08, 0x1f5d449d, + 0xae4153cd, 0x6d096a28, 0xe6bdb07c, 0xd0e87cdd, + 0xad5ac1d1, 0xcd7153c8, 0xb313634b, 0xfa507906, + 0xefd74671, 0xcbd126ea, 0x51418e17, 0x43ec6973, + 0x4c28d874, 0xce7c2fb7, 0x59627e9b, 0x0d71d899, + 0x1679ce3a, 0xe7578b23, 0x7b5c43e4, 0xe93d2313, + 0x0b09b9f4, 0x62e26321, 0xc08da4ad, 0xd03e459f, + 0xc705d09a, 0xfabd5d2b, 0xd817fcb4, 0xc61fbe8c, + 0xa216cbc0, 0xa844f721, 0xb1c44147, 0x383a2589, + 0x1c26ed0a, 0x66e837ab, 0xf2c158ac, 0x91ab35a5, + 0x4ac10d6e, 0xce73a342, 0x8ab5e6a7, 0xdd4e6278, + 0x37ae66b3, 0x3c21ffd7, 0x575d7013, 0x68c5ed99, + 0xa4bb530f, 0x9c233812, 0xda6817c5, 0x3eda3a7e, + 0x02e81b6f, 0x57b8b9eb, 0x6b3f1bad, 0xc267a085, + 0x7f9ece08, 0x9b72eb5a, 0x25861ce3, 0x7821c4b9, + 0x87fd9a93, 0x80683eb8, 0xd203432a, 0x9281544f, + 0x9385bd78, 0x7c75f0ee, 0x20a72d75, 0xfe9b3d5d, + 0x0309006c, 0x7c295280, 0xf91efe20, 0xc1f9db0c, + 0x7873af11, 0x816dd3e1, 0xc750c0d3, 0xc038fb60, + 0x4934e055, 0x660fc920, 0x8611b0c0, 0x5fcdb814, + 0x8c8eb7c5, 0x769da935, 0x08138d4f, 0x5b4fae17, + 0x6991be76, 0xfef63442, 0xef554565, 0x119ac2a4, + 0x7237898b, 0xbbfddec5, 0x396b9e2c, 0x7cd52890, + 0xdcec9de6, 0x83c47ede, 0x34a05845, 0x0c210e8a, + 0x65810421, 0x63eade0b, 0x0ba1c957, 0xbec6d006, + 0xc36e7402, 0x2784fa19, 0x7a3e246a, 0xcf110e8b, + 0xc3f4dd61, 0xe9a8d6ec, 0xfb63b0ce, 0x7cc2e35d, + 0x6d8b1883, 0x14369707, 0xd6c37e16, 0xb634047d, + 0x25c02b3d, 0x7ddc3504, 0x5aad3917, 0x663f641a, + 0x399cb455, 0x54becc41, 0x23c2b715, 0xe039d8fb, + 0x51e80309, 0xf20f1460, 0x6bde63bf, 0x8064aadc, + 0xc4037a27, 0x60ece5f5, 0x0b6b72bd, 0x3b804ca9, + 0x1b908ced, 0x6fba1773, 0xe415203c, 0xd9823431, + 0x446ea0e9, 0xe7d21771, 0x903d3805, 0x3f512124, + 0x19414ce9, 0xabd95d7d, 0x2363ff6d, 0xba47b061, + 0x4382c277, 0x63b01743, 0xbec54415, 0xdd06dd91, + 0x7ce565fb, 0x8660d02b, 0xf13e4e5c, 0x71241c8d, + 0x505f298d, 0x42d4a434, 0x1bb5254f, 0xb4502dfa, + 0xf76a59ca, 0x6185caef, 0xddd5b940, 0x13577870, + 0xd79c5b38, 0x814245f5, 0x14beb2d0, 0x28ce5345, + 0x439b8dfb, 0xcb4e9b67, 0x0441d3d8, 0xcc0640c7, + 0x4d868505, 0xda87621c, 0xe4795039, 0xd586c8ea, + 0x8308073a, 0x78559ce3, 0xc4f93658, 0xe8df85ba, + 0x9aed2c23, 0x1ef7c4b3, 0x4613829c, 0x0bfe4683, + 0x1b7a1f2a, 0xd85f2584, 0x74fae5a6, 0x7d64660c, + 0xf1d6cdc0, 0x1db730d3, 0x03650f53, 0x4809a85e, + 0xd5c41303, 0x2239e054, 0xf1a6de34, 0x53e4a8d5, + 0x28b166e9, 0x40dae4a1, 0x5e6cdb6f, 0x924b3867, + 0x48188d16, 0x4855da97, 0xef986afc, 0xf65f1c49, + 0x7914b1f3, 0x10c182b8, 0xdadc1cee, 0x0e7422e3, + 0xfc308219, 0x67098cc9, 0x5380b7ed, 0x65f7d3a6, + 0x711e0657, 0x59e7cabf, 0xb1c47735, 0xf7e0034a, + 0xab62300c, 0x2f636eaf, 0x746ac675, 0xcb7b4bda, + 0x01f117cd, 0x8af07a1e, 0x39616883, 0x22a8e329, + 0x80fa99e5, 0xfc48b995, 0x9c43516e, 0x40411674, + 0x52647c1e, 0x29659ea1, 0x5f8b6429, 0x8ad95229, + 0x5a77c499, 0x3fe94266, 0xe21d84cb, 0x15140834, + 0xeb6e862a, 0xf93cfeb8, 0xd1435c17, 0x2ed2d4d6, + 0xe94b371f, 0x1dfa1a35, 0xf8eefd0c, 0xfc502190, + 0x3022d1e7, 0x8e98dc70, 0xb3941c72, 0x48ce162e, + 0x04def7d2, 0x05505c46, 0xce8253fd, 0x727f4df1, + 0x5cf5d8a0, 0x125b5812, 0x1b1b715e, 0xaa322065, + 0x846ed704, 0x86f73cf7, 0xbe585d0c, 0xac05cff0, + 0xe6762d2a, 0xd6409b1f, 0xfeadc485, 0x14eeca23, + 0xf75ed62e, 0xc4c19528, 0x16b1ee8f, 0x34137e4c, + 0xeaa695c2, 0x5a2c7542, 0x40f886f9, 0x6e901f70, + 0x59265bf3, 0x54dbf006, 0x98ebf58e, 0x0d88e5e8, + 0x95b34bf2, 0xb3375ead, 0x027495a2, 0xceebe58d, + 0xf9351f6f, 0x97f088fa, 0x86ce4b3b, 0xad4c488a, + 0x2134e0f6, 0xc61fd37c, 0x47e6b2d5, 0x55d2a66c, + 0x57471792, 0x5cc3af34, 0x69cb3eb2, 0xd3f4e2cc, + 0x371d07e5, 0xe72a5df5, 0x6ae73a0e, 0x82d06141, + 0x50d338d6, 0xb097808e, 0xa928f699, 0xce757e78, + 0x2371b850, 0x5c54c120, 0x94cee629, 0xb67686a3, + 0x09ad4704, 0xf0a155b7, 0xcc179b36, 0xa6aeced0, + 0xb3f51661, 0x9cbcd13f, 0x94e8c76e, 0x024361f6, + 0xcd887436, 0x2bf4d7a1, 0xf7c17b37, 0x133e8eeb, + 0x3ea6a45f, 0x520d492e, 0x742d90e8, 0x2ce299fd, + 0xd0a875d5, 0x0a5a57f2, 0xcaae21e5, 0x9086856d, + 0x8ac23fa2, 0xe7b4d462, 0x4999f32d, 0x60274da4, + 0x6a5ee783, 0xca34744a, 0x7f64c6ee, 0xf699a281, + 0x5ece3f79, 0xe7afc768, 0x7836a20a, 0x390502fe, + 0xaf39bfe1, 0x5f8c0721, 0x0f5aac11, 0xd3052ccc, + 0xba7c23aa, 0x6da80adf, 0xf4634e0e, 0x2663505d, + 0x117d649c, 0x5fc39b44, 0x1ec1cc7f, 0x0e666e4e, + 0xd3279646, 0x32862aca, 0x90ce9078, 0x9b18c91f, + 0xba531b12, 0x73f42de1, 0x5a374359, 0x3aa5989b, + 0xad23fc0f, 0xcde1c203, 0x2389c404, 0xf1d6b5c4, + 0x86cb6fba, 0x2ae50b83, 0x30aacd67, 0x20b657df, + 0xbb25fdb7, 0x04b5c269, 0xaea481af, 0xe89b2fae, + 0x2ca04b4b, 0xe6b53b3c, 0x55ac73f1, 0xceceba11, + 0x3b317b02, 0xf920f5c7, 0x2112e25f, 0x9f1399a5, + 0x3b5aed97, 0x82fa3db6, 0x32da32ce, 0x61aa356c, + 0xd9eef8a3, 0x5ad1a4a8, 0xbb0cc345, 0x7f25edea, + 0xd9ae7b9b, 0x22575550, 0xd3ef4ba6, 0xb9ade338, + 0x942e2317, 0x2f5e3e65, 0x6e6dd63d, 0xc7837067, + 0xba1be094, 0xc07d82eb, 0x3b241ff9, 0x92844bbe, + 0xeea2e10f, 0x2a194f95, 0x133ba864, 0xdf698784, + 0x7e632e2f, 0x99d5dcb9, 0xfa78c04f, 0x2d02fbce, + 0xb7597402, 0xe60a3216, 0x0f213875, 0xcb448cd9, + 0xcc024c70, 0xa47a7983, 0x6fcef001, 0x34a50c04, + 0x0b5a4a5b, 0xd36e43f6, 0xc86c5f31, 0x3add4a92, + 0x7f046e63, 0x7456031d, 0x4cac381b, 0x23bc33be, + 0xfa562030, 0x86b4ac9a, 0x80f47e71, 0x83d06b96, + 0x56eb1b14, 0xc4dc487c, 0x7fd6b538, 0x17173b7b, + 0x9c4586c3, 0x691b85b8, 0x7ff336c8, 0xc5b6593e, + 0x3f6ccc20, 0xbf268878, 0xcaff2726, 0x122aee01, + 0xe43c6e44, 0xb72b3568, 0x4e1697fa, 0xe51dad88, + 0xd5eec231, 0x7fe6b74e, 0x7e4cb0dd, 0x924a4b42, + 0x35745453, 0xe39021dc, 0xe961be10, 0x41b255b5, + 0x40921705, 0xb979c943, 0xeb9c766d, 0xa6d1e044, + 0xceec56a6, 0x073f7166, 0x66ef10bd, 0x820bab05, + 0xf8cfdd84, 0x3ac5a605, 0x8f0e8aff, 0x7f289d22, + 0x72aafac8, 0x607e9d8c, 0x7a204ee4, 0x7d69e188, + 0xb733f89f, 0x216c50a1, 0x1775d87f, 0x92cb5854, + 0x16726cb0, 0xaada1cdc, 0xceab8da0, 0x5ac08515, + 0x7222d621, 0x2d3bf547, 0xb2a46d39, 0x0a55e404, + 0xd0f96092, 0x0a43bbfd, 0x779d431b, 0xd609119d, + 0xe697cc29, 0xc4e32548, 0x113046c7, 0x92d36739, + 0x949850b4, 0xcca28eff, 0x9b782d07, 0xf1fb4163, + 0x7658cd91, 0x3c8bf795, 0xffe6a68e, 0x75bc1e62, + 0xcdc63834, 0xd1c34186, 0xb579135b, 0xc7eb7d2d, + 0xd3452086, 0x679e302d, 0x0747bee7, 0x25318574, + 0x758eefe7, 0x12a3b686, 0x2a2c7026, 0x53957f5b, + 0xa68abe52, 0x2f4b07be, 0xec811b09, 0x28784687, + 0x475bde35, 0xf4a568a2, 0xa18bdf37, 0x885986b3, + 0x99b2a57a, 0x2733dfed, 0x1d4f2eca, 0x7709ed9f, + 0x0871af03, 0x44bdf6df, 0x39f9442f, 0x845c147c, + 0x729d2f05, 0x18338f18, 0xccb3c963, 0xfc7ad8aa, + 0x99a2f4fc, 0x8623ad7a, 0xfbf465d8, 0x35d1c38a, + 0xb4f128a3, 0xd42f5685, 0xcbed5c09, 0xf0025603, + 0x3777cd54, 0x7b420f01, 0x8f6b58bd, 0xfa0aef03, + 0x8afa1826, 0x48de3c1c, 0x2bc4310f, 0x95253743, + 0x11b55236, 0xd54775a9, 0xde3fff8b, 0x6b3f5bc7, + 0x06dc676e, 0x7b8f3f71, 0x50375e23, 0x1c17605e, + 0x480e3072, 0x10d2dbff, 0x7f64178e, 0xb4655d95, + 0x89f6a71c, 0x055850f5, 0xf131342d, 0x4019b083, + 0x35f83286, 0x3f2802d6, 0x1ccad590, 0x8d30bbc9, + 0x0db48257, 0x623f5161, 0x4f0a481b, 0xaa474fdb, + 0x56c1009d, 0x53465fb2, 0x4f924a49, 0xfd639965, + 0x532fa28e, 0x54cd2cc2, 0x61288c49, 0x8a2bcce3, + 0xa5675c7b, 0xe12a3be0, 0x08e66dbc, 0x8b7414c2, + 0x635888d4, 0xa263d533, 0x50db6461, 0xf8199d4e, + 0xb8f1667f, 0xed571290, 0x9f1d222c, 0xd9add4b7, + 0x66037020, 0xfa0d25ac, 0x7cd3c0d0, 0xce280271, + 0x1932ba92, 0xd6be5076, 0xd7b3d11d, 0xf1fb5981, + 0xd8c6a441, 0x58cdff75, 0x808a2b55, 0x6d973a34, + 0x319de89c, 0x27769381, 0x056768af, 0xf878d036, + 0x9f63efb1, 0x6135e150, 0xba675883, 0x81042913, + 0x2550419d, 0xddbe61d5, 0xc81a8da9, 0xe9089ba7, + 0xa5dd3918, 0xdab05623, 0xac841d16, 0x7a864bdf, + 0x46ae5d33, 0x3180fbd3, 0x8e230a5b, 0x1f8d9fa7, + 0xc174d6cd, 0xd0522dfa, 0xed499bae, 0x9fe63278, + 0x813ab3fc, 0xdc3e2d0a, 0x0ed5951d, 0xf51ee2d4, + 0x592c2bca, 0xad780575, 0xb86b8caa, 0xb4ab113a, + 0x890b756b, 0xdfb71bbd, 0x47ac5f8b, 0x0f68e078, + 0xc112fc4f, 0xe0e409d4, 0x4a5cc89c, 0x1bf61256, + 0x49ce9b62, 0x18e47e44, 0x6e01609a, 0x916190f8, + 0x8e1d1bbb, 0xbdaec593, 0x6d5114e1, 0xaf91d407, + 0x062cc782, 0x957dbe4b, 0x4de1f42b, 0x318afaa9, + 0x2f1067ad, 0x6687998f, 0xe7f887b5, 0xe9cbc3ea, + 0xcd552a52, 0x45fcaacb, 0x1f4a1e4e, 0xa87e4274, + 0xb418aa40, 0xdf7f30cc, 0x5a044a5b, 0xf797bc5d, + 0xe8ba9054, 0x261f08c3, 0xf611337e, 0x9a30fd97, + 0x29e9daab, 0x59113c28, 0xe79046ed, 0xc6175e4b, + 0x11db74ea, 0xa671fd1c, 0x7bd62061, 0xd5b5d377, + 0x4b900be9, 0x5e5226ac, 0xf3b663a3, 0x3166e685, + 0x097259d4, 0x482a03e5, 0x401fdd84, 0x8cd79939, + 0x4b18a6bb, 0xa7f79818, 0x04d794a9, 0x6e9ba6c5, + 0xd53f0063, 0x18265a15, 0x978b673b, 0xdca20ad1, + 0xf8909d73, 0xc3215238, 0x93fdabd3, 0x715d53bb, + 0x0f26a37a, 0xc9eb821d, 0xf27257d7, 0x0bcd73d3, + 0xa1fcf2d2, 0x4ab25bf8, 0x1167cddb, 0x202c00a7, + 0x697afe18, 0x4bdf8fdd, 0x7532710e, 0x9829abb2, + 0xa24ebb8a, 0x56f66505, 0x6e91067f, 0xf31f7c76, + 0x87aa0191, 0x501fe66a, 0x640a3180, 0xefa32181, + 0xaaea0e03, 0x47aa7a2d, 0x1cc55c2a, 0x154ccb03, + 0xf6f717a3, 0x2aea78ad, 0xf4d6132b, 0xc78a6acf, + 0x123cdf52, 0xff4bf2e7, 0xda02924d, 0xfe03ab9b, + 0x755b6f25, 0x9d4a5428, 0x38e816ef, 0xac958ddd, + 0xf688caf4, 0xd565bd38, 0x0a2f534f, 0x3af3dc2e, + 0xe6b9af6d, 0x67d5e6ba, 0x3e322b23, 0x6d65d663, + 0x558ebe4c, 0x7fc567a5, 0x2aa6b0cb, 0xdb23312c, + 0x95ef5f3e, 0x79419a81, 0x8150fef9, 0xd453b954, + 0x661e23b0, 0xde16a0b7, 0xa007dc74, 0x9a9c28e9, + 0xde5becbd, 0x5f34bb32, 0x1852ea78, 0xc7312271, + 0x3da2a26c, 0x36b6f593, 0xac766916, 0x37c63eb6, + 0x972c3928, 0x4453ba46, 0xfda8992d, 0x059b3982, + 0x846a03a1, 0x639648c8, 0x0b655eba, 0x77c9d10d, + 0xe2d5adc8, 0x2f76cd22, 0xcb817adf, 0x20b42438, + 0x72340883, 0x02494a75, 0x2dab7976, 0x00cbc5af, + 0xfe356cd2, 0xbde2c706, 0xbf6321bc, 0x330a9fc4, + 0x0d9c78ee, 0xc8134ad8, 0xb6d331e9, 0xfa6d61a8, + 0xfcb3f05a, 0x6f728e48, 0xa051cd9a, 0x6a47dc1b, + 0x62d967b9, 0x06447515, 0xde7feee7, 0xd2306a03, + 0x71ddf8da, 0xa20fb50f, 0x1f233990, 0x3b8c7328, + 0x7e6b3149, 0xa0927d88, 0x316eeef3, 0x73532916, + 0xc1a2c9eb, 0x0b84f1f6, 0xe5d42a13, 0x9235e6f7, + 0xb5c53568, 0x77e7fc23, 0x87133210, 0xa50378d6, + 0xa6c761ec, 0x0ed2ad00, 0x5048961f, 0x69352031, + 0x274d9f59, 0x900cecf3, 0x15b846d1, 0x6f41240f, + 0xb0bac716, 0xfd913172, 0xa9ee7733, 0x415ca79d, + 0xc7adb3a7, 0x1b21b7f1, 0x46f97f7d, 0xcb666a59, + 0x45c1e930, 0xe178cfed, 0xb0a4e287, 0xd4565967, + 0xd5e1b84c, 0x35f2ccc8, 0x69576869, 0xb5ed3da9, + 0x69e48e1e, 0x00c070ce, 0x22c1ed82, 0x3b0302be, + 0x58fca488, 0x5b027e58, 0xdea55117, 0xe1b14089, + 0x5a5e34a1, 0x604059bb, 0xb67bbc68, 0xa2ee3188, + 0x5339bf75, 0x44eeaee9, 0x130297fb, 0x0ac960a2, + 0x1dbe6756, 0xa0b6afe7, 0x89f4a68a, 0xd9761d47, + 0x0313bf98, 0x8c2a9a4e, 0x5335bd7f, 0xec1f7210, + 0xb899b3c2, 0x8c76f63f, 0x324b1123, 0xc79cc31d, + 0x70defa52, 0x1f9d068f, 0xfe68684f, 0xfc34f99a, + 0x497e2ba9, 0xafde1a2e, 0xd3e5efc9, 0x7a767f96, + 0x4854cff5, 0x86d26e2a, 0x756d3858, 0x4b138d76, + 0x8ebf96d1, 0x504b2cfd, 0x2b342daa, 0x3bce0fcd, + 0x4c1329bc, 0xaaa0b662, 0xd826add9, 0xba2294ca, + 0x328f227c, 0x8b11dc5c, 0x641069b8, 0x85d2f558, + 0x8db40b5b, 0x22ba2372, 0xdcde53c5, 0x79406548, + 0xda717c22, 0x3edcdbbb, 0xd3bf588c, 0x4d21dc09, + 0xbfbe0835, 0x445d79c2, 0x9186154b, 0xd8757931, + 0x6cc2fda5, 0xee5bec7a, 0xa406a703, 0x1f382345, + 0xeda58f77, 0x138a5396, 0x8f330eeb, 0x8c0bfe6d, + 0x406170fa, 0x1a26c83e, 0x89da729d, 0xc0a36a93, + 0xab107add, 0x895b0dba, 0x44c72fdf, 0xafb497f2, + 0x07e595dd, 0x82f10ac6, 0x05533816, 0xa508c8e4, + 0x06967120, 0x843fc145, 0x088a9254, 0xc9fa8c99, + 0xf8c9e485, 0x10166a50, 0x93098cbf, 0x8bd33259, + 0xbfe45bbf, 0x4593eada, 0x4ded8aeb, 0x8da9b4fc, + 0x6500a2c5, 0xcb0ed4a3, 0x9b875b07, 0xbbf626f9, + 0x65f9a0e8, 0x95bee21e, 0xadc6f514, 0x2530164a, + 0x6a3cc255, 0x8dc4e14d, 0x8e600ee4, 0xc7c2edfd, + 0x2c00aed0, 0x902a3b97, 0x39069f67, 0xc1d66342, + 0x935a7012, 0xdb4bdae1, 0xfd5e6d06, 0x5474664b, + 0xe7051ffd, 0xbee1e0bd, 0x5acf1aaa, 0x3a6a5f92, + 0x9130e4fe, 0xe9ee424c, 0x4a475aea, 0xff851640, + 0x69c24a9c, 0x4a055b88, 0x24d7028e, 0xb8f5a11b, + 0x7b451dce, 0x36b90efa, 0x0816c853, 0x36247966, + 0x457b7fb4, 0x082dda9a, 0x6e515ab8, 0x09784a04, + 0x279e3e51, 0xebce6723, 0xc3f87fae, 0xd22884e6, + 0xcc61399e, 0x36e7194c, 0xfc9035e0, 0xd0d0cf09, + 0xe538fe52, 0xfcf309b3, 0x24e7cc29, 0x7dfeb54f, + 0x7bb9c289, 0x5b5ace34, 0xbc048587, 0x181c6ba7, + 0x68a21ec9, 0x067922d2, 0x256d6392, 0x96c3ce60, + 0x7beaccaf, 0x11635cd2, 0xe9f2e8c7, 0x864eb506, + 0xdbc5369d, 0x98201a87, 0x81805dfb, 0xcdb68451, + 0x4bde831c, 0x52c9a44e, 0xccb7ebc8, 0xdd04cf8a, + 0xff631388, 0xc6b4a68b, 0x5b9e8643, 0x0b783754, + 0x330e86c1, 0xa3146d54, 0x23129703, 0xe0f462dc, + 0xa0e27e2d, 0x03b413f8, 0x97aeb991, 0xd93f60c9, + 0xe6816707, 0xf9f7623b, 0xf6737142, 0x9546adbb, + 0xd701e5f6, 0x6df8ddeb, 0xcda63487, 0x0663f283, + 0x921a49f8, 0x298d6b62, 0xe6d0c061, 0xf9a351c9, + 0x21fc5a29, 0xf80360e9, 0xfa40159e, 0x68a67bc5, + 0x16b26133, 0x672d361f, 0x31a15e46, 0x0b2e2ead, + 0x2a7982a9, 0x5350d494, 0x0bbb2836, 0x8eb00983, + 0x4efb127e, 0xabc5254f, 0x5830b321, 0xc36b67eb, + 0x3be1629a, 0x9fa8974a, 0xfeb63ab4, 0x19224f6f, + 0xc7ff35c4, 0xc9f50be0, 0x7b352263, 0x632d81b4, + 0x23cc9877, 0xa1d20d50, 0xa1bb25fa, 0x68739501, + 0x09a740f7, 0x5c99f10b, 0x927e7d8b, 0xaaa48590, + 0xf8c85d0e, 0xb78afbf3, 0xc7e64477, 0xc1744f7f, + 0xdd94991e, 0x0c8fc3cf, 0x8d8ed675, 0xbe527132, + 0x427a946e, 0x1378322d, 0x549df0bd, 0xba2258a0, + 0xf6b5391b, 0x75c73dc7, 0xb50023c0, 0xa9ee16fb, + 0x9f1fdf02, 0x5db168c0, 0x866c520e, 0xab4137da, + 0x05615ade, 0xea30a15f, 0x709f68eb, 0xd24862c0, + 0x5af24b5c, 0x5a4b0579, 0x1c44e1ea, 0xe66bddb7, + 0x08b0c7f7, 0x201c61c7, 0xc2aff628, 0x93763863, + 0x921586f2, 0x3130137c, 0x46b381f2, 0x7d1bc7eb, + 0xbebde217, 0x42af3319, 0xf2ced318, 0x52cee723, + 0x63586e1b, 0xfcbdc19a, 0xb2505e9b, 0xabbc98ce, + 0x7e706262, 0x40a52361, 0x98ff4565, 0x30dbe4db, + 0xa4743710, 0xc5275397, 0x4d39c879, 0x5c68fa8d, + 0x02a4fb6d, 0x765c1aba, 0x228e3b92, 0xd04752e8, + 0xa95e7e69, 0xbf760bbe, 0x3eb46677, 0xa601e376, + 0x72ddfdcd, 0xd7a4a683, 0x97dbb641, 0x86a7e27e, + 0x942cfe36, 0x4088cf58, 0xa7d3f1c5, 0x0d97794c, + 0xcfa57b9d, 0x8894c96f, 0x79562a3c, 0xbd2eafe3, + 0xe07ad19d, 0x0136fdfa, 0x4d5cf83f, 0x522dfcb1, + 0xe4ef93cb, 0x4fc31ac5, 0x67676d1c, 0x7d2e3bb3, + 0xf3d89c14, 0xf09d83d6, 0x01fb8b26, 0xf8062cfa, + 0x0b3d9aad, 0xbe5702a4, 0xee1d769c, 0x12b573ac, + 0xc4a7a43c, 0xe19b7d65, 0x09fc15f8, 0x688556e6, + 0x67f3ff37, 0x46860995, 0xca2ad83c, 0xe0413f37, + 0x7cbc74f0, 0x3f1395fd, 0xfb4f1db9, 0xde029a4d, + 0x3ae29aad, 0x770623c8, 0xf7f367dc, 0xc08a2a66, + 0xaf8f8d83, 0xbd247a9d, 0x977a00bc, 0x483d13ec, + 0xe53cdb66, 0xf6ed2acf, 0xb38826b7, 0xcde53a2e, + 0xf1936f7e, 0xeaf64b9f, 0x590390a8, 0xdedf8298, + 0x187173f6, 0x079ba901, 0xce905c53, 0xe3b7bdf1, + 0xf4bc2b1d, 0x92670795, 0x9ffe5e01, 0xde676ad9, + 0x11b031ab, 0x8b36b068, 0xbc50c114, 0x2292479d, + 0x48e5c480, 0x731b1223, 0xa9bf2216, 0x0caea825, + 0x13be48ba, 0xfb00d6ab, 0x130ea973, 0x44110a8b, + 0x8de72774, 0x98996fc5, 0xdaf7e6c4, 0x4feaff06, + 0x4db97c3f, 0x5b025a0b, 0xe2e49643, 0xc0f2e737, + 0x91a75aa2, 0x003d9592, 0x94a01495, 0xc33c69ed, + 0xc562cf5f, 0x6c743acc, 0x111e592f, 0x842b7050, + 0xb1297d34, 0xd44d4b80, 0x7350b0c8, 0x59c39193, + 0x68b31697, 0x6495fdff, 0xaafa67d1, 0xcd1f5f46, + 0xf5bb17d1, 0x78b7e743, 0x6931f3d1, 0x87b90ecb, + 0x8c7aa961, 0x398b83c9, 0x580c192e, 0x7666a8cd, + 0xfd45b4e8, 0x8593f2a0, 0xe2dfd37d, 0x16567816, + 0x16c10d33, 0xbe038067, 0xafafbb44, 0x83637c33, + 0xcdca84b9, 0x3c516321, 0xf198ddf0, 0x7bdc4b7c, + 0x11880844, 0xca6b670d, 0x3d57b609, 0x7196ffad, + 0xacf163c1, 0x08d1eb86, 0xea8fb4ae, 0xc1d5affe, + 0x26fa287e, 0xecade3c5, 0x5000416f, 0xf7cf603b, + 0xc17b0ca5, 0x4cacc97a, 0x217b1442, 0x42ac4d77, + 0x938309a1, 0x561d06a9, 0x1bd39686, 0x8b560889, + 0xa85b8309, 0x191e5458, 0x51a7c28e, 0x519c77e9, + 0x460b1fd0, 0x4fb27662, 0xc13033ce, 0xa25f2b45, + 0x38b507bb, 0xa7743f25, 0x2cf52299, 0xf8d1a303, + 0xe0def3f8, 0x787cd345, 0xb8bbdb12, 0x953e00d2, + 0x16d60be6, 0xfc00bc63, 0x185b0ef5, 0x0264cd05, + 0xda62f4e7, 0x9a7ae78e, 0x8f97b28c, 0x890d45b7, + 0xb0b7764c, 0x2a57f4da, 0x6c2bc675, 0x151ecc64, + 0x4ee7e8be, 0xedabe1ee, 0x1746de0a, 0x98f58e8d, + 0x93334686, 0xaa77e498, 0x7fe049a0, 0x0a6ed9b1, + 0x251146f1, 0x18f92378, 0x293b93a5, 0x67697c76, + 0xbcbd1e34, 0xb64d5372, 0x49e24c2c, 0xc642ac96, + 0xad2ca528, 0x7b22c2ed, 0xa509b8af, 0xc2e1f8b9, + 0xb493316f, 0xaeff84d8, 0x3b8203b7, 0x989f56ad, + 0x6b2c87d1, 0x036e2bac, 0x5a854fcf, 0x160aa0d0, + 0x54dd376d, 0xe88e0861, 0x89949ad8, 0xe7ce6297, + 0x4958a424, 0x6067f7b8, 0x4424dbf8, 0xb8fcf27e, + 0x88490419, 0x2867674a, 0x125c5fc6, 0x30b40e53, + 0xa36645ac, 0xd2132796, 0x9633255a, 0xf5d9a47a, + 0x23e2778a, 0x07994dbd, 0x2cac2037, 0x662ff0db, + 0xdcd76674, 0x240e2e46, 0x68eb9947, 0xf47c01a7, + 0x0f78eebf, 0x75f2c7e6, 0xf4ea2a54, 0x833f7869, + 0x19aaea84, 0x71f43bc7, 0x1e8bad09, 0x93552f9c, + 0x57bc3fc0, 0x90f65a10, 0x2cb23682, 0x536863d7, + 0x642c8e70, 0x17aa1ad5, 0x95390357, 0xa0300b25, + 0x787919b1, 0xbb1c7630, 0x5d6afad9, 0xda23ca3e, + 0x17a408d7, 0x54a2bbd4, 0x199e3300, 0xe301ac6a, + 0xcb021156, 0xaa3982e0, 0x906a5e15, 0x050e23d8, + 0xe091ef1b, 0xd8f6e478, 0x22efbe5e, 0xf37fc04c, + 0x88f3f7f0, 0x751824d7, 0xb4bbcc32, 0xe1b667e7, + 0x59326f7b, 0xc5c474e0, 0xb8abab00, 0xee9383b3, + 0x01d8914d, 0xa7e95c24, 0x6a93ac10, 0xe0bccd1e, + 0xf174f290, 0x4351b48d, 0x78b49e91, 0xb2eae046, + 0xfaa39124, 0x274be1f1, 0xa860b8f9, 0x6d12d876, + 0x1c4f08ac, 0x2e31b4dc, 0x2cc62112, 0x3860e4ae, + 0xe1cbfd43, 0x1a153233, 0xb08fa237, 0x0e67f4e4, + 0xce687d17, 0x3e66f9f9, 0x1b10cdcd, 0x498d6218, + 0x1659a1c1, 0xf127900d, 0x377fae38, 0x07c4e3a7, + 0xe43b9dee, 0x8c5bf70b, 0xa95a3bf8, 0x1141b347, + 0xadee4f86, 0x74893714, 0x5b8bf395, 0xb2418987, + 0x3e716c6f, 0x6056cede, 0xc664361e, 0x630e6949, + 0xce1bd0c0, 0xdb87f09c, 0x63c33f7a, 0x04de7e67, + 0x44a3af83, 0xb31aac95, 0x954073a4, 0xf155cfc1, + 0x5706fd07, 0xec36d3ec, 0xb9a62d76, 0xa7fbd558, + 0xe1be62c6, 0x2cb0f254, 0xdaf8147c, 0xc018f5a8, + 0x15e9f7ea, 0xf8e41b6b, 0xaa47efd2, 0x869d9340, + 0x08a9579f, 0x53d043e3, 0xd7e8ecda, 0xa94b8af1, + 0x019447b3, 0xbb9340f8, 0x86631524, 0x56119d33, + 0xf56ccfff, 0x90277fba, 0xfe80743e, 0x3c4f7210, + 0xe9ae478e, 0xbf28e0d7, 0xc1ba190a, 0xc6e1f336, + 0x3348bdc5, 0xba301b06, 0x109c28a9, 0x93f00944, + 0xde71dedb, 0x75db5a8e, 0x3fd50476, 0x502177f1, + 0xef867f0e, 0xc697a9cf, 0x2fb33834, 0xc2ae73a1, + 0x0ef411e7, 0xaca15582, 0xa631b708, 0x5e29a326, + 0x19d4fb1e, 0x0e14bbbb, 0x69b9da7c, 0x9adf734c, + 0xaa3cbf09, 0xf49a1914, 0xedc06e2a, 0x2e26907c, + 0xe4e7b0f3, 0x555e18bd, 0x64b9378c, 0xc015228c, + 0x6652b24c, 0x964f67df, 0x53e52747, 0x437f0435, + 0xf5eaae4d, 0x67e627a8, 0x88922d96, 0xacefb73d, + 0x196b3dab, 0x18df6f1d, 0x1fb1e3a4, 0x41368e0e, + 0xe6b38563, 0x2217d9b7, 0xd60fcd57, 0xc6e54482, + 0xe13857b7, 0x9608f663, 0xa98387d0, 0xd0dc79e9, + 0x5eb66007, 0xa6d47edc, 0x216ce2ff, 0x774fbfab, + 0x015327b3, 0x601bc15e, 0x11008332, 0x9530321f, + 0x81f5a229, 0x1ec81430, 0xa9b62b58, 0xad7106c6, + 0x316ccc64, 0xaf84878f, 0x57196f56, 0x337e718e, + 0x599624b5, 0x783bbb19, 0x0bd61790, 0x5ea38aeb, + 0x80924f04, 0xfb90c004, 0x517a5a49, 0x72dc2f94, + 0xc67f6691, 0xa5fa6d1b, 0xf37258d2, 0x052a2710, + 0x2265b5d6, 0x1ff7543f, 0x8d98d31a, 0xd07d518e, + 0xc693a93b, 0xe322f235, 0xfd5a13a6, 0xf4b5bec7, + 0x6a879bf6, 0xb5c9c3c5, 0x02b4c679, 0x79126fcc, + 0x9471f8ca, 0x240b738f, 0x82d6eed8, 0x5cebe2ab, + 0xd0ce0802, 0xc352d955, 0xab391b94, 0x255e337b, + 0xe24e9d28, 0x590b078f, 0x6f02bdcf, 0xa798c871, + 0x032a8771, 0x4c177274, 0xe6e5f8fd, 0x5802dd90, + 0x99c73404, 0x3d6d3858, 0x888fee18, 0x54fe3a75, + 0xd1de4ef6, 0xe70daa9e, 0xd8117486, 0x5e724f88, + 0x7484de9a, 0x416b0091, 0x649600dd, 0x79cfdc3f, + 0xdf187828, 0xfb82fa6a, 0xe1373450, 0x99b1b237, + 0x625c568c, 0x346de1e2, 0x3d09ae1c, 0x61e47376, + 0x3b3e6b1b, 0x143a8e94, 0xe8f18ca6, 0x930210e2, + 0xc7ad686f, 0xd79827d0, 0x843e3682, 0xb8df98e7, + 0xdbb1452f, 0xfd7718fb, 0x050c794d, 0x620c3ed3, + 0x37a9b4e9, 0x930917b0, 0xcf005633, 0x37881383, + 0xbccfabf2, 0x1ef2b275, 0x5373eb32, 0xf720edd7, + 0xf7e2c7be, 0xf510f803, 0xe0af57df, 0xed683137, + 0x3b1824d7, 0x4e518264, 0x75ca2a31, 0x8e665a08, + 0xda2f2631, 0x90f2e624, 0x0b7f10ed, 0x13c77405, + 0xbc8f1852, 0x50efce03, 0x6f37e62c, 0x2146f0ac, + 0xcba12673, 0xb0cf7aa3, 0x62c260c6, 0x914a686e, + 0x4f88de7d, 0xe08828e4, 0x836ade2e, 0x1169dea1, + 0xfa527a96, 0xdb0b67db, 0x81c54c3f, 0x3242a174, + 0x3720d1eb, 0xa2d66d86, 0x3aa9d815, 0x2f50dd70, + 0x7ebd695b, 0xa23ce46e, 0x809e2b62, 0x80868a12, + 0x9fb19fde, 0x063cf06c, 0x5fb5c6be, 0x02305e67, + 0xb07a8437, 0x802d6f3c, 0xa3ae466f, 0x78b26abc, + 0x1b794720, 0x32909b4d, 0x341790e7, 0xe970c75d, + 0xe486e869, 0x77ff3164, 0x2af5bb86, 0x8cbe9546, + 0x0c554b7f, 0x1d6733f9, 0xc8a2e9dc, 0x55be433a, + 0xa8822719, 0xc3bb4f7d, 0x8ff63bad, 0xccfca1d7, + 0xfbd989c3, 0x00cc0aed, 0x62d8ea04, 0x28db507e, + 0x9b010be7, 0x5ba82df9, 0xc5033952, 0xbb36456a, + 0x503bedc2, 0x7f34a7d8, 0x4c95f684, 0xa9fe83c0, + 0x2119ef47, 0xb140a84c, 0x110d1d3e, 0x29d56f44, + 0x6d005db8, 0xb5266ffb, 0x5cd3945d, 0x2245bf69, + 0xc0240f64, 0x1ab59295, 0x3dbfbe90, 0xce0195d8, + 0xeb62d7af, 0xc674e175, 0xb9a0b91a, 0x04f4fd68, + 0x5034bc19, 0xb5f1e1d0, 0x4d17664b, 0xf3a3b573, + 0x45bd805d, 0xec3af23f, 0x83026378, 0x7b5796e6, + 0xedafef9a, 0xcc728ce5, 0x8e7b49b5, 0x30b6e2ea, + 0xd624ca20, 0xf92dc17d, 0xe1cf296a, 0x5391caed, + 0x993eb46a, 0x7eadd9ee, 0x20e03f32, 0x10309bda, + 0xc42a95b2, 0x264c9739, 0x47d678a3, 0x5aca4b99, + 0x27c8bd0c, 0x08dc0c8e, 0x41a0d977, 0x84495d9a, + 0xb3e7c7f5, 0xbb7208c3, 0xeeffd6af, 0x99728ae8, + 0x96e3acc5, 0x46c5b5f0, 0x4e9692c7, 0x4a2856b6, + 0xa6e70afd, 0x0ebfa9d7, 0x5a617dfe, 0x136458c5, + 0xe81577fb, 0x9a346ce6, 0x2276bd4b, 0x19872c41, + 0xebeeaf79, 0xf1eee391, 0x3a092d4b, 0x6d480ae7, + 0x11cbc262, 0xfd19181e, 0xcd2baf7b, 0xf3d3b630, + 0x7e02cd19, 0xeafa37c0, 0xfc3ab903, 0x19d7d5ea, + 0x1522555d, 0xe659e8af, 0x4241187a, 0x0c95a038, + 0xf7a8c439, 0x2ba81067, 0x8537a7da, 0x3fffa8f8, + 0xa86c8fe5, 0xee860d78, 0x9cdde285, 0xe59c35d1, + 0xf3423ace, 0x3b9f18d6, 0xe6b4d111, 0x6307359e, + 0xc10d0c18, 0xdd6a1283, 0xd61b5cdb, 0xa52c1e9f, + 0x1cf0ee74, 0x207bfe55, 0xab0c199a, 0x6680655f, + 0x458ac1c5, 0x59669d48, 0xde00456a, 0xfa24fb02, + 0xdb25e6b3, 0x4759b8d5, 0xc297affa, 0xd24e5878, + 0xf79ba7bd, 0xcb7ec9d8, 0x8df35387, 0x29ee1378, + 0x296aa1a2, 0x0292c907, 0xf2a42aec, 0x2d91514a, + 0xcff397e1, 0xdd316608, 0x6d45c90a, 0x361936da, + 0xed008c30, 0x24fa496f, 0x5c1ecc6c, 0xd239ade4, + 0x143fcedc, 0xeb5a8ea5, 0x893127d2, 0xa1c06528, + 0xfeab6608, 0x8f773eff, 0x17b1cd39, 0xb6cdb5f1, + 0xae013c68, 0x6757a0e1, 0x236096f1, 0xa994b205, + 0x7c717a31, 0xdf765300, 0xcf9936c7, 0x5d5edb37, + 0xeaa7c17c, 0x73ae0a85, 0x4f0a3a26, 0xadf63001, + 0xeeabbc57, 0x65e37d8c, 0x93e64068, 0xc5686912, + 0x810e38bb, 0x1c89b1e6, 0xdb5c9e5a, 0x217f4efb, + 0x054ca07a, 0x90624ad1, 0x4f1212c8, 0x9099eb4c, + 0x8ca443a3, 0x99887edb, 0xb8428dd8, 0x60ad4105, + 0x9153afa4, 0xefdf8bcd, 0xb82041ce, 0x22c39153, + 0x4ba5ab79, 0x73b4a621, 0x45a91da2, 0x9d7597c7, + 0xe501fdaa, 0x45a8fce2, 0x2b32624d, 0xcef2645e, + 0xc88eead4, 0x72bbee6a, 0xb63e6cb9, 0xc17830fc, + 0x5fc477f0, 0x56f8f783, 0x8742083a, 0xd3bdf98f, + 0x2222e3ce, 0xf20cd44a, 0xa3c8f166, 0xfb70b222, + 0x88cf7d3c, 0x97064ca0, 0xa81e37c3, 0x2045a54e, + 0xec70f5d7, 0x8461dad2, 0x0478a8a7, 0x88753a88, + 0x9753a230, 0x982cff7a, 0xafeff6b7, 0x7913a243, + 0x44e314b1, 0xb71105e0, 0x9d0e8204, 0x237c3118, + 0x4d8873df, 0x0368c70b, 0x432f8cb4, 0xfd493409, + 0xafea07a6, 0x4afb576d, 0x8e517d06, 0x7a3b84f6, + 0x1bae9381, 0x8f62e882, 0xa9f1e783, 0x9824163a, + 0x8054f277, 0xe62e9cbd, 0xc39dde1b, 0x24e232f8, + 0x5acdaacb, 0x27074e5b, 0x5383d8ff, 0xd28f6398, + 0x4bd1d713, 0xd6282ec9, 0x4cc38f04, 0x02432175, + 0x18386f71, 0x3cf5efea, 0xa4913139, 0x5ab9eb4c, + 0x63ec6690, 0x0b882807, 0x6ae93e1e, 0x25a6cd92, + 0x71fa0fb7, 0x5c4d0517, 0x507a5f0b, 0x9ad2772b, + 0x7d3f0e07, 0x3205aa7a, 0x7c946116, 0x6b243eaf, + 0x7d33f31e, 0x45c18845, 0xdae4efc6, 0xa9047dfe, + 0xd178dcd1, 0x6aa30ca9, 0xdeabd81f, 0x2876c341, + 0xde3095a5, 0x8f93d022, 0x9a78e64b, 0x147aa0a0, + 0x5dfeb2f9, 0x158167ff, 0x1335d1b4, 0x675d6ea6, + 0x066f0909, 0xc9324702, 0x68a75527, 0x740aa84f, + 0xea686192, 0x78af651b, 0xe99f5db7, 0x09cbc101, + 0xdbee388f, 0x1694ff29, 0x30d9ed06, 0x1d4a9a16, + 0x0c60ca8f, 0x2ca66130, 0xb4ec8db1, 0x6171e7b1, + 0xef850685, 0xf54862d4, 0x16c0dadf, 0x12f2dfc9, + 0x2b243a21, 0x52a919a8, 0x8d5f31e7, 0xc088c5ce, + 0x7a19e823, 0xc1e6b67e, 0xa4f9108d, 0x8db0d42a, + 0x7875a613, 0xa255a349, 0xd97b2cb6, 0x559065be, + 0x6fcd2ef6, 0x8d1171bb, 0x8f18fddb, 0xe595af9d, + 0xfcc7b725, 0xd4dd9eab, 0x8eb142c2, 0x0dba44ee, + 0xbc15e3c2, 0xdd4ac8ae, 0x983f0570, 0xbde2b8f4, + 0x05d637bf, 0x9b743557, 0x09715719, 0x0ff8e59a, + 0x149f663e, 0xeebf9293, 0x3c185a86, 0x6840c25e, + 0xc55135f1, 0xa2f18168, 0x8bcfe5d5, 0x6fccbd86, + 0x3788ec27, 0xf329aa1c, 0x58660612, 0x16117c7e, + 0x14f2d445, 0x4920e0b0, 0xff40c550, 0x3b63926c, + 0x0381f602, 0xfdea61fa, 0x2e38a30e, 0xfc5126c0, + 0xab87149e, 0x5feec484, 0x637981b0, 0x8c0f6a85, + 0x104a7e55, 0xa90838d3, 0xa939d5b4, 0xbe2af69d, + 0x1a317bd4, 0x4a9b5f22, 0x63d814d9, 0xc85123be, + 0x7e1481ef, 0xa603d165, 0xb7e841fe, 0x30ed4470, + 0x863de857, 0xe32a5888, 0x1cd57a0c, 0x43c1cdfb, + 0x04674312, 0xc35d2105, 0x371e3da1, 0x0d1e1e4a, + 0x4b40954c, 0x390999f6, 0xe716caa2, 0x652a4e26, + 0xd5c0cd7f, 0xec4ae3f0, 0xa3d608ec, 0x1dededb3, + 0x182ed1cc, 0xe489b2ad, 0xb054197c, 0x42c190a8, + 0xa8506f5b, 0x6418f784, 0x92d4c59f, 0x4b418817, + 0x5d201fe1, 0x5a9a37d2, 0xb0091aff, 0x1fe39f66, + 0x84780a91, 0xe6064a1b, 0x1cd45cbe, 0x6c755ad5, + 0x4caf827f, 0x75dd9197, 0x3729cec0, 0x8aca424d, + 0x776e9d2e, 0xef760768, 0xdf4198de, 0x9f05d70b, + 0xef057918, 0xec188356, 0x4ece4eb0, 0x772f0f1d, + 0x362ff7e3, 0x4a03ec39, 0xca53b1ac, 0x73c28a2e, + 0x40e5b160, 0x16e86af3, 0xa0cbdb1c, 0xa6aed291, + 0x0ab81158, 0x0c7f02b0, 0x275ae7bf, 0xe0d7c4a9, + 0x5522d0ba, 0xdae982a3, 0x8a0b4523, 0x894f1444, + 0x7756510f, 0x1c9b8981, 0x5f069df3, 0x7c8c7760, + 0xa3ee5d29, 0xd06d000b, 0x7728c354, 0xc1c4591b, + 0xfde7cbd0, 0x544700a4, 0xdffce270, 0x32d2487b, + 0x2ca88ecb, 0xe7cce47b, 0xf83288bd, 0xdd339922, + 0xbdd47228, 0x76db965e, 0x431c0f8f, 0xba5d25a3, + 0xcd834ae9, 0x86921f22, 0xe4877ac2, 0x3e1b5b95, + 0xd5234c8f, 0xc7e7385e, 0x928ddc50, 0x0e4a0fa2, + 0x8050e130, 0x82f33e5c, 0x58138b8c, 0x09dc5478, + 0x2c289b5f, 0x15b50b6e, 0xe644f3c2, 0x1ec32392, + 0x6329f8d3, 0x4bec7bba, 0xf287393f, 0x6ddfdc28, + 0x19279547, 0xd959cbe9, 0xde36bdfe, 0xd331cb85, + 0xfb54623f, 0x27312ff7, 0xa130674d, 0xf685a278, + 0x66568885, 0xf91e7b16, 0xd6d478f9, 0xeb3e71e3, + 0x12539a50, 0x59daf29a, 0x1ea64234, 0xe969a7c4, + 0xacaa2ce2, 0x8f0031dc, 0x1d08a790, 0xac89aea9, + 0xc2a043c8, 0x6bcf4143, 0x946fface, 0x1adef1ab, + 0xebf52457, 0xd475c20b, 0x3a39c57f, 0x30c9780c, + 0xc0f043ef, 0x5b5a39be, 0xe645e543, 0x255f0ba3, + 0xab3b85c4, 0x21759224, 0x756cd543, 0xb7742f3a, + 0xaf97507c, 0xa2453bde, 0x96b1f799, 0xfec73877, + 0x9c34bf8e, 0xdf9231db, 0xeedff688, 0xf67910c3, + 0xde6024ae, 0x0a62d30e, 0x65d1c88c, 0x3011e133, + 0x39f50d0b, 0xfd243709, 0x2da0e404, 0xdb4e401c, + 0xf3aff2f8, 0x6047fc17, 0xf0e9ead3, 0xdf1ae302, + 0xaabdc780, 0x5b63e544, 0x22bed644, 0x4dcf2470, + 0x19d2a919, 0x903382c1, 0x2e402150, 0x4872f3f9, + 0x0d4ca05e, 0x0a3d9ae2, 0xe61503aa, 0xaf5aa08c, + 0xaad5d0d9, 0x38340bfc, 0x8a5d80d3, 0xac4102b2, + 0x4370fc0d, 0x9bfe01a7, 0xf615110a, 0x4f503457, + 0x498dd852, 0xf300128d, 0xeaf6bfd7, 0x768fb7bf, + 0x83ef2619, 0x05514fe9, 0xd50aa19a, 0xf86947f2, + 0xfc74994b, 0xfd5c9a73, 0x38e27cac, 0x6b262e0c, + 0x34be3f6e, 0x87cb6bb3, 0x3dbdd583, 0xb8e9c34c, + 0xb311507a, 0x79935daf, 0x263da6ae, 0x7ad52658, + 0x319fada4, 0x5e71607e, 0x761fd4e5, 0x00f87dcf, + 0x09270f2d, 0xd93aff66, 0xfb26e3a9, 0xdb25947c, + 0xc5629920, 0x45e5085c, 0xd936f257, 0x317f73a2, + 0x39a0e9ba, 0xa26e9f7c, 0xe1dd2b14, 0x60b43ee8, + 0xc735576f, 0xf0f57ce3, 0x15a992cc, 0x85e2e70f, + 0x41252493, 0xa00fc96e, 0xee0d164e, 0x9a2fd342, + 0x17bb6ddc, 0x43bb570e, 0x4d76b6ac, 0xd4936e7f, + 0x986a6732, 0xe4c03135, 0xc6b14bc4, 0x55ba9b73, + 0x9034db90, 0xfe753761, 0xf7975632, 0x2a178d8b, + 0x322b692a, 0xb31a855d, 0x362689d5, 0x20780137, + 0x79bbbd00, 0xbceaae8a, 0x224a74e8, 0x0fb909fd, + 0xb890dff6, 0xd4089bfa, 0x926d8b60, 0x6f5c0e24, + 0x71977fb0, 0x46413ccf, 0x513ca99d, 0xe2d8c8ae, + 0x7a4252d0, 0xeeed8154, 0xc680e6c1, 0x5a8c66ac, + 0xa855ccd6, 0xffdef525, 0x5f968fe1, 0xfb8756aa, + 0x1a5cb2c4, 0xeac328f6, 0x93a4e911, 0xb5a09138, + 0xba9ac8a8, 0x4191c901, 0x53ec0c31, 0x85c96494, + 0x4f972ed2, 0xf9f71b28, 0xdabcb423, 0xe82713ac, + 0x4d72f3df, 0x831af5df, 0x1715e437, 0x8b6f6a68, + 0x76252952, 0x8cc152b0, 0xbea262b4, 0x102f1560, + 0x18a2c2f6, 0x5839d7cd, 0x7ac4e51c, 0xaa94091e, + 0xa25211d9, 0xc1c30509, 0x669b09b0, 0xc44c6de2, + 0xa9b78ae1, 0x8790646c, 0x78049e2e, 0x22edab05, + 0xf68a2e25, 0xbeb03399, 0xa47f6039, 0x279e4d42, + 0x66629c7e, 0x6ce2d290, 0xa688d117, 0x2acac477, + 0xa3587cf4, 0x3f6a4bbe, 0xee014b78, 0xeb8a8f51, + 0x41d49058, 0x28ec1df3, 0x2bbf4908, 0x8c46e525, + 0xbb7e6a2b, 0x2ef264a7, 0x80f2ea8c, 0x1bdcc09e, + 0x359a9f19, 0xff25ddb6, 0xd23c07aa, 0xd7a6999b, + 0x6650425b, 0x6e0e62de, 0xf0efedd0, 0x67b5d110, + 0xf2853e31, 0x22e72b2b, 0xcf42eedf, 0x19a1ade4, + 0x5ec9217e, 0x979d620b, 0x4716de11, 0x4dc51dcd, + 0x07c751ac, 0xa18ec017, 0xa9360d50, 0x5f5567b9, + 0xaa29ee88, 0x359acec2, 0xffe70d66, 0xe0a4d339, + 0xa30b0041, 0xffbdc17e, 0xea9a34b5, 0xdf5ef104, + 0x8e2b9779, 0x6118b665, 0xa3e9bfc8, 0x4582c1de, + 0xf41570a0, 0x067a2ae6, 0x381e704c, 0xc919a87d, + 0x4fa95cbc, 0x151cbe8c, 0x07aacaa6, 0x46d48b01, + 0xd87a8dbc, 0xdec805d4, 0x91526f9a, 0x0086f881, + 0xe9b56bb4, 0x92c84ec8, 0x0c1defa4, 0x140f7fc0, + 0x59af67a0, 0xe4b7064e, 0xc743ac3f, 0x03daf36f, + 0x3beb03d1, 0xafa266e6, 0x0841dbf8, 0x2f5c8573, + 0x1d8ebedc, 0xec7784e8, 0x574fe13a, 0x8dd6d989, + 0xd084f5e3, 0x718fffa8, 0xc6ceb8a1, 0x056ff3e7, + 0x8213e34b, 0x8d65a185, 0x5cebf134, 0xeabeb5b4, + 0x22161265, 0xc05581f8, 0x9871f6fd, 0xba60da2d, + 0xdba85220, 0x5e8660b0, 0xd88c8f67, 0xaabcb748, + 0xddcb74b4, 0xfb404f6a, 0xbbdd2ed7, 0x4b7b3501, + 0x7d71379c, 0x9e72eb89, 0x69e385c6, 0x7c6c1427, + 0x3ddb8cb7, 0xafa28900, 0x16592d8f, 0x1e00232f, + 0x3f01c408, 0x92bf2031, 0x284c780c, 0x3446ad71, + 0xe85881b7, 0x3eeed4da, 0x343526b0, 0x4fa3a536, + 0x7e555986, 0xf68db7a0, 0x3b6dc978, 0x83c0fcbb, + 0xe6621f11, 0xb5655e40, 0x0ce1f9a2, 0xc09fd28c, + 0x78ddfcd8, 0x9472bfed, 0x74547420, 0x725903ee, + 0xdbd220d5, 0xe3881f96, 0x4146a6b7, 0xb04cbdfa, + 0x4fe69746, 0xe17334f0, 0xac460fbc, 0x49b29cc9, + 0x9d5ecaff, 0x1248a36e, 0x9f6dc260, 0xdaab7b50, + 0x96dfc49a, 0xb5f1366b, 0x817e4272, 0xed869802, + 0x6d908607, 0xa2c5b9fe, 0xc0efd578, 0xbbb42a02, + 0xed1d3c7c, 0x3cf29a98, 0xa8249ed9, 0x7a29768e, + 0x97ada287, 0xaecf9ead, 0x26d483a0, 0x17216d12, + 0x2eca6e6b, 0x77e0c2a7, 0x329158b6, 0xa4c61d43, + 0xc903e068, 0x6561939c, 0xec320289, 0x079ff8e3, + 0x24d8cdd5, 0x9b4e370c, 0x90672bb1, 0xb6c7aaf9, + 0x8dd0ac13, 0x36adc925, 0xd262e319, 0x6dbebf09, + 0xef8f288e, 0xeea4ad16, 0xc93f3706, 0x48849c65, + 0xf7f780dd, 0x55f3fa2f, 0x5896c272, 0x6e743071, + 0xaf675bdb, 0xe16f4c3e, 0xec48aad7, 0x9fb145a6, + 0x90086058, 0xdae0d020, 0xa50f73c3, 0x4e43b7e0, + 0xfc103a19, 0x2f3fcbde, 0xeaeca2d8, 0x74910aa1, + 0xd40fa076, 0xb718e2a3, 0xa9fb6add, 0xd0a5bc70, + 0x05d17b2c, 0x594954de, 0x59bf3f5e, 0x41624d25, + 0x60770de2, 0x9d32f8e3, 0x0e7588c1, 0x1f3677b0, + 0x21c379f3, 0x3fcbb7ac, 0x79764479, 0x37c20880, + 0x7d491746, 0xb03d6fc6, 0x691e3054, 0x57542bfa, + 0x959cc18d, 0x22ee98a5, 0x6110a373, 0xd429b7fc, + 0x9181496c, 0x17e5e56d, 0xf7b69960, 0x81c3f770, + 0x11c2ec89, 0xb1a132b7, 0x54286945, 0x0a1b4eaa, + 0x8cb1b5cd, 0x9ed6cd13, 0x0a6477ee, 0x724a5b35, + 0x3550905c, 0x79d6d986, 0x37724798, 0x5ba2169c, + 0xd122657b, 0x79fbd815, 0x26aee21e, 0xd6e7243f, + 0x62c48828, 0x0562d740, 0xa1bbe8a3, 0x9ae5dbaa, + 0xeb3ec654, 0xeeac837f, 0xa54bba8c, 0x7fac6536, + 0xffa8c35b, 0x061f8bfa, 0x7d9533ec, 0x78f87477, + 0xcabd108e, 0x5bcf62f1, 0x58d83fef, 0x05e6a00f, + 0xd5e4cff0, 0x4c44180f, 0xf21050b4, 0x255cbabb, + 0x8f4ae68d, 0xaa822b11, 0x1c3bb1b5, 0x347c77cb, + 0x366ef0d6, 0x0f742f69, 0x3d5e3fc3, 0x7e4dec5e, + 0xe6515e83, 0x101f8de5, 0xd8237dda, 0x0d700c40, + 0x13ac76ba, 0x008f46d3, 0x9f1a0edf, 0x0eeace4e, + 0x1596d8f4, 0x46d843c9, 0xd1aeb9be, 0x72e09971, + 0xa93353ba, 0xb9c3c6aa, 0x73b4947d, 0xc62131e2, + 0x2a92f319, 0xb09606d4, 0xcb133c6e, 0x0d5d85ec, + 0xa757b193, 0x00785404, 0x16e66999, 0x4f76e608, + 0xbfd6b3bd, 0x3e3d93e6, 0x6f63d7dd, 0x8c3dfb98, + 0x6a102833, 0xa91ea02c, 0xd1070130, 0xb6bf3c3e, + 0x21fb4b30, 0xdf6297fd, 0xed73d0ad, 0xf791741e, + 0x8518ea52, 0xadb6b7ff, 0xe2bd4fe0, 0x5c844be4, + 0x3a5567c8, 0x4f6ec218, 0xdc67a1c3, 0x59f2b806, + 0x646ad07d, 0xe5abd80a, 0xbf0eb949, 0x03e4844e, + 0x3ac74739, 0xa2bce00d, 0x08c21c92, 0xf0e6759c, + 0x8fd20178, 0x79ff53e1, 0x2bd18ac1, 0x4fdf3ddf, + 0xfc54f10a, 0x7665fff2, 0xd98cd3ff, 0xfe2ba8e2, + 0x52dd9a64, 0xc3d1f3b0, 0x15f41c0f, 0x7669f39b, + 0x9072e300, 0x9efa554f, 0x0fb67177, 0xdbcfc4ac, + 0x861ec40d, 0x8f6fa82c, 0xe2de1597, 0x4964d065, + 0x8f15846a, 0xc382e6e2, 0x58770e9f, 0xa09bb14b, + 0x708eb67f, 0xa49f057f, 0x83b11fcb, 0xb0d34112, + 0x7a9a5daf, 0xafd33ba5, 0xe5d89e53, 0xc1afc620, + 0x229da718, 0xddf2759f, 0x45c0efb1, 0x9d5da4a6, + 0xd5230d44, 0x7ebf292f, 0x3996a3f1, 0x7bb08a21, + 0x8fe43e7f, 0xcefe1068, 0xae1c2659, 0x3e682d77, + 0x31b27947, 0xde0620e2, 0xc2d11457, 0x39f82f72, + 0xd4bdea10, 0xd4048eb7, 0xb8efda7a, 0x6c34ce7f, + 0xedf09103, 0x58d1b66c, 0x02a70f28, 0x732b9b67, + 0xbdd49541, 0x2e2cf321, 0xb1cdb375, 0x8dde29db, + 0x601f6b01, 0x785529e8, 0x41ad52a9, 0xed71153f, + 0x07c79c1f, 0x9e461531, 0x501068ef, 0x2dc5363d, + 0x33cef6d4, 0x064ad3a2, 0xfaaa9bfb, 0xf76c5b83, + 0x9289e370, 0x0154d7cd, 0x83d0e636, 0x4b3842ba, + 0x2cae0edd, 0x5ce95b31, 0x3db27a61, 0x0f51b0ca, + 0x95bda166, 0x8df62ddf, 0x2cc5641e, 0x3b300f09, + 0x26e76f94, 0xfd78be19, 0xc6792770, 0x22d84fe2, + 0xd8eb196c, 0xe31d6b01, 0xdb03bb74, 0xf6e121ac, + 0xc1cdde3a, 0xe4c11ad4, 0xb4bc4bf2, 0xceb0e8b8, + 0x4ea9774b, 0x16a5e47b, 0xaa971fec, 0x1194532e, + 0x9128d77d, 0x03bc2c57, 0x87c7e234, 0x7d6b1d7e, + 0x78cee50f, 0x776a5ead, 0x07a11696, 0xfa84a709, + 0xfea6994f, 0xed358a6f, 0xdeb08ffc, 0x5d2f6dc5, + 0x2755ef28, 0x846a53fd, 0x63db6af1, 0x76ecd9c2, + 0x17258c17, 0x34295fc7, 0x397dbd9b, 0x9e4cee04, + 0x4be32c1b, 0x132d214e, 0x5bbcce39, 0x9a2625a4, + 0x0ab4a812, 0x16bf4dfc, 0x59119f94, 0x539c8bec, + 0xb3fc6822, 0x1925d683, 0x52918b41, 0xa70912fb, + 0x707d6f19, 0x2eb3abc2, 0xc1346a8b, 0x77b15003, + 0xf9b94f05, 0x93de2cec, 0x8b5dd8a8, 0x6da2d243, + 0xe983be77, 0x3900428d, 0x89ca7386, 0xfeeb986e, + 0x809e485e, 0xe6e278f9, 0x0878a9a2, 0xa885bce2, + 0x760c8195, 0xd32bbe96, 0x8fae0dd5, 0xdc34b30d, + 0x16ae4373, 0x145399ab, 0xb15e8d82, 0x985afd4a, + 0x940e003d, 0xaeebaf5b, 0xd480e43a, 0x8739a867, + 0xbabf7203, 0x4a9a3cf1, 0x921ba29c, 0x3297b9ea, + 0x95fa0d58, 0x4d3b4b0b, 0xb2d5664c, 0x46e2119c, + 0xcca14ac4, 0x976a18e3, 0x2897eaa4, 0x027121e9, + 0xed13e632, 0x6b6f0121, 0x56c171f6, 0x706a9172, + 0x6544f1b1, 0xb6ff2537, 0x3574b6b9, 0xf8652021, + 0xf4232bb5, 0x70af56bd, 0x49c4647a, 0xf844d462, + 0x029cd35d, 0x556c1755, 0xa8175a9c, 0x52eb80f2, + 0xc11acf51, 0x318533a5, 0x512efd2f, 0x52ed6298, + 0xec6ced43, 0x711e465f, 0xfbff9bd2, 0x218a90db, + 0x87fdd5e9, 0x72b4193b, 0x9936e8c1, 0x5d4aec55, + 0xec0330ec, 0x93587390, 0xca7d3e24, 0x23cb68e2, + 0x118dd06f, 0x2886289c, 0x91512d10, 0xa6b6a2c1, + 0x664301c5, 0x88b752b7, 0x64898d8a, 0xeb640624, + 0x23d0d326, 0x72a1f775, 0x92d6f0eb, 0x4dd8738f, + 0xd078d93a, 0x06753e1c, 0x9cf0c82c, 0xf00cc737, + 0xfc0ecc80, 0x33143b0c, 0x4dbc5b7d, 0x48b0f487, + 0x949f695c, 0xeb6e3068, 0x1aee517a, 0x8eabd9d1, + 0xb93e0ffc, 0xc4b49583, 0xd910f46d, 0x2844c6c2, + 0x24dc24d7, 0xa46eba6d, 0x554136eb, 0x7f7829ad, + 0x01a0ac92, 0xf119a06b, 0x8062e710, 0xf10ccaf2, + 0x6dd59f14, 0x5ac0ba38, 0xd3a4dde1, 0xc64cae46, + 0xb72a8bb3, 0x52ef37f5, 0x343766ed, 0x5fb6a469, + 0xa5c94b87, 0x8e6b898f, 0x0e2b0d8e, 0xbe8acd6f, + 0x82233d64, 0x5e86a977, 0xa776c960, 0xcacf60d5, + 0xa57f2025, 0x52ea9bd0, 0xb295e953, 0xb1270add, + 0xf15658c5, 0x5a6d399a, 0x34c8fb55, 0x40fc94f0, + 0x3b83bd2a, 0xf894c342, 0x15f0179f, 0xf1ebf249, + 0xe985b001, 0xd36553bc, 0x45b449b5, 0x66e02d8e, + 0x0fedbd4d, 0xce5a6f83, 0x44991f4d, 0x3e77771a, + 0x557e741e, 0xcb9c8fb7, 0x6f96d05f, 0x6bc3ad7c, + 0xfe74f377, 0xabb544f9, 0xc8e5c138, 0x042cef42, + 0x36e6e463, 0x6d16afab, 0x2f2b9bd3, 0x32079836, + 0x51769d1e, 0x8cc04292, 0x525565be, 0x01d56797, + 0x720ad744, 0x2b5df827, 0x7c6e7011, 0xde5bf3d3, + 0xef9d6a47, 0xbf01585c, 0xe1603753, 0x01e68b5b, + 0x58d8acf0, 0x361a243c, 0x3776bb5e, 0x85a6ecf0, + 0x63c02a88, 0xaed9b0ca, 0xe40c2f4f, 0x514ea59e, + 0xd7bb50a6, 0x7001b952, 0x6ca0a02f, 0x67e8539b, + 0xe1f361c8, 0xe3716e13, 0xd586fef9, 0xfaf596b0, + 0x4640fa6d, 0x80705225, 0xacb7d58c, 0x7fae4071, + 0x26ee2f89, 0x48b8d5dd, 0xf4574eff, 0x98a58c8b, + 0x618e6e9a, 0x347e98ab, 0x5cd6cfae, 0x4f5b528e, + 0x771d54b4, 0x21516d45, 0xf38af4d4, 0xec0b3b4b, + 0x14e6034f, 0x7fbd2f59, 0xe6239e0b, 0x5ebc33b9, + 0x570813e7, 0x60d71433, 0x2e1904a6, 0xd812f1e2, + 0xcc3fdb32, 0xaf49475a, 0x1ae1a880, 0xe51fc578, + 0xb55554c1, 0xf949cc2c, 0xeabe1429, 0x2960311f, + 0x53230b20, 0xa5a3894e, 0x20446134, 0x74c8b394, + 0xb8431124, 0x076686a6, 0x2a0150a0, 0xfb6c2ce8, + 0xc8e5fbbe, 0xd0d0fa89, 0xe8665995, 0x9ce4ca40, + 0x4eadf970, 0xe072ed22, 0x452c3086, 0x2764ed1b, + 0xd448e31d, 0x4c8c021a, 0x99c64394, 0x2ba2d7c7, + 0x8934267c, 0x8cb9794e, 0x3199ceee, 0x04d33b9f, + 0x088b031e, 0x24943620, 0xe2f9107f, 0xb4abbd6e, + 0xb38eaaa1, 0xa57c73ed, 0xce94691d, 0x04d698c2, + 0x4e7fb748, 0xf2c08794, 0x686c6194, 0x43444a75, + 0x1d58410c, 0x7dabdc47, 0xdd74abbf, 0x3ec0abc1, + 0xb7b670d2, 0x7b0de6c2, 0x8a9f70f9, 0x6ccc208a, + 0x6ce3de6f, 0x551fb837, 0x8d025ec4, 0xc7442d5a, + 0x40f816f7, 0x2094a730, 0xfe1f6937, 0x80d0db62, + 0x183becf2, 0xd35d3f49, 0xcc998142, 0xb6739af0, + 0x97b0368c, 0x441b052c, 0x70ca379a, 0x577e6cdd, + 0x7437d170, 0xb787ea6b, 0x6d3b604f, 0x3b09f548, + 0x97f7c5b4, 0xfcf26e94, 0xb6f45efb, 0x79a8935b, + 0xbecadb7d, 0xeb675066, 0xe6c22273, 0xd2cf07b8, + 0xc0861fb9, 0x5cfd6a54, 0x365d62b9, 0xa609756d, + 0x7b72e7f7, 0x102f49fb, 0x90027250, 0xda9eb6b2, + 0x65fba88c, 0x62fa6f4e, 0x6e879917, 0x7d927e47, + 0x8002767c, 0x79151e4f, 0xe66a40fe, 0x1f2439d6, + 0x17a01a2b, 0x897cebd5, 0x2ad301cf, 0x43d218d7, + 0xc715e53a, 0xcee15463, 0x90bb7eb7, 0x167ee2c2, + 0x550941e6, 0x1c8a8a47, 0xd740f5b5, 0xdf8251ff, + 0x6df5fc79, 0xc2430fd2, 0x7201d76c, 0xc5002d57, + 0xbaeec9a5, 0x4843f217, 0x728f1a02, 0xceb636b1, + 0x63743721, 0x6ddd4de1, 0x4a67f6f0, 0x8a2a1ab6, + 0x8c44023b, 0x15f9cc7b, 0xaa420aea, 0xabd03e1e, + 0xbbfb1f2b, 0x1bb238bb, 0x2c5f33d6, 0x926fe3d2, + 0x737922c0, 0xcb0eccd7, 0x8e3b46c5, 0xc348f724, + 0x54b0eb04, 0x385da1f9, 0xea039a00, 0xdaf6e3d6, + 0xd258a9b2, 0xf43a1c73, 0xeee7349a, 0xe6b7901d, + 0x01be8c8b, 0x882b3a06, 0x38c02aa1, 0xc49b2165, + 0xcb388a1d, 0x74210862, 0xc434cbfc, 0x8e500a12, + 0x508803ac, 0x8043dabd, 0x2cecf15b, 0x048e5649, + 0xfe645dab, 0xeaceb60b, 0x8311ca61, 0xab9f4511, + 0x7a0ffa90, 0x3411961b, 0x7b2c4f72, 0x73130c5c, + 0x643632f0, 0xdca6055e, 0x4b8cd13b, 0x7a52e0cc, + 0xb1d00e0e, 0x54ae56a7, 0xe0ec71b2, 0x1b6e774a, + 0x2ab8e5e8, 0x9672b8a7, 0x025ac7b4, 0x6b08cdcc, + 0x32ccedf5, 0xb1141149, 0x12fa8126, 0x373afaab, + 0x83e42c76, 0x0159c8a2, 0xb13cf6bf, 0xd8da66d3, + 0x24b60bdd, 0x8b5b060b, 0x402b300d, 0xfff0c83c, + 0xf6a8ea62, 0xac272df6, 0x53086cb5, 0x4ea409a2, + 0x6cb249e2, 0x4ea1be62, 0xb879b594, 0x315f2c8b, + 0x55762201, 0x7a7d3b17, 0x383e6c9a, 0xf0e5b411, + 0xa6ddddfd, 0x1f0d69d7, 0x40207544, 0xcec14837, + 0x82a869dd, 0xadb4a24f, 0xb42dfde2, 0xee6daca2, + 0xfd993731, 0x2b3a9667, 0xa5efb2dc, 0x60ab758b, + 0x904823e5, 0x8b397ec6, 0x583bdc39, 0x2f684911, + 0xcad9fa2a, 0x19ff56df, 0x0a2fe1a5, 0x5c509a75, + 0xc596710d, 0xacb8dfac, 0x2394f499, 0xe1ce4e85, + 0x849e2e31, 0xca844ddc, 0x77e773a5, 0xa7282ff6, + 0xb7419e7a, 0x9f162e55, 0xae797c86, 0x48eaba22, + 0x7658346f, 0x9f68d435, 0x8ff92ee8, 0xafb8bac3, + 0x27d12c8d, 0x24d39bc5, 0xddf983a7, 0x15df80e6, + 0xf1874da4, 0x6f1cfffd, 0xfc90c1e5, 0x086a24af, + 0xe2b7a6d1, 0x29c2dd81, 0x03fe3085, 0x2b6ca57c, + 0x294dd96c, 0x9c919f8a, 0x1e8b3e28, 0x641bb984, + 0x9b164c7d, 0x3bf59568, 0xc2732dfe, 0x3ae42a9b, + 0x51ffd5ef, 0xb46f3080, 0x5a8fc9ec, 0xc850715b, + 0x6c9b29ea, 0x327043ad, 0x85fb278a, 0x0a03d808, + 0x4bfc9cc7, 0xd5da3807, 0x40438ce5, 0xbf4ba07b, + 0x348ef9c3, 0x68981b8c, 0x04fd77b8, 0x808eaed4, + 0x4024f961, 0x43c60bf6, 0x33ce96c7, 0x2641e352, + 0xdde4129b, 0x2f263f1d, 0x046ab1df, 0x913a20a5, + 0x9e147635, 0xe2bfff03, 0x728ab89d, 0x63fa4abb, + 0x3acafd43, 0xf09a0b18, 0x34f8efeb, 0x47150130, + 0xf1ac1beb, 0xa01721b9, 0xe38d5aad, 0xfd56a4d9, + 0x892ab9ab, 0xea173f66, 0xc9b77a86, 0x47307a51, + 0xd84571cc, 0xb96c7c28, 0x5468cf27, 0x3d1bc060, + 0x2cf06fb0, 0x7e2a059a, 0xe76aa885, 0xc7d202d3, + 0xf987735f, 0x7bf69df9, 0xa4193b44, 0xc4072f63, + 0x63991b95, 0x945d2547, 0x20fc01a1, 0x0b402cea, + 0x1cfecda1, 0x196c9850, 0xc94a7a8f, 0x45cbde21, + 0x21c0ca0d, 0x8e9bb55b, 0xb6ed98ae, 0x0249a938, + 0x30e011e1, 0x27c8d7c2, 0x9e80e963, 0xe6d92f0b, + 0x04e474f9, 0xe1d709f1, 0x1a53d51d, 0x0353c881, + 0xfa068cfd, 0xe02b14a9, 0x89246dd0, 0xb116fa1c, + 0x0c75dbc0, 0x5960758c, 0xa7617739, 0x601e7af3, + 0x0b145e7b, 0xecab38b4, 0x9cd6d9dc, 0x24922fe7, + 0x5392ed2f, 0xd520c878, 0xbf49bfee, 0xcde77d02, + 0xe0d5c3d4, 0x58af2dce, 0x0fa35621, 0xfead6943, + 0x4d134689, 0xedd86ec4, 0x1c585bad, 0x5dcc5011, + 0xe693cdad, 0x08bc39ef, 0x4d5c2eb8, 0x562fc8ea, + 0x5722d5a0, 0x4b6d1a81, 0xd918439a, 0xffb036b8, + 0x0875f77a, 0x2aa45832, 0xe57f674e, 0x82865775, + 0x0777538a, 0xf6e2a2c6, 0x05800e76, 0x8aec959e, + 0xd48b20cd, 0xf654b1c5, 0xf69d4a1f, 0xa67f1175, + 0xe7659527, 0x6556a72f, 0xc668df31, 0x24ee119a, + 0x29ab3c17, 0x18add733, 0xca05fc8d, 0xc06bb38a, + 0x889ac6ff, 0xed44ec98, 0x9e6e95d2, 0x2b0d6d52, + 0xea3452bb, 0x34243ed0, 0xc8a08a5d, 0xc1bbab18, + 0x5e581153, 0xbac12814, 0xd2357305, 0xcb70d646, + 0xf487b1d6, 0xfcd1e9dd, 0x21777851, 0x5b92f071, + 0x67c845e9, 0x6321ea09, 0x827f7274, 0x22c01684, + 0x798684cb, 0xba8ef875, 0xf1278dfb, 0x1c5cb755, + 0x18fd2615, 0xad58062b, 0xc4300928, 0xa0d3104a, + 0x712a1440, 0x8894b46c, 0xfb4b84d4, 0x55cbf0c7, + 0xfedf3627, 0x2ea77c79, 0xa1b78735, 0xd6e5a364, + 0x35965a2d, 0x8bc0e5db, 0x9cd0194a, 0x11ddd727, + 0xe08db7fc, 0x4df6fc69, 0xd17f011a, 0xfae3c4b8, + 0x2c3c5c73, 0xa467c3cb, 0x89f6501d, 0xaf32cb3a, + 0x380dc067, 0x41596623, 0x22a7d4a8, 0xbe8b0434, + 0x0f7800df, 0xab523ed0, 0x9d7dc989, 0x5ec4bcf6, + 0x4f022e80, 0x99b97f3b, 0x4faaf990, 0x03a13ca5, + 0x820ab836, 0x6adb2a3e, 0x5ce24831, 0x8ed91c35, + 0xe620f720, 0x55d25cf9, 0xc54fbcbf, 0xa5fc7938, + 0xc87a81f1, 0xd74e02b9, 0xf64cf87c, 0x623fa08a, + 0x0cce5093, 0xa36151ee, 0xb866b3eb, 0x84910e75, + 0xf661e712, 0x3a05d594, 0xdcddb707, 0x21ebcff5, + 0x885e5df6, 0x78bba2ae, 0x8e476778, 0x1a96a94a, + 0xfb21c330, 0x0ba8c353, 0xbd43c2f2, 0x2e90c656, + 0x3cf1ea31, 0xc0376d4c, 0x7da645b9, 0x17a721dd, + 0xf36d91bf, 0xef039f41, 0x170fb94f, 0x412eb43a, + 0xca9bb538, 0x79dbf629, 0x53d8e9d6, 0x6c2873a3, + 0xb20aa7b0, 0x411ea772, 0xd3940300, 0xe3eeb2b1, + 0xb1447842, 0xfa968e41, 0xf86f6d53, 0xea74a6e4, + 0x50017ed1, 0x137b64ef, 0x57aa89e6, 0x58bcfdbf, + 0x313df290, 0xeee35be7, 0xff6371aa, 0x7824087e, + 0x6a6af46a, 0x5eb17e3e, 0x66aa29f1, 0x390d2224, + 0x9a3103f4, 0xe917080f, 0x8f14c563, 0x7fa6073a, + 0x3dc5a464, 0x83429234, 0x33e53a2e, 0x53ac6111, + 0x66c554d2, 0xbc1aa8c6, 0xa6c8643b, 0x3dea0eca, + 0x30449e5d, 0x2a9877e5, 0x559ca66d, 0x6514aa69, + 0x6c69e2a4, 0xdbfe8dfb, 0xfdf29c50, 0x6f437112, + 0x51d9f7d1, 0x030c0ae4, 0xb1805d8e, 0xa58131b6, + 0xf8f278b0, 0x8c213886, 0x64704d93, 0x494d9951, + 0x2c6021ab, 0xff3efcae, 0x36834cdf, 0xccd660bf, + 0xc058237d, 0xbd527c49, 0x16574e3d, 0x235ea78c, + 0x670a728f, 0xc3ea2598, 0x87d9124b, 0x4b147e87, + 0x31b49aff, 0x16bd0265, 0x2ee20101, 0x8782f2e1, + 0xfba8663d, 0xa89589ee, 0x83b536c7, 0x27fcab8b, + 0xcca38f50, 0x1b0bad50, 0x308efb8b, 0xd8c736ed, + 0x7730e97b, 0x91ea5131, 0xfbcc9fbe, 0x29365daa, + 0xe02916f6, 0xf0c27e05, 0xceda5df1, 0x34ee39a3, + 0x1375df92, 0x710a961e, 0x450ed796, 0xcdae04b7, + 0x89b701c0, 0x1280670a, 0xb0477c8d, 0x8e18717e, + 0x4b1f7f00, 0xfbaa0da9, 0x5adbcf4e, 0x11244a8b, + 0x65846f9c, 0xe5c460bd, 0x75992da6, 0xa302551a, + 0x073443d7, 0x1c8b99d1, 0x6fec0447, 0xc1a17c28, + 0x931f3aea, 0x6fa840bd, 0x6f6d19bd, 0xac13195a, + 0x2e4cc277, 0xb0a7f22b, 0x3b66eb78, 0x118dc92f, + 0x99bf634e, 0xfdc075d3, 0x3812edf6, 0xa9bc9863, + 0xa73adaab, 0x26eebd69, 0xfcacdf51, 0x219f808f, + 0x3a860155, 0xeffed15c, 0xa68b41a9, 0x51341a4d, + 0x94262c2a, 0xcfa064ee, 0x4add813b, 0x1f9a2384, + 0x95b0c413, 0x10b1c740, 0xcfcb4015, 0xd47df89f, + 0xcb1ced78, 0xe82e2b5d, 0x0509bfbe, 0xd6e567cd, + 0x47c63990, 0x2797cd61, 0x0b23673b, 0x02c9558e, + 0xd10f8637, 0xb0b74f37, 0xf815f24d, 0xcff48230, + 0x63b2632a, 0xb505c39e, 0x2ee5ecd6, 0x7e275fff, + 0xdc528dcc, 0x181e426e, 0x0f61bbb2, 0x5b805240, + 0x6ed556d2, 0x021b8d45, 0x7a399a7e, 0x038ddd4f, + 0xa3830f78, 0xcba6400d, 0x250da41f, 0x269e4863, + 0xc40dee2e, 0xf31b451d, 0xe12831ec, 0x0233f1db, + 0xfde934c5, 0xb72dc8d5, 0xc7059be7, 0x34a11f1d, + 0x02abc4a0, 0x48bfb4eb, 0xafdaaa5f, 0xff416152, + 0x9a47b765, 0x42f8cfe9, 0x85b7d7d8, 0x5bd1c0a5, + 0x6e630534, 0x3dbbf977, 0xba09d82d, 0x82d0bfc3, + 0x5127bb6c, 0xdc15a078, 0xa17fb836, 0xa1fcf1b7, + 0x652dc96b, 0xad3f7c1c, 0x8ba84f6e, 0x8b454c78, + 0xd78ff2f1, 0x9449c56a, 0x2bc9ab5f, 0x15d39aae, + 0x501a09f2, 0x2f94aadb, 0x4fbb92d4, 0xc3f86f8f, + 0xd7372c17, 0xe69d7c19, 0xf0e03d13, 0x0221c7dd, + 0xb41a6236, 0xd9d517ef, 0x6267dfa1, 0xfc341357, + 0xb128aa71, 0xed797b03, 0xbf7ec359, 0x97d4ba34, + 0x47c127de, 0x8dafe9e7, 0xc33227c4, 0x9b8b5274, + 0x6fd5ecd1, 0x9751158b, 0xe3045a12, 0x6bd7a121, + 0x32f09731, 0x063ac542, 0xdc800b17, 0x107d33c7, + 0xada5c07b, 0xa6ec05b4, 0xe5681e29, 0x65c5d6bd, + 0xdd811551, 0x0eed9893, 0x5532e0c7, 0x766e6d14, + 0x74f5c2b7, 0x8c3a64e4, 0xede1d969, 0xfc70b733, + 0xf1dbc965, 0x919af426, 0xe19121d8, 0xeffc6577, + 0x5e87b1cb, 0x62c19cb3, 0x51358ff6, 0xdd366c74, + 0x78830da7, 0x6885d628, 0x4855c5d4, 0x729df091, + 0x736e2e59, 0xa29a58ac, 0x28d0a070, 0x5b2d472b, + 0x319b794d, 0x218f1457, 0x10f56298, 0x00977b80, + 0x9766ce20, 0x5109c226, 0x057b67ac, 0x432a7df7, + 0x915a8464, 0x1f75cc31, 0x9019204c, 0x8e4ba49d, + 0x80a5a121, 0xbda48f11, 0x12d69925, 0xf18f6be3, + 0x0472067e, 0xc61d82aa, 0x474ed278, 0x0fd576f4, + 0x821d8a25, 0x190aacd0, 0x407fbcfd, 0xc6f8a72c, + 0x616e1154, 0x9f03dc6a, 0xcce5c742, 0x6bfbc28e, + 0xad360bb0, 0x72389018, 0x45ee84b0, 0x58b68943, + 0xac08e844, 0xa2ab1783, 0xb10d1dcb, 0x51784a73, + 0x0ff46a4c, 0xe76d72c8, 0x9605e763, 0xfa200113, + 0x8f6615af, 0x1434afb7, 0x151ab4b7, 0x2b96c172, diff --git a/src/soc/intel/broadwell/microcode/microcode_blob.c b/src/soc/intel/broadwell/microcode/microcode_blob.c new file mode 100644 index 0000000000..62468dd25f --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode_blob.c @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +unsigned microcode[] = { +#include "microcode_blob.h" +}; + diff --git a/src/soc/intel/broadwell/microcode/microcode_blob.h b/src/soc/intel/broadwell/microcode/microcode_blob.h new file mode 100644 index 0000000000..fa3e6a6f59 --- /dev/null +++ b/src/soc/intel/broadwell/microcode/microcode_blob.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "microcode-M7240651_0000001C.h" /* Haswell ULT C0 or D0 */ +#include "microcode-MF2306D2_FFFF0009.h" /* Broadwell C0 */ +#include "microcode-MC0306D3_FFFF0010.h" /* Broadwell D0 */ +#include "microcode-MC0306D4_00000018.h" /* Broadwell E0/F0 */ + + /* Dummy terminator */ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, diff --git a/src/soc/intel/broadwell/minihd.c b/src/soc/intel/broadwell/minihd.c new file mode 100644 index 0000000000..c20bbf6894 --- /dev/null +++ b/src/soc/intel/broadwell/minihd.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const u32 minihd_verb_table[] = { + /* coreboot specific header */ + 0x80862807, // Codec Vendor / Device ID: Intel Mini-HD + 0x00000000, // Subsystem ID + 0x00000004, // Number of jacks + + /* Enable 3rd Pin and Converter Widget */ + 0x00878101, + + /* Pin Widget 5 - PORT B */ + 0x00571C10, + 0x00571D00, + 0x00571E56, + 0x00571F18, + + /* Pin Widget 6 - PORT C */ + 0x00671C20, + 0x00671D00, + 0x00671E56, + 0x00671F18, + + /* Pin Widget 7 - PORT D */ + 0x00771C30, + 0x00771D00, + 0x00771E56, + 0x00771F18, + + /* Disable 3rd Pin and Converter Widget */ + 0x00878100, + + /* Dummy entries to fill out the table */ + 0x00878100, + 0x00878100, +}; + +static void minihd_init(struct device *dev) +{ + struct resource *res; + u32 base, reg32; + int codec_mask, i; + + /* Find base address */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "Mini-HD: base = %08x\n", (u32)base); + + /* Set Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER); + + /* Mini-HD configuration */ + reg32 = read32(base + 0x100c); + reg32 &= 0xfffc0000; + reg32 |= 0x4; + write32(base + 0x100c, reg32); + + reg32 = read32(base + 0x1010); + reg32 &= 0xfffc0000; + reg32 |= 0x4b; + write32(base + 0x1010, reg32); + + /* Init the codec and write the verb table */ + codec_mask = hda_codec_detect(base); + + if (codec_mask) { + for (i = 3; i >= 0; i--) { + if (codec_mask & (1 << i)) + hda_codec_init(base, i, + sizeof(minihd_verb_table), + minihd_verb_table); + } + } +} + +static struct device_operations minihd_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &minihd_init, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x0a0c, /* Haswell */ + 0x160c, /* Broadwell */ + 0 +}; + +static const struct pci_driver minihd_driver __pci_driver = { + .ops = &minihd_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/monotonic_timer.c b/src/soc/intel/broadwell/monotonic_timer.c new file mode 100644 index 0000000000..39134ef20a --- /dev/null +++ b/src/soc/intel/broadwell/monotonic_timer.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +static struct monotonic_counter { + int initialized; + struct mono_time time; + uint32_t last_value; +} mono_counter; + +static inline uint32_t read_counter_msr(void) +{ + /* Even though the MSR is 64-bit it is assumed that the hardware + * is polled frequently enough to only use the lower 32-bits. */ + msr_t counter_msr; + + counter_msr = rdmsr(MSR_COUNTER_24_MHZ); + + return counter_msr.lo; +} + +void timer_monotonic_get(struct mono_time *mt) +{ + uint32_t current_tick; + uint32_t usecs_elapsed; + + if (!mono_counter.initialized) { + mono_counter.last_value = read_counter_msr(); + mono_counter.initialized = 1; + } + + current_tick = read_counter_msr(); + usecs_elapsed = (current_tick - mono_counter.last_value) / 24; + + /* Update current time and tick values only if a full tick occurred. */ + if (usecs_elapsed) { + mono_time_add_usecs(&mono_counter.time, usecs_elapsed); + mono_counter.last_value = current_tick; + } + + /* Save result. */ + *mt = mono_counter.time; +} diff --git a/src/soc/intel/broadwell/pch.c b/src/soc/intel/broadwell/pch.c new file mode 100644 index 0000000000..75ef718828 --- /dev/null +++ b/src/soc/intel/broadwell/pch.c @@ -0,0 +1,221 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +u8 pch_revision(void) +{ + return pci_read_config8(PCH_DEV_LPC, PCI_REVISION_ID); +} + +u16 pch_type(void) +{ + return pci_read_config16(PCH_DEV_LPC, PCI_DEVICE_ID); +} + +/* Return 1 if PCH type is WildcatPoint */ +int pch_is_wpt(void) +{ + return ((pch_type() & 0xfff0) == 0x9cc0) ? 1 : 0; +} + +/* Return 1 if PCH type is WildcatPoint ULX */ +int pch_is_wpt_ulx(void) +{ + u16 lpcid = pch_type(); + + switch (lpcid) { + case PCH_WPT_BDW_Y_SAMPLE: + case PCH_WPT_BDW_Y_PREMIUM: + case PCH_WPT_BDW_Y_BASE: + return 1; + } + + return 0; +} + +u32 pch_read_soft_strap(int id) +{ + u32 fdoc; + + fdoc = SPIBAR32(SPIBAR_FDOC); + fdoc &= ~0x00007ffc; + SPIBAR32(SPIBAR_FDOC) = fdoc; + + fdoc |= 0x00004000; + fdoc |= id * 4; + SPIBAR32(SPIBAR_FDOC) = fdoc; + + return SPIBAR32(SPIBAR_FDOD); +} + +#ifndef __PRE_RAM__ + +/* Put device in D3Hot Power State */ +static void pch_enable_d3hot(device_t dev) +{ + u32 reg32 = pci_read_config32(dev, PCH_PCS); + reg32 |= PCH_PCS_PS_D3HOT; + pci_write_config32(dev, PCH_PCS, reg32); +} + +/* RCBA function disable and posting read to flush the transaction */ +static void rcba_function_disable(u32 reg, u32 bit) +{ + RCBA32_OR(reg, bit); + RCBA32(reg); +} + +/* Set bit in Function Disble register to hide this device */ +void pch_disable_devfn(device_t dev) +{ + switch (dev->path.pci.devfn) { + case PCH_DEVFN_ADSP: /* Audio DSP */ + rcba_function_disable(FD, PCH_DISABLE_ADSPD); + break; + case PCH_DEVFN_XHCI: /* XHCI */ + rcba_function_disable(FD, PCH_DISABLE_XHCI); + break; + case PCH_DEVFN_SDMA: /* DMA */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_I2C0: /* I2C0 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_I2C1: /* I2C1 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_SPI0: /* SPI0 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_SPI1: /* SPI1 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_UART0: /* UART0 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_UART1: /* UART1 */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_ME: /* MEI #1 */ + rcba_function_disable(FD2, PCH_DISABLE_MEI1); + break; + case PCH_DEVFN_ME_2: /* MEI #2 */ + rcba_function_disable(FD2, PCH_DISABLE_MEI2); + break; + case PCH_DEVFN_ME_IDER: /* IDE-R */ + rcba_function_disable(FD2, PCH_DISABLE_IDER); + break; + case PCH_DEVFN_ME_KT: /* KT */ + rcba_function_disable(FD2, PCH_DISABLE_KT); + break; + case PCH_DEVFN_SDIO: /* SDIO */ + pch_enable_d3hot(dev); + pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS); + break; + case PCH_DEVFN_GBE: /* Gigabit Ethernet */ + rcba_function_disable(BUC, PCH_DISABLE_GBE); + break; + case PCH_DEVFN_HDA: /* HD Audio Controller */ + rcba_function_disable(FD, PCH_DISABLE_HD_AUDIO); + break; + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 0): /* PCI Express Root Port 1 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 1): /* PCI Express Root Port 2 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 2): /* PCI Express Root Port 3 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 3): /* PCI Express Root Port 4 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 4): /* PCI Express Root Port 5 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 5): /* PCI Express Root Port 6 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 6): /* PCI Express Root Port 7 */ + case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 7): /* PCI Express Root Port 8 */ + rcba_function_disable(FD, + PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn))); + break; + case PCH_DEVFN_EHCI: /* EHCI #1 */ + rcba_function_disable(FD, PCH_DISABLE_EHCI1); + break; + case PCH_DEVFN_LPC: /* LPC */ + rcba_function_disable(FD, PCH_DISABLE_LPC); + break; + case PCH_DEVFN_SATA: /* SATA #1 */ + rcba_function_disable(FD, PCH_DISABLE_SATA1); + break; + case PCH_DEVFN_SMBUS: /* SMBUS */ + rcba_function_disable(FD, PCH_DISABLE_SMBUS); + break; + case PCH_DEVFN_SATA2: /* SATA #2 */ + rcba_function_disable(FD, PCH_DISABLE_SATA2); + break; + case PCH_DEVFN_THERMAL: /* Thermal Subsystem */ + rcba_function_disable(FD, PCH_DISABLE_THERMAL); + break; + } +} + +void broadwell_pch_enable_dev(device_t dev) +{ + u32 reg32; + + /* These devices need special enable/disable handling */ + switch (PCI_SLOT(dev->path.pci.devfn)) { + case PCH_DEV_SLOT_PCIE: + case PCH_DEV_SLOT_EHCI: + case PCH_DEV_SLOT_HDA: + return; + } + + if (!dev->enabled) { + printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); + + /* Ensure memory, io, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Disable this device if possible */ + pch_disable_devfn(dev); + } else { + /* Enable SERR */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_SERR; + pci_write_config32(dev, PCI_COMMAND, reg32); + } +} + +#endif diff --git a/src/soc/intel/broadwell/pcie.c b/src/soc/intel/broadwell/pcie.c new file mode 100644 index 0000000000..b58db42b43 --- /dev/null +++ b/src/soc/intel/broadwell/pcie.c @@ -0,0 +1,697 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or); +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or); + +/* Low Power variant has 6 root ports. */ +#define NUM_ROOT_PORTS 6 + +struct root_port_config { + /* RPFN is a write-once register so keep a copy until it is written */ + u32 orig_rpfn; + u32 new_rpfn; + u32 pin_ownership; + u32 strpfusecfg1; + u32 strpfusecfg2; + u32 strpfusecfg3; + u32 b0d28f0_32c; + u32 b0d28f4_32c; + u32 b0d28f5_32c; + int coalesce; + int gbe_port; + int num_ports; + device_t ports[NUM_ROOT_PORTS]; +}; + +static struct root_port_config rpc; + +static inline int root_port_is_first(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) == 0; +} + +static inline int root_port_is_last(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1); +} + +/* Root ports are numbered 1..N in the documentation. */ +static inline int root_port_number(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) + 1; +} + +static void root_port_config_update_gbe_port(void) +{ + /* Is the Gbe Port enabled? */ + if (!((rpc.strpfusecfg1 >> 19) & 1)) + return; + + switch ((rpc.strpfusecfg1 >> 16) & 0x7) { + case 0: + rpc.gbe_port = 3; + break; + case 1: + rpc.gbe_port = 4; + break; + case 2: + case 3: + case 4: + case 5: + /* Lanes 0-4 of Root Port 5. */ + rpc.gbe_port = 5; + break; + default: + printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n"); + } +} + +static void pcie_iosf_port_grant_count(device_t dev) +{ + u8 update_val; + u32 rpcd = (pci_read_config32(dev, 0xfc) > 14) & 0x3; + + switch (rpcd) { + case 1: + case 3: + update_val = 0x02; + break; + case 2: + update_val = 0x22; + break; + default: + update_val = 0x00; + break; + } + + RCBA32(0x103C) = (RCBA32(0x103C) & (~0xff)) | update_val; +} + +static void root_port_init_config(device_t dev) +{ + int rp; + u32 data; + u8 resp, id; + + if (root_port_is_first(dev)) { + rpc.orig_rpfn = RCBA32(RPFN); + rpc.new_rpfn = rpc.orig_rpfn; + rpc.num_ports = NUM_ROOT_PORTS; + rpc.gbe_port = -1; + /* RP0 f5[3:0] = 0101b*/ + pcie_update_cfg8(dev, 0xf5, ~0xa, 0x5); + + pcie_iosf_port_grant_count(dev); + + rpc.pin_ownership = pci_read_config32(dev, 0x410); + root_port_config_update_gbe_port(); + + pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4)); + if (dev->chip_info != NULL) { + config_t *config = dev->chip_info; + rpc.coalesce = config->pcie_port_coalesce; + } + } + + rp = root_port_number(dev); + if (rp > rpc.num_ports) { + printk(BIOS_ERR, "Found Root Port %d, expecting %d\n", + rp, rpc.num_ports); + return; + } + + /* Read the fuse configuration and pin ownership. */ + switch (rp) { + case 1: + rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc); + rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c); + break; + case 5: + rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc); + rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c); + break; + case 6: + rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c); + rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc); + break; + default: + break; + } + + pcie_update_cfg(dev, 0x418, 0, 0x02000430); + + if (root_port_is_first(dev)) { + /* + * set RP0 PCICFG E2h[5:4] = 11b and E1h[6] = 1 + * before configuring ASPM + */ + id = 0xe0 + (u8)(RCBA32(RPFN) & 0x07); + pch_iobp_exec(0xE00000E0, IOBP_PCICFG_READ, id, &data, &resp); + data |= ((0x30 << 16) | (0x40 << 8)); + pch_iobp_exec(0xE00000E0, IOBP_PCICFG_WRITE, id, &data, &resp); + } + + /* Cache pci device. */ + rpc.ports[rp - 1] = dev; +} + +/* Update devicetree with new Root Port function number assignment */ +static void pch_pcie_device_set_func(int index, int pci_func) +{ + device_t dev; + unsigned new_devfn; + + dev = rpc.ports[index]; + + /* Set the new PCI function field for this Root Port. */ + rpc.new_rpfn &= ~RPFN_FNMASK(index); + rpc.new_rpfn |= RPFN_FNSET(index, pci_func); + + /* Determine the new devfn for this port */ + new_devfn = PCI_DEVFN(PCH_DEV_SLOT_PCIE, pci_func); + + if (dev->path.pci.devfn != new_devfn) { + printk(BIOS_DEBUG, + "PCH: PCIe map %02x.%1x -> %02x.%1x\n", + PCI_SLOT(dev->path.pci.devfn), + PCI_FUNC(dev->path.pci.devfn), + PCI_SLOT(new_devfn), PCI_FUNC(new_devfn)); + + dev->path.pci.devfn = new_devfn; + } +} + +static void pcie_enable_clock_gating(void) +{ + int i; + int enabled_ports = 0; + int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT); + + for (i = 0; i < rpc.num_ports; i++) { + device_t dev; + int rp; + + dev = rpc.ports[i]; + rp = root_port_number(dev); + + if (!dev->enabled) { + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || rp == 6) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + + pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4)); + pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31)); + + /* Per-Port CLKREQ# handling. */ + if (gpio_is_native(18 + rp - 1)) + pcie_update_cfg(dev, 0x420, ~0, (3 << 29)); + + /* Enable static clock gating. */ + if (rp == 1 && !rpc.ports[1]->enabled && + !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } else if (rp == 5 || rp == 6) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + continue; + } + + enabled_ports++; + + /* Enable dynamic clock gating. */ + pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03); + pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6)); + pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2)); + + /* Update PECR1 register. */ + pcie_update_cfg8(dev, 0xe8, ~0, 3); + if (is_broadwell) { + pcie_update_cfg(dev, 0x324, ~((1 << 5) | (1 << 14)), + ((1 << 5) | (1 << 14))); + } else { + pcie_update_cfg(dev, 0x324, ~(1 << 5), (1 << 5)); + } + /* Per-Port CLKREQ# handling. */ + if (gpio_is_native(18 + rp - 1)) + /* + * In addition to D28Fx PCICFG 420h[30:29] = 11b, + * set 420h[17] = 0b and 420[0] = 1b for L1 SubState. + */ + pcie_update_cfg(dev, 0x420, ~0x20000, (3 << 29) | 1); + + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || rp == 6) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + + /* CLKREQ# VR Idle Enable */ + RCBA32_OR(0x2b1c, (1 << (16 + i))); + } + + if (!enabled_ports) + pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6)); +} + +static void root_port_commit_config(void) +{ + int i; + + /* If the first root port is disabled the coalesce ports. */ + if (!rpc.ports[0]->enabled) + rpc.coalesce = 1; + + /* Perform clock gating configuration. */ + pcie_enable_clock_gating(); + + for (i = 0; i < rpc.num_ports; i++) { + device_t dev; + u32 reg32; + + dev = rpc.ports[i]; + + if (dev == NULL) { + printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1); + continue; + } + + if (dev->enabled) + continue; + + printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); + + /* Ensure memory, io, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Disable this device if possible */ + pch_disable_devfn(dev); + } + + if (rpc.coalesce) { + int current_func; + + /* For all Root Ports N enabled ports get assigned the lower + * PCI function number. The disabled ones get upper PCI + * function numbers. */ + current_func = 0; + for (i = 0; i < rpc.num_ports; i++) { + if (!rpc.ports[i]->enabled) + continue; + pch_pcie_device_set_func(i, current_func); + current_func++; + } + + /* Allocate the disabled devices' PCI function number. */ + for (i = 0; i < rpc.num_ports; i++) { + if (rpc.ports[i]->enabled) + continue; + pch_pcie_device_set_func(i, current_func); + current_func++; + } + } + + printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n", + rpc.orig_rpfn, rpc.new_rpfn); + RCBA32(RPFN) = rpc.new_rpfn; +} + +static void root_port_mark_disable(device_t dev) +{ + /* Mark device as disabled. */ + dev->enabled = 0; + /* Mark device to be hidden. */ + rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn)); +} + +static void root_port_check_disable(device_t dev) +{ + int rp; + + /* Device already disabled. */ + if (!dev->enabled) { + root_port_mark_disable(dev); + return; + } + + rp = root_port_number(dev); + + /* Is the GbE port mapped to this Root Port? */ + if (rp == rpc.gbe_port) { + root_port_mark_disable(dev); + return; + } + + /* Check Root Port Configuration. */ + switch (rp) { + case 2: + /* Root Port 2 is disabled for all lane configurations + * but config 00b (4x1 links). */ + if ((rpc.strpfusecfg1 >> 14) & 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 3: + /* Root Port 3 is disabled in config 11b (1x4 links). */ + if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 4: + /* Root Port 4 is disabled in configs 11b (1x4 links) + * and 10b (2x2 links). */ + if ((rpc.strpfusecfg1 >> 14) & 0x2) { + root_port_mark_disable(dev); + return; + } + break; + } + + /* Check Pin Ownership. */ + switch (rp) { + case 1: + /* Bit 0 is Root Port 1 ownership. */ + if ((rpc.pin_ownership & 0x1) == 0) { + root_port_mark_disable(dev); + return; + } + break; + case 2: + /* Bit 2 is Root Port 2 ownership. */ + if ((rpc.pin_ownership & 0x4) == 0) { + root_port_mark_disable(dev); + return; + } + break; + case 6: + /* Bits 7:4 are Root Port 6 pin-lane ownership. */ + if ((rpc.pin_ownership & 0xf0) == 0) { + root_port_mark_disable(dev); + return; + } + break; + } +} + +static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or) +{ + u8 reg8; + + reg8 = pci_read_config8(dev, reg); + reg8 &= mask; + reg8 |= or; + pci_write_config8(dev, reg, reg8); +} + +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or) +{ + u32 reg32; + + reg32 = pci_read_config32(dev, reg); + reg32 &= mask; + reg32 |= or; + pci_write_config32(dev, reg, reg32); +} + +static void pcie_add_0x0202000_iobp(u32 reg) +{ + u32 reg32; + + reg32 = pch_iobp_read(reg); + reg32 += (0x2 << 16) | (0x2 << 8); + pch_iobp_write(reg, reg32); +} + +static void pch_pcie_early(struct device *dev) +{ + config_t *config = dev->chip_info; + int do_aspm = 0; + int rp = root_port_number(dev); + + switch (rp) { + case 1: + case 2: + case 3: + case 4: + /* + * Bits 31:28 of b0d28f0 0x32c register correspnd to + * Root Ports 4:1. + */ + do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1))); + break; + case 5: + /* + * Bit 28 of b0d28f4 0x32c register correspnd to + * Root Ports 4:1. + */ + do_aspm = !!(rpc.b0d28f4_32c & (1 << 28)); + break; + case 6: + /* + * Bit 28 of b0d28f5 0x32c register correspnd to + * Root Ports 4:1. + */ + do_aspm = !!(rpc.b0d28f5_32c & (1 << 28)); + break; + } + + /* Allow ASPM to be forced on in devicetree */ + if (config && (config->pcie_port_force_aspm & (1 << (rp - 1)))) + do_aspm = 1; + + printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n", + rp, do_aspm ? "en" : "dis"); + + if (do_aspm) { + /* Set ASPM bits in MPC2 register. */ + pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2)); + + /* Set unique clock exit latency in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18)); + + switch (rp) { + case 1: + pcie_add_0x0202000_iobp(0xe9002440); + break; + case 2: + pcie_add_0x0202000_iobp(0xe9002640); + break; + case 3: + pcie_add_0x0202000_iobp(0xe9000840); + break; + case 4: + pcie_add_0x0202000_iobp(0xe9000a40); + break; + case 5: + pcie_add_0x0202000_iobp(0xe9000c40); + pcie_add_0x0202000_iobp(0xe9000e40); + pcie_add_0x0202000_iobp(0xe9001040); + pcie_add_0x0202000_iobp(0xe9001240); + break; + case 6: + /* Update IOBP based on lane ownership. */ + if (rpc.pin_ownership & (1 << 4)) + pcie_add_0x0202000_iobp(0xea002040); + if (rpc.pin_ownership & (1 << 5)) + pcie_add_0x0202000_iobp(0xea002240); + if (rpc.pin_ownership & (1 << 6)) + pcie_add_0x0202000_iobp(0xea002440); + if (rpc.pin_ownership & (1 << 7)) + pcie_add_0x0202000_iobp(0xea002640); + break; + } + + pcie_update_cfg(dev, 0x338, ~(1 << 26), 0); + } + + /* Enable LTR in Root Port. Disbale OBFF. */ + pcie_update_cfg(dev, 0x64, ~(1 << 11) & ~(3 << 18), (1 << 11)); + pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10)); + + pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16)); + + /* Set L1 exit latency in LCAP register. */ + if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1)) + pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15)); + else + pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15)); + + pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b); + + /* Set Common Clock Exit Latency in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15)); + + pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74); + + /* Set Invalid Recieve Range Check Enable in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~0, (1 << 25)); + + pcie_update_cfg8(dev, 0xf5, 0x0f, 0); + + /* Set AER Extended Cap ID to 01h and Next Cap Pointer to 200h. */ + pcie_update_cfg(dev, 0x100, ~(1 << 29) & ~0xfffff, (1 << 29) | 0x10001); + + /* Set L1 Sub-State Cap ID to 1Eh and Next Cap Pointer to None. */ + pcie_update_cfg(dev, 0x200, ~0xffff, 0x001e); + + pcie_update_cfg(dev, 0x320, ~(3 << 20) & ~(7 << 6), + (1 << 20) | (3 << 6)); + /* Enable Relaxed Order from Root Port. */ + pcie_update_cfg(dev, 0x320, ~(3 << 23), (3 << 23)); + + if (rp == 1 || rp == 5 || rp == 6) + pcie_update_cfg8(dev, 0xf7, ~0xc, 0); + + /* Set EOI forwarding disable. */ + pcie_update_cfg(dev, 0xd4, ~0, (1 << 1)); + + /* Read and write back write-once capability registers. */ + pcie_update_cfg(dev, 0x34, ~0, 0); + pcie_update_cfg(dev, 0x40, ~0, 0); + pcie_update_cfg(dev, 0x80, ~0, 0); + pcie_update_cfg(dev, 0x90, ~0, 0); +} + +static void pch_pcie_init(struct device *dev) +{ + u16 reg16; + u32 reg32; + + printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n"); + + /* Enable SERR */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_SERR; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Enable Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Set Cache Line Size to 0x10 */ + pci_write_config8(dev, 0x0c, 0x10); + + reg16 = pci_read_config16(dev, 0x3e); + reg16 &= ~(1 << 0); /* disable parity error response */ + reg16 |= (1 << 2); /* ISA enable */ + pci_write_config16(dev, 0x3e, reg16); + +#ifdef EVEN_MORE_DEBUG + reg32 = pci_read_config32(dev, 0x20); + printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32); + reg32 = pci_read_config32(dev, 0x24); + printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32); + reg32 = pci_read_config32(dev, 0x28); + printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32); + reg32 = pci_read_config32(dev, 0x2c); + printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32); +#endif + + /* Clear errors in status registers */ + reg16 = pci_read_config16(dev, 0x06); + pci_write_config16(dev, 0x06, reg16); + reg16 = pci_read_config16(dev, 0x1e); + pci_write_config16(dev, 0x1e, reg16); +} + +static void pch_pcie_enable(device_t dev) +{ + /* Add this device to the root port config structure. */ + root_port_init_config(dev); + + /* Check to see if this Root Port should be disabled. */ + root_port_check_disable(dev); + + /* Power Management init before enumeration */ + if (dev->enabled) + pch_pcie_early(dev); + + /* + * When processing the last PCIe root port we can now + * update the Root Port Function Number and Hide register. + */ + if (root_port_is_last(dev)) + root_port_commit_config(); +} + +static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + /* NOTE: This is not the default position! */ + if (!vendor || !device) + pci_write_config32(dev, 0x94, pci_read_config32(dev, 0)); + else + pci_write_config32(dev, 0x94, (device << 16) | vendor); +} + +static void pcie_set_L1_ss_max_latency(device_t dev, unsigned int off) +{ + /* Set max snoop and non-snoop latency for Broadwell */ + pci_mmio_write_config32(dev, off, 0x10031003); +} + +static struct pci_operations pcie_ops = { + .set_subsystem = pcie_set_subsystem, + .set_L1_ss_latency = pcie_set_L1_ss_max_latency, +}; + +static struct device_operations device_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = pch_pcie_init, + .enable = pch_pcie_enable, + .scan_bus = pciexp_scan_bridge, + .ops_pci = &pcie_ops, +}; + +static const unsigned short pcie_device_ids[] = { + /* Lynxpoint-LP */ + 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a, + /* WildcatPoint */ + 0x9c90, 0x9c92, 0x9c94, 0x9c96, 0x9c98, 0x9c9a, 0x2448, + 0 +}; + +static const struct pci_driver pch_pcie __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pcie_device_ids, +}; diff --git a/src/soc/intel/broadwell/pei_data.c b/src/soc/intel/broadwell/pei_data.c new file mode 100644 index 0000000000..03ed1421a8 --- /dev/null +++ b/src/soc/intel/broadwell/pei_data.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static void ABI_X86 send_to_console(unsigned char b) +{ + console_tx_byte(b); +} + +void broadwell_fill_pei_data(struct pei_data *pei_data) +{ + pei_data->pei_version = PEI_VERSION; + pei_data->board_type = BOARD_TYPE_ULT; + pei_data->usbdebug = CONFIG_USBDEBUG; + pei_data->pciexbar = MCFG_BASE_ADDRESS; + pei_data->smbusbar = SMBUS_BASE_ADDRESS; + pei_data->ehcibar = EARLY_EHCI_BAR; + pei_data->xhcibar = EARLY_XHCI_BAR; + pei_data->gttbar = EARLY_GTT_BAR; + pei_data->pmbase = ACPI_BASE_ADDRESS; + pei_data->gpiobase = GPIO_BASE_ADDRESS; + pei_data->tseg_size = smm_region_size(); + pei_data->temp_mmio_base = EARLY_TEMP_MMIO; + pei_data->tx_byte = &send_to_console; +} diff --git a/src/soc/intel/broadwell/pmutil.c b/src/soc/intel/broadwell/pmutil.c new file mode 100644 index 0000000000..7686387f97 --- /dev/null +++ b/src/soc/intel/broadwell/pmutil.c @@ -0,0 +1,452 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Helper functions for dealing with power management registers + * and the differences between PCH variants. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Print status bits with descriptive names */ +static void print_status_bits(u32 status, const char *bit_names[]) +{ + int i; + + if (!status) + return; + + for (i=31; i>=0; i--) { + if (status & (1 << i)) { + if (bit_names[i]) + printk(BIOS_DEBUG, "%s ", bit_names[i]); + else + printk(BIOS_DEBUG, "BIT%d ", i); + } + } +} + +/* Print status bits as GPIO numbers */ +static void print_gpio_status(u32 status, int start) +{ + int i; + + if (!status) + return; + + for (i=31; i>=0; i--) { + if (status & (1 << i)) + printk(BIOS_DEBUG, "GPIO%d ", start + i); + } +} + + +/* + * PM1_CNT + */ + +/* Enable events in PM1 control register */ +void enable_pm1_control(u32 mask) +{ + u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + pm1_cnt |= mask; + outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT); +} + +/* Disable events in PM1 control register */ +void disable_pm1_control(u32 mask) +{ + u32 pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + pm1_cnt &= ~mask; + outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT); +} + + +/* + * PM1 + */ + +/* Clear and return PM1 status register */ +static u16 reset_pm1_status(void) +{ + u16 pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS); + outw(pm1_sts, ACPI_BASE_ADDRESS + PM1_STS); + return pm1_sts; +} + +/* Print PM1 status bits */ +static u16 print_pm1_status(u16 pm1_sts) +{ + const char *pm1_sts_bits[] = { + [0] = "TMROF", + [4] = "BM", + [5] = "GBL", + [8] = "PWRBTN", + [10] = "RTC", + [11] = "PRBTNOR", + [14] = "PCIEXPWAK", + [15] = "WAK", + }; + + if (!pm1_sts) + return 0; + + printk(BIOS_SPEW, "PM1_STS: "); + print_status_bits(pm1_sts, pm1_sts_bits); + printk(BIOS_SPEW, "\n"); + + return pm1_sts; +} + +/* Print, clear, and return PM1 status */ +u16 clear_pm1_status(void) +{ + return print_pm1_status(reset_pm1_status()); +} + +/* Set the PM1 register to events */ +void enable_pm1(u16 events) +{ + outw(events, ACPI_BASE_ADDRESS + PM1_EN); +} + + +/* + * SMI + */ + +/* Clear and return SMI status register */ +static u32 reset_smi_status(void) +{ + u32 smi_sts = inl(ACPI_BASE_ADDRESS + SMI_STS); + outl(smi_sts, ACPI_BASE_ADDRESS + SMI_STS); + return smi_sts; +} + +/* Print SMI status bits */ +static u32 print_smi_status(u32 smi_sts) +{ + const char *smi_sts_bits[] = { + [2] = "BIOS", + [3] = "LEGACY_USB", + [4] = "SLP_SMI", + [5] = "APM", + [6] = "SWSMI_TMR", + [8] = "PM1", + [9] = "GPE0", + [10] = "GPI", + [11] = "MCSMI", + [12] = "DEVMON", + [13] = "TCO", + [14] = "PERIODIC", + [15] = "SERIRQ_SMI", + [16] = "SMBUS_SMI", + [17] = "LEGACY_USB2", + [18] = "INTEL_USB2", + [20] = "PCI_EXP_SMI", + [21] = "MONITOR", + [26] = "SPI", + [27] = "GPIO_UNLOCK" + }; + + if (!smi_sts) + return 0; + + printk(BIOS_DEBUG, "SMI_STS: "); + print_status_bits(smi_sts, smi_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return smi_sts; +} + +/* Print, clear, and return SMI status */ +u32 clear_smi_status(void) +{ + return print_smi_status(reset_smi_status()); +} + +/* Enable SMI event */ +void enable_smi(u32 mask) +{ + u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN); + smi_en |= mask; + outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN); +} + +/* Disable SMI event */ +void disable_smi(u32 mask) +{ + u32 smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN); + smi_en &= ~mask; + outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN); +} + + +/* + * ALT_GP_SMI + */ + +/* Clear GPIO SMI status and return events that are enabled and active */ +static u32 reset_alt_smi_status(void) +{ + u32 alt_sts, alt_en; + + /* Low Power variant moves this to GPIO region as dword */ + alt_sts = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS); + outl(alt_sts, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_STS); + alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN); + + /* Only report enabled events */ + return alt_sts & alt_en; +} + +/* Print GPIO SMI status bits */ +static u32 print_alt_smi_status(u32 alt_sts) +{ + if (!alt_sts) + return 0; + + printk(BIOS_DEBUG, "ALT_STS: "); + + /* First 16 events are GPIO 32-47 */ + print_gpio_status(alt_sts & 0xffff, 32); + + printk(BIOS_DEBUG, "\n"); + + return alt_sts; +} + +/* Print, clear, and return GPIO SMI status */ +u32 clear_alt_smi_status(void) +{ + return print_alt_smi_status(reset_alt_smi_status()); +} + +/* Enable GPIO SMI events */ +void enable_alt_smi(u32 mask) +{ + u32 alt_en; + + alt_en = inl(GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN); + alt_en |= mask; + outl(alt_en, GPIO_BASE_ADDRESS + GPIO_ALT_GPI_SMI_EN); +} + + +/* + * TCO + */ + +/* Clear TCO status and return events that are enabled and active */ +static u32 reset_tco_status(void) +{ + u32 tcobase = ACPI_BASE_ADDRESS + 0x60; + u32 tco_sts = inl(tcobase + 0x04); + u32 tco_en = inl(ACPI_BASE_ADDRESS + 0x68); + + /* Don't clear BOOT_STS before SECOND_TO_STS */ + outl(tco_sts & ~(1 << 18), tcobase + 0x04); + + /* Clear BOOT_STS */ + if (tco_sts & (1 << 18)) + outl(tco_sts & (1 << 18), tcobase + 0x04); + + return tco_sts & tco_en; +} + +/* Print TCO status bits */ +static u32 print_tco_status(u32 tco_sts) +{ + const char *tco_sts_bits[] = { + [0] = "NMI2SMI", + [1] = "SW_TCO", + [2] = "TCO_INT", + [3] = "TIMEOUT", + [7] = "NEWCENTURY", + [8] = "BIOSWR", + [9] = "DMISCI", + [10] = "DMISMI", + [12] = "DMISERR", + [13] = "SLVSEL", + [16] = "INTRD_DET", + [17] = "SECOND_TO", + [18] = "BOOT", + [20] = "SMLINK_SLV" + }; + + if (!tco_sts) + return 0; + + printk(BIOS_DEBUG, "TCO_STS: "); + print_status_bits(tco_sts, tco_sts_bits); + printk(BIOS_DEBUG, "\n"); + + return tco_sts; +} + +/* Print, clear, and return TCO status */ +u32 clear_tco_status(void) +{ + return print_tco_status(reset_tco_status()); +} + +/* Enable TCO SCI */ +void enable_tco_sci(void) +{ + /* Clear pending events */ + outl(ACPI_BASE_ADDRESS + GPE0_STS(3), TCOSCI_STS); + + /* Enable TCO SCI events */ + enable_gpe(TCOSCI_EN); +} + + +/* + * GPE0 + */ + +/* Clear a GPE0 status and return events that are enabled and active */ +static u32 reset_gpe(u16 sts_reg, u16 en_reg) +{ + u32 gpe0_sts = inl(ACPI_BASE_ADDRESS + sts_reg); + u32 gpe0_en = inl(ACPI_BASE_ADDRESS + en_reg); + + outl(gpe0_sts, ACPI_BASE_ADDRESS + sts_reg); + + /* Only report enabled events */ + return gpe0_sts & gpe0_en; +} + +/* Print GPE0 status bits */ +static u32 print_gpe_status(u32 gpe0_sts, const char *bit_names[]) +{ + if (!gpe0_sts) + return 0; + + printk(BIOS_DEBUG, "GPE0_STS: "); + print_status_bits(gpe0_sts, bit_names); + printk(BIOS_DEBUG, "\n"); + + return gpe0_sts; +} + +/* Print GPE0 GPIO status bits */ +static u32 print_gpe_gpio(u32 gpe0_sts, int start) +{ + if (!gpe0_sts) + return 0; + + printk(BIOS_DEBUG, "GPE0_STS: "); + print_gpio_status(gpe0_sts, start); + printk(BIOS_DEBUG, "\n"); + + return gpe0_sts; +} + +/* Clear all GPE status and return "standard" GPE event status */ +u32 clear_gpe_status(void) +{ + const char *gpe0_sts_3_bits[] = { + [1] = "HOTPLUG", + [2] = "SWGPE", + [6] = "TCO_SCI", + [7] = "SMB_WAK", + [9] = "PCI_EXP", + [10] = "BATLOW", + [11] = "PME", + [12] = "ME", + [13] = "PME_B0", + [16] = "GPIO27", + [18] = "WADT" + }; + + print_gpe_gpio(reset_gpe(GPE0_STS(GPE_31_0), GPE0_EN(GPE_31_0)), 0); + print_gpe_gpio(reset_gpe(GPE0_STS(GPE_63_32), GPE0_EN(GPE_63_32)), 32); + print_gpe_gpio(reset_gpe(GPE0_STS(GPE_94_64), GPE0_EN(GPE_94_64)), 64); + return print_gpe_status(reset_gpe(GPE0_STS(GPE_STD), GPE0_EN(GPE_STD)), + gpe0_sts_3_bits); +} + +/* Enable all requested GPE */ +void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4) +{ + outl(set1, ACPI_BASE_ADDRESS + GPE0_EN(GPE_31_0)); + outl(set2, ACPI_BASE_ADDRESS + GPE0_EN(GPE_63_32)); + outl(set3, ACPI_BASE_ADDRESS + GPE0_EN(GPE_94_64)); + outl(set4, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD)); +} + +/* Disable all GPE */ +void disable_all_gpe(void) +{ + enable_all_gpe(0, 0, 0, 0); +} + +/* Enable a standard GPE */ +void enable_gpe(u32 mask) +{ + u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD)); + gpe0_en |= mask; + outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD)); +} + +/* Disable a standard GPE */ +void disable_gpe(u32 mask) +{ + u32 gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD)); + gpe0_en &= ~mask; + outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(GPE_STD)); +} + +int acpi_sci_irq(void) +{ + int scis = pci_read_config32(PCH_DEV_LPC, ACPI_CNTL) & SCI_IRQ_SEL; + int sci_irq = 9; + + /* Determine how SCI is routed. */ + switch (scis) { + case SCIS_IRQ9: + case SCIS_IRQ10: + case SCIS_IRQ11: + sci_irq = scis - SCIS_IRQ9 + 9; + break; + case SCIS_IRQ20: + case SCIS_IRQ21: + case SCIS_IRQ22: + case SCIS_IRQ23: + sci_irq = scis - SCIS_IRQ20 + 20; + break; + default: + printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n"); + sci_irq = 9; + break; + } + + printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq); + return sci_irq; +} diff --git a/src/soc/intel/broadwell/ramstage.c b/src/soc/intel/broadwell/ramstage.c new file mode 100644 index 0000000000..6377c57048 --- /dev/null +++ b/src/soc/intel/broadwell/ramstage.c @@ -0,0 +1,111 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Save bit index for PM1_STS and GPE_STS for ACPI _SWS */ +static void save_acpi_wake_source(global_nvs_t *gnvs) +{ + struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE); + uint16_t pm1; + int gpe_reg; + + if (!ps) + return; + + pm1 = ps->pm1_sts & ps->pm1_en; + + /* Scan for first set bit in PM1 */ + for (gnvs->pm1i = 0; gnvs->pm1i < 16; gnvs->pm1i++) { + if (pm1 & 1) + break; + pm1 >>= 1; + } + + /* If unable to determine then return -1 */ + if (gnvs->pm1i >= 16) + gnvs->pm1i = -1; + + /* Scan for first set bit in GPE registers */ + gnvs->gpei = -1; + for (gpe_reg = 0; gpe_reg < GPE0_REG_MAX; gpe_reg++) { + u32 gpe = ps->gpe0_sts[gpe_reg] & ps->gpe0_en[gpe_reg]; + int start = gpe_reg * GPE0_REG_SIZE; + int end = start + GPE0_REG_SIZE; + + if (gpe == 0) { + if (!gnvs->gpei) + gnvs->gpei = end; + continue; + } + + for (gnvs->gpei = start; gnvs->gpei < end; gnvs->gpei++) { + if (gpe & 1) + break; + gpe >>= 1; + } + } + + /* If unable to determine then return -1 */ + if (gnvs->gpei >= (GPE0_REG_MAX * GPE0_REG_SIZE)) + gnvs->gpei = -1; + + printk(BIOS_DEBUG, "ACPI _SWS is PM1 Index %lld GPE Index %lld\n", + gnvs->pm1i, gnvs->gpei); +} + +static inline void set_acpi_sleep_type(int val) +{ +#if CONFIG_HAVE_ACPI_RESUME + acpi_slp_type = val; +#endif +} + +static void s3_resume_prepare(void) +{ + global_nvs_t *gnvs; + struct romstage_handoff *romstage_handoff; + + gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t)); + + romstage_handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO); + if (romstage_handoff == NULL || romstage_handoff->s3_resume == 0) { + if (gnvs != NULL) + memset(gnvs, 0, sizeof(global_nvs_t)); + return; + } + + set_acpi_sleep_type(3); + save_acpi_wake_source(gnvs); +} + +void broadwell_init_pre_device(void *chip_info) +{ + s3_resume_prepare(); + broadwell_run_reference_code(); +} diff --git a/src/soc/intel/broadwell/refcode.c b/src/soc/intel/broadwell/refcode.c new file mode 100644 index 0000000000..6e844ed348 --- /dev/null +++ b/src/soc/intel/broadwell/refcode.c @@ -0,0 +1,192 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline int is_s3_resume(void) +{ +#if CONFIG_HAVE_ACPI_RESUME + return acpi_slp_type == 3; +#else + return 0; +#endif +} + +static inline struct ramstage_cache *next_cache(struct ramstage_cache *c) +{ + return (struct ramstage_cache *)&c->program[c->size]; +} + +static pei_wrapper_entry_t load_refcode_from_cache(void) +{ + struct ramstage_cache *c; + long cache_size; + + printk(BIOS_DEBUG, "refcode loading from cache.\n"); + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid ramstage cache descriptor.\n"); + return NULL; + } + + c = next_cache(c); + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "Invalid refcode cache descriptor.\n"); + return NULL; + } + + printk(BIOS_DEBUG, "Loading cached reference code from 0x%08x(%x)\n", + c->load_address, c->size); + memcpy((void *)c->load_address, &c->program[0], c->size); + + return (pei_wrapper_entry_t)c->entry_point; +} + +static void cache_refcode(const struct rmod_stage_load *rsl) +{ + struct ramstage_cache *c; + long cache_size; + + c = ramstage_cache_location(&cache_size); + + if (!ramstage_cache_is_valid(c)) { + printk(BIOS_DEBUG, "No place to cache reference code.\n"); + return; + } + + /* Determine how much remaining cache available. */ + cache_size -= c->size + sizeof(*c); + + if (cache_size < (sizeof(*c) + cbmem_entry_size(rsl->cbmem_entry))) { + printk(BIOS_DEBUG, "Not enough cache space for ref code.\n"); + return; + } + + c = next_cache(c); + c->magic = RAMSTAGE_CACHE_MAGIC; + c->entry_point = (uint32_t)rsl->entry; + c->load_address = (uint32_t)cbmem_entry_start(rsl->cbmem_entry); + c->size = cbmem_entry_size(rsl->cbmem_entry);; + + printk(BIOS_DEBUG, "Caching refcode at 0x%p(%x)\n", + &c->program[0], c->size); + memcpy(&c->program[0], (void *)c->load_address, c->size); +} + +static int load_refcode_from_vboot(struct rmod_stage_load *refcode, + struct cbfs_stage *stage) +{ + printk(BIOS_DEBUG, "refcode loading from vboot rw area.\n"); + + if (rmodule_stage_load(refcode, stage) || refcode->entry == NULL) { + printk(BIOS_DEBUG, "Error loading reference code.\n"); + return -1; + } + return 0; +} + +static int load_refcode_from_cbfs(struct rmod_stage_load *refcode) +{ + printk(BIOS_DEBUG, "refcode loading from cbfs.\n"); + + if (rmodule_stage_load_from_cbfs(refcode) || refcode->entry == NULL) { + printk(BIOS_DEBUG, "Error loading reference code.\n"); + return -1; + } + + return 0; +} + +static pei_wrapper_entry_t load_reference_code(void) +{ + struct vboot_handoff *vboot_handoff; + const struct firmware_component *fwc; + struct rmod_stage_load refcode = { + .cbmem_id = CBMEM_ID_REFCODE, + .name = CONFIG_CBFS_PREFIX "/refcode", + }; + int ret; + + if (is_s3_resume()) { + return load_refcode_from_cache(); + } + + vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + fwc = &vboot_handoff->components[CONFIG_VBOOT_REFCODE_INDEX]; + + if (vboot_handoff == NULL || + vboot_handoff->selected_firmware == VB_SELECT_FIRMWARE_READONLY || + CONFIG_VBOOT_REFCODE_INDEX >= MAX_PARSED_FW_COMPONENTS || + fwc->size == 0 || fwc->address == 0) { + ret = load_refcode_from_cbfs(&refcode); + } else { + ret = load_refcode_from_vboot(&refcode, (void *)fwc->address); + + if (ret < 0) + ret = load_refcode_from_cbfs(&refcode); + } + + if (ret < 0) + return NULL; + + /* Cache loaded reference code. */ + cache_refcode(&refcode); + + return refcode.entry; +} + +void broadwell_run_reference_code(void) +{ + int ret, dummy; + struct pei_data pei_data; + pei_wrapper_entry_t entry; + + memset(&pei_data, 0, sizeof(pei_data)); + mainboard_fill_pei_data(&pei_data); + broadwell_fill_pei_data(&pei_data); + + pei_data.boot_mode = acpi_slp_type; + pei_data.saved_data = (void *) &dummy; + + entry = load_reference_code(); + if (entry == NULL) { + printk(BIOS_ERR, "Reference code not found\n"); + return; + } + + /* Call into reference code. */ + ret = entry(&pei_data); + if (ret != 0) { + printk(BIOS_ERR, "Reference code returned %d\n", ret); + return; + } +} diff --git a/src/soc/intel/broadwell/reset.c b/src/soc/intel/broadwell/reset.c new file mode 100644 index 0000000000..44026ca473 --- /dev/null +++ b/src/soc/intel/broadwell/reset.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +/* + * Soft reset (INIT# to cpu) - write 0x1 to I/O 0x92 + * Soft reset (INIT# to cpu)- write 0x4 to I/0 0xcf9 + * Cold reset (S0->S5->S0) - write 0xe to I/0 0xcf9 + * Warm reset (PLTRST# assertion) - write 0x6 to I/O 0xcf9 + * Global reset (S0->S5->S0 with ME reset) - write 0x6 or 0xe to 0xcf9 but + * with ETR[20] set. + */ + +void soft_reset(void) +{ + outb(0x04, 0xcf9); +} + +void hard_reset(void) +{ + outb(0x06, 0xcf9); +} + +void reset_system(void) +{ + hard_reset(); + while (1) { + hlt(); + } +} diff --git a/src/soc/intel/broadwell/romstage/Makefile.inc b/src/soc/intel/broadwell/romstage/Makefile.inc new file mode 100644 index 0000000000..8486e3f341 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/Makefile.inc @@ -0,0 +1,21 @@ +ifeq ($(CONFIG_HAVE_MRC),y) +cpu_incs += $(src)/soc/intel/broadwell/romstage/cache_as_ram.inc +else +ifeq ($(CONFIG_PLATFORM_USES_FSP),y) +cpu_incs += $(src)/soc/intel/broadwell/romstage/fsp_1_1.inc +endif +endif + +romstage-y += cpu.c +romstage-$(CONFIG_PLATFORM_USES_FSP) += fsp.c +romstage-y += pch.c +romstage-y += power_state.c +romstage-$(CONFIG_HAVE_MRC) += raminit.c +romstage-y += report_platform.c +romstage-y += romstage.c +romstage-y += smbus.c +romstage-y += spi.c +romstage-y += stack.c +romstage-y += systemagent.c +romstage-$(CONFIG_CONSOLE_SERIAL8250MEM) += uart.c + diff --git a/src/soc/intel/broadwell/romstage/cache_as_ram.inc b/src/soc/intel/broadwell/romstage/cache_as_ram.inc new file mode 100644 index 0000000000..1890323527 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/cache_as_ram.inc @@ -0,0 +1,342 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +/* The full cache-as-ram size includes the cache-as-ram portion from coreboot + * and the space used by the reference code. These 2 values combined should + * be a power of 2 because the MTRR setup assumes that. */ +#define CACHE_AS_RAM_SIZE \ + (CONFIG_DCACHE_RAM_SIZE + CONFIG_DCACHE_RAM_MRC_VAR_SIZE) +#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE +#define CACHE_AS_RAM_LIMIT (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE) +#define USBDEBUG_VAR_SIZE 36 /* sizeof(struct ehci_debug_info) */ + +/* Cache 4GB - MRC_SIZE_KB for MRC */ +#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1) +#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES) +#define CACHE_MRC_MASK (~CACHE_MRC_BYTES) + +#define CPU_MAXPHYSADDR CONFIG_CPU_ADDR_BITS +#define CPU_PHYSMASK_HI (1 << (CPU_MAXPHYSADDR - 32) - 1) + +#define NoEvictMod_MSR 0x2e0 + + /* Save the BIST result. */ + movl %eax, %ebp + +cache_as_ram: + post_code(0x20) + + /* Send INIT IPI to all excluding ourself. */ + movl $0x000C4500, %eax + movl $0xFEE00300, %esi + movl %eax, (%esi) + + /* All CPUs need to be in Wait for SIPI state */ +wait_for_sipi: + movl (%esi), %eax + bt $12, %eax + jc wait_for_sipi + + post_code(0x21) + /* Zero out all fixed range and variable range MTRRs. */ + movl $mtrr_table, %esi + movl $((mtrr_table_end - mtrr_table) / 2), %edi + xorl %eax, %eax + xorl %edx, %edx +clear_mtrrs: + movw (%esi), %bx + movzx %bx, %ecx + wrmsr + add $2, %esi + dec %edi + jnz clear_mtrrs + + post_code(0x22) + /* Configure the default memory type to uncacheable. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + andl $(~0x00000cff), %eax + wrmsr + + post_code(0x23) + /* Set Cache-as-RAM base address. */ + movl $(MTRRphysBase_MSR(0)), %ecx + movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax + xorl %edx, %edx + wrmsr + + post_code(0x24) + /* Set Cache-as-RAM mask. */ + movl $(MTRRphysMask_MSR(0)), %ecx + movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $CPU_PHYSMASK_HI, %edx + wrmsr + + post_code(0x25) + + /* Enable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + /* Enable cache (CR0.CD = 0, CR0.NW = 0). */ + movl %cr0, %eax + andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax + invd + movl %eax, %cr0 + + /* enable the 'no eviction' mode */ + movl $NoEvictMod_MSR, %ecx + rdmsr + orl $1, %eax + andl $~2, %eax + wrmsr + + /* Clear the cache memory region. This will also fill up the cache */ + movl $CACHE_AS_RAM_BASE, %esi + movl %esi, %edi + movl $(CACHE_AS_RAM_SIZE / 4), %ecx + xorl %eax, %eax + rep stosl + + /* enable the 'no eviction run' state */ + movl $NoEvictMod_MSR, %ecx + rdmsr + orl $3, %eax + wrmsr + + post_code(0x26) + /* Enable Cache-as-RAM mode by disabling cache. */ + movl %cr0, %eax + orl $CR0_CacheDisable, %eax + movl %eax, %cr0 + + /* Enable cache for our code in Flash because we do XIP here */ + movl $MTRRphysBase_MSR(1), %ecx + xorl %edx, %edx + /* + * IMPORTANT: The following calculation _must_ be done at runtime. See + * http://www.coreboot.org/pipermail/coreboot/2010-October/060855.html + */ + movl $copy_and_run, %eax + andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax + orl $MTRR_TYPE_WRPROT, %eax + wrmsr + + movl $MTRRphysMask_MSR(1), %ecx + movl $CPU_PHYSMASK_HI, %edx + movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax + wrmsr + + post_code(0x27) +#if CONFIG_CACHE_MRC_BIN + /* Enable caching for ram init code to run faster */ + movl $MTRRphysBase_MSR(2), %ecx + movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax + xorl %edx, %edx + wrmsr + movl $MTRRphysMask_MSR(2), %ecx + movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax + movl $CPU_PHYSMASK_HI, %edx + wrmsr +#endif + + post_code(0x28) + /* Enable cache. */ + movl %cr0, %eax + andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax + movl %eax, %cr0 + + /* Setup the stack. */ + movl $(CACHE_AS_RAM_LIMIT), %eax +#if CONFIG_USBDEBUG + sub $(USBDEBUG_VAR_SIZE), %eax +#endif + movl %eax, %esp + + /* Restore the BIST result. */ + movl %ebp, %eax + + /* Build the call frame. */ + movl %esp, %ebp + movd %mm1, %ebx + pushl %ebx + movd %mm0, %ebx + pushl %ebx + pushl %eax + +before_romstage: + post_code(0x29) + /* Call romstage.c main function. */ + call romstage_main + /* Save return value from romstage_main. It contains the stack to use + * after cache-as-ram is torn down. It also contains the information + * for setting up MTRRs. */ + movl %eax, %ebx + + post_code(0x2f) + + /* Copy global variable space (for USBDEBUG) to memory */ +#if CONFIG_USBDEBUG + cld + movl $(CACHE_AS_RAM_LIMIT - USBDEBUG_VAR_SIZE), %esi + movl $(CONFIG_RAMTOP - USBDEBUG_VAR_SIZE), %edi + movl $USBDEBUG_VAR_SIZE, %ecx + rep movsb +#endif + + post_code(0x30) + + /* Disable cache. */ + movl %cr0, %eax + orl $CR0_CacheDisable, %eax + movl %eax, %cr0 + + post_code(0x31) + + /* Disable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + andl $(~MTRRdefTypeEn), %eax + wrmsr + + post_code(0x31) + + /* Disable the no eviction run state */ + movl $NoEvictMod_MSR, %ecx + rdmsr + andl $~2, %eax + wrmsr + + invd + + /* Disable the no eviction mode */ + rdmsr + andl $~1, %eax + wrmsr + +#if CONFIG_CACHE_MRC_BIN + /* Clear MTRR that was used to cache MRC */ + xorl %eax, %eax + xorl %edx, %edx + movl $MTRRphysBase_MSR(2), %ecx + wrmsr + movl $MTRRphysMask_MSR(2), %ecx + wrmsr +#endif + + post_code(0x33) + + /* Enable cache. */ + movl %cr0, %eax + andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax + movl %eax, %cr0 + + post_code(0x36) + + /* Disable cache. */ + movl %cr0, %eax + orl $CR0_CacheDisable, %eax + movl %eax, %cr0 + + post_code(0x38) + + /* Setup stack as indicated by return value from ramstage_main(). */ + movl %ebx, %esp + + /* Get number of MTRRs. */ + popl %ebx + movl $MTRRphysBase_MSR(0), %ecx +1: + testl %ebx, %ebx + jz 1f + + /* Low 32 bits of MTRR base. */ + popl %eax + /* Upper 32 bits of MTRR base. */ + popl %edx + /* Write MTRR base. */ + wrmsr + inc %ecx + /* Low 32 bits of MTRR mask. */ + popl %eax + /* Upper 32 bits of MTRR mask. */ + popl %edx + /* Write MTRR mask. */ + wrmsr + inc %ecx + + dec %ebx + jmp 1b +1: + post_code(0x39) + + /* And enable cache again after setting MTRRs. */ + movl %cr0, %eax + andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax + movl %eax, %cr0 + + post_code(0x3a) + + /* Enable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + post_code(0x3b) + + /* Invalidate the cache again. */ + invd + + post_code(0x3c) + +__main: + post_code(POST_PREPARE_RAMSTAGE) + cld /* Clear direction flag. */ + call romstage_after_car + +.Lhlt: + post_code(POST_DEAD_CODE) + hlt + jmp .Lhlt + +mtrr_table: + /* Fixed MTRRs */ + .word 0x250, 0x258, 0x259 + .word 0x268, 0x269, 0x26A + .word 0x26B, 0x26C, 0x26D + .word 0x26E, 0x26F + /* Variable MTRRs */ + .word 0x200, 0x201, 0x202, 0x203 + .word 0x204, 0x205, 0x206, 0x207 + .word 0x208, 0x209, 0x20A, 0x20B + .word 0x20C, 0x20D, 0x20E, 0x20F + .word 0x210, 0x211, 0x212, 0x213 +mtrr_table_end: + diff --git a/src/soc/intel/broadwell/romstage/cpu.c b/src/soc/intel/broadwell/romstage/cpu.c new file mode 100644 index 0000000000..af175be86f --- /dev/null +++ b/src/soc/intel/broadwell/romstage/cpu.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +u32 cpu_family_model(void) +{ + return cpuid_eax(1) & 0x0fff0ff0; +} + +void set_max_freq(void) +{ + msr_t msr, perf_ctl, platform_info; + + /* Check for configurable TDP option */ + platform_info = rdmsr(MSR_PLATFORM_INFO); + + if ((platform_info.hi >> 1) & 3) { + /* Set to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = rdmsr(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + + perf_ctl.hi = 0; + wrmsr(IA32_PERF_CTL, perf_ctl); + + printk(BIOS_DEBUG, "CPU: frequency set to %d MHz\n", + ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK); +} diff --git a/src/soc/intel/broadwell/romstage/fsp.c b/src/soc/intel/broadwell/romstage/fsp.c new file mode 100644 index 0000000000..dd21aaef47 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/fsp.c @@ -0,0 +1,108 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include // hexdump +#include +#include +#include +#include + +void raminit(struct romstage_params *params, struct pei_data *pei_data) +{ + FSP_INFO_HEADER *fsp_header; + FSP_MEMORY_INIT fsp_memory_init; + FSP_MEMORY_INIT_PARAMS fsp_memory_init_params; + FSP_INIT_RT_COMMON_BUFFER fsp_rt_common_buffer; + void *hob_list_ptr; + EFI_STATUS status; + VPD_DATA_REGION *vpd_data; + UPD_DATA_REGION *upd_data; + UPD_DATA_REGION upd_data_buffer; + + /* Find and copy the UPD region to the stack so the platform can modify + * the settings if needed. Modifications to the UPD buffer are done in + * the platform callback code. The platform callback code is also + * responsible for assigning the UpdDataRngPtr to this buffer if any + * updates are made. The default state is to leave the UpdDataRngPtr + * set to NULL. This indicates that the FSP code will use the UPD + * region in the FSP binary.*/ + fsp_header = find_fsp(); + vpd_data = (VPD_DATA_REGION *)(fsp_header->CfgRegionOffset + + fsp_header->ImageBase); + printk(BIOS_DEBUG, "VPD Data: 0x%p\n", vpd_data); + upd_data = (UPD_DATA_REGION *)(vpd_data->PcdUpdRegionOffset + + fsp_header->ImageBase); + printk(BIOS_DEBUG, "UPD Data: 0x%p\n", upd_data); + memcpy(&upd_data_buffer, upd_data, sizeof(upd_data_buffer)); + + /* Zero fill RT Buffer data and start populating fields. */ + memset(&fsp_rt_common_buffer, sizeof(fsp_rt_common_buffer), 0); + fsp_rt_common_buffer.BootMode = pei_data->boot_mode; + fsp_rt_common_buffer.UpdDataRgnPtr = &upd_data_buffer; + + /* Get any board specific changes */ + fsp_memory_init_params.NvsBufferPtr = NULL; + fsp_memory_init_params.RtBufferPtr = &fsp_rt_common_buffer; + fsp_memory_init_params.HobListPtr = &hob_list_ptr; + board_fsp_memory_init_params(params, fsp_header, + &fsp_memory_init_params); + + /* Display the UPD data */ + printk(BIOS_SPEW, "Updated Product Data (UPD):\n"); + hexdump32(BIOS_SPEW, (void *)&upd_data_buffer, sizeof(upd_data_buffer)); + + /* Call FspMemoryInit to initialize RAM */ + fsp_memory_init = (FSP_MEMORY_INIT)(fsp_header->ImageBase + + fsp_header->FspMemoryInitEntryOffset); + printk(BIOS_DEBUG, "Calling FspMemoryInit: 0x%p\n", fsp_memory_init); + printk(BIOS_SPEW, " 0x%p: NvsBufferPtr\n", + fsp_memory_init_params.NvsBufferPtr); + printk(BIOS_SPEW, " 0x%p: RtBufferPtr\n", + fsp_memory_init_params.RtBufferPtr); + printk(BIOS_SPEW, " 0x%p: HobListPtr\n", + fsp_memory_init_params.HobListPtr); + status = fsp_memory_init(&fsp_memory_init_params); + printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status); + if (status != EFI_SUCCESS) + die("ERROR - FspMemoryInit failed to initialize memory!\n"); + + /* Display the memory configuration */ + report_memory_config(); + + if (pei_data->boot_mode != SLEEP_STATE_S3) { + cbmem_initialize_empty(); + } else if (cbmem_initialize()) { +#if CONFIG_HAVE_ACPI_RESUME + printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n"); + /* Failed S3 resume, reset to come up cleanly */ + reset_system(); +#endif + } + + /* Save the HOB list */ + set_hob_list(hob_list_ptr); + + /* Display the HOBs */ + if (hob_list_ptr == NULL) + die("ERROR - HOB pointer is NULL!\n"); + print_hob_type_structure(0, hob_list_ptr); +} diff --git a/src/soc/intel/broadwell/romstage/fsp_1_1.inc b/src/soc/intel/broadwell/romstage/fsp_1_1.inc new file mode 100644 index 0000000000..2cdea6924a --- /dev/null +++ b/src/soc/intel/broadwell/romstage/fsp_1_1.inc @@ -0,0 +1,302 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Replacement for cache_as_ram.inc when using the FSP binary. This code + * locates the FSP binary, initializes the cache as RAM and performs the + * first stage of initialization. Next this code switches the stack from + * the cache to RAM and then disables the cache as RAM. Finally this code + * performs the final stage of initialization. + */ + +#include +#include +#include +#include +#include + +#ifndef CONFIG_FSP_LOC +# error "CONFIG_FSP_LOC must be set." +#endif + +#ifndef CONFIG_POST_IO +# error "CONFIG_POST_IO must be set." +#endif + +#if CONFIG_POST_IO +# ifndef CONFIG_POST_IO_PORT +# error "CONFIG_POST_IO_PORT must be set." +# endif +#endif + +#ifndef CONFIG_CPU_MICROCODE_CBFS_LOC +# error "CONFIG_CPU_MICROCODE_CBFS_LOC must be set." +#endif + +#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */ + + /* + * eax: BIST value + * mm0: low 32-bits of TSC value + * mm1: high 32-bits of TSC value + */ + + cmp $0, %eax + jne bisthalt + +cache_as_ram: + post_code(0x20) + + /* + * BIST value is zero + * mm0: low 32-bits of TSC value + * mm1: high 32-bits of TSC value + */ + + /* + * Find the FSP binary in cbfs. + * Make a fake stack that has the return value back to this code. + */ + lea fake_fsp_stack, %esp + jmp find_fsp +find_fsp_ret: + /* Save the FSP location */ + mov %eax, %ebp + cmp $CONFIG_FSP_LOC, %eax + jb halt1 + + post_code(0x22) + + /* Calculate entry into FSP */ + mov 0x30(%ebp), %eax /* Load TempRamInitEntry */ + add 0x1c(%ebp), %eax /* add in the offset for the FSP base address */ + + /* + * Pass early init variables on a fake stack (no memory yet) + * as well as the return location + */ + lea CAR_init_stack, %esp + + /* + * BIST value is zero + * eax: TempRamInitApi address + * ebp: FSP_INFO_HEADER address + * mm0: low 32-bits of TSC value + * mm1: high 32-bits of TSC value + */ + + /* call FSP binary to setup temporary stack */ + jmp *%eax + +CAR_init_done: + addl $4, %esp + cmp $0, %eax + jne halt2 + + /* Setup bootloader stack */ + lea -4(%edx), %esp + + /* + * ebp: FSP_INFO_HEADER address + * ecx: temp RAM base (stack base) + * edx: temp RAM top (stack top) + * mm0: low 32-bits of TSC value + * mm1: high 32-bits of TSC value + */ + + /* Coreboot assumes stack/heap region will be zero */ + cld + movl %ecx, %esi + movl %esi, %edi + sub %ecx, %edx + movl %edx, %ecx + shrl $2, %ecx + xorl %eax, %eax + rep stosl + + /* Save FSP_INFO_HEADER location in ebx */ + mov %ebp, %ebx + + /* + * ebx: FSP_INFO_HEADER address + * esi: temp RAM base + * mm0: low 32-bits of TSC value + * mm1: high 32-bits of TSC value + */ + + /* Build the call frame */ + movl %esp, %ebp + movd %mm1, %eax + pushl %eax + movd %mm0, %eax + pushl %eax + pushl $0 + +before_romstage: + post_code(0x23) + + /* Call romstage.c main function. */ + call romstage_main + + /* + * eax: New stack address + * ebx: FSP_INFO_HEADER address + */ + + /* Switch to the stack in RAM */ + movl %eax, %esp + + /* Calculate TempRamExit entry into FSP */ + movl %ebx, %ebp + mov 0x40(%ebp), %eax + add 0x1c(%ebp), %eax + + /* Build the call frame */ + movl %esp, %ebx + pushl $0 + + /* Call TempRamExit */ + call *%eax + + /* + * ebx: FSP_INFO_HEADER address + */ + + /* Get number of MTRRs. */ + popl %ebx + movl $MTRRphysBase_MSR(0), %ecx +1: + testl %ebx, %ebx + jz 1f + + /* Low 32 bits of MTRR base. */ + popl %eax + /* Upper 32 bits of MTRR base. */ + popl %edx + /* Write MTRR base. */ + wrmsr + inc %ecx + /* Low 32 bits of MTRR mask. */ + popl %eax + /* Upper 32 bits of MTRR mask. */ + popl %edx + /* Write MTRR mask. */ + wrmsr + inc %ecx + + dec %ebx + jmp 1b +1: + post_code(0x39) + + /* And enable cache again after setting MTRRs. */ + movl %cr0, %eax + andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax + movl %eax, %cr0 + + post_code(0x3a) + + /* Enable MTRR. */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + post_code(0x3b) + + /* Invalidate the cache again. */ + invd + + post_code(0x3c) + +__main: + post_code(POST_PREPARE_RAMSTAGE) + cld /* Clear direction flag. */ + call romstage_after_car + + + movb $0x69, %ah + jmp .Lhlt + +bisthalt: + movb $0xB9, %ah + jmp .Lhlt + +halt1: + /* + * Failures for postcode 0xBA - failed in find_fsp() + * + * Values are: + * 0x01 - FV signature, "_FVH" not present + * 0x02 - FFS GUID not present + * 0x03 - FSP INFO Header not found + * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased to + * a different location, or does it need to be? + * 0x05 - FSP INFO Header signature "FSPH" not found + * 0x06 - FSP Image ID is not the expected ID. + */ + movb $0xBA, %ah + jmp .Lhlt + +halt2: + /* + * Failures for postcode 0xBB - failed in the FSP: + * + * 0x00 - FSP_SUCCESS: Temp RAM was initialized successfully. + * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid. + * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode region. + * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met. + * 0x07 - FSP_DEVICE_ERROR: Temp RAM initialization failed + * 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked + */ + movb $0xBB, %ah + +.Lhlt: + xchg %al, %ah +#if CONFIG_POST_IO + outb %al, $CONFIG_POST_IO_PORT +#else + post_code(POST_DEAD_CODE) +#endif + movl $LHLT_DELAY, %ecx +.Lhlt_Delay: + outb %al, $0xED + loop .Lhlt_Delay + jmp .Lhlt + +/* + * esp is set to this location so that the call into and return from the FSP + * in find_fsp will work. + */ + .align 4 +fake_fsp_stack: + .long find_fsp_ret + +CAR_init_params: + .long CONFIG_CPU_MICROCODE_CBFS_LOC /* Microcode Location */ + .long CONFIG_CPU_MICROCODE_CBFS_LEN /* Microcode Length */ + .long 0xFFFFFFFF - CONFIG_CBFS_SIZE + 1 /* Firmware Location */ + .long CONFIG_CBFS_SIZE /* Total Firmware Length */ + +CAR_init_stack: + .long CAR_init_done + .long CAR_init_params + diff --git a/src/soc/intel/broadwell/romstage/pch.c b/src/soc/intel/broadwell/romstage/pch.c new file mode 100644 index 0000000000..f31e6baa76 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/pch.c @@ -0,0 +1,146 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct reg_script pch_early_init_script[] = { + /* Setup southbridge BARs */ + REG_PCI_WRITE32(RCBA, RCBA_BASE_ADDRESS | 1), + REG_PCI_WRITE32(PMBASE, ACPI_BASE_ADDRESS | 1), + REG_PCI_WRITE8(ACPI_CNTL, ACPI_EN), + REG_PCI_WRITE32(GPIO_BASE, GPIO_BASE_ADDRESS | 1), + REG_PCI_WRITE8(GPIO_CNTL, GPIO_EN), + + /* Set COM1/COM2 decode range */ + REG_PCI_WRITE16(LPC_IO_DEC, 0x0010), + /* Enable legacy decode ranges */ + REG_PCI_WRITE16(LPC_EN, CNF1_LPC_EN | CNF2_LPC_EN | GAMEL_LPC_EN | + COMA_LPC_EN | KBC_LPC_EN | MC_LPC_EN), + + /* Enable IOAPIC */ + REG_MMIO_WRITE16(RCBA_BASE_ADDRESS + OIC, 0x0100), + /* Read back for posted write */ + REG_MMIO_READ16(RCBA_BASE_ADDRESS + OIC), + + /* Set HPET address and enable it */ + REG_MMIO_RMW32(RCBA_BASE_ADDRESS + HPTC, ~3, (1 << 7)), + /* Read back for posted write */ + REG_MMIO_READ32(RCBA_BASE_ADDRESS + HPTC), + /* Enable HPET to start counter */ + REG_MMIO_OR32(HPET_BASE_ADDRESS + 0x10, (1 << 0)), + + /* Disable reset */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + GCS, (1 << 5)), + /* TCO timer halt */ + REG_IO_OR16(ACPI_BASE_ADDRESS + TCO1_CNT, TCO_TMR_HLT), + + /* Enable upper 128 bytes of CMOS */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + RC, (1 << 2)), + + /* Disable unused device (always) */ + REG_MMIO_OR32(RCBA_BASE_ADDRESS + FD, PCH_DISABLE_ALWAYS), + + REG_SCRIPT_END +}; + +const struct reg_script pch_interrupt_init_script[] = { + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P1IP PCIE INTA -> PIRQA + * D29IP_E1P EHCI INTA -> PIRQD + * D20IP_XHCI XHCI INTA -> PIRQC (MSI) + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQG + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQG (MSI) + */ + + /* Device interrupt pin register (board specific) */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D31IP, + (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D29IP, (INTA << D29IP_E1P)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D28IP, + (INTA << D28IP_P1IP) | (INTC << D28IP_P3IP) | + (INTB << D28IP_P4IP)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D27IP, (INTA << D27IP_ZIP)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D26IP, (INTA << D26IP_E2P)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D22IP, (NOINT << D22IP_MEI1IP)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D20IP, (INTA << D20IP_XHCI)), + + /* Device interrupt route registers */ + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D31IR, /* LPC */ + DIR_ROUTE(PIRQG, PIRQC, PIRQB, PIRQA)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D29IR, /* EHCI */ + DIR_ROUTE(PIRQD, PIRQD, PIRQD, PIRQD)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D28IR, /* PCIE */ + DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D27IR, /* HDA */ + DIR_ROUTE(PIRQG, PIRQG, PIRQG, PIRQG)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D22IR, /* ME */ + DIR_ROUTE(PIRQA, PIRQA, PIRQA, PIRQA)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D21IR, /* SIO */ + DIR_ROUTE(PIRQE, PIRQF, PIRQF, PIRQF)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D20IR, /* XHCI */ + DIR_ROUTE(PIRQC, PIRQC, PIRQC, PIRQC)), + REG_MMIO_WRITE32(RCBA_BASE_ADDRESS + D23IR, /* SDIO */ + DIR_ROUTE(PIRQH, PIRQH, PIRQH, PIRQH)), + + REG_SCRIPT_END +}; + +static void pch_enable_lpc(void) +{ + /* Lookup device tree in romstage */ + const struct device *dev; + const config_t *config; + + dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0)); + if (!dev || !dev->chip_info) + return; + config = dev->chip_info; + + pci_write_config32(PCH_DEV_LPC, LPC_GEN1_DEC, config->gen1_dec); + pci_write_config32(PCH_DEV_LPC, LPC_GEN2_DEC, config->gen2_dec); + pci_write_config32(PCH_DEV_LPC, LPC_GEN3_DEC, config->gen3_dec); + pci_write_config32(PCH_DEV_LPC, LPC_GEN4_DEC, config->gen4_dec); +} + +void pch_early_init(void) +{ + reg_script_run_on_dev(PCH_DEV_LPC, pch_early_init_script); + reg_script_run_on_dev(PCH_DEV_LPC, pch_interrupt_init_script); + + pch_enable_lpc(); + + enable_smbus(); +} diff --git a/src/soc/intel/broadwell/romstage/power_state.c b/src/soc/intel/broadwell/romstage/power_state.c new file mode 100644 index 0000000000..097a07644f --- /dev/null +++ b/src/soc/intel/broadwell/romstage/power_state.c @@ -0,0 +1,132 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct chipset_power_state power_state CAR_GLOBAL; + +static void migrate_power_state(void) +{ + struct chipset_power_state *ps_cbmem; + struct chipset_power_state *ps_car; + + ps_car = car_get_var_ptr(&power_state); + ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem)); + + if (ps_cbmem == NULL) { + printk(BIOS_DEBUG, "Not adding power state to cbmem!\n"); + return; + } + memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem)); +} +ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state) + +/* Return 0, 3, or 5 to indicate the previous sleep state. */ +static int prev_sleep_state(struct chipset_power_state *ps) +{ + /* Default to S0. */ + int prev_sleep_state = SLEEP_STATE_S0; + + if (ps->pm1_sts & WAK_STS) { + switch ((ps->pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) { +#if CONFIG_HAVE_ACPI_RESUME + case SLP_TYP_S3: + prev_sleep_state = SLEEP_STATE_S3; + break; +#endif + case SLP_TYP_S5: + prev_sleep_state = SLEEP_STATE_S5; + break; + } + /* Clear SLP_TYP. */ + outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT); + } + + if (ps->gen_pmcon3 & (PWR_FLR | SUS_PWR_FLR)) + prev_sleep_state = SLEEP_STATE_S5; + + return prev_sleep_state; +} + +static void dump_power_state(struct chipset_power_state *ps) +{ + printk(BIOS_DEBUG, "PM1_STS: %04x\n", ps->pm1_sts); + printk(BIOS_DEBUG, "PM1_EN: %04x\n", ps->pm1_en); + printk(BIOS_DEBUG, "PM1_CNT: %08x\n", ps->pm1_cnt); + printk(BIOS_DEBUG, "TCO_STS: %04x %04x\n", + ps->tco1_sts, ps->tco2_sts); + + printk(BIOS_DEBUG, "GPE0_STS: %08x %08x %08x %08x\n", + ps->gpe0_sts[0], ps->gpe0_sts[1], + ps->gpe0_sts[2], ps->gpe0_sts[3]); + printk(BIOS_DEBUG, "GPE0_EN: %08x %08x %08x %08x\n", + ps->gpe0_en[0], ps->gpe0_en[1], + ps->gpe0_en[2], ps->gpe0_en[3]); + + printk(BIOS_DEBUG, "GEN_PMCON: %04x %04x %04x\n", + ps->gen_pmcon1, ps->gen_pmcon2, ps->gen_pmcon3); + + printk(BIOS_DEBUG, "Previous Sleep State: S%d\n", + ps->prev_sleep_state); +} + +/* Fill power state structure from ACPI PM registers */ +struct chipset_power_state *fill_power_state(void) +{ + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + + ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS); + ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN); + ps->pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT); + ps->tco1_sts = inw(ACPI_BASE_ADDRESS + TCO1_STS); + ps->tco2_sts = inw(ACPI_BASE_ADDRESS + TCO2_STS); + ps->gpe0_sts[0] = inl(ACPI_BASE_ADDRESS + GPE0_STS(0)); + ps->gpe0_sts[1] = inl(ACPI_BASE_ADDRESS + GPE0_STS(1)); + ps->gpe0_sts[2] = inl(ACPI_BASE_ADDRESS + GPE0_STS(2)); + ps->gpe0_sts[3] = inl(ACPI_BASE_ADDRESS + GPE0_STS(3)); + ps->gpe0_en[0] = inl(ACPI_BASE_ADDRESS + GPE0_EN(0)); + ps->gpe0_en[1] = inl(ACPI_BASE_ADDRESS + GPE0_EN(1)); + ps->gpe0_en[2] = inl(ACPI_BASE_ADDRESS + GPE0_EN(2)); + ps->gpe0_en[3] = inl(ACPI_BASE_ADDRESS + GPE0_EN(3)); + + ps->gen_pmcon1 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_1); + ps->gen_pmcon2 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_2); + ps->gen_pmcon3 = pci_read_config16(PCH_DEV_LPC, GEN_PMCON_3); + + ps->prev_sleep_state = prev_sleep_state(ps); + + dump_power_state(ps); + + return ps; +} diff --git a/src/soc/intel/broadwell/romstage/raminit.c b/src/soc/intel/broadwell/romstage/raminit.c new file mode 100644 index 0000000000..c541299ac7 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/raminit.c @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Find PEI executable in coreboot filesystem and execute it. + */ +void raminit(struct romstage_params *params, struct pei_data *pei_data) +{ + pei_wrapper_entry_t entry; + int ret; + + /* Determine if mrc.bin is in the cbfs. */ + entry = (pei_wrapper_entry_t)cbfs_get_file_content( + CBFS_DEFAULT_MEDIA, "mrc.bin", 0xab); + if (entry == NULL) { + printk(BIOS_DEBUG, "Couldn't find mrc.bin\n"); + return; + } + + printk(BIOS_DEBUG, "Starting Memory Reference Code\n"); + + ret = entry(pei_data); + if (ret < 0) + die("pei_data version mismatch\n"); + + /* Print the MRC version after executing the UEFI PEI stage. */ + u32 version = MCHBAR32(MCHBAR_PEI_VERSION); + printk(BIOS_DEBUG, "MRC Version %d.%d.%d Build %d\n", + version >> 24 , (version >> 16) & 0xff, + (version >> 8) & 0xff, version & 0xff); + + report_memory_config(); + + /* Basic memory sanity test */ + quick_ram_check(); + + if (pei_data->boot_mode != SLEEP_STATE_S3) { + cbmem_initialize_empty(); + } else if (cbmem_initialize()) { +#if CONFIG_HAVE_ACPI_RESUME + printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n"); + /* Failed S3 resume, reset to come up cleanly */ + reset_system(); +#endif + } +} diff --git a/src/soc/intel/broadwell/romstage/report_platform.c b/src/soc/intel/broadwell/romstage/report_platform.c new file mode 100644 index 0000000000..713b3e7abf --- /dev/null +++ b/src/soc/intel/broadwell/romstage/report_platform.c @@ -0,0 +1,243 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct { + u32 cpuid; + const char *name; +} cpu_table[] = { + { CPUID_HASWELL_A0, "Haswell A0" }, + { CPUID_HASWELL_B0, "Haswell B0" }, + { CPUID_HASWELL_C0, "Haswell C0" }, + { CPUID_HASWELL_ULT_B0, "Haswell ULT B0" }, + { CPUID_HASWELL_ULT, "Haswell ULT C0 or D0" }, + { CPUID_HASWELL_HALO, "Haswell Perf Halo" }, + { CPUID_BROADWELL_C0, "Broadwell C0" }, + { CPUID_BROADWELL_D0, "Broadwell D0" }, + { CPUID_BROADWELL_E0, "Broadwell E0 or F0" }, +}; + +static struct { + u8 revid; + const char *name; +} mch_rev_table[] = { + { MCH_BROADWELL_REV_D0, "Broadwell D0" }, + { MCH_BROADWELL_REV_E0, "Broadwell E0" }, + { MCH_BROADWELL_REV_F0, "Broadwell F0" }, +}; + +static struct { + u16 lpcid; + const char *name; +} pch_table[] = { + { PCH_LPT_LP_SAMPLE, "LynxPoint LP Sample" }, + { PCH_LPT_LP_PREMIUM, "LynxPoint LP Premium" }, + { PCH_LPT_LP_MAINSTREAM, "LynxPoint LP Mainstream" }, + { PCH_LPT_LP_VALUE, "LynxPoint LP Value" }, + { PCH_WPT_HSW_U_SAMPLE, "Haswell U Sample" }, + { PCH_WPT_BDW_U_SAMPLE, "Broadwell U Sample" }, + { PCH_WPT_BDW_U_PREMIUM, "Broadwell U Premium" }, + { PCH_WPT_BDW_U_BASE, "Broadwell U Base" }, + { PCH_WPT_BDW_Y_SAMPLE, "Broadwell Y Sample" }, + { PCH_WPT_BDW_Y_PREMIUM, "Broadwell Y Premium" }, + { PCH_WPT_BDW_Y_BASE, "Broadwell Y Base" }, + { PCH_WPT_BDW_H, "Broadwell H" }, +}; + +static struct { + u16 igdid; + const char *name; +} igd_table[] = { + { IGD_HASWELL_ULT_GT1, "Haswell ULT GT1" }, + { IGD_HASWELL_ULT_GT2, "Haswell ULT GT2" }, + { IGD_HASWELL_ULT_GT3, "Haswell ULT GT3" }, + { IGD_BROADWELL_U_GT1, "Broadwell U GT1" }, + { IGD_BROADWELL_U_GT2, "Broadwell U GT2" }, + { IGD_BROADWELL_U_GT3_15W, "Broadwell U GT3 (15W)" }, + { IGD_BROADWELL_U_GT3_28W, "Broadwell U GT3 (28W)" }, + { IGD_BROADWELL_Y_GT2, "Broadwell Y GT2" }, + { IGD_BROADWELL_H_GT2, "Broadwell U GT2" }, + { IGD_BROADWELL_H_GT3, "Broadwell U GT3" }, +}; + +static void report_cpu_info(void) +{ + struct cpuid_result cpuidr; + u32 i, index; + char cpu_string[50], *cpu_name = cpu_string; /* 48 bytes are reported */ + int vt, txt, aes; + msr_t microcode_ver; + const char *mode[] = {"NOT ", ""}; + const char *cpu_type = "Unknown"; + + index = 0x80000000; + cpuidr = cpuid(index); + if (cpuidr.eax < 0x80000004) { + strcpy(cpu_string, "Platform info not available"); + } else { + u32 *p = (u32*) cpu_string; + for (i = 2; i <= 4 ; i++) { + cpuidr = cpuid(index + i); + *p++ = cpuidr.eax; + *p++ = cpuidr.ebx; + *p++ = cpuidr.ecx; + *p++ = cpuidr.edx; + } + } + /* Skip leading spaces in CPU name string */ + while (cpu_name[0] == ' ') + cpu_name++; + + microcode_ver.lo = 0; + microcode_ver.hi = 0; + wrmsr(0x8B, microcode_ver); + cpuidr = cpuid(1); + microcode_ver = rdmsr(0x8b); + + /* Look for string to match the name */ + for (i = 0; i < ARRAY_SIZE(cpu_table); i++) { + if (cpu_table[i].cpuid == cpuidr.eax) { + cpu_type = cpu_table[i].name; + break; + } + } + + printk(BIOS_DEBUG, "CPU: %s\n", cpu_name); + printk(BIOS_DEBUG, "CPU: ID %x, %s, ucode: %08x\n", + cpuidr.eax, cpu_type, microcode_ver.hi); + + aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0; + txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0; + vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0; + printk(BIOS_DEBUG, "CPU: AES %ssupported, TXT %ssupported, " + "VT %ssupported\n", mode[aes], mode[txt], mode[vt]); +} + +static void report_mch_info(void) +{ + int i; + u16 mch_device = pci_read_config16(SA_DEV_ROOT, PCI_DEVICE_ID); + u8 mch_revision = pci_read_config8(SA_DEV_ROOT, PCI_REVISION_ID); + const char *mch_type = "Unknown"; + + /* Look for string to match the revision for Broadwell U/Y */ + if (mch_device == MCH_BROADWELL_ID_U_Y) { + for (i = 0; i < ARRAY_SIZE(mch_rev_table); i++) { + if (mch_rev_table[i].revid == mch_revision) { + mch_type = mch_rev_table[i].name; + break; + } + } + } + + printk(BIOS_DEBUG, "MCH: device id %04x (rev %02x) is %s\n", + mch_device, mch_revision, mch_type); +} + +static void report_pch_info(void) +{ + int i; + u16 lpcid = pch_type(); + const char *pch_type = "Unknown"; + + for (i = 0; i < ARRAY_SIZE(pch_table); i++) { + if (pch_table[i].lpcid == lpcid) { + pch_type = pch_table[i].name; + break; + } + } + printk(BIOS_DEBUG, "PCH: device id %04x (rev %02x) is %s\n", + lpcid, pch_revision(), pch_type); +} + +static void report_igd_info(void) +{ + int i; + u16 igdid = pci_read_config16(SA_DEV_IGD, PCI_DEVICE_ID); + const char *igd_type = "Unknown"; + + for (i = 0; i < ARRAY_SIZE(igd_table); i++) { + if (igd_table[i].igdid == igdid) { + igd_type = igd_table[i].name; + break; + } + } + printk(BIOS_DEBUG, "IGD: device id %04x (rev %02x) is %s\n", + igdid, pci_read_config8(SA_DEV_IGD, PCI_REVISION_ID), igd_type); +} + +void report_platform_info(void) +{ + report_cpu_info(); + report_mch_info(); + report_pch_info(); + report_igd_info(); +} + +/* + * Dump in the log memory controller configuration as read from the memory + * controller registers. + */ +void report_memory_config(void) +{ + u32 addr_decoder_common, addr_decode_ch[2]; + int i; + + addr_decoder_common = MCHBAR32(0x5000); + addr_decode_ch[0] = MCHBAR32(0x5004); + addr_decode_ch[1] = MCHBAR32(0x5008); + + printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n", + (MCHBAR32(0x5e04) * 13333 * 2 + 50)/100); + printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n", + addr_decoder_common & 3, + (addr_decoder_common >> 2) & 3, + (addr_decoder_common >> 4) & 3); + + for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { + u32 ch_conf = addr_decode_ch[i]; + printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", + i, ch_conf); + printk(BIOS_DEBUG, " enhanced interleave mode %s\n", + ((ch_conf >> 22) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " rank interleave %s\n", + ((ch_conf >> 21) & 1) ? "on" : "off"); + printk(BIOS_DEBUG, " DIMMA %d MB width %s %s rank%s\n", + ((ch_conf >> 0) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", + ((ch_conf >> 17) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? "" : ", selected"); + printk(BIOS_DEBUG, " DIMMB %d MB width %s %s rank%s\n", + ((ch_conf >> 8) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? "x16" : "x8 or x32", + ((ch_conf >> 18) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? ", selected" : ""); + } +} diff --git a/src/soc/intel/broadwell/romstage/romstage.c b/src/soc/intel/broadwell/romstage/romstage.c new file mode 100644 index 0000000000..cf0370dbf6 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/romstage.c @@ -0,0 +1,253 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Entry from cache-as-ram.inc. */ +asmlinkage void *romstage_main(unsigned int bist, + uint32_t tsc_low, uint32_t tsc_hi) +{ + void *top_of_stack; + struct romstage_params rp = { + .bist = bist, + .pei_data = NULL, + }; + + post_code(0x30); + + timestamp_early_init((((uint64_t)tsc_hi) << 32) | (uint64_t)tsc_low); + timestamp_add_now(TS_START_ROMSTAGE); + + /* System Agent Early Initialization */ + systemagent_early_init(); + + /* PCH Early Initialization */ + pch_early_init(); + + /* Call into mainboard pre console init. Needed to enable serial port + on IT8772 */ + mainboard_pre_console_init(); + + /* Start console drivers */ + console_init(); + + /* Display parameters */ + printk(BIOS_SPEW, "bist: 0x%08x\n", bist); + printk(BIOS_SPEW, "tsc_low: 0x%08x\n", tsc_low); + printk(BIOS_SPEW, "tsc_hi: 0x%08x\n", tsc_hi); + printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n", + CONFIG_MMCONF_BASE_ADDRESS); + printk(BIOS_INFO, "Using: %s\n", + IS_ENABLED(CONFIG_PLATFORM_USES_FSP) ? "FSP" : + (IS_ENABLED(CONFIG_HAVE_MRC) ? "MRC" : + "No Memory Support")); + + /* Display FSP banner */ +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + printk(BIOS_DEBUG, "FSP TempRamInit successful\n"); + print_fsp_info(find_fsp()); +#endif /* CONFIG_PLATFORM_USES_FSP */ + + /* Get power state */ + rp.power_state = fill_power_state(); + + /* Print useful platform information */ + report_platform_info(); + + /* Set CPU frequency to maximum */ + set_max_freq(); + + /* Call into mainboard. */ + mainboard_romstage_entry(&rp); + + top_of_stack = setup_stack_and_mttrs(); + +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + printk(BIOS_DEBUG, "Calling FspTempRamExit API\n"); +#endif /* CONFIG_PLATFORM_USES_FSP */ + + return top_of_stack; +} + +static inline void chromeos_init(int prev_sleep_state) +{ +#if CONFIG_CHROMEOS + /* Normalize the sleep state to what init_chromeos() wants for S3: 2 */ + init_chromeos(prev_sleep_state == SLEEP_STATE_S3 ? 2 : 0); +#endif +} + +/* Entry from the mainboard. */ +void romstage_common(struct romstage_params *params) +{ + struct romstage_handoff *handoff; + struct pei_data *pei_data; + + post_code(0x32); + + timestamp_add_now(TS_BEFORE_INITRAM); + + pei_data = params->pei_data; + pei_data->boot_mode = params->power_state->prev_sleep_state; + +#if CONFIG_ELOG_BOOT_COUNT + if (params->power_state->prev_sleep_state != SLEEP_STATE_S3) + boot_count_increment(); +#endif + + /* Print ME state before MRC */ + intel_me_status(); + + /* Save ME HSIO version */ + intel_me_hsio_version(¶ms->power_state->hsio_version, + ¶ms->power_state->hsio_checksum); + + /* Prepare to initialize memory */ + const struct mrc_saved_data *cache; + struct memory_info *mem_info; + + broadwell_fill_pei_data(pei_data); + + if (recovery_mode_enabled()) { + /* Recovery mode does not use MRC cache */ + printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n"); + } else if (!mrc_cache_get_current(&cache)) { + /* MRC cache found */ + pei_data->saved_data_size = cache->size; + pei_data->saved_data = &cache->data[0]; + } else if (pei_data->boot_mode == SLEEP_STATE_S3) { + /* Waking from S3 and no cache. */ + printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n"); + post_code(POST_RESUME_FAILURE); + reset_system(); + } else { + printk(BIOS_DEBUG, "No MRC cache found.\n"); +#if CONFIG_EC_GOOGLE_CHROMEEC + if (pei_data->boot_mode == SLEEP_STATE_S0) { + /* Ensure EC is running RO firmware. */ + google_chromeec_check_ec_image(EC_IMAGE_RO); + } +#endif + } + + /* + * Do not use saved pei data. Can be set by mainboard romstage + * to force a full train of memory on every boot. + */ + if (pei_data->disable_saved_data) { + printk(BIOS_DEBUG, "Disabling PEI saved data by request\n"); + pei_data->saved_data = NULL; + pei_data->saved_data_size = 0; + } + + /* Initialize RAM */ + raminit(params, pei_data); + timestamp_add_now(TS_AFTER_INITRAM); + + printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", pei_data->data_to_save, + pei_data->data_to_save_size); + + if (pei_data->data_to_save != NULL && pei_data->data_to_save_size > 0) + mrc_cache_stash_data(pei_data->data_to_save, + pei_data->data_to_save_size); + + printk(BIOS_DEBUG, "create cbmem for dimm information\n"); + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info)); + memcpy(mem_info, &pei_data->meminfo, sizeof(struct memory_info)); + + handoff = romstage_handoff_find_or_add(); + if (handoff != NULL) + handoff->s3_resume = (params->power_state->prev_sleep_state == + SLEEP_STATE_S3); + else + printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); + + chromeos_init(params->power_state->prev_sleep_state); +} + +void asmlinkage romstage_after_car(void) +{ +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + FSP_INFO_HEADER *fsp_info_header; + FSP_SILICON_INIT fsp_silicon_init; + EFI_STATUS status; + + printk(BIOS_DEBUG, "FspTempRamExit returned successfully\n"); +#endif /* CONFIG_PLATFORM_USES_FSP */ + + timestamp_add_now(TS_END_ROMSTAGE); + +#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP) + printk(BIOS_DEBUG, "Calling FspSiliconInit\n"); + fsp_info_header = find_fsp(); + fsp_silicon_init = (FSP_SILICON_INIT)(fsp_info_header->ImageBase + + fsp_info_header->FspSiliconInitEntryOffset); + status = fsp_silicon_init(NULL); + printk(BIOS_DEBUG, "FspSiliconInit returned 0x%08x\n", status); +#endif /* CONFIG_PLATFORM_USES_FSP */ + + /* Run vboot verification if configured. */ + vboot_verify_firmware(romstage_handoff_find_or_add()); + + /* Load the ramstage. */ + copy_and_run(); + while (1); +} + +void ramstage_cache_invalid(struct ramstage_cache *cache) +{ +#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE + /* Perform cold reset on invalid ramstage cache. */ + reset_system(); +#endif +} + +#if CONFIG_CHROMEOS +int vboot_get_sw_write_protect(void) +{ + u8 status; + /* Return unprotected status if status read fails. */ + return (early_spi_read_wpsr(&status) ? 0 : !!(status & 0x80)); +} + +void __attribute__((weak)) mainboard_pre_console_init(void) {} +#endif diff --git a/src/soc/intel/broadwell/romstage/smbus.c b/src/soc/intel/broadwell/romstage/smbus.c new file mode 100644 index 0000000000..f09459bedd --- /dev/null +++ b/src/soc/intel/broadwell/romstage/smbus.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct reg_script smbus_init_script[] = { + /* Set SMBUS I/O base address */ + REG_PCI_WRITE32(SMB_BASE, SMBUS_BASE_ADDRESS | 1), + /* Set SMBUS enable */ + REG_PCI_WRITE8(HOSTC, HST_EN), + /* Enable I/O access */ + REG_PCI_WRITE16(PCI_COMMAND, PCI_COMMAND_IO), + /* Disable interrupts */ + REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTCTL, 0), + /* Clear errors */ + REG_IO_WRITE8(SMBUS_BASE_ADDRESS + SMBHSTSTAT, 0xff), + /* Indicate the end of this array by REG_SCRIPT_END */ + REG_SCRIPT_END, +}; + +void enable_smbus(void) +{ + reg_script_run_on_dev(PCH_DEV_SMBUS, smbus_init_script); +} + +int smbus_read_byte(unsigned device, unsigned address) +{ + return do_smbus_read_byte(SMBUS_BASE_ADDRESS, device, address); +} diff --git a/src/soc/intel/broadwell/romstage/spi.c b/src/soc/intel/broadwell/romstage/spi.c new file mode 100644 index 0000000000..a717d67f67 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/spi.c @@ -0,0 +1,149 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPI_DELAY 10 /* 10us */ +#define SPI_RETRY 200000 /* 2s */ + +static int early_spi_read_block(u32 offset, u8 size, u8 *buffer) +{ + u32 *ptr32 = (u32*)buffer; + u32 i; + + /* Clear status bits */ + SPIBAR16(SPIBAR_HSFS) |= SPIBAR_HSFS_AEL | SPIBAR_HSFS_FCERR | + SPIBAR_HSFS_FDONE; + + if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) { + printk(BIOS_ERR, "SPI ERROR: transaction in progress\n"); + return -1; + } + + /* Set flash address */ + SPIBAR32(SPIBAR_FADDR) = offset; + + /* Setup read transaction */ + SPIBAR16(SPIBAR_HSFC) = SPIBAR_HSFC_BYTE_COUNT(size) | + SPIBAR_HSFC_CYCLE_READ; + + /* Start transactinon */ + SPIBAR16(SPIBAR_HSFC) |= SPIBAR_HSFC_GO; + + /* Wait for completion */ + for (i = 0; i < SPI_RETRY; i++) { + if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_SCIP) { + /* Cycle in progress, wait 1ms */ + udelay(SPI_DELAY); + continue; + } + + if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_AEL) { + printk(BIOS_ERR, "SPI ERROR: Access Error\n"); + return -1; + + } + + if (SPIBAR16(SPIBAR_HSFS) & SPIBAR_HSFS_FCERR) { + printk(BIOS_ERR, "SPI ERROR: Flash Cycle Error\n"); + return -1; + } + break; + } + + if (i >= SPI_RETRY) { + printk(BIOS_ERR, "SPI ERROR: Timeout\n"); + return -1; + } + + /* Read the data */ + for (i = 0; i < size; i+=sizeof(u32)) { + if (size-i >= 4) { + /* reading >= dword */ + *ptr32++ = SPIBAR32(SPIBAR_FDATA(i/sizeof(u32))); + } else { + /* reading < dword */ + u8 j, *ptr8 = (u8*)ptr32; + u32 temp = SPIBAR32(SPIBAR_FDATA(i/sizeof(u32))); + for (j = 0; j < (size-i); j++) { + *ptr8++ = temp & 0xff; + temp >>= 8; + } + } + } + + return size; +} + +int early_spi_read(u32 offset, u32 size, u8 *buffer) +{ + u32 current = 0; + + while (size > 0) { + u8 count = (size < 64) ? size : 64; + if (early_spi_read_block(offset + current, count, + buffer + current) < 0) + return -1; + size -= count; + current += count; + } + + return 0; +} + +/* + * Minimal set of commands to read WPSR from SPI. + * Don't use this code outside romstage -- it trashes the opmenu table. + * Returns 0 on success, < 0 on failure. + */ +int early_spi_read_wpsr(u8 *sr) +{ + int retry; + + /* No address associated with rdsr */ + SPIBAR8(SPIBAR_OPTYPE) = 0x0; + /* Setup opcode[0] = read wpsr */ + SPIBAR8(SPIBAR_OPMENU_LOWER) = 0x5; + + /* Start transaction */ + SPIBAR16(SPIBAR_SSFC) = SPIBAR_SSFC_DATA | SPIBAR_SSFC_GO; + + /* Wait for error / complete status */ + for (retry = SPI_RETRY; retry; retry--) { + u16 status = SPIBAR16(SPIBAR_SSFS); + if (status & SPIBAR_SSFS_ERROR) { + printk(BIOS_ERR, "SPI rdsr failed\n"); + return -1; + } else if (status & SPIBAR_SSFS_DONE) { + break; + } + + udelay(SPI_DELAY); + } + + *sr = SPIBAR32(SPIBAR_FDATA(0)) & 0xff; + return 0; +} diff --git a/src/soc/intel/broadwell/romstage/stack.c b/src/soc/intel/broadwell/romstage/stack.c new file mode 100644 index 0000000000..a81eb07639 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/stack.c @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static inline uint32_t *stack_push(u32 *stack, u32 value) +{ + stack = &stack[-1]; + *stack = value; + return stack; +} + +/* Romstage needs quite a bit of stack for decompressing images since the lzma + * lib keeps its state on the stack during romstage. */ +static unsigned long choose_top_of_stack(void) +{ + unsigned long stack_top; + const unsigned long romstage_ram_stack_size = 0x5000; + + /* cbmem_add() does a find() before add(). */ + stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, + romstage_ram_stack_size); + stack_top += romstage_ram_stack_size; + return stack_top; +} + +/* setup_stack_and_mttrs() determines the stack to use after + * cache-as-ram is torn down as well as the MTRR settings to use. */ +void *setup_stack_and_mttrs(void) +{ + unsigned long top_of_stack; + int num_mtrrs; + uint32_t *slot; + uint32_t mtrr_mask_upper; + uint32_t top_of_ram; + + /* Top of stack needs to be aligned to a 4-byte boundary. */ + top_of_stack = choose_top_of_stack() & ~3; + slot = (void *)top_of_stack; + num_mtrrs = 0; + + /* The upper bits of the MTRR mask need to set according to the number + * of physical address bits. */ + mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1; + + /* The order for each MTTR is value then base with upper 32-bits of + * each value coming before the lower 32-bits. The reasoning for + * this ordering is to create a stack layout like the following: + * +0: Number of MTRRs + * +4: MTTR base 0 31:0 + * +8: MTTR base 0 63:32 + * +12: MTTR mask 0 31:0 + * +16: MTTR mask 0 63:32 + * +20: MTTR base 1 31:0 + * +24: MTTR base 1 63:32 + * +28: MTTR mask 1 31:0 + * +32: MTTR mask 1 63:32 + */ + + /* Cache the ROM as WP just below 4GiB. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT); + num_mtrrs++; + + /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK); + num_mtrrs++; + + top_of_ram = (uint32_t)cbmem_top(); + /* Cache 8MiB below the top of ram. The top of ram under 4GiB is the + * start of the TSEG region. It is required to be 8MiB aligned. Set + * this area as cacheable so it can be used later for ramstage before + * setting up the entire RAM as cacheable. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, (top_of_ram - (8 << 20)) | MTRR_TYPE_WRBACK); + num_mtrrs++; + + /* Cache 8MiB at the top of ram. Top of ram is where the TSEG + * region resides. However, it is not restricted to SMM mode until + * SMM has been relocated. By setting the region to cacheable it + * provides faster access when relocating the SMM handler as well + * as using the TSEG region for other purposes. */ + slot = stack_push(slot, mtrr_mask_upper); /* upper mask */ + slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid); + slot = stack_push(slot, 0); /* upper base */ + slot = stack_push(slot, top_of_ram | MTRR_TYPE_WRBACK); + num_mtrrs++; + + /* Save the number of MTTRs to setup. Return the stack location + * pointing to the number of MTRRs. */ + slot = stack_push(slot, num_mtrrs); + + return slot; +} diff --git a/src/soc/intel/broadwell/romstage/systemagent.c b/src/soc/intel/broadwell/romstage/systemagent.c new file mode 100644 index 0000000000..7a43917601 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/systemagent.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct reg_script systemagent_early_init_script[] = { + REG_PCI_WRITE32(MCHBAR, MCH_BASE_ADDRESS | 1), + REG_PCI_WRITE32(DMIBAR, DMI_BASE_ADDRESS | 1), + REG_PCI_WRITE32(EPBAR, EP_BASE_ADDRESS | 1), + REG_MMIO_WRITE32(MCH_BASE_ADDRESS + EDRAMBAR, EDRAM_BASE_ADDRESS | 1), + REG_MMIO_WRITE32(MCH_BASE_ADDRESS + GDXCBAR, GDXC_BASE_ADDRESS | 1), + + /* Set C0000-FFFFF to access RAM on both reads and writes */ + REG_PCI_WRITE8(PAM0, 0x30), + REG_PCI_WRITE8(PAM1, 0x33), + REG_PCI_WRITE8(PAM2, 0x33), + REG_PCI_WRITE8(PAM3, 0x33), + REG_PCI_WRITE8(PAM4, 0x33), + REG_PCI_WRITE8(PAM5, 0x33), + REG_PCI_WRITE8(PAM6, 0x33), + + /* Device enable: IGD and Mini-HD */ + REG_PCI_WRITE32(DEVEN, DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN), + + REG_SCRIPT_END +}; + +void systemagent_early_init(void) +{ + reg_script_run_on_dev(SA_DEV_ROOT, systemagent_early_init_script); +} diff --git a/src/soc/intel/broadwell/romstage/uart.c b/src/soc/intel/broadwell/romstage/uart.c new file mode 100644 index 0000000000..96c96343f1 --- /dev/null +++ b/src/soc/intel/broadwell/romstage/uart.c @@ -0,0 +1,85 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct reg_script uart_init[] = { + /* Set MMIO BAR */ + REG_PCI_WRITE32(PCI_BASE_ADDRESS_0, CONFIG_TTYS0_BASE), + /* Enable Memory access and Bus Master */ + REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER), + /* Initialize LTR */ + REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_GEN, + ~SIO_REG_PPR_GEN_LTR_MODE_MASK, 0), + REG_MMIO_RMW32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST, + ~(SIO_REG_PPR_RST_ASSERT), 0), + /* Take UART out of reset */ + REG_MMIO_OR32(CONFIG_TTYS0_BASE + SIO_REG_PPR_RST, + SIO_REG_PPR_RST_ASSERT), + /* Set M and N divisor inputs and enable clock */ + REG_MMIO_WRITE32(CONFIG_TTYS0_BASE + SIO_REG_PPR_CLOCK, + SIO_REG_PPR_CLOCK_EN | SIO_REG_PPR_CLOCK_UPDATE | + (SIO_REG_PPR_CLOCK_N_DIV << 16) | + (SIO_REG_PPR_CLOCK_M_DIV << 1)), + REG_SCRIPT_END +}; + +void pch_uart_init(void) +{ + /* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */ + u32 gpiodf = 0x131f; + device_t dev; + + /* Put UART in byte access mode for 16550 compatibility */ + switch (CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER) { + case 0: + dev = PCH_DEV_UART0; + gpiodf |= SIO_IOBP_GPIODF_UART0_BYTE_ACCESS; + break; + case 1: + dev = PCH_DEV_UART1; + gpiodf |= SIO_IOBP_GPIODF_UART1_BYTE_ACCESS; + break; + default: + return; + } + + /* Program IOBP GPIODF */ + pch_iobp_update(SIO_IOBP_GPIODF, ~gpiodf, gpiodf); + + /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */ + pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f); + + /* Initialize chipset uart interface */ + reg_script_run_on_dev(dev, uart_init); + + /* + * Perform standard UART initialization + * Divisor 1 is 115200 BAUD + */ + uart8250_mem_init(CONFIG_TTYS0_BASE, 1); +} diff --git a/src/soc/intel/broadwell/sata.c b/src/soc/intel/broadwell/sata.c new file mode 100644 index 0000000000..c24c33eabc --- /dev/null +++ b/src/soc/intel/broadwell/sata.c @@ -0,0 +1,255 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline u32 sir_read(struct device *dev, int idx) +{ + pci_write_config32(dev, SATA_SIRI, idx); + return pci_read_config32(dev, SATA_SIRD); +} + +static inline void sir_write(struct device *dev, int idx, u32 value) +{ + pci_write_config32(dev, SATA_SIRI, idx); + pci_write_config32(dev, SATA_SIRD, value); +} + +static void sata_init(struct device *dev) +{ + config_t *config = dev->chip_info; + u32 reg32, abar; + u16 reg16; + int port; + + printk(BIOS_DEBUG, "SATA: Initializing controller in AHCI mode.\n"); + + /* Enable BARs */ + pci_write_config16(dev, PCI_COMMAND, 0x0007); + + /* Set Interrupt Line */ + /* Interrupt Pin is set by D31IP.PIP */ + pci_write_config8(dev, PCI_INTERRUPT_LINE, 0x0a); + + /* Set timings */ + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE); + + /* for AHCI, Port Enable is managed in memory mapped space */ + reg16 = pci_read_config16(dev, 0x92); + reg16 &= ~0xf; + reg16 |= 0x8000 | config->sata_port_map; + pci_write_config16(dev, 0x92, reg16); + udelay(2); + + /* Setup register 98h */ + reg32 = pci_read_config32(dev, 0x98); + reg32 &= ~((1 << 31) | (1 << 30)); + reg32 |= 1 << 23; + reg32 |= 1 << 24; /* Enable MPHY Dynamic Power Gating */ + pci_write_config32(dev, 0x98, reg32); + + /* Setup register 9Ch */ + reg16 = 0; /* Disable alternate ID */ + reg16 = 1 << 5; /* BWG step 12 */ + pci_write_config16(dev, 0x9c, reg16); + + /* SATA Initialization register */ + reg32 = 0x183; + reg32 |= (config->sata_port_map ^ 0xf) << 24; + reg32 |= (config->sata_devslp_mux & 1) << 15; + pci_write_config32(dev, 0x94, reg32); + + /* Initialize AHCI memory-mapped space */ + abar = pci_read_config32(dev, PCI_BASE_ADDRESS_5); + printk(BIOS_DEBUG, "ABAR: %08X\n", abar); + + /* CAP (HBA Capabilities) : enable power management */ + reg32 = read32(abar + 0x00); + reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */ + reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */ + reg32 |= (1 << 18); /* SAM: SATA AHCI MODE ONLY */ + write32(abar + 0x00, reg32); + + /* PI (Ports implemented) */ + write32(abar + 0x0c, config->sata_port_map); + (void) read32(abar + 0x0c); /* Read back 1 */ + (void) read32(abar + 0x0c); /* Read back 2 */ + + /* CAP2 (HBA Capabilities Extended)*/ + if (config->sata_devslp_disable) { + reg32 = read32(abar + 0x24); + reg32 &= ~(1 << 3); + write32(abar + 0x24, reg32); + } else { + /* Enable DEVSLP */ + reg32 = read32(abar + 0x24); + reg32 |= (1 << 5)|(1 << 4)|(1 << 3)|(1 << 2); + write32(abar + 0x24, reg32); + + for (port = 0; port < 4; port++) { + if (!(config->sata_port_map & (1 << port))) + continue; + reg32 = read32(abar + 0x144 + (0x80 * port)); + reg32 |= (1 << 1); /* DEVSLP DSP */ + write32(abar + 0x144 + (0x80 * port), reg32); + } + } + + /* + * Static Power Gating for unused ports + */ + reg32 = RCBA32(0x3a84); + /* Port 3 and 2 disabled */ + if ((config->sata_port_map & ((1 << 3)|(1 << 2))) == 0) + reg32 |= (1 << 24) | (1 << 26); + /* Port 1 and 0 disabled */ + if ((config->sata_port_map & ((1 << 1)|(1 << 0))) == 0) + reg32 |= (1 << 20) | (1 << 18); + RCBA32(0x3a84) = reg32; + + /* Set Gen3 Transmitter settings if needed */ + if (config->sata_port0_gen3_tx) + pch_iobp_update(SATA_IOBP_SP0G3IR, 0, + config->sata_port0_gen3_tx); + + if (config->sata_port1_gen3_tx) + pch_iobp_update(SATA_IOBP_SP1G3IR, 0, + config->sata_port1_gen3_tx); + + /* Set Gen3 DTLE DATA / EDGE registers if needed */ + if (config->sata_port0_gen3_dtle) { + pch_iobp_update(SATA_IOBP_SP0DTLE_DATA, + ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), + (config->sata_port0_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_DATA_SHIFT); + + pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE, + ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), + (config->sata_port0_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_EDGE_SHIFT); + } + + if (config->sata_port1_gen3_dtle) { + pch_iobp_update(SATA_IOBP_SP1DTLE_DATA, + ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), + (config->sata_port1_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_DATA_SHIFT); + + pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE, + ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), + (config->sata_port1_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_EDGE_SHIFT); + } + + /* + * Additional Programming Requirements for Power Optimizer + */ + + /* Step 1 */ + sir_write(dev, 0x64, 0x883c9003); + + /* Step 2: SIR 68h[15:0] = 880Ah */ + reg32 = sir_read(dev, 0x68); + reg32 &= 0xffff0000; + reg32 |= 0x880a; + sir_write(dev, 0x68, reg32); + + /* Step 3: SIR 60h[3] = 1 */ + reg32 = sir_read(dev, 0x60); + reg32 |= (1 << 3); + sir_write(dev, 0x60, reg32); + + /* Step 4: SIR 60h[0] = 1 */ + reg32 = sir_read(dev, 0x60); + reg32 |= (1 << 0); + sir_write(dev, 0x60, reg32); + + /* Step 5: SIR 60h[1] = 1 */ + reg32 = sir_read(dev, 0x60); + reg32 |= (1 << 1); + sir_write(dev, 0x60, reg32); + + /* Clock Gating */ + sir_write(dev, 0x70, 0x3f00bf1f); + sir_write(dev, 0x54, 0xcf000f0f); + sir_write(dev, 0x58, 0x00190000); + RCBA32_AND_OR(0x333c, 0xffcfffff, 0x00c00000); + + reg32 = pci_read_config32(dev, 0x300); + reg32 |= (1 << 17) | (1 << 16) | (1 << 19); + reg32 |= (1 << 31) | (1 << 30) | (1 << 29); + pci_write_config32(dev, 0x300, reg32); + + reg32 = pci_read_config32(dev, 0x98); + reg32 |= 1 << 29; + pci_write_config32(dev, 0x98, reg32); + + /* Register Lock */ + reg32 = pci_read_config32(dev, 0x9c); + reg32 |= (1 << 31); + pci_write_config32(dev, 0x9c, reg32); +} + +/* + * Set SATA controller mode early so the resource allocator can + * properly assign IO/Memory resources for the controller. + */ +static void sata_enable(device_t dev) +{ + /* Get the chip configuration */ + config_t *config = dev->chip_info; + u16 map = 0x0060; + + map |= (config->sata_port_map ^ 0xf) << 8; + + pci_write_config16(dev, 0x90, map); +} + +static struct device_operations sata_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &sata_init, + .enable = &sata_enable, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c03, 0x9c05, 0x9c07, 0x9c0f, /* LynxPoint-LP */ + 0x9c83, 0x9c85, 0x282a, 0x9c87, 0x282a, 0x9c8f, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_sata __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/serialio.c b/src/soc/intel/broadwell/serialio.c new file mode 100644 index 0000000000..9189059746 --- /dev/null +++ b/src/soc/intel/broadwell/serialio.c @@ -0,0 +1,318 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Set D3Hot Power State in ACPI mode */ +static void serialio_enable_d3hot(struct resource *res) +{ + u32 reg32 = read32(res->base + PCH_PCS); + reg32 |= PCH_PCS_PS_D3HOT; + write32(res->base + PCH_PCS, reg32); +} + +static int serialio_uart_is_debug(struct device *dev) +{ +#if CONFIG_INTEL_PCH_UART_CONSOLE + switch (dev->path.pci.devfn) { + case PCH_DEVFN_UART0: /* UART0 */ + return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 0); + case PCH_DEVFN_UART1: /* UART1 */ + return !!(CONFIG_INTEL_PCH_UART_CONSOLE_NUMBER == 1); + } +#endif + return 0; +} + +/* Enable clock in PCI mode */ +static void serialio_enable_clock(struct resource *bar0) +{ + u32 reg32 = read32(bar0->base + SIO_REG_PPR_CLOCK); + reg32 |= SIO_REG_PPR_CLOCK_EN; + write32(bar0->base + SIO_REG_PPR_CLOCK, reg32); +} + +/* Put Serial IO D21:F0-F6 device into desired mode. */ +static void serialio_d21_mode(int sio_index, int int_pin, int acpi_mode) +{ + u32 portctrl = SIO_IOBP_PORTCTRL_PM_CAP_PRSNT; + + /* Snoop select 1. */ + portctrl |= SIO_IOBP_PORTCTRL_SNOOP_SELECT(1); + + /* Set interrupt pin. */ + portctrl |= SIO_IOBP_PORTCTRL_INT_PIN(int_pin); + + if (acpi_mode) { + /* Enable ACPI interrupt mode. */ + portctrl |= SIO_IOBP_PORTCTRL_ACPI_IRQ_EN; + + /* Disable PCI config space. */ + portctrl |= SIO_IOBP_PORTCTRL_PCI_CONF_DIS; + } + + pch_iobp_update(SIO_IOBP_PORTCTRLX(sio_index), 0, portctrl); +} + +/* Put Serial IO D23:F0 device into desired mode. */ +static void serialio_d23_mode(int acpi_mode) +{ + u32 portctrl = 0; + + /* Snoop select 1. */ + pch_iobp_update(SIO_IOBP_PORTCTRL1, 0, + SIO_IOBP_PORTCTRL1_SNOOP_SELECT(1)); + + if (acpi_mode) { + /* Enable ACPI interrupt mode. */ + portctrl |= SIO_IOBP_PORTCTRL0_ACPI_IRQ_EN; + + /* Disable PCI config space. */ + portctrl |= SIO_IOBP_PORTCTRL0_PCI_CONF_DIS; + } + + pch_iobp_update(SIO_IOBP_PORTCTRL0, 0, portctrl); +} + +/* Enable LTR Auto Mode for D21:F1-F6. */ +static void serialio_d21_ltr(struct resource *bar0) +{ + u32 reg; + + /* 1. Program BAR0 + 808h[2] = 0b */ + reg = read32(bar0->base + SIO_REG_PPR_GEN); + reg &= ~SIO_REG_PPR_GEN_LTR_MODE_MASK; + write32(bar0->base + SIO_REG_PPR_GEN, reg); + + /* 2. Program BAR0 + 804h[1:0] = 00b */ + reg = read32(bar0->base + SIO_REG_PPR_RST); + reg &= ~SIO_REG_PPR_RST_ASSERT; + write32(bar0->base + SIO_REG_PPR_RST, reg); + + /* 3. Program BAR0 + 804h[1:0] = 11b */ + reg = read32(bar0->base + SIO_REG_PPR_RST); + reg |= SIO_REG_PPR_RST_ASSERT; + write32(bar0->base + SIO_REG_PPR_RST, reg); + + /* 4. Program BAR0 + 814h[31:0] = 00000000h */ + write32(bar0->base + SIO_REG_AUTO_LTR, 0); +} + +/* Enable LTR Auto Mode for D23:F0. */ +static void serialio_d23_ltr(struct resource *bar0) +{ + u32 reg; + + /* Program BAR0 + 1008h[2] = 1b */ + reg = read32(bar0->base + SIO_REG_SDIO_PPR_GEN); + reg |= SIO_REG_PPR_GEN_LTR_MODE_MASK; + write32(bar0->base + SIO_REG_SDIO_PPR_GEN, reg); + + /* Program BAR0 + 1010h = 0x00000000 */ + write32(bar0->base + SIO_REG_SDIO_PPR_SW_LTR, 0); + + /* Program BAR0 + 3Ch[30] = 1b */ + reg = read32(bar0->base + SIO_REG_SDIO_PPR_CMD12); + reg |= SIO_REG_SDIO_PPR_CMD12_B30; + write32(bar0->base + SIO_REG_SDIO_PPR_CMD12, reg); +} + +/* Select I2C voltage of 1.8V or 3.3V. */ +static void serialio_i2c_voltage_sel(struct resource *bar0, u8 voltage) +{ + u32 reg32 = read32(bar0->base + SIO_REG_PPR_GEN); + reg32 &= ~SIO_REG_PPR_GEN_VOLTAGE_MASK; + reg32 |= SIO_REG_PPR_GEN_VOLTAGE(voltage); + write32(bar0->base + SIO_REG_PPR_GEN, reg32); +} + +/* Init sequence to be run once, done as part of D21:F0 (SDMA) init. */ +static void serialio_init_once(int acpi_mode) +{ + if (acpi_mode) { + /* Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCBA. */ + RCBA32_OR(ACPIIRQEN, (1 << 13)|(1 << 7)|(1 << 6)|(1 << 5)); + } + + /* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b. */ + pch_iobp_update(SIO_IOBP_GPIODF, ~0x0000131f, 0x0000131f); + + /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */ + pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f); +} + +static void serialio_init(struct device *dev) +{ + config_t *config = dev->chip_info; + struct resource *bar0, *bar1; + int sio_index = -1; + u32 reg32; + + printk(BIOS_DEBUG, "Initializing Serial IO device\n"); + + /* Ensure memory and bus master are enabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Find BAR0 and BAR1 */ + bar0 = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!bar0) + return; + bar1 = find_resource(dev, PCI_BASE_ADDRESS_1); + if (!bar1) + return; + + if (!config->sio_acpi_mode) + serialio_enable_clock(bar0); + + switch (dev->path.pci.devfn) { + case PCH_DEVFN_SDMA: /* SDMA */ + sio_index = SIO_ID_SDMA; + serialio_init_once(config->sio_acpi_mode); + serialio_d21_mode(sio_index, SIO_PIN_INTB, + config->sio_acpi_mode); + break; + case PCH_DEVFN_I2C0: /* I2C0 */ + sio_index = SIO_ID_I2C0; + serialio_d21_ltr(bar0); + serialio_i2c_voltage_sel(bar0, config->sio_i2c0_voltage); + serialio_d21_mode(sio_index, SIO_PIN_INTC, + config->sio_acpi_mode); + break; + case PCH_DEVFN_I2C1: /* I2C1 */ + sio_index = SIO_ID_I2C1; + serialio_d21_ltr(bar0); + serialio_i2c_voltage_sel(bar0, config->sio_i2c1_voltage); + serialio_d21_mode(sio_index, SIO_PIN_INTC, + config->sio_acpi_mode); + break; + case PCH_DEVFN_SPI0: /* SPI0 */ + sio_index = SIO_ID_SPI0; + serialio_d21_ltr(bar0); + serialio_d21_mode(sio_index, SIO_PIN_INTC, + config->sio_acpi_mode); + break; + case PCH_DEVFN_SPI1: /* SPI1 */ + sio_index = SIO_ID_SPI1; + serialio_d21_ltr(bar0); + serialio_d21_mode(sio_index, SIO_PIN_INTC, + config->sio_acpi_mode); + break; + case PCH_DEVFN_UART0: /* UART0 */ + sio_index = SIO_ID_UART0; + if (!serialio_uart_is_debug(dev)) + serialio_d21_ltr(bar0); + serialio_d21_mode(sio_index, SIO_PIN_INTD, + config->sio_acpi_mode); + break; + case PCH_DEVFN_UART1: /* UART1 */ + sio_index = SIO_ID_UART1; + if (!serialio_uart_is_debug(dev)) + serialio_d21_ltr(bar0); + serialio_d21_mode(sio_index, SIO_PIN_INTD, + config->sio_acpi_mode); + break; + case PCH_DEVFN_SDIO: /* SDIO */ + sio_index = SIO_ID_SDIO; + serialio_d23_ltr(bar0); + serialio_d23_mode(config->sio_acpi_mode); + break; + default: + return; + } + + if (config->sio_acpi_mode) { + global_nvs_t *gnvs; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + gnvs->dev.bar0[sio_index] = (u32)bar0->base; + gnvs->dev.bar1[sio_index] = (u32)bar1->base; + + /* Do not enable UART if it is used as debug port */ + if (!serialio_uart_is_debug(dev)) + gnvs->dev.enable[sio_index] = 1; + + /* Put device in D3hot state via BAR1 */ + if (dev->path.pci.devfn != PCH_DEVFN_SDMA) + serialio_enable_d3hot(bar1); /* all but SDMA */ + } +} + +static void serialio_set_resources(struct device *dev) +{ + pci_dev_set_resources(dev); + +#if CONFIG_INTEL_PCH_UART_CONSOLE + /* Update UART base address if used for debug */ + if (serialio_uart_is_debug(dev)) { + struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) + uartmem_setbaseaddr(res->base); + } +#endif +} + +static struct device_operations device_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &serialio_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &serialio_init, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c60, 0x9ce0, /* 0:15.0 - SDMA */ + 0x9c61, 0x9ce1, /* 0:15.1 - I2C0 */ + 0x9c62, 0x9ce2, /* 0:15.2 - I2C1 */ + 0x9c65, 0x9ce5, /* 0:15.3 - SPI0 */ + 0x9c66, 0x9ce6, /* 0:15.4 - SPI1 */ + 0x9c63, 0x9ce3, /* 0:15.5 - UART0 */ + 0x9c64, 0x9ce4, /* 0:15.6 - UART1 */ + 0x9c35, 0x9cb5, /* 0:17.0 - SDIO */ + 0 +}; + +static const struct pci_driver pch_pcie __pci_driver = { + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/smbus.c b/src/soc/intel/broadwell/smbus.c new file mode 100644 index 0000000000..0ec84b27db --- /dev/null +++ b/src/soc/intel/broadwell/smbus.c @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void pch_smbus_init(device_t dev) +{ + struct resource *res; + u16 reg16; + + /* Enable clock gating */ + reg16 = pci_read_config32(dev, 0x80); + reg16 &= ~((1 << 8)|(1 << 10)|(1 << 12)|(1 << 14)); + pci_write_config32(dev, 0x80, reg16); + + /* Set Receive Slave Address */ + res = find_resource(dev, PCI_BASE_ADDRESS_4); + if (res) + outb(SMBUS_SLAVE_ADDR, res->base + SMB_RCV_SLVA); +} + +static int lsmbus_read_byte(device_t dev, u8 address) +{ + u16 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); + + return do_smbus_read_byte(res->base, device, address); +} + +static int lsmbus_write_byte(device_t dev, u8 address, u8 data) +{ + u16 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); + return do_smbus_write_byte(res->base, device, address, data); +} + +static struct smbus_bus_operations lops_smbus_bus = { + .read_byte = lsmbus_read_byte, + .write_byte = lsmbus_write_byte, +}; + +static void smbus_read_resources(device_t dev) +{ + struct resource *res = new_resource(dev, PCI_BASE_ADDRESS_4); + res->base = SMBUS_BASE_ADDRESS; + res->size = 32; + res->limit = res->base + res->size - 1; + res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | + IORESOURCE_STORED | IORESOURCE_ASSIGNED; + + /* Also add MMIO resource */ + res = pci_get_resource(dev, PCI_BASE_ADDRESS_0); +} + +static struct device_operations smbus_ops = { + .read_resources = &smbus_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .scan_bus = &scan_static_bus, + .init = &pch_smbus_init, + .ops_smbus_bus = &lops_smbus_bus, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c22, /* LynxPoint */ + 0x9ca2, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_smbus __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/soc/intel/broadwell/smbus_common.c b/src/soc/intel/broadwell/smbus_common.c new file mode 100644 index 0000000000..41416c712c --- /dev/null +++ b/src/soc/intel/broadwell/smbus_common.c @@ -0,0 +1,155 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2005 Yinghai Lu + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void smbus_delay(void) +{ + inb(0x80); +} + +static int smbus_wait_until_ready(u16 smbus_base) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(smbus_base + SMBHSTSTAT); + } while (byte & 1); + return loops ? 0 : -1; +} + +static int smbus_wait_until_done(u16 smbus_base) +{ + unsigned loops = SMBUS_TIMEOUT; + unsigned char byte; + do { + smbus_delay(); + if (--loops == 0) + break; + byte = inb(smbus_base + SMBHSTSTAT); + } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0); + return loops ? 0 : -1; +} + +int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address) +{ + unsigned char global_status_register; + unsigned char byte; + + if (smbus_wait_until_ready(smbus_base) < 0) { + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + } + /* Setup transaction */ + /* Disable interrupts */ + outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL); + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD); + /* Set the command/address... */ + outb(address & 0xff, smbus_base + SMBHSTCMD); + /* Set up for a byte data read */ + outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2), + (smbus_base + SMBHSTCTL)); + /* Clear any lingering errors, so the transaction will run */ + outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); + + /* Clear the data byte... */ + outb(0, smbus_base + SMBHSTDAT0); + + /* Start the command */ + outb((inb(smbus_base + SMBHSTCTL) | 0x40), + smbus_base + SMBHSTCTL); + + /* Poll for transaction completion */ + if (smbus_wait_until_done(smbus_base) < 0) { + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inb(smbus_base + SMBHSTSTAT); + + /* Ignore the "In Use" status... */ + global_status_register &= ~(3 << 5); + + /* Read results of transaction */ + byte = inb(smbus_base + SMBHSTDAT0); + if (global_status_register != (1 << 1)) { + return SMBUS_ERROR; + } + return byte; +} + +int do_smbus_write_byte(unsigned smbus_base, unsigned device, + unsigned address, unsigned data) +{ + unsigned char global_status_register; + + if (smbus_wait_until_ready(smbus_base) < 0) + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + + /* Setup transaction */ + /* Disable interrupts */ + outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL); + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD); + /* Set the command/address... */ + outb(address & 0xff, smbus_base + SMBHSTCMD); + /* Set up for a byte data read */ + outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2), + (smbus_base + SMBHSTCTL)); + /* Clear any lingering errors, so the transaction will run */ + outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); + + /* Clear the data byte... */ + outb(data, smbus_base + SMBHSTDAT0); + + /* Start the command */ + outb((inb(smbus_base + SMBHSTCTL) | 0x40), + smbus_base + SMBHSTCTL); + + /* Poll for transaction completion */ + if (smbus_wait_until_done(smbus_base) < 0) { + printk(BIOS_ERR, "SMBUS transaction timeout\n"); + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inb(smbus_base + SMBHSTSTAT); + + /* Ignore the "In Use" status... */ + global_status_register &= ~(3 << 5); + + /* Read results of transaction */ + if (global_status_register != (1 << 1)) { + printk(BIOS_ERR, "SMBUS transaction error\n"); + return SMBUS_ERROR; + } + + return 0; +} diff --git a/src/soc/intel/broadwell/smi.c b/src/soc/intel/broadwell/smi.c new file mode 100644 index 0000000000..85a508b629 --- /dev/null +++ b/src/soc/intel/broadwell/smi.c @@ -0,0 +1,123 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void southbridge_smm_clear_state(void) +{ + u32 smi_en; + + printk(BIOS_DEBUG, "Initializing Southbridge SMI..."); + printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", ACPI_BASE_ADDRESS); + + smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN); + if (smi_en & APMC_EN) { + printk(BIOS_INFO, "SMI# handler already enabled?\n"); + return; + } + + printk(BIOS_DEBUG, "\n"); + + /* Dump and clear status registers */ + clear_smi_status(); + clear_pm1_status(); + clear_tco_status(); + clear_gpe_status(); +} + +void southbridge_smm_enable_smi(void) +{ + printk(BIOS_DEBUG, "Enabling SMIs.\n"); + /* Configure events */ + enable_pm1(PWRBTN_EN | GBL_EN); + disable_gpe(PME_B0_EN); + + /* Enable SMI generation: + * - on APMC writes (io 0xb2) + * - on writes to SLP_EN (sleep states) + * - on writes to GBL_RLS (bios commands) + * No SMIs: + * - on microcontroller writes (io 0x62/0x66) + * - on TCO events + */ + enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS); +} + +void southbridge_trigger_smi(void) +{ + /** + * There are several methods of raising a controlled SMI# via + * software, among them: + * - Writes to io 0xb2 (APMC) + * - Writes to the Local Apic ICR with Delivery mode SMI. + * + * Using the local apic is a bit more tricky. According to + * AMD Family 11 Processor BKDG no destination shorthand must be + * used. + * The whole SMM initialization is quite a bit hardware specific, so + * I'm not too worried about the better of the methods at the moment + */ + + /* raise an SMI interrupt */ + printk(BIOS_SPEW, " ... raise SMI#\n"); + outb(0x00, 0xb2); +} + +void southbridge_clear_smi_status(void) +{ + /* Clear SMI status */ + clear_smi_status(); + + /* Clear PM1 status */ + clear_pm1_status(); + + /* Set EOS bit so other SMIs can occur. */ + enable_smi(EOS); +} + +void smm_setup_structures(void *gnvs, void *tcg, void *smi1) +{ + /* + * Issue SMI to set the gnvs pointer in SMM. + * tcg and smi1 are unused. + * + * EAX = APM_CNT_GNVS_UPDATE + * EBX = gnvs pointer + * EDX = APM_CNT + */ + asm volatile ( + "outb %%al, %%dx\n\t" + : /* ignore result */ + : "a" (APM_CNT_GNVS_UPDATE), + "b" ((u32)gnvs), + "d" (APM_CNT) + ); +} diff --git a/src/soc/intel/broadwell/smihandler.c b/src/soc/intel/broadwell/smihandler.c new file mode 100644 index 0000000000..235bbd5218 --- /dev/null +++ b/src/soc/intel/broadwell/smihandler.c @@ -0,0 +1,548 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u8 smm_initialized = 0; + +/* + * GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located + * by coreboot. + */ +static global_nvs_t *gnvs; +global_nvs_t *smm_get_gnvs(void) +{ + return gnvs; +} + +int southbridge_io_trap_handler(int smif) +{ + switch (smif) { + case 0x32: + printk(BIOS_DEBUG, "OS Init\n"); + /* gnvs->smif: + * On success, the IO Trap Handler returns 0 + * On failure, the IO Trap Handler returns a value != 0 + */ + gnvs->smif = 0; + return 1; /* IO trap handled */ + } + + /* Not handled */ + return 0; +} + +/** + * @brief Set the EOS bit + */ +void southbridge_smi_set_eos(void) +{ + enable_smi(EOS); +} + +static void busmaster_disable_on_bus(int bus) +{ + int slot, func; + unsigned int val; + unsigned char hdr; + + for (slot = 0; slot < 0x20; slot++) { + for (func = 0; func < 8; func++) { + u32 reg32; + device_t dev = PCI_DEV(bus, slot, func); + + val = pci_read_config32(dev, PCI_VENDOR_ID); + + if (val == 0xffffffff || val == 0x00000000 || + val == 0x0000ffff || val == 0xffff0000) + continue; + + /* Disable Bus Mastering for this one device */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~PCI_COMMAND_MASTER; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* If this is a bridge, then follow it. */ + hdr = pci_read_config8(dev, PCI_HEADER_TYPE); + hdr &= 0x7f; + if (hdr == PCI_HEADER_TYPE_BRIDGE || + hdr == PCI_HEADER_TYPE_CARDBUS) { + unsigned int buses; + buses = pci_read_config32(dev, PCI_PRIMARY_BUS); + busmaster_disable_on_bus((buses >> 8) & 0xff); + } + } + } +} + + +static void southbridge_smi_sleep(void) +{ + u8 reg8; + u32 reg32; + u8 slp_typ; + u8 s5pwr = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + + /* save and recover RTC port values */ + u8 tmp70, tmp72; + tmp70 = inb(0x70); + tmp72 = inb(0x72); + get_option(&s5pwr, "power_on_after_fail"); + outb(tmp70, 0x70); + outb(tmp72, 0x72); + + /* First, disable further SMIs */ + disable_smi(SLP_SMI_EN); + + /* Figure out SLP_TYP */ + reg32 = inl(ACPI_BASE_ADDRESS + PM1_CNT); + printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32); + slp_typ = (reg32 >> 10) & 7; + + /* Do any mainboard sleep handling */ + mainboard_smi_sleep(slp_typ-2); + + /* USB sleep preparations */ + usb_xhci_sleep_prepare(PCH_DEV_XHCI, slp_typ); + +#if CONFIG_ELOG_GSMI + /* Log S3, S4, and S5 entry */ + if (slp_typ >= 5) + elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2); +#endif + + /* Clear pending GPE events */ + clear_gpe_status(); + + /* Next, do the deed. + */ + + switch (slp_typ) { + case SLP_TYP_S0: + printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); + break; + case SLP_TYP_S1: + printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n"); + break; + case SLP_TYP_S3: + printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n"); + + /* Invalidate the cache before going to S3 */ + wbinvd(); + break; + case SLP_TYP_S4: + printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); + break; + case SLP_TYP_S5: + printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n"); + + /* Disable all GPE */ + disable_all_gpe(); + + /* Always set the flag in case CMOS was changed on runtime. For + * "KEEP", switch to "OFF" - KEEP is software emulated + */ + reg8 = pci_read_config8(PCH_DEV_LPC, GEN_PMCON_3); + if (s5pwr == MAINBOARD_POWER_ON) + reg8 &= ~1; + else + reg8 |= 1; + pci_write_config8(PCH_DEV_LPC, GEN_PMCON_3, reg8); + + /* also iterates over all bridges on bus 0 */ + busmaster_disable_on_bus(0); + break; + default: + printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); + break; + } + + /* + * Write back to the SLP register to cause the originally intended + * event again. We need to set BIT13 (SLP_EN) though to make the + * sleep happen. + */ + enable_pm1_control(SLP_EN); + + /* Make sure to stop executing code here for S3/S4/S5 */ + if (slp_typ > 1) + hlt(); + + /* + * In most sleep states, the code flow of this function ends at + * the line above. However, if we entered sleep state S1 and wake + * up again, we will continue to execute code in this function. + */ + reg32 = inl(ACPI_BASE_ADDRESS + PM1_CNT); + if (reg32 & SCI_EN) { + /* The OS is not an ACPI OS, so we set the state to S0 */ + disable_pm1_control(SLP_EN | SLP_TYP); + } +} + +/* + * Look for Synchronous IO SMI and use save state from that + * core in case we are not running on the same core that + * initiated the IO transaction. + */ +static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd) +{ + em64t101_smm_state_save_area_t *state; + int node; + + /* Check all nodes looking for the one that issued the IO */ + for (node = 0; node < CONFIG_MAX_CPUS; node++) { + state = smm_get_save_state(node); + + /* Check for Synchronous IO (bit0==1) */ + if (!(state->io_misc_info & (1 << 0))) + continue; + + /* Make sure it was a write (bit4==0) */ + if (state->io_misc_info & (1 << 4)) + continue; + + /* Check for APMC IO port */ + if (((state->io_misc_info >> 16) & 0xff) != APM_CNT) + continue; + + /* Check AX against the requested command */ + if ((state->rax & 0xff) != cmd) + continue; + + return state; + } + + return NULL; +} + +#if CONFIG_ELOG_GSMI +static void southbridge_smi_gsmi(void) +{ + u32 *ret, *param; + u8 sub_command; + em64t101_smm_state_save_area_t *io_smi = + smi_apmc_find_state_save(ELOG_GSMI_APM_CNT); + + if (!io_smi) + return; + + /* Command and return value in EAX */ + ret = (u32*)&io_smi->rax; + sub_command = (u8)(*ret >> 8); + + /* Parameter buffer in EBX */ + param = (u32*)&io_smi->rbx; + + /* drivers/elog/gsmi.c */ + *ret = gsmi_exec(sub_command, param); +} +#endif + +static void finalize(void) +{ + static int finalize_done; + + if (finalize_done) { + printk(BIOS_DEBUG, "SMM already finalized.\n"); + return; + } + finalize_done = 1; + +#if CONFIG_SPI_FLASH_SMM + /* Re-init SPI driver to handle locked BAR */ + spi_init(); +#endif +} + +static void southbridge_smi_apmc(void) +{ + u8 reg8; + em64t101_smm_state_save_area_t *state; + + /* Emulate B2 register as the FADT / Linux expects it */ + + reg8 = inb(APM_CNT); + switch (reg8) { + case APM_CNT_CST_CONTROL: + printk(BIOS_DEBUG, "C-state control\n"); + break; + case APM_CNT_PST_CONTROL: + printk(BIOS_DEBUG, "P-state control\n"); + break; + case APM_CNT_ACPI_DISABLE: + disable_pm1_control(SCI_EN); + printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n"); + break; + case APM_CNT_ACPI_ENABLE: + enable_pm1_control(SCI_EN); + printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n"); + break; + case APM_CNT_FINALIZE: + finalize(); + break; + case APM_CNT_GNVS_UPDATE: + if (smm_initialized) { + printk(BIOS_DEBUG, + "SMI#: SMM structures already initialized!\n"); + return; + } + state = smi_apmc_find_state_save(reg8); + if (state) { + /* EBX in the state save contains the GNVS pointer */ + gnvs = (global_nvs_t *)((u32)state->rbx); + smm_initialized = 1; + printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs); + } + break; +#if CONFIG_ELOG_GSMI + case ELOG_GSMI_APM_CNT: + southbridge_smi_gsmi(); + break; +#endif + } + + mainboard_smi_apmc(reg8); +} + +static void southbridge_smi_pm1(void) +{ + u16 pm1_sts = clear_pm1_status(); + + /* While OSPM is not active, poweroff immediately + * on a power button event. + */ + if (pm1_sts & PWRBTN_STS) { + /* power button pressed */ +#if CONFIG_ELOG_GSMI + elog_add_event(ELOG_TYPE_POWER_BUTTON); +#endif + disable_pm1_control(-1UL); + enable_pm1_control(SLP_EN | (SLP_TYP_S5 << 10)); + } +} + +static void southbridge_smi_gpe0(void) +{ + clear_gpe_status(); +} + +static void southbridge_smi_gpi(void) +{ + mainboard_smi_gpi(clear_alt_smi_status()); + + /* Clear again after mainboard handler */ + clear_alt_smi_status(); +} + +static void southbridge_smi_mc(void) +{ + u32 reg32 = inl(ACPI_BASE_ADDRESS + SMI_EN); + + /* Are microcontroller SMIs enabled? */ + if ((reg32 & MCSMI_EN) == 0) + return; + + printk(BIOS_DEBUG, "Microcontroller SMI.\n"); +} + +static void southbridge_smi_tco(void) +{ + u32 tco_sts = clear_tco_status(); + + /* Any TCO event? */ + if (!tco_sts) + return; + + if (tco_sts & (1 << 8)) { // BIOSWR + u8 bios_cntl = pci_read_config16(PCH_DEV_LPC, BIOS_CNTL); + + if (bios_cntl & 1) { + /* + * BWE is RW, so the SMI was caused by a + * write to BWE, not by a write to the BIOS + * + * This is the place where we notice someone + * is trying to tinker with the BIOS. We are + * trying to be nice and just ignore it. A more + * resolute answer would be to power down the + * box. + */ + printk(BIOS_DEBUG, "Switching back to RO\n"); + pci_write_config32(PCH_DEV_LPC, BIOS_CNTL, + (bios_cntl & ~1)); + } /* No else for now? */ + } else if (tco_sts & (1 << 3)) { /* TIMEOUT */ + /* Handle TCO timeout */ + printk(BIOS_DEBUG, "TCO Timeout.\n"); + } +} + +static void southbridge_smi_periodic(void) +{ + u32 reg32 = inl(ACPI_BASE_ADDRESS + SMI_EN); + + /* Are periodic SMIs enabled? */ + if ((reg32 & PERIODIC_EN) == 0) + return; + + printk(BIOS_DEBUG, "Periodic SMI.\n"); +} + +static void southbridge_smi_monitor(void) +{ +#define IOTRAP(x) (trap_sts & (1 << x)) + u32 trap_sts, trap_cycle; + u32 data, mask = 0; + int i; + + trap_sts = RCBA32(0x1e00); // TRSR - Trap Status Register + RCBA32(0x1e00) = trap_sts; // Clear trap(s) in TRSR + + trap_cycle = RCBA32(0x1e10); + for (i=16; i<20; i++) { + if (trap_cycle & (1 << i)) + mask |= (0xff << ((i - 16) << 2)); + } + + + /* IOTRAP(3) SMI function call */ + if (IOTRAP(3)) { + if (gnvs && gnvs->smif) + io_trap_handler(gnvs->smif); // call function smif + return; + } + + /* IOTRAP(2) currently unused + * IOTRAP(1) currently unused */ + + /* IOTRAP(0) SMIC */ + if (IOTRAP(0)) { + if (!(trap_cycle & (1 << 24))) { // It's a write + printk(BIOS_DEBUG, "SMI1 command\n"); + data = RCBA32(0x1e18); + data &= mask; + // if (smi1) + // southbridge_smi_command(data); + // return; + } + // Fall through to debug + } + + printk(BIOS_DEBUG, " trapped io address = 0x%x\n", + trap_cycle & 0xfffc); + for (i=0; i < 4; i++) + if(IOTRAP(i)) printk(BIOS_DEBUG, " TRAP = %d\n", i); + printk(BIOS_DEBUG, " AHBE = %x\n", (trap_cycle >> 16) & 0xf); + printk(BIOS_DEBUG, " MASK = 0x%08x\n", mask); + printk(BIOS_DEBUG, " read/write: %s\n", + (trap_cycle & (1 << 24)) ? "read" : "write"); + + if (!(trap_cycle & (1 << 24))) { + /* Write Cycle */ + data = RCBA32(0x1e18); + printk(BIOS_DEBUG, " iotrap written data = 0x%08x\n", data); + } +#undef IOTRAP +} + +typedef void (*smi_handler_t)(void); + +static smi_handler_t southbridge_smi[32] = { + NULL, // [0] reserved + NULL, // [1] reserved + NULL, // [2] BIOS_STS + NULL, // [3] LEGACY_USB_STS + southbridge_smi_sleep, // [4] SLP_SMI_STS + southbridge_smi_apmc, // [5] APM_STS + NULL, // [6] SWSMI_TMR_STS + NULL, // [7] reserved + southbridge_smi_pm1, // [8] PM1_STS + southbridge_smi_gpe0, // [9] GPE0_STS + southbridge_smi_gpi, // [10] GPI_STS + southbridge_smi_mc, // [11] MCSMI_STS + NULL, // [12] DEVMON_STS + southbridge_smi_tco, // [13] TCO_STS + southbridge_smi_periodic, // [14] PERIODIC_STS + NULL, // [15] SERIRQ_SMI_STS + NULL, // [16] SMBUS_SMI_STS + NULL, // [17] LEGACY_USB2_STS + NULL, // [18] INTEL_USB2_STS + NULL, // [19] reserved + NULL, // [20] PCI_EXP_SMI_STS + southbridge_smi_monitor, // [21] MONITOR_STS + NULL, // [22] reserved + NULL, // [23] reserved + NULL, // [24] reserved + NULL, // [25] EL_SMI_STS + NULL, // [26] SPI_STS + NULL, // [27] reserved + NULL, // [28] reserved + NULL, // [29] reserved + NULL, // [30] reserved + NULL // [31] reserved +}; + +/** + * @brief Interrupt handler for SMI# + * + * @param smm_revision revision of the smm state save map + */ + +void southbridge_smi_handler(void) +{ + int i; + u32 smi_sts; + + /* We need to clear the SMI status registers, or we won't see what's + * happening in the following calls. + */ + smi_sts = clear_smi_status(); + + /* Call SMI sub handler for each of the status bits */ + for (i = 0; i < 31; i++) { + if (smi_sts & (1 << i)) { + if (southbridge_smi[i]) { + southbridge_smi[i](); + } else { + printk(BIOS_DEBUG, + "SMI_STS[%d] occured, but no " + "handler available.\n", i); + } + } + } +} diff --git a/src/soc/intel/broadwell/smmrelocate.c b/src/soc/intel/broadwell/smmrelocate.c new file mode 100644 index 0000000000..47d6385a63 --- /dev/null +++ b/src/soc/intel/broadwell/smmrelocate.c @@ -0,0 +1,439 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* This gets filled in and used during relocation. */ +static struct smm_relocation_params smm_reloc_params; + +static inline void write_smrr(struct smm_relocation_params *relo_params) +{ + printk(BIOS_DEBUG, "Writing SMRR. base = 0x%08x, mask=0x%08x\n", + relo_params->smrr_base.lo, relo_params->smrr_mask.lo); + wrmsr(SMRRphysBase_MSR, relo_params->smrr_base); + wrmsr(SMRRphysMask_MSR, relo_params->smrr_mask); +} + +static inline void write_emrr(struct smm_relocation_params *relo_params) +{ + printk(BIOS_DEBUG, "Writing EMRR. base = 0x%08x, mask=0x%08x\n", + relo_params->emrr_base.lo, relo_params->emrr_mask.lo); + wrmsr(EMRRphysBase_MSR, relo_params->emrr_base); + wrmsr(EMRRphysMask_MSR, relo_params->emrr_mask); +} + +static inline void write_uncore_emrr(struct smm_relocation_params *relo_params) +{ + printk(BIOS_DEBUG, + "Writing UNCORE_EMRR. base = 0x%08x, mask=0x%08x\n", + relo_params->uncore_emrr_base.lo, + relo_params->uncore_emrr_mask.lo); + wrmsr(UNCORE_EMRRphysBase_MSR, relo_params->uncore_emrr_base); + wrmsr(UNCORE_EMRRphysMask_MSR, relo_params->uncore_emrr_mask); +} + +static void update_save_state(int cpu, + struct smm_relocation_params *relo_params, + const struct smm_runtime *runtime) +{ + u32 smbase; + u32 iedbase; + + /* The relocated handler runs with all CPUs concurrently. Therefore + * stagger the entry points adjusting SMBASE downwards by save state + * size * CPU num. */ + smbase = relo_params->smram_base - cpu * runtime->save_state_size; + iedbase = relo_params->ied_base; + + printk(BIOS_DEBUG, "New SMBASE=0x%08x IEDBASE=0x%08x\n", + smbase, iedbase); + + /* All threads need to set IEDBASE and SMBASE to the relocated + * handler region. However, the save state location depends on the + * smm_save_state_in_msrs field in the relocation parameters. If + * smm_save_state_in_msrs is non-zero then the CPUs are relocating + * the SMM handler in parallel, and each CPUs save state area is + * located in their respective MSR space. If smm_save_state_in_msrs + * is zero then the SMM relocation is happening serially so the + * save state is at the same default location for all CPUs. */ + if (relo_params->smm_save_state_in_msrs) { + msr_t smbase_msr; + msr_t iedbase_msr; + + smbase_msr.lo = smbase; + smbase_msr.hi = 0; + + /* According the BWG the IEDBASE MSR is in bits 63:32. It's + * not clear why it differs from the SMBASE MSR. */ + iedbase_msr.lo = 0; + iedbase_msr.hi = iedbase; + + wrmsr(SMBASE_MSR, smbase_msr); + wrmsr(IEDBASE_MSR, iedbase_msr); + } else { + em64t101_smm_state_save_area_t *save_state; + + save_state = (void *)(runtime->smbase + SMM_DEFAULT_SIZE - + runtime->save_state_size); + + save_state->smbase = smbase; + save_state->iedbase = iedbase; + } +} + +/* Returns 1 if SMM MSR save state was set. */ +static int bsp_setup_msr_save_state(struct smm_relocation_params *relo_params) +{ + msr_t smm_mca_cap; + + smm_mca_cap = rdmsr(SMM_MCA_CAP_MSR); + if (smm_mca_cap.hi & SMM_CPU_SVRSTR_MASK) { + msr_t smm_feature_control; + + smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR); + smm_feature_control.hi = 0; + smm_feature_control.lo |= SMM_CPU_SAVE_EN; + wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control); + relo_params->smm_save_state_in_msrs = 1; + } + return relo_params->smm_save_state_in_msrs; +} + +/* The relocation work is actually performed in SMM context, but the code + * resides in the ramstage module. This occurs by trampolining from the default + * SMRAM entry point to here. */ +static void asmlinkage cpu_smm_do_relocation(void *arg) +{ + msr_t mtrr_cap; + struct smm_relocation_params *relo_params; + const struct smm_module_params *p; + const struct smm_runtime *runtime; + int cpu; + + p = arg; + runtime = p->runtime; + relo_params = p->arg; + cpu = p->cpu; + + if (cpu >= CONFIG_MAX_CPUS) { + printk(BIOS_CRIT, + "Invalid CPU number assigned in SMM stub: %d\n", cpu); + return; + } + + printk(BIOS_DEBUG, "In relocation handler: cpu %d\n", cpu); + + /* Determine if the processor supports saving state in MSRs. If so, + * enable it before the non-BSPs run so that SMM relocation can occur + * in parallel in the non-BSP CPUs. */ + if (cpu == 0) { + /* If smm_save_state_in_msrs is 1 then that means this is the + * 2nd time through the relocation handler for the BSP. + * Parallel SMM handler relocation is taking place. However, + * it is desired to access other CPUs save state in the real + * SMM handler. Therefore, disable the SMM save state in MSRs + * feature. */ + if (relo_params->smm_save_state_in_msrs) { + msr_t smm_feature_control; + + smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR); + smm_feature_control.lo &= ~SMM_CPU_SAVE_EN; + wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control); + } else if (bsp_setup_msr_save_state(relo_params)) + /* Just return from relocation handler if MSR save + * state is enabled. In that case the BSP will come + * back into the relocation handler to setup the new + * SMBASE as well disabling SMM save state in MSRs. */ + return; + } + + /* Make appropriate changes to the save state map. */ + update_save_state(cpu, relo_params, runtime); + + /* Write EMRR and SMRR MSRs based on indicated support. */ + mtrr_cap = rdmsr(MTRRcap_MSR); + if (mtrr_cap.lo & SMRR_SUPPORTED) + write_smrr(relo_params); + + if (mtrr_cap.lo & EMRR_SUPPORTED) { + write_emrr(relo_params); + /* UNCORE_EMRR msrs are package level. Therefore, only + * configure these MSRs on the BSP. */ + if (cpu == 0) + write_uncore_emrr(relo_params); + } +} + +static u32 northbridge_get_base_reg(device_t dev, int reg) +{ + u32 value; + + value = pci_read_config32(dev, reg); + /* Base registers are at 1MiB granularity. */ + value &= ~((1 << 20) - 1); + return value; +} + +static void fill_in_relocation_params(device_t dev, + struct smm_relocation_params *params) +{ + u32 tseg_size; + u32 tsegmb; + u32 bgsm; + u32 emrr_base; + u32 emrr_size; + int phys_bits; + /* All range registers are aligned to 4KiB */ + const u32 rmask = ~((1 << 12) - 1); + + /* Some of the range registers are dependent on the number of physical + * address bits supported. */ + phys_bits = cpuid_eax(0x80000008) & 0xff; + + /* The range bounded by the TSEGMB and BGSM registers encompasses the + * SMRAM range as well as the IED range. However, the SMRAM available + * to the handler is 4MiB since the IEDRAM lives TSEGMB + 4MiB. + */ + tsegmb = northbridge_get_base_reg(dev, TSEG); + bgsm = northbridge_get_base_reg(dev, BGSM); + tseg_size = bgsm - tsegmb; + + params->smram_base = tsegmb; + params->smram_size = 4 << 20; + params->ied_base = tsegmb + params->smram_size; + params->ied_size = tseg_size - params->smram_size; + + /* Adjust available SMM handler memory size. */ + params->smram_size -= CONFIG_SMM_RESERVED_SIZE; + + /* SMRR has 32-bits of valid address aligned to 4KiB. */ + params->smrr_base.lo = (params->smram_base & rmask) | MTRR_TYPE_WRBACK; + params->smrr_base.hi = 0; + params->smrr_mask.lo = (~(tseg_size - 1) & rmask) | MTRRphysMaskValid; + params->smrr_mask.hi = 0; + + /* The EMRR and UNCORE_EMRR are at IEDBASE + 2MiB */ + emrr_base = (params->ied_base + (2 << 20)) & rmask; + emrr_size = params->ied_size - (2 << 20); + + /* EMRR has 46 bits of valid address aligned to 4KiB. It's dependent + * on the number of physical address bits supported. */ + params->emrr_base.lo = emrr_base | MTRR_TYPE_WRBACK; + params->emrr_base.hi = 0; + params->emrr_mask.lo = (~(emrr_size - 1) & rmask) | MTRRphysMaskValid; + params->emrr_mask.hi = (1 << (phys_bits - 32)) - 1; + + /* UNCORE_EMRR has 39 bits of valid address aligned to 4KiB. */ + params->uncore_emrr_base.lo = emrr_base; + params->uncore_emrr_base.hi = 0; + params->uncore_emrr_mask.lo = (~(emrr_size - 1) & rmask) | + MTRRphysMaskValid; + params->uncore_emrr_mask.hi = (1 << (39 - 32)) - 1; +} + +static void adjust_apic_id_map(struct smm_loader_params *smm_params) +{ + struct smm_runtime *runtime; + int i; + + /* Adjust the APIC id map if HT is disabled. */ + if (!ht_disabled) + return; + + runtime = smm_params->runtime; + + /* The APIC ids increment by 2 when HT is disabled. */ + for (i = 0; i < CONFIG_MAX_CPUS; i++) + runtime->apic_id_to_cpu[i] = runtime->apic_id_to_cpu[i] * 2; +} + +static int install_relocation_handler(int num_cpus, + struct smm_relocation_params *relo_params) +{ + /* The default SMM entry can happen in parallel or serially. If the + * default SMM entry is done in parallel the BSP has already setup + * the saving state to each CPU's MSRs. At least one save state size + * is required for the initial SMM entry for the BSP to determine if + * parallel SMM relocation is even feasible. Set the stack size to + * the save state size, and call into the do_relocation handler. */ + int save_state_size = sizeof(em64t101_smm_state_save_area_t); + struct smm_loader_params smm_params = { + .per_cpu_stack_size = save_state_size, + .num_concurrent_stacks = num_cpus, + .per_cpu_save_state_size = save_state_size, + .num_concurrent_save_states = 1, + .handler = (smm_handler_t)&cpu_smm_do_relocation, + .handler_arg = (void *)relo_params, + }; + + if (smm_setup_relocation_handler(&smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; +} + +static void setup_ied_area(struct smm_relocation_params *params) +{ + char *ied_base; + + struct ied_header ied = { + .signature = "INTEL RSVD", + .size = params->ied_size, + .reserved = {0}, + }; + + ied_base = (void *)params->ied_base; + + /* Place IED header at IEDBASE. */ + memcpy(ied_base, &ied, sizeof(ied)); + + /* Zero out 32KiB at IEDBASE + 1MiB */ + memset(ied_base + (1 << 20), 0, (32 << 10)); +} + +static int install_permanent_handler(int num_cpus, + struct smm_relocation_params *relo_params) +{ + /* There are num_cpus concurrent stacks and num_cpus concurrent save + * state areas. Lastly, set the stack size to the save state size. */ + int save_state_size = sizeof(em64t101_smm_state_save_area_t); + struct smm_loader_params smm_params = { + .per_cpu_stack_size = save_state_size, + .num_concurrent_stacks = num_cpus, + .per_cpu_save_state_size = save_state_size, + .num_concurrent_save_states = num_cpus, + }; + + printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", + relo_params->smram_base); + if (smm_load_module((void *)relo_params->smram_base, + relo_params->smram_size, &smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; +} + +static int cpu_smm_setup(void) +{ + device_t dev = SA_DEV_ROOT; + int num_cpus; + msr_t msr; + + printk(BIOS_DEBUG, "Setting up SMI for CPU\n"); + + fill_in_relocation_params(dev, &smm_reloc_params); + + setup_ied_area(&smm_reloc_params); + + msr = rdmsr(CORE_THREAD_COUNT_MSR); + num_cpus = msr.lo & 0xffff; + if (num_cpus > CONFIG_MAX_CPUS) { + printk(BIOS_CRIT, + "Error: Hardware CPUs (%d) > MAX_CPUS (%d)\n", + num_cpus, CONFIG_MAX_CPUS); + } + + if (install_relocation_handler(num_cpus, &smm_reloc_params)) { + printk(BIOS_CRIT, "SMM Relocation handler install failed.\n"); + return -1; + } + + if (install_permanent_handler(num_cpus, &smm_reloc_params)) { + printk(BIOS_CRIT, "SMM Permanent handler install failed.\n"); + return -1; + } + + /* Ensure the SMM handlers hit DRAM before performing first SMI. */ + /* TODO(adurbin): Is this really needed? */ + wbinvd(); + + return 0; +} + +int smm_initialize(void) +{ + /* Return early if CPU SMM setup failed. */ + if (cpu_smm_setup()) + return -1; + + /* Clear the SMM state in the southbridge. */ + southbridge_smm_clear_state(); + + /* Run the relocation handler. */ + smm_initiate_relocation(); + + if (smm_reloc_params.smm_save_state_in_msrs) { + printk(BIOS_DEBUG, "Doing parallel SMM relocation.\n"); + } + + return 0; +} + +void smm_relocate(void) +{ + /* + * If smm_save_state_in_msrs is non-zero then parallel SMM relocation + * shall take place. Run the relocation handler a second time on the + * BSP to do * the final move. For APs, a relocation handler always + * needs to be run. + */ + if (smm_reloc_params.smm_save_state_in_msrs) + smm_initiate_relocation_parallel(); + else if (!boot_cpu()) + smm_initiate_relocation(); +} + +void smm_init(void) +{ + /* smm_init() is normally called from initialize_cpus() in + * lapic_cpu_init.c. However, that path is no longer used. Don't reuse + * the function name because that would cause confusion. + * The smm_initialize() function above is used to setup SMM at the + * appropriate time. */ +} + +void smm_lock(void) +{ + /* LOCK the SMM memory window and enable normal SMM. + * After running this function, only a full reset can + * make the SMM registers writable again. + */ + printk(BIOS_DEBUG, "Locking SMM.\n"); + pci_write_config8(SA_DEV_ROOT, SMRAM, D_LCK | G_SMRAME | C_BASE_SEG); +} diff --git a/src/soc/intel/broadwell/spi.c b/src/soc/intel/broadwell/spi.c new file mode 100644 index 0000000000..e95231e006 --- /dev/null +++ b/src/soc/intel/broadwell/spi.c @@ -0,0 +1,637 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file is derived from the flashrom project. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define min(a, b) ((a)<(b)?(a):(b)) + +#ifdef __SMM__ +#define pci_read_config_byte(dev, reg, targ)\ + *(targ) = pci_read_config8(dev, reg) +#define pci_read_config_word(dev, reg, targ)\ + *(targ) = pci_read_config16(dev, reg) +#define pci_read_config_dword(dev, reg, targ)\ + *(targ) = pci_read_config32(dev, reg) +#define pci_write_config_byte(dev, reg, val)\ + pci_write_config8(dev, reg, val) +#define pci_write_config_word(dev, reg, val)\ + pci_write_config16(dev, reg, val) +#define pci_write_config_dword(dev, reg, val)\ + pci_write_config32(dev, reg, val) +#else /* !__SMM__ */ +#include +#include +#define pci_read_config_byte(dev, reg, targ)\ + *(targ) = pci_read_config8(dev, reg) +#define pci_read_config_word(dev, reg, targ)\ + *(targ) = pci_read_config16(dev, reg) +#define pci_read_config_dword(dev, reg, targ)\ + *(targ) = pci_read_config32(dev, reg) +#define pci_write_config_byte(dev, reg, val)\ + pci_write_config8(dev, reg, val) +#define pci_write_config_word(dev, reg, val)\ + pci_write_config16(dev, reg, val) +#define pci_write_config_dword(dev, reg, val)\ + pci_write_config32(dev, reg, val) +#endif /* !__SMM__ */ + +typedef struct spi_slave ich_spi_slave; + +static int ichspi_lock = 0; + +typedef struct ich9_spi_regs { + uint32_t bfpr; + uint16_t hsfs; + uint16_t hsfc; + uint32_t faddr; + uint32_t _reserved0; + uint32_t fdata[16]; + uint32_t frap; + uint32_t freg[5]; + uint32_t _reserved1[3]; + uint32_t pr[5]; + uint32_t _reserved2[2]; + uint8_t ssfs; + uint8_t ssfc[3]; + uint16_t preop; + uint16_t optype; + uint8_t opmenu[8]; + uint32_t bbar; + uint8_t _reserved3[12]; + uint32_t fdoc; + uint32_t fdod; + uint8_t _reserved4[8]; + uint32_t afc; + uint32_t lvscc; + uint32_t uvscc; + uint8_t _reserved5[4]; + uint32_t fpb; + uint8_t _reserved6[28]; + uint32_t srdl; + uint32_t srdc; + uint32_t srd; +} __attribute__((packed)) ich9_spi_regs; + +typedef struct ich_spi_controller { + int locked; + + uint8_t *opmenu; + int menubytes; + uint16_t *preop; + uint16_t *optype; + uint32_t *addr; + uint8_t *data; + unsigned databytes; + uint8_t *status; + uint16_t *control; + uint32_t *bbar; +} ich_spi_controller; + +static ich_spi_controller cntlr; + +enum { + SPIS_SCIP = 0x0001, + SPIS_GRANT = 0x0002, + SPIS_CDS = 0x0004, + SPIS_FCERR = 0x0008, + SSFS_AEL = 0x0010, + SPIS_LOCK = 0x8000, + SPIS_RESERVED_MASK = 0x7ff0, + SSFS_RESERVED_MASK = 0x7fe2 +}; + +enum { + SPIC_SCGO = 0x000002, + SPIC_ACS = 0x000004, + SPIC_SPOP = 0x000008, + SPIC_DBC = 0x003f00, + SPIC_DS = 0x004000, + SPIC_SME = 0x008000, + SSFC_SCF_MASK = 0x070000, + SSFC_RESERVED = 0xf80000 +}; + +enum { + HSFS_FDONE = 0x0001, + HSFS_FCERR = 0x0002, + HSFS_AEL = 0x0004, + HSFS_BERASE_MASK = 0x0018, + HSFS_BERASE_SHIFT = 3, + HSFS_SCIP = 0x0020, + HSFS_FDOPSS = 0x2000, + HSFS_FDV = 0x4000, + HSFS_FLOCKDN = 0x8000 +}; + +enum { + HSFC_FGO = 0x0001, + HSFC_FCYCLE_MASK = 0x0006, + HSFC_FCYCLE_SHIFT = 1, + HSFC_FDBC_MASK = 0x3f00, + HSFC_FDBC_SHIFT = 8, + HSFC_FSMIE = 0x8000 +}; + +enum { + SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0, + SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1, + SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2, + SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3 +}; + +#if CONFIG_DEBUG_SPI_FLASH + +static u8 readb_(const void *addr) +{ + u8 v = read8((unsigned long)addr); + printk(BIOS_DEBUG, "read %2.2x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static u16 readw_(const void *addr) +{ + u16 v = read16((unsigned long)addr); + printk(BIOS_DEBUG, "read %4.4x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static u32 readl_(const void *addr) +{ + u32 v = read32((unsigned long)addr); + printk(BIOS_DEBUG, "read %8.8x from %4.4x\n", + v, ((unsigned) addr & 0xffff) - 0xf020); + return v; +} + +static void writeb_(u8 b, const void *addr) +{ + write8((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %2.2x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +static void writew_(u16 b, const void *addr) +{ + write16((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %4.4x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +static void writel_(u32 b, const void *addr) +{ + write32((unsigned long)addr, b); + printk(BIOS_DEBUG, "wrote %8.8x to %4.4x\n", + b, ((unsigned) addr & 0xffff) - 0xf020); +} + +#else /* CONFIG_DEBUG_SPI_FLASH ^^^ enabled vvv NOT enabled */ + +#define readb_(a) read8((uint32_t)a) +#define readw_(a) read16((uint32_t)a) +#define readl_(a) read32((uint32_t)a) +#define writeb_(val, addr) write8((uint32_t)addr, val) +#define writew_(val, addr) write16((uint32_t)addr, val) +#define writel_(val, addr) write32((uint32_t)addr, val) + +#endif /* CONFIG_DEBUG_SPI_FLASH ^^^ NOT enabled */ + +static void write_reg(const void *value, void *dest, uint32_t size) +{ + const uint8_t *bvalue = value; + uint8_t *bdest = dest; + + while (size >= 4) { + writel_(*(const uint32_t *)bvalue, bdest); + bdest += 4; bvalue += 4; size -= 4; + } + while (size) { + writeb_(*bvalue, bdest); + bdest++; bvalue++; size--; + } +} + +static void read_reg(const void *src, void *value, uint32_t size) +{ + const uint8_t *bsrc = src; + uint8_t *bvalue = value; + + while (size >= 4) { + *(uint32_t *)bvalue = readl_(bsrc); + bsrc += 4; bvalue += 4; size -= 4; + } + while (size) { + *bvalue = readb_(bsrc); + bsrc++; bvalue++; size--; + } +} + +static void ich_set_bbar(uint32_t minaddr) +{ + const uint32_t bbar_mask = 0x00ffff00; + uint32_t ichspi_bbar; + + minaddr &= bbar_mask; + ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask; + ichspi_bbar |= minaddr; + writel_(ichspi_bbar, cntlr.bbar); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + ich_spi_slave *slave = malloc(sizeof(*slave)); + + if (!slave) { + printk(BIOS_DEBUG, "ICH SPI: Bad allocation\n"); + return NULL; + } + + memset(slave, 0, sizeof(*slave)); + + slave->bus = bus; + slave->cs = cs; + return slave; +} + +void spi_init(void) +{ + uint8_t *rcrb; /* Root Complex Register Block */ + uint32_t rcba; /* Root Complex Base Address */ + uint8_t bios_cntl; + device_t dev = PCH_DEV_LPC; + ich9_spi_regs *ich9_spi; + + pci_read_config_dword(dev, 0xf0, &rcba); + /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */ + rcrb = (uint8_t *)(rcba & 0xffffc000); + ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800); + ichspi_lock = readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN; + cntlr.opmenu = ich9_spi->opmenu; + cntlr.menubytes = sizeof(ich9_spi->opmenu); + cntlr.optype = &ich9_spi->optype; + cntlr.addr = &ich9_spi->faddr; + cntlr.data = (uint8_t *)ich9_spi->fdata; + cntlr.databytes = sizeof(ich9_spi->fdata); + cntlr.status = &ich9_spi->ssfs; + cntlr.control = (uint16_t *)ich9_spi->ssfc; + cntlr.bbar = &ich9_spi->bbar; + cntlr.preop = &ich9_spi->preop; + ich_set_bbar(0); + + /* Disable the BIOS write protect so write commands are allowed. */ + pci_read_config_byte(dev, 0xdc, &bios_cntl); + bios_cntl &= ~(1 << 5); + pci_write_config_byte(dev, 0xdc, bios_cntl | 0x1); +} + +static void spi_init_cb(void *unused) +{ + spi_init(); +} + +BOOT_STATE_INIT_ENTRIES(spi_init_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL), +}; + +int spi_claim_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ +} + +typedef struct spi_transaction { + const uint8_t *out; + uint32_t bytesout; + uint8_t *in; + uint32_t bytesin; + uint8_t type; + uint8_t opcode; + uint32_t offset; +} spi_transaction; + +static inline void spi_use_out(spi_transaction *trans, unsigned bytes) +{ + trans->out += bytes; + trans->bytesout -= bytes; +} + +static inline void spi_use_in(spi_transaction *trans, unsigned bytes) +{ + trans->in += bytes; + trans->bytesin -= bytes; +} + +static void spi_setup_type(spi_transaction *trans) +{ + trans->type = 0xFF; + + /* Try to guess spi type from read/write sizes. */ + if (trans->bytesin == 0) { + if (trans->bytesout > 4) + /* + * If bytesin = 0 and bytesout > 4, we presume this is + * a write data operation, which is accompanied by an + * address. + */ + trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; + else + trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; + return; + } + + if (trans->bytesout == 1) { /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; + return; + } + + if (trans->bytesout == 4) { /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + } + + /* Fast read command is called with 5 bytes instead of 4 */ + if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) { + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + --trans->bytesout; + } +} + +static int spi_setup_opcode(spi_transaction *trans) +{ + uint16_t optypes; + uint8_t opmenu[cntlr.menubytes]; + + trans->opcode = trans->out[0]; + spi_use_out(trans, 1); + if (!ichspi_lock) { + /* The lock is off, so just use index 0. */ + writeb_(trans->opcode, cntlr.opmenu); + optypes = readw_(cntlr.optype); + optypes = (optypes & 0xfffc) | (trans->type & 0x3); + writew_(optypes, cntlr.optype); + return 0; + } else { + /* The lock is on. See if what we need is on the menu. */ + uint8_t optype; + uint16_t opcode_index; + + /* Write Enable is handled as atomic prefix */ + if (trans->opcode == SPI_OPCODE_WREN) + return 0; + + read_reg(cntlr.opmenu, opmenu, sizeof(opmenu)); + for (opcode_index = 0; opcode_index < cntlr.menubytes; + opcode_index++) { + if (opmenu[opcode_index] == trans->opcode) + break; + } + + if (opcode_index == cntlr.menubytes) { + printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n", + trans->opcode); + return -1; + } + + optypes = readw_(cntlr.optype); + optype = (optypes >> (opcode_index * 2)) & 0x3; + if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS && + optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS && + trans->bytesout >= 3) { + /* We guessed wrong earlier. Fix it up. */ + trans->type = optype; + } + if (optype != trans->type) { + printk(BIOS_DEBUG, "ICH SPI: Transaction doesn't fit type %d\n", + optype); + return -1; + } + return opcode_index; + } +} + +static int spi_setup_offset(spi_transaction *trans) +{ + /* Separate the SPI address and data. */ + switch (trans->type) { + case SPI_OPCODE_TYPE_READ_NO_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS: + return 0; + case SPI_OPCODE_TYPE_READ_WITH_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS: + trans->offset = ((uint32_t)trans->out[0] << 16) | + ((uint32_t)trans->out[1] << 8) | + ((uint32_t)trans->out[2] << 0); + spi_use_out(trans, 3); + return 1; + default: + printk(BIOS_DEBUG, "Unrecognized SPI transaction type %#x\n", trans->type); + return -1; + } +} + +/* + * Wait for up to 60ms til status register bit(s) turn 1 (in case wait_til_set + * below is True) or 0. In case the wait was for the bit(s) to set - write + * those bits back, which would cause resetting them. + * + * Return the last read status value on success or -1 on failure. + */ +static int ich_status_poll(u16 bitmask, int wait_til_set) +{ + int timeout = 6000; /* This will result in 60 ms */ + u16 status = 0; + + while (timeout--) { + status = readw_(cntlr.status); + if (wait_til_set ^ ((status & bitmask) == 0)) { + if (wait_til_set) + writew_((status & bitmask), cntlr.status); + return status; + } + udelay(10); + } + + printk(BIOS_DEBUG, "ICH SPI: SCIP timeout, read %x, expected %x\n", + status, bitmask); + return -1; +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int bytesout, void *din, unsigned int bytesin) +{ + uint16_t control; + int16_t opcode_index; + int with_address; + int status; + + spi_transaction trans = { + dout, bytesout, + din, bytesin, + 0xff, 0xff, 0 + }; + + /* There has to always at least be an opcode. */ + if (!bytesout || !dout) { + printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n"); + return -1; + } + /* Make sure if we read something we have a place to put it. */ + if (bytesin != 0 && !din) { + printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n"); + return -1; + } + + if (ich_status_poll(SPIS_SCIP, 0) == -1) + return -1; + + writew_(SPIS_CDS | SPIS_FCERR, cntlr.status); + + spi_setup_type(&trans); + if ((opcode_index = spi_setup_opcode(&trans)) < 0) + return -1; + if ((with_address = spi_setup_offset(&trans)) < 0) + return -1; + + if (trans.opcode == SPI_OPCODE_WREN) { + /* + * Treat Write Enable as Atomic Pre-Op if possible + * in order to prevent the Management Engine from + * issuing a transaction between WREN and DATA. + */ + if (!ichspi_lock) + writew_(trans.opcode, cntlr.preop); + return 0; + } + + /* Preset control fields */ + control = SPIC_SCGO | ((opcode_index & 0x07) << 4); + + /* Issue atomic preop cycle if needed */ + if (readw_(cntlr.preop)) + control |= SPIC_ACS; + + if (!trans.bytesout && !trans.bytesin) { + /* SPI addresses are 24 bit only */ + if (with_address) + writel_(trans.offset & 0x00FFFFFF, cntlr.addr); + + /* + * This is a 'no data' command (like Write Enable), its + * bitesout size was 1, decremented to zero while executing + * spi_setup_opcode() above. Tell the chip to send the + * command. + */ + writew_(control, cntlr.control); + + /* wait for the result */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + printk(BIOS_DEBUG, "ICH SPI: Command transaction error\n"); + return -1; + } + + return 0; + } + + /* + * Check if this is a write command atempting to transfer more bytes + * than the controller can handle. Iterations for writes are not + * supported here because each SPI write command needs to be preceded + * and followed by other SPI commands, and this sequence is controlled + * by the SPI chip driver. + */ + if (trans.bytesout > cntlr.databytes) { + printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use" + " CONTROLLER_PAGE_LIMIT?\n"); + return -1; + } + + /* + * Read or write up to databytes bytes at a time until everything has + * been sent. + */ + while (trans.bytesout || trans.bytesin) { + uint32_t data_length; + + /* SPI addresses are 24 bit only */ + writel_(trans.offset & 0x00FFFFFF, cntlr.addr); + + if (trans.bytesout) + data_length = min(trans.bytesout, cntlr.databytes); + else + data_length = min(trans.bytesin, cntlr.databytes); + + /* Program data into FDATA0 to N */ + if (trans.bytesout) { + write_reg(trans.out, cntlr.data, data_length); + spi_use_out(&trans, data_length); + if (with_address) + trans.offset += data_length; + } + + /* Add proper control fields' values */ + control &= ~((cntlr.databytes - 1) << 8); + control |= SPIC_DS; + control |= (data_length - 1) << 8; + + /* write it */ + writew_(control, cntlr.control); + + /* Wait for Cycle Done Status or Flash Cycle Error. */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + printk(BIOS_DEBUG, "ICH SPI: Data transaction error\n"); + return -1; + } + + if (trans.bytesin) { + read_reg(cntlr.data, trans.in, data_length); + spi_use_in(&trans, data_length); + if (with_address) + trans.offset += data_length; + } + } + + /* Clear atomic preop now that xfer is done */ + writew_(0, cntlr.preop); + + return 0; +} diff --git a/src/soc/intel/broadwell/spi_loading.c b/src/soc/intel/broadwell/spi_loading.c new file mode 100644 index 0000000000..d7247c6571 --- /dev/null +++ b/src/soc/intel/broadwell/spi_loading.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define CACHELINE_SIZE 64 +#define INTRA_CACHELINE_MASK (CACHELINE_SIZE - 1) +#define CACHELINE_MASK (~INTRA_CACHELINE_MASK) + +/* Mirror the payload file to the default SMM location if it is small enough. + * The default SMM region can be used since no one is using the memory at this + * location at this stage in the boot. */ +static inline void *spi_mirror(void *file_start, int file_len) +{ + int alignment_diff; + char *src; + char *dest = (void *)SMM_DEFAULT_BASE; + + alignment_diff = (INTRA_CACHELINE_MASK & (long)file_start); + + /* Adjust file length so that the start and end points are aligned to a + * cacheline. Coupled with the ROM caching in the CPU the SPI hardware + * will read and cache full length cachelines. It will also prefetch + * data as well. Once things are mirrored in memory all accesses should + * hit the CPUs cache. */ + file_len += alignment_diff; + file_len = ALIGN(file_len, CACHELINE_SIZE); + + printk(BIOS_DEBUG, "Payload aligned size: 0x%x\n", file_len); + + /* Just pass back the pointer to ROM space if the file is larger + * than the RAM mirror region. */ + if (file_len > SMM_DEFAULT_SIZE) + return file_start; + + src = (void *)(CACHELINE_MASK & (long)file_start); + /* Note that if mempcy is not using 32-bit moves the performance will + * degrade because the SPI hardware prefetchers look for + * cacheline-aligned 32-bit accesses to kick in. */ + memcpy(dest, src, file_len); + + /* Provide pointer into mirrored space. */ + return &dest[alignment_diff]; +} + +void *cbfs_load_payload(struct cbfs_media *media, const char *name) +{ + int file_len; + void *file_start; + struct cbfs_file *file; + + file_start = vboot_get_payload(&file_len); + + if (file_start != NULL) + return spi_mirror(file_start, file_len); + + file = cbfs_get_file(media, name); + + if (file == NULL) + return NULL; + + if (ntohl(file->type) != CBFS_TYPE_PAYLOAD) + return NULL; + + file_len = ntohl(file->len); + + file_start = CBFS_SUBHEADER(file); + + return spi_mirror(file_start, file_len); +} diff --git a/src/soc/intel/broadwell/stage_cache.c b/src/soc/intel/broadwell/stage_cache.c new file mode 100644 index 0000000000..cb34297cdd --- /dev/null +++ b/src/soc/intel/broadwell/stage_cache.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +struct ramstage_cache *ramstage_cache_location(long *size) +{ + /* The ramstage cache lives in the TSEG region. + * The top of ram is defined to be the TSEG base address. */ + u32 offset = smm_region_size(); + offset -= CONFIG_IED_REGION_SIZE; + offset -= CONFIG_SMM_RESERVED_SIZE; + + *size = CONFIG_SMM_RESERVED_SIZE; + return (void *)(cbmem_top() + offset); +} diff --git a/src/soc/intel/broadwell/systemagent.c b/src/soc/intel/broadwell/systemagent.c new file mode 100644 index 0000000000..1dc0bb40c3 --- /dev/null +++ b/src/soc/intel/broadwell/systemagent.c @@ -0,0 +1,461 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +u8 systemagent_revision(void) +{ + return pci_read_config8(SA_DEV_ROOT, PCI_REVISION_ID); +} + +static int get_pcie_bar(device_t dev, unsigned int index, u32 *base, u32 *len) +{ + u32 pciexbar_reg; + + *base = 0; + *len = 0; + + pciexbar_reg = pci_read_config32(dev, index); + + if (!(pciexbar_reg & (1 << 0))) + return 0; + + switch ((pciexbar_reg >> 1) & 3) { + case 0: // 256MB + *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)| + (1 << 28)); + *len = 256 * 1024 * 1024; + return 1; + case 1: // 128M + *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)| + (1 << 28)|(1 << 27)); + *len = 128 * 1024 * 1024; + return 1; + case 2: // 64M + *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)| + (1 << 28)|(1 << 27)|(1 << 26)); + *len = 64 * 1024 * 1024; + return 1; + } + + return 0; +} + +static int get_bar(device_t dev, unsigned int index, u32 *base, u32 *len) +{ + u32 bar; + + bar = pci_read_config32(dev, index); + + /* If not enabled don't report it. */ + if (!(bar & 0x1)) + return 0; + + /* Knock down the enable bit. */ + *base = bar & ~1; + + return 1; +} + +/* There are special BARs that actually are programmed in the MCHBAR. These + * Intel special features, but they do consume resources that need to be + * accounted for. */ +static int get_bar_in_mchbar(device_t dev, unsigned int index, u32 *base, + u32 *len) +{ + u32 bar; + + bar = MCHBAR32(index); + + /* If not enabled don't report it. */ + if (!(bar & 0x1)) + return 0; + + /* Knock down the enable bit. */ + *base = bar & ~1; + + return 1; +} + +struct fixed_mmio_descriptor { + unsigned int index; + u32 size; + int (*get_resource)(device_t dev, unsigned int index, + u32 *base, u32 *size); + const char *description; +}; + +struct fixed_mmio_descriptor mc_fixed_resources[] = { + { PCIEXBAR, 0, get_pcie_bar, "PCIEXBAR" }, + { MCHBAR, MCH_BASE_SIZE, get_bar, "MCHBAR" }, + { DMIBAR, DMI_BASE_SIZE, get_bar, "DMIBAR" }, + { EPBAR, EP_BASE_SIZE, get_bar, "EPBAR" }, + { GDXCBAR, GDXC_BASE_SIZE, get_bar_in_mchbar, "GDXCBAR" }, + { EDRAMBAR, EDRAM_BASE_SIZE, get_bar_in_mchbar, "EDRAMBAR" }, +}; + +/* + * Add all known fixed MMIO ranges that hang off the host bridge/memory + * controller device. + */ +static void mc_add_fixed_mmio_resources(device_t dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mc_fixed_resources); i++) { + u32 base; + u32 size; + struct resource *resource; + unsigned int index; + + size = mc_fixed_resources[i].size; + index = mc_fixed_resources[i].index; + if (!mc_fixed_resources[i].get_resource(dev, index, + &base, &size)) + continue; + + resource = new_resource(dev, mc_fixed_resources[i].index); + resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_RESERVE | + IORESOURCE_ASSIGNED; + resource->base = base; + resource->size = size; + printk(BIOS_DEBUG, "%s: Adding %s @ %x 0x%08lx-0x%08lx.\n", + __func__, mc_fixed_resources[i].description, index, + (unsigned long)base, (unsigned long)(base + size - 1)); + } +} + +/* Host Memory Map: + * + * +--------------------------+ TOUUD + * | | + * +--------------------------+ 4GiB + * | PCI Address Space | + * +--------------------------+ TOLUD (also maps into MC address space) + * | iGD | + * +--------------------------+ BDSM + * | GTT | + * +--------------------------+ BGSM + * | TSEG | + * +--------------------------+ TSEGMB + * | Usage DRAM | + * +--------------------------+ 0 + * + * Some of the base registers above can be equal making the size of those + * regions 0. The reason is because the memory controller internally subtracts + * the base registers from each other to determine sizes of the regions. In + * other words, the memory map is in a fixed order no matter what. + */ + +struct map_entry { + int reg; + int is_64_bit; + int is_limit; + const char *description; +}; + +static void read_map_entry(device_t dev, struct map_entry *entry, + uint64_t *result) +{ + uint64_t value; + uint64_t mask; + + /* All registers are on a 1MiB granularity. */ + mask = ((1ULL<<20)-1); + mask = ~mask; + + value = 0; + + if (entry->is_64_bit) { + value = pci_read_config32(dev, entry->reg + 4); + value <<= 32; + } + + value |= pci_read_config32(dev, entry->reg); + value &= mask; + + if (entry->is_limit) + value |= ~mask; + + *result = value; +} + +#define MAP_ENTRY(reg_, is_64_, is_limit_, desc_) \ + { \ + .reg = reg_, \ + .is_64_bit = is_64_, \ + .is_limit = is_limit_, \ + .description = desc_, \ + } + +#define MAP_ENTRY_BASE_64(reg_, desc_) \ + MAP_ENTRY(reg_, 1, 0, desc_) +#define MAP_ENTRY_LIMIT_64(reg_, desc_) \ + MAP_ENTRY(reg_, 1, 1, desc_) +#define MAP_ENTRY_BASE_32(reg_, desc_) \ + MAP_ENTRY(reg_, 0, 0, desc_) + +enum { + TOM_REG, + TOUUD_REG, + MESEG_BASE_REG, + MESEG_LIMIT_REG, + REMAP_BASE_REG, + REMAP_LIMIT_REG, + TOLUD_REG, + BGSM_REG, + BDSM_REG, + TSEG_REG, + // Must be last. + NUM_MAP_ENTRIES +}; + +static struct map_entry memory_map[NUM_MAP_ENTRIES] = { + [TOM_REG] = MAP_ENTRY_BASE_64(TOM, "TOM"), + [TOUUD_REG] = MAP_ENTRY_BASE_64(TOUUD, "TOUUD"), + [MESEG_BASE_REG] = MAP_ENTRY_BASE_64(MESEG_BASE, "MESEG_BASE"), + [MESEG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(MESEG_LIMIT, "MESEG_LIMIT"), + [REMAP_BASE_REG] = MAP_ENTRY_BASE_64(REMAPBASE, "REMAP_BASE"), + [REMAP_LIMIT_REG] = MAP_ENTRY_LIMIT_64(REMAPLIMIT, "REMAP_LIMIT"), + [TOLUD_REG] = MAP_ENTRY_BASE_32(TOLUD, "TOLUD"), + [BDSM_REG] = MAP_ENTRY_BASE_32(BDSM, "BDSM"), + [BGSM_REG] = MAP_ENTRY_BASE_32(BGSM, "BGSM"), + [TSEG_REG] = MAP_ENTRY_BASE_32(TSEG, "TESGMB"), +}; + +static void mc_read_map_entries(device_t dev, uint64_t *values) +{ + int i; + for (i = 0; i < NUM_MAP_ENTRIES; i++) { + read_map_entry(dev, &memory_map[i], &values[i]); + } +} + +static void mc_report_map_entries(device_t dev, uint64_t *values) +{ + int i; + for (i = 0; i < NUM_MAP_ENTRIES; i++) { + printk(BIOS_DEBUG, "MC MAP: %s: 0x%llx\n", + memory_map[i].description, values[i]); + } + /* One can validate the BDSM and BGSM against the GGC. */ + printk(BIOS_DEBUG, "MC MAP: GGC: 0x%x\n", pci_read_config16(dev, GGC)); +} + +static void mc_add_dram_resources(device_t dev) +{ + unsigned long base_k, size_k; + unsigned long touud_k; + unsigned long index; + struct resource *resource; + uint64_t mc_values[NUM_MAP_ENTRIES]; + unsigned long dpr_size = 0; + u32 dpr_reg; + + /* Read in the MAP registers and report their values. */ + mc_read_map_entries(dev, &mc_values[0]); + mc_report_map_entries(dev, &mc_values[0]); + + /* + * DMA Protected Range can be reserved below TSEG for PCODE patch + * or TXT/BootGuard related data. Rather than report a base address + * the DPR register reports the TOP of the region, which is the same + * as TSEG base. The region size is reported in MiB in bits 11:4. + */ + dpr_reg = pci_read_config32(SA_DEV_ROOT, DPR); + if (dpr_reg & DPR_EPM) { + dpr_size = (dpr_reg & DPR_SIZE_MASK) << 16; + printk(BIOS_INFO, "DPR SIZE: 0x%lx\n", dpr_size); + } + + /* + * These are the host memory ranges that should be added: + * - 0 -> 0xa0000: cacheable + * - 0xc0000 -> TSEG : cacheable + * - TESG -> BGSM: cacheable with standard MTRRs and reserved + * - BGSM -> TOLUD: not cacheable with standard MTRRs and reserved + * - 4GiB -> TOUUD: cacheable + * + * The default SMRAM space is reserved so that the range doesn't + * have to be saved during S3 Resume. Once marked reserved the OS + * cannot use the memory. This is a bit of an odd place to reserve + * the region, but the CPU devices don't have dev_ops->read_resources() + * called on them. + * + * The range 0xa0000 -> 0xc0000 does not have any resources + * associated with it to handle legacy VGA memory. If this range + * is not omitted the mtrr code will setup the area as cacheable + * causing VGA access to not work. + * + * The TSEG region is mapped as cacheable so that one can perform + * SMRAM relocation faster. Once the SMRR is enabled the SMRR takes + * precedence over the existing MTRRs covering this region. + * + * It should be noted that cacheable entry types need to be added in + * order. The reason is that the current MTRR code assumes this and + * falls over itself if it isn't. + * + * The resource index starts low and should not meet or exceed + * PCI_BASE_ADDRESS_0. + */ + index = 0; + + /* 0 - > 0xa0000 */ + base_k = 0; + size_k = (0xa0000 >> 10) - base_k; + ram_resource(dev, index++, base_k, size_k); + + /* 0xc0000 -> TSEG - DPR */ + base_k = 0xc0000 >> 10; + size_k = (unsigned long)(mc_values[TSEG_REG] >> 10) - base_k; + size_k -= dpr_size >> 10; + ram_resource(dev, index++, base_k, size_k); + + /* TSEG - DPR -> BGSM */ + resource = new_resource(dev, index++); + resource->base = mc_values[TSEG_REG] - dpr_size; + resource->size = mc_values[BGSM_REG] - resource->base; + resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_RESERVE | + IORESOURCE_ASSIGNED | IORESOURCE_CACHEABLE; + + /* BGSM -> TOLUD */ + resource = new_resource(dev, index++); + resource->base = mc_values[BGSM_REG]; + resource->size = mc_values[TOLUD_REG] - resource->base; + resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_RESERVE | + IORESOURCE_ASSIGNED; + + /* 4GiB -> TOUUD */ + base_k = 4096 * 1024; /* 4GiB */ + touud_k = mc_values[TOUUD_REG] >> 10; + size_k = touud_k - base_k; + if (touud_k > base_k) + ram_resource(dev, index++, base_k, size_k); + + /* Reserve everything between A segment and 1MB: + * + * 0xa0000 - 0xbffff: legacy VGA + * 0xc0000 - 0xfffff: RAM + */ + mmio_resource(dev, index++, (0xa0000 >> 10), (0xc0000 - 0xa0000) >> 10); + reserved_ram_resource(dev, index++, (0xc0000 >> 10), + (0x100000 - 0xc0000) >> 10); + + chromeos_reserve_ram_oops(dev, index++); +} + +static void systemagent_read_resources(device_t dev) +{ + /* Read standard PCI resources. */ + pci_dev_read_resources(dev); + + /* Add all fixed MMIO resources. */ + mc_add_fixed_mmio_resources(dev); + + /* Calculate and add DRAM resources. */ + mc_add_dram_resources(dev); +} + +static void systemagent_init(struct device *dev) +{ + u8 bios_reset_cpl, pair; + + /* Enable Power Aware Interrupt Routing */ + pair = MCHBAR8(MCH_PAIR); + pair &= ~0x7; /* Clear 2:0 */ + pair |= 0x4; /* Fixed Priority */ + MCHBAR8(MCH_PAIR) = pair; + + /* + * Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU + * that BIOS has initialized memory and power management + */ + bios_reset_cpl = MCHBAR8(BIOS_RESET_CPL); + bios_reset_cpl |= 3; + MCHBAR8(BIOS_RESET_CPL) = bios_reset_cpl; + printk(BIOS_DEBUG, "Set BIOS_RESET_CPL\n"); + + /* Configure turbo power limits 1ms after reset complete bit */ + mdelay(1); + set_power_limits(28); +} + +static void systemagent_enable(device_t dev) +{ +#if CONFIG_HAVE_ACPI_RESUME + struct romstage_handoff *handoff; + + handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO); + + if (handoff == NULL) { + printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n"); + acpi_slp_type = 0; + } else if (handoff->s3_resume) { + printk(BIOS_DEBUG, "S3 Resume.\n"); + acpi_slp_type = 3; + } else { + printk(BIOS_DEBUG, "Normal boot.\n"); + acpi_slp_type = 0; + } +#endif +} + +static struct device_operations systemagent_ops = { + .read_resources = &systemagent_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .init = &systemagent_init, + .enable = &systemagent_enable, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short systemagent_ids[] = { + 0x0a04, /* Haswell ULT */ + 0x1604, /* Broadwell-U/Y */ + 0x1610, /* Broadwell-H Desktop */ + 0x1614, /* Broadwell-H Mobile */ + 0 +}; + +static const struct pci_driver systemagent_driver __pci_driver = { + .ops = &systemagent_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = systemagent_ids +}; diff --git a/src/soc/intel/broadwell/tsc_freq.c b/src/soc/intel/broadwell/tsc_freq.c new file mode 100644 index 0000000000..5487b16b8c --- /dev/null +++ b/src/soc/intel/broadwell/tsc_freq.c @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +unsigned long tsc_freq_mhz(void) +{ + msr_t platform_info; + + platform_info = rdmsr(MSR_PLATFORM_INFO); + return CPU_BCLK * ((platform_info.lo >> 8) & 0xff); +} diff --git a/src/soc/intel/broadwell/usbdebug.c b/src/soc/intel/broadwell/usbdebug.c new file mode 100644 index 0000000000..736a1a3c44 --- /dev/null +++ b/src/soc/intel/broadwell/usbdebug.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +void set_debug_port(unsigned int port) +{ + /* Hardcoded to physical port 1 */ +} + +void enable_usbdebug(unsigned int port) +{ + u32 tmp32; + + tmp32 = pci_read_config32(PCH_DEV_EHCI, PCI_VENDOR_ID); + if (tmp32 == 0xffffffff || tmp32 == 0) + return; + + /* Set the EHCI BAR address. */ + pci_write_config32(PCH_DEV_EHCI, EHCI_BAR_INDEX, CONFIG_EHCI_BAR); + + /* Enable access to the EHCI memory space registers. */ + pci_write_config8(PCH_DEV_EHCI, PCI_COMMAND, PCI_COMMAND_MEMORY); + + /* Force ownership of the Debug Port to the EHCI controller. */ + tmp32 = read32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET); + tmp32 |= (1 << 30); + write32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET, tmp32); +} diff --git a/src/soc/intel/broadwell/xhci.c b/src/soc/intel/broadwell/xhci.c new file mode 100644 index 0000000000..566763b56e --- /dev/null +++ b/src/soc/intel/broadwell/xhci.c @@ -0,0 +1,213 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __SMM__ +static u32 usb_xhci_mem_base(device_t dev) +{ + u32 mem_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + + /* Check if the controller is disabled or not present */ + if (mem_base == 0 || mem_base == 0xffffffff) + return 0; + + return mem_base & ~0xf; +} + +static int usb_xhci_port_count_usb3(device_t dev) +{ + /* PCH-LP has 4 SS ports */ + return 4; +} + +static void usb_xhci_reset_status_usb3(u32 mem_base, int port) +{ + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + u32 status = read32(portsc); + /* Do not set Port Enabled/Disabled field */ + status &= ~XHCI_USB3_PORTSC_PED; + /* Clear all change status bits */ + status |= XHCI_USB3_PORTSC_CHST; + write32(portsc, status); +} + +static void usb_xhci_reset_port_usb3(u32 mem_base, int port) +{ + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + write32(portsc, read32(portsc) | XHCI_USB3_PORTSC_WPR); +} + +#define XHCI_RESET_DELAY_US 1000 /* 1ms */ +#define XHCI_RESET_TIMEOUT 100 /* 100ms */ + +/* + * 1) Wait until port is done polling + * 2) If port is disconnected + * a) Issue warm port reset + * b) Poll for warm reset complete + * c) Write 1 to port change status bits + */ +static void usb_xhci_reset_usb3(device_t dev, int all) +{ + u32 status, port_disabled; + int timeout, port; + int port_count = usb_xhci_port_count_usb3(dev); + u32 mem_base = usb_xhci_mem_base(dev); + + if (!mem_base || !port_count) + return; + + /* Get mask of disabled ports */ + port_disabled = pci_read_config32(dev, XHCI_USB3PDO); + + /* Wait until all enabled ports are done polling */ + for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) { + int complete = 1; + for (port = 0; port < port_count; port++) { + /* Skip disabled ports */ + if (port_disabled & (1 << port)) + continue; + /* Read port link status field */ + status = read32(mem_base + XHCI_USB3_PORTSC(port)); + status &= XHCI_USB3_PORTSC_PLS; + if (status == XHCI_PLSR_POLLING) + complete = 0; + } + /* Exit if all ports not polling */ + if (complete) + break; + udelay(XHCI_RESET_DELAY_US); + } + + /* Reset all requested ports */ + for (port = 0; port < port_count; port++) { + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + /* Skip disabled ports */ + if (port_disabled & (1 << port)) + continue; + status = read32(portsc) & XHCI_USB3_PORTSC_PLS; + /* Reset all or only disconnected ports */ + if (all || (status == XHCI_PLSR_RXDETECT || + status == XHCI_PLSR_POLLING)) + usb_xhci_reset_port_usb3(mem_base, port); + else + port_disabled |= 1 << port; + } + + /* Wait for warm reset complete on all reset ports */ + for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) { + int complete = 1; + for (port = 0; port < port_count; port++) { + /* Only check ports that were reset */ + if (port_disabled & (1 << port)) + continue; + /* Check if warm reset is complete */ + status = read32(mem_base + XHCI_USB3_PORTSC(port)); + if (!(status & XHCI_USB3_PORTSC_WRC)) + complete = 0; + } + /* Check for warm reset complete in any port */ + if (complete) + break; + udelay(XHCI_RESET_DELAY_US); + } + + /* Clear port change status bits */ + for (port = 0; port < port_count; port++) + usb_xhci_reset_status_usb3(mem_base, port); +} + +/* Handler for XHCI controller on entry to S3/S4/S5 */ +void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ) +{ + u16 reg16; + u32 reg32; + u32 mem_base = usb_xhci_mem_base(dev); + u8 is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT); + + if (!mem_base || slp_typ < 3) + return; + + /* Set D0 state */ + reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); + reg16 &= ~XHCI_PWR_CTL_SET_MASK; + reg16 |= XHCI_PWR_CTL_SET_D0; + pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); + + if (!is_broadwell) { + /* This WA is only for lpt */ + + /* Clear PCI 0xB0[14:13] */ + reg32 = pci_read_config32(dev, 0xb0); + reg32 &= ~((1 << 14) | (1 << 13)); + pci_write_config32(dev, 0xb0, reg32); + + /* Clear MMIO 0x816c[14,2] */ + reg32 = read32(mem_base + 0x816c); + reg32 &= ~((1 << 14) | (1 << 2)); + write32(mem_base + 0x816c, reg32); + + /* Reset disconnected USB3 ports */ + usb_xhci_reset_usb3(dev, 0); + + /* Set MMIO 0x80e0[15] */ + reg32 = read32(mem_base + 0x80e0); + reg32 |= (1 << 15); + write32(mem_base + 0x80e0, reg32); + } + + reg32 = read32(mem_base + 0x8154); + reg32 &= ~(1 << 31); + write32(mem_base + 0x8154, reg32); + + /* Set D3Hot state and enable PME */ + pci_or_config16(dev, XHCI_PWR_CTL_STS, XHCI_PWR_CTL_SET_D3); + pci_or_config16(dev, XHCI_PWR_CTL_STS, XHCI_PWR_CTL_STATUS_PME); + pci_or_config16(dev, XHCI_PWR_CTL_STS, XHCI_PWR_CTL_ENABLE_PME); +} +#else /* !__SMM__ */ + +static struct device_operations usb_xhci_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .ops_pci = &broadwell_pci_ops, +}; + +static const unsigned short pci_device_ids[] = { + 0x9c31, /* LynxPoint-LP */ + 0x9cb1, /* WildcatPoint */ + 0 +}; + +static const struct pci_driver pch_usb_xhci __pci_driver = { + .ops = &usb_xhci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; +#endif /* !__SMM__ */ diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig new file mode 100644 index 0000000000..8b02a4a905 --- /dev/null +++ b/src/soc/intel/common/Kconfig @@ -0,0 +1,19 @@ +if HAVE_MRC + +config CACHE_MRC_SETTINGS + bool "Save cached MRC settings" + default n + +if CACHE_MRC_SETTINGS + +config MRC_SETTINGS_CACHE_BASE + hex + default 0xffb00000 + +config MRC_SETTINGS_CACHE_SIZE + hex + default 0x10000 + +endif # CACHE_MRC_SETTINGS + +endif # HAVE_MRC diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc new file mode 100644 index 0000000000..0c39d80340 --- /dev/null +++ b/src/soc/intel/common/Makefile.inc @@ -0,0 +1,4 @@ +ramstage-y += hda_verb.c +ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += nvm.c +ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c +romstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c diff --git a/src/soc/intel/common/hda_verb.c b/src/soc/intel/common/hda_verb.c new file mode 100644 index 0000000000..e059a1a0c5 --- /dev/null +++ b/src/soc/intel/common/hda_verb.c @@ -0,0 +1,266 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "hda_verb.h" + +/** + * Set bits in a register and wait for status + */ +static int set_bits(u32 port, u32 mask, u32 val) +{ + u32 reg32; + int count; + + /* Write (val & mask) to port */ + val &= mask; + reg32 = read32(port); + reg32 &= ~mask; + reg32 |= val; + write32(port, reg32); + + /* Wait for readback of register to + * match what was just written to it + */ + count = 50; + do { + /* Wait 1ms based on BKDG wait time */ + mdelay(1); + reg32 = read32(port); + reg32 &= mask; + } while ((reg32 != val) && --count); + + /* Timeout occurred */ + if (!count) + return -1; + return 0; +} + +/** + * Probe for supported codecs + */ +int hda_codec_detect(u32 base) +{ + u8 reg8; + + /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ + if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0) + goto no_codec; + + /* Write back the value once reset bit is set. */ + write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG)); + + /* Clear the "State Change Status Register" STATESTS bits + * for each of the "SDIN Stat Change Status Flag" + */ + write8(base + HDA_STATESTS_REG, 0xf); + + /* Turn off the link and poll RESET# bit until it reads back as 0 */ + if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, ~HDA_GCTL_CRST) < 0) + goto no_codec; + + /* Turn on the link and poll RESET# bit until it reads back as 1 */ + if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0) + goto no_codec; + + /* Read in Codec location (BAR + 0xe)[2..0]*/ + reg8 = read8(base + HDA_STATESTS_REG); + reg8 &= 0x0f; + if (!reg8) + goto no_codec; + + return reg8; + +no_codec: + /* Codec Not found */ + /* Put HDA back in reset (BAR + 0x8) [0] */ + set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, 0); + printk(BIOS_DEBUG, "HDA: No codec!\n"); + return 0; +} + +/** + * Wait 50usec for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ +static int hda_wait_for_ready(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + + while(timeout--) { + u32 reg32 = read32(base + HDA_ICII_REG); + if (!(reg32 & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ +static int hda_wait_for_valid(u32 base) +{ + u32 reg32; + + /* Send the verb to the codec */ + reg32 = read32(base + HDA_ICII_REG); + reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID; + write32(base + HDA_ICII_REG, reg32); + + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + while(timeout--) { + reg32 = read32(base + HDA_ICII_REG); + if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Find a specific entry within a verb table + * + * @verb_table_bytes: verb table size in bytes + * @verb_table_data: verb table data + * @viddid: vendor/device to search for + * @verb_out: pointer to entry within table + * + * Returns size of the entry within the verb table, + * Returns 0 if the entry is not found + * + * The HDA verb table is composed of dwords. A set of 4 dwords is + * grouped together to form a "jack" descriptor. + * Bits 31:28 - Codec Address + * Bits 27:20 - NID + * Bits 19:8 - Verb ID + * Bits 7:0 - Payload + * + * coreboot groups different codec verb tables into a single table + * and prefixes each with a specific header consisting of 3 + * dword entries: + * 1 - Codec Vendor/Device ID + * 2 - Subsystem ID + * 3 - Number of jacks (groups of 4 dwords) for this codec + */ +static u32 hda_find_verb(u32 verb_table_bytes, + const u32 *verb_table_data, + u32 viddid, const u32 ** verb) +{ + int idx=0; + + while (idx < (verb_table_bytes / sizeof(u32))) { + u32 verb_size = 4 * verb_table_data[idx+2]; // in u32 + if (verb_table_data[idx] != viddid) { + idx += verb_size + 3; // skip verb + header + continue; + } + *verb = &verb_table_data[idx+3]; + return verb_size; + } + + /* Not all codecs need to load another verb */ + return 0; +} + +/** + * Write a supplied verb table + */ +int hda_codec_write(u32 base, u32 size, const u32 *data) +{ + int i; + + for (i = 0; i < size; i++) { + if (hda_wait_for_ready(base) < 0) + return -1; + + write32(base + HDA_IC_REG, data[i]); + + if (hda_wait_for_valid(base) < 0) + return -1; + } + + return 0; +} + +/** + * Initialize codec, then find the verb table and write it + */ +int hda_codec_init(u32 base, int addr, int verb_size, const u32 *verb_data) +{ + const u32 *verb; + u32 reg32, size; + int rc; + + printk(BIOS_DEBUG, "HDA: Initializing codec #%d\n", addr); + + if (!verb_size || !verb_data) { + printk(BIOS_DEBUG, "HDA: No verb list!\n"); + return -1; + } + + /* 1 */ + if (hda_wait_for_ready(base) < 0) { + printk(BIOS_DEBUG, " codec not ready.\n"); + return -1; + } + + reg32 = (addr << 28) | 0x000f0000; + write32(base + HDA_IC_REG, reg32); + + if (hda_wait_for_valid(base) < 0) { + printk(BIOS_DEBUG, " codec not valid.\n"); + return -1; + } + + /* 2 */ + reg32 = read32(base + HDA_IR_REG); + printk(BIOS_DEBUG, "HDA: codec viddid: %08x\n", reg32); + + size = hda_find_verb(verb_size, verb_data, reg32, &verb); + if (!size) { + printk(BIOS_DEBUG, "HDA: No verb table entry found\n"); + return -1; + } + + /* 3 */ + rc = hda_codec_write(base, size, verb); + + if (rc < 0) + printk(BIOS_DEBUG, "HDA: verb not loaded\n"); + else + printk(BIOS_DEBUG, "HDA: verb loaded.\n"); + + return rc; +} diff --git a/src/soc/intel/common/hda_verb.h b/src/soc/intel/common/hda_verb.h new file mode 100644 index 0000000000..a9c93c6e4f --- /dev/null +++ b/src/soc/intel/common/hda_verb.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COMMON_HDA_VERB_H_ +#define _COMMON_HDA_VERB_H_ + +#include + +#define HDA_GCAP_REG 0x00 +#define HDA_GCTL_REG 0x08 +#define HDA_GCTL_CRST (1 << 0) +#define HDA_STATESTS_REG 0x0e +#define HDA_IC_REG 0x60 +#define HDA_IR_REG 0x64 +#define HDA_ICII_REG 0x68 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + +int hda_codec_detect(u32 base); +int hda_codec_write(u32 base, u32 size, const u32 *data); +int hda_codec_init(u32 base, int addr, int verb_size, const u32 *verb_data); + +#endif /* _COMMON_HDA_VERB_H_ */ diff --git a/src/soc/intel/common/mrc_cache.c b/src/soc/intel/common/mrc_cache.c new file mode 100644 index 0000000000..6d2003c2b9 --- /dev/null +++ b/src/soc/intel/common/mrc_cache.c @@ -0,0 +1,311 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#if CONFIG_CHROMEOS +#include +#endif +#include "mrc_cache.h" + +#define MRC_DATA_ALIGN 0x1000 +#define MRC_DATA_SIGNATURE (('M'<<0)|('R'<<8)|('C'<<16)|('D'<<24)) + +/* The mrc_data_region describes the larger non-volatile area to store + * mrc_saved_data objects.*/ +struct mrc_data_region { + void *base; + uint32_t size; +}; + +/* common code */ +static int mrc_cache_get_region(struct mrc_data_region *region) +{ +#if CONFIG_CHROMEOS + int ret; + ret = find_fmap_entry("RW_MRC_CACHE", ®ion->base); + if (ret >= 0) { + region->size = ret; + return 0; + } +#endif + region->base = (void *)CONFIG_MRC_SETTINGS_CACHE_BASE; + region->size = CONFIG_MRC_SETTINGS_CACHE_SIZE; + return 0; +} + +static int mrc_cache_in_region(const struct mrc_data_region *region, + const struct mrc_saved_data *cache) +{ + uintptr_t region_end; + uintptr_t cache_end; + + if ((uintptr_t)cache < (uintptr_t)region->base) + return 0; + + region_end = (uintptr_t)region->base; + region_end += region->size; + + if ((uintptr_t)cache >= region_end) + return 0; + + if ((sizeof(*cache) + (uintptr_t)cache) >= region_end) + return 0; + + cache_end = (uintptr_t)cache; + cache_end += cache->size + sizeof(*cache); + + if (cache_end > region_end) + return 0; + + return 1; +} + +static int mrc_cache_valid(const struct mrc_data_region *region, + const struct mrc_saved_data *cache) +{ + uint32_t checksum; + + if (cache->signature != MRC_DATA_SIGNATURE) + return 0; + + if (cache->size > region->size) + return 0; + + if (cache->reserved != 0) + return 0; + + checksum = compute_ip_checksum((void *)&cache->data[0], cache->size); + + if (cache->checksum != checksum) + return 0; + + return 1; +} + +static const struct mrc_saved_data * +next_cache_block(const struct mrc_saved_data *cache) +{ + uintptr_t next = (uintptr_t)cache; + + next += ALIGN(cache->size + sizeof(*cache), MRC_DATA_ALIGN); + + return (const struct mrc_saved_data *)next; +} + +/* Locate the most recently saved MRC data. */ +static int __mrc_cache_get_current(const struct mrc_data_region *region, + const struct mrc_saved_data **cache) +{ + const struct mrc_saved_data *msd; + const struct mrc_saved_data *verified_cache; + int slot = 0; + + msd = region->base; + + verified_cache = NULL; + + while (mrc_cache_in_region(region, msd) && + mrc_cache_valid(region, msd)) { + verified_cache = msd; + msd = next_cache_block(msd); + slot++; + } + + if (verified_cache == NULL) + return -1; + + *cache = verified_cache; + printk(BIOS_DEBUG, "MRC cache slot %d @ %p\n", slot-1, verified_cache); + + return 0; +} + +int mrc_cache_get_current(const struct mrc_saved_data **cache) +{ + struct mrc_data_region region; + + if (mrc_cache_get_region(®ion) < 0) + return -1; + + return __mrc_cache_get_current(®ion, cache); +} + +#if defined(__PRE_RAM__) + +/* + * romstage code + */ + +/* Fill in mrc_saved_data structure with payload. */ +static void mrc_cache_fill(struct mrc_saved_data *cache, void *data, + size_t size) +{ + cache->signature = MRC_DATA_SIGNATURE; + cache->size = size; + cache->reserved = 0; + memcpy(&cache->data[0], data, size); + cache->checksum = compute_ip_checksum((void *)&cache->data[0], + cache->size); +} + +int mrc_cache_stash_data(void *data, size_t size) +{ + int cbmem_size; + struct mrc_saved_data *cache; + + cbmem_size = sizeof(*cache) + ALIGN(size, 16); + + cache = cbmem_add(CBMEM_ID_MRCDATA, cbmem_size); + + if (cache == NULL) { + printk(BIOS_ERR, "No space in cbmem for MRC data.\n"); + return -1; + } + + /* Clear alignment padding bytes at end of data. */ + memset(&cache->data[size], 0, cbmem_size - size - sizeof(*cache)); + + printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n", + data, cache, size); + + mrc_cache_fill(cache, data, size); + + return 0; +} + +#else + +/* + * ramstage code + */ + +#include +#include "nvm.h" + +static int mrc_slot_valid(const struct mrc_data_region *region, + const struct mrc_saved_data *slot, + const struct mrc_saved_data *to_save) +{ + uintptr_t region_begin; + uintptr_t region_end; + uintptr_t slot_end; + uintptr_t slot_begin; + uint32_t size; + + region_begin = (uintptr_t)region->base; + region_end = region_begin + region->size; + slot_begin = (uintptr_t)slot; + size = to_save->size + sizeof(*to_save); + slot_end = slot_begin + size; + + if (slot_begin < region_begin || slot_begin >= region_end) + return 0; + + if (size > region->size) + return 0; + + if (slot_end > region_end || slot_end < region_begin) + return 0; + + if (!nvm_is_erased(slot, size)) + return 0; + + return 1; +} + +static const struct mrc_saved_data * +mrc_cache_next_slot(const struct mrc_data_region *region, + const struct mrc_saved_data *current_slot) +{ + const struct mrc_saved_data *next_slot; + + if (current_slot == NULL) { + next_slot = region->base; + } else { + next_slot = next_cache_block(current_slot); + } + + return next_slot; +} + +static void update_mrc_cache(void *unused) +{ + const struct mrc_saved_data *current_boot; + const struct mrc_saved_data *current_saved; + const struct mrc_saved_data *next_slot; + struct mrc_data_region region; + + printk(BIOS_DEBUG, "Updating MRC cache data.\n"); + + current_boot = cbmem_find(CBMEM_ID_MRCDATA); + if (!current_boot) { + printk(BIOS_ERR, "No MRC cache in cbmem.\n"); + return; + } + + if (mrc_cache_get_region(®ion)) { + printk(BIOS_ERR, "Could not obtain MRC cache region.\n"); + return; + } + + if (!mrc_cache_valid(®ion, current_boot)) { + printk(BIOS_ERR, "MRC cache data in cbmem invalid.\n"); + return; + } + + current_saved = NULL; + + if (!__mrc_cache_get_current(®ion, ¤t_saved)) { + if (current_saved->size == current_boot->size && + !memcmp(¤t_saved->data[0], ¤t_boot->data[0], + current_saved->size)) { + printk(BIOS_DEBUG, "MRC cache up to date.\n"); + return; + } + } + + next_slot = mrc_cache_next_slot(®ion, current_saved); + + if (!mrc_slot_valid(®ion, next_slot, current_boot)) { + printk(BIOS_DEBUG, "Slot @ %p is invalid.\n", next_slot); + if (!nvm_is_erased(region.base, region.size)) { + if (nvm_erase(region.base, region.size) < 0) { + printk(BIOS_DEBUG, "Failure erasing region.\n"); + return; + } + } + next_slot = region.base; + } + + if (nvm_write((void *)next_slot, current_boot, + current_boot->size + sizeof(*current_boot))) { + printk(BIOS_DEBUG, "Failure writing MRC cache to %p.\n", + next_slot); + } +} + +BOOT_STATE_INIT_ENTRIES(mrc_cache_update) = { + BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, + update_mrc_cache, NULL), +}; + +#endif /* defined(__PRE_RAM__) */ diff --git a/src/soc/intel/common/mrc_cache.h b/src/soc/intel/common/mrc_cache.h new file mode 100644 index 0000000000..14767e52b3 --- /dev/null +++ b/src/soc/intel/common/mrc_cache.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COMMON_MRC_CACHE_H_ +#define _COMMON_MRC_CACHE_H_ + +#include +#include + +/* Wrapper object to save MRC information. */ +struct mrc_saved_data { + uint32_t signature; + uint32_t size; + uint32_t checksum; + uint32_t reserved; + uint8_t data[0]; +} __attribute__((packed)); + +/* Locate the most recently saved MRC data. */ +int mrc_cache_get_current(const struct mrc_saved_data **cache); + +/* Stash the resulting MRC data to be saved in non-volatile storage later. */ +int mrc_cache_stash_data(void *data, size_t size); + +#endif /* _COMMON_MRC_CACHE_H_ */ diff --git a/src/soc/intel/common/nvm.c b/src/soc/intel/common/nvm.c new file mode 100644 index 0000000000..791422fe30 --- /dev/null +++ b/src/soc/intel/common/nvm.c @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "nvm.h" + +/* This module assumes the flash is memory mapped just below 4GiB in the + * address space for reading. Also this module assumes an area it erased + * when all bytes read as all 0xff's. */ + +static struct spi_flash *flash; + +static int nvm_init(void) +{ + if (flash != NULL) + return 0; + + spi_init(); + flash = spi_flash_probe(0, 0); + if (!flash) { + printk(BIOS_DEBUG, "Could not find SPI device\n"); + return -1; + } + + return 0; +} + +/* Convert memory mapped pointer to flash offset. */ +static inline uint32_t to_flash_offset(void *p) +{ + return CONFIG_ROM_SIZE + (uintptr_t)p; +} + +int nvm_is_erased(const void *start, size_t size) +{ + const uint8_t *cur = start; + const uint8_t erased_value = 0xff; + + while (size > 0) { + if (*cur != erased_value) + return 0; + cur++; + size--; + } + return 1; +} + +int nvm_erase(void *start, size_t size) +{ + if (nvm_init() < 0) + return -1; + return flash->erase(flash, to_flash_offset(start), size); +} + +/* Write data to NVM. Returns 0 on success < 0 on error. */ +int nvm_write(void *start, const void *data, size_t size) +{ + if (nvm_init() < 0) + return -1; + return flash->write(flash, to_flash_offset(start), size, data); +} diff --git a/src/soc/intel/common/nvm.h b/src/soc/intel/common/nvm.h new file mode 100644 index 0000000000..d332d831f7 --- /dev/null +++ b/src/soc/intel/common/nvm.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _COMMON_NVM_H_ +#define _COMMON_NVM_H_ + +#include + +/* Determine if area is erased. returns 1 if erased. 0 otherwise. */ +int nvm_is_erased(const void *start, size_t size); + +/* Erase region according to start and size. Returns < 0 on error else 0. */ +int nvm_erase(void *start, size_t size); + +/* Write data to NVM. Returns 0 on success < 0 on error. */ +int nvm_write(void *start, const void *data, size_t size); + +#endif /* _COMMON_NVM_H_ */ diff --git a/src/soc/marvell/Kconfig b/src/soc/marvell/Kconfig new file mode 100644 index 0000000000..95b8c50f54 --- /dev/null +++ b/src/soc/marvell/Kconfig @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +source src/soc/marvell/bg4cd/Kconfig diff --git a/src/soc/marvell/Makefile.inc b/src/soc/marvell/Makefile.inc new file mode 100644 index 0000000000..ef7bcd9e2e --- /dev/null +++ b/src/soc/marvell/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-$(CONFIG_SOC_MARVELL_BG4CD) += bg4cd diff --git a/src/soc/marvell/bg4cd/Kconfig b/src/soc/marvell/bg4cd/Kconfig new file mode 100644 index 0000000000..fb525a8ffa --- /dev/null +++ b/src/soc/marvell/bg4cd/Kconfig @@ -0,0 +1,46 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config SOC_MARVELL_BG4CD + bool + default n + select ARCH_BOOTBLOCK_ARM_V7_M + select ARCH_RAMSTAGE_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_VERSTAGE_ARM_V7_M + select BOOTBLOCK_CONSOLE + select CPU_HAS_BOOTBLOCK_INIT + select DYNAMIC_CBMEM + select EARLY_CONSOLE + select GENERIC_UDELAY + select HAVE_MONOTONIC_TIMER + select HAVE_UART_MEMORY_MAPPED + select HAVE_UART_SPECIAL + select GENERIC_GPIO_LIB + # RETURN_FROM_VERSTAGE is disabled because vboot2_verify_firmware is + # part of bootblock, so, verstage is called as a function instead of + # as a stage + +if SOC_MARVELL_BG4CD + +config BOOTBLOCK_CPU_INIT + string + default "soc/marvell/bg4cd/bootblock.c" + +endif diff --git a/src/soc/marvell/bg4cd/Makefile.inc b/src/soc/marvell/bg4cd/Makefile.inc new file mode 100644 index 0000000000..2255cf3803 --- /dev/null +++ b/src/soc/marvell/bg4cd/Makefile.inc @@ -0,0 +1,53 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bootblock-y += bootblock.c +bootblock-y += cbmem.c +bootblock-y += i2c.c +bootblock-y += monotonic_timer.c +bootblock-$(CONFIG_SPI_FLASH) += spi.c +bootblock-$(CONFIG_CONSOLE_SERIAL) += uart.c + +verstage-y += i2c.c +verstage-y += monotonic_timer.c +verstage-$(CONFIG_SPI_FLASH) += spi.c +verstage-$(CONFIG_CONSOLE_SERIAL) += uart.c + +romstage-y += cbmem.c +romstage-y += i2c.c +romstage-y += monotonic_timer.c +romstage-y += sdram.c +romstage-$(CONFIG_SPI_FLASH) += spi.c +romstage-$(CONFIG_CONSOLE_SERIAL) += uart.c + +ramstage-y += cbmem.c +ramstage-y += i2c.c +ramstage-y += monotonic_timer.c +ramstage-$(CONFIG_SPI_FLASH) += spi.c +ramstage-$(CONFIG_CONSOLE_SERIAL) += uart.c + +INCLUDES += -Isrc/soc/marvell/bg4cd/include/ + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin + @printf "Generating: $(subst $(obj)/,,$(@))\n" + @mkdir -p $(dir $@) + @mv $< $@ diff --git a/src/soc/marvell/bg4cd/bootblock.c b/src/soc/marvell/bg4cd/bootblock.c new file mode 100644 index 0000000000..236a71810a --- /dev/null +++ b/src/soc/marvell/bg4cd/bootblock.c @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +void bootblock_soc_init(void) +{ +/* TODO: I assume this is a placeholder. If it's not really needed delete it. */ +} diff --git a/src/soc/marvell/bg4cd/cbmem.c b/src/soc/marvell/bg4cd/cbmem.c new file mode 100644 index 0000000000..168673d800 --- /dev/null +++ b/src/soc/marvell/bg4cd/cbmem.c @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void *cbmem_top(void) +{ + return NULL; +} diff --git a/src/soc/marvell/bg4cd/i2c.c b/src/soc/marvell/bg4cd/i2c.c new file mode 100644 index 0000000000..16ad9abcf3 --- /dev/null +++ b/src/soc/marvell/bg4cd/i2c.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count) +{ + return 0; +} + +void i2c_init(unsigned int bus, unsigned int hz) +{ +} diff --git a/src/soc/marvell/bg4cd/include/soc/gpio.h b/src/soc/marvell/bg4cd/include/soc/gpio.h new file mode 100644 index 0000000000..86882c7af7 --- /dev/null +++ b/src/soc/marvell/bg4cd/include/soc/gpio.h @@ -0,0 +1,8 @@ +#ifndef __SOC_MARVELL_BG4CD_GPIO_H__ +#define __SOC_MARVELL_BG4CD_GPIO_H__ + +#include + +typedef u32 gpio_t; + +#endif /* __SOC_MARVELL_BG4CD_GPIO_H__ */ diff --git a/src/soc/marvell/bg4cd/include/soc/i2c.h b/src/soc/marvell/bg4cd/include/soc/i2c.h new file mode 100644 index 0000000000..40db31a9ee --- /dev/null +++ b/src/soc/marvell/bg4cd/include/soc/i2c.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_MARVELL_BG4CD_I2C_H__ +#define __SOC_MARVELL_BG4CD_I2C_H__ + +void i2c_init(unsigned int bus, unsigned int hz); + +#endif + diff --git a/src/soc/marvell/bg4cd/include/soc/memlayout.ld b/src/soc/marvell/bg4cd/include/soc/memlayout.ld new file mode 100644 index 0000000000..45cf3950c3 --- /dev/null +++ b/src/soc/marvell/bg4cd/include/soc/memlayout.ld @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +SECTIONS +{ + DRAM_START(0x00000000) + RAMSTAGE(0x00200000, 128K) + POSTRAM_CBFS_CACHE(0x01000000, 1M) + + SRAM_START(0x80000000) + TTB(0x80000000, 16K) + BOOTBLOCK(0x80004004, 16K - 4) + VBOOT2_WORK(0x80008000, 16K) + OVERLAP_VERSTAGE_ROMSTAGE(0x8000C000, 40K) + PRERAM_CBFS_CACHE(0x80016000, 4K) + STACK(0x80017000, 4K) + SRAM_END(0x80018000) +} diff --git a/src/soc/marvell/bg4cd/include/soc/sdram.h b/src/soc/marvell/bg4cd/include/soc/sdram.h new file mode 100644 index 0000000000..6850d2752a --- /dev/null +++ b/src/soc/marvell/bg4cd/include/soc/sdram.h @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_MARVELL_BG4CD_SDRAM_H__ +#define __SOC_MARVELL_BG4CD_SDRAM_H__ + +void sdram_init(void); +#endif diff --git a/src/soc/marvell/bg4cd/monotonic_timer.c b/src/soc/marvell/bg4cd/monotonic_timer.c new file mode 100644 index 0000000000..efc2a8fa55 --- /dev/null +++ b/src/soc/marvell/bg4cd/monotonic_timer.c @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +void timer_monotonic_get(struct mono_time *mt) +{ +} diff --git a/src/soc/marvell/bg4cd/sdram.c b/src/soc/marvell/bg4cd/sdram.c new file mode 100644 index 0000000000..0ebee151fb --- /dev/null +++ b/src/soc/marvell/bg4cd/sdram.c @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +void sdram_init(void) +{ + printk(BIOS_INFO, "Starting SDRAM initialization...\n"); + printk(BIOS_INFO, "Finish SDRAM initialization...\n"); +} diff --git a/src/soc/marvell/bg4cd/spi.c b/src/soc/marvell/bg4cd/spi.c new file mode 100644 index 0000000000..8ae22d1487 --- /dev/null +++ b/src/soc/marvell/bg4cd/spi.c @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + return NULL; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned out_bytes, void *din, unsigned in_bytes) +{ + return 0; +} diff --git a/src/soc/marvell/bg4cd/uart.c b/src/soc/marvell/bg4cd/uart.c new file mode 100644 index 0000000000..3de37c0c98 --- /dev/null +++ b/src/soc/marvell/bg4cd/uart.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +void uart_init(void) +{ +} + +void uart_tx_byte(unsigned char data) +{ +} + +int uart_can_rx_byte(void) +{ + return 0; +} + +void uart_tx_flush(void) +{ +} + +unsigned char uart_rx_byte(void) +{ + return '\0'; +} + +/* Not really needed on this chip, but helps to keep coreboot table happy. */ +u32 uartmem_getbaseaddr(void) +{ + return 0; +} diff --git a/src/soc/nvidia/Kconfig b/src/soc/nvidia/Kconfig new file mode 100644 index 0000000000..cb1f468d5e --- /dev/null +++ b/src/soc/nvidia/Kconfig @@ -0,0 +1,2 @@ +source src/soc/nvidia/tegra124/Kconfig +source src/soc/nvidia/tegra132/Kconfig diff --git a/src/soc/nvidia/Makefile.inc b/src/soc/nvidia/Makefile.inc new file mode 100644 index 0000000000..100cb940a8 --- /dev/null +++ b/src/soc/nvidia/Makefile.inc @@ -0,0 +1,2 @@ +subdirs-$(CONFIG_SOC_NVIDIA_TEGRA124) += tegra124 +subdirs-$(CONFIG_SOC_NVIDIA_TEGRA132) += tegra132 diff --git a/src/soc/nvidia/tegra/apbmisc.c b/src/soc/nvidia/tegra/apbmisc.c new file mode 100644 index 0000000000..3fc0ef7de1 --- /dev/null +++ b/src/soc/nvidia/tegra/apbmisc.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "apbmisc.h" + +static struct apbmisc *misc = (struct apbmisc *)TEGRA_APB_MISC_BASE; + +void enable_jtag(void) +{ + write32(PP_CONFIG_CTL_JTAG, &misc->pp_config_ctl); +} + +void clamp_tristate_inputs(void) +{ + write32(PP_PINMUX_CLAMP_INPUTS, &misc->pp_pinmux_global); +} + +void tegra_revision_info(struct tegra_revision *id) +{ + uintptr_t gp_hidrev= (uintptr_t)TEGRA_APB_MISC_BASE + MISC_GP_HIDREV; + uint32_t reg; + + reg = read32((void *)(gp_hidrev)); + + id->hid_fam = (reg >> 0) & 0x0f; + id->chip_id = (reg >> 8) & 0xff; + id->major = (reg >> 4) & 0x0f; + id->minor = (reg >> 16) & 0x07; +} diff --git a/src/soc/nvidia/tegra/apbmisc.h b/src/soc/nvidia/tegra/apbmisc.h new file mode 100644 index 0000000000..38cd527c9f --- /dev/null +++ b/src/soc/nvidia/tegra/apbmisc.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_APBMISC_H__ +#define __SOC_NVIDIA_TEGRA_APBMISC_H__ + +#include + +struct apbmisc { + u32 reserved0[9]; /* ABP_MISC_PP_ offsets 00-20 */ + u32 pp_config_ctl; /* _CONFIG_CTL_0, offset 24 */ + u32 reserved1[6]; /* APB_MISC_PP_ offsets 28-3C */ + u32 pp_pinmux_global; /* _PINMUX_GLOBAL_0, offset 40 */ +}; + +#define PP_CONFIG_CTL_TBE (1 << 7) +#define PP_CONFIG_CTL_JTAG (1 << 6) + +#define PP_PINMUX_CLAMP_INPUTS (1 << 0) + +enum { + MISC_GP_HIDREV = 0x804 +}; + +struct tegra_revision { + int hid_fam; + int chip_id; + int major; + int minor; +}; + +void enable_jtag(void); +void clamp_tristate_inputs(void); +void tegra_revision_info(struct tegra_revision *id); + +#endif /* __SOC_NVIDIA_TEGRA_APBMISC_H__ */ diff --git a/src/soc/nvidia/tegra/dc.h b/src/soc/nvidia/tegra/dc.h new file mode 100644 index 0000000000..39693c9d80 --- /dev/null +++ b/src/soc/nvidia/tegra/dc.h @@ -0,0 +1,514 @@ +/* + * Copyright 2013 Google Inc. + * (C) Copyright 2010 + * NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_DC_H +#define __SOC_NVIDIA_TEGRA_DC_H +#include +#include + +/* Register definitions for the Tegra display controller */ + +/* CMD register 0x000 ~ 0x43 */ +struct dc_cmd_reg { + /* Address 0x000 ~ 0x002 */ + u32 gen_incr_syncpt; /* _CMD_GENERAL_INCR_SYNCPT_0 */ + u32 gen_incr_syncpt_ctrl; /* _CMD_GENERAL_INCR_SYNCPT_CNTRL_0 */ + u32 gen_incr_syncpt_err; /* _CMD_GENERAL_INCR_SYNCPT_ERROR_0 */ + + u32 reserved0[5]; /* reserved_0[5] */ + + /* Address 0x008 ~ 0x00a */ + u32 win_a_incr_syncpt; /* _CMD_WIN_A_INCR_SYNCPT_0 */ + u32 win_a_incr_syncpt_ctrl; /* _CMD_WIN_A_INCR_SYNCPT_CNTRL_0 */ + u32 win_a_incr_syncpt_err; /* _CMD_WIN_A_INCR_SYNCPT_ERROR_0 */ + + u32 reserved1[5]; /* reserved_1[5] */ + + /* Address 0x010 ~ 0x012 */ + u32 win_b_incr_syncpt; /* _CMD_WIN_B_INCR_SYNCPT_0 */ + u32 win_b_incr_syncpt_ctrl; /* _CMD_WIN_B_INCR_SYNCPT_CNTRL_0 */ + u32 win_b_incr_syncpt_err; /* _CMD_WIN_B_INCR_SYNCPT_ERROR_0 */ + + u32 reserved2[5]; /* reserved_2[5] */ + + /* Address 0x018 ~ 0x01a */ + u32 win_c_incr_syncpt; /* _CMD_WIN_C_INCR_SYNCPT_0 */ + u32 win_c_incr_syncpt_ctrl; /* _CMD_WIN_C_INCR_SYNCPT_CNTRL_0 */ + u32 win_c_incr_syncpt_err; /* _CMD_WIN_C_INCR_SYNCPT_ERROR_0 */ + + u32 reserved3[13]; /* reserved_3[13] */ + + /* Address 0x028 */ + u32 cont_syncpt_vsync; /* _CMD_CONT_SYNCPT_VSYNC_0 */ + + u32 reserved4[7]; /* reserved_4[7] */ + + /* Address 0x030 ~ 0x033 */ + u32 ctxsw; /* _CMD_CTXSW_0 */ + u32 disp_cmd_opt0; /* _CMD_DISPLAY_COMMAND_OPTION0_0 */ + u32 disp_cmd; /* _CMD_DISPLAY_COMMAND_0 */ + u32 sig_raise; /* _CMD_SIGNAL_RAISE_0 */ + + u32 reserved5[2]; /* reserved_0[2] */ + + /* Address 0x036 ~ 0x03e */ + u32 disp_pow_ctrl; /* _CMD_DISPLAY_POWER_CONTROL_0 */ + u32 int_stat; /* _CMD_INT_STATUS_0 */ + u32 int_mask; /* _CMD_INT_MASK_0 */ + u32 int_enb; /* _CMD_INT_ENABLE_0 */ + u32 int_type; /* _CMD_INT_TYPE_0 */ + u32 int_polarity; /* _CMD_INT_POLARITY_0 */ + u32 sig_raise1; /* _CMD_SIGNAL_RAISE1_0 */ + u32 sig_raise2; /* _CMD_SIGNAL_RAISE2_0 */ + u32 sig_raise3; /* _CMD_SIGNAL_RAISE3_0 */ + + u32 reserved6; /* reserved_6 */ + + /* Address 0x040 ~ 0x043 */ + u32 state_access; /* _CMD_STATE_ACCESS_0 */ + u32 state_ctrl; /* _CMD_STATE_CONTROL_0 */ + u32 disp_win_header; /* _CMD_DISPLAY_WINDOW_HEADER_0 */ + u32 reg_act_ctrl; /* _CMD_REG_ACT_CONTROL_0 */ +}; +check_member(dc_cmd_reg, reg_act_ctrl, 0x43 * 4); + +enum { + PIN_REG_COUNT = 4, + PIN_OUTPUT_SEL_COUNT = 7, +}; + +/* COM register 0x300 ~ 0x329 */ +struct dc_com_reg { + /* Address 0x300 ~ 0x301 */ + u32 crc_ctrl; /* _COM_CRC_CONTROL_0 */ + u32 crc_checksum; /* _COM_CRC_CHECKSUM_0 */ + + /* _COM_PIN_OUTPUT_ENABLE0/1/2/3_0: Address 0x302 ~ 0x305 */ + u32 pin_output_enb[PIN_REG_COUNT]; + + /* _COM_PIN_OUTPUT_POLARITY0/1/2/3_0: Address 0x306 ~ 0x309 */ + u32 pin_output_polarity[PIN_REG_COUNT]; + + /* _COM_PIN_OUTPUT_DATA0/1/2/3_0: Address 0x30a ~ 0x30d */ + u32 pin_output_data[PIN_REG_COUNT]; + + /* _COM_PIN_INPUT_ENABLE0_0: Address 0x30e ~ 0x311 */ + u32 pin_input_enb[PIN_REG_COUNT]; + + /* Address 0x312 ~ 0x313 */ + u32 pin_input_data0; /* _COM_PIN_INPUT_DATA0_0 */ + u32 pin_input_data1; /* _COM_PIN_INPUT_DATA1_0 */ + + /* _COM_PIN_OUTPUT_SELECT0/1/2/3/4/5/6_0: Address 0x314 ~ 0x31a */ + u32 pin_output_sel[PIN_OUTPUT_SEL_COUNT]; + + /* Address 0x31b ~ 0x329 */ + u32 pin_misc_ctrl; /* _COM_PIN_MISC_CONTROL_0 */ + u32 pm0_ctrl; /* _COM_PM0_CONTROL_0 */ + u32 pm0_duty_cycle; /* _COM_PM0_DUTY_CYCLE_0 */ + u32 pm1_ctrl; /* _COM_PM1_CONTROL_0 */ + u32 pm1_duty_cycle; /* _COM_PM1_DUTY_CYCLE_0 */ + u32 spi_ctrl; /* _COM_SPI_CONTROL_0 */ + u32 spi_start_byte; /* _COM_SPI_START_BYTE_0 */ + u32 hspi_wr_data_ab; /* _COM_HSPI_WRITE_DATA_AB_0 */ + u32 hspi_wr_data_cd; /* _COM_HSPI_WRITE_DATA_CD */ + u32 hspi_cs_dc; /* _COM_HSPI_CS_DC_0 */ + u32 scratch_reg_a; /* _COM_SCRATCH_REGISTER_A_0 */ + u32 scratch_reg_b; /* _COM_SCRATCH_REGISTER_B_0 */ + u32 gpio_ctrl; /* _COM_GPIO_CTRL_0 */ + u32 gpio_debounce_cnt; /* _COM_GPIO_DEBOUNCE_COUNTER_0 */ + u32 crc_checksum_latched; /* _COM_CRC_CHECKSUM_LATCHED_0 */ +}; +check_member(dc_com_reg, crc_checksum_latched, (0x329 - 0x300) * 4); + +enum dc_disp_h_pulse_pos { + H_PULSE0_POSITION_A, + H_PULSE0_POSITION_B, + H_PULSE0_POSITION_C, + H_PULSE0_POSITION_D, + H_PULSE0_POSITION_COUNT, +}; + +struct _disp_h_pulse { + /* _DISP_H_PULSE0/1/2_CONTROL_0 */ + u32 h_pulse_ctrl; + /* _DISP_H_PULSE0/1/2_POSITION_A/B/C/D_0 */ + u32 h_pulse_pos[H_PULSE0_POSITION_COUNT]; +}; + +enum dc_disp_v_pulse_pos { + V_PULSE0_POSITION_A, + V_PULSE0_POSITION_B, + V_PULSE0_POSITION_C, + V_PULSE0_POSITION_COUNT, +}; + +struct _disp_v_pulse0 { + /* _DISP_H_PULSE0/1_CONTROL_0 */ + u32 v_pulse_ctrl; + /* _DISP_H_PULSE0/1_POSITION_A/B/C_0 */ + u32 v_pulse_pos[V_PULSE0_POSITION_COUNT]; +}; + +struct _disp_v_pulse2 { + /* _DISP_H_PULSE2/3_CONTROL_0 */ + u32 v_pulse_ctrl; + /* _DISP_H_PULSE2/3_POSITION_A_0 */ + u32 v_pulse_pos_a; +}; + +enum dc_disp_h_pulse_reg { + H_PULSE0, + H_PULSE1, + H_PULSE2, + H_PULSE_COUNT, +}; + +enum dc_disp_pp_select { + PP_SELECT_A, + PP_SELECT_B, + PP_SELECT_C, + PP_SELECT_D, + PP_SELECT_COUNT, +}; + +/* DISP register 0x400 ~ 0x4c1 */ +struct dc_disp_reg { + /* Address 0x400 ~ 0x40a */ + u32 disp_signal_opt0; /* _DISP_DISP_SIGNAL_OPTIONS0_0 */ + u32 rsvd_401; + u32 disp_win_opt; /* _DISP_DISP_WIN_OPTIONS_0 */ + u32 rsvd_403[2]; /* 403 - 404 */ + u32 disp_timing_opt; /* _DISP_DISP_TIMING_OPTIONS_0 */ + u32 ref_to_sync; /* _DISP_REF_TO_SYNC_0 */ + u32 sync_width; /* _DISP_SYNC_WIDTH_0 */ + u32 back_porch; /* _DISP_BACK_PORCH_0 */ + u32 disp_active; /* _DISP_DISP_ACTIVE_0 */ + u32 front_porch; /* _DISP_FRONT_PORCH_0 */ + + /* Address 0x40b ~ 0x419: _DISP_H_PULSE0/1/2_ */ + struct _disp_h_pulse h_pulse[H_PULSE_COUNT]; + + /* Address 0x41a ~ 0x421 */ + struct _disp_v_pulse0 v_pulse0; /* _DISP_V_PULSE0_ */ + struct _disp_v_pulse0 v_pulse1; /* _DISP_V_PULSE1_ */ + + /* Address 0x422 ~ 0x425 */ + struct _disp_v_pulse2 v_pulse3; /* _DISP_V_PULSE2_ */ + struct _disp_v_pulse2 v_pulse4; /* _DISP_V_PULSE3_ */ + + u32 rsvd_426[8]; /* 426 - 42d */ + + /* Address 0x42e ~ 0x430 */ + u32 disp_clk_ctrl; /* _DISP_DISP_CLOCK_CONTROL_0 */ + u32 disp_interface_ctrl; /* _DISP_DISP_INTERFACE_CONTROL_0 */ + u32 disp_color_ctrl; /* _DISP_DISP_COLOR_CONTROL_0 */ + + u32 rsvd_431[6]; /* 431 - 436 */ + + /* Address 0x437 ~ 0x439 */ + u32 color_key0_upper; /* _DISP_COLOR_KEY0_UPPER_0 */ + u32 color_key1_lower; /* _DISP_COLOR_KEY1_LOWER_0 */ + u32 color_key1_upper; /* _DISP_COLOR_KEY1_UPPER_0 */ + + u32 reserved0[2]; /* 43a - 43b */ + + /* Address 0x43c ~ 0x441 */ + u32 cursor_foreground; /* _DISP_CURSOR_FOREGROUND_0 */ + u32 cursor_background; /* _DISP_CURSOR_BACKGROUND_0 */ + u32 cursor_start_addr; /* _DISP_CURSOR_START_ADDR_0 */ + u32 cursor_start_addr_ns; /* _DISP_CURSOR_START_ADDR_NS_0 */ + u32 cursor_pos; /* _DISP_CURSOR_POSITION_0 */ + u32 cursor_pos_ns; /* _DISP_CURSOR_POSITION_NS_0 */ + + u32 rsvd_442[62]; /* 442 - 47f */ + + /* Address 0x480 ~ 0x483 */ + u32 dc_mccif_fifoctrl; /* _DISP_DC_MCCIF_FIFOCTRL_0 */ + u32 mccif_disp0a_hyst; /* _DISP_MCCIF_DISPLAY0A_HYST_0 */ + u32 mccif_disp0b_hyst; /* _DISP_MCCIF_DISPLAY0B_HYST_0 */ + u32 mccif_disp0c_hyst; /* _DISP_MCCIF_DISPLAY0C_HYST_0 */ + + u32 rsvd_484[61]; /* 484 - 4c0 */ + + /* Address 0x4c1 */ + u32 disp_misc_ctrl; /* _DISP_DISP_MISC_CONTROL_0 */ + + u32 rsvd_4c2[34]; /* 4c2 - 4e3 */ + + /* Address 0x4e4 */ + u32 blend_background_color; /* _DISP_BLEND_BACKGROUND_COLOR_0 */ +}; +check_member(dc_disp_reg, blend_background_color, (0x4e4 - 0x400) * 4); + +enum dc_winc_filter_p { + WINC_FILTER_COUNT = 0x10, +}; + +/* Window A/B/C register 0x500 ~ 0x628 */ +struct dc_winc_reg { + + /* Address 0x500 */ + u32 color_palette; /* _WINC_COLOR_PALETTE_0 */ + + u32 reserved0[0xff]; /* reserved_0[0xff] */ + + /* Address 0x600 */ + u32 palette_color_ext; /* _WINC_PALETTE_COLOR_EXT_0 */ + + /* _WINC_H_FILTER_P00~0F_0 */ + /* Address 0x601 ~ 0x610 */ + u32 h_filter_p[WINC_FILTER_COUNT]; + + /* Address 0x611 ~ 0x618 */ + u32 csc_yof; /* _WINC_CSC_YOF_0 */ + u32 csc_kyrgb; /* _WINC_CSC_KYRGB_0 */ + u32 csc_kur; /* _WINC_CSC_KUR_0 */ + u32 csc_kvr; /* _WINC_CSC_KVR_0 */ + u32 csc_kug; /* _WINC_CSC_KUG_0 */ + u32 csc_kvg; /* _WINC_CSC_KVG_0 */ + u32 csc_kub; /* _WINC_CSC_KUB_0 */ + u32 csc_kvb; /* _WINC_CSC_KVB_0 */ + + /* Address 0x619 ~ 0x628: _WINC_V_FILTER_P00~0F_0 */ + u32 v_filter_p[WINC_FILTER_COUNT]; +}; +check_member(dc_winc_reg, v_filter_p, (0x619 - 0x500) * 4); + +/* WIN A/B/C Register 0x700 ~ 0x719*/ +struct dc_win_reg { + /* Address 0x700 ~ 0x719 */ + u32 win_opt; /* _WIN_WIN_OPTIONS_0 */ + u32 byte_swap; /* _WIN_BYTE_SWAP_0 */ + u32 buffer_ctrl; /* _WIN_BUFFER_CONTROL_0 */ + u32 color_depth; /* _WIN_COLOR_DEPTH_0 */ + u32 pos; /* _WIN_POSITION_0 */ + u32 size; /* _WIN_SIZE_0 */ + u32 prescaled_size; /* _WIN_PRESCALED_SIZE_0 */ + u32 h_initial_dda; /* _WIN_H_INITIAL_DDA_0 */ + u32 v_initial_dda; /* _WIN_V_INITIAL_DDA_0 */ + u32 dda_increment; /* _WIN_DDA_INCREMENT_0 */ + u32 line_stride; /* _WIN_LINE_STRIDE_0 */ + u32 buf_stride; /* _WIN_BUF_STRIDE_0 */ + u32 uv_buf_stride; /* _WIN_UV_BUF_STRIDE_0 */ + u32 buffer_addr_mode; /* _WIN_BUFFER_ADDR_MODE_0 */ + u32 dv_ctrl; /* _WIN_DV_CONTROL_0 */ + u32 blend_nokey; /* _WIN_BLEND_NOKEY_0 */ + u32 blend_1win; /* _WIN_BLEND_1WIN_0 */ + u32 blend_2win_x; /* _WIN_BLEND_2WIN_X_0 */ + u32 blend_2win_y; /* _WIN_BLEND_2WIN_Y_0 */ + u32 blend_3win_xy; /* _WIN_BLEND_3WIN_XY_0 */ + u32 hp_fetch_ctrl; /* _WIN_HP_FETCH_CONTROL_0 */ + u32 global_alpha; /* _WIN_GLOBAL_ALPHA */ + u32 blend_layer_ctrl; /* _WINBUF_BLEND_LAYER_CONTROL_0 */ + u32 blend_match_select; /* _WINBUF_BLEND_MATCH_SELECT_0 */ + u32 blend_nomatch_select; /* _WINBUF_BLEND_NOMATCH_SELECT_0 */ + u32 blend_alpha_1bit; /* _WINBUF_BLEND_ALPHA_1BIT_0 */ +}; +check_member(dc_win_reg, blend_alpha_1bit, (0x719 - 0x700) * 4); + +/* WINBUF A/B/C Register 0x800 ~ 0x80d */ +struct dc_winbuf_reg { + /* Address 0x800 ~ 0x80d */ + u32 start_addr; /* _WINBUF_START_ADDR_0 */ + u32 start_addr_ns; /* _WINBUF_START_ADDR_NS_0 */ + u32 start_addr_u; /* _WINBUF_START_ADDR_U_0 */ + u32 start_addr_u_ns; /* _WINBUF_START_ADDR_U_NS_0 */ + u32 start_addr_v; /* _WINBUF_START_ADDR_V_0 */ + u32 start_addr_v_ns; /* _WINBUF_START_ADDR_V_NS_0 */ + u32 addr_h_offset; /* _WINBUF_ADDR_H_OFFSET_0 */ + u32 addr_h_offset_ns; /* _WINBUF_ADDR_H_OFFSET_NS_0 */ + u32 addr_v_offset; /* _WINBUF_ADDR_V_OFFSET_0 */ + u32 addr_v_offset_ns; /* _WINBUF_ADDR_V_OFFSET_NS_0 */ + u32 uflow_status; /* _WINBUF_UFLOW_STATUS_0 */ + u32 buffer_surface_kind; /* DC_WIN_BUFFER_SURFACE_KIND */ + u32 rsvd_80c; + u32 start_addr_hi; /* DC_WINBUF_START_ADDR_HI_0 */ +}; +check_member(dc_winbuf_reg, start_addr_hi, (0x80d - 0x800) * 4); + +/* Display Controller (DC_) regs */ +struct display_controller { + struct dc_cmd_reg cmd; /* CMD register 0x000 ~ 0x43 */ + u32 reserved0[0x2bc]; + + struct dc_com_reg com; /* COM register 0x300 ~ 0x329 */ + u32 reserved1[0xd6]; + + struct dc_disp_reg disp; /* DISP register 0x400 ~ 0x4e4 */ + u32 reserved2[0x1b]; + + struct dc_winc_reg winc; /* Window A/B/C 0x500 ~ 0x628 */ + u32 reserved3[0xd7]; + + struct dc_win_reg win; /* WIN A/B/C 0x700 ~ 0x719*/ + u32 reserved4[0xe6]; + + struct dc_winbuf_reg winbuf; /* WINBUF A/B/C 0x800 ~ 0x80d */ +}; +check_member(display_controller, winbuf, 0x800 * 4); + +#define BIT(pos) (1U << pos) + +/* DC_CMD_DISPLAY_COMMAND 0x032 */ +#define DISP_COMMAND_RAISE (1 << 0) +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_COMMAND_RAISE_VECTOR(x) (((x) & 0x1f) << 22) +#define DISP_COMMAND_RAISE_CHANNEL_ID(x) (((x) & 0xf) << 27) + +/* DC_CMD_DISPLAY_POWER_CONTROL 0x036 */ +#define PW0_ENABLE BIT(0) +#define PW1_ENABLE BIT(2) +#define PW2_ENABLE BIT(4) +#define PW3_ENABLE BIT(6) +#define PW4_ENABLE BIT(8) +#define PM0_ENABLE BIT(16) +#define PM1_ENABLE BIT(18) +#define SPI_ENABLE BIT(24) +#define HSPI_ENABLE BIT(25) + +/* DC_CMD_STATE_ACCESS 0x040 */ +#define READ_MUX_ASSEMBLY (0 << 0) +#define READ_MUX_ACTIVE (1 << 0) +#define WRITE_MUX_ASSEMBLY (0 << 2) +#define WRITE_MUX_ACTIVE (1 << 2) + +/* DC_CMD_STATE_CONTROL 0x041 */ +#define GENERAL_ACT_REQ BIT(0) +#define WIN_A_ACT_REQ BIT(1) +#define WIN_B_ACT_REQ BIT(2) +#define WIN_C_ACT_REQ BIT(3) +#define WIN_D_ACT_REQ BIT(4) +#define WIN_H_ACT_REQ BIT(5) +#define CURSOR_ACT_REQ BIT(7) +#define GENERAL_UPDATE BIT(8) +#define WIN_A_UPDATE BIT(9) +#define WIN_B_UPDATE BIT(10) +#define WIN_C_UPDATE BIT(11) +#define WIN_D_UPDATE BIT(12) +#define WIN_H_UPDATE BIT(13) +#define CURSOR_UPDATE BIT(15) +#define NC_HOST_TRIG BIT(24) + +/* DC_CMD_DISPLAY_WINDOW_HEADER 0x042 */ +#define WINDOW_A_SELECT BIT(4) +#define WINDOW_B_SELECT BIT(5) +#define WINDOW_C_SELECT BIT(6) +#define WINDOW_D_SELECT BIT(7) +#define WINDOW_H_SELECT BIT(8) + +/* DC_DISP_DISP_WIN_OPTIONS 0x402 */ +#define CURSOR_ENABLE BIT(16) +#define SOR_ENABLE BIT(25) +#define TVO_ENABLE BIT(28) +#define DSI_ENABLE BIT(29) +#define HDMI_ENABLE BIT(30) + +/* DC_DISP_DISP_TIMING_OPTIONS 0x405 */ +#define VSYNC_H_POSITION(x) ((x) & 0xfff) + +/* DC_DISP_DISP_CLOCK_CONTROL 0x42e */ +#define SHIFT_CLK_DIVIDER_SHIFT 0 +#define SHIFT_CLK_DIVIDER_MASK (0xff << SHIFT_CLK_DIVIDER_SHIFT) +#define PIXEL_CLK_DIVIDER_SHIFT 8 +#define PIXEL_CLK_DIVIDER_MSK (0xf << PIXEL_CLK_DIVIDER_SHIFT) +enum { + PIXEL_CLK_DIVIDER_PCD1, + PIXEL_CLK_DIVIDER_PCD1H, + PIXEL_CLK_DIVIDER_PCD2, + PIXEL_CLK_DIVIDER_PCD3, + PIXEL_CLK_DIVIDER_PCD4, + PIXEL_CLK_DIVIDER_PCD6, + PIXEL_CLK_DIVIDER_PCD8, + PIXEL_CLK_DIVIDER_PCD9, + PIXEL_CLK_DIVIDER_PCD12, + PIXEL_CLK_DIVIDER_PCD16, + PIXEL_CLK_DIVIDER_PCD18, + PIXEL_CLK_DIVIDER_PCD24, + PIXEL_CLK_DIVIDER_PCD13, +}; +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +/* DC_WIN_WIN_OPTIONS 0x700 */ +#define H_DIRECTION_DECREMENT(x) ((x) << 0) +#define V_DIRECTION_DECREMENT(x) ((x) << 2) +#define WIN_SCAN_COLUMN BIT(4) +#define COLOR_EXPAND BIT(6) +#define H_FILTER_ENABLE(x) ((x) << 8) +#define V_FILTER_ENABLE(x) ((x) << 10) +#define CP_ENABLE BIT(16) +#define CSC_ENABLE BIT(18) +#define DV_ENABLE BIT(20) +#define INTERLACE_ENABLE BIT(23) +#define INTERLACE_DISABLE (0 << 23) +#define WIN_ENABLE BIT(30) + +/* _WIN_COLOR_DEPTH_0 0x703 */ +enum { + COLOR_DEPTH_P8 = 3, + COLOR_DEPTH_B4G4R4A4, + COLOR_DEPTH_B5G5R5A, + COLOR_DEPTH_B5G6R5, + COLOR_DEPTH_AB5G5R5, + COLOR_DEPTH_B8G8R8A8 = 12, + COLOR_DEPTH_R8G8B8A8, + COLOR_DEPTH_YCbCr422 = 16, + COLOR_DEPTH_YUV422, + COLOR_DEPTH_YCbCr420P, + COLOR_DEPTH_YUV420P, + COLOR_DEPTH_YCbCr422P, + COLOR_DEPTH_YUV422P, + COLOR_DEPTH_N422R, + COLOR_DEPTH_YCbCr422R = COLOR_DEPTH_N422R, + COLOR_DEPTH_N422R_TRUE, + COLOR_DEPTH_YUV422R = COLOR_DEPTH_N422R_TRUE, + COLOR_DEPTH_CrYCbY422, + COLOR_DEPTH_VYUY422, +}; + +/* DC_WIN_DDA_INCREMENT 0x709 */ +#define DDA_INC(prescaled_size, post_scaled_size) \ + (((prescaled_size) - 1) * 0x1000 / ((post_scaled_size) - 1)) +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +struct tegra_dc { + void *config; + void *out; + void *base; +}; + +unsigned long READL(void * p); +void WRITEL(unsigned long value, void * p); + +#ifndef __PRE_RAM__ +void display_startup(device_t dev); +#endif +void dp_init(void * _config); +void dp_enable(void * _dp); +unsigned int fb_base_mb(void); + +#endif /* __SOC_NVIDIA_TEGRA_DC_H */ diff --git a/src/soc/nvidia/tegra/displayport.h b/src/soc/nvidia/tegra/displayport.h new file mode 100644 index 0000000000..b7face5d4e --- /dev/null +++ b/src/soc/nvidia/tegra/displayport.h @@ -0,0 +1,473 @@ +/* + * drivers/video/tegra/dc/dpaux_regs.h + * + * Copyright (c) 2014, NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__ +#define __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__ + +#include + +/* things we can't get rid of just yet. */ +#define DPAUX_INTR_EN_AUX (0x1) +#define DPAUX_INTR_AUX (0x5) +#define DPAUX_DP_AUXDATA_WRITE_W(i) (0x9 + 4*(i)) +#define DPAUX_DP_AUXDATA_READ_W(i) (0x19 + 4*(i)) +#define DPAUX_DP_AUXADDR (0x29) +#define DPAUX_DP_AUXCTL (0x2d) +#define DPAUX_DP_AUXCTL_CMDLEN_SHIFT (0) +#define DPAUX_DP_AUXCTL_CMDLEN_FIELD (0xff) +#define DPAUX_DP_AUXCTL_CMD_SHIFT (12) +#define DPAUX_DP_AUXCTL_CMD_MASK (0xf << 12) +#define DPAUX_DP_AUXCTL_CMD_I2CWR (0 << 12) +#define DPAUX_DP_AUXCTL_CMD_I2CRD (1 << 12) +#define DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT (2 << 12) +#define DPAUX_DP_AUXCTL_CMD_MOTWR (4 << 12) +#define DPAUX_DP_AUXCTL_CMD_MOTRD (5 << 12) +#define DPAUX_DP_AUXCTL_CMD_MOTREQWSTAT (6 << 12) +#define DPAUX_DP_AUXCTL_CMD_AUXWR (8 << 12) +#define DPAUX_DP_AUXCTL_CMD_AUXRD (9 << 12) +#define DPAUX_DP_AUXCTL_TRANSACTREQ_SHIFT (16) +#define DPAUX_DP_AUXCTL_TRANSACTREQ_MASK (0x1 << 16) +#define DPAUX_DP_AUXCTL_TRANSACTREQ_DONE (0 << 16) +#define DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING (1 << 16) +#define DPAUX_DP_AUXCTL_RST_SHIFT (31) +#define DPAUX_DP_AUXCTL_RST_DEASSERT (0 << 31) +#define DPAUX_DP_AUXCTL_RST_ASSERT (1 << 31) +#define DPAUX_DP_AUXSTAT (0x31) +#define DPAUX_DP_AUXSTAT_HPD_STATUS_SHIFT (28) +#define DPAUX_DP_AUXSTAT_HPD_STATUS_UNPLUG (0 << 28) +#define DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED (1 << 28) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_SHIFT (20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_MASK (0xf << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_IDLE (0 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_SYNC (1 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_START1 (2 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_COMMAND (3 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_ADDRESS (4 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_LENGTH (5 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_WRITE1 (6 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_READ1 (7 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_GET_M (8 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_STOP1 (9 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_STOP2 (10 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_REPLY (11 << 20) +#define DPAUX_DP_AUXSTAT_AUXCTL_STATE_CLEANUP (12 << 20) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_SHIFT (16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_MASK (0xf << 16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_ACK (0 << 16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_NACK (1 << 16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER (2 << 16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_I2CNACK (4 << 16) +#define DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER (8 << 16) +#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_SHIFT (11) +#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_NOT_PENDING (0 << 11) +#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING (1 << 11) +#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_SHIFT (10) +#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_NOT_PENDING (0 << 10) +#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING (1 << 10) +#define DPAUX_DP_AUXSTAT_RX_ERROR_SHIFT (9) +#define DPAUX_DP_AUXSTAT_RX_ERROR_NOT_PENDING (0 << 9) +#define DPAUX_DP_AUXSTAT_RX_ERROR_PENDING (1 << 9) +#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_SHIFT (8) +#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_NOT_PENDING (0 << 8) +#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING (1 << 8) +#define DPAUX_DP_AUXSTAT_REPLY_M_SHIFT (0) +#define DPAUX_DP_AUXSTAT_REPLY_M_MASK (0xff << 0) +#define DPAUX_HPD_CONFIG (0x3d) +#define DPAUX_HPD_IRQ_CONFIG (0x41) +#define DPAUX_DP_AUX_CONFIG (0x45) +#define DPAUX_HYBRID_PADCTL (0x49) +#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_SHIFT (15) +#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_DISABLE (0 << 15) +#define DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV_ENABLE (1 << 15) +#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_SHIFT (14) +#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_DISABLE (0 << 14) +#define DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV_ENABLE (1 << 14) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_SHIFT (12) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_DEFAULT_MASK (0x3 << 12) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_60 (0 << 12) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_64 (1 << 12) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 (2 << 12) +#define DPAUX_HYBRID_PADCTL_AUX_CMH_V0_56 (3 << 12) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_SHIFT (8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_DEFAULT_MASK (0x7 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_78 (0 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_60 (1 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_54 (2 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_45 (3 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 (4 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_42 (5 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_39 (6 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_34 (7 << 8) +#define DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT (2) +#define DPAUX_HYBRID_PADCTL_AUX_DRVI_DEFAULT_MASK (0x3f << 2) +#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_SHIFT (1) +#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_DISABLE (0 << 1) +#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE (1 << 1) +#define DPAUX_HYBRID_PADCTL_MODE_SHIFT (0) +#define DPAUX_HYBRID_PADCTL_MODE_AUX (0) +#define DPAUX_HYBRID_PADCTL_MODE_I2C (1) +#define DPAUX_HYBRID_SPARE (0x4d) +#define DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP (0) +#define DPAUX_HYBRID_SPARE_PAD_PWR_POWERDOWN (1) + +#define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME_SHIFT (16) + +/* TODO: figure out which of the NV_ constants are the same as all the other + * display port standard constants. + */ + +#define DP_AUX_DEFER_MAX_TRIES 7 +#define DP_AUX_TIMEOUT_MAX_TRIES 2 +#define DP_POWER_ON_MAX_TRIES 3 +#define DP_CLOCK_RECOVERY_MAX_TRIES 7 +#define DP_CLOCK_RECOVERY_TOT_TRIES 15 + +#define DP_AUX_MAX_BYTES 16 + +#define DP_AUX_TIMEOUT_MS 40 +#define DP_DPCP_RETRY_SLEEP_NS 400 + +static const u32 tegra_dp_vs_regs[][4][4] = { + /* postcursor2 L0 */ + { + /* pre-emphasis: L0, L1, L2, L3 */ + {0x13, 0x19, 0x1e, 0x28}, /* voltage swing: L0 */ + {0x1e, 0x25, 0x2d}, /* L1 */ + {0x28, 0x32}, /* L2 */ + {0x3c}, /* L3 */ + }, + + /* postcursor2 L1 */ + { + {0x12, 0x17, 0x1b, 0x25}, + {0x1c, 0x23, 0x2a}, + {0x25, 0x2f}, + {0x39}, + }, + + /* postcursor2 L2 */ + { + {0x12, 0x16, 0x1a, 0x22}, + {0x1b, 0x20, 0x27}, + {0x24, 0x2d}, + {0x36}, + }, + + /* postcursor2 L3 */ + { + {0x11, 0x14, 0x17, 0x1f}, + {0x19, 0x1e, 0x24}, + {0x22, 0x2a}, + {0x32}, + }, +}; + +static const u32 tegra_dp_pe_regs[][4][4] = { + /* postcursor2 L0 */ + { + /* pre-emphasis: L0, L1, L2, L3 */ + {0x00, 0x09, 0x13, 0x25}, /* voltage swing: L0 */ + {0x00, 0x0f, 0x1e}, /* L1 */ + {0x00, 0x14}, /* L2 */ + {0x00}, /* L3 */ + }, + + /* postcursor2 L1 */ + { + {0x00, 0x0a, 0x14, 0x28}, + {0x00, 0x0f, 0x1e}, + {0x00, 0x14}, + {0x00}, + }, + + /* postcursor2 L2 */ + { + {0x00, 0x0a, 0x14, 0x28}, + {0x00, 0x0f, 0x1e}, + {0x00, 0x14}, + {0x00}, + }, + + /* postcursor2 L3 */ + { + {0x00, 0x0a, 0x14, 0x28}, + {0x00, 0x0f, 0x1e}, + {0x00, 0x14}, + {0x00}, + }, +}; + +static const u32 tegra_dp_pc_regs[][4][4] = { + /* postcursor2 L0 */ + { + /* pre-emphasis: L0, L1, L2, L3 */ + {0x00, 0x00, 0x00, 0x00}, /* voltage swing: L0 */ + {0x00, 0x00, 0x00}, /* L1 */ + {0x00, 0x00}, /* L2 */ + {0x00}, /* L3 */ + }, + + /* postcursor2 L1 */ + { + {0x02, 0x02, 0x04, 0x05}, + {0x02, 0x04, 0x05}, + {0x04, 0x05}, + {0x05}, + }, + + /* postcursor2 L2 */ + { + {0x04, 0x05, 0x08, 0x0b}, + {0x05, 0x09, 0x0b}, + {0x08, 0x0a}, + {0x0b}, + }, + + /* postcursor2 L3 */ + { + {0x05, 0x09, 0x0b, 0x12}, + {0x09, 0x0d, 0x12}, + {0x0b, 0x0f}, + {0x12}, + }, +}; + +static const u32 tegra_dp_tx_pu[][4][4] = { + /* postcursor2 L0 */ + { + /* pre-emphasis: L0, L1, L2, L3 */ + {0x20, 0x30, 0x40, 0x60}, /* voltage swing: L0 */ + {0x30, 0x40, 0x60}, /* L1 */ + {0x40, 0x60}, /* L2 */ + {0x60}, /* L3 */ + }, + + /* postcursor2 L1 */ + { + {0x20, 0x20, 0x30, 0x50}, + {0x30, 0x40, 0x50}, + {0x40, 0x50}, + {0x60}, + }, + + /* postcursor2 L2 */ + { + {0x20, 0x20, 0x30, 0x40}, + {0x30, 0x30, 0x40}, + {0x40, 0x50}, + {0x60}, + }, + + /* postcursor2 L3 */ + { + {0x20, 0x20, 0x20, 0x40}, + {0x30, 0x30, 0x40}, + {0x40, 0x40}, + {0x60}, + }, +}; + +enum { + driveCurrent_Level0 = 0, + driveCurrent_Level1 = 1, + driveCurrent_Level2 = 2, + driveCurrent_Level3 = 3, +}; + +enum { + preEmphasis_Disabled = 0, + preEmphasis_Level1 = 1, + preEmphasis_Level2 = 2, + preEmphasis_Level3 = 3, +}; + +enum { + postCursor2_Level0 = 0, + postCursor2_Level1 = 1, + postCursor2_Level2 = 2, + postCursor2_Level3 = 3, + postCursor2_Supported +}; + +static inline int tegra_dp_is_max_vs(u32 pe, u32 vs) +{ + return (vs < (driveCurrent_Level3 - pe)) ? 0 : 1; +} + +static inline int tegra_dp_is_max_pe(u32 pe, u32 vs) +{ + return (pe < (preEmphasis_Level3 - vs)) ? 0 : 1; +} + +static inline int tegra_dp_is_max_pc(u32 pc) +{ + return (pc < postCursor2_Level3) ? 0 : 1; +} + +/* the +10ms is the time for power rail going up from 10-90% or + 90%-10% on powerdown */ +/* Time from power-rail is turned on and aux/12c-over-aux is available */ +#define EDP_PWR_ON_TO_AUX_TIME_MS (200+10) +/* Time from power-rail is turned on and MainLink is available for LT */ +#define EDP_PWR_ON_TO_ML_TIME_MS (200+10) +/* Time from turning off power to turn-it on again (does not include post + poweron time) */ +#define EDP_PWR_OFF_TO_ON_TIME_MS (500+10) + +struct tegra_dc_dp_data { + struct tegra_dc *dc; + struct tegra_dc_sor_data sor; + void *aux_base; + struct tegra_dc_dp_link_config link_cfg; + u8 revision; + int enabled; +}; + + +/* DPCD definitions */ +/* you know, all the vendors pick their own set of defines. + * All of them. + * FIXME so we can use the ones in include/device/drm_dp_helper.h + */ +#define NV_DPCD_REV (0x00000000) +#define NV_DPCD_REV_MAJOR_SHIFT (4) +#define NV_DPCD_REV_MAJOR_MASK (0xf << 4) +#define NV_DPCD_REV_MINOR_SHIFT (0) +#define NV_DPCD_REV_MINOR_MASK (0xf) +#define NV_DPCD_MAX_LINK_BANDWIDTH (0x00000001) +#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_1_62_GPBS (0x00000006) +#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_2_70_GPBS (0x0000000a) +#define NV_DPCD_MAX_LINK_BANDWIDTH_VAL_5_40_GPBS (0x00000014) +#define NV_DPCD_MAX_LANE_COUNT (0x00000002) +#define NV_DPCD_MAX_LANE_COUNT_MASK (0x1f) +#define NV_DPCD_MAX_LANE_COUNT_LANE_1 (0x00000001) +#define NV_DPCD_MAX_LANE_COUNT_LANE_2 (0x00000002) +#define NV_DPCD_MAX_LANE_COUNT_LANE_4 (0x00000004) +#define NV_DPCD_MAX_LANE_COUNT_TPS3_SUPPORTED_YES (0x00000001 << 6) +#define NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_NO (0x00000000 << 7) +#define NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES (0x00000001 << 7) +#define NV_DPCD_MAX_DOWNSPREAD (0x00000003) +#define NV_DPCD_MAX_DOWNSPREAD_VAL_NONE (0x00000000) +#define NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT (0x00000001) +#define NV_DPCD_MAX_DOWNSPREAD_NO_AUX_HANDSHAKE_LT_F (0x00000000 << 6) +#define NV_DPCD_MAX_DOWNSPREAD_NO_AUX_HANDSHAKE_LT_T (0x00000001 << 6) +#define NV_DPCD_EDP_CONFIG_CAP (0x0000000D) +#define NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_NO (0x00000000) +#define NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES (0x00000001) +#define NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_NO (0x00000000 << 1) +#define NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES (0x00000001 << 1) +#define NV_DPCD_TRAINING_AUX_RD_INTERVAL (0x0000000E) +#define NV_DPCD_LINK_BANDWIDTH_SET (0x00000100) +#define NV_DPCD_LANE_COUNT_SET (0x00000101) +#define NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_F (0x00000000 << 7) +#define NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_T (0x00000001 << 7) +#define NV_DPCD_TRAINING_PATTERN_SET (0x00000102) +#define NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK 0x3 +#define NV_DPCD_TRAINING_PATTERN_SET_TPS_NONE (0x00000000) +#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1 (0x00000001) +#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP2 (0x00000002) +#define NV_DPCD_TRAINING_PATTERN_SET_TPS_TP3 (0x00000003) +#define NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F (0x00000000 << 5) +#define NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T (0x00000001 << 5) +#define NV_DPCD_TRAINING_LANE0_SET (0x00000103) +#define NV_DPCD_TRAINING_LANE1_SET (0x00000104) +#define NV_DPCD_TRAINING_LANE2_SET (0x00000105) +#define NV_DPCD_TRAINING_LANE3_SET (0x00000106) +#define NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT 0 +#define NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T (0x00000001 << 2) +#define NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_F (0x00000000 << 2) +#define NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3 +#define NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T (0x00000001 << 5) +#define NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_F (0x00000000 << 5) +#define NV_DPCD_DOWNSPREAD_CTRL (0x00000107) +#define NV_DPCD_DOWNSPREAD_CTRL_SPREAD_AMP_NONE (0x00000000 << 4) +#define NV_DPCD_DOWNSPREAD_CTRL_SPREAD_AMP_LT_0_5 (0x00000001 << 4) +#define NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET (0x00000108) +#define NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET_ANSI_8B10B 1 +#define NV_DPCD_EDP_CONFIG_SET (0x0000010A) +#define NV_DPCD_EDP_CONFIG_SET_ASC_RESET_DISABLE (0x00000000) +#define NV_DPCD_EDP_CONFIG_SET_ASC_RESET_ENABLE (0x00000001) +#define NV_DPCD_EDP_CONFIG_SET_FRAMING_CHANGE_DISABLE (0x00000000 << 1) +#define NV_DPCD_EDP_CONFIG_SET_FRAMING_CHANGE_ENABLE (0x00000001 << 1) +#define NV_DPCD_TRAINING_LANE0_1_SET2 (0x0000010F) +#define NV_DPCD_TRAINING_LANE2_3_SET2 (0x00000110) +#define NV_DPCD_LANEX_SET2_PC2_SHIFT 0 +#define NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T (0x00000001 << 2) +#define NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_F (0x00000000 << 2) +#define NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT 4 +#define NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T (0x00000001 << 6) +#define NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_F (0x00000000 << 6) +#define NV_DPCD_SINK_COUNT (0x00000200) +#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR (0x00000201) +#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_AUTO_TEST_NO (0x00000000 << 1) +#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_AUTO_TEST_YES (0x00000001 << 1) +#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_CP_NO (0x00000000 << 2) +#define NV_DPCD_DEVICE_SERVICE_IRQ_VECTOR_CP_YES (0x00000001 << 2) +#define NV_DPCD_LANE0_1_STATUS (0x00000202) +#define NV_DPCD_LANE2_3_STATUS (0x00000203) +#define NV_DPCD_STATUS_LANEX_CR_DONE_SHIFT 0 +#define NV_DPCD_STATUS_LANEX_CR_DONE_NO (0x00000000) +#define NV_DPCD_STATUS_LANEX_CR_DONE_YES (0x00000001) +#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT 1 +#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_NO (0x00000000 << 1) +#define NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_YES (0x00000001 << 1) +#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT 2 +#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_NO (0x00000000 << 2) +#define NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_YES (0x00000001 << 2) +#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_SHIFT 4 +#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_NO (0x00000000 << 4) +#define NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES (0x00000001 << 4) +#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT 5 +#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_NO (0x00000000 << 5) +#define NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES (0x00000001 << 5) +#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT 6 +#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_NO (0x00000000 << 6) +#define NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES (0x00000001 << 6) +#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED (0x00000204) +#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_NO (0x00000000) +#define NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES (0x00000001) +#define NV_DPCD_LANE0_1_ADJUST_REQ (0x00000206) +#define NV_DPCD_LANE2_3_ADJUST_REQ (0x00000207) +#define NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT 0 +#define NV_DPCD_ADJUST_REQ_LANEX_DC_MASK 0x3 +#define NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT 2 +#define NV_DPCD_ADJUST_REQ_LANEX_PE_MASK (0x3 << 2) +#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT 4 +#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK (0x3 << 4) +#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT 6 +#define NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK (0x3 << 6) +#define NV_DPCD_ADJUST_REQ_POST_CURSOR2 (0x0000020C) +#define NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK 0x3 +#define NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(i) (i*2) +#define NV_DPCD_TEST_REQUEST (0x00000218) +#define NV_DPCD_SOURCE_IEEE_OUI (0x00000300) +#define NV_DPCD_SINK_IEEE_OUI (0x00000400) +#define NV_DPCD_BRANCH_IEEE_OUI (0x00000500) +#define NV_DPCD_SET_POWER (0x00000600) +#define NV_DPCD_SET_POWER_VAL_RESERVED (0x00000000) +#define NV_DPCD_SET_POWER_VAL_D0_NORMAL (0x00000001) +#define NV_DPCD_SET_POWER_VAL_D3_PWRDWN (0x00000002) +#define NV_DPCD_HDCP_BKSV_OFFSET (0x00068000) +#define NV_DPCD_HDCP_RPRIME_OFFSET (0x00068005) +#define NV_DPCD_HDCP_AKSV_OFFSET (0x00068007) +#define NV_DPCD_HDCP_AN_OFFSET (0x0006800C) +#define NV_DPCD_HDCP_VPRIME_OFFSET (0x00068014) +#define NV_DPCD_HDCP_BCAPS_OFFSET (0x00068028) +#define NV_DPCD_HDCP_BSTATUS_OFFSET (0x00068029) +#define NV_DPCD_HDCP_BINFO_OFFSET (0x0006802A) +#define NV_DPCD_HDCP_KSV_FIFO_OFFSET (0x0006802C) +#define NV_DPCD_HDCP_AINFO_OFFSET (0x0006803B) +#endif /* __SOC_NVIDIA_TEGRA_DISPLAYPORT_H__ */ diff --git a/src/soc/nvidia/tegra/gpio.c b/src/soc/nvidia/tegra/gpio.c new file mode 100644 index 0000000000..009334f74c --- /dev/null +++ b/src/soc/nvidia/tegra/gpio.c @@ -0,0 +1,223 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinmux.h" + +static void __gpio_input(gpio_t gpio, u32 pull) +{ + u32 pinmux_config = PINMUX_INPUT_ENABLE | pull; + + gpio_set_int_enable(gpio, 0); + gpio_set_out_enable(gpio, 0); + gpio_set_mode(gpio, GPIO_MODE_GPIO); + pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, pinmux_config); +} + +static void __gpio_output(gpio_t gpio, int value, u32 od) +{ + gpio_set_int_enable(gpio, 0); + gpio_set(gpio, value); + gpio_set_out_enable(gpio, 1); + gpio_set_mode(gpio, GPIO_MODE_GPIO); + pinmux_set_config(gpio >> GPIO_PINMUX_SHIFT, PINMUX_PULL_NONE | od); +} + +static const struct gpio_bank *gpio_banks = (void *)TEGRA_GPIO_BASE; + +static u32 gpio_read_port(int index, size_t offset) +{ + int bank = index / GPIO_GPIOS_PER_BANK; + int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT; + + return read32((u8 *)&gpio_banks[bank] + offset + + port * sizeof(u32)); +} + +static void gpio_write_port(int index, size_t offset, u32 mask, u32 value) +{ + int bank = index / GPIO_GPIOS_PER_BANK; + int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT; + + u32 reg = read32((u8 *)&gpio_banks[bank] + offset + + port * sizeof(u32)); + u32 new_reg = (reg & ~mask) | (value & mask); + + if (new_reg != reg) { + write32(new_reg, (u8 *)&gpio_banks[bank] + offset + + port * sizeof(u32)); + } +} + +void gpio_set_mode(gpio_t gpio, enum gpio_mode mode) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, config), + 1 << bit, mode ? (1 << bit) : 0); +} + +int gpio_get_mode(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, config)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_lock(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, config), + 1 << bit, 1 << bit); +} + +int gpio_get_lock(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, config)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_out_enable(gpio_t gpio, int enable) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, out_enable), + 1 << bit, enable ? (1 << bit) : 0); +} + +int gpio_get_out_enable(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, out_enable)); + return (port & (1 << bit)) != 0; +} + +void gpio_set(gpio_t gpio, int value) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, out_value), + 1 << bit, value ? (1 << bit) : 0); +} + +int gpio_get_out_value(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, out_value)); + return (port & (1 << bit)) != 0; +} + +int gpio_get(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, in_value)); + return (port & (1 << bit)) != 0; +} + +int gpio_get_int_status(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, int_status)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_int_enable(gpio_t gpio, int enable) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, int_enable), + 1 << bit, enable ? (1 << bit) : 0); +} + +int gpio_get_int_enable(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, int_enable)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_int_level(gpio_t gpio, int high_rise, int edge, int delta) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 value = (high_rise ? (0x000001 << bit) : 0) | + (edge ? (0x000100 << bit) : 0) | + (delta ? (0x010000 << bit) : 0); + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, config), + 0x010101 << bit, value); +} + +void gpio_get_int_level(gpio_t gpio, int *high_rise, int *edge, int *delta) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + u32 port = gpio_read_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, int_level)); + *high_rise = ((port & (0x000001 << bit)) != 0); + *edge = ((port & (0x000100 << bit)) != 0); + *delta = ((port & (0x010000 << bit)) != 0); +} + +void gpio_set_int_clear(gpio_t gpio) +{ + int bit = gpio % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio & ((1 << GPIO_PINMUX_SHIFT) - 1), + offsetof(struct gpio_bank, int_clear), + 1 << bit, 1 << bit); +} + +void gpio_input_pulldown(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_DOWN); +} + +void gpio_input_pullup(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_UP); +} + +void gpio_input(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_NONE); +} + +void gpio_output(gpio_t gpio, int value) +{ + __gpio_output(gpio, value, 0); +} + +void gpio_output_open_drain(gpio_t gpio, int value) +{ + __gpio_output(gpio, value, PINMUX_OPEN_DRAIN); +} diff --git a/src/soc/nvidia/tegra/gpio.h b/src/soc/nvidia/tegra/gpio.h new file mode 100644 index 0000000000..72c7179f7c --- /dev/null +++ b/src/soc/nvidia/tegra/gpio.h @@ -0,0 +1,111 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_GPIO_H__ +#define __SOC_NVIDIA_TEGRA_GPIO_H__ + +#include + +#include "pinmux.h" + +typedef u32 gpio_t; + +#define GPIO_PINMUX_SHIFT 16 +#define GPIO(name) ((gpio_t)(GPIO_##name##_INDEX | \ + (PINMUX_GPIO_##name << GPIO_PINMUX_SHIFT))) + +/* Functions to modify specific GPIO control values. */ + +enum gpio_mode { + GPIO_MODE_SPIO = 0, + GPIO_MODE_GPIO = 1 +}; +void gpio_set_mode(gpio_t gpio, enum gpio_mode); +int gpio_get_mode(gpio_t gpio); + +// Lock a GPIO with extreme caution since they can't be unlocked. +void gpio_set_lock(gpio_t gpio); +int gpio_get_lock(gpio_t gpio); + +void gpio_set_out_enable(gpio_t gpio, int enable); +int gpio_get_out_enable(gpio_t gpio); + +int gpio_get_out_value(gpio_t gpio); + +int gpio_get_int_status(gpio_t gpio); + +void gpio_set_int_enable(gpio_t gpio, int enable); +int gpio_get_int_enable(gpio_t gpio); + +void gpio_set_int_level(gpio_t gpio, int high_rise, int edge, int delta); +void gpio_get_int_level(gpio_t gpio, int *high_rise, int *edge, int *delta); + +void gpio_set_int_clear(gpio_t gpio); + +void gpio_output_open_drain(gpio_t gpio, int value); + +/* Hardware definitions. */ + +enum { + GPIO_GPIOS_PER_PORT = 8, + GPIO_PORTS_PER_BANK = 4, + GPIO_BANKS = 8, + + GPIO_GPIOS_PER_BANK = GPIO_GPIOS_PER_PORT * GPIO_PORTS_PER_BANK, + GPIO_GPIOS = GPIO_BANKS * GPIO_GPIOS_PER_BANK +}; + +static inline int gpio_index_to_bank(int index) +{ + return index / GPIO_GPIOS_PER_BANK; +} + +static inline int gpio_index_to_port(int index) +{ + return (index % GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT; +} + +static inline int gpio_to_bit(int index) +{ + return index % GPIO_GPIOS_PER_PORT; +} + +struct gpio_bank { + // Values + u32 config[GPIO_PORTS_PER_BANK]; + u32 out_enable[GPIO_PORTS_PER_BANK]; + u32 out_value[GPIO_PORTS_PER_BANK]; + u32 in_value[GPIO_PORTS_PER_BANK]; + u32 int_status[GPIO_PORTS_PER_BANK]; + u32 int_enable[GPIO_PORTS_PER_BANK]; + u32 int_level[GPIO_PORTS_PER_BANK]; + u32 int_clear[GPIO_PORTS_PER_BANK]; + + // Masks + u32 config_mask[GPIO_PORTS_PER_BANK]; + u32 out_enable_mask[GPIO_PORTS_PER_BANK]; + u32 out_value_mask[GPIO_PORTS_PER_BANK]; + u32 in_value_mask[GPIO_PORTS_PER_BANK]; + u32 int_status_mask[GPIO_PORTS_PER_BANK]; + u32 int_enable_mask[GPIO_PORTS_PER_BANK]; + u32 int_level_mask[GPIO_PORTS_PER_BANK]; + u32 int_clear_mask[GPIO_PORTS_PER_BANK]; +}; + +#endif /* __SOC_NVIDIA_TEGRA_GPIO_H__ */ diff --git a/src/soc/nvidia/tegra/i2c.c b/src/soc/nvidia/tegra/i2c.c new file mode 100644 index 0000000000..6f9142ca6d --- /dev/null +++ b/src/soc/nvidia/tegra/i2c.c @@ -0,0 +1,212 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "i2c.h" + +static void do_bus_clear(int bus) +{ + struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus]; + struct tegra_i2c_regs * const regs = info->base; + uint32_t bc; + int i, timeout_ms = 10; + + // BUS CLEAR regs (from TRM): + // 1. Reset the I2C controller (already done) + // 2. Set the # of clock pulses required (using default of 9) + // 3. Select STOP condition (using default of 1 = STOP) + // 4. Set TERMINATE condition (1 = IMMEDIATE) + bc = read32(®s->bus_clear_config); + bc |= I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE; + write32(bc, ®s->bus_clear_config); + // 4.1 Set MSTR_CONFIG_LOAD and wait for clear + write32(I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE, ®s->config_load); + for (i = 0; i < timeout_ms * 10 && (read32(®s->config_load) & + I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE); i++) { + printk(BIOS_DEBUG, "%s: wait for MSTR_CONFIG_LOAD to clear\n", + __func__); + udelay(100); + } + // 5. Set ENABLE to start the bus clear op + write32(bc | I2C_BUS_CLEAR_CONFIG_BC_ENABLE, ®s->bus_clear_config); + for (i = 0; i < timeout_ms * 10 && (read32(®s->bus_clear_config) & + I2C_BUS_CLEAR_CONFIG_BC_ENABLE); i++) { + printk(BIOS_DEBUG, "%s: wait for bus clear completion\n", + __func__); + udelay(100); + } +} + +static int tegra_i2c_send_recv(int bus, int read, + uint32_t *headers, int header_words, + uint8_t *data, int data_len) +{ + struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus]; + struct tegra_i2c_regs * const regs = info->base; + + while (data_len) { + uint32_t status = read32(®s->fifo_status); + int tx_empty = status & I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK; + tx_empty >>= I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT; + int rx_full = status & I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_MASK; + rx_full >>= I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT; + + while (header_words && tx_empty) { + write32(*headers++, ®s->tx_packet_fifo); + header_words--; + tx_empty--; + } + + if (!header_words) { + if (read) { + while (data_len && rx_full) { + uint32_t word = read32(®s->rx_fifo); + int todo = MIN(data_len, sizeof(word)); + + memcpy(data, &word, todo); + data_len -= todo; + data += sizeof(word); + rx_full--; + } + } else { + while (data_len && tx_empty) { + uint32_t word; + int todo = MIN(data_len, sizeof(word)); + + memcpy(&word, data, todo); + write32(word, ®s->tx_packet_fifo); + data_len -= todo; + data += sizeof(word); + tx_empty--; + } + } + } + + uint32_t transfer_status = + read32(®s->packet_transfer_status); + + if (transfer_status & I2C_PKT_STATUS_NOACK_ADDR) { + printk(BIOS_ERR, + "%s: The address was not acknowledged.\n", + __func__); + info->reset_func(info->reset_bit); + i2c_init(bus); + return -1; + } else if (transfer_status & I2C_PKT_STATUS_NOACK_DATA) { + printk(BIOS_ERR, + "%s: The data was not acknowledged.\n", + __func__); + info->reset_func(info->reset_bit); + i2c_init(bus); + return -1; + } else if (transfer_status & I2C_PKT_STATUS_ARB_LOST) { + printk(BIOS_ERR, + "%s: Lost arbitration.\n", + __func__); + info->reset_func(info->reset_bit); + + /* Use Tegra bus clear registers to unlock SDA */ + do_bus_clear(bus); + + /* re-init i2c controller */ + i2c_init(bus); + + /* Return w/error, let caller decide what to do */ + return -1; + } + } + + return 0; +} + +static int tegra_i2c_request(int bus, unsigned chip, int cont, int restart, + int read, void *data, int data_len) +{ + uint32_t headers[3]; + + if (restart && cont) { + printk(BIOS_ERR, "%s: Repeat start and continue xfer are " + "mutually exclusive.\n", __func__); + return -1; + } + + headers[0] = (0 << IOHEADER_PROTHDRSZ_SHIFT) | + (1 << IOHEADER_PKTID_SHIFT) | + (bus << IOHEADER_CONTROLLER_ID_SHIFT) | + IOHEADER_PROTOCOL_I2C | IOHEADER_PKTTYPE_REQUEST; + + headers[1] = (data_len - 1) << IOHEADER_PAYLOADSIZE_SHIFT; + + uint32_t slave_addr = (chip << 1) | (read ? 1 : 0); + headers[2] = IOHEADER_I2C_REQ_ADDR_MODE_7BIT | + (slave_addr << IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT); + if (read) + headers[2] |= IOHEADER_I2C_REQ_READ; + if (restart) + headers[2] |= IOHEADER_I2C_REQ_REPEAT_START; + if (cont) + headers[2] |= IOHEADER_I2C_REQ_CONTINUE_XFER; + + return tegra_i2c_send_recv(bus, read, headers, ARRAY_SIZE(headers), + data, data_len); +} + +static int i2c_transfer_segment(unsigned bus, unsigned chip, int restart, + int read, void *buf, int len) +{ + const uint32_t max_payload = + (IOHEADER_PAYLOADSIZE_MASK + 1) >> IOHEADER_PAYLOADSIZE_SHIFT; + + while (len) { + int todo = MIN(len, max_payload); + int cont = (todo < len); + if (tegra_i2c_request(bus, chip, cont, restart, + read, buf, todo)) + return -1; + len -= todo; + buf += todo; + } + return 0; +} + +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) +{ + struct i2c_seg *seg = segments; + + int i; + for (i = 0; i < count; seg++, i++) { + if (i2c_transfer_segment(bus, seg->chip, i < count - 1, + seg->read, seg->buf, seg->len)) + return -1; + } + return 0; +} + +void i2c_init(unsigned bus) +{ + struct tegra_i2c_regs * const regs = tegra_i2c_info[bus].base; + + write32(I2C_CNFG_PACKET_MODE_EN, ®s->cnfg); +} diff --git a/src/soc/nvidia/tegra/i2c.h b/src/soc/nvidia/tegra/i2c.h new file mode 100644 index 0000000000..9d7de14a1e --- /dev/null +++ b/src/soc/nvidia/tegra/i2c.h @@ -0,0 +1,175 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_I2C_H__ +#define __SOC_NVIDIA_TEGRA_I2C_H__ + +#include + +void i2c_init(unsigned bus); +void tegra_software_i2c_init(unsigned bus); +void tegra_software_i2c_disable(unsigned bus); + +enum { + /* Word 0 */ + IOHEADER_PROTHDRSZ_SHIFT = 28, + IOHEADER_PROTHDRSZ_MASK = 0x3 << IOHEADER_PROTHDRSZ_SHIFT, + IOHEADER_PKTID_SHIFT = 16, + IOHEADER_PKTID_MASK = 0xff << IOHEADER_PKTID_SHIFT, + IOHEADER_CONTROLLER_ID_SHIFT = 12, + IOHEADER_CONTROLLER_ID_MASK = 0xf << IOHEADER_CONTROLLER_ID_SHIFT, + IOHEADER_PROTOCOL_SHIFT = 4, + IOHEADER_PROTOCOL_MASK = 0xf << IOHEADER_PROTOCOL_SHIFT, + IOHEADER_PROTOCOL_I2C = 1 << IOHEADER_PROTOCOL_SHIFT, + IOHEADER_PKTTYPE_SHIFT = 0, + IOHEADER_PKTTYPE_MASK = 0x7 << IOHEADER_PKTTYPE_SHIFT, + IOHEADER_PKTTYPE_REQUEST = 0 << IOHEADER_PKTTYPE_SHIFT, + IOHEADER_PKTTYPE_RESPONSE = 1 << IOHEADER_PKTTYPE_SHIFT, + IOHEADER_PKTTYPE_INTERRUPT = 2 << IOHEADER_PKTTYPE_SHIFT, + IOHEADER_PKTTYPE_STOP = 3 << IOHEADER_PKTTYPE_SHIFT, + + /* Word 1 */ + IOHEADER_PAYLOADSIZE_SHIFT = 0, + IOHEADER_PAYLOADSIZE_MASK = 0xfff << IOHEADER_PAYLOADSIZE_SHIFT +}; + +enum { + IOHEADER_I2C_REQ_RESP_FREQ_MASK = 0x1 << 25, + IOHEADER_I2C_REQ_RESP_FREQ_END = 0 << 25, + IOHEADER_I2C_REQ_RESP_FREQ_EACH = 1 << 25, + IOHEADER_I2C_REQ_RESP_ENABLE = 0x1 << 24, + IOHEADER_I2C_REQ_HS_MODE = 0x1 << 22, + IOHEADER_I2C_REQ_CONTINUE_ON_NACK = 0x1 << 21, + IOHEADER_I2C_REQ_SEND_START_BYTE = 0x1 << 20, + IOHEADER_I2C_REQ_READ = 0x1 << 19, + IOHEADER_I2C_REQ_ADDR_MODE_MASK = 0x1 << 18, + IOHEADER_I2C_REQ_ADDR_MODE_7BIT = 0 << 18, + IOHEADER_I2C_REQ_ADDR_MODE_10BIT = 1 << 18, + IOHEADER_I2C_REQ_IE = 0x1 << 17, + IOHEADER_I2C_REQ_REPEAT_START = 0x1 << 16, + IOHEADER_I2C_REQ_STOP = 0x0 << 16, + IOHEADER_I2C_REQ_CONTINUE_XFER = 0x1 << 15, + IOHEADER_I2C_REQ_HS_MASTER_ADDR_SHIFT = 12, + IOHEADER_I2C_REQ_HS_MASTER_ADDR_MASK = + 0x7 << IOHEADER_I2C_REQ_HS_MASTER_ADDR_SHIFT, + IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT = 0, + IOHEADER_I2C_REQ_SLAVE_ADDR_MASK = + 0x3ff << IOHEADER_I2C_REQ_SLAVE_ADDR_SHIFT +}; + +enum { + I2C_CNFG_MSTR_CLR_BUS_ON_TIMEOUT = 0x1 << 15, + I2C_CNFG_DEBOUNCE_CNT_SHIFT = 12, + I2C_CNFG_DEBOUNCE_CNT_MASK = 0x7 << I2C_CNFG_DEBOUNCE_CNT_SHIFT, + I2C_CNFG_NEW_MASTER_FSM = 0x1 << 11, + I2C_CNFG_PACKET_MODE_EN = 0x1 << 10, + I2C_CNFG_SEND = 0x1 << 9, + I2C_CNFG_NOACK = 0x1 << 8, + I2C_CNFG_CMD2 = 0x1 << 7, + I2C_CNFG_CMD1 = 0x1 << 6, + I2C_CNFG_START = 0x1 << 5, + I2C_CNFG_SLV2_SHIFT = 4, + I2C_CNFG_SLV2_MASK = 0x1 << I2C_CNFG_SLV2_SHIFT, + I2C_CNFG_LENGTH_SHIFT = 1, + I2C_CNFG_LENGTH_MASK = 0x7 << I2C_CNFG_LENGTH_SHIFT, + I2C_CNFG_A_MOD = 0x1 << 0, +}; + +enum { + I2C_PKT_STATUS_COMPLETE = 0x1 << 24, + I2C_PKT_STATUS_PKT_ID_SHIFT = 16, + I2C_PKT_STATUS_PKT_ID_MASK = 0xff << I2C_PKT_STATUS_PKT_ID_SHIFT, + I2C_PKT_STATUS_BYTENUM_SHIFT = 4, + I2C_PKT_STATUS_BYTENUM_MASK = 0xfff << I2C_PKT_STATUS_BYTENUM_SHIFT, + I2C_PKT_STATUS_NOACK_ADDR = 0x1 << 3, + I2C_PKT_STATUS_NOACK_DATA = 0x1 << 2, + I2C_PKT_STATUS_ARB_LOST = 0x1 << 1, + I2C_PKT_STATUS_BUSY = 0x1 << 0 +}; + +enum { + I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT = 4, + I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK = + 0xf << I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_SHIFT, + I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT = 0, + I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_MASK = + 0xf << I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT +}; + +enum { + I2C_BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD_SHIFT = 16, + I2C_BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD_MASK = + 0xff << I2C_BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD_SHIFT, + I2C_BUS_CLEAR_CONFIG_BC_STOP_COND_STOP = 0x1 << 2, + I2C_BUS_CLEAR_CONFIG_BC_TERMINATE_IMMEDIATE = 0x1 << 1, + I2C_BUS_CLEAR_CONFIG_BC_ENABLE = 0x1 << 0, + + I2C_BUS_CLEAR_STATUS_CLEARED = 0x1 << 0, + + I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE = 0x1 << 0 +}; + +struct tegra_i2c_bus_info { + void *base; + uint32_t reset_bit; + void (*reset_func)(u32 bit); +}; + +extern struct tegra_i2c_bus_info tegra_i2c_info[]; + +struct tegra_i2c_regs { + uint32_t cnfg; + uint32_t cmd_addr0; + uint32_t cmd_addr1; + uint32_t cmd_data1; + uint32_t cmd_data2; + uint8_t _rsv0[8]; + uint32_t status; + uint32_t sl_cnfg; + uint32_t sl_rcvd; + uint32_t sl_status; + uint32_t sl_addr1; + uint32_t sl_addr2; + uint32_t tlow_sext; + uint8_t _rsv1[4]; + uint32_t sl_delay_count; + uint32_t sl_int_mask; + uint32_t sl_int_source; + uint32_t sl_int_set; + uint8_t _rsv2[4]; + uint32_t tx_packet_fifo; + uint32_t rx_fifo; + uint32_t packet_transfer_status; + uint32_t fifo_control; + uint32_t fifo_status; + uint32_t interrupt_mask; + uint32_t interrupt_status; + uint32_t clk_divisor; + uint32_t interrupt_source; + uint32_t interrupt_set; + uint32_t slv_tx_packet_fifo; + uint32_t slv_rx_fifo; + uint32_t slv_packet_status; + uint32_t bus_clear_config; + uint32_t bus_clear_status; + uint32_t config_load; +}; +check_member(tegra_i2c_regs, config_load, 0x8C); + +#endif /* __SOC_NVIDIA_TEGRA_I2C_H__ */ diff --git a/src/soc/nvidia/tegra/pingroup.c b/src/soc/nvidia/tegra/pingroup.c new file mode 100644 index 0000000000..858cb44e34 --- /dev/null +++ b/src/soc/nvidia/tegra/pingroup.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "pingroup.h" + +static uint32_t *pingroup_regs = (void *)TEGRA_APB_PINGROUP_BASE; + +void pingroup_set_config(int group_index, uint32_t config) +{ + write32(config, &pingroup_regs[group_index]); +} + +uint32_t pingroup_get_config(int group_index) +{ + return read32(&pingroup_regs[group_index]); +} diff --git a/src/soc/nvidia/tegra/pingroup.h b/src/soc/nvidia/tegra/pingroup.h new file mode 100644 index 0000000000..f04b66541d --- /dev/null +++ b/src/soc/nvidia/tegra/pingroup.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_PINGROUP_H__ +#define __SOC_NVIDIA_TEGRA_PINGROUP_H__ + +#include + +void pingroup_set_config(int group_index, uint32_t config); +uint32_t pingroup_get_config(int group_index); + +enum { + PINGROUP_HSM = 1 << 2, + PINGROUP_SCHMT = 1 << 3, + PINGROUP_LPMD_SHIFT = 4, + PINGROUP_LPMD_MASK = 3 << 4, + PINGROUP_DRVDN_SHIFT = 12, + PINGROUP_DRVDN_MASK = 0x7f << 12, + PINGROUP_DRVUP_SHIFT = 20, + PINGROUP_DRVUP_MASK = 0x7f << 20, + PINGROUP_SLWR_SHIFT = 28, + PINGROUP_SLWR_MASK = 0x3 << 28, + PINGROUP_SLWF_SHIFT = 30, + PINGROUP_SLWF_MASK = 0x3 << 30 +}; + +#endif /* __SOC_NVIDIA_TEGRA_PINGROUP_H__ */ diff --git a/src/soc/nvidia/tegra/pinmux.c b/src/soc/nvidia/tegra/pinmux.c new file mode 100644 index 0000000000..6e4b3ff195 --- /dev/null +++ b/src/soc/nvidia/tegra/pinmux.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "pinmux.h" + +static uint32_t *pinmux_regs = (void *)TEGRA_APB_PINMUX_BASE; + +void pinmux_set_config(int pin_index, uint32_t config) +{ + write32(config, &pinmux_regs[pin_index]); +} + +uint32_t pinmux_get_config(int pin_index) +{ + return read32(&pinmux_regs[pin_index]); +} diff --git a/src/soc/nvidia/tegra/pinmux.h b/src/soc/nvidia/tegra/pinmux.h new file mode 100644 index 0000000000..e42135d9a4 --- /dev/null +++ b/src/soc/nvidia/tegra/pinmux.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_PINMUX_H__ +#define __SOC_NVIDIA_TEGRA_PINMUX_H__ + +#include + +void pinmux_set_config(int pin_index, uint32_t config); +uint32_t pinmux_get_config(int pin_index); + +enum { + PINMUX_FUNC_MASK = 3 << 0, + + PINMUX_PULL_MASK = 3 << 2, + PINMUX_PULL_NONE = 0 << 2, + PINMUX_PULL_DOWN = 1 << 2, + PINMUX_PULL_UP = 2 << 2, + + PINMUX_TRISTATE = 1 << 4, + PINMUX_INPUT_ENABLE = 1 << 5, + PINMUX_OPEN_DRAIN = 1 << 6, + PINMUX_LOCK = 1 << 7, + PINMUX_IO_RESET = 1 << 8, + PINMUX_RCV_SEL = 1 << 9 +}; + +#endif /* __SOC_NVIDIA_TEGRA_PINMUX_H__ */ diff --git a/src/cpu/samsung/exynos5-common/adc.h b/src/soc/nvidia/tegra/pwm.h similarity index 61% rename from src/cpu/samsung/exynos5-common/adc.h rename to src/soc/nvidia/tegra/pwm.h index 64f4813495..eea5b07b91 100644 --- a/src/cpu/samsung/exynos5-common/adc.h +++ b/src/soc/nvidia/tegra/pwm.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2010 Samsung Electronics - * Minkyu Kang - * MyungJoo Ham + * Copyright 2014 Google Inc. + * (C) Copyright 2010 + * NVIDIA Corporation * * See file CREDITS for list of people who contributed to this * project. @@ -22,21 +22,22 @@ * MA 02111-1307 USA */ -#ifndef __ASM_ARM_ARCH_COMMON_ADC_H_ -#define __ASM_ARM_ARCH_COMMON_ADC_H_ +#ifndef __SOC_NVIDIA_TEGRA_PWM_H +#define __SOC_NVIDIA_TEGRA_PWM_H -#ifndef __ASSEMBLER__ -struct s5p_adc { - unsigned int adccon; - unsigned int adctsc; - unsigned int adcdly; - unsigned int adcdat0; - unsigned int adcdat1; - unsigned int adcupdn; - unsigned int adcclrint; - unsigned int adcmux; - unsigned int adcclrintpndnup; +#include + +/* Register definitions for the Tegra pwm controller */ +#define NV_PWM_CSR_ENABLE_SHIFT 31 +#define NV_PWM_CSR_PULSE_WIDTH_SHIFT 16 + +struct pwm_reg { + u32 csr; + u32 rsvd[3]; }; -#endif -#endif /* __ASM_ARM_ARCH_COMMON_ADC_H_ */ +struct pwm_controller { + struct pwm_reg pwm[4]; +}; + +#endif /* __SOC_NVIDIA_TEGRA_PWM_H */ diff --git a/src/soc/nvidia/tegra/software_i2c.c b/src/soc/nvidia/tegra/software_i2c.c new file mode 100644 index 0000000000..d1172bcde6 --- /dev/null +++ b/src/soc/nvidia/tegra/software_i2c.c @@ -0,0 +1,96 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +#include "i2c.h" + +static struct { + int pinmux_func; + gpio_t sda; + gpio_t scl; +} pins[] = { + [0]{.pinmux_func = PINMUX_GEN1_I2C_SCL_FUNC_I2C1, + .sda = GPIO(C5), .scl = GPIO(C4)}, + [1]{.pinmux_func = PINMUX_GEN2_I2C_SCL_FUNC_I2C2, + .sda = GPIO(T6), .scl = GPIO(T5)}, + [2]{.pinmux_func = PINMUX_CAM_I2C_SCL_FUNC_I2C3, + .sda = GPIO(BB2), .scl = GPIO(BB1)}, + [3]{.pinmux_func = PINMUX_DDC_SCL_FUNC_I2C4, + .sda = GPIO(V5), .scl = GPIO(V4)}, + [4]{.pinmux_func = PINMUX_PWR_I2C_SCL_FUNC_I2CPMU, + .sda = GPIO(Z7), .scl = GPIO(Z6)}, +}; + +static void tegra_set_sda(unsigned bus, int high) +{ + if (high) + gpio_input_pullup(pins[bus].sda); + else + gpio_output(pins[bus].sda, 0); +} + +static void tegra_set_scl(unsigned bus, int high) +{ + if (high) + gpio_input_pullup(pins[bus].scl); + else + gpio_output(pins[bus].scl, 0); +} + +static int tegra_get_sda(unsigned bus) +{ + return gpio_get(pins[bus].sda); +} + +static int tegra_get_scl(unsigned bus) +{ + return gpio_get(pins[bus].scl); +} + +static struct software_i2c_ops tegra_ops = { + .set_sda = tegra_set_sda, + .set_scl = tegra_set_scl, + .get_sda = tegra_get_sda, + .get_scl = tegra_get_scl, +}; + +void tegra_software_i2c_init(unsigned bus) +{ + software_i2c[bus] = &tegra_ops; + + /* Initialize bus to idle state. */ + tegra_set_sda(bus, 1); + tegra_set_scl(bus, 1); +} + +void tegra_software_i2c_disable(unsigned bus) +{ + software_i2c[bus] = NULL; + + /* Return pins to I2C controller. */ + pinmux_set_config(pins[bus].sda >> GPIO_PINMUX_SHIFT, + pins[bus].pinmux_func | PINMUX_INPUT_ENABLE); + pinmux_set_config(pins[bus].scl >> GPIO_PINMUX_SHIFT, + pins[bus].pinmux_func | PINMUX_INPUT_ENABLE); + gpio_set_mode(pins[bus].sda, GPIO_MODE_SPIO); + gpio_set_mode(pins[bus].scl, GPIO_MODE_SPIO); +} diff --git a/src/soc/nvidia/tegra/types.h b/src/soc/nvidia/tegra/types.h new file mode 100644 index 0000000000..ce0b6bb088 --- /dev/null +++ b/src/soc/nvidia/tegra/types.h @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __TEGRA_MISC_TYPES_H__ +#define __TEGRA_MISC_TYPES_H__ + +#define EFAULT 1 +#define EINVAL 2 +#define ETIMEDOUT 3 +#define ENOSPC 4 +#define ENOSYS 5 +#define EPTR 6 + +#define IS_ERR_PTR(ptr) \ + (ptr == (void *)-EPTR) + +#ifndef bool +#define bool int +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) + +/* + * Divide positive or negative dividend by positive divisor and round + * to closest integer. Result is undefined for negative divisors and + * for negative dividends if the divisor variable type is unsigned. + */ +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) > 0 || \ + ((typeof(divisor))-1) > 0 || (__x) > 0) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +} \ +) + +#endif /* __TEGRA_MISC_TYPES_H__ */ diff --git a/src/soc/nvidia/tegra/usb.c b/src/soc/nvidia/tegra/usb.c new file mode 100644 index 0000000000..c8761a231f --- /dev/null +++ b/src/soc/nvidia/tegra/usb.c @@ -0,0 +1,216 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "usb.h" + +struct utmip_ctlr { + u32 pll0; + u32 pll1; + u32 xcvr0; + u32 bias0; + u32 hsrx0; + u32 hsrx1; + u32 fslsrx0; + u32 fslsrx1; + u32 tx; + u32 misc0; + u32 misc1; + u32 debounce; + u32 batchrgr; + u32 spare; + u32 xcvr1; + u32 bias1; + u32 bias_sts; + u32 chrgr_debounce; + u32 misc_sts; + u32 pmc_wakeup; +}; +check_member(utmip_ctlr, pmc_wakeup, 0x84c - 0x800); + +struct usb_ctlr { + u32 id; + u32 _rsv0; + u32 host; + u32 device; + u32 txbuf; /* 0x010 */ + u32 rxbuf; + u32 _rsv1[58]; + u16 ehci_caplen; /* 0x100 */ + u16 ehci_version; + u32 ehci_hcsp; + u32 ehci_hccp; + u32 _rsv2[5]; + u32 dci_version; /* 0x120 */ + u32 dcc_params; + u32 extsts; + u32 extintr; + u32 ehci_usbcmd; /* 0x130 */ + u32 ehci_usbsts; + u32 ehci_usbintr; + u32 ehci_frindex; + u32 _rsv3; /* 0x140 */ + u32 ehci_periodic_base; + u32 ehci_async_base; + u32 async_ttsts; + u32 burst_size; /* 0x150 */ + u32 tx_fill_tuning; + u32 _rsv4; + u32 icusb_ctrl; + u32 ulpi_viewport; /* 0x160 */ + u32 _rsv5[4]; + u32 ehci_portsc; + u32 _rsv6[15]; + u32 lpm_ctrl; + u32 _rsv7[15]; + u32 otgsc; + u32 usb_mode; + u32 _rsv8; + u32 ep_nak; /* 0x200 */ + u32 ep_nak_enable; + u32 ep_setup; + u32 ep_init; + u32 ep_deinit; + u32 ep_sts; + u32 ep_complete; + u32 ep_ctrl[16]; + u32 _rsv9[105]; + u32 suspend_ctrl; /* 0x400 */ + u32 vbus_sensors; + u32 vbus_wakeup_id; + u32 alt_vbus_sts; + u32 legacy_ctrl; + u32 _rsv10[3]; + u32 interpacket_delay; + u32 _rsv11[27]; + u32 resume_delay; + u32 _rsv12; + u32 spare; + u32 _rsv13[9]; + u32 new_ctrl; + u32 _rsv14[207]; + struct utmip_ctlr utmip; /* 0x800 */ +}; +check_member(usb_ctlr, utmip, 0x800); + +/* + * Tegra EHCI controllers need their usb_mode, lpm_ctrl and tx_fill_tuning + * registers initialized after every EHCI reset and before any other actions + * (such as Run/Stop bit) are taken. We reset the controller here, set those + * registers and rely on the fact that libpayload doesn't reset EHCI controllers + * on initialization for whatever weird reason. This is ugly, fragile, and I + * really don't like it, but making this work will require an ugly hack one way + * or another so we might as well take the path of least resistance for now. + */ +static void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type) +{ + int timeout = 1000; + + write32(1 << 1, &usb->ehci_usbcmd); /* Host Controller Reset */ + /* TODO: Resets are long, find way to parallelize... or just use XHCI */ + while (--timeout && (read32(&usb->ehci_usbcmd) & 1 << 1)) + /* wait for HC to reset */; + + if (!timeout) { + printk(BIOS_ERR, "ERROR: EHCI(%p) reset timeout", usb); + return; + } + + write32(3 << 0, &usb->usb_mode); /* Controller mode: HOST */ + write32(type << 29, &usb->lpm_ctrl); /* Parallel transceiver selct */ + write32(0x10 << 16, &usb->tx_fill_tuning); /* Tx FIFO Burst thresh */ +} + +/* Assume USBx clocked, out of reset, UTMI+ PLL set up, SAMP_x out of pwrdn */ +void usb_setup_utmip(void *usb_base) +{ + struct usb_ctlr *usb = (struct usb_ctlr *)usb_base; + + /* KHz formulas were guessed from U-Boot constants. Formats unclear. */ + int khz = clock_get_pll_input_khz(); + + /* Stop UTMI+ crystal clock while we mess with its settings */ + clrbits_le32(&usb->utmip.misc1, 1 << 30); /* PHY_XTAL_CLKEN */ + udelay(1); + + /* Take stuff out of pwrdn and add some magic numbers from U-Boot */ + write32(0x8 << 25 | /* HS slew rate [10:4] */ + 0x3 << 22 | /* HS driver output 'SETUP' [6:4] */ + 0 << 21 | /* LS bias selection */ + 0 << 18 | /* PDZI pwrdn */ + 0 << 16 | /* PD2 pwrdn */ + 0 << 14 | /* PD pwrdn */ + 1 << 13 | /* (rst) HS receiver terminations */ + 0x1 << 10 | /* (rst) LS falling slew rate */ + 0x1 << 8 | /* (rst) LS rising slew rate */ + 0x4 << 0 | /* HS driver output 'SETUP' [3:0] */ + 0, &usb->utmip.xcvr0); + write32(0x7 << 18 | /* Termination range adjustment */ + 0 << 4 | /* PDDR pwrdn */ + 0 << 2 | /* PDCHRP pwrdn */ + 0 << 0 | /* PDDISC pwrdn */ + 0, &usb->utmip.xcvr1); + write32(1 << 19 | /* FS send initial J before sync(?) */ + 1 << 16 | /* (rst) Allow stuff error on SoP */ + 1 << 9 | /* (rst) Check disc only on EoP */ + 0, &usb->utmip.tx); + write32(0x2 << 30 | /* (rst) Keep pattern on active */ + 1 << 28 | /* (rst) Realign inertia on pkt */ + 0x1 << 24 | /* (rst) edges-1 to move sampling */ + 0x3 << 21 | /* (rst) squelch delay on EoP */ + 0x11 << 15 | /* cycles until IDLE */ + 0x10 << 10 | /* elastic input depth */ + 0, &usb->utmip.hsrx0); + + /* U-Boot claims the USBD values for these are used across all UTMI+ + * PHYs. That sounds so horribly wrong that I'm not going to implement + * it, but keep it in mind if we're ever not using the USBD port. */ + write32(0x1 << 24 | /* HS disconnect detect level [2] */ + 1 << 23 | /* (rst) IDPD value */ + 1 << 22 | /* (rst) IDPD select */ + 1 << 11 | /* (rst) OTG pwrdn */ + 0 << 10 | /* bias pwrdn */ + 0x1 << 2 | /* HS disconnect detect level [1:0] */ + 0x2 << 0 | /* HS squelch detect level */ + 0, &usb->utmip.bias0); + + write32(khz / 2200 << 3 | /* bias pwrdn cycles (20us?) */ + 1 << 2 | /* (rst) VBUS wakeup pwrdn */ + 0 << 0 | /* PDTRK pwrdn */ + 0, &usb->utmip.bias1); + + write32(0xffff << 16 | /* (rst) */ + 25 * khz / 10 << 0 | /* TODO: what's this, really? */ + 0, &usb->utmip.debounce); + + udelay(1); + setbits_le32(&usb->utmip.misc1, 1 << 30); /* PHY_XTAL_CLKEN */ + + write32(1 << 12 | /* UTMI+ enable */ + 0 << 11 | /* UTMI+ reset */ + 0, &usb->suspend_ctrl); + + usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP); + printk(BIOS_DEBUG, "USB controller @ %p set up with UTMI+ PHY\n",usb_base); +} + diff --git a/src/soc/nvidia/tegra/usb.h b/src/soc/nvidia/tegra/usb.h new file mode 100644 index 0000000000..9d22b0b867 --- /dev/null +++ b/src/soc/nvidia/tegra/usb.h @@ -0,0 +1,34 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_USB_H__ +#define __SOC_NVIDIA_TEGRA_USB_H__ + +#include + +enum usb_phy_type { /* For use in lpm_ctrl[31:29] */ + USB_PHY_UTMIP = 0, + USB_PHY_ULPI = 2, + USB_PHY_ICUSB_SER = 3, + USB_PHY_HSIC = 4, +}; + +void usb_setup_utmip(void *usb_base); + +#endif diff --git a/src/soc/nvidia/tegra124/Kconfig b/src/soc/nvidia/tegra124/Kconfig new file mode 100644 index 0000000000..4fa16272d5 --- /dev/null +++ b/src/soc/nvidia/tegra124/Kconfig @@ -0,0 +1,96 @@ +config SOC_NVIDIA_TEGRA124 + bool + default n + select HAVE_UART_MEMORY_MAPPED + select HAVE_UART_SPECIAL + select HAVE_HARD_RESET + select HAVE_MONOTONIC_TIMER + select GENERIC_UDELAY + select BOOTBLOCK_CONSOLE + select EARLY_CONSOLE + select DYNAMIC_CBMEM + select ARM_BOOTBLOCK_CUSTOM + select ARCH_BOOTBLOCK_ARM_V4 + select ARCH_VERSTAGE_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + select ARM_LPAE + select COLLECT_TIMESTAMPS + select HAS_PRECBMEM_TIMESTAMP_REGION + select GENERIC_GPIO_LIB + +if SOC_NVIDIA_TEGRA124 + +config BOOTBLOCK_CPU_INIT + string + default "soc/nvidia/tegra124/bootblock.c" + help + CPU/SoC-specific bootblock code. This is useful if the + bootblock must load microcode or copy data from ROM before + searching for the bootblock. + +choice CONSOLE_SERIAL_TEGRA124_UART_CHOICES + prompt "Serial Console UART" + default CONSOLE_SERIAL_UARTA + depends on CONSOLE_SERIAL_UART + +config CONSOLE_SERIAL_UARTA + bool "UARTA" + help + Serial console on UART A. + +config CONSOLE_SERIAL_UARTB + bool "UARTB" + help + Serial console on UART B. + +config CONSOLE_SERIAL_UARTC + bool "UARTC" + help + Serial console on UART C. + +config CONSOLE_SERIAL_UARTD + bool "UARTD" + help + Serial console on UART D. + +config CONSOLE_SERIAL_UARTE + bool "UARTE" + help + Serial console on UART E. + +endchoice + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0x70006000 if CONSOLE_SERIAL_UARTA + default 0x70006040 if CONSOLE_SERIAL_UARTB + default 0x70006200 if CONSOLE_SERIAL_UARTC + default 0x70006300 if CONSOLE_SERIAL_UARTD + default 0x70006400 if CONSOLE_SERIAL_UARTE + help + Map the UART names to the respective MMIO addres. + +config TEGRA124_MODEL_TD570D + bool "TD570D" + +config TEGRA124_MODEL_TD580D + bool "TD580D" + +config TEGRA124_MODEL_CD570M + bool "CD570M" + +config TEGRA124_MODEL_CD580M + bool "CD580M" + +# Default to 2GHz, the lowest maximum frequency. +config PLLX_KHZ + int + default 2000000 if TEGRA124_MODEL_TD570D + default 2300000 if TEGRA124_MODEL_TD580D + default 2100000 if TEGRA124_MODEL_CD570M + default 2300000 if TEGRA124_MODEL_CD580M + default 2000000 + +endif diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc new file mode 100644 index 0000000000..e9f83e0f56 --- /dev/null +++ b/src/soc/nvidia/tegra124/Makefile.inc @@ -0,0 +1,108 @@ +CBOOTIMAGE = cbootimage + +bootblock-y += bootblock.c +bootblock-y += bootblock_asm.S +bootblock-y += cbfs.c +bootblock-y += clock.c +bootblock-y += dma.c +bootblock-y += i2c.c +bootblock-y += dma.c +bootblock-y += maincpu.S +bootblock-y += monotonic_timer.c +bootblock-y += power.c +bootblock-y += spi.c +bootblock-y += ../tegra/gpio.c +bootblock-y += ../tegra/i2c.c +bootblock-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c +bootblock-y += ../tegra/pingroup.c +bootblock-y += ../tegra/pinmux.c +bootblock-y += ../tegra/apbmisc.c +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif + +verstage-y += verstage.c +verstage-y += cbfs.c +verstage-y += dma.c +verstage-y += monotonic_timer.c +verstage-y += spi.c +verstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +verstage-y += ../tegra/gpio.c +verstage-y += ../tegra/i2c.c +verstage-y += ../tegra/pinmux.c +verstage-y += clock.c +verstage-y += i2c.c +verstage-y += cache.c + +romstage-y += cbfs.c +romstage-y += cbmem.c +romstage-y += clock.c +romstage-y += dma.c +romstage-y += i2c.c +romstage-y += monotonic_timer.c +romstage-y += power.c +romstage-y += sdram.c +romstage-y += sdram_lp0.c +romstage-y += spi.c +romstage-y += ../tegra/gpio.c +romstage-y += ../tegra/i2c.c +romstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c +romstage-y += ../tegra/pinmux.c +romstage-y += cache.c +ifeq ($(CONFIG_EARLY_CONSOLE),y) +romstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif + +ramstage-y += cbfs.c +ramstage-y += cbmem.c +ramstage-y += clock.c +ramstage-y += display.c +ramstage-y += dma.c +ramstage-y += i2c.c +ramstage-y += maincpu.S +ramstage-y += monotonic_timer.c +ramstage-y += sdram.c +ramstage-y += soc.c +ramstage-y += sor.c +ramstage-y += spi.c +ramstage-y += dp.c +ramstage-y += ../tegra/gpio.c +ramstage-y += ../tegra/i2c.c +ramstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c +ramstage-y += ../tegra/pinmux.c +ramstage-y += ../tegra/usb.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c + +rmodules_$(ARCH-ROMSTAGE-y)-y += monotonic_timer.c +VBOOT_STUB_DEPS += $(obj)/soc/nvidia/tegra124/monotonic_timer.rmodules_$(ARCH-ROMSTAGE-y).o + +INCLUDES += -Isrc/soc/nvidia/tegra124/include/ + +# We want to grab the bootblock right before it goes into the image and wrap +# it inside a BCT, but ideally we would do that without making special, one +# use modifications to the main ARM Makefile. We do this in two ways. First, +# we copy bootblock.elf to bootblock.raw.elf and allow the %.bin: %.elf +# template rule to turn it into bootblock.raw.bin. This makes sure whatever +# processing is supposed to happen to turn an .elf into a .bin happens. +# +# Second, we add our own rule for creating bootblock.bin from +# bootblock.raw.bin which displaces the template rule. When other rules that +# package up the image pull in bootblock.bin, it will be this wrapped version +# instead of the raw bootblock. + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(obj)/generated/bct.bin: $(obj)/generated/bct.cfg + @printf " CBOOTIMAGE $(subst $(obj)/,,$(@))\n" + $(CBOOTIMAGE) -gbct --soc tegra124 $< $@ + +BCT_BIN = $(obj)/generated/bct.bin +BCT_WRAPPER = $(obj)/generated/bct.wrapper +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin $(BCT_BIN) + echo "Version = 1;" > $(BCT_WRAPPER) + echo "Redundancy = 1;" >> $(BCT_WRAPPER) + echo "Bctfile = $(BCT_BIN);" >> $(BCT_WRAPPER) + echo "BootLoader = $<,$(call loadaddr,bootblock),$(call loadaddr,bootblock),Complete;" >> $(BCT_WRAPPER) + @printf " CBOOTIMAGE $(subst $(obj)/,,$(@))\n" + $(CBOOTIMAGE) $(BCT_WRAPPER) $@ diff --git a/src/soc/nvidia/tegra124/bootblock.c b/src/soc/nvidia/tegra124/bootblock.c new file mode 100644 index 0000000000..fd5d5052ef --- /dev/null +++ b/src/soc/nvidia/tegra124/bootblock.c @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void main(void) +{ + void *entry; + + // enable pinmux clamp inputs + clamp_tristate_inputs(); + + // enable JTAG at the earliest stage + enable_jtag(); + + clock_early_uart(); + + // Serial out, tristate off. + pinmux_set_config(PINMUX_KB_ROW9_INDEX, PINMUX_KB_ROW9_FUNC_UA3); + // Serial in, tristate_on. + pinmux_set_config(PINMUX_KB_ROW10_INDEX, PINMUX_KB_ROW10_FUNC_UA3 | + PINMUX_PULL_UP | + PINMUX_INPUT_ENABLE); + // Mux some pins away from uart A. + pinmux_set_config(PINMUX_UART2_CTS_N_INDEX, + PINMUX_UART2_CTS_N_FUNC_UB3 | + PINMUX_INPUT_ENABLE); + pinmux_set_config(PINMUX_UART2_RTS_N_INDEX, + PINMUX_UART2_RTS_N_FUNC_UB3); + + if (CONFIG_BOOTBLOCK_CONSOLE) { + console_init(); + exception_init(); + } + + clock_init(); + + timestamp_early_init(0); + + bootblock_mainboard_init(); + + pinmux_set_config(PINMUX_CORE_PWR_REQ_INDEX, + PINMUX_CORE_PWR_REQ_FUNC_PWRON); + pinmux_set_config(PINMUX_CPU_PWR_REQ_INDEX, + PINMUX_CPU_PWR_REQ_FUNC_CPU); + pinmux_set_config(PINMUX_PWR_INT_N_INDEX, + PINMUX_PWR_INT_N_FUNC_PMICINTR | + PINMUX_INPUT_ENABLE); + + if (IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE)) + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/verstage"); + else + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/romstage"); + + ASSERT(entry); + clock_cpu0_config(entry); + + power_enable_and_ungate_cpu(); + + /* Repair ram on cluster0 and cluster1 after CPU is powered on. */ + ram_repair(); + + clock_cpu0_remove_reset(); + + clock_halt_avp(); +} diff --git a/src/soc/nvidia/tegra124/bootblock_asm.S b/src/soc/nvidia/tegra124/bootblock_asm.S new file mode 100644 index 0000000000..1a30dda65e --- /dev/null +++ b/src/soc/nvidia/tegra124/bootblock_asm.S @@ -0,0 +1,75 @@ +/* + * Early initialization code for ARM architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +ENTRY(_start) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr_cxf, #0xdf + + /* + * Initialize the stack to a known value. This is used to check for + * stack overflow later in the boot process. + */ + ldr r0, =_stack + ldr r1, =_estack + ldr r2, =0xdeadbeef +init_stack_loop: + str r2, [r0] + add r0, #4 + cmp r0, r1 + bne init_stack_loop + +/* Set stackpointer in internal RAM to call bootblock main() */ +call_bootblock: + ldr sp, =_estack /* Set up stack pointer */ + ldr r0,=0x00000000 + /* + * The current design of cpu_info places the + * struct at the top of the stack. The number of + * words pushed must be at least as large as that + * struct. + */ + push {r0-r2} + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + /* + * Use "bl" instead of "b" even though we do not intend to return. + * "bl" gets compiled to "blx" if we're transitioning from ARM to + * Thumb. However, "b" will not and GCC may attempt to create a + * wrapper which is currently broken. + */ + bl main +ENDPROC(_start) diff --git a/src/soc/nvidia/tegra124/cache.c b/src/soc/nvidia/tegra124/cache.c new file mode 100644 index 0000000000..a925eafa63 --- /dev/null +++ b/src/soc/nvidia/tegra124/cache.c @@ -0,0 +1,66 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +enum { + L2CTLR_ECC_PARITY = 0x1 << 21, + L2CTLR_TAG_RAM_LATENCY_MASK = 0x7 << 6, + L2CTLR_TAG_RAM_LATENCY_CYCLES_3 = 2 << 6, + L2CTLR_DATA_RAM_LATENCY_MASK = 0x7 << 0, + L2CTLR_DATA_RAM_LATENCY_CYCLES_3 = 2 << 0 +}; + +enum { + L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE = 0x1 << 27, + L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT = 0x1 << 7, + L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL = 0x1 << 3 +}; + +/* Configures L2 Control Register to use 3 cycles for DATA/TAG RAM latency. */ +static void configure_l2ctlr(void) +{ + uint32_t val; + + val = read_l2ctlr(); + val &= ~(L2CTLR_DATA_RAM_LATENCY_MASK | L2CTLR_TAG_RAM_LATENCY_MASK); + val |= (L2CTLR_DATA_RAM_LATENCY_CYCLES_3 | + L2CTLR_TAG_RAM_LATENCY_CYCLES_3 | L2CTLR_ECC_PARITY); + write_l2ctlr(val); +} + +/* Configures L2 Auxiliary Control Register for Cortex A15. */ +static void configure_l2actlr(void) +{ + uint32_t val; + + val = read_l2actlr(); + val |= (L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL | + L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT | + L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE); + write_l2actlr(val); +} + +void configure_l2_cache(void) +{ + configure_l2ctlr(); + configure_l2actlr(); +} diff --git a/src/soc/nvidia/tegra124/cbfs.c b/src/soc/nvidia/tegra124/cbfs.c new file mode 100644 index 0000000000..33a7258feb --- /dev/null +++ b/src/soc/nvidia/tegra124/cbfs.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include /* This driver serves as a CBFS media source. */ +#include +#include + +int init_default_cbfs_media(struct cbfs_media *media) +{ + return initialize_tegra_spi_cbfs_media(media, + _cbfs_cache, _cbfs_cache_size); +} diff --git a/src/soc/nvidia/tegra124/cbmem.c b/src/soc/nvidia/tegra124/cbmem.c new file mode 100644 index 0000000000..fcc19da350 --- /dev/null +++ b/src/soc/nvidia/tegra124/cbmem.c @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void *cbmem_top(void) +{ + return (void *)((sdram_max_addressable_mb() - FB_SIZE_MB) << 20UL); +} diff --git a/src/soc/nvidia/tegra124/chip.h b/src/soc/nvidia/tegra124/chip.h new file mode 100644 index 0000000000..acabd37f7b --- /dev/null +++ b/src/soc/nvidia/tegra124/chip.h @@ -0,0 +1,107 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_CHIP_H__ +#define __SOC_NVIDIA_TEGRA124_CHIP_H__ +#include +#include +#include + +#define EFAULT 1 +#define EINVAL 2 + +/* this is a misuse of the device tree. We're going to let it go for now but + * we should at minimum have a struct for the display controller, since + * the chip supports two. + */ +struct soc_nvidia_tegra124_config { + u32 xres; + u32 yres; + u32 framebuffer_bits_per_pixel; + u32 color_depth; + u32 panel_bits_per_pixel; + int cache_policy; + /* there are two. It's not unimaginable that we might someday + * have two of these structs in a single mainboard. + */ + u32 display_controller; + u32 framebuffer_base; + /* Technically, we can compute this. At the same time, some platforms + * might want to specify a specific size for their own reasons. If it is + * zero the soc code will compute it as xres*yres*framebuffer_bits_per_pixel/4 + */ + u32 framebuffer_size; + /* GPIOs -- all, some, or none are used. Unused ones can be ignored + * in devicetree.cb since if they are not set there they default to 0, + * and 0 for a gpio means 'unused GPIO'. + */ + gpio_t backlight_en_gpio; + gpio_t lvds_shutdown_gpio; + gpio_t backlight_vdd_gpio; + gpio_t panel_vdd_gpio; + + /* required info. */ + /* pwm to use to set display contrast */ + int pwm; + /* timings -- five numbers, all relative to the previous + * event, not to absolute time. e.g., vdd_data_delay is the + * delay from vdd on to data, not from power on to data. + * This is stated to be four timings in the + * u-boot docs. In any event, in coreboot, we generally + * only delay long enough to let the panel wake up and then + * do the control operations -- meaning, for *coreboot* + * we probably only need the vdd_delay, but payloads may + * need the other info. + */ + /* Delay before from power on asserting vdd */ + int vdd_delay_ms; + + /* Delay beween pwm and backlight_en_gpio is asserted */ + int pwm_to_bl_delay_ms; + + /* Delay before HPD high */ + int vdd_to_hpd_delay_ms; + + int hpd_unplug_min_us; + int hpd_plug_min_us; + int hpd_irq_min_us; + + int href_to_sync; + int hsync_width; + int hback_porch; + int hfront_porch; + int vref_to_sync; + int vsync_width; + int vback_porch; + int vfront_porch; + + int pixel_clock; + + /* The minimum link configuraton settings */ + u32 lane_count; + u32 enhanced_framing; + u32 link_bw; + u32 drive_current; + u32 preemphasis; + u32 postcursor; + + void *dc_data; +}; + +#endif /* __SOC_NVIDIA_TEGRA124_CHIP_H__ */ diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c new file mode 100644 index 0000000000..f944ac4e34 --- /dev/null +++ b/src/soc/nvidia/tegra124/clock.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; +static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE; +static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE; +static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE; + +struct pll_dividers { + u32 n : 10; + u32 m : 8; + u32 p : 4; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +/* Some PLLs have more restrictive divider bit lengths or are missing some + * fields. Make sure to use the right struct in the osc_table definition to get + * compile-time checking, but keep the bits aligned with struct pll_dividers so + * they can be used interchangeably at run time. Add new formats as required. */ +struct pllcx_dividers { + u32 n : 8; + u32 : 2; + u32 m : 8; + u32 p : 4; + u32 : 10; +}; +struct pllpad_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 3; + u32 : 1; + u32 cpcon : 4; + u32 : 6; +}; +struct pllu_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 1; + u32 : 3; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +union __attribute__((transparent_union)) pll_fields { + u32 raw; + struct pll_dividers div; + struct pllcx_dividers cx; + struct pllpad_dividers pad; + struct pllu_dividers u; +}; + +/* This table defines the frequency dividers for every PLL to turn the external + * OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h. + * All PLLs have three dividers (n, m and p), with the governing formula for + * the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p). + * All divisor configurations must meet the PLL's constraints for VCO and CF: + * PLLX: 12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz + * PLLC: 12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz + * PLLM: 12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz + * PLLP: 1 MHz < CF < 6 MHz, 200 MHz < VCO < 700 MHz + * PLLD: 1 MHz < CF < 6 MHz, 500 MHz < VCO < 1000 MHz + * PLLU: 1 MHz < CF < 6 MHz, 480 MHz < VCO < 960 MHz + * PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz + * (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */ +struct { + int khz; + struct pllcx_dividers pllx; /* target: CONFIG_PLLX_KHZ */ + struct pllcx_dividers pllc; /* target: 600 MHz */ + /* PLLM is set up dynamically by clock_sdram(). */ + /* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */ + struct pllu_dividers pllu; /* target; 960 MHz */ + struct pllcx_dividers plldp; /* target; 270 MHz */ + /* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */ +} static const osc_table[16] = { + [OSC_FREQ_12]{ + .khz = 12000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, + [OSC_FREQ_13]{ + .khz = 13000, + .pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m = 1, .p = 0}, + .pllc = {.n = 46, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 1, .p = 3}, /* 269.8 MHz */ + }, + [OSC_FREQ_16P8]{ + .khz = 16800, + .pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m = 1, .p = 0}, + .pllc = {.n = 71, .m = 1, .p = 1}, /* 596.4 MHz */ + .pllu = {.n = 400, .m = 7, .p = 0, .cpcon = 5, .lfcon = 2}, + .plldp = {.n = 64, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_19P2]{ + .khz = 19200, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_26]{ + .khz = 26000, + .pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m = 1, .p = 0}, + .pllc = {.n = 23, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 2, .p = 3}, /* 269.8 MHz */ + }, + /* These oscillators get predivided as PLL inputs... n/m/p divisors for + * 38.4 should always match 19.2, and 48 should always match 12. */ + [OSC_FREQ_38P4]{ + .khz = 38400, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_48]{ + .khz = 48000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, +}; + +/* Get the oscillator frequency, from the corresponding hardware + * configuration field. This is actually a per-soc thing. Avoid the + * temptation to make it common. + */ +static u32 clock_get_osc_bits(void) +{ + return (readl(&clk_rst->osc_ctrl) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + +int clock_get_osc_khz(void) +{ + return osc_table[clock_get_osc_bits()].khz; +} + +int clock_get_pll_input_khz(void) +{ + u32 osc_ctrl = readl(&clk_rst->osc_ctrl); + u32 osc_bits = (osc_ctrl & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + u32 pll_ref_div = (osc_ctrl & OSC_PREDIV_MASK) >> OSC_PREDIV_SHIFT; + return osc_table[osc_bits].khz >> pll_ref_div; +} + +void clock_init_arm_generic_timer(void) +{ + uint32_t freq = clock_get_osc_khz() * 1000; + // Set the cntfrq register. + set_cntfrq(freq); + + // Record the system timer frequency. + write32(freq, &sysctr->cntfid0); + // Enable the system counter. + uint32_t cntcr = read32(&sysctr->cntcr); + cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG; + write32(cntcr, &sysctr->cntcr); +} + +#define SOR0_CLK_SEL0 (1 << 14) +#define SOR0_CLK_SEL1 (1 << 15) + +void sor_clock_stop(void) +{ + /* The Serial Output Resource clock has to be off + * before we start the plldp. Learned the hard way. + * FIXME: this has to be cleaned up a bit more. + * Waiting on some new info from Nvidia. + */ + clrbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0 | SOR0_CLK_SEL1); +} + +void sor_clock_start(void) +{ + /* uses PLLP, has a non-standard bit layout. */ + setbits_le32(&clk_rst->clk_src_sor, SOR0_CLK_SEL0); +} + +static void init_pll(u32 *base, u32 *misc, const union pll_fields pll, u32 lock) +{ + u32 dividers = pll.div.n << PLL_BASE_DIVN_SHIFT | + pll.div.m << PLL_BASE_DIVM_SHIFT | + pll.div.p << PLL_BASE_DIVP_SHIFT; + u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT | + pll.div.lfcon << PLL_MISC_LFCON_SHIFT; + + /* Write dividers but BYPASS the PLL while we're messing with it. */ + writel(dividers | PLL_BASE_BYPASS, base); + /* + * Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't + * exist for this PLL) + */ + writel(lock | misc_con, misc); + + /* Enable PLL and take it back out of BYPASS */ + writel(dividers | PLL_BASE_ENABLE, base); + + /* Wait for lock ready */ + while (!(readl(base) & PLL_BASE_LOCK)); +} + +static void init_utmip_pll(void) +{ + int khz = clock_get_pll_input_khz(); + + /* Shut off PLL crystal clock while we mess with it */ + clrbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */ + udelay(1); + + write32(80 << 16 | /* (rst) phy_divn */ + 1 << 8 | /* (rst) phy_divm */ + 0, &clk_rst->utmip_pll_cfg0); /* 960MHz * 1 / 80 == 12 MHz */ + + write32(div_round_up(khz, 8000) << 27 | /* pllu_enbl_cnt / 8 (1us) */ + 0 << 16 | /* PLLU pwrdn */ + 0 << 14 | /* pll_enable pwrdn */ + 0 << 12 | /* pll_active pwrdn */ + div_round_up(khz, 102) << 0 | /* phy_stbl_cnt / 256 (2.5ms) */ + 0, &clk_rst->utmip_pll_cfg1); + + /* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */ + write32(0 << 24 | /* SAMP_D/XDEV pwrdn */ + div_round_up(khz, 3200) << 18 | /* phy_actv_cnt / 16 (5us) */ + div_round_up(khz, 256) << 6 | /* pllu_stbl_cnt / 256 (1ms) */ + 0 << 4 | /* SAMP_C/USB3 pwrdn */ + 0 << 2 | /* SAMP_B/XHOST pwrdn */ + 0 << 0 | /* SAMP_A/USBD pwrdn */ + 0, &clk_rst->utmip_pll_cfg2); + + setbits_le32(&clk_rst->utmip_pll_cfg2, 1 << 30); /* PHY_XTAL_CLKEN */ +} + +/* Graphics just has to be different. There's a few more bits we + * need to set in here, but it makes sense just to restrict all the + * special bits to this one function. + */ +static void graphics_pll(void) +{ + int osc = clock_get_osc_bits(); + u32 *cfg = &clk_rst->plldp_ss_cfg; + /* the vendor code sets the dither bit (28) + * an undocumented bit (24) + * and clamp while we mess with it (22) + * Dither is pretty important to display port + * so we really do need to handle these bits. + * I'm not willing to not clamp it, even if + * it might "mostly work" with it not set, + * I don't want to find out in a few months + * that it is needed. + */ + u32 scfg = (1<<28) | (1<<24) | (1<<22); + writel(scfg, cfg); + init_pll(&clk_rst->plldp_base, &clk_rst->plldp_misc, + osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE); + /* leave dither and undoc bits set, release clamp */ + scfg = (1<<28) | (1<<24); + writel(scfg, cfg); + + /* disp1 will be set when panel information (pixel clock) is + * retrieved (clock_display). + */ +} + +/* + * Init PLLD clock source. + * + * @frequency: the requested plld frequency + * + * Return the plld frequency if success, otherwise return 0. + */ +u32 +clock_display(u32 frequency) +{ + /** + * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz + * = (cf * n) >> p, where 1MHz < cf < 6MHz + * = ((ref / m) * n) >> p + * + * Iterate the possible values of p (3 bits, 2^7) to find out a minimum + * safe vco, then find best (m, n). since m has only 5 bits, we can + * iterate all possible values. Note Tegra 124 supports 11 bits for n, + * but our pll_fields has only 10 bits for n. + * + * Note values undershoot or overshoot target output frequency may not + * work if the values are not in "safe" range by panel specification. + */ + struct pllpad_dividers plld = { 0 }; + u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0; + u32 cf, vco, rounded_rate = frequency; + u32 diff, best_diff; + const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3, + mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz, + min_cf = 1 * mhz, max_cf = 6 * mhz; + + for (vco = frequency; vco < min_vco && p < max_p; p++) + vco <<= 1; + + if (vco < min_vco || vco > max_vco) { + printk(BIOS_ERR, "%s: Cannot find out a supported VCO" + " for Frequency (%u).\n", __func__, frequency); + return 0; + } + + plld.p = p; + best_diff = vco; + + for (m = 1; m < max_m && best_diff; m++) { + cf = ref / m; + if (cf < min_cf) + break; + if (cf > max_cf) + continue; + + n = vco / cf; + if (n >= max_n) + continue; + + diff = vco - n * cf; + if (n + 1 < max_n && diff > cf / 2) { + n++; + diff = cf - diff; + } + + if (diff >= best_diff) + continue; + + best_diff = diff; + plld.m = m; + plld.n = n; + } + + if (plld.n < 50) + plld.cpcon = 2; + else if (plld.n < 300) + plld.cpcon = 3; + else if (plld.n < 600) + plld.cpcon = 8; + else + plld.cpcon = 12; + + if (best_diff) { + printk(BIOS_WARNING, "%s: Failed to match output frequency %u, " + "best difference is %u.\n", __func__, frequency, + best_diff); + rounded_rate = (ref / plld.m * plld.n) >> plld.p; + } + + printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n", + __func__, rounded_rate, ref, plld.m, plld.n, plld.p, plld.cpcon); + + init_pll(&clk_rst->plld_base, &clk_rst->plld_misc, plld, + (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE)); + + return rounded_rate; +} + +/* Initialize the UART and put it on CLK_M so we can use it during clock_init(). + * Will later move it to PLLP in clock_config(). The divisor must be very small + * to accomodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1 + * CLK_SOURCE divider to get more precision. (This might still not be enough for + * some OSCs... if you use 13KHz, be prepared to have a bad time.) The 1900 has + * been determined through trial and error (must lead to div 13 at 24MHz). */ +void clock_early_uart(void) +{ + write32(CLK_M << CLK_SOURCE_SHIFT | CLK_UART_DIV_OVERRIDE | + CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900), &clk_rst->clk_src_uarta); + setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_UARTA); + udelay(2); + clrbits_le32(&clk_rst->rst_dev_l, CLK_L_UARTA); +} + +/* Enable output clock (CLK1~3) for external peripherals. */ +void clock_external_output(int clk_id) +{ + switch (clk_id) { + case 1: + setbits_le32(&pmc->clk_out_cntrl, 1 << 2); + break; + case 2: + setbits_le32(&pmc->clk_out_cntrl, 1 << 10); + break; + case 3: + setbits_le32(&pmc->clk_out_cntrl, 1 << 18); + break; + default: + printk(BIOS_CRIT, "ERROR: Unknown output clock id %d\n", + clk_id); + break; + } +} + +/* Start PLLM for SDRAM. */ +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq) +{ + u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) | + (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) | + (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) | + (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)), + misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | + (kcp << PLLM_MISC2_KCP_SHIFT)), + base; + + if (same_freq) + emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + else + emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + + /* + * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and + * PLLM_BASE.ENABLE must be in DISABLE state (both are the default + * values after coldboot reset). + */ + + writel(misc1, &clk_rst->pllm_misc1); + writel(misc2, &clk_rst->pllm_misc2); + + /* PLLM.BASE needs BYPASS=0, different from general init_pll */ + base = readl(&clk_rst->pllm_base); + base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK | + PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS); + base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) | + (p << PLL_BASE_DIVP_SHIFT)); + writel(base, &clk_rst->pllm_base); + + setbits_le32(&clk_rst->pllm_base, PLL_BASE_ENABLE); + /* stable_time is required, before we can start to check lock. */ + udelay(stable_time); + + while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) { + udelay(1); + } + /* + * After PLLM reports being locked, we have to delay 10us before + * enabling PLLM_OUT. + */ + udelay(10); + + /* Put OUT1 out of reset state (start to output). */ + setbits_le32(&clk_rst->pllm_out, PLLM_OUT1_RSTN_RESET_DISABLE); + + /* Enable and start MEM(MC) and EMC. */ + clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0); + writel(emc_source, &clk_rst->clk_src_emc); + udelay(IO_STABILIZATION_DELAY); +} + +void clock_cpu0_config(void *entry) +{ + void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100; + + write32((uintptr_t)_estack, &maincpu_stack_pointer); + write32((uintptr_t)entry, &maincpu_entry_point); + write32((uintptr_t)&maincpu_setup, evp_cpu_reset); + + /* Set active CPU cluster to G */ + clrbits_le32(&flow->cluster_control, 1); + + // Set up cclk_brst and divider. + write32((CRC_CCLK_BRST_POL_PLLX_OUT0 << 0) | + (CRC_CCLK_BRST_POL_PLLX_OUT0 << 4) | + (CRC_CCLK_BRST_POL_PLLX_OUT0 << 8) | + (CRC_CCLK_BRST_POL_PLLX_OUT0 << 12) | + (CRC_CCLK_BRST_POL_CPU_STATE_RUN << 28), + &clk_rst->cclk_brst_pol); + write32(CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB, + &clk_rst->super_cclk_div); + + // Enable the clocks for CPUs 0-3. + uint32_t cpu_cmplx_clr = read32(&clk_rst->clk_cpu_cmplx_clr); + cpu_cmplx_clr |= CRC_CLK_CLR_CPU0_STP | CRC_CLK_CLR_CPU1_STP | + CRC_CLK_CLR_CPU2_STP | CRC_CLK_CLR_CPU3_STP; + write32(cpu_cmplx_clr, &clk_rst->clk_cpu_cmplx_clr); + + // Enable other CPU related clocks. + setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU); + setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG); + setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP); +} + +void clock_cpu0_remove_reset(void) +{ + // Disable the reset on the non-CPU parts of the fast cluster. + write32(CRC_RST_CPUG_CLR_NONCPU, + &clk_rst->rst_cpug_cmplx_clr); + // Disable the various resets on the CPUs. + write32(CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_CPU1 | + CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_CPU3 | + CRC_RST_CPUG_CLR_DBG0 | CRC_RST_CPUG_CLR_DBG1 | + CRC_RST_CPUG_CLR_DBG2 | CRC_RST_CPUG_CLR_DBG3 | + CRC_RST_CPUG_CLR_CORE0 | CRC_RST_CPUG_CLR_CORE1 | + CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CORE3 | + CRC_RST_CPUG_CLR_CX0 | CRC_RST_CPUG_CLR_CX1 | + CRC_RST_CPUG_CLR_CX2 | CRC_RST_CPUG_CLR_CX3 | + CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG, + &clk_rst->rst_cpug_cmplx_clr); + + // Disable the reset on the non-CPU parts of the slow cluster. + write32(CRC_RST_CPULP_CLR_NONCPU, + &clk_rst->rst_cpulp_cmplx_clr); + // Disable the various resets on the LP CPU. + write32(CRC_RST_CPULP_CLR_CPU0 | CRC_RST_CPULP_CLR_DBG0 | + CRC_RST_CPULP_CLR_CORE0 | CRC_RST_CPULP_CLR_CX0 | + CRC_RST_CPULP_CLR_L2 | CRC_RST_CPULP_CLR_PDBG, + &clk_rst->rst_cpulp_cmplx_clr); +} + +void clock_halt_avp(void) +{ + for (;;) { + write32(FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ | + FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT, + &flow->halt_cop_events); + } +} + +void clock_init(void) +{ + u32 osc = clock_get_osc_bits(); + + /* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */ + writel(0x2b << 17 | 0xb << 9, &clk_rst->pllc_misc2); + + /* Max out the AVP clock before everything else (need PLLC for that). */ + init_pll(&clk_rst->pllc_base, &clk_rst->pllc_misc, + osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE); + + /* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA + * features section in the TRM). */ + write32(TEGRA_HCLK_RATIO << HCLK_DIVISOR_SHIFT | + TEGRA_PCLK_RATIO << PCLK_DIVISOR_SHIFT, + &clk_rst->clk_sys_rate); + write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, TEGRA_SCLK_KHZ) << + PLL_OUT_RATIO_SHIFT | PLL_OUT_CLKEN | + PLL_OUT_RSTN, &clk_rst->pllc_out); + write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT | + SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT, + &clk_rst->sclk_brst_pol); /* sclk = 300 MHz */ + + /* Change the oscillator drive strength (from U-Boot -- why?) */ + clrsetbits_le32(&clk_rst->osc_ctrl, OSC_XOFS_MASK, + OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); + + /* + * Ambiguous quote from u-boot. TODO: what's this mean? + * "should update same value in PMC_OSC_EDPD_OVER XOFS + * field for warmboot " + */ + clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK, + OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT); + + /* Disable IDDQ for PLLX before we set it up (from U-Boot -- why?) */ + clrbits_le32(&clk_rst->pllx_misc3, PLLX_IDDQ_MASK); + + /* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */ + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT, + &clk_rst->pllp_outa); + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT, + &clk_rst->pllp_outb); + + /* init pllx */ + init_pll(&clk_rst->pllx_base, &clk_rst->pllx_misc, + osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE); + + /* init pllu */ + init_pll(&clk_rst->pllu_base, &clk_rst->pllu_misc, + osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE); + + init_utmip_pll(); + graphics_pll(); +} + +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x) +{ + if (l) writel(l, &clk_rst->clk_enb_l_set); + if (h) writel(h, &clk_rst->clk_enb_h_set); + if (u) writel(u, &clk_rst->clk_enb_u_set); + if (v) writel(v, &clk_rst->clk_enb_v_set); + if (w) writel(w, &clk_rst->clk_enb_w_set); + if (x) writel(x, &clk_rst->clk_enb_x_set); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); + + if (l) writel(l, &clk_rst->rst_dev_l_clr); + if (h) writel(h, &clk_rst->rst_dev_h_clr); + if (u) writel(u, &clk_rst->rst_dev_u_clr); + if (v) writel(v, &clk_rst->rst_dev_v_clr); + if (w) writel(w, &clk_rst->rst_dev_w_clr); + if (x) writel(x, &clk_rst->rst_dev_x_clr); +} + +void clock_reset_l(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_l_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_l_clr); +} + +void clock_reset_h(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_h_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_h_clr); +} + +void clock_reset_u(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_u_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_u_clr); +} + +void clock_reset_v(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_v_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_v_clr); +} + +void clock_reset_w(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_w_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_w_clr); +} + +void clock_reset_x(u32 bit) +{ + writel(bit, &clk_rst->rst_dev_x_set); + udelay(1); + writel(bit, &clk_rst->rst_dev_x_clr); +} diff --git a/src/soc/nvidia/tegra124/display.c b/src/soc/nvidia/tegra124/display.c new file mode 100644 index 0000000000..71fff1c93e --- /dev/null +++ b/src/soc/nvidia/tegra124/display.c @@ -0,0 +1,345 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +struct tegra_dc dc_data; + +int dump = 0; +unsigned long READL(void * p) +{ + unsigned long value; + + /* + * In case of hard hung on readl(p), we can set dump > 1 to print out + * the address accessed. + */ + if (dump > 1) + printk(BIOS_SPEW, "readl %p\n", p); + + value = readl(p); + if (dump) + printk(BIOS_SPEW, "readl %p %08lx\n", p, value); + return value; +} + +void WRITEL(unsigned long value, void * p) +{ + if (dump) + printk(BIOS_SPEW, "writel %p %08lx\n", p, value); + writel(value, p); +} + +/* return in 1000ths of a Hertz */ +static int tegra_dc_calc_refresh(const struct soc_nvidia_tegra124_config *config) +{ + int h_total, v_total, refresh; + int pclk = config->pixel_clock; + + h_total = config->xres + config->hfront_porch + config->hback_porch + + config->hsync_width; + v_total = config->yres + config->vfront_porch + config->vback_porch + + config->vsync_width; + if (!pclk || !h_total || !v_total) + return 0; + refresh = pclk / h_total; + refresh *= 1000; + refresh /= v_total; + return refresh; +} + +static void print_mode(const struct soc_nvidia_tegra124_config *config) +{ + if (config) { + int refresh = tegra_dc_calc_refresh(config); + printk(BIOS_ERR, + "MODE:%dx%d@%d.%03uHz pclk=%d\n", + config->xres, config->yres, + refresh / 1000, refresh % 1000, + config->pixel_clock); + } +} + +static int update_display_mode(struct display_controller *disp_ctrl, + struct soc_nvidia_tegra124_config *config) +{ + print_mode(config); + + WRITEL(0x1, &disp_ctrl->disp.disp_timing_opt); + + WRITEL(config->vref_to_sync << 16 | config->href_to_sync, + &disp_ctrl->disp.ref_to_sync); + + WRITEL(config->vsync_width << 16 | config->hsync_width, + &disp_ctrl->disp.sync_width); + + WRITEL(((config->vback_porch - config->vref_to_sync) << 16) | config->hback_porch, + &disp_ctrl->disp.back_porch); + + WRITEL(((config->vfront_porch + config->vref_to_sync) << 16) | config->hfront_porch, + &disp_ctrl->disp.front_porch); + + WRITEL(config->xres | (config->yres << 16), + &disp_ctrl->disp.disp_active); + + /** + * We want to use PLLD_out0, which is PLLD / 2: + * PixelClock = (PLLD / 2) / ShiftClockDiv / PixelClockDiv. + * + * Currently most panels work inside clock range 50MHz~100MHz, and PLLD + * has some requirements to have VCO in range 500MHz~1000MHz (see + * clock.c for more detail). To simplify calculation, we set + * PixelClockDiv to 1 and ShiftClockDiv to 1. In future these values + * may be calculated by clock_display, to allow wider frequency range. + * + * Note ShiftClockDiv is a 7.1 format value. + */ + const u32 shift_clock_div = 1; + WRITEL((PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT) | + ((shift_clock_div - 1) * 2) << SHIFT_CLK_DIVIDER_SHIFT, + &disp_ctrl->disp.disp_clk_ctrl); + printk(BIOS_DEBUG, "%s: PixelClock=%u, ShiftClockDiv=%u\n", + __func__, config->pixel_clock, shift_clock_div); + return 0; +} + +static void update_window(struct display_controller *disp_ctrl, + struct soc_nvidia_tegra124_config *config) +{ + u32 val; + + WRITEL(WINDOW_A_SELECT, &disp_ctrl->cmd.disp_win_header); + + WRITEL(((config->yres << 16) | config->xres), &disp_ctrl->win.size); + WRITEL(((config->yres << 16) | + (config->xres * config->framebuffer_bits_per_pixel / 8)), + &disp_ctrl->win.prescaled_size); + WRITEL(((config->xres * config->framebuffer_bits_per_pixel / 8 + 31) / + 32 * 32), &disp_ctrl->win.line_stride); + + WRITEL(config->color_depth, &disp_ctrl->win.color_depth); + + WRITEL(config->framebuffer_base, &disp_ctrl->winbuf.start_addr); + WRITEL((V_DDA_INC(0x1000) | H_DDA_INC(0x1000)), &disp_ctrl->win.dda_increment); + + WRITEL(COLOR_WHITE, &disp_ctrl->disp.blend_background_color); + WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); + + WRITEL(WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access); + + val = GENERAL_ACT_REQ | WIN_A_ACT_REQ; + val |= GENERAL_UPDATE | WIN_A_UPDATE; + WRITEL(val, &disp_ctrl->cmd.state_ctrl); + + // Enable win_a + val = READL(&disp_ctrl->win.win_opt); + WRITEL(val | WIN_ENABLE, &disp_ctrl->win.win_opt); +} + +static int tegra_dc_init(struct display_controller *disp_ctrl) +{ + /* do not accept interrupts during initialization */ + WRITEL(0x00000000, &disp_ctrl->cmd.int_mask); + WRITEL(WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, + &disp_ctrl->cmd.state_access); + WRITEL(WINDOW_A_SELECT, &disp_ctrl->cmd.disp_win_header); + WRITEL(0x00000000, &disp_ctrl->win.win_opt); + WRITEL(0x00000000, &disp_ctrl->win.byte_swap); + WRITEL(0x00000000, &disp_ctrl->win.buffer_ctrl); + + WRITEL(0x00000000, &disp_ctrl->win.pos); + WRITEL(0x00000000, &disp_ctrl->win.h_initial_dda); + WRITEL(0x00000000, &disp_ctrl->win.v_initial_dda); + WRITEL(0x00000000, &disp_ctrl->win.dda_increment); + WRITEL(0x00000000, &disp_ctrl->win.dv_ctrl); + + WRITEL(0x01000000, &disp_ctrl->win.blend_layer_ctrl); + WRITEL(0x00000000, &disp_ctrl->win.blend_match_select); + WRITEL(0x00000000, &disp_ctrl->win.blend_nomatch_select); + WRITEL(0x00000000, &disp_ctrl->win.blend_alpha_1bit); + + WRITEL(0x00000000, &disp_ctrl->winbuf.start_addr_hi); + WRITEL(0x00000000, &disp_ctrl->winbuf.addr_h_offset); + WRITEL(0x00000000, &disp_ctrl->winbuf.addr_v_offset); + + WRITEL(0x00000000, &disp_ctrl->com.crc_checksum); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[0]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[1]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[2]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[3]); + WRITEL(0x00000000, &disp_ctrl->disp.disp_signal_opt0); + + return 0; +} + +uint32_t fb_base_mb(void) +{ + return sdram_max_addressable_mb() - FB_SIZE_MB; +} + +/* this is really aimed at the lcd panel. That said, there are two display + * devices on this part and we may someday want to extend it for other boards. + */ +void display_startup(device_t dev) +{ + struct soc_nvidia_tegra124_config *config = dev->chip_info; + struct display_controller *disp_ctrl = (void *)config->display_controller; + struct pwm_controller *pwm = (void *)TEGRA_PWM_BASE; + struct tegra_dc *dc = &dc_data; + u32 plld_rate; + + /* init dc */ + dc->base = (void *)TEGRA_ARM_DISPLAYA; + dc->config = config; + config->dc_data = dc; + + /* Note dp_init may read EDID and change some config values. */ + dp_init(config); + + /* should probably just make it all MiB ... in future */ + u32 framebuffer_size_mb = config->framebuffer_size / MiB; + u32 framebuffer_base_mb= config->framebuffer_base / MiB; + + /* light it all up */ + /* This one may have been done in romstage but that's ok for now. */ + if (config->panel_vdd_gpio){ + gpio_output(config->panel_vdd_gpio, 1); + printk(BIOS_SPEW,"%s: panel_vdd setting gpio %08x to %d\n", + __func__, config->panel_vdd_gpio, 1); + } + udelay(config->vdd_delay_ms * 1000); + if (config->backlight_vdd_gpio){ + gpio_output(config->backlight_vdd_gpio, 1); + printk(BIOS_SPEW,"%s: backlight vdd setting gpio %08x to %d\n", + __func__, config->backlight_vdd_gpio, 1); + } + if (config->lvds_shutdown_gpio){ + gpio_output(config->lvds_shutdown_gpio, 0); + printk(BIOS_SPEW,"%s: lvds shutdown setting gpio %08x to %d\n", + __func__, config->lvds_shutdown_gpio, 0); + } + + if (framebuffer_size_mb == 0){ + framebuffer_size_mb = ALIGN_UP(config->xres * config->yres * + (config->framebuffer_bits_per_pixel / 8), MiB)/MiB; + } + + if (! framebuffer_base_mb) + framebuffer_base_mb = fb_base_mb(); + + config->framebuffer_size = framebuffer_size_mb * MiB; + config->framebuffer_base = framebuffer_base_mb * MiB; + + mmu_config_range(framebuffer_base_mb, framebuffer_size_mb, + config->cache_policy); + + printk(BIOS_SPEW, "LCD frame buffer at %dMiB to %dMiB\n", framebuffer_base_mb, + framebuffer_base_mb + framebuffer_size_mb); + + /* GPIO magic here if needed to start powering up things. You + * really only want to enable vdd, wait a bit, and then enable + * the panel. However ... the timings in the tegra20 dts make + * no sense to me. I'm pretty sure they're wrong. + * The panel_vdd is done in the romstage, so we need only + * light things up here once we're sure it's all working. + */ + + /* The plld is programmed with the assumption of the SHIFT_CLK_DIVIDER + * and PIXEL_CLK_DIVIDER are zero (divide by 1). See the + * update_display_mode() for detail. + */ + plld_rate = clock_display(config->pixel_clock * 2); + if (plld_rate == 0) { + printk(BIOS_ERR, "dc: clock init failed\n"); + return; + } else if (plld_rate != config->pixel_clock * 2) { + printk(BIOS_WARNING, "dc: plld rounded to %u\n", plld_rate); + config->pixel_clock = plld_rate / 2; + } + + /* Init dc */ + if (tegra_dc_init(disp_ctrl)) { + printk(BIOS_ERR, "dc: init failed\n"); + return; + } + + /* Configure dc mode */ + if (update_display_mode(disp_ctrl, config)) { + printk(BIOS_ERR, "dc: failed to configure display mode.\n"); + return; + } + + /* Enable dp */ + dp_enable(dc->out); + + /* Init frame buffer */ + memset((void *)(framebuffer_base_mb*MiB), 0x00, + framebuffer_size_mb*MiB); + + update_window(disp_ctrl, config); + + /* Set up Tegra PWM n (where n is specified in config->pwm) to drive the + * panel backlight. + */ + printk(BIOS_SPEW, "%s: enable panel backlight pwm\n", __func__); + WRITEL(((1 << NV_PWM_CSR_ENABLE_SHIFT) | + (220 << NV_PWM_CSR_PULSE_WIDTH_SHIFT) | /* 220/256 */ + 0x02e), /* frequency divider */ + &pwm->pwm[config->pwm].csr); + + udelay(config->pwm_to_bl_delay_ms * 1000); + if (config->backlight_en_gpio){ + gpio_output(config->backlight_en_gpio, 1); + printk(BIOS_SPEW,"%s: backlight enable setting gpio %08x to %d\n", + __func__, config->backlight_en_gpio, 1); + } + + printk(BIOS_INFO, "%s: display init done.\n", __func__); + + /* tell depthcharge ... + */ + struct edid edid; + edid.bytes_per_line = ((config->xres * config->framebuffer_bits_per_pixel / 8 + 31) / + 32 * 32); + edid.x_resolution = edid.bytes_per_line / (config->framebuffer_bits_per_pixel / 8); + edid.y_resolution = config->yres; + edid.framebuffer_bits_per_pixel = config->framebuffer_bits_per_pixel; + set_vbe_mode_info_valid(&edid, (uintptr_t)(framebuffer_base_mb*MiB)); +} + diff --git a/src/soc/nvidia/tegra124/dma.c b/src/soc/nvidia/tegra124/dma.c new file mode 100644 index 0000000000..37375fd797 --- /dev/null +++ b/src/soc/nvidia/tegra124/dma.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +struct apb_dma * const apb_dma = (struct apb_dma *)TEGRA_APB_DMA_BASE; + +#define APB_DMA_OFFSET(n) \ + (struct apb_dma_channel_regs *)(TEGRA_APB_DMA_BASE + n) +struct apb_dma_channel apb_dma_channels[] = { + { .num = 0, .regs = APB_DMA_OFFSET(0x1000) }, + { .num = 1, .regs = APB_DMA_OFFSET(0x1040) }, + { .num = 2, .regs = APB_DMA_OFFSET(0x1080) }, + { .num = 3, .regs = APB_DMA_OFFSET(0x10c0) }, + { .num = 4, .regs = APB_DMA_OFFSET(0x1100) }, + { .num = 5, .regs = APB_DMA_OFFSET(0x1140) }, + { .num = 6, .regs = APB_DMA_OFFSET(0x1180) }, + { .num = 7, .regs = APB_DMA_OFFSET(0x11c0) }, + { .num = 8, .regs = APB_DMA_OFFSET(0x1200) }, + { .num = 9, .regs = APB_DMA_OFFSET(0x1240) }, + { .num = 10, .regs = APB_DMA_OFFSET(0x1280) }, + { .num = 11, .regs = APB_DMA_OFFSET(0x12c0) }, + { .num = 12, .regs = APB_DMA_OFFSET(0x1300) }, + { .num = 13, .regs = APB_DMA_OFFSET(0x1340) }, + { .num = 14, .regs = APB_DMA_OFFSET(0x1380) }, + { .num = 15, .regs = APB_DMA_OFFSET(0x13c0) }, + { .num = 16, .regs = APB_DMA_OFFSET(0x1400) }, + { .num = 17, .regs = APB_DMA_OFFSET(0x1440) }, + { .num = 18, .regs = APB_DMA_OFFSET(0x1480) }, + { .num = 19, .regs = APB_DMA_OFFSET(0x14c0) }, + { .num = 20, .regs = APB_DMA_OFFSET(0x1500) }, + { .num = 21, .regs = APB_DMA_OFFSET(0x1540) }, + { .num = 22, .regs = APB_DMA_OFFSET(0x1580) }, + { .num = 23, .regs = APB_DMA_OFFSET(0x15c0) }, + { .num = 24, .regs = APB_DMA_OFFSET(0x1600) }, + { .num = 25, .regs = APB_DMA_OFFSET(0x1640) }, + { .num = 26, .regs = APB_DMA_OFFSET(0x1680) }, + { .num = 27, .regs = APB_DMA_OFFSET(0x16c0) }, + { .num = 28, .regs = APB_DMA_OFFSET(0x1700) }, + { .num = 29, .regs = APB_DMA_OFFSET(0x1740) }, + { .num = 30, .regs = APB_DMA_OFFSET(0x1780) }, + { .num = 31, .regs = APB_DMA_OFFSET(0x17c0) }, +}; + +int dma_busy(struct apb_dma_channel * const channel) +{ + /* + * In continuous mode, the BSY_n bit in APB_DMA_STATUS and + * BSY in APBDMACHAN_CHANNEL_n_STA_0 will remain set as '1' so long + * as the channel is enabled. So for this function we'll use the + * DMA_ACTIVITY bit. + */ + return read32(&channel->regs->sta) & APB_STA_DMA_ACTIVITY ? 1 : 0; +} +/* claim a DMA channel */ +struct apb_dma_channel * const dma_claim(void) +{ + int i; + struct apb_dma_channel_regs *regs = NULL; + + /* + * Set global enable bit, otherwise register access to channel + * DMA registers will not be possible. + */ + setbits_le32(&apb_dma->command, APB_COMMAND_GEN); + + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + regs = apb_dma_channels[i].regs; + + if (!apb_dma_channels[i].in_use) { + u32 status = read32(®s->sta); + if (status & (1 << i)) { + /* FIXME: should this be fatal? */ + printk(BIOS_DEBUG, "%s: DMA channel %d busy?\n", + __func__, i); + } + break; + } + } + + if (i == ARRAY_SIZE(apb_dma_channels)) + return NULL; + + apb_dma_channels[i].in_use = 1; + return &apb_dma_channels[i]; +} + +/* release a DMA channel */ +void dma_release(struct apb_dma_channel * const channel) +{ + int i; + + /* FIXME: make this "thread" friendly */ + while (dma_busy(channel)) + ; + + channel->in_use = 0; + + /* clear the global enable bit if no channels are in use */ + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + if (apb_dma_channels[i].in_use) + return; + } + + clrbits_le32(&apb_dma->command, APB_COMMAND_GEN); +} + +int dma_start(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Set ENB bit for this channel */ + setbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} + +int dma_stop(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Clear ENB bit for this channel */ + clrbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} diff --git a/src/soc/nvidia/tegra124/dp.c b/src/soc/nvidia/tegra124/dp.c new file mode 100644 index 0000000000..1e125f6ad0 --- /dev/null +++ b/src/soc/nvidia/tegra124/dp.c @@ -0,0 +1,1477 @@ +/* + * drivers/video/tegra/dc/dp.c + * + * Copyright (c) 2011-2013, NVIDIA Corporation. + * Copyright 2014 Google Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +enum { + DP_LT_SUCCESS = 0, + DP_LT_FAILED = -1, +}; + +struct tegra_dc_dp_data dp_data; + +static inline u32 tegra_dpaux_readl(struct tegra_dc_dp_data *dp, u32 reg) +{ + void *addr = dp->aux_base + (u32) (reg << 2); + u32 reg_val = READL(addr); + return reg_val; +} + +static inline void tegra_dpaux_writel(struct tegra_dc_dp_data *dp, + u32 reg, u32 val) +{ + void *addr = dp->aux_base + (u32) (reg << 2); + WRITEL(val, addr); +} + +static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dc_dp_data *dp, + u32 reg, u32 mask, u32 exp_val, + u32 poll_interval_us, + u32 timeout_us) +{ + u32 reg_val = 0; + u32 temp = timeout_us; + + do { + udelay(poll_interval_us); + reg_val = tegra_dpaux_readl(dp, reg); + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + } while ((reg_val & mask) != exp_val); + + if ((reg_val & mask) == exp_val) + return 0; /* success */ + printk(BIOS_ERR, + "dpaux_poll_register 0x%x: timeout: " + "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n", + reg, reg_val, mask, exp_val); + return temp; +} + +static inline int tegra_dpaux_wait_transaction(struct tegra_dc_dp_data *dp) +{ + /* According to DP spec, each aux transaction needs to finish + within 40ms. */ + if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL, + DPAUX_DP_AUXCTL_TRANSACTREQ_MASK, + DPAUX_DP_AUXCTL_TRANSACTREQ_DONE, + 100, DP_AUX_TIMEOUT_MS * 1000) != 0) { + printk(BIOS_INFO, "dp: DPAUX transaction timeout\n"); + return -1; + } + return 0; +} + +static int tegra_dc_dpaux_write_chunk(struct tegra_dc_dp_data *dp, u32 cmd, + u32 addr, u8 *data, u32 *size, + u32 *aux_stat) +{ + int i; + u32 reg_val; + u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES; + u32 defer_retries = DP_AUX_DEFER_MAX_TRIES; + u32 temp_data; + + if (*size > DP_AUX_MAX_BYTES) + return -1; /* only write one chunk of data */ + + /* Make sure the command is write command */ + switch (cmd) { + case DPAUX_DP_AUXCTL_CMD_I2CWR: + case DPAUX_DP_AUXCTL_CMD_MOTWR: + case DPAUX_DP_AUXCTL_CMD_AUXWR: + break; + default: + printk(BIOS_ERR, "dp: aux write cmd 0x%x is invalid\n", + cmd); + return -1; + } + + tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr); + for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) { + memcpy(&temp_data, data, 4); + tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i), temp_data); + data += 4; + } + + reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL); + reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK; + reg_val |= cmd; + reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD; + reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); + + while ((timeout_retries > 0) && (defer_retries > 0)) { + if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) || + (defer_retries != DP_AUX_DEFER_MAX_TRIES)) + udelay(1); + + reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING; + tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val); + + if (tegra_dpaux_wait_transaction(dp)) + printk(BIOS_ERR, "dp: aux write transaction timeout\n"); + + *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); + + if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) { + if (timeout_retries-- > 0) { + printk(BIOS_INFO, "dp: aux write retry (0x%x) -- %d\n", + *aux_stat, timeout_retries); + /* clear the error bits */ + tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); + continue; + } else { + printk(BIOS_ERR, "dp: aux write got error (0x%x)\n", + *aux_stat); + return -1; + } + } + + if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) || + (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) { + if (defer_retries-- > 0) { + printk(BIOS_INFO, "dp: aux write defer (0x%x) -- %d\n", + *aux_stat, defer_retries); + /* clear the error bits */ + tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); + continue; + } else { + printk(BIOS_ERR, "dp: aux write defer exceeds max retries " + "(0x%x)\n", *aux_stat); + return -1; + } + } + + if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) == + DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) { + *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK); + return 0; + } else { + printk(BIOS_ERR, "dp: aux write failed (0x%x)\n", + *aux_stat); + return -1; + } + } + /* Should never come to here */ + return -1; +} + +static int tegra_dc_dpaux_read_chunk(struct tegra_dc_dp_data *dp, u32 cmd, + u32 addr, u8 *data, u32 *size, + u32 *aux_stat) +{ + u32 reg_val; + u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES; + u32 defer_retries = DP_AUX_DEFER_MAX_TRIES; + + if (*size > DP_AUX_MAX_BYTES) + return -1; /* only read one chunk */ + + /* Check to make sure the command is read command */ + switch (cmd) { + case DPAUX_DP_AUXCTL_CMD_I2CRD: + case DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT: + case DPAUX_DP_AUXCTL_CMD_MOTRD: + case DPAUX_DP_AUXCTL_CMD_AUXRD: + break; + default: + printk(BIOS_ERR, "dp: aux read cmd 0x%x is invalid\n", + cmd); + return -1; + } + + *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); + if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { + printk(BIOS_SPEW, "dp: HPD is not detected\n"); + return -1; + } + + tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr); + + reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL); + reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK; + reg_val |= cmd; + reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD; + reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT); + while ((timeout_retries > 0) && (defer_retries > 0)) { + if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) || + (defer_retries != DP_AUX_DEFER_MAX_TRIES)) + udelay(DP_DPCP_RETRY_SLEEP_NS * 2); + + reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING; + tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val); + + if (tegra_dpaux_wait_transaction(dp)) + printk(BIOS_INFO, "dp: aux read transaction timeout\n"); + + *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); + + if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) || + (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) { + if (timeout_retries-- > 0) { + printk(BIOS_INFO, "dp: aux read retry (0x%x)" + " -- %d\n", *aux_stat, + timeout_retries); + /* clear the error bits */ + tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, + *aux_stat); + continue; /* retry */ + } else { + printk(BIOS_ERR, "dp: aux read got error" + " (0x%x)\n", *aux_stat); + return -1; + } + } + + if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) || + (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) { + if (defer_retries-- > 0) { + printk(BIOS_INFO, "dp: aux read defer (0x%x) -- %d\n", + *aux_stat, defer_retries); + /* clear the error bits */ + tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT, *aux_stat); + continue; + } else { + printk(BIOS_INFO, "dp: aux read defer exceeds max retries " + "(0x%x)\n", *aux_stat); + return -1; + } + } + + if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) == + DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) { + int i; + u32 temp_data[4]; + + for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) + temp_data[i] = tegra_dpaux_readl(dp, + DPAUX_DP_AUXDATA_READ_W(i)); + + *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK); + memcpy(data, temp_data, *size); + + return 0; + } else { + printk(BIOS_ERR, "dp: aux read failed (0x%x\n", + *aux_stat); + return -1; + } + } + /* Should never come to here */ + printk(BIOS_ERR, "%s: can't\n", __func__); + return -1; +} + +static int tegra_dc_dpaux_read(struct tegra_dc_dp_data *dp, u32 cmd, u32 addr, + u8 *data, u32 *size, u32 *aux_stat) +{ + u32 finished = 0; + u32 cur_size; + int ret = 0; + + do { + cur_size = *size - finished; + if (cur_size > DP_AUX_MAX_BYTES) + cur_size = DP_AUX_MAX_BYTES; + + ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr, + data, &cur_size, aux_stat); + if (ret) + break; + + /* cur_size should be the real size returned */ + addr += cur_size; + data += cur_size; + finished += cur_size; + + } while (*size > finished); + + *size = finished; + return ret; +} + +static int tegra_dc_dp_dpcd_read(struct tegra_dc_dp_data *dp, u32 cmd, + u8 * data_ptr) +{ + u32 size = 1; + u32 status = 0; + int ret; + + ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, + cmd, data_ptr, &size, &status); + if (ret) + printk(BIOS_ERR, + "dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n", + cmd, status); + + return ret; +} + +static int tegra_dc_dp_dpcd_write(struct tegra_dc_dp_data *dp, u32 cmd, + u8 data) +{ + u32 size = 1; + u32 status = 0; + int ret; + + ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR, + cmd, &data, &size, &status); + if (ret) + printk(BIOS_ERR, + "dp: Failed to write DPCD data. CMD 0x%x, Status 0x%x\n", + cmd, status); + return ret; +} + +static int tegra_dc_i2c_aux_read(struct tegra_dc_dp_data *dp, u32 i2c_addr, + u8 addr, u8 *data, u32 *size, u32 *aux_stat) +{ + u32 finished = 0; + int ret = 0; + + do { + u32 cur_size = MIN(DP_AUX_MAX_BYTES, *size - finished); + + u32 len = 1; + ret = tegra_dc_dpaux_write_chunk( + dp, DPAUX_DP_AUXCTL_CMD_MOTWR, i2c_addr, + &addr, &len, aux_stat); + if (ret) { + printk(BIOS_ERR, "%s: error sending address to read.\n", + __func__); + break; + } + + ret = tegra_dc_dpaux_read_chunk( + dp, DPAUX_DP_AUXCTL_CMD_I2CRD, i2c_addr, + data, &cur_size, aux_stat); + if (ret) { + printk(BIOS_ERR, "%s: error reading data.\n", __func__); + break; + } + + /* cur_size should be the real size returned */ + addr += cur_size; + data += cur_size; + finished += cur_size; + } while (*size > finished); + + *size = finished; + return ret; +} + +static void tegra_dc_dpaux_enable(struct tegra_dc_dp_data *dp) +{ + /* clear interrupt */ + tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff); + /* do not enable interrupt for now. Enable them when Isr in place */ + tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0); + + tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL, + DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 | + DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 | + 0x18 << DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT | + DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE); + + tegra_dpaux_writel(dp, DPAUX_HYBRID_SPARE, + DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP); +} + +static void tegra_dc_dp_dump_link_cfg(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *link_cfg) +{ + printk(BIOS_INFO, "DP config: cfg_name " + "cfg_value\n"); + printk(BIOS_INFO, " Lane Count %d\n", + link_cfg->max_lane_count); + printk(BIOS_INFO, " SupportEnhancedFraming %s\n", + link_cfg->support_enhanced_framing ? "Y" : "N"); + printk(BIOS_INFO, " Bandwidth %d\n", + link_cfg->max_link_bw); + printk(BIOS_INFO, " bpp %d\n", + link_cfg->bits_per_pixel); + printk(BIOS_INFO, " EnhancedFraming %s\n", + link_cfg->enhanced_framing ? "Y" : "N"); + printk(BIOS_INFO, " Scramble_enabled %s\n", + link_cfg->scramble_ena ? "Y" : "N"); + printk(BIOS_INFO, " LinkBW %d\n", + link_cfg->link_bw); + printk(BIOS_INFO, " lane_count %d\n", + link_cfg->lane_count); + printk(BIOS_INFO, " activespolarity %d\n", + link_cfg->activepolarity); + printk(BIOS_INFO, " active_count %d\n", + link_cfg->active_count); + printk(BIOS_INFO, " tu_size %d\n", + link_cfg->tu_size); + printk(BIOS_INFO, " active_frac %d\n", + link_cfg->active_frac); + printk(BIOS_INFO, " watermark %d\n", + link_cfg->watermark); + printk(BIOS_INFO, " hblank_sym %d\n", + link_cfg->hblank_sym); + printk(BIOS_INFO, " vblank_sym %d\n", + link_cfg->vblank_sym); +} + +static int _tegra_dp_lower_link_config(struct tegra_dc_dp_data *dp, + struct tegra_dc_dp_link_config *cfg) +{ + + switch (cfg->link_bw){ + case SOR_LINK_SPEED_G1_62: + if (cfg->max_link_bw > SOR_LINK_SPEED_G1_62) + cfg->link_bw = SOR_LINK_SPEED_G2_7; + cfg->lane_count /= 2; + break; + case SOR_LINK_SPEED_G2_7: + cfg->link_bw = SOR_LINK_SPEED_G1_62; + break; + case SOR_LINK_SPEED_G5_4: + if (cfg->lane_count == 1) { + cfg->link_bw = SOR_LINK_SPEED_G2_7; + cfg->lane_count = cfg->max_lane_count; + } else + cfg->lane_count /= 2; + break; + default: + printk(BIOS_ERR,"dp: Error link rate %d\n", cfg->link_bw); + return DP_LT_FAILED; + } + + return (cfg->lane_count > 0) ? DP_LT_SUCCESS : DP_LT_FAILED; +} + +/* Calcuate if given cfg can meet the mode request. */ +/* Return true if mode is possible, false otherwise. */ +static int tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp, + const struct soc_nvidia_tegra124_config *config, + struct tegra_dc_dp_link_config *link_cfg) +{ + const u32 link_rate = 27 * link_cfg->link_bw * 1000 * 1000; + const u64 f = 100000; /* precision factor */ + + u32 num_linkclk_line; /* Number of link clocks per line */ + u64 ratio_f; /* Ratio of incoming to outgoing data rate */ + + u64 frac_f; + u64 activesym_f; /* Activesym per TU */ + u64 activecount_f; + u32 activecount; + u32 activepolarity; + u64 approx_value_f; + u32 activefrac = 0; + u64 accumulated_error_f = 0; + u32 lowest_neg_activecount = 0; + u32 lowest_neg_activepolarity = 0; + u32 lowest_neg_tusize = 64; + u32 num_symbols_per_line; + u64 lowest_neg_activefrac = 0; + u64 lowest_neg_error_f = 64 * f; + u64 watermark_f; + + int i; + int neg; + + if (!link_rate || !link_cfg->lane_count || !config->pixel_clock || + !link_cfg->bits_per_pixel) + return -1; + + if ((u64)config->pixel_clock * link_cfg->bits_per_pixel >= + (u64)link_rate * 8 * link_cfg->lane_count) + return -1; + + num_linkclk_line = (u32)((u64)link_rate * (u64)config->xres / config->pixel_clock); + + ratio_f = (u64)config->pixel_clock * link_cfg->bits_per_pixel * f; + ratio_f /= 8; + ratio_f = (u64)(ratio_f / (link_rate * link_cfg->lane_count)); + + for (i = 64; i >= 32; --i) { + activesym_f = ratio_f * i; + activecount_f = (u64)(activesym_f / (u32)f) * f; + frac_f = activesym_f - activecount_f; + activecount = (u32)((u64)(activecount_f / (u32)f)); + + if (frac_f < (f / 2)) /* fraction < 0.5 */ + activepolarity = 0; + else { + activepolarity = 1; + frac_f = f - frac_f; + } + + if (frac_f != 0) { + frac_f = (u64)((f * f) / frac_f); /* 1/fraction */ + if (frac_f > (15 * f)) + activefrac = activepolarity ? 1 : 15; + else + activefrac = activepolarity ? + (u32)((u64)(frac_f / (u32)f)) + 1 : + (u32)((u64)(frac_f / (u32)f)); + } + + if (activefrac == 1) + activepolarity = 0; + + if (activepolarity == 1) + approx_value_f = activefrac ? (u64)( + (activecount_f + (activefrac * f - f) * f) / + (activefrac * f)) : + activecount_f + f; + else + approx_value_f = activefrac ? + activecount_f + (u64)(f / activefrac) : + activecount_f; + + if (activesym_f < approx_value_f) { + accumulated_error_f = num_linkclk_line * + (u64)((approx_value_f - activesym_f) / i); + neg = 1; + } else { + accumulated_error_f = num_linkclk_line * + (u64)((activesym_f - approx_value_f) / i); + neg = 0; + } + + if ((neg && (lowest_neg_error_f > accumulated_error_f)) || + (accumulated_error_f == 0)) { + lowest_neg_error_f = accumulated_error_f; + lowest_neg_tusize = i; + lowest_neg_activecount = activecount; + lowest_neg_activepolarity = activepolarity; + lowest_neg_activefrac = activefrac; + + if (accumulated_error_f == 0) + break; + } + } + + if (lowest_neg_activefrac == 0) { + link_cfg->activepolarity = 0; + link_cfg->active_count = lowest_neg_activepolarity ? + lowest_neg_activecount : lowest_neg_activecount - 1; + link_cfg->tu_size = lowest_neg_tusize; + link_cfg->active_frac = 1; + } else { + link_cfg->activepolarity = lowest_neg_activepolarity; + link_cfg->active_count = (u32)lowest_neg_activecount; + link_cfg->tu_size = lowest_neg_tusize; + link_cfg->active_frac = (u32)lowest_neg_activefrac; + } + + watermark_f = (u64)((ratio_f * link_cfg->tu_size * (f - ratio_f)) / f); + link_cfg->watermark = (u32)((u64)((watermark_f + lowest_neg_error_f) / + f)) + link_cfg->bits_per_pixel / 4 - 1; + num_symbols_per_line = (config->xres * link_cfg->bits_per_pixel) / + (8 * link_cfg->lane_count); + + if (link_cfg->watermark > 30) { + printk(BIOS_INFO, + "dp: sor setting: unable to get a good tusize, " + "force watermark to 30.\n"); + link_cfg->watermark = 30; + return -1; + } else if (link_cfg->watermark > num_symbols_per_line) { + printk(BIOS_INFO, + "dp: sor setting: force watermark to the number " + "of symbols in the line.\n"); + link_cfg->watermark = num_symbols_per_line; + return -1; + } + + /* Refer to dev_disp.ref for more information. */ + /* # symbols/hblank = ((SetRasterBlankEnd.X + SetRasterSize.Width - */ + /* SetRasterBlankStart.X - 7) * link_clk / pclk) */ + /* - 3 * enhanced_framing - Y */ + /* where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12 */ + link_cfg->hblank_sym = (int)((u64)(((u64)(config->hback_porch + + config->hfront_porch + config->hsync_width - 7) * + link_rate) / config->pixel_clock)) - + 3 * link_cfg->enhanced_framing - + (12 / link_cfg->lane_count); + + if (link_cfg->hblank_sym < 0) + link_cfg->hblank_sym = 0; + + + /* Refer to dev_disp.ref for more information. */ + /* # symbols/vblank = ((SetRasterBlankStart.X - */ + /* SetRasterBlankEen.X - 25) * link_clk / pclk) */ + /* - Y - 1; */ + /* where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39 */ + link_cfg->vblank_sym = (int)((u64)((u64)(config->xres - 25) + * link_rate / config->pixel_clock)) - (36 / + link_cfg->lane_count) - 4; + + if (link_cfg->vblank_sym < 0) + link_cfg->vblank_sym = 0; + + link_cfg->is_valid = 1; + tegra_dc_dp_dump_link_cfg(dp, link_cfg); + + return 0; +} + +static int tegra_dc_dp_init_max_link_cfg( + struct soc_nvidia_tegra124_config *config, + struct tegra_dc_dp_data *dp, + struct tegra_dc_dp_link_config *link_cfg) +{ + u8 dpcd_data; + int ret; + + CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LANE_COUNT, + &dpcd_data)); + link_cfg->max_lane_count = dpcd_data & NV_DPCD_MAX_LANE_COUNT_MASK; + link_cfg->tps3_supported = (dpcd_data & + NV_DPCD_MAX_LANE_COUNT_TPS3_SUPPORTED_YES) ? 1 : 0; + + link_cfg->support_enhanced_framing = + (dpcd_data & NV_DPCD_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ? + 1 : 0; + + CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_DOWNSPREAD, + &dpcd_data)); + link_cfg->downspread = (dpcd_data & NV_DPCD_MAX_DOWNSPREAD_VAL_0_5_PCT)? + 1 : 0; + + CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_TRAINING_AUX_RD_INTERVAL, + &link_cfg->aux_rd_interval)); + + CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_MAX_LINK_BANDWIDTH, + &link_cfg->max_link_bw)); + + link_cfg->bits_per_pixel = config->panel_bits_per_pixel; + + /* + * Set to a high value for link training and attach. + * Will be re-programmed when dp is enabled. + */ + link_cfg->drive_current = config->drive_current; + link_cfg->preemphasis = config->preemphasis; + link_cfg->postcursor = config->postcursor; + + CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP, + &dpcd_data)); + link_cfg->alt_scramber_reset_cap = + (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_ASC_RESET_YES) ? + 1 : 0; + link_cfg->only_enhanced_framing = + (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ? + 1 : 0; + + link_cfg->lane_count = link_cfg->max_lane_count; + link_cfg->link_bw = link_cfg->max_link_bw; + link_cfg->enhanced_framing = link_cfg->support_enhanced_framing; + + tegra_dc_dp_calc_config(dp, config, link_cfg); + return 0; +} + +static int tegra_dc_dp_set_assr(struct tegra_dc_dp_data *dp, int ena) +{ + int ret; + + u8 dpcd_data = ena ? + NV_DPCD_EDP_CONFIG_SET_ASC_RESET_ENABLE : + NV_DPCD_EDP_CONFIG_SET_ASC_RESET_DISABLE; + + CHECK_RET(tegra_dc_dp_dpcd_write(dp, NV_DPCD_EDP_CONFIG_SET, + dpcd_data)); + + /* Also reset the scrambler to 0xfffe */ + tegra_dc_sor_set_internal_panel(&dp->sor, ena); + return 0; +} + +static int tegra_dp_set_link_bandwidth(struct tegra_dc_dp_data *dp, u8 link_bw) +{ + tegra_dc_sor_set_link_bandwidth(&dp->sor, link_bw); + + /* Sink side */ + return tegra_dc_dp_dpcd_write(dp, NV_DPCD_LINK_BANDWIDTH_SET, link_bw); +} + +static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *link_cfg) +{ + u8 dpcd_data; + int ret; + + /* check if panel support enhanched_framing */ + dpcd_data = link_cfg->lane_count; + if (link_cfg->enhanced_framing) + dpcd_data |= NV_DPCD_LANE_COUNT_SET_ENHANCEDFRAMING_T; + CHECK_RET(tegra_dc_dp_dpcd_write(dp, NV_DPCD_LANE_COUNT_SET, + dpcd_data)); + + tegra_dc_sor_set_lane_count(&dp->sor, link_cfg->lane_count); + + /* Also power down lanes that will not be used */ + return 0; +} + +static int tegra_dc_dp_link_trained(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *cfg) +{ + u32 lane; + u8 mask; + u8 data; + int ret; + + for (lane = 0; lane < cfg->lane_count; ++lane) { + CHECK_RET(tegra_dc_dp_dpcd_read(dp, (lane/2) ? + NV_DPCD_LANE2_3_STATUS : NV_DPCD_LANE0_1_STATUS, + &data)); + mask = (lane & 1) ? + NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES | + NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES | + NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES : + NV_DPCD_STATUS_LANEX_CR_DONE_YES | + NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_YES | + NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_YES; + if ((data & mask) != mask) + return -1; + } + return 0; +} + +static int tegra_dp_channel_eq_status(struct tegra_dc_dp_data *dp) +{ + u32 cnt; + u32 n_lanes = dp->link_cfg.lane_count; + u8 data; + u8 ce_done = 1; + + for (cnt = 0; cnt < n_lanes / 2; cnt++) { + tegra_dc_dp_dpcd_read(dp, (NV_DPCD_LANE0_1_STATUS + cnt), &data); + + if (n_lanes == 1) { + ce_done = (data & + (0x1 << NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) && + (data & (0x1 << NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT)); + break; + } else if (!(data & (0x1 << NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) || + !(data & (0x1 << NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT)) || + !(data & (0x1 << NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT)) || + !(data & (0x1 << NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT))) + return 0; + } + + if (ce_done) { + tegra_dc_dp_dpcd_read(dp, NV_DPCD_LANE_ALIGN_STATUS_UPDATED, &data); + if (!(data & NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES)) + ce_done = 0; + } + + return ce_done; +} + +static u8 tegra_dp_clock_recovery_status(struct tegra_dc_dp_data *dp) +{ + u32 cnt; + u32 n_lanes = dp->link_cfg.lane_count; + u8 data_ptr; + + for (cnt = 0; cnt < n_lanes / 2; cnt++) { + tegra_dc_dp_dpcd_read(dp, + (NV_DPCD_LANE0_1_STATUS + cnt), &data_ptr); + + if (n_lanes == 1) + return (data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ? 1 : 0; + else if (!(data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) || + !(data_ptr & + (NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES))) + return 0; + } + + return 1; +} + +static void tegra_dp_lt_adjust(struct tegra_dc_dp_data *dp, + u32 pe[4], u32 vs[4], u32 pc[4], + u8 pc_supported) +{ + size_t cnt; + u8 data_ptr; + u32 n_lanes = dp->link_cfg.lane_count; + + for (cnt = 0; cnt < n_lanes / 2; cnt++) { + tegra_dc_dp_dpcd_read(dp, + (NV_DPCD_LANE0_1_ADJUST_REQ + cnt), &data_ptr); + pe[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_PE_MASK) >> + NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT; + vs[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_DC_MASK) >> + NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT; + pe[1 + 2 * cnt] = + (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK) >> + NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT; + vs[1 + 2 * cnt] = + (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK) >> + NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT; + } + if (pc_supported) { + tegra_dc_dp_dpcd_read(dp, + NV_DPCD_ADJUST_REQ_POST_CURSOR2, &data_ptr); + for (cnt = 0; cnt < n_lanes; cnt++) { + pc[cnt] = (data_ptr >> + NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(cnt)) & + NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK; + } + } +} + +static inline u32 tegra_dp_wait_aux_training(struct tegra_dc_dp_data *dp, + u8 is_clk_recovery) +{ + if (!dp->link_cfg.aux_rd_interval) + is_clk_recovery ? udelay(200) : + udelay(500); + else + mdelay(dp->link_cfg.aux_rd_interval * 4); + + return dp->link_cfg.aux_rd_interval; +} + +static void tegra_dp_tpg(struct tegra_dc_dp_data *dp, u32 tp, u32 n_lanes) +{ + u8 data = (tp == training_pattern_disabled) + ? (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F) + : (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T); + + tegra_dc_sor_set_dp_linkctl(&dp->sor, 1, tp, &dp->link_cfg); + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, data); +} + +static int tegra_dp_link_config(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *link_cfg) +{ + u8 dpcd_data; + u32 retry; + + if (link_cfg->lane_count == 0) { + printk(BIOS_ERR, "dp: error: lane count is 0. " + "Can not set link config.\n"); + return DP_LT_FAILED; + } + + /* Set power state if it is not in normal level */ + if(tegra_dc_dp_dpcd_read(dp, NV_DPCD_SET_POWER, &dpcd_data)) + return DP_LT_FAILED; + + if (dpcd_data == NV_DPCD_SET_POWER_VAL_D3_PWRDWN) { + dpcd_data = NV_DPCD_SET_POWER_VAL_D0_NORMAL; + + /* DP spec requires 3 retries */ + for (retry = 3; retry > 0; --retry){ + if (tegra_dc_dp_dpcd_write(dp, NV_DPCD_SET_POWER, dpcd_data)) + break; + if (retry == 1){ + printk(BIOS_ERR, "dp: Failed to set DP panel power\n"); + return DP_LT_FAILED; + } + } + } + + /* Enable ASSR if possible */ + if (link_cfg->alt_scramber_reset_cap) + if(tegra_dc_dp_set_assr(dp, 1)) + return DP_LT_FAILED; + + if (tegra_dp_set_link_bandwidth(dp, link_cfg->link_bw)) { + printk(BIOS_ERR, "dp: Failed to set link bandwidth\n"); + return DP_LT_FAILED; + } + if (tegra_dp_set_lane_count(dp, link_cfg)) { + printk(BIOS_ERR, "dp: Failed to set lane count\n"); + return DP_LT_FAILED; + } + tegra_dc_sor_set_dp_linkctl(&dp->sor, 1, training_pattern_none, + link_cfg); + return DP_LT_SUCCESS; +} + +static int tegra_dp_lower_link_config(struct tegra_dc_dp_data *dp, + struct tegra_dc_dp_link_config *cfg) +{ + struct tegra_dc_dp_link_config tmp_cfg; + + tmp_cfg = dp->link_cfg; + cfg->is_valid = 0; + + if (_tegra_dp_lower_link_config(dp, cfg)) + goto fail; + + if (tegra_dc_dp_calc_config(dp, dp->dc->config, cfg)) + goto fail; + tegra_dp_link_config(dp, cfg); + + return DP_LT_SUCCESS; +fail: + dp->link_cfg = tmp_cfg; + tegra_dp_link_config(dp, &tmp_cfg); + return DP_LT_FAILED; +} + +static void tegra_dp_lt_config(struct tegra_dc_dp_data *dp, + u32 pe[4], u32 vs[4], u32 pc[4]) +{ + struct tegra_dc_sor_data *sor = &dp->sor; + u32 n_lanes = dp->link_cfg.lane_count; + u8 pc_supported = dp->link_cfg.tps3_supported; + u32 cnt; + u32 val; + + for (cnt = 0; cnt < n_lanes; cnt++) { + u32 mask = 0; + u32 pe_reg, vs_reg, pc_reg; + u32 shift = 0; + + switch (cnt) { + case 0: + mask = NV_SOR_PR_LANE2_DP_LANE0_MASK; + shift = NV_SOR_PR_LANE2_DP_LANE0_SHIFT; + break; + case 1: + mask = NV_SOR_PR_LANE1_DP_LANE1_MASK; + shift = NV_SOR_PR_LANE1_DP_LANE1_SHIFT; + break; + case 2: + mask = NV_SOR_PR_LANE0_DP_LANE2_MASK; + shift = NV_SOR_PR_LANE0_DP_LANE2_SHIFT; + break; + case 3: + mask = NV_SOR_PR_LANE3_DP_LANE3_MASK; + shift = NV_SOR_PR_LANE3_DP_LANE3_SHIFT; + break; + default: + printk(BIOS_ERR, + "dp: incorrect lane cnt\n"); + } + + pe_reg = tegra_dp_pe_regs[pc[cnt]][vs[cnt]][pe[cnt]]; + vs_reg = tegra_dp_vs_regs[pc[cnt]][vs[cnt]][pe[cnt]]; + pc_reg = tegra_dp_pc_regs[pc[cnt]][vs[cnt]][pe[cnt]]; + + tegra_dp_set_pe_vs_pc(sor, mask, pe_reg << shift, + vs_reg << shift, pc_reg << shift, pc_supported); + } + + tegra_dp_disable_tx_pu(&dp->sor); + udelay(20); + + for (cnt = 0; cnt < n_lanes; cnt++) { + u32 max_vs_flag = tegra_dp_is_max_vs(pe[cnt], vs[cnt]); + u32 max_pe_flag = tegra_dp_is_max_pe(pe[cnt], vs[cnt]); + + val = (vs[cnt] << NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT) | + (max_vs_flag ? + NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T : + NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_F) | + (pe[cnt] << NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT) | + (max_pe_flag ? + NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T : + NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_F); + tegra_dc_dp_dpcd_write(dp, + (NV_DPCD_TRAINING_LANE0_SET + cnt), val); + } + + if (pc_supported) { + for (cnt = 0; cnt < n_lanes / 2; cnt++) { + u32 max_pc_flag0 = tegra_dp_is_max_pc(pc[cnt]); + u32 max_pc_flag1 = tegra_dp_is_max_pc(pc[cnt + 1]); + val = (pc[cnt] << NV_DPCD_LANEX_SET2_PC2_SHIFT) | + (max_pc_flag0 ? + NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T : + NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_F) | + (pc[cnt + 1] << + NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT) | + (max_pc_flag1 ? + NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T : + NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_F); + tegra_dc_dp_dpcd_write(dp, + (NV_DPCD_TRAINING_LANE0_1_SET2 + cnt), val); + } + } +} + +static int _tegra_dp_channel_eq(struct tegra_dc_dp_data *dp, u32 pe[4], + u32 vs[4], u32 pc[4], u8 pc_supported, + u32 n_lanes) +{ + u32 retry_cnt; + + for (retry_cnt = 0; retry_cnt < 4; retry_cnt++) { + if (retry_cnt){ + tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported); + tegra_dp_lt_config(dp, pe, vs, pc); + } + + tegra_dp_wait_aux_training(dp, 0); + + if (!tegra_dp_clock_recovery_status(dp)) { + printk(BIOS_ERR,"dp: CR failed in channel EQ sequence!\n"); + break; + } + + if (tegra_dp_channel_eq_status(dp)) + return DP_LT_SUCCESS; + } + + return DP_LT_FAILED; +} + +static int tegra_dp_channel_eq(struct tegra_dc_dp_data *dp, + u32 pe[4], u32 vs[4], u32 pc[4]) +{ + u32 n_lanes = dp->link_cfg.lane_count; + u8 pc_supported = dp->link_cfg.tps3_supported; + int err; + u32 tp_src = training_pattern_2; + + if (pc_supported) + tp_src = training_pattern_3; + + tegra_dp_tpg(dp, tp_src, n_lanes); + + err = _tegra_dp_channel_eq(dp, pe, vs, pc, pc_supported, n_lanes); + + tegra_dp_tpg(dp, training_pattern_disabled, n_lanes); + + return err; +} + +static int _tegra_dp_clk_recovery(struct tegra_dc_dp_data *dp, u32 pe[4], + u32 vs[4], u32 pc[4], u8 pc_supported, + u32 n_lanes) +{ + u32 vs_temp[4]; + u32 retry_cnt = 0; + + do { + tegra_dp_lt_config(dp, pe, vs, pc); + tegra_dp_wait_aux_training(dp, 1); + + if (tegra_dp_clock_recovery_status(dp)) + return DP_LT_SUCCESS; + + memcpy(vs_temp, vs, sizeof(vs_temp)); + tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported); + + if (memcmp(vs_temp, vs, sizeof(vs_temp))) + retry_cnt = 0; + else + ++retry_cnt; + } while (retry_cnt < 5); + + return DP_LT_FAILED; +} + +static int tegra_dp_clk_recovery(struct tegra_dc_dp_data *dp, + u32 pe[4], u32 vs[4], u32 pc[4]) +{ + u32 n_lanes = dp->link_cfg.lane_count; + u8 pc_supported = dp->link_cfg.tps3_supported; + int err; + + tegra_dp_tpg(dp, training_pattern_1, n_lanes); + + err = _tegra_dp_clk_recovery(dp, pe, vs, pc, pc_supported, n_lanes); + if (err < 0) + tegra_dp_tpg(dp, training_pattern_disabled, n_lanes); + + return err; +} + +static int tegra_dc_dp_full_link_training(struct tegra_dc_dp_data *dp) +{ + struct tegra_dc_sor_data *sor = &dp->sor; + int err; + u32 pe[4], vs[4], pc[4]; + + tegra_sor_precharge_lanes(sor); + +retry_cr: + memset(pe, preEmphasis_Disabled, sizeof(pe)); + memset(vs, driveCurrent_Level0, sizeof(vs)); + memset(pc, postCursor2_Level0, sizeof(pc)); + + err = tegra_dp_clk_recovery(dp, pe, vs, pc); + if (err != DP_LT_SUCCESS) { + if (!tegra_dp_lower_link_config(dp, &dp->link_cfg)) + goto retry_cr; + + printk(BIOS_ERR, "dp: clk recovery failed\n"); + goto fail; + } + + err = tegra_dp_channel_eq(dp, pe, vs, pc); + if (err != DP_LT_SUCCESS) { + if (!tegra_dp_lower_link_config(dp, &dp->link_cfg)) + goto retry_cr; + + printk(BIOS_ERR, + "dp: channel equalization failed\n"); + goto fail; + } + + tegra_dc_dp_dump_link_cfg(dp, &dp->link_cfg); + + return 0; + +fail: + return err; +} +/* + * All link training functions are ported from kernel dc driver. + * See more details at drivers/video/tegra/dc/dp.c + */ +static int tegra_dc_dp_fast_link_training(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *link_cfg) +{ + struct tegra_dc_sor_data *sor = &dp->sor; + u8 link_bw; + u8 lane_count; + u16 data16; + u32 data32; + u32 size; + u32 status; + int j; + u32 mask = 0xffff >> ((4 - link_cfg->lane_count) * 4); + + tegra_dc_sor_set_lane_parm(sor, link_cfg); + tegra_dc_dp_dpcd_write(dp, NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET, + NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET_ANSI_8B10B); + + /* Send TP1 */ + tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_1, link_cfg); + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, + NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1); + + for (j = 0; j < link_cfg->lane_count; ++j) + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j, + 0x24); + udelay(520); + + size = sizeof(data16); + tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, + NV_DPCD_LANE0_1_STATUS, (u8 *)&data16, &size, &status); + status = mask & 0x1111; + if ((data16 & status) != status) { + printk(BIOS_ERR, + "dp: Link training error for TP1 (%#x)\n", data16); + return -EFAULT; + } + + /* enable ASSR */ + tegra_dc_dp_set_assr(dp, link_cfg->scramble_ena); + tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_3, link_cfg); + + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, + link_cfg->link_bw == 20 ? 0x23 : 0x22); + for (j = 0; j < link_cfg->lane_count; ++j) + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j, + 0x24); + udelay(520); + + size = sizeof(data32); + tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, + NV_DPCD_LANE0_1_STATUS, (u8 *)&data32, &size, &status); + if ((data32 & mask) != (0x7777 & mask)) { + printk(BIOS_ERR, + "dp: Link training error for TP2/3 (0x%x)\n", data32); + return -EFAULT; + } + + tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_disabled, + link_cfg); + tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, 0); + + if (tegra_dc_dp_link_trained(dp, link_cfg)) { + tegra_dc_sor_read_link_config(&dp->sor, &link_bw, + &lane_count); + printk(BIOS_ERR, + "Fast link trainging failed, link bw %d, lane # %d\n", + link_bw, lane_count); + return -EFAULT; + } + + printk(BIOS_INFO, + "Fast link trainging succeeded, link bw %d, lane %d\n", + link_cfg->link_bw, link_cfg->lane_count); + + return 0; +} + +static int tegra_dp_do_link_training(struct tegra_dc_dp_data *dp, + const struct tegra_dc_dp_link_config *link_cfg) +{ + u8 link_bw; + u8 lane_count; + int ret; + + /* Now do the fast link training for eDP */ + ret = tegra_dc_dp_fast_link_training(dp, link_cfg); + if (ret) { + printk(BIOS_ERR, "dp: fast link training failed\n"); + + /* Try full link training then */ + if (tegra_dc_dp_full_link_training(dp)){ + printk(BIOS_ERR, "dp: full link training failed\n"); + return ret; + } + } else { + /* set to a known-good drive setting if fast link succeeded */ + tegra_dc_sor_set_voltage_swing(&dp->sor); + } + + /* Everything goes well, double check the link config */ + /* TODO: record edc/c2 data for debugging */ + tegra_dc_sor_read_link_config(&dp->sor, &link_bw, &lane_count); + + if ((link_cfg->link_bw == link_bw) && + (link_cfg->lane_count == lane_count)) + return 0; + else + return -EFAULT; +} + +static int tegra_dc_dp_explore_link_cfg(struct tegra_dc_dp_data *dp, + struct tegra_dc_dp_link_config *link_cfg, + const struct soc_nvidia_tegra124_config *config) +{ + struct tegra_dc_dp_link_config temp_cfg; + + if (!config->pixel_clock || !config->xres || !config->yres) { + printk(BIOS_ERR, + "dp: error mode configuration"); + return -EINVAL; + } + if (!link_cfg->max_link_bw || !link_cfg->max_lane_count) { + printk(BIOS_ERR, + "dp: error link configuration"); + return -EINVAL; + } + + link_cfg->is_valid = 0; + + memcpy(&temp_cfg, link_cfg, sizeof(temp_cfg)); + + temp_cfg.link_bw = temp_cfg.max_link_bw; + temp_cfg.lane_count = temp_cfg.max_lane_count; + + /* + * set to max link config + */ + if ((!tegra_dc_dp_calc_config(dp, config, &temp_cfg)) && + (!tegra_dp_link_config(dp, &temp_cfg)) && + (!tegra_dp_do_link_training(dp, &temp_cfg))) + /* the max link cfg is doable */ + memcpy(link_cfg, &temp_cfg, sizeof(temp_cfg)); + + return link_cfg->is_valid ? 0 : -EFAULT; +} + +static void tegra_dp_update_config(struct tegra_dc_dp_data *dp, + struct soc_nvidia_tegra124_config *config) +{ + struct edid edid; + u8 buf[128] = {0}; + u32 size = sizeof(buf), aux_stat = 0; + + tegra_dc_dpaux_enable(dp); + if (tegra_dc_i2c_aux_read(dp, TEGRA_EDID_I2C_ADDRESS, 0, buf, &size, + &aux_stat)) { + printk(BIOS_ERR, "%s: Failed to read EDID. Use defaults.\n", + __func__); + return; + } + + if (decode_edid(buf, sizeof(buf), &edid, 0)) { + printk(BIOS_ERR, "%s: Failed to decode EDID. Use defaults.\n", + __func__); + return; + } + + config->xres = edid.mode.ha; + config->yres = edid.mode.va; + config->pixel_clock = edid.mode.pixel_clock * 1000; + + config->hfront_porch = edid.mode.hso; + config->hsync_width = edid.mode.hspw; + config->hback_porch = edid.mode.hbl - edid.mode.hso - edid.mode.hspw; + + config->vfront_porch = edid.mode.vso; + config->vsync_width = edid.mode.vspw; + config->vback_porch = edid.mode.vbl - edid.mode.vso - edid.mode.vspw; + + /** + * Note edid->framebuffer_bits_per_pixel is currently hard-coded as 32, + * so we should keep the default value in device config. + * + * EDID v1.3 panels may not have color depth info, so we need to check + * if these values are zero before updating config. + */ + if (edid.panel_bits_per_pixel) + config->panel_bits_per_pixel = edid.panel_bits_per_pixel; + if (edid.panel_bits_per_color) + config->color_depth = edid.panel_bits_per_color; + printk(BIOS_SPEW, "%s: configuration updated by EDID.\n", __func__); +} + +void dp_init(void * _config) +{ + struct soc_nvidia_tegra124_config *config = (void *)_config; + struct tegra_dc *dc = config->dc_data; + struct tegra_dc_dp_data *dp = &dp_data; + + // set up links among config, dc, dp and sor + dp->dc = dc; + dc->out = dp; + dp->sor.dc = dc; + + dp->sor.power_is_up = 0; + dp->sor.base = (void *)TEGRA_ARM_SOR; + dp->sor.pmc_base = (void *)TEGRA_PMC_BASE; + dp->sor.portnum = 0; + dp->sor.link_cfg = &dp->link_cfg; + dp->aux_base = (void *)TEGRA_ARM_DPAUX; + dp->link_cfg.is_valid = 0; + dp->enabled = 0; + + tegra_dp_update_config(dp, config); +} + +static void tegra_dp_hpd_config(struct tegra_dc_dp_data *dp, + struct soc_nvidia_tegra124_config *config) +{ + u32 val; + + val = config->hpd_plug_min_us | + (config->hpd_unplug_min_us << + DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME_SHIFT); + tegra_dpaux_writel(dp, DPAUX_HPD_CONFIG, val); + + tegra_dpaux_writel(dp, DPAUX_HPD_IRQ_CONFIG, config->hpd_irq_min_us); +} + +static int tegra_dp_hpd_plug(struct tegra_dc_dp_data *dp, int timeout_ms) +{ + u32 val; + u32 timeout = timeout_ms * 1000; + do { + val = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT); + if (val & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED) + return 0; + udelay(100); + timeout -= 100; + } while (timeout > 0); + return -1; +} + +void dp_enable(void * _dp) +{ + struct tegra_dc_dp_data *dp = _dp; + struct tegra_dc *dc = dp->dc; + struct soc_nvidia_tegra124_config *config = dc->config; + + u8 data; + u32 retry; + int ret; + + tegra_dc_dpaux_enable(dp); + + tegra_dp_hpd_config(dp, config); + if (tegra_dp_hpd_plug(dp, config->vdd_to_hpd_delay_ms) < 0) { + printk(BIOS_ERR, "dp: hpd plug failed\n"); + goto error_enable; + } + + if (tegra_dc_dp_init_max_link_cfg(config, dp, &dp->link_cfg)) { + printk(BIOS_ERR, "dp: failed to init link configuration\n"); + goto error_enable; + } + + tegra_dc_sor_enable_dp(&dp->sor); + + tegra_dc_sor_set_panel_power(&dp->sor, 1); + + /* Write power on to DPCD */ + data = NV_DPCD_SET_POWER_VAL_D0_NORMAL; + retry = 0; + do { + ret = tegra_dc_dp_dpcd_write(dp, + NV_DPCD_SET_POWER, data); + } while ((retry++ < DP_POWER_ON_MAX_TRIES) && ret); + + if (ret || retry >= DP_POWER_ON_MAX_TRIES) { + printk(BIOS_ERR, + "dp: failed to power on panel (0x%x)\n", ret); + goto error_enable; + } + + /* Confirm DP is plugging status */ + if (!(tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT) & + DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) { + printk(BIOS_ERR, "dp: could not detect HPD\n"); + goto error_enable; + } + + /* Check DP version */ + if (tegra_dc_dp_dpcd_read(dp, NV_DPCD_REV, &dp->revision)) + printk(BIOS_ERR, + "dp: failed to read the revision number from sink\n"); + + if (tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, config)) { + printk(BIOS_ERR, "dp: error to configure link\n"); + goto error_enable; + } + + tegra_dc_sor_set_power_state(&dp->sor, 1); + tegra_dc_sor_attach(&dp->sor); + + /* + * Power down the unused lanes to save power + * (about hundreds milli-watts, varies from boards). + */ + tegra_dc_sor_power_down_unused_lanes(&dp->sor); + + dp->enabled = 1; +error_enable: + return; +} diff --git a/src/soc/nvidia/tegra124/i2c.c b/src/soc/nvidia/tegra124/i2c.c new file mode 100644 index 0000000000..a7eee686b0 --- /dev/null +++ b/src/soc/nvidia/tegra124/i2c.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +struct tegra_i2c_bus_info tegra_i2c_info[] = { + { + .base = (void *)TEGRA_I2C_BASE, + .reset_bit = CLK_L_I2C1, + .reset_func = &clock_reset_l + }, + { + .base = (void *)TEGRA_I2C2_BASE, + .reset_bit = CLK_H_I2C2, + .reset_func = &clock_reset_h + }, + { + .base = (void *)TEGRA_I2C3_BASE, + .reset_bit = CLK_U_I2C3, + .reset_func = &clock_reset_u + }, + { + .base = (void *)TEGRA_I2C4_BASE, + .reset_bit = CLK_V_I2C4, + .reset_func = &clock_reset_v + }, + { + .base = (void *)TEGRA_I2C5_BASE, + .reset_bit = CLK_H_I2C5, + .reset_func = &clock_reset_h + }, + { + .base = (void *)TEGRA_I2C6_BASE, + .reset_bit = CLK_X_I2C6, + .reset_func = &clock_reset_x + } +}; diff --git a/src/soc/nvidia/tegra124/include/soc/addressmap.h b/src/soc/nvidia/tegra124/include/soc/addressmap.h new file mode 100644 index 0000000000..1afaba84cd --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/addressmap.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2013 Google Inc. + * + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_ADDRESS_MAP_H__ +#define __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_ADDRESS_MAP_H__ + +#include + +enum { + TEGRA_SRAM_BASE = 0x40000000, + TEGRA_SRAM_SIZE = 0x20000 +}; + +enum { + TEGRA_ARM_PERIPHBASE = 0x50040000, + TEGRA_ARM_DISPLAYA = 0x54200000, + TEGRA_ARM_DISPLAYB = 0x54240000, + TEGRA_ARM_SOR = 0x54540000, + TEGRA_ARM_DPAUX = 0x545c0000, + TEGRA_PG_UP_BASE = 0x60000000, + TEGRA_TMRUS_BASE = 0x60005010, + TEGRA_CLK_RST_BASE = 0x60006000, + TEGRA_FLOW_BASE = 0x60007000, + TEGRA_GPIO_BASE = 0x6000D000, + TEGRA_EVP_BASE = 0x6000F000, + TEGRA_APB_DMA_BASE = 0x60020000, + TEGRA_APB_MISC_BASE = 0x70000000, + TEGRA_APB_MISC_GP_BASE = TEGRA_APB_MISC_BASE + 0x0800, + TEGRA_APB_PINGROUP_BASE = TEGRA_APB_MISC_BASE + 0x0868, + TEGRA_APB_PINMUX_BASE = TEGRA_APB_MISC_BASE + 0x3000, + TEGRA_APB_UARTA_BASE = TEGRA_APB_MISC_BASE + 0x6000, + TEGRA_APB_UARTB_BASE = TEGRA_APB_MISC_BASE + 0x6040, + TEGRA_APB_UARTC_BASE = TEGRA_APB_MISC_BASE + 0x6200, + TEGRA_APB_UARTD_BASE = TEGRA_APB_MISC_BASE + 0x6300, + TEGRA_APB_UARTE_BASE = TEGRA_APB_MISC_BASE + 0x6400, + TEGRA_NAND_BASE = TEGRA_APB_MISC_BASE + 0x8000, + TEGRA_PWM_BASE = TEGRA_APB_MISC_BASE + 0xA000, + TEGRA_I2C_BASE = TEGRA_APB_MISC_BASE + 0xC000, + TEGRA_SPI_BASE = TEGRA_APB_MISC_BASE + 0xC380, + TEGRA_I2C2_BASE = TEGRA_APB_MISC_BASE + 0xC400, + TEGRA_I2C3_BASE = TEGRA_APB_MISC_BASE + 0xC500, + TEGRA_I2C4_BASE = TEGRA_APB_MISC_BASE + 0xC700, + TEGRA_I2C5_BASE = TEGRA_APB_MISC_BASE + 0xD000, + TEGRA_I2C6_BASE = TEGRA_APB_MISC_BASE + 0xD100, + TEGRA_SPI1_BASE = TEGRA_APB_MISC_BASE + 0xD400, + TEGRA_SPI2_BASE = TEGRA_APB_MISC_BASE + 0xD600, + TEGRA_SPI3_BASE = TEGRA_APB_MISC_BASE + 0xD800, + TEGRA_SPI4_BASE = TEGRA_APB_MISC_BASE + 0xDA00, + TEGRA_SPI5_BASE = TEGRA_APB_MISC_BASE + 0xDC00, + TEGRA_SPI6_BASE = TEGRA_APB_MISC_BASE + 0xDE00, + TEGRA_DVC_BASE = TEGRA_APB_MISC_BASE + 0xD000, + TEGRA_PMC_BASE = TEGRA_APB_MISC_BASE + 0xE400, + TEGRA_FUSE_BASE = TEGRA_APB_MISC_BASE + 0xF800, + TEGRA_MC_BASE = 0x70019000, + TEGRA_EMC_BASE = 0x7001B000, + TEGRA_CSITE_BASE = 0x70040000, + TEGRA_SYSCTR0_BASE = 0x700F0000, + TEGRA_USBD_BASE = 0x7D000000, + TEGRA_USB2_BASE = 0x7D004000, + TEGRA_USB3_BASE = 0x7D008000, +}; + +enum { + TEGRA_I2C_BASE_COUNT = 6, + TEGRA_EDID_I2C_ADDRESS = 0x50, +}; + +#endif /* __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_ADDRESS_MAP_H__ */ diff --git a/src/arch/x86/boot/ramstage_module_header.c b/src/soc/nvidia/tegra124/include/soc/cache.h similarity index 82% rename from src/arch/x86/boot/ramstage_module_header.c rename to src/soc/nvidia/tegra124/include/soc/cache.h index b958c16085..3723cd7650 100644 --- a/src/arch/x86/boot/ramstage_module_header.c +++ b/src/soc/nvidia/tegra124/include/soc/cache.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 ChromeOS Authors + * Copyright (C) 2014 Google, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,8 +17,4 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - -extern char _start[]; - -DEFINE_RMODULE_HEADER(ramstage_module, _start, RMODULE_TYPE_STAGE); +void configure_l2_cache(void); diff --git a/src/soc/nvidia/tegra124/include/soc/clk_rst.h b/src/soc/nvidia/tegra124/include/soc/clk_rst.h new file mode 100644 index 0000000000..d2249f7669 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/clk_rst.h @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA124_CLK_RST_H_ +#define _TEGRA124_CLK_RST_H_ + +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ +struct __attribute__ ((__packed__)) clk_rst_ctlr { + u32 rst_src; /* _RST_SOURCE, 0x000 */ + u32 rst_dev_l; /* _RST_DEVICES_L, 0x004 */ + u32 rst_dev_h; /* _RST_DEVICES_H, 0x008 */ + u32 rst_dev_u; /* _RST_DEVICES_U, 0x00c */ + u32 clk_out_enb_l; /* _CLK_OUT_ENB_L, 0x010 */ + u32 clk_out_enb_h; /* _CLK_OUT_ENB_H, 0x014 */ + u32 clk_out_enb_u; /* _CLK_OUT_ENB_U, 0x018 */ + u32 _rsv0; /* 0x01c */ + u32 cclk_brst_pol; /* _CCLK_BURST_POLICY, 0x020 */ + u32 super_cclk_div; /* _SUPER_CCLK_DIVIDER, 0x024 */ + u32 sclk_brst_pol; /* _SCLK_BURST_POLICY, 0x028 */ + u32 super_sclk_div; /* _SUPER_SCLK_DIVIDER, 0x02C */ + u32 clk_sys_rate; /* _CLK_SYSTEM_RATE, 0x030 */ + u32 _rsv1[3]; /* 0x034-03c */ + u32 cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY, 0x040 */ + u32 clk_mask_arm; /* _CLK_MASK_ARM, 0x044 */ + u32 misc_clk_enb; /* _MISC_CLK_ENB, 0x048 */ + u32 clk_cpu_cmplx; /* _CLK_CPU_CMPLX, 0x04C */ + u32 osc_ctrl; /* _OSC_CTRL, 0x050 */ + u32 pll_lfsr; /* _PLL_LFSR, 0x054 */ + u32 osc_freq_det; /* _OSC_FREQ_DET, 0x058 */ + u32 osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS, 0x05C */ + u32 _rsv2[8]; /* 0x060-07C */ + u32 pllc_base; /* _PLLC_BASE, 0x080 */ + u32 pllc_out; /* _PLLC_OUT, 0x084 */ + u32 pllc_misc2; /* _PLLC_MISC2, 0x088 */ + u32 pllc_misc; /* _PLLC_MISC, 0x08c */ + u32 pllm_base; /* _PLLM_BASE, 0x090 */ + u32 pllm_out; /* _PLLM_OUT, 0x094 */ + u32 pllm_misc1; /* _PLLM_MISC1, 0x098 */ + u32 pllm_misc2; /* _PLLM_MISC2, 0x09c */ + u32 pllp_base; /* _PLLP_BASE, 0x0a0 */ + u32 pllp_outa; /* _PLLP_OUTA, 0x0a4 */ + u32 pllp_outb; /* _PLLP_OUTB, 0x0a8 */ + u32 pllp_misc; /* _PLLP_MISC, 0x0ac */ + u32 plla_base; /* _PLLA_BASE, 0x0b0 */ + u32 plla_out; /* _PLLA_OUT, 0x0b4 */ + u32 _rsv3; /* 0x0b8 */ + u32 plla_misc; /* _PLLA_MISC, 0x0bc */ + u32 pllu_base; /* _PLLU_BASE, 0x0c0 */ + u32 _rsv4[2]; /* 0x0c4-0c8 */ + u32 pllu_misc; /* _PLLU_MISC, 0x0cc */ + u32 plld_base; /* _PLLD_BASE, 0x0d0 */ + u32 _rsv5[2]; /* 0x0d4-0d8 */ + u32 plld_misc; /* _PLLD_MISC, 0x0dc */ + u32 pllx_base; /* _PLLX_BASE, 0x0e0 */ + u32 pllx_misc; /* _PLLX_MISC, 0x0e4 */ + u32 plle_base; /* _PLLE_BASE, 0x0e8 */ + u32 plle_misc; /* _PLLE_MISC, 0x0ec */ + u32 plls_base; /* _PLLS_BASE, 0x0f0 */ + u32 plls_misc; /* _PLLS_MISC, 0x0f4 */ + u32 _rsv6[2]; /* 0x0f8-0fc */ + u32 clk_src_i2s1; /* _CLK_SOURCE_I2S1, 0x100 */ + u32 clk_src_i2s2; /* _CLK_SOURCE_I2S2, 0x104 */ + u32 clk_src_spdif_out; /* _CLK_SOURCE_SPDIF_OUT, 0x108 */ + u32 clk_src_spdif_in; /* _CLK_SOURCE_SPDIF_IN, 0x10c */ + u32 clk_src_pwm; /* _CLK_SOURCE_PWM, 0x110 */ + u32 _rsv7; /* 0x114 */ + u32 clk_src_sbc2; /* _CLK_SOURCE_SBC2, 0x118 */ + u32 clk_src_sbc3; /* _CLK_SOURCE_SBC3, 0x11c */ + u32 _rsv8; /* 0x120 */ + u32 clk_src_i2c1; /* _CLK_SOURCE_I2C1, 0x124 */ + u32 clk_src_i2c5; /* _CLK_SOURCE_I2C5, 0x128 */ + u32 _rsv9[2]; /* 0x12c-130 */ + u32 clk_src_sbc1; /* _CLK_SOURCE_SBC1, 0x134 */ + u32 clk_src_disp1; /* _CLK_SOURCE_DISP1, 0x138 */ + u32 clk_src_disp2; /* _CLK_SOURCE_DISP2, 0x13c */ + u32 _rsv10[2]; /* 0x140-144 */ + u32 clk_src_vi; /* _CLK_SOURCE_VI, 0x148 */ + u32 _rsv11; /* 0x14c */ + u32 clk_src_sdmmc1; /* _CLK_SOURCE_SDMMC1, 0x150 */ + u32 clk_src_sdmmc2; /* _CLK_SOURCE_SDMMC2, 0x154 */ + u32 clk_src_g3d; /* _CLK_SOURCE_G3D, 0x158 */ + u32 clk_src_g2d; /* _CLK_SOURCE_G2D, 0x15c */ + u32 clk_src_ndflash; /* _CLK_SOURCE_NDFLASH, 0x160 */ + u32 clk_src_sdmmc4; /* _CLK_SOURCE_SDMMC4, 0x164 */ + u32 clk_src_vfir; /* _CLK_SOURCE_VFIR, 0x168 */ + u32 clk_src_epp; /* _CLK_SOURCE_EPP, 0x16c */ + u32 clk_src_mpe; /* _CLK_SOURCE_MPE, 0x170 */ + u32 clk_src_hsi; /* _CLK_SOURCE_HSI, 0x174 */ + u32 clk_src_uarta; /* _CLK_SOURCE_UARTA, 0x178 */ + u32 clk_src_uartb; /* _CLK_SOURCE_UARTB, 0x17c */ + u32 clk_src_host1x; /* _CLK_SOURCE_HOST1X, 0x180 */ + u32 _rsv12[2]; /* 0x184-188 */ + u32 clk_src_hdmi; /* _CLK_SOURCE_HDMI, 0x18c */ + u32 _rsv13[2]; /* 0x190-194 */ + u32 clk_src_i2c2; /* _CLK_SOURCE_I2C2, 0x198 */ + u32 clk_src_emc; /* _CLK_SOURCE_EMC, 0x19c */ + u32 clk_src_uartc; /* _CLK_SOURCE_UARTC, 0x1a0 */ + u32 _rsv14; /* 0x1a4 */ + u32 clk_src_vi_sensor; /* _CLK_SOURCE_VI_SENSOR, 0x1a8 */ + u32 _rsv15[2]; /* 0x1ac-1b0 */ + u32 clk_src_sbc4; /* _CLK_SOURCE_SBC4, 0x1b4 */ + u32 clk_src_i2c3; /* _CLK_SOURCE_I2C3, 0x1b8 */ + u32 clk_src_sdmmc3; /* _CLK_SOURCE_SDMMC3, 0x1bc */ + u32 clk_src_uartd; /* _CLK_SOURCE_UARTD, 0x1c0 */ + u32 clk_src_uarte; /* _CLK_SOURCE_UARTE, 0x1c4 */ + u32 clk_src_vde; /* _CLK_SOURCE_VDE, 0x1c8 */ + u32 clk_src_owr; /* _CLK_SOURCE_OWR, 0x1cc */ + u32 clk_src_nor; /* _CLK_SOURCE_NOR, 0x1d0 */ + u32 clk_src_csite; /* _CLK_SOURCE_CSITE, 0x1d4 */ + u32 clk_src_i2s0; /* _CLK_SOURCE_I2S0, 0x1d8 */ + u32 clk_src_dtv; /* _CLK_SOURCE_DTV, 0x1dc */ + u32 _rsv16[4]; /* 0x1e0-1ec */ + u32 clk_src_msenc; /* _CLK_SOURCE_MSENC, 0x1f0 */ + u32 clk_src_tsec; /* _CLK_SOURCE_TSEC, 0x1f4 */ + u32 _rsv17; /* 0x1f8 */ + u32 clk_src_osc; /* _CLK_SOURCE_OSC, 0x1fc */ + u32 _rsv18[32]; /* 0x200-27c */ + u32 clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + u32 clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + u32 clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + u32 rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + u32 rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + u32 rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + u32 _rsv19[23]; /* 0x298-2f0 */ + u32 dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + u32 _rsv20[2]; /* 0x2f8-2fc */ + u32 rst_dev_l_set; /* _RST_DEV_L_SET 0x300 */ + u32 rst_dev_l_clr; /* _RST_DEV_L_CLR 0x304 */ + u32 rst_dev_h_set; /* _RST_DEV_H_SET 0x308 */ + u32 rst_dev_h_clr; /* _RST_DEV_H_CLR 0x30c */ + u32 rst_dev_u_set; /* _RST_DEV_U_SET 0x310 */ + u32 rst_dev_u_clr; /* _RST_DEV_U_CLR 0x314 */ + u32 _rsv21[2]; /* 0x318-31c */ + u32 clk_enb_l_set; /* _CLK_ENB_L_SET 0x320 */ + u32 clk_enb_l_clr; /* _CLK_ENB_L_CLR 0x324 */ + u32 clk_enb_h_set; /* _CLK_ENB_H_SET 0x328 */ + u32 clk_enb_h_clr; /* _CLK_ENB_H_CLR 0x32c */ + u32 clk_enb_u_set; /* _CLK_ENB_U_SET 0x330 */ + u32 clk_enb_u_clk; /* _CLK_ENB_U_CLR 0x334 */ + u32 _rsv22; /* 0x338 */ + u32 ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD, 0x33c */ + u32 rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET, 0x340 */ + u32 rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR, 0x344 */ + u32 clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET, 0x348 */ + u32 clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET, 0x34c */ + u32 _rsv23[2]; /* 0x350-354 */ + u32 rst_dev_v; /* _RST_DEVICES_V, 0x358 */ + u32 rst_dev_w; /* _RST_DEVICES_W, 0x35c */ + u32 clk_out_enb_v; /* _CLK_OUT_ENB_V, 0x360 */ + u32 clk_out_enb_w; /* _CLK_OUT_ENB_W, 0x364 */ + u32 cclkg_brst_pol; /* _CCLKG_BURST_POLICY, 0x368 */ + u32 super_cclkg_div; /* _SUPER_CCLKG_DIVIDER, 0x36c */ + u32 cclklp_brst_pol; /* _CCLKLP_BURST_POLICY, 0x370 */ + u32 super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER, 0x374 */ + u32 clk_cpug_cmplx; /* _CLK_CPUG_CMPLX, 0x378 */ + u32 clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX, 0x37c */ + u32 cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL, 0x380 */ + u32 cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1, 0x384 */ + u32 cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2, 0x388 */ + u32 _rsv24[9]; /* 0x38c-3ac */ + u32 clk_src_g3d2; /* _CLK_SOURCE_G3D2, 0x3b0 */ + u32 clk_src_mselect; /* _CLK_SOURCE_MSELECT, 0x3b4 */ + u32 clk_src_tsensor; /* _CLK_SOURCE_TSENSOR, 0x3b8 */ + u32 clk_src_i2s3; /* _CLK_SOURCE_I2S3, 0x3bc */ + u32 clk_src_i2s4; /* _CLK_SOURCE_I2S4, 0x3c0 */ + u32 clk_src_i2c4; /* _CLK_SOURCE_I2C4, 0x3c4 */ + u32 clk_src_sbc5; /* _CLK_SOURCE_SBC5, 0x3c8 */ + u32 clk_src_sbc6; /* _CLK_SOURCE_SBC6, 0x3cc */ + u32 clk_src_audio; /* _CLK_SOURCE_AUDIO, 0x3d0 */ + u32 _rsv25; /* 0x3d4 */ + u32 clk_src_dam0; /* _CLK_SOURCE_DAM0, 0x3d8 */ + u32 clk_src_dam1; /* _CLK_SOURCE_DAM1, 0x3dc */ + u32 clk_src_dam2; /* _CLK_SOURCE_DAM2, 0x3e0 */ + u32 clk_src_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X,0x3e4 */ + u32 clk_src_actmon; /* _CLK_SOURCE_ACTMON, 0x3e8 */ + u32 clk_src_extperiph1; /* _CLK_SOURCE_EXTPERIPH1, 0x3ec */ + u32 clk_src_extperiph2; /* _CLK_SOURCE_EXTPERIPH2, 0x3f0 */ + u32 clk_src_extperiph3; /* _CLK_SOURCE_EXTPERIPH3, 0x3f4 */ + u32 clk_src_nand_speed; /* _CLK_SOURCE_NAND_SPEED, 0x3f8 */ + u32 clk_src_i2c_slow; /* _CLK_SOURCE_I2C_SLOW, 0x3fc */ + u32 clk_src_sys; /* _CLK_SOURCE_SYS, 0x400 */ + u32 _rsv26[4]; /* 0x404-410 */ + u32 clk_src_sor; /* _CLK_SOURCE_SOR_0, 0x414 */ + u32 _rsv261[2]; /* 0x404-410 */ + u32 clk_src_sata_oob; /* _CLK_SOURCE_SATA_OOB, 0x420 */ + u32 clk_src_sata; /* _CLK_SOURCE_SATA, 0x424 */ + u32 clk_src_hda; /* _CLK_SOURCE_HDA, 0x428 */ + u32 _rsv27; /* 0x42c */ + u32 rst_dev_v_set; /* _RST_DEV_V_SET, 0x430 */ + u32 rst_dev_v_clr; /* _RST_DEV_V_CLR, 0x434 */ + u32 rst_dev_w_set; /* _RST_DEV_W_SET, 0x438 */ + u32 rst_dev_w_clr; /* _RST_DEV_W_CLR, 0x43c */ + u32 clk_enb_v_set; /* _CLK_ENB_V_SET, 0x440 */ + u32 clk_enb_v_clr; /* _CLK_ENB_V_CLR, 0x444 */ + u32 clk_enb_w_set; /* _CLK_ENB_W_SET, 0x448 */ + u32 clk_enb_w_clr; /* _CLK_ENB_W_CLR, 0x44c */ + u32 rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET, 0x450 */ + u32 rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR, 0x454 */ + u32 rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET, 0x458 */ + u32 rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR, 0x45C */ + u32 clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET, 0x460 */ + u32 clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR, 0x464 */ + u32 clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET, 0x468 */ + u32 clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR, 0x46c */ + u32 cpu_cmplx_status; /* _CPU_CMPLX_STATUS, 0x470 */ + u32 _rsv28; /* 0x474 */ + u32 intstatus; /* _INTSTATUS, 0x478 */ + u32 intmask; /* _INTMASK, 0x47c */ + u32 utmip_pll_cfg0; /* _UTMIP_PLL_CFG0, 0x480 */ + u32 utmip_pll_cfg1; /* _UTMIP_PLL_CFG1, 0x484 */ + u32 utmip_pll_cfg2; /* _UTMIP_PLL_CFG2, 0x488 */ + u32 plle_aux; /* _PLLE_AUX, 0x48c */ + u32 sata_pll_cfg0; /* _SATA_PLL_CFG0, 0x490 */ + u32 sata_pll_cfg1; /* _SATA_PLL_CFG1, 0x494 */ + u32 pcie_pll_cfg0; /* _PCIE_PLL_CFG0, 0x498 */ + u32 prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK, 0x49c */ + u32 audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0, 0x4a0 */ + u32 audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1, 0x4a4 */ + u32 audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2, 0x4a8 */ + u32 audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3, 0x4ac */ + u32 audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4, 0x4b0 */ + u32 audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF, 0x4b4 */ + u32 plld2_base; /* _PLLD2_BASE, 0x4b8 */ + u32 plld2_misc; /* _PLLD2_MISC, 0x4bc */ + u32 utmip_pll_cfg3; /* _UTMIP_PLL_CFG3, 0x4c0 */ + u32 pllrefe_base; /* _PLLREFE_BASE, 0x4c4 */ + u32 pllrefe_misc; /* _PLLREFE_MISC, 0x4c8 */ + u32 _rsv29[7]; /* 0x4cc-4e4 */ + u32 pllc2_base; /* _PLLC2_BASE, 0x4e8 */ + u32 pllc2_misc0; /* _PLLC2_MISC_0, 0x4ec */ + u32 pllc2_misc1; /* _PLLC2_MISC_1, 0x4f0 */ + u32 pllc2_misc2; /* _PLLC2_MISC_2, 0x4f4 */ + u32 pllc2_misc3; /* _PLLC2_MISC_3, 0x4f8 */ + u32 pllc3_base; /* _PLLC3_BASE, 0x4fc */ + u32 pllc3_misc0; /* _PLLC3_MISC_0, 0x500 */ + u32 pllc3_misc1; /* _PLLC3_MISC_1, 0x504 */ + u32 pllc3_misc2; /* _PLLC3_MISC_2, 0x508 */ + u32 pllc3_misc3; /* _PLLC3_MISC_3, 0x50c */ + u32 pllx_misc1; /* _PLLX_MISC_1, 0x510 */ + u32 pllx_misc2; /* _PLLX_MISC_2, 0x514 */ + u32 pllx_misc3; /* _PLLX_MISC_3, 0x518 */ + u32 xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0, 0x51c */ + u32 xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG1, 0x520 */ + u32 plle_aux1; /* _PLLE_AUX1, 0x524 */ + u32 pllp_reshift; /* _PLLP_RESHIFT, 0x528 */ + u32 utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0, 0x52c */ + u32 pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0, 0x530 */ + u32 xusb_pll_cfg0; /* _XUSB_PLL_CFG0, 0x534 */ + u32 _rsv30; /* 0x538 */ + u32 clk_cpu_misc; /* _CLK_CPU_MISC, 0x53c */ + u32 clk_cpug_misc; /* _CLK_CPUG_MISC, 0x540 */ + u32 clk_cpulp_misc; /* _CLK_CPULP_MISC, 0x544 */ + u32 pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG, 0x548 */ + u32 pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG, 0x54c */ + u32 pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS, 0x550 */ + u32 _rsv31; /* 0x554 */ + u32 super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER, 0x558 */ + u32 spare_reg0; /* _SPARE_REG0, 0x55c */ + u32 _rsv32[4]; /* 0x560-0x56c */ + u32 plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ + u32 _rsv32_1[7]; /* 0x574-58c */ + u32 plldp_base; /* _PLLDP_BASE, 0x590 */ + u32 plldp_misc; /* _PLLDP_MISC, 0x594 */ + u32 plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + u32 _rsrv32_2[25]; + u32 clk_src_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST 0x600 */ + u32 clk_src_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON 0x604 */ + u32 clk_src_xusb_fs; /* _CLK_SOURCE_XUSB_FS 0x608 */ + u32 clk_src_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV 0x60c */ + u32 clk_src_xusb_ss; /* _CLK_SOURCE_XUSB_SS 0x610 */ + u32 clk_src_cilab; /* _CLK_SOURCE_CILAB 0x614 */ + u32 clk_src_cilcd; /* _CLK_SOURCE_CILCD 0x618 */ + u32 clk_src_cile; /* _CLK_SOURCE_CILE 0x61c */ + u32 clk_src_dsia_lp; /* _CLK_SOURCE_DSIA_LP 0x620 */ + u32 clk_src_dsib_lp; /* _CLK_SOURCE_DSIB_LP 0x624 */ + u32 clk_src_entropy; /* _CLK_SOURCE_ENTROPY 0x628 */ + u32 clk_src_dvfs_ref; /* _CLK_SOURCE_DVFS_REF 0x62c */ + u32 clk_src_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC 0x630 */ + u32 clk_src_traceclkin; /* _CLK_SOURCE_TRACECLKIN 0x634 */ + u32 clk_src_adx0; /* _CLK_SOURCE_ADX0 0x638 */ + u32 clk_src_amx0; /* _CLK_SOURCE_AMX0 0x63c */ + u32 clk_src_emc_latency; /* _CLK_SOURCE_EMC_LATENCY 0x640 */ + u32 clk_src_soc_therm; /* _CLK_SOURCE_SOC_THERM 0x644 */ +}; +check_member(clk_rst_ctlr, clk_src_soc_therm, 0x644); + +#define TEGRA_DEV_L 0 +#define TEGRA_DEV_H 1 +#define TEGRA_DEV_U 2 +#define TEGRA_DEV_V 0 +#define TEGRA_DEV_W 1 + +#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) + +/* Bits to enable/reset modules */ +#define CLK_ENB_CPU (1 << 0) +#define SWR_TRIG_SYS_RST (1 << 2) +#define SWR_CSITE_RST (1 << 9) +#define CLK_ENB_CSITE (1 << 9) + +/* CRC_SUPER_CCLK_DIVIDER_0 0x24 */ +#define SUPER_CDIV_ENB_ENABLE (1 << 31) + +/* CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 */ +#define EN_PPSB_STOPCLK (1 << 0) + +/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 (0x4C) */ +#define CPU3_CLK_STP_SHIFT 11 +#define CPU2_CLK_STP_SHIFT 10 +#define CPU1_CLK_STP_SHIFT 9 +#define CPU0_CLK_STP_SHIFT 8 +#define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT) + +/* CRC_OSC_CTRL_0 0x50 */ +#define OSC_FREQ_SHIFT 28 +#define OSC_FREQ_MASK (0xf << OSC_FREQ_SHIFT) +#define OSC_PREDIV_SHIFT 26 +#define OSC_PREDIV_MASK (0x3 << OSC_PREDIV_SHIFT) +#define OSC_XOFS_SHIFT 4 +#define OSC_XOFS_MASK (0x3F << OSC_XOFS_SHIFT) +#define OSC_DRIVE_STRENGTH 7 +#define OSC_XOBP (1 << 1) +#define OSC_XOE (1 << 0) + +enum { + OSC_FREQ_12 = 8, /* 12.0MHz */ + OSC_FREQ_13 = 0, /* 13.0MHz */ + OSC_FREQ_16P8 = 1, /* 16.8MHz */ + OSC_FREQ_19P2 = 4, /* 19.2MHz */ + OSC_FREQ_26 = 12, /* 26.0MHz */ + OSC_FREQ_38P4 = 5, /* 38.4MHz */ + OSC_FREQ_48 = 9, /* 48.0MHz */ +}; + +/* CLK_RST_CONTROLLER_PLL*_BASE_0 */ +#define PLL_BASE_BYPASS (1U << 31) +#define PLL_BASE_ENABLE (1U << 30) +#define PLL_BASE_REF_DIS (1U << 29) +#define PLL_BASE_OVRRIDE (1U << 28) +#define PLL_BASE_LOCK (1U << 27) + +#define PLL_BASE_DIVP_SHIFT 20 +#define PLL_BASE_DIVP_MASK (7U << PLL_BASE_DIVP_SHIFT) + +#define PLL_BASE_DIVN_SHIFT 8 +#define PLL_BASE_DIVN_MASK (0x3ffU << PLL_BASE_DIVN_SHIFT) + +#define PLL_BASE_DIVM_SHIFT 0 +#define PLL_BASE_DIVM_MASK (0x1f << PLL_BASE_DIVM_SHIFT) + +/* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */ +#define PLLCX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT) +#define PLLM_BASE_DIVP_MASK (0x1U << PLL_BASE_DIVP_SHIFT) +#define PLLCMX_BASE_DIVN_MASK (0xffU << PLL_BASE_DIVN_SHIFT) +#define PLLCMX_BASE_DIVM_MASK (0xffU << PLL_BASE_DIVM_SHIFT) + +/* PLLM specific registers */ +#define PLLM_MISC1_SETUP_SHIFT 0 +#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT 28 +#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT 29 +#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT 30 +#define PLLM_MISC2_KCP_SHIFT 1 +#define PLLM_MISC2_KVCO_SHIFT 0 +#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) + +/* Generic, indiscriminate divisor mask. May catch some innocent bystander bits + * on the side that we don't particularly care about. */ +#define PLL_BASE_DIV_MASK (0xffffff) + +/* CLK_RST_CONTROLLER_PLL*_OUT*_0 */ +#define PLL_OUT_RSTN (1 << 0) +#define PLL_OUT_CLKEN (1 << 1) +#define PLL_OUT_OVR (1 << 2) + +#define PLL_OUT_RATIO_SHIFT 8 +#define PLL_OUT_RATIO_MASK (0xffU << PLL_OUT_RATIO_SHIFT) + +#define PLL_OUT1_SHIFT 0 +#define PLL_OUT2_SHIFT 16 +#define PLL_OUT3_SHIFT 0 +#define PLL_OUT4_SHIFT 16 + +/* CLK_RST_CONTROLLER_PLL*_MISC_0 */ +#define PLL_MISC_DCCON (1 << 20) + +#define PLL_MISC_CPCON_SHIFT 8 +#define PLL_MISC_CPCON_MASK (0xfU << PLL_MISC_CPCON_SHIFT) + +#define PLL_MISC_LFCON_SHIFT 4 +#define PLL_MISC_LFCON_MASK (0xfU << PLL_MISC_LFCON_SHIFT) + +/* This bit is different all over the place. Oh joy... */ +#define PLLDPD2_MISC_LOCK_ENABLE (1 << 30) +#define PLLC_MISC_LOCK_ENABLE (1 << 24) +#define PLLUD_MISC_LOCK_ENABLE (1 << 22) +#define PLLD_MISC_CLK_ENABLE (1 << 30) +#define PLLPAXS_MISC_LOCK_ENABLE (1 << 18) +#define PLLE_MISC_LOCK_ENABLE (1 << 9) + +#define PLLU_MISC_VCO_FREQ (1 << 20) + +/* PLLX_BASE_0 0xe0 */ +#define PLLX_BASE_PLLX_ENABLE (1 << 30) + +/* CLK_RST_CONTROLLER_PLLX_MISC_3 */ +#define PLLX_IDDQ_SHIFT 3 +#define PLLX_IDDQ_MASK (1U << PLLX_IDDQ_SHIFT) + +#define CLK_DIVISOR_MASK (0xffff) + +#define CLK_SOURCE_SHIFT 29 +#define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT) + +#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16) + +#define CLK_UART_DIV_OVERRIDE (1 << 24) + +/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */ +#define SCLK_SYS_STATE_SHIFT 28U +#define SCLK_SYS_STATE_MASK (15U << SCLK_SYS_STATE_SHIFT) +enum { + SCLK_SYS_STATE_STDBY, + SCLK_SYS_STATE_IDLE, + SCLK_SYS_STATE_RUN, + SCLK_SYS_STATE_IRQ = 4U, + SCLK_SYS_STATE_FIQ = 8U, +}; +#define SCLK_COP_FIQ_MASK (1 << 27) +#define SCLK_CPU_FIQ_MASK (1 << 26) +#define SCLK_COP_IRQ_MASK (1 << 25) +#define SCLK_CPU_IRQ_MASK (1 << 24) + +#define SCLK_FIQ_SHIFT 12 +#define SCLK_FIQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IRQ_SHIFT 8 +#define SCLK_IRQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_RUN_SHIFT 4 +#define SCLK_RUN_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IDLE_SHIFT 0 +#define SCLK_IDLE_MASK (7 << SCLK_FIQ_SHIFT) +enum { + SCLK_SOURCE_CLKM, + SCLK_SOURCE_PLLC_OUT1, + SCLK_SOURCE_PLLP_OUT4, + SCLK_SOURCE_PLLP_OUT3, + SCLK_SOURCE_PLLP_OUT2, + SCLK_SOURCE_PLLC_OUT0, + SCLK_SOURCE_CLKS, + SCLK_SOURCE_PLLM_OUT1, +}; + +/* CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2c */ +#define SCLK_DIV_ENB (1 << 31) +#define SCLK_DIVIDEND_SHIFT 8 +#define SCLK_DIVIDEND_MASK (0xff << SCLK_DIVIDEND_SHIFT) +#define SCLK_DIVISOR_SHIFT 0 +#define SCLK_DIVISOR_MASK (0xff << SCLK_DIVISOR_SHIFT) + +/* CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 */ +#define HCLK_DISABLE (1 << 7) +#define HCLK_DIVISOR_SHIFT 4 +#define HCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) +#define PCLK_DISABLE (1 << 3) +#define PCLK_DIVISOR_SHIFT 0 +#define PCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) + +/* CRC_CLK_SOURCE_MSELECT_0 0x3b4 */ +#define MSELECT_CLK_SRC_PLLP_OUT0 (0 << 29) + +/* CRC_CLK_ENB_V_SET_0 0x440 */ +#define SET_CLK_ENB_CPUG_ENABLE (1 << 0) +#define SET_CLK_ENB_CPULP_ENABLE (1 << 1) +#define SET_CLK_ENB_MSELECT_ENABLE (1 << 3) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 0x484 */ +#define PLLU_POWERDOWN (1 << 16) +#define PLL_ENABLE_POWERDOWN (1 << 14) +#define PLL_ACTIVE_POWERDOWN (1 << 12) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG2_0 0x488 */ +#define UTMIP_FORCE_PD_SAMP_C_POWERDOWN (1 << 4) +#define UTMIP_FORCE_PD_SAMP_B_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PD_SAMP_A_POWERDOWN (1 << 0) + +// CCLK_BRST_POL +enum { + CRC_CCLK_BRST_POL_PLLX_OUT0 = 0x8, + CRC_CCLK_BRST_POL_CPU_STATE_RUN = 0x2 +}; + +// SUPER_CCLK_DIVIDER +enum { + CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31 +}; + +// CLK_CPU_CMPLX_CLR +enum { + CRC_CLK_CLR_CPU0_STP = 0x1 << 8, + CRC_CLK_CLR_CPU1_STP = 0x1 << 9, + CRC_CLK_CLR_CPU2_STP = 0x1 << 10, + CRC_CLK_CLR_CPU3_STP = 0x1 << 11 +}; + +// RST_CPUG_CMPLX_CLR +enum { + CRC_RST_CPUG_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPUG_CLR_CPU1 = 0x1 << 1, + CRC_RST_CPUG_CLR_CPU2 = 0x1 << 2, + CRC_RST_CPUG_CLR_CPU3 = 0x1 << 3, + CRC_RST_CPUG_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPUG_CLR_DBG1 = 0x1 << 13, + CRC_RST_CPUG_CLR_DBG2 = 0x1 << 14, + CRC_RST_CPUG_CLR_DBG3 = 0x1 << 15, + CRC_RST_CPUG_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPUG_CLR_CORE1 = 0x1 << 17, + CRC_RST_CPUG_CLR_CORE2 = 0x1 << 18, + CRC_RST_CPUG_CLR_CORE3 = 0x1 << 19, + CRC_RST_CPUG_CLR_CX0 = 0x1 << 20, + CRC_RST_CPUG_CLR_CX1 = 0x1 << 21, + CRC_RST_CPUG_CLR_CX2 = 0x1 << 22, + CRC_RST_CPUG_CLR_CX3 = 0x1 << 23, + CRC_RST_CPUG_CLR_L2 = 0x1 << 24, + CRC_RST_CPUG_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPUG_CLR_PDBG = 0x1 << 30, +}; + +// RST_CPULP_CMPLX_CLR +enum { + CRC_RST_CPULP_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPULP_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPULP_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPULP_CLR_CX0 = 0x1 << 20, + CRC_RST_CPULP_CLR_L2 = 0x1 << 24, + CRC_RST_CPULP_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPULP_CLR_PDBG = 0x1 << 30, +}; + +#endif /* _TEGRA124_CLK_RST_H_ */ diff --git a/src/soc/nvidia/tegra124/include/soc/clock.h b/src/soc/nvidia/tegra124/include/soc/clock.h new file mode 100644 index 0000000000..3133d0f76a --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/clock.h @@ -0,0 +1,310 @@ +/* + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA124_CLOCK_H__ +#define __SOC_NVIDIA_TEGRA124_CLOCK_H__ + +#include +#include +#include +#include +#include +#include + +enum { + CLK_L_CPU = 0x1 << 0, + CLK_L_COP = 0x1 << 1, + CLK_L_TRIG_SYS = 0x1 << 2, + CLK_L_RTC = 0x1 << 4, + CLK_L_TMR = 0x1 << 5, + CLK_L_UARTA = 0x1 << 6, + CLK_L_UARTB = 0x1 << 7, + CLK_L_GPIO = 0x1 << 8, + CLK_L_SDMMC2 = 0x1 << 9, + CLK_L_SPDIF = 0x1 << 10, + CLK_L_I2S1 = 0x1 << 11, + CLK_L_I2C1 = 0x1 << 12, + CLK_L_NDFLASH = 0x1 << 13, + CLK_L_SDMMC1 = 0x1 << 14, + CLK_L_SDMMC4 = 0x1 << 15, + CLK_L_PWM = 0x1 << 17, + CLK_L_I2S2 = 0x1 << 18, + CLK_L_EPP = 0x1 << 19, + CLK_L_VI = 0x1 << 20, + CLK_L_2D = 0x1 << 21, + CLK_L_USBD = 0x1 << 22, + CLK_L_ISP = 0x1 << 23, + CLK_L_3D = 0x1 << 24, + CLK_L_DISP2 = 0x1 << 26, + CLK_L_DISP1 = 0x1 << 27, + CLK_L_HOST1X = 0x1 << 28, + CLK_L_VCP = 0x1 << 29, + CLK_L_I2S0 = 0x1 << 30, + CLK_L_CACHE2 = 0x1 << 31, + + CLK_H_MEM = 0x1 << 0, + CLK_H_AHBDMA = 0x1 << 1, + CLK_H_APBDMA = 0x1 << 2, + CLK_H_KBC = 0x1 << 4, + CLK_H_STAT_MON = 0x1 << 5, + CLK_H_PMC = 0x1 << 6, + CLK_H_FUSE = 0x1 << 7, + CLK_H_KFUSE = 0x1 << 8, + CLK_H_SBC1 = 0x1 << 9, + CLK_H_SNOR = 0x1 << 10, + CLK_H_JTAG2TBC = 0x1 << 11, + CLK_H_SBC2 = 0x1 << 12, + CLK_H_SBC3 = 0x1 << 14, + CLK_H_I2C5 = 0x1 << 15, + CLK_H_DSI = 0x1 << 16, + CLK_H_HSI = 0x1 << 18, + CLK_H_HDMI = 0x1 << 19, + CLK_H_CSI = 0x1 << 20, + CLK_H_I2C2 = 0x1 << 22, + CLK_H_UARTC = 0x1 << 23, + CLK_H_MIPI_CAL = 0x1 << 24, + CLK_H_EMC = 0x1 << 25, + CLK_H_USB2 = 0x1 << 26, + CLK_H_USB3 = 0x1 << 27, + CLK_H_MPE = 0x1 << 28, + CLK_H_VDE = 0x1 << 29, + CLK_H_BSEA = 0x1 << 30, + CLK_H_BSEV = 0x1 << 31, + + CLK_U_UARTD = 0x1 << 1, + CLK_U_UARTE = 0x1 << 2, + CLK_U_I2C3 = 0x1 << 3, + CLK_U_SBC4 = 0x1 << 4, + CLK_U_SDMMC3 = 0x1 << 5, + CLK_U_PCIE = 0x1 << 6, + CLK_U_OWR = 0x1 << 7, + CLK_U_AFI = 0x1 << 8, + CLK_U_CSITE = 0x1 << 9, + CLK_U_PCIEXCLK = 0x1 << 10, + CLK_U_AVPUCQ = 0x1 << 11, + CLK_U_TRACECLKIN = 0x1 << 13, + CLK_U_SOC_THERM = 0x1 << 14, + CLK_U_DTV = 0x1 << 15, + CLK_U_NAND_SPEED = 0x1 << 16, + CLK_U_I2C_SLOW = 0x1 << 17, + CLK_U_DSIB = 0x1 << 18, + CLK_U_TSEC = 0x1 << 19, + CLK_U_IRAMA = 0x1 << 20, + CLK_U_IRAMB = 0x1 << 21, + CLK_U_IRAMC = 0x1 << 22, + + // Clock reset. + CLK_U_EMUCIF = 0x1 << 23, + // Clock enable. + CLK_U_IRAMD = 0x1 << 23, + + CLK_U_CRAM2 = 0x2 << 24, + CLK_U_XUSB_HOST = 0x1 << 25, + CLK_U_MSENC = 0x1 << 27, + CLK_U_SUS_OUT = 0x1 << 28, + CLK_U_DEV2_OUT = 0x1 << 29, + CLK_U_DEV1_OUT = 0x1 << 30, + CLK_U_XUSB_DEV = 0x1 << 31, + + CLK_V_CPUG = 0x1 << 0, + CLK_V_CPULP = 0x1 << 1, + CLK_V_3D2 = 0x1 << 2, + CLK_V_MSELECT = 0x1 << 3, + CLK_V_I2S3 = 0x1 << 5, + CLK_V_I2S4 = 0x1 << 6, + CLK_V_I2C4 = 0x1 << 7, + CLK_V_SBC5 = 0x1 << 8, + CLK_V_SBC6 = 0x1 << 9, + CLK_V_AUDIO = 0x1 << 10, + CLK_V_APBIF = 0x1 << 11, + CLK_V_DAM0 = 0x1 << 12, + CLK_V_DAM1 = 0x1 << 13, + CLK_V_DAM2 = 0x1 << 14, + CLK_V_HDA2CODEC_2X = 0x1 << 15, + CLK_V_ATOMICS = 0x1 << 16, + CLK_V_ACTMON = 0x1 << 23, + CLK_V_EXTPERIPH1 = 0x1 << 24, + CLK_V_SATA = 0x1 << 28, + CLK_V_HDA = 0x1 << 29, + + CLK_W_HDA2HDMICODEC = 0x1 << 0, + CLK_W_SATACOLD = 0x1 << 1, + CLK_W_CEC = 0x1 << 8, + CLK_W_XUSB_PADCTL = 0x1 << 14, + CLK_W_ENTROPY = 0x1 << 21, + CLK_W_AMX0 = 0x1 << 25, + CLK_W_ADX0 = 0x1 << 26, + CLK_W_DVFS = 0x1 << 27, + CLK_W_XUSB_SS = 0x1 << 28, + CLK_W_MC1 = 0x1 << 30, + CLK_W_EMC1 = 0x1 << 31, + + CLK_X_AFC0 = 0x1 << 31, + CLK_X_AFC1 = 0x1 << 30, + CLK_X_AFC2 = 0x1 << 29, + CLK_X_AFC3 = 0x1 << 28, + CLK_X_AFC4 = 0x1 << 27, + CLK_X_AFC5 = 0x1 << 26, + CLK_X_AMX1 = 0x1 << 25, + CLK_X_GPU = 0x1 << 24, + CLK_X_SOR0 = 0x1 << 22, + CLK_X_DPAUX = 0x1 << 21, + CLK_X_ADX1 = 0x1 << 20, + CLK_X_VIC = 0x1 << 18, + CLK_X_CLK72MHZ = 0x1 << 17, + CLK_X_HDMI_AUDIO = 0x1 << 16, + CLK_X_EMC_DLL = 0x1 << 14, + CLK_X_VIM2_CLK = 0x1 << 11, + CLK_X_I2C6 = 0x1 << 6, + CLK_X_CAM_MCLK2 = 0x1 << 5, + CLK_X_CAM_MCLK = 0x1 << 4, + CLK_X_SPARE = 0x1 << 0, +}; + +/* PLL stabilization delay in usec */ +#define CLOCK_PLL_STABLE_DELAY_US 300 + +#define IO_STABILIZATION_DELAY (2) + +/* Calculate clock fractional divider value from ref and target frequencies. + * This is for a U7.1 format. This is not well written up in the book and + * there have been some questions about this macro, so here we go. + * U7.1 format is defined as (ddddddd+1) + (h*.5) + * The lowest order bit is actually a fractional bit. + * Hence, the divider can be thought of as 9 bits. + * So: + * divider = ((ref/freq) << 1 - 1) (upper 7 bits) | + * (ref/freq & 1) (low order half-bit) + * however we can't do fractional arithmetic ... these are integers! + * So we normalize by shifting the result left 1 bit, and extracting + * ddddddd and h directly to the returned u8. + * divider = 2*(ref/freq); + * We want to + * preserve 7 bits of divisor and one bit of fraction, in 8 bits, as well as + * subtract one from ddddddd. Since we computed ref*2, the dddddd is now nicely + * situated in the upper 7 bits, and the h is sitting there in the low order + * bit. To subtract 1 from ddddddd, just subtract 2 from the 8-bit number + * and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you + * will assign this to a u8, it gets nicely truncated for you. + */ +#define CLK_DIVIDER(REF, FREQ) (div_round_up(((REF) * 2), (FREQ)) - 2) + +/* Calculate clock frequency value from reference and clock divider value + * The discussion in the book is pretty lacking. + * The idea is that we need to divide a ref clock by a divisor + * in U7.1 format, where 7 upper bits are the integer + * and lowest order bit is a fraction. + * from the book, U7.1 is (ddddddd+1) + (h*.5) + * To normalize to an actual number, we might do this: + * ((d>>7+1)&0x7f) + (d&1 >> 1) + * but as you might guess, the low order bit would be lost. + * Since we can't express the fractional bit, we need to multiply it all by 2. + * ((d + 2)&0xfe) + (d & 1) + * Since we're just adding +2, the lowest order bit is preserved. Hence + * (d+2) is the same as ((d + 2)&0xfe) + (d & 1) + * + * Since you multiply denominator * 2 (by NOT shifting it), + * you multiply numerator * 2 to cancel it out. + */ +#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / ((REG) + 2)) + +static inline void _clock_set_div(u32 *reg, const char *name, u32 div, + u32 div_mask, u32 src) +{ + // The I2C and UART divisors are 16 bit while all the others are 8 bit. + // The I2C clocks are handled by the specialized macro below, but the + // UART clocks aren't. Don't use this function on UART clocks. + if (div & ~div_mask) { + printk(BIOS_ERR, "%s clock divisor overflow!", name); + hlt(); + } + clrsetbits_le32(reg, CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + src << CLK_SOURCE_SHIFT | div); +} + +#define clock_configure_irregular_source(device, src, freq, src_id) \ + _clock_set_div(&clk_rst->clk_src_##device, #device, \ + CLK_DIVIDER(TEGRA_##src##_KHZ, freq), 0xff, src_id) + +/* Warning: Some devices just use different bits for the same sources for no + * apparent reason. *Always* double-check the TRM before trusting this macro. */ +#define clock_configure_source(device, src, freq) \ + clock_configure_irregular_source(device, src, freq, src) + +/* The I2C divisors are not 7.1 divisors like the others, they divide by n + 1 + * directly. Also, there are internal divisors in the I2C controller itself. + * We can deal with those here and make it easier to select what the actual + * bus frequency will be. The 0x19 value is the default divisor in the + * clk_divisor register in the controller, and 8 is just a magic number in the + * documentation. + */ +#define clock_configure_i2c_scl_freq(device, src, freq) \ + _clock_set_div(&clk_rst->clk_src_##device, #device, \ + div_round_up(TEGRA_##src##_KHZ, (freq) * (0x19 + 1) * 8) - 1, \ + 0xffff, src) + +enum clock_source { /* Careful: Not true for all sources, always check TRM! */ + PLLP = 0, + PLLC2 = 1, + PLLC = 2, + PLLD = 2, + PLLC3 = 3, + PLLA = 3, + PLLM = 4, + PLLD2 = 5, + CLK_M = 6, +}; + +/* soc-specific */ +#define TEGRA_CLK_M_KHZ clock_get_osc_khz() +#define TEGRA_PLLX_KHZ CONFIG_PLLX_KHZ +#define TEGRA_PLLP_KHZ (408000) +#define TEGRA_PLLC_KHZ (600000) +#define TEGRA_PLLD_KHZ (925000) +#define TEGRA_PLLU_KHZ (960000) + +#define TEGRA_SCLK_KHZ (300000) +#define TEGRA_HCLK_RATIO 1 +#define TEGRA_HCLK_KHZ (TEGRA_SCLK_KHZ / (1 + TEGRA_HCLK_RATIO)) +#define TEGRA_PCLK_RATIO 0 +#define TEGRA_PCLK_KHZ (TEGRA_HCLK_KHZ / (1 + TEGRA_PCLK_RATIO)) + +int clock_get_osc_khz(void); +int clock_get_pll_input_khz(void); +u32 clock_display(u32 frequency); +void clock_early_uart(void); +void clock_external_output(int clk_id); +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq); +void clock_cpu0_config(void * entry); +void clock_cpu0_remove_reset(void); +void clock_halt_avp(void); +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x); +void clock_reset_l(u32 l); +void clock_reset_h(u32 h); +void clock_reset_u(u32 u); +void clock_reset_v(u32 v); +void clock_reset_w(u32 w); +void clock_reset_x(u32 x); +void clock_init(void); +void clock_init_arm_generic_timer(void); +void sor_clock_stop(void); +void sor_clock_start(void); + +#endif /* __SOC_NVIDIA_TEGRA124_CLOCK_H__ */ + diff --git a/src/soc/nvidia/tegra124/include/soc/display.h b/src/soc/nvidia/tegra124/include/soc/display.h new file mode 100644 index 0000000000..980d2b38db --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/display.h @@ -0,0 +1,27 @@ +/* + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__ +#define __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__ + +#define COLOR_WHITE 0xFFFFFF + +struct soc_nvidia_tegra124_config; /* forward declaration */ +void setup_display(struct soc_nvidia_tegra124_config *config); + +#define FB_SIZE_MB (32) + +#endif /* __SOC_NVIDIA_TEGRA124_INCLUDE_SOC_DISPLAY_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/dma.h b/src/soc/nvidia/tegra124/include/soc/dma.h new file mode 100644 index 0000000000..e37bf743ad --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/dma.h @@ -0,0 +1,190 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __NVIDIA_TEGRA124_DMA_H__ +#define __NVIDIA_TEGRA124_DMA_H__ + +#include +#include + +/* + * The DMA engine operates on 4 bytes at a time, so make sure any data + * passed via DMA is aligned to avoid underrun/overrun. + */ +#define TEGRA_DMA_ALIGN_BYTES 4 + +/* + * Note: Many APB DMA controller registers are laid out such that each + * bit controls or represents the status for the corresponding channel. + * So we will not bother to list each individual bit in this case. + */ +#define APB_COMMAND_GEN (1 << 31) + +#define APB_CNTRL_REG_COUNT_VALUE_MASK 0xffff +#define APB_CNTRL_REG_COUNT_VALUE_SHIFT 0 + +/* + * Note: Many APB DMA controller registers are laid out such that each + * bit controls or represents the status for the corresponding channel. + * So we will not bother to list each individual bit in this case. + */ +#define APB_COMMAND_GEN (1 << 31) + +#define APB_CNTRL_REG_COUNT_VALUE_MASK 0xffff +#define APB_CNTRL_REG_COUNT_VALUE_SHIFT 0 +struct apb_dma { + u32 command; /* 0x00 */ + u32 status; /* 0x04 */ + u32 rsvd1[2]; + u32 cntrl_reg; /* 0x10 */ + u32 irq_sta_cpu; /* 0x14 */ + u32 irq_sta_cop; /* 0x18 */ + u32 irq_mask; /* 0x1c */ + u32 irq_mask_set; /* 0x20 */ + u32 irq_mask_clr; /* 0x24 */ + u32 trig_reg; /* 0x28 */ + u32 channel_trig_reg; /* 0x2c */ + u32 dma_status; /* 0x30 */ + u32 channel_en_reg; /* 0x34 */ + u32 security_reg; /* 0x38 */ + u32 channel_swid; /* 0x3c */ + u32 rsvd[1]; + u32 chan_wt_reg0; /* 0x44 */ + u32 chan_wt_reg1; /* 0x48 */ + u32 chan_wt_reg2; /* 0x4c */ + u32 chan_wr_reg3; /* 0x50 */ + u32 channel_swid1; /* 0x54 */ +} __attribute__((packed)); +check_member(apb_dma, channel_swid1, 0x54); + +/* + * Naming in the doc included a superfluous _CHANNEL_n_ for + * each entry and was left out for the sake of conciseness. + */ +#define APB_CSR_ENB (1 << 31) +#define APB_CSR_IE_EOC (1 << 30) +#define APB_CSR_HOLD (1 << 29) +#define APB_CSR_DIR (1 << 28) +#define APB_CSR_ONCE (1 << 27) +#define APB_CSR_FLOW (1 << 21) +#define APB_CSR_REQ_SEL_MASK 0x1f +#define APB_CSR_REQ_SEL_SHIFT 16 + +enum apbdmachan_req_sel { + APBDMA_SLAVE_CNTR_REQ = 0, + APBDMA_SLAVE_APBIF_CH0 = 1, + APBDMA_SLAVE_APBIF_CH1 = 2, + APBDMA_SLAVE_APBIF_CH2 = 3, + APBDMA_SLAVE_APBIF_CH3 = 4, + APBDMA_SLAVE_HSI = 5, + APBDMA_SLAVE_APBIF_CH4 = 6, + APBDMA_SLAVE_APBIF_CH5 = 7, + APBDMA_SLAVE_UART_A = 8, + APBDMA_SLAVE_UART_B = 9, + APBDMA_SLAVE_UART_C = 10, + APBDMA_SLAVE_DTV = 11, + APBDMA_SLAVE_APBIF_CH6 = 12, + APBDMA_SLAVE_APBIF_CH7 = 13, + APBDMA_SLAVE_APBIF_CH8 = 14, + APBDMA_SLAVE_SL2B1 = 15, + APBDMA_SLAVE_SL2B2 = 16, + APBDMA_SLAVE_SL2B3 = 17, + APBDMA_SLAVE_SL2B4 = 18, + APBDMA_SLAVE_UART_D = 19, + APBDMA_SLAVE_UART_E = 20, + APBDMA_SLAVE_I2C = 21, + APBDMA_SLAVE_I2C2 = 22, + APBDMA_SLAVE_I2C3 = 23, + APBDMA_SLAVE_DVC_I2C = 24, + APBDMA_SLAVE_OWR = 25, + APBDMA_SLAVE_I2C4 = 26, + APBDMA_SLAVE_SL2B5 = 27, + APBDMA_SLAVE_SL2B6 = 28, + APBDMA_SLAVE_APBIF_CH9 = 29, + APBDMA_SLAVE_I2C6 = 30, + APBDMA_SLAVE_NA31 = 31, +}; + +#define APB_STA_BSY (1 << 31) +#define APB_STA_ISE_EOC (1 << 30) +#define APB_STA_HALT (1 << 29) +#define APB_STA_PING_PONG_STA (1 << 28) +#define APB_STA_DMA_ACTIVITY (1 << 27) +#define APB_STA_CHANNEL_PAUSE (1 << 26) + +#define APB_CSRE_CHANNEL_PAUSE (1 << 31) +#define APB_CSRE_TRIG_SEL_MASK 0x3f +#define APB_CSRE_TRIG_SEL_SHIFT 14 + +#define AHB_PTR_MASK (0x3fffffff) +#define AHB_PTR_SHIFT 2 + +#define AHB_SEQ_INTR_ENB (1 << 31) +#define AHB_BUS_WIDTH_MASK 0x7 +#define AHB_BUS_WIDTH_SHIFT 28 +#define AHB_DATA_SWAP (1 << 27) +#define AHB_BURST_MASK 0x7 +#define AHB_BURST_SHIFT 24 +#define AHB_SEQ_DBL_BUF (1 << 19) +#define AHB_SEQ_WRAP_MASK 0x7 +#define AHB_SEQ_WRAP_SHIFT 16 + +#define APB_PTR_MASK 0x3fffffff +#define APB_PTR_SHIFT 2 + +#define APB_BUS_WIDTH_MASK 0x7 +#define APB_BUS_WIDTH_SHIFT 28 +#define APB_DATA_SWAP (1 << 27) +#define APB_ADDR_WRAP_MASK 0x7 +#define APB_ADDR_WRAP_SHIFT 16 + +#define APB_WORD_TRANSFER_MASK 0x0fffffff +#define APB_WORD_TRANSFER_SHIFT 2 + +struct apb_dma_channel_regs { + u32 csr; /* 0x00 */ + u32 sta; /* 0x04 */ + u32 dma_byte_sta; /* 0x08 */ + u32 csre; /* 0x0c */ + u32 ahb_ptr; /* 0x10 */ + u32 ahb_seq; /* 0x14 */ + u32 apb_ptr; /* 0x18 */ + u32 apb_seq; /* 0x1c */ + u32 wcount; /* 0x20 */ + u32 word_transfer; /* 0x24 */ +} __attribute__((packed)); +check_member(apb_dma_channel_regs, word_transfer, 0x24); + +struct apb_dma_channel { + const int num; + struct apb_dma_channel_regs *regs; + + /* + * Basic high-level semaphore that can be used to "claim" + * a DMA channel e.g. by SPI, I2C, or other peripheral driver. + */ + int in_use; +}; + +struct apb_dma_channel * const dma_claim(void); +void dma_release(struct apb_dma_channel * const channel); +int dma_start(struct apb_dma_channel * const channel); +int dma_stop(struct apb_dma_channel * const channel); +int dma_busy(struct apb_dma_channel * const channel); + +#endif /* __NVIDIA_TEGRA124_DMA_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/early_configs.h b/src/soc/nvidia/tegra124/include/soc/early_configs.h new file mode 100644 index 0000000000..69511d2765 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/early_configs.h @@ -0,0 +1,20 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +void early_mainboard_init(void); diff --git a/src/soc/nvidia/tegra124/include/soc/emc.h b/src/soc/nvidia/tegra124/include/soc/emc.h new file mode 100644 index 0000000000..f9d415bcef --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/emc.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA124_EMC_H__ +#define __SOC_NVIDIA_TEGRA124_EMC_H__ + +#include +#include + +enum { + EMC_PIN_RESET_MASK = 1 << 8, + EMC_PIN_RESET_ACTIVE = 0 << 8, + EMC_PIN_RESET_INACTIVE = 1 << 8, + EMC_PIN_DQM_MASK = 1 << 4, + EMC_PIN_DQM_NORMAL = 0 << 4, + EMC_PIN_DQM_INACTIVE = 1 << 4, + EMC_PIN_CKE_MASK = 1 << 0, + EMC_PIN_CKE_POWERDOWN = 0 << 0, + EMC_PIN_CKE_NORMAL = 1 << 0, + + EMC_REF_CMD_MASK = 1 << 0, + EMC_REF_CMD_REFRESH = 1 << 0, + EMC_REF_NORMAL_MASK = 1 << 1, + EMC_REF_NORMAL_INIT = 0 << 1, + EMC_REF_NORMAL_ENABLED = 1 << 1, + EMC_REF_NUM_SHIFT = 8, + EMC_REF_NUM_MASK = 0xFF << EMC_REF_NUM_SHIFT, + EMC_REF_DEV_SELECTN_SHIFT = 30, + EMC_REF_DEV_SELECTN_MASK = 3 << EMC_REF_DEV_SELECTN_SHIFT, + + EMC_REFCTRL_REF_VALID_MASK = 1 << 31, + EMC_REFCTRL_REF_VALID_DISABLED = 0 << 31, + EMC_REFCTRL_REF_VALID_ENABLED = 1 << 31, + + EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK = 1 << 1, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK = 1 << 2, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK = 1 << 3, + + EMC_NOP_NOP_CMD_SHIFT = 0, + EMC_NOP_NOP_CMD_MASK = 1 << EMC_NOP_NOP_CMD_SHIFT, + EMC_NOP_NOP_DEV_SELECTN_SHIFT = 30, + EMC_NOP_NOP_DEV_SELECTN_MASK = 3 << EMC_NOP_NOP_DEV_SELECTN_SHIFT, + + EMC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +struct tegra_emc_regs { + uint32_t intstatus; /* 0x0 */ + uint32_t intmask; /* 0x4 */ + uint32_t dbg; /* 0x8 */ + uint32_t cfg; /* 0xc */ + uint32_t adr_cfg; /* 0x10 */ + uint32_t rsvd_0x14[3]; /* 0x14 */ + + uint32_t refctrl; /* 0x20 */ + uint32_t pin; /* 0x24 */ + uint32_t timing_control; /* 0x28 */ + uint32_t rc; /* 0x2c */ + uint32_t rfc; /* 0x30 */ + uint32_t ras; /* 0x34 */ + uint32_t rp; /* 0x38 */ + uint32_t r2w; /* 0x3c */ + uint32_t w2r; /* 0x40 */ + uint32_t r2p; /* 0x44 */ + uint32_t w2p; /* 0x48 */ + uint32_t rd_rcd; /* 0x4c */ + uint32_t wr_rcd; /* 0x50 */ + uint32_t rrd; /* 0x54 */ + uint32_t rext; /* 0x58 */ + uint32_t wdv; /* 0x5c */ + uint32_t quse; /* 0x60 */ + uint32_t qrst; /* 0x64 */ + uint32_t qsafe; /* 0x68 */ + uint32_t rdv; /* 0x6c */ + uint32_t refresh; /* 0x70 */ + uint32_t burst_refresh_num; /* 0x74 */ + uint32_t pdex2wr; /* 0x78 */ + uint32_t pdex2rd; /* 0x7c */ + uint32_t pchg2pden; /* 0x80 */ + uint32_t act2pden; /* 0x84 */ + uint32_t ar2pden; /* 0x88 */ + uint32_t rw2pden; /* 0x8c */ + uint32_t txsr; /* 0x90 */ + uint32_t tcke; /* 0x94 */ + uint32_t tfaw; /* 0x98 */ + uint32_t trpab; /* 0x9c */ + uint32_t tclkstable; /* 0xa0 */ + uint32_t tclkstop; /* 0xa4 */ + uint32_t trefbw; /* 0xa8 */ + uint32_t rsvd_0xac[1]; /* 0xac */ + uint32_t odt_write; /* 0xb0 */ + uint32_t odt_read; /* 0xb4 */ + uint32_t wext; /* 0xb8 */ + uint32_t ctt; /* 0xbc */ + uint32_t rfc_slr; /* 0xc0 */ + uint32_t mrs_wait_cnt2; /* 0xc4 */ + uint32_t mrs_wait_cnt; /* 0xc8 */ + uint32_t mrs; /* 0xcc */ + uint32_t emrs; /* 0xd0 */ + uint32_t ref; /* 0xd4 */ + uint32_t pre; /* 0xd8 */ + uint32_t nop; /* 0xdc */ + uint32_t self_ref; /* 0xe0 */ + uint32_t dpd; /* 0xe4 */ + uint32_t mrw; /* 0xe8 */ + uint32_t mrr; /* 0xec */ + uint32_t cmdq; /* 0xf0 */ + uint32_t mc2emcq; /* 0xf4 */ + uint32_t xm2dqspadctrl3; /* 0xf8 */ + uint32_t rsvd_0xfc[1]; /* 0xfc */ + uint32_t fbio_spare; /* 0x100 */ + uint32_t fbio_cfg5; /* 0x104 */ + uint32_t fbio_wrptr_eq_2; /* 0x108 */ + uint32_t rsvd_0x10c[2]; /* 0x10c */ + + uint32_t fbio_cfg6; /* 0x114 */ + uint32_t rsvd_0x118[2]; /* 0x118 */ + + uint32_t cfg_rsv; /* 0x120 */ + uint32_t acpd_control; /* 0x124 */ + uint32_t rsvd_0x128[1]; /* 0x128 */ + uint32_t emrs2; /* 0x12c */ + uint32_t emrs3; /* 0x130 */ + uint32_t mrw2; /* 0x134 */ + uint32_t mrw3; /* 0x138 */ + uint32_t mrw4; /* 0x13c */ + uint32_t clken_override; /* 0x140 */ + uint32_t r2r; /* 0x144 */ + uint32_t w2w; /* 0x148 */ + uint32_t einput; /* 0x14c */ + uint32_t einput_duration; /* 0x150 */ + uint32_t puterm_extra; /* 0x154 */ + uint32_t tckesr; /* 0x158 */ + uint32_t tpd; /* 0x15c */ + uint32_t rsvd_0x160[81]; /* 0x160 */ + + uint32_t auto_cal_config; /* 0x2a4 */ + uint32_t auto_cal_interval; /* 0x2a8 */ + uint32_t auto_cal_status; /* 0x2ac */ + uint32_t req_ctrl; /* 0x2b0 */ + uint32_t status; /* 0x2b4 */ + uint32_t cfg_2; /* 0x2b8 */ + uint32_t cfg_dig_dll; /* 0x2bc */ + uint32_t cfg_dig_dll_period; /* 0x2c0 */ + uint32_t rsvd_0x2c4[1]; /* 0x2c4 */ + uint32_t dig_dll_status; /* 0x2c8 */ + uint32_t rdv_mask; /* 0x2cc */ + uint32_t wdv_mask; /* 0x2d0 */ + uint32_t rsvd_0x2d4[1]; /* 0x2d4 */ + uint32_t ctt_duration; /* 0x2d8 */ + uint32_t ctt_term_ctrl; /* 0x2dc */ + uint32_t zcal_interval; /* 0x2e0 */ + uint32_t zcal_wait_cnt; /* 0x2e4 */ + uint32_t zcal_mrw_cmd; /* 0x2e8 */ + uint32_t zq_cal; /* 0x2ec */ + uint32_t xm2cmdpadctrl; /* 0x2f0 */ + uint32_t xm2cmdpadctrl2; /* 0x2f4 */ + uint32_t xm2dqspadctrl; /* 0x2f8 */ + uint32_t xm2dqspadctrl2; /* 0x2fc */ + uint32_t xm2dqpadctrl; /* 0x300 */ + uint32_t xm2dqpadctrl2; /* 0x304 */ + uint32_t xm2clkpadctrl; /* 0x308 */ + uint32_t xm2comppadctrl; /* 0x30c */ + uint32_t xm2vttgenpadctrl; /* 0x310 */ + uint32_t xm2vttgenpadctrl2; /* 0x314 */ + uint32_t xm2vttgenpadctrl3; /* 0x318 */ + uint32_t emcpaden; /* 0x31c */ + uint32_t xm2dqspadctrl4; /* 0x320 */ + uint32_t scratch0; /* 0x324 */ + uint32_t dll_xform_dqs0; /* 0x328 */ + uint32_t dll_xform_dqs1; /* 0x32c */ + uint32_t dll_xform_dqs2; /* 0x330 */ + uint32_t dll_xform_dqs3; /* 0x334 */ + uint32_t dll_xform_dqs4; /* 0x338 */ + uint32_t dll_xform_dqs5; /* 0x33c */ + uint32_t dll_xform_dqs6; /* 0x340 */ + uint32_t dll_xform_dqs7; /* 0x344 */ + uint32_t dll_xform_quse0; /* 0x348 */ + uint32_t dll_xform_quse1; /* 0x34c */ + uint32_t dll_xform_quse2; /* 0x350 */ + uint32_t dll_xform_quse3; /* 0x354 */ + uint32_t dll_xform_quse4; /* 0x358 */ + uint32_t dll_xform_quse5; /* 0x35c */ + uint32_t dll_xform_quse6; /* 0x360 */ + uint32_t dll_xform_quse7; /* 0x364 */ + uint32_t dll_xform_dq0; /* 0x368 */ + uint32_t dll_xform_dq1; /* 0x36c */ + uint32_t dll_xform_dq2; /* 0x370 */ + uint32_t dll_xform_dq3; /* 0x374 */ + uint32_t dli_rx_trim0; /* 0x378 */ + uint32_t dli_rx_trim1; /* 0x37c */ + uint32_t dli_rx_trim2; /* 0x380 */ + uint32_t dli_rx_trim3; /* 0x384 */ + uint32_t dli_rx_trim4; /* 0x388 */ + uint32_t dli_rx_trim5; /* 0x38c */ + uint32_t dli_rx_trim6; /* 0x390 */ + uint32_t dli_rx_trim7; /* 0x394 */ + uint32_t dli_tx_trim0; /* 0x398 */ + uint32_t dli_tx_trim1; /* 0x39c */ + uint32_t dli_tx_trim2; /* 0x3a0 */ + uint32_t dli_tx_trim3; /* 0x3a4 */ + uint32_t dli_trim_txdqs0; /* 0x3a8 */ + uint32_t dli_trim_txdqs1; /* 0x3ac */ + uint32_t dli_trim_txdqs2; /* 0x3b0 */ + uint32_t dli_trim_txdqs3; /* 0x3b4 */ + uint32_t dli_trim_txdqs4; /* 0x3b8 */ + uint32_t dli_trim_txdqs5; /* 0x3bc */ + uint32_t dli_trim_txdqs6; /* 0x3c0 */ + uint32_t dli_trim_txdqs7; /* 0x3c4 */ + uint32_t rsvd_0x3c8[1]; /* 0x3c8 */ + uint32_t stall_then_exe_after_clkchange; /* 0x3cc */ + uint32_t rsvd_0x3d0[1]; /* 0x3d0 */ + uint32_t auto_cal_clk_status; /* 0x3d4 */ + uint32_t sel_dpd_ctrl; /* 0x3d8 */ + uint32_t pre_refresh_req_cnt; /* 0x3dc */ + uint32_t dyn_self_ref_control; /* 0x3e0 */ + uint32_t txsrdll; /* 0x3e4 */ + uint32_t ccfifo_addr; /* 0x3e8 */ + uint32_t ccfifo_data; /* 0x3ec */ + uint32_t ccfifo_status; /* 0x3f0 */ + uint32_t cdb_cntl_1; /* 0x3f4 */ + uint32_t cdb_cntl_2; /* 0x3f8 */ + uint32_t xm2clkpadctrl2; /* 0x3fc */ + uint32_t swizzle_rank0_byte_cfg; /* 0x400 */ + uint32_t swizzle_rank0_byte0; /* 0x404 */ + uint32_t swizzle_rank0_byte1; /* 0x408 */ + uint32_t swizzle_rank0_byte2; /* 0x40c */ + uint32_t swizzle_rank0_byte3; /* 0x410 */ + uint32_t swizzle_rank1_byte_cfg; /* 0x414 */ + uint32_t swizzle_rank1_byte0; /* 0x418 */ + uint32_t swizzle_rank1_byte1; /* 0x41c */ + uint32_t swizzle_rank1_byte2; /* 0x420 */ + uint32_t swizzle_rank1_byte3; /* 0x424 */ + uint32_t ca_training_start; /* 0x428 */ + uint32_t ca_training_busy; /* 0x42c */ + uint32_t ca_training_cfg; /* 0x430 */ + uint32_t ca_training_timing_cntl1; /* 0x434 */ + uint32_t ca_training_timing_cntl2; /* 0x438 */ + uint32_t ca_training_ca_lead_in; /* 0x43c */ + uint32_t ca_training_ca; /* 0x440 */ + uint32_t ca_training_ca_lead_out; /* 0x444 */ + uint32_t ca_training_result1; /* 0x448 */ + uint32_t ca_training_result2; /* 0x44c */ + uint32_t ca_training_result3; /* 0x450 */ + uint32_t ca_training_result4; /* 0x454 */ + uint32_t auto_cal_config2; /* 0x458 */ + uint32_t auto_cal_config3; /* 0x45c */ + uint32_t auto_cal_status2; /* 0x460 */ + uint32_t xm2cmdpadctrl3; /* 0x464 */ + uint32_t ibdly; /* 0x468 */ + uint32_t dll_xform_addr0; /* 0x46c */ + uint32_t dll_xform_addr1; /* 0x470 */ + uint32_t dll_xform_addr2; /* 0x474 */ + uint32_t dli_addr_trim; /* 0x478 */ + uint32_t dsr_vttgen_drv; /* 0x47c */ + uint32_t txdsrvttgen; /* 0x480 */ + uint32_t xm2cmdpadctrl4; /* 0x484 */ + uint32_t xm2cmdpadctrl5; /* 0x488 */ + uint32_t rsvd_0x48c[5]; /* 0x48c */ + + uint32_t dll_xform_dqs8; /* 0x4a0 */ + uint32_t dll_xform_dqs9; /* 0x4a4 */ + uint32_t dll_xform_dqs10; /* 0x4a8 */ + uint32_t dll_xform_dqs11; /* 0x4ac */ + uint32_t dll_xform_dqs12; /* 0x4b0 */ + uint32_t dll_xform_dqs13; /* 0x4b4 */ + uint32_t dll_xform_dqs14; /* 0x4b8 */ + uint32_t dll_xform_dqs15; /* 0x4bc */ + uint32_t dll_xform_quse8; /* 0x4c0 */ + uint32_t dll_xform_quse9; /* 0x4c4 */ + uint32_t dll_xform_quse10; /* 0x4c8 */ + uint32_t dll_xform_quse11; /* 0x4cc */ + uint32_t dll_xform_quse12; /* 0x4d0 */ + uint32_t dll_xform_quse13; /* 0x4d4 */ + uint32_t dll_xform_quse14; /* 0x4d8 */ + uint32_t dll_xform_quse15; /* 0x4dc */ + uint32_t dll_xform_dq4; /* 0x4e0 */ + uint32_t dll_xform_dq5; /* 0x4e4 */ + uint32_t dll_xform_dq6; /* 0x4e8 */ + uint32_t dll_xform_dq7; /* 0x4ec */ + uint32_t rsvd_0x4f0[12]; /* 0x4f0 */ + + uint32_t dli_trim_txdqs8; /* 0x520 */ + uint32_t dli_trim_txdqs9; /* 0x524 */ + uint32_t dli_trim_txdqs10; /* 0x528 */ + uint32_t dli_trim_txdqs11; /* 0x52c */ + uint32_t dli_trim_txdqs12; /* 0x530 */ + uint32_t dli_trim_txdqs13; /* 0x534 */ + uint32_t dli_trim_txdqs14; /* 0x538 */ + uint32_t dli_trim_txdqs15; /* 0x53c */ + uint32_t cdb_cntl_3; /* 0x540 */ + uint32_t xm2dqspadctrl5; /* 0x544 */ + uint32_t xm2dqspadctrl6; /* 0x548 */ + uint32_t xm2dqpadctrl3; /* 0x54c */ + uint32_t dll_xform_addr3; /* 0x550 */ + uint32_t dll_xform_addr4; /* 0x554 */ + uint32_t dll_xform_addr5; /* 0x558 */ + uint32_t rsvd_0x55c[1]; /* 0x55c */ + uint32_t cfg_pipe; /* 0x560 */ + uint32_t qpop; /* 0x564 */ + uint32_t quse_width; /* 0x568 */ + uint32_t puterm_width; /* 0x56c */ + uint32_t bgbias_ctl0; /* 0x570 */ + uint32_t puterm_adj; /* 0x574 */ +} __attribute__((packed)); + +check_member(tegra_emc_regs, puterm_adj, 0x574); + +#endif /* __SOC_NVIDIA_TEGRA124_EMC_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/flow.h b/src/soc/nvidia/tegra124/include/soc/flow.h new file mode 100644 index 0000000000..416681ac8f --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/flow.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA124_FLOW_H_ +#define _TEGRA124_FLOW_H_ + +struct flow_ctlr { + u32 halt_cpu_events; /* offset 0x00 */ + u32 halt_cop_events; /* offset 0x04 */ + u32 cpu_csr; /* offset 0x08 */ + u32 cop_csr; /* offset 0x0c */ + u32 xrq_events; /* offset 0x10 */ + u32 halt_cpu1_events; /* offset 0x14 */ + u32 cpu1_csr; /* offset 0x18 */ + u32 halt_cpu2_events; /* offset 0x1c */ + u32 cpu2_csr; /* offset 0x20 */ + u32 halt_cpu3_events; /* offset 0x24 */ + u32 cpu3_csr; /* offset 0x28 */ + u32 cluster_control; /* offset 0x2c */ + u32 halt_cop1_events; /* offset 0x30 */ + u32 halt_cop1_csr; /* offset 0x34 */ + u32 cpu_pwr_csr; /* offset 0x38 */ + u32 mpid; /* offset 0x3c */ + u32 ram_repair; /* offset 0x40 */ + u32 flow_dbg_sel; /* offset 0x44 */ + u32 flow_dbg_cnt0; /* offset 0x48 */ + u32 flow_dbg_cnt1; /* offset 0x4c */ + u32 flow_dbg_qual; /* offset 0x50 */ + u32 flow_ctlr_spare; /* offset 0x54 */ + u32 ram_repair_cluster1;/* offset 0x58 */ +}; +check_member(flow_ctlr, ram_repair_cluster1, 0x58); + +enum { + FLOW_MODE_SHIFT = 29, + FLOW_MODE_MASK = 0x7 << FLOW_MODE_SHIFT, + + FLOW_MODE_NONE = 0 << FLOW_MODE_SHIFT, + FLOW_MODE_RUN_AND_INT = 1 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT = 2 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT_AND_INT = 3 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ = 4 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ_AND_INT = 5 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_EVENT_AND_IRQ = 6 << FLOW_MODE_SHIFT, +}; + +/* HALT_COP_EVENTS_0, 0x04 */ +enum { + FLOW_EVENT_GIC_FIQ = 1 << 8, + FLOW_EVENT_GIC_IRQ = 1 << 9, + FLOW_EVENT_LIC_FIQ = 1 << 10, + FLOW_EVENT_LIC_IRQ = 1 << 11, + FLOW_EVENT_IBF = 1 << 12, + FLOW_EVENT_IBE = 1 << 13, + FLOW_EVENT_OBF = 1 << 14, + FLOW_EVENT_OBE = 1 << 15, + FLOW_EVENT_XRQ_A = 1 << 16, + FLOW_EVENT_XRQ_B = 1 << 17, + FLOW_EVENT_XRQ_C = 1 << 18, + FLOW_EVENT_XRQ_D = 1 << 19, + FLOW_EVENT_SMP30 = 1 << 20, + FLOW_EVENT_SMP31 = 1 << 21, + FLOW_EVENT_X_RDY = 1 << 22, + FLOW_EVENT_SEC = 1 << 23, + FLOW_EVENT_MSEC = 1 << 24, + FLOW_EVENT_USEC = 1 << 25, + FLOW_EVENT_X32K = 1 << 26, + FLOW_EVENT_SCLK = 1 << 27, + FLOW_EVENT_JTAG = 1 << 28 +}; + +/* RAM_REPAIR, 0x40, 0x58 */ +enum { + RAM_REPAIR_REQ = 0x1 << 0, + RAM_REPAIR_STS = 0x1 << 1, +}; + +#endif /* _TEGRA124_FLOW_H_ */ diff --git a/src/soc/nvidia/tegra124/include/soc/gpio.h b/src/soc/nvidia/tegra124/include/soc/gpio.h new file mode 100644 index 0000000000..34de5b93df --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/gpio.h @@ -0,0 +1,69 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_GPIO_H__ +#define __SOC_NVIDIA_TEGRA124_GPIO_H__ + +#include +#include /* for pinmux constants in GPIO macro */ +#include + +/* GPIO index constants. */ + +#define GPIO_PORT_CONSTANTS(port) \ + GPIO_##port##0_INDEX, GPIO_##port##1_INDEX, GPIO_##port##2_INDEX, \ + GPIO_##port##3_INDEX, GPIO_##port##4_INDEX, GPIO_##port##5_INDEX, \ + GPIO_##port##6_INDEX, GPIO_##port##7_INDEX + +enum { + GPIO_PORT_CONSTANTS(A), + GPIO_PORT_CONSTANTS(B), + GPIO_PORT_CONSTANTS(C), + GPIO_PORT_CONSTANTS(D), + GPIO_PORT_CONSTANTS(E), + GPIO_PORT_CONSTANTS(F), + GPIO_PORT_CONSTANTS(G), + GPIO_PORT_CONSTANTS(H), + GPIO_PORT_CONSTANTS(I), + GPIO_PORT_CONSTANTS(J), + GPIO_PORT_CONSTANTS(K), + GPIO_PORT_CONSTANTS(L), + GPIO_PORT_CONSTANTS(M), + GPIO_PORT_CONSTANTS(N), + GPIO_PORT_CONSTANTS(O), + GPIO_PORT_CONSTANTS(P), + GPIO_PORT_CONSTANTS(Q), + GPIO_PORT_CONSTANTS(R), + GPIO_PORT_CONSTANTS(S), + GPIO_PORT_CONSTANTS(T), + GPIO_PORT_CONSTANTS(U), + GPIO_PORT_CONSTANTS(V), + GPIO_PORT_CONSTANTS(W), + GPIO_PORT_CONSTANTS(X), + GPIO_PORT_CONSTANTS(Y), + GPIO_PORT_CONSTANTS(Z), + GPIO_PORT_CONSTANTS(AA), + GPIO_PORT_CONSTANTS(BB), + GPIO_PORT_CONSTANTS(CC), + GPIO_PORT_CONSTANTS(DD), + GPIO_PORT_CONSTANTS(EE), + GPIO_PORT_CONSTANTS(FF) +}; + +#endif /* __SOC_NVIDIA_TEGRA124_GPIO_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/maincpu.h b/src/soc/nvidia/tegra124/include/soc/maincpu.h new file mode 100644 index 0000000000..1d5a907a80 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/maincpu.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_MAINCPU_H__ +#define __SOC_NVIDIA_TEGRA124_MAINCPU_H__ + +#include + +extern u32 maincpu_stack_pointer; +extern u32 maincpu_entry_point; +void maincpu_setup(void); + +#endif /* __SOC_NVIDIA_TEGRA124_MAINCPU_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/mc.h b/src/soc/nvidia/tegra124/include/soc/mc.h new file mode 100644 index 0000000000..567b32a226 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/mc.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA124_MC_H__ +#define __SOC_NVIDIA_TEGRA124_MC_H__ + +#include +#include + +// Memory Controller registers we need/care about + +struct tegra_mc_regs { + uint32_t rsvd_0x0[4]; /* 0x00 */ + uint32_t smmu_config; /* 0x10 */ + uint32_t smmu_tlb_config; /* 0x14 */ + uint32_t smmu_ptc_config; /* 0x18 */ + uint32_t smmu_ptb_asid; /* 0x1c */ + uint32_t smmu_ptb_data; /* 0x20 */ + uint32_t rsvd_0x24[3]; /* 0x24 */ + uint32_t smmu_tlb_flush; /* 0x30 */ + uint32_t smmu_ptc_flush; /* 0x34 */ + uint32_t rsvd_0x38[6]; /* 0x38 */ + uint32_t emem_cfg; /* 0x50 */ + uint32_t emem_adr_cfg; /* 0x54 */ + uint32_t emem_adr_cfg_dev0; /* 0x58 */ + uint32_t emem_adr_cfg_dev1; /* 0x5c */ + uint32_t rsvd_0x60[1]; /* 0x60 */ + uint32_t emem_adr_cfg_bank_mask_0; /* 0x64 */ + uint32_t emem_adr_cfg_bank_mask_1; /* 0x68 */ + uint32_t emem_adr_cfg_bank_mask_2; /* 0x6c */ + uint32_t rsvd_0x70[8]; /* 0x70 */ + uint32_t emem_arb_cfg; /* 0x90 */ + uint32_t emem_arb_outstanding_req; /* 0x94 */ + uint32_t emem_arb_timing_rcd; /* 0x98 */ + uint32_t emem_arb_timing_rp; /* 0x9c */ + uint32_t emem_arb_timing_rc; /* 0xa0 */ + uint32_t emem_arb_timing_ras; /* 0xa4 */ + uint32_t emem_arb_timing_faw; /* 0xa8 */ + uint32_t emem_arb_timing_rrd; /* 0xac */ + uint32_t emem_arb_timing_rap2pre; /* 0xb0 */ + uint32_t emem_arb_timing_wap2pre; /* 0xb4 */ + uint32_t emem_arb_timing_r2r; /* 0xb8 */ + uint32_t emem_arb_timing_w2w; /* 0xbc */ + uint32_t emem_arb_timing_r2w; /* 0xc0 */ + uint32_t emem_arb_timing_w2r; /* 0xc4 */ + uint32_t rsvd_0xc8[2]; /* 0xc8 */ + uint32_t emem_arb_da_turns; /* 0xd0 */ + uint32_t emem_arb_da_covers; /* 0xd4 */ + uint32_t emem_arb_misc0; /* 0xd8 */ + uint32_t emem_arb_misc1; /* 0xdc */ + uint32_t emem_arb_ring1_throttle; /* 0xe0 */ + uint32_t emem_arb_ring3_throttle; /* 0xe4 */ + uint32_t emem_arb_override; /* 0xe8 */ + uint32_t emem_arb_rsv; /* 0xec */ + uint32_t rsvd_0xf0[1]; /* 0xf0 */ + uint32_t clken_override; /* 0xf4 */ + uint32_t timing_control_dbg; /* 0xf8 */ + uint32_t timing_control; /* 0xfc */ + uint32_t stat_control; /* 0x100 */ + uint32_t rsvd_0x104[65]; /* 0x104 */ + uint32_t emem_arb_isochronous_0; /* 0x208 */ + uint32_t emem_arb_isochronous_1; /* 0x20c */ + uint32_t emem_arb_isochronous_2; /* 0x210 */ + uint32_t rsvd_0x214[38]; /* 0x214 */ + uint32_t dis_extra_snap_levels; /* 0x2ac */ + uint32_t rsvd_0x2b0[90]; /* 0x2b0 */ + uint32_t video_protect_vpr_override; /* 0x418 */ + uint32_t rsvd_0x41c[93]; /* 0x41c */ + uint32_t video_protect_vpr_override1; /* 0x590 */ + uint32_t rsvd_0x594[29]; /* 0x594 */ + uint32_t display_snap_ring; /* 0x608 */ + uint32_t rsvd_0x60c[15]; /* 0x60c */ + uint32_t video_protect_bom; /* 0x648 */ + uint32_t video_protect_size_mb; /* 0x64c */ + uint32_t video_protect_reg_ctrl; /* 0x650 */ + uint32_t rsvd_0x654[4]; /* 0x654 */ + uint32_t emem_cfg_access_ctrl; /* 0x664 */ + uint32_t rsvd_0x668[2]; /* 0x668 */ + uint32_t sec_carveout_bom; /* 0x670 */ + uint32_t sec_carveout_size_mb; /* 0x674 */ + uint32_t sec_carveout_reg_ctrl; /* 0x678 */ + uint32_t rsvd_0x67c[187]; /* 0x67c */ + uint32_t emem_arb_override_1; /* 0x968 */ + uint32_t rsvd_0x96c[3]; /* 0x96c */ + uint32_t video_protect_bom_adr_hi; /* 0x978 */ + uint32_t rsvd_0x97c[2]; /* 0x97c */ + uint32_t video_protect_gpu_override_0; /* 0x984 */ + uint32_t video_protect_gpu_override_1; /* 0x988 */ + uint32_t rsvd_0x98c[5]; /* 0x98c */ + uint32_t mts_carveout_bom; /* 0x9a0 */ + uint32_t mts_carveout_size_mb; /* 0x9a4 */ + uint32_t mts_carveout_adr_hi; /* 0x9a8 */ + uint32_t mts_carveout_reg_ctrl; /* 0x9ac */ + uint32_t rsvd_0x9b0[4]; /* 0x9b0 */ + uint32_t emem_bank_swizzle_cfg0; /* 0x9c0 */ + uint32_t emem_bank_swizzle_cfg1; /* 0x9c4 */ + uint32_t emem_bank_swizzle_cfg2; /* 0x9c8 */ + uint32_t emem_bank_swizzle_cfg3; /* 0x9cc */ + uint32_t rsvd_0x9d0[1]; /* 0x9d0 */ + uint32_t sec_carveout_adr_hi; /* 0x9d4 */ +}; + +enum { + MC_EMEM_CFG_SIZE_MB_SHIFT = 0, + MC_EMEM_CFG_SIZE_MB_MASK = 0x3fff, + + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_SHIFT = 27, + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK = 1 << 27, + + MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED = 1, + + MC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +check_member(tegra_mc_regs, sec_carveout_adr_hi, 0x9d4); + +#endif /* __SOC_NVIDIA_TEGRA124_MC_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/memlayout.ld b/src/soc/nvidia/tegra124/include/soc/memlayout.ld new file mode 100644 index 0000000000..00674780e6 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/memlayout.ld @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +/* + * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself, + * so the bootblock loading address must be placed after that. After the + * handoff that area may be reclaimed for other uses, e.g. CBFS cache. + */ + +SECTIONS +{ + SRAM_START(0x40000000) + TTB(0x40000000, 16K + 32) + PRERAM_CBMEM_CONSOLE(0x40004020, 8K - 32) + PRERAM_CBFS_CACHE(0x40006000, 16K) + VBOOT2_WORK(0x4000A000, 16K) + STACK(0x4000E000, 7K) + TIMESTAMP(0x4000FC00, 1K) + BOOTBLOCK(0x40010000, 24K) + VERSTAGE(0x40016000, 72K) + ROMSTAGE(0x40028000, 96K) + SRAM_END(0x40040000) + + DRAM_START(0x80000000) + POSTRAM_CBFS_CACHE(0x80100000, 1M) + RAMSTAGE(0x80200000, 128K) + DMA_COHERENT(0x90000000, 2M) +} diff --git a/src/soc/nvidia/tegra124/include/soc/pingroup.h b/src/soc/nvidia/tegra124/include/soc/pingroup.h new file mode 100644 index 0000000000..ed9557b1ba --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/pingroup.h @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_PINGROUP_H__ +#define __SOC_NVIDIA_TEGRA124_PINGROUP_H__ + +#include +#include + +enum { + PINGROUP_AO1_INDEX = 0, /* offset 0x868 */ + PINGROUP_AO2_INDEX = 1, + PINGROUP_AT1_INDEX = 2, + PINGROUP_AT2_INDEX = 3, + PINGROUP_AT3_INDEX = 4, + PINGROUP_AT4_INDEX = 5, + PINGROUP_AT5_INDEX = 6, + PINGROUP_CDEV1_INDEX = 7, + PINGROUP_CDEV2_INDEX = 8, + PINGROUP_DAP1_INDEX = 10, /* offset 0x890 */ + PINGROUP_DAP2_INDEX = 11, + PINGROUP_DAP3_INDEX = 12, + PINGROUP_DAP4_INDEX = 13, + PINGROUP_DBG_INDEX = 14, + PINGROUP_SDIO3_INDEX = 18, /* offset 0x8B0 */ + PINGROUP_SPI_INDEX = 19, + PINGROUP_UAA_INDEX = 20, + PINGROUP_UAB_INDEX = 21, + PINGROUP_UART2_INDEX = 22, + PINGROUP_UART3_INDEX = 23, + PINGROUP_SDIO1_INDEX = 33, /* offset 0x8EC */ + PINGROUP_DDC_INDEX = 37, /* offset 0x8FC */ + PINGROUP_GMA_INDEX = 38, + PINGROUP_GME_INDEX = 42, /* offset 0x910 */ + PINGROUP_GMF_INDEX = 43, + PINGROUP_GMG_INDEX = 44, + PINGROUP_GMH_INDEX = 45, + PINGROUP_OWR_INDEX = 46, + PINGROUP_UAD_INDEX = 47, + PINGROUP_DEV3_INDEX = 49, /* offset 0x92c */ + PINGROUP_CEC_INDEX = 52, /* offset 0x938 */ + PINGROUP_AT6_INDEX = 75, /* offset 0x994 */ + PINGROUP_DAP5_INDEX = 76, + PINGROUP_VBUS_INDEX = 77, + PINGROUP_AO3_INDEX = 78, + PINGROUP_HVC_INDEX = 79, + PINGROUP_SDIO4_INDEX = 80, + PINGROUP_AO0_INDEX = 81, +}; + +#endif /* __SOC_NVIDIA_TEGRA124_PINGROUP_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/pinmux.h b/src/soc/nvidia/tegra124/include/soc/pinmux.h new file mode 100644 index 0000000000..c79732b7e2 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/pinmux.h @@ -0,0 +1,260 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_PINMUX_H__ +#define __SOC_NVIDIA_TEGRA124_PINMUX_H__ + +#include +#include + +#define PINMUX_CONSTANTS(index, name, gpio, func0, func1, func2, func3) \ + PINMUX_##name##_INDEX = index, \ + PINMUX_##name##_FUNC_##func0 = 0, \ + PINMUX_##name##_FUNC_##func1 = 1, \ + PINMUX_##name##_FUNC_##func2 = 2, \ + PINMUX_##name##_FUNC_##func3 = 3, \ + PINMUX_GPIO_##gpio = PINMUX_##name##_INDEX + +enum { + PINMUX_CONSTANTS(0, ULPI_DATA0, O1, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(1, ULPI_DATA1, O2, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(2, ULPI_DATA2, O3, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(3, ULPI_DATA3, O4, SPI3, HSI, UA3, ULPI), + PINMUX_CONSTANTS(4, ULPI_DATA4, O5, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(5, ULPI_DATA5, O6, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(6, ULPI_DATA6, O7, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(7, ULPI_DATA7, O0, SPI2, HSI, UA3, ULPI), + PINMUX_CONSTANTS(8, ULPI_CLK, Y0, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(9, ULPI_DIR, Y1, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(10, ULPI_NXT, Y2, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(11, ULPI_STP, Y3, SPI1, SPI5, UD3, ULPI), + PINMUX_CONSTANTS(12, DAP3_FS, P0, I2S2, SPI5, DCA, DCB), + PINMUX_CONSTANTS(13, DAP3_DIN, P1, I2S2, SPI5, DCA, DCB), + PINMUX_CONSTANTS(14, DAP3_DOUT, P2, I2S2, SPI5, DCA, RES3), + PINMUX_CONSTANTS(15, DAP3_SCLK, P3, I2S2, SPI5, RES2, DCB), + PINMUX_CONSTANTS(16, GPIO_PV0, V0, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(17, GPIO_PV1, V1, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(18, SDMMC1_CLK, Z0, SDMMC1, CLK12M, RES2, RES3), + PINMUX_CONSTANTS(19, SDMMC1_CMD, Z1, SDMMC1, SPDIF, SPI4, UA3), + PINMUX_CONSTANTS(20, SDMMC1_DAT3, Y4, SDMMC1, SPDIF, SPI4, UA3), + PINMUX_CONSTANTS(21, SDMMC1_DAT2, Y5, SDMMC1, PWM0, SPI4, UA3), + PINMUX_CONSTANTS(22, SDMMC1_DAT1, Y6, SDMMC1, PWM1, SPI4, UA3), + PINMUX_CONSTANTS(23, SDMMC1_DAT0, Y7, SDMMC1, RES1, SPI4, UA3), + PINMUX_CONSTANTS(26, CLK2_OUT, W5, EXTPERIPH2, RES1, RES2, RES3), + PINMUX_CONSTANTS(27, CLK2_REQ, CC5, DAP, RES1, RES2, RES3), + PINMUX_CONSTANTS(68, HDMI_INT, N7, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(69, DDC_SCL, V4, I2C4, RES1, RES2, RES3), + PINMUX_CONSTANTS(70, DDC_SDA, V5, I2C4, RES1, RES2, RES3), + PINMUX_CONSTANTS(89, UART2_RXD, C3, IR3, SPDIF, UA3, SPI4), + PINMUX_CONSTANTS(90, UART2_TXD, C2, IR3, SPDIF, UA3, SPI4), + PINMUX_CONSTANTS(91, UART2_RTS_N, J6, UA3, UB3, NOR, SPI4), + PINMUX_CONSTANTS(92, UART2_CTS_N, J5, UA3, UB3, NOR, SPI4), + PINMUX_CONSTANTS(93, UART3_TXD, W6, UC3, RES1, NOR, SPI4), + PINMUX_CONSTANTS(94, UART3_RXD, W7, UC3, RES1, NOR, SPI4), + PINMUX_CONSTANTS(95, UART3_CTS_N, A1, UC3, SDMMC1, DTV, NOR), + PINMUX_CONSTANTS(96, UART3_RTS_N, C0, UC3, PWM0, DTV, NOR), + PINMUX_CONSTANTS(97, GPIO_PU0, U0, OWR, UA3, NOR, RES3), + PINMUX_CONSTANTS(98, GPIO_PU1, U1, RES0, UA3, NOR, RES3), + PINMUX_CONSTANTS(99, GPIO_PU2, U2, RES0, UA3, NOR, RES3), + PINMUX_CONSTANTS(100, GPIO_PU3, U3, PWM0, UA3, NOR, DCB), + PINMUX_CONSTANTS(101, GPIO_PU4, U4, PWM1, UA3, NOR, DCB), + PINMUX_CONSTANTS(102, GPIO_PU5, U5, PWM2, UA3, NOR, DCB), + PINMUX_CONSTANTS(103, GPIO_PU6, U6, PWM3, UA3, RES2, NOR), + PINMUX_CONSTANTS(104, GEN1_I2C_SDA, C5, I2C1, RES1, RES2, RES3), + PINMUX_CONSTANTS(105, GEN1_I2C_SCL, C4, I2C1, RES1, RES2, RES3), + PINMUX_CONSTANTS(106, DAP4_FS, P4, I2S3, NOR, DTV, RES3), + PINMUX_CONSTANTS(107, DAP4_DIN, P5, I2S3, NOR, RES2, RES3), + PINMUX_CONSTANTS(108, DAP4_DOUT, P6, I2S3, NOR, DTV, RES3), + PINMUX_CONSTANTS(109, DAP4_SCLK, P7, I2S3, NOR, RES2, RES3), + PINMUX_CONSTANTS(110, CLK3_OUT, EE0, EXTPERIPH3, RES1, RES2, RES3), + PINMUX_CONSTANTS(111, CLK3_REQ, EE1, DEV3, RES1, RES2, RES3), + PINMUX_CONSTANTS(112, GPIO_PC7, C7, RES0, RES1, NOR_WP_N, NOR_INT1), + PINMUX_CONSTANTS(113, GPIO_PI5, I5, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(114, GPIO_PI7, I7, RES0, TRACE, NOR, DTV), + PINMUX_CONSTANTS(115, GPIO_PK0, K0, RES0, SDMMC3, NOR, SOC_THERM), + PINMUX_CONSTANTS(116, GPIO_PK1, K1, SDMMC2, TRACE, NOR, RES3), + PINMUX_CONSTANTS(117, GPIO_PJ0, J0, RES0, RES1, NOR, USB), + PINMUX_CONSTANTS(118, GPIO_PJ2, J2, RES0, RES1, NOR, SOC_THERM), + PINMUX_CONSTANTS(119, GPIO_PK3, K3, SDMMC2, TRACE, NOR, CCLA), + PINMUX_CONSTANTS(120, GPIO_PK4, K4, SDMMC2, RES1, NOR_AD22, NOR_INT1), + PINMUX_CONSTANTS(121, GPIO_PK2, K2, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(122, GPIO_PI3, I3, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(123, GPIO_PI6, I6, RES0, RES1, NOR, SDMMC2), + PINMUX_CONSTANTS(124, GPIO_PG0, G0, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(125, GPIO_PG1, G1, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(126, GPIO_PG2, G2, RES0, TRACE, NOR, RES3), + PINMUX_CONSTANTS(127, GPIO_PG3, G3, RES0, TRACE, NOR, RES3), + PINMUX_CONSTANTS(128, GPIO_PG4, G4, RES0, TMDS, NOR, SPI4), + PINMUX_CONSTANTS(129, GPIO_PG5, G5, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(130, GPIO_PG6, G6, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(131, GPIO_PG7, G7, RES0, RES1, NOR, SPI4), + PINMUX_CONSTANTS(132, GPIO_PH0, H0, PWM0, TRACE, NOR, DTV), + PINMUX_CONSTANTS(133, GPIO_PH1, H1, PWM1, TMDS, NOR, DCA), + PINMUX_CONSTANTS(134, GPIO_PH2, H2, PWM2, TDMS, NOR, CLDVFS), + PINMUX_CONSTANTS(135, GPIO_PH3, H3, PWM3, SPI4, NOR, CLDVFS), + PINMUX_CONSTANTS(136, GPIO_PH4, H4, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(137, GPIO_PH5, H5, SDMMC2, RES1, NOR, RES3), + PINMUX_CONSTANTS(138, GPIO_PH6, H6, SDMMC2, TRACE, NOR, DTV), + PINMUX_CONSTANTS(139, GPIO_PH7, H7, SDMMC2, TRACE, NOR, DTV), + PINMUX_CONSTANTS(140, GPIO_PJ7, J7, UD3, RES1, NOR_AD16, NOR_INT2), + PINMUX_CONSTANTS(141, GPIO_PB0, B0, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(142, GPIO_PB1, B1, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(143, GPIO_PK7, K7, UD3, RES1, NOR, RES3), + PINMUX_CONSTANTS(144, GPIO_PI0, I0, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(145, GPIO_PI1, I1, RES0, RES1, NOR, RES3), + PINMUX_CONSTANTS(146, GPIO_PI2, I2, SDMMC2, TRACE, NOR, RES3), + PINMUX_CONSTANTS(147, GPIO_PI4, I4, SPI4, TRACE, NOR, DCA), + PINMUX_CONSTANTS(148, GEN2_I2C_SCL, T5, I2C2, RES1, NOR, RES3), + PINMUX_CONSTANTS(149, GEN2_I2C_SDA, T6, I2C2, RES1, NOR, RES3), + PINMUX_CONSTANTS(150, SDMMC4_CLK, CC4, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(151, SDMMC4_CMD, T7, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(152, SDMMC4_DAT0, AA0, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(153, SDMMC4_DAT1, AA1, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(154, SDMMC4_DAT2, AA2, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(155, SDMMC4_DAT3, AA3, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(156, SDMMC4_DAT4, AA4, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(157, SDMMC4_DAT5, AA5, SDMMC4, SPI3, RES2, RES3), + PINMUX_CONSTANTS(158, SDMMC4_DAT6, AA6, SDMMC4, SPI3, NOR, RES3), + PINMUX_CONSTANTS(159, SDMMC4_DAT7, AA7, SDMMC4, RES1, NOR, RES3), + PINMUX_CONSTANTS(161, CAM_MCLK, CC0, VIMCLK_PRI, VIMCLK_ALT1, + VIMCLK_ALT3, SDMMC2), + PINMUX_CONSTANTS(162, GPIO_PCC1, CC1, I2S4, RES1, RES2, SDMMC2), + PINMUX_CONSTANTS(163, GPIO_PBB0, BB0, VGP6, VIMCLK2_PRI, SDMMC2, + VIMCLK2_ALT3), + PINMUX_CONSTANTS(164, CAM_I2C_SCL, BB1, VGP1, I2C3, RES2, SDMMC2), + PINMUX_CONSTANTS(165, CAM_I2C_SDA, BB2, VGP2, I2C3, RES2, SDMMC2), + PINMUX_CONSTANTS(166, GPIO_PBB3, BB3, VGP3, DCA, DCB, SDMMC2), + PINMUX_CONSTANTS(167, GPIO_PBB4, BB4, VGP4, DCA, DCB, SDMMC2), + PINMUX_CONSTANTS(168, GPIO_PBB5, BB5, VGP5, DCA, RES2, SDMMC2), + PINMUX_CONSTANTS(169, GPIO_PBB6, BB6, I2S4, RES1, DCB, SDMMC2), + PINMUX_CONSTANTS(170, GPIO_PBB7, BB7, I2S4, RES1, RES2, SDMMC2), + PINMUX_CONSTANTS(171, GPIO_PCC2, CC2, I2S4, RES1, SDMMC3, SDMMC2), + PINMUX_CONSTANTS(172, JTAG_RTCK, NONE172, RTCK, RES1, RES2, RES3), + PINMUX_CONSTANTS(173, PWR_I2C_SCL, Z6, I2CPMU, RES1, RES2, RES3), + PINMUX_CONSTANTS(174, PWR_I2C_SDA, Z7, I2CPMU, RES1, RES2, RES3), + PINMUX_CONSTANTS(175, KB_ROW0, R0, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(176, KB_ROW1, R1, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(177, KB_ROW2, R2, RES0, RES1, RES2, RES3), + PINMUX_CONSTANTS(178, KB_ROW3, R3, RES0, DCA, SYS_CLK, DCB), + PINMUX_CONSTANTS(179, KB_ROW4, R4, RES0, DCA, RES2, DCB), + PINMUX_CONSTANTS(180, KB_ROW5, R5, RES0, DCA, RES2, DCB), + PINMUX_CONSTANTS(181, KB_ROW6, R6, RES0, DCA_LSC0, DCA_LSPII, DCB), + PINMUX_CONSTANTS(182, KB_ROW7, R7, RES0, RES1, CLDVFS, UA3), + PINMUX_CONSTANTS(183, KB_ROW8, S0, RES0, RES1, CLDVFS, UA3), + PINMUX_CONSTANTS(184, KB_ROW9, S1, RES0, RES1, RES2, UA3), + PINMUX_CONSTANTS(185, KB_ROW10, S2, RES0, RES1, RES2, UA3), + PINMUX_CONSTANTS(186, KB_ROW11, S3, RES0, RES1, RES2, IR3), + PINMUX_CONSTANTS(187, KB_ROW12, S4, RES0, RES1, RES2, IR3), + PINMUX_CONSTANTS(188, KB_ROW13, S5, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(189, KB_ROW14, S6, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(190, KB_ROW15, S7, RES0, SOC_THERM, RES2, RES3), + PINMUX_CONSTANTS(191, KB_COL0, Q0, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(192, KB_COL1, Q1, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(193, KB_COL2, Q2, RES0, RES1, SPI2, RES3), + PINMUX_CONSTANTS(194, KB_COL3, Q3, RES0, DCA, PWM2, UA3), + PINMUX_CONSTANTS(195, KB_COL4, Q4, RES0, OWR, SDMMC3, UA3), + PINMUX_CONSTANTS(196, KB_COL5, Q5, RES0, RES1, SDMMC3, RES3), + PINMUX_CONSTANTS(197, KB_COL6, Q6, RES0, RES1, SPI2, UD3), + PINMUX_CONSTANTS(198, KB_COL7, Q7, RES0, RES1, SPI2, UD3), + PINMUX_CONSTANTS(199, CLK_32K_OUT, A0, BLINK, SOC_THERM, RES2, RES3), + PINMUX_CONSTANTS(201, CORE_PWR_REQ, NONE201, PWRON, RES1, RES2, RES3), + PINMUX_CONSTANTS(202, CPU_PWR_REQ, NONE202, CPU, RES1, RES2, RES3), + PINMUX_CONSTANTS(203, PWR_INT_N, NONE203, PMICINTR, RES1, RES2, RES3), + PINMUX_CONSTANTS(204, CLK_32K_IN, NONE204, CLK_32K_IN, RES1, RES2, + RES3), + PINMUX_CONSTANTS(205, OWR, NONE205, OWR, RES1, RES2, RES3), + PINMUX_CONSTANTS(206, DAP1_FS, N0, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(207, DAP1_DIN, N1, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(208, DAP1_DOUT, N2, I2S0, DAP1, NOR, SATA), + PINMUX_CONSTANTS(209, DAP1_SCLK, N3, I2S0, DAP1, NOR, RES3), + PINMUX_CONSTANTS(210, DAP_MCLK1_REQ, EE2, DAP, DAP1, SATA, RES3), + PINMUX_CONSTANTS(211, DAP_MCLK1, W4, EXTPERIPH1, DAP2, RES2, RES3), + PINMUX_CONSTANTS(212, SPDIF_IN, K6, SPDIF, RES1, RES2, I2C3), + PINMUX_CONSTANTS(213, SPDIF_OUT, K5, SPDIF, RES1, RES2, I2C3), + PINMUX_CONSTANTS(214, DAP2_FS, A2, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(215, DAP2_DIN, A4, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(216, DAP2_DOUT, A5, I2S1, DAP2, NOR, RES3), + PINMUX_CONSTANTS(217, DAP2_SCLK, A3, I2S1, SAP2, NOR, RES3), + PINMUX_CONSTANTS(218, DVFS_PWM, X0, SPI6, CLDVFS, NOR, RES3), + PINMUX_CONSTANTS(219, GPIO_X1_AUD, X1, SPI6, RES1, NOR, RES3), + PINMUX_CONSTANTS(220, GPIO_X3_AUD, X3, SPI6, SPI1, NOR, RES3), + PINMUX_CONSTANTS(221, DVFS_CLK, X2, SPI6, CLDVFS_CLK, NOR, RES3), + PINMUX_CONSTANTS(222, GPIO_X4_AUD, X4, NOR, SPI1, SPI2, DAP2), + PINMUX_CONSTANTS(223, GPIO_X5_AUD, X5, NOR, SPI1, SPI2, RES3), + PINMUX_CONSTANTS(224, GPIO_X6_AUD, X6, SPI6, SPI1, SPI2, NOR), + PINMUX_CONSTANTS(225, GPIO_X7_AUD, X7, RES0, SPI1, SPI2, RES3), + PINMUX_CONSTANTS(228, SDMMC3_CLK, A6, SDMMC3, RES1, RES2, SPI3), + PINMUX_CONSTANTS(229, SDMMC3_CMD, A7, SDMMC3, PWM3, UA3, SPI3), + PINMUX_CONSTANTS(230, SDMMC3_DAT0, B7, SDMMC3, RES1, RES2, SPI3), + PINMUX_CONSTANTS(231, SDMMC3_DAT1, B6, SDMMC3, PWM2, UA3, SPI3), + PINMUX_CONSTANTS(232, SDMMC3_DAT2, B5, SDMMC3, PWM1, DCA, SPI3), + PINMUX_CONSTANTS(233, SDMMC3_DAT3, B4, SDMMC3, PWM0, DCB, SPI3), + PINMUX_CONSTANTS(239, PEX_L0_RST_N, DD1, PE0, RES1, RES2, RES3), + PINMUX_CONSTANTS(240, PEX_L0_CLKREQ_N, DD2, PE0, RES1, RES2, RES3), + PINMUX_CONSTANTS(241, PEX_WAKE_N, DD3, PE, RES1, RES2, RES3), + PINMUX_CONSTANTS(243, PEX_L1_RST_N, DD5, PE1, RES1, RES2, RES3), + PINMUX_CONSTANTS(244, PEX_L1_CLKREQ_N, DD6, PE1, RES1, RES2, RES3), + PINMUX_CONSTANTS(248, HDMI_CEC, EE3, CEC, RES1, RES2, RES3), + PINMUX_CONSTANTS(249, SDMMC1_WP_N, V3, SDMMC1, CLK12M, SPI4, UA3), + PINMUX_CONSTANTS(250, SDMMC3_CD_N, V2, SDMMC3, OWR, RES2, RES3), + PINMUX_CONSTANTS(251, GPIO_W2_AUD, W2, SPI6, RES1, SPI2, I2C1), + PINMUX_CONSTANTS(252, GPIO_W3_AUD, W3, SPI6, SPI1, SPI2, I2C1), + PINMUX_CONSTANTS(253, USB_VBUS_EN0, N4, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(254, USB_VBUS_EN1, N5, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(255, SDMMC3_CLK_LB_IN, EE5, SDMMC3, RES1, RES2, RES3), + PINMUX_CONSTANTS(256, SDMMC3_CLK_LB_OUT, EE4, SDMMC3, RES1, RES2, RES3), + PINMUX_CONSTANTS(258, RESET_OUT_N, NONE258, RES0, RES1, RES2, RESET), + PINMUX_CONSTANTS(259, KB_ROW16, T0, RES0, RES1, RES2, UC3), + PINMUX_CONSTANTS(260, KB_ROW17, T1, RES0, RES1, RES2, UC3), + PINMUX_CONSTANTS(261, USB_VBUS_EN2, FF1, USB, RES1, RES2, RES3), + PINMUX_CONSTANTS(262, GPIO_PFF2, FF2, SATA, RES1, RES2, RES3), + PINMUX_CONSTANTS(268, DP_HPD, FF0, DP, RES1, RES2, RES3), + + // Where do these go? + /* + PINMUX_JTAG_TRST_N_JTAG_TRST_N = 0, + + PINMUX_JTAG_TDO_JTAG_TDO = 0, + + PINMUX_JTAG_TMS_JTAG_TMS = 0, + + PINMUX_JTAG_TCK_JTAG_TCK = 0, + // What do functions 1 and 2 do? + + PINMUX_JTAG_TDI_JTAG_TDI = 0, + PINMUX_JTAG_TDI_PWR_BREAK = 1, + + PINMUX_TEST_MODE_EN_TEST_MODE_EN = 0, + PINMUX_TEST_MODE_EN_VIMCLK_PRI = 1, + PINMUX_TEST_MODE_EN_VIMCLK_ALT1 = 2, + PINMUX_TEST_MODE_EN_VIMCLK_ALT3 = 3, + + PINMUX_DP_AUX_CH0_P_I2C_CLK = 0, + PINMUX_DP_AUX_CH0_P_SDMMC3_DAT3 = 1, + PINMUX_DP_AUX_CH0_P_PM3_PWM0 = 2, + PINMUX_DP_AUX_CH0_P_DCB_LPM0 = 3, + + PINMUX_DP_AUX_CH0_N_I2C6_DAT = 0, + PINMUX_DP_AUX_CH0_N_SDMMC3_DAT2 = 1, + PINMUX_DP_AUX_CH0_N_PM3_PWM1 = 2, + PINMUX_DP_AUX_CH0_N_DCA_LPM0 = 3, + */ +}; + +#endif /* __SOC_NVIDIA_TEGRA124_PINMUX_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/pmc.h b/src/soc/nvidia/tegra124/include/soc/pmc.h new file mode 100644 index 0000000000..2dfdaadb60 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/pmc.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA124_PMC_H_ +#define _TEGRA124_PMC_H_ + +#include + +enum { + POWER_PARTID_CRAIL = 0, + POWER_PARTID_TD = 1, + POWER_PARTID_VE = 2, + POWER_PARTID_VDE = 4, + POWER_PARTID_L2C = 5, + POWER_PARTID_MPE = 6, + POWER_PARTID_HEG = 7, + POWER_PARTID_CE1 = 9, + POWER_PARTID_CE2 = 10, + POWER_PARTID_CE3 = 11, + POWER_PARTID_CELP = 12, + POWER_PARTID_CE0 = 14, + POWER_PARTID_C0NC = 15, + POWER_PARTID_C1NC = 16, + POWER_PARTID_DIS = 18, + POWER_PARTID_DISB = 19, + POWER_PARTID_XUSBA = 20, + POWER_PARTID_XUSBB = 21, + POWER_PARTID_XUSBC = 22 +}; + +struct tegra_pmc_regs { + u32 cntrl; + u32 sec_disable; + u32 pmc_swrst; + u32 wake_mask; + u32 wake_lvl; + u32 wake_status; + u32 sw_wake_status; + u32 dpd_pads_oride; + u32 dpd_sample; + u32 dpd_enable; + u32 pwrgate_timer_off; + u32 clamp_status; + u32 pwrgate_toggle; + u32 remove_clamping_cmd; + u32 pwrgate_status; + u32 pwrgood_timer; + u32 blink_timer; + u32 no_iopower; + u32 pwr_det; + u32 pwr_det_latch; + u32 scratch0; + u32 scratch1; + u32 scratch2; + u32 scratch3; + u32 scratch4; + u32 scratch5; + u32 scratch6; + u32 scratch7; + u32 scratch8; + u32 scratch9; + u32 scratch10; + u32 scratch11; + u32 scratch12; + u32 scratch13; + u32 scratch14; + u32 scratch15; + u32 scratch16; + u32 scratch17; + u32 scratch18; + u32 scratch19; + u32 odmdata; + u32 scratch21; + u32 scratch22; + u32 scratch23; + u32 secure_scratch0; + u32 secure_scratch1; + u32 secure_scratch2; + u32 secure_scratch3; + u32 secure_scratch4; + u32 secure_scratch5; + u32 cpupwrgood_timer; + u32 cpupwroff_timer; + u32 pg_mask; + u32 pg_mask_1; + u32 auto_wake_lvl; + u32 auto_wake_lvl_mask; + u32 wake_delay; + u32 pwr_det_val; + u32 ddr_pwr; + u32 usb_debounce_del; + u32 usb_a0; + u32 crypto_op; + u32 pllp_wb0_override; + u32 scratch24; + u32 scratch25; + u32 scratch26; + u32 scratch27; + u32 scratch28; + u32 scratch29; + u32 scratch30; + u32 scratch31; + u32 scratch32; + u32 scratch33; + u32 scratch34; + u32 scratch35; + u32 scratch36; + u32 scratch37; + u32 scratch38; + u32 scratch39; + u32 scratch40; + u32 scratch41; + u32 scratch42; + u32 bondout_mirror[3]; + u32 sys_33v_en; + u32 bondout_mirror_access; + u32 gate; + u32 wake2_mask; + u32 wake2_lvl; + u32 wake2_status; + u32 sw_wake2_status; + u32 auto_wake2_lvl_mask; + u32 pg_mask_2; + u32 pg_mask_ce1; + u32 pg_mask_ce2; + u32 pg_mask_ce3; + u32 pwrgate_timer_ce[7]; + u32 pcx_edpd_cntrl; + u32 osc_edpd_over; + u32 clk_out_cntrl; + u32 sata_pwrgt; + u32 sensor_ctrl; + u32 rst_status; + u32 io_dpd_req; + u32 io_dpd_status; + u32 io_dpd2_req; + u32 io_dpd2_status; + u32 sel_dpd_tim; + u32 vddp_sel; + u32 ddr_cfg; + u32 e_no_vttgen; + u8 _rsv0[4]; + u32 pllm_wb0_override_freq; + u32 test_pwrgate; + u32 pwrgate_timer_mult; + u32 dis_sel_dpd; + u32 utmip_uhsic_triggers; + u32 utmip_uhsic_saved_state; + u32 utmip_pad_cfg; + u32 utmip_term_pad_cfg; + u32 utmip_uhsic_sleep_cfg; + u32 utmip_uhsic_sleepwalk_cfg; + u32 utmip_sleepwalk_p[3]; + u32 uhsic_sleepwalk_p0; + u32 utmip_uhsic_status; + u32 utmip_uhsic_fake; + u32 bondout_mirror3[5 - 3]; + u32 secure_scratch6; + u32 secure_scratch7; + u32 scratch43; + u32 scratch44; + u32 scratch45; + u32 scratch46; + u32 scratch47; + u32 scratch48; + u32 scratch49; + u32 scratch50; + u32 scratch51; + u32 scratch52; + u32 scratch53; + u32 scratch54; + u32 scratch55; + u32 scratch0_eco; + u32 por_dpd_ctrl; + u32 scratch2_eco; + u32 utmip_uhsic_line_wakeup; + u32 utmip_bias_master_cntrl; + u32 utmip_master_config; + u32 td_pwrgate_inter_part_timer; + u32 utmip_uhsic2_triggers; + u32 utmip_uhsic2_saved_state; + u32 utmip_uhsic2_sleep_cfg; + u32 utmip_uhsic2_sleepwalk_cfg; + u32 uhsic2_sleepwalk_p1; + u32 utmip_uhsic2_status; + u32 utmip_uhsic2_fake; + u32 utmip_uhsic2_line_wakeup; + u32 utmip_master2_config; + u32 utmip_uhsic_rpd_cfg; + u32 pg_mask_ce0; + u32 pg_mask3[5 - 3]; + u32 pllm_wb0_override2; + u32 tsc_mult; + u32 cpu_vsense_override; + u32 glb_amap_cfg; + u32 sticky_bits; + u32 sec_disable2; + u32 weak_bias; + u32 reg_short; + u32 pg_mask_andor; + u8 _rsv1[0x2c]; + u32 secure_scratch8; + u32 secure_scratch9; + u32 secure_scratch10; + u32 secure_scratch11; + u32 secure_scratch12; + u32 secure_scratch13; + u32 secure_scratch14; + u32 secure_scratch15; + u32 secure_scratch16; + u32 secure_scratch17; + u32 secure_scratch18; + u32 secure_scratch19; + u32 secure_scratch20; + u32 secure_scratch21; + u32 secure_scratch22; + u32 secure_scratch23; + u32 secure_scratch24; + u32 secure_scratch25; + u32 secure_scratch26; + u32 secure_scratch27; + u32 secure_scratch28; + u32 secure_scratch29; + u32 secure_scratch30; + u32 secure_scratch31; + u32 secure_scratch32; + u32 secure_scratch33; + u32 secure_scratch34; + u32 secure_scratch35; + u8 _rsv2[0xd0]; + u32 cntrl2; + u8 _rsv3[0x18]; + u32 io_dpd3_req; + u32 io_dqd3_status; + u32 strapping_opt_a; + u8 _rsv4[0x198]; + u32 scratch56; + u32 scratch57; + u32 scratch58; + u32 scratch59; + u32 scratch60; + u32 scratch61; + u32 scratch62; + u32 scratch63; + u32 scratch64; + u32 scratch65; + u32 scratch66; + u32 scratch67; + u32 scratch68; + u32 scratch69; + u32 scratch70; + u32 scratch71; + u32 scratch72; + u32 scratch73; + u32 scratch74; + u32 scratch75; + u32 scratch76; + u32 scratch77; + u32 scratch78; + u32 scratch79; + u32 scratch80; + u32 scratch81; + u32 scratch82; + u32 scratch83; + u32 scratch84; + u32 scratch85; + u32 scratch86; + u32 scratch87; + u32 scratch88; + u32 scratch89; + u32 scratch90; + u32 scratch91; + u32 scratch92; + u32 scratch93; + u32 scratch94; + u32 scratch95; + u32 scratch96; + u32 scratch97; + u32 scratch98; + u32 scratch99; + u32 scratch100; + u32 scratch101; + u32 scratch102; + u32 scratch103; + u32 scratch104; + u32 scratch105; + u32 scratch106; + u32 scratch107; + u32 scratch108; + u32 scratch109; + u32 scratch110; + u32 scratch111; + u32 scratch112; + u32 scratch113; + u32 scratch114; + u32 scratch115; + u32 scratch116; + u32 scratch117; + u32 scratch118; + u32 scratch119; +}; + +check_member(tegra_pmc_regs, scratch119, 0x6fc); + +enum { + PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f, + PMC_PWRGATE_TOGGLE_PARTID_SHIFT = 0, + PMC_PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +enum { + PMC_CNTRL_KBC_CLK_DIS = 0x1 << 0, + PMC_CNTRL_RTC_CLK_DIS = 0x1 << 1, + PMC_CNTRL_RTC_RST = 0x1 << 2, + PMC_CNTRL_KBC_RST = 0x1 << 3, + PMC_CNTRL_MAIN_RST = 0x1 << 4, + PMC_CNTRL_LATCHWAKE_EN = 0x1 << 5, + PMC_CNTRL_GLITCHDET_DIS = 0x1 << 6, + PMC_CNTRL_BLINK_EN = 0x1 << 7, + PMC_CNTRL_PWRREQ_POLARITY = 0x1 << 8, + PMC_CNTRL_PWRREQ_OE = 0x1 << 9, + PMC_CNTRL_SYSCLK_POLARITY = 0x1 << 10, + PMC_CNTRL_SYSCLK_OE = 0x1 << 11, + PMC_CNTRL_PWRGATE_DIS = 0x1 << 12, + PMC_CNTRL_AOINIT = 0x1 << 13, + PMC_CNTRL_SIDE_EFFECT_LP0 = 0x1 << 14, + PMC_CNTRL_CPUPWRREQ_POLARITY = 0x1 << 15, + PMC_CNTRL_CPUPWRREQ_OE = 0x1 << 16, + PMC_CNTRL_INTR_POLARITY = 0x1 << 17, + PMC_CNTRL_FUSE_OVERRIDE = 0x1 << 18, + PMC_CNTRL_CPUPWRGOOD_EN = 0x1 << 19, + PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT = 20, + PMC_CNTRL_CPUPWRGOOD_SEL_MASK = + 0x3 << PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT +}; + +enum { + PMC_DDR_PWR_EMMC_MASK = 1 << 1, + PMC_DDR_PWR_VAL_MASK = 1 << 0, +}; + +enum { + PMC_DDR_CFG_PKG_MASK = 1 << 0, + PMC_DDR_CFG_IF_MASK = 1 << 1, + PMC_DDR_CFG_XM0_RESET_TRI_MASK = 1 << 12, + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK = 1 << 13, +}; + +enum { + PMC_NO_IOPOWER_MEM_MASK = 1 << 7, + PMC_NO_IOPOWER_MEM_COMP_MASK = 1 << 16, +}; + +enum { + PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK = 1 << 0, + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK = 1 << 1, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK = 1 << 31, +}; + +enum { + PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12 +}; + +enum { + PMC_OSC_EDPD_OVER_XOFS_SHIFT = 1, + PMC_OSC_EDPD_OVER_XOFS_MASK = + 0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT +}; + +enum { + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT = 4, + PMC_STRAPPING_OPT_A_RAM_CODE_MASK = + 0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT, +}; + +#endif /* _TEGRA124_PMC_H_ */ diff --git a/src/soc/nvidia/tegra124/include/soc/power.h b/src/soc/nvidia/tegra124/include/soc/power.h new file mode 100644 index 0000000000..f536865cea --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/power.h @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_POWER_H__ +#define __SOC_NVIDIA_TEGRA124_POWER_H__ + +// This function does not enable the external power to the rail, it enables +// the rail itself internal to the SOC. +void power_enable_and_ungate_cpu(void); + + +// power_reset_status returns one of the following possible sources for the +// most recent reset. +enum { + POWER_RESET_POR = 0, + POWER_RESET_WATCHDOG = 1, + POWER_RESET_SENSOR = 2, + POWER_RESET_SW_MAIN = 3, + POWER_RESET_LP0 = 4 +}; +int power_reset_status(void); + +void ram_repair(void); + +#endif /* __SOC_NVIDIA_TEGRA124_POWER_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/sdram.h b/src/soc/nvidia/tegra124/include/soc/sdram.h new file mode 100644 index 0000000000..1571521995 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/sdram.h @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_SDRAM_H__ +#define __SOC_NVIDIA_TEGRA124_SDRAM_H__ + +#include + +uint32_t sdram_get_ram_code(void); +void sdram_init(const struct sdram_params *param); +int sdram_size_mb(void); +uintptr_t sdram_max_addressable_mb(void); + +/* Save params to PMC scratch registers for use by BootROM on LP0 resume. */ +void sdram_lp0_save_params(const struct sdram_params *sdram); + +#endif /* __SOC_NVIDIA_TEGRA124_SDRAM_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/sdram_param.h b/src/soc/nvidia/tegra124/include/soc/sdram_param.h new file mode 100644 index 0000000000..c845611da0 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/sdram_param.h @@ -0,0 +1,818 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. The field names are in camel case to ease + * directly converting BCT config files (*.cfg) into C structure. + */ + +#ifndef __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ +#define __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ + +#include +#include + +enum { + /* Specifies the memory type to be undefined */ + NvBootMemoryType_None = 0, + + /* Specifies the memory type to be DDR SDRAM */ + NvBootMemoryType_Ddr = 0, + + /* Specifies the memory type to be LPDDR SDRAM */ + NvBootMemoryType_LpDdr = 0, + + /* Specifies the memory type to be DDR2 SDRAM */ + NvBootMemoryType_Ddr2 = 0, + + /* Specifies the memory type to be LPDDR2 SDRAM */ + NvBootMemoryType_LpDdr2, + + /* Specifies the memory type to be DDR3 SDRAM */ + NvBootMemoryType_Ddr3, + + NvBootMemoryType_Num, + + /* Specifies an entry in the ram_code table that's not in use */ + NvBootMemoryType_Unused = 0X7FFFFFF, +}; + +enum { + BOOT_ROM_PATCH_CONTROL_ENABLE_MASK = 0x1 << 31, + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT = 0, + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK = 0x7FFFFFFF << 0, + BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS = 0x70000000, + + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK = 1 << 0, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params { + + /* Specifies the type of memory device */ + uint32_t MemoryType; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t PllMInputDivider; + /* Specifies the N value for PllM */ + uint32_t PllMFeedbackDivider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t PllMStableTime; + /* Specifies misc. control bits */ + uint32_t PllMSetupControl; + /* Enables the Div by 2 */ + uint32_t PllMSelectDiv2; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh45; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh90; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh135; + /* Specifies value for Charge Pump Gain Control */ + uint32_t PllMKCP; + /* Specifies VCO gain */ + uint32_t PllMKVCO; + /* Spare BCT param */ + uint32_t EmcBctSpare0; + /* Spare BCT param */ + uint32_t EmcBctSpare1; + /* Spare BCT param */ + uint32_t EmcBctSpare2; + /* Spare BCT param */ + uint32_t EmcBctSpare3; + /* Spare BCT param */ + uint32_t EmcBctSpare4; + /* Spare BCT param */ + uint32_t EmcBctSpare5; + /* Spare BCT param */ + uint32_t EmcBctSpare6; + /* Spare BCT param */ + uint32_t EmcBctSpare7; + /* Spare BCT param */ + uint32_t EmcBctSpare8; + /* Spare BCT param */ + uint32_t EmcBctSpare9; + /* Spare BCT param */ + uint32_t EmcBctSpare10; + /* Spare BCT param */ + uint32_t EmcBctSpare11; + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t EmcClockSource; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t EmcAutoCalInterval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t EmcAutoCalConfig; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t EmcAutoCalConfig2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t EmcAutoCalConfig3; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t EmcAutoCalWait; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t EmcAdrCfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t EmcPinProgramWait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t EmcPinExtraWait; + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t EmcTimingControlWait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t EmcRc; + /* Specifies the value for EMC_RFC */ + uint32_t EmcRfc; + /* Specifies the value for EMC_RFC_SLR */ + uint32_t EmcRfcSlr; + /* Specifies the value for EMC_RAS */ + uint32_t EmcRas; + /* Specifies the value for EMC_RP */ + uint32_t EmcRp; + /* Specifies the value for EMC_R2R */ + uint32_t EmcR2r; + /* Specifies the value for EMC_W2W */ + uint32_t EmcW2w; + /* Specifies the value for EMC_R2W */ + uint32_t EmcR2w; + /* Specifies the value for EMC_W2R */ + uint32_t EmcW2r; + /* Specifies the value for EMC_R2P */ + uint32_t EmcR2p; + /* Specifies the value for EMC_W2P */ + uint32_t EmcW2p; + /* Specifies the value for EMC_RD_RCD */ + uint32_t EmcRdRcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t EmcWrRcd; + /* Specifies the value for EMC_RRD */ + uint32_t EmcRrd; + /* Specifies the value for EMC_REXT */ + uint32_t EmcRext; + /* Specifies the value for EMC_WEXT */ + uint32_t EmcWext; + /* Specifies the value for EMC_WDV */ + uint32_t EmcWdv; + /* Specifies the value for EMC_WDV_MASK */ + uint32_t EmcWdvMask; + /* Specifies the value for EMC_QUSE */ + uint32_t EmcQUse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t EmcQuseWidth; + /* Specifies the value for EMC_IBDLY */ + uint32_t EmcIbdly; + /* Specifies the value for EMC_EINPUT */ + uint32_t EmcEInput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t EmcEInputDuration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t EmcPutermExtra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t EmcPutermWidth; + /* Specifies the value for EMC_PUTERM_ADJ */ + uint32_t EmcPutermAdj; + /* Specifies the value for EMC_CDB_CNTL_1 */ + uint32_t EmcCdbCntl1; + /* Specifies the value for EMC_CDB_CNTL_2 */ + uint32_t EmcCdbCntl2; + /* Specifies the value for EMC_CDB_CNTL_3 */ + uint32_t EmcCdbCntl3; + /* Specifies the value for EMC_QRST */ + uint32_t EmcQRst; + /* Specifies the value for EMC_QSAFE */ + uint32_t EmcQSafe; + /* Specifies the value for EMC_RDV */ + uint32_t EmcRdv; + /* Specifies the value for EMC_RDV_MASK */ + uint32_t EmcRdvMask; + /* Specifies the value for EMC_QPOP */ + uint32_t EmcQpop; + /* Specifies the value for EMC_CTT */ + uint32_t EmcCtt; + /* Specifies the value for EMC_CTT_DURATION */ + uint32_t EmcCttDuration; + /* Specifies the value for EMC_REFRESH */ + uint32_t EmcRefresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t EmcBurstRefreshNum; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t EmcPreRefreshReqCnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t EmcPdEx2Wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t EmcPdEx2Rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t EmcPChg2Pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t EmcAct2Pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t EmcAr2Pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t EmcRw2Pden; + /* Specifies the value for EMC_TXSR */ + uint32_t EmcTxsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t EmcTxsrDll; + /* Specifies the value for EMC_TCKE */ + uint32_t EmcTcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t EmcTckesr; + /* Specifies the value for EMC_TPD */ + uint32_t EmcTpd; + /* Specifies the value for EMC_TFAW */ + uint32_t EmcTfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t EmcTrpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t EmcTClkStable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t EmcTClkStop; + /* Specifies the value for EMC_TREFBW */ + uint32_t EmcTRefBw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t EmcFbioCfg5; + /* Specifies the value for EMC_FBIO_CFG6 */ + uint32_t EmcFbioCfg6; + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t EmcFbioSpare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t EmcCfgRsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t EmcMrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t EmcEmrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t EmcEmrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t EmcEmrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t EmcMrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t EmcMrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t EmcMrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw4; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t EmcMrwExtra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t EmcWarmBootMrwExtra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t EmcWarmBootExtraModeRegWriteEnable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t EmcExtraModeRegWriteEnable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t EmcMrwResetCommand; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t EmcMrwResetNInitWait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t EmcMrsWaitCnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t EmcMrsWaitCnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t EmcCfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t EmcCfg2; + /* Specifies the pipe bypass controls */ + uint32_t EmcCfgPipe; + /* Specifies the value for EMC_DBG */ + uint32_t EmcDbg; + /* Specifies the value for EMC_CMDQ */ + uint32_t EmcCmdQ; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t EmcMc2EmcQ; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t EmcDynSelfRefControl; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t AhbArbitrationXbarCtrlMemInitDone; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t EmcCfgDigDll; + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t EmcCfgDigDllPeriod; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t EmcDevSelect; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t EmcSelDpdCtrl; + + /* Pads trimmer delays */ + + /* Specifies the value for EMC_DLL_XFORM_DQS0 */ + uint32_t EmcDllXformDqs0; + /* Specifies the value for EMC_DLL_XFORM_DQS1 */ + uint32_t EmcDllXformDqs1; + /* Specifies the value for EMC_DLL_XFORM_DQS2 */ + uint32_t EmcDllXformDqs2; + /* Specifies the value for EMC_DLL_XFORM_DQS3 */ + uint32_t EmcDllXformDqs3; + /* Specifies the value for EMC_DLL_XFORM_DQS4 */ + uint32_t EmcDllXformDqs4; + /* Specifies the value for EMC_DLL_XFORM_DQS5 */ + uint32_t EmcDllXformDqs5; + /* Specifies the value for EMC_DLL_XFORM_DQS6 */ + uint32_t EmcDllXformDqs6; + /* Specifies the value for EMC_DLL_XFORM_DQS7 */ + uint32_t EmcDllXformDqs7; + /* Specifies the value for EMC_DLL_XFORM_DQS8 */ + uint32_t EmcDllXformDqs8; + /* Specifies the value for EMC_DLL_XFORM_DQS9 */ + uint32_t EmcDllXformDqs9; + /* Specifies the value for EMC_DLL_XFORM_DQS10 */ + uint32_t EmcDllXformDqs10; + /* Specifies the value for EMC_DLL_XFORM_DQS11 */ + uint32_t EmcDllXformDqs11; + /* Specifies the value for EMC_DLL_XFORM_DQS12 */ + uint32_t EmcDllXformDqs12; + /* Specifies the value for EMC_DLL_XFORM_DQS13 */ + uint32_t EmcDllXformDqs13; + /* Specifies the value for EMC_DLL_XFORM_DQS14 */ + uint32_t EmcDllXformDqs14; + /* Specifies the value for EMC_DLL_XFORM_DQS15 */ + uint32_t EmcDllXformDqs15; + /* Specifies the value for EMC_DLL_XFORM_QUSE0 */ + uint32_t EmcDllXformQUse0; + /* Specifies the value for EMC_DLL_XFORM_QUSE1 */ + uint32_t EmcDllXformQUse1; + /* Specifies the value for EMC_DLL_XFORM_QUSE2 */ + uint32_t EmcDllXformQUse2; + /* Specifies the value for EMC_DLL_XFORM_QUSE3 */ + uint32_t EmcDllXformQUse3; + /* Specifies the value for EMC_DLL_XFORM_QUSE4 */ + uint32_t EmcDllXformQUse4; + /* Specifies the value for EMC_DLL_XFORM_QUSE5 */ + uint32_t EmcDllXformQUse5; + /* Specifies the value for EMC_DLL_XFORM_QUSE6 */ + uint32_t EmcDllXformQUse6; + /* Specifies the value for EMC_DLL_XFORM_QUSE7 */ + uint32_t EmcDllXformQUse7; + /* Specifies the value for EMC_DLL_XFORM_ADDR0 */ + uint32_t EmcDllXformAddr0; + /* Specifies the value for EMC_DLL_XFORM_ADDR1 */ + uint32_t EmcDllXformAddr1; + /* Specifies the value for EMC_DLL_XFORM_ADDR2 */ + uint32_t EmcDllXformAddr2; + /* Specifies the value for EMC_DLL_XFORM_ADDR3 */ + uint32_t EmcDllXformAddr3; + /* Specifies the value for EMC_DLL_XFORM_ADDR4 */ + uint32_t EmcDllXformAddr4; + /* Specifies the value for EMC_DLL_XFORM_ADDR5 */ + uint32_t EmcDllXformAddr5; + /* Specifies the value for EMC_DLL_XFORM_QUSE8 */ + uint32_t EmcDllXformQUse8; + /* Specifies the value for EMC_DLL_XFORM_QUSE9 */ + uint32_t EmcDllXformQUse9; + /* Specifies the value for EMC_DLL_XFORM_QUSE10 */ + uint32_t EmcDllXformQUse10; + /* Specifies the value for EMC_DLL_XFORM_QUSE11 */ + uint32_t EmcDllXformQUse11; + /* Specifies the value for EMC_DLL_XFORM_QUSE12 */ + uint32_t EmcDllXformQUse12; + /* Specifies the value for EMC_DLL_XFORM_QUSE13 */ + uint32_t EmcDllXformQUse13; + /* Specifies the value for EMC_DLL_XFORM_QUSE14 */ + uint32_t EmcDllXformQUse14; + /* Specifies the value for EMC_DLL_XFORM_QUSE15 */ + uint32_t EmcDllXformQUse15; + /* Specifies the value for EMC_DLI_TRIM_TXDQS0 */ + uint32_t EmcDliTrimTxDqs0; + /* Specifies the value for EMC_DLI_TRIM_TXDQS1 */ + uint32_t EmcDliTrimTxDqs1; + /* Specifies the value for EMC_DLI_TRIM_TXDQS2 */ + uint32_t EmcDliTrimTxDqs2; + /* Specifies the value for EMC_DLI_TRIM_TXDQS3 */ + uint32_t EmcDliTrimTxDqs3; + /* Specifies the value for EMC_DLI_TRIM_TXDQS4 */ + uint32_t EmcDliTrimTxDqs4; + /* Specifies the value for EMC_DLI_TRIM_TXDQS5 */ + uint32_t EmcDliTrimTxDqs5; + /* Specifies the value for EMC_DLI_TRIM_TXDQS6 */ + uint32_t EmcDliTrimTxDqs6; + /* Specifies the value for EMC_DLI_TRIM_TXDQS7 */ + uint32_t EmcDliTrimTxDqs7; + /* Specifies the value for EMC_DLI_TRIM_TXDQS8 */ + uint32_t EmcDliTrimTxDqs8; + /* Specifies the value for EMC_DLI_TRIM_TXDQS9 */ + uint32_t EmcDliTrimTxDqs9; + /* Specifies the value for EMC_DLI_TRIM_TXDQS10 */ + uint32_t EmcDliTrimTxDqs10; + /* Specifies the value for EMC_DLI_TRIM_TXDQS11 */ + uint32_t EmcDliTrimTxDqs11; + /* Specifies the value for EMC_DLI_TRIM_TXDQS12 */ + uint32_t EmcDliTrimTxDqs12; + /* Specifies the value for EMC_DLI_TRIM_TXDQS13 */ + uint32_t EmcDliTrimTxDqs13; + /* Specifies the value for EMC_DLI_TRIM_TXDQS14 */ + uint32_t EmcDliTrimTxDqs14; + /* Specifies the value for EMC_DLI_TRIM_TXDQS15 */ + uint32_t EmcDliTrimTxDqs15; + /* Specifies the value for EMC_DLL_XFORM_DQ0 */ + uint32_t EmcDllXformDq0; + /* Specifies the value for EMC_DLL_XFORM_DQ1 */ + uint32_t EmcDllXformDq1; + /* Specifies the value for EMC_DLL_XFORM_DQ2 */ + uint32_t EmcDllXformDq2; + /* Specifies the value for EMC_DLL_XFORM_DQ3 */ + uint32_t EmcDllXformDq3; + /* Specifies the value for EMC_DLL_XFORM_DQ4 */ + uint32_t EmcDllXformDq4; + /* Specifies the value for EMC_DLL_XFORM_DQ5 */ + uint32_t EmcDllXformDq5; + /* Specifies the value for EMC_DLL_XFORM_DQ6 */ + uint32_t EmcDllXformDq6; + /* Specifies the value for EMC_DLL_XFORM_DQ7 */ + uint32_t EmcDllXformDq7; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t WarmBootWait; + + /* Specifies the value for EMC_CTT_TERM_CTRL */ + uint32_t EmcCttTermCtrl; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtWrite; + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtRead; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t EmcZcalInterval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t EmcZcalWaitCnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t EmcZcalMrwCmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t EmcMrsResetDll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t EmcZcalInitDev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t EmcZcalInitDev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t EmcZcalInitWait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t EmcZcalWarmColdBootEnables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t EmcMrwLpddr2ZcalWarmBoot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t EmcZqCalDdr3WarmBoot; + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t EmcZcalWarmBootWait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t EmcMrsWarmBootEnable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t EmcMrsResetDllWait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t EmcMrsExtra; + /* Specifies the extra MRS command at warm boot */ + uint32_t EmcWarmBootMrsExtra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t EmcEmrsDdr2DllEnable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t EmcMrsDdr2DllReset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t EmcEmrsDdr2OcdCalib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t EmcDdr2Wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t EmcClkenOverride; + /* Specifies the value for MC_DIS_EXTRA_SNAP_LEVELS */ + uint32_t McDisExtraSnapLevels; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t EmcExtraRefreshNum; + /* Specifies the master override for all EMC clocks */ + uint32_t EmcClkenOverrideAllWarmBoot; + /* Specifies the master override for all MC clocks */ + uint32_t McClkenOverrideAllWarmBoot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t EmcCfgDigDllPeriodWarmBoot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t PmcVddpSel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t PmcVddpSelWait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t PmcDdrPwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t PmcDdrCfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3Req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3ReqWait; + /* Specifies the value for PMC_REG_SHORT */ + uint32_t PmcRegShort; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t PmcNoIoPower; + /* Specifies the wait time after programming PMC_POR_DPD_CTRL */ + uint32_t PmcPorDpdCtrlWait; + /* Specifies the value for EMC_XM2CMDPADCTRL */ + uint32_t EmcXm2CmdPadCtrl; + /* Specifies the value for EMC_XM2CMDPADCTRL2 */ + uint32_t EmcXm2CmdPadCtrl2; + /* Specifies the value for EMC_XM2CMDPADCTRL3 */ + uint32_t EmcXm2CmdPadCtrl3; + /* Specifies the value for EMC_XM2CMDPADCTRL4 */ + uint32_t EmcXm2CmdPadCtrl4; + /* Specifies the value for EMC_XM2CMDPADCTRL5 */ + uint32_t EmcXm2CmdPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL */ + uint32_t EmcXm2DqsPadCtrl; + /* Specifies the value for EMC_XM2DQSPADCTRL2 */ + uint32_t EmcXm2DqsPadCtrl2; + /* Specifies the value for EMC_XM2DQSPADCTRL3 */ + uint32_t EmcXm2DqsPadCtrl3; + /* Specifies the value for EMC_XM2DQSPADCTRL4 */ + uint32_t EmcXm2DqsPadCtrl4; + /* Specifies the value for EMC_XM2DQSPADCTRL5 */ + uint32_t EmcXm2DqsPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL6 */ + uint32_t EmcXm2DqsPadCtrl6; + /* Specifies the value for EMC_XM2DQPADCTRL */ + uint32_t EmcXm2DqPadCtrl; + /* Specifies the value for EMC_XM2DQPADCTRL2 */ + uint32_t EmcXm2DqPadCtrl2; + /* Specifies the value for EMC_XM2DQPADCTRL3 */ + uint32_t EmcXm2DqPadCtrl3; + /* Specifies the value for EMC_XM2CLKPADCTRL */ + uint32_t EmcXm2ClkPadCtrl; + /* Specifies the value for EMC_XM2CLKPADCTRL2 */ + uint32_t EmcXm2ClkPadCtrl2; + /* Specifies the value for EMC_XM2COMPPADCTRL */ + uint32_t EmcXm2CompPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL */ + uint32_t EmcXm2VttGenPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL2 */ + uint32_t EmcXm2VttGenPadCtrl2; + /* Specifies the value for EMC_XM2VTTGENPADCTRL3 */ + uint32_t EmcXm2VttGenPadCtrl3; + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t EmcAcpdControl; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */ + uint32_t EmcSwizzleRank0ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t EmcSwizzleRank0Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t EmcSwizzleRank0Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t EmcSwizzleRank0Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t EmcSwizzleRank0Byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */ + uint32_t EmcSwizzleRank1ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t EmcSwizzleRank1Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t EmcSwizzleRank1Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t EmcSwizzleRank1Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t EmcSwizzleRank1Byte3; + + /* Specifies the value for EMC_DSR_VTTGEN_DRV */ + uint32_t EmcDsrVttgenDrv; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t EmcTxdsrvttgen; + /* Specifies the value for EMC_BGBIAS_CTL */ + uint32_t EmcBgbiasCtl0; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t McEmemAdrCfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t McEmemAdrCfgDev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t McEmemAdrCfgDev1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + uint32_t McEmemAdrCfgBankMask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t McEmemAdrCfgBankMask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t McEmemAdrCfgBankMask2; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG3 */ + uint32_t McEmemAdrCfgBankSwizzle3; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t McEmemCfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t McEmemArbCfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t McEmemArbOutstandingReq; + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t McEmemArbTimingRcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t McEmemArbTimingRp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t McEmemArbTimingRc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t McEmemArbTimingRas; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t McEmemArbTimingFaw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t McEmemArbTimingRrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t McEmemArbTimingRap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t McEmemArbTimingWap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t McEmemArbTimingR2R; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t McEmemArbTimingW2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t McEmemArbTimingR2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t McEmemArbTimingW2R; + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t McEmemArbDaTurns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t McEmemArbDaCovers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t McEmemArbMisc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t McEmemArbMisc1; + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t McEmemArbRing1Throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t McEmemArbOverride; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t McEmemArbOverride1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t McEmemArbRsv; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t McClkenOverride; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t McStatControl; + /* Specifies the value for MC_DISPLAY_SNAP_RING */ + uint32_t McDisplaySnapRing; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t McVideoProtectBom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t McVideoProtectBomAdrHi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t McVideoProtectSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t McVideoProtectVprOverride; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t McVideoProtectVprOverride1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t McVideoProtectGpuOverride0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t McVideoProtectGpuOverride1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t McSecCarveoutBom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t McSecCarveoutAdrHi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t McSecCarveoutSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + uint32_t McVideoProtectWriteAccess; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + uint32_t McSecCarveoutProtectWriteAccess; + + /* Specifies enable for CA training */ + uint32_t EmcCaTrainingEnable; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL1 */ + uint32_t EmcCaTrainingTimingCntl1; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL2 */ + uint32_t EmcCaTrainingTimingCntl2; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t SwizzleRankByteEncode; + /* Specifies enable and offset for patched boot rom write */ + uint32_t BootRomPatchControl; + /* Specifies data for patched boot rom write */ + uint32_t BootRomPatchData; + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t McMtsCarveoutBom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t McMtsCarveoutAdrHi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t McMtsCarveoutSizeMb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t McMtsCarveoutRegCtrl; + + /* End of generated code by warmboot_code_gen */ +}; + +check_member(sdram_params, McMtsCarveoutRegCtrl, 0x4d0); + +#endif /* __SOC_NVIDIA_TEGRA124_SDRAM_PARAM_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/sor.h b/src/soc/nvidia/tegra124/include/soc/sor.h new file mode 100644 index 0000000000..569cdb970b --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/sor.h @@ -0,0 +1,928 @@ +/* + * drivers/video/tegra/dc/sor_regs.h + * + * Copyright (c) 2011-2013, NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __TEGRA124_SOR_H__ +#define __TEGRA124_SOR_H__ + +#define NV_SOR_SUPER_STATE0 (0x1) +#define NV_SOR_SUPER_STATE0_UPDATE_SHIFT (0) +#define NV_SOR_SUPER_STATE0_UPDATE_DEFAULT_MASK (0x1) +#define NV_SOR_SUPER_STATE1 (0x2) +#define NV_SOR_SUPER_STATE1_ATTACHED_SHIFT (3) +#define NV_SOR_SUPER_STATE1_ATTACHED_NO (0 << 3) +#define NV_SOR_SUPER_STATE1_ATTACHED_YES (1 << 3) +#define NV_SOR_SUPER_STATE1_ASY_ORMODE_SHIFT (2) +#define NV_SOR_SUPER_STATE1_ASY_ORMODE_SAFE (0 << 2) +#define NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL (1 << 2) +#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SHIFT (0) +#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_DEFAULT_MASK (0x3) +#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SLEEP (0) +#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_SNOOZE (1) +#define NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE (2) +#define NV_SOR_STATE0 (0x3) +#define NV_SOR_STATE0_UPDATE_SHIFT (0) +#define NV_SOR_STATE0_UPDATE_DEFAULT_MASK (0x1) +#define NV_SOR_STATE1 (0x4) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_SHIFT (17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_DEFAULT_MASK (0xf << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_16_422 (1 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444 (2 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_20_422 (3 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_422 (4 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 (5 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_30_444 (6 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_32_422 (7 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_36_444 (8 << 17) +#define NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_48_444 (9 << 17) +#define NV_SOR_STATE1_ASY_REPLICATE_SHIFT (15) +#define NV_SOR_STATE1_ASY_REPLICATE_DEFAULT_MASK (0x3 << 15) +#define NV_SOR_STATE1_ASY_REPLICATE_OFF (0 << 15) +#define NV_SOR_STATE1_ASY_REPLICATE_X2 (1 << 15) +#define NV_SOR_STATE1_ASY_REPLICATE_X4 (2 << 15) +#define NV_SOR_STATE1_ASY_DEPOL_SHIFT (14) +#define NV_SOR_STATE1_ASY_DEPOL_DEFAULT_MASK (0x1 << 14) +#define NV_SOR_STATE1_ASY_DEPOL_POSITIVE_TRUE (0 << 14) +#define NV_SOR_STATE1_ASY_DEPOL_NEGATIVE_TRUE (1 << 14) +#define NV_SOR_STATE1_ASY_VSYNCPOL_SHIFT (13) +#define NV_SOR_STATE1_ASY_VSYNCPOL_DEFAULT_MASK (0x1 << 13) +#define NV_SOR_STATE1_ASY_VSYNCPOL_POSITIVE_TRUE (0 << 13) +#define NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE (1 << 13) +#define NV_SOR_STATE1_ASY_HSYNCPOL_SHIFT (12) +#define NV_SOR_STATE1_ASY_HSYNCPOL_DEFAULT_MASK (0x1 << 12) +#define NV_SOR_STATE1_ASY_HSYNCPOL_POSITIVE_TRUE (0 << 12) +#define NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE (1 << 12) +#define NV_SOR_STATE1_ASY_PROTOCOL_SHIFT (8) +#define NV_SOR_STATE1_ASY_PROTOCOL_DEFAULT_MASK (0xf << 8) +#define NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM (0 << 8) +#define NV_SOR_STATE1_ASY_PROTOCOL_DP_A (8 << 8) +#define NV_SOR_STATE1_ASY_PROTOCOL_DP_B (9 << 8) +#define NV_SOR_STATE1_ASY_PROTOCOL_CUSTOM (15 << 8) +#define NV_SOR_STATE1_ASY_CRCMODE_SHIFT (6) +#define NV_SOR_STATE1_ASY_CRCMODE_DEFAULT_MASK (0x3 << 6) +#define NV_SOR_STATE1_ASY_CRCMODE_ACTIVE_RASTER (0 << 6) +#define NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER (1 << 6) +#define NV_SOR_STATE1_ASY_CRCMODE_NON_ACTIVE_RASTER (2 << 6) +#define NV_SOR_STATE1_ASY_SUBOWNER_SHIFT (4) +#define NV_SOR_STATE1_ASY_SUBOWNER_DEFAULT_MASK (0x3 << 4) +#define NV_SOR_STATE1_ASY_SUBOWNER_NONE (0 << 4) +#define NV_SOR_STATE1_ASY_SUBOWNER_SUBHEAD0 (1 << 4) +#define NV_SOR_STATE1_ASY_SUBOWNER_SUBHEAD1 (2 << 4) +#define NV_SOR_STATE1_ASY_SUBOWNER_BOTH (3 << 4) +#define NV_SOR_STATE1_ASY_OWNER_SHIFT (0) +#define NV_SOR_STATE1_ASY_OWNER_DEFAULT_MASK (0xf) +#define NV_SOR_STATE1_ASY_OWNER_NONE (0) +#define NV_SOR_STATE1_ASY_OWNER_HEAD0 (1) +#define NV_SOR_STATE1_ASY_OWNER_HEAD1 (2) +#define NV_HEAD_STATE0(i) (0x5) +#define NV_HEAD_STATE0_INTERLACED_SHIFT (4) +#define NV_HEAD_STATE0_INTERLACED_DEFAULT_MASK (0x3 << 4) +#define NV_HEAD_STATE0_INTERLACED_PROGRESSIVE (0 << 4) +#define NV_HEAD_STATE0_INTERLACED_INTERLACED (1 << 4) +#define NV_HEAD_STATE0_RANGECOMPRESS_SHIFT (3) +#define NV_HEAD_STATE0_RANGECOMPRESS_DEFAULT_MASK (0x1 << 3) +#define NV_HEAD_STATE0_RANGECOMPRESS_DISABLE (0 << 3) +#define NV_HEAD_STATE0_RANGECOMPRESS_ENABLE (1 << 3) +#define NV_HEAD_STATE0_DYNRANGE_SHIFT (2) +#define NV_HEAD_STATE0_DYNRANGE_DEFAULT_MASK (0x1 << 2) +#define NV_HEAD_STATE0_DYNRANGE_VESA (0 << 2) +#define NV_HEAD_STATE0_DYNRANGE_CEA (1 << 2) +#define NV_HEAD_STATE0_COLORSPACE_SHIFT (0) +#define NV_HEAD_STATE0_COLORSPACE_DEFAULT_MASK (0x3) +#define NV_HEAD_STATE0_COLORSPACE_RGB (0) +#define NV_HEAD_STATE0_COLORSPACE_YUV_601 (1) +#define NV_HEAD_STATE0_COLORSPACE_YUV_709 (2) +#define NV_HEAD_STATE1(i) (0x7 + i) +#define NV_HEAD_STATE1_VTOTAL_SHIFT (16) +#define NV_HEAD_STATE1_VTOTAL_DEFAULT_MASK (0x7fff << 16) +#define NV_HEAD_STATE1_HTOTAL_SHIFT (0) +#define NV_HEAD_STATE1_HTOTAL_DEFAULT_MASK (0x7fff) +#define NV_HEAD_STATE2(i) (0x9 + i) +#define NV_HEAD_STATE2_VSYNC_END_SHIFT (16) +#define NV_HEAD_STATE2_VSYNC_END_DEFAULT_MASK (0x7fff << 16) +#define NV_HEAD_STATE2_HSYNC_END_SHIFT (0) +#define NV_HEAD_STATE2_HSYNC_END_DEFAULT_MASK (0x7fff) +#define NV_HEAD_STATE3(i) (0xb + i) +#define NV_HEAD_STATE3_VBLANK_END_SHIFT (16) +#define NV_HEAD_STATE3_VBLANK_END_DEFAULT_MASK (0x7fff << 16) +#define NV_HEAD_STATE3_HBLANK_END_SHIFT (0) +#define NV_HEAD_STATE3_HBLANK_END_DEFAULT_MASK (0x7fff) +#define NV_HEAD_STATE4(i) (0xd + i) +#define NV_HEAD_STATE4_VBLANK_START_SHIFT (16) +#define NV_HEAD_STATE4_VBLANK_START_DEFAULT_MASK (0x7fff << 16) +#define NV_HEAD_STATE4_HBLANK_START_SHIFT (0) +#define NV_HEAD_STATE4_HBLANK_START_DEFAULT_MASK (0x7fff) +#define NV_HEAD_STATE5(i) (0xf + i) +#define NV_SOR_CRC_CNTRL (0x11) +#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_SHIFT (0) +#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_NO (0) +#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_YES (1) +#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_DIS (0) +#define NV_SOR_CRC_CNTRL_ARM_CRC_ENABLE_EN (1) +#define NV_SOR_CLK_CNTRL (0x13) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SHIFT (0) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK (0x3) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK (0) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_PCLK (1) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK (2) +#define NV_SOR_CLK_CNTRL_DP_CLK_SEL_DIFF_DPCLK (3) +#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT (2) +#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK (0x1f << 2) +#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62 (6 << 2) +#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G2_7 (10 << 2) +#define NV_SOR_CLK_CNTRL_DP_LINK_SPEED_LVDS (7 << 2) +#define NV_SOR_CAP (0x14) +#define NV_SOR_CAP_DP_A_SHIFT (24) +#define NV_SOR_CAP_DP_A_DEFAULT_MASK (0x1 << 24) +#define NV_SOR_CAP_DP_A_FALSE (0 << 24) +#define NV_SOR_CAP_DP_A_TRUE (1 << 24) +#define NV_SOR_CAP_DP_B_SHIFT (25) +#define NV_SOR_CAP_DP_B_DEFAULT_MASK (0x1 << 24) +#define NV_SOR_CAP_DP_B_FALSE (0 << 24) +#define NV_SOR_CAP_DP_B_TRUE (1 << 24) +#define NV_SOR_PWR (0x15) +#define NV_SOR_PWR_SETTING_NEW_SHIFT (31) +#define NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK (0x1 << 31) +#define NV_SOR_PWR_SETTING_NEW_DONE (0 << 31) +#define NV_SOR_PWR_SETTING_NEW_PENDING (1 << 31) +#define NV_SOR_PWR_SETTING_NEW_TRIGGER (1 << 31) +#define NV_SOR_PWR_MODE_SHIFT (28) +#define NV_SOR_PWR_MODE_DEFAULT_MASK (0x1 << 28) +#define NV_SOR_PWR_MODE_NORMAL (0 << 28) +#define NV_SOR_PWR_MODE_SAFE (1 << 28) +#define NV_SOR_PWR_HALT_DELAY_SHIFT (24) +#define NV_SOR_PWR_HALT_DELAY_DEFAULT_MASK (0x1 << 24) +#define NV_SOR_PWR_HALT_DELAY_DONE (0 << 24) +#define NV_SOR_PWR_HALT_DELAY_ACTIVE (1 << 24) +#define NV_SOR_PWR_SAFE_START_SHIFT (17) +#define NV_SOR_PWR_SAFE_START_DEFAULT_MASK (0x1 << 17) +#define NV_SOR_PWR_SAFE_START_NORMAL (0 << 17) +#define NV_SOR_PWR_SAFE_START_ALT (1 << 17) +#define NV_SOR_PWR_SAFE_STATE_SHIFT (16) +#define NV_SOR_PWR_SAFE_STATE_DEFAULT_MASK (0x1 << 16) +#define NV_SOR_PWR_SAFE_STATE_PD (0 << 16) +#define NV_SOR_PWR_SAFE_STATE_PU (1 << 16) +#define NV_SOR_PWR_NORMAL_START_SHIFT (1) +#define NV_SOR_PWR_NORMAL_START_DEFAULT_MASK (0x1 << 1) +#define NV_SOR_PWR_NORMAL_START_NORMAL (0 << 16) +#define NV_SOR_PWR_NORMAL_START_ALT (1 << 16) +#define NV_SOR_PWR_NORMAL_STATE_SHIFT (0) +#define NV_SOR_PWR_NORMAL_STATE_DEFAULT_MASK (0x1) +#define NV_SOR_PWR_NORMAL_STATE_PD (0) +#define NV_SOR_PWR_NORMAL_STATE_PU (1) +#define NV_SOR_TEST (0x16) +#define NV_SOR_TEST_TESTMUX_SHIFT (24) +#define NV_SOR_TEST_TESTMUX_DEFAULT_MASK (0xff << 24) +#define NV_SOR_TEST_TESTMUX_AVSS (0 << 24) +#define NV_SOR_TEST_TESTMUX_CLOCKIN (2 << 24) +#define NV_SOR_TEST_TESTMUX_PLL_VOL (4 << 24) +#define NV_SOR_TEST_TESTMUX_SLOWCLKINT (8 << 24) +#define NV_SOR_TEST_TESTMUX_AVDD (16 << 24) +#define NV_SOR_TEST_TESTMUX_VDDREG (32 << 24) +#define NV_SOR_TEST_TESTMUX_REGREF_VDDREG (64 << 24) +#define NV_SOR_TEST_TESTMUX_REGREF_AVDD (128 << 24) +#define NV_SOR_TEST_CRC_SHIFT (23) +#define NV_SOR_TEST_CRC_PRE_SERIALIZE (0 << 23) +#define NV_SOR_TEST_CRC_POST_DESERIALIZE (1 << 23) +#define NV_SOR_TEST_TPAT_SHIFT (20) +#define NV_SOR_TEST_TPAT_DEFAULT_MASK (0x7 << 20) +#define NV_SOR_TEST_TPAT_LO (0 << 20) +#define NV_SOR_TEST_TPAT_TDAT (1 << 20) +#define NV_SOR_TEST_TPAT_RAMP (2 << 20) +#define NV_SOR_TEST_TPAT_WALK (3 << 20) +#define NV_SOR_TEST_TPAT_MAXSTEP (4 << 20) +#define NV_SOR_TEST_TPAT_MINSTEP (5 << 20) +#define NV_SOR_TEST_DSRC_SHIFT (16) +#define NV_SOR_TEST_DSRC_DEFAULT_MASK (0x3 << 16) +#define NV_SOR_TEST_DSRC_NORMAL (0 << 16) +#define NV_SOR_TEST_DSRC_DEBUG (1 << 16) +#define NV_SOR_TEST_DSRC_TGEN (2 << 16) +#define NV_SOR_TEST_HEAD_NUMBER_SHIFT (12) +#define NV_SOR_TEST_HEAD_NUMBER_DEFAULT_MASK (0x3 << 12) +#define NV_SOR_TEST_HEAD_NUMBER_NONE (0 << 12) +#define NV_SOR_TEST_HEAD_NUMBER_HEAD0 (1 << 12) +#define NV_SOR_TEST_HEAD_NUMBER_HEAD1 (2 << 12) +#define NV_SOR_TEST_ATTACHED_SHIFT (10) +#define NV_SOR_TEST_ATTACHED_DEFAULT_MASK (0x1 << 10) +#define NV_SOR_TEST_ATTACHED_FALSE (0 << 10) +#define NV_SOR_TEST_ATTACHED_TRUE (1 << 10) +#define NV_SOR_TEST_ACT_HEAD_OPMODE_SHIFT (8) +#define NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK (0x3 << 8) +#define NV_SOR_TEST_ACT_HEAD_OPMODE_SLEEP (0 << 8) +#define NV_SOR_TEST_ACT_HEAD_OPMODE_SNOOZE (1 << 8) +#define NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE (2 << 8) +#define NV_SOR_TEST_INVD_SHIFT (6) +#define NV_SOR_TEST_INVD_DISABLE (0 << 6) +#define NV_SOR_TEST_INVD_ENABLE (1 << 6) +#define NV_SOR_TEST_TEST_ENABLE_SHIFT (1) +#define NV_SOR_TEST_TEST_ENABLE_DISABLE (0 << 1) +#define NV_SOR_TEST_TEST_ENABLE_ENABLE (1 << 1) +#define NV_SOR_PLL0 (0x17) +#define NV_SOR_PLL0_ICHPMP_SHFIT (24) +#define NV_SOR_PLL0_ICHPMP_DEFAULT_MASK (0xf << 24) +#define NV_SOR_PLL0_VCOCAP_SHIFT (8) +#define NV_SOR_PLL0_VCOCAP_DEFAULT_MASK (0xf << 8) +#define NV_SOR_PLL0_PLLREG_LEVEL_SHIFT (6) +#define NV_SOR_PLL0_PLLREG_LEVEL_DEFAULT_MASK (0x3 << 6) +#define NV_SOR_PLL0_PLLREG_LEVEL_V25 (0 << 6) +#define NV_SOR_PLL0_PLLREG_LEVEL_V15 (1 << 6) +#define NV_SOR_PLL0_PLLREG_LEVEL_V35 (2 << 6) +#define NV_SOR_PLL0_PLLREG_LEVEL_V45 (3 << 6) +#define NV_SOR_PLL0_PULLDOWN_SHIFT (5) +#define NV_SOR_PLL0_PULLDOWN_DEFAULT_MASK (0x1 << 5) +#define NV_SOR_PLL0_PULLDOWN_DISABLE (0 << 5) +#define NV_SOR_PLL0_PULLDOWN_ENABLE (1 << 5) +#define NV_SOR_PLL0_RESISTORSEL_SHIFT (4) +#define NV_SOR_PLL0_RESISTORSEL_DEFAULT_MASK (0x1 << 4) +#define NV_SOR_PLL0_RESISTORSEL_INT (0 << 4) +#define NV_SOR_PLL0_RESISTORSEL_EXT (1 << 4) +#define NV_SOR_PLL0_VCOPD_SHIFT (2) +#define NV_SOR_PLL0_VCOPD_MASK (1 << 2) +#define NV_SOR_PLL0_VCOPD_RESCIND (0 << 2) +#define NV_SOR_PLL0_VCOPD_ASSERT (1 << 2) +#define NV_SOR_PLL0_PWR_SHIFT (0) +#define NV_SOR_PLL0_PWR_MASK (1) +#define NV_SOR_PLL0_PWR_ON (0) +#define NV_SOR_PLL0_PWR_OFF (1) +#define NV_SOR_PLL1_TMDS_TERM_SHIFT (8) +#define NV_SOR_PLL1_TMDS_TERM_DISABLE (0 << 8) +#define NV_SOR_PLL1_TMDS_TERM_ENABLE (1 << 8) +#define NV_SOR_PLL1 (0x18) +#define NV_SOR_PLL1_TERM_COMPOUT_SHIFT (15) +#define NV_SOR_PLL1_TERM_COMPOUT_LOW (0 << 15) +#define NV_SOR_PLL1_TERM_COMPOUT_HIGH (1 << 15) +#define NV_SOR_PLL2 (0x19) +#define NV_SOR_PLL2_DCIR_PLL_RESET_SHIFT (0) +#define NV_SOR_PLL2_DCIR_PLL_RESET_OVERRIDE (0 << 0) +#define NV_SOR_PLL2_DCIR_PLL_RESET_ALLOW (1 << 0) +#define NV_SOR_PLL2_AUX1_SHIFT (17) +#define NV_SOR_PLL2_AUX1_SEQ_MASK (1 << 17) +#define NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_ALLOW (0 << 17) +#define NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE (1 << 17) +#define NV_SOR_PLL2_AUX2_SHIFT (18) +#define NV_SOR_PLL2_AUX2_MASK (1 << 18) +#define NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN (0 << 18) +#define NV_SOR_PLL2_AUX2_ALLOW_POWERDOWN (1 << 18) +#define NV_SOR_PLL2_AUX6_SHIFT (22) +#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK (1 << 22) +#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE (0 << 22) +#define NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE (1 << 22) +#define NV_SOR_PLL2_AUX7_SHIFT (23) +#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK (1 << 23) +#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE (0 << 23) +#define NV_SOR_PLL2_AUX7_PORT_POWERDOWN_ENABLE (1 << 23) +#define NV_SOR_PLL2_AUX8_SHIFT (24) +#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK (1 << 24) +#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE (0 << 24) +#define NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE (1 << 24) +#define NV_SOR_PLL2_AUX9_SHIFT (25) +#define NV_SOR_PLL2_AUX9_LVDSEN_ALLOW (0 << 25) +#define NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE (1 << 25) +#define NV_SOR_PLL3 (0x1a) +#define NV_SOR_PLL3_PLLVDD_MODE_SHIFT (13) +#define NV_SOR_PLL3_PLLVDD_MODE_MASK (1 << 13) +#define NV_SOR_PLL3_PLLVDD_MODE_V1_8 (0 << 13) +#define NV_SOR_PLL3_PLLVDD_MODE_V3_3 (1 << 13) +#define NV_SOR_CSTM (0x1b) +#define NV_SOR_CSTM_ROTDAT_SHIFT (28) +#define NV_SOR_CSTM_ROTDAT_DEFAULT_MASK (0x7 << 28) +#define NV_SOR_CSTM_ROTCLK_SHIFT (24) +#define NV_SOR_CSTM_ROTCLK_DEFAULT_MASK (0xf << 24) +#define NV_SOR_CSTM_LVDS_EN_SHIFT (16) +#define NV_SOR_CSTM_LVDS_EN_DISABLE (0 << 16) +#define NV_SOR_CSTM_LVDS_EN_ENABLE (1 << 16) +#define NV_SOR_CSTM_LINKACTB_SHIFT (15) +#define NV_SOR_CSTM_LINKACTB_DISABLE (0 << 15) +#define NV_SOR_CSTM_LINKACTB_ENABLE (1 << 15) +#define NV_SOR_CSTM_LINKACTA_SHIFT (14) +#define NV_SOR_CSTM_LINKACTA_DISABLE (0 << 14) +#define NV_SOR_CSTM_LINKACTA_ENABLE (1 << 14) +#define NV_SOR_LVDS (0x1c) +#define NV_SOR_LVDS_ROTDAT_SHIFT (28) +#define NV_SOR_LVDS_ROTDAT_DEFAULT_MASK (0x7 << 28) +#define NV_SOR_LVDS_ROTDAT_RST (0 << 28) +#define NV_SOR_LVDS_ROTCLK_SHIFT (24) +#define NV_SOR_LVDS_ROTCLK_DEFAULT_MASK (0xf << 24) +#define NV_SOR_LVDS_ROTCLK_RST (0 << 24) +#define NV_SOR_LVDS_PLLDIV_SHIFT (21) +#define NV_SOR_LVDS_PLLDIV_DEFAULT_MASK (0x1 << 21) +#define NV_SOR_LVDS_PLLDIV_BY_7 (0 << 21) +#define NV_SOR_LVDS_BALANCED_SHIFT (19) +#define NV_SOR_LVDS_BALANCED_DEFAULT_MASK (0x1 << 19) +#define NV_SOR_LVDS_BALANCED_DISABLE (0 << 19) +#define NV_SOR_LVDS_BALANCED_ENABLE (1 << 19) +#define NV_SOR_LVDS_NEW_MODE_SHIFT (18) +#define NV_SOR_LVDS_NEW_MODE_DEFAULT_MASK (0x1 << 18) +#define NV_SOR_LVDS_NEW_MODE_DISABLE (0 << 18) +#define NV_SOR_LVDS_NEW_MODE_ENABLE (1 << 18) +#define NV_SOR_LVDS_DUP_SYNC_SHIFT (17) +#define NV_SOR_LVDS_DUP_SYNC_DEFAULT_MASK (0x1 << 17) +#define NV_SOR_LVDS_DUP_SYNC_DISABLE (0 << 17) +#define NV_SOR_LVDS_DUP_SYNC_ENABLE (1 << 17) +#define NV_SOR_LVDS_LVDS_EN_SHIFT (16) +#define NV_SOR_LVDS_LVDS_EN_DEFAULT_MASK (0x1 << 16) +#define NV_SOR_LVDS_LVDS_EN_ENABLE (1 << 16) +#define NV_SOR_LVDS_LINKACTB_SHIFT (15) +#define NV_SOR_LVDS_LINKACTB_DEFAULT_MASK (0x1 << 15) +#define NV_SOR_LVDS_LINKACTB_DISABLE (0 << 15) +#define NV_SOR_LVDS_LINKACTB_ENABLE (1 << 15) +#define NV_SOR_LVDS_LINKACTA_SHIFT (14) +#define NV_SOR_LVDS_LINKACTA_DEFAULT_MASK (0x1 << 14) +#define NV_SOR_LVDS_LINKACTA_ENABLE (1 << 14) +#define NV_SOR_LVDS_MODE_SHIFT (12) +#define NV_SOR_LVDS_MODE_DEFAULT_MASK (0x3 << 12) +#define NV_SOR_LVDS_MODE_LVDS (0 << 12) +#define NV_SOR_LVDS_UPPER_SHIFT (11) +#define NV_SOR_LVDS_UPPER_DEFAULT_MASK (0x1 << 11) +#define NV_SOR_LVDS_UPPER_FALSE (0 << 11) +#define NV_SOR_LVDS_UPPER_TRUE (1 << 11) +#define NV_SOR_LVDS_PD_TXCB_SHIFT (9) +#define NV_SOR_LVDS_PD_TXCB_DEFAULT_MASK (0x1 << 9) +#define NV_SOR_LVDS_PD_TXCB_ENABLE (0 << 9) +#define NV_SOR_LVDS_PD_TXCB_DISABLE (1 << 9) +#define NV_SOR_LVDS_PD_TXCA_SHIFT (8) +#define NV_SOR_LVDS_PD_TXCA_DEFAULT_MASK (0x1 << 8) +#define NV_SOR_LVDS_PD_TXCA_ENABLE (0 << 8) +#define NV_SOR_LVDS_PD_TXDB_3_SHIFT (7) +#define NV_SOR_LVDS_PD_TXDB_3_DEFAULT_MASK (0x1 << 7) +#define NV_SOR_LVDS_PD_TXDB_3_ENABLE (0 << 7) +#define NV_SOR_LVDS_PD_TXDB_3_DISABLE (1 << 7) +#define NV_SOR_LVDS_PD_TXDB_2_SHIFT (6) +#define NV_SOR_LVDS_PD_TXDB_2_DEFAULT_MASK (0x1 << 6) +#define NV_SOR_LVDS_PD_TXDB_2_ENABLE (0 << 6) +#define NV_SOR_LVDS_PD_TXDB_2_DISABLE (1 << 6) +#define NV_SOR_LVDS_PD_TXDB_1_SHIFT (5) +#define NV_SOR_LVDS_PD_TXDB_1_DEFAULT_MASK (0x1 << 5) +#define NV_SOR_LVDS_PD_TXDB_1_ENABLE (0 << 5) +#define NV_SOR_LVDS_PD_TXDB_1_DISABLE (1 << 5) +#define NV_SOR_LVDS_PD_TXDB_0_SHIFT (4) +#define NV_SOR_LVDS_PD_TXDB_0_DEFAULT_MASK (0x1 << 4) +#define NV_SOR_LVDS_PD_TXDB_0_ENABLE (0 << 4) +#define NV_SOR_LVDS_PD_TXDB_0_DISABLE (1 << 4) +#define NV_SOR_LVDS_PD_TXDA_3_SHIFT (3) +#define NV_SOR_LVDS_PD_TXDA_3_DEFAULT_MASK (0x1 << 3) +#define NV_SOR_LVDS_PD_TXDA_3_ENABLE (0 << 3) +#define NV_SOR_LVDS_PD_TXDA_3_DISABLE (1 << 3) +#define NV_SOR_LVDS_PD_TXDA_2_SHIFT (2) +#define NV_SOR_LVDS_PD_TXDA_2_DEFAULT_MASK (0x1 << 2) +#define NV_SOR_LVDS_PD_TXDA_2_ENABLE (0 << 2) +#define NV_SOR_LVDS_PD_TXDA_1_SHIFT (1) +#define NV_SOR_LVDS_PD_TXDA_1_DEFAULT_MASK (0x1 << 1) +#define NV_SOR_LVDS_PD_TXDA_1_ENABLE (0 << 1) +#define NV_SOR_LVDS_PD_TXDA_0_SHIFT (0) +#define NV_SOR_LVDS_PD_TXDA_0_DEFAULT_MASK (0x1) +#define NV_SOR_LVDS_PD_TXDA_0_ENABLE (0) +#define NV_SOR_CRCA (0x1d) +#define NV_SOR_CRCA_VALID_FALSE (0) +#define NV_SOR_CRCA_VALID_TRUE (1) +#define NV_SOR_CRCA_VALID_RST (1) +#define NV_SOR_CRCB (0x1e) +#define NV_SOR_CRCB_CRC_DEFAULT_MASK (0xffffffff) +#define NV_SOR_SEQ_CTL (0x20) +#define NV_SOR_SEQ_CTL_SWITCH_SHIFT (30) +#define NV_SOR_SEQ_CTL_SWITCH_MASK (0x1 << 30) +#define NV_SOR_SEQ_CTL_SWITCH_WAIT (0 << 30) +#define NV_SOR_SEQ_CTL_SWITCH_FORCE (1 << 30) +#define NV_SOR_SEQ_CTL_STATUS_SHIFT (28) +#define NV_SOR_SEQ_CTL_STATUS_MASK (0x1 << 28) +#define NV_SOR_SEQ_CTL_STATUS_STOPPED (0 << 28) +#define NV_SOR_SEQ_CTL_STATUS_RUNNING (1 << 28) +#define NV_SOR_SEQ_CTL_PC_SHIFT (16) +#define NV_SOR_SEQ_CTL_PC_MASK (0xf << 16) +#define NV_SOR_SEQ_CTL_PD_PC_ALT_SHIFT (12) +#define NV_SOR_SEQ_CTL_PD_PC_ALT_MASK (0xf << 12) +#define NV_SOR_SEQ_CTL_PD_PC_SHIFT (8) +#define NV_SOR_SEQ_CTL_PD_PC_MASK (0xf << 8) +#define NV_SOR_SEQ_CTL_PU_PC_ALT_SHIFT (4) +#define NV_SOR_SEQ_CTL_PU_PC_ALT_MASK (0xf << 4) +#define NV_SOR_SEQ_CTL_PU_PC_SHIFT (0) +#define NV_SOR_SEQ_CTL_PU_PC_MASK (0xf) +#define NV_SOR_LANE_SEQ_CTL (0x21) +#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_SHIFT (31) +#define NV_SOR_LANE_SEQ_CTL_SETTING_MASK (1 << 31) +#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE (0 << 31) +#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_PENDING (1 << 31) +#define NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER (1 << 31) +#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_SHIFT (28) +#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_IDLE (0 << 28) +#define NV_SOR_LANE_SEQ_CTL_SEQ_STATE_BUSY (1 << 28) +#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_SHIFT (20) +#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP (0 << 20) +#define NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN (1 << 20) +#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_SHIFT (16) +#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU (0 << 16) +#define NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD (1 << 16) +#define NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT (12) +#define NV_SOR_LANE_SEQ_CTL_DELAY_DEFAULT_MASK (0xf << 12) +#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_SHIFT (9) +#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_POWERUP (0 << 9) +#define NV_SOR_LANE_SEQ_CTL_LANE9_STATE_POWERDOWN (1 << 9) +#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_SHIFT (8) +#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_POWERUP (0 << 8) +#define NV_SOR_LANE_SEQ_CTL_LANE8_STATE_POWERDOWN (1 << 8) +#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_SHIFT (7) +#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_POWERUP (0 << 7) +#define NV_SOR_LANE_SEQ_CTL_LANE7_STATE_POWERDOWN (1 << 7) +#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_SHIFT (6) +#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_POWERUP (0 << 6) +#define NV_SOR_LANE_SEQ_CTL_LANE6_STATE_POWERDOWN (1 << 6) +#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_SHIFT (5) +#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_POWERUP (0 << 5) +#define NV_SOR_LANE_SEQ_CTL_LANE5_STATE_POWERDOWN (1 << 5) +#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_SHIFT (4) +#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_POWERUP (0 << 4) +#define NV_SOR_LANE_SEQ_CTL_LANE4_STATE_POWERDOWN (1 << 4) +#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_SHIFT (3) +#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_POWERUP (0 << 3) +#define NV_SOR_LANE_SEQ_CTL_LANE3_STATE_POWERDOWN (1 << 3) +#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_SHIFT (2) +#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_POWERUP (0 << 2) +#define NV_SOR_LANE_SEQ_CTL_LANE2_STATE_POWERDOWN (1 << 2) +#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_SHIFT (1) +#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_POWERUP (0 << 1) +#define NV_SOR_LANE_SEQ_CTL_LANE1_STATE_POWERDOWN (1 << 1) +#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_SHIFT (0) +#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_POWERUP (0) +#define NV_SOR_LANE_SEQ_CTL_LANE0_STATE_POWERDOWN (1) +#define NV_SOR_SEQ_INST(i) (0x22 + i) +#define NV_SOR_SEQ_INST_PLL_PULLDOWN_SHIFT (31) +#define NV_SOR_SEQ_INST_PLL_PULLDOWN_DISABLE (0 << 31) +#define NV_SOR_SEQ_INST_PLL_PULLDOWN_ENABLE (1 << 31) +#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_SHIFT (30) +#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_NORMAL (0 << 30) +#define NV_SOR_SEQ_INST_POWERDOWN_MACRO_POWERDOWN (1 << 30) +#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_SHIFT (29) +#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_NORMAL (0 << 29) +#define NV_SOR_SEQ_INST_ASSERT_PLL_RESET_RST (1 << 29) +#define NV_SOR_SEQ_INST_BLANK_V_SHIFT (28) +#define NV_SOR_SEQ_INST_BLANK_V_NORMAL (0 << 28) +#define NV_SOR_SEQ_INST_BLANK_V_INACTIVE (1 << 28) +#define NV_SOR_SEQ_INST_BLANK_H_SHIFT (27) +#define NV_SOR_SEQ_INST_BLANK_H_NORMAL (0 << 27) +#define NV_SOR_SEQ_INST_BLANK_H_INACTIVE (1 << 27) +#define NV_SOR_SEQ_INST_BLANK_DE_SHIFT (26) +#define NV_SOR_SEQ_INST_BLANK_DE_NORMAL (0 << 26) +#define NV_SOR_SEQ_INST_BLANK_DE_INACTIVE (1 << 26) +#define NV_SOR_SEQ_INST_BLACK_DATA_SHIFT (25) +#define NV_SOR_SEQ_INST_BLACK_DATA_NORMAL (0 << 25) +#define NV_SOR_SEQ_INST_BLACK_DATA_BLACK (1 << 25) +#define NV_SOR_SEQ_INST_TRISTATE_IOS_SHIFT (24) +#define NV_SOR_SEQ_INST_TRISTATE_IOS_ENABLE_PINS (0 << 24) +#define NV_SOR_SEQ_INST_TRISTATE_IOS_TRISTATE (1 << 24) +#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_SHIFT (23) +#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_FALSE (0 << 23) +#define NV_SOR_SEQ_INST_DRIVE_PWM_OUT_LO_TRUE (1 << 23) +#define NV_SOR_SEQ_INST_PIN_B_SHIFT (22) +#define NV_SOR_SEQ_INST_PIN_B_LOW (0 << 22) +#define NV_SOR_SEQ_INST_PIN_B_HIGH (1 << 22) +#define NV_SOR_SEQ_INST_PIN_A_SHIFT (21) +#define NV_SOR_SEQ_INST_PIN_A_LOW (0 << 21) +#define NV_SOR_SEQ_INST_PIN_A_HIGH (1 << 21) +#define NV_SOR_SEQ_INST_SEQUENCE_SHIFT (19) +#define NV_SOR_SEQ_INST_SEQUENCE_UP (0 << 19) +#define NV_SOR_SEQ_INST_SEQUENCE_DOWN (1 << 19) +#define NV_SOR_SEQ_INST_LANE_SEQ_SHIFT (18) +#define NV_SOR_SEQ_INST_LANE_SEQ_STOP (0 << 18) +#define NV_SOR_SEQ_INST_LANE_SEQ_RUN (1 << 18) +#define NV_SOR_SEQ_INST_PDPORT_SHIFT (17) +#define NV_SOR_SEQ_INST_PDPORT_NO (0 << 17) +#define NV_SOR_SEQ_INST_PDPORT_YES (1 << 17) +#define NV_SOR_SEQ_INST_PDPLL_SHIFT (16) +#define NV_SOR_SEQ_INST_PDPLL_NO (0 << 16) +#define NV_SOR_SEQ_INST_PDPLL_YES (1 << 16) +#define NV_SOR_SEQ_INST_HALT_SHIFT (15) +#define NV_SOR_SEQ_INST_HALT_FALSE (0 << 15) +#define NV_SOR_SEQ_INST_HALT_TRUE (1 << 15) +#define NV_SOR_SEQ_INST_WAIT_UNITS_SHIFT (12) +#define NV_SOR_SEQ_INST_WAIT_UNITS_DEFAULT_MASK (0x3 << 12) +#define NV_SOR_SEQ_INST_WAIT_UNITS_US (0 << 12) +#define NV_SOR_SEQ_INST_WAIT_UNITS_MS (1 << 12) +#define NV_SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12) +#define NV_SOR_SEQ_INST_WAIT_TIME_SHIFT (0) +#define NV_SOR_SEQ_INST_WAIT_TIME_DEFAULT_MASK (0x3ff) +#define NV_SOR_PWM_DIV (0x32) +#define NV_SOR_PWM_DIV_DIVIDE_DEFAULT_MASK (0xffffff) +#define NV_SOR_PWM_CTL (0x33) +#define NV_SOR_PWM_CTL_SETTING_NEW_SHIFT (31) +#define NV_SOR_PWM_CTL_SETTING_NEW_DONE (0 << 31) +#define NV_SOR_PWM_CTL_SETTING_NEW_PENDING (1 << 31) +#define NV_SOR_PWM_CTL_SETTING_NEW_TRIGGER (1 << 31) +#define NV_SOR_PWM_CTL_CLKSEL_SHIFT (30) +#define NV_SOR_PWM_CTL_CLKSEL_PCLK (0 << 30) +#define NV_SOR_PWM_CTL_CLKSEL_XTAL (1 << 30) +#define NV_SOR_PWM_CTL_DUTY_CYCLE_SHIFT (0) +#define NV_SOR_PWM_CTL_DUTY_CYCLE_MASK (0xffffff) +#define NV_SOR_MSCHECK (0x49) +#define NV_SOR_MSCHECK_CTL_SHIFT (31) +#define NV_SOR_MSCHECK_CTL_CLEAR (0 << 31) +#define NV_SOR_MSCHECK_CTL_RUN (1 << 31) +#define NV_SOR_XBAR_CTRL (0x4a) +#define NV_SOR_DP_LINKCTL(i) (0x4c + (i)) +#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_SHIFT (31) +#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_NO (0 << 31) +#define NV_SOR_DP_LINKCTL_FORCE_IDLEPTTRN_YES (1 << 31) +#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_SHIFT (28) +#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_NOPATTERN (0 << 28) +#define NV_SOR_DP_LINKCTL_COMPLIANCEPTTRN_COLORSQARE (1 << 28) +#define NV_SOR_DP_LINKCTL_LANECOUNT_SHIFT (16) +#define NV_SOR_DP_LINKCTL_LANECOUNT_MASK (0x1f << 16) +#define NV_SOR_DP_LINKCTL_LANECOUNT_ZERO (0 << 16) +#define NV_SOR_DP_LINKCTL_LANECOUNT_ONE (1 << 16) +#define NV_SOR_DP_LINKCTL_LANECOUNT_TWO (3 << 16) +#define NV_SOR_DP_LINKCTL_LANECOUNT_FOUR (15 << 16) +#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_SHIFT (14) +#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_DISABLE (0 << 14) +#define NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE (1 << 14) +#define NV_SOR_DP_LINKCTL_SYNCMODE_SHIFT (10) +#define NV_SOR_DP_LINKCTL_SYNCMODE_DISABLE (0 << 10) +#define NV_SOR_DP_LINKCTL_SYNCMODE_ENABLE (1 << 10) +#define NV_SOR_DP_LINKCTL_TUSIZE_SHIFT (2) +#define NV_SOR_DP_LINKCTL_TUSIZE_MASK (0x7f << 2) +#define NV_SOR_DP_LINKCTL_ENABLE_SHIFT (0) +#define NV_SOR_DP_LINKCTL_ENABLE_NO (0) +#define NV_SOR_DP_LINKCTL_ENABLE_YES (1) +#define NV_SOR_DC(i) (0x4e + (i)) +#define NV_SOR_DC_LANE3_DP_LANE3_SHIFT (24) +#define NV_SOR_DC_LANE3_DP_LANE3_MASK (0xff << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL0 (17 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL0 (21 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P2_LEVEL0 (26 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P3_LEVEL0 (34 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL1 (26 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL1 (32 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P2_LEVEL1 (39 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL2 (34 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P1_LEVEL2 (43 << 24) +#define NV_SOR_DC_LANE3_DP_LANE3_P0_LEVEL3 (51 << 24) +#define NV_SOR_DC_LANE2_DP_LANE0_SHIFT (16) +#define NV_SOR_DC_LANE2_DP_LANE0_MASK (0xff << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL0 (17 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL0 (21 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P2_LEVEL0 (26 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P3_LEVEL0 (34 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL1 (26 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL1 (32 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P2_LEVEL1 (39 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL2 (34 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P1_LEVEL2 (43 << 16) +#define NV_SOR_DC_LANE2_DP_LANE0_P0_LEVEL3 (51 << 16) +#define NV_SOR_DC_LANE1_DP_LANE1_SHIFT (8) +#define NV_SOR_DC_LANE1_DP_LANE1_MASK (0xff << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL0 (17 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL0 (21 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P2_LEVEL0 (26 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P3_LEVEL0 (34 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL1 (26 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL1 (32 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P2_LEVEL1 (39 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL2 (34 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P1_LEVEL2 (43 << 8) +#define NV_SOR_DC_LANE1_DP_LANE1_P0_LEVEL3 (51 << 8) +#define NV_SOR_DC_LANE0_DP_LANE2_SHIFT (0) +#define NV_SOR_DC_LANE0_DP_LANE2_MASK (0xff) +#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL0 (17) +#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL0 (21) +#define NV_SOR_DC_LANE0_DP_LANE2_P2_LEVEL0 (26) +#define NV_SOR_DC_LANE0_DP_LANE2_P3_LEVEL0 (34) +#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL1 (26) +#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL1 (32) +#define NV_SOR_DC_LANE0_DP_LANE2_P2_LEVEL1 (39) +#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL2 (34) +#define NV_SOR_DC_LANE0_DP_LANE2_P1_LEVEL2 (43) +#define NV_SOR_DC_LANE0_DP_LANE2_P0_LEVEL3 (51) +#define NV_SOR_LANE_DRIVE_CURRENT(i) (0x4e + (i)) +#define NV_SOR_PR(i) (0x52 + (i)) +#define NV_SOR_PR_LANE3_DP_LANE3_SHIFT (24) +#define NV_SOR_PR_LANE3_DP_LANE3_MASK (0xff << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL0 (0 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL0 (0 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D2_LEVEL0 (0 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D3_LEVEL0 (0 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL1 (4 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL1 (6 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D2_LEVEL1 (17 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL2 (8 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D1_LEVEL2 (13 << 24) +#define NV_SOR_PR_LANE3_DP_LANE3_D0_LEVEL3 (17 << 24) +#define NV_SOR_PR_LANE2_DP_LANE0_SHIFT (16) +#define NV_SOR_PR_LANE2_DP_LANE0_MASK (0xff << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL0 (0 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL0 (0 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D2_LEVEL0 (0 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D3_LEVEL0 (0 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL1 (4 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL1 (6 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D2_LEVEL1 (17 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL2 (8 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D1_LEVEL2 (13 << 16) +#define NV_SOR_PR_LANE2_DP_LANE0_D0_LEVEL3 (17 << 16) +#define NV_SOR_PR_LANE1_DP_LANE1_SHIFT (8) +#define NV_SOR_PR_LANE1_DP_LANE1_MASK (0xff >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL0 (0 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL0 (0 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D2_LEVEL0 (0 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D3_LEVEL0 (0 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL1 (4 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL1 (6 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D2_LEVEL1 (17 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL2 (8 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D1_LEVEL2 (13 >> 8) +#define NV_SOR_PR_LANE1_DP_LANE1_D0_LEVEL3 (17 >> 8) +#define NV_SOR_PR_LANE0_DP_LANE2_SHIFT (0) +#define NV_SOR_PR_LANE0_DP_LANE2_MASK (0xff) +#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL0 (0) +#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL0 (0) +#define NV_SOR_PR_LANE0_DP_LANE2_D2_LEVEL0 (0) +#define NV_SOR_PR_LANE0_DP_LANE2_D3_LEVEL0 (0) +#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL1 (4) +#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL1 (6) +#define NV_SOR_PR_LANE0_DP_LANE2_D2_LEVEL1 (17) +#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL2 (8) +#define NV_SOR_PR_LANE0_DP_LANE2_D1_LEVEL2 (13) +#define NV_SOR_PR_LANE0_DP_LANE2_D0_LEVEL3 (17) +#define NV_SOR_LANE4_PREEMPHASIS(i) (0x54 + (i)) +#define NV_SOR_POSTCURSOR(i) (0x56 + (i)) +#define NV_SOR_DP_CONFIG(i) (0x58 + (i)) +#define NV_SOR_DP_CONFIG_RD_RESET_VAL_SHIFT (31) +#define NV_SOR_DP_CONFIG_RD_RESET_VAL_POSITIVE (0 << 31) +#define NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE (1 << 31) +#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_SHIFT (28) +#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_DISABLE (0 << 28) +#define NV_SOR_DP_CONFIG_IDLE_BEFORE_ATTACH_ENABLE (1 << 28) +#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_SHIFT (26) +#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_DISABLE (0 << 26) +#define NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE (1 << 26) +#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_SHIFT (24) +#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_NEGATIVE (0 << 24) +#define NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE (1 << 24) +#define NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT (16) +#define NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK (0xf << 16) +#define NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT (8) +#define NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK (0x7f << 8) +#define NV_SOR_DP_CONFIG_WATERMARK_SHIFT (0) +#define NV_SOR_DP_CONFIG_WATERMARK_MASK (0x3f) +#define NV_SOR_DP_MN(i) (0x5a + i) +#define NV_SOR_DP_MN_M_MOD_SHIFT (30) +#define NV_SOR_DP_MN_M_MOD_DEFAULT_MASK (0x3 << 30) +#define NV_SOR_DP_MN_M_MOD_NONE (0 << 30) +#define NV_SOR_DP_MN_M_MOD_INC (1 << 30) +#define NV_SOR_DP_MN_M_MOD_DEC (2 << 30) +#define NV_SOR_DP_MN_M_DELTA_SHIFT (24) +#define NV_SOR_DP_MN_M_DELTA_DEFAULT_MASK (0xf << 24) +#define NV_SOR_DP_MN_N_VAL_SHIFT (0) +#define NV_SOR_DP_MN_N_VAL_DEFAULT_MASK (0xffffff) +#define NV_SOR_DP_PADCTL(i) (0x5c + (i)) +#define NV_SOR_DP_PADCTL_SPARE_SHIFT (25) +#define NV_SOR_DP_PADCTL_SPARE_DEFAULT_MASK (0x7f << 25) +#define NV_SOR_DP_PADCTL_VCO_2X_SHIFT (24) +#define NV_SOR_DP_PADCTL_VCO_2X_DISABLE (0 << 24) +#define NV_SOR_DP_PADCTL_VCO_2X_ENABLE (1 << 24) +#define NV_SOR_DP_PADCTL_PAD_CAL_PD_SHIFT (23) +#define NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP (0 << 23) +#define NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN (1 << 23) +#define NV_SOR_DP_PADCTL_TX_PU_SHIFT (22) +#define NV_SOR_DP_PADCTL_TX_PU_DISABLE (0 << 22) +#define NV_SOR_DP_PADCTL_TX_PU_ENABLE (1 << 22) +#define NV_SOR_DP_PADCTL_TX_PU_MASK (1 << 22) +#define NV_SOR_DP_PADCTL_REG_CTRL_SHIFT (20) +#define NV_SOR_DP_PADCTL_REG_CTRL_DEFAULT_MASK (0x3 << 20) +#define NV_SOR_DP_PADCTL_VCMMODE_SHIFT (16) +#define NV_SOR_DP_PADCTL_VCMMODE_DEFAULT_MASK (0xf << 16) +#define NV_SOR_DP_PADCTL_VCMMODE_TRISTATE (0 << 16) +#define NV_SOR_DP_PADCTL_VCMMODE_TEST_MUX (1 << 16) +#define NV_SOR_DP_PADCTL_VCMMODE_WEAK_PULLDOWN (2 << 16) +#define NV_SOR_DP_PADCTL_VCMMODE_STRONG_PULLDOWN (4 << 16) +#define NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT (8) +#define NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK (0xff << 8) +#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_SHIFT (7) +#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_DISABLE (0 << 7) +#define NV_SOR_DP_PADCTL_COMODE_TXD_3_DP_TXD_3_ENABLE (1 << 7) +#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_SHIFT (6) +#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_DISABLE (0 << 6) +#define NV_SOR_DP_PADCTL_COMODE_TXD_2_DP_TXD_0_ENABLE (1 << 6) +#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_SHIFT (5) +#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_DISABLE (0 << 5) +#define NV_SOR_DP_PADCTL_COMODE_TXD_1_DP_TXD_1_ENABLE (1 << 5) +#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT (4) +#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_DISABLE (0 << 4) +#define NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_ENABLE (1 << 4) +#define NV_SOR_DP_PADCTL_PD_TXD_3_SHIFT (3) +#define NV_SOR_DP_PADCTL_PD_TXD_3_YES (0 << 3) +#define NV_SOR_DP_PADCTL_PD_TXD_3_NO (1 << 3) +#define NV_SOR_DP_PADCTL_PD_TXD_0_SHIFT (2) +#define NV_SOR_DP_PADCTL_PD_TXD_0_YES (0 << 2) +#define NV_SOR_DP_PADCTL_PD_TXD_0_NO (1 << 2) +#define NV_SOR_DP_PADCTL_PD_TXD_1_SHIFT (1) +#define NV_SOR_DP_PADCTL_PD_TXD_1_YES (0 << 1) +#define NV_SOR_DP_PADCTL_PD_TXD_1_NO (1 << 1) +#define NV_SOR_DP_PADCTL_PD_TXD_2_SHIFT (0) +#define NV_SOR_DP_PADCTL_PD_TXD_2_YES (0) +#define NV_SOR_DP_PADCTL_PD_TXD_2_NO (1) +#define NV_SOR_DP_DEBUG(i) (0x5e + i) +#define NV_SOR_DP_SPARE(i) (0x60 + (i)) +#define NV_SOR_DP_SPARE_REG_SHIFT (3) +#define NV_SOR_DP_SPARE_REG_DEFAULT_MASK (0x1fffffff << 3) +#define NV_SOR_DP_SPARE_SOR_CLK_SEL_SHIFT (2) +#define NV_SOR_DP_SPARE_SOR_CLK_SEL_DEFAULT_MASK (0x1 << 2) +#define NV_SOR_DP_SPARE_SOR_CLK_SEL_SAFE_SORCLK (0 << 2) +#define NV_SOR_DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK (1 << 2) +#define NV_SOR_DP_SPARE_PANEL_SHIFT (1) +#define NV_SOR_DP_SPARE_PANEL_EXTERNAL (0 << 1) +#define NV_SOR_DP_SPARE_PANEL_INTERNAL (1 << 1) +#define NV_SOR_DP_SPARE_SEQ_ENABLE_SHIFT (0) +#define NV_SOR_DP_SPARE_SEQ_ENABLE_NO (0) +#define NV_SOR_DP_SPARE_SEQ_ENABLE_YES (1) +#define NV_SOR_DP_AUDIO_CTRL (0x62) +#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS (0x63) +#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK (0x1ffff) +#define NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_VALUE_SHIFT (0) +#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS (0x64) +#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK (0x1ffff) +#define NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_SHIFT (0) +#define NV_SOR_DP_GENERIC_INFOFRAME_HEADER (0x65) +#define NV_SOR_DP_GENERIC_INFOFRAME_SUBPACK(i) (0x66 + (i)) +#define NV_SOR_DP_TPG (0x6d) +#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_SHIFT (30) +#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_DISABLE (0 << 30) +#define NV_SOR_DP_TPG_LANE3_CHANNELCODING_ENABLE (1 << 30) +#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_SHIFT (28) +#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_ENABLE_GALIOS (1 << 28) +#define NV_SOR_DP_TPG_LANE3_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 28) +#define NV_SOR_DP_TPG_LANE3_PATTERN_SHIFT (24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_DEFAULT_MASK (0xf << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_NOPATTERN (0 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING1 (1 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING2 (2 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_TRAINING3 (3 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_D102 (4 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_SBLERRRATE (5 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_PRBS7 (6 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_CSTM (7 << 24) +#define NV_SOR_DP_TPG_LANE3_PATTERN_HBR2_COMPLIANCE (8 << 24) +#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_SHIFT (22) +#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_DISABLE (0 << 22) +#define NV_SOR_DP_TPG_LANE2_CHANNELCODING_ENABLE (1 << 22) +#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_SHIFT (20) +#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_DEFAULT_MASK (0x3 << 20) +#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_DISABLE (0 << 20) +#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_ENABLE_GALIOS (1 << 20) +#define NV_SOR_DP_TPG_LANE2_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 20) +#define NV_SOR_DP_TPG_LANE2_PATTERN_SHIFT (16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_DEFAULT_MASK (0xf << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_NOPATTERN (0 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING1 (1 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING2 (2 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_TRAINING3 (3 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_D102 (4 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_SBLERRRATE (5 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_PRBS7 (6 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_CSTM (7 << 16) +#define NV_SOR_DP_TPG_LANE2_PATTERN_HBR2_COMPLIANCE (8 << 16) +#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_SHIFT (14) +#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_DISABLE (0 << 14) +#define NV_SOR_DP_TPG_LANE1_CHANNELCODING_ENABLE (1 << 14) +#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_SHIFT (12) +#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_DEFAULT_MASK (0x3 << 12) +#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_DISABLE (0 << 12) +#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_ENABLE_GALIOS (1 << 12) +#define NV_SOR_DP_TPG_LANE1_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 12) +#define NV_SOR_DP_TPG_LANE1_PATTERN_SHIFT (8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_DEFAULT_MASK (0xf << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_NOPATTERN (0 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING1 (1 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING2 (2 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_TRAINING3 (3 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_D102 (4 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_SBLERRRATE (5 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_PRBS7 (6 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_CSTM (7 << 8) +#define NV_SOR_DP_TPG_LANE1_PATTERN_HBR2_COMPLIANCE (8 << 8) +#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_SHIFT (6) +#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_DISABLE (0 << 6) +#define NV_SOR_DP_TPG_LANE0_CHANNELCODING_ENABLE (1 << 6) +#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_SHIFT (4) +#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_DEFAULT_MASK (0x3 << 4) +#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_DISABLE (0 << 4) +#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_ENABLE_GALIOS (1 << 4) +#define NV_SOR_DP_TPG_LANE0_SCRAMBLEREN_ENABLE_FIBONACCI (2 << 4) +#define NV_SOR_DP_TPG_LANE0_PATTERN_SHIFT (0) +#define NV_SOR_DP_TPG_LANE0_PATTERN_DEFAULT_MASK (0xf) +#define NV_SOR_DP_TPG_LANE0_PATTERN_NOPATTERN (0) +#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING1 (1) +#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING2 (2) +#define NV_SOR_DP_TPG_LANE0_PATTERN_TRAINING3 (3) +#define NV_SOR_DP_TPG_LANE0_PATTERN_D102 (4) +#define NV_SOR_DP_TPG_LANE0_PATTERN_SBLERRRATE (5) +#define NV_SOR_DP_TPG_LANE0_PATTERN_PRBS7 (6) +#define NV_SOR_DP_TPG_LANE0_PATTERN_CSTM (7) +#define NV_SOR_DP_TPG_LANE0_PATTERN_HBR2_COMPLIANCE (8) + +enum { + training_pattern_disabled = 0, + training_pattern_1 = 1, + training_pattern_2 = 2, + training_pattern_3 = 3, + training_pattern_none = 0xff +}; + +enum tegra_dc_sor_protocol { + SOR_DP, + SOR_LVDS, +}; + +#define SOR_LINK_SPEED_G1_62 6 +#define SOR_LINK_SPEED_G2_7 10 +#define SOR_LINK_SPEED_G5_4 20 +#define SOR_LINK_SPEED_LVDS 7 + +/* todo: combine this and the intel_dp struct into one struct. */ +struct tegra_dc_dp_link_config { + int is_valid; + + /* Supported configuration */ + u8 max_link_bw; + u8 max_lane_count; + int downspread; + int support_enhanced_framing; + u32 bits_per_pixel; + int alt_scramber_reset_cap; /* true for eDP */ + int only_enhanced_framing; /* enhanced_frame_en ignored */ + + /* Actual configuration */ + u8 link_bw; + u8 lane_count; + int enhanced_framing; + int scramble_ena; + + u32 activepolarity; + u32 active_count; + u32 tu_size; + u32 active_frac; + u32 watermark; + + s32 hblank_sym; + s32 vblank_sym; + + /* Training data */ + u32 drive_current; + u32 preemphasis; + u32 postcursor; + u8 aux_rd_interval; + u8 tps3_supported; +}; + +/* TODO: just pull these up into one struct? Need to see how this impacts + * having two channels. + */ +struct tegra_dc_sor_data { + struct tegra_dc *dc; + void *base; + void *pmc_base; + u8 portnum; /* 0 or 1 */ + struct tegra_dc_dp_link_config *link_cfg; + int power_is_up; +}; + +#define TEGRA_SOR_TIMEOUT_MS 1000 +#define TEGRA_SOR_ATTACH_TIMEOUT_MS 100000 + +#define CHECK_RET(x) \ + do { \ + ret = (x); \ + if (ret != 0) \ + return ret; \ + } while (0) + +void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor); +int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd); +void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena, + u8 training_pattern, const struct tegra_dc_dp_link_config *link_cfg); +void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw); +void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count); +void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor, + int power_up); +void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int); +void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw, + u8 *lane_count); +void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor); +void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor, + const struct tegra_dc_dp_link_config *link_cfg); +void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor); +void tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor); +void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor); +void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor); +void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask, + u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported); +#endif /*__TEGRA124_SOR_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/spi.h b/src/soc/nvidia/tegra124/include/soc/spi.h new file mode 100644 index 0000000000..ab046323b1 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/spi.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __NVIDIA_TEGRA124_SPI_H__ +#define __NVIDIA_TEGRA124_SPI_H__ + +#include +#include +#include + +struct tegra_spi_regs { + u32 command1; /* 0x000: SPI_COMMAND1 */ + u32 command2; /* 0x004: SPI_COMMAND2 */ + u32 timing1; /* 0x008: SPI_CS_TIM1 */ + u32 timing2; /* 0x00c: SPI_CS_TIM2 */ + u32 trans_status; /* 0x010: SPI_TRANS_STATUS */ + u32 fifo_status; /* 0x014: SPI_FIFO_STATUS */ + u32 tx_data; /* 0x018: SPI_TX_DATA */ + u32 rx_data; /* 0x01c: SPI_RX_DATA */ + u32 dma_ctl; /* 0x020: SPI_DMA_CTL */ + u32 dma_blk; /* 0x024: SPI_DMA_BLK */ + u32 rsvd[56]; /* 0x028-0x107: reserved */ + u32 tx_fifo; /* 0x108: SPI_FIFO1 */ + u32 rsvd2[31]; /* 0x10c-0x187 reserved */ + u32 rx_fifo; /* 0x188: SPI_FIFO2 */ + u32 spare_ctl; /* 0x18c: SPI_SPARE_CTRL */ +} __attribute__((packed)); +check_member(tegra_spi_regs, spare_ctl, 0x18c); + +enum spi_xfer_mode { + XFER_MODE_NONE = 0, + XFER_MODE_PIO, + XFER_MODE_DMA, +}; + +struct tegra_spi_channel { + struct tegra_spi_regs *regs; + + /* static configuration */ + struct spi_slave slave; + unsigned int req_sel; + + int dual_mode; /* for x2 transfers with bit interleaving */ + + /* context (used internally) */ + u8 *in_buf, *out_buf; + struct apb_dma_channel *dma_out, *dma_in; + enum spi_xfer_mode xfer_mode; +}; + +struct cbfs_media; +int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size); + +struct tegra_spi_channel *tegra_spi_init(unsigned int bus); + +#endif /* __NVIDIA_TEGRA124_SPI_H__ */ diff --git a/src/soc/nvidia/tegra124/include/soc/sysctr.h b/src/soc/nvidia/tegra124/include/soc/sysctr.h new file mode 100644 index 0000000000..1d7f53c3e1 --- /dev/null +++ b/src/soc/nvidia/tegra124/include/soc/sysctr.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA124_SYSCTR_H__ +#define __SOC_NVIDIA_TEGRA124_SYSCTR_H__ + +#include + +enum { + SYSCTR_CNTCR_EN = 1 << 0, + SYSCTR_CNTCR_HDBG = 1 << 1, + SYSCTR_CNTCR_FCREQ = 1 << 8 +}; + +struct sysctr_regs { + uint32_t cntcr; + uint32_t cntsr; + uint32_t cntcv0; + uint32_t cntcv1; + uint8_t _rsv0[0x10]; + uint32_t cntfid0; + uint32_t cntfid1; + uint8_t _rsv1[0xfa8]; + uint32_t counterid4; + uint32_t counterid5; + uint32_t counterid6; + uint32_t counterid7; + uint32_t counterid0; + uint32_t counterid1; + uint32_t counterid2; + uint32_t counterid3; + uint32_t counterid8; + uint32_t counterid9; + uint32_t counterid10; + uint32_t counterid11; +}; +check_member(sysctr_regs, counterid11, 0xffc); + +#endif /* __SOC_NVIDIA_TEGRA124_SYSCTR_H__ */ diff --git a/src/soc/nvidia/tegra124/lp0/Makefile b/src/soc/nvidia/tegra124/lp0/Makefile new file mode 100644 index 0000000000..57680c562f --- /dev/null +++ b/src/soc/nvidia/tegra124/lp0/Makefile @@ -0,0 +1,58 @@ +################################################################################ +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +CC = $(GCC_PREFIX)gcc +NM = $(GCC_PREFIX)nm +OBJCOPY = $(GCC_PREFIX)objcopy + +OPENSSL = openssl +DD = dd +CP = cp +MV = mv +RM = rm + +SIGKEY = 00000000000000000000000000000000 + +.PHONY: all +all: tegra_lp0_resume.fw + +tegra_lp0_resume.elf: tegra_lp0_resume.ld tegra_lp0_resume.c + $(CC) -marm -march=armv4t -mno-unaligned-access -nostdlib -static \ + -Os -fpie -Wl,--build-id=none -ggdb3 -T tegra_lp0_resume.ld \ + -o $@ $(filter %.c,$+) + +tegra_lp0_resume.fw: tegra_lp0_resume.elf + @# Get rid of any files we're about to create. + $(RM) -f $@.nosig $@.sig $@.tosig + @# Convert the ELF image into a binary image. + $(OBJCOPY) -O binary $< $@.nosig + @# Extract the part of the binary which needs to be signed. + $(DD) bs=1 skip=544 if=$@.nosig of=$@.tosig + @# Calculate a signature for that part. + $(OPENSSL) dgst -mac cmac -macopt cipher:aes-128-cbc \ + -macopt hexkey:$(SIGKEY) -md5 -binary \ + $@.tosig > $@.sig + @# Inject the signature into the binary image's header. + $(DD) conv=notrunc bs=1 seek=272 count=16 if=$@.sig of=$@.nosig + @# Copy the signed binary to the target file name. + $(MV) $@.nosig $@ + +clean: + $(RM) -f tegra_lp0_resume.fw tegra_lp0_resume.fw.sig + $(RM) -f tegra_lp0_resume.fw.tosig tegra_lp0_resume.elf diff --git a/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c new file mode 100644 index 0000000000..e5409af0fb --- /dev/null +++ b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c @@ -0,0 +1,673 @@ +/* + * Copyright 2014 Google Inc. + * Copyright 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/* Function unit addresses. */ +enum { + UP_TAG_BASE = 0X60000000, + TIMER_BASE = 0X60005000, + CLK_RST_BASE = 0X60006000, + FLOW_CTLR_BASE = 0X60007000, + TEGRA_EVP_BASE = 0x6000f000, + APB_MISC_BASE = 0x70000000, + PMC_CTLR_BASE = 0X7000e400, + MC_CTLR_BASE = 0X70019000, + SYSCTR_CTLR_BASE = 0X700f0000 +}; + + + +/* UP tag registers. */ +static uint32_t *up_tag_ptr = (void *)(UP_TAG_BASE + 0x0); +enum { + UP_TAG_AVP = 0xaaaaaaaa +}; + + +/* APB Misc JTAG Configuration Register */ +static uint32_t *misc_pp_config_ctl_ptr = (void *)(APB_MISC_BASE + 0x24); +enum { + PP_CONFIG_CTL_JTAG = 0x1 << 6 +}; + + +/* Timer registers. */ +static uint32_t *timer_us_ptr = (void *)(TIMER_BASE + 0x10); + + + +/* Clock and reset controller registers. */ +static uint32_t *clk_rst_rst_devices_l_ptr = (void *)(CLK_RST_BASE + 0x4); +enum { + SWR_TRIG_SYS_RST = 0x1 << 2 +}; + +static uint32_t *clk_rst_cclk_burst_policy_ptr = (void *)(CLK_RST_BASE + 0x20); +enum { + CCLK_PLLP_BURST_POLICY = 0x20004444 +}; + +static uint32_t *clk_rst_super_cclk_div_ptr = (void *)(CLK_RST_BASE + 0x24); +enum { + SUPER_CDIV_ENB = 0x1 << 31 +}; + +static uint32_t *clk_rst_osc_ctrl_ptr = (void *)(CLK_RST_BASE + 0x50); +enum { + OSC_XOE = 0x1 << 0, + OSC_XOFS_SHIFT = 4, + OSC_XOFS_MASK = 0x3f << OSC_XOFS_SHIFT, + OSC_FREQ_SHIFT = 28, + OSC_FREQ_MASK = 0xf << OSC_FREQ_SHIFT +}; +enum { + OSC_FREQ_13 = 0, + OSC_FREQ_16P8 = 1, + OSC_FREQ_19P2 = 4, + OSC_FREQ_38P4 = 5, + OSC_FREQ_12 = 8, + OSC_FREQ_48 = 9, + OSC_FREQ_26 = 12 +}; + +static uint32_t *clk_rst_pllu_base_ptr = (void *)(CLK_RST_BASE + 0xc0); +enum { + PLLU_DIVM_SHIFT = 0, + PLLU_DIVN_SHIFT = 8, + PLLU_OVERRIDE = 0x1 << 24, + PLLU_ENABLE = 0x1 << 30, + PLLU_BYPASS = 0x1 << 31 +}; + +static uint32_t *clk_rst_pllu_misc_ptr = (void *)(CLK_RST_BASE + 0xcc); +enum { + PLLU_LFCON_SHIFT = 4, + PLLU_CPCON_SHIFT = 8, + PLLU_LOCK_ENABLE = 22 +}; + +static uint32_t *clk_rst_pllx_base_ptr = (void *)(CLK_RST_BASE + 0xe0); +enum { + PLLX_ENABLE = 0x1 << 30 +}; + +static uint32_t *clk_rst_rst_dev_u_clr_ptr = (void *)(CLK_RST_BASE + 0x314); +enum { + SWR_CSITE_RST = 0x1 << 9 +}; + +static uint32_t *clk_rst_clk_enb_l_set_ptr = (void *)(CLK_RST_BASE + 0x320); +enum { + CLK_ENB_CPU = 0x1 << 0 +}; + +static uint32_t *clk_rst_clk_out_enb_u_set_ptr = + (void *)(CLK_RST_BASE + 0x330); +enum { + CLK_ENB_CSITE = 0x1 << 9 +}; + +static uint32_t *clk_rst_cpu_softrst_ctrl2_ptr = + (void *)(CLK_RST_BASE + 0x388); +enum { + CAR2PMC_CPU_ACK_WIDTH_SHIFT = 0, + CAR2PMC_CPU_ACK_WIDTH_MASK = 0xfff << CAR2PMC_CPU_ACK_WIDTH_SHIFT +}; + +static uint32_t *clk_rst_clk_src_mselect_ptr = + (void *)(CLK_RST_BASE + 0x3b4); +enum { + MSELECT_CLK_DIV_SHIFT = 0, + MSELECT_CLK_SRC_SHIFT = 29, + MSELECT_CLK_SRC_PLLP_OUT0 = 0x0 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC2_OUT0 = 0x1 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC_OUT0 = 0x2 << MSELECT_CLK_SRC_SHIFT, + MSELECT_CLK_SRC_PLLC3_OUT0 = 0x3 << MSELECT_CLK_SRC_SHIFT +}; + +static uint32_t *clk_rst_rst_dev_v_clr_ptr = (void *)(CLK_RST_BASE + 0x434); +enum { + SWR_MSELECT_RST = 0x1 << 3 +}; + +static uint32_t *clk_rst_clk_enb_v_set_ptr = (void *)(CLK_RST_BASE + 0x440); +enum { + CLK_ENB_CPUG = 0x1 << 0, + CLK_ENB_CPULP = 0x1 << 1, + CLK_ENB_MSELECT = 0x1 << 3 +}; + +static uint32_t *clk_rst_rst_cpulp_cmplx_clr_ptr = + (void *)(CLK_RST_BASE + 0x45c); +static uint32_t *clk_rst_rst_cpug_cmplx_clr_ptr = + (void *)(CLK_RST_BASE + 0x454); +enum { + CLR_CPURESET0 = 0x1 << 0, + CLR_CPURESET1 = 0x1 << 1, + CLR_CPURESET2 = 0x1 << 2, + CLR_CPURESET3 = 0x1 << 3, + CLR_DBGRESET0 = 0x1 << 12, + CLR_DBGRESET1 = 0x1 << 13, + CLR_DBGRESET2 = 0x1 << 14, + CLR_DBGRESET3 = 0x1 << 15, + CLR_CORERESET0 = 0x1 << 16, + CLR_CORERESET1 = 0x1 << 17, + CLR_CORERESET2 = 0x1 << 18, + CLR_CORERESET3 = 0x1 << 19, + CLR_CXRESET0 = 0x1 << 20, + CLR_CXRESET1 = 0x1 << 21, + CLR_CXRESET2 = 0x1 << 22, + CLR_CXRESET3 = 0x1 << 23, + CLR_NONCPURESET = 0x1 << 29 +}; + + + +/* Reset vector. */ + +static uint32_t *evp_cpu_reset_ptr = (void *)(TEGRA_EVP_BASE + 0x100); + + + +/* Flow controller registers. */ +static uint32_t *flow_ctlr_halt_cop_events_ptr = + (void *)(FLOW_CTLR_BASE + 0x4); +enum { + EVENT_MSEC = 0x1 << 24, + EVENT_JTAG = 0x1 << 28, + FLOW_MODE_SHIFT = 29, + FLOW_MODE_STOP = 2 << FLOW_MODE_SHIFT, +}; + +static uint32_t *flow_ctlr_cluster_control_ptr = + (void *)(FLOW_CTLR_BASE + 0x2c); +enum { + FLOW_CLUSTER_ACTIVE_LP = 0x1 << 0 +}; + +static uint32_t *flow_ctlr_ram_repair_ptr = + (void *)(FLOW_CTLR_BASE + 0x40); +static uint32_t *flow_ctlr_ram_repair_cluster1_ptr = + (void *)(FLOW_CTLR_BASE + 0x58); +enum { + RAM_REPAIR_REQ = 0x1 << 0, + RAM_REPAIR_STS = 0x1 << 1, +}; + + +/* Power management controller registers. */ +enum { + PARTID_CRAIL = 0, + PARTID_CELP = 12, + PARTID_CE0 = 14, + PARTID_C0NC = 15, + PARTID_C1NC = 16 +}; + +static uint32_t *pmc_ctlr_clamp_status_ptr = (void *)(PMC_CTLR_BASE + 0x2c); + +static uint32_t *pmc_ctlr_pwrgate_toggle_ptr = (void *)(PMC_CTLR_BASE + 0x30); +enum { + PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +static uint32_t *pmc_ctlr_pwrgate_status_ptr = (void *)(PMC_CTLR_BASE + 0x38); + +static uint32_t *pmc_ctlr_scratch4_ptr = (void *)(PMC_CTLR_BASE + 0x60); +enum { + PMC_SCRATCH4_LP = 0x1 << 31 +}; + +static uint32_t *pmc_ctlr_cpupwrgood_timer_ptr = + (void *)(PMC_CTLR_BASE + 0xc8); + +static uint32_t *pmc_ctlr_scratch41_ptr = (void *)(PMC_CTLR_BASE + 0x140); + +static uint32_t *pmc_ctlr_osc_edpd_over_ptr = (void *)(PMC_CTLR_BASE + 0x1a4); +enum { + PMC_XOFS_SHIFT = 1, + PMC_XOFS_MASK = 0x3f << PMC_XOFS_SHIFT +}; + + + +/* Memory controller registers. */ +static uint32_t *mc_video_protect_size_mb_ptr = (void *)(MC_CTLR_BASE + 0x64c); + +static uint32_t *mc_video_protect_reg_ctrl_ptr = + (void *)(MC_CTLR_BASE + 0x650); +enum { + VIDEO_PROTECT_WRITE_ACCESS_DISABLE = 0x1 << 0, + VIDEO_PROTECT_ALLOW_TZ_WRITE_ACCESS = 0x1 << 1 +}; + + + +/* System counter registers. */ +static uint32_t *sysctr_cntcr_ptr = (void *)(SYSCTR_CTLR_BASE + 0x0); +enum { + TSC_CNTCR_ENABLE = 0x1 << 0, + TSC_CNTCR_HDBG = 0x1 << 1 +}; + +static uint32_t *sysctr_cntfid0_ptr = (void *)(SYSCTR_CTLR_BASE + 0x20); + + + +/* Utility functions. */ + +static inline void __attribute__((always_inline)) + __attribute__((noreturn)) halt(void) +{ + for (;;); +} + +inline static uint32_t read32(const void *addr) +{ + return *(volatile uint32_t *)addr; +} + +inline static void write32(uint32_t val, void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +inline static void setbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) | bits, addr); +} + +inline static void clrbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) & ~bits, addr); +} + +static void __attribute__((noreturn)) reset(void) +{ + write32(SWR_TRIG_SYS_RST, clk_rst_rst_devices_l_ptr); + halt(); +} + +static void udelay(unsigned usecs) +{ + uint32_t start = read32(timer_us_ptr); + while (read32(timer_us_ptr) - start < usecs) + ; +} + + + +/* Accessors. */ + +static int wakeup_on_lp(void) +{ + return !!(read32(pmc_ctlr_scratch4_ptr) & PMC_SCRATCH4_LP); +} + +static uint32_t get_wakeup_vector(void) +{ + return read32(pmc_ctlr_scratch41_ptr); +} + +static unsigned get_osc_freq(void) +{ + return (read32(clk_rst_osc_ctrl_ptr) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + + +/* Jtag configuration. */ + +static void enable_jtag(void) +{ + write32(PP_CONFIG_CTL_JTAG, misc_pp_config_ctl_ptr); +} + +/* Clock configuration. */ + +static void config_oscillator(void) +{ + // Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy + // to OSC_CTRL.XOFS and set XOE. + uint32_t xofs = (read32(pmc_ctlr_osc_edpd_over_ptr) & + PMC_XOFS_MASK) >> PMC_XOFS_SHIFT; + + uint32_t osc_ctrl = read32(clk_rst_osc_ctrl_ptr); + osc_ctrl &= ~OSC_XOFS_MASK; + osc_ctrl |= (xofs << OSC_XOFS_SHIFT); + osc_ctrl |= OSC_XOE; + write32(osc_ctrl, clk_rst_osc_ctrl_ptr); +} + +static void config_pllu(void) +{ + // Figure out what parameters to use for PLLU. + uint32_t divm, divn, cpcon, lfcon; + switch (get_osc_freq()) { + case OSC_FREQ_12: + case OSC_FREQ_48: + divm = 0x0c; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + case OSC_FREQ_16P8: + divm = 0x07; + divn = 0x190; + cpcon = 0x05; + lfcon = 0x02; + break; + case OSC_FREQ_19P2: + case OSC_FREQ_38P4: + divm = 0x04; + divn = 0xc8; + cpcon = 0x03; + lfcon = 0x02; + break; + case OSC_FREQ_26: + divm = 0x1a; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + default: + // Map anything that's not recognized to 13MHz. + divm = 0x0d; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } + + // Configure PLLU. + uint32_t base = PLLU_BYPASS | PLLU_OVERRIDE | + (divn << PLLU_DIVN_SHIFT) | (divm << PLLU_DIVM_SHIFT); + write32(base, clk_rst_pllu_base_ptr); + uint32_t misc = (cpcon << PLLU_CPCON_SHIFT) | + (lfcon << PLLU_LFCON_SHIFT); + write32(misc, clk_rst_pllu_misc_ptr); + + // Enable PLLU. + base &= ~PLLU_BYPASS; + base |= PLLU_ENABLE; + write32(base, clk_rst_pllu_base_ptr); + misc |= PLLU_LOCK_ENABLE; + write32(misc, clk_rst_pllu_misc_ptr); +} + +static void config_tsc(void) +{ + // Tell the TSC the oscillator frequency. + switch (get_osc_freq()) { + case OSC_FREQ_12: + write32(12000000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_48: + write32(48000000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_16P8: + write32(16800000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_19P2: + write32(19200000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_38P4: + write32(38400000, sysctr_cntfid0_ptr); + break; + case OSC_FREQ_26: + write32(26000000, sysctr_cntfid0_ptr); + break; + default: + // Default to 13MHz. + write32(13000000, sysctr_cntfid0_ptr); + break; + } + + // Enable the TSC. + setbits32(TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG, sysctr_cntcr_ptr); +} + +static void enable_cpu_clocks(void) +{ + // Enable the CPU complex clock. + write32(CLK_ENB_CPU, clk_rst_clk_enb_l_set_ptr); + write32(CLK_ENB_CPUG | CLK_ENB_CPULP, clk_rst_clk_enb_v_set_ptr); +} + + + +/* Function unit configuration. */ + +static void config_core_sight(void) +{ + // Enable the CoreSight clock. + write32(CLK_ENB_CSITE, clk_rst_clk_out_enb_u_set_ptr); + + /* + * De-assert CoreSight reset. + * NOTE: We're leaving the CoreSight clock on the oscillator for + * now. It will be restored to its original clock source + * when the CPU-side restoration code runs. + */ + write32(SWR_CSITE_RST, clk_rst_rst_dev_u_clr_ptr); +} + +static void config_mselect(void) +{ + // Set MSELECT clock source to PLLP with 1:4 divider. + write32((6 << MSELECT_CLK_DIV_SHIFT) | MSELECT_CLK_SRC_PLLP_OUT0, + clk_rst_clk_src_mselect_ptr); + + // Enable clock to MSELECT. + write32(CLK_ENB_MSELECT, clk_rst_clk_enb_v_set_ptr); + + udelay(2); + + // Bring MSELECT out of reset. + write32(SWR_MSELECT_RST, clk_rst_rst_dev_v_clr_ptr); +} + + + +/* Resets. */ + +static void clear_cpu_resets(void) +{ + // Take the non-cpu of the G and LP clusters out of reset. + write32(CLR_NONCPURESET, clk_rst_rst_cpulp_cmplx_clr_ptr); + write32(CLR_NONCPURESET, clk_rst_rst_cpug_cmplx_clr_ptr); + + // Clear software controlled reset of the slow cluster. + write32(CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0, + clk_rst_rst_cpulp_cmplx_clr_ptr); + + // Clear software controlled reset of the fast cluster. + write32(CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 | + CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 | + CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 | + CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3, + clk_rst_rst_cpug_cmplx_clr_ptr); +} + + + +/* RAM repair */ + +void ram_repair(void) +{ + // Request Cluster0 RAM repair. + setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_ptr); + // Poll for Cluster0 RAM repair status. + while (!(read32(flow_ctlr_ram_repair_ptr) & RAM_REPAIR_STS)) + ; + + // Request Cluster1 RAM repair. + setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_cluster1_ptr); + // Poll for Cluster1 RAM repair status. + while (!(read32(flow_ctlr_ram_repair_cluster1_ptr) & RAM_REPAIR_STS)) + ; +} + + +/* Power. */ + +static void power_on_partition(unsigned id) +{ + uint32_t bit = 0x1 << id; + if (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) { + // Partition is not on. Turn it on. + write32(id | PWRGATE_TOGGLE_START, pmc_ctlr_pwrgate_toggle_ptr); + + // Wait until the partition is powerd on. + while (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) + ; + + // Wait until clamp is off. + while (read32(pmc_ctlr_clamp_status_ptr) & bit) + ; + } +} + +static void power_on_main_cpu(void) +{ + /* + * Reprogram PMC_CPUPWRGOOD_TIMER register: + * + * XXX This is a fragile assumption. XXX + * The kernel prepares PMC_CPUPWRGOOD_TIMER based on a 32768Hz clock. + * Note that PMC_CPUPWRGOOD_TIMER is running at pclk. + * + * We need to reprogram PMC_CPUPWRGOOD_TIMER based on the current pclk + * which is at 204Mhz (pclk = sclk = pllp_out2) after BootROM. Multiply + * PMC_CPUPWRGOOD_TIMER by 204M / 32K. + * + * Save the original PMC_CPUPWRGOOD_TIMER register which we need to + * restore after the CPU is powered up. + */ + uint32_t orig_timer = read32(pmc_ctlr_cpupwrgood_timer_ptr); + + write32(orig_timer * (204000000 / 32768), + pmc_ctlr_cpupwrgood_timer_ptr); + + if (wakeup_on_lp()) { + power_on_partition(PARTID_C1NC); + power_on_partition(PARTID_CELP); + } else { + power_on_partition(PARTID_CRAIL); + power_on_partition(PARTID_C0NC); + power_on_partition(PARTID_CE0); + } + + // Restore the original PMC_CPUPWRGOOD_TIMER. + write32(orig_timer, pmc_ctlr_cpupwrgood_timer_ptr); +} + + + +/* Entry point. */ + +void lp0_resume(void) +{ + // If not on the AVP, reset. + if (read32(up_tag_ptr) != UP_TAG_AVP) + reset(); + + // Enable JTAG + enable_jtag(); + + config_oscillator(); + + // Tell the flow controller which cluster to wake up. The default is + // the fast cluster. + if (wakeup_on_lp()) + setbits32(FLOW_CLUSTER_ACTIVE_LP, + flow_ctlr_cluster_control_ptr); + + // Program SUPER_CCLK_DIVIDER. + write32(SUPER_CDIV_ENB, clk_rst_super_cclk_div_ptr); + + config_core_sight(); + + config_pllu(); + + // Set the CPU reset vector. + write32(get_wakeup_vector(), evp_cpu_reset_ptr); + + // Select CPU complex clock source. + write32(CCLK_PLLP_BURST_POLICY, clk_rst_cclk_burst_policy_ptr); + + config_mselect(); + + // Disable PLLX since it isn't used as CPU clock source. + clrbits32(PLLX_ENABLE, clk_rst_pllx_base_ptr); + + // Set CAR2PMC_CPU_ACK_WIDTH to 408. + uint32_t ack_width = read32(clk_rst_cpu_softrst_ctrl2_ptr); + ack_width &= ~CAR2PMC_CPU_ACK_WIDTH_MASK; + ack_width |= 408 << CAR2PMC_CPU_ACK_WIDTH_SHIFT; + write32(ack_width, clk_rst_cpu_softrst_ctrl2_ptr); + + config_tsc(); + + // Disable VPR. + write32(0, mc_video_protect_size_mb_ptr); + write32(VIDEO_PROTECT_WRITE_ACCESS_DISABLE, + mc_video_protect_reg_ctrl_ptr); + + enable_cpu_clocks(); + + power_on_main_cpu(); + + // Perform ram repair after cpu is powered on. + ram_repair(); + + clear_cpu_resets(); + + // Halt the AVP. + while (1) + write32(FLOW_MODE_STOP | EVENT_JTAG, + flow_ctlr_halt_cop_events_ptr); +} + + + +/* Header. */ + +extern uint8_t blob_data; +extern uint8_t blob_data_size; +extern uint8_t blob_total_size; + +struct lp0_header { + uint32_t length_insecure; // Insecure total length. + uint32_t reserved[3]; + uint8_t rsa_modulus[256]; // RSA key modulus. + uint8_t aes_signature[16]; // AES signature. + uint8_t rsa_signature[256]; // RSA-PSS signature. + uint8_t random_aes_block[16]; // Random data, may be zero. + uint32_t length_secure; // Secure total length. + uint32_t destination; // Where to load the blob in iRAM. + uint32_t entry_point; // Entry point for the blob. + uint32_t code_length; // Length of just the data. +} __attribute__((packed)); + +struct lp0_header header __attribute__((section(".header"))) = +{ + .length_insecure = (uintptr_t)&blob_total_size, + .length_secure = (uintptr_t)&blob_total_size, + .destination = (uintptr_t)&blob_data, + .entry_point = (uintptr_t)&lp0_resume, + .code_length = (uintptr_t)&blob_data_size +}; diff --git a/src/arch/armv7/bootblock.lds b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld similarity index 59% rename from src/arch/armv7/bootblock.lds rename to src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld index 6f6040dacb..c4c508ff4c 100644 --- a/src/arch/armv7/bootblock.lds +++ b/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.ld @@ -1,8 +1,5 @@ /* - * This file is part of the coreboot project. - * - * Copyright (C) 2006 Advanced Micro Devices, Inc. - * Copyright (C) 2008-2010 coresystems GmbH + * Copyright 2014 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,25 +19,49 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) -TARGET(binary) +PHDRS +{ + to_load PT_LOAD; +} + +ENTRY(lp0_resume) SECTIONS { - ROMLOC = CONFIG_BOOTBLOCK_BASE - (CONFIG_BL1_SIZE_KB * 1024); + . = 0x40020000 - 0x240; - /* This section might be better named .setup */ - .rom ROMLOC : { - _rom = .; - *(.bl1); - *(.start); - *(.id); + /* + * The lp0 blob header is built as a static data structure and put + * in the .header section. + */ + .header_start = .; + .header . : { + *(.header); + } : to_load = 0xff + .header_end = .; + + . = 0x40020000; + + /* The actual lp0 blob code. */ + .data_start = .; + .data . : { *(.text); *(.text.*); - *(.rom.text); - *(.rom.data); - *(.rom.data.*); + *(.rodata); *(.rodata.*); - _erom = .; - } = 0xff + *(.data); + *(.data.*); + *(.bss); + *(.bss.*); + *(.sbss); + *(.sbss.*); + . = ALIGN(16); + } + .data_end = .; + + /* Some values we need in the header. */ + blob_data = .data_start; + blob_data_size = .data_end - .data_start; + blob_total_size = .data_end - .header_start; /DISCARD/ : { *(.comment) diff --git a/src/soc/nvidia/tegra124/maincpu.S b/src/soc/nvidia/tegra124/maincpu.S new file mode 100644 index 0000000000..11367480ad --- /dev/null +++ b/src/soc/nvidia/tegra124/maincpu.S @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +.arm +ENTRY(maincpu_setup) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr_cxf, #0xdf + + ldr sp, maincpu_stack_pointer + eor lr, lr + ldr r0, maincpu_entry_point + bx r0 +ENDPROC(maincpu_setup) + + .align 2 + + .global maincpu_stack_pointer +maincpu_stack_pointer: + .word 0 + + .global maincpu_entry_point +maincpu_entry_point: + .word 0 diff --git a/src/soc/nvidia/tegra124/monotonic_timer.c b/src/soc/nvidia/tegra124/monotonic_timer.c new file mode 100644 index 0000000000..7967b83bef --- /dev/null +++ b/src/soc/nvidia/tegra124/monotonic_timer.c @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void timer_monotonic_get(struct mono_time *mt) +{ + mono_time_set_usecs(mt, read32((void *)TEGRA_TMRUS_BASE)); +} diff --git a/src/soc/nvidia/tegra124/power.c b/src/soc/nvidia/tegra124/power.c new file mode 100644 index 0000000000..825b27bda9 --- /dev/null +++ b/src/soc/nvidia/tegra124/power.c @@ -0,0 +1,109 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE; +static struct flow_ctlr * const flow = (void *)TEGRA_FLOW_BASE; + +static int partition_powered(int id) +{ + return read32(&pmc->pwrgate_status) & (0x1 << id); +} + +static int partition_clamp_on(int id) +{ + return read32(&pmc->clamp_status) & (0x1 << id); +} + +static void power_ungate_partition(uint32_t id) +{ + printk(BIOS_INFO, "Ungating power partition %d.\n", id); + + if (!partition_powered(id)) { + uint32_t pwrgate_toggle = read32(&pmc->pwrgate_toggle); + pwrgate_toggle &= ~(PMC_PWRGATE_TOGGLE_PARTID_MASK); + pwrgate_toggle |= (id << PMC_PWRGATE_TOGGLE_PARTID_SHIFT); + pwrgate_toggle |= PMC_PWRGATE_TOGGLE_START; + write32(pwrgate_toggle, &pmc->pwrgate_toggle); + + // Wait for the request to be accepted. + while (read32(&pmc->pwrgate_toggle) & PMC_PWRGATE_TOGGLE_START) + ; + printk(BIOS_DEBUG, "Power gate toggle request accepted.\n"); + + // Wait for the partition to be powered. + while (!partition_powered(id)) + ; + + // Wait for clamp off. + while (partition_clamp_on(id)) + ; + } + + printk(BIOS_INFO, "Ungated power partition %d.\n", id); +} + +void power_enable_and_ungate_cpu(void) +{ + /* + * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (150MHz), + * set it for 5ms as per SysEng (5ms * PCLK_KHZ * 1000 / 1s). + */ + write32((TEGRA_PCLK_KHZ * 5), &pmc->cpupwrgood_timer); + + uint32_t cntrl = read32(&pmc->cntrl); + cntrl &= ~PMC_CNTRL_CPUPWRREQ_POLARITY; + cntrl |= PMC_CNTRL_CPUPWRREQ_OE; + write32(cntrl, &pmc->cntrl); + + power_ungate_partition(POWER_PARTID_CRAIL); + + // Ungate power to the non-core parts of the fast cluster. + power_ungate_partition(POWER_PARTID_C0NC); + + // Ungate power to CPU0 in the fast cluster. + power_ungate_partition(POWER_PARTID_CE0); +} + +int power_reset_status(void) +{ + return read32(&pmc->rst_status) & 0x7; +} + +void ram_repair(void) +{ + // Request RAM repair for cluster 0 + setbits_le32(&flow->ram_repair, RAM_REPAIR_REQ); + // Poll for completion + while (!(read32(&flow->ram_repair) & RAM_REPAIR_STS)) + ; + // Request RAM repair for cluster 1 + setbits_le32(&flow->ram_repair_cluster1, RAM_REPAIR_REQ); + // Poll for completion + while (!(read32(&flow->ram_repair_cluster1) & RAM_REPAIR_STS)) + ; +} diff --git a/src/soc/nvidia/tegra124/sdram.c b/src/soc/nvidia/tegra124/sdram.c new file mode 100644 index 0000000000..d094c18594 --- /dev/null +++ b/src/soc/nvidia/tegra124/sdram.c @@ -0,0 +1,648 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void sdram_patch(uintptr_t addr, uint32_t value) +{ + if (addr) + writel(value, (uint32_t*)addr); +} + +static void writebits(uint32_t value, uint32_t *addr, uint32_t mask) +{ + clrsetbits_le32(addr, mask, (value & mask)); +} + +/* PMC must be configured before clock-enable and de-reset of MC/EMC. */ +static void sdram_configure_pmc(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* VDDP Select */ + writel(param->PmcVddpSel, ®s->vddp_sel); + udelay(param->PmcVddpSelWait); + + /* Set DDR pad voltage */ + writebits(param->PmcDdrPwr, ®s->ddr_pwr, PMC_DDR_PWR_VAL_MASK); + + /* Set package and DPD pad control */ + writebits(param->PmcDdrCfg, ®s->ddr_cfg, + (PMC_DDR_CFG_PKG_MASK | PMC_DDR_CFG_IF_MASK | + PMC_DDR_CFG_XM0_RESET_TRI_MASK | + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK)); + + /* Turn on MEM IO Power */ + writebits(param->PmcNoIoPower, ®s->no_iopower, + (PMC_NO_IOPOWER_MEM_MASK | PMC_NO_IOPOWER_MEM_COMP_MASK)); + + writel(param->PmcRegShort, ®s->reg_short); +} + +static void sdram_start_clocks(const struct sdram_params *param) +{ + u32 is_same_freq = (param->McEmemArbMisc0 & + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK) ? 1 : 0; + + clock_sdram(param->PllMInputDivider, param->PllMFeedbackDivider, + param->PllMSelectDiv2, param->PllMSetupControl, + param->PllMPDLshiftPh45, param->PllMPDLshiftPh90, + param->PllMPDLshiftPh135, param->PllMKVCO, + param->PllMKCP, param->PllMStableTime, + param->EmcClockSource, is_same_freq); +} + +static void sdram_deassert_clock_enable_signal(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK); + udelay(param->PmcPorDpdCtrlWait); +} + +static void sdram_deassert_sel_dpd(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + (PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK | + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK)); + /* + * Note NVIDIA recommended to always do 10us delay here and ignore + * BCT.PmcPorDpdCtrlWait. + * */ + udelay(10); +} + +static void sdram_set_swizzle(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + writel(param->EmcSwizzleRank0ByteCfg, ®s->swizzle_rank0_byte_cfg); + writel(param->EmcSwizzleRank0Byte0, ®s->swizzle_rank0_byte0); + writel(param->EmcSwizzleRank0Byte1, ®s->swizzle_rank0_byte1); + writel(param->EmcSwizzleRank0Byte2, ®s->swizzle_rank0_byte2); + writel(param->EmcSwizzleRank0Byte3, ®s->swizzle_rank0_byte3); + writel(param->EmcSwizzleRank1ByteCfg, ®s->swizzle_rank1_byte_cfg); + writel(param->EmcSwizzleRank1Byte0, ®s->swizzle_rank1_byte0); + writel(param->EmcSwizzleRank1Byte1, ®s->swizzle_rank1_byte1); + writel(param->EmcSwizzleRank1Byte2, ®s->swizzle_rank1_byte2); + writel(param->EmcSwizzleRank1Byte3, ®s->swizzle_rank1_byte3); +} + +static void sdram_set_pad_controls(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program the pad controls */ + writel(param->EmcXm2CmdPadCtrl, ®s->xm2cmdpadctrl); + writel(param->EmcXm2CmdPadCtrl2, ®s->xm2cmdpadctrl2); + writel(param->EmcXm2CmdPadCtrl3, ®s->xm2cmdpadctrl3); + writel(param->EmcXm2CmdPadCtrl4, ®s->xm2cmdpadctrl4); + writel(param->EmcXm2CmdPadCtrl5, ®s->xm2cmdpadctrl5); + + writel(param->EmcXm2DqsPadCtrl, ®s->xm2dqspadctrl); + writel(param->EmcXm2DqsPadCtrl2, ®s->xm2dqspadctrl2); + writel(param->EmcXm2DqsPadCtrl3, ®s->xm2dqspadctrl3); + writel(param->EmcXm2DqsPadCtrl4, ®s->xm2dqspadctrl4); + writel(param->EmcXm2DqsPadCtrl5, ®s->xm2dqspadctrl5); + writel(param->EmcXm2DqsPadCtrl6, ®s->xm2dqspadctrl6); + + writel(param->EmcXm2DqPadCtrl, ®s->xm2dqpadctrl); + writel(param->EmcXm2DqPadCtrl2, ®s->xm2dqpadctrl2); + writel(param->EmcXm2DqPadCtrl3, ®s->xm2dqpadctrl3); + + writel(param->EmcXm2ClkPadCtrl, ®s->xm2clkpadctrl); + writel(param->EmcXm2ClkPadCtrl2, ®s->xm2clkpadctrl2); + + writel(param->EmcXm2CompPadCtrl, ®s->xm2comppadctrl); + + writel(param->EmcXm2VttGenPadCtrl, ®s->xm2vttgenpadctrl); + writel(param->EmcXm2VttGenPadCtrl2, ®s->xm2vttgenpadctrl2); + writel(param->EmcXm2VttGenPadCtrl3, ®s->xm2vttgenpadctrl3); + + writel(param->EmcCttTermCtrl, ®s->ctt_term_ctrl); +} + +static void sdram_trigger_emc_timing_update(struct tegra_emc_regs *regs) +{ + writel(EMC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); +} + +static void sdram_init_mc(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Initialize MC VPR settings */ + writel(param->McDisplaySnapRing, ®s->display_snap_ring); + writel(param->McVideoProtectBom, ®s->video_protect_bom); + writel(param->McVideoProtectBomAdrHi, ®s->video_protect_bom_adr_hi); + writel(param->McVideoProtectSizeMb, ®s->video_protect_size_mb); + writel(param->McVideoProtectVprOverride, + ®s->video_protect_vpr_override); + writel(param->McVideoProtectVprOverride1, + ®s->video_protect_vpr_override1); + writel(param->McVideoProtectGpuOverride0, + ®s->video_protect_gpu_override_0); + writel(param->McVideoProtectGpuOverride1, + ®s->video_protect_gpu_override_1); + + /* Program SDRAM geometry paarameters */ + writel(param->McEmemAdrCfg, ®s->emem_adr_cfg); + writel(param->McEmemAdrCfgDev0, ®s->emem_adr_cfg_dev0); + writel(param->McEmemAdrCfgDev1, ®s->emem_adr_cfg_dev1); + + /* Program bank swizzling */ + writel(param->McEmemAdrCfgBankMask0, ®s->emem_bank_swizzle_cfg0); + writel(param->McEmemAdrCfgBankMask1, ®s->emem_bank_swizzle_cfg1); + writel(param->McEmemAdrCfgBankMask2, ®s->emem_bank_swizzle_cfg2); + writel(param->McEmemAdrCfgBankSwizzle3, ®s->emem_bank_swizzle_cfg3); + + /* Program external memory aperature (base and size) */ + writel(param->McEmemCfg, ®s->emem_cfg); + + /* Program SEC carveout (base and size) */ + writel(param->McSecCarveoutBom, ®s->sec_carveout_bom); + writel(param->McSecCarveoutAdrHi, ®s->sec_carveout_adr_hi); + writel(param->McSecCarveoutSizeMb, ®s->sec_carveout_size_mb); + + /* Program MTS carveout (base and size) */ + writel(param->McMtsCarveoutBom, ®s->mts_carveout_bom); + writel(param->McMtsCarveoutAdrHi, ®s->mts_carveout_adr_hi); + writel(param->McMtsCarveoutSizeMb, ®s->mts_carveout_size_mb); + + /* Program the memory arbiter */ + writel(param->McEmemArbCfg, ®s->emem_arb_cfg); + writel(param->McEmemArbOutstandingReq, ®s->emem_arb_outstanding_req); + writel(param->McEmemArbTimingRcd, ®s->emem_arb_timing_rcd); + writel(param->McEmemArbTimingRp, ®s->emem_arb_timing_rp); + writel(param->McEmemArbTimingRc, ®s->emem_arb_timing_rc); + writel(param->McEmemArbTimingRas, ®s->emem_arb_timing_ras); + writel(param->McEmemArbTimingFaw, ®s->emem_arb_timing_faw); + writel(param->McEmemArbTimingRrd, ®s->emem_arb_timing_rrd); + writel(param->McEmemArbTimingRap2Pre, ®s->emem_arb_timing_rap2pre); + writel(param->McEmemArbTimingWap2Pre, ®s->emem_arb_timing_wap2pre); + writel(param->McEmemArbTimingR2R, ®s->emem_arb_timing_r2r); + writel(param->McEmemArbTimingW2W, ®s->emem_arb_timing_w2w); + writel(param->McEmemArbTimingR2W, ®s->emem_arb_timing_r2w); + writel(param->McEmemArbTimingW2R, ®s->emem_arb_timing_w2r); + writel(param->McEmemArbDaTurns, ®s->emem_arb_da_turns); + writel(param->McEmemArbDaCovers, ®s->emem_arb_da_covers); + writel(param->McEmemArbMisc0, ®s->emem_arb_misc0); + writel(param->McEmemArbMisc1, ®s->emem_arb_misc1); + writel(param->McEmemArbRing1Throttle, ®s->emem_arb_ring1_throttle); + writel(param->McEmemArbOverride, ®s->emem_arb_override); + writel(param->McEmemArbOverride1, ®s->emem_arb_override_1); + writel(param->McEmemArbRsv, ®s->emem_arb_rsv); + + /* Program extra snap levels for display client */ + writel(param->McDisExtraSnapLevels, ®s->dis_extra_snap_levels); + + /* Trigger MC timing update */ + writel(MC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); + + /* Program second-level clock enable overrides */ + writel(param->McClkenOverride, ®s->clken_override); + + /* Program statistics gathering */ + writel(param->McStatControl, ®s->stat_control); +} + +static void sdram_init_emc(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program SDRAM geometry parameters */ + writel(param->EmcAdrCfg, ®s->adr_cfg); + + /* Program second-level clock enable overrides */ + writel(param->EmcClkenOverride, ®s->clken_override); + + /* Program EMC pad auto calibration */ + writel(param->EmcAutoCalInterval, ®s->auto_cal_interval); + writel(param->EmcAutoCalConfig2, ®s->auto_cal_config2); + writel(param->EmcAutoCalConfig3, ®s->auto_cal_config3); + writel(param->EmcAutoCalConfig, ®s->auto_cal_config); + udelay(param->EmcAutoCalWait); +} + +static void sdram_set_emc_timing(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program EMC timing configuration */ + writel(param->EmcCfg2, ®s->cfg_2); + writel(param->EmcCfgPipe, ®s->cfg_pipe); + writel(param->EmcDbg, ®s->dbg); + writel(param->EmcCmdQ, ®s->cmdq); + writel(param->EmcMc2EmcQ, ®s->mc2emcq); + writel(param->EmcMrsWaitCnt, ®s->mrs_wait_cnt); + writel(param->EmcMrsWaitCnt2, ®s->mrs_wait_cnt2); + writel(param->EmcFbioCfg5, ®s->fbio_cfg5); + writel(param->EmcRc, ®s->rc); + writel(param->EmcRfc, ®s->rfc); + writel(param->EmcRfcSlr, ®s->rfc_slr); + writel(param->EmcRas, ®s->ras); + writel(param->EmcRp, ®s->rp); + writel(param->EmcR2r, ®s->r2r); + writel(param->EmcW2w, ®s->w2w); + writel(param->EmcR2w, ®s->r2w); + writel(param->EmcW2r, ®s->w2r); + writel(param->EmcR2p, ®s->r2p); + writel(param->EmcW2p, ®s->w2p); + writel(param->EmcRdRcd, ®s->rd_rcd); + writel(param->EmcWrRcd, ®s->wr_rcd); + writel(param->EmcRrd, ®s->rrd); + writel(param->EmcRext, ®s->rext); + writel(param->EmcWext, ®s->wext); + writel(param->EmcWdv, ®s->wdv); + writel(param->EmcWdvMask, ®s->wdv_mask); + writel(param->EmcQUse, ®s->quse); + writel(param->EmcQuseWidth, ®s->quse_width); + writel(param->EmcIbdly, ®s->ibdly); + writel(param->EmcEInput, ®s->einput); + writel(param->EmcEInputDuration, ®s->einput_duration); + writel(param->EmcPutermExtra, ®s->puterm_extra); + writel(param->EmcPutermWidth, ®s->puterm_width); + writel(param->EmcPutermAdj, ®s->puterm_adj); + writel(param->EmcCdbCntl1, ®s->cdb_cntl_1); + writel(param->EmcCdbCntl2, ®s->cdb_cntl_2); + writel(param->EmcCdbCntl3, ®s->cdb_cntl_3); + writel(param->EmcQRst, ®s->qrst); + writel(param->EmcQSafe, ®s->qsafe); + writel(param->EmcRdv, ®s->rdv); + writel(param->EmcRdvMask, ®s->rdv_mask); + writel(param->EmcQpop, ®s->qpop); + writel(param->EmcCtt, ®s->ctt); + writel(param->EmcCttDuration, ®s->ctt_duration); + writel(param->EmcRefresh, ®s->refresh); + writel(param->EmcBurstRefreshNum, ®s->burst_refresh_num); + writel(param->EmcPreRefreshReqCnt, ®s->pre_refresh_req_cnt); + writel(param->EmcPdEx2Wr, ®s->pdex2wr); + writel(param->EmcPdEx2Rd, ®s->pdex2rd); + writel(param->EmcPChg2Pden, ®s->pchg2pden); + writel(param->EmcAct2Pden, ®s->act2pden); + writel(param->EmcAr2Pden, ®s->ar2pden); + writel(param->EmcRw2Pden, ®s->rw2pden); + writel(param->EmcTxsr, ®s->txsr); + writel(param->EmcTxsrDll, ®s->txsrdll); + writel(param->EmcTcke, ®s->tcke); + writel(param->EmcTckesr, ®s->tckesr); + writel(param->EmcTpd, ®s->tpd); + writel(param->EmcTfaw, ®s->tfaw); + writel(param->EmcTrpab, ®s->trpab); + writel(param->EmcTClkStable, ®s->tclkstable); + writel(param->EmcTClkStop, ®s->tclkstop); + writel(param->EmcTRefBw, ®s->trefbw); + writel(param->EmcOdtWrite, ®s->odt_write); + writel(param->EmcOdtRead, ®s->odt_read); + writel(param->EmcFbioCfg6, ®s->fbio_cfg6); + writel(param->EmcCfgDigDll, ®s->cfg_dig_dll); + writel(param->EmcCfgDigDllPeriod, ®s->cfg_dig_dll_period); + + /* Don't write bit 1: addr swizzle lock bit. Written at end of sequence. */ + writel(param->EmcFbioSpare & 0xfffffffd, ®s->fbio_spare); + + writel(param->EmcCfgRsv, ®s->cfg_rsv); + writel(param->EmcDllXformDqs0, ®s->dll_xform_dqs0); + writel(param->EmcDllXformDqs1, ®s->dll_xform_dqs1); + writel(param->EmcDllXformDqs2, ®s->dll_xform_dqs2); + writel(param->EmcDllXformDqs3, ®s->dll_xform_dqs3); + writel(param->EmcDllXformDqs4, ®s->dll_xform_dqs4); + writel(param->EmcDllXformDqs5, ®s->dll_xform_dqs5); + writel(param->EmcDllXformDqs6, ®s->dll_xform_dqs6); + writel(param->EmcDllXformDqs7, ®s->dll_xform_dqs7); + writel(param->EmcDllXformDqs8, ®s->dll_xform_dqs8); + writel(param->EmcDllXformDqs9, ®s->dll_xform_dqs9); + writel(param->EmcDllXformDqs10, ®s->dll_xform_dqs10); + writel(param->EmcDllXformDqs11, ®s->dll_xform_dqs11); + writel(param->EmcDllXformDqs12, ®s->dll_xform_dqs12); + writel(param->EmcDllXformDqs13, ®s->dll_xform_dqs13); + writel(param->EmcDllXformDqs14, ®s->dll_xform_dqs14); + writel(param->EmcDllXformDqs15, ®s->dll_xform_dqs15); + writel(param->EmcDllXformQUse0, ®s->dll_xform_quse0); + writel(param->EmcDllXformQUse1, ®s->dll_xform_quse1); + writel(param->EmcDllXformQUse2, ®s->dll_xform_quse2); + writel(param->EmcDllXformQUse3, ®s->dll_xform_quse3); + writel(param->EmcDllXformQUse4, ®s->dll_xform_quse4); + writel(param->EmcDllXformQUse5, ®s->dll_xform_quse5); + writel(param->EmcDllXformQUse6, ®s->dll_xform_quse6); + writel(param->EmcDllXformQUse7, ®s->dll_xform_quse7); + writel(param->EmcDllXformQUse8, ®s->dll_xform_quse8); + writel(param->EmcDllXformQUse9, ®s->dll_xform_quse9); + writel(param->EmcDllXformQUse10, ®s->dll_xform_quse10); + writel(param->EmcDllXformQUse11, ®s->dll_xform_quse11); + writel(param->EmcDllXformQUse12, ®s->dll_xform_quse12); + writel(param->EmcDllXformQUse13, ®s->dll_xform_quse13); + writel(param->EmcDllXformQUse14, ®s->dll_xform_quse14); + writel(param->EmcDllXformQUse15, ®s->dll_xform_quse15); + writel(param->EmcDllXformDq0, ®s->dll_xform_dq0); + writel(param->EmcDllXformDq1, ®s->dll_xform_dq1); + writel(param->EmcDllXformDq2, ®s->dll_xform_dq2); + writel(param->EmcDllXformDq3, ®s->dll_xform_dq3); + writel(param->EmcDllXformDq4, ®s->dll_xform_dq4); + writel(param->EmcDllXformDq5, ®s->dll_xform_dq5); + writel(param->EmcDllXformDq6, ®s->dll_xform_dq6); + writel(param->EmcDllXformDq7, ®s->dll_xform_dq7); + writel(param->EmcDllXformAddr0, ®s->dll_xform_addr0); + writel(param->EmcDllXformAddr1, ®s->dll_xform_addr1); + writel(param->EmcDllXformAddr2, ®s->dll_xform_addr2); + writel(param->EmcDllXformAddr3, ®s->dll_xform_addr3); + writel(param->EmcDllXformAddr4, ®s->dll_xform_addr4); + writel(param->EmcDllXformAddr5, ®s->dll_xform_addr5); + writel(param->EmcAcpdControl, ®s->acpd_control); + writel(param->EmcDsrVttgenDrv, ®s->dsr_vttgen_drv); + writel(param->EmcTxdsrvttgen, ®s->txdsrvttgen); + writel(param->EmcBgbiasCtl0, ®s->bgbias_ctl0); + + /* + * Set pipe bypass enable bits before sending any DRAM commands. + * Note other bits in EMC_CFG must be set AFTER REFCTRL is configured. + */ + writebits(param->EmcCfg, ®s->cfg, + (EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK)); +} + +static void sdram_patch_bootrom(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + if (param->BootRomPatchControl & BOOT_ROM_PATCH_CONTROL_ENABLE_MASK) { + uintptr_t addr = ((param->BootRomPatchControl & + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK) >> + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT); + addr = BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS + (addr << 2); + writel(param->BootRomPatchData, (uint32_t *)addr); + writel(1, ®s->timing_control); + } +} + +static void sdram_set_dpd3(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* Program DPD request */ + writel(param->PmcIoDpd3Req, ®s->io_dpd3_req); + udelay(param->PmcIoDpd3ReqWait); +} + +static void sdram_set_dli_trims(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program DLI trims */ + writel(param->EmcDliTrimTxDqs0, ®s->dli_trim_txdqs0); + writel(param->EmcDliTrimTxDqs1, ®s->dli_trim_txdqs1); + writel(param->EmcDliTrimTxDqs2, ®s->dli_trim_txdqs2); + writel(param->EmcDliTrimTxDqs3, ®s->dli_trim_txdqs3); + writel(param->EmcDliTrimTxDqs4, ®s->dli_trim_txdqs4); + writel(param->EmcDliTrimTxDqs5, ®s->dli_trim_txdqs5); + writel(param->EmcDliTrimTxDqs6, ®s->dli_trim_txdqs6); + writel(param->EmcDliTrimTxDqs7, ®s->dli_trim_txdqs7); + writel(param->EmcDliTrimTxDqs8, ®s->dli_trim_txdqs8); + writel(param->EmcDliTrimTxDqs9, ®s->dli_trim_txdqs9); + writel(param->EmcDliTrimTxDqs10, ®s->dli_trim_txdqs10); + writel(param->EmcDliTrimTxDqs11, ®s->dli_trim_txdqs11); + writel(param->EmcDliTrimTxDqs12, ®s->dli_trim_txdqs12); + writel(param->EmcDliTrimTxDqs13, ®s->dli_trim_txdqs13); + writel(param->EmcDliTrimTxDqs14, ®s->dli_trim_txdqs14); + writel(param->EmcDliTrimTxDqs15, ®s->dli_trim_txdqs15); + + writel(param->EmcCaTrainingTimingCntl1, + ®s->ca_training_timing_cntl1); + writel(param->EmcCaTrainingTimingCntl2, + ®s->ca_training_timing_cntl2); + + sdram_trigger_emc_timing_update(regs); + udelay(param->EmcTimingControlWait); +} + +static void sdram_set_clock_enable_signal(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + volatile uint32_t dummy = 0; + clrbits_le32(®s->pin, (EMC_PIN_RESET_MASK | EMC_PIN_DQM_MASK | + EMC_PIN_CKE_MASK)); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(200 + param->EmcPinExtraWait); + + /* Deassert reset */ + setbits_le32(®s->pin, EMC_PIN_RESET_INACTIVE); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(500 + param->EmcPinExtraWait); + + /* Enable clock enable signal */ + setbits_le32(®s->pin, EMC_PIN_CKE_NORMAL); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(param->EmcPinProgramWait); + + if (!dummy) { + die("Failed to program EMC pin."); + } + + /* Send NOP (trigger) */ + writebits(((1 << EMC_NOP_NOP_CMD_SHIFT) | + (param->EmcDevSelect << EMC_NOP_NOP_DEV_SELECTN_SHIFT)), + ®s->nop, + EMC_NOP_NOP_CMD_MASK | EMC_NOP_NOP_DEV_SELECTN_MASK); + + /* Write mode registers */ + writel(param->EmcEmrs2, ®s->emrs2); + writel(param->EmcEmrs3, ®s->emrs3); + writel(param->EmcEmrs, ®s->emrs); + writel(param->EmcMrs, ®s->mrs); + + if (param->EmcExtraModeRegWriteEnable) { + writel(param->EmcMrwExtra, ®s->mrs); + } +} + +static void sdram_init_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + if ((param->EmcZcalWarmColdBootEnables & + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK) == 1) { + /* Need to initialize ZCAL on coldboot. */ + writel(param->EmcZcalInitDev0, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + + if ((param->EmcDevSelect & 2) == 0) { + writel(param->EmcZcalInitDev1, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + } + } else { + udelay(param->EmcZcalInitWait); + } +} + +static void sdram_set_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Start periodic ZQ calibration */ + writel(param->EmcZcalInterval, ®s->zcal_interval); + writel(param->EmcZcalWaitCnt, ®s->zcal_wait_cnt); + writel(param->EmcZcalMrwCmd, ®s->zcal_mrw_cmd); +} + +static void sdram_set_refresh(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Insert burst refresh */ + if (param->EmcExtraRefreshNum > 0) { + uint32_t refresh_num = (1 << param->EmcExtraRefreshNum) - 1; + writebits((EMC_REF_CMD_REFRESH | EMC_REF_NORMAL_ENABLED | + (refresh_num << EMC_REF_NUM_SHIFT) | + (param->EmcDevSelect << EMC_REF_DEV_SELECTN_SHIFT)), + ®s->ref, (EMC_REF_CMD_MASK | EMC_REF_NORMAL_MASK | + EMC_REF_NUM_MASK | + EMC_REF_DEV_SELECTN_MASK)); + } + + /* Enable refresh */ + writel((param->EmcDevSelect | EMC_REFCTRL_REF_VALID_ENABLED), + ®s->refctrl); + + writel(param->EmcDynSelfRefControl, ®s->dyn_self_ref_control); + writel(param->EmcCfg, ®s->cfg); + writel(param->EmcSelDpdCtrl, ®s->sel_dpd_ctrl); + + /* Write addr swizzle lock bit */ + writel(param->EmcFbioSpare, ®s->fbio_spare); + + /* Re-trigger timing to latch power saving functions */ + sdram_trigger_emc_timing_update(regs); +} + +static void sdram_enable_arbiter(const struct sdram_params *param) +{ + /* TODO(hungte) Move values here to standalone header file. */ + uint32_t *AHB_ARBITRATION_XBAR_CTRL = (uint32_t*)(0x6000c000 + 0xe0); + setbits_le32(AHB_ARBITRATION_XBAR_CTRL, + param->AhbArbitrationXbarCtrlMemInitDone << 16); +} + +static void sdram_lock_carveouts(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Lock carveouts, and emem_cfg registers */ + writel(param->McVideoProtectWriteAccess, ®s->video_protect_reg_ctrl); + writel(MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED, + ®s->emem_cfg_access_ctrl); + writel(param->McSecCarveoutProtectWriteAccess, + ®s->sec_carveout_reg_ctrl); + writel(param->McMtsCarveoutRegCtrl, ®s->mts_carveout_reg_ctrl); +} + +void sdram_init(const struct sdram_params *param) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + struct tegra_mc_regs *mc = (struct tegra_mc_regs*)TEGRA_MC_BASE; + struct tegra_emc_regs *emc = (struct tegra_emc_regs*)TEGRA_EMC_BASE; + + printk(BIOS_DEBUG, "Initializing SDRAM of type %d with %dKHz\n", + param->MemoryType, clock_get_pll_input_khz() * + param->PllMFeedbackDivider / param->PllMInputDivider / + (1 + param->PllMSelectDiv2)); + if (param->MemoryType != NvBootMemoryType_Ddr3) + die("Unsupported memory type!\n"); + + sdram_configure_pmc(param, pmc); + sdram_patch(param->EmcBctSpare0, param->EmcBctSpare1); + + sdram_start_clocks(param); + sdram_patch(param->EmcBctSpare2, param->EmcBctSpare3); + + sdram_deassert_sel_dpd(param, pmc); + sdram_set_swizzle(param, emc); + sdram_set_pad_controls(param, emc); + sdram_patch(param->EmcBctSpare4, param->EmcBctSpare5); + + sdram_trigger_emc_timing_update(emc); + sdram_init_mc(param, mc); + sdram_init_emc(param, emc); + sdram_patch(param->EmcBctSpare6, param->EmcBctSpare7); + + sdram_set_emc_timing(param, emc); + sdram_patch_bootrom(param, mc); + sdram_set_dpd3(param, pmc); + sdram_set_dli_trims(param, emc); + sdram_deassert_clock_enable_signal(param, pmc); + sdram_set_clock_enable_signal(param, emc); + sdram_init_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare8, param->EmcBctSpare9); + + sdram_set_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare10, param->EmcBctSpare11); + + sdram_trigger_emc_timing_update(emc); + sdram_set_refresh(param, emc); + sdram_enable_arbiter(param); + sdram_lock_carveouts(param, mc); + + sdram_lp0_save_params(param); +} + +uint32_t sdram_get_ram_code(void) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + return ((readl(&pmc->strapping_opt_a) & + PMC_STRAPPING_OPT_A_RAM_CODE_MASK) >> + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT); +} + +/* returns total amount of DRAM (in MB) from memory controller registers */ +int sdram_size_mb(void) +{ + struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE; + static int total_size = 0; + + if (total_size) + return total_size; + + /* + * This obtains memory size from the External Memory Aperture + * Configuration register. Nvidia confirmed that it is safe to assume + * this value represents the total physical DRAM size. + */ + total_size = (read32(&mc->emem_cfg) >> + MC_EMEM_CFG_SIZE_MB_SHIFT) & MC_EMEM_CFG_SIZE_MB_MASK; + + printk(BIOS_DEBUG, "%s: Total SDRAM (MB): %u\n", __func__, total_size); + return total_size; +} + +uintptr_t sdram_max_addressable_mb(void) +{ + return MIN(((uintptr_t)_dram/MiB) + sdram_size_mb(), 4096); +} diff --git a/src/soc/nvidia/tegra124/sdram_lp0.c b/src/soc/nvidia/tegra124/sdram_lp0.c new file mode 100644 index 0000000000..11e8bc0aba --- /dev/null +++ b/src/soc/nvidia/tegra124/sdram_lp0.c @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * This function reads SDRAM parameters (and a few CLK_RST regsiter values) from + * the common BCT format and writes them into PMC scratch registers (where the + * BootROM expects them on LP0 resume). Since those store the same values in a + * different format, we follow a "translation table" taken from Nvidia's U-Boot + * implementation to shift bits into the right position. + * + * Contrary to U-Boot, we transform the same macros directly into hardcoded + * assignments (without any pesky function calls or volatile qualifiers) to give + * the compiler as much room for optimization as possible. For that reason, we + * also intentionally avoid read/write macros, under the assumption + * that PMC scratch register accesses should not have side effects and can be + * arbitrarily reordered. For the few accesses that do have side-effects, the + * code must contain explicit memory barriers. + */ +void sdram_lp0_save_params(const struct sdram_params *sdram) +{ + struct tegra_pmc_regs * pmc = (void *)TEGRA_PMC_BASE; + struct clk_rst_ctlr * clk_rst = (void *)TEGRA_CLK_RST_BASE; + +#define pack(src, src_bits, dst, dst_bits) { \ + _Static_assert((1 ? src_bits) >= (0 ? src_bits) && (1 ? dst_bits) >= \ + (0 ? dst_bits), "byte range flipped (must be MSB:LSB)" ); \ + _Static_assert((1 ? src_bits) - (0 ? src_bits) == (1 ? dst_bits) - \ + (0 ? dst_bits), "src and dst byte range lengths differ" ); \ + u32 mask = 0xffffffff >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \ + dst &= ~(mask << (0 ? dst_bits)); \ + dst |= ((src >> (0 ? src_bits)) & mask) << (0 ? dst_bits); \ +} + +#define s(param, src_bits, pmcreg, dst_bits) \ + pack(sdram->param, src_bits, pmc->pmcreg, dst_bits) + +#define m(clkreg, src_bits, pmcreg, dst_bits) \ + pack(clk_rst->clkreg, src_bits, pmc->pmcreg, dst_bits) + +#define c(value, pmcreg, dst_bits) \ + pack(value, (1 ? dst_bits) - (0 ? dst_bits) : 0, pmc->pmcreg, dst_bits) + + s(EmcClockSource, 7:0, scratch6, 15:8); + s(EmcClockSource, 31:29, scratch6, 18:16); + s(EmcClockSource, 26:26, scratch6, 19:19); + s(EmcOdtWrite, 5:0, scratch6, 25:20); + s(EmcOdtWrite, 11:8, scratch6, 29:26); + s(EmcOdtWrite, 30:30, scratch6, 30:30); + s(EmcOdtWrite, 31:31, scratch6, 31:31); + s(EmcXm2DqPadCtrl2, 18:16, scratch7, 22:20); + s(EmcXm2DqPadCtrl2, 22:20, scratch7, 25:23); + s(EmcXm2DqPadCtrl2, 26:24, scratch7, 28:26); + s(EmcXm2DqPadCtrl2, 30:28, scratch7, 31:29); + s(EmcXm2DqPadCtrl3, 18:16, scratch8, 22:20); + s(EmcXm2DqPadCtrl3, 22:20, scratch8, 25:23); + s(EmcXm2DqPadCtrl3, 26:24, scratch8, 28:26); + s(EmcXm2DqPadCtrl3, 30:28, scratch8, 31:29); + s(EmcTxsrDll, 11:0, scratch9, 31:20); + c(0, scratch10, 31:0); + s(EmcDsrVttgenDrv, 5:0, scratch10, 25:20); + s(EmcDsrVttgenDrv, 18:16, scratch10, 28:26); + s(EmcDsrVttgenDrv, 26:24, scratch10, 31:29); + s(EmcFbioSpare, 31:24, scratch11, 7:0); + s(EmcFbioSpare, 23:16, scratch11, 15:8); + s(EmcFbioSpare, 15:8, scratch11, 23:16); + s(EmcFbioSpare, 7:0, scratch11, 31:24); + s(EmcCfgRsv, 31:0, scratch12, 31:0); + s(EmcCdbCntl2, 31:0, scratch13, 31:0); + s(McEmemArbDaTurns, 31:0, scratch14, 31:0); + s(EmcCfgDigDll, 0:0, scratch17, 0:0); + s(EmcCfgDigDll, 25:2, scratch17, 24:1); + s(EmcCfgDigDll, 31:27, scratch17, 29:25); + s(EmcCdbCntl1, 29:0, scratch18, 29:0); + s(McEmemArbMisc0, 14:0, scratch19, 14:0); + s(McEmemArbMisc0, 30:16, scratch19, 29:15); + s(EmcXm2DqsPadCtrl, 4:0, scratch22, 4:0); + s(EmcXm2DqsPadCtrl, 12:8, scratch22, 9:5); + s(EmcXm2DqsPadCtrl, 31:14, scratch22, 27:10); + s(EmcRrd, 3:0, scratch22, 31:28); + s(EmcXm2DqPadCtrl, 31:4, scratch23, 27:0); + s(EmcRext, 3:0, scratch23, 31:28); + s(EmcXm2CompPadCtrl, 16:0, scratch24, 16:0); + s(EmcXm2CompPadCtrl, 24:20, scratch24, 21:17); + s(EmcXm2CompPadCtrl, 27:27, scratch24, 22:22); + s(EmcXm2CompPadCtrl, 31:28, scratch24, 26:23); + s(EmcR2w, 4:0, scratch24, 31:27); + s(EmcCfg, 9:1, scratch25, 8:0); + s(EmcCfg, 26:16, scratch25, 19:9); + s(EmcCfg, 31:28, scratch25, 23:20); + s(EmcXm2VttGenPadCtrl, 0:0, scratch25, 24:24); + s(EmcXm2VttGenPadCtrl, 2:2, scratch25, 25:25); + s(EmcXm2VttGenPadCtrl, 18:16, scratch25, 28:26); + s(EmcXm2VttGenPadCtrl, 26:24, scratch25, 31:29); + s(EmcZcalInterval, 23:10, scratch26, 13:0); + s(EmcZcalInterval, 9:0, scratch26, 23:14); + s(EmcSelDpdCtrl, 5:2, scratch26, 27:24); + s(EmcSelDpdCtrl, 8:8, scratch26, 28:28); + s(EmcSelDpdCtrl, 18:16, scratch26, 31:29); + s(EmcXm2VttGenPadCtrl3, 22:0, scratch27, 22:0); + s(EmcXm2VttGenPadCtrl3, 24:24, scratch27, 23:23); + s(EmcSwizzleRank0ByteCfg, 1:0, scratch27, 25:24); + s(EmcSwizzleRank0ByteCfg, 5:4, scratch27, 27:26); + s(EmcSwizzleRank0ByteCfg, 9:8, scratch27, 29:28); + s(EmcSwizzleRank0ByteCfg, 13:12, scratch27, 31:30); + s(EmcXm2ClkPadCtrl2, 5:0, scratch28, 5:0); + s(EmcXm2ClkPadCtrl2, 13:8, scratch28, 11:6); + s(EmcXm2ClkPadCtrl2, 20:16, scratch28, 16:12); + s(EmcXm2ClkPadCtrl2, 23:23, scratch28, 17:17); + s(EmcXm2ClkPadCtrl2, 28:24, scratch28, 22:18); + s(EmcXm2ClkPadCtrl2, 31:31, scratch28, 23:23); + s(EmcSwizzleRank1ByteCfg, 1:0, scratch28, 25:24); + s(EmcSwizzleRank1ByteCfg, 5:4, scratch28, 27:26); + s(EmcSwizzleRank1ByteCfg, 9:8, scratch28, 29:28); + s(EmcSwizzleRank1ByteCfg, 13:12, scratch28, 31:30); + s(McEmemArbDaCovers, 23:0, scratch29, 23:0); + s(McEmemArbRsv, 7:0, scratch29, 31:24); + s(EmcAutoCalConfig, 4:0, scratch30, 4:0); + s(EmcAutoCalConfig, 12:8, scratch30, 9:5); + s(EmcAutoCalConfig, 18:16, scratch30, 12:10); + s(EmcAutoCalConfig, 25:20, scratch30, 18:13); + s(EmcAutoCalConfig, 31:28, scratch30, 22:19); + s(EmcRfc, 8:0, scratch30, 31:23); + s(EmcXm2DqsPadCtrl2, 21:0, scratch31, 21:0); + s(EmcXm2DqsPadCtrl2, 24:24, scratch31, 22:22); + s(EmcAr2Pden, 8:0, scratch31, 31:23); + s(EmcXm2ClkPadCtrl, 0:0, scratch32, 0:0); + s(EmcXm2ClkPadCtrl, 4:2, scratch32, 3:1); + s(EmcXm2ClkPadCtrl, 7:7, scratch32, 4:4); + s(EmcXm2ClkPadCtrl, 31:14, scratch32, 22:5); + s(EmcRfcSlr, 8:0, scratch32, 31:23); + s(EmcXm2DqsPadCtrl3, 0:0, scratch33, 0:0); + s(EmcXm2DqsPadCtrl3, 5:5, scratch33, 1:1); + s(EmcXm2DqsPadCtrl3, 12:8, scratch33, 6:2); + s(EmcXm2DqsPadCtrl3, 18:14, scratch33, 11:7); + s(EmcXm2DqsPadCtrl3, 24:20, scratch33, 16:12); + s(EmcXm2DqsPadCtrl3, 30:26, scratch33, 21:17); + s(EmcTxsr, 9:0, scratch33, 31:22); + s(McEmemArbCfg, 8:0, scratch40, 8:0); + s(McEmemArbCfg, 20:16, scratch40, 13:9); + s(McEmemArbCfg, 27:24, scratch40, 17:14); + s(McEmemArbCfg, 31:28, scratch40, 21:18); + s(EmcMc2EmcQ, 2:0, scratch40, 24:22); + s(EmcMc2EmcQ, 10:8, scratch40, 27:25); + s(EmcMc2EmcQ, 27:24, scratch40, 31:28); + s(EmcAutoCalInterval, 20:0, scratch42, 20:0); + s(McEmemArbOutstandingReq, 8:0, scratch42, 29:21); + s(McEmemArbOutstandingReq, 31:30, scratch42, 31:30); + s(EmcMrsWaitCnt2, 9:0, scratch44, 9:0); + s(EmcMrsWaitCnt2, 25:16, scratch44, 19:10); + s(EmcTxdsrvttgen, 11:0, scratch44, 31:20); + s(EmcMrsWaitCnt, 9:0, scratch45, 9:0); + s(EmcMrsWaitCnt, 25:16, scratch45, 19:10); + s(EmcCfgPipe, 1:0, scratch45, 21:20); + s(EmcCfgPipe, 9:4, scratch45, 27:22); + s(EmcCfgPipe, 15:12, scratch45, 31:28); + s(EmcXm2DqsPadCtrl4, 22:18, scratch46, 4:0); + s(EmcXm2DqsPadCtrl4, 16:12, scratch46, 9:5); + s(EmcXm2DqsPadCtrl4, 10:6, scratch46, 14:10); + s(EmcXm2DqsPadCtrl4, 4:0, scratch46, 19:15); + s(EmcZcalWaitCnt, 9:0, scratch46, 29:20); + s(EmcXm2DqsPadCtrl5, 22:18, scratch47, 4:0); + s(EmcXm2DqsPadCtrl5, 16:12, scratch47, 9:5); + s(EmcXm2DqsPadCtrl5, 10:6, scratch47, 14:10); + s(EmcXm2DqsPadCtrl5, 4:0, scratch47, 19:15); + s(EmcXm2VttGenPadCtrl2, 5:0, scratch47, 25:20); + s(EmcXm2VttGenPadCtrl2, 31:28, scratch47, 29:26); + s(EmcXm2DqsPadCtrl6, 12:8, scratch48, 4:0); + s(EmcXm2DqsPadCtrl6, 18:14, scratch48, 9:5); + s(EmcXm2DqsPadCtrl6, 24:20, scratch48, 14:10); + s(EmcXm2DqsPadCtrl6, 30:26, scratch48, 19:15); + s(EmcAutoCalConfig3, 4:0, scratch48, 24:20); + s(EmcAutoCalConfig3, 12:8, scratch48, 29:25); + s(EmcFbioCfg5, 1:0, scratch48, 31:30); + s(EmcDllXformQUse8, 4:0, scratch50, 4:0); + s(EmcDllXformQUse8, 22:8, scratch50, 19:5); + s(McEmemArbRing1Throttle, 4:0, scratch50, 24:20); + s(McEmemArbRing1Throttle, 20:16, scratch50, 29:25); + s(EmcFbioCfg5, 3:2, scratch50, 31:30); + s(EmcDllXformQUse9, 4:0, scratch51, 4:0); + s(EmcDllXformQUse9, 22:8, scratch51, 19:5); + s(EmcCttTermCtrl, 2:0, scratch51, 22:20); + s(EmcCttTermCtrl, 12:8, scratch51, 27:23); + s(EmcCttTermCtrl, 31:31, scratch51, 28:28); + s(EmcFbioCfg6, 2:0, scratch51, 31:29); + s(EmcDllXformQUse10, 4:0, scratch56, 4:0); + s(EmcDllXformQUse10, 22:8, scratch56, 19:5); + s(EmcXm2CmdPadCtrl, 10:3, scratch56, 27:20); + s(EmcXm2CmdPadCtrl, 28:28, scratch56, 28:28); + s(EmcPutermAdj, 1:0, scratch56, 30:29); + s(EmcPutermAdj, 7:7, scratch56, 31:31); + s(EmcDllXformQUse11, 4:0, scratch57, 4:0); + s(EmcDllXformQUse11, 22:8, scratch57, 19:5); + s(EmcWdv, 3:0, scratch57, 31:28); + s(EmcDllXformQUse12, 4:0, scratch58, 4:0); + s(EmcDllXformQUse12, 22:8, scratch58, 19:5); + s(EmcBurstRefreshNum, 3:0, scratch58, 31:28); + s(EmcDllXformQUse13, 4:0, scratch59, 4:0); + s(EmcDllXformQUse13, 22:8, scratch59, 19:5); + s(EmcWext, 3:0, scratch59, 31:28); + s(EmcDllXformQUse14, 4:0, scratch60, 4:0); + s(EmcDllXformQUse14, 22:8, scratch60, 19:5); + s(EmcClkenOverride, 3:1, scratch60, 30:28); + s(EmcClkenOverride, 6:6, scratch60, 31:31); + s(EmcDllXformQUse15, 4:0, scratch61, 4:0); + s(EmcDllXformQUse15, 22:8, scratch61, 19:5); + s(EmcR2r, 3:0, scratch61, 31:28); + s(EmcDllXformDq4, 4:0, scratch62, 4:0); + s(EmcDllXformDq4, 22:8, scratch62, 19:5); + s(EmcRc, 6:0, scratch62, 26:20); + s(EmcW2r, 4:0, scratch62, 31:27); + s(EmcDllXformDq5, 4:0, scratch63, 4:0); + s(EmcDllXformDq5, 22:8, scratch63, 19:5); + s(EmcTfaw, 6:0, scratch63, 26:20); + s(EmcR2p, 4:0, scratch63, 31:27); + s(EmcDllXformDq6, 4:0, scratch64, 4:0); + s(EmcDllXformDq6, 22:8, scratch64, 19:5); + s(EmcDliTrimTxDqs0, 6:0, scratch64, 26:20); + s(EmcQSafe, 4:0, scratch64, 31:27); + s(EmcDllXformDq7, 4:0, scratch65, 4:0); + s(EmcDllXformDq7, 22:8, scratch65, 19:5); + s(EmcDliTrimTxDqs1, 6:0, scratch65, 26:20); + s(EmcTClkStable, 4:0, scratch65, 31:27); + s(EmcAutoCalConfig2, 4:0, scratch66, 4:0); + s(EmcAutoCalConfig2, 12:8, scratch66, 9:5); + s(EmcAutoCalConfig2, 20:16, scratch66, 14:10); + s(EmcAutoCalConfig2, 28:24, scratch66, 19:15); + s(EmcDliTrimTxDqs2, 6:0, scratch66, 26:20); + s(EmcTClkStop, 4:0, scratch66, 31:27); + s(McEmemArbMisc1, 1:0, scratch67, 1:0); + s(McEmemArbMisc1, 12:4, scratch67, 10:2); + s(McEmemArbMisc1, 25:21, scratch67, 15:11); + s(McEmemArbMisc1, 31:28, scratch67, 19:16); + s(EmcDliTrimTxDqs3, 6:0, scratch67, 26:20); + s(EmcEInputDuration, 4:0, scratch67, 31:27); + s(EmcZcalMrwCmd, 7:0, scratch68, 7:0); + s(EmcZcalMrwCmd, 23:16, scratch68, 15:8); + s(EmcZcalMrwCmd, 31:30, scratch68, 17:16); + s(EmcTRefBw, 13:0, scratch68, 31:18); + s(EmcXm2CmdPadCtrl2, 31:14, scratch69, 17:0); + s(EmcDliTrimTxDqs4, 6:0, scratch69, 24:18); + s(EmcDliTrimTxDqs5, 6:0, scratch69, 31:25); + s(EmcXm2CmdPadCtrl3, 31:14, scratch70, 17:0); + s(EmcDliTrimTxDqs6, 6:0, scratch70, 24:18); + s(EmcDliTrimTxDqs7, 6:0, scratch70, 31:25); + s(EmcXm2CmdPadCtrl5, 2:0, scratch71, 2:0); + s(EmcXm2CmdPadCtrl5, 6:4, scratch71, 5:3); + s(EmcXm2CmdPadCtrl5, 10:8, scratch71, 8:6); + s(EmcXm2CmdPadCtrl5, 14:12, scratch71, 11:9); + s(EmcXm2CmdPadCtrl5, 18:16, scratch71, 14:12); + s(EmcXm2CmdPadCtrl5, 22:20, scratch71, 17:15); + s(EmcDliTrimTxDqs8, 6:0, scratch71, 24:18); + s(EmcDliTrimTxDqs9, 6:0, scratch71, 31:25); + s(EmcCdbCntl3, 17:0, scratch72, 17:0); + s(EmcDliTrimTxDqs10, 6:0, scratch72, 24:18); + s(EmcDliTrimTxDqs11, 6:0, scratch72, 31:25); + s(EmcSwizzleRank0Byte0, 2:0, scratch73, 2:0); + s(EmcSwizzleRank0Byte0, 6:4, scratch73, 5:3); + s(EmcSwizzleRank0Byte0, 10:8, scratch73, 8:6); + s(EmcSwizzleRank0Byte0, 14:12, scratch73, 11:9); + s(EmcSwizzleRank0Byte0, 18:16, scratch73, 14:12); + s(EmcSwizzleRank0Byte0, 22:20, scratch73, 17:15); + s(EmcDliTrimTxDqs12, 6:0, scratch73, 24:18); + s(EmcDliTrimTxDqs13, 6:0, scratch73, 31:25); + s(EmcSwizzleRank0Byte1, 2:0, scratch74, 2:0); + s(EmcSwizzleRank0Byte1, 6:4, scratch74, 5:3); + s(EmcSwizzleRank0Byte1, 10:8, scratch74, 8:6); + s(EmcSwizzleRank0Byte1, 14:12, scratch74, 11:9); + s(EmcSwizzleRank0Byte1, 18:16, scratch74, 14:12); + s(EmcSwizzleRank0Byte1, 22:20, scratch74, 17:15); + s(EmcDliTrimTxDqs14, 6:0, scratch74, 24:18); + s(EmcDliTrimTxDqs15, 6:0, scratch74, 31:25); + s(EmcSwizzleRank0Byte2, 2:0, scratch75, 2:0); + s(EmcSwizzleRank0Byte2, 6:4, scratch75, 5:3); + s(EmcSwizzleRank0Byte2, 10:8, scratch75, 8:6); + s(EmcSwizzleRank0Byte2, 14:12, scratch75, 11:9); + s(EmcSwizzleRank0Byte2, 18:16, scratch75, 14:12); + s(EmcSwizzleRank0Byte2, 22:20, scratch75, 17:15); + s(McEmemArbTimingRp, 6:0, scratch75, 24:18); + s(McEmemArbTimingRc, 6:0, scratch75, 31:25); + s(EmcSwizzleRank0Byte3, 2:0, scratch76, 2:0); + s(EmcSwizzleRank0Byte3, 6:4, scratch76, 5:3); + s(EmcSwizzleRank0Byte3, 10:8, scratch76, 8:6); + s(EmcSwizzleRank0Byte3, 14:12, scratch76, 11:9); + s(EmcSwizzleRank0Byte3, 18:16, scratch76, 14:12); + s(EmcSwizzleRank0Byte3, 22:20, scratch76, 17:15); + s(McEmemArbTimingFaw, 6:0, scratch76, 24:18); + s(McEmemArbTimingWap2Pre, 6:0, scratch76, 31:25); + s(EmcSwizzleRank1Byte0, 2:0, scratch77, 2:0); + s(EmcSwizzleRank1Byte0, 6:4, scratch77, 5:3); + s(EmcSwizzleRank1Byte0, 10:8, scratch77, 8:6); + s(EmcSwizzleRank1Byte0, 14:12, scratch77, 11:9); + s(EmcSwizzleRank1Byte0, 18:16, scratch77, 14:12); + s(EmcSwizzleRank1Byte0, 22:20, scratch77, 17:15); + s(EmcRas, 5:0, scratch77, 23:18); + s(EmcRp, 5:0, scratch77, 29:24); + s(EmcCfg2, 9:8, scratch77, 31:30); + s(EmcSwizzleRank1Byte1, 2:0, scratch78, 2:0); + s(EmcSwizzleRank1Byte1, 6:4, scratch78, 5:3); + s(EmcSwizzleRank1Byte1, 10:8, scratch78, 8:6); + s(EmcSwizzleRank1Byte1, 14:12, scratch78, 11:9); + s(EmcSwizzleRank1Byte1, 18:16, scratch78, 14:12); + s(EmcSwizzleRank1Byte1, 22:20, scratch78, 17:15); + s(EmcW2p, 5:0, scratch78, 23:18); + s(EmcRdRcd, 5:0, scratch78, 29:24); + s(EmcCfg2, 27:26, scratch78, 31:30); + s(EmcSwizzleRank1Byte2, 2:0, scratch79, 2:0); + s(EmcSwizzleRank1Byte2, 6:4, scratch79, 5:3); + s(EmcSwizzleRank1Byte2, 10:8, scratch79, 8:6); + s(EmcSwizzleRank1Byte2, 14:12, scratch79, 11:9); + s(EmcSwizzleRank1Byte2, 18:16, scratch79, 14:12); + s(EmcSwizzleRank1Byte2, 22:20, scratch79, 17:15); + s(EmcWrRcd, 5:0, scratch79, 23:18); + s(EmcQUse, 5:0, scratch79, 29:24); + s(EmcFbioCfg5, 4:4, scratch79, 31:31); + s(EmcSwizzleRank1Byte3, 2:0, scratch80, 2:0); + s(EmcSwizzleRank1Byte3, 6:4, scratch80, 5:3); + s(EmcSwizzleRank1Byte3, 10:8, scratch80, 8:6); + s(EmcSwizzleRank1Byte3, 14:12, scratch80, 11:9); + s(EmcSwizzleRank1Byte3, 18:16, scratch80, 14:12); + s(EmcSwizzleRank1Byte3, 22:20, scratch80, 17:15); + s(EmcQRst, 5:0, scratch80, 23:18); + s(EmcRdv, 5:0, scratch80, 29:24); + s(EmcFbioCfg5, 6:5, scratch80, 31:30); + s(EmcDynSelfRefControl, 15:0, scratch81, 15:0); + s(EmcDynSelfRefControl, 31:31, scratch81, 16:16); + s(EmcPdEx2Wr, 5:0, scratch81, 22:17); + s(EmcPdEx2Rd, 5:0, scratch81, 28:23); + s(EmcRefresh, 5:0, scratch82, 5:0); + s(EmcRefresh, 15:6, scratch82, 15:6); + s(EmcCmdQ, 4:0, scratch82, 20:16); + s(EmcCmdQ, 10:8, scratch82, 23:21); + s(EmcCmdQ, 14:12, scratch82, 26:24); + s(EmcCmdQ, 28:24, scratch82, 31:27); + s(EmcAcpdControl, 15:0, scratch83, 15:0); + s(EmcCfgDigDllPeriod, 15:0, scratch83, 31:16); + s(EmcDllXformDqs0, 4:0, scratch84, 4:0); + s(EmcDllXformDqs0, 22:12, scratch84, 15:5); + s(EmcDllXformDqs1, 4:0, scratch84, 20:16); + s(EmcDllXformDqs1, 22:12, scratch84, 31:21); + s(EmcDllXformDqs2, 4:0, scratch85, 4:0); + s(EmcDllXformDqs2, 22:12, scratch85, 15:5); + s(EmcDllXformDqs3, 4:0, scratch85, 20:16); + s(EmcDllXformDqs3, 22:12, scratch85, 31:21); + s(EmcDllXformDqs4, 4:0, scratch86, 4:0); + s(EmcDllXformDqs4, 22:12, scratch86, 15:5); + s(EmcDllXformDqs5, 4:0, scratch86, 20:16); + s(EmcDllXformDqs5, 22:12, scratch86, 31:21); + s(EmcDllXformDqs6, 4:0, scratch87, 4:0); + s(EmcDllXformDqs6, 22:12, scratch87, 15:5); + s(EmcDllXformDqs7, 4:0, scratch87, 20:16); + s(EmcDllXformDqs7, 22:12, scratch87, 31:21); + s(EmcDllXformDqs8, 4:0, scratch88, 4:0); + s(EmcDllXformDqs8, 22:12, scratch88, 15:5); + s(EmcDllXformDqs9, 4:0, scratch88, 20:16); + s(EmcDllXformDqs9, 22:12, scratch88, 31:21); + s(EmcDllXformDqs10, 4:0, scratch89, 4:0); + s(EmcDllXformDqs10, 22:12, scratch89, 15:5); + s(EmcDllXformDqs11, 4:0, scratch89, 20:16); + s(EmcDllXformDqs11, 22:12, scratch89, 31:21); + s(EmcDllXformDqs12, 4:0, scratch90, 4:0); + s(EmcDllXformDqs12, 22:12, scratch90, 15:5); + s(EmcDllXformDqs13, 4:0, scratch90, 20:16); + s(EmcDllXformDqs13, 22:12, scratch90, 31:21); + s(EmcDllXformDqs14, 4:0, scratch91, 4:0); + s(EmcDllXformDqs14, 22:12, scratch91, 15:5); + s(EmcDllXformDqs15, 4:0, scratch91, 20:16); + s(EmcDllXformDqs15, 22:12, scratch91, 31:21); + s(EmcDllXformQUse0, 4:0, scratch92, 4:0); + s(EmcDllXformQUse0, 22:12, scratch92, 15:5); + s(EmcDllXformQUse1, 4:0, scratch92, 20:16); + s(EmcDllXformQUse1, 22:12, scratch92, 31:21); + s(EmcDllXformQUse2, 4:0, scratch93, 4:0); + s(EmcDllXformQUse2, 22:12, scratch93, 15:5); + s(EmcDllXformQUse3, 4:0, scratch93, 20:16); + s(EmcDllXformQUse3, 22:12, scratch93, 31:21); + s(EmcDllXformQUse4, 4:0, scratch94, 4:0); + s(EmcDllXformQUse4, 22:12, scratch94, 15:5); + s(EmcDllXformQUse5, 4:0, scratch94, 20:16); + s(EmcDllXformQUse5, 22:12, scratch94, 31:21); + s(EmcDllXformQUse6, 4:0, scratch95, 4:0); + s(EmcDllXformQUse6, 22:12, scratch95, 15:5); + s(EmcDllXformQUse7, 4:0, scratch95, 20:16); + s(EmcDllXformQUse7, 22:12, scratch95, 31:21); + s(EmcDllXformDq0, 4:0, scratch96, 4:0); + s(EmcDllXformDq0, 22:12, scratch96, 15:5); + s(EmcDllXformDq1, 4:0, scratch96, 20:16); + s(EmcDllXformDq1, 22:12, scratch96, 31:21); + s(EmcDllXformDq2, 4:0, scratch97, 4:0); + s(EmcDllXformDq2, 22:12, scratch97, 15:5); + s(EmcDllXformDq3, 4:0, scratch97, 20:16); + s(EmcDllXformDq3, 22:12, scratch97, 31:21); + s(EmcPreRefreshReqCnt, 15:0, scratch98, 15:0); + s(EmcDllXformAddr0, 4:0, scratch98, 20:16); + s(EmcDllXformAddr0, 22:12, scratch98, 31:21); + s(EmcDllXformAddr1, 4:0, scratch99, 4:0); + s(EmcDllXformAddr1, 22:12, scratch99, 15:5); + s(EmcDllXformAddr2, 4:0, scratch99, 20:16); + s(EmcDllXformAddr2, 22:12, scratch99, 31:21); + s(EmcDllXformAddr3, 4:0, scratch100, 4:0); + s(EmcDllXformAddr3, 22:12, scratch100, 15:5); + s(EmcDllXformAddr4, 4:0, scratch100, 20:16); + s(EmcDllXformAddr4, 22:12, scratch100, 31:21); + s(EmcDllXformAddr5, 4:0, scratch101, 4:0); + s(EmcDllXformAddr5, 22:12, scratch101, 15:5); + s(EmcPChg2Pden, 5:0, scratch102, 5:0); + s(EmcAct2Pden, 5:0, scratch102, 11:6); + s(EmcRw2Pden, 5:0, scratch102, 17:12); + s(EmcTcke, 5:0, scratch102, 23:18); + s(EmcTrpab, 5:0, scratch102, 29:24); + s(EmcFbioCfg5, 8:7, scratch102, 31:30); + s(EmcCtt, 5:0, scratch103, 5:0); + s(EmcEInput, 5:0, scratch103, 11:6); + s(EmcPutermExtra, 21:16, scratch103, 17:12); + s(EmcTckesr, 5:0, scratch103, 23:18); + s(EmcTpd, 5:0, scratch103, 29:24); + s(EmcFbioCfg5, 10:9, scratch103, 31:30); + s(EmcRdvMask, 5:0, scratch104, 5:0); + s(EmcXm2CmdPadCtrl4, 0:0, scratch104, 6:6); + s(EmcXm2CmdPadCtrl4, 2:2, scratch104, 7:7); + s(EmcXm2CmdPadCtrl4, 4:4, scratch104, 8:8); + s(EmcXm2CmdPadCtrl4, 6:6, scratch104, 9:9); + s(EmcXm2CmdPadCtrl4, 8:8, scratch104, 10:10); + s(EmcXm2CmdPadCtrl4, 10:10, scratch104, 11:11); + s(EmcQpop, 5:0, scratch104, 17:12); + s(McEmemArbTimingRcd, 5:0, scratch104, 23:18); + s(McEmemArbTimingRas, 5:0, scratch104, 29:24); + s(EmcFbioCfg5, 12:11, scratch104, 31:30); + s(McEmemArbTimingRap2Pre, 5:0, scratch105, 5:0); + s(McEmemArbTimingR2W, 5:0, scratch105, 11:6); + s(McEmemArbTimingW2R, 5:0, scratch105, 17:12); + s(EmcIbdly, 4:0, scratch105, 22:18); + s(McEmemArbTimingR2R, 4:0, scratch105, 27:23); + s(EmcW2w, 3:0, scratch105, 31:28); + s(McEmemArbTimingW2W, 4:0, scratch106, 4:0); + s(McEmemArbOverride, 27:27, scratch106, 5:5); + s(McEmemArbOverride, 26:26, scratch106, 6:6); + s(McEmemArbOverride, 16:16, scratch106, 7:7); + s(McEmemArbOverride, 10:10, scratch106, 8:8); + s(McEmemArbOverride, 4:4, scratch106, 9:9); + s(EmcWdvMask, 3:0, scratch106, 13:10); + s(EmcCttDuration, 3:0, scratch106, 17:14); + s(EmcQuseWidth, 3:0, scratch106, 21:18); + s(EmcPutermWidth, 3:0, scratch106, 25:22); + s(EmcBgbiasCtl0, 3:0, scratch106, 29:26); + s(EmcFbioCfg5, 25:24, scratch106, 31:30); + s(McEmemArbTimingRrd, 3:0, scratch107, 3:0); + s(EmcFbioCfg5, 23:20, scratch107, 10:7); + s(EmcFbioCfg5, 15:13, scratch107, 13:11); + s(EmcCfg2, 5:3, scratch107, 16:14); + s(EmcFbioCfg5, 26:26, scratch107, 17:17); + s(EmcFbioCfg5, 28:28, scratch107, 18:18); + s(EmcCfg2, 2:0, scratch107, 21:19); + s(EmcCfg2, 7:6, scratch107, 23:22); + s(EmcCfg2, 15:10, scratch107, 29:24); + s(EmcCfg2, 23:22, scratch107, 31:30); + s(EmcCfg2, 25:24, scratch108, 1:0); + s(EmcCfg2, 31:28, scratch108, 5:2); + s(BootRomPatchData, 31:0, scratch15, 31:0); + s(BootRomPatchControl, 31:0, scratch16, 31:0); + s(EmcDevSelect, 1:0, scratch17, 31:30); + s(EmcZcalWarmColdBootEnables, 1:0, scratch18, 31:30); + s(EmcCfgDigDllPeriodWarmBoot, 1:0, scratch19, 31:30); + s(EmcWarmBootExtraModeRegWriteEnable, 0:0, scratch46, 30:30); + s(McClkenOverrideAllWarmBoot, 0:0, scratch46, 31:31); + s(EmcClkenOverrideAllWarmBoot, 0:0, scratch47, 30:30); + s(EmcMrsWarmBootEnable, 0:0, scratch47, 31:31); + s(EmcTimingControlWait, 7:0, scratch57, 27:20); + s(EmcZcalWarmBootWait, 7:0, scratch58, 27:20); + s(EmcAutoCalWait, 7:0, scratch59, 27:20); + s(WarmBootWait, 7:0, scratch60, 27:20); + s(EmcPinProgramWait, 7:0, scratch61, 27:20); + s(AhbArbitrationXbarCtrlMemInitDone, 0:0, scratch79, 30:30); + s(EmcExtraRefreshNum, 2:0, scratch81, 31:29); + s(SwizzleRankByteEncode, 15:0, scratch101, 31:16); + s(MemoryType, 2:0, scratch107, 6:4); + + switch (sdram->MemoryType) { + case NvBootMemoryType_LpDdr2: + s(EmcMrwLpddr2ZcalWarmBoot, 23:16, scratch5, 7:0); + s(EmcMrwLpddr2ZcalWarmBoot, 7:0, scratch5, 15:8); + s(EmcWarmBootMrwExtra, 23:16, scratch5, 23:16); + s(EmcWarmBootMrwExtra, 7:0, scratch5, 31:24); + s(EmcMrwLpddr2ZcalWarmBoot, 31:30, scratch6, 1:0); + s(EmcWarmBootMrwExtra, 31:30, scratch6, 3:2); + s(EmcMrwLpddr2ZcalWarmBoot, 27:26, scratch6, 5:4); + s(EmcWarmBootMrwExtra, 27:26, scratch6, 7:6); + s(EmcMrw1, 7:0, scratch7, 7:0); + s(EmcMrw1, 23:16, scratch7, 15:8); + s(EmcMrw1, 27:26, scratch7, 17:16); + s(EmcMrw1, 31:30, scratch7, 19:18); + s(EmcMrw2, 7:0, scratch8, 7:0); + s(EmcMrw2, 23:16, scratch8, 15:8); + s(EmcMrw2, 27:26, scratch8, 17:16); + s(EmcMrw2, 31:30, scratch8, 19:18); + s(EmcMrw3, 7:0, scratch9, 7:0); + s(EmcMrw3, 23:16, scratch9, 15:8); + s(EmcMrw3, 27:26, scratch9, 17:16); + s(EmcMrw3, 31:30, scratch9, 19:18); + s(EmcMrw4, 7:0, scratch10, 7:0); + s(EmcMrw4, 23:16, scratch10, 15:8); + s(EmcMrw4, 27:26, scratch10, 17:16); + s(EmcMrw4, 31:30, scratch10, 19:18); + break; + case NvBootMemoryType_Ddr3: + s(EmcMrs, 13:0, scratch5, 13:0); + s(EmcEmrs, 13:0, scratch5, 27:14); + s(EmcMrs, 21:20, scratch5, 29:28); + s(EmcMrs, 31:30, scratch5, 31:30); + s(EmcEmrs2, 13:0, scratch7, 13:0); + s(EmcEmrs, 21:20, scratch7, 15:14); + s(EmcEmrs, 31:30, scratch7, 17:16); + s(EmcEmrs2, 21:20, scratch7, 19:18); + s(EmcEmrs3, 13:0, scratch8, 13:0); + s(EmcEmrs2, 31:30, scratch8, 15:14); + s(EmcEmrs3, 21:20, scratch8, 17:16); + s(EmcEmrs3, 31:30, scratch8, 19:18); + s(EmcWarmBootMrsExtra, 13:0, scratch9, 13:0); + s(EmcWarmBootMrsExtra, 31:30, scratch9, 15:14); + s(EmcWarmBootMrsExtra, 21:20, scratch9, 17:16); + s(EmcZqCalDdr3WarmBoot, 31:30, scratch9, 19:18); + s(EmcMrs, 27:26, scratch10, 1:0); + s(EmcEmrs, 27:26, scratch10, 3:2); + s(EmcEmrs2, 27:26, scratch10, 5:4); + s(EmcEmrs3, 27:26, scratch10, 7:6); + s(EmcWarmBootMrsExtra, 27:27, scratch10, 8:8); + s(EmcWarmBootMrsExtra, 26:26, scratch10, 9:9); + s(EmcZqCalDdr3WarmBoot, 0:0, scratch10, 10:10); + s(EmcZqCalDdr3WarmBoot, 4:4, scratch10, 11:11); + c(0, scratch116, 31:0); + c(0, scratch117, 31:0); + break; + default: + printk(BIOS_CRIT, "ERROR: %s() unrecognized MemoryType %d!\n", + __func__, sdram->MemoryType); + } + + s(McVideoProtectGpuOverride0, 31:0, secure_scratch8, 31:0); + s(McVideoProtectVprOverride, 3:0, secure_scratch9, 3:0); + s(McVideoProtectVprOverride, 11:6, secure_scratch9, 9:4); + s(McVideoProtectVprOverride, 23:14, secure_scratch9, 19:10); + s(McVideoProtectVprOverride, 26:26, secure_scratch9, 20:20); + s(McVideoProtectVprOverride, 31:29, secure_scratch9, 23:21); + s(EmcFbioCfg5, 19:16, secure_scratch9, 27:24); + s(McDisplaySnapRing, 1:0, secure_scratch9, 29:28); + s(McDisplaySnapRing, 31:31, secure_scratch9, 30:30); + s(EmcAdrCfg, 0:0, secure_scratch9, 31:31); + s(McVideoProtectGpuOverride1, 15:0, secure_scratch10, 15:0); + s(McEmemAdrCfgBankMask0, 15:0, secure_scratch10, 31:16); + s(McEmemAdrCfgBankMask1, 15:0, secure_scratch11, 15:0); + s(McEmemAdrCfgBankMask2, 15:0, secure_scratch11, 31:16); + s(McEmemCfg, 13:0, secure_scratch12, 13:0); + s(McEmemCfg, 31:31, secure_scratch12, 14:14); + s(McVideoProtectBom, 31:20, secure_scratch12, 26:15); + s(McVideoProtectVprOverride1, 1:0, secure_scratch12, 28:27); + s(McVideoProtectVprOverride1, 4:4, secure_scratch12, 29:29); + s(McVideoProtectBomAdrHi, 1:0, secure_scratch12, 31:30); + s(McVideoProtectSizeMb, 11:0, secure_scratch13, 11:0); + s(McSecCarveoutBom, 31:20, secure_scratch13, 23:12); + s(McEmemAdrCfgBankSwizzle3, 2:0, secure_scratch13, 26:24); + s(McVideoProtectWriteAccess, 1:0, secure_scratch13, 28:27); + s(McSecCarveoutAdrHi, 1:0, secure_scratch13, 30:29); + s(McEmemAdrCfg, 0:0, secure_scratch13, 31:31); + s(McSecCarveoutSizeMb, 11:0, secure_scratch14, 11:0); + s(McMtsCarveoutBom, 31:20, secure_scratch14, 23:12); + s(McMtsCarveoutAdrHi, 1:0, secure_scratch14, 25:24); + s(McSecCarveoutProtectWriteAccess, 0:0, secure_scratch14, 26:26); + s(McMtsCarveoutRegCtrl, 0:0, secure_scratch14, 27:27); + s(McMtsCarveoutSizeMb, 11:0, secure_scratch15, 11:0); + s(McEmemAdrCfgDev0, 2:0, secure_scratch15, 14:12); + s(McEmemAdrCfgDev0, 9:8, secure_scratch15, 16:15); + s(McEmemAdrCfgDev0, 19:16, secure_scratch15, 20:17); + s(McEmemAdrCfgDev1, 2:0, secure_scratch15, 23:21); + s(McEmemAdrCfgDev1, 9:8, secure_scratch15, 25:24); + s(McEmemAdrCfgDev1, 19:16, secure_scratch15, 29:26); + + /* Make sure all writes complete before we lock the secure_scratchs. */ + dmb(); + c(0x1555555, sec_disable2, 25:0); + c(0xff, sec_disable, 19:12); + + c(0, scratch2, 31:0); + m(pllm_base, 15:0, scratch2, 15:0); + m(pllm_base, 20:20, scratch2, 16:16); + m(pllm_misc2, 2:0, scratch2, 19:17); + c(0, scratch35, 31:0); + m(pllm_misc1, 23:0, scratch35, 23:0); + m(pllm_misc1, 30:28, scratch35, 30:28); + c(0, scratch3, 31:0); + s(PllMInputDivider, 7:0, scratch3, 7:0); + c(0x3e, scratch3, 15:8); + c(0, scratch3, 19:16); + s(PllMKVCO, 0:0, scratch3, 20:20); + s(PllMKCP, 1:0, scratch3, 22:21); + c(0, scratch36, 31:0); + s(PllMSetupControl, 23:0, scratch36, 23:0); + c(0, scratch4, 31:0); + s(PllMStableTime, 9:0, scratch4, 9:0); + s(PllMStableTime, 9:0, scratch4, 19:10); + + s(PllMSelectDiv2, 0:0, pllm_wb0_override2, 27:27); + s(PllMKVCO, 0:0, pllm_wb0_override2, 26:26); + s(PllMKCP, 1:0, pllm_wb0_override2, 25:24); + s(PllMSetupControl, 23:0, pllm_wb0_override2, 23:0); + s(PllMFeedbackDivider, 7:0, pllm_wb0_override_freq, 15:8); + s(PllMInputDivider, 7:0, pllm_wb0_override_freq, 7:0); + + /* Need to ensure override params are written before we activate it. */ + dmb(); + c(3, pllp_wb0_override, 12:11); +} diff --git a/src/soc/nvidia/tegra124/soc.c b/src/soc/nvidia/tegra124/soc.c new file mode 100644 index 0000000000..57772ba281 --- /dev/null +++ b/src/soc/nvidia/tegra124/soc.c @@ -0,0 +1,83 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +/* this sucks, but for now, fb size/location are hardcoded. + * Will break if we get 2. Sigh. + * We assume it's all multiples of MiB for MMUs sake. + */ +static void soc_enable(device_t dev) +{ + u32 lcdbase = fb_base_mb(); + unsigned long fb_size = FB_SIZE_MB; + + ram_resource(dev, 0, (uintptr_t)_dram/KiB, + (sdram_max_addressable_mb() - fb_size)*KiB - + (uintptr_t)_dram/KiB); + mmio_resource(dev, 1, lcdbase*KiB, fb_size*KiB); + + u32 sdram_end_mb = sdram_size_mb() + (uintptr_t)_dram/MiB; + + if (sdram_end_mb > sdram_max_addressable_mb()) + ram_resource(dev, 2, sdram_max_addressable_mb()*KiB, + (sdram_end_mb - sdram_max_addressable_mb())*KiB); +} + +static void soc_init(device_t dev) +{ + if (vboot_skip_display_init()) + printk(BIOS_INFO, "Skipping display init.\n"); + else + display_startup(dev); + printk(BIOS_INFO, "CPU: Tegra124\n"); +} + +static void soc_noop(device_t dev) +{ +} + +static struct device_operations soc_ops = { + .read_resources = soc_noop, + .set_resources = soc_noop, + .enable_resources = soc_enable, + .init = soc_init, + .scan_bus = 0, +}; + +static void enable_tegra124_dev(device_t dev) +{ + dev->ops = &soc_ops; +} + +struct chip_operations soc_nvidia_tegra124_ops = { + CHIP_NAME("SOC Nvidia Tegra124") + .enable_dev = enable_tegra124_dev, +}; diff --git a/src/soc/nvidia/tegra124/sor.c b/src/soc/nvidia/tegra124/sor.c new file mode 100644 index 0000000000..c5f3f7a3ab --- /dev/null +++ b/src/soc/nvidia/tegra124/sor.c @@ -0,0 +1,930 @@ +/* + * drivers/video/tegra/dc/sor.c + * + * Copyright (c) 2011-2013, NVIDIA Corporation. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +#define DEBUG_SOR 0 + +#define APBDEV_PMC_DPD_SAMPLE (0x20) +#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE (0) +#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE (1) +#define APBDEV_PMC_SEL_DPD_TIM (0x1c8) +#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT (0x7f) +#define APBDEV_PMC_IO_DPD2_REQ (0x1c0) +#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT (25) +#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF (0 << 25) +#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON (1 << 25) +#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT (30) +#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK (0x3 << 30) +#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE (0 << 30) +#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF (1 << 30) +#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON (2 << 30) +#define APBDEV_PMC_IO_DPD2_STATUS (0x1c4) +#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT (25) +#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF (0 << 25) +#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON (1 << 25) + +static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg) +{ + void *addr = sor->base + (u32) (reg << 2); + u32 reg_val = READL(addr); + return reg_val; +} + +static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor, + u32 reg, u32 val) +{ + void *addr = sor->base + (u32) (reg << 2); + WRITEL(val, addr); +} + +static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor, + u32 reg, u32 mask, u32 val) +{ + u32 reg_val = tegra_sor_readl(sor, reg); + reg_val &= ~mask; + reg_val |= val; + tegra_sor_writel(sor, reg, reg_val); +} + +void tegra_dp_disable_tx_pu(struct tegra_dc_sor_data *sor) +{ + tegra_sor_write_field(sor, + NV_SOR_DP_PADCTL(sor->portnum), + NV_SOR_DP_PADCTL_TX_PU_MASK, + NV_SOR_DP_PADCTL_TX_PU_DISABLE); +} + +void tegra_dp_set_pe_vs_pc(struct tegra_dc_sor_data *sor, u32 mask, + u32 pe_reg, u32 vs_reg, u32 pc_reg, u8 pc_supported) +{ + tegra_sor_write_field(sor, NV_SOR_PR(sor->portnum), + mask, pe_reg); + tegra_sor_write_field(sor, NV_SOR_DC(sor->portnum), + mask, vs_reg); + if (pc_supported) { + tegra_sor_write_field( + sor, NV_SOR_POSTCURSOR(sor->portnum), + mask, pc_reg); + } +} + +static u32 tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor, + u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us, u32 timeout_us) +{ + u32 temp = timeout_us; + u32 reg_val = 0; + + do { + udelay(poll_interval_us); + reg_val = tegra_sor_readl(sor, reg); + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + } while ((reg_val & mask) != exp_val); + + if ((reg_val & mask) == exp_val) + return 0; /* success */ + printk(BIOS_ERR, + "sor_poll_register 0x%x: timeout, " + "(reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n", + reg, reg_val, mask, exp_val); + + return temp; +} + +int tegra_dc_sor_set_power_state(struct tegra_dc_sor_data *sor, int pu_pd) +{ + u32 reg_val; + u32 orig_val; + + orig_val = tegra_sor_readl(sor, NV_SOR_PWR); + + reg_val = pu_pd ? NV_SOR_PWR_NORMAL_STATE_PU : + NV_SOR_PWR_NORMAL_STATE_PD; /* normal state only */ + + if (reg_val == orig_val) + return 0; /* No update needed */ + + reg_val |= NV_SOR_PWR_SETTING_NEW_TRIGGER; + tegra_sor_writel(sor, NV_SOR_PWR, reg_val); + + /* Poll to confirm it is done */ + if (tegra_dc_sor_poll_register(sor, NV_SOR_PWR, + NV_SOR_PWR_SETTING_NEW_DEFAULT_MASK, + NV_SOR_PWR_SETTING_NEW_DONE, + 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { + printk(BIOS_ERR, + "dc timeout waiting for SOR_PWR = NEW_DONE\n"); + return -EFAULT; + } + return 0; +} + +void tegra_dc_sor_set_dp_linkctl(struct tegra_dc_sor_data *sor, int ena, + u8 training_pattern, const struct tegra_dc_dp_link_config *link_cfg) +{ + u32 reg_val; + + reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum)); + + if (ena) + reg_val |= NV_SOR_DP_LINKCTL_ENABLE_YES; + else + reg_val &= NV_SOR_DP_LINKCTL_ENABLE_NO; + + reg_val &= ~NV_SOR_DP_LINKCTL_TUSIZE_MASK; + reg_val |= (link_cfg->tu_size << NV_SOR_DP_LINKCTL_TUSIZE_SHIFT); + + if (link_cfg->enhanced_framing) + reg_val |= NV_SOR_DP_LINKCTL_ENHANCEDFRAME_ENABLE; + + tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val); + + switch (training_pattern) { + case training_pattern_1: + tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x41414141); + break; + case training_pattern_2: + case training_pattern_3: + reg_val = (link_cfg->link_bw == SOR_LINK_SPEED_G5_4) ? + 0x43434343 : 0x42424242; + tegra_sor_writel(sor, NV_SOR_DP_TPG, reg_val); + break; + default: + tegra_sor_writel(sor, NV_SOR_DP_TPG, 0x50505050); + break; + } +} + +static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor, + int pu, int is_lvds) +{ + u32 reg_val; + + /* SOR lane sequencer */ + if (pu) + reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER | + NV_SOR_LANE_SEQ_CTL_SEQUENCE_DOWN | + NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PU; + else + reg_val = NV_SOR_LANE_SEQ_CTL_SETTING_NEW_TRIGGER | + NV_SOR_LANE_SEQ_CTL_SEQUENCE_UP | + NV_SOR_LANE_SEQ_CTL_NEW_POWER_STATE_PD; + + if (is_lvds) + reg_val |= 15 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT; + else + reg_val |= 1 << NV_SOR_LANE_SEQ_CTL_DELAY_SHIFT; + + tegra_sor_writel(sor, NV_SOR_LANE_SEQ_CTL, reg_val); + + if (tegra_dc_sor_poll_register(sor, NV_SOR_LANE_SEQ_CTL, + NV_SOR_LANE_SEQ_CTL_SETTING_MASK, + NV_SOR_LANE_SEQ_CTL_SETTING_NEW_DONE, + 100, TEGRA_SOR_TIMEOUT_MS*1000)) { + printk(BIOS_ERR, + "dp: timeout while waiting for SOR lane sequencer " + "to power down langes\n"); + return -1; + } + return 0; +} + +static int tegra_dc_sor_power_dplanes(struct tegra_dc_sor_data *sor, + u32 lane_count, int pu) +{ + u32 reg_val; + + reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum)); + + if (pu) { + switch (lane_count) { + case 4: + reg_val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO | + NV_SOR_DP_PADCTL_PD_TXD_2_NO); + /* fall through */ + case 2: + reg_val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO; + case 1: + reg_val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO; + break; + default: + printk(BIOS_ERR, + "dp: invalid lane number %d\n", lane_count); + return -1; + } + + tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val); + tegra_dc_sor_set_lane_count(sor, lane_count); + } + return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0); +} + +void tegra_dc_sor_set_panel_power(struct tegra_dc_sor_data *sor, + int power_up) +{ + u32 reg_val; + + /* !!TODO: need to enable panel power through GPIO operations */ + /* Check bug 790854 for HW progress */ + + reg_val = tegra_sor_readl(sor, NV_SOR_DP_PADCTL(sor->portnum)); + + if (power_up) + reg_val |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP; + else + reg_val &= ~NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERUP; + + tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), reg_val); +} + +static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div, + u32 pwm_dutycycle) +{ + tegra_sor_writel(sor, NV_SOR_PWM_DIV, pwm_div); + tegra_sor_writel(sor, NV_SOR_PWM_CTL, + (pwm_dutycycle & NV_SOR_PWM_CTL_DUTY_CYCLE_MASK) | + NV_SOR_PWM_CTL_SETTING_NEW_TRIGGER); + + if (tegra_dc_sor_poll_register(sor, NV_SOR_PWM_CTL, + NV_SOR_PWM_CTL_SETTING_NEW_SHIFT, + NV_SOR_PWM_CTL_SETTING_NEW_DONE, + 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { + printk(BIOS_ERR, + "dp: timeout while waiting for SOR PWM setting\n"); + } +} + +static void tegra_dc_sor_set_dp_mode(struct tegra_dc_sor_data *sor, + const struct tegra_dc_dp_link_config *link_cfg) +{ + u32 reg_val; + + tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw); + + tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_none, link_cfg); + reg_val = tegra_sor_readl(sor, NV_SOR_DP_CONFIG(sor->portnum)); + reg_val &= ~NV_SOR_DP_CONFIG_WATERMARK_MASK; + reg_val |= link_cfg->watermark; + reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_MASK; + reg_val |= (link_cfg->active_count << + NV_SOR_DP_CONFIG_ACTIVESYM_COUNT_SHIFT); + reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_MASK; + reg_val |= (link_cfg->active_frac << + NV_SOR_DP_CONFIG_ACTIVESYM_FRAC_SHIFT); + if (link_cfg->activepolarity) + reg_val |= NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE; + else + reg_val &= ~NV_SOR_DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE; + reg_val |= (NV_SOR_DP_CONFIG_ACTIVESYM_CNTL_ENABLE | + NV_SOR_DP_CONFIG_RD_RESET_VAL_NEGATIVE); + + tegra_sor_writel(sor, NV_SOR_DP_CONFIG(sor->portnum), reg_val); + + /* program h/vblank sym */ + tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_HBLANK_SYMBOLS, + NV_SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK, link_cfg->hblank_sym); + + tegra_sor_write_field(sor, NV_SOR_DP_AUDIO_VBLANK_SYMBOLS, + NV_SOR_DP_AUDIO_VBLANK_SYMBOLS_MASK, link_cfg->vblank_sym); +} + +static inline void tegra_dc_sor_super_update(struct tegra_dc_sor_data *sor) +{ + tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0); + tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 1); + tegra_sor_writel(sor, NV_SOR_SUPER_STATE0, 0); +} + +static inline void tegra_dc_sor_update(struct tegra_dc_sor_data *sor) +{ + tegra_sor_writel(sor, NV_SOR_STATE0, 0); + tegra_sor_writel(sor, NV_SOR_STATE0, 1); + tegra_sor_writel(sor, NV_SOR_STATE0, 0); +} + +static void tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up) +{ + u32 reg_val; + void *pmc_base = sor->pmc_base; + + if (up) { + WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_ENABLE, + pmc_base + APBDEV_PMC_DPD_SAMPLE); + WRITEL(10, pmc_base + APBDEV_PMC_SEL_DPD_TIM); + } + + reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_REQ); + reg_val &= ~(APBDEV_PMC_IO_DPD2_REQ_LVDS_ON || + APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK); + + reg_val = up ? APBDEV_PMC_IO_DPD2_REQ_LVDS_ON | + APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF : + APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF | + APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON; + + WRITEL(reg_val, pmc_base + APBDEV_PMC_IO_DPD2_REQ); + + /* Polling */ + u32 temp = 10*1000; + do { + udelay(20); + reg_val = READL(pmc_base + APBDEV_PMC_IO_DPD2_STATUS); + if (temp > 20) + temp -= 20; + else + break; + } while ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0); + + if ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0) + printk(BIOS_ERR, + "PMC_IO_DPD2 polling failed (0x%x)\n", reg_val); + + if (up) + WRITEL(APBDEV_PMC_DPD_SAMPLE_ON_DISABLE, + pmc_base + APBDEV_PMC_DPD_SAMPLE); +} + +void tegra_dc_sor_set_internal_panel(struct tegra_dc_sor_data *sor, int is_int) +{ + u32 reg_val; + + reg_val = tegra_sor_readl(sor, NV_SOR_DP_SPARE(sor->portnum)); + if (is_int) + reg_val |= NV_SOR_DP_SPARE_PANEL_INTERNAL; + else + reg_val &= ~NV_SOR_DP_SPARE_PANEL_INTERNAL; + + reg_val |= NV_SOR_DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK | + NV_SOR_DP_SPARE_SEQ_ENABLE_YES; + tegra_sor_writel(sor, NV_SOR_DP_SPARE(sor->portnum), reg_val); +} + +void tegra_dc_sor_read_link_config(struct tegra_dc_sor_data *sor, u8 *link_bw, + u8 *lane_count) +{ + u32 reg_val; + + reg_val = tegra_sor_readl(sor, NV_SOR_CLK_CNTRL); + *link_bw = (reg_val & NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK) + >> NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT; + reg_val = tegra_sor_readl(sor, + NV_SOR_DP_LINKCTL(sor->portnum)); + + switch (reg_val & NV_SOR_DP_LINKCTL_LANECOUNT_MASK) { + case NV_SOR_DP_LINKCTL_LANECOUNT_ZERO: + *lane_count = 0; + break; + case NV_SOR_DP_LINKCTL_LANECOUNT_ONE: + *lane_count = 1; + break; + case NV_SOR_DP_LINKCTL_LANECOUNT_TWO: + *lane_count = 2; + break; + case NV_SOR_DP_LINKCTL_LANECOUNT_FOUR: + *lane_count = 4; + break; + default: + printk(BIOS_ERR, "Unknown lane count\n"); + } +} + +void tegra_dc_sor_set_link_bandwidth(struct tegra_dc_sor_data *sor, u8 link_bw) +{ + tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL, + NV_SOR_CLK_CNTRL_DP_LINK_SPEED_MASK, + link_bw << NV_SOR_CLK_CNTRL_DP_LINK_SPEED_SHIFT); +} + +void tegra_dc_sor_set_lane_count(struct tegra_dc_sor_data *sor, u8 lane_count) +{ + u32 reg_val; + + reg_val = tegra_sor_readl(sor, NV_SOR_DP_LINKCTL(sor->portnum)); + reg_val &= ~NV_SOR_DP_LINKCTL_LANECOUNT_MASK; + switch (lane_count) { + case 0: + break; + case 1: + reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_ONE; + break; + case 2: + reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_TWO; + break; + case 4: + reg_val |= NV_SOR_DP_LINKCTL_LANECOUNT_FOUR; + break; + default: + /* 0 should be handled earlier. */ + printk(BIOS_ERR, "dp: Invalid lane count %d\n", + lane_count); + return; + } + tegra_sor_writel(sor, NV_SOR_DP_LINKCTL(sor->portnum), reg_val); +} + +static void tegra_sor_enable_edp_clock(struct tegra_dc_sor_data *sor) +{ + sor_clock_start(); +} + +/* The SOR power sequencer does not work for t124 so SW has to + go through the power sequence manually */ +/* Power up steps from spec: */ +/* STEP PDPORT PDPLL PDBG PLLVCOD PLLCAPD E_DPD PDCAL */ +/* 1 1 1 1 1 1 1 1 */ +/* 2 1 1 1 1 1 0 1 */ +/* 3 1 1 0 1 1 0 1 */ +/* 4 1 0 0 0 0 0 1 */ +/* 5 0 0 0 0 0 0 1 */ +static void tegra_dc_sor_power_up(struct tegra_dc_sor_data *sor, + int is_lvds) +{ + if (sor->power_is_up) + return; + + /* Set link bw */ + tegra_dc_sor_set_link_bandwidth(sor, + is_lvds ? NV_SOR_CLK_CNTRL_DP_LINK_SPEED_LVDS : + NV_SOR_CLK_CNTRL_DP_LINK_SPEED_G1_62); + + /* step 1 */ + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK | /* PDPORT */ + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK | /* PDBG */ + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */ + NV_SOR_PLL2_AUX7_PORT_POWERDOWN_ENABLE | + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE | + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE); + tegra_sor_write_field(sor, NV_SOR_PLL0, + NV_SOR_PLL0_PWR_MASK | /* PDPLL */ + NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */ + NV_SOR_PLL0_PWR_OFF | + NV_SOR_PLL0_VCOPD_ASSERT); + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN, /* PDCAL */ + NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN); + + /* step 2 */ + tegra_dc_sor_io_set_dpd(sor, 1); + udelay(15); + + /* step 3 */ + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK, + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE); + udelay(25); + + /* step 4 */ + tegra_sor_write_field(sor, NV_SOR_PLL0, + NV_SOR_PLL0_PWR_MASK | /* PDPLL */ + NV_SOR_PLL0_VCOPD_MASK, /* PLLVCOPD */ + NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND); + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */ + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE); + udelay(225); + + /* step 5 */ + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK, /* PDPORT */ + NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE); + + sor->power_is_up = 1; +} + +#if DEBUG_SOR +static void dump_sor_reg(struct tegra_dc_sor_data *sor) +{ +#define DUMP_REG(a) printk(BIOS_INFO, "%-32s %03x %08x\n", \ + #a, a, tegra_sor_readl(sor, a)); + + DUMP_REG(NV_SOR_SUPER_STATE0); + DUMP_REG(NV_SOR_SUPER_STATE1); + DUMP_REG(NV_SOR_STATE0); + DUMP_REG(NV_SOR_STATE1); + DUMP_REG(NV_HEAD_STATE0(0)); + DUMP_REG(NV_HEAD_STATE0(1)); + DUMP_REG(NV_HEAD_STATE1(0)); + DUMP_REG(NV_HEAD_STATE1(1)); + DUMP_REG(NV_HEAD_STATE2(0)); + DUMP_REG(NV_HEAD_STATE2(1)); + DUMP_REG(NV_HEAD_STATE3(0)); + DUMP_REG(NV_HEAD_STATE3(1)); + DUMP_REG(NV_HEAD_STATE4(0)); + DUMP_REG(NV_HEAD_STATE4(1)); + DUMP_REG(NV_HEAD_STATE5(0)); + DUMP_REG(NV_HEAD_STATE5(1)); + DUMP_REG(NV_SOR_CRC_CNTRL); + DUMP_REG(NV_SOR_CLK_CNTRL); + DUMP_REG(NV_SOR_CAP); + DUMP_REG(NV_SOR_PWR); + DUMP_REG(NV_SOR_TEST); + DUMP_REG(NV_SOR_PLL0); + DUMP_REG(NV_SOR_PLL1); + DUMP_REG(NV_SOR_PLL2); + DUMP_REG(NV_SOR_PLL3); + DUMP_REG(NV_SOR_CSTM); + DUMP_REG(NV_SOR_LVDS); + DUMP_REG(NV_SOR_CRCA); + DUMP_REG(NV_SOR_CRCB); + DUMP_REG(NV_SOR_SEQ_CTL); + DUMP_REG(NV_SOR_LANE_SEQ_CTL); + DUMP_REG(NV_SOR_SEQ_INST(0)); + DUMP_REG(NV_SOR_SEQ_INST(1)); + DUMP_REG(NV_SOR_SEQ_INST(2)); + DUMP_REG(NV_SOR_SEQ_INST(3)); + DUMP_REG(NV_SOR_SEQ_INST(4)); + DUMP_REG(NV_SOR_SEQ_INST(5)); + DUMP_REG(NV_SOR_SEQ_INST(6)); + DUMP_REG(NV_SOR_SEQ_INST(7)); + DUMP_REG(NV_SOR_SEQ_INST(8)); + DUMP_REG(NV_SOR_PWM_DIV); + DUMP_REG(NV_SOR_PWM_CTL); + DUMP_REG(NV_SOR_MSCHECK); + DUMP_REG(NV_SOR_XBAR_CTRL); + DUMP_REG(NV_SOR_DP_LINKCTL(0)); + DUMP_REG(NV_SOR_DP_LINKCTL(1)); + DUMP_REG(NV_SOR_DC(0)); + DUMP_REG(NV_SOR_DC(1)); + DUMP_REG(NV_SOR_LANE_DRIVE_CURRENT(0)); + DUMP_REG(NV_SOR_PR(0)); + DUMP_REG(NV_SOR_LANE4_PREEMPHASIS(0)); + DUMP_REG(NV_SOR_POSTCURSOR(0)); + DUMP_REG(NV_SOR_DP_CONFIG(0)); + DUMP_REG(NV_SOR_DP_CONFIG(1)); + DUMP_REG(NV_SOR_DP_MN(0)); + DUMP_REG(NV_SOR_DP_MN(1)); + DUMP_REG(NV_SOR_DP_PADCTL(0)); + DUMP_REG(NV_SOR_DP_PADCTL(1)); + DUMP_REG(NV_SOR_DP_DEBUG(0)); + DUMP_REG(NV_SOR_DP_DEBUG(1)); + DUMP_REG(NV_SOR_DP_SPARE(0)); + DUMP_REG(NV_SOR_DP_SPARE(1)); + DUMP_REG(NV_SOR_DP_TPG); + + return; +} +#endif + +static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor, + int is_lvds) +{ + const struct tegra_dc *dc = sor->dc; + const struct tegra_dc_dp_data *dp = dc->out; + const struct tegra_dc_dp_link_config *link_cfg = &dp->link_cfg; + const struct soc_nvidia_tegra124_config *config = dc->config; + + const int head_num = 0; // based on kernel dc driver + u32 reg_val = NV_SOR_STATE1_ASY_OWNER_HEAD0 << head_num; + u32 vtotal, htotal; + u32 vsync_end, hsync_end; + u32 vblank_end, hblank_end; + u32 vblank_start, hblank_start; + + reg_val |= is_lvds ? NV_SOR_STATE1_ASY_PROTOCOL_LVDS_CUSTOM : + NV_SOR_STATE1_ASY_PROTOCOL_DP_A; + reg_val |= NV_SOR_STATE1_ASY_SUBOWNER_NONE | + NV_SOR_STATE1_ASY_CRCMODE_COMPLETE_RASTER; + + reg_val |= NV_SOR_STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE; + reg_val |= NV_SOR_STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE; + reg_val |= (link_cfg->bits_per_pixel > 18) ? + NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_24_444 : + NV_SOR_STATE1_ASY_PIXELDEPTH_BPP_18_444; + + tegra_sor_writel(sor, NV_SOR_STATE1, reg_val); + + /* Skipping programming NV_HEAD_STATE0, assuming: + interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB */ + + vtotal = config->vsync_width + config->vback_porch + + config->yres + config->vfront_porch; + htotal = config->hsync_width + config->hback_porch + + config->xres + config->hfront_porch; + + tegra_sor_writel(sor, NV_HEAD_STATE1(head_num), + vtotal << NV_HEAD_STATE1_VTOTAL_SHIFT | + htotal << NV_HEAD_STATE1_HTOTAL_SHIFT); + + vsync_end = config->vsync_width - 1; + hsync_end = config->hsync_width - 1; + tegra_sor_writel(sor, NV_HEAD_STATE2(head_num), + vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT | + hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT); + + vblank_end = vsync_end + config->vback_porch; + hblank_end = hsync_end + config->hback_porch; + tegra_sor_writel(sor, NV_HEAD_STATE3(head_num), + vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT | + hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT); + + vblank_start = vblank_end + config->yres; + hblank_start = hblank_end + config->xres; + tegra_sor_writel(sor, NV_HEAD_STATE4(head_num), + vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT | + hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT); + + /* TODO: adding interlace mode support */ + tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1); + + tegra_sor_write_field(sor, NV_SOR_CSTM, + NV_SOR_CSTM_ROTCLK_DEFAULT_MASK | + NV_SOR_CSTM_LVDS_EN_ENABLE, + 2 << NV_SOR_CSTM_ROTCLK_SHIFT | + is_lvds ? NV_SOR_CSTM_LVDS_EN_ENABLE : + NV_SOR_CSTM_LVDS_EN_DISABLE); + + tegra_dc_sor_config_pwm(sor, 1024, 1024); +} + +static void tegra_dc_sor_enable_dc(struct tegra_dc_sor_data *sor) +{ + struct tegra_dc *dc = sor->dc; + struct display_controller *disp_ctrl = (void *)dc->base; + + u32 reg_val = READL(&disp_ctrl->cmd.state_access); + + WRITEL(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access); + WRITEL(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt); + + /* Enable DC now - otherwise pure text console may not show. */ + WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); + WRITEL(reg_val, &disp_ctrl->cmd.state_access); +} + +void tegra_dc_sor_enable_dp(struct tegra_dc_sor_data *sor) +{ + const struct tegra_dc_dp_link_config *link_cfg = sor->link_cfg; + + tegra_sor_write_field(sor, NV_SOR_CLK_CNTRL, + NV_SOR_CLK_CNTRL_DP_CLK_SEL_MASK, + NV_SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK); + + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_MASK, + NV_SOR_PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE); + udelay(25); + + tegra_sor_write_field(sor, NV_SOR_PLL3, + NV_SOR_PLL3_PLLVDD_MODE_MASK, + NV_SOR_PLL3_PLLVDD_MODE_V3_3); + tegra_sor_writel(sor, NV_SOR_PLL0, + 0xf << NV_SOR_PLL0_ICHPMP_SHFIT | + 0x3 << NV_SOR_PLL0_VCOCAP_SHIFT | + NV_SOR_PLL0_PLLREG_LEVEL_V45 | + NV_SOR_PLL0_RESISTORSEL_EXT | + NV_SOR_PLL0_PWR_ON | NV_SOR_PLL0_VCOPD_RESCIND); + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX1_SEQ_MASK | NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE | + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, + NV_SOR_PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE | + NV_SOR_PLL2_AUX9_LVDSEN_OVERRIDE | + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE); + tegra_sor_writel(sor, NV_SOR_PLL1, + NV_SOR_PLL1_TERM_COMPOUT_HIGH | NV_SOR_PLL1_TMDS_TERM_ENABLE); + + if (tegra_dc_sor_poll_register(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, + NV_SOR_PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE, + 100, TEGRA_SOR_TIMEOUT_MS * 1000)) { + printk(BIOS_ERR, "DP failed to lock PLL\n"); + return; + } + + tegra_sor_write_field(sor, NV_SOR_PLL2, + NV_SOR_PLL2_AUX2_MASK | NV_SOR_PLL2_AUX7_PORT_POWERDOWN_MASK, + NV_SOR_PLL2_AUX2_OVERRIDE_POWERDOWN | + NV_SOR_PLL2_AUX7_PORT_POWERDOWN_DISABLE); + + tegra_dc_sor_power_up(sor, 0); + + /* re-enable SOR clock */ + tegra_sor_enable_edp_clock(sor); // select pll_dp as clock source + + /* Power up lanes */ + tegra_dc_sor_power_dplanes(sor, link_cfg->lane_count, 1); + + tegra_dc_sor_set_dp_mode(sor, link_cfg); + +} + +void tegra_dc_sor_attach(struct tegra_dc_sor_data *sor) +{ + u32 reg_val; + struct display_controller *disp_ctrl = (void *)sor->dc->base; + + tegra_dc_sor_enable_dc(sor); + tegra_dc_sor_config_panel(sor, 0); + + WRITEL(0x9f00, &disp_ctrl->cmd.state_ctrl); + WRITEL(0x9f, &disp_ctrl->cmd.state_ctrl); + + WRITEL(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | + PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE, + &disp_ctrl->cmd.disp_pow_ctrl); + + reg_val = tegra_sor_readl(sor, NV_SOR_TEST); + if (reg_val & NV_SOR_TEST_ATTACHED_TRUE) + return; + + tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, + NV_SOR_SUPER_STATE1_ATTACHED_NO); + + /* + * Enable display2sor clock at least 2 cycles before DC start, + * to clear sor internal valid signal. + */ + WRITEL(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt); + WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); + WRITEL(0, &disp_ctrl->disp.disp_win_opt); + WRITEL(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl); + + /* Attach head */ + tegra_dc_sor_update(sor); + tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, + NV_SOR_SUPER_STATE1_ATTACHED_YES); + tegra_sor_writel(sor, NV_SOR_SUPER_STATE1, + NV_SOR_SUPER_STATE1_ATTACHED_YES | + NV_SOR_SUPER_STATE1_ASY_HEAD_OP_AWAKE | + NV_SOR_SUPER_STATE1_ASY_ORMODE_NORMAL); + tegra_dc_sor_super_update(sor); + + /* Enable dc */ + reg_val = READL(&disp_ctrl->cmd.state_access); + WRITEL(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access); + WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); + WRITEL(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt); + WRITEL(reg_val, &disp_ctrl->cmd.state_access); + + if (tegra_dc_sor_poll_register(sor, NV_SOR_TEST, + NV_SOR_TEST_ACT_HEAD_OPMODE_DEFAULT_MASK, + NV_SOR_TEST_ACT_HEAD_OPMODE_AWAKE, + 100, TEGRA_SOR_ATTACH_TIMEOUT_MS * 1000)) + printk(BIOS_ERR, "dc timeout waiting for OPMOD = AWAKE\n"); + else + printk(BIOS_INFO, "%s: sor is attached\n", __func__); + +#if DEBUG_SOR + dump_sor_reg(sor); +#endif +} + +void tegra_dc_sor_set_lane_parm(struct tegra_dc_sor_data *sor, + const struct tegra_dc_dp_link_config *link_cfg) +{ + tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum), + link_cfg->drive_current); + tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), + link_cfg->preemphasis); + tegra_sor_writel(sor, NV_SOR_POSTCURSOR(sor->portnum), + link_cfg->postcursor); + tegra_sor_writel(sor, NV_SOR_LVDS, 0); + + tegra_dc_sor_set_link_bandwidth(sor, link_cfg->link_bw); + tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count); + + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + NV_SOR_DP_PADCTL_TX_PU_ENABLE | + NV_SOR_DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK, + NV_SOR_DP_PADCTL_TX_PU_ENABLE | + 2 << NV_SOR_DP_PADCTL_TX_PU_VALUE_SHIFT); + + /* Precharge */ + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + 0xf0, 0xf0); + udelay(20); + + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + 0xf0, 0x0); +} + +void tegra_dc_sor_set_voltage_swing(struct tegra_dc_sor_data *sor) +{ + u32 drive_current = 0; + u32 pre_emphasis = 0; + + /* Set to a known-good pre-calibrated setting */ + switch (sor->link_cfg->link_bw) { + case SOR_LINK_SPEED_G1_62: + case SOR_LINK_SPEED_G2_7: + drive_current = 0x13131313; + pre_emphasis = 0; + break; + case SOR_LINK_SPEED_G5_4: + printk(BIOS_WARNING, "T124 does not support 5.4G link clock.\n"); + default: + printk(BIOS_WARNING, "Invalid sor link bandwidth: %d\n", + sor->link_cfg->link_bw); + return; + } + + tegra_sor_writel(sor, NV_SOR_LANE_DRIVE_CURRENT(sor->portnum), + drive_current); + tegra_sor_writel(sor, NV_SOR_PR(sor->portnum), pre_emphasis); +} + +void tegra_dc_sor_power_down_unused_lanes(struct tegra_dc_sor_data *sor) +{ + u32 pad_ctrl = 0; + int err = 0; + + switch (sor->link_cfg->lane_count) { + case 4: + pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | + NV_SOR_DP_PADCTL_PD_TXD_1_NO | + NV_SOR_DP_PADCTL_PD_TXD_2_NO | + NV_SOR_DP_PADCTL_PD_TXD_3_NO); + break; + case 2: + pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | + NV_SOR_DP_PADCTL_PD_TXD_1_NO | + NV_SOR_DP_PADCTL_PD_TXD_2_YES | + NV_SOR_DP_PADCTL_PD_TXD_3_YES); + break; + case 1: + pad_ctrl = (NV_SOR_DP_PADCTL_PD_TXD_0_NO | + NV_SOR_DP_PADCTL_PD_TXD_1_YES | + NV_SOR_DP_PADCTL_PD_TXD_2_YES | + NV_SOR_DP_PADCTL_PD_TXD_3_YES); + break; + default: + printk(BIOS_ERR, "Invalid sor lane count: %u\n", + sor->link_cfg->lane_count); + return; + } + + pad_ctrl |= NV_SOR_DP_PADCTL_PAD_CAL_PD_POWERDOWN; + tegra_sor_writel(sor, NV_SOR_DP_PADCTL(sor->portnum), pad_ctrl); + + err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0); + if (err) { + printk(BIOS_ERR, + "Wait for lane power down failed: %d\n", err); + return; + } +} + +void tegra_sor_precharge_lanes(struct tegra_dc_sor_data *sor) +{ + const struct tegra_dc_dp_link_config *cfg = sor->link_cfg; + u32 val = 0; + + switch (cfg->lane_count) { + case 4: + val |= (NV_SOR_DP_PADCTL_PD_TXD_3_NO | + NV_SOR_DP_PADCTL_PD_TXD_2_NO); + /* fall through */ + case 2: + val |= NV_SOR_DP_PADCTL_PD_TXD_1_NO; + /* fall through */ + case 1: + val |= NV_SOR_DP_PADCTL_PD_TXD_0_NO; + break; + default: + printk(BIOS_ERR, + "dp: invalid lane number %d\n", cfg->lane_count); + return; + } + + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), + (val << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT)); + udelay(100); + tegra_sor_write_field(sor, NV_SOR_DP_PADCTL(sor->portnum), + (0xf << NV_SOR_DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT), 0); +} diff --git a/src/soc/nvidia/tegra124/spi.c b/src/soc/nvidia/tegra124/spi.c new file mode 100644 index 0000000000..8b0f941d07 --- /dev/null +++ b/src/soc/nvidia/tegra124/spi.c @@ -0,0 +1,934 @@ +/* + * NVIDIA Tegra SPI controller (T114 and later) + * + * Copyright (c) 2010-2013 NVIDIA Corporation + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI +# define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "TEGRA_SPI: " x) +#else +# define DEBUG_SPI(x,...) +#endif + +/* + * 64 packets in FIFO mode, BLOCK_SIZE packets in DMA mode. Packets can vary + * in size from 4 to 32 bits. To keep things simple we'll use 8-bit packets. + */ +#define SPI_PACKET_SIZE_BYTES 1 +#define SPI_MAX_TRANSFER_BYTES_FIFO (64 * SPI_PACKET_SIZE_BYTES) +#define SPI_MAX_TRANSFER_BYTES_DMA (65535 * SPI_PACKET_SIZE_BYTES) + +/* + * This is used to workaround an issue seen where it may take some time for + * packets to show up in the FIFO after they have been received and the + * BLOCK_COUNT has been incremented. + */ +#define SPI_FIFO_XFER_TIMEOUT_US 1000 + +/* COMMAND1 */ +#define SPI_CMD1_GO (1 << 31) +#define SPI_CMD1_M_S (1 << 30) +#define SPI_CMD1_MODE_MASK 0x3 +#define SPI_CMD1_MODE_SHIFT 28 +#define SPI_CMD1_CS_SEL_MASK 0x3 +#define SPI_CMD1_CS_SEL_SHIFT 26 +#define SPI_CMD1_CS_POL_INACTIVE3 (1 << 25) +#define SPI_CMD1_CS_POL_INACTIVE2 (1 << 24) +#define SPI_CMD1_CS_POL_INACTIVE1 (1 << 23) +#define SPI_CMD1_CS_POL_INACTIVE0 (1 << 22) +#define SPI_CMD1_CS_SW_HW (1 << 21) +#define SPI_CMD1_CS_SW_VAL (1 << 20) +#define SPI_CMD1_IDLE_SDA_MASK 0x3 +#define SPI_CMD1_IDLE_SDA_SHIFT 18 +#define SPI_CMD1_BIDIR (1 << 17) +#define SPI_CMD1_LSBI_FE (1 << 16) +#define SPI_CMD1_LSBY_FE (1 << 15) +#define SPI_CMD1_BOTH_EN_BIT (1 << 14) +#define SPI_CMD1_BOTH_EN_BYTE (1 << 13) +#define SPI_CMD1_RX_EN (1 << 12) +#define SPI_CMD1_TX_EN (1 << 11) +#define SPI_CMD1_PACKED (1 << 5) +#define SPI_CMD1_BIT_LEN_MASK 0x1f +#define SPI_CMD1_BIT_LEN_SHIFT 0 + +/* COMMAND2 */ +#define SPI_CMD2_TX_CLK_TAP_DELAY (1 << 6) +#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK (0x3F << 6) +#define SPI_CMD2_RX_CLK_TAP_DELAY (1 << 0) +#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK (0x3F << 0) + +/* SPI_TRANS_STATUS */ +#define SPI_STATUS_RDY (1 << 30) +#define SPI_STATUS_SLV_IDLE_COUNT_MASK 0xff +#define SPI_STATUS_SLV_IDLE_COUNT_SHIFT 16 +#define SPI_STATUS_BLOCK_COUNT 0xffff +#define SPI_STATUS_BLOCK_COUNT_SHIFT 0 + +/* SPI_FIFO_STATUS */ +#define SPI_FIFO_STATUS_CS_INACTIVE (1 << 31) +#define SPI_FIFO_STATUS_FRAME_END (1 << 30) +#define SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_MASK 0x7f +#define SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_SHIFT 23 +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY_COUNT_MASK 0x7f +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY_COUNT_SHIFT 16 +#define SPI_FIFO_STATUS_RX_FIFO_FLUSH (1 << 15) +#define SPI_FIFO_STATUS_TX_FIFO_FLUSH (1 << 14) +#define SPI_FIFO_STATUS_ERR (1 << 8) +#define SPI_FIFO_STATUS_TX_FIFO_OVF (1 << 7) +#define SPI_FIFO_STATUS_TX_FIFO_UNR (1 << 6) +#define SPI_FIFO_STATUS_RX_FIFO_OVF (1 << 5) +#define SPI_FIFO_STATUS_RX_FIFO_UNR (1 << 4) +#define SPI_FIFO_STATUS_TX_FIFO_FULL (1 << 3) +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY (1 << 2) +#define SPI_FIFO_STATUS_RX_FIFO_FULL (1 << 1) +#define SPI_FIFO_STATUS_RX_FIFO_EMPTY (1 << 0) + +/* SPI_DMA_CTL */ +#define SPI_DMA_CTL_DMA (1 << 31) +#define SPI_DMA_CTL_CONT (1 << 30) +#define SPI_DMA_CTL_IE_RX (1 << 29) +#define SPI_DMA_CTL_IE_TX (1 << 28) +#define SPI_DMA_CTL_RX_TRIG_MASK 0x3 +#define SPI_DMA_CTL_RX_TRIG_SHIFT 19 +#define SPI_DMA_CTL_TX_TRIG_MASK 0x3 +#define SPI_DMA_CTL_TX_TRIG_SHIFT 15 + +/* SPI_DMA_BLK */ +#define SPI_DMA_CTL_BLOCK_SIZE_MASK 0xffff +#define SPI_DMA_CTL_BLOCK_SIZE_SHIFT 0 + +static struct tegra_spi_channel tegra_spi_channels[] = { + /* + * Note: Tegra pinmux must be setup for corresponding SPI channel in + * order for its registers to be accessible. If pinmux has not been + * set up, access to the channel's registers will simply hang. + * + * TODO(dhendrix): Clarify or remove this comment (is clock setup + * necessary first, or just pinmux, or both?) + */ + { + .slave = { .bus = 1, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI1_BASE, + .req_sel = APBDMA_SLAVE_SL2B1, + }, + { + .slave = { .bus = 2, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI2_BASE, + .req_sel = APBDMA_SLAVE_SL2B2, + }, + { + .slave = { .bus = 3, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI3_BASE, + .req_sel = APBDMA_SLAVE_SL2B3, + }, + { + .slave = { .bus = 4, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI4_BASE, + .req_sel = APBDMA_SLAVE_SL2B4, + }, + { + .slave = { .bus = 5, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI5_BASE, + .req_sel = APBDMA_SLAVE_SL2B5, + }, + { + .slave = { .bus = 6, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI6_BASE, + .req_sel = APBDMA_SLAVE_SL2B6, + }, +}; + +enum spi_direction { + SPI_SEND, + SPI_RECEIVE, +}; + +struct tegra_spi_channel *tegra_spi_init(unsigned int bus) +{ + int i; + struct tegra_spi_channel *spi = NULL; + + for (i = 0; i < ARRAY_SIZE(tegra_spi_channels); i++) { + if (tegra_spi_channels[i].slave.bus == bus) { + spi = &tegra_spi_channels[i]; + break; + } + } + if (!spi) + return NULL; + + /* software drives chip-select, set value to high */ + setbits_le32(&spi->regs->command1, + SPI_CMD1_CS_SW_HW | SPI_CMD1_CS_SW_VAL); + + /* 8-bit transfers, unpacked mode, most significant bit first */ + clrbits_le32(&spi->regs->command1, + SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED); + setbits_le32(&spi->regs->command1, 7 << SPI_CMD1_BIT_LEN_SHIFT); + + return spi; +} + +static struct tegra_spi_channel * const to_tegra_spi(int bus) { + return &tegra_spi_channels[bus - 1]; +} + +static unsigned int tegra_spi_speed(unsigned int bus) +{ + /* FIXME: implement this properly, for now use max value (50MHz) */ + return 50000000; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs; + u32 val; + + tegra_spi_init(slave->bus); + + val = read32(®s->command1); + + /* select appropriate chip-select line */ + val &= ~(SPI_CMD1_CS_SEL_MASK << SPI_CMD1_CS_SEL_SHIFT); + val |= (slave->cs << SPI_CMD1_CS_SEL_SHIFT); + + /* drive chip-select with the inverse of the "inactive" value */ + if (val & (SPI_CMD1_CS_POL_INACTIVE0 << slave->cs)) + val &= ~SPI_CMD1_CS_SW_VAL; + else + val |= SPI_CMD1_CS_SW_VAL; + + write32(val, ®s->command1); + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs; + u32 val; + + val = read32(®s->command1); + + if (val & (SPI_CMD1_CS_POL_INACTIVE0 << slave->cs)) + val |= SPI_CMD1_CS_SW_VAL; + else + val &= ~SPI_CMD1_CS_SW_VAL; + + write32(val, ®s->command1); +} + +static void dump_fifo_status(struct tegra_spi_channel *spi) +{ + u32 status = read32(&spi->regs->fifo_status); + + printk(BIOS_INFO, "Raw FIFO status: 0x%08x\n", status); + if (status & SPI_FIFO_STATUS_TX_FIFO_OVF) + printk(BIOS_INFO, "\tTx overflow detected\n"); + if (status & SPI_FIFO_STATUS_TX_FIFO_UNR) + printk(BIOS_INFO, "\tTx underrun detected\n"); + if (status & SPI_FIFO_STATUS_RX_FIFO_OVF) + printk(BIOS_INFO, "\tRx overflow detected\n"); + if (status & SPI_FIFO_STATUS_RX_FIFO_UNR) + printk(BIOS_INFO, "\tRx underrun detected\n"); + + printk(BIOS_INFO, "TX_FIFO: 0x%08x, TX_DATA: 0x%08x\n", + read32(&spi->regs->tx_fifo), read32(&spi->regs->tx_data)); + printk(BIOS_INFO, "RX_FIFO: 0x%08x, RX_DATA: 0x%08x\n", + read32(&spi->regs->rx_fifo), read32(&spi->regs->rx_data)); +} + +static void clear_fifo_status(struct tegra_spi_channel *spi) +{ + clrbits_le32(&spi->regs->fifo_status, + SPI_FIFO_STATUS_ERR | + SPI_FIFO_STATUS_TX_FIFO_OVF | + SPI_FIFO_STATUS_TX_FIFO_UNR | + SPI_FIFO_STATUS_RX_FIFO_OVF | + SPI_FIFO_STATUS_RX_FIFO_UNR); +} + +static void dump_spi_regs(struct tegra_spi_channel *spi) +{ + printk(BIOS_INFO, "SPI regs:\n" + "\tdma_blk: 0x%08x\n" + "\tcommand1: 0x%08x\n" + "\tdma_ctl: 0x%08x\n" + "\ttrans_status: 0x%08x\n", + read32(&spi->regs->dma_blk), + read32(&spi->regs->command1), + read32(&spi->regs->dma_ctl), + read32(&spi->regs->trans_status)); +} + +static void dump_dma_regs(struct apb_dma_channel *dma) +{ + printk(BIOS_INFO, "DMA regs:\n" + "\tahb_ptr: 0x%08x\n" + "\tapb_ptr: 0x%08x\n" + "\tahb_seq: 0x%08x\n" + "\tapb_seq: 0x%08x\n" + "\tcsr: 0x%08x\n" + "\tcsre: 0x%08x\n" + "\twcount: 0x%08x\n" + "\tdma_byte_sta: 0x%08x\n" + "\tword_transfer: 0x%08x\n", + read32(&dma->regs->ahb_ptr), + read32(&dma->regs->apb_ptr), + read32(&dma->regs->ahb_seq), + read32(&dma->regs->apb_seq), + read32(&dma->regs->csr), + read32(&dma->regs->csre), + read32(&dma->regs->wcount), + read32(&dma->regs->dma_byte_sta), + read32(&dma->regs->word_transfer)); +} + +static inline unsigned int spi_byte_count(struct tegra_spi_channel *spi) +{ + /* FIXME: Make this take total packet size into account */ + return read32(&spi->regs->trans_status) & + (SPI_STATUS_BLOCK_COUNT << SPI_STATUS_BLOCK_COUNT_SHIFT); +} + +/* + * This calls udelay() with a calculated value based on the SPI speed and + * number of bytes remaining to be transferred. It assumes that if the + * calculated delay period is less than MIN_DELAY_US then it is probably + * not worth the overhead of yielding. + */ +#define MIN_DELAY_US 250 +static void spi_delay(struct tegra_spi_channel *spi, + unsigned int bytes_remaining) +{ + unsigned int ns_per_byte, delay_us; + + ns_per_byte = 1000000000 / (tegra_spi_speed(spi->slave.bus) / 8); + delay_us = (ns_per_byte * bytes_remaining) / 1000; + + if (delay_us < MIN_DELAY_US) + return; + + udelay(delay_us); +} + +static void tegra_spi_wait(struct tegra_spi_channel *spi) +{ + unsigned int count, dma_blk; + + dma_blk = 1 + (read32(&spi->regs->dma_blk) & + (SPI_DMA_CTL_BLOCK_SIZE_MASK << SPI_DMA_CTL_BLOCK_SIZE_SHIFT)); + + while ((count = spi_byte_count(spi)) != dma_blk) + spi_delay(spi, dma_blk - count); +} + + +static int fifo_error(struct tegra_spi_channel *spi) +{ + return read32(&spi->regs->fifo_status) & SPI_FIFO_STATUS_ERR ? 1 : 0; +} + +static int tegra_spi_pio_prepare(struct tegra_spi_channel *spi, + unsigned int bytes, enum spi_direction dir) +{ + u8 *p = spi->out_buf; + unsigned int todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_FIFO); + u32 flush_mask, enable_mask; + + if (dir == SPI_SEND) { + flush_mask = SPI_FIFO_STATUS_TX_FIFO_FLUSH; + enable_mask = SPI_CMD1_TX_EN; + } else { + flush_mask = SPI_FIFO_STATUS_RX_FIFO_FLUSH; + enable_mask = SPI_CMD1_RX_EN; + } + + setbits_le32(&spi->regs->fifo_status, flush_mask); + while (read32(&spi->regs->fifo_status) & flush_mask) + ; + + setbits_le32(&spi->regs->command1, enable_mask); + + /* BLOCK_SIZE in SPI_DMA_BLK register applies to both DMA and + * PIO transfers */ + write32(todo - 1, &spi->regs->dma_blk); + + if (dir == SPI_SEND) { + unsigned int to_fifo = bytes; + while (to_fifo) { + write32(*p, &spi->regs->tx_fifo); + p++; + to_fifo--; + } + } + + return todo; +} + +static void tegra_spi_pio_start(struct tegra_spi_channel *spi) +{ + setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY); + setbits_le32(&spi->regs->command1, SPI_CMD1_GO); + /* Make sure the write to command1 completes. */ + read32(&spi->regs->command1); +} + +static inline u32 rx_fifo_count(struct tegra_spi_channel *spi) +{ + return (read32(&spi->regs->fifo_status) >> + SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_SHIFT) & + SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_MASK; +} + +static int tegra_spi_pio_finish(struct tegra_spi_channel *spi) +{ + u8 *p = spi->in_buf; + struct stopwatch sw; + + clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN | SPI_CMD1_TX_EN); + + /* + * Allow some time in case the Rx FIFO does not yet have + * all packets pushed into it. See chrome-os-partner:24215. + */ + stopwatch_init_usecs_expire(&sw, SPI_FIFO_XFER_TIMEOUT_US); + do { + if (rx_fifo_count(spi) == spi_byte_count(spi)) + break; + } while (!stopwatch_expired(&sw)); + + while (!(read32(&spi->regs->fifo_status) & + SPI_FIFO_STATUS_RX_FIFO_EMPTY)) { + *p = read8(&spi->regs->rx_fifo); + p++; + } + + if (fifo_error(spi)) { + printk(BIOS_ERR, "%s: ERROR:\n", __func__); + dump_spi_regs(spi); + dump_fifo_status(spi); + return -1; + } + + return 0; +} + +static void setup_dma_params(struct tegra_spi_channel *spi, + struct apb_dma_channel *dma) +{ + /* APB bus width = 8-bits, address wrap for each word */ + clrbits_le32(&dma->regs->apb_seq, + APB_BUS_WIDTH_MASK << APB_BUS_WIDTH_SHIFT); + /* AHB 1 word burst, bus width = 32 bits (fixed in hardware), + * no address wrapping */ + clrsetbits_le32(&dma->regs->ahb_seq, + (AHB_BURST_MASK << AHB_BURST_SHIFT), + 4 << AHB_BURST_SHIFT); + + /* Set ONCE mode to transfer one "block" at a time (64KB) and enable + * flow control. */ + clrbits_le32(&dma->regs->csr, + APB_CSR_REQ_SEL_MASK << APB_CSR_REQ_SEL_SHIFT); + setbits_le32(&dma->regs->csr, APB_CSR_ONCE | APB_CSR_FLOW | + (spi->req_sel << APB_CSR_REQ_SEL_SHIFT)); +} + +static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi, + unsigned int bytes, enum spi_direction dir) +{ + unsigned int todo, wcount; + + /* + * For DMA we need to think of things in terms of word count. + * AHB width is fixed at 32-bits. To avoid overrunning + * the in/out buffers we must align down. (Note: lowest 2-bits + * in WCOUNT register are ignored, and WCOUNT seems to count + * words starting at n-1) + * + * Example: If "bytes" is 7 and we are transferring 1-byte at a time, + * WCOUNT should be 4. The remaining 3 bytes must be transferred + * using PIO. + */ + todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_DMA - TEGRA_DMA_ALIGN_BYTES); + todo = ALIGN_DOWN(todo, TEGRA_DMA_ALIGN_BYTES); + wcount = ALIGN_DOWN(todo - TEGRA_DMA_ALIGN_BYTES, TEGRA_DMA_ALIGN_BYTES); + + if (dir == SPI_SEND) { + spi->dma_out = dma_claim(); + if (!spi->dma_out) + return -1; + + /* ensure bytes to send will be visible to DMA controller */ + dcache_clean_by_mva(spi->out_buf, bytes); + + write32((u32)&spi->regs->tx_fifo, &spi->dma_out->regs->apb_ptr); + write32((u32)spi->out_buf, &spi->dma_out->regs->ahb_ptr); + setbits_le32(&spi->dma_out->regs->csr, APB_CSR_DIR); + setup_dma_params(spi, spi->dma_out); + write32(wcount, &spi->dma_out->regs->wcount); + } else { + spi->dma_in = dma_claim(); + if (!spi->dma_in) + return -1; + + /* avoid data collisions */ + dcache_clean_invalidate_by_mva(spi->in_buf, bytes); + + write32((u32)&spi->regs->rx_fifo, &spi->dma_in->regs->apb_ptr); + write32((u32)spi->in_buf, &spi->dma_in->regs->ahb_ptr); + clrbits_le32(&spi->dma_in->regs->csr, APB_CSR_DIR); + setup_dma_params(spi, spi->dma_in); + write32(wcount, &spi->dma_in->regs->wcount); + } + + /* BLOCK_SIZE starts at n-1 */ + write32(todo - 1, &spi->regs->dma_blk); + return todo; +} + +static void tegra_spi_dma_start(struct tegra_spi_channel *spi) +{ + /* + * The RDY bit in SPI_TRANS_STATUS needs to be cleared manually + * (set bit to clear) between each transaction. Otherwise the next + * transaction does not start. + */ + setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY); + + if (spi->dma_out) + setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN); + if (spi->dma_in) + setbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN); + + /* + * To avoid underrun conditions, enable APB DMA before SPI DMA for + * Tx and enable SPI DMA before APB DMA before Rx. + */ + if (spi->dma_out) + dma_start(spi->dma_out); + setbits_le32(&spi->regs->dma_ctl, SPI_DMA_CTL_DMA); + if (spi->dma_in) + dma_start(spi->dma_in); + + +} + +static int tegra_spi_dma_finish(struct tegra_spi_channel *spi) +{ + int ret; + unsigned int todo; + + todo = read32(&spi->dma_in->regs->wcount); + + if (spi->dma_in) { + while ((read32(&spi->dma_in->regs->dma_byte_sta) < todo) || + dma_busy(spi->dma_in)) + ; /* this shouldn't take long, no udelay */ + dma_stop(spi->dma_in); + clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN); + dma_release(spi->dma_in); + } + + if (spi->dma_out) { + while ((read32(&spi->dma_out->regs->dma_byte_sta) < todo) || + dma_busy(spi->dma_out)) + spi_delay(spi, todo - spi_byte_count(spi)); + clrbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN); + dma_stop(spi->dma_out); + dma_release(spi->dma_out); + } + + if (fifo_error(spi)) { + printk(BIOS_ERR, "%s: ERROR:\n", __func__); + dump_dma_regs(spi->dma_out); + dump_dma_regs(spi->dma_in); + dump_spi_regs(spi); + dump_fifo_status(spi); + ret = -1; + goto done; + } + + ret = 0; +done: + spi->dma_in = NULL; + spi->dma_out = NULL; + return ret; +} + +/* + * xfer_setup() prepares a transfer. It does sanity checking, alignment, and + * sets transfer mode used by this channel (if not set already). + * + * A few caveats to watch out for: + * - The number of bytes which can be transferred may be smaller than the + * number of bytes the caller specifies. The number of bytes ready for + * a transfer will be returned (unless an error occurs). + * + * - Only one mode can be used for both RX and TX. The transfer mode of the + * SPI channel (spi->xfer_mode) is checked each time this function is called. + * If conflicting modes are detected, spi->xfer_mode will be set to + * XFER_MODE_NONE and an error will be returned. + * + * Returns bytes ready for transfer if successful, <0 to indicate error. + */ +static int xfer_setup(struct tegra_spi_channel *spi, void *buf, + unsigned int bytes, enum spi_direction dir) +{ + unsigned int line_size = dcache_line_bytes(); + unsigned int align; + int ret = -1; + + if (!bytes) + return 0; + + if (dir == SPI_SEND) + spi->out_buf = buf; + else if (dir == SPI_RECEIVE) + spi->in_buf = buf; + + /* + * Alignment consideratons: + * When we enable caching we'll need to clean/invalidate portions of + * memory. So we need to be careful about memory alignment. Also, DMA + * likes to operate on 4-bytes at a time on the AHB side. So for + * example, if we only want to receive 1 byte, 4 bytes will be be + * written in memory even if those extra 3 bytes are beyond the length + * we want. + * + * For now we'll use PIO to send/receive unaligned bytes. We may + * consider setting aside some space for a kind of bounce buffer to + * stay in DMA mode once we have a chance to benchmark the two + * approaches. + */ + + if (bytes < line_size) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, bytes, dir); + } + goto done; + } + + /* transfer bytes before the aligned boundary */ + align = line_size - ((uintptr_t)buf % line_size); + if ((align != 0) && (align != line_size)) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, align, dir); + } + goto done; + } + + /* do aligned DMA transfer */ + align = (((uintptr_t)buf + bytes) % line_size); + if (bytes - align > 0) { + unsigned int dma_bytes = bytes - align; + + if (spi->xfer_mode == XFER_MODE_PIO) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_DMA; + ret = tegra_spi_dma_prepare(spi, dma_bytes, dir); + } + + goto done; + } + + /* transfer any remaining unaligned bytes */ + if (align) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, align, dir); + } + goto done; + } + +done: + return ret; +} + +static void xfer_start(struct tegra_spi_channel *spi) +{ + if (spi->xfer_mode == XFER_MODE_DMA) + tegra_spi_dma_start(spi); + else + tegra_spi_pio_start(spi); +} + +static void xfer_wait(struct tegra_spi_channel *spi) +{ + tegra_spi_wait(spi); +} + +static int xfer_finish(struct tegra_spi_channel *spi) +{ + int ret; + + if (spi->xfer_mode == XFER_MODE_DMA) + ret = tegra_spi_dma_finish(spi); + else + ret = tegra_spi_pio_finish(spi); + + spi->xfer_mode = XFER_MODE_NONE; + return ret; +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int out_bytes, void *din, unsigned int in_bytes) +{ + struct tegra_spi_channel *spi = to_tegra_spi(slave->bus); + u8 *out_buf = (u8 *)dout; + u8 *in_buf = (u8 *)din; + unsigned int todo; + int ret = 0; + + /* tegra bus numbers start at 1 */ + ASSERT(slave->bus >= 1 && slave->bus <= ARRAY_SIZE(tegra_spi_channels)); + + while (out_bytes || in_bytes) { + int x = 0; + + if (out_bytes == 0) + todo = in_bytes; + else if (in_bytes == 0) + todo = out_bytes; + else + todo = MIN(out_bytes, in_bytes); + + if (out_bytes) { + x = xfer_setup(spi, out_buf, todo, SPI_SEND); + if (x < 0) { + if (spi->xfer_mode == XFER_MODE_NONE) { + spi->xfer_mode = XFER_MODE_PIO; + continue; + } else { + ret = -1; + break; + } + } + } + if (in_bytes) { + x = xfer_setup(spi, in_buf, todo, SPI_RECEIVE); + if (x < 0) { + if (spi->xfer_mode == XFER_MODE_NONE) { + spi->xfer_mode = XFER_MODE_PIO; + continue; + } else { + ret = -1; + break; + } + } + } + + /* + * Note: Some devices (such as Chrome EC) are sensitive to + * delays, so be careful when adding debug prints not to + * cause timeouts between transfers. + */ + xfer_start(spi); + xfer_wait(spi); + if (xfer_finish(spi)) { + ret = -1; + break; + } + + /* Post-processing. */ + if (out_bytes) { + out_bytes -= x; + out_buf += x; + } + if (in_bytes) { + in_bytes -= x; + in_buf += x; + } + } + + if (ret < 0) { + printk(BIOS_ERR, "%s: Error detected\n", __func__); + printk(BIOS_ERR, "Transaction size: %u, bytes remaining: " + "%u out / %u in\n", todo, out_bytes, in_bytes); + clear_fifo_status(spi); + } + return ret; +} + +/* SPI as CBFS media. */ +struct tegra_spi_media { + struct spi_slave *slave; + struct cbfs_simple_buffer buffer; +}; + +static int tegra_spi_cbfs_open(struct cbfs_media *media) +{ + DEBUG_SPI("tegra_spi_cbfs_open\n"); + return 0; +} + +static int tegra_spi_cbfs_close(struct cbfs_media *media) +{ + DEBUG_SPI("tegra_spi_cbfs_close\n"); + return 0; +} + +#define JEDEC_READ 0x03 +#define JEDEC_READ_OUTSIZE 0x04 +#define JEDEC_FAST_READ_DUAL 0x3b +#define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05 + +static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context; + u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE]; + unsigned int read_cmd_bytes; + int ret = count; + struct tegra_spi_channel *channel; + + channel = to_tegra_spi(spi->slave->bus); + + if (channel->dual_mode) { + /* + * Command 0x3b will interleave data only, command 0xbb will + * interleave the address as well. It's nice to see the address + * plainly when debugging, and we're mostly concerned with + * large transfers so the optimization of using 0xbb isn't + * really worthwhile. + */ + spi_read_cmd[0] = JEDEC_FAST_READ_DUAL; + spi_read_cmd[4] = 0x00; /* dummy byte */ + read_cmd_bytes = JEDEC_FAST_READ_DUAL_OUTSIZE; + } else { + spi_read_cmd[0] = JEDEC_READ; + read_cmd_bytes = JEDEC_READ_OUTSIZE; + } + spi_read_cmd[1] = (offset >> 16) & 0xff; + spi_read_cmd[2] = (offset >> 8) & 0xff; + spi_read_cmd[3] = offset & 0xff; + + spi_claim_bus(spi->slave); + + if (spi_xfer(spi->slave, spi_read_cmd, + read_cmd_bytes, NULL, 0) < 0) { + ret = -1; + printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n", + __func__, sizeof(spi_read_cmd)); + goto tegra_spi_cbfs_read_exit; + } + + if (channel->dual_mode) { + setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); + } + if (spi_xfer(spi->slave, NULL, 0, dest, count)) { + ret = -1; + printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n", + __func__, count); + } + if (channel->dual_mode) + clrbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); + +tegra_spi_cbfs_read_exit: + /* de-assert /CS */ + spi_release_bus(spi->slave); + return (ret < 0) ? 0 : ret; +} + +static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; + void *map; + DEBUG_SPI("tegra_spi_cbfs_map\n"); + map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count); + return map; +} + +static void *tegra_spi_cbfs_unmap(struct cbfs_media *media, + const void *address) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; + DEBUG_SPI("tegra_spi_cbfs_unmap\n"); + return cbfs_simple_buffer_unmap(&spi->buffer, address); +} + +int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size) +{ + // TODO Replace static variable to support multiple streams. + static struct tegra_spi_media context; + static struct tegra_spi_channel *channel; + + channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; + channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT; + + DEBUG_SPI("Initializing CBFS media on SPI\n"); + + context.slave = &channel->slave; + context.buffer.allocated = context.buffer.last_allocate = 0; + context.buffer.buffer = buffer_address; + context.buffer.size = buffer_size; + media->context = (void*)&context; + media->open = tegra_spi_cbfs_open; + media->close = tegra_spi_cbfs_close; + media->read = tegra_spi_cbfs_read; + media->map = tegra_spi_cbfs_map; + media->unmap = tegra_spi_cbfs_unmap; + +#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1 + channel->dual_mode = 1; +#endif + + return 0; +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + struct tegra_spi_channel *channel = to_tegra_spi(bus); + if (!channel) + return NULL; + + return &channel->slave; +} diff --git a/src/soc/nvidia/tegra124/uart.c b/src/soc/nvidia/tegra124/uart.c new file mode 100644 index 0000000000..372b139138 --- /dev/null +++ b/src/soc/nvidia/tegra124/uart.c @@ -0,0 +1,137 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include /* for __console definition */ +#include +#include +#include + +struct tegra124_uart { + union { + uint32_t thr; // Transmit holding register. + uint32_t rbr; // Receive buffer register. + uint32_t dll; // Divisor latch lsb. + }; + union { + uint32_t ier; // Interrupt enable register. + uint32_t dlm; // Divisor latch msb. + }; + union { + uint32_t iir; // Interrupt identification register. + uint32_t fcr; // FIFO control register. + }; + uint32_t lcr; // Line control register. + uint32_t mcr; // Modem control register. + uint32_t lsr; // Line status register. + uint32_t msr; // Modem status register. +} __attribute__ ((packed)); + +static struct tegra124_uart * const uart_ptr = + (void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + +static void tegra124_uart_tx_flush(void); +static int tegra124_uart_tst_byte(void); + +static void tegra124_uart_init(void) +{ + // Use a hardcoded divisor for now. + const unsigned divisor = 221; + const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1 + + tegra124_uart_tx_flush(); + + // Disable interrupts. + write8(0, &uart_ptr->ier); + // Force DTR and RTS to high. + write8(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr); + // Set line configuration, access divisor latches. + write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr); + // Set the divisor. + write8(divisor & 0xff, &uart_ptr->dll); + write8((divisor >> 8) & 0xff, &uart_ptr->dlm); + // Hide the divisor latches. + write8(line_config, &uart_ptr->lcr); + // Enable FIFOs, and clear receive and transmit. + write8(UART8250_FCR_FIFO_EN | + UART8250_FCR_CLEAR_RCVR | + UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr); +} + +static void tegra124_uart_tx_byte(unsigned char data) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE)); + write8(data, &uart_ptr->thr); +} + +static void tegra124_uart_tx_flush(void) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT)); +} + +static unsigned char tegra124_uart_rx_byte(void) +{ + if (!tegra124_uart_tst_byte()) + return 0; + return read8(&uart_ptr->rbr); +} + +static int tegra124_uart_tst_byte(void) +{ + return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR; +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver tegra124_uart_console __console = { + .init = tegra124_uart_init, + .tx_byte = tegra124_uart_tx_byte, + .tx_flush = tegra124_uart_tx_flush, + .rx_byte = tegra124_uart_rx_byte, + .tst_byte = tegra124_uart_tst_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return (uintptr_t)uart_ptr; +} + +#else + +void uart_init(void) +{ + tegra124_uart_init(); +} + +void uart_tx_byte(unsigned char data) +{ + tegra124_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ + tegra124_uart_tx_flush(); +} + +unsigned char uart_rx_byte(void) +{ + return tegra124_uart_rx_byte(); +} + +#endif diff --git a/src/soc/nvidia/tegra124/verstage.c b/src/soc/nvidia/tegra124/verstage.c new file mode 100644 index 0000000000..2d7a9530b6 --- /dev/null +++ b/src/soc/nvidia/tegra124/verstage.c @@ -0,0 +1,71 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void enable_cache(void) +{ + mmu_init(); + /* Whole space is uncached. */ + mmu_config_range(0, 4096, DCACHE_OFF); + /* SRAM is cached. MMU code will round size up to page size. */ + mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB), + DCACHE_WRITEBACK); + mmu_disable_range(0, 1); + dcache_mmu_enable(); +} + +/* Do the minimum to run vboot at full speed */ +static void soc_init(void) +{ + configure_l2_cache(); + console_init(); + exception_init(); + enable_cache(); +} + +static void verstage(void) +{ + void *entry; + + soc_init(); + early_mainboard_init(); + + entry = vboot2_verify_firmware(); + if (entry != (void *)-1) + stage_exit(entry); +} + +void main(void) +{ + asm volatile ("bl arm_init_caches" + : : : "r0", "r1", "r2", "r3", "r4", "r5", "ip"); + + verstage(); + hlt(); +} diff --git a/src/soc/nvidia/tegra132/32bit_reset.S b/src/soc/nvidia/tegra132/32bit_reset.S new file mode 100644 index 0000000000..ce92dc50de --- /dev/null +++ b/src/soc/nvidia/tegra132/32bit_reset.S @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This code is compiled for both arm64 and arm4, however the code is only + * executed by the armv8 cores coming out of reset. + */ + +#if !defined(__PRE_RAM__) +#define INST .inst +#else +#define INST .word +#endif + +/* + * The Denver cores come up in aarch32 mode. In order to transition to + * 64-bit mode a write to the RMR (reest mangement register) with the + * AA64 bit (0) set while setting RR (reset request bit 1). + */ +.align 6 +.global reset_entry_32bit +reset_entry_32bit: + INST 0xe3a00003 /* mov r0, #3 */ + INST 0xee0c0f50 /* mcr 15, 0, r0, cr12, cr0, {2} */ + INST 0xeafffffe /* b . */ diff --git a/src/soc/nvidia/tegra132/Kconfig b/src/soc/nvidia/tegra132/Kconfig new file mode 100644 index 0000000000..a16c9a3679 --- /dev/null +++ b/src/soc/nvidia/tegra132/Kconfig @@ -0,0 +1,118 @@ +config SOC_NVIDIA_TEGRA132 + bool + default n + select ARCH_BOOTBLOCK_ARM_V4 + select ARCH_VERSTAGE_ARM_V4 + select ARCH_ROMSTAGE_ARM_V4 + select ARCH_RAMSTAGE_ARM_V8_64 + select BOOTBLOCK_CONSOLE + select GIC + select HAVE_MONOTONIC_TIMER + select GENERIC_UDELAY + select HAVE_HARD_RESET + select HAVE_UART_SPECIAL + select HAVE_UART_MEMORY_MAPPED + select EARLY_CONSOLE + select ARM_BOOTBLOCK_CUSTOM + select DYNAMIC_CBMEM + select SMP + select ARCH_USE_SECURE_MONITOR + select COLLECT_TIMESTAMPS + select HAS_PRECBMEM_TIMESTAMP_REGION + select CHROMEOS_RAMOOPS_NON_ACPI + select GENERIC_GPIO_LIB + +if SOC_NVIDIA_TEGRA132 + +config MAINBOARD_DO_DSI_INIT + bool "Use dsi graphics interface" + depends on MAINBOARD_DO_NATIVE_VGA_INIT + default n + help + Initialize dsi display + +config MAINBOARD_DO_SOR_INIT + bool "Use dp graphics interface" + depends on MAINBOARD_DO_NATIVE_VGA_INIT + default n + help + Initialize dp display + +config BOOTBLOCK_CPU_INIT + string + default "soc/nvidia/tegra132/bootblock.c" + help + CPU/SoC-specific bootblock code. This is useful if the + bootblock must load microcode or copy data from ROM before + searching for the bootblock. + +config MAX_CPUS + int + default 2 + +choice CONSOLE_SERIAL_TEGRA132_UART_CHOICES + prompt "Serial Console UART" + default CONSOLE_SERIAL_TEGRA132_UARTA + depends on CONSOLE_SERIAL_UART + +config CONSOLE_SERIAL_TEGRA132_UARTA + bool "UARTA" + help + Serial console on UART A. + +config CONSOLE_SERIAL_TEGRA132_UARTB + bool "UARTB" + help + Serial console on UART B. + +config CONSOLE_SERIAL_TEGRA132_UARTC + bool "UARTC" + help + Serial console on UART C. + +config CONSOLE_SERIAL_TEGRA132_UARTD + bool "UARTD" + help + Serial console on UART D. + +config CONSOLE_SERIAL_TEGRA132_UARTE + bool "UARTE" + help + Serial console on UART E. + +endchoice + +config CONSOLE_SERIAL_TEGRA132_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0x70006000 if CONSOLE_SERIAL_TEGRA132_UARTA + default 0x70006040 if CONSOLE_SERIAL_TEGRA132_UARTB + default 0x70006200 if CONSOLE_SERIAL_TEGRA132_UARTC + default 0x70006300 if CONSOLE_SERIAL_TEGRA132_UARTD + default 0x70006400 if CONSOLE_SERIAL_TEGRA132_UARTE + help + Map the UART names to the respective MMIO addres. + +config MTS_DIRECTORY + string "Directory where MTS microcode files are located" + default "." + help + Path to directory where MTS microcode files are located. + +config TRUSTZONE_CARVEOUT_SIZE_MB + hex "Size of Trust Zone region" + default 0x4 + help + Size of Trust Zone area in MiB to reserve in memory map. + +config BOOTROM_SDRAM_INIT + bool "SoC BootROM does SDRAM init with full BCT" + default n + help + Use during Ryu LPDDR3 bringup + +# Default to 700MHz. This value is based on nv bootloader setting. +config PLLX_KHZ + int + default 700000 +endif diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc new file mode 100644 index 0000000000..e0754b308c --- /dev/null +++ b/src/soc/nvidia/tegra132/Makefile.inc @@ -0,0 +1,154 @@ +CBOOTIMAGE = cbootimage +CBOOTIMAGE_OPTS = --soc tegra132 + +bootblock-y += bootblock.c +bootblock-y += bootblock_asm.S +bootblock-y += cbfs.c +bootblock-y += clock.c +bootblock-y += spi.c +bootblock-y += i2c.c +bootblock-y += dma.c +bootblock-y += monotonic_timer.c +bootblock-y += padconfig.c +bootblock-y += power.c +bootblock-y += funitcfg.c +bootblock-y += reset.c +bootblock-y += ../tegra/gpio.c +bootblock-y += ../tegra/i2c.c +bootblock-y += ../tegra/pingroup.c +bootblock-y += ../tegra/pinmux.c +bootblock-y += ../tegra/apbmisc.c +bootblock-y += ../tegra/usb.c +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif + +verstage-y += verstage.c +verstage-y += cbfs.c +verstage-y += dma.c +verstage-y += monotonic_timer.c +verstage-y += spi.c +verstage-y += padconfig.c +verstage-y += funitcfg.c +verstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +verstage-y += ../tegra/gpio.c +verstage-y += ../tegra/i2c.c +verstage-y += ../tegra/pinmux.c +verstage-y += clock.c +verstage-y += i2c.c + +romstage-y += 32bit_reset.S +romstage-y += romstage_asm.S +romstage-y += addressmap.c +romstage-y += cbfs.c +romstage-y += cbmem.c +romstage-y += ccplex.c +romstage-y += clock.c +romstage-y += cpu.c +romstage-y += reset.c +romstage-y += spi.c +romstage-y += i2c.c +romstage-y += dma.c +romstage-y += monotonic_timer.c +romstage-y += padconfig.c +romstage-y += funitcfg.c +romstage-y += romstage.c +romstage-y += power.c +romstage-y += sdram.c +romstage-y += sdram_lp0.c +romstage-y += ../tegra/gpio.c +romstage-y += ../tegra/i2c.c +romstage-y += ../tegra/pinmux.c +romstage-y += ../tegra/usb.c +ifeq ($(CONFIG_EARLY_CONSOLE),y) +romstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif + +ramstage-y += 32bit_reset.S +ramstage-y += addressmap.c +ramstage-y += cbfs.c +ramstage-y += cbmem.c +ramstage-y += cpu.c +ramstage-y += cpu_lib.S +ramstage-y += clock.c +ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += dc.c +ramstage-$(CONFIG_MAINBOARD_DO_DSI_INIT) += dsi.c +ramstage-$(CONFIG_MAINBOARD_DO_DSI_INIT) += mipi_dsi.c +ramstage-$(CONFIG_MAINBOARD_DO_DSI_INIT) += mipi.c +ramstage-$(CONFIG_MAINBOARD_DO_DSI_INIT) += mipi-phy.c +ramstage-$(CONFIG_MAINBOARD_DO_DSI_INIT) += ./jdi_25x18_display/panel-jdi-lpm102a188a.c +ramstage-$(CONFIG_MAINBOARD_DO_SOR_INIT) += dp.c + +ramstage-y += soc.c +ramstage-y += spi.c +ramstage-y += i2c.c +ramstage-y += i2c6.c +ramstage-y += power.c +ramstage-y += dma.c +ramstage-y += gic.c +ramstage-y += monotonic_timer.c +ramstage-y += padconfig.c +ramstage-y += funitcfg.c +ramstage-y += reset.c +ramstage-y += ../tegra/apbmisc.c +ramstage-y += ../tegra/gpio.c +ramstage-y += ../tegra/i2c.c +ramstage-y += ../tegra/pinmux.c +ramstage-y += ramstage.c +ramstage-y += mmu_operations.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +ramstage-y += ../tegra/usb.c +ramstage-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon.c + +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += 32bit_reset.S +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += cpu_lib.S +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += flow_ctrl.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += power.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += psci.c +secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += uart.c + +rmodules_arm-y += monotonic_timer.c +VBOOT_STUB_DEPS += $(obj)/soc/nvidia/tegra132/monotonic_timer.rmodules_arm.o + +INCLUDES += -Isrc/soc/nvidia/tegra132/include/ + +# We want to grab the bootblock right before it goes into the image and wrap +# it inside a BCT, but ideally we would do that without making special, one +# use modifications to the main ARM Makefile. We do this in two ways. First, +# we copy bootblock.elf to bootblock.raw.elf and allow the %.bin: %.elf +# template rule to turn it into bootblock.raw.bin. This makes sure whatever +# processing is supposed to happen to turn an .elf into a .bin happens. +# +# Second, we add our own rule for creating bootblock.bin from +# bootblock.raw.bin which displaces the template rule. When other rules that +# package up the image pull in bootblock.bin, it will be this wrapped version +# instead of the raw bootblock. + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(obj)/generated/bct.bin: $(obj)/generated/bct.cfg + @printf " CBOOTIMAGE $(subst $(obj)/,,$(@))\n" + $(CBOOTIMAGE) -gbct $(CBOOTIMAGE_OPTS) $< $@ + +BCT_BIN = $(obj)/generated/bct.bin +BCT_WRAPPER = $(obj)/generated/bct.wrapper +MTS_DIR = $(CONFIG_MTS_DIRECTORY) +PREBOOT_MTS_FILE = $(MTS_DIR)/mts_preboot_si +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin $(BCT_BIN) + echo "Version = 1;" > $(BCT_WRAPPER) + echo "Redundancy = 1;" >> $(BCT_WRAPPER) + echo "Bctcopy = 1;" >> $(BCT_WRAPPER) + echo "Bctfile = $(BCT_BIN);" >> $(BCT_WRAPPER) + echo "MtsPreboot = $(PREBOOT_MTS_FILE),0x4000f000,0x4000f000,Complete;" >> $(BCT_WRAPPER) + echo "BootLoader = $<,$(call loadaddr,bootblock),$(call loadaddr,bootblock),Complete;" >> $(BCT_WRAPPER) + @printf " CBOOTIMAGE $(subst $(obj)/,,$(@))\n" + $(CBOOTIMAGE) $(CBOOTIMAGE_OPTS) $(BCT_WRAPPER) $@ + +# MTS microcode +MTS_FILE = $(MTS_DIR)/mts_si +MTS_FILE_CBFS = mts +cbfs-files-y += $(MTS_FILE_CBFS) +$(MTS_FILE_CBFS)-file := $(MTS_FILE) +$(MTS_FILE_CBFS)-type := 0x50 diff --git a/src/soc/nvidia/tegra132/addressmap.c b/src/soc/nvidia/tegra132/addressmap.c new file mode 100644 index 0000000000..6eb511b1f0 --- /dev/null +++ b/src/soc/nvidia/tegra132/addressmap.c @@ -0,0 +1,195 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t tz_base_mib; +static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB; + +/* returns total amount of DRAM (in MB) from memory controller registers */ +int sdram_size_mb(void) +{ + struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE; + static int total_size = 0; + + if (total_size) + return total_size; + + /* + * This obtains memory size from the External Memory Aperture + * Configuration register. Nvidia confirmed that it is safe to assume + * this value represents the total physical DRAM size. + */ + total_size = (read32(&mc->emem_cfg) >> + MC_EMEM_CFG_SIZE_MB_SHIFT) & MC_EMEM_CFG_SIZE_MB_MASK; + + return total_size; +} + +static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib, + uint32_t bom, uint32_t bom_hi, uint32_t size) +{ + + /* All size regs of carveouts are in MiB. */ + if (size == 0) + return; + + *size_mib = size; + bom >>= 20; + bom |= bom_hi << (32 - 20); + + *base_mib = bom; +} + +void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib) +{ + *base_mib = 0; + *size_mib = 0; + struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE; + + switch (id) { + case CARVEOUT_TZ: + *base_mib = tz_base_mib; + *size_mib = tz_size_mib; + break; + case CARVEOUT_SEC: + carveout_from_regs(base_mib, size_mib, + read32(&mc->sec_carveout_bom), + read32(&mc->sec_carveout_adr_hi), + read32(&mc->sec_carveout_size_mb)); + break; + case CARVEOUT_MTS: + carveout_from_regs(base_mib, size_mib, + read32(&mc->mts_carveout_bom), + read32(&mc->mts_carveout_adr_hi), + read32(&mc->mts_carveout_size_mb)); + break; + case CARVEOUT_VPR: + carveout_from_regs(base_mib, size_mib, + read32(&mc->video_protect_bom), + read32(&mc->video_protect_bom_adr_hi), + read32(&mc->video_protect_size_mb)); + break; + default: + break; + } +} + +static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib, + int ignore_tz) +{ + uintptr_t base; + uintptr_t end; + int i; + + base = (uintptr_t)_dram / MiB; + end = base + sdram_size_mb(); + + /* Requested limits out of range. */ + if (*end_mib <= base || *base_mib >= end) { + *end_mib = *base_mib = 0; + return; + } + + /* Clip region to passed in limits. */ + if (*end_mib < end) + end = *end_mib; + if (*base_mib > base) + base = *base_mib; + + for (i = 0; i < CARVEOUT_NUM; i++) { + uintptr_t carveout_base; + uintptr_t carveout_end; + size_t carveout_size; + + if (i == CARVEOUT_TZ && ignore_tz) + continue; + + carveout_range(i, &carveout_base, &carveout_size); + + if (carveout_size == 0) + continue; + + carveout_end = carveout_base + carveout_size; + + /* Bypass carveouts out of requested range. */ + if (carveout_base >= end || carveout_end <= base) + continue; + + /* + * This is crude, but the assumption is that carveouts live + * at the upper range of physical memory. Therefore, update + * the end address to be equal to the base of the carveout. + */ + end = carveout_base; + } + + *base_mib = base; + *end_mib = end; +} + +void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib) +{ + *base_mib = 0; + *end_mib = 4096; + memory_in_range(base_mib, end_mib, 0); +} + +void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib) +{ + *base_mib = 4096; + *end_mib = ~0UL; + memory_in_range(base_mib, end_mib, 0); +} + +void trustzone_region_init(void) +{ + struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE; + uintptr_t end = 4096; + + /* Already has been initialized. */ + if (tz_size_mib != 0 && tz_base_mib != 0) + return; + + /* + * Get memory layout below 4GiB ignoring the TZ carveout because + * that's the one to initialize. + */ + memory_in_range(&tz_base_mib, &end, 1); + tz_base_mib = end - tz_size_mib; + + /* AVP cannot set the TZ registers proper as it is always non-secure. */ + if (context_avp()) + return; + + /* Set the carveout region. */ + write32(tz_base_mib << 20, &mc->security_cfg0); + write32(tz_size_mib, &mc->security_cfg1); + + /* Enable SMMU translations */ + write32(MC_SMMU_CONFIG_ENABLE, &mc->smmu_config); +} diff --git a/src/soc/nvidia/tegra132/bootblock.c b/src/soc/nvidia/tegra132/bootblock.c new file mode 100644 index 0000000000..c0c4a2f855 --- /dev/null +++ b/src/soc/nvidia/tegra132/bootblock.c @@ -0,0 +1,121 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BCT_OFFSET_IN_BIT 0x50 +#define ODMDATA_OFFSET_IN_BCT 0x6A8 +#define TEGRA_SRAM_MAX (TEGRA_SRAM_BASE + TEGRA_SRAM_SIZE) + +static void save_odmdata(void) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + uintptr_t bct_offset; + u32 odmdata; + + // pmc.odmdata: [18:19]: console type, [15:17]: UART id. + // TODO(twarren) ODMDATA is stored in the BCT, from bct/odmdata.cfg. + // I use the BCT offset in the BIT in SRAM to locate the BCT, and + // pick up the ODMDATA word at BCT offset 0x6A8. I could use a BCT + // struct header from cbootimage, but it seems like overkill for this. + + bct_offset = read32((void *)(TEGRA_SRAM_BASE + BCT_OFFSET_IN_BIT)); + if (bct_offset > TEGRA_SRAM_BASE && bct_offset < TEGRA_SRAM_MAX) { + odmdata = read32((void *)(bct_offset + ODMDATA_OFFSET_IN_BCT)); + write32(odmdata, &pmc->odmdata); + } +} + +void __attribute__((weak)) bootblock_mainboard_early_init(void) +{ + /* Empty default implementation. */ +} + +void main(void) +{ + void *entry = NULL; + + timestamp_early_init(0); + timestamp_add_now(TS_START_BOOTBLOCK); + + // enable JTAG at the earliest stage + enable_jtag(); + + clock_early_uart(); + + /* Configure mselect clock. */ + clock_configure_source(mselect, PLLP, 102000); + + /* Enable AVP cache, timer, APB dma, and mselect blocks. */ + clock_enable_clear_reset(CLK_L_CACHE2 | CLK_L_TMR, + CLK_H_APBDMA, + 0, CLK_V_MSELECT, 0, 0); + + /* Find ODMDATA in IRAM and save it to scratch reg */ + save_odmdata(); + + bootblock_mainboard_early_init(); + + if (CONFIG_BOOTBLOCK_CONSOLE) { + console_init(); + exception_init(); + printk(BIOS_INFO, "T132: Bootblock here\n"); + } + + clock_init(); + + printk(BIOS_INFO, "T132 bootblock: Clock init done\n"); + + pmc_print_rst_status(); + + bootblock_mainboard_init(); + + printk(BIOS_INFO, "T132 bootblock: Mainboard bootblock init done\n"); + + if (IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE)) { + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/verstage"); + printk(BIOS_DEBUG, "T132 bootblock: jumping to verstage\n"); + } else { + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/romstage"); + printk(BIOS_INFO, "T132 bootblock: jumping to romstage\n"); + } + + timestamp_add_now(TS_END_BOOTBLOCK); + + if (entry != CBFS_LOAD_ERROR) + stage_exit(entry); + else + printk(BIOS_INFO, "T132 bootblock: stage not found\n"); + + hlt(); +} diff --git a/src/soc/nvidia/tegra132/bootblock_asm.S b/src/soc/nvidia/tegra132/bootblock_asm.S new file mode 100644 index 0000000000..bf63c02433 --- /dev/null +++ b/src/soc/nvidia/tegra132/bootblock_asm.S @@ -0,0 +1,46 @@ +/* + * Early initialization code for ARM architecture. + * + * This file is based off of the OMAP3530/ARM Cortex start.S file from Das + * U-Boot, which itself got the file from armboot. + * + * Copyright (c) 2004 Texas Instruments + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim + * Copyright (c) 2013 The Chromium OS Authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#include "stack.S" + +ENTRY(_start) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr_cxf, #0xdf + + stack_init stack_top=_estack stack_bottom=_stack seed=1 func=main +ENDPROC(_start) diff --git a/src/soc/nvidia/tegra132/cbfs.c b/src/soc/nvidia/tegra132/cbfs.c new file mode 100644 index 0000000000..2efd48bccf --- /dev/null +++ b/src/soc/nvidia/tegra132/cbfs.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include /* This driver serves as a CBFS media source. */ +#include +#include + +int init_default_cbfs_media(struct cbfs_media *media) +{ + return initialize_tegra_spi_cbfs_media(media, + _cbfs_cache, _cbfs_cache_size); +} diff --git a/src/soc/nvidia/tegra132/cbmem.c b/src/soc/nvidia/tegra132/cbmem.c new file mode 100644 index 0000000000..914b57ea7c --- /dev/null +++ b/src/soc/nvidia/tegra132/cbmem.c @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void *cbmem_top(void) +{ + static uintptr_t addr; + + if (addr == 0) { + uintptr_t begin_mib; + uintptr_t end_mib; + + memory_in_range_below_4gb(&begin_mib, &end_mib); + /* Make sure we consume everything up to 4GIB. */ + if (end_mib == 4096) + addr = ~(uint32_t)0; + else + addr = end_mib << 20; + } + + return (void *)addr; +} diff --git a/src/soc/nvidia/tegra132/ccplex.c b/src/soc/nvidia/tegra132/ccplex.c new file mode 100644 index 0000000000..ea92b31324 --- /dev/null +++ b/src/soc/nvidia/tegra132/ccplex.c @@ -0,0 +1,177 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMC_REGS (void *)(uintptr_t)(TEGRA_PMC_BASE) +#define MTS_FILE_NAME "mts" + +static int ccplex_start(void) +{ + struct stopwatch sw; + const long timeout_ms = 1500; + const uint32_t handshake_mask = 1; + const uint32_t cxreset1_mask = 1 << 21; + uint32_t reg; + struct tegra_pmc_regs * const pmc = PMC_REGS; + + /* Set the handshake bit to be knocked down. */ + write32(handshake_mask, &pmc->scratch118); + + /* Assert nCXRSET[1] */ + reg = read32(CLK_RST_REG(rst_cpu_cmplx_set)); + reg |= cxreset1_mask; + write32(reg, CLK_RST_REG(rst_cpu_cmplx_set)); + + stopwatch_init_msecs_expire(&sw, timeout_ms); + while (1) { + reg = read32(&pmc->scratch118); + + /* Wait for the bit to be knocked down. */ + if ((reg & handshake_mask) != handshake_mask) + break; + + if (stopwatch_expired(&sw)) { + printk(BIOS_DEBUG, "MTS handshake timeout.\n"); + return -1; + } + } + + printk(BIOS_DEBUG, "MTS handshake took %ld usecs.\n", + stopwatch_duration_usecs(&sw)); + + return 0; +} + +int ccplex_load_mts(void) +{ + struct cbfs_file file; + ssize_t offset; + size_t nread; + struct stopwatch sw; + + /* + * MTS location is hard coded to this magic address. The hardware will + * take the MTS from this location and place it in the final resting + * place in the carveout region. + */ + void * const mts = (void *)(uintptr_t)MTS_LOAD_ADDRESS; + struct cbfs_media *media = CBFS_DEFAULT_MEDIA; + + stopwatch_init(&sw); + offset = cbfs_locate_file(media, &file, MTS_FILE_NAME); + if (offset < 0) { + printk(BIOS_DEBUG, "MTS file not found: %s\n", MTS_FILE_NAME); + return -1; + } + + /* Read MTS file into the carveout region. */ + nread = cbfs_read(media, mts, offset, file.len); + + if (nread != file.len) { + printk(BIOS_DEBUG, "MTS bytes read (%zu) != file length(%u)!\n", + nread, file.len); + return -1; + } + + printk(BIOS_DEBUG, "MTS: %zu bytes loaded @ %p in %ld usecs.\n", + nread, mts, stopwatch_duration_usecs(&sw)); + + return ccplex_start(); +} + +static void enable_cpu_clocks(void) +{ + clock_enable(CLK_ENB_CPU, 0, 0, SET_CLK_ENB_CPUG_ENABLE | + SET_CLK_ENB_CPULP_ENABLE, 0, 0); +} + +static void enable_cpu_power_partitions(void) +{ + /* Bring up fast cluster, non-CPU, CPU0, and CPU1 partitions. */ + power_ungate_partition(POWER_PARTID_CRAIL); + power_ungate_partition(POWER_PARTID_C0NC); + power_ungate_partition(POWER_PARTID_CE0); + power_ungate_partition(POWER_PARTID_CE1); +} + +static void request_ram_repair(void) +{ + struct flow_ctlr * const flow = (void *)(uintptr_t)TEGRA_FLOW_BASE; + const uint32_t req = 1 << 0; + const uint32_t sts = 1 << 1; + uint32_t reg; + struct stopwatch sw; + + printk(BIOS_DEBUG, "Requesting RAM repair.\n"); + + reg = read32(&flow->ram_repair); + reg |= req; + write32(reg, &flow->ram_repair); + + stopwatch_init(&sw); + while ((read32(&flow->ram_repair) & sts) != sts) + ; + + printk(BIOS_DEBUG, "RAM repair complete in %ld usecs.\n", + stopwatch_duration_usecs(&sw)); +} + +void ccplex_cpu_prepare(void) +{ + enable_cpu_clocks(); + enable_cpu_power_partitions(); + + mainboard_configure_pmc(); + mainboard_enable_vdd_cpu(); + + request_ram_repair(); +} + +static void start_common_clocks(void) +{ + /* Clear fast CPU partition reset. */ + write32(CRC_RST_CPUG_CLR_NONCPU, CLK_RST_REG(rst_cpug_cmplx_clr)); + + /* Clear reset of L2 and CoreSight components. */ + write32(CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG, + CLK_RST_REG(rst_cpug_cmplx_clr)); +} + +void ccplex_cpu_start(void *entry_addr) +{ + /* Enable common clocks for the shared resources between the cores. */ + start_common_clocks(); + + start_cpu(0, entry_addr); +} diff --git a/src/soc/nvidia/tegra132/chip.h b/src/soc/nvidia/tegra132/chip.h new file mode 100644 index 0000000000..fbbef500d4 --- /dev/null +++ b/src/soc/nvidia/tegra132/chip.h @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_CHIP_H__ +#define __SOC_NVIDIA_TEGRA132_CHIP_H__ +#include +#include +#include + +struct soc_nvidia_tegra132_config { + /* Address to monitor if spintable employed. */ + uintptr_t spintable_addr; + + /* + * panel resolution + * The two parameters below provides dc about panel spec. + */ + u32 xres; /* the width of H display active area */ + u32 yres; /* the height of V display active area */ + u32 framebuffer_bits_per_pixel; + u32 color_depth; /* color format */ + + u64 display_controller; /* dc block base address */ + u32 framebuffer_base; + + /* + * Technically, we can compute this. At the same time, some platforms + * might want to specify a specific size for their own reasons. If it + * is zero the soc code will compute it as + * xres*yres*framebuffer_bits_per_pixel/8 + */ + u32 framebuffer_size; + + /* + * Framebuffer resolution + * The two parameters below provides dc about framebuffer's sdram size. + * When they are not the same as panel resolution, we need to program + * dc's DDA_INCREMENT and some other registers to resize dc output. + */ + u32 display_xres; + u32 display_yres; + + int href_to_sync; /* HSYNC position with respect to line start */ + int hsync_width; /* the width of HSYNC pulses */ + int hback_porch; /* the distance between HSYNC trailing edge to + beginning of H display active area */ + int hfront_porch; /* the distance between end of H display active + area to the leading edge of HSYNC */ + int vref_to_sync; + int vsync_width; + int vback_porch; + int vfront_porch; + int refresh; /* display refresh rate */ + + int pixel_clock; /* dc pixel clock source rate */ + int win_opt; +}; + +#endif /* __SOC_NVIDIA_TEGRA132_CHIP_H__ */ diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c new file mode 100644 index 0000000000..e6a9b09733 --- /dev/null +++ b/src/soc/nvidia/tegra132/clock.c @@ -0,0 +1,728 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clst_clk_ctlr *clst_clk = (void *)TEGRA_CLUSTER_CLOCK_BASE; +static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE; +static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE; +static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE; + +struct pll_dividers { + u32 n : 10; + u32 m : 8; + u32 p : 4; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +/* Some PLLs have more restrictive divider bit lengths or are missing some + * fields. Make sure to use the right struct in the osc_table definition to get + * compile-time checking, but keep the bits aligned with struct pll_dividers so + * they can be used interchangeably at run time. Add new formats as required. */ +struct pllcx_dividers { + u32 n : 8; + u32 : 2; + u32 m : 8; + u32 p : 4; + u32 : 10; +}; +struct pllpad_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 3; + u32 : 1; + u32 cpcon : 4; + u32 : 6; +}; +struct pllu_dividers { + u32 n : 10; + u32 m : 5; + u32 : 3; + u32 p : 1; + u32 : 3; + u32 cpcon : 4; + u32 lfcon : 4; + u32 : 2; +}; + +union __attribute__((transparent_union)) pll_fields { + u32 raw; + struct pll_dividers div; + struct pllcx_dividers cx; + struct pllpad_dividers pad; + struct pllu_dividers u; +}; + +/* This table defines the frequency dividers for every PLL to turn the external + * OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h. + * All PLLs have three dividers (n, m and p), with the governing formula for + * the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p). + * All divisor configurations must meet the PLL's constraints for VCO and CF: + * PLLX: 12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz + * PLLC: 12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz + * PLLM: 12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz + * PLLP: 1 MHz < CF < 6 MHz, 200 MHz < VCO < 700 MHz + * PLLD: 1 MHz < CF < 6 MHz, 500 MHz < VCO < 1000 MHz + * PLLU: 1 MHz < CF < 6 MHz, 480 MHz < VCO < 960 MHz + * PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz + * (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */ +struct { + int khz; + struct pllcx_dividers pllx; /* target: CONFIG_PLLX_KHZ */ + struct pllcx_dividers pllc; /* target: 600 MHz */ + /* PLLM is set up dynamically by clock_sdram(). */ + /* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */ + struct pllu_dividers pllu; /* target; 960 MHz */ + struct pllcx_dividers plldp; /* target; 270 MHz */ + /* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */ +} static const osc_table[16] = { + [OSC_FREQ_12]{ + .khz = 12000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, + [OSC_FREQ_13]{ + .khz = 13000, + .pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m = 1, .p = 0}, + .pllc = {.n = 46, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 1, .p = 3}, /* 269.8 MHz */ + }, + [OSC_FREQ_16P8]{ + .khz = 16800, + .pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m = 1, .p = 0}, + .pllc = {.n = 71, .m = 1, .p = 1}, /* 596.4 MHz */ + .pllu = {.n = 400, .m = 7, .p = 0, .cpcon = 5, .lfcon = 2}, + .plldp = {.n = 64, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_19P2]{ + .khz = 19200, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_26]{ + .khz = 26000, + .pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m = 1, .p = 0}, + .pllc = {.n = 23, .m = 1, .p = 0}, /* 598.0 MHz */ + .pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 83, .m = 2, .p = 3}, /* 269.8 MHz */ + }, + /* These oscillators get predivided as PLL inputs... n/m/p divisors for + * 38.4 should always match 19.2, and 48 should always match 12. */ + [OSC_FREQ_38P4]{ + .khz = 38400, + .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, + .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ + .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, + .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ + }, + [OSC_FREQ_48]{ + .khz = 48000, + .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, + .pllc = {.n = 50, .m = 1, .p = 0}, + .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, + .plldp = {.n = 90, .m = 1, .p = 3}, + }, +}; + +/* Get the oscillator frequency, from the corresponding hardware + * configuration field. This is actually a per-soc thing. Avoid the + * temptation to make it common. + */ +static u32 clock_get_osc_bits(void) +{ + return (readl(CLK_RST_REG(osc_ctrl)) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + +int clock_get_osc_khz(void) +{ + return osc_table[clock_get_osc_bits()].khz; +} + +int clock_get_pll_input_khz(void) +{ + u32 osc_ctrl = readl(CLK_RST_REG(osc_ctrl)); + u32 osc_bits = (osc_ctrl & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; + u32 pll_ref_div = (osc_ctrl & OSC_PREDIV_MASK) >> OSC_PREDIV_SHIFT; + return osc_table[osc_bits].khz >> pll_ref_div; +} + +void clock_init_arm_generic_timer(void) +{ + uint32_t freq = clock_get_osc_khz() * 1000; + // Set the cntfrq register. + set_cntfrq(freq); + + // Record the system timer frequency. + write32(freq, &sysctr->cntfid0); + // Enable the system counter. + uint32_t cntcr = read32(&sysctr->cntcr); + cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG; + write32(cntcr, &sysctr->cntcr); +} + +#define SOR0_CLK_SEL0 (1 << 14) +#define SOR0_CLK_SEL1 (1 << 15) + +void sor_clock_stop(void) +{ + /* The Serial Output Resource clock has to be off + * before we start the plldp. Learned the hard way. + * FIXME: this has to be cleaned up a bit more. + * Waiting on some new info from Nvidia. + */ + clrbits_le32(CLK_RST_REG(clk_src_sor), SOR0_CLK_SEL0 | SOR0_CLK_SEL1); +} + +void sor_clock_start(void) +{ + /* uses PLLP, has a non-standard bit layout. */ + setbits_le32(CLK_RST_REG(clk_src_sor), SOR0_CLK_SEL0); +} + +static void init_pll(u32 *base, u32 *misc, const union pll_fields pll, u32 lock) +{ + u32 dividers = pll.div.n << PLL_BASE_DIVN_SHIFT | + pll.div.m << PLL_BASE_DIVM_SHIFT | + pll.div.p << PLL_BASE_DIVP_SHIFT; + u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT | + pll.div.lfcon << PLL_MISC_LFCON_SHIFT; + + /* Write dividers but BYPASS the PLL while we're messing with it. */ + writel(dividers | PLL_BASE_BYPASS, base); + /* + * Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't + * exist for this PLL) + */ + writel(lock | misc_con, misc); + + /* Enable PLL and take it back out of BYPASS */ + writel(dividers | PLL_BASE_ENABLE, base); + + /* Wait for lock ready */ + while (!(readl(base) & PLL_BASE_LOCK)); +} + +static void init_utmip_pll(void) +{ + int khz = clock_get_pll_input_khz(); + + /* Shut off PLL crystal clock while we mess with it */ + clrbits_le32(CLK_RST_REG(utmip_pll_cfg2), 1 << 30); /* PHY_XTAL_CLKEN */ + udelay(1); + + write32(80 << 16 | /* (rst) phy_divn */ + 1 << 8 | /* (rst) phy_divm */ + 0, CLK_RST_REG(utmip_pll_cfg0));/* 960MHz * 1 / 80 == 12 MHz */ + + write32(div_round_up(khz, 8000) << 27 | /* pllu_enbl_cnt / 8 (1us) */ + 0 << 16 | /* PLLU pwrdn */ + 0 << 14 | /* pll_enable pwrdn */ + 0 << 12 | /* pll_active pwrdn */ + div_round_up(khz, 102) << 0 | /* phy_stbl_cnt / 256 (2.5ms) */ + 0, CLK_RST_REG(utmip_pll_cfg1)); + + /* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */ + write32(0 << 24 | /* SAMP_D/XDEV pwrdn */ + div_round_up(khz, 3200) << 18 | /* phy_actv_cnt / 16 (5us) */ + div_round_up(khz, 256) << 6 | /* pllu_stbl_cnt / 256 (1ms) */ + 0 << 4 | /* SAMP_C/USB3 pwrdn */ + 0 << 2 | /* SAMP_B/XHOST pwrdn */ + 0 << 0 | /* SAMP_A/USBD pwrdn */ + 0, CLK_RST_REG(utmip_pll_cfg2)); + + setbits_le32(CLK_RST_REG(utmip_pll_cfg2), 1 << 30); /* PHY_XTAL_CLKEN */ +} + +/* Graphics just has to be different. There's a few more bits we + * need to set in here, but it makes sense just to restrict all the + * special bits to this one function. + */ +static void graphics_pll(void) +{ + int osc = clock_get_osc_bits(); + u32 *cfg = CLK_RST_REG(plldp_ss_cfg); + /* the vendor code sets the dither bit (28) + * an undocumented bit (24) + * and clamp while we mess with it (22) + * Dither is pretty important to display port + * so we really do need to handle these bits. + * I'm not willing to not clamp it, even if + * it might "mostly work" with it not set, + * I don't want to find out in a few months + * that it is needed. + */ + u32 scfg = (1<<28) | (1<<24) | (1<<22); + writel(scfg, cfg); + init_pll(CLK_RST_REG(plldp_base), CLK_RST_REG(plldp_misc), + osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE); + /* leave dither and undoc bits set, release clamp */ + scfg = (1<<28) | (1<<24); + writel(scfg, cfg); +} + +/* + * Init PLLD clock source. + * + * @frequency: the requested plld frequency + * + * Return the plld frequency if success, otherwise return 0. + */ +u32 clock_configure_plld(u32 frequency) +{ + /** + * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz + * = (cf * n) >> p, where 1MHz < cf < 6MHz + * = ((ref / m) * n) >> p + * + * Iterate the possible values of p (3 bits, 2^7) to find out a minimum + * safe vco, then find best (m, n). since m has only 5 bits, we can + * iterate all possible values. Note Tegra 124 supports 11 bits for n, + * but our pll_fields has only 10 bits for n. + * + * Note values undershoot or overshoot target output frequency may not + * work if the values are not in "safe" range by panel specification. + */ + struct pllpad_dividers plld = { 0 }; + u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0; + u32 cf, vco, rounded_rate = frequency; + u32 diff, best_diff; + const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3, + mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz, + min_cf = 1 * mhz, max_cf = 6 * mhz; + + for (vco = frequency; vco < min_vco && p < max_p; p++) + vco <<= 1; + + if (vco < min_vco || vco > max_vco) { + printk(BIOS_ERR, "%s: Cannot find out a supported VCO" + " for Frequency (%u).\n", __func__, frequency); + return 0; + } + + plld.p = p; + best_diff = vco; + + for (m = 1; m < max_m && best_diff; m++) { + cf = ref / m; + if (cf < min_cf) + break; + if (cf > max_cf) + continue; + + n = vco / cf; + if (n >= max_n) + continue; + + diff = vco - n * cf; + if (n + 1 < max_n && diff > cf / 2) { + n++; + diff = cf - diff; + } + + if (diff >= best_diff) + continue; + + best_diff = diff; + plld.m = m; + plld.n = n; + } + + if (plld.n < 50) + plld.cpcon = 2; + else if (plld.n < 300) + plld.cpcon = 3; + else if (plld.n < 600) + plld.cpcon = 8; + else + plld.cpcon = 12; + + if (best_diff) { + printk(BIOS_WARNING, "%s: Failed to match output frequency %u, " + "best difference is %u.\n", __func__, frequency, + best_diff); + rounded_rate = (ref / plld.m * plld.n) >> plld.p; + } + + printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n", + __func__, rounded_rate, ref, plld.m, plld.n, plld.p, plld.cpcon); + + init_pll(CLK_RST_REG(plld_base), CLK_RST_REG(plld_misc), plld, + (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE)); + + if (rounded_rate != frequency) + printk(BIOS_DEBUG, "PLLD rate: %u vs %u\n", rounded_rate, + frequency); + + return rounded_rate; +} + +/* Initialize the UART and put it on CLK_M so we can use it during clock_init(). + * Will later move it to PLLP in clock_config(). The divisor must be very small + * to accomodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1 + * CLK_SOURCE divider to get more precision. (This might still not be enough for + * some OSCs... if you use 13KHz, be prepared to have a bad time.) The 1900 has + * been determined through trial and error (must lead to div 13 at 24MHz). */ +void clock_early_uart(void) +{ + write32(CLK_SRC_DEV_ID(UARTA, CLK_M) << CLK_SOURCE_SHIFT | + CLK_UART_DIV_OVERRIDE | + CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900), CLK_RST_REG(clk_src_uarta)); + + clock_enable_clear_reset_l(CLK_L_UARTA); +} + +/* Enable output clock (CLK1~3) for external peripherals. */ +void clock_external_output(int clk_id) +{ + switch (clk_id) { + case 1: + setbits_le32(&pmc->clk_out_cntrl, 1 << 2); + break; + case 2: + setbits_le32(&pmc->clk_out_cntrl, 1 << 10); + break; + case 3: + setbits_le32(&pmc->clk_out_cntrl, 1 << 18); + break; + default: + printk(BIOS_CRIT, "ERROR: Unknown output clock id %d\n", + clk_id); + break; + } +} + +/* Start PLLM for SDRAM. */ +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq) +{ + u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) | + (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) | + (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) | + (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)), + misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | + (kcp << PLLM_MISC2_KCP_SHIFT)), + base; + + if (same_freq) + emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + else + emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; + + /* + * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and + * PLLM_BASE.ENABLE must be in DISABLE state (both are the default + * values after coldboot reset). + */ + + writel(misc1, CLK_RST_REG(pllm_misc1)); + writel(misc2, CLK_RST_REG(pllm_misc2)); + + /* PLLM.BASE needs BYPASS=0, different from general init_pll */ + base = readl(CLK_RST_REG(pllm_base)); + base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK | + PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS); + base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) | + (p << PLL_BASE_DIVP_SHIFT)); + writel(base, CLK_RST_REG(pllm_base)); + + setbits_le32(CLK_RST_REG(pllm_base), PLL_BASE_ENABLE); + /* stable_time is required, before we can start to check lock. */ + udelay(stable_time); + + while (!(readl(CLK_RST_REG(pllm_base)) & PLL_BASE_LOCK)) + udelay(1); + + /* + * After PLLM reports being locked, we have to delay 10us before + * enabling PLLM_OUT. + */ + udelay(10); + + /* Put OUT1 out of reset state (start to output). */ + setbits_le32(CLK_RST_REG(pllm_out), PLLM_OUT1_RSTN_RESET_DISABLE); + + /* Enable and start MEM(MC) and EMC. */ + clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0); + writel(emc_source, CLK_RST_REG(clk_src_emc)); + udelay(IO_STABILIZATION_DELAY); +} + +void clock_cpu0_config(void) +{ + u32 reg; + u32 osc = clock_get_osc_bits(); + u32 timeout = 0; + + /* disable IDDQ */ + reg = readl(&clst_clk->pllx_misc3); + reg &= ~PLLX_IDDQ; + writel(reg, &clst_clk->pllx_misc3); + + /* init pllx */ + init_pll(&clst_clk->pllx_base, &clst_clk->pllx_misc, + osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE); + + /* + * Change CPU clock source to PLLX_OUT0_LJ + * when above pllx programming has taken effect. + */ + do { + if (readl(&clst_clk->misc_ctrl) & CLK_SWITCH_MATCH) { + write32((CC_CCLK_BRST_POL_PLLX_OUT0_LJ << 28), + &clst_clk->cclk_brst_pol); + break; + } + + /* wait and try again */ + if (timeout >= CLK_SWITCH_TIMEOUT_US) { + printk(BIOS_ERR, "%s: PLLX programming timeout. " + "Switching cpu clock has falied.\n", + __func__); + break; + } + udelay(10); + timeout += 10; + + } while (1); +} + +void clock_halt_avp(void) +{ + for (;;) { + write32(FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ | + FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT, + &flow->halt_cop_events); + } +} + +void clock_init(void) +{ + u32 osc = clock_get_osc_bits(); + + /* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */ + writel(0x2b << 17 | 0xb << 9, CLK_RST_REG(pllc_misc2)); + + /* Max out the AVP clock before everything else (need PLLC for that). */ + init_pll(CLK_RST_REG(pllc_base), CLK_RST_REG(pllc_misc), + osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE); + + /* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA + * features section in the TRM). */ + write32(1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT, + CLK_RST_REG(clk_sys_rate)); /* pclk = hclk = sclk/2 */ + write32(CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_CLKEN | PLL_OUT_RSTN, CLK_RST_REG(pllc_out)); + write32(SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT | + SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT, + CLK_RST_REG(sclk_brst_pol)); /* sclk = 300 MHz */ + + /* Change the oscillator drive strength (from U-Boot -- why?) */ + clrsetbits_le32(CLK_RST_REG(osc_ctrl), OSC_XOFS_MASK, + OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); + + /* + * Ambiguous quote from u-boot. TODO: what's this mean? + * "should update same value in PMC_OSC_EDPD_OVER XOFS + * field for warmboot " + */ + clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK, + OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT); + + /* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */ + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT, + CLK_RST_REG(pllp_outa)); + write32((CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT | + (CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT | + PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT, + CLK_RST_REG(pllp_outb)); + + /* init pllu */ + init_pll(CLK_RST_REG(pllu_base), CLK_RST_REG(pllu_misc), + osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE); + + init_utmip_pll(); + graphics_pll(); +} + +void clock_grp_enable_clear_reset(u32 val, u32* clk_enb_set_reg, + u32 *rst_dev_clr_reg) +{ + writel(val, clk_enb_set_reg); + udelay(IO_STABILIZATION_DELAY); + writel(val, rst_dev_clr_reg); +} + +static u32 * const clk_enb_set_arr[DEV_CONFIG_BLOCKS] = { + CLK_RST_REG(clk_enb_l_set), + CLK_RST_REG(clk_enb_h_set), + CLK_RST_REG(clk_enb_u_set), + CLK_RST_REG(clk_enb_v_set), + CLK_RST_REG(clk_enb_w_set), + CLK_RST_REG(clk_enb_x_set), +}; + +static u32 * const clk_enb_clr_arr[DEV_CONFIG_BLOCKS] = { + CLK_RST_REG(clk_enb_l_clr), + CLK_RST_REG(clk_enb_h_clr), + CLK_RST_REG(clk_enb_u_clr), + CLK_RST_REG(clk_enb_v_clr), + CLK_RST_REG(clk_enb_w_clr), + CLK_RST_REG(clk_enb_x_clr), +}; + +static u32 * const rst_dev_set_arr[DEV_CONFIG_BLOCKS] = { + CLK_RST_REG(rst_dev_l_set), + CLK_RST_REG(rst_dev_h_set), + CLK_RST_REG(rst_dev_u_set), + CLK_RST_REG(rst_dev_v_set), + CLK_RST_REG(rst_dev_w_set), + CLK_RST_REG(rst_dev_x_set), +}; + +static u32 * const rst_dev_clr_arr[DEV_CONFIG_BLOCKS] = { + CLK_RST_REG(rst_dev_l_clr), + CLK_RST_REG(rst_dev_h_clr), + CLK_RST_REG(rst_dev_u_clr), + CLK_RST_REG(rst_dev_v_clr), + CLK_RST_REG(rst_dev_w_clr), + CLK_RST_REG(rst_dev_x_clr), +}; + +static void clock_write_regs(u32 * const regs[DEV_CONFIG_BLOCKS], + u32 bits[DEV_CONFIG_BLOCKS]) +{ + int i = 0; + + for (; i < DEV_CONFIG_BLOCKS; i++) + if (bits[i]) + writel(bits[i], regs[i]); +} + +void clock_enable_regs(u32 bits[DEV_CONFIG_BLOCKS]) +{ + clock_write_regs(clk_enb_set_arr, bits); +} + +void clock_disable_regs(u32 bits[DEV_CONFIG_BLOCKS]) +{ + clock_write_regs(clk_enb_clr_arr, bits); +} + +void clock_set_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]) +{ + clock_write_regs(rst_dev_set_arr, bits); +} + +void clock_clr_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]) +{ + clock_write_regs(rst_dev_clr_arr, bits); +} + +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x) +{ + clock_enable(l, h, u, v, w, x); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); + + clock_clr_reset(l, h, u, v, w, x); +} + +static void clock_reset_dev(u32 *setaddr, u32 *clraddr, u32 bit) +{ + writel(bit, setaddr); + udelay(LOGIC_STABILIZATION_DELAY); + writel(bit, clraddr); +} + +void clock_reset_l(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_l_set), CLK_RST_REG(rst_dev_l_clr), + bit); +} + +void clock_reset_h(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_h_set), CLK_RST_REG(rst_dev_h_clr), + bit); +} + +void clock_reset_u(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_u_set), CLK_RST_REG(rst_dev_u_clr), + bit); +} + +void clock_reset_v(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_v_set), CLK_RST_REG(rst_dev_v_clr), + bit); +} + +void clock_reset_w(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_w_set), CLK_RST_REG(rst_dev_w_clr), + bit); +} + +void clock_reset_x(u32 bit) +{ + clock_reset_dev(CLK_RST_REG(rst_dev_x_set), CLK_RST_REG(rst_dev_x_clr), + bit); +} + +/* Enable/unreset all audio toys under AHUB */ +void clock_enable_audio(void) +{ + /* + * Confirmed by NVIDIA hardware team, we need to take ALL audio devices + * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out + * of reset and clock-enabled, otherwise reading AHUB devices (in our + * case, I2S/APBIF/AUDIO) will hang. + */ + clock_enable_clear_reset(CLK_L_I2S0 | CLK_L_I2S1 | CLK_L_I2S2 | CLK_L_SPDIF, + 0, 0, + CLK_V_I2S3 | CLK_V_I2S4 | CLK_V_AUDIO | CLK_V_APBIF | + CLK_V_DAM0 | CLK_V_DAM1 | CLK_V_DAM2 | CLK_V_EXTPERIPH1, + CLK_W_AMX0 | CLK_W_ADX0, + CLK_X_ADX1 | CLK_X_AFC0 | CLK_X_AFC1 | CLK_X_AFC2 | + CLK_X_AFC3 | CLK_X_AFC4 | CLK_X_AFC5 | CLK_X_AMX1); +} diff --git a/src/soc/nvidia/tegra132/cpu.c b/src/soc/nvidia/tegra132/cpu.c new file mode 100644 index 0000000000..c79bc9cf4e --- /dev/null +++ b/src/soc/nvidia/tegra132/cpu.c @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define EVP_CPU_RESET_VECTOR (void *)(uintptr_t)(TEGRA_EVP_BASE + 0x100) +#define PMC_REGS (void *)(uintptr_t)(TEGRA_PMC_BASE) + +static void enable_core_clocks(int cpu) +{ + const uint32_t cpu0_clocks = CRC_RST_CPUG_CLR_CPU0 | + CRC_RST_CPUG_CLR_DBG0 | + CRC_RST_CPUG_CLR_CORE0 | + CRC_RST_CPUG_CLR_CX0; + const uint32_t cpu1_clocks = CRC_RST_CPUG_CLR_CPU1 | + CRC_RST_CPUG_CLR_DBG1 | + CRC_RST_CPUG_CLR_CORE1 | + CRC_RST_CPUG_CLR_CX1; + + /* Clear reset of CPU components. */ + if (cpu == 0) + write32(cpu0_clocks, CLK_RST_REG(rst_cpug_cmplx_clr)); + else + write32(cpu1_clocks, CLK_RST_REG(rst_cpug_cmplx_clr)); +} + +static void set_armv8_32bit_reset_vector(uintptr_t entry) +{ + void * const evp_cpu_reset_vector = EVP_CPU_RESET_VECTOR; + write32(entry, evp_cpu_reset_vector); +} + +static void set_armv8_64bit_reset_vector(uintptr_t entry) +{ + struct tegra_pmc_regs * const pmc = PMC_REGS; + + /* Currently assume 32-bit addresses only. */ + write32(entry, &pmc->secure_scratch34); + write32(0, &pmc->secure_scratch35); +} + +void cpu_prepare_startup(void *entry_64) +{ + /* Warm reset vector is pulled from the PMC scratch registers. */ + set_armv8_64bit_reset_vector((uintptr_t)entry_64); + + /* + * The Denver cores start in 32-bit mode. Therefore a trampoline + * is needed to get into 64-bit mode. Point the cold reset vector + * to the traompoline location. + */ + set_armv8_32bit_reset_vector((uintptr_t)reset_entry_32bit); +} + +void start_cpu_silent(int cpu, void *entry_64) +{ + cpu_prepare_startup(entry_64); + enable_core_clocks(cpu); +} + +void start_cpu(int cpu, void *entry_64) +{ + printk(BIOS_DEBUG, "Starting CPU%d @ %p trampolining to %p.\n", + cpu, reset_entry_32bit, entry_64); + + start_cpu_silent(cpu, entry_64); +} diff --git a/src/soc/nvidia/tegra132/cpu_lib.S b/src/soc/nvidia/tegra132/cpu_lib.S new file mode 100644 index 0000000000..6d458d3ab7 --- /dev/null +++ b/src/soc/nvidia/tegra132/cpu_lib.S @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +.text +.global smp_processor_id +smp_processor_id: + /* Core 0 and 1 are encoded in the Aff0 (7:0) field of MPIDR_EL1. */ + mrs x0, mpidr_el1 + uxtb w0, w0 + ret diff --git a/src/soc/nvidia/tegra132/dc.c b/src/soc/nvidia/tegra132/dc.c new file mode 100644 index 0000000000..e5ab23ad89 --- /dev/null +++ b/src/soc/nvidia/tegra132/dc.c @@ -0,0 +1,223 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include "chip.h" +#include + +int dump = 0; +unsigned long READL(void * p) +{ + unsigned long value; + + /* + * In case of hard hung on readl(p), we can set dump > 1 to print out + * the address accessed. + */ + if (dump > 1) + printk(BIOS_SPEW, "readl %p\n", p); + + value = readl(p); + if (dump) + printk(BIOS_SPEW, "readl %p %08lx\n", p, value); + return value; +} + +void WRITEL(unsigned long value, void * p) +{ + if (dump) + printk(BIOS_SPEW, "writel %p %08lx\n", p, value); + writel(value, p); +} + +/* return in 1000ths of a Hertz */ +static int tegra_calc_refresh(const struct soc_nvidia_tegra132_config *config) +{ + int refresh; + int h_total = htotal(config); + int v_total = vtotal(config); + int pclk = config->pixel_clock; + + if (!pclk || !h_total || !v_total) + return 0; + refresh = pclk / h_total; + refresh *= 1000; + refresh /= v_total; + return refresh; +} + +static void print_mode(const struct soc_nvidia_tegra132_config *config) +{ + if (config) { + int refresh = tegra_calc_refresh(config); + printk(BIOS_ERR, + "Panel Mode: %dx%d@%d.%03uHz pclk=%d\n", + config->xres, config->yres, + refresh / 1000, refresh % 1000, + config->pixel_clock); + } +} + +int update_display_mode(struct display_controller *disp_ctrl, + struct soc_nvidia_tegra132_config *config) +{ + print_mode(config); + + printk(BIOS_ERR, "config: xres:yres: %d x %d\n ", + config->xres, config->yres); + printk(BIOS_ERR, " href_sync:vref_sync: %d x %d\n ", + config->href_to_sync, config->vref_to_sync); + printk(BIOS_ERR, " hsyn_width:vsyn_width: %d x %d\n ", + config->hsync_width, config->vsync_width); + printk(BIOS_ERR, " hfnt_porch:vfnt_porch: %d x %d\n ", + config->hfront_porch, config->vfront_porch); + printk(BIOS_ERR, " hbk_porch:vbk_porch: %d x %d\n ", + config->hback_porch, config->vback_porch); + + WRITEL(0x0, &disp_ctrl->disp.disp_timing_opt); + WRITEL(0x0, &disp_ctrl->disp.disp_color_ctrl); + + /* select win opt */ + WRITEL(config->win_opt, &disp_ctrl->disp.disp_win_opt); + + WRITEL(config->vref_to_sync << 16 | config->href_to_sync, + &disp_ctrl->disp.ref_to_sync); + + WRITEL(config->vsync_width << 16 | config->hsync_width, + &disp_ctrl->disp.sync_width); + + + WRITEL((config->vback_porch << 16) | config->hback_porch, + &disp_ctrl->disp.back_porch); + + WRITEL((config->vfront_porch << 16) | config->hfront_porch, + &disp_ctrl->disp.front_porch); + + WRITEL(config->xres | (config->yres << 16), + &disp_ctrl->disp.disp_active); + + /** + * We want to use PLLD_out0, which is PLLD / 2: + * PixelClock = (PLLD / 2) / ShiftClockDiv / PixelClockDiv. + * + * Currently most panels work inside clock range 50MHz~100MHz, and PLLD + * has some requirements to have VCO in range 500MHz~1000MHz (see + * clock.c for more detail). To simplify calculation, we set + * PixelClockDiv to 1 and ShiftClockDiv to 1. In future these values + * may be calculated by clock_configure_plld(), to allow wider + * frequency range. + * + * Note ShiftClockDiv is a 7.1 format value. + */ + const u32 shift_clock_div = 1; + WRITEL((PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT) | + ((shift_clock_div - 1) * 2 + 1) << SHIFT_CLK_DIVIDER_SHIFT, + &disp_ctrl->disp.disp_clk_ctrl); + printk(BIOS_DEBUG, "%s: PixelClock=%u, ShiftClockDiv=%u\n", + __func__, config->pixel_clock, shift_clock_div); + return 0; +} + +/* + * update_window: + * set up window registers and activate window except two: + * frame buffer base address register (WINBUF_START_ADDR) and + * display enable register (_DISP_DISP_WIN_OPTIONS). This is + * becasue framebuffer is not available until payload stage. + */ +void update_window(const struct soc_nvidia_tegra132_config *config) +{ + struct display_controller *disp_ctrl = + (void *)config->display_controller; + u32 val; + + WRITEL(WINDOW_A_SELECT, &disp_ctrl->cmd.disp_win_header); + + WRITEL(((config->yres << 16) | config->xres), &disp_ctrl->win.size); + + WRITEL(((config->display_yres << 16) | + (config->display_xres * + config->framebuffer_bits_per_pixel / 8)), + &disp_ctrl->win.prescaled_size); + + val = ALIGN_UP((config->display_xres * + config->framebuffer_bits_per_pixel / 8), 64); + WRITEL(val, &disp_ctrl->win.line_stride); + + WRITEL(config->color_depth, &disp_ctrl->win.color_depth); + WRITEL(COLOR_BLACK, &disp_ctrl->disp.blend_background_color); + + WRITEL(((DDA_INC(config->display_yres, config->yres) << 16) | + DDA_INC(config->display_xres, config->xres)), + &disp_ctrl->win.dda_increment); + + WRITEL(DISP_CTRL_MODE_C_DISPLAY, &disp_ctrl->cmd.disp_cmd); + + WRITEL(WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access); + + WRITEL(0, &disp_ctrl->win.buffer_addr_mode); + + val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; + WRITEL(val, &disp_ctrl->cmd.disp_pow_ctrl); + + val = GENERAL_UPDATE | WIN_A_UPDATE; + val |= GENERAL_ACT_REQ | WIN_A_ACT_REQ; + WRITEL(val, &disp_ctrl->cmd.state_ctrl); +} + +int tegra_dc_init(struct display_controller *disp_ctrl) +{ + /* do not accept interrupts during initialization */ + WRITEL(0x00000000, &disp_ctrl->cmd.int_mask); + WRITEL(WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, + &disp_ctrl->cmd.state_access); + WRITEL(WINDOW_A_SELECT, &disp_ctrl->cmd.disp_win_header); + WRITEL(0x00000000, &disp_ctrl->win.win_opt); + WRITEL(0x00000000, &disp_ctrl->win.byte_swap); + WRITEL(0x00000000, &disp_ctrl->win.buffer_ctrl); + + WRITEL(0x00000000, &disp_ctrl->win.pos); + WRITEL(0x00000000, &disp_ctrl->win.h_initial_dda); + WRITEL(0x00000000, &disp_ctrl->win.v_initial_dda); + WRITEL(0x00000000, &disp_ctrl->win.dda_increment); + WRITEL(0x00000000, &disp_ctrl->win.dv_ctrl); + + WRITEL(0x01000000, &disp_ctrl->win.blend_layer_ctrl); + WRITEL(0x00000000, &disp_ctrl->win.blend_match_select); + WRITEL(0x00000000, &disp_ctrl->win.blend_nomatch_select); + WRITEL(0x00000000, &disp_ctrl->win.blend_alpha_1bit); + + WRITEL(0x00000000, &disp_ctrl->winbuf.start_addr_hi); + WRITEL(0x00000000, &disp_ctrl->winbuf.addr_h_offset); + WRITEL(0x00000000, &disp_ctrl->winbuf.addr_v_offset); + + WRITEL(0x00000000, &disp_ctrl->com.crc_checksum); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[0]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[1]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[2]); + WRITEL(0x00000000, &disp_ctrl->com.pin_output_enb[3]); + WRITEL(0x00000000, &disp_ctrl->disp.disp_signal_opt0); + + return 0; +} diff --git a/src/soc/nvidia/tegra132/dma.c b/src/soc/nvidia/tegra132/dma.c new file mode 100644 index 0000000000..9f04e9777f --- /dev/null +++ b/src/soc/nvidia/tegra132/dma.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +struct apb_dma * const apb_dma = (struct apb_dma *)TEGRA_APB_DMA_BASE; + +#define APB_DMA_OFFSET(n) \ + (struct apb_dma_channel_regs *)(TEGRA_APB_DMA_BASE + n) +struct apb_dma_channel apb_dma_channels[] = { + { .num = 0, .regs = APB_DMA_OFFSET(0x1000) }, + { .num = 1, .regs = APB_DMA_OFFSET(0x1040) }, + { .num = 2, .regs = APB_DMA_OFFSET(0x1080) }, + { .num = 3, .regs = APB_DMA_OFFSET(0x10c0) }, + { .num = 4, .regs = APB_DMA_OFFSET(0x1100) }, + { .num = 5, .regs = APB_DMA_OFFSET(0x1140) }, + { .num = 6, .regs = APB_DMA_OFFSET(0x1180) }, + { .num = 7, .regs = APB_DMA_OFFSET(0x11c0) }, + { .num = 8, .regs = APB_DMA_OFFSET(0x1200) }, + { .num = 9, .regs = APB_DMA_OFFSET(0x1240) }, + { .num = 10, .regs = APB_DMA_OFFSET(0x1280) }, + { .num = 11, .regs = APB_DMA_OFFSET(0x12c0) }, + { .num = 12, .regs = APB_DMA_OFFSET(0x1300) }, + { .num = 13, .regs = APB_DMA_OFFSET(0x1340) }, + { .num = 14, .regs = APB_DMA_OFFSET(0x1380) }, + { .num = 15, .regs = APB_DMA_OFFSET(0x13c0) }, + { .num = 16, .regs = APB_DMA_OFFSET(0x1400) }, + { .num = 17, .regs = APB_DMA_OFFSET(0x1440) }, + { .num = 18, .regs = APB_DMA_OFFSET(0x1480) }, + { .num = 19, .regs = APB_DMA_OFFSET(0x14c0) }, + { .num = 20, .regs = APB_DMA_OFFSET(0x1500) }, + { .num = 21, .regs = APB_DMA_OFFSET(0x1540) }, + { .num = 22, .regs = APB_DMA_OFFSET(0x1580) }, + { .num = 23, .regs = APB_DMA_OFFSET(0x15c0) }, + { .num = 24, .regs = APB_DMA_OFFSET(0x1600) }, + { .num = 25, .regs = APB_DMA_OFFSET(0x1640) }, + { .num = 26, .regs = APB_DMA_OFFSET(0x1680) }, + { .num = 27, .regs = APB_DMA_OFFSET(0x16c0) }, + { .num = 28, .regs = APB_DMA_OFFSET(0x1700) }, + { .num = 29, .regs = APB_DMA_OFFSET(0x1740) }, + { .num = 30, .regs = APB_DMA_OFFSET(0x1780) }, + { .num = 31, .regs = APB_DMA_OFFSET(0x17c0) }, +}; + +int dma_busy(struct apb_dma_channel * const channel) +{ + /* + * In continuous mode, the BSY_n bit in APB_DMA_STATUS and + * BSY in APBDMACHAN_CHANNEL_n_STA_0 will remain set as '1' so long + * as the channel is enabled. So for this function we'll use the + * DMA_ACTIVITY bit. + */ + return read32(&channel->regs->sta) & APB_STA_DMA_ACTIVITY ? 1 : 0; +} +/* claim a DMA channel */ +struct apb_dma_channel * const dma_claim(void) +{ + int i; + struct apb_dma_channel_regs *regs = NULL; + + /* + * Set global enable bit, otherwise register access to channel + * DMA registers will not be possible. + */ + setbits_le32(&apb_dma->command, APB_COMMAND_GEN); + + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + regs = apb_dma_channels[i].regs; + + if (!apb_dma_channels[i].in_use) { + u32 status = read32(®s->sta); + if (status & (1 << i)) { + /* FIXME: should this be fatal? */ + printk(BIOS_DEBUG, "%s: DMA channel %d busy?\n", + __func__, i); + } + break; + } + } + + if (i == ARRAY_SIZE(apb_dma_channels)) + return NULL; + + apb_dma_channels[i].in_use = 1; + return &apb_dma_channels[i]; +} + +/* release a DMA channel */ +void dma_release(struct apb_dma_channel * const channel) +{ + int i; + + /* FIXME: make this "thread" friendly */ + while (dma_busy(channel)) + ; + + channel->in_use = 0; + + /* clear the global enable bit if no channels are in use */ + for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) { + if (apb_dma_channels[i].in_use) + return; + } + + clrbits_le32(&apb_dma->command, APB_COMMAND_GEN); +} + +int dma_start(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Set ENB bit for this channel */ + setbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} + +int dma_stop(struct apb_dma_channel * const channel) +{ + struct apb_dma_channel_regs *regs = channel->regs; + + /* Clear ENB bit for this channel */ + clrbits_le32(®s->csr, APB_CSR_ENB); + + return 0; +} diff --git a/src/soc/nvidia/tegra132/dp.c b/src/soc/nvidia/tegra132/dp.c new file mode 100644 index 0000000000..7bd35e8a19 --- /dev/null +++ b/src/soc/nvidia/tegra132/dp.c @@ -0,0 +1,34 @@ +/* + * drivers/video/tegra/dc/dp.c + * + * Copyright (c) 2011-2013, NVIDIA Corporation. + * Copyright 2014 Google Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +void dp_display_startup(device_t dev) +{ + struct soc_nvidia_tegra132_config *config = dev->chip_info; + struct display_controller *disp_ctrl = + (void *)config->display_controller; + + printk(BIOS_INFO, "%s: entry: disp_ctrl: %p.\n", + __func__, disp_ctrl); +} diff --git a/src/soc/nvidia/tegra132/dsi.c b/src/soc/nvidia/tegra132/dsi.c new file mode 100644 index 0000000000..ad27b3d8b4 --- /dev/null +++ b/src/soc/nvidia/tegra132/dsi.c @@ -0,0 +1,970 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" +#include +#include +#include +#include +#include +#include "jdi_25x18_display/panel-jdi-lpm102a188a.h" + +struct tegra_mipi_device mipi_device_data[NUM_DSI]; + +struct tegra_dsi dsi_data[NUM_DSI] = { + { + .regs = (void *)TEGRA_DSIA_BASE, + .channel = 0, + .slave = &dsi_data[DSI_B], + .master = NULL, + .video_fifo_depth = MAX_DSI_VIDEO_FIFO_DEPTH, + .host_fifo_depth = MAX_DSI_HOST_FIFO_DEPTH, + }, + { + .regs = (void *)TEGRA_DSIB_BASE, + .channel = 0, + .slave = NULL, + .master = &dsi_data[DSI_A], + .video_fifo_depth = MAX_DSI_VIDEO_FIFO_DEPTH, + .host_fifo_depth = MAX_DSI_HOST_FIFO_DEPTH, + }, +}; + +static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host) +{ + return container_of(host, struct tegra_dsi, host); +} + +/* + * non-burst mode with sync pulses + */ +static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = { + [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | + PKT_LP, + [ 1] = 0, + [ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | + PKT_LP, + [ 3] = 0, + [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | + PKT_LP, + [ 5] = 0, + [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), + [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | + PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | + PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), + [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) | + PKT_LP, + [ 9] = 0, + [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) | + PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0), + [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) | + PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) | + PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4), +}; + +/* + * non-burst mode with sync events + */ +static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = { + [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | + PKT_LP, + [ 1] = 0, + [ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | + PKT_LP, + [ 3] = 0, + [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | + PKT_LP, + [ 5] = 0, + + [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | + PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), + + [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), + [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) | + PKT_LP, + [ 9] = 0, + + [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) | + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) | + PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3), + + [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4), +}; + +static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = { + [ 0] = 0, + [ 1] = 0, + [ 2] = 0, + [ 3] = 0, + [ 4] = 0, + [ 5] = 0, + [ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP, + [ 7] = 0, + [ 8] = 0, + [ 9] = 0, + [10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP, + [11] = 0, +}; + +static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi) +{ + int err; + + err = mipi_dphy_set_timing(dsi); + if (err < 0) { + printk(BIOS_ERR, "failed to set D-PHY timing: %d\n", err); + return err; + } + + if (dsi->slave) + tegra_dsi_set_phy_timing(dsi->slave); + return 0; +} + +static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format, + unsigned int *mulp, unsigned int *divp) +{ + switch (format) { + case MIPI_DSI_FMT_RGB666_PACKED: + case MIPI_DSI_FMT_RGB888: + *mulp = 3; + *divp = 1; + break; + + case MIPI_DSI_FMT_RGB565: + *mulp = 2; + *divp = 1; + break; + + case MIPI_DSI_FMT_RGB666: + *mulp = 9; + *divp = 4; + break; + + default: + return -EINVAL; + } + return 0; +} + +static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format, + enum tegra_dsi_format *fmt) +{ + switch (format) { + case MIPI_DSI_FMT_RGB888: + *fmt = TEGRA_DSI_FORMAT_24P; + break; + + case MIPI_DSI_FMT_RGB666: + *fmt = TEGRA_DSI_FORMAT_18NP; + break; + + case MIPI_DSI_FMT_RGB666_PACKED: + *fmt = TEGRA_DSI_FORMAT_18P; + break; + + case MIPI_DSI_FMT_RGB565: + *fmt = TEGRA_DSI_FORMAT_16P; + break; + + default: + return -EINVAL; + } + return 0; +} + +static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start, + unsigned int size) +{ + u32 value; + + tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START); + tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE); + + value = DSI_GANGED_MODE_CONTROL_ENABLE; + tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL); +} + +static void tegra_dsi_enable(struct tegra_dsi *dsi) +{ + u32 value; + + value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); + value |= DSI_POWER_CONTROL_ENABLE; + tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); + + if (dsi->slave) + tegra_dsi_enable(dsi->slave); +} + +static int tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe, + const struct soc_nvidia_tegra132_config *mode) +{ + unsigned int hact, hsw, hbp, hfp, i, mul, div; + enum tegra_dsi_format format; + const u32 *pkt_seq; + u32 value; + int err; + + if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { + printk(BIOS_SPEW, "Non-burst video mode with sync pulses\n"); + pkt_seq = pkt_seq_video_non_burst_sync_pulses; + } else if (dsi->flags & MIPI_DSI_MODE_VIDEO) { + printk(BIOS_SPEW, "Non-burst video mode with sync events\n"); + pkt_seq = pkt_seq_video_non_burst_sync_events; + } else { + printk(BIOS_SPEW, "Command mode\n"); + pkt_seq = pkt_seq_command_mode; + } + + err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); + if (err < 0) + return err; + + err = tegra_dsi_get_format(dsi->format, &format); + if (err < 0) + return err; + + value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(format) | + DSI_CONTROL_LANES(dsi->lanes - 1) | + DSI_CONTROL_SOURCE(pipe); + tegra_dsi_writel(dsi, value, DSI_CONTROL); + + tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD); + + value = DSI_HOST_CONTROL_HS; + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + + value = tegra_dsi_readl(dsi, DSI_CONTROL); + + if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) + value |= DSI_CONTROL_HS_CLK_CTRL; + + value &= ~DSI_CONTROL_TX_TRIG(3); + + /* enable DCS commands for command mode */ + if (dsi->flags & MIPI_DSI_MODE_VIDEO) + value &= ~DSI_CONTROL_DCS_ENABLE; + else + value |= DSI_CONTROL_DCS_ENABLE; + + value |= DSI_CONTROL_VIDEO_ENABLE; + value &= ~DSI_CONTROL_HOST_ENABLE; + tegra_dsi_writel(dsi, value, DSI_CONTROL); + + for (i = 0; i < NUM_PKT_SEQ; i++) + tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i); + + if (dsi->flags & MIPI_DSI_MODE_VIDEO) { + /* horizontal active pixels */ + hact = mode->xres * mul / div; + + /* horizontal sync width */ + hsw = (hsync_end(mode) - hsync_start(mode)) * mul / div; + hsw -= 10; + + /* horizontal back porch */ + hbp = (htotal(mode) - hsync_end(mode)) * mul / div; + hbp -= 14; + + /* horizontal front porch */ + hfp = (hsync_start(mode) - mode->xres) * mul / div; + hfp -= 8; + + tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1); + tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3); + tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5); + tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7); + + /* set SOL delay (for non-burst mode only) */ + tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY); + + /* TODO: implement ganged mode */ + } else { + u16 bytes; + if (dsi->ganged_mode) { + /* + * For ganged mode, assume symmetric left-right mode. + */ + bytes = 1 + (mode->xres / 2) * mul / div; + } else { + /* 1 byte (DCS command) + pixel data */ + bytes = 1 + mode->xres * mul / div; + } + + tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1); + tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3); + tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5); + tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7); + + value = MIPI_DCS_WRITE_MEMORY_START << 8 | + MIPI_DCS_WRITE_MEMORY_CONTINUE; + tegra_dsi_writel(dsi, value, DSI_DCS_CMDS); + + /* set SOL delay */ + if (dsi->ganged_mode) { + unsigned long delay, bclk, bclk_ganged; + unsigned int lanes = dsi->ganged_lanes; + + /* SOL to valid, valid to FIFO and FIFO write delay */ + delay = 4 + 4 + 2; + delay = DIV_ROUND_UP(delay * mul, div * lanes); + /* FIFO read delay */ + delay = delay + 6; + + bclk = DIV_ROUND_UP(htotal(mode) * mul, div * lanes); + bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); + value = bclk - bclk_ganged + delay + 20; + } else { + /* TODO: revisit for non-ganged mode */ + value = 8 * mul / div; + } + + tegra_dsi_writel(dsi, value, DSI_SOL_DELAY); + } + + if (dsi->slave) { + err = tegra_dsi_configure(dsi->slave, pipe, mode); + if (err < 0) + return err; + + /* + * enable ganged mode + */ + if (dsi->ganged_mode) { + tegra_dsi_ganged_enable(dsi, mode->xres / 2, + mode->xres / 2); + tegra_dsi_ganged_enable(dsi->slave, 0, mode->xres / 2); + } + } + return 0; +} + +static int tegra_output_dsi_enable(struct tegra_dsi *dsi, + const struct soc_nvidia_tegra132_config *config) +{ + int err; + + if (dsi->enabled) + return 0; + + err = tegra_dsi_configure(dsi, 0, config); + if (err < 0) + return err; + + /* enable DSI controller */ + tegra_dsi_enable(dsi); + + dsi->enabled = true; + return 0; +} + + +static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, + unsigned int vrefresh) +{ + unsigned int timeout; + u32 value; + + /* one frame high-speed transmission timeout */ + timeout = (bclk / vrefresh) / 512; + value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout); + tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0); + + /* 2 ms peripheral timeout for panel */ + timeout = 2 * bclk / 512 * 1000; + value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000); + tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1); + + value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); + tegra_dsi_writel(dsi, value, DSI_TO_TALLY); + + if (dsi->slave) + tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh); +} + +static int tegra_output_dsi_setup_clock(struct tegra_dsi *dsi, + const struct soc_nvidia_tegra132_config *config) +{ + unsigned int mul, div, num_lanes; // , vrefresh, num_lanes; + unsigned long bclk; + unsigned long pclk = config->pixel_clock; + int plld; + int err; + + err = tegra_dsi_get_muldiv(dsi->format, &mul, &div); + if (err < 0) + return err; + + /* + * In ganged mode, account for the total number of lanes across both + * DSI channels so that the bit clock is properly computed. + */ + if (dsi->ganged_mode) + num_lanes = dsi->ganged_lanes; + else + num_lanes = dsi->lanes; + + /* compute byte clock */ + bclk = (pclk * mul) / (div * num_lanes); + + /* + * Compute bit clock and round up to the next MHz. + */ + plld = DIV_ROUND_UP(bclk * 8, USECS_PER_SEC) * USECS_PER_SEC; + + /* + * the actual rate on PLLD_OUT0 is 1/2 plld + */ + dsi->clk_rate = plld / 2; + if (dsi->slave) + dsi->slave->clk_rate = dsi->clk_rate; + + /* set up plld */ + plld = clock_configure_plld(plld); + if (plld == 0) { + printk(BIOS_ERR, "%s: clock init failed\n", __func__); + return -1; + } + + tegra_dsi_set_timeout(dsi, bclk, config->refresh); + return plld/1000000; +} + + + +static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) +{ + unsigned long value; + + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); + tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); + return 0; +} + +static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) +{ + u32 value; + + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); + + /* start calibration */ + tegra_dsi_pad_enable(dsi); + + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | + DSI_PAD_OUT_CLK(0x0); + tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); + + return tegra_mipi_calibrate(dsi->mipi); +} + +static const char * const error_report[16] = { + "SoT Error", + "SoT Sync Error", + "EoT Sync Error", + "Escape Mode Entry Command Error", + "Low-Power Transmit Sync Error", + "Peripheral Timeout Error", + "False Control Error", + "Contention Detected", + "ECC Error, single-bit", + "ECC Error, multi-bit", + "Checksum Error", + "DSI Data Type Not Recognized", + "DSI VC ID Invalid", + "Invalid Transmission Length", + "Reserved", + "DSI Protocol Violation", +}; + +static int tegra_dsi_read_response(struct tegra_dsi *dsi, + const struct mipi_dsi_msg *msg, + unsigned int count) +{ + u8 *rx = msg->rx_buf; + unsigned int i, j, k; + size_t size = 0; + u16 errors; + u32 value; + + /* read and parse packet header */ + value = tegra_dsi_readl(dsi, DSI_RD_DATA); + + switch (value & 0x3f) { + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: + errors = (value >> 8) & 0xffff; + printk(BIOS_ERR, "Acknowledge and error report: %04x\n", + errors); + for (i = 0; i < ARRAY_SIZE(error_report); i++) + if (errors & BIT(i)) + printk(BIOS_INFO, " %2u: %s\n", i, + error_report[i]); + break; + + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: + rx[0] = (value >> 8) & 0xff; + break; + + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: + rx[0] = (value >> 8) & 0xff; + rx[1] = (value >> 16) & 0xff; + break; + + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: + size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); + break; + + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: + size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff); + break; + + default: + printk(BIOS_ERR, "unhandled response type: %02x\n", + value & 0x3f); + break; + } + + size = MIN(size, msg->rx_len); + + if (msg->rx_buf && size > 0) { + for (i = 0, j = 0; i < count - 1; i++, j += 4) { + value = tegra_dsi_readl(dsi, DSI_RD_DATA); + + for (k = 0; k < 4 && (j + k) < msg->rx_len; k++) + rx[j + k] = (value >> (k << 3)) & 0xff; + } + } + return 0; +} + +static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout_ms) +{ + u32 poll_interval_us = 2000; + u32 timeout_us = timeout_ms * 1000; + + tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER); + udelay(poll_interval_us); + + do { + u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER); + if ((value & DSI_TRIGGER_HOST) == 0) + return 0; + + //usleep_range(1000, 2000); + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + + udelay(poll_interval_us); + } while (1); + + printk(BIOS_ERR, "%s: ERROR: timeout waiting for transmission" + " to complete\n", __func__); + return -ETIMEDOUT; +} + +static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi, + unsigned long timeout_ms) +{ + u32 poll_interval_us = 2000; + u32 timeout_us = timeout_ms * 1000; + + do { + u32 value = tegra_dsi_readl(dsi, DSI_STATUS); + u8 count = value & 0x1f; + + if (count > 0) + return count; + + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + + udelay(poll_interval_us); + } while (1); + + printk(BIOS_ERR, "%s: ERROR: timeout\n", __func__); + + return -ETIMEDOUT; +} + +static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct tegra_dsi *dsi = host_to_tegra(host); + const u8 *tx = msg->tx_buf; + unsigned int count, i, j; + u32 value; + int err; + + if (msg->tx_len > dsi->video_fifo_depth * 4) + return -ENOSPC; + + /* reset underflow/overflow flags */ + value = tegra_dsi_readl(dsi, DSI_STATUS); + if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) { + value = DSI_HOST_CONTROL_FIFO_RESET; + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + udelay(20); // usleep_range(10, 20); + } + + value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); + value |= DSI_POWER_CONTROL_ENABLE; + tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); + + udelay(7000); //usleep_range(5000, 10000); + + value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | + DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC; + + if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0) + value |= DSI_HOST_CONTROL_HS; + + /* + * The host FIFO has a maximum of 64 words, so larger transmissions + * need to use the video FIFO. + */ + if (msg->tx_len > dsi->host_fifo_depth * 4) + value |= DSI_HOST_CONTROL_FIFO_SEL; + + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + + /* + * For reads and messages with explicitly requested ACK, generate a + * BTA sequence after the transmission of the packet. + */ + if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || + (msg->rx_buf && msg->rx_len > 0)) { + value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL); + value |= DSI_HOST_CONTROL_PKT_BTA; + tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); + } + + value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE; + tegra_dsi_writel(dsi, value, DSI_CONTROL); + + /* write packet header */ + value = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); + + if (tx && msg->tx_len > 0) + value |= tx[0] << 8; + + if (tx && msg->tx_len > 1) + value |= tx[1] << 16; + + tegra_dsi_writel(dsi, value, DSI_WR_DATA); + + /* write payload (if any) */ + if (msg->tx_len > 2) { + for (j = 2; j < msg->tx_len; j += 4) { + value = 0; + + for (i = 0; i < 4 && j + i < msg->tx_len; i++) + value |= tx[j + i] << (i << 3); + + tegra_dsi_writel(dsi, value, DSI_WR_DATA); + } + } + + err = tegra_dsi_transmit(dsi, 250); + if (err < 0) + return err; + + if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) || + (msg->rx_buf && msg->rx_len > 0)) { + err = tegra_dsi_wait_for_response(dsi, 250); + if (err < 0) + return err; + + count = err; + + value = tegra_dsi_readl(dsi, DSI_RD_DATA); + switch (value) { + case 0x84: + /* + dev_dbg(dsi->dev, "ACK\n"); + */ + break; + + case 0x87: + /* + dev_dbg(dsi->dev, "ESCAPE\n"); + */ + break; + + default: + printk(BIOS_INFO, "unknown status: %08x\n", value); + break; + } + + if (count > 1) { + err = tegra_dsi_read_response(dsi, msg, count); + if (err < 0) + printk(BIOS_INFO, + "failed to parse response: %d\n", + err); + } + } + return 0; +} + +static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi, + struct tegra_dsi *slave) +{ + /* + * The number of ganged lanes is the sum of lanes of all peripherals + * in the gang. + */ + dsi->slave->ganged_lanes = dsi->lanes + dsi->slave->lanes; + dsi->slave->ganged_mode = 1; + + dsi->ganged_lanes = dsi->lanes + dsi->slave->lanes; + dsi->ganged_mode = 1; + return 0; +} + +static int tegra_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) +{ + struct tegra_dsi *dsi = host_to_tegra(host); + int err; + + dsi->flags = device->mode_flags; + dsi->format = device->format; + dsi->lanes = device->lanes; + + if (dsi->master) { + err = tegra_dsi_ganged_setup(dsi->master, dsi); + if (err < 0) { + printk(BIOS_ERR, "failed to set up ganged mode: %d\n", + err); + return err; + } + } + return 0; +} + +static const struct mipi_dsi_host_ops tegra_dsi_host_ops = { + .attach = tegra_dsi_host_attach, + .transfer = tegra_dsi_host_transfer, +}; + +static int dsi_probe_if(int dsi_index, + struct soc_nvidia_tegra132_config *config) +{ + struct tegra_dsi *dsi = &dsi_data[dsi_index]; + int err; + + /* + * Set default value. Will be taken from attached device once detected + */ + dsi->flags = 0; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->lanes = 4; + + /* get tegra_mipi_device */ + dsi->mipi = tegra_mipi_request(&mipi_device_data[dsi_index], dsi_index); + + /* calibrate */ + err = tegra_dsi_pad_calibrate(dsi); + if (err < 0) { + printk(BIOS_ERR, "MIPI calibration failed: %d\n", err); + return err; + } + + dsi->host.ops = &tegra_dsi_host_ops; + err = mipi_dsi_host_register(&dsi->host); + if (err < 0) { + printk(BIOS_ERR, "failed to register DSI host: %d\n", err); + return err; + } + + /* get panel */ + dsi->panel = panel_jdi_dsi_probe((struct mipi_dsi_device *)dsi->host.dev); + if (IS_ERR_PTR(dsi->panel)) { + printk(BIOS_ERR, "failed to get dsi panel\n"); + return -EPTR; + } + dsi->panel->mode = config; + return 0; +} + +static int dsi_probe(struct soc_nvidia_tegra132_config *config) +{ + dsi_probe_if(DSI_A, config); + dsi_probe_if(DSI_B, config); + return 0; +} + +static int dsi_enable(struct soc_nvidia_tegra132_config *config) +{ + struct tegra_dsi *dsi_a = &dsi_data[DSI_A]; + + dsi_probe(config); + + /* set up clock and TimeOutRegisters */ + tegra_output_dsi_setup_clock(dsi_a, config); + + /* configure APB_MISC_GP_MIPI_PAD_CTRL_0 */ + write32(DSIB_MODE_DSI, (unsigned int *)APB_MISC_GP_MIPI_PAD_CTRL_0); + + /* configure phy interface timing registers */ + tegra_dsi_set_phy_timing(dsi_a); + + /* prepare panel */ + panel_jdi_prepare(dsi_a->panel); + + /* enable dsi */ + if (tegra_output_dsi_enable(dsi_a, config)) { + printk(BIOS_ERR,"%s: Error: failed to enable dsi output.\n", + __func__); + return -1; + } + + return 0; +} + +void dsi_display_startup(device_t dev) +{ + struct soc_nvidia_tegra132_config *config = dev->chip_info; + struct display_controller *disp_ctrl = + (void *)config->display_controller; + u32 plld_rate; + + u32 framebuffer_size_mb = config->framebuffer_size / MiB; + u32 framebuffer_base_mb= config->framebuffer_base / MiB; + + printk(BIOS_INFO, "%s: entry: disp_ctrl: %p.\n", + __func__, disp_ctrl); + + if (disp_ctrl == NULL) { + printk(BIOS_ERR, "Error: No dc is assigned by dt.\n"); + return; + } + + if (framebuffer_size_mb == 0){ + framebuffer_size_mb = ALIGN_UP(config->display_xres * + config->display_yres * + (config->framebuffer_bits_per_pixel / 8), MiB)/MiB; + } + + config->framebuffer_size = framebuffer_size_mb * MiB; + config->framebuffer_base = framebuffer_base_mb * MiB; + + /* + * The plld is programmed with the assumption of the SHIFT_CLK_DIVIDER + * and PIXEL_CLK_DIVIDER are zero (divide by 1). See the + * update_display_mode() for detail. + */ + /* set default plld */ + plld_rate = clock_configure_plld(config->pixel_clock * 2); + if (plld_rate == 0) { + printk(BIOS_ERR, "dc: clock init failed\n"); + return; + } + + /* set disp1's clock source to PLLD_OUT0 */ + clock_configure_source(disp1, PLLD, (plld_rate/KHz)/2); + + /* Init dc */ + if (tegra_dc_init(disp_ctrl)) { + printk(BIOS_ERR, "dc: init failed\n"); + return; + } + + /* Configure dc mode */ + if (update_display_mode(disp_ctrl, config)) { + printk(BIOS_ERR, "dc: failed to configure display mode.\n"); + return; + } + + /* Configure and enable dsi controller and panel */ + if (dsi_enable(config)) { + printk(BIOS_ERR, "%s: failed to enable dsi controllers.\n", + __func__); + return; + } + + /* Set up window */ + update_window(config); + printk(BIOS_INFO, "%s: display init done.\n", __func__); + + /* + * Pass panel information to cb tables + */ + struct edid edid; + /* Align bytes_per_line to 64 bytes as required by dc */ + edid.bytes_per_line = ALIGN_UP((config->display_xres * + config->framebuffer_bits_per_pixel / 8), 64); + edid.x_resolution = edid.bytes_per_line / + (config->framebuffer_bits_per_pixel / 8); + edid.y_resolution = config->display_yres; + edid.framebuffer_bits_per_pixel = config->framebuffer_bits_per_pixel; + + printk(BIOS_INFO, "%s: bytes_per_line: %d, bits_per_pixel: %d\n " + " x_res x y_res: %d x %d, size: %d\n", + __func__, edid.bytes_per_line, + edid.framebuffer_bits_per_pixel, + edid.x_resolution, edid.y_resolution, + (edid.bytes_per_line * edid.y_resolution)); + + set_vbe_mode_info_valid(&edid, 0); + + /* + * After this point, it is payload's responsibility to allocate + * framebuffer and sets the base address to dc's + * WINBUF_START_ADDR register and enables window by setting dc's + * DISP_DISP_WIN_OPTIONS register. + */ +} diff --git a/src/soc/nvidia/tegra132/flow_ctrl.c b/src/soc/nvidia/tegra132/flow_ctrl.c new file mode 100644 index 0000000000..4da54b1ea1 --- /dev/null +++ b/src/soc/nvidia/tegra132/flow_ctrl.c @@ -0,0 +1,96 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#define FLOW_CTRL_HALT_CPU0_EVENTS 0x0 +#define FLOW_CTRL_WAITEVENT (2 << 29) +#define FLOW_CTRL_WAIT_FOR_INTERRUPT (4 << 29) +#define FLOW_CTRL_HALT_LIC_IRQ (1 << 11) +#define FLOW_CTRL_HALT_LIC_FIQ (1 << 10) +#define FLOW_CTRL_CPU0_CSR 0x8 +#define FLOW_CTRL_CSR_INTR_FLAG (1 << 15) +#define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14) +#define FLOW_CTRL_CSR_WFI_CPU0 (1 << 8) +#define FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8) +#define FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4) +#define FLOW_CTRL_CSR_ENABLE (1 << 0) +#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14 +#define FLOW_CTRL_CPU1_CSR 0x18 + +#define HALT_REG_CORE0 (\ + FLOW_CTRL_WAIT_FOR_INTERRUPT | \ + FLOW_CTRL_HALT_LIC_IRQ | \ + FLOW_CTRL_HALT_LIC_FIQ) + +#define HALT_REG_CORE1 FLOW_CTRL_WAITEVENT + +static void *tegra_flowctrl_base = (void*)TEGRA_FLOW_BASE; + +static const uint8_t flowctrl_offset_halt_cpu[] = { + FLOW_CTRL_HALT_CPU0_EVENTS, + FLOW_CTRL_HALT_CPU1_EVENTS +}; + +static const uint8_t flowctrl_offset_cpu_csr[] = { + FLOW_CTRL_CPU0_CSR, + FLOW_CTRL_CPU1_CSR +}; + +static uint32_t flowctrl_read_cpu_csr(int cpu) +{ + return read32(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]); +} + +static void flowctrl_write_cpu_csr(int cpu, uint32_t val) +{ + write32(val, tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]); + val = readl(tegra_flowctrl_base + flowctrl_offset_cpu_csr[cpu]); +} + +void flowctrl_write_cpu_halt(int cpu, uint32_t val) +{ + writel(val, tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]); + val = readl(tegra_flowctrl_base + flowctrl_offset_halt_cpu[cpu]); +} + +static void flowctrl_prepare_cpu_off(int cpu) +{ + uint32_t reg; + + reg = flowctrl_read_cpu_csr(cpu); + reg &= ~FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */ + reg &= ~FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */ + reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */ + reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */ + reg |= FLOW_CTRL_CSR_WFI_CPU0 << cpu; /* power gating on wfi */ + reg |= FLOW_CTRL_CSR_ENABLE; /* enable power gating */ + flowctrl_write_cpu_csr(cpu, reg); +} + +void flowctrl_cpu_off(int cpu) +{ + uint32_t reg; + + reg = cpu ? HALT_REG_CORE1 : HALT_REG_CORE0; + flowctrl_prepare_cpu_off(cpu); + flowctrl_write_cpu_halt(cpu, reg); +} diff --git a/src/soc/nvidia/tegra132/funitcfg.c b/src/soc/nvidia/tegra132/funitcfg.c new file mode 100644 index 0000000000..4c584c0028 --- /dev/null +++ b/src/soc/nvidia/tegra132/funitcfg.c @@ -0,0 +1,186 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +struct clk_dev_control { + uint32_t *clk_enb_set; + uint32_t *rst_dev_clr; +}; + +struct funit_cfg_data { + const char *name; + void *ctlr_base; + uint32_t *clk_src_reg; + const struct clk_dev_control * const dev_control; + uint32_t clk_enb_val; +}; + +enum { + CLK_L_SET = 0, + CLK_H_SET = 1, + CLK_U_SET = 2, + CLK_V_SET = 3, + CLK_W_SET = 4, + CLK_X_SET = 5, +}; + +#define CLK_SET_REGS(x) \ + { \ + CLK_RST_REG(clk_enb_##x##_set), \ + CLK_RST_REG(rst_dev_##x##_clr), \ + } + +static const struct clk_dev_control clk_data_arr[] = { + [CLK_L_SET] = CLK_SET_REGS(l), + [CLK_H_SET] = CLK_SET_REGS(h), + [CLK_U_SET] = CLK_SET_REGS(u), + [CLK_V_SET] = CLK_SET_REGS(v), + [CLK_W_SET] = CLK_SET_REGS(w), + [CLK_X_SET] = CLK_SET_REGS(x), +}; + +#define FUNIT_DATA(funit_, loname_, clk_set_) \ + [FUNIT_INDEX(funit_)] = { \ + .name = STRINGIFY(loname_), \ + .ctlr_base = (void *)(uintptr_t)TEGRA_##funit_##_BASE, \ + .clk_src_reg = CLK_RST_REG(clk_src_##loname_), \ + .dev_control = &clk_data_arr[CLK_##clk_set_##_SET], \ + .clk_enb_val = CLK_##clk_set_##_##funit_, \ + } + +#define FUNIT_DATA_USB(funit_, clk_set_) \ + [FUNIT_INDEX(funit_)] = { \ + .name = STRINGIFY(funit_), \ + .ctlr_base = (void *)(uintptr_t)TEGRA_##funit_##_BASE, \ + .dev_control = &clk_data_arr[CLK_##clk_set_##_SET], \ + .clk_enb_val = CLK_##clk_set_##_##funit_, \ + } + +static const struct funit_cfg_data funit_data[] = { + FUNIT_DATA(SBC1, sbc1, H), + FUNIT_DATA(SBC4, sbc4, U), + FUNIT_DATA(I2C1, i2c1, L), + FUNIT_DATA(I2C2, i2c2, H), + FUNIT_DATA(I2C3, i2c3, U), + FUNIT_DATA(I2C5, i2c5, H), + FUNIT_DATA(I2C6, i2c6, X), + FUNIT_DATA(SDMMC3, sdmmc3, U), + FUNIT_DATA(SDMMC4, sdmmc4, L), + FUNIT_DATA_USB(USBD, L), + FUNIT_DATA_USB(USB2, H), + FUNIT_DATA_USB(USB3, H), + FUNIT_DATA(I2S1, i2s1, L), +}; +_Static_assert(ARRAY_SIZE(funit_data) == FUNIT_INDEX_MAX, + "funit_cfg_data array not filled out!"); + +static inline uint32_t get_clk_src_freq(uint32_t clk_src_freq_id) +{ + uint32_t freq = 0; + + switch (clk_src_freq_id) { + case CLK_M: + freq = TEGRA_CLK_M_KHZ; + break; + case PLLP: + freq = TEGRA_PLLP_KHZ; + break; + default: + printk(BIOS_SPEW, "%s ERROR: Unknown clk_src %d\n", + __func__, clk_src_freq_id); + } + + return freq; +} + +static void configure_clock(const struct funit_cfg * const entry, + const struct funit_cfg_data * const funit) +{ + const char *funit_i2c = "i2c"; + uint32_t clk_div; + uint32_t clk_div_mask; + uint32_t clk_src_freq; + + clk_src_freq = get_clk_src_freq(entry->clk_src_freq_id); + + if (strncmp(funit->name, funit_i2c, strlen(funit_i2c)) == 0) { + /* I2C funit */ + clk_div = get_i2c_clk_div(clk_src_freq, + entry->clk_dev_freq_khz); + clk_div_mask = CLK_DIV_MASK_I2C; + } else { + /* Non I2C */ + clk_div = get_clk_div(clk_src_freq, entry->clk_dev_freq_khz); + clk_div_mask = CLK_DIV_MASK; + } + + _clock_set_div(funit->clk_src_reg, funit->name, clk_div, + clk_div_mask, entry->clk_src_id); +} + +static inline int is_usb(uint32_t idx) +{ + return (idx == FUNIT_USBD || idx == FUNIT_USB2 || idx == FUNIT_USB3); +} + +void soc_configure_funits(const struct funit_cfg * const entries, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) { + const struct funit_cfg * const entry = &entries[i]; + const struct funit_cfg_data *funit; + const struct clk_dev_control *dev_control; + int funit_usb = is_usb(entry->funit_index); + + if (entry->funit_index >= FUNIT_INDEX_MAX) { + printk(BIOS_ERR, "Error: Index out of bounds\n"); + continue; + } + + funit = &funit_data[entry->funit_index]; + dev_control = funit->dev_control; + + /* USB controllers have a fixed clock source. */ + if (!funit_usb) + configure_clock(entry, funit); + + clock_grp_enable_clear_reset(funit->clk_enb_val, + dev_control->clk_enb_set, + dev_control->rst_dev_clr); + + if (funit_usb) + usb_setup_utmip(funit->ctlr_base); + + soc_configure_pads(entry->pad_cfg,entry->pad_cfg_size); + } +} + +void __attribute__((weak)) usb_setup_utmip(void *usb_base) +{ + /* default empty implementation required if usb.c is not included */ + printk(BIOS_ERR, "USB setup is not supported in current stage\n"); +} diff --git a/src/soc/nvidia/tegra132/gic.c b/src/soc/nvidia/tegra132/gic.c new file mode 100644 index 0000000000..a8cd58e045 --- /dev/null +++ b/src/soc/nvidia/tegra132/gic.c @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +void *gicd_base(void) +{ + return (void *)(uintptr_t)TEGRA_GICD_BASE; +} + +void *gicc_base(void) +{ + return (void *)(uintptr_t)TEGRA_GICC_BASE; +} diff --git a/src/soc/nvidia/tegra132/i2c.c b/src/soc/nvidia/tegra132/i2c.c new file mode 100644 index 0000000000..dc85806967 --- /dev/null +++ b/src/soc/nvidia/tegra132/i2c.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +struct tegra_i2c_bus_info tegra_i2c_info[] = { + { + .base = (void *)TEGRA_I2C1_BASE, + .reset_bit = CLK_L_I2C1, + .reset_func = &clock_reset_l + }, + { + .base = (void *)TEGRA_I2C2_BASE, + .reset_bit = CLK_H_I2C2, + .reset_func = &clock_reset_h + }, + { + .base = (void *)TEGRA_I2C3_BASE, + .reset_bit = CLK_U_I2C3, + .reset_func = &clock_reset_u + }, + { + .base = (void *)TEGRA_I2C4_BASE, + .reset_bit = CLK_V_I2C4, + .reset_func = &clock_reset_v + }, + { + .base = (void *)TEGRA_I2C5_BASE, + .reset_bit = CLK_H_I2C5, + .reset_func = &clock_reset_h + }, + { + .base = (void *)TEGRA_I2C6_BASE, + .reset_bit = CLK_X_I2C6, + .reset_func = &clock_reset_x + } +}; diff --git a/src/soc/nvidia/tegra132/i2c6.c b/src/soc/nvidia/tegra132/i2c6.c new file mode 100644 index 0000000000..7acb004bc4 --- /dev/null +++ b/src/soc/nvidia/tegra132/i2c6.c @@ -0,0 +1,106 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2014, NVIDIA CORPORATION. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define I2C6_PADCTL 0xC001 +#define DPAUX_HYBRID_PADCTL 0x545C0124 + +static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE; + +static int partition_clamp_on(int id) +{ + return read32(&pmc->clamp_status) & (1 << id); +} + +static void remove_clamps(int id) +{ + if (!partition_clamp_on(id)) + return; + + /* Remove clamp */ + write32((1 << id), &pmc->remove_clamping_cmd); + + /* Wait for clamp off */ + while (partition_clamp_on(id)) + ; +} + +static void enable_sor_periph_clocks(void) +{ + clock_enable(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); +} + +static void disable_sor_periph_clocks(void) +{ + clock_disable(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX); + + /* Give clocks time to stabilize. */ + udelay(IO_STABILIZATION_DELAY); +} + +static void unreset_sor_periphs(void) +{ + clock_clr_reset(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX); +} + +void soc_configure_i2c6pad(void) +{ + /* + * I2C6 on Tegra124/132 requires some special init. + * The SOR block must be unpowergated, and a couple of + * display-based peripherals must be clocked and taken + * out of reset so that a DPAUX register can be + * configured to enable the I2C6 mux routing. + * Afterwards, we can disable clocks to the display blocks + * and put Host1X back in reset. DPAUX must remain out of + * reset and the SOR partition must remained unpowergated. + */ + power_ungate_partition(POWER_PARTID_SOR); + /* Host1X needs a valid clock source so DPAUX can be accessed. */ + clock_configure_source(host1x, PLLP, 204000); + + enable_sor_periph_clocks(); + remove_clamps(POWER_PARTID_SOR); + unreset_sor_periphs(); + + /* Now we can write the I2C6 mux in DPAUX */ + write32(I2C6_PADCTL, (void *)DPAUX_HYBRID_PADCTL); + + /* + * Delay before turning off Host1X/DPAUX clocks. + * This delay is needed to keep the sequence from + * hanging the system. + */ + udelay(CLOCK_PLL_STABLE_DELAY_US); + + /* Stop Host1X/DPAUX clocks and reset Host1X */ + disable_sor_periph_clocks(); + clock_set_reset_l(CLK_L_HOST1X); +} diff --git a/src/soc/nvidia/tegra132/include/soc/addressmap.h b/src/soc/nvidia/tegra132/include/soc/addressmap.h new file mode 100644 index 0000000000..02ab2d4e5f --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/addressmap.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ADDRESS_MAP_H__ +#define __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ADDRESS_MAP_H__ + +#include +#include + +enum { + TEGRA_SRAM_BASE = 0x40000000, + TEGRA_SRAM_SIZE = 0x40000 +}; + +enum { + TEGRA_ARM_PERIPHBASE = 0x50040000, + TEGRA_GICD_BASE = 0x50041000, + TEGRA_GICC_BASE = 0x50042000, + TEGRA_ARM_DISPLAYA = 0x54200000, + TEGRA_ARM_DISPLAYB = 0x54240000, + TEGRA_DSIA_BASE = 0x54300000, + TEGRA_DSIB_BASE = 0x54400000, + TEGRA_ARM_SOR = 0x54540000, + TEGRA_ARM_DPAUX = 0x545c0000, + TEGRA_PG_UP_BASE = 0x60000000, + TEGRA_TMRUS_BASE = 0x60005010, + TEGRA_CLK_RST_BASE = 0x60006000, + TEGRA_FLOW_BASE = 0x60007000, + TEGRA_GPIO_BASE = 0x6000D000, + TEGRA_EVP_BASE = 0x6000F000, + TEGRA_APB_DMA_BASE = 0x60020000, + TEGRA_APB_MISC_BASE = 0x70000000, + TEGRA_APB_MISC_GP_BASE = TEGRA_APB_MISC_BASE + 0x0800, + TEGRA_APB_PINGROUP_BASE = TEGRA_APB_MISC_BASE + 0x0868, + TEGRA_APB_PINMUX_BASE = TEGRA_APB_MISC_BASE + 0x3000, + TEGRA_APB_UARTA_BASE = TEGRA_APB_MISC_BASE + 0x6000, + TEGRA_APB_UARTB_BASE = TEGRA_APB_MISC_BASE + 0x6040, + TEGRA_APB_UARTC_BASE = TEGRA_APB_MISC_BASE + 0x6200, + TEGRA_APB_UARTD_BASE = TEGRA_APB_MISC_BASE + 0x6300, + TEGRA_APB_UARTE_BASE = TEGRA_APB_MISC_BASE + 0x6400, + TEGRA_NAND_BASE = TEGRA_APB_MISC_BASE + 0x8000, + TEGRA_PWM_BASE = TEGRA_APB_MISC_BASE + 0xA000, + TEGRA_I2C1_BASE = TEGRA_APB_MISC_BASE + 0xC000, + TEGRA_SPI_BASE = TEGRA_APB_MISC_BASE + 0xC380, + TEGRA_I2C2_BASE = TEGRA_APB_MISC_BASE + 0xC400, + TEGRA_I2C3_BASE = TEGRA_APB_MISC_BASE + 0xC500, + TEGRA_I2C4_BASE = TEGRA_APB_MISC_BASE + 0xC700, + TEGRA_I2C5_BASE = TEGRA_APB_MISC_BASE + 0xD000, + TEGRA_I2C6_BASE = TEGRA_APB_MISC_BASE + 0xD100, + TEGRA_SPI1_BASE = TEGRA_APB_MISC_BASE + 0xD400, + TEGRA_SPI2_BASE = TEGRA_APB_MISC_BASE + 0xD600, + TEGRA_SPI3_BASE = TEGRA_APB_MISC_BASE + 0xD800, + TEGRA_SPI4_BASE = TEGRA_APB_MISC_BASE + 0xDA00, + TEGRA_SPI5_BASE = TEGRA_APB_MISC_BASE + 0xDC00, + TEGRA_SPI6_BASE = TEGRA_APB_MISC_BASE + 0xDE00, + TEGRA_SBC1_BASE = TEGRA_SPI1_BASE, + TEGRA_SBC2_BASE = TEGRA_SPI2_BASE, + TEGRA_SBC3_BASE = TEGRA_SPI3_BASE, + TEGRA_SBC4_BASE = TEGRA_SPI4_BASE, + TEGRA_SBC5_BASE = TEGRA_SPI5_BASE, + TEGRA_SBC6_BASE = TEGRA_SPI6_BASE, + TEGRA_PMC_BASE = TEGRA_APB_MISC_BASE + 0xE400, + TEGRA_FUSE_BASE = TEGRA_APB_MISC_BASE + 0xF800, + TEGRA_MC_BASE = 0x70019000, + TEGRA_EMC_BASE = 0x7001B000, + TEGRA_CLUSTER_CLOCK_BASE = 0x70040000, + TEGRA_CSITE_BASE = 0x70800000, + TEGRA_SDMMC_BASE = 0x700b0000, + TEGRA_SDMMC1_BASE = TEGRA_SDMMC_BASE + 0x0000, + TEGRA_SDMMC2_BASE = TEGRA_SDMMC_BASE + 0x0200, + TEGRA_SDMMC3_BASE = TEGRA_SDMMC_BASE + 0x0400, + TEGRA_SDMMC4_BASE = TEGRA_SDMMC_BASE + 0x0600, + TEGRA_MIPI_CAL_BASE = 0x700E3000, + TEGRA_SYSCTR0_BASE = 0x700F0000, + TEGRA_I2S1_BASE = 0x70301100, + TEGRA_USBD_BASE = 0x7D000000, + TEGRA_USB2_BASE = 0x7D004000, + TEGRA_USB3_BASE = 0x7D008000, +}; + +enum { + TEGRA_I2C_BASE_COUNT = 6, +}; + +/* Return total size of DRAM memory configured on the platform. */ +int sdram_size_mb(void); + +/* Find memory below and above 4GiB boundary repsectively. All units 1MiB. */ +void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib); +void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib); + +enum { + CARVEOUT_TZ, + CARVEOUT_SEC, + CARVEOUT_MTS, + CARVEOUT_VPR, + CARVEOUT_NUM, +}; + +/* Provided the careout id, obtain the base and size in 1MiB units. */ +void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib); + + +/* + * Add any board-specific memory ranges to the address map when executing + * on aarchv8 core. + */ +struct memranges; +void mainboard_add_memory_ranges(struct memranges *map); + +/* + * There are complications accessing the Trust Zone carveout region. The + * AVP cannot access these registers and the CPU can't access this register + * as a non-secure access. When the page tables live in non-secure memory + * these registers cannot be accessed either. Thus, this function handles + * both the AVP case and non-secured access case by keeping global state. + */ +void trustzone_region_init(void); + +#endif /* __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ADDRESS_MAP_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/ccplex.h b/src/soc/nvidia/tegra132/include/soc/ccplex.h new file mode 100644 index 0000000000..bd0679b259 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/ccplex.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_CCPLEX_H__ +#define __SOC_NVIDIA_TEGRA132_CCPLEX_H__ + +#include + +#define MTS_LOAD_ADDRESS 0x82000000 + +/* Prepare the clocks and rails to start the cpu. */ +void ccplex_cpu_prepare(void); + +/* Loads the MTS microcode. Return 0 on success, < 0 on error. */ +int ccplex_load_mts(void); + +/* Start cpu0 and have it start executing at entry_addr */ +void ccplex_cpu_start(void *entry_addr); + +#endif /* __SOC_NVIDIA_TEGRA132_CCPLEX_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/clk_rst.h b/src/soc/nvidia/tegra132/include/soc/clk_rst.h new file mode 100644 index 0000000000..bde2b56fd3 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/clk_rst.h @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA132_CLK_RST_H_ +#define _TEGRA132_CLK_RST_H_ +#include +#include + +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ +struct __attribute__ ((__packed__)) clk_rst_ctlr { + u32 rst_src; /* _RST_SOURCE, 0x000 */ + u32 rst_dev_l; /* _RST_DEVICES_L, 0x004 */ + u32 rst_dev_h; /* _RST_DEVICES_H, 0x008 */ + u32 rst_dev_u; /* _RST_DEVICES_U, 0x00c */ + u32 clk_out_enb_l; /* _CLK_OUT_ENB_L, 0x010 */ + u32 clk_out_enb_h; /* _CLK_OUT_ENB_H, 0x014 */ + u32 clk_out_enb_u; /* _CLK_OUT_ENB_U, 0x018 */ + u32 _rsv0; /* 0x01c */ + u32 cclk_brst_pol; /* _CCLK_BURST_POLICY, 0x020 */ + u32 super_cclk_div; /* _SUPER_CCLK_DIVIDER, 0x024 */ + u32 sclk_brst_pol; /* _SCLK_BURST_POLICY, 0x028 */ + u32 super_sclk_div; /* _SUPER_SCLK_DIVIDER, 0x02C */ + u32 clk_sys_rate; /* _CLK_SYSTEM_RATE, 0x030 */ + u32 _rsv1[3]; /* 0x034-03c */ + u32 cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY, 0x040 */ + u32 clk_mask_arm; /* _CLK_MASK_ARM, 0x044 */ + u32 misc_clk_enb; /* _MISC_CLK_ENB, 0x048 */ + u32 clk_cpu_cmplx; /* _CLK_CPU_CMPLX, 0x04C */ + u32 osc_ctrl; /* _OSC_CTRL, 0x050 */ + u32 pll_lfsr; /* _PLL_LFSR, 0x054 */ + u32 osc_freq_det; /* _OSC_FREQ_DET, 0x058 */ + u32 osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS, 0x05C */ + u32 _rsv2[8]; /* 0x060-07C */ + u32 pllc_base; /* _PLLC_BASE, 0x080 */ + u32 pllc_out; /* _PLLC_OUT, 0x084 */ + u32 pllc_misc2; /* _PLLC_MISC2, 0x088 */ + u32 pllc_misc; /* _PLLC_MISC, 0x08c */ + u32 pllm_base; /* _PLLM_BASE, 0x090 */ + u32 pllm_out; /* _PLLM_OUT, 0x094 */ + u32 pllm_misc1; /* _PLLM_MISC1, 0x098 */ + u32 pllm_misc2; /* _PLLM_MISC2, 0x09c */ + u32 pllp_base; /* _PLLP_BASE, 0x0a0 */ + u32 pllp_outa; /* _PLLP_OUTA, 0x0a4 */ + u32 pllp_outb; /* _PLLP_OUTB, 0x0a8 */ + u32 pllp_misc; /* _PLLP_MISC, 0x0ac */ + u32 plla_base; /* _PLLA_BASE, 0x0b0 */ + u32 plla_out; /* _PLLA_OUT, 0x0b4 */ + u32 _rsv3; /* 0x0b8 */ + u32 plla_misc; /* _PLLA_MISC, 0x0bc */ + u32 pllu_base; /* _PLLU_BASE, 0x0c0 */ + u32 _rsv4[2]; /* 0x0c4-0c8 */ + u32 pllu_misc; /* _PLLU_MISC, 0x0cc */ + u32 plld_base; /* _PLLD_BASE, 0x0d0 */ + u32 _rsv5[2]; /* 0x0d4-0d8 */ + u32 plld_misc; /* _PLLD_MISC, 0x0dc */ + u32 pllx_base; /* _PLLX_BASE, 0x0e0 */ + u32 pllx_misc; /* _PLLX_MISC, 0x0e4 */ + u32 plle_base; /* _PLLE_BASE, 0x0e8 */ + u32 plle_misc; /* _PLLE_MISC, 0x0ec */ + u32 plls_base; /* _PLLS_BASE, 0x0f0 */ + u32 plls_misc; /* _PLLS_MISC, 0x0f4 */ + u32 _rsv6[2]; /* 0x0f8-0fc */ + u32 clk_src_i2s1; /* _CLK_SOURCE_I2S1, 0x100 */ + u32 clk_src_i2s2; /* _CLK_SOURCE_I2S2, 0x104 */ + u32 clk_src_spdif_out; /* _CLK_SOURCE_SPDIF_OUT, 0x108 */ + u32 clk_src_spdif_in; /* _CLK_SOURCE_SPDIF_IN, 0x10c */ + u32 clk_src_pwm; /* _CLK_SOURCE_PWM, 0x110 */ + u32 _rsv7; /* 0x114 */ + u32 clk_src_sbc2; /* _CLK_SOURCE_SBC2, 0x118 */ + u32 clk_src_sbc3; /* _CLK_SOURCE_SBC3, 0x11c */ + u32 _rsv8; /* 0x120 */ + u32 clk_src_i2c1; /* _CLK_SOURCE_I2C1, 0x124 */ + u32 clk_src_i2c5; /* _CLK_SOURCE_I2C5, 0x128 */ + u32 _rsv9[2]; /* 0x12c-130 */ + u32 clk_src_sbc1; /* _CLK_SOURCE_SBC1, 0x134 */ + u32 clk_src_disp1; /* _CLK_SOURCE_DISP1, 0x138 */ + u32 clk_src_disp2; /* _CLK_SOURCE_DISP2, 0x13c */ + u32 _rsv10[2]; /* 0x140-144 */ + u32 clk_src_vi; /* _CLK_SOURCE_VI, 0x148 */ + u32 _rsv11; /* 0x14c */ + u32 clk_src_sdmmc1; /* _CLK_SOURCE_SDMMC1, 0x150 */ + u32 clk_src_sdmmc2; /* _CLK_SOURCE_SDMMC2, 0x154 */ + u32 clk_src_g3d; /* _CLK_SOURCE_G3D, 0x158 */ + u32 clk_src_g2d; /* _CLK_SOURCE_G2D, 0x15c */ + u32 clk_src_ndflash; /* _CLK_SOURCE_NDFLASH, 0x160 */ + u32 clk_src_sdmmc4; /* _CLK_SOURCE_SDMMC4, 0x164 */ + u32 clk_src_vfir; /* _CLK_SOURCE_VFIR, 0x168 */ + u32 clk_src_epp; /* _CLK_SOURCE_EPP, 0x16c */ + u32 clk_src_mpe; /* _CLK_SOURCE_MPE, 0x170 */ + u32 clk_src_hsi; /* _CLK_SOURCE_HSI, 0x174 */ + u32 clk_src_uarta; /* _CLK_SOURCE_UARTA, 0x178 */ + u32 clk_src_uartb; /* _CLK_SOURCE_UARTB, 0x17c */ + u32 clk_src_host1x; /* _CLK_SOURCE_HOST1X, 0x180 */ + u32 _rsv12[2]; /* 0x184-188 */ + u32 clk_src_hdmi; /* _CLK_SOURCE_HDMI, 0x18c */ + u32 _rsv13[2]; /* 0x190-194 */ + u32 clk_src_i2c2; /* _CLK_SOURCE_I2C2, 0x198 */ + u32 clk_src_emc; /* _CLK_SOURCE_EMC, 0x19c */ + u32 clk_src_uartc; /* _CLK_SOURCE_UARTC, 0x1a0 */ + u32 _rsv14; /* 0x1a4 */ + u32 clk_src_vi_sensor; /* _CLK_SOURCE_VI_SENSOR, 0x1a8 */ + u32 _rsv15[2]; /* 0x1ac-1b0 */ + u32 clk_src_sbc4; /* _CLK_SOURCE_SBC4, 0x1b4 */ + u32 clk_src_i2c3; /* _CLK_SOURCE_I2C3, 0x1b8 */ + u32 clk_src_sdmmc3; /* _CLK_SOURCE_SDMMC3, 0x1bc */ + u32 clk_src_uartd; /* _CLK_SOURCE_UARTD, 0x1c0 */ + u32 clk_src_uarte; /* _CLK_SOURCE_UARTE, 0x1c4 */ + u32 clk_src_vde; /* _CLK_SOURCE_VDE, 0x1c8 */ + u32 clk_src_owr; /* _CLK_SOURCE_OWR, 0x1cc */ + u32 clk_src_nor; /* _CLK_SOURCE_NOR, 0x1d0 */ + u32 clk_src_csite; /* _CLK_SOURCE_CSITE, 0x1d4 */ + u32 clk_src_i2s0; /* _CLK_SOURCE_I2S0, 0x1d8 */ + u32 clk_src_dtv; /* _CLK_SOURCE_DTV, 0x1dc */ + u32 _rsv16[4]; /* 0x1e0-1ec */ + u32 clk_src_msenc; /* _CLK_SOURCE_MSENC, 0x1f0 */ + u32 clk_src_tsec; /* _CLK_SOURCE_TSEC, 0x1f4 */ + u32 _rsv17; /* 0x1f8 */ + u32 clk_src_osc; /* _CLK_SOURCE_OSC, 0x1fc */ + u32 _rsv18[32]; /* 0x200-27c */ + u32 clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + u32 clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + u32 clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + u32 rst_dev_x; /* _RST_DEVICES_X_0, 0x28c */ + u32 rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + u32 rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + u32 _rsv19[23]; /* 0x298-2f0 */ + u32 dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + u32 _rsv20[2]; /* 0x2f8-2fc */ + u32 rst_dev_l_set; /* _RST_DEV_L_SET 0x300 */ + u32 rst_dev_l_clr; /* _RST_DEV_L_CLR 0x304 */ + u32 rst_dev_h_set; /* _RST_DEV_H_SET 0x308 */ + u32 rst_dev_h_clr; /* _RST_DEV_H_CLR 0x30c */ + u32 rst_dev_u_set; /* _RST_DEV_U_SET 0x310 */ + u32 rst_dev_u_clr; /* _RST_DEV_U_CLR 0x314 */ + u32 _rsv21[2]; /* 0x318-31c */ + u32 clk_enb_l_set; /* _CLK_ENB_L_SET 0x320 */ + u32 clk_enb_l_clr; /* _CLK_ENB_L_CLR 0x324 */ + u32 clk_enb_h_set; /* _CLK_ENB_H_SET 0x328 */ + u32 clk_enb_h_clr; /* _CLK_ENB_H_CLR 0x32c */ + u32 clk_enb_u_set; /* _CLK_ENB_U_SET 0x330 */ + u32 clk_enb_u_clr; /* _CLK_ENB_U_CLR 0x334 */ + u32 _rsv22; /* 0x338 */ + u32 ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD, 0x33c */ + u32 rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET, 0x340 */ + u32 rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR, 0x344 */ + u32 clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET, 0x348 */ + u32 clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET, 0x34c */ + u32 _rsv23[2]; /* 0x350-354 */ + u32 rst_dev_v; /* _RST_DEVICES_V, 0x358 */ + u32 rst_dev_w; /* _RST_DEVICES_W, 0x35c */ + u32 clk_out_enb_v; /* _CLK_OUT_ENB_V, 0x360 */ + u32 clk_out_enb_w; /* _CLK_OUT_ENB_W, 0x364 */ + u32 cclkg_brst_pol; /* _CCLKG_BURST_POLICY, 0x368 */ + u32 super_cclkg_div; /* _SUPER_CCLKG_DIVIDER, 0x36c */ + u32 cclklp_brst_pol; /* _CCLKLP_BURST_POLICY, 0x370 */ + u32 super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER, 0x374 */ + u32 clk_cpug_cmplx; /* _CLK_CPUG_CMPLX, 0x378 */ + u32 clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX, 0x37c */ + u32 cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL, 0x380 */ + u32 cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1, 0x384 */ + u32 cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2, 0x388 */ + u32 _rsv24[9]; /* 0x38c-3ac */ + u32 clk_src_g3d2; /* _CLK_SOURCE_G3D2, 0x3b0 */ + u32 clk_src_mselect; /* _CLK_SOURCE_MSELECT, 0x3b4 */ + u32 clk_src_tsensor; /* _CLK_SOURCE_TSENSOR, 0x3b8 */ + u32 clk_src_i2s3; /* _CLK_SOURCE_I2S3, 0x3bc */ + u32 clk_src_i2s4; /* _CLK_SOURCE_I2S4, 0x3c0 */ + u32 clk_src_i2c4; /* _CLK_SOURCE_I2C4, 0x3c4 */ + u32 clk_src_sbc5; /* _CLK_SOURCE_SBC5, 0x3c8 */ + u32 clk_src_sbc6; /* _CLK_SOURCE_SBC6, 0x3cc */ + u32 clk_src_audio; /* _CLK_SOURCE_AUDIO, 0x3d0 */ + u32 _rsv25; /* 0x3d4 */ + u32 clk_src_dam0; /* _CLK_SOURCE_DAM0, 0x3d8 */ + u32 clk_src_dam1; /* _CLK_SOURCE_DAM1, 0x3dc */ + u32 clk_src_dam2; /* _CLK_SOURCE_DAM2, 0x3e0 */ + u32 clk_src_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X,0x3e4 */ + u32 clk_src_actmon; /* _CLK_SOURCE_ACTMON, 0x3e8 */ + u32 clk_src_extperiph1; /* _CLK_SOURCE_EXTPERIPH1, 0x3ec */ + u32 clk_src_extperiph2; /* _CLK_SOURCE_EXTPERIPH2, 0x3f0 */ + u32 clk_src_extperiph3; /* _CLK_SOURCE_EXTPERIPH3, 0x3f4 */ + u32 clk_src_nand_speed; /* _CLK_SOURCE_NAND_SPEED, 0x3f8 */ + u32 clk_src_i2c_slow; /* _CLK_SOURCE_I2C_SLOW, 0x3fc */ + u32 clk_src_sys; /* _CLK_SOURCE_SYS, 0x400 */ + u32 _rsv26[4]; /* 0x404-410 */ + u32 clk_src_sor; /* _CLK_SOURCE_SOR_0, 0x414 */ + u32 _rsv261[2]; /* 0x404-410 */ + u32 clk_src_sata_oob; /* _CLK_SOURCE_SATA_OOB, 0x420 */ + u32 clk_src_sata; /* _CLK_SOURCE_SATA, 0x424 */ + u32 clk_src_hda; /* _CLK_SOURCE_HDA, 0x428 */ + u32 _rsv27; /* 0x42c */ + u32 rst_dev_v_set; /* _RST_DEV_V_SET, 0x430 */ + u32 rst_dev_v_clr; /* _RST_DEV_V_CLR, 0x434 */ + u32 rst_dev_w_set; /* _RST_DEV_W_SET, 0x438 */ + u32 rst_dev_w_clr; /* _RST_DEV_W_CLR, 0x43c */ + u32 clk_enb_v_set; /* _CLK_ENB_V_SET, 0x440 */ + u32 clk_enb_v_clr; /* _CLK_ENB_V_CLR, 0x444 */ + u32 clk_enb_w_set; /* _CLK_ENB_W_SET, 0x448 */ + u32 clk_enb_w_clr; /* _CLK_ENB_W_CLR, 0x44c */ + u32 rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET, 0x450 */ + u32 rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR, 0x454 */ + u32 rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET, 0x458 */ + u32 rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR, 0x45C */ + u32 clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET, 0x460 */ + u32 clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR, 0x464 */ + u32 clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET, 0x468 */ + u32 clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR, 0x46c */ + u32 cpu_cmplx_status; /* _CPU_CMPLX_STATUS, 0x470 */ + u32 _rsv28; /* 0x474 */ + u32 intstatus; /* _INTSTATUS, 0x478 */ + u32 intmask; /* _INTMASK, 0x47c */ + u32 utmip_pll_cfg0; /* _UTMIP_PLL_CFG0, 0x480 */ + u32 utmip_pll_cfg1; /* _UTMIP_PLL_CFG1, 0x484 */ + u32 utmip_pll_cfg2; /* _UTMIP_PLL_CFG2, 0x488 */ + u32 plle_aux; /* _PLLE_AUX, 0x48c */ + u32 sata_pll_cfg0; /* _SATA_PLL_CFG0, 0x490 */ + u32 sata_pll_cfg1; /* _SATA_PLL_CFG1, 0x494 */ + u32 pcie_pll_cfg0; /* _PCIE_PLL_CFG0, 0x498 */ + u32 prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK, 0x49c */ + u32 audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0, 0x4a0 */ + u32 audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1, 0x4a4 */ + u32 audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2, 0x4a8 */ + u32 audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3, 0x4ac */ + u32 audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4, 0x4b0 */ + u32 audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF, 0x4b4 */ + u32 plld2_base; /* _PLLD2_BASE, 0x4b8 */ + u32 plld2_misc; /* _PLLD2_MISC, 0x4bc */ + u32 utmip_pll_cfg3; /* _UTMIP_PLL_CFG3, 0x4c0 */ + u32 pllrefe_base; /* _PLLREFE_BASE, 0x4c4 */ + u32 pllrefe_misc; /* _PLLREFE_MISC, 0x4c8 */ + u32 _rsv29[7]; /* 0x4cc-4e4 */ + u32 pllc2_base; /* _PLLC2_BASE, 0x4e8 */ + u32 pllc2_misc0; /* _PLLC2_MISC_0, 0x4ec */ + u32 pllc2_misc1; /* _PLLC2_MISC_1, 0x4f0 */ + u32 pllc2_misc2; /* _PLLC2_MISC_2, 0x4f4 */ + u32 pllc2_misc3; /* _PLLC2_MISC_3, 0x4f8 */ + u32 pllc3_base; /* _PLLC3_BASE, 0x4fc */ + u32 pllc3_misc0; /* _PLLC3_MISC_0, 0x500 */ + u32 pllc3_misc1; /* _PLLC3_MISC_1, 0x504 */ + u32 pllc3_misc2; /* _PLLC3_MISC_2, 0x508 */ + u32 pllc3_misc3; /* _PLLC3_MISC_3, 0x50c */ + u32 pllx_misc1; /* _PLLX_MISC_1, 0x510 */ + u32 pllx_misc2; /* _PLLX_MISC_2, 0x514 */ + u32 pllx_misc3; /* _PLLX_MISC_3, 0x518 */ + u32 xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0, 0x51c */ + u32 xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG1, 0x520 */ + u32 plle_aux1; /* _PLLE_AUX1, 0x524 */ + u32 pllp_reshift; /* _PLLP_RESHIFT, 0x528 */ + u32 utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0, 0x52c */ + u32 pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0, 0x530 */ + u32 xusb_pll_cfg0; /* _XUSB_PLL_CFG0, 0x534 */ + u32 _rsv30; /* 0x538 */ + u32 clk_cpu_misc; /* _CLK_CPU_MISC, 0x53c */ + u32 clk_cpug_misc; /* _CLK_CPUG_MISC, 0x540 */ + u32 clk_cpulp_misc; /* _CLK_CPULP_MISC, 0x544 */ + u32 pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG, 0x548 */ + u32 pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG, 0x54c */ + u32 pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS, 0x550 */ + u32 _rsv31; /* 0x554 */ + u32 super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER, 0x558 */ + u32 spare_reg0; /* _SPARE_REG0, 0x55c */ + u32 _rsv32[4]; /* 0x560-0x56c */ + u32 plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ + u32 _rsv32_1[7]; /* 0x574-58c */ + u32 plldp_base; /* _PLLDP_BASE, 0x590 */ + u32 plldp_misc; /* _PLLDP_MISC, 0x594 */ + u32 plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + u32 _rsrv32_2[25]; + u32 clk_src_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST 0x600 */ + u32 clk_src_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON 0x604 */ + u32 clk_src_xusb_fs; /* _CLK_SOURCE_XUSB_FS 0x608 */ + u32 clk_src_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV 0x60c */ + u32 clk_src_xusb_ss; /* _CLK_SOURCE_XUSB_SS 0x610 */ + u32 clk_src_cilab; /* _CLK_SOURCE_CILAB 0x614 */ + u32 clk_src_cilcd; /* _CLK_SOURCE_CILCD 0x618 */ + u32 clk_src_cile; /* _CLK_SOURCE_CILE 0x61c */ + u32 clk_src_dsia_lp; /* _CLK_SOURCE_DSIA_LP 0x620 */ + u32 clk_src_dsib_lp; /* _CLK_SOURCE_DSIB_LP 0x624 */ + u32 clk_src_entropy; /* _CLK_SOURCE_ENTROPY 0x628 */ + u32 clk_src_dvfs_ref; /* _CLK_SOURCE_DVFS_REF 0x62c */ + u32 clk_src_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC 0x630 */ + u32 clk_src_traceclkin; /* _CLK_SOURCE_TRACECLKIN 0x634 */ + u32 clk_src_adx0; /* _CLK_SOURCE_ADX0 0x638 */ + u32 clk_src_amx0; /* _CLK_SOURCE_AMX0 0x63c */ + u32 clk_src_emc_latency; /* _CLK_SOURCE_EMC_LATENCY 0x640 */ + u32 clk_src_soc_therm; /* _CLK_SOURCE_SOC_THERM 0x644 */ + u32 _rsv33[5]; /* 0x648-658 */ + u32 clk_src_i2c6; /* _CLK_SOURCE_I2C6, 0x65c */ +}; +check_member(clk_rst_ctlr, clk_src_i2c6, 0x65C); + +#define CLK_RST_REG(field_) \ + (&(((struct clk_rst_ctlr *)TEGRA_CLK_RST_BASE)->field_)) + +/* L, H, U, V, W, X */ +#define DEV_CONFIG_BLOCKS 6 + +#define TEGRA_DEV_L 0 +#define TEGRA_DEV_H 1 +#define TEGRA_DEV_U 2 +#define TEGRA_DEV_V 0 +#define TEGRA_DEV_W 1 + +#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) + +/* Bits to enable/reset modules */ +#define CLK_ENB_CPU (1 << 0) +#define SWR_TRIG_SYS_RST (1 << 2) +#define SWR_CSITE_RST (1 << 9) +#define CLK_ENB_CSITE (1 << 9) + +/* CRC_SUPER_CCLK_DIVIDER_0 0x24 */ +#define SUPER_CDIV_ENB_ENABLE (1 << 31) + +/* CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 */ +#define EN_PPSB_STOPCLK (1 << 0) + +/* CLK_RST_CONTROLLER_CLK_CPU_CMPLX_0 (0x4C) */ +#define CPU3_CLK_STP_SHIFT 11 +#define CPU2_CLK_STP_SHIFT 10 +#define CPU1_CLK_STP_SHIFT 9 +#define CPU0_CLK_STP_SHIFT 8 +#define CPU0_CLK_STP_MASK (1U << CPU0_CLK_STP_SHIFT) + +/* CRC_OSC_CTRL_0 0x50 */ +#define OSC_FREQ_SHIFT 28 +#define OSC_FREQ_MASK (0xf << OSC_FREQ_SHIFT) +#define OSC_PREDIV_SHIFT 26 +#define OSC_PREDIV_MASK (0x3 << OSC_PREDIV_SHIFT) +#define OSC_XOFS_SHIFT 4 +#define OSC_XOFS_MASK (0x3F << OSC_XOFS_SHIFT) +#define OSC_DRIVE_STRENGTH 7 +#define OSC_XOBP (1 << 1) +#define OSC_XOE (1 << 0) + +enum { + OSC_FREQ_12 = 8, /* 12.0MHz */ + OSC_FREQ_13 = 0, /* 13.0MHz */ + OSC_FREQ_16P8 = 1, /* 16.8MHz */ + OSC_FREQ_19P2 = 4, /* 19.2MHz */ + OSC_FREQ_26 = 12, /* 26.0MHz */ + OSC_FREQ_38P4 = 5, /* 38.4MHz */ + OSC_FREQ_48 = 9, /* 48.0MHz */ +}; + +/* CLK_RST_CONTROLLER_PLL*_BASE_0 */ +#define PLL_BASE_BYPASS (1U << 31) +#define PLL_BASE_ENABLE (1U << 30) +#define PLL_BASE_REF_DIS (1U << 29) +#define PLL_BASE_OVRRIDE (1U << 28) +#define PLL_BASE_LOCK (1U << 27) + +#define PLL_BASE_DIVP_SHIFT 20 +#define PLL_BASE_DIVP_MASK (7U << PLL_BASE_DIVP_SHIFT) + +#define PLL_BASE_DIVN_SHIFT 8 +#define PLL_BASE_DIVN_MASK (0x3ffU << PLL_BASE_DIVN_SHIFT) + +#define PLL_BASE_DIVM_SHIFT 0 +#define PLL_BASE_DIVM_MASK (0x1f << PLL_BASE_DIVM_SHIFT) + +/* SPECIAL CASE: PLLM, PLLC and PLLX use different-sized fields here */ +#define PLLCX_BASE_DIVP_MASK (0xfU << PLL_BASE_DIVP_SHIFT) +#define PLLM_BASE_DIVP_MASK (0x1U << PLL_BASE_DIVP_SHIFT) +#define PLLCMX_BASE_DIVN_MASK (0xffU << PLL_BASE_DIVN_SHIFT) +#define PLLCMX_BASE_DIVM_MASK (0xffU << PLL_BASE_DIVM_SHIFT) + +/* PLLM specific registers */ +#define PLLM_MISC1_SETUP_SHIFT 0 +#define PLLM_MISC1_PD_LSHIFT_PH45_SHIFT 28 +#define PLLM_MISC1_PD_LSHIFT_PH90_SHIFT 29 +#define PLLM_MISC1_PD_LSHIFT_PH135_SHIFT 30 +#define PLLM_MISC2_KCP_SHIFT 1 +#define PLLM_MISC2_KVCO_SHIFT 0 +#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) + +/* Generic, indiscriminate divisor mask. May catch some innocent bystander bits + * on the side that we don't particularly care about. */ +#define PLL_BASE_DIV_MASK (0xffffff) + +/* CLK_RST_CONTROLLER_PLL*_OUT*_0 */ +#define PLL_OUT_RSTN (1 << 0) +#define PLL_OUT_CLKEN (1 << 1) +#define PLL_OUT_OVR (1 << 2) + +#define PLL_OUT_RATIO_SHIFT 8 +#define PLL_OUT_RATIO_MASK (0xffU << PLL_OUT_RATIO_SHIFT) + +#define PLL_OUT1_SHIFT 0 +#define PLL_OUT2_SHIFT 16 +#define PLL_OUT3_SHIFT 0 +#define PLL_OUT4_SHIFT 16 + +/* CLK_RST_CONTROLLER_PLL*_MISC_0 */ +#define PLL_MISC_DCCON (1 << 20) + +#define PLL_MISC_CPCON_SHIFT 8 +#define PLL_MISC_CPCON_MASK (0xfU << PLL_MISC_CPCON_SHIFT) + +#define PLL_MISC_LFCON_SHIFT 4 +#define PLL_MISC_LFCON_MASK (0xfU << PLL_MISC_LFCON_SHIFT) + +/* This bit is different all over the place. Oh joy... */ +#define PLLDPD2_MISC_LOCK_ENABLE (1 << 30) +#define PLLC_MISC_LOCK_ENABLE (1 << 24) +#define PLLUD_MISC_LOCK_ENABLE (1 << 22) +#define PLLD_MISC_CLK_ENABLE (1 << 30) +#define PLLPAXS_MISC_LOCK_ENABLE (1 << 18) +#define PLLE_MISC_LOCK_ENABLE (1 << 9) + +#define PLLU_MISC_VCO_FREQ (1 << 20) + +/* PLLX_BASE_0 0xe0 */ +#define PLLX_BASE_PLLX_ENABLE (1 << 30) + +/* CLK_RST_CONTROLLER_PLLX_MISC_3 */ +#define PLLX_IDDQ_SHIFT 3 +#define PLLX_IDDQ_MASK (1U << PLLX_IDDQ_SHIFT) + +#define CLK_DIVISOR_MASK (0xffff) + +#define CLK_SOURCE_SHIFT 29 +#define CLK_SOURCE_MASK (0x7 << CLK_SOURCE_SHIFT) + +#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ (1 << 16) + +#define CLK_UART_DIV_OVERRIDE (1 << 24) + +/* CLK_RST_CONTROLLER_SCLK_BURST_POLICY */ +#define SCLK_SYS_STATE_SHIFT 28U +#define SCLK_SYS_STATE_MASK (15U << SCLK_SYS_STATE_SHIFT) +enum { + SCLK_SYS_STATE_STDBY, + SCLK_SYS_STATE_IDLE, + SCLK_SYS_STATE_RUN, + SCLK_SYS_STATE_IRQ = 4U, + SCLK_SYS_STATE_FIQ = 8U, +}; +#define SCLK_COP_FIQ_MASK (1 << 27) +#define SCLK_CPU_FIQ_MASK (1 << 26) +#define SCLK_COP_IRQ_MASK (1 << 25) +#define SCLK_CPU_IRQ_MASK (1 << 24) + +#define SCLK_FIQ_SHIFT 12 +#define SCLK_FIQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IRQ_SHIFT 8 +#define SCLK_IRQ_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_RUN_SHIFT 4 +#define SCLK_RUN_MASK (7 << SCLK_FIQ_SHIFT) +#define SCLK_IDLE_SHIFT 0 +#define SCLK_IDLE_MASK (7 << SCLK_FIQ_SHIFT) +enum { + SCLK_SOURCE_CLKM, + SCLK_SOURCE_PLLC_OUT1, + SCLK_SOURCE_PLLP_OUT4, + SCLK_SOURCE_PLLP_OUT3, + SCLK_SOURCE_PLLP_OUT2, + SCLK_SOURCE_PLLC_OUT0, + SCLK_SOURCE_CLKS, + SCLK_SOURCE_PLLM_OUT1, +}; + +/* CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2c */ +#define SCLK_DIV_ENB (1 << 31) +#define SCLK_DIVIDEND_SHIFT 8 +#define SCLK_DIVIDEND_MASK (0xff << SCLK_DIVIDEND_SHIFT) +#define SCLK_DIVISOR_SHIFT 0 +#define SCLK_DIVISOR_MASK (0xff << SCLK_DIVISOR_SHIFT) + +/* CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 */ +#define HCLK_DISABLE (1 << 7) +#define HCLK_DIVISOR_SHIFT 4 +#define HCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) +#define PCLK_DISABLE (1 << 3) +#define PCLK_DIVISOR_SHIFT 0 +#define PCLK_DIVISOR_MASK (3 << AHB_RATE_SHIFT) + +/* CRC_CLK_SOURCE_MSELECT_0 0x3b4 */ +#define MSELECT_CLK_SRC_PLLP_OUT0 (0 << 29) + +/* CRC_CLK_ENB_V_SET_0 0x440 */ +#define SET_CLK_ENB_CPUG_ENABLE (1 << 0) +#define SET_CLK_ENB_CPULP_ENABLE (1 << 1) +#define SET_CLK_ENB_MSELECT_ENABLE (1 << 3) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG1_0 0x484 */ +#define PLLU_POWERDOWN (1 << 16) +#define PLL_ENABLE_POWERDOWN (1 << 14) +#define PLL_ACTIVE_POWERDOWN (1 << 12) + +/* CLK_RST_CONTROLLER_UTMIP_PLL_CFG2_0 0x488 */ +#define UTMIP_FORCE_PD_SAMP_C_POWERDOWN (1 << 4) +#define UTMIP_FORCE_PD_SAMP_B_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PD_SAMP_A_POWERDOWN (1 << 0) + +// CCLK_BRST_POL +enum { + CRC_CCLK_BRST_POL_PLLX_OUT0 = 0x8, + CRC_CCLK_BRST_POL_CPU_STATE_RUN = 0x2 +}; + +// SUPER_CCLK_DIVIDER +enum { + CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31 +}; + +// CLK_CPU_CMPLX_CLR +enum { + CRC_CLK_CLR_CPU0_STP = 0x1 << 8, + CRC_CLK_CLR_CPU1_STP = 0x1 << 9, + CRC_CLK_CLR_CPU2_STP = 0x1 << 10, + CRC_CLK_CLR_CPU3_STP = 0x1 << 11 +}; + +// RST_CPUG_CMPLX_CLR +enum { + CRC_RST_CPUG_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPUG_CLR_CPU1 = 0x1 << 1, + CRC_RST_CPUG_CLR_CPU2 = 0x1 << 2, + CRC_RST_CPUG_CLR_CPU3 = 0x1 << 3, + CRC_RST_CPUG_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPUG_CLR_DBG1 = 0x1 << 13, + CRC_RST_CPUG_CLR_DBG2 = 0x1 << 14, + CRC_RST_CPUG_CLR_DBG3 = 0x1 << 15, + CRC_RST_CPUG_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPUG_CLR_CORE1 = 0x1 << 17, + CRC_RST_CPUG_CLR_CORE2 = 0x1 << 18, + CRC_RST_CPUG_CLR_CORE3 = 0x1 << 19, + CRC_RST_CPUG_CLR_CX0 = 0x1 << 20, + CRC_RST_CPUG_CLR_CX1 = 0x1 << 21, + CRC_RST_CPUG_CLR_CX2 = 0x1 << 22, + CRC_RST_CPUG_CLR_CX3 = 0x1 << 23, + CRC_RST_CPUG_CLR_L2 = 0x1 << 24, + CRC_RST_CPUG_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPUG_CLR_PDBG = 0x1 << 30, +}; + +// RST_CPULP_CMPLX_CLR +enum { + CRC_RST_CPULP_CLR_CPU0 = 0x1 << 0, + CRC_RST_CPULP_CLR_DBG0 = 0x1 << 12, + CRC_RST_CPULP_CLR_CORE0 = 0x1 << 16, + CRC_RST_CPULP_CLR_CX0 = 0x1 << 20, + CRC_RST_CPULP_CLR_L2 = 0x1 << 24, + CRC_RST_CPULP_CLR_NONCPU = 0x1 << 29, + CRC_RST_CPULP_CLR_PDBG = 0x1 << 30, +}; + +#endif /* _TEGRA132_CLK_RST_H_ */ diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h new file mode 100644 index 0000000000..1928788d23 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/clock.h @@ -0,0 +1,413 @@ +/* + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA132_CLOCK_H__ +#define __SOC_NVIDIA_TEGRA132_CLOCK_H__ + +#include +#include +#include +#include +#include +#include + +enum { + CLK_L_CPU = 0x1 << 0, + CLK_L_COP = 0x1 << 1, + CLK_L_TRIG_SYS = 0x1 << 2, + CLK_L_RTC = 0x1 << 4, + CLK_L_TMR = 0x1 << 5, + CLK_L_UARTA = 0x1 << 6, + CLK_L_UARTB = 0x1 << 7, + CLK_L_GPIO = 0x1 << 8, + CLK_L_SDMMC2 = 0x1 << 9, + CLK_L_SPDIF = 0x1 << 10, + CLK_L_I2S1 = 0x1 << 11, + CLK_L_I2C1 = 0x1 << 12, + CLK_L_NDFLASH = 0x1 << 13, + CLK_L_SDMMC1 = 0x1 << 14, + CLK_L_SDMMC4 = 0x1 << 15, + CLK_L_PWM = 0x1 << 17, + CLK_L_I2S2 = 0x1 << 18, + CLK_L_EPP = 0x1 << 19, + CLK_L_VI = 0x1 << 20, + CLK_L_2D = 0x1 << 21, + CLK_L_USBD = 0x1 << 22, + CLK_L_ISP = 0x1 << 23, + CLK_L_3D = 0x1 << 24, + CLK_L_DISP2 = 0x1 << 26, + CLK_L_DISP1 = 0x1 << 27, + CLK_L_HOST1X = 0x1 << 28, + CLK_L_VCP = 0x1 << 29, + CLK_L_I2S0 = 0x1 << 30, + CLK_L_CACHE2 = 0x1 << 31, + + CLK_H_MEM = 0x1 << 0, + CLK_H_AHBDMA = 0x1 << 1, + CLK_H_APBDMA = 0x1 << 2, + CLK_H_KBC = 0x1 << 4, + CLK_H_STAT_MON = 0x1 << 5, + CLK_H_PMC = 0x1 << 6, + CLK_H_FUSE = 0x1 << 7, + CLK_H_KFUSE = 0x1 << 8, + CLK_H_SBC1 = 0x1 << 9, + CLK_H_SNOR = 0x1 << 10, + CLK_H_JTAG2TBC = 0x1 << 11, + CLK_H_SBC2 = 0x1 << 12, + CLK_H_SBC3 = 0x1 << 14, + CLK_H_I2C5 = 0x1 << 15, + CLK_H_DSI = 0x1 << 16, + CLK_H_HSI = 0x1 << 18, + CLK_H_HDMI = 0x1 << 19, + CLK_H_CSI = 0x1 << 20, + CLK_H_I2C2 = 0x1 << 22, + CLK_H_UARTC = 0x1 << 23, + CLK_H_MIPI_CAL = 0x1 << 24, + CLK_H_EMC = 0x1 << 25, + CLK_H_USB2 = 0x1 << 26, + CLK_H_USB3 = 0x1 << 27, + CLK_H_MPE = 0x1 << 28, + CLK_H_VDE = 0x1 << 29, + CLK_H_BSEA = 0x1 << 30, + CLK_H_BSEV = 0x1 << 31, + + CLK_U_UARTD = 0x1 << 1, + CLK_U_UARTE = 0x1 << 2, + CLK_U_I2C3 = 0x1 << 3, + CLK_U_SBC4 = 0x1 << 4, + CLK_U_SDMMC3 = 0x1 << 5, + CLK_U_PCIE = 0x1 << 6, + CLK_U_OWR = 0x1 << 7, + CLK_U_AFI = 0x1 << 8, + CLK_U_CSITE = 0x1 << 9, + CLK_U_PCIEXCLK = 0x1 << 10, + CLK_U_AVPUCQ = 0x1 << 11, + CLK_U_TRACECLKIN = 0x1 << 13, + CLK_U_SOC_THERM = 0x1 << 14, + CLK_U_DTV = 0x1 << 15, + CLK_U_NAND_SPEED = 0x1 << 16, + CLK_U_I2C_SLOW = 0x1 << 17, + CLK_U_DSIB = 0x1 << 18, + CLK_U_TSEC = 0x1 << 19, + CLK_U_IRAMA = 0x1 << 20, + CLK_U_IRAMB = 0x1 << 21, + CLK_U_IRAMC = 0x1 << 22, + + // Clock reset. + CLK_U_EMUCIF = 0x1 << 23, + // Clock enable. + CLK_U_IRAMD = 0x1 << 23, + + CLK_U_CRAM2 = 0x2 << 24, + CLK_U_XUSB_HOST = 0x1 << 25, + CLK_U_MSENC = 0x1 << 27, + CLK_U_SUS_OUT = 0x1 << 28, + CLK_U_DEV2_OUT = 0x1 << 29, + CLK_U_DEV1_OUT = 0x1 << 30, + CLK_U_XUSB_DEV = 0x1 << 31, + + CLK_V_CPUG = 0x1 << 0, + CLK_V_CPULP = 0x1 << 1, + CLK_V_3D2 = 0x1 << 2, + CLK_V_MSELECT = 0x1 << 3, + CLK_V_I2S3 = 0x1 << 5, + CLK_V_I2S4 = 0x1 << 6, + CLK_V_I2C4 = 0x1 << 7, + CLK_V_SBC5 = 0x1 << 8, + CLK_V_SBC6 = 0x1 << 9, + CLK_V_AUDIO = 0x1 << 10, + CLK_V_APBIF = 0x1 << 11, + CLK_V_DAM0 = 0x1 << 12, + CLK_V_DAM1 = 0x1 << 13, + CLK_V_DAM2 = 0x1 << 14, + CLK_V_HDA2CODEC_2X = 0x1 << 15, + CLK_V_ATOMICS = 0x1 << 16, + CLK_V_ACTMON = 0x1 << 23, + CLK_V_EXTPERIPH1 = 0x1 << 24, + CLK_V_SATA = 0x1 << 28, + CLK_V_HDA = 0x1 << 29, + + CLK_W_HDA2HDMICODEC = 0x1 << 0, + CLK_W_SATACOLD = 0x1 << 1, + CLK_W_CEC = 0x1 << 8, + CLK_W_XUSB_PADCTL = 0x1 << 14, + CLK_W_ENTROPY = 0x1 << 21, + CLK_W_DP2 = 0x1 << 24, + CLK_W_AMX0 = 0x1 << 25, + CLK_W_ADX0 = 0x1 << 26, + CLK_W_DVFS = 0x1 << 27, + CLK_W_XUSB_SS = 0x1 << 28, + CLK_W_MC1 = 0x1 << 30, + CLK_W_EMC1 = 0x1 << 31, + + CLK_X_AFC0 = 0x1 << 31, + CLK_X_AFC1 = 0x1 << 30, + CLK_X_AFC2 = 0x1 << 29, + CLK_X_AFC3 = 0x1 << 28, + CLK_X_AFC4 = 0x1 << 27, + CLK_X_AFC5 = 0x1 << 26, + CLK_X_AMX1 = 0x1 << 25, + CLK_X_GPU = 0x1 << 24, + CLK_X_SOR0 = 0x1 << 22, + CLK_X_DPAUX = 0x1 << 21, + CLK_X_ADX1 = 0x1 << 20, + CLK_X_VIC = 0x1 << 18, + CLK_X_CLK72MHZ = 0x1 << 17, + CLK_X_HDMI_AUDIO = 0x1 << 16, + CLK_X_EMC_DLL = 0x1 << 14, + CLK_X_VIM2_CLK = 0x1 << 11, + CLK_X_I2C6 = 0x1 << 6, + CLK_X_CAM_MCLK2 = 0x1 << 5, + CLK_X_CAM_MCLK = 0x1 << 4, + CLK_X_SPARE = 0x1 << 0, +}; + +enum { + PLLP = 0, + PLLC2 = 1, + PLLC = 2, + PLLC3 = 3, + PLLM = 4, + CLK_M = 5, + CLK_S = 6, + PLLE = 7, + PLLA = 8, + PLLD = 9, + PLLD2 = 10, + UNUSED = 100, + UNUSED1 = 101, + UNUSED2 = 102, + UNUSED3 = 103, +}; + +#define CLK_SRC_DEV_ID(dev, src) CLK_SRC_##dev##_##src +#define CLK_SRC_FREQ_ID(dev, src) CLK_SRC_FREQ_##dev##_##src + +#define CLK_SRC_DEVICE(dev, a, b, c, d, e, f, g) \ + CLK_SRC_DEV_ID(dev, a) = 0, \ + CLK_SRC_DEV_ID(dev, b) = 1, \ + CLK_SRC_DEV_ID(dev, c) = 2, \ + CLK_SRC_DEV_ID(dev, d) = 3, \ + CLK_SRC_DEV_ID(dev, e) = 4, \ + CLK_SRC_DEV_ID(dev, f) = 5, \ + CLK_SRC_DEV_ID(dev, g) = 6, \ + CLK_SRC_FREQ_ID(dev, a) = a, \ + CLK_SRC_FREQ_ID(dev, b) = b, \ + CLK_SRC_FREQ_ID(dev, c) = c, \ + CLK_SRC_FREQ_ID(dev, d) = d, \ + CLK_SRC_FREQ_ID(dev, e) = e, \ + CLK_SRC_FREQ_ID(dev, f) = f, \ + CLK_SRC_FREQ_ID(dev, g) = g + +enum { + CLK_SRC_DEVICE(disp1, PLLP, PLLM, PLLD, PLLA, PLLC, PLLD2, CLK_M), + CLK_SRC_DEVICE(host1x, PLLM, PLLC2, PLLC, PLLC3, PLLP, UNUSED, PLLA), + CLK_SRC_DEVICE(I2C1, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C2, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C3, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C5, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C6, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2S1, PLLA, UNUSED, CLK_S, UNUSED1, PLLP, UNUSED2, CLK_M), + CLK_SRC_DEVICE(mselect, PLLP, PLLC2, PLLC, PLLC3, PLLM, CLK_S, CLK_M), + CLK_SRC_DEVICE(SBC1, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(SBC4, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(SDMMC3, PLLP, PLLC2, PLLC, PLLC3, PLLM, PLLE, CLK_M), + CLK_SRC_DEVICE(SDMMC4, PLLP, PLLC2, PLLC, PLLC3, PLLM, PLLE, CLK_M), + CLK_SRC_DEVICE(UARTA, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(i2s1, PLLA, UNUSED, CLK_S, UNUSED1, PLLP, UNUSED2, CLK_M), + CLK_SRC_DEVICE(extperiph1, PLLA, CLK_S, PLLP, CLK_M, PLLE, UNUSED, UNUSED1), +}; + +/* PLL stabilization delay in usec */ +#define CLOCK_PLL_STABLE_DELAY_US 300 + +#define IO_STABILIZATION_DELAY (2) +#define LOGIC_STABILIZATION_DELAY (2) + +/* Calculate clock fractional divider value from ref and target frequencies. + * This is for a U7.1 format. This is not well written up in the book and + * there have been some questions about this macro, so here we go. + * U7.1 format is defined as (ddddddd+1) + (h*.5) + * The lowest order bit is actually a fractional bit. + * Hence, the divider can be thought of as 9 bits. + * So: + * divider = ((ref/freq) << 1 - 1) (upper 7 bits) | + * (ref/freq & 1) (low order half-bit) + * however we can't do fractional arithmetic ... these are integers! + * So we normalize by shifting the result left 1 bit, and extracting + * ddddddd and h directly to the returned u8. + * divider = 2*(ref/freq); + * We want to + * preserve 7 bits of divisor and one bit of fraction, in 8 bits, as well as + * subtract one from ddddddd. Since we computed ref*2, the dddddd is now nicely + * situated in the upper 7 bits, and the h is sitting there in the low order + * bit. To subtract 1 from ddddddd, just subtract 2 from the 8-bit number + * and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you + * will assign this to a u8, it gets nicely truncated for you. + */ +#define CLK_DIVIDER(REF, FREQ) (div_round_up(((REF) * 2), (FREQ)) - 2) + +/* Calculate clock frequency value from reference and clock divider value + * The discussion in the book is pretty lacking. + * The idea is that we need to divide a ref clock by a divisor + * in U7.1 format, where 7 upper bits are the integer + * and lowest order bit is a fraction. + * from the book, U7.1 is (ddddddd+1) + (h*.5) + * To normalize to an actual number, we might do this: + * ((d>>7+1)&0x7f) + (d&1 >> 1) + * but as you might guess, the low order bit would be lost. + * Since we can't express the fractional bit, we need to multiply it all by 2. + * ((d + 2)&0xfe) + (d & 1) + * Since we're just adding +2, the lowest order bit is preserved. Hence + * (d+2) is the same as ((d + 2)&0xfe) + (d & 1) + * + * Since you multiply denominator * 2 (by NOT shifting it), + * you multiply numerator * 2 to cancel it out. + */ +#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / ((REG) + 2)) + +static inline void _clock_set_div(u32 *reg, const char *name, u32 div, + u32 div_mask, u32 src) +{ + // The I2C and UART divisors are 16 bit while all the others are 8 bit. + // The I2C clocks are handled by the specialized macro below, but the + // UART clocks aren't. Don't use this function on UART clocks. + if (div & ~div_mask) { + printk(BIOS_ERR, "%s clock divisor overflow!", name); + hlt(); + } + clrsetbits_le32(reg, CLK_SOURCE_MASK | CLK_DIVISOR_MASK, + src << CLK_SOURCE_SHIFT | div); +} + +#define get_i2c_clk_div(src,freq) (div_round_up(src, (freq) * (0x19 + 1) * 8) - 1) +#define get_clk_div(src,freq) CLK_DIVIDER(src,freq) +#define CLK_DIV_MASK 0xff +#define CLK_DIV_MASK_I2C 0xffff + +#define clock_configure_source(device, src, freq) \ + _clock_set_div(CLK_RST_REG(clk_src_##device), #device, \ + get_clk_div(TEGRA_##src##_KHZ, freq), CLK_DIV_MASK, \ + CLK_SRC_DEV_ID(device, src)) + +/* soc-specific */ +#define TEGRA_CLK_M_KHZ clock_get_osc_khz() +#define TEGRA_PLLX_KHZ CONFIG_PLLX_KHZ +#define TEGRA_PLLP_KHZ (408000) +#define TEGRA_PLLC_KHZ (600000) +#define TEGRA_PLLD_KHZ (925000) +#define TEGRA_PLLU_KHZ (960000) + +#define clock_enable(l, h, u, v, w, x) \ + do { \ + u32 bits[DEV_CONFIG_BLOCKS] = {l, h, u, v, w, x}; \ + clock_enable_regs(bits); \ + } while (0) + +#define clock_disable(l, h, u, v, w, x) \ + do { \ + u32 bits[DEV_CONFIG_BLOCKS] = {l, h, u, v, w, x}; \ + clock_disable_regs(bits); \ + } while (0) + +#define clock_set_reset(l, h, u, v, w, x) \ + do { \ + u32 bits[DEV_CONFIG_BLOCKS] = {l, h, u, v, w, x}; \ + clock_set_reset_regs(bits); \ + } while (0) + +#define clock_clr_reset(l, h, u, v, w, x) \ + do { \ + u32 bits[DEV_CONFIG_BLOCKS] = {l, h, u, v, w, x}; \ + clock_clr_reset_regs(bits); \ + } while (0) + +#define clock_enable_l(l) clock_enable(l, 0, 0, 0, 0, 0) +#define clock_enable_h(h) clock_enable(0, h, 0, 0, 0, 0) +#define clock_enable_u(u) clock_enable(0, 0, u, 0, 0, 0) +#define clock_enable_v(v) clock_enable(0, 0, 0, v, 0, 0) +#define clock_enable_w(w) clock_enable(0, 0, 0, 0, w, 0) +#define clock_enable_x(x) clock_enable(0, 0, 0, 0, 0, x) + +#define clock_disable_l(l) clock_disable(l, 0, 0, 0, 0, 0) +#define clock_disable_h(h) clock_disable(0, h, 0, 0, 0, 0) +#define clock_disable_u(u) clock_disable(0, 0, u, 0, 0, 0) +#define clock_disable_v(v) clock_disable(0, 0, 0, v, 0, 0) +#define clock_disable_w(w) clock_disable(0, 0, 0, 0, w, 0) +#define clock_disable_x(x) clock_disable(0, 0, 0, 0, 0, x) + +#define clock_set_reset_l(l) clock_set_reset(l, 0, 0, 0, 0, 0) +#define clock_set_reset_h(h) clock_set_reset(0, h, 0, 0, 0, 0) +#define clock_set_reset_u(u) clock_set_reset(0, 0, u, 0, 0, 0) +#define clock_set_reset_v(v) clock_set_reset(0, 0, 0, v, 0, 0) +#define clock_set_reset_w(w) clock_set_reset(0, 0, 0, 0, w, 0) +#define clock_set_reset_x(x) clock_set_reset(0, 0, 0, 0, 0, x) + +#define clock_clr_reset_l(l) clock_clr_reset(l, 0, 0, 0, 0, 0) +#define clock_clr_reset_h(h) clock_clr_reset(0, h, 0, 0, 0, 0) +#define clock_clr_reset_u(u) clock_clr_reset(0, 0, u, 0, 0, 0) +#define clock_clr_reset_v(v) clock_clr_reset(0, 0, 0, v, 0, 0) +#define clock_clr_reset_w(w) clock_clr_reset(0, 0, 0, 0, w, 0) +#define clock_clr_reset_x(x) clock_clr_reset(0, 0, 0, 0, 0, x) + +#define clock_enable_clear_reset_l(l) \ + clock_enable_clear_reset(l, 0, 0, 0, 0, 0) +#define clock_enable_clear_reset_h(h) \ + clock_enable_clear_reset(0, h, 0, 0, 0, 0) +#define clock_enable_clear_reset_u(u) \ + clock_enable_clear_reset(0, 0, u, 0, 0, 0) +#define clock_enable_clear_reset_v(v) \ + clock_enable_clear_reset(0, 0, 0, v, 0, 0) +#define clock_enable_clear_reset_w(w) \ + clock_enable_clear_reset(0, 0, 0, 0, w, 0) +#define clock_enable_clear_reset_x(x) \ + clock_enable_clear_reset(0, 0, 0, 0, 0, x) + +int clock_get_osc_khz(void); +int clock_get_pll_input_khz(void); +/* + * Configure PLLD to requested frequency. Returned value is closest match + * within the PLLD's constraints or 0 if an error. + */ +u32 clock_configure_plld(u32 frequency); +void clock_early_uart(void); +void clock_external_output(int clk_id); +void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, + u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, + u32 same_freq); +void clock_cpu0_config(void); +void clock_halt_avp(void); +void clock_enable_regs(u32 bits[DEV_CONFIG_BLOCKS]); +void clock_disable_regs(u32 bits[DEV_CONFIG_BLOCKS]); +void clock_set_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]); +void clock_clr_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]); +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x); +void clock_grp_enable_clear_reset(u32 val, u32* clk_enb_set_reg, u32* rst_dev_clr_reg); +void clock_reset_l(u32 l); +void clock_reset_h(u32 h); +void clock_reset_u(u32 u); +void clock_reset_v(u32 v); +void clock_reset_w(u32 w); +void clock_reset_x(u32 x); +void clock_init(void); +void clock_init_arm_generic_timer(void); +void sor_clock_stop(void); +void sor_clock_start(void); +void clock_enable_audio(void); + +#endif /* __SOC_NVIDIA_TEGRA132_CLOCK_H__ */ + diff --git a/src/soc/nvidia/tegra132/include/soc/clst_clk.h b/src/soc/nvidia/tegra132/include/soc/clst_clk.h new file mode 100644 index 0000000000..151ead6341 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/clst_clk.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA132_CLST_CLK_H_ +#define _TEGRA132_CLST_CLK_H_ + +/* Cluster Clock (CLUSTER_CLOCKS_PUBLIC_) regs */ +struct __attribute__ ((__packed__)) clst_clk_ctlr { + u32 pllx_base; /* _PLLX_BASE, 0x000 */ + u32 pllx_misc; /* _PLLX_MISC, 0x004 */ + u32 pllx_misc1; /* _PLLX_MISC_1, 0x008 */ + u32 pllx_misc2; /* _PLLX_MISC_2, 0x00c */ + u32 pllx_misc3; /* _PLLX_MISC_3, 0x010 */ + u32 pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG, 0x014 */ + u32 pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG, 0x018 */ + u32 pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS, 0x01c */ + u32 cclk_brst_pol; /* _CCLK_BURST_POLICY, 0x020 */ + u32 super_cclk_div; /* _SUPER_CCLK_DIVIDER, 0x024 */ + u32 _rsv1[10]; /* 0x028-04c */ + u32 shaper; /* _SHAPER, 0x050 */ + u32 shaper1; /* _SHAPER_1, 0x054 */ + u32 _rsv2[80]; /* 0x058-194 */ + u32 misc_ctrl; /* _MISC_CTRL, 0x198 */ +}; +check_member(clst_clk_ctlr, misc_ctrl, 0x198); + +/* CC_CCLK_BRST_POL */ +enum { + CC_CCLK_BRST_POL_PLLX_OUT0_LJ = 0x8, +}; + +/* CC_SUPER_CCLK_DIVIDER */ +enum { + CC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB = 1 << 31 +}; + +/* PLLX_MISC3 */ +enum { + PLLX_IDDQ = 1 << 3, +}; + +/* MISC_CTRL */ +enum { + CLK_SWITCH_MATCH = 1 << 5, +}; + +#define CLK_SWITCH_TIMEOUT_US 1000 +#endif /* _TEGRA132_CLST_CLK_H_ */ diff --git a/src/soc/nvidia/tegra132/include/soc/cpu.h b/src/soc/nvidia/tegra132/include/soc/cpu.h new file mode 100644 index 0000000000..b50c09bf89 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/cpu.h @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_CPU_H__ +#define __SOC_NVIDIA_TEGRA132_CPU_H__ + +/* + * Start a core in 64-bit mode at the entry_64 address. Note that entry_64 + * should be a 32-bit address. + */ +void start_cpu(int cpu, void *entry_64); +/* Start CPU wthout any log messages. */ +void start_cpu_silent(int cpu, void *entry_64); +/* Prepare SoC for starting a CPU. Initialize the global state of the SoC. */ +void cpu_prepare_startup(void *entry_64); + +void reset_entry_32bit(void); + +#endif /* __SOC_NVIDIA_TEGRA132_CPU_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/display.h b/src/soc/nvidia/tegra132/include/soc/display.h new file mode 100644 index 0000000000..d7c172d71c --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/display.h @@ -0,0 +1,48 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_DISPLAY_H__ +#define __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_DISPLAY_H__ + +#define COLOR_WHITE 0xFFFFFF +#define COLOR_BLACK 0x000000 + +#define hsync_start(mode) \ + (mode->xres + mode->hfront_porch) + +#define hsync_end(mode) \ + (mode->xres + mode->hfront_porch + mode->hsync_width) + +#define htotal(mode) \ + (mode->xres + mode->hfront_porch + \ + mode->hsync_width + mode->hback_porch) + +#define vtotal(mode) \ + (mode->yres + mode->vfront_porch + \ + mode->vsync_width + mode->vback_porch) + +/* forward declaration */ +struct soc_nvidia_tegra132_config; +struct display_controller; + +void dsi_display_startup(device_t dev); +void dp_display_startup(device_t dev); + +int tegra_dc_init(struct display_controller *disp_ctrl); +int update_display_mode(struct display_controller *disp_ctrl, + struct soc_nvidia_tegra132_config *config); +void update_window(const struct soc_nvidia_tegra132_config *config); +#endif /* __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_DISPLAY_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/dma.h b/src/soc/nvidia/tegra132/include/soc/dma.h new file mode 100644 index 0000000000..7b07cbc89b --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/dma.h @@ -0,0 +1,190 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __NVIDIA_TEGRA132_DMA_H__ +#define __NVIDIA_TEGRA132_DMA_H__ + +#include +#include + +/* + * The DMA engine operates on 4 bytes at a time, so make sure any data + * passed via DMA is aligned to avoid underrun/overrun. + */ +#define TEGRA_DMA_ALIGN_BYTES 4 + +/* + * Note: Many APB DMA controller registers are laid out such that each + * bit controls or represents the status for the corresponding channel. + * So we will not bother to list each individual bit in this case. + */ +#define APB_COMMAND_GEN (1 << 31) + +#define APB_CNTRL_REG_COUNT_VALUE_MASK 0xffff +#define APB_CNTRL_REG_COUNT_VALUE_SHIFT 0 + +/* + * Note: Many APB DMA controller registers are laid out such that each + * bit controls or represents the status for the corresponding channel. + * So we will not bother to list each individual bit in this case. + */ +#define APB_COMMAND_GEN (1 << 31) + +#define APB_CNTRL_REG_COUNT_VALUE_MASK 0xffff +#define APB_CNTRL_REG_COUNT_VALUE_SHIFT 0 +struct apb_dma { + u32 command; /* 0x00 */ + u32 status; /* 0x04 */ + u32 rsvd1[2]; + u32 cntrl_reg; /* 0x10 */ + u32 irq_sta_cpu; /* 0x14 */ + u32 irq_sta_cop; /* 0x18 */ + u32 irq_mask; /* 0x1c */ + u32 irq_mask_set; /* 0x20 */ + u32 irq_mask_clr; /* 0x24 */ + u32 trig_reg; /* 0x28 */ + u32 channel_trig_reg; /* 0x2c */ + u32 dma_status; /* 0x30 */ + u32 channel_en_reg; /* 0x34 */ + u32 security_reg; /* 0x38 */ + u32 channel_swid; /* 0x3c */ + u32 rsvd[1]; + u32 chan_wt_reg0; /* 0x44 */ + u32 chan_wt_reg1; /* 0x48 */ + u32 chan_wt_reg2; /* 0x4c */ + u32 chan_wr_reg3; /* 0x50 */ + u32 channel_swid1; /* 0x54 */ +} __attribute__((packed)); +check_member(apb_dma, channel_swid1, 0x54); + +/* + * Naming in the doc included a superfluous _CHANNEL_n_ for + * each entry and was left out for the sake of conciseness. + */ +#define APB_CSR_ENB (1 << 31) +#define APB_CSR_IE_EOC (1 << 30) +#define APB_CSR_HOLD (1 << 29) +#define APB_CSR_DIR (1 << 28) +#define APB_CSR_ONCE (1 << 27) +#define APB_CSR_FLOW (1 << 21) +#define APB_CSR_REQ_SEL_MASK 0x1f +#define APB_CSR_REQ_SEL_SHIFT 16 + +enum apbdmachan_req_sel { + APBDMA_SLAVE_CNTR_REQ = 0, + APBDMA_SLAVE_APBIF_CH0 = 1, + APBDMA_SLAVE_APBIF_CH1 = 2, + APBDMA_SLAVE_APBIF_CH2 = 3, + APBDMA_SLAVE_APBIF_CH3 = 4, + APBDMA_SLAVE_HSI = 5, + APBDMA_SLAVE_APBIF_CH4 = 6, + APBDMA_SLAVE_APBIF_CH5 = 7, + APBDMA_SLAVE_UART_A = 8, + APBDMA_SLAVE_UART_B = 9, + APBDMA_SLAVE_UART_C = 10, + APBDMA_SLAVE_DTV = 11, + APBDMA_SLAVE_APBIF_CH6 = 12, + APBDMA_SLAVE_APBIF_CH7 = 13, + APBDMA_SLAVE_APBIF_CH8 = 14, + APBDMA_SLAVE_SL2B1 = 15, + APBDMA_SLAVE_SL2B2 = 16, + APBDMA_SLAVE_SL2B3 = 17, + APBDMA_SLAVE_SL2B4 = 18, + APBDMA_SLAVE_UART_D = 19, + APBDMA_SLAVE_UART_E = 20, + APBDMA_SLAVE_I2C = 21, + APBDMA_SLAVE_I2C2 = 22, + APBDMA_SLAVE_I2C3 = 23, + APBDMA_SLAVE_DVC_I2C = 24, + APBDMA_SLAVE_OWR = 25, + APBDMA_SLAVE_I2C4 = 26, + APBDMA_SLAVE_SL2B5 = 27, + APBDMA_SLAVE_SL2B6 = 28, + APBDMA_SLAVE_APBIF_CH9 = 29, + APBDMA_SLAVE_I2C6 = 30, + APBDMA_SLAVE_NA31 = 31, +}; + +#define APB_STA_BSY (1 << 31) +#define APB_STA_ISE_EOC (1 << 30) +#define APB_STA_HALT (1 << 29) +#define APB_STA_PING_PONG_STA (1 << 28) +#define APB_STA_DMA_ACTIVITY (1 << 27) +#define APB_STA_CHANNEL_PAUSE (1 << 26) + +#define APB_CSRE_CHANNEL_PAUSE (1 << 31) +#define APB_CSRE_TRIG_SEL_MASK 0x3f +#define APB_CSRE_TRIG_SEL_SHIFT 14 + +#define AHB_PTR_MASK (0x3fffffff) +#define AHB_PTR_SHIFT 2 + +#define AHB_SEQ_INTR_ENB (1 << 31) +#define AHB_BUS_WIDTH_MASK 0x7 +#define AHB_BUS_WIDTH_SHIFT 28 +#define AHB_DATA_SWAP (1 << 27) +#define AHB_BURST_MASK 0x7 +#define AHB_BURST_SHIFT 24 +#define AHB_SEQ_DBL_BUF (1 << 19) +#define AHB_SEQ_WRAP_MASK 0x7 +#define AHB_SEQ_WRAP_SHIFT 16 + +#define APB_PTR_MASK 0x3fffffff +#define APB_PTR_SHIFT 2 + +#define APB_BUS_WIDTH_MASK 0x7 +#define APB_BUS_WIDTH_SHIFT 28 +#define APB_DATA_SWAP (1 << 27) +#define APB_ADDR_WRAP_MASK 0x7 +#define APB_ADDR_WRAP_SHIFT 16 + +#define APB_WORD_TRANSFER_MASK 0x0fffffff +#define APB_WORD_TRANSFER_SHIFT 2 + +struct apb_dma_channel_regs { + u32 csr; /* 0x00 */ + u32 sta; /* 0x04 */ + u32 dma_byte_sta; /* 0x08 */ + u32 csre; /* 0x0c */ + u32 ahb_ptr; /* 0x10 */ + u32 ahb_seq; /* 0x14 */ + u32 apb_ptr; /* 0x18 */ + u32 apb_seq; /* 0x1c */ + u32 wcount; /* 0x20 */ + u32 word_transfer; /* 0x24 */ +} __attribute__((packed)); +check_member(apb_dma_channel_regs, word_transfer, 0x24); + +struct apb_dma_channel { + const int num; + struct apb_dma_channel_regs *regs; + + /* + * Basic high-level semaphore that can be used to "claim" + * a DMA channel e.g. by SPI, I2C, or other peripheral driver. + */ + int in_use; +}; + +struct apb_dma_channel * const dma_claim(void); +void dma_release(struct apb_dma_channel * const channel); +int dma_start(struct apb_dma_channel * const channel); +int dma_stop(struct apb_dma_channel * const channel); +int dma_busy(struct apb_dma_channel * const channel); + +#endif /* __NVIDIA_TEGRA132_DMA_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/emc.h b/src/soc/nvidia/tegra132/include/soc/emc.h new file mode 100644 index 0000000000..2aa814fc41 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/emc.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA132_EMC_H__ +#define __SOC_NVIDIA_TEGRA132_EMC_H__ + +#include +#include + +enum { + EMC_PIN_RESET_MASK = 1 << 8, + EMC_PIN_RESET_ACTIVE = 0 << 8, + EMC_PIN_RESET_INACTIVE = 1 << 8, + EMC_PIN_DQM_MASK = 1 << 4, + EMC_PIN_DQM_NORMAL = 0 << 4, + EMC_PIN_DQM_INACTIVE = 1 << 4, + EMC_PIN_CKE_MASK = 1 << 0, + EMC_PIN_CKE_POWERDOWN = 0 << 0, + EMC_PIN_CKE_NORMAL = 1 << 0, + + EMC_REF_CMD_MASK = 1 << 0, + EMC_REF_CMD_REFRESH = 1 << 0, + EMC_REF_NORMAL_MASK = 1 << 1, + EMC_REF_NORMAL_INIT = 0 << 1, + EMC_REF_NORMAL_ENABLED = 1 << 1, + EMC_REF_NUM_SHIFT = 8, + EMC_REF_NUM_MASK = 0xFF << EMC_REF_NUM_SHIFT, + EMC_REF_DEV_SELECTN_SHIFT = 30, + EMC_REF_DEV_SELECTN_MASK = 3 << EMC_REF_DEV_SELECTN_SHIFT, + + EMC_REFCTRL_REF_VALID_MASK = 1 << 31, + EMC_REFCTRL_REF_VALID_DISABLED = 0 << 31, + EMC_REFCTRL_REF_VALID_ENABLED = 1 << 31, + + EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK = 1 << 1, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK = 1 << 2, + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK = 1 << 3, + + EMC_NOP_NOP_CMD_SHIFT = 0, + EMC_NOP_NOP_CMD_MASK = 1 << EMC_NOP_NOP_CMD_SHIFT, + EMC_NOP_NOP_DEV_SELECTN_SHIFT = 30, + EMC_NOP_NOP_DEV_SELECTN_MASK = 3 << EMC_NOP_NOP_DEV_SELECTN_SHIFT, + + EMC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +struct tegra_emc_regs { + uint32_t intstatus; /* 0x0 */ + uint32_t intmask; /* 0x4 */ + uint32_t dbg; /* 0x8 */ + uint32_t cfg; /* 0xc */ + uint32_t adr_cfg; /* 0x10 */ + uint32_t rsvd_0x14[3]; /* 0x14 */ + + uint32_t refctrl; /* 0x20 */ + uint32_t pin; /* 0x24 */ + uint32_t timing_control; /* 0x28 */ + uint32_t rc; /* 0x2c */ + uint32_t rfc; /* 0x30 */ + uint32_t ras; /* 0x34 */ + uint32_t rp; /* 0x38 */ + uint32_t r2w; /* 0x3c */ + uint32_t w2r; /* 0x40 */ + uint32_t r2p; /* 0x44 */ + uint32_t w2p; /* 0x48 */ + uint32_t rd_rcd; /* 0x4c */ + uint32_t wr_rcd; /* 0x50 */ + uint32_t rrd; /* 0x54 */ + uint32_t rext; /* 0x58 */ + uint32_t wdv; /* 0x5c */ + uint32_t quse; /* 0x60 */ + uint32_t qrst; /* 0x64 */ + uint32_t qsafe; /* 0x68 */ + uint32_t rdv; /* 0x6c */ + uint32_t refresh; /* 0x70 */ + uint32_t burst_refresh_num; /* 0x74 */ + uint32_t pdex2wr; /* 0x78 */ + uint32_t pdex2rd; /* 0x7c */ + uint32_t pchg2pden; /* 0x80 */ + uint32_t act2pden; /* 0x84 */ + uint32_t ar2pden; /* 0x88 */ + uint32_t rw2pden; /* 0x8c */ + uint32_t txsr; /* 0x90 */ + uint32_t tcke; /* 0x94 */ + uint32_t tfaw; /* 0x98 */ + uint32_t trpab; /* 0x9c */ + uint32_t tclkstable; /* 0xa0 */ + uint32_t tclkstop; /* 0xa4 */ + uint32_t trefbw; /* 0xa8 */ + uint32_t rsvd_0xac[1]; /* 0xac */ + uint32_t odt_write; /* 0xb0 */ + uint32_t odt_read; /* 0xb4 */ + uint32_t wext; /* 0xb8 */ + uint32_t ctt; /* 0xbc */ + uint32_t rfc_slr; /* 0xc0 */ + uint32_t mrs_wait_cnt2; /* 0xc4 */ + uint32_t mrs_wait_cnt; /* 0xc8 */ + uint32_t mrs; /* 0xcc */ + uint32_t emrs; /* 0xd0 */ + uint32_t ref; /* 0xd4 */ + uint32_t pre; /* 0xd8 */ + uint32_t nop; /* 0xdc */ + uint32_t self_ref; /* 0xe0 */ + uint32_t dpd; /* 0xe4 */ + uint32_t mrw; /* 0xe8 */ + uint32_t mrr; /* 0xec */ + uint32_t cmdq; /* 0xf0 */ + uint32_t mc2emcq; /* 0xf4 */ + uint32_t xm2dqspadctrl3; /* 0xf8 */ + uint32_t rsvd_0xfc[1]; /* 0xfc */ + uint32_t fbio_spare; /* 0x100 */ + uint32_t fbio_cfg5; /* 0x104 */ + uint32_t fbio_wrptr_eq_2; /* 0x108 */ + uint32_t rsvd_0x10c[2]; /* 0x10c */ + + uint32_t fbio_cfg6; /* 0x114 */ + uint32_t rsvd_0x118[2]; /* 0x118 */ + + uint32_t cfg_rsv; /* 0x120 */ + uint32_t acpd_control; /* 0x132 */ + uint32_t rsvd_0x128[1]; /* 0x128 */ + uint32_t emrs2; /* 0x12c */ + uint32_t emrs3; /* 0x130 */ + uint32_t mrw2; /* 0x134 */ + uint32_t mrw3; /* 0x138 */ + uint32_t mrw4; /* 0x13c */ + uint32_t clken_override; /* 0x140 */ + uint32_t r2r; /* 0x144 */ + uint32_t w2w; /* 0x148 */ + uint32_t einput; /* 0x14c */ + uint32_t einput_duration; /* 0x150 */ + uint32_t puterm_extra; /* 0x154 */ + uint32_t tckesr; /* 0x158 */ + uint32_t tpd; /* 0x15c */ + uint32_t rsvd_0x160[81]; /* 0x160 */ + + uint32_t auto_cal_config; /* 0x2a4 */ + uint32_t auto_cal_interval; /* 0x2a8 */ + uint32_t auto_cal_status; /* 0x2ac */ + uint32_t req_ctrl; /* 0x2b0 */ + uint32_t status; /* 0x2b4 */ + uint32_t cfg_2; /* 0x2b8 */ + uint32_t cfg_dig_dll; /* 0x2bc */ + uint32_t cfg_dig_dll_period; /* 0x2c0 */ + uint32_t rsvd_0x2c4[1]; /* 0x2c4 */ + uint32_t dig_dll_status; /* 0x2c8 */ + uint32_t rdv_mask; /* 0x2cc */ + uint32_t wdv_mask; /* 0x2d0 */ + uint32_t rsvd_0x2d4[1]; /* 0x2d4 */ + uint32_t ctt_duration; /* 0x2d8 */ + uint32_t ctt_term_ctrl; /* 0x2dc */ + uint32_t zcal_interval; /* 0x2e0 */ + uint32_t zcal_wait_cnt; /* 0x2e4 */ + uint32_t zcal_mrw_cmd; /* 0x2e8 */ + uint32_t zq_cal; /* 0x2ec */ + uint32_t xm2cmdpadctrl; /* 0x2f0 */ + uint32_t xm2cmdpadctrl2; /* 0x2f4 */ + uint32_t xm2dqspadctrl; /* 0x2f8 */ + uint32_t xm2dqspadctrl2; /* 0x2fc */ + uint32_t xm2dqpadctrl; /* 0x300 */ + uint32_t xm2dqpadctrl2; /* 0x304 */ + uint32_t xm2clkpadctrl; /* 0x308 */ + uint32_t xm2comppadctrl; /* 0x30c */ + uint32_t xm2vttgenpadctrl; /* 0x310 */ + uint32_t xm2vttgenpadctrl2; /* 0x314 */ + uint32_t xm2vttgenpadctrl3; /* 0x318 */ + uint32_t emcpaden; /* 0x31c */ + uint32_t xm2dqspadctrl4; /* 0x320 */ + uint32_t scratch0; /* 0x324 */ + uint32_t dll_xform_dqs0; /* 0x328 */ + uint32_t dll_xform_dqs1; /* 0x32c */ + uint32_t dll_xform_dqs2; /* 0x330 */ + uint32_t dll_xform_dqs3; /* 0x334 */ + uint32_t dll_xform_dqs4; /* 0x338 */ + uint32_t dll_xform_dqs5; /* 0x33c */ + uint32_t dll_xform_dqs6; /* 0x340 */ + uint32_t dll_xform_dqs7; /* 0x344 */ + uint32_t dll_xform_quse0; /* 0x348 */ + uint32_t dll_xform_quse1; /* 0x34c */ + uint32_t dll_xform_quse2; /* 0x350 */ + uint32_t dll_xform_quse3; /* 0x354 */ + uint32_t dll_xform_quse4; /* 0x358 */ + uint32_t dll_xform_quse5; /* 0x35c */ + uint32_t dll_xform_quse6; /* 0x360 */ + uint32_t dll_xform_quse7; /* 0x364 */ + uint32_t dll_xform_dq0; /* 0x368 */ + uint32_t dll_xform_dq1; /* 0x36c */ + uint32_t dll_xform_dq2; /* 0x370 */ + uint32_t dll_xform_dq3; /* 0x374 */ + uint32_t dli_rx_trim0; /* 0x378 */ + uint32_t dli_rx_trim1; /* 0x37c */ + uint32_t dli_rx_trim2; /* 0x380 */ + uint32_t dli_rx_trim3; /* 0x384 */ + uint32_t dli_rx_trim4; /* 0x388 */ + uint32_t dli_rx_trim5; /* 0x38c */ + uint32_t dli_rx_trim6; /* 0x390 */ + uint32_t dli_rx_trim7; /* 0x394 */ + uint32_t dli_tx_trim0; /* 0x398 */ + uint32_t dli_tx_trim1; /* 0x39c */ + uint32_t dli_tx_trim2; /* 0x3a0 */ + uint32_t dli_tx_trim3; /* 0x3a4 */ + uint32_t dli_trim_txdqs0; /* 0x3a8 */ + uint32_t dli_trim_txdqs1; /* 0x3ac */ + uint32_t dli_trim_txdqs2; /* 0x3b0 */ + uint32_t dli_trim_txdqs3; /* 0x3b4 */ + uint32_t dli_trim_txdqs4; /* 0x3b8 */ + uint32_t dli_trim_txdqs5; /* 0x3bc */ + uint32_t dli_trim_txdqs6; /* 0x3c0 */ + uint32_t dli_trim_txdqs7; /* 0x3c4 */ + uint32_t rsvd_0x3c8[1]; /* 0x3c8 */ + uint32_t stall_then_exe_after_clkchange; /* 0x3cc */ + uint32_t rsvd_0x3d0[1]; /* 0x3d0 */ + uint32_t auto_cal_clk_status; /* 0x3d4 */ + uint32_t sel_dpd_ctrl; /* 0x3d8 */ + uint32_t pre_refresh_req_cnt; /* 0x3dc */ + uint32_t dyn_self_ref_control; /* 0x3e0 */ + uint32_t txsrdll; /* 0x3e4 */ + uint32_t ccfifo_addr; /* 0x3e8 */ + uint32_t ccfifo_data; /* 0x3ec */ + uint32_t ccfifo_status; /* 0x3f0 */ + uint32_t cdb_cntl_1; /* 0x3f4 */ + uint32_t cdb_cntl_2; /* 0x3f8 */ + uint32_t xm2clkpadctrl2; /* 0x3fc */ + uint32_t swizzle_rank0_byte_cfg; /* 0x400 */ + uint32_t swizzle_rank0_byte0; /* 0x404 */ + uint32_t swizzle_rank0_byte1; /* 0x408 */ + uint32_t swizzle_rank0_byte2; /* 0x40c */ + uint32_t swizzle_rank0_byte3; /* 0x410 */ + uint32_t swizzle_rank1_byte_cfg; /* 0x414 */ + uint32_t swizzle_rank1_byte0; /* 0x418 */ + uint32_t swizzle_rank1_byte1; /* 0x41c */ + uint32_t swizzle_rank1_byte2; /* 0x420 */ + uint32_t swizzle_rank1_byte3; /* 0x424 */ + uint32_t ca_training_start; /* 0x428 */ + uint32_t ca_training_busy; /* 0x42c */ + uint32_t ca_training_cfg; /* 0x430 */ + uint32_t ca_training_timing_cntl1; /* 0x434 */ + uint32_t ca_training_timing_cntl2; /* 0x438 */ + uint32_t ca_training_ca_lead_in; /* 0x43c */ + uint32_t ca_training_ca; /* 0x440 */ + uint32_t ca_training_ca_lead_out; /* 0x444 */ + uint32_t ca_training_result1; /* 0x448 */ + uint32_t ca_training_result2; /* 0x44c */ + uint32_t ca_training_result3; /* 0x450 */ + uint32_t ca_training_result4; /* 0x454 */ + uint32_t auto_cal_config2; /* 0x458 */ + uint32_t auto_cal_config3; /* 0x45c */ + uint32_t auto_cal_status2; /* 0x460 */ + uint32_t xm2cmdpadctrl3; /* 0x464 */ + uint32_t ibdly; /* 0x468 */ + uint32_t dll_xform_addr0; /* 0x46c */ + uint32_t dll_xform_addr1; /* 0x470 */ + uint32_t dll_xform_addr2; /* 0x474 */ + uint32_t dli_addr_trim; /* 0x478 */ + uint32_t dsr_vttgen_drv; /* 0x47c */ + uint32_t txdsrvttgen; /* 0x480 */ + uint32_t xm2cmdpadctrl4; /* 0x484 */ + uint32_t xm2cmdpadctrl5; /* 0x488 */ + uint32_t rsvd_0x48c[5]; /* 0x48c */ + + uint32_t dll_xform_dqs8; /* 0x4a0 */ + uint32_t dll_xform_dqs9; /* 0x4a4 */ + uint32_t dll_xform_dqs10; /* 0x4a8 */ + uint32_t dll_xform_dqs11; /* 0x4ac */ + uint32_t dll_xform_dqs12; /* 0x4b0 */ + uint32_t dll_xform_dqs13; /* 0x4b4 */ + uint32_t dll_xform_dqs14; /* 0x4b8 */ + uint32_t dll_xform_dqs15; /* 0x4bc */ + uint32_t dll_xform_quse8; /* 0x4c0 */ + uint32_t dll_xform_quse9; /* 0x4c4 */ + uint32_t dll_xform_quse10; /* 0x4c8 */ + uint32_t dll_xform_quse11; /* 0x4cc */ + uint32_t dll_xform_quse12; /* 0x4d0 */ + uint32_t dll_xform_quse13; /* 0x4d4 */ + uint32_t dll_xform_quse14; /* 0x4d8 */ + uint32_t dll_xform_quse15; /* 0x4dc */ + uint32_t dll_xform_dq4; /* 0x4e0 */ + uint32_t dll_xform_dq5; /* 0x4e4 */ + uint32_t dll_xform_dq6; /* 0x4e8 */ + uint32_t dll_xform_dq7; /* 0x4ec */ + uint32_t rsvd_0x4f0[12]; /* 0x4f0 */ + + uint32_t dli_trim_txdqs8; /* 0x520 */ + uint32_t dli_trim_txdqs9; /* 0x524 */ + uint32_t dli_trim_txdqs10; /* 0x528 */ + uint32_t dli_trim_txdqs11; /* 0x52c */ + uint32_t dli_trim_txdqs12; /* 0x530 */ + uint32_t dli_trim_txdqs13; /* 0x534 */ + uint32_t dli_trim_txdqs14; /* 0x538 */ + uint32_t dli_trim_txdqs15; /* 0x53c */ + uint32_t cdb_cntl_3; /* 0x540 */ + uint32_t xm2dqspadctrl5; /* 0x544 */ + uint32_t xm2dqspadctrl6; /* 0x548 */ + uint32_t xm2dqpadctrl3; /* 0x54c */ + uint32_t dll_xform_addr3; /* 0x550 */ + uint32_t dll_xform_addr4; /* 0x554 */ + uint32_t dll_xform_addr5; /* 0x558 */ + uint32_t rsvd_0x55c[1]; /* 0x55c */ + uint32_t cfg_pipe; /* 0x560 */ + uint32_t qpop; /* 0x564 */ + uint32_t quse_width; /* 0x568 */ + uint32_t puterm_width; /* 0x56c */ + uint32_t bgbias_ctl0; /* 0x570 */ + uint32_t puterm_adj; /* 0x574 */ +} __attribute__((packed)); + +check_member(tegra_emc_regs, puterm_adj, 0x574); + +#endif /* __SOC_NVIDIA_TEGRA132_EMC_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/flow.h b/src/soc/nvidia/tegra132/include/soc/flow.h new file mode 100644 index 0000000000..01dbc14208 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/flow.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA132_FLOW_H_ +#define _TEGRA132_FLOW_H_ + +struct flow_ctlr { + u32 halt_cpu_events; /* offset 0x00 */ + u32 halt_cop_events; /* offset 0x04 */ + u32 cpu_csr; /* offset 0x08 */ + u32 cop_csr; /* offset 0x0c */ + u32 xrq_events; /* offset 0x10 */ + u32 halt_cpu1_events; /* offset 0x14 */ + u32 cpu1_csr; /* offset 0x18 */ + u32 halt_cpu2_events; /* offset 0x1c */ + u32 cpu2_csr; /* offset 0x20 */ + u32 halt_cpu3_events; /* offset 0x24 */ + u32 cpu3_csr; /* offset 0x28 */ + u32 cluster_control; /* offset 0x2c */ + u32 halt_cop1_events; /* offset 0x30 */ + u32 halt_cop1_csr; /* offset 0x34 */ + u32 cpu_pwr_csr; /* offset 0x38 */ + u32 mpid; /* offset 0x3c */ + u32 ram_repair; /* offset 0x40 */ +}; +check_member(flow_ctlr, ram_repair, 0x40); + +enum { + FLOW_MODE_SHIFT = 29, + FLOW_MODE_MASK = 0x7 << FLOW_MODE_SHIFT, + + FLOW_MODE_NONE = 0 << FLOW_MODE_SHIFT, + FLOW_MODE_RUN_AND_INT = 1 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT = 2 << FLOW_MODE_SHIFT, + FLOW_MODE_WAITEVENT_AND_INT = 3 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ = 4 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_IRQ_AND_INT = 5 << FLOW_MODE_SHIFT, + FLOW_MODE_STOP_UNTIL_EVENT_AND_IRQ = 6 << FLOW_MODE_SHIFT, +}; + +/* HALT_COP_EVENTS_0, 0x04 */ +enum { + FLOW_EVENT_GIC_FIQ = 1 << 8, + FLOW_EVENT_GIC_IRQ = 1 << 9, + FLOW_EVENT_LIC_FIQ = 1 << 10, + FLOW_EVENT_LIC_IRQ = 1 << 11, + FLOW_EVENT_IBF = 1 << 12, + FLOW_EVENT_IBE = 1 << 13, + FLOW_EVENT_OBF = 1 << 14, + FLOW_EVENT_OBE = 1 << 15, + FLOW_EVENT_XRQ_A = 1 << 16, + FLOW_EVENT_XRQ_B = 1 << 17, + FLOW_EVENT_XRQ_C = 1 << 18, + FLOW_EVENT_XRQ_D = 1 << 19, + FLOW_EVENT_SMP30 = 1 << 20, + FLOW_EVENT_SMP31 = 1 << 21, + FLOW_EVENT_X_RDY = 1 << 22, + FLOW_EVENT_SEC = 1 << 23, + FLOW_EVENT_MSEC = 1 << 24, + FLOW_EVENT_USEC = 1 << 25, + FLOW_EVENT_X32K = 1 << 26, + FLOW_EVENT_SCLK = 1 << 27, + FLOW_EVENT_JTAG = 1 << 28 +}; + +#endif /* _TEGRA132_FLOW_H_ */ diff --git a/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h new file mode 100644 index 0000000000..28fe8466fd --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/flow_ctrl.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TEGRA132_FLOW_CTRL_H_ +#define _TEGRA132_FLOW_CTRL_H_ + +void flowctrl_cpu_off(int cpu); +void flowctrl_write_cpu_halt(int cpu, uint32_t val); + +#endif diff --git a/src/soc/nvidia/tegra132/include/soc/funitcfg.h b/src/soc/nvidia/tegra132/include/soc/funitcfg.h new file mode 100644 index 0000000000..580bd755e6 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/funitcfg.h @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_FUNIT_CFG_H +#define __SOC_NVIDIA_TEGRA132_FUNIT_CFG_H + +#include +#include +#include +#include + +#define FUNIT_INDEX(_name) FUNIT_##_name + +enum { + FUNIT_INDEX(SBC1), + FUNIT_INDEX(SBC4), + FUNIT_INDEX(I2C1), + FUNIT_INDEX(I2C2), + FUNIT_INDEX(I2C3), + FUNIT_INDEX(I2C5), + FUNIT_INDEX(I2C6), + FUNIT_INDEX(SDMMC3), + FUNIT_INDEX(SDMMC4), + FUNIT_INDEX(USBD), + FUNIT_INDEX(USB2), + FUNIT_INDEX(USB3), + FUNIT_INDEX(I2S1), + FUNIT_INDEX_MAX, +}; + +/* + * Note: these bus numbers are dependent on the driver implementations, and + * currently the I2C is 0-based and SPI is 1-based in its indexing. + */ +enum { + + I2C1_BUS = 0, + I2C2_BUS = 1, + I2C3_BUS = 2, + I2C5_BUS = 4, + I2CPWR_BUS = I2C5_BUS, + I2C6_BUS = 5, + + SPI1_BUS = 1, + SPI4_BUS = 4, +}; + +struct funit_cfg { + uint32_t funit_index; + uint32_t clk_src_id; + uint32_t clk_src_freq_id; + uint32_t clk_dev_freq_khz; + struct pad_config const* pad_cfg; + size_t pad_cfg_size; +}; + +#define FUNIT_CFG(_funit,_clk_src,_clk_freq,_cfg,_cfg_size) \ + { \ + .funit_index = FUNIT_INDEX(_funit), \ + .clk_src_id = CLK_SRC_DEV_ID(_funit, _clk_src), \ + .clk_src_freq_id = CLK_SRC_FREQ_ID(_funit, _clk_src), \ + .clk_dev_freq_khz = _clk_freq, \ + .pad_cfg = _cfg, \ + .pad_cfg_size = _cfg_size, \ + } + +#define FUNIT_CFG_USB(_funit) \ + { \ + .funit_index = FUNIT_INDEX(_funit), \ + .pad_cfg = NULL, \ + .pad_cfg_size = 0, \ + } + +/* + * Configure the funits associated with entry according to the configuration. + */ +void soc_configure_funits(const struct funit_cfg * const entries, size_t num); + +#endif /* __SOC_NVIDIA_TEGRA132_FUNIT_CFG_H */ diff --git a/src/soc/nvidia/tegra132/include/soc/gpio.h b/src/soc/nvidia/tegra132/include/soc/gpio.h new file mode 100644 index 0000000000..b28a87f687 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/gpio.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_GPIO_H__ +#define __SOC_NVIDIA_TEGRA132_GPIO_H__ + +#include + +#endif /* __SOC_NVIDIA_TEGRA132_GPIO_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/id.h b/src/soc/nvidia/tegra132/include/soc/id.h new file mode 100644 index 0000000000..6ce3df54f0 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/id.h @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ID_H__ +#define __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ID_H__ + + +#include +#include + +static inline int context_avp(void) +{ + const uint32_t avp_id = 0xaaaaaaaa; + void * const uptag = (void *)(uintptr_t)TEGRA_PG_UP_BASE; + + return read32(uptag) == avp_id; +} + +#endif /* define __SOC_NVIDIA_TEGRA132_INCLUDE_SOC_ID_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/maincpu.h b/src/soc/nvidia/tegra132/include/soc/maincpu.h new file mode 100644 index 0000000000..1f795dfc66 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/maincpu.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_MAINCPU_H__ +#define __SOC_NVIDIA_TEGRA132_MAINCPU_H__ + +#include + +extern u32 maincpu_stack_pointer; +extern u32 maincpu_entry_point; +void maincpu_setup(void); + +#endif /* __SOC_NVIDIA_TEGRA132_MAINCPU_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/mc.h b/src/soc/nvidia/tegra132/include/soc/mc.h new file mode 100644 index 0000000000..3ce790022b --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/mc.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SOC_NVIDIA_TEGRA132_MC_H__ +#define __SOC_NVIDIA_TEGRA132_MC_H__ + +#include +#include + +// Memory Controller registers we need/care about + +struct tegra_mc_regs { + uint32_t rsvd_0x0[4]; /* 0x00 */ + uint32_t smmu_config; /* 0x10 */ + uint32_t smmu_tlb_config; /* 0x14 */ + uint32_t smmu_ptc_config; /* 0x18 */ + uint32_t smmu_ptb_asid; /* 0x1c */ + uint32_t smmu_ptb_data; /* 0x20 */ + uint32_t rsvd_0x24[3]; /* 0x24 */ + uint32_t smmu_tlb_flush; /* 0x30 */ + uint32_t smmu_ptc_flush; /* 0x34 */ + uint32_t rsvd_0x38[6]; /* 0x38 */ + uint32_t emem_cfg; /* 0x50 */ + uint32_t emem_adr_cfg; /* 0x54 */ + uint32_t emem_adr_cfg_dev0; /* 0x58 */ + uint32_t emem_adr_cfg_dev1; /* 0x5c */ + uint32_t rsvd_0x60[1]; /* 0x60 */ + uint32_t emem_adr_cfg_bank_mask_0; /* 0x64 */ + uint32_t emem_adr_cfg_bank_mask_1; /* 0x68 */ + uint32_t emem_adr_cfg_bank_mask_2; /* 0x6c */ + uint32_t security_cfg0; /* 0x70 */ + uint32_t security_cfg1; /* 0x74 */ + uint32_t rsvd_0x78[6]; /* 0x78 */ + uint32_t emem_arb_cfg; /* 0x90 */ + uint32_t emem_arb_outstanding_req; /* 0x94 */ + uint32_t emem_arb_timing_rcd; /* 0x98 */ + uint32_t emem_arb_timing_rp; /* 0x9c */ + uint32_t emem_arb_timing_rc; /* 0xa0 */ + uint32_t emem_arb_timing_ras; /* 0xa4 */ + uint32_t emem_arb_timing_faw; /* 0xa8 */ + uint32_t emem_arb_timing_rrd; /* 0xac */ + uint32_t emem_arb_timing_rap2pre; /* 0xb0 */ + uint32_t emem_arb_timing_wap2pre; /* 0xb4 */ + uint32_t emem_arb_timing_r2r; /* 0xb8 */ + uint32_t emem_arb_timing_w2w; /* 0xbc */ + uint32_t emem_arb_timing_r2w; /* 0xc0 */ + uint32_t emem_arb_timing_w2r; /* 0xc4 */ + uint32_t rsvd_0xc8[2]; /* 0xc8 */ + uint32_t emem_arb_da_turns; /* 0xd0 */ + uint32_t emem_arb_da_covers; /* 0xd4 */ + uint32_t emem_arb_misc0; /* 0xd8 */ + uint32_t emem_arb_misc1; /* 0xdc */ + uint32_t emem_arb_ring1_throttle; /* 0xe0 */ + uint32_t emem_arb_ring3_throttle; /* 0xe4 */ + uint32_t emem_arb_override; /* 0xe8 */ + uint32_t emem_arb_rsv; /* 0xec */ + uint32_t rsvd_0xf0[1]; /* 0xf0 */ + uint32_t clken_override; /* 0xf4 */ + uint32_t timing_control_dbg; /* 0xf8 */ + uint32_t timing_control; /* 0xfc */ + uint32_t stat_control; /* 0x100 */ + uint32_t rsvd_0x104[65]; /* 0x104 */ + uint32_t emem_arb_isochronous_0; /* 0x208 */ + uint32_t emem_arb_isochronous_1; /* 0x20c */ + uint32_t emem_arb_isochronous_2; /* 0x210 */ + uint32_t rsvd_0x214[38]; /* 0x214 */ + uint32_t dis_extra_snap_levels; /* 0x2ac */ + uint32_t rsvd_0x2b0[90]; /* 0x2b0 */ + uint32_t video_protect_vpr_override; /* 0x418 */ + uint32_t rsvd_0x41c[93]; /* 0x41c */ + uint32_t video_protect_vpr_override1; /* 0x590 */ + uint32_t rsvd_0x594[29]; /* 0x594 */ + uint32_t display_snap_ring; /* 0x608 */ + uint32_t rsvd_0x60c[15]; /* 0x60c */ + uint32_t video_protect_bom; /* 0x648 */ + uint32_t video_protect_size_mb; /* 0x64c */ + uint32_t video_protect_reg_ctrl; /* 0x650 */ + uint32_t rsvd_0x654[4]; /* 0x654 */ + uint32_t emem_cfg_access_ctrl; /* 0x664 */ + uint32_t rsvd_0x668[2]; /* 0x668 */ + uint32_t sec_carveout_bom; /* 0x670 */ + uint32_t sec_carveout_size_mb; /* 0x674 */ + uint32_t sec_carveout_reg_ctrl; /* 0x678 */ + uint32_t rsvd_0x67c[187]; /* 0x67c */ + uint32_t emem_arb_override_1; /* 0x968 */ + uint32_t rsvd_0x96c[3]; /* 0x96c */ + uint32_t video_protect_bom_adr_hi; /* 0x978 */ + uint32_t rsvd_0x97c[2]; /* 0x97c */ + uint32_t video_protect_gpu_override_0; /* 0x984 */ + uint32_t video_protect_gpu_override_1; /* 0x988 */ + uint32_t rsvd_0x98c[5]; /* 0x98c */ + uint32_t mts_carveout_bom; /* 0x9a0 */ + uint32_t mts_carveout_size_mb; /* 0x9a4 */ + uint32_t mts_carveout_adr_hi; /* 0x9a8 */ + uint32_t mts_carveout_reg_ctrl; /* 0x9ac */ + uint32_t rsvd_0x9b0[4]; /* 0x9b0 */ + uint32_t emem_bank_swizzle_cfg0; /* 0x9c0 */ + uint32_t emem_bank_swizzle_cfg1; /* 0x9c4 */ + uint32_t emem_bank_swizzle_cfg2; /* 0x9c8 */ + uint32_t emem_bank_swizzle_cfg3; /* 0x9cc */ + uint32_t rsvd_0x9d0[1]; /* 0x9d0 */ + uint32_t sec_carveout_adr_hi; /* 0x9d4 */ +}; + +enum { + MC_SMMU_CONFIG_ENABLE = 1, + + MC_EMEM_CFG_SIZE_MB_SHIFT = 0, + MC_EMEM_CFG_SIZE_MB_MASK = 0x3fff, + + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_SHIFT = 27, + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK = 1 << 27, + + MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED = 1, + + MC_TIMING_CONTROL_TIMING_UPDATE = 1, +}; + +check_member(tegra_mc_regs, sec_carveout_adr_hi, 0x9d4); + +#endif /* __SOC_NVIDIA_TEGRA132_MC_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout.ld b/src/soc/nvidia/tegra132/include/soc/memlayout.ld new file mode 100644 index 0000000000..28f8d59592 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/memlayout.ld @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +/* + * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself, + * so the bootblock loading address must be placed after that. After the + * handoff that area may be reclaimed for other uses, e.g. CBFS cache. + * TODO: Did this change on Tegra132? What's the new valid range? + */ + +SECTIONS +{ + SRAM_START(0x40000000) + PRERAM_CBMEM_CONSOLE(0x40000000, 8K) + PRERAM_CBFS_CACHE(0x40002000, 84K) + STACK(0x40017000, 16K) + TIMESTAMP(0x4001B000, 2K) + BOOTBLOCK(0x4001B800, 22K) + ROMSTAGE(0x40021000, 124K) + SRAM_END(0x40040000) + + DRAM_START(0x80000000) + POSTRAM_CBFS_CACHE(0x80100000, 1M) + RAMSTAGE(0x80200000, 256K) +} diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld new file mode 100644 index 0000000000..1b5abcc479 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +/* + * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself, + * so the bootblock loading address must be placed after that. After the + * handoff that area may be reclaimed for other uses, e.g. CBFS cache. + * TODO: Did this change on Tegra132? What's the new valid range? + */ + +SECTIONS +{ + SRAM_START(0x40000000) + PRERAM_CBMEM_CONSOLE(0x40000000, 8K) + PRERAM_CBFS_CACHE(0x40002000, 72K) + VBOOT2_WORK(0x40014000, 16K) + STACK(0x40018000, 2K) + TIMESTAMP(0x40018800, 2K) + BOOTBLOCK(0x40019000, 22K) + VERSTAGE(0x4001E800, 58K) + ROMSTAGE(0x4002D000, 76K) + SRAM_END(0x40040000) + + DRAM_START(0x80000000) + POSTRAM_CBFS_CACHE(0x80100000, 1M) + RAMSTAGE(0x80200000, 256K) +} diff --git a/src/soc/nvidia/tegra132/include/soc/mipi-phy.h b/src/soc/nvidia/tegra132/include/soc/mipi-phy.h new file mode 100644 index 0000000000..2ec3fce113 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/mipi-phy.h @@ -0,0 +1,46 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _TEGRA_MIPI_PHY_H +#define _TEGRA_MIPI_PHY_H + +#include + +/* + * Macros for calculating the phy timings + */ +/* Period of one bit time in nano seconds */ +#define DSI_TBIT_Factorized(Freq) (((1000) * (1000))/(Freq)) +#define DSI_TBIT(Freq) (DSI_TBIT_Factorized(Freq)/(1000)) + +//#define NV_MAX(a,b) (((a) > (b)) ? (a) : (b)) + +/* Period of one byte time in nano seconds */ +#define DSI_TBYTE(Freq) ((DSI_TBIT_Factorized(Freq)) * (8)) +#define DSI_PHY_TIMING_DIV(X, Freq) ((X*1000) / (DSI_TBYTE(Freq))) + +/* + * As per Mipi spec (minimum): + * (3 + MAX(8 * DSI_TBIT, 60 + 4 * DSI_TBIT) / DSI_TBYTE) + */ +#define DSI_THSTRAIL_VAL(Freq) \ + (MAX(((8) * (DSI_TBIT(Freq))), ((60) + ((4) * (DSI_TBIT(Freq)))))) + +int mipi_dphy_set_timing(struct tegra_dsi *dsi); + +#endif diff --git a/src/soc/nvidia/tegra132/include/soc/mipi_display.h b/src/soc/nvidia/tegra132/include/soc/mipi_display.h new file mode 100644 index 0000000000..99bfa93ea7 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/mipi_display.h @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * Defines for Mobile Industry Processor Interface (MIPI(R)) + * Display Working Group standards: DSI, DCS, DBI, DPI + * + * Copyright (C) 2010 Guennadi Liakhovetski + * Copyright (C) 2006 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef MIPI_DISPLAY_H +#define MIPI_DISPLAY_H + +/* MIPI DSI Processor-to-Peripheral transaction types */ +enum { + MIPI_DSI_V_SYNC_START = 0x01, + MIPI_DSI_V_SYNC_END = 0x11, + MIPI_DSI_H_SYNC_START = 0x21, + MIPI_DSI_H_SYNC_END = 0x31, + + MIPI_DSI_COLOR_MODE_OFF = 0x02, + MIPI_DSI_COLOR_MODE_ON = 0x12, + MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22, + MIPI_DSI_TURN_ON_PERIPHERAL = 0x32, + + MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03, + MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13, + MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23, + + MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04, + MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14, + MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24, + + MIPI_DSI_DCS_SHORT_WRITE = 0x05, + MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15, + + MIPI_DSI_DCS_READ = 0x06, + + MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37, + + MIPI_DSI_END_OF_TRANSMISSION = 0x08, + + MIPI_DSI_NULL_PACKET = 0x09, + MIPI_DSI_BLANKING_PACKET = 0x19, + MIPI_DSI_GENERIC_LONG_WRITE = 0x29, + MIPI_DSI_DCS_LONG_WRITE = 0x39, + + MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c, + MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c, + MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c, + + MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d, + MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d, + MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d, + + MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e, + MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e, + MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e, + MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e, +}; + +/* MIPI DSI Peripheral-to-Processor transaction types */ +enum { + MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02, + MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08, + MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11, + MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12, + MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a, + MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c, + MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21, + MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22, +}; + +/* MIPI DCS commands */ +enum { + MIPI_DCS_NOP = 0x00, + MIPI_DCS_SOFT_RESET = 0x01, + MIPI_DCS_GET_DISPLAY_ID = 0x04, + MIPI_DCS_GET_RED_CHANNEL = 0x06, + MIPI_DCS_GET_GREEN_CHANNEL = 0x07, + MIPI_DCS_GET_BLUE_CHANNEL = 0x08, + MIPI_DCS_GET_DISPLAY_STATUS = 0x09, + MIPI_DCS_GET_POWER_MODE = 0x0A, + MIPI_DCS_GET_ADDRESS_MODE = 0x0B, + MIPI_DCS_GET_PIXEL_FORMAT = 0x0C, + MIPI_DCS_GET_DISPLAY_MODE = 0x0D, + MIPI_DCS_GET_SIGNAL_MODE = 0x0E, + MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F, + MIPI_DCS_ENTER_SLEEP_MODE = 0x10, + MIPI_DCS_EXIT_SLEEP_MODE = 0x11, + MIPI_DCS_ENTER_PARTIAL_MODE = 0x12, + MIPI_DCS_ENTER_NORMAL_MODE = 0x13, + MIPI_DCS_EXIT_INVERT_MODE = 0x20, + MIPI_DCS_ENTER_INVERT_MODE = 0x21, + MIPI_DCS_SET_GAMMA_CURVE = 0x26, + MIPI_DCS_SET_DISPLAY_OFF = 0x28, + MIPI_DCS_SET_DISPLAY_ON = 0x29, + MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A, + MIPI_DCS_SET_PAGE_ADDRESS = 0x2B, + MIPI_DCS_WRITE_MEMORY_START = 0x2C, + MIPI_DCS_WRITE_LUT = 0x2D, + MIPI_DCS_READ_MEMORY_START = 0x2E, + MIPI_DCS_SET_PARTIAL_AREA = 0x30, + MIPI_DCS_SET_SCROLL_AREA = 0x33, + MIPI_DCS_SET_TEAR_OFF = 0x34, + MIPI_DCS_SET_TEAR_ON = 0x35, + MIPI_DCS_SET_ADDRESS_MODE = 0x36, + MIPI_DCS_SET_SCROLL_START = 0x37, + MIPI_DCS_EXIT_IDLE_MODE = 0x38, + MIPI_DCS_ENTER_IDLE_MODE = 0x39, + MIPI_DCS_SET_PIXEL_FORMAT = 0x3A, + MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C, + MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E, + MIPI_DCS_SET_TEAR_SCANLINE = 0x44, + MIPI_DCS_GET_SCANLINE = 0x45, + MIPI_DCS_READ_DDB_START = 0xA1, + MIPI_DCS_READ_DDB_CONTINUE = 0xA8, +}; + +/* MIPI DCS pixel formats */ +#define MIPI_DCS_PIXEL_FMT_24BIT 7 +#define MIPI_DCS_PIXEL_FMT_18BIT 6 +#define MIPI_DCS_PIXEL_FMT_16BIT 5 +#define MIPI_DCS_PIXEL_FMT_12BIT 3 +#define MIPI_DCS_PIXEL_FMT_8BIT 2 +#define MIPI_DCS_PIXEL_FMT_3BIT 1 + +#endif diff --git a/src/soc/nvidia/tegra132/include/soc/mipi_dsi.h b/src/soc/nvidia/tegra132/include/soc/mipi_dsi.h new file mode 100644 index 0000000000..ed4b199120 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/mipi_dsi.h @@ -0,0 +1,285 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MIPI_DSI_H__ +#define __MIPI_DSI_H__ + +struct mipi_dsi_host; +struct mipi_dsi_device; + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +/** + * struct mipi_dsi_msg - read/write DSI buffer + * @channel: virtual channel id + * @type: payload data type + * @flags: flags controlling this message transmission + * @tx_len: length of @tx_buf + * @tx_buf: data to be written + * @rx_len: length of @rx_buf + * @rx_buf: data to be read, or NULL + */ +struct mipi_dsi_msg { + u8 channel; + u8 type; + u16 flags; + + size_t tx_len; + const void *tx_buf; + + size_t rx_len; + void *rx_buf; +}; + +/** + * struct mipi_dsi_host_ops - DSI bus operations + * @attach: attach DSI device to DSI host + * @detach: detach DSI device from DSI host + * @transfer: transmit a DSI packet + * + * DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg + * structures. This structure contains information about the type of packet + * being transmitted as well as the transmit and receive buffers. When an + * error is encountered during transmission, this function will return a + * negative error code. On success it shall return the number of bytes + * transmitted for write packets or the number of bytes received for read + * packets. + * + * Note that typically DSI packet transmission is atomic, so the .transfer() + * function will seldomly return anything other than the number of bytes + * contained in the transmit buffer on success. + */ +struct mipi_dsi_host_ops { + int (*attach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + int (*detach)(struct mipi_dsi_host *host, + struct mipi_dsi_device *dsi); + ssize_t (*transfer)(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg); +}; + +/** + * struct mipi_dsi_host - DSI host device + * @dev: driver model device node for this DSI host + * @ops: DSI host operations + */ +struct mipi_dsi_host { + //struct device *dev; + void *dev; + const struct mipi_dsi_host_ops *ops; +}; + +int mipi_dsi_host_register(struct mipi_dsi_host *host); + +#define BIT(pos) (1U << pos) + +/* DSI mode flags */ + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET BIT(9) +/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ +#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) + +enum mipi_dsi_pixel_format { + MIPI_DSI_FMT_RGB888, + MIPI_DSI_FMT_RGB666, + MIPI_DSI_FMT_RGB666_PACKED, + MIPI_DSI_FMT_RGB565, +}; + +struct mipi_dsi_master_ops { + int (*enslave)(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave); + int (*liberate)(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave); +}; + +/** + * struct mipi_dsi_device - DSI peripheral device + * @host: DSI host for this peripheral + * @dev: driver model device node for this peripheral + * @channel: virtual channel assigned to the peripheral + * @format: pixel format for video mode + * @lanes: number of active data lanes + * @mode_flags: DSI operation mode related flags + * @ops: callbacks for master/slave setup + * @master: master interface for dual-channel peripherals + * @slave: slave interface for dual-channel peripherals + * + * For dual-channel interfaces, the master interface can be identified by the + * fact that it's .slave field is set to non-NULL. The slave interface will + * have the .master field set to non-NULL. + */ +struct mipi_dsi_device { + struct mipi_dsi_host *host; + + unsigned int channel; + unsigned int lanes; + enum mipi_dsi_pixel_format format; + unsigned long mode_flags; + + const struct mipi_dsi_master_ops *ops; + struct mipi_dsi_device *master; + struct mipi_dsi_device *slave; +}; + +int mipi_dsi_attach(struct mipi_dsi_device *dsi); +int mipi_dsi_detach(struct mipi_dsi_device *dsi); +int mipi_dsi_enslave(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave); +int mipi_dsi_liberate(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave); + +/** + * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode + * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking + * information only + * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both + * V-Blanking and H-Blanking information + */ +enum mipi_dsi_dcs_tear_mode { + MIPI_DSI_DCS_TEAR_MODE_VBLANK, + MIPI_DSI_DCS_TEAR_MODE_VHBLANK, +}; + +#define MIPI_DSI_DCS_POWER_MODE_DISPLAY (1 << 2) +#define MIPI_DSI_DCS_POWER_MODE_NORMAL (1 << 3) +#define MIPI_DSI_DCS_POWER_MODE_SLEEP (1 << 4) +#define MIPI_DSI_DCS_POWER_MODE_PARTIAL (1 << 5) +#define MIPI_DSI_DCS_POWER_MODE_IDLE (1 << 6) + +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len); +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end); +int mipi_dsi_dcs_set_address_mode(struct mipi_dsi_device *dsi, + bool reverse_page_address, + bool reverse_col_address, + bool reverse_page_col_address, + bool refresh_from_bottom, + bool reverse_rgb, + bool latch_right_to_left, + bool flip_horizontal, + bool flip_vertical); +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode); +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format); + +#define MIPI_CAL_CTRL 0x00 +#define MIPI_CAL_CTRL_START (1 << 0) + +#define MIPI_CAL_AUTOCAL_CTRL 0x01 + +#define MIPI_CAL_STATUS 0x02 +#define MIPI_CAL_STATUS_DONE (1 << 16) +#define MIPI_CAL_STATUS_ACTIVE (1 << 0) + +#define MIPI_CAL_CONFIG_CSIA 0x05 +#define MIPI_CAL_CONFIG_CSIB 0x06 +#define MIPI_CAL_CONFIG_CSIC 0x07 +#define MIPI_CAL_CONFIG_CSID 0x08 +#define MIPI_CAL_CONFIG_CSIE 0x09 +#define MIPI_CAL_CONFIG_DSIA 0x0e +#define MIPI_CAL_CONFIG_DSIB 0x0f +#define MIPI_CAL_CONFIG_DSIC 0x10 +#define MIPI_CAL_CONFIG_DSID 0x11 + +#define MIPI_CAL_CONFIG_DSIAB_CLK 0x19 +#define MIPI_CAL_CONFIG_DSICD_CLK 0x1a +#define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b +#define MIPI_CAL_CONFIG_CSICD_CLK 0x1c +#define MIPI_CAL_CONFIG_CSIE_CLK 0x1d + +#define MIPI_CAL_CONFIG_SELECT (1 << 21) +#define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16) +#define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0) +#define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0) + +#define MIPI_CAL_BIAS_PAD_CFG0 0x16 +#define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1) +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0) + +#define MIPI_CAL_BIAS_PAD_CFG1 0x17 +#define MIPI_CAL_BIAS_PAD_CFG1_DEFAULT (0x20000) + +#define MIPI_CAL_BIAS_PAD_CFG2 0x18 +#define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1) + +struct calibration_regs { + unsigned long data; + unsigned long clk; +}; + +struct tegra_mipi_config { + int calibrate_clk_lane; + int num_pads; + const struct calibration_regs *regs; +}; + +struct tegra_mipi { + void *regs; +}; + +struct tegra_mipi_device { + struct tegra_mipi *mipi; + const struct tegra_mipi_config *config; + unsigned long pads; +}; + +struct tegra_mipi_device *tegra_mipi_request(struct tegra_mipi_device *device, + int device_index); +int tegra_mipi_calibrate(struct tegra_mipi_device *device); +#endif /* __MIPI_DSI_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/mmu_operations.h b/src/soc/nvidia/tegra132/include/soc/mmu_operations.h new file mode 100644 index 0000000000..8c82b26477 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/mmu_operations.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_MMU_OPERATIONS_H__ +#define __SOC_NVIDIA_TEGRA132_MMU_OPERATIONS_H__ + +void tegra132_mmu_init(void); + +/* Default ttb size of 1MiB */ +#define TTB_SIZE 0x1 + +#endif //__SOC_NVIDIA_TEGRA132_MMU_OPERATIONS_H__ diff --git a/src/soc/nvidia/tegra132/include/soc/padconfig.h b/src/soc/nvidia/tegra132/include/soc/padconfig.h new file mode 100644 index 0000000000..569fe4624c --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/padconfig.h @@ -0,0 +1,91 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_PAD_CFG_H +#define __SOC_NVIDIA_TEGRA132_PAD_CFG_H + +#include +#include + +struct pad_config { + uint8_t pinmux_flags; /* PU/PU, OD, INPUT, SFIO, etc */ + uint8_t gpio_index; /* bank, port, index */ + uint16_t pinmux_index:9; + uint16_t unused:1; + uint16_t sfio:1; + uint16_t gpio_out0:1; + uint16_t gpio_out1:1; + uint16_t pad_has_gpio:1; + uint16_t por_pullup:1; +}; + +#define PAD_CFG_GPIO_INPUT(ball_, pinmux_flgs_) \ + { \ + .pinmux_flags = pinmux_flgs_ | PINMUX_INPUT_ENABLE, \ + .gpio_index = PAD_TO_GPIO_##ball_, \ + .pinmux_index = PINMUX_##ball_##_INDEX, \ + .sfio = 0, \ + .pad_has_gpio = PAD_HAS_GPIO_##ball_, \ + } + +#define PAD_CFG_GPIO_OUT0(ball_, pinmux_flgs_) \ + { \ + .pinmux_flags = pinmux_flgs_, \ + .gpio_index = PAD_TO_GPIO_##ball_, \ + .pinmux_index = PINMUX_##ball_##_INDEX, \ + .sfio = 0, \ + .gpio_out0 = 1, \ + .pad_has_gpio = PAD_HAS_GPIO_##ball_, \ + } + +#define PAD_CFG_GPIO_OUT1(ball_, pinmux_flgs_) \ + { \ + .pinmux_flags = pinmux_flgs_, \ + .gpio_index = PAD_TO_GPIO_##ball_, \ + .pinmux_index = PINMUX_##ball_##_INDEX, \ + .sfio = 0, \ + .gpio_out1 = 1, \ + .pad_has_gpio = PAD_HAS_GPIO_##ball_, \ + } + +#define PAD_CFG_SFIO(ball_, pinmux_flgs_, sfio_) \ + { \ + .pinmux_flags = pinmux_flgs_ | \ + PINMUX_##ball_##_FUNC_##sfio_, \ + .gpio_index = PAD_TO_GPIO_##ball_, \ + .pinmux_index = PINMUX_##ball_##_INDEX, \ + .sfio = 1, \ + .pad_has_gpio = PAD_HAS_GPIO_##ball_, \ + } + +#define PAD_CFG_UNUSED(ball_) \ + { \ + .gpio_index = PAD_TO_GPIO_##ball_, \ + .pinmux_index = PINMUX_##ball_##_INDEX, \ + .unused = 1, \ + .pad_has_gpio = PAD_HAS_GPIO_##ball_, \ + } +/* + * Configure the pads associated with entry according to the configuration. + */ +void soc_configure_pads(const struct pad_config * const entries, size_t num); +/* I2C6 requires special init as its pad lives int the SOR/DPAUX block */ +void soc_configure_i2c6pad(void); + +#endif /* __SOC_NVIDIA_TEGRA132_PAD_CFG_H */ diff --git a/src/soc/nvidia/tegra132/include/soc/pinmux.h b/src/soc/nvidia/tegra132/include/soc/pinmux.h new file mode 100644 index 0000000000..f3bab1da01 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/pinmux.h @@ -0,0 +1,292 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_PINMUX_H__ +#define __SOC_NVIDIA_TEGRA132_PINMUX_H__ + +#include +#include +#include + +/* GPIO index constants. */ + +#define GPIO_PORT_CONSTANTS(port) \ + GPIO_##port##0_INDEX, GPIO_##port##1_INDEX, GPIO_##port##2_INDEX, \ + GPIO_##port##3_INDEX, GPIO_##port##4_INDEX, GPIO_##port##5_INDEX, \ + GPIO_##port##6_INDEX, GPIO_##port##7_INDEX + +enum { + GPIO_PORT_CONSTANTS(A), + GPIO_PORT_CONSTANTS(B), + GPIO_PORT_CONSTANTS(C), + GPIO_PORT_CONSTANTS(D), + GPIO_PORT_CONSTANTS(E), + GPIO_PORT_CONSTANTS(F), + GPIO_PORT_CONSTANTS(G), + GPIO_PORT_CONSTANTS(H), + GPIO_PORT_CONSTANTS(I), + GPIO_PORT_CONSTANTS(J), + GPIO_PORT_CONSTANTS(K), + GPIO_PORT_CONSTANTS(L), + GPIO_PORT_CONSTANTS(M), + GPIO_PORT_CONSTANTS(N), + GPIO_PORT_CONSTANTS(O), + GPIO_PORT_CONSTANTS(P), + GPIO_PORT_CONSTANTS(Q), + GPIO_PORT_CONSTANTS(R), + GPIO_PORT_CONSTANTS(S), + GPIO_PORT_CONSTANTS(T), + GPIO_PORT_CONSTANTS(U), + GPIO_PORT_CONSTANTS(V), + GPIO_PORT_CONSTANTS(W), + GPIO_PORT_CONSTANTS(X), + GPIO_PORT_CONSTANTS(Y), + GPIO_PORT_CONSTANTS(Z), + GPIO_PORT_CONSTANTS(AA), + GPIO_PORT_CONSTANTS(BB), + GPIO_PORT_CONSTANTS(CC), + GPIO_PORT_CONSTANTS(DD), + GPIO_PORT_CONSTANTS(EE), + GPIO_PORT_CONSTANTS(FF), + GPIO_NONE_INDEX = 0, +}; + +#define PINMUX_CONSTANTS_GPIO(name, gpio) \ + PINMUX_GPIO_##gpio = PINMUX_##name##_INDEX + +#define PINMUX_CONSTANTS(index, name, por_pu, gpio, has_gpio, \ + func0, func1, func2, func3) \ + PINMUX_##name##_INDEX = index, \ + PINMUX_##name##_FUNC_##func0 = 0, \ + PINMUX_##name##_FUNC_##func1 = 1, \ + PINMUX_##name##_FUNC_##func2 = 2, \ + PINMUX_##name##_FUNC_##func3 = 3, \ + PAD_TO_GPIO_##name = GPIO_##gpio##_INDEX, \ + PAD_HAS_GPIO_##name = has_gpio, \ + PAD_POR_PU_##name = por_pu + +#define PAD_GPIO(index, name, por_pu, gpio, func0, func1, func2, func3) \ + PINMUX_CONSTANTS(index, name, por_pu, gpio, 1, \ + func0, func1, func2, func3), \ + PINMUX_CONSTANTS_GPIO(name, gpio) + +#define PAD_NO_GPIO(index, name, por_pu, func0, func1, func2, func3) \ + PINMUX_CONSTANTS(index, name, por_pu, NONE, 0, \ + func0, func1, func2, func3) + +enum { + /* Power-on-reset pull states. */ + POR_PU = 1, + POR_PD = 0, + POR_NP = 0, + + PAD_GPIO(0, ULPI_DATA0, POR_PU, O1, SPI3, HSI, UA3, ULPI), + PAD_GPIO(1, ULPI_DATA1, POR_PU, O2, SPI3, HSI, UA3, ULPI), + PAD_GPIO(2, ULPI_DATA2, POR_PU, O3, SPI3, HSI, UA3, ULPI), + PAD_GPIO(3, ULPI_DATA3, POR_PU, O4, SPI3, HSI, UA3, ULPI), + PAD_GPIO(4, ULPI_DATA4, POR_PU, O5, SPI2, HSI, UA3, ULPI), + PAD_GPIO(5, ULPI_DATA5, POR_PU, O6, SPI2, HSI, UA3, ULPI), + PAD_GPIO(6, ULPI_DATA6, POR_PU, O7, SPI2, HSI, UA3, ULPI), + PAD_GPIO(7, ULPI_DATA7, POR_PU, O0, SPI2, HSI, UA3, ULPI), + PAD_GPIO(8, ULPI_CLK, POR_NP, Y0, SPI1, SPI5, UD3, ULPI), + PAD_GPIO(9, ULPI_DIR, POR_NP, Y1, SPI1, SPI5, UD3, ULPI), + PAD_GPIO(10, ULPI_NXT, POR_NP, Y2, SPI1, SPI5, UD3, ULPI), + PAD_GPIO(11, ULPI_STP, POR_NP, Y3, SPI1, SPI5, UD3, ULPI), + PAD_GPIO(12, DAP3_FS, POR_PD, P0, I2S2, SPI5, DCA, DCB), + PAD_GPIO(13, DAP3_DIN, POR_PD, P1, I2S2, SPI5, DCA, DCB), + PAD_GPIO(14, DAP3_DOUT, POR_PD, P2, I2S2, SPI5, DCA, RES3), + PAD_GPIO(15, DAP3_SCLK, POR_PD, P3, I2S2, SPI5, RES2, DCB), + PAD_GPIO(16, GPIO_PV0, POR_NP, V0, RES0, RES1, RES2, RES3), + PAD_GPIO(17, GPIO_PV1, POR_NP, V1, RES0, RES1, RES2, RES3), + PAD_GPIO(18, SDMMC1_CLK, POR_PD, Z0, SDMMC1, CLK12M, RES2, RES3), + PAD_GPIO(19, SDMMC1_CMD, POR_PU, Z1, SDMMC1, SPDIF, SPI4, UA3), + PAD_GPIO(20, SDMMC1_DAT3, POR_PU, Y4, SDMMC1, SPDIF, SPI4, UA3), + PAD_GPIO(21, SDMMC1_DAT2, POR_PU, Y5, SDMMC1, PWM0, SPI4, UA3), + PAD_GPIO(22, SDMMC1_DAT1, POR_PU, Y6, SDMMC1, PWM1, SPI4, UA3), + PAD_GPIO(23, SDMMC1_DAT0, POR_PU, Y7, SDMMC1, RES1, SPI4, UA3), + PAD_GPIO(26, CLK2_OUT, POR_PD, W5, EXTPERIPH2, RES1, RES2, RES3), + PAD_GPIO(27, CLK2_REQ, POR_NP, CC5, DAP, RES1, RES2, RES3), + PAD_GPIO(68, HDMI_INT, POR_PD, N7, RES0, RES1, RES2, RES3), + PAD_GPIO(69, DDC_SCL, POR_NP, V4, I2C4, RES1, RES2, RES3), + PAD_GPIO(70, DDC_SDA, POR_NP, V5, I2C4, RES1, RES2, RES3), + PAD_GPIO(89, UART2_RXD, POR_PU, C3, IR3, SPDIF, UA3, SPI4), + PAD_GPIO(90, UART2_TXD, POR_PU, C2, IR3, SPDIF, UA3, SPI4), + PAD_GPIO(91, UART2_RTS_N, POR_PU, J6, UA3, UB3, NOR, SPI4), + PAD_GPIO(92, UART2_CTS_N, POR_PU, J5, UA3, UB3, NOR, SPI4), + PAD_GPIO(93, UART3_TXD, POR_PU, W6, UC3, RES1, NOR, SPI4), + PAD_GPIO(94, UART3_RXD, POR_PU, W7, UC3, RES1, NOR, SPI4), + PAD_GPIO(95, UART3_CTS_N, POR_PU, A1, UC3, SDMMC1, DTV, NOR), + PAD_GPIO(96, UART3_RTS_N, POR_PU, C0, UC3, PWM0, DTV, NOR), + PAD_GPIO(97, GPIO_PU0, POR_NP, U0, OWR, UA3, NOR, RES3), + PAD_GPIO(98, GPIO_PU1, POR_NP, U1, RES0, UA3, NOR, RES3), + PAD_GPIO(99, GPIO_PU2, POR_NP, U2, RES0, UA3, NOR, RES3), + PAD_GPIO(100, GPIO_PU3, POR_NP, U3, PWM0, UA3, NOR, DCB), + PAD_GPIO(101, GPIO_PU4, POR_NP, U4, PWM1, UA3, NOR, DCB), + PAD_GPIO(102, GPIO_PU5, POR_NP, U5, PWM2, UA3, NOR, DCB), + PAD_GPIO(103, GPIO_PU6, POR_NP, U6, PWM3, UA3, RES2, NOR), + PAD_GPIO(104, GEN1_I2C_SDA, POR_NP, C5, I2C1, RES1, RES2, RES3), + PAD_GPIO(105, GEN1_I2C_SCL, POR_NP, C4, I2C1, RES1, RES2, RES3), + PAD_GPIO(106, DAP4_FS, POR_PD, P4, I2S3, NOR, DTV, RES3), + PAD_GPIO(107, DAP4_DIN, POR_PD, P5, I2S3, NOR, RES2, RES3), + PAD_GPIO(108, DAP4_DOUT, POR_PD, P6, I2S3, NOR, DTV, RES3), + PAD_GPIO(109, DAP4_SCLK, POR_PD, P7, I2S3, NOR, RES2, RES3), + PAD_GPIO(110, CLK3_OUT, POR_NP, EE0, EXTPERIPH3, RES1, RES2, RES3), + PAD_GPIO(111, CLK3_REQ, POR_NP, EE1, DEV3, RES1, RES2, RES3), + PAD_GPIO(112, GPIO_PC7, POR_PU, C7, RES0, RES1, NOR_WP_N, NOR_INT1), + PAD_GPIO(113, GPIO_PI5, POR_PU, I5, SDMMC2, RES1, NOR, RES3), + PAD_GPIO(114, GPIO_PI7, POR_PU, I7, RES0, TRACE, NOR, DTV), + PAD_GPIO(115, GPIO_PK0, POR_PU, K0, RES0, SDMMC3, NOR, SOC_THERM), + PAD_GPIO(116, GPIO_PK1, POR_PD, K1, SDMMC2, TRACE, NOR, RES3), + PAD_GPIO(117, GPIO_PJ0, POR_PU, J0, RES0, RES1, NOR, USB), + PAD_GPIO(118, GPIO_PJ2, POR_PU, J2, RES0, RES1, NOR, SOC_THERM), + PAD_GPIO(119, GPIO_PK3, POR_PU, K3, SDMMC2, TRACE, NOR, CCLA), + PAD_GPIO(120, GPIO_PK4, POR_PU, K4, SDMMC2, RES1, NOR_AD22, NOR_INT1), + PAD_GPIO(121, GPIO_PK2, POR_PU, K2, RES0, RES1, NOR, RES3), + PAD_GPIO(122, GPIO_PI3, POR_PU, I3, RES0, RES1, NOR, SPI4), + PAD_GPIO(123, GPIO_PI6, POR_PU, I6, RES0, RES1, NOR, SDMMC2), + PAD_GPIO(124, GPIO_PG0, POR_NP, G0, RES0, RES1, NOR, RES3), + PAD_GPIO(125, GPIO_PG1, POR_NP, G1, RES0, RES1, NOR, RES3), + PAD_GPIO(126, GPIO_PG2, POR_NP, G2, RES0, TRACE, NOR, RES3), + PAD_GPIO(127, GPIO_PG3, POR_NP, G3, RES0, TRACE, NOR, RES3), + PAD_GPIO(128, GPIO_PG4, POR_NP, G4, RES0, TMDS, NOR, SPI4), + PAD_GPIO(129, GPIO_PG5, POR_NP, G5, RES0, RES1, NOR, SPI4), + PAD_GPIO(130, GPIO_PG6, POR_NP, G6, RES0, RES1, NOR, SPI4), + PAD_GPIO(131, GPIO_PG7, POR_NP, G7, RES0, RES1, NOR, SPI4), + PAD_GPIO(132, GPIO_PH0, POR_PD, H0, PWM0, TRACE, NOR, DTV), + PAD_GPIO(133, GPIO_PH1, POR_PD, H1, PWM1, TMDS, NOR, DCA), + PAD_GPIO(134, GPIO_PH2, POR_PD, H2, PWM2, TDMS, NOR, CLDVFS), + PAD_GPIO(135, GPIO_PH3, POR_PD, H3, PWM3, SPI4, NOR, CLDVFS), + PAD_GPIO(136, GPIO_PH4, POR_PU, H4, SDMMC2, RES1, NOR, RES3), + PAD_GPIO(137, GPIO_PH5, POR_PD, H5, SDMMC2, RES1, NOR, RES3), + PAD_GPIO(138, GPIO_PH6, POR_PU, H6, SDMMC2, TRACE, NOR, DTV), + PAD_GPIO(139, GPIO_PH7, POR_PU, H7, SDMMC2, TRACE, NOR, DTV), + PAD_GPIO(140, GPIO_PJ7, POR_NP, J7, UD3, RES1, NOR_AD16, NOR_INT2), + PAD_GPIO(141, GPIO_PB0, POR_NP, B0, UD3, RES1, NOR, RES3), + PAD_GPIO(142, GPIO_PB1, POR_NP, B1, UD3, RES1, NOR, RES3), + PAD_GPIO(143, GPIO_PK7, POR_NP, K7, UD3, RES1, NOR, RES3), + PAD_GPIO(144, GPIO_PI0, POR_PU, I0, RES0, RES1, NOR, RES3), + PAD_GPIO(145, GPIO_PI1, POR_PU, I1, RES0, RES1, NOR, RES3), + PAD_GPIO(146, GPIO_PI2, POR_PU, I2, SDMMC2, TRACE, NOR, RES3), + PAD_GPIO(147, GPIO_PI4, POR_PD, I4, SPI4, TRACE, NOR, DCA), + PAD_GPIO(148, GEN2_I2C_SCL, POR_NP, T5, I2C2, RES1, NOR, RES3), + PAD_GPIO(149, GEN2_I2C_SDA, POR_NP, T6, I2C2, RES1, NOR, RES3), + PAD_GPIO(150, SDMMC4_CLK, POR_PD, CC4, SDMMC4, RES1, NOR, RES3), + PAD_GPIO(151, SDMMC4_CMD, POR_PU, T7, SDMMC4, RES1, NOR, RES3), + PAD_GPIO(152, SDMMC4_DAT0, POR_PU, AA0, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(153, SDMMC4_DAT1, POR_PU, AA1, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(154, SDMMC4_DAT2, POR_PU, AA2, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(155, SDMMC4_DAT3, POR_PU, AA3, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(156, SDMMC4_DAT4, POR_PU, AA4, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(157, SDMMC4_DAT5, POR_PU, AA5, SDMMC4, SPI3, RES2, RES3), + PAD_GPIO(158, SDMMC4_DAT6, POR_PU, AA6, SDMMC4, SPI3, NOR, RES3), + PAD_GPIO(159, SDMMC4_DAT7, POR_PU, AA7, SDMMC4, RES1, NOR, RES3), + PAD_GPIO(161, CAM_MCLK, POR_PU, CC0, VIMCLK_PRI, VIMCLK_ALT1, + VIMCLK_ALT3, SDMMC2), + PAD_GPIO(162, GPIO_PCC1, POR_PU, CC1, I2S4, RES1, RES2, SDMMC2), + PAD_GPIO(163, GPIO_PBB0, POR_PD, BB0, VGP6, VIMCLK2_PRI, SDMMC2, VIMCLK2_ALT3), + PAD_GPIO(164, CAM_I2C_SCL, POR_NP, BB1, VGP1, I2C3, RES2, SDMMC2), + PAD_GPIO(165, CAM_I2C_SDA, POR_NP, BB2, VGP2, I2C3, RES2, SDMMC2), + PAD_GPIO(166, GPIO_PBB3, POR_PD, BB3, VGP3, DCA, DCB, SDMMC2), + PAD_GPIO(167, GPIO_PBB4, POR_PD, BB4, VGP4, DCA, DCB, SDMMC2), + PAD_GPIO(168, GPIO_PBB5, POR_PD, BB5, VGP5, DCA, RES2, SDMMC2), + PAD_GPIO(169, GPIO_PBB6, POR_PD, BB6, I2S4, RES1, DCB, SDMMC2), + PAD_GPIO(170, GPIO_PBB7, POR_PD, BB7, I2S4, RES1, RES2, SDMMC2), + PAD_GPIO(171, GPIO_PCC2, POR_PU, CC2, I2S4, RES1, SDMMC3, SDMMC2), + PAD_NO_GPIO(172, JTAG_RTCK, POR_PU, RTCK, RES1, RES2, RES3), + PAD_GPIO(173, PWR_I2C_SCL, POR_NP, Z6, I2CPMU, RES1, RES2, RES3), + PAD_GPIO(174, PWR_I2C_SDA, POR_NP, Z7, I2CPMU, RES1, RES2, RES3), + PAD_GPIO(175, KB_ROW0, POR_PD, R0, RES0, RES1, RES2, RES3), + PAD_GPIO(176, KB_ROW1, POR_PD, R1, RES0, RES1, RES2, RES3), + PAD_GPIO(177, KB_ROW2, POR_PD, R2, RES0, RES1, RES2, RES3), + PAD_GPIO(178, KB_ROW3, POR_NP, R3, RES0, DCA, SYS_CLK, DCB), + PAD_GPIO(179, KB_ROW4, POR_PD, R4, RES0, DCA, RES2, DCB), + PAD_GPIO(180, KB_ROW5, POR_PD, R5, RES0, DCA, RES2, DCB), + PAD_GPIO(181, KB_ROW6, POR_PD, R6, RES0, DCA_LSC0, DCA_LSPII, DCB), + PAD_GPIO(182, KB_ROW7, POR_PD, R7, RES0, RES1, CLDVFS, UA3), + PAD_GPIO(183, KB_ROW8, POR_PD, S0, RES0, RES1, CLDVFS, UA3), + PAD_GPIO(184, KB_ROW9, POR_PD, S1, RES0, RES1, RES2, UA3), + PAD_GPIO(185, KB_ROW10, POR_PD, S2, RES0, RES1, RES2, UA3), + PAD_GPIO(186, KB_ROW11, POR_PD, S3, RES0, RES1, RES2, IR3), + PAD_GPIO(187, KB_ROW12, POR_PD, S4, RES0, RES1, RES2, IR3), + PAD_GPIO(188, KB_ROW13, POR_PD, S5, RES0, RES1, SPI2, RES3), + PAD_GPIO(189, KB_ROW14, POR_PD, S6, RES0, RES1, SPI2, RES3), + PAD_GPIO(190, KB_ROW15, POR_PD, S7, RES0, SOC_THERM, RES2, RES3), + PAD_GPIO(191, KB_COL0, POR_PU, Q0, RES0, RES1, SPI2, RES3), + PAD_GPIO(192, KB_COL1, POR_PU, Q1, RES0, RES1, SPI2, RES3), + PAD_GPIO(193, KB_COL2, POR_PU, Q2, RES0, RES1, SPI2, RES3), + PAD_GPIO(194, KB_COL3, POR_PU, Q3, RES0, DCA, PWM2, UA3), + PAD_GPIO(195, KB_COL4, POR_PU, Q4, RES0, OWR, SDMMC3, UA3), + PAD_GPIO(196, KB_COL5, POR_PU, Q5, RES0, RES1, SDMMC3, RES3), + PAD_GPIO(197, KB_COL6, POR_PU, Q6, RES0, RES1, SPI2, UD3), + PAD_GPIO(198, KB_COL7, POR_PU, Q7, RES0, RES1, SPI2, UD3), + PAD_GPIO(199, CLK_32K_OUT, POR_PD, A0, BLINK, SOC_THERM, RES2, RES3), + PAD_NO_GPIO(201, CORE_PWR_REQ, POR_NP, PWRON, RES1, RES2, RES3), + PAD_NO_GPIO(202, CPU_PWR_REQ, POR_NP, CPU, RES1, RES2, RES3), + PAD_NO_GPIO(203, PWR_INT_N, POR_NP, PMICINTR, RES1, RES2, RES3), + PAD_NO_GPIO(204, CLK_32K_IN, POR_NP, CLK_32K_IN, RES1, RES2, RES3), + PAD_NO_GPIO(205, OWR, POR_NP, OWR, RES1, RES2, RES3), + PAD_GPIO(206, DAP1_FS, POR_PD, N0, I2S0, DAP1, NOR, RES3), + PAD_GPIO(207, DAP1_DIN, POR_PD, N1, I2S0, DAP1, NOR, RES3), + PAD_GPIO(208, DAP1_DOUT, POR_PD, N2, I2S0, DAP1, NOR, SATA), + PAD_GPIO(209, DAP1_SCLK, POR_PD, N3, I2S0, DAP1, NOR, RES3), + PAD_GPIO(210, DAP_MCLK1_REQ, POR_PD, EE2, DAP, DAP1, SATA, RES3), + PAD_GPIO(211, DAP_MCLK1, POR_PD, W4, EXTPERIPH1, DAP2, RES2, RES3), + PAD_GPIO(212, SPDIF_IN, POR_PU, K6, SPDIF, RES1, RES2, I2C3), + PAD_GPIO(213, SPDIF_OUT, POR_PU, K5, SPDIF, RES1, RES2, I2C3), + PAD_GPIO(214, DAP2_FS, POR_PD, A2, I2S1, DAP2, NOR, RES3), + PAD_GPIO(215, DAP2_DIN, POR_PD, A4, I2S1, DAP2, NOR, RES3), + PAD_GPIO(216, DAP2_DOUT, POR_PD, A5, I2S1, DAP2, NOR, RES3), + PAD_GPIO(217, DAP2_SCLK, POR_PD, A3, I2S1, SAP2, NOR, RES3), + PAD_GPIO(218, DVFS_PWM, POR_PD, X0, SPI6, CLDVFS, NOR, RES3), + PAD_GPIO(219, GPIO_X1_AUD, POR_PD, X1, SPI6, RES1, NOR, RES3), + PAD_GPIO(220, GPIO_X3_AUD, POR_PU, X3, SPI6, SPI1, NOR, RES3), + PAD_GPIO(221, DVFS_CLK, POR_PU, X2, SPI6, CLDVFS_CLK, NOR, RES3), + PAD_GPIO(222, GPIO_X4_AUD, POR_PD, X4, NOR, SPI1, SPI2, DAP2), + PAD_GPIO(223, GPIO_X5_AUD, POR_PU, X5, NOR, SPI1, SPI2, RES3), + PAD_GPIO(224, GPIO_X6_AUD, POR_PU, X6, SPI6, SPI1, SPI2, NOR), + PAD_GPIO(225, GPIO_X7_AUD, POR_PD, X7, RES0, SPI1, SPI2, RES3), + PAD_GPIO(228, SDMMC3_CLK, POR_PD, A6, SDMMC3, RES1, RES2, SPI3), + PAD_GPIO(229, SDMMC3_CMD, POR_PU, A7, SDMMC3, PWM3, UA3, SPI3), + PAD_GPIO(230, SDMMC3_DAT0, POR_PU, B7, SDMMC3, RES1, RES2, SPI3), + PAD_GPIO(231, SDMMC3_DAT1, POR_PU, B6, SDMMC3, PWM2, UA3, SPI3), + PAD_GPIO(232, SDMMC3_DAT2, POR_PU, B5, SDMMC3, PWM1, DCA, SPI3), + PAD_GPIO(233, SDMMC3_DAT3, POR_PU, B4, SDMMC3, PWM0, DCB, SPI3), + PAD_GPIO(239, PEX_L0_RST_N, POR_NP, DD1, PE0, RES1, RES2, RES3), + PAD_GPIO(240, PEX_L0_CLKREQ_N, POR_NP, DD2, PE0, RES1, RES2, RES3), + PAD_GPIO(241, PEX_WAKE_N, POR_NP, DD3, PE, RES1, RES2, RES3), + PAD_GPIO(243, PEX_L1_RST_N, POR_NP, DD5, PE1, RES1, RES2, RES3), + PAD_GPIO(244, PEX_L1_CLKREQ_N, POR_NP, DD6, PE1, RES1, RES2, RES3), + PAD_GPIO(248, HDMI_CEC, POR_NP, EE3, CEC, RES1, RES2, RES3), + PAD_GPIO(249, SDMMC1_WP_N, POR_PU, V3, SDMMC1, CLK12M, SPI4, UA3), + PAD_GPIO(250, SDMMC3_CD_N, POR_PU, V2, SDMMC3, OWR, RES2, RES3), + PAD_GPIO(251, GPIO_W2_AUD, POR_PU, W2, SPI6, RES1, SPI2, I2C1), + PAD_GPIO(252, GPIO_W3_AUD, POR_PU, W3, SPI6, SPI1, SPI2, I2C1), + PAD_GPIO(253, USB_VBUS_EN0, POR_NP, N4, USB, RES1, RES2, RES3), + PAD_GPIO(254, USB_VBUS_EN1, POR_NP, N5, USB, RES1, RES2, RES3), + PAD_GPIO(255, SDMMC3_CLK_LB_IN, POR_PD, EE5, SDMMC3, RES1, RES2, RES3), + PAD_GPIO(256, SDMMC3_CLK_LB_OUT, POR_NP, EE4, SDMMC3, RES1, RES2, RES3), + PAD_NO_GPIO(258, RESET_OUT_N, POR_NP, RES0, RES1, RES2, RESET), + PAD_GPIO(259, KB_ROW16, POR_PD, T0, RES0, RES1, RES2, UC3), + PAD_GPIO(260, KB_ROW17, POR_PD, T1, RES0, RES1, RES2, UC3), + PAD_GPIO(261, USB_VBUS_EN2, POR_NP, FF1, USB, RES1, RES2, RES3), + PAD_GPIO(262, GPIO_PFF2, POR_NP, FF2, SATA, RES1, RES2, RES3), + PAD_GPIO(268, DP_HPD, POR_NP, FF0, DP, RES1, RES2, RES3), +}; + +#endif /* __SOC_NVIDIA_TEGRA132_PINMUX_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/pmc.h b/src/soc/nvidia/tegra132/include/soc/pmc.h new file mode 100644 index 0000000000..119b3be54b --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/pmc.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2010 - 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TEGRA132_PMC_H_ +#define _TEGRA132_PMC_H_ + +#include + +enum { + POWER_PARTID_CRAIL = 0, + POWER_PARTID_TD = 1, + POWER_PARTID_VE = 2, + POWER_PARTID_VDE = 4, + POWER_PARTID_L2C = 5, + POWER_PARTID_MPE = 6, + POWER_PARTID_HEG = 7, + POWER_PARTID_CE1 = 9, + POWER_PARTID_CE2 = 10, + POWER_PARTID_CE3 = 11, + POWER_PARTID_CELP = 12, + POWER_PARTID_CE0 = 14, + POWER_PARTID_C0NC = 15, + POWER_PARTID_C1NC = 16, + POWER_PARTID_SOR = 17, + POWER_PARTID_DIS = 18, + POWER_PARTID_DISB = 19, + POWER_PARTID_XUSBA = 20, + POWER_PARTID_XUSBB = 21, + POWER_PARTID_XUSBC = 22 +}; + +struct tegra_pmc_regs { + u32 cntrl; + u32 sec_disable; + u32 pmc_swrst; + u32 wake_mask; + u32 wake_lvl; + u32 wake_status; + u32 sw_wake_status; + u32 dpd_pads_oride; + u32 dpd_sample; + u32 dpd_enable; + u32 pwrgate_timer_off; + u32 clamp_status; + u32 pwrgate_toggle; + u32 remove_clamping_cmd; + u32 pwrgate_status; + u32 pwrgood_timer; + u32 blink_timer; + u32 no_iopower; + u32 pwr_det; + u32 pwr_det_latch; + u32 scratch0; + u32 scratch1; + u32 scratch2; + u32 scratch3; + u32 scratch4; + u32 scratch5; + u32 scratch6; + u32 scratch7; + u32 scratch8; + u32 scratch9; + u32 scratch10; + u32 scratch11; + u32 scratch12; + u32 scratch13; + u32 scratch14; + u32 scratch15; + u32 scratch16; + u32 scratch17; + u32 scratch18; + u32 scratch19; + u32 odmdata; + u32 scratch21; + u32 scratch22; + u32 scratch23; + u32 secure_scratch0; + u32 secure_scratch1; + u32 secure_scratch2; + u32 secure_scratch3; + u32 secure_scratch4; + u32 secure_scratch5; + u32 cpupwrgood_timer; + u32 cpupwroff_timer; + u32 pg_mask; + u32 pg_mask_1; + u32 auto_wake_lvl; + u32 auto_wake_lvl_mask; + u32 wake_delay; + u32 pwr_det_val; + u32 ddr_pwr; + u32 usb_debounce_del; + u32 usb_a0; + u32 crypto_op; + u32 pllp_wb0_override; + u32 scratch24; + u32 scratch25; + u32 scratch26; + u32 scratch27; + u32 scratch28; + u32 scratch29; + u32 scratch30; + u32 scratch31; + u32 scratch32; + u32 scratch33; + u32 scratch34; + u32 scratch35; + u32 scratch36; + u32 scratch37; + u32 scratch38; + u32 scratch39; + u32 scratch40; + u32 scratch41; + u32 scratch42; + u32 bondout_mirror[3]; + u32 sys_33v_en; + u32 bondout_mirror_access; + u32 gate; + u32 wake2_mask; + u32 wake2_lvl; + u32 wake2_status; + u32 sw_wake2_status; + u32 auto_wake2_lvl_mask; + u32 pg_mask_2; + u32 pg_mask_ce1; + u32 pg_mask_ce2; + u32 pg_mask_ce3; + u32 pwrgate_timer_ce[7]; + u32 pcx_edpd_cntrl; + u32 osc_edpd_over; + u32 clk_out_cntrl; + u32 sata_pwrgt; + u32 sensor_ctrl; + u32 rst_status; + u32 io_dpd_req; + u32 io_dpd_status; + u32 io_dpd2_req; + u32 io_dpd2_status; + u32 sel_dpd_tim; + u32 vddp_sel; + u32 ddr_cfg; + u32 e_no_vttgen; + u8 _rsv0[4]; + u32 pllm_wb0_override_freq; + u32 test_pwrgate; + u32 pwrgate_timer_mult; + u32 dis_sel_dpd; + u32 utmip_uhsic_triggers; + u32 utmip_uhsic_saved_state; + u32 utmip_pad_cfg; + u32 utmip_term_pad_cfg; + u32 utmip_uhsic_sleep_cfg; + u32 utmip_uhsic_sleepwalk_cfg; + u32 utmip_sleepwalk_p[3]; + u32 uhsic_sleepwalk_p0; + u32 utmip_uhsic_status; + u32 utmip_uhsic_fake; + u32 bondout_mirror3[5 - 3]; + u32 secure_scratch6; + u32 secure_scratch7; + u32 scratch43; + u32 scratch44; + u32 scratch45; + u32 scratch46; + u32 scratch47; + u32 scratch48; + u32 scratch49; + u32 scratch50; + u32 scratch51; + u32 scratch52; + u32 scratch53; + u32 scratch54; + u32 scratch55; + u32 scratch0_eco; + u32 por_dpd_ctrl; + u32 scratch2_eco; + u32 utmip_uhsic_line_wakeup; + u32 utmip_bias_master_cntrl; + u32 utmip_master_config; + u32 td_pwrgate_inter_part_timer; + u32 utmip_uhsic2_triggers; + u32 utmip_uhsic2_saved_state; + u32 utmip_uhsic2_sleep_cfg; + u32 utmip_uhsic2_sleepwalk_cfg; + u32 uhsic2_sleepwalk_p1; + u32 utmip_uhsic2_status; + u32 utmip_uhsic2_fake; + u32 utmip_uhsic2_line_wakeup; + u32 utmip_master2_config; + u32 utmip_uhsic_rpd_cfg; + u32 pg_mask_ce0; + u32 pg_mask3[5 - 3]; + u32 pllm_wb0_override2; + u32 tsc_mult; + u32 cpu_vsense_override; + u32 glb_amap_cfg; + u32 sticky_bits; + u32 sec_disable2; + u32 weak_bias; + u32 reg_short; + u32 pg_mask_andor; + u8 _rsv1[0x2c]; + u32 secure_scratch8; + u32 secure_scratch9; + u32 secure_scratch10; + u32 secure_scratch11; + u32 secure_scratch12; + u32 secure_scratch13; + u32 secure_scratch14; + u32 secure_scratch15; + u32 secure_scratch16; + u32 secure_scratch17; + u32 secure_scratch18; + u32 secure_scratch19; + u32 secure_scratch20; + u32 secure_scratch21; + u32 secure_scratch22; + u32 secure_scratch23; + u32 secure_scratch24; + u32 secure_scratch25; + u32 secure_scratch26; + u32 secure_scratch27; + u32 secure_scratch28; + u32 secure_scratch29; + u32 secure_scratch30; + u32 secure_scratch31; + u32 secure_scratch32; + u32 secure_scratch33; + u32 secure_scratch34; + u32 secure_scratch35; + u8 _rsv2[0xd0]; + u32 cntrl2; + u8 _rsv3[0x18]; + u32 io_dpd3_req; + u32 io_dqd3_status; + u32 strapping_opt_a; + u8 _rsv4[0x198]; + u32 scratch56; + u32 scratch57; + u32 scratch58; + u32 scratch59; + u32 scratch60; + u32 scratch61; + u32 scratch62; + u32 scratch63; + u32 scratch64; + u32 scratch65; + u32 scratch66; + u32 scratch67; + u32 scratch68; + u32 scratch69; + u32 scratch70; + u32 scratch71; + u32 scratch72; + u32 scratch73; + u32 scratch74; + u32 scratch75; + u32 scratch76; + u32 scratch77; + u32 scratch78; + u32 scratch79; + u32 scratch80; + u32 scratch81; + u32 scratch82; + u32 scratch83; + u32 scratch84; + u32 scratch85; + u32 scratch86; + u32 scratch87; + u32 scratch88; + u32 scratch89; + u32 scratch90; + u32 scratch91; + u32 scratch92; + u32 scratch93; + u32 scratch94; + u32 scratch95; + u32 scratch96; + u32 scratch97; + u32 scratch98; + u32 scratch99; + u32 scratch100; + u32 scratch101; + u32 scratch102; + u32 scratch103; + u32 scratch104; + u32 scratch105; + u32 scratch106; + u32 scratch107; + u32 scratch108; + u32 scratch109; + u32 scratch110; + u32 scratch111; + u32 scratch112; + u32 scratch113; + u32 scratch114; + u32 scratch115; + u32 scratch116; + u32 scratch117; + u32 scratch118; + u32 scratch119; +}; + +check_member(tegra_pmc_regs, scratch119, 0x6fc); + +enum { + PMC_RST_STATUS_SOURCE_MASK = 0x7, + PMC_RST_STATUS_SOURCE_POR = 0x0, + PMC_RST_STATUS_SOURCE_WATCHDOG = 0x1, + PMC_RST_STATUS_SOURCE_SENSOR = 0x2, + PMC_RST_STATUS_SOURCE_SW_MAIN = 0x3, + PMC_RST_STATUS_SOURCE_LP0 = 0x4, + PMC_RST_STATUS_NUM_SOURCES = 0x5, +}; + +enum { + PMC_PWRGATE_TOGGLE_PARTID_MASK = 0x1f, + PMC_PWRGATE_TOGGLE_PARTID_SHIFT = 0, + PMC_PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +enum { + PMC_CNTRL_KBC_CLK_DIS = 0x1 << 0, + PMC_CNTRL_RTC_CLK_DIS = 0x1 << 1, + PMC_CNTRL_RTC_RST = 0x1 << 2, + PMC_CNTRL_KBC_RST = 0x1 << 3, + PMC_CNTRL_MAIN_RST = 0x1 << 4, + PMC_CNTRL_LATCHWAKE_EN = 0x1 << 5, + PMC_CNTRL_GLITCHDET_DIS = 0x1 << 6, + PMC_CNTRL_BLINK_EN = 0x1 << 7, + PMC_CNTRL_PWRREQ_POLARITY = 0x1 << 8, + PMC_CNTRL_PWRREQ_OE = 0x1 << 9, + PMC_CNTRL_SYSCLK_POLARITY = 0x1 << 10, + PMC_CNTRL_SYSCLK_OE = 0x1 << 11, + PMC_CNTRL_PWRGATE_DIS = 0x1 << 12, + PMC_CNTRL_AOINIT = 0x1 << 13, + PMC_CNTRL_SIDE_EFFECT_LP0 = 0x1 << 14, + PMC_CNTRL_CPUPWRREQ_POLARITY = 0x1 << 15, + PMC_CNTRL_CPUPWRREQ_OE = 0x1 << 16, + PMC_CNTRL_INTR_POLARITY = 0x1 << 17, + PMC_CNTRL_FUSE_OVERRIDE = 0x1 << 18, + PMC_CNTRL_CPUPWRGOOD_EN = 0x1 << 19, + PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT = 20, + PMC_CNTRL_CPUPWRGOOD_SEL_MASK = + 0x3 << PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT +}; + +enum { + PMC_DDR_PWR_EMMC_MASK = 1 << 1, + PMC_DDR_PWR_VAL_MASK = 1 << 0, +}; + +enum { + PMC_DDR_CFG_PKG_MASK = 1 << 0, + PMC_DDR_CFG_IF_MASK = 1 << 1, + PMC_DDR_CFG_XM0_RESET_TRI_MASK = 1 << 12, + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK = 1 << 13, +}; + +enum { + PMC_NO_IOPOWER_MEM_MASK = 1 << 7, + PMC_NO_IOPOWER_MEM_COMP_MASK = 1 << 16, +}; + +enum { + PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK = 1 << 0, + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK = 1 << 1, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK = 1 << 31, +}; + +enum { + PMC_CNTRL2_HOLD_CKE_LOW_EN = 0x1 << 12 +}; + +enum { + PMC_OSC_EDPD_OVER_XOFS_SHIFT = 1, + PMC_OSC_EDPD_OVER_XOFS_MASK = + 0x3f << PMC_OSC_EDPD_OVER_XOFS_SHIFT +}; + +enum { + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT = 4, + PMC_STRAPPING_OPT_A_RAM_CODE_MASK = + 0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT, +}; + +#endif /* _TEGRA132_PMC_H_ */ diff --git a/src/soc/nvidia/tegra132/include/soc/power.h b/src/soc/nvidia/tegra132/include/soc/power.h new file mode 100644 index 0000000000..d42116eb75 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/power.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_POWER_H__ +#define __SOC_NVIDIA_TEGRA132_POWER_H__ + +#include + +void power_ungate_partition(uint32_t id); + +uint8_t pmc_rst_status(void); +void pmc_print_rst_status(void); + +#endif /* __SOC_NVIDIA_TEGRA132_POWER_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/romstage.h b/src/soc/nvidia/tegra132/include/soc/romstage.h new file mode 100644 index 0000000000..14358d8d58 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/romstage.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SOC_ROMSTAGE_H__ +#define __SOC_NVIDIA_TEGRA132_SOC_ROMSTAGE_H__ + +void romstage(void); +void romstage_mainboard_init(void); + +void mainboard_configure_pmc(void); +void mainboard_enable_vdd_cpu(void); + +#endif /* __SOC_NVIDIA_TEGRA132_SOC_ROMSTAGE_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/sdram.h b/src/soc/nvidia/tegra132/include/soc/sdram.h new file mode 100644 index 0000000000..1e6e70de8c --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/sdram.h @@ -0,0 +1,31 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SDRAM_H__ +#define __SOC_NVIDIA_TEGRA132_SDRAM_H__ + +#include + +uint32_t sdram_get_ram_code(void); +void sdram_init(const struct sdram_params *param); + +/* Save params to PMC scratch registers for use by BootROM on LP0 resume. */ +void sdram_lp0_save_params(const struct sdram_params *sdram); + +#endif /* __SOC_NVIDIA_TEGRA132_SDRAM_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/sdram_configs.h b/src/soc/nvidia/tegra132/include/soc/sdram_configs.h new file mode 100644 index 0000000000..38368fb69b --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/sdram_configs.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SDRAM_CONFIGS_H__ +#define __SOC_NVIDIA_TEGRA132_SDRAM_CONFIGS_H__ + +#include + +/* Loads SDRAM configurations for current system. */ +const struct sdram_params *get_sdram_config(void); + +#endif /* __SOC_NVIDIA_TEGRA132_SDRAM_CONFIGS_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/sdram_param.h b/src/soc/nvidia/tegra132/include/soc/sdram_param.h new file mode 100644 index 0000000000..7688930c9a --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/sdram_param.h @@ -0,0 +1,821 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. The field names are in camel case to ease + * directly converting BCT config files (*.cfg) into C structure. + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SDRAM_PARAM_H__ +#define __SOC_NVIDIA_TEGRA132_SDRAM_PARAM_H__ + +#include +#include + +enum { + /* Specifies the memory type to be undefined */ + NvBootMemoryType_None = 0, + + /* Specifies the memory type to be DDR SDRAM */ + NvBootMemoryType_Ddr = 0, + + /* Specifies the memory type to be LPDDR SDRAM */ + NvBootMemoryType_LpDdr = 0, + + /* Specifies the memory type to be DDR2 SDRAM */ + NvBootMemoryType_Ddr2 = 0, + + /* Specifies the memory type to be LPDDR2 SDRAM */ + NvBootMemoryType_LpDdr2, + + /* Specifies the memory type to be DDR3 SDRAM */ + NvBootMemoryType_Ddr3, + + NvBootMemoryType_Num, + + /* Specifies an entry in the ram_code table that's not in use */ + NvBootMemoryType_Unused = 0X7FFFFFF, +}; + +enum { + BOOT_ROM_PATCH_CONTROL_ENABLE_MASK = 0x1 << 31, + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT = 0, + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK = 0x7FFFFFFF << 0, + BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS = 0x70000000, + + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK = 1 << 0, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params { + + /* Specifies the type of memory device */ + uint32_t MemoryType; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t PllMInputDivider; + /* Specifies the N value for PllM */ + uint32_t PllMFeedbackDivider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t PllMStableTime; + /* Specifies misc. control bits */ + uint32_t PllMSetupControl; + /* Enables the Div by 2 */ + uint32_t PllMSelectDiv2; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh45; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh90; + /* Powers down VCO output Level shifter */ + uint32_t PllMPDLshiftPh135; + /* Specifies value for Charge Pump Gain Control */ + uint32_t PllMKCP; + /* Specifies VCO gain */ + uint32_t PllMKVCO; + /* Spare BCT param */ + uint32_t EmcBctSpare0; + /* Spare BCT param */ + uint32_t EmcBctSpare1; + /* Spare BCT param */ + uint32_t EmcBctSpare2; + /* Spare BCT param */ + uint32_t EmcBctSpare3; + /* Spare BCT param */ + uint32_t EmcBctSpare4; + /* Spare BCT param */ + uint32_t EmcBctSpare5; + /* Spare BCT param */ + uint32_t EmcBctSpare6; + /* Spare BCT param */ + uint32_t EmcBctSpare7; + /* Spare BCT param */ + uint32_t EmcBctSpare8; + /* Spare BCT param */ + uint32_t EmcBctSpare9; + /* Spare BCT param */ + uint32_t EmcBctSpare10; + /* Spare BCT param */ + uint32_t EmcBctSpare11; + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t EmcClockSource; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t EmcAutoCalInterval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t EmcAutoCalConfig; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t EmcAutoCalConfig2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t EmcAutoCalConfig3; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t EmcAutoCalWait; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t EmcAdrCfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t EmcPinProgramWait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t EmcPinExtraWait; + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t EmcTimingControlWait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t EmcRc; + /* Specifies the value for EMC_RFC */ + uint32_t EmcRfc; + /* Specifies the value for EMC_RFC_SLR */ + uint32_t EmcRfcSlr; + /* Specifies the value for EMC_RAS */ + uint32_t EmcRas; + /* Specifies the value for EMC_RP */ + uint32_t EmcRp; + /* Specifies the value for EMC_R2R */ + uint32_t EmcR2r; + /* Specifies the value for EMC_W2W */ + uint32_t EmcW2w; + /* Specifies the value for EMC_R2W */ + uint32_t EmcR2w; + /* Specifies the value for EMC_W2R */ + uint32_t EmcW2r; + /* Specifies the value for EMC_R2P */ + uint32_t EmcR2p; + /* Specifies the value for EMC_W2P */ + uint32_t EmcW2p; + /* Specifies the value for EMC_RD_RCD */ + uint32_t EmcRdRcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t EmcWrRcd; + /* Specifies the value for EMC_RRD */ + uint32_t EmcRrd; + /* Specifies the value for EMC_REXT */ + uint32_t EmcRext; + /* Specifies the value for EMC_WEXT */ + uint32_t EmcWext; + /* Specifies the value for EMC_WDV */ + uint32_t EmcWdv; + /* Specifies the value for EMC_WDV_MASK */ + uint32_t EmcWdvMask; + /* Specifies the value for EMC_QUSE */ + uint32_t EmcQUse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t EmcQuseWidth; + /* Specifies the value for EMC_IBDLY */ + uint32_t EmcIbdly; + /* Specifies the value for EMC_EINPUT */ + uint32_t EmcEInput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t EmcEInputDuration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t EmcPutermExtra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t EmcPutermWidth; + /* Specifies the value for EMC_PUTERM_ADJ */ + uint32_t EmcPutermAdj; + /* Specifies the value for EMC_CDB_CNTL_1 */ + uint32_t EmcCdbCntl1; + /* Specifies the value for EMC_CDB_CNTL_2 */ + uint32_t EmcCdbCntl2; + /* Specifies the value for EMC_CDB_CNTL_3 */ + uint32_t EmcCdbCntl3; + /* Specifies the value for EMC_QRST */ + uint32_t EmcQRst; + /* Specifies the value for EMC_QSAFE */ + uint32_t EmcQSafe; + /* Specifies the value for EMC_RDV */ + uint32_t EmcRdv; + /* Specifies the value for EMC_RDV_MASK */ + uint32_t EmcRdvMask; + /* Specifies the value for EMC_QPOP */ + uint32_t EmcQpop; + /* Specifies the value for EMC_CTT */ + uint32_t EmcCtt; + /* Specifies the value for EMC_CTT_DURATION */ + uint32_t EmcCttDuration; + /* Specifies the value for EMC_REFRESH */ + uint32_t EmcRefresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t EmcBurstRefreshNum; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t EmcPreRefreshReqCnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t EmcPdEx2Wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t EmcPdEx2Rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t EmcPChg2Pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t EmcAct2Pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t EmcAr2Pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t EmcRw2Pden; + /* Specifies the value for EMC_TXSR */ + uint32_t EmcTxsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t EmcTxsrDll; + /* Specifies the value for EMC_TCKE */ + uint32_t EmcTcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t EmcTckesr; + /* Specifies the value for EMC_TPD */ + uint32_t EmcTpd; + /* Specifies the value for EMC_TFAW */ + uint32_t EmcTfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t EmcTrpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t EmcTClkStable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t EmcTClkStop; + /* Specifies the value for EMC_TREFBW */ + uint32_t EmcTRefBw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t EmcFbioCfg5; + /* Specifies the value for EMC_FBIO_CFG6 */ + uint32_t EmcFbioCfg6; + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t EmcFbioSpare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t EmcCfgRsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t EmcMrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t EmcEmrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t EmcEmrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t EmcEmrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t EmcMrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t EmcMrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t EmcMrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw4; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t EmcMrwExtra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t EmcWarmBootMrwExtra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t EmcWarmBootExtraModeRegWriteEnable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t EmcExtraModeRegWriteEnable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t EmcMrwResetCommand; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t EmcMrwResetNInitWait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t EmcMrsWaitCnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t EmcMrsWaitCnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t EmcCfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t EmcCfg2; + /* Specifies the pipe bypass controls */ + uint32_t EmcCfgPipe; + /* Specifies the value for EMC_DBG */ + uint32_t EmcDbg; + /* Specifies the value for EMC_CMDQ */ + uint32_t EmcCmdQ; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t EmcMc2EmcQ; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t EmcDynSelfRefControl; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t AhbArbitrationXbarCtrlMemInitDone; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t EmcCfgDigDll; + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t EmcCfgDigDllPeriod; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t EmcDevSelect; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t EmcSelDpdCtrl; + + /* Pads trimmer delays */ + + /* Specifies the value for EMC_DLL_XFORM_DQS0 */ + uint32_t EmcDllXformDqs0; + /* Specifies the value for EMC_DLL_XFORM_DQS1 */ + uint32_t EmcDllXformDqs1; + /* Specifies the value for EMC_DLL_XFORM_DQS2 */ + uint32_t EmcDllXformDqs2; + /* Specifies the value for EMC_DLL_XFORM_DQS3 */ + uint32_t EmcDllXformDqs3; + /* Specifies the value for EMC_DLL_XFORM_DQS4 */ + uint32_t EmcDllXformDqs4; + /* Specifies the value for EMC_DLL_XFORM_DQS5 */ + uint32_t EmcDllXformDqs5; + /* Specifies the value for EMC_DLL_XFORM_DQS6 */ + uint32_t EmcDllXformDqs6; + /* Specifies the value for EMC_DLL_XFORM_DQS7 */ + uint32_t EmcDllXformDqs7; + /* Specifies the value for EMC_DLL_XFORM_DQS8 */ + uint32_t EmcDllXformDqs8; + /* Specifies the value for EMC_DLL_XFORM_DQS9 */ + uint32_t EmcDllXformDqs9; + /* Specifies the value for EMC_DLL_XFORM_DQS10 */ + uint32_t EmcDllXformDqs10; + /* Specifies the value for EMC_DLL_XFORM_DQS11 */ + uint32_t EmcDllXformDqs11; + /* Specifies the value for EMC_DLL_XFORM_DQS12 */ + uint32_t EmcDllXformDqs12; + /* Specifies the value for EMC_DLL_XFORM_DQS13 */ + uint32_t EmcDllXformDqs13; + /* Specifies the value for EMC_DLL_XFORM_DQS14 */ + uint32_t EmcDllXformDqs14; + /* Specifies the value for EMC_DLL_XFORM_DQS15 */ + uint32_t EmcDllXformDqs15; + /* Specifies the value for EMC_DLL_XFORM_QUSE0 */ + uint32_t EmcDllXformQUse0; + /* Specifies the value for EMC_DLL_XFORM_QUSE1 */ + uint32_t EmcDllXformQUse1; + /* Specifies the value for EMC_DLL_XFORM_QUSE2 */ + uint32_t EmcDllXformQUse2; + /* Specifies the value for EMC_DLL_XFORM_QUSE3 */ + uint32_t EmcDllXformQUse3; + /* Specifies the value for EMC_DLL_XFORM_QUSE4 */ + uint32_t EmcDllXformQUse4; + /* Specifies the value for EMC_DLL_XFORM_QUSE5 */ + uint32_t EmcDllXformQUse5; + /* Specifies the value for EMC_DLL_XFORM_QUSE6 */ + uint32_t EmcDllXformQUse6; + /* Specifies the value for EMC_DLL_XFORM_QUSE7 */ + uint32_t EmcDllXformQUse7; + /* Specifies the value for EMC_DLL_XFORM_ADDR0 */ + uint32_t EmcDllXformAddr0; + /* Specifies the value for EMC_DLL_XFORM_ADDR1 */ + uint32_t EmcDllXformAddr1; + /* Specifies the value for EMC_DLL_XFORM_ADDR2 */ + uint32_t EmcDllXformAddr2; + /* Specifies the value for EMC_DLL_XFORM_ADDR3 */ + uint32_t EmcDllXformAddr3; + /* Specifies the value for EMC_DLL_XFORM_ADDR4 */ + uint32_t EmcDllXformAddr4; + /* Specifies the value for EMC_DLL_XFORM_ADDR5 */ + uint32_t EmcDllXformAddr5; + /* Specifies the value for EMC_DLL_XFORM_QUSE8 */ + uint32_t EmcDllXformQUse8; + /* Specifies the value for EMC_DLL_XFORM_QUSE9 */ + uint32_t EmcDllXformQUse9; + /* Specifies the value for EMC_DLL_XFORM_QUSE10 */ + uint32_t EmcDllXformQUse10; + /* Specifies the value for EMC_DLL_XFORM_QUSE11 */ + uint32_t EmcDllXformQUse11; + /* Specifies the value for EMC_DLL_XFORM_QUSE12 */ + uint32_t EmcDllXformQUse12; + /* Specifies the value for EMC_DLL_XFORM_QUSE13 */ + uint32_t EmcDllXformQUse13; + /* Specifies the value for EMC_DLL_XFORM_QUSE14 */ + uint32_t EmcDllXformQUse14; + /* Specifies the value for EMC_DLL_XFORM_QUSE15 */ + uint32_t EmcDllXformQUse15; + /* Specifies the value for EMC_DLI_TRIM_TXDQS0 */ + uint32_t EmcDliTrimTxDqs0; + /* Specifies the value for EMC_DLI_TRIM_TXDQS1 */ + uint32_t EmcDliTrimTxDqs1; + /* Specifies the value for EMC_DLI_TRIM_TXDQS2 */ + uint32_t EmcDliTrimTxDqs2; + /* Specifies the value for EMC_DLI_TRIM_TXDQS3 */ + uint32_t EmcDliTrimTxDqs3; + /* Specifies the value for EMC_DLI_TRIM_TXDQS4 */ + uint32_t EmcDliTrimTxDqs4; + /* Specifies the value for EMC_DLI_TRIM_TXDQS5 */ + uint32_t EmcDliTrimTxDqs5; + /* Specifies the value for EMC_DLI_TRIM_TXDQS6 */ + uint32_t EmcDliTrimTxDqs6; + /* Specifies the value for EMC_DLI_TRIM_TXDQS7 */ + uint32_t EmcDliTrimTxDqs7; + /* Specifies the value for EMC_DLI_TRIM_TXDQS8 */ + uint32_t EmcDliTrimTxDqs8; + /* Specifies the value for EMC_DLI_TRIM_TXDQS9 */ + uint32_t EmcDliTrimTxDqs9; + /* Specifies the value for EMC_DLI_TRIM_TXDQS10 */ + uint32_t EmcDliTrimTxDqs10; + /* Specifies the value for EMC_DLI_TRIM_TXDQS11 */ + uint32_t EmcDliTrimTxDqs11; + /* Specifies the value for EMC_DLI_TRIM_TXDQS12 */ + uint32_t EmcDliTrimTxDqs12; + /* Specifies the value for EMC_DLI_TRIM_TXDQS13 */ + uint32_t EmcDliTrimTxDqs13; + /* Specifies the value for EMC_DLI_TRIM_TXDQS14 */ + uint32_t EmcDliTrimTxDqs14; + /* Specifies the value for EMC_DLI_TRIM_TXDQS15 */ + uint32_t EmcDliTrimTxDqs15; + /* Specifies the value for EMC_DLL_XFORM_DQ0 */ + uint32_t EmcDllXformDq0; + /* Specifies the value for EMC_DLL_XFORM_DQ1 */ + uint32_t EmcDllXformDq1; + /* Specifies the value for EMC_DLL_XFORM_DQ2 */ + uint32_t EmcDllXformDq2; + /* Specifies the value for EMC_DLL_XFORM_DQ3 */ + uint32_t EmcDllXformDq3; + /* Specifies the value for EMC_DLL_XFORM_DQ4 */ + uint32_t EmcDllXformDq4; + /* Specifies the value for EMC_DLL_XFORM_DQ5 */ + uint32_t EmcDllXformDq5; + /* Specifies the value for EMC_DLL_XFORM_DQ6 */ + uint32_t EmcDllXformDq6; + /* Specifies the value for EMC_DLL_XFORM_DQ7 */ + uint32_t EmcDllXformDq7; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t WarmBootWait; + + /* Specifies the value for EMC_CTT_TERM_CTRL */ + uint32_t EmcCttTermCtrl; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtWrite; + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtRead; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t EmcZcalInterval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t EmcZcalWaitCnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t EmcZcalMrwCmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t EmcMrsResetDll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t EmcZcalInitDev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t EmcZcalInitDev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t EmcZcalInitWait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t EmcZcalWarmColdBootEnables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t EmcMrwLpddr2ZcalWarmBoot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t EmcZqCalDdr3WarmBoot; + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t EmcZcalWarmBootWait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t EmcMrsWarmBootEnable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t EmcMrsResetDllWait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t EmcMrsExtra; + /* Specifies the extra MRS command at warm boot */ + uint32_t EmcWarmBootMrsExtra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t EmcEmrsDdr2DllEnable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t EmcMrsDdr2DllReset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t EmcEmrsDdr2OcdCalib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t EmcDdr2Wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t EmcClkenOverride; + /* Specifies the value for MC_DIS_EXTRA_SNAP_LEVELS */ + uint32_t McDisExtraSnapLevels; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t EmcExtraRefreshNum; + /* Specifies the master override for all EMC clocks */ + uint32_t EmcClkenOverrideAllWarmBoot; + /* Specifies the master override for all MC clocks */ + uint32_t McClkenOverrideAllWarmBoot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t EmcCfgDigDllPeriodWarmBoot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t PmcVddpSel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t PmcVddpSelWait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t PmcDdrPwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t PmcDdrCfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3Req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3ReqWait; + /* Specifies the value for PMC_REG_SHORT */ + uint32_t PmcRegShort; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t PmcNoIoPower; + /* Specifies the wait time after programming PMC_POR_DPD_CTRL */ + uint32_t PmcPorDpdCtrlWait; + /* Specifies the value for EMC_XM2CMDPADCTRL */ + uint32_t EmcXm2CmdPadCtrl; + /* Specifies the value for EMC_XM2CMDPADCTRL2 */ + uint32_t EmcXm2CmdPadCtrl2; + /* Specifies the value for EMC_XM2CMDPADCTRL3 */ + uint32_t EmcXm2CmdPadCtrl3; + /* Specifies the value for EMC_XM2CMDPADCTRL4 */ + uint32_t EmcXm2CmdPadCtrl4; + /* Specifies the value for EMC_XM2CMDPADCTRL5 */ + uint32_t EmcXm2CmdPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL */ + uint32_t EmcXm2DqsPadCtrl; + /* Specifies the value for EMC_XM2DQSPADCTRL2 */ + uint32_t EmcXm2DqsPadCtrl2; + /* Specifies the value for EMC_XM2DQSPADCTRL3 */ + uint32_t EmcXm2DqsPadCtrl3; + /* Specifies the value for EMC_XM2DQSPADCTRL4 */ + uint32_t EmcXm2DqsPadCtrl4; + /* Specifies the value for EMC_XM2DQSPADCTRL5 */ + uint32_t EmcXm2DqsPadCtrl5; + /* Specifies the value for EMC_XM2DQSPADCTRL6 */ + uint32_t EmcXm2DqsPadCtrl6; + /* Specifies the value for EMC_XM2DQPADCTRL */ + uint32_t EmcXm2DqPadCtrl; + /* Specifies the value for EMC_XM2DQPADCTRL2 */ + uint32_t EmcXm2DqPadCtrl2; + /* Specifies the value for EMC_XM2DQPADCTRL3 */ + uint32_t EmcXm2DqPadCtrl3; + /* Specifies the value for EMC_XM2CLKPADCTRL */ + uint32_t EmcXm2ClkPadCtrl; + /* Specifies the value for EMC_XM2CLKPADCTRL2 */ + uint32_t EmcXm2ClkPadCtrl2; + /* Specifies the value for EMC_XM2COMPPADCTRL */ + uint32_t EmcXm2CompPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL */ + uint32_t EmcXm2VttGenPadCtrl; + /* Specifies the value for EMC_XM2VTTGENPADCTRL2 */ + uint32_t EmcXm2VttGenPadCtrl2; + /* Specifies the value for EMC_XM2VTTGENPADCTRL3 */ + uint32_t EmcXm2VttGenPadCtrl3; + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t EmcAcpdControl; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */ + uint32_t EmcSwizzleRank0ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t EmcSwizzleRank0Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t EmcSwizzleRank0Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t EmcSwizzleRank0Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t EmcSwizzleRank0Byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */ + uint32_t EmcSwizzleRank1ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t EmcSwizzleRank1Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t EmcSwizzleRank1Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t EmcSwizzleRank1Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t EmcSwizzleRank1Byte3; + + /* Specifies the value for EMC_DSR_VTTGEN_DRV */ + uint32_t EmcDsrVttgenDrv; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t EmcTxdsrvttgen; + /* Specifies the value for EMC_BGBIAS_CTL */ + uint32_t EmcBgbiasCtl0; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t McEmemAdrCfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t McEmemAdrCfgDev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t McEmemAdrCfgDev1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + uint32_t McEmemAdrCfgBankMask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t McEmemAdrCfgBankMask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t McEmemAdrCfgBankMask2; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG3 */ + uint32_t McEmemAdrCfgBankSwizzle3; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t McEmemCfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t McEmemArbCfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t McEmemArbOutstandingReq; + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t McEmemArbTimingRcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t McEmemArbTimingRp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t McEmemArbTimingRc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t McEmemArbTimingRas; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t McEmemArbTimingFaw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t McEmemArbTimingRrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t McEmemArbTimingRap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t McEmemArbTimingWap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t McEmemArbTimingR2R; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t McEmemArbTimingW2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t McEmemArbTimingR2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t McEmemArbTimingW2R; + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t McEmemArbDaTurns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t McEmemArbDaCovers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t McEmemArbMisc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t McEmemArbMisc1; + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t McEmemArbRing1Throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t McEmemArbOverride; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t McEmemArbOverride1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t McEmemArbRsv; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t McClkenOverride; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t McStatControl; + /* Specifies the value for MC_DISPLAY_SNAP_RING */ + uint32_t McDisplaySnapRing; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t McVideoProtectBom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t McVideoProtectBomAdrHi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t McVideoProtectSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t McVideoProtectVprOverride; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t McVideoProtectVprOverride1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t McVideoProtectGpuOverride0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t McVideoProtectGpuOverride1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t McSecCarveoutBom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t McSecCarveoutAdrHi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t McSecCarveoutSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL. + VIDEO_PROTECT_WRITE_ACCESS */ + uint32_t McVideoProtectWriteAccess; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL. + SEC_CARVEOUT_WRITE_ACCESS */ + uint32_t McSecCarveoutProtectWriteAccess; + + /* Specifies enable for CA training */ + uint32_t EmcCaTrainingEnable; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL1 */ + uint32_t EmcCaTrainingTimingCntl1; + /* Specifies the value for EMC_CA_TRAINING_TIMING_CNTRL2 */ + uint32_t EmcCaTrainingTimingCntl2; + /* Set if bit 6 select is greater than bit 7 select; uses aremc. + spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t SwizzleRankByteEncode; + /* Specifies enable and offset for patched boot rom write */ + uint32_t BootRomPatchControl; + /* Specifies data for patched boot rom write */ + uint32_t BootRomPatchData; + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t McMtsCarveoutBom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t McMtsCarveoutAdrHi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t McMtsCarveoutSizeMb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t McMtsCarveoutRegCtrl; + + /* End of generated code by warmboot_code_gen */ +}; + +check_member(sdram_params, McMtsCarveoutRegCtrl, 0x4d0); + +#endif /* __SOC_NVIDIA_TEGRA132_SDRAM_PARAM_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/spi.h b/src/soc/nvidia/tegra132/include/soc/spi.h new file mode 100644 index 0000000000..2fd9562599 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/spi.h @@ -0,0 +1,72 @@ +/* + * Copyright 2014 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __NVIDIA_TEGRA132_SPI_H__ +#define __NVIDIA_TEGRA132_SPI_H__ + +#include +#include +#include + +struct tegra_spi_regs { + u32 command1; /* 0x000: SPI_COMMAND1 */ + u32 command2; /* 0x004: SPI_COMMAND2 */ + u32 timing1; /* 0x008: SPI_CS_TIM1 */ + u32 timing2; /* 0x00c: SPI_CS_TIM2 */ + u32 trans_status; /* 0x010: SPI_TRANS_STATUS */ + u32 fifo_status; /* 0x014: SPI_FIFO_STATUS */ + u32 tx_data; /* 0x018: SPI_TX_DATA */ + u32 rx_data; /* 0x01c: SPI_RX_DATA */ + u32 dma_ctl; /* 0x020: SPI_DMA_CTL */ + u32 dma_blk; /* 0x024: SPI_DMA_BLK */ + u32 rsvd[56]; /* 0x028-0x107: reserved */ + u32 tx_fifo; /* 0x108: SPI_FIFO1 */ + u32 rsvd2[31]; /* 0x10c-0x187 reserved */ + u32 rx_fifo; /* 0x188: SPI_FIFO2 */ + u32 spare_ctl; /* 0x18c: SPI_SPARE_CTRL */ +} __attribute__((packed)); +check_member(tegra_spi_regs, spare_ctl, 0x18c); + +enum spi_xfer_mode { + XFER_MODE_NONE = 0, + XFER_MODE_PIO, + XFER_MODE_DMA, +}; + +struct tegra_spi_channel { + struct tegra_spi_regs *regs; + + /* static configuration */ + struct spi_slave slave; + unsigned int req_sel; + + int dual_mode; /* for x2 transfers with bit interleaving */ + + /* context (used internally) */ + u8 *in_buf, *out_buf; + struct apb_dma_channel *dma_out, *dma_in; + enum spi_xfer_mode xfer_mode; +}; + +struct cbfs_media; +int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size); + +struct tegra_spi_channel *tegra_spi_init(unsigned int bus); + +#endif /* __NVIDIA_TEGRA132_SPI_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/sysctr.h b/src/soc/nvidia/tegra132/include/soc/sysctr.h new file mode 100644 index 0000000000..ea9746ddf2 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/sysctr.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SYSCTR_H__ +#define __SOC_NVIDIA_TEGRA132_SYSCTR_H__ + +#include + +enum { + SYSCTR_CNTCR_EN = 1 << 0, + SYSCTR_CNTCR_HDBG = 1 << 1, + SYSCTR_CNTCR_FCREQ = 1 << 8 +}; + +struct sysctr_regs { + uint32_t cntcr; + uint32_t cntsr; + uint32_t cntcv0; + uint32_t cntcv1; + uint8_t _rsv0[0x10]; + uint32_t cntfid0; + uint32_t cntfid1; + uint8_t _rsv1[0xfa8]; + uint32_t counterid4; + uint32_t counterid5; + uint32_t counterid6; + uint32_t counterid7; + uint32_t counterid0; + uint32_t counterid1; + uint32_t counterid2; + uint32_t counterid3; + uint32_t counterid8; + uint32_t counterid9; + uint32_t counterid10; + uint32_t counterid11; +}; +check_member(sysctr_regs, counterid11, 0xffc); + +#endif /* __SOC_NVIDIA_TEGRA132_SYSCTR_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/tegra_dsi.h b/src/soc/nvidia/tegra132/include/soc/tegra_dsi.h new file mode 100644 index 0000000000..830257d7cc --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/tegra_dsi.h @@ -0,0 +1,219 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __TEGRA_DSI_H__ +#define __TEGRA_DSI_H__ + +#define DSI_INCR_SYNCPT 0x00 +#define DSI_INCR_SYNCPT_CONTROL 0x01 +#define DSI_INCR_SYNCPT_ERROR 0x02 +#define DSI_CTXSW 0x08 +#define DSI_RD_DATA 0x09 +#define DSI_WR_DATA 0x0a +#define DSI_POWER_CONTROL 0x0b +#define DSI_POWER_CONTROL_ENABLE (1 << 0) +#define DSI_INT_ENABLE 0x0c +#define DSI_INT_STATUS 0x0d +#define DSI_INT_MASK 0x0e +#define DSI_HOST_CONTROL 0x0f +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_STATUS_IDLE (1 << 10) +#define DSI_STATUS_UNDERFLOW (1 << 9) +#define DSI_STATUS_OVERFLOW (1 << 8) +#define DSI_INIT_SEQ_CONTROL 0x1a +#define DSI_INIT_SEQ_DATA_0 0x1b +#define DSI_INIT_SEQ_DATA_1 0x1c +#define DSI_INIT_SEQ_DATA_2 0x1d +#define DSI_INIT_SEQ_DATA_3 0x1e +#define DSI_INIT_SEQ_DATA_4 0x1f +#define DSI_INIT_SEQ_DATA_5 0x20 +#define DSI_INIT_SEQ_DATA_6 0x21 +#define DSI_INIT_SEQ_DATA_7 0x22 +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2a +#define DSI_PKT_SEQ_4_LO 0x2b +#define DSI_PKT_SEQ_4_HI 0x2c +#define DSI_PKT_SEQ_5_LO 0x2d +#define DSI_PKT_SEQ_5_HI 0x2e +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3c +#define DSI_PHY_TIMING_1 0x3d +#define DSI_PHY_TIMING_2 0x3e +#define DSI_BTA_TIMING 0x3f + +#define DSI_TIMING_FIELD(value, period, hwinc) \ + ((DIV_ROUND_CLOSEST(value, period) - (hwinc)) & 0xff) + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) +#define DSI_TO_TALLY 0x46 +#define DSI_TALLY_TA(x) (((x) & 0xff) << 16) +#define DSI_TALLY_LRX(x) (((x) & 0xff) << 8) +#define DSI_TALLY_HTX(x) (((x) & 0xff) << 0) +#define DSI_PAD_CONTROL_0 0x4b +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_PAD_CD_STATUS 0x4d +#define DSI_VIDEO_MODE_CONTROL 0x4e +#define DSI_PAD_CONTROL_1 0x4f +#define DSI_PAD_CONTROL_2 0x50 +#define DSI_PAD_OUT_CLK(x) (((x) & 0x7) << 0) +#define DSI_PAD_LP_DN(x) (((x) & 0x7) << 4) +#define DSI_PAD_LP_UP(x) (((x) & 0x7) << 8) +#define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12) +#define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16) +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_CONTROL_4 0x52 +#define DSI_GANGED_MODE_CONTROL 0x53 +#define DSI_GANGED_MODE_CONTROL_ENABLE (1 << 0) +#define DSI_GANGED_MODE_START 0x54 +#define DSI_GANGED_MODE_SIZE 0x55 +#define DSI_RAW_DATA_BYTE_COUNT 0x56 +#define DSI_ULTRA_LOW_POWER_CONTROL 0x57 +#define DSI_INIT_SEQ_DATA_8 0x58 +#define DSI_INIT_SEQ_DATA_9 0x59 +#define DSI_INIT_SEQ_DATA_10 0x5a +#define DSI_INIT_SEQ_DATA_11 0x5b +#define DSI_INIT_SEQ_DATA_12 0x5c +#define DSI_INIT_SEQ_DATA_13 0x5d +#define DSI_INIT_SEQ_DATA_14 0x5e +#define DSI_INIT_SEQ_DATA_15 0x5f + +#define PKT_ID0(id) ((((id) & 0x3f) << 3) | (1 << 9)) +#define PKT_LEN0(len) (((len) & 0x07) << 0) +#define PKT_ID1(id) ((((id) & 0x3f) << 13) | (1 << 19)) +#define PKT_LEN1(len) (((len) & 0x07) << 10) +#define PKT_ID2(id) ((((id) & 0x3f) << 23) | (1 << 29)) +#define PKT_LEN2(len) (((len) & 0x07) << 20) + +#define PKT_LP (1 << 30) +#define NUM_PKT_SEQ 12 + +#define APB_MISC_GP_MIPI_PAD_CTRL_0 (TEGRA_APB_MISC_GP_BASE + 0x20) +#define DSIB_MODE_SHIFT 1 +#define DSIB_MODE_CSI (0 << DSIB_MODE_SHIFT) +#define DSIB_MODE_DSI (1 << DSIB_MODE_SHIFT) + +/* + * pixel format as used in the DSI_CONTROL_FORMAT field + */ +enum tegra_dsi_format { + TEGRA_DSI_FORMAT_16P, + TEGRA_DSI_FORMAT_18NP, + TEGRA_DSI_FORMAT_18P, + TEGRA_DSI_FORMAT_24P, +}; + +enum dsi_dev { + DSI_A = 0, + DSI_B, + NUM_DSI, +}; + +struct panel_jdi; +struct tegra_mipi_device; +struct mipi_dsi_host; +struct mipi_dsi_msg; + +#define MAX_DSI_VIDEO_FIFO_DEPTH 96 +#define MAX_DSI_HOST_FIFO_DEPTH 64 + +struct tegra_dsi { + struct panel_jdi *panel; + //struct tegra_output output; + void *regs; + u8 channel; + unsigned long clk_rate; + + unsigned long flags; + enum mipi_dsi_pixel_format format; + unsigned int lanes; + + struct tegra_mipi_device *mipi; + struct mipi_dsi_host host; + bool enabled; + + unsigned int video_fifo_depth; + unsigned int host_fifo_depth; + + /* for ganged-mode support */ + unsigned int ganged_lanes; + struct tegra_dsi *slave; + int ganged_mode; + + struct tegra_dsi *master; +}; + +static inline unsigned long tegra_dsi_readl(struct tegra_dsi *dsi, + unsigned long reg) +{ + return readl(dsi->regs + (reg << 2)); +} + +static inline void tegra_dsi_writel(struct tegra_dsi *dsi, unsigned long value, + unsigned long reg) +{ + writel(value, dsi->regs + (reg << 2)); +} + +#endif /* __TEGRA_DSI_H__ */ diff --git a/src/soc/nvidia/tegra132/include/soc/verstage.h b/src/soc/nvidia/tegra132/include/soc/verstage.h new file mode 100644 index 0000000000..6901bc3497 --- /dev/null +++ b/src/soc/nvidia/tegra132/include/soc/verstage.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA132_SOC_VERSTAGE_H__ +#define __SOC_NVIDIA_TEGRA132_SOC_VERSTAGE_H__ + +void verstage_mainboard_init(void); + +#endif /* __SOC_NVIDIA_TEGRA132_SOC_VERSTAGE_H__ */ diff --git a/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.c b/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.c new file mode 100644 index 0000000000..45797b1cc5 --- /dev/null +++ b/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.c @@ -0,0 +1,213 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../chip.h" +#include +#include +#include +#include "panel-jdi-lpm102a188a.h" + +struct panel_jdi jdi_data[NUM_DSI]; + +int panel_jdi_prepare(struct panel_jdi *jdi) +{ + int ret; + u8 data; + + if (jdi->enabled) + return 0; + + ret = mipi_dsi_dcs_set_column_address(jdi->dsi, 0, + jdi->mode->xres / 2 - 1); // 2560/2 + if (ret < 0) + printk(BIOS_ERR, "failed to set column address: %d\n", ret); + + ret = mipi_dsi_dcs_set_column_address(jdi->dsi->slave, 0, + jdi->mode->xres / 2 - 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set column address: %d\n", ret); + + ret = mipi_dsi_dcs_set_page_address(jdi->dsi, 0, + jdi->mode->yres - 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set page address: %d\n", ret); + + ret = mipi_dsi_dcs_set_page_address(jdi->dsi->slave, 0, + jdi->mode->yres - 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set page address: %d\n", ret); + + ret = mipi_dsi_dcs_exit_sleep_mode(jdi->dsi); + if (ret < 0) + printk(BIOS_ERR, "failed to exit sleep mode: %d\n", ret); + + ret = mipi_dsi_dcs_exit_sleep_mode(jdi->dsi->slave); + if (ret < 0) + printk(BIOS_ERR, "failed to exit sleep mode: %d\n", ret); + + ret = mipi_dsi_dcs_set_tear_on(jdi->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret < 0) + printk(BIOS_ERR, "failed to set tear on: %d\n", ret); + + ret = mipi_dsi_dcs_set_tear_on(jdi->dsi->slave, + MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret < 0) + printk(BIOS_ERR, "failed to set tear on: %d\n", ret); + + ret = mipi_dsi_dcs_set_address_mode(jdi->dsi, false, false, false, + false, false, false, false, false); + if (ret < 0) + printk(BIOS_ERR, "failed to set address mode: %d\n", ret); + + ret = mipi_dsi_dcs_set_address_mode(jdi->dsi->slave, false, false, + false, false, false, false, false, false); + if (ret < 0) + printk(BIOS_ERR, "failed to set address mode: %d\n", ret); + + ret = mipi_dsi_dcs_set_pixel_format(jdi->dsi, 0x77); + if (ret < 0) + printk(BIOS_ERR, "failed to set pixel format: %d\n", ret); + + ret = mipi_dsi_dcs_set_pixel_format(jdi->dsi->slave, 0x77); + if (ret < 0) + printk(BIOS_ERR, "failed to set pixel format: %d\n", ret); + + data = 0xFF; + ret = mipi_dsi_dcs_write(jdi->dsi, 0x51, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x51: %d\n", ret); + + data = 0xFF; + ret = mipi_dsi_dcs_write(jdi->dsi->slave, 0x51, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x51: %d\n", ret); + + data = 0x24; + ret = mipi_dsi_dcs_write(jdi->dsi, 0x53, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x53: %d\n", ret); + + data = 0x24; + ret = mipi_dsi_dcs_write(jdi->dsi->slave, 0x53, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x53: %d\n", ret); + + data = 0x00; + ret = mipi_dsi_dcs_write(jdi->dsi, 0x55, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x55: %d\n", ret); + + data = 0x00; + ret = mipi_dsi_dcs_write(jdi->dsi->slave, 0x55, &data, 1); + if (ret < 0) + printk(BIOS_ERR, "failed to set 0x55: %d\n", ret); + + ret = mipi_dsi_dcs_set_display_on(jdi->dsi); + if (ret < 0) + printk(BIOS_ERR, "failed to set display on: %d\n", ret); + + ret = mipi_dsi_dcs_set_display_on(jdi->dsi->slave); + if (ret < 0) + printk(BIOS_ERR, "failed to set display on: %d\n", ret); + + jdi->enabled = true; + + return 0; +} + +static int panel_jdi_enslave(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave) +{ + int ret; + + ret = mipi_dsi_attach(master); + if (ret < 0) + return ret; + + return ret; +} + +static int panel_jdi_liberate(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave) +{ + int ret; + + ret = mipi_dsi_detach(master); + if (ret < 0) + return ret; + + return 0; +} + +static const struct mipi_dsi_master_ops panel_jdi_master_ops = { + .enslave = panel_jdi_enslave, + .liberate = panel_jdi_liberate, +}; + +struct panel_jdi *panel_jdi_dsi_probe(struct mipi_dsi_device *dsi) +{ + static int index = 0; + struct panel_jdi *jdi; + int ret; + + if (index >= NUM_DSI) + return (void *)-EPTR; + + jdi = &jdi_data[index++]; + + jdi->dsi = dsi; + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = 0; + + if (dsi->master) { + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + printk(BIOS_ERR, "mipi_dsi_attach() failed: %d\n", ret); + return (void *)-EPTR; + } + + ret = mipi_dsi_enslave(dsi->master, dsi); + if (ret < 0) { + printk(BIOS_ERR, "mipi_dsi_enslave() failed: %d\n", + ret); + return (void *)-EPTR; + } + + return jdi; + } + + dsi->ops = &panel_jdi_master_ops; + + jdi->enabled = 0; + jdi->width_mm = 211; + jdi->height_mm = 148; + + return jdi; +} diff --git a/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.h b/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.h new file mode 100644 index 0000000000..a44882d386 --- /dev/null +++ b/src/soc/nvidia/tegra132/jdi_25x18_display/panel-jdi-lpm102a188a.h @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _PANEL_JDI_LPM102A188A_H_ +#define _PANEL_JDI_LPM102A188A_H_ + +#define LP8557_MAX_BRIGHTNESS 0xFFF; + +#define LP8557_COMMAND 0x00 +#define LP8557_COMMAND_ON (1 << 0) + +#define LP8557_BRIGHTNESS_LOW 0x03 +#define LP8557_BRIGHTNESS_LOW_MASK(x) (((x) & 0xF) << 4) + +#define LP8557_BRIGHTNESS_HIGH 0x04 +#define LP8557_BRIGHTNESS_HIGH_MASK(x) (((x) & 0xFF0) >> 4) + +enum lp8557_config_brightness_mode { + LP8557_CONFIG_BRTMODE_PWM = 0x0, + LP8557_CONFIG_BRTMODE_REG, + LP8557_CONFIG_BRTMODE_PWM_REG_SHAPE_PWM, + LP8557_CONFIG_BRTMODE_PWM_REG_SHAPE_BRIGHTNESS, + LP8557_CONFIG_BRTMODE_MAX, +}; +#define LP8557_CONFIG 0x10 +#define LP8557_CONFIG_BRTMODE(x) (((x) & 0x3) << 0) +#define LP8557_CONFIG_AUTO_DETECT_LED (1 << 2) +#define LP8557_CONFIG_PWM_STANDBY (1 << 7) + +enum lp8557_current { + LP8557_CURRENT_5_MA = 0x0, + LP8557_CURRENT_10_MA, + LP8557_CURRENT_13_MA, + LP8557_CURRENT_15_MA, + LP8557_CURRENT_18_MA, + LP8557_CURRENT_20_MA, + LP8557_CURRENT_23_MA, + LP8557_CURRENT_25_MA, + LP8557_CURRENT_MAX, +}; +#define LP8557_CURRENT 0x11 +#define LP8557_CURRENT_MAXCURR(x) (((x) & 0x7) << 0) +#define LP8557_CURRENT_ISET (1 << 7) + +enum lp8557_pgen_frequency { + LP8557_PGEN_FREQ_4_9_KHZ = 0x0, + LP8557_PGEN_FREQ_9_8_KHZ, + LP8557_PGEN_FREQ_14_6_KHZ, + LP8557_PGEN_FREQ_19_5_KHZ, + LP8557_PGEN_FREQ_24_4_KHZ, + LP8557_PGEN_FREQ_29_3_KHZ, + LP8557_PGEN_FREQ_34_2_KHZ, + LP8557_PGEN_FREQ_39_1_KHZ, + LP8557_PGEN_FREQ_MAX, +}; +#define LP8557_PGEN 0x12 +#define LP8557_PGEN_FREQ(x) (((x) & 0x7) << 0) +#define LP8557_PGEN_MAGIC (5 << 3) +#define LP8557_PGEN_FSET (1 << 7) + +enum lp8557_boost_freq { + LP8557_BOOST_FREQ_500_KHZ = 0x0, + LP8557_BOOST_FREQ_1_MHZ, + LP8557_BOOST_FREQ_MAX, +}; +enum lp8557_boost_bcomp { + LP8557_BOOST_BCOMP_OPTION_0 = 0x0, + LP8557_BOOST_BCOMP_OPTION_1, + LP8557_BOOST_BCOMP_MAX, +}; +#define LP8557_BOOST 0x13 +#define LP8557_BOOST_FREQ(x) (((x) & 0x1) << 0) +#define LP8557_BOOST_BCOMP(x) (((x) & 0x1) << 1) +#define LP8557_BOOST_BCSET (1 << 6) +#define LP8557_BOOST_BFSET (1 << 7) + +#define LP8557_LED_ENABLE 0x14 +#define LP8557_LED_ENABLE_SINKS(x) (((x) & 0x3F) << 0) +#define LP8557_LED_ENABLE_MAGIC (2 << 6) + +enum lp8557_step_ramp { + LP8557_STEP_RAMP_0_MS = 0x0, + LP8557_STEP_RAMP_50_MS, + LP8557_STEP_RAMP_100_MS, + LP8557_STEP_RAMP_200_MS, + LP8557_STEP_RAMP_MAX, +}; +enum lp8557_step_smoothing { + LP8557_STEP_SMOOTHING_NONE = 0x0, + LP8557_STEP_SMOOTHING_LIGHT, + LP8557_STEP_SMOOTHING_MEDIUM, + LP8557_STEP_SMOOTHING_HEAVY, + LP8557_STEP_SMOOTHING_MAX, +}; +#define LP8557_STEP 0x15 +#define LP8557_STEP_RAMP(x) (((x) & 0x3) << 0) +#define LP8557_STEP_SMOOTHING(x) (((x) & 0x3) << 6) + +struct mipi_dsi_device; +struct soc_nvidia_tegra132_config; + +struct panel_jdi { + struct mipi_dsi_device *dsi; + const struct soc_nvidia_tegra132_config *mode; + + /* Physical size */ + unsigned int width_mm; + unsigned int height_mm; + + int enabled; +}; + +struct panel_jdi *panel_jdi_dsi_probe(struct mipi_dsi_device *dsi); +int panel_jdi_prepare(struct panel_jdi *jdi); + +#endif diff --git a/src/soc/nvidia/tegra132/lp0/Makefile b/src/soc/nvidia/tegra132/lp0/Makefile new file mode 100644 index 0000000000..57680c562f --- /dev/null +++ b/src/soc/nvidia/tegra132/lp0/Makefile @@ -0,0 +1,58 @@ +################################################################################ +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## +################################################################################ + +CC = $(GCC_PREFIX)gcc +NM = $(GCC_PREFIX)nm +OBJCOPY = $(GCC_PREFIX)objcopy + +OPENSSL = openssl +DD = dd +CP = cp +MV = mv +RM = rm + +SIGKEY = 00000000000000000000000000000000 + +.PHONY: all +all: tegra_lp0_resume.fw + +tegra_lp0_resume.elf: tegra_lp0_resume.ld tegra_lp0_resume.c + $(CC) -marm -march=armv4t -mno-unaligned-access -nostdlib -static \ + -Os -fpie -Wl,--build-id=none -ggdb3 -T tegra_lp0_resume.ld \ + -o $@ $(filter %.c,$+) + +tegra_lp0_resume.fw: tegra_lp0_resume.elf + @# Get rid of any files we're about to create. + $(RM) -f $@.nosig $@.sig $@.tosig + @# Convert the ELF image into a binary image. + $(OBJCOPY) -O binary $< $@.nosig + @# Extract the part of the binary which needs to be signed. + $(DD) bs=1 skip=544 if=$@.nosig of=$@.tosig + @# Calculate a signature for that part. + $(OPENSSL) dgst -mac cmac -macopt cipher:aes-128-cbc \ + -macopt hexkey:$(SIGKEY) -md5 -binary \ + $@.tosig > $@.sig + @# Inject the signature into the binary image's header. + $(DD) conv=notrunc bs=1 seek=272 count=16 if=$@.sig of=$@.nosig + @# Copy the signed binary to the target file name. + $(MV) $@.nosig $@ + +clean: + $(RM) -f tegra_lp0_resume.fw tegra_lp0_resume.fw.sig + $(RM) -f tegra_lp0_resume.fw.tosig tegra_lp0_resume.elf diff --git a/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.c b/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.c new file mode 100644 index 0000000000..a52e918ee0 --- /dev/null +++ b/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.c @@ -0,0 +1,690 @@ +/* + * Copyright 2014 Google Inc. + * Copyright 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +/* Function unit addresses. */ +enum { + UP_TAG_BASE = 0X60000000, + TIMER_BASE = 0X60005000, + CLK_RST_BASE = 0X60006000, + FLOW_CTLR_BASE = 0X60007000, + TEGRA_EVP_BASE = 0x6000f000, + APB_MISC_BASE = 0x70000000, + PMC_CTLR_BASE = 0X7000e400, + MC_CTLR_BASE = 0X70019000, +}; + + + +/* UP tag registers. */ +static uint32_t *up_tag_ptr = (void *)(UP_TAG_BASE + 0x0); +enum { + UP_TAG_AVP = 0xaaaaaaaa +}; + + +/* APB Misc JTAG Configuration Register */ +static uint32_t *misc_pp_config_ctl_ptr = (void *)(APB_MISC_BASE + 0x24); +enum { + PP_CONFIG_CTL_JTAG = 0x1 << 6 +}; + + +/* Timer registers. */ +static uint32_t *timer_us_ptr = (void *)(TIMER_BASE + 0x10); + + + +/* Clock and reset controller registers. */ +static uint32_t *clk_rst_rst_devices_l_ptr = (void *)(CLK_RST_BASE + 0x4); +enum { + SWR_TRIG_SYS_RST = 0x1 << 2 +}; + +static uint32_t *clk_rst_cclk_burst_policy_ptr = (void *)(CLK_RST_BASE + 0x20); +enum { + CCLK_PLLP_BURST_POLICY = 0x20004444 +}; + +static uint32_t *clk_rst_super_cclk_div_ptr = (void *)(CLK_RST_BASE + 0x24); +enum { + SUPER_CDIV_ENB = 0x1 << 31 +}; + +static uint32_t *clk_rst_osc_ctrl_ptr = (void *)(CLK_RST_BASE + 0x50); +enum { + OSC_XOE = 0x1 << 0, + OSC_XOFS_SHIFT = 4, + OSC_XOFS_MASK = 0x3f << OSC_XOFS_SHIFT, + OSC_FREQ_SHIFT = 28, + OSC_FREQ_MASK = 0xf << OSC_FREQ_SHIFT +}; +enum { + OSC_FREQ_13 = 0, + OSC_FREQ_16P8 = 1, + OSC_FREQ_19P2 = 4, + OSC_FREQ_38P4 = 5, + OSC_FREQ_12 = 8, + OSC_FREQ_48 = 9, + OSC_FREQ_26 = 12 +}; + +static uint32_t *clk_rst_pllu_base_ptr = (void *)(CLK_RST_BASE + 0xc0); +enum { + PLLU_DIVM_SHIFT = 0, + PLLU_DIVN_SHIFT = 8, + PLLU_OVERRIDE = 0x1 << 24, + PLLU_ENABLE = 0x1 << 30, + PLLU_BYPASS = 0x1 << 31 +}; + +static uint32_t *clk_rst_pllu_misc_ptr = (void *)(CLK_RST_BASE + 0xcc); +enum { + PLLU_LFCON_SHIFT = 4, + PLLU_CPCON_SHIFT = 8, + PLLU_LOCK_ENABLE = 22 +}; + +static uint32_t *clk_rst_pllx_base_ptr = (void *)(CLK_RST_BASE + 0xe0); +enum { + PLLX_ENABLE = 0x1 << 30 +}; + +static uint32_t *clk_rst_rst_dev_u_clr_ptr = (void *)(CLK_RST_BASE + 0x314); +enum { + SWR_CSITE_RST = 0x1 << 9 +}; + +static uint32_t *clk_rst_clk_enb_l_set_ptr = (void *)(CLK_RST_BASE + 0x320); +enum { + CLK_ENB_CPU = 0x1 << 0 +}; + +static uint32_t *clk_rst_clk_out_enb_u_set_ptr = + (void *)(CLK_RST_BASE + 0x330); +enum { + CLK_ENB_CSITE = 0x1 << 9 +}; + +static uint32_t *clk_rst_cpu_softrst_ctrl2_ptr = + (void *)(CLK_RST_BASE + 0x388); +enum { + CAR2PMC_CPU_ACK_WIDTH_SHIFT = 0, + CAR2PMC_CPU_ACK_WIDTH_MASK = 0xfff << CAR2PMC_CPU_ACK_WIDTH_SHIFT +}; + +static uint32_t *clk_rst_clk_enb_v_set_ptr = (void *)(CLK_RST_BASE + 0x440); +enum { + CLK_ENB_CPUG = 0x1 << 0, + CLK_ENB_CPULP = 0x1 << 1, +}; + +static uint32_t *clk_rst_rst_cpulp_cmplx_set_ptr = + (void *)(CLK_RST_BASE + 0x450); +enum { + SET_CXRESET0 = 0x1 << 20, + SET_CXRESET1 = 0x1 << 21 +}; +static uint32_t *clk_rst_rst_cpug_cmplx_clr_ptr = + (void *)(CLK_RST_BASE + 0x454); +enum { + CLR_CPURESET0 = 0x1 << 0, + CLR_CPURESET1 = 0x1 << 1, + CLR_CPURESET2 = 0x1 << 2, + CLR_CPURESET3 = 0x1 << 3, + CLR_DBGRESET0 = 0x1 << 12, + CLR_DBGRESET1 = 0x1 << 13, + CLR_DBGRESET2 = 0x1 << 14, + CLR_DBGRESET3 = 0x1 << 15, + CLR_CORERESET0 = 0x1 << 16, + CLR_CORERESET1 = 0x1 << 17, + CLR_CORERESET2 = 0x1 << 18, + CLR_CORERESET3 = 0x1 << 19, + CLR_CXRESET0 = 0x1 << 20, + CLR_CXRESET1 = 0x1 << 21, + CLR_CXRESET2 = 0x1 << 22, + CLR_CXRESET3 = 0x1 << 23, + CLR_L2RESET = 0x1 << 24, + CLR_NONCPURESET = 0x1 << 29, + CLR_PRESETDBG = 0x1 << 30 +}; + + +/* Reset vector. */ + +static uint32_t *evp_cpu_reset_ptr = (void *)(TEGRA_EVP_BASE + 0x100); + + + +/* Flow controller registers. */ +static uint32_t *flow_ctlr_halt_cop_events_ptr = + (void *)(FLOW_CTLR_BASE + 0x4); +enum { + EVENT_MSEC = 0x1 << 24, + EVENT_JTAG = 0x1 << 28, + FLOW_MODE_SHIFT = 29, + FLOW_MODE_STOP = 2 << FLOW_MODE_SHIFT, +}; + +static uint32_t *flow_ctlr_cluster_control_ptr = + (void *)(FLOW_CTLR_BASE + 0x2c); +enum { + FLOW_CLUSTER_ACTIVE_LP = 0x1 << 0 +}; + +static uint32_t *flow_ctlr_ram_repair_ptr = + (void *)(FLOW_CTLR_BASE + 0x40); +static uint32_t *flow_ctlr_ram_repair_cluster1_ptr = + (void *)(FLOW_CTLR_BASE + 0x58); +enum { + RAM_REPAIR_REQ = 0x1 << 0, + RAM_REPAIR_STS = 0x1 << 1, +}; + + +/* Power management controller registers. */ +enum { + PARTID_CRAIL = 0, + PARTID_CE0 = 14, + PARTID_C0NC = 15, +}; + +static uint32_t *pmc_ctlr_clamp_status_ptr = (void *)(PMC_CTLR_BASE + 0x2c); + +static uint32_t *pmc_ctlr_pwrgate_toggle_ptr = (void *)(PMC_CTLR_BASE + 0x30); +enum { + PWRGATE_TOGGLE_START = 0x1 << 8 +}; + +static uint32_t *pmc_ctlr_pwrgate_status_ptr = (void *)(PMC_CTLR_BASE + 0x38); + +static uint32_t *pmc_ctlr_cpupwrgood_timer_ptr = + (void *)(PMC_CTLR_BASE + 0xc8); + +static uint32_t *pmc_odmdata_ptr = (void *)(PMC_CTLR_BASE + 0xa0); + +static uint32_t *pmc_ctlr_scratch41_ptr = (void *)(PMC_CTLR_BASE + 0x140); +static uint32_t *pmc_ctlr_secure_scratch34_ptr = (void *)(PMC_CTLR_BASE + 0x368); +static uint32_t *pmc_ctlr_secure_scratch35_ptr = (void *)(PMC_CTLR_BASE + 0x36c); + +static uint32_t *pmc_ctlr_osc_edpd_over_ptr = (void *)(PMC_CTLR_BASE + 0x1a4); +enum { + PMC_XOFS_SHIFT = 1, + PMC_XOFS_MASK = 0x3f << PMC_XOFS_SHIFT +}; + + + +/* Memory controller registers. */ +static uint32_t *mc_video_protect_size_mb_ptr = (void *)(MC_CTLR_BASE + 0x64c); + +static uint32_t *mc_video_protect_reg_ctrl_ptr = + (void *)(MC_CTLR_BASE + 0x650); +enum { + VIDEO_PROTECT_WRITE_ACCESS_DISABLE = 0x1 << 0, + VIDEO_PROTECT_ALLOW_TZ_WRITE_ACCESS = 0x1 << 1 +}; + + +/* Utility functions. */ + +static inline void __attribute__((always_inline)) + __attribute__((noreturn)) halt(void) +{ + for (;;); +} + +inline static uint32_t read32(const void *addr) +{ + return *(volatile uint32_t *)addr; +} + +inline static void write32(uint32_t val, void *addr) +{ + *(volatile uint32_t *)addr = val; +} + +inline static void setbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) | bits, addr); +} + +inline static void clrbits32(uint32_t bits, void *addr) +{ + write32(read32(addr) & ~bits, addr); +} + +static void __attribute__((noreturn)) reset(void) +{ + write32(SWR_TRIG_SYS_RST, clk_rst_rst_devices_l_ptr); + halt(); +} + +static void udelay(unsigned usecs) +{ + uint32_t start = read32(timer_us_ptr); + while (read32(timer_us_ptr) - start < usecs) + ; +} + +/* UART related defines */ +static uint32_t *uart_clk_out_enb_regs[4] = { + (uint32_t *)0x60006010, + (uint32_t *)0x60006010, + (uint32_t *)0x60006014, + (uint32_t *)0x60006018 +}; + +static uint32_t *uart_rst_devices_regs[4] = { + (uint32_t *)0x60006004, + (uint32_t *)0x60006004, + (uint32_t *)0x60006008, + (uint32_t *)0x6000600c +}; + +static uint32_t uart_enable_mask[4] = { + 1 << 6, + 1 << 7, + 1 << 23, + 1 << 1 +}; + +static uint32_t *uart_clk_source_regs[4] = { + (uint32_t *)0x60006178, + (uint32_t *)0x6000617c, + (uint32_t *)0x600061a0, + (uint32_t *)0x600061c0, +}; + +static uint32_t *uart_base_regs[4] = { + (uint32_t *)0x70006000, + (uint32_t *)0x70006040, + (uint32_t *)0x70006200, + (uint32_t *)0x70006300, +}; +enum { + UART_THR_DLAB = 0x0, + UART_IER_DLAB = 0x1, + UART_IIR_FCR = 0x2, + UART_LCR = 0x3 +}; +enum { + UART_RATE_115200 = (408000000/115200/16), /* based on 408000000 PLLP */ + FCR_TX_CLR = 0x4, /* bit 2 of FCR : clear TX FIFO */ + FCR_RX_CLR = 0x2, /* bit 1 of FCR : clear RX FIFO */ + FCR_EN_FIFO = 0x1, /* bit 0 of FCR : enable TX & RX FIFO */ + LCR_DLAB = 0x80, /* bit 7 of LCR : Divisor Latch Access Bit */ + LCR_WD_SIZE_8 = 0x3, /* bit 1:0 of LCR : word length of 8 */ +}; + +static void enable_uart(void) +{ + uint32_t *uart_clk_enb_reg; + uint32_t *uart_rst_reg; + uint32_t *uart_clk_source; + uint32_t uart_port; + uint32_t uart_mask; + uint32_t *uart_base; + + /* + * Read odmdata (stored in pmc->odmdata) to determine debug uart port. + * + * Bits 15-17 of odmdata contains debug uart port. + * 0 : UARTA + * 1 : UARTB + * 2 : UARTC + * 3 : UARTD + */ + uart_port = (read32(pmc_odmdata_ptr) >> 15) & 0x7; + + /* Default to UARTA if uart_port is out of range */ + if (uart_port >= 4) + uart_port = 0; + + uart_clk_enb_reg = uart_clk_out_enb_regs[uart_port]; + uart_rst_reg = uart_rst_devices_regs[uart_port]; + uart_mask = uart_enable_mask[uart_port]; + uart_clk_source = uart_clk_source_regs[uart_port]; + uart_base = uart_base_regs[uart_port]; + + /* Enable UART clock */ + setbits32(uart_mask, uart_clk_enb_reg); + + /* Reset and unreset UART */ + setbits32(uart_mask, uart_rst_reg); + clrbits32(uart_mask, uart_rst_reg); + + /* Program UART clock source: PLLP (408000000) */ + write32(0, uart_clk_source); + + /* Program 115200n8 to the uart port */ + /* baud-rate of 115200 */ + write32(LCR_DLAB, (uart_base + UART_LCR)); + write32((UART_RATE_115200 & 0xff), (uart_base + UART_THR_DLAB)); + write32((UART_RATE_115200 >> 8), (uart_base + UART_IER_DLAB)); + /* 8-bit and no parity */ + write32(LCR_WD_SIZE_8, (uart_base + UART_LCR)); + /* enable and clear RX/TX FIFO */ + write32((FCR_TX_CLR + FCR_RX_CLR + FCR_EN_FIFO), + (uart_base + UART_IIR_FCR)); +} + +/* Accessors. */ + +static uint32_t get_wakeup_vector(void) +{ + return read32(pmc_ctlr_scratch41_ptr); +} + +static unsigned get_osc_freq(void) +{ + return (read32(clk_rst_osc_ctrl_ptr) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; +} + + +/* Jtag configuration. */ + +static void enable_jtag(void) +{ + write32(PP_CONFIG_CTL_JTAG, misc_pp_config_ctl_ptr); +} + +/* Clock configuration. */ + +static void config_oscillator(void) +{ + // Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy + // to OSC_CTRL.XOFS and set XOE. + uint32_t xofs = (read32(pmc_ctlr_osc_edpd_over_ptr) & + PMC_XOFS_MASK) >> PMC_XOFS_SHIFT; + + uint32_t osc_ctrl = read32(clk_rst_osc_ctrl_ptr); + osc_ctrl &= ~OSC_XOFS_MASK; + osc_ctrl |= (xofs << OSC_XOFS_SHIFT); + osc_ctrl |= OSC_XOE; + write32(osc_ctrl, clk_rst_osc_ctrl_ptr); +} + +static void config_pllu(void) +{ + // Figure out what parameters to use for PLLU. + uint32_t divm, divn, cpcon, lfcon; + switch (get_osc_freq()) { + case OSC_FREQ_12: + case OSC_FREQ_48: + divm = 0x0c; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + case OSC_FREQ_16P8: + divm = 0x07; + divn = 0x190; + cpcon = 0x05; + lfcon = 0x02; + break; + case OSC_FREQ_19P2: + case OSC_FREQ_38P4: + divm = 0x04; + divn = 0xc8; + cpcon = 0x03; + lfcon = 0x02; + break; + case OSC_FREQ_26: + divm = 0x1a; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + break; + default: + // Map anything that's not recognized to 13MHz. + divm = 0x0d; + divn = 0x3c0; + cpcon = 0x0c; + lfcon = 0x02; + } + + // Configure PLLU. + uint32_t base = PLLU_BYPASS | PLLU_OVERRIDE | + (divn << PLLU_DIVN_SHIFT) | (divm << PLLU_DIVM_SHIFT); + write32(base, clk_rst_pllu_base_ptr); + uint32_t misc = (cpcon << PLLU_CPCON_SHIFT) | + (lfcon << PLLU_LFCON_SHIFT); + write32(misc, clk_rst_pllu_misc_ptr); + + // Enable PLLU. + base &= ~PLLU_BYPASS; + base |= PLLU_ENABLE; + write32(base, clk_rst_pllu_base_ptr); + misc |= PLLU_LOCK_ENABLE; + write32(misc, clk_rst_pllu_misc_ptr); +} + +static void enable_cpu_clocks(void) +{ + // Enable the CPU complex clock. + write32(CLK_ENB_CPU, clk_rst_clk_enb_l_set_ptr); + write32(CLK_ENB_CPUG | CLK_ENB_CPULP, clk_rst_clk_enb_v_set_ptr); +} + + + +/* Function unit configuration. */ + +static void config_core_sight(void) +{ + // Enable the CoreSight clock. + write32(CLK_ENB_CSITE, clk_rst_clk_out_enb_u_set_ptr); + + /* + * De-assert CoreSight reset. + * NOTE: We're leaving the CoreSight clock on the oscillator for + * now. It will be restored to its original clock source + * when the CPU-side restoration code runs. + */ + write32(SWR_CSITE_RST, clk_rst_rst_dev_u_clr_ptr); +} + + +/* Resets. */ + +static void clear_cpu_resets(void) +{ + /* Hold CPU1 in reset */ + setbits32(SET_CXRESET1, clk_rst_rst_cpulp_cmplx_set_ptr); + + write32(CLR_NONCPURESET | CLR_L2RESET | CLR_PRESETDBG, + clk_rst_rst_cpug_cmplx_clr_ptr); + + write32(CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0, + clk_rst_rst_cpug_cmplx_clr_ptr); +} + + + +/* RAM repair */ + +void ram_repair(void) +{ + // Request Cluster0 RAM repair. + setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_ptr); + // Poll for Cluster0 RAM repair status. + while (!(read32(flow_ctlr_ram_repair_ptr) & RAM_REPAIR_STS)) + ; + + // Request Cluster1 RAM repair. + setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_cluster1_ptr); + // Poll for Cluster1 RAM repair status. + while (!(read32(flow_ctlr_ram_repair_cluster1_ptr) & RAM_REPAIR_STS)) + ; +} + + +/* Power. */ + +static void power_on_partition(unsigned id) +{ + uint32_t bit = 0x1 << id; + if (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) { + // Partition is not on. Turn it on. + write32(id | PWRGATE_TOGGLE_START, pmc_ctlr_pwrgate_toggle_ptr); + + // Wait until the partition is powerd on. + while (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) + ; + + // Wait until clamp is off. + while (read32(pmc_ctlr_clamp_status_ptr) & bit) + ; + } +} + +static void power_on_main_cpu(void) +{ + /* + * Reprogram PMC_CPUPWRGOOD_TIMER register: + * + * XXX This is a fragile assumption. XXX + * The kernel prepares PMC_CPUPWRGOOD_TIMER based on a 32768Hz clock. + * Note that PMC_CPUPWRGOOD_TIMER is running at pclk. + * + * We need to reprogram PMC_CPUPWRGOOD_TIMER based on the current pclk + * which is at 204Mhz (pclk = sclk = pllp_out2) after BootROM. Multiply + * PMC_CPUPWRGOOD_TIMER by 204M / 32K. + * + * Save the original PMC_CPUPWRGOOD_TIMER register which we need to + * restore after the CPU is powered up. + */ + uint32_t orig_timer = read32(pmc_ctlr_cpupwrgood_timer_ptr); + + write32(orig_timer * (204000000 / 32768), + pmc_ctlr_cpupwrgood_timer_ptr); + + power_on_partition(PARTID_CRAIL); + power_on_partition(PARTID_C0NC); + power_on_partition(PARTID_CE0); + + // Restore the original PMC_CPUPWRGOOD_TIMER. + write32(orig_timer, pmc_ctlr_cpupwrgood_timer_ptr); +} + + +static void aarch64_trampoline(void) +{ + uint32_t val = 3; /* bit1: to warm reset; bit0: AARCH64*/ + + asm volatile ("mcr p15, 0, %0, c12, c0, 2" : : "r" (val)); + + /* unreachable */ + halt(); +} + + +/* Entry point. */ + +void lp0_resume(void) +{ + // If not on the AVP, reset. + if (read32(up_tag_ptr) != UP_TAG_AVP) + reset(); + + // Enable JTAG + enable_jtag(); + + config_oscillator(); + + // Program SUPER_CCLK_DIVIDER. + write32(SUPER_CDIV_ENB, clk_rst_super_cclk_div_ptr); + + config_core_sight(); + + enable_uart(); + + config_pllu(); + + /* + * Set the CPU reset vector. + * + * T132 always resets to AARCH32 and SW needs to write RMR_EL3 + * to bootstrap into AARCH64. + */ + write32(get_wakeup_vector(), pmc_ctlr_secure_scratch34_ptr); + write32(0, pmc_ctlr_secure_scratch35_ptr); + write32((uint32_t)aarch64_trampoline, evp_cpu_reset_ptr); + + // Select CPU complex clock source. + write32(CCLK_PLLP_BURST_POLICY, clk_rst_cclk_burst_policy_ptr); + + // Disable PLLX since it isn't used as CPU clock source. + clrbits32(PLLX_ENABLE, clk_rst_pllx_base_ptr); + + // Set CAR2PMC_CPU_ACK_WIDTH to 408. + uint32_t ack_width = read32(clk_rst_cpu_softrst_ctrl2_ptr); + ack_width &= ~CAR2PMC_CPU_ACK_WIDTH_MASK; + ack_width |= 408 << CAR2PMC_CPU_ACK_WIDTH_SHIFT; + write32(ack_width, clk_rst_cpu_softrst_ctrl2_ptr); + + // Disable VPR. + write32(0, mc_video_protect_size_mb_ptr); + write32(VIDEO_PROTECT_WRITE_ACCESS_DISABLE, + mc_video_protect_reg_ctrl_ptr); + + enable_cpu_clocks(); + + power_on_main_cpu(); + + // Perform ram repair after cpu is powered on. + ram_repair(); + + clear_cpu_resets(); + + // Halt the AVP. + while (1) + write32(FLOW_MODE_STOP | EVENT_JTAG, + flow_ctlr_halt_cop_events_ptr); +} + + + +/* Header. */ + +extern uint8_t blob_data; +extern uint8_t blob_data_size; +extern uint8_t blob_total_size; + +struct lp0_header { + uint32_t length_insecure; // Insecure total length. + uint32_t reserved[3]; + uint8_t rsa_modulus[256]; // RSA key modulus. + uint8_t aes_signature[16]; // AES signature. + uint8_t rsa_signature[256]; // RSA-PSS signature. + uint8_t random_aes_block[16]; // Random data, may be zero. + uint32_t length_secure; // Secure total length. + uint32_t destination; // Where to load the blob in iRAM. + uint32_t entry_point; // Entry point for the blob. + uint32_t code_length; // Length of just the data. +} __attribute__((packed)); + +struct lp0_header header __attribute__((section(".header"))) = +{ + .length_insecure = (uintptr_t)&blob_total_size, + .length_secure = (uintptr_t)&blob_total_size, + .destination = (uintptr_t)&blob_data, + .entry_point = (uintptr_t)&lp0_resume, + .code_length = (uintptr_t)&blob_data_size +}; diff --git a/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.ld b/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.ld new file mode 100644 index 0000000000..c4c508ff4c --- /dev/null +++ b/src/soc/nvidia/tegra132/lp0/tegra_lp0_resume.ld @@ -0,0 +1,73 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* We use ELF as output format. So that we can debug the code in some form. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +PHDRS +{ + to_load PT_LOAD; +} + +ENTRY(lp0_resume) +SECTIONS +{ + . = 0x40020000 - 0x240; + + /* + * The lp0 blob header is built as a static data structure and put + * in the .header section. + */ + .header_start = .; + .header . : { + *(.header); + } : to_load = 0xff + .header_end = .; + + . = 0x40020000; + + /* The actual lp0 blob code. */ + .data_start = .; + .data . : { + *(.text); + *(.text.*); + *(.rodata); + *(.rodata.*); + *(.data); + *(.data.*); + *(.bss); + *(.bss.*); + *(.sbss); + *(.sbss.*); + . = ALIGN(16); + } + .data_end = .; + + /* Some values we need in the header. */ + blob_data = .data_start; + blob_data_size = .data_end - .data_start; + blob_total_size = .data_end - .header_start; + + /DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.ARM.*) + } +} diff --git a/src/soc/nvidia/tegra132/maincpu.S b/src/soc/nvidia/tegra132/maincpu.S new file mode 100644 index 0000000000..898d821d7e --- /dev/null +++ b/src/soc/nvidia/tegra132/maincpu.S @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +ENTRY(maincpu_setup) + /* + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. + */ + msr cpsr, #0xdf + + ldr sp, maincpu_stack_pointer + eor lr, lr + ldr r0, maincpu_entry_point + bx r0 +ENDPROC(maincpu_setup) + + .align 2 + + .global maincpu_stack_pointer +maincpu_stack_pointer: + .word 0 + + .global maincpu_entry_point +maincpu_entry_point: + .word 0 diff --git a/src/soc/nvidia/tegra132/mipi-phy.c b/src/soc/nvidia/tegra132/mipi-phy.c new file mode 100644 index 0000000000..35adf6e6ee --- /dev/null +++ b/src/soc/nvidia/tegra132/mipi-phy.c @@ -0,0 +1,92 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int mipi_dphy_set_timing(struct tegra_dsi *dsi) +{ + + u32 freq = (dsi->clk_rate * 2) / 1000000; + + u32 thsdexit = (DSI_PHY_TIMING_DIV(120, (freq))); + u32 thstrial = (((3) + (DSI_PHY_TIMING_DIV((DSI_THSTRAIL_VAL(freq)), + freq)))); + u32 tdatzero = DSI_PHY_TIMING_DIV(((145) + (5 * (DSI_TBIT(freq)))), + (freq)); + u32 thsprepare = DSI_PHY_TIMING_DIV((65 + (5*(DSI_TBIT(freq)))), freq); + u32 tclktrial = (DSI_PHY_TIMING_DIV(80, freq)); + u32 tclkpost = ((DSI_PHY_TIMING_DIV(((70) + ((52) * (DSI_TBIT(freq)))), + freq))); + u32 tclkzero = (DSI_PHY_TIMING_DIV(260, freq)); + u32 ttlpx = (DSI_PHY_TIMING_DIV(60, freq)) ; + u32 tclkprepare = (DSI_PHY_TIMING_DIV(60, freq)); + u32 tclkpre = 1; //min = 8*UI per mipi spec, tclk_pre=0 should be ok, but using 1 value + u32 twakeup = 0x7F; //min = 1ms + + u32 ttaget; + u32 ttassure; + u32 ttago; + u32 value; + + if (!ttlpx) { + ttaget = 5; + ttassure = 2; + ttago = 4; + } else { + ttaget = 5 * ttlpx; + ttassure = 2 * ttlpx; + ttago = 4 * ttlpx; + } + + value = (thsdexit << 24) | + (thstrial << 16) | + (tdatzero << 8) | + (thsprepare << 0); + tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0); + + value = (tclktrial << 24) | + (tclkpost << 16) | + (tclkzero << 8) | + (ttlpx << 0); + tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1); + + value = (tclkprepare << 16) | + (tclkpre << 8) | + (twakeup << 0); + tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2); + + value = (ttaget << 16) | + (ttassure << 8) | + (ttago << 0), + tegra_dsi_writel(dsi, value, DSI_BTA_TIMING); + return 0; +} diff --git a/src/soc/nvidia/tegra132/mipi.c b/src/soc/nvidia/tegra132/mipi.c new file mode 100644 index 0000000000..abd2230378 --- /dev/null +++ b/src/soc/nvidia/tegra132/mipi.c @@ -0,0 +1,151 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jdi_25x18_display/panel-jdi-lpm102a188a.h" + +static unsigned long dsi_pads[] = { + 0x060, /* DSIA & DSIB pads */ + 0x180, /* DSIC & DSID pads */ +}; + +static struct tegra_mipi mipi_data = { + .regs = (void *)TEGRA_MIPI_CAL_BASE, +}; + +static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi, + unsigned long reg) +{ + return readl(mipi->regs + (reg << 2)); +} + +static inline void tegra_mipi_writel(struct tegra_mipi *mipi, + unsigned long value, unsigned long reg) +{ + writel(value, mipi->regs + (reg << 2)); +} + +static const struct calibration_regs tegra124_mipi_calibration_regs[] = { + { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, + { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK }, + { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, + { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK }, + { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK }, + { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, + { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIAB_CLK }, +}; +static const struct tegra_mipi_config tegra124_mipi_config = { + .calibrate_clk_lane = 1, + .regs = tegra124_mipi_calibration_regs, + .num_pads = ARRAY_SIZE(tegra124_mipi_calibration_regs), +}; + +struct tegra_mipi_device *tegra_mipi_request(struct tegra_mipi_device *device, + int device_index) +{ + device->mipi = &mipi_data; + device->config = &tegra124_mipi_config; + device->pads = dsi_pads[device_index]; + + return device; +} + +static int tegra_mipi_wait(struct tegra_mipi *mipi) +{ + u32 poll_interval_us = 1000; + u32 timeout_us = 250 * 1000; + unsigned long value; + + do { + value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS); + if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 && + (value & MIPI_CAL_STATUS_DONE) != 0) + return 0; + + if (timeout_us > poll_interval_us) + timeout_us -= poll_interval_us; + else + break; + + udelay(poll_interval_us); + } while (1); + + printk(BIOS_ERR, "%s: ERROR: timeout\n", __func__); + return -ETIMEDOUT; +} + +int tegra_mipi_calibrate(struct tegra_mipi_device *device) +{ + const struct tegra_mipi_config *cfg = device->config; + unsigned long value, clk_value; + unsigned int i; + int err; + + value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0); + value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP; + value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF; + tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0); + + tegra_mipi_writel(device->mipi, MIPI_CAL_BIAS_PAD_CFG1_DEFAULT, + MIPI_CAL_BIAS_PAD_CFG1); + + value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2); + value &= ~MIPI_CAL_BIAS_PAD_PDVREG; + tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2); + + for (i = 0; i < cfg->num_pads; i++) { + if (device->pads & BIT(i)) { + value = MIPI_CAL_CONFIG_SELECT | + MIPI_CAL_CONFIG_HSPDOS(0) | + MIPI_CAL_CONFIG_HSPUOS(4) | + MIPI_CAL_CONFIG_TERMOS(5); + clk_value = MIPI_CAL_CONFIG_SELECT | + MIPI_CAL_CONFIG_HSCLKPDOSD(0) | + MIPI_CAL_CONFIG_HSCLKPUOSD(4); + } else { + value = 0; + clk_value = 0; + } + + tegra_mipi_writel(device->mipi, value, cfg->regs[i].data); + + if (cfg->calibrate_clk_lane) + tegra_mipi_writel(device->mipi, clk_value, + cfg->regs[i].clk); + } + + value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL); + value |= MIPI_CAL_CTRL_START; + tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL); + + err = tegra_mipi_wait(device->mipi); + + return err; +} diff --git a/src/soc/nvidia/tegra132/mipi_dsi.c b/src/soc/nvidia/tegra132/mipi_dsi.c new file mode 100644 index 0000000000..440bb23dfc --- /dev/null +++ b/src/soc/nvidia/tegra132/mipi_dsi.c @@ -0,0 +1,431 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mipi_dsi_device mipi_dsi_device_data[NUM_DSI] = { + { + .master = NULL, + .slave = &mipi_dsi_device_data[DSI_B], + }, + { + .master = &mipi_dsi_device_data[DSI_A], + .slave = NULL, + }, +}; + +static struct mipi_dsi_device * +mipi_dsi_device_alloc(struct mipi_dsi_host *host) +{ + static int index = 0; + struct mipi_dsi_device *dsi; + + if (index >= NUM_DSI) + return (void *)-EPTR; + + dsi = &mipi_dsi_device_data[index++]; + dsi->host = host; + return dsi; +} + +static struct mipi_dsi_device * +of_mipi_dsi_device_add(struct mipi_dsi_host *host) +{ + struct mipi_dsi_device *dsi; + u32 reg = 0; + + dsi = mipi_dsi_device_alloc(host); + if (IS_ERR_PTR(dsi)) { + printk(BIOS_ERR, "failed to allocate DSI device\n"); + return dsi; + } + + dsi->channel = reg; + host->dev = (void *)dsi; + + return dsi; +} + +int mipi_dsi_host_register(struct mipi_dsi_host *host) +{ + of_mipi_dsi_device_add(host); + return 0; +} + +/** + * mipi_dsi_attach - attach a DSI device to its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_attach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->attach) + return -ENOSYS; + + return ops->attach(dsi->host, dsi); +} + +/** + * mipi_dsi_detach - detach a DSI device from its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_detach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->detach) + return -ENOSYS; + + return ops->detach(dsi->host, dsi); +} + +/** + * mipi_dsi_enslave() - use a MIPI DSI peripheral as slave for dual-channel + * operation + * @master: master DSI peripheral device + * @slave: slave DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_enslave(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave) +{ + int err = 0; + + slave->master = master; + master->slave = slave; + + if (master->ops && master->ops->enslave) + err = master->ops->enslave(master, slave); + + return err; +} + +/** + * mipi_dsi_liberate() - stop using a MIPI DSI peripheral as slave for dual- + * channel operation + * @master: master DSI peripheral device + * @slave: slave DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_liberate(struct mipi_dsi_device *master, + struct mipi_dsi_device *slave) +{ + int err = 0; + + if (master->ops && master->ops->liberate) + err = master->ops->liberate(master, slave); + + master->slave = NULL; + slave->master = NULL; + + return err; +} + +/** + * mipi_dsi_dcs_write() - send DCS write command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer containing the command payload + * @len: command payload length + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len) +{ + struct mipi_dsi_msg msg; + ssize_t err; + size_t size; + + u8 buffer[MAX_DSI_HOST_FIFO_DEPTH + 4]; + u8 *tx = buffer; + + if (len > MAX_DSI_HOST_FIFO_DEPTH) { + printk(BIOS_ERR, "%s: Error: too large payload length: %zu\n", + __func__, len); + + return -EINVAL; + } + + if (len > 0) { + unsigned int offset = 0; + + /* + * DCS long write packets contain the word count in the header + * bytes 1 and 2 and have a payload containing the DCS command + * byte folowed by word count minus one bytes. + * + * DCS short write packets encode the DCS command and up to + * one parameter in header bytes 1 and 2. + */ + if (len > 1) + size = 3 + len; + else + size = 1 + len; + + /* write word count to header for DCS long write packets */ + if (len > 1) { + tx[offset++] = ((1 + len) >> 0) & 0xff; + tx[offset++] = ((1 + len) >> 8) & 0xff; + } + + /* write the DCS command byte followed by the payload */ + tx[offset++] = cmd; + memcpy(tx + offset, data, len); + } else { + tx = &cmd; + size = 1; + } + + memset(&msg, 0, sizeof(msg)); + msg.flags = MIPI_DSI_MSG_USE_LPM; + msg.channel = dsi->channel; + msg.tx_len = size; + msg.tx_buf = tx; + + switch (len) { + case 0: + msg.type = MIPI_DSI_DCS_SHORT_WRITE; + break; + case 1: + msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + default: + msg.type = MIPI_DSI_DCS_LONG_WRITE; + break; + } + + err = dsi->host->ops->transfer(dsi->host, &msg); + + return err; +} + +/** + * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display + * module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_display_on() - start displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_column_address() - define the column extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first column of frame memory + * @end: last column of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_page_address() - define the page extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first page of frame memory + * @end: last page of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect + * output signal on the TE signal line. + * @dsi: DSI peripheral device + * @mode: the Tearing Effect Output Line mode + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode) +{ + u8 value = mode; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value, + sizeof(value)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format, + sizeof(format)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_address_mode() - sets the data order for forward transfers + * from the host to the peripheral + * @dsi: DSI peripheral device + * @reverse_page_address: reverses the page addressing to bottom->top + * @reverse_col_address: reverses the column addressing to right->left + * @reverse_page_col_address: reverses the page/column addressing order + * @refresh_from_bottom: refresh the display bottom to top + * @reverse_rgb: send pixel data bgr instead of rgb + * @latch_right_to_left: latch the incoming display data right to left + * @flip_horizontal: flip the image horizontally, left to right + * @flip_vertical: flip the image vertically, top to bottom + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_address_mode(struct mipi_dsi_device *dsi, + bool reverse_page_address, + bool reverse_col_address, + bool reverse_page_col_address, + bool refresh_from_bottom, + bool reverse_rgb, + bool latch_right_to_left, + bool flip_horizontal, + bool flip_vertical) +{ + ssize_t err; + u8 data; + + data = ((flip_vertical ? 1 : 0) << 0) | + ((flip_horizontal ? 1 : 0) << 1) | + ((latch_right_to_left ? 1 : 0) << 2) | + ((reverse_rgb ? 1 : 0) << 3) | + ((refresh_from_bottom ? 1 : 0) << 4) | + ((reverse_page_col_address ? 1 : 0) << 5) | + ((reverse_col_address ? 1 : 0) << 6) | + ((reverse_page_address ? 1 : 0) << 7); + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &data, 1); + if (err < 0) + return err; + + return 0; +} diff --git a/src/soc/nvidia/tegra132/mmu_operations.c b/src/soc/nvidia/tegra132/mmu_operations.c new file mode 100644 index 0000000000..42678fc280 --- /dev/null +++ b/src/soc/nvidia/tegra132/mmu_operations.c @@ -0,0 +1,81 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +/* This structure keeps track of all the mmap memory ranges for t132 */ +static struct memranges t132_mmap_ranges; + +static void tegra132_memrange_init(struct memranges *map) +{ + uint64_t start,end; + const unsigned long devmem = MA_DEV | MA_S | MA_RW; + const unsigned long cachedmem = MA_MEM | MA_NS | MA_RW; + const unsigned long secure_mem = MA_MEM | MA_S | MA_RW; + uintptr_t tz_base_mib; + size_t tz_size_mib; + + memranges_init_empty(map); + + memory_in_range_below_4gb(&start,&end); + + /* Device memory below DRAM */ + memranges_insert(map, 0, start * MiB, devmem); + + /* DRAM */ + memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + + memory_in_range_above_4gb(&start,&end); + + memranges_insert(map, start * MiB, (end-start) * MiB, cachedmem); + + /* SRAM */ + memranges_insert(map, TEGRA_SRAM_BASE, TEGRA_SRAM_SIZE, cachedmem); + + /* Add TZ carveout. */ + carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); + memranges_insert(map, tz_base_mib * MiB, tz_size_mib * MiB, secure_mem); +} + +void __attribute__((weak)) mainboard_add_memory_ranges(struct memranges *map) +{ + /* Don't add any ranges by default. */ +} + +void tegra132_mmu_init(void) +{ + uintptr_t tz_base_mib; + size_t tz_size_mib; + size_t ttb_size_mib; + struct memranges *map = &t132_mmap_ranges; + + tegra132_memrange_init(map); + mainboard_add_memory_ranges(map); + /* Place page tables at the base of the trust zone region. */ + carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); + tz_base_mib *= MiB; + ttb_size_mib = TTB_SIZE * MiB; + mmu_init(map, (void *)tz_base_mib, ttb_size_mib); + mmu_enable(); +} diff --git a/src/soc/nvidia/tegra132/monotonic_timer.c b/src/soc/nvidia/tegra132/monotonic_timer.c new file mode 100644 index 0000000000..d6c30b4ffa --- /dev/null +++ b/src/soc/nvidia/tegra132/monotonic_timer.c @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void timer_monotonic_get(struct mono_time *mt) +{ + mono_time_set_usecs(mt, read32((void *)TEGRA_TMRUS_BASE)); +} diff --git a/src/soc/nvidia/tegra132/padconfig.c b/src/soc/nvidia/tegra132/padconfig.c new file mode 100644 index 0000000000..5f7f2e4f93 --- /dev/null +++ b/src/soc/nvidia/tegra132/padconfig.c @@ -0,0 +1,137 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +static uint32_t * const pinmux_regs = (void *)(uintptr_t)TEGRA_APB_PINMUX_BASE; +static struct gpio_bank * const gpio_regs = (void *)(uintptr_t)TEGRA_GPIO_BASE; + +static inline struct gpio_bank * const get_gpio_bank_regs(int index) +{ + return &gpio_regs[gpio_index_to_bank(index)]; +} + +static inline uint32_t pad_get_pinmux(int index) +{ + return read32(&pinmux_regs[index]); +} + +static inline void pad_set_pinmux(int index, uint32_t reg) +{ + return write32(reg, &pinmux_regs[index]); +} + +static inline void pad_set_gpio_out(int gpio_index, int val) +{ + struct gpio_bank * const regs = get_gpio_bank_regs(gpio_index); + int port = gpio_index_to_port(gpio_index); + int bit = gpio_to_bit(gpio_index); + + write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (val << bit), + ®s->out_value_mask[port]); + write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (1 << bit), + ®s->out_enable_mask[port]); +} + +static inline void pad_set_mode(int gpio_index, int sfio_or_gpio) +{ + struct gpio_bank * const regs = get_gpio_bank_regs(gpio_index); + int port = gpio_index_to_port(gpio_index); + int bit = gpio_to_bit(gpio_index); + + write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (sfio_or_gpio << bit), + ®s->config_mask[port]); +} + +static inline void pad_set_gpio_mode(int gpio_index) +{ + pad_set_mode(gpio_index, 1); +} + +static inline void pad_set_sfio_mode(int gpio_index) +{ + pad_set_mode(gpio_index, 0); +} + +static void configure_unused_pad(const struct pad_config * const entry) +{ + uint32_t reg; + + /* + * Tristate the pad and disable input. If power-on-reset state is a + * pullup maintain that. Otherwise enable pulldown. + */ + reg = pad_get_pinmux(entry->pinmux_index); + reg &= ~PINMUX_INPUT_ENABLE; + reg |= PINMUX_TRISTATE; + reg &= ~PINMUX_PULL_MASK; + if (entry->por_pullup) + reg |= PINMUX_PULL_UP; + else + reg |= PINMUX_PULL_DOWN; + pad_set_pinmux(entry->pinmux_index, reg); + + /* + * Set to GPIO mode if GPIO available to bypass collisions of + * controller signals going to more than one pad. + */ + if (entry->pad_has_gpio) + pad_set_gpio_mode(entry->gpio_index); +} + +static void configure_sfio_pad(const struct pad_config * const entry) +{ + pad_set_pinmux(entry->pinmux_index, entry->pinmux_flags); + pad_set_sfio_mode(entry->gpio_index); +} + +static void configure_gpio_pad(const struct pad_config * const entry) +{ + uint32_t reg; + + if (entry->gpio_out0 || entry->gpio_out1) + pad_set_gpio_out(entry->gpio_index, entry->gpio_out1 ? 1 : 0); + + /* Keep the original SFIO selection. */ + reg = pinmux_get_config(entry->pinmux_index); + reg &= PINMUX_FUNC_MASK; + reg |= entry->pinmux_flags; + + pad_set_pinmux(entry->pinmux_index, reg); + pad_set_gpio_mode(entry->gpio_index); +} + +void soc_configure_pads(const struct pad_config * const entries, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) { + const struct pad_config * const entry = &entries[i]; + + if (entry->unused) { + configure_unused_pad(entry); + } else if (entry->sfio) { + configure_sfio_pad(entry); + } else { + configure_gpio_pad(entry); + } + } +} diff --git a/src/soc/nvidia/tegra132/power.c b/src/soc/nvidia/tegra132/power.c new file mode 100644 index 0000000000..b4bfc7c2b6 --- /dev/null +++ b/src/soc/nvidia/tegra132/power.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +static struct tegra_pmc_regs * const pmc = (void *)TEGRA_PMC_BASE; + +static int partition_powered(int id) +{ + return read32(&pmc->pwrgate_status) & (0x1 << id); +} + +void power_ungate_partition(uint32_t id) +{ + printk(BIOS_INFO, "Ungating power partition %d.\n", id); + + if (!partition_powered(id)) { + uint32_t pwrgate_toggle = read32(&pmc->pwrgate_toggle); + pwrgate_toggle &= ~(PMC_PWRGATE_TOGGLE_PARTID_MASK); + pwrgate_toggle |= (id << PMC_PWRGATE_TOGGLE_PARTID_SHIFT); + pwrgate_toggle |= PMC_PWRGATE_TOGGLE_START; + write32(pwrgate_toggle, &pmc->pwrgate_toggle); + + // Wait for the request to be accepted. + while (read32(&pmc->pwrgate_toggle) & PMC_PWRGATE_TOGGLE_START) + ; + printk(BIOS_DEBUG, "Power gate toggle request accepted.\n"); + + // Wait for the partition to be powered. + while (!partition_powered(id)) + ; + } + + printk(BIOS_INFO, "Ungated power partition %d.\n", id); +} + +uint8_t pmc_rst_status(void) +{ + return read32(&pmc->rst_status) & PMC_RST_STATUS_SOURCE_MASK; +} + +static const char *pmc_rst_status_str[PMC_RST_STATUS_NUM_SOURCES] = { + [PMC_RST_STATUS_SOURCE_POR] = "POR", + [PMC_RST_STATUS_SOURCE_WATCHDOG] = "Watchdog", + [PMC_RST_STATUS_SOURCE_SENSOR] = "Sensor", + [PMC_RST_STATUS_SOURCE_SW_MAIN] = "SW Main", + [PMC_RST_STATUS_SOURCE_LP0] = "LP0", +}; + +void pmc_print_rst_status(void) +{ + uint8_t rst_status = pmc_rst_status(); + assert(rst_status < PMC_RST_STATUS_NUM_SOURCES); + printk(BIOS_INFO, "PMC Reset Status: %s\n", + pmc_rst_status_str[rst_status]); +} diff --git a/src/soc/nvidia/tegra132/psci.c b/src/soc/nvidia/tegra132/psci.c new file mode 100644 index 0000000000..4525f98cdc --- /dev/null +++ b/src/soc/nvidia/tegra132/psci.c @@ -0,0 +1,145 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void *cpu_on_entry_point; + +void psci_soc_init(uintptr_t cpu_on_entry) +{ + /* + * Stash secmon entry point for CPUs starting up. The 32-bit reset + * vector register is accessible in < EL3 so one has to attempt to + * plug the potential race for that register being changed out from + * under us. Therefore, we set the appropriate registers here, but + * it is also done on each CPU_ON request. + */ + cpu_on_entry_point = (void *)cpu_on_entry; + cpu_prepare_startup(cpu_on_entry_point); +} + +static size_t children_at_level(int parent_level, uint64_t mpidr) +{ + if (mpidr != 0) + return 0; + + /* T132 just has 2 cores. 0. Level 1 has 2 children at level 0. */ + switch (parent_level) { + case PSCI_AFFINITY_ROOT: + return 1; + case PSCI_AFFINITY_LEVEL_3: + return 1; + case PSCI_AFFINITY_LEVEL_2: + return 1; + case PSCI_AFFINITY_LEVEL_1: + return 2; + case PSCI_AFFINITY_LEVEL_0: + return 0; + default: + return 0; + } +} + +#define TEGRA132_PM_CORE_C7 0x3 + +static inline void tegra132_enter_sleep(unsigned long pmstate) +{ + asm volatile( + " isb\n" + " msr actlr_el1, %0\n" + " wfi\n" + : + : "r" (pmstate)); +} + +static void prepare_cpu_on(int cpu) +{ + uint32_t partid; + + partid = cpu ? POWER_PARTID_CE1 : POWER_PARTID_CE0; + + power_ungate_partition(partid); + flowctrl_write_cpu_halt(cpu, 0); +} + +static int cmd_prepare(struct psci_cmd *cmd) +{ + int ret; + + switch (cmd->type) { + case PSCI_CMD_ON: + prepare_cpu_on(cmd->target->cpu_state.ci->id); + ret = PSCI_RET_SUCCESS; + break; + case PSCI_CMD_OFF: + if (cmd->state_id != -1) { + ret = PSCI_RET_INVALID_PARAMETERS; + break; + } + cmd->state_id = TEGRA132_PM_CORE_C7; + ret = PSCI_RET_SUCCESS; + break; + default: + ret = PSCI_RET_NOT_SUPPORTED; + break; + } + return ret; +} + +static int cmd_commit(struct psci_cmd *cmd) +{ + int ret; + struct cpu_info *ci; + + ci = cmd->target->cpu_state.ci; + + switch (cmd->type) { + case PSCI_CMD_ON: + /* Take CPU out of reset */ + start_cpu_silent(ci->id, cpu_on_entry_point); + ret = PSCI_RET_SUCCESS; + break; + case PSCI_CMD_OFF: + flowctrl_cpu_off(ci->id); + tegra132_enter_sleep(cmd->state_id); + /* Never reach here */ + ret = PSCI_RET_NOT_SUPPORTED; + printk(BIOS_ERR, "t132 CPU%d PSCI_CMD_OFF fail\n", ci->id); + break; + default: + ret = PSCI_RET_NOT_SUPPORTED; + break; + } + return ret; +} + +struct psci_soc_ops soc_psci_ops = { + .children_at_level = &children_at_level, + .cmd_prepare = &cmd_prepare, + .cmd_commit = &cmd_commit, +}; diff --git a/src/soc/nvidia/tegra132/ramstage.c b/src/soc/nvidia/tegra132/ramstage.c new file mode 100644 index 0000000000..ec8839fe95 --- /dev/null +++ b/src/soc/nvidia/tegra132/ramstage.c @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void arm64_soc_init(void) +{ + trustzone_region_init(); + + tegra132_mmu_init(); + + clock_cpu0_config(); +} diff --git a/src/soc/nvidia/tegra132/reset.c b/src/soc/nvidia/tegra132/reset.c new file mode 100644 index 0000000000..dc49c3302b --- /dev/null +++ b/src/soc/nvidia/tegra132/reset.c @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +/* + * Promote cpu_reset() to a hard_reset(). A shallower reset can be added, + * if needed, at a later time. + */ +void cpu_reset(void) +{ + hard_reset(); +} diff --git a/src/soc/nvidia/tegra132/romstage.c b/src/soc/nvidia/tegra132/romstage.c new file mode 100644 index 0000000000..390059d07a --- /dev/null +++ b/src/soc/nvidia/tegra132/romstage.c @@ -0,0 +1,131 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void __attribute__((weak)) romstage_mainboard_init(void) +{ + /* Default empty implementation. */ +} + +static void *load_ramstage(void) +{ + void *entry; + struct stopwatch sw; + + stopwatch_init(&sw); + + timestamp_add_now(TS_START_COPYRAM); + +#if IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE) + entry = vboot2_load_ramstage(); +#else + /* + * This platform does not need to cache a loaded ramstage nor do we + * go down this path on resume. Therefore, no romstage_handoff is + * required. + */ + entry = vboot_verify_firmware_get_entry(NULL); +#endif + + if (entry == NULL) + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/ramstage"); + + timestamp_add_now(TS_END_COPYRAM); + + printk(BIOS_DEBUG, "Ramstage load time: %ld usecs.\n", + stopwatch_duration_usecs(&sw)); + + return entry; +} + +void romstage(void) +{ + void *entry; + + timestamp_add_now(TS_START_ROMSTAGE); + + console_init(); + exception_init(); + + printk(BIOS_INFO, "T132: romstage here\n"); + + timestamp_add_now(TS_BEFORE_INITRAM); + +#if CONFIG_BOOTROM_SDRAM_INIT + printk(BIOS_INFO, "T132 romstage: SDRAM init done by BootROM, RAMCODE = %d\n", + sdram_get_ram_code()); +#else + sdram_init(get_sdram_config()); + printk(BIOS_INFO, "T132 romstage: sdram_init done\n"); +#endif + + timestamp_add_now(TS_AFTER_INITRAM); + + /* + * Trust Zone needs to be initialized after the DRAM initialization + * because carveout registers are programmed during DRAM init. + * cbmem_initialize() is dependent on the Trust Zone region + * initalization because CBMEM lives right below the Trust Zone which + * needs to be properly identified. + */ + trustzone_region_init(); + + /* + * When romstage is running it's always on the reboot path -- never a + * resume path where cbmem recovery is required. Therefore, always + * initialize the cbmem area to be empty. + */ + cbmem_initialize_empty(); + + ccplex_cpu_prepare(); + printk(BIOS_INFO, "T132 romstage: cpu prepare done\n"); + + ccplex_load_mts(); + printk(BIOS_INFO, "T132 romstage: MTS loading done\n"); + + romstage_mainboard_init(); + + entry = load_ramstage(); + + if (entry == NULL) { + printk(BIOS_INFO, "T132 romstage: error loading ramstage\n"); + clock_halt_avp(); + } + + timestamp_add_now(TS_END_ROMSTAGE); + + ccplex_cpu_start(entry); + + clock_halt_avp(); +} diff --git a/src/soc/nvidia/tegra132/romstage_asm.S b/src/soc/nvidia/tegra132/romstage_asm.S new file mode 100644 index 0000000000..d0b036cbd6 --- /dev/null +++ b/src/soc/nvidia/tegra132/romstage_asm.S @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "stack.S" + + .section ".text", "ax", %progbits + +ENTRY(main) + stack_init stack_top=_estack stack_bottom=_stack seed=0 func=romstage +ENDPROC(main) diff --git a/src/soc/nvidia/tegra132/sdram.c b/src/soc/nvidia/tegra132/sdram.c new file mode 100644 index 0000000000..14d2b50fe1 --- /dev/null +++ b/src/soc/nvidia/tegra132/sdram.c @@ -0,0 +1,659 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void sdram_patch(uintptr_t addr, uint32_t value) +{ + if (addr) + writel(value, (uint32_t*)addr); +} + +static void writebits(uint32_t value, uint32_t *addr, uint32_t mask) +{ + clrsetbits_le32(addr, mask, (value & mask)); +} + +/* PMC must be configured before clock-enable and de-reset of MC/EMC. */ +static void sdram_configure_pmc(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* VDDP Select */ + writel(param->PmcVddpSel, ®s->vddp_sel); + udelay(param->PmcVddpSelWait); + + /* Set DDR pad voltage */ + writebits(param->PmcDdrPwr, ®s->ddr_pwr, PMC_DDR_PWR_VAL_MASK); + + /* Set package and DPD pad control */ + writebits(param->PmcDdrCfg, ®s->ddr_cfg, + (PMC_DDR_CFG_PKG_MASK | PMC_DDR_CFG_IF_MASK | + PMC_DDR_CFG_XM0_RESET_TRI_MASK | + PMC_DDR_CFG_XM0_RESET_DPDIO_MASK)); + + /* Turn on MEM IO Power */ + writebits(param->PmcNoIoPower, ®s->no_iopower, + (PMC_NO_IOPOWER_MEM_MASK | PMC_NO_IOPOWER_MEM_COMP_MASK)); + + writel(param->PmcRegShort, ®s->reg_short); +} + +static void sdram_start_clocks(const struct sdram_params *param) +{ + u32 is_same_freq = (param->McEmemArbMisc0 & + MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK) ? 1 : 0; + + clock_sdram(param->PllMInputDivider, param->PllMFeedbackDivider, + param->PllMSelectDiv2, param->PllMSetupControl, + param->PllMPDLshiftPh45, param->PllMPDLshiftPh90, + param->PllMPDLshiftPh135, param->PllMKVCO, + param->PllMKCP, param->PllMStableTime, + param->EmcClockSource, is_same_freq); +} + +static void sdram_deassert_clock_enable_signal(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK); + udelay(param->PmcPorDpdCtrlWait); +} + +static void sdram_deassert_sel_dpd(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + clrbits_le32(®s->por_dpd_ctrl, + (PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK | + PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK)); + /* + * Note NVIDIA recommended to always do 10us delay here and ignore + * BCT.PmcPorDpdCtrlWait. + * */ + udelay(10); +} + +static void sdram_set_swizzle(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + writel(param->EmcSwizzleRank0ByteCfg, ®s->swizzle_rank0_byte_cfg); + writel(param->EmcSwizzleRank0Byte0, ®s->swizzle_rank0_byte0); + writel(param->EmcSwizzleRank0Byte1, ®s->swizzle_rank0_byte1); + writel(param->EmcSwizzleRank0Byte2, ®s->swizzle_rank0_byte2); + writel(param->EmcSwizzleRank0Byte3, ®s->swizzle_rank0_byte3); + writel(param->EmcSwizzleRank1ByteCfg, ®s->swizzle_rank1_byte_cfg); + writel(param->EmcSwizzleRank1Byte0, ®s->swizzle_rank1_byte0); + writel(param->EmcSwizzleRank1Byte1, ®s->swizzle_rank1_byte1); + writel(param->EmcSwizzleRank1Byte2, ®s->swizzle_rank1_byte2); + writel(param->EmcSwizzleRank1Byte3, ®s->swizzle_rank1_byte3); +} + +static void sdram_set_pad_controls(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program the pad controls */ + writel(param->EmcXm2CmdPadCtrl, ®s->xm2cmdpadctrl); + writel(param->EmcXm2CmdPadCtrl2, ®s->xm2cmdpadctrl2); + writel(param->EmcXm2CmdPadCtrl3, ®s->xm2cmdpadctrl3); + writel(param->EmcXm2CmdPadCtrl4, ®s->xm2cmdpadctrl4); + writel(param->EmcXm2CmdPadCtrl5, ®s->xm2cmdpadctrl5); + + writel(param->EmcXm2DqsPadCtrl, ®s->xm2dqspadctrl); + writel(param->EmcXm2DqsPadCtrl2, ®s->xm2dqspadctrl2); + writel(param->EmcXm2DqsPadCtrl3, ®s->xm2dqspadctrl3); + writel(param->EmcXm2DqsPadCtrl4, ®s->xm2dqspadctrl4); + writel(param->EmcXm2DqsPadCtrl5, ®s->xm2dqspadctrl5); + writel(param->EmcXm2DqsPadCtrl6, ®s->xm2dqspadctrl6); + + writel(param->EmcXm2DqPadCtrl, ®s->xm2dqpadctrl); + writel(param->EmcXm2DqPadCtrl2, ®s->xm2dqpadctrl2); + writel(param->EmcXm2DqPadCtrl3, ®s->xm2dqpadctrl3); + + writel(param->EmcXm2ClkPadCtrl, ®s->xm2clkpadctrl); + writel(param->EmcXm2ClkPadCtrl2, ®s->xm2clkpadctrl2); + + writel(param->EmcXm2CompPadCtrl, ®s->xm2comppadctrl); + + writel(param->EmcXm2VttGenPadCtrl, ®s->xm2vttgenpadctrl); + writel(param->EmcXm2VttGenPadCtrl2, ®s->xm2vttgenpadctrl2); + writel(param->EmcXm2VttGenPadCtrl3, ®s->xm2vttgenpadctrl3); + + writel(param->EmcCttTermCtrl, ®s->ctt_term_ctrl); +} + +static void sdram_trigger_emc_timing_update(struct tegra_emc_regs *regs) +{ + writel(EMC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); +} + +static void sdram_init_mc(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Initialize MC VPR settings */ + writel(param->McDisplaySnapRing, ®s->display_snap_ring); + writel(param->McVideoProtectBom, ®s->video_protect_bom); + writel(param->McVideoProtectBomAdrHi, ®s->video_protect_bom_adr_hi); + writel(param->McVideoProtectSizeMb, ®s->video_protect_size_mb); + writel(param->McVideoProtectVprOverride, + ®s->video_protect_vpr_override); + writel(param->McVideoProtectVprOverride1, + ®s->video_protect_vpr_override1); + writel(param->McVideoProtectGpuOverride0, + ®s->video_protect_gpu_override_0); + writel(param->McVideoProtectGpuOverride1, + ®s->video_protect_gpu_override_1); + + /* Program SDRAM geometry paarameters */ + writel(param->McEmemAdrCfg, ®s->emem_adr_cfg); + writel(param->McEmemAdrCfgDev0, ®s->emem_adr_cfg_dev0); + writel(param->McEmemAdrCfgDev1, ®s->emem_adr_cfg_dev1); + + /* Program bank swizzling */ + writel(param->McEmemAdrCfgBankMask0, ®s->emem_bank_swizzle_cfg0); + writel(param->McEmemAdrCfgBankMask1, ®s->emem_bank_swizzle_cfg1); + writel(param->McEmemAdrCfgBankMask2, ®s->emem_bank_swizzle_cfg2); + writel(param->McEmemAdrCfgBankSwizzle3, ®s->emem_bank_swizzle_cfg3); + + /* Program external memory aperature (base and size) */ + writel(param->McEmemCfg, ®s->emem_cfg); + + /* Program SEC carveout (base and size) */ + writel(param->McSecCarveoutBom, ®s->sec_carveout_bom); + writel(param->McSecCarveoutAdrHi, ®s->sec_carveout_adr_hi); + writel(param->McSecCarveoutSizeMb, ®s->sec_carveout_size_mb); + + /* Program MTS carveout (base and size) */ + writel(param->McMtsCarveoutBom, ®s->mts_carveout_bom); + writel(param->McMtsCarveoutAdrHi, ®s->mts_carveout_adr_hi); + writel(param->McMtsCarveoutSizeMb, ®s->mts_carveout_size_mb); + + /* Program the memory arbiter */ + writel(param->McEmemArbCfg, ®s->emem_arb_cfg); + writel(param->McEmemArbOutstandingReq, ®s->emem_arb_outstanding_req); + writel(param->McEmemArbTimingRcd, ®s->emem_arb_timing_rcd); + writel(param->McEmemArbTimingRp, ®s->emem_arb_timing_rp); + writel(param->McEmemArbTimingRc, ®s->emem_arb_timing_rc); + writel(param->McEmemArbTimingRas, ®s->emem_arb_timing_ras); + writel(param->McEmemArbTimingFaw, ®s->emem_arb_timing_faw); + writel(param->McEmemArbTimingRrd, ®s->emem_arb_timing_rrd); + writel(param->McEmemArbTimingRap2Pre, ®s->emem_arb_timing_rap2pre); + writel(param->McEmemArbTimingWap2Pre, ®s->emem_arb_timing_wap2pre); + writel(param->McEmemArbTimingR2R, ®s->emem_arb_timing_r2r); + writel(param->McEmemArbTimingW2W, ®s->emem_arb_timing_w2w); + writel(param->McEmemArbTimingR2W, ®s->emem_arb_timing_r2w); + writel(param->McEmemArbTimingW2R, ®s->emem_arb_timing_w2r); + writel(param->McEmemArbDaTurns, ®s->emem_arb_da_turns); + writel(param->McEmemArbDaCovers, ®s->emem_arb_da_covers); + writel(param->McEmemArbMisc0, ®s->emem_arb_misc0); + writel(param->McEmemArbMisc1, ®s->emem_arb_misc1); + writel(param->McEmemArbRing1Throttle, ®s->emem_arb_ring1_throttle); + writel(param->McEmemArbOverride, ®s->emem_arb_override); + writel(param->McEmemArbOverride1, ®s->emem_arb_override_1); + writel(param->McEmemArbRsv, ®s->emem_arb_rsv); + + /* Program extra snap levels for display client */ + writel(param->McDisExtraSnapLevels, ®s->dis_extra_snap_levels); + + /* Trigger MC timing update */ + writel(MC_TIMING_CONTROL_TIMING_UPDATE, ®s->timing_control); + + /* Program second-level clock enable overrides */ + writel(param->McClkenOverride, ®s->clken_override); + + /* Program statistics gathering */ + writel(param->McStatControl, ®s->stat_control); +} + +static void sdram_init_emc(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program SDRAM geometry parameters */ + writel(param->EmcAdrCfg, ®s->adr_cfg); + + /* Program second-level clock enable overrides */ + writel(param->EmcClkenOverride, ®s->clken_override); + + /* Program EMC pad auto calibration */ + writel(param->EmcAutoCalInterval, ®s->auto_cal_interval); + writel(param->EmcAutoCalConfig2, ®s->auto_cal_config2); + writel(param->EmcAutoCalConfig3, ®s->auto_cal_config3); + writel(param->EmcAutoCalConfig, ®s->auto_cal_config); + udelay(param->EmcAutoCalWait); +} + +static void sdram_set_emc_timing(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program EMC timing configuration */ + writel(param->EmcCfg2, ®s->cfg_2); + writel(param->EmcCfgPipe, ®s->cfg_pipe); + writel(param->EmcDbg, ®s->dbg); + writel(param->EmcCmdQ, ®s->cmdq); + writel(param->EmcMc2EmcQ, ®s->mc2emcq); + writel(param->EmcMrsWaitCnt, ®s->mrs_wait_cnt); + writel(param->EmcMrsWaitCnt2, ®s->mrs_wait_cnt2); + writel(param->EmcFbioCfg5, ®s->fbio_cfg5); + writel(param->EmcRc, ®s->rc); + writel(param->EmcRfc, ®s->rfc); + writel(param->EmcRfcSlr, ®s->rfc_slr); + writel(param->EmcRas, ®s->ras); + writel(param->EmcRp, ®s->rp); + writel(param->EmcR2r, ®s->r2r); + writel(param->EmcW2w, ®s->w2w); + writel(param->EmcR2w, ®s->r2w); + writel(param->EmcW2r, ®s->w2r); + writel(param->EmcR2p, ®s->r2p); + writel(param->EmcW2p, ®s->w2p); + writel(param->EmcRdRcd, ®s->rd_rcd); + writel(param->EmcWrRcd, ®s->wr_rcd); + writel(param->EmcRrd, ®s->rrd); + writel(param->EmcRext, ®s->rext); + writel(param->EmcWext, ®s->wext); + writel(param->EmcWdv, ®s->wdv); + writel(param->EmcWdvMask, ®s->wdv_mask); + writel(param->EmcQUse, ®s->quse); + writel(param->EmcQuseWidth, ®s->quse_width); + writel(param->EmcIbdly, ®s->ibdly); + writel(param->EmcEInput, ®s->einput); + writel(param->EmcEInputDuration, ®s->einput_duration); + writel(param->EmcPutermExtra, ®s->puterm_extra); + writel(param->EmcPutermWidth, ®s->puterm_width); + writel(param->EmcPutermAdj, ®s->puterm_adj); + writel(param->EmcCdbCntl1, ®s->cdb_cntl_1); + writel(param->EmcCdbCntl2, ®s->cdb_cntl_2); + writel(param->EmcCdbCntl3, ®s->cdb_cntl_3); + writel(param->EmcQRst, ®s->qrst); + writel(param->EmcQSafe, ®s->qsafe); + writel(param->EmcRdv, ®s->rdv); + writel(param->EmcRdvMask, ®s->rdv_mask); + writel(param->EmcQpop, ®s->qpop); + writel(param->EmcCtt, ®s->ctt); + writel(param->EmcCttDuration, ®s->ctt_duration); + writel(param->EmcRefresh, ®s->refresh); + writel(param->EmcBurstRefreshNum, ®s->burst_refresh_num); + writel(param->EmcPreRefreshReqCnt, ®s->pre_refresh_req_cnt); + writel(param->EmcPdEx2Wr, ®s->pdex2wr); + writel(param->EmcPdEx2Rd, ®s->pdex2rd); + writel(param->EmcPChg2Pden, ®s->pchg2pden); + writel(param->EmcAct2Pden, ®s->act2pden); + writel(param->EmcAr2Pden, ®s->ar2pden); + writel(param->EmcRw2Pden, ®s->rw2pden); + writel(param->EmcTxsr, ®s->txsr); + writel(param->EmcTxsrDll, ®s->txsrdll); + writel(param->EmcTcke, ®s->tcke); + writel(param->EmcTckesr, ®s->tckesr); + writel(param->EmcTpd, ®s->tpd); + writel(param->EmcTfaw, ®s->tfaw); + writel(param->EmcTrpab, ®s->trpab); + writel(param->EmcTClkStable, ®s->tclkstable); + writel(param->EmcTClkStop, ®s->tclkstop); + writel(param->EmcTRefBw, ®s->trefbw); + writel(param->EmcOdtWrite, ®s->odt_write); + writel(param->EmcOdtRead, ®s->odt_read); + writel(param->EmcFbioCfg6, ®s->fbio_cfg6); + writel(param->EmcCfgDigDll, ®s->cfg_dig_dll); + writel(param->EmcCfgDigDllPeriod, ®s->cfg_dig_dll_period); + + /* Don't write bit 1: addr swizzle lock bit. Written at end of sequence. */ + writel(param->EmcFbioSpare & 0xfffffffd, ®s->fbio_spare); + + writel(param->EmcCfgRsv, ®s->cfg_rsv); + writel(param->EmcDllXformDqs0, ®s->dll_xform_dqs0); + writel(param->EmcDllXformDqs1, ®s->dll_xform_dqs1); + writel(param->EmcDllXformDqs2, ®s->dll_xform_dqs2); + writel(param->EmcDllXformDqs3, ®s->dll_xform_dqs3); + writel(param->EmcDllXformDqs4, ®s->dll_xform_dqs4); + writel(param->EmcDllXformDqs5, ®s->dll_xform_dqs5); + writel(param->EmcDllXformDqs6, ®s->dll_xform_dqs6); + writel(param->EmcDllXformDqs7, ®s->dll_xform_dqs7); + writel(param->EmcDllXformDqs8, ®s->dll_xform_dqs8); + writel(param->EmcDllXformDqs9, ®s->dll_xform_dqs9); + writel(param->EmcDllXformDqs10, ®s->dll_xform_dqs10); + writel(param->EmcDllXformDqs11, ®s->dll_xform_dqs11); + writel(param->EmcDllXformDqs12, ®s->dll_xform_dqs12); + writel(param->EmcDllXformDqs13, ®s->dll_xform_dqs13); + writel(param->EmcDllXformDqs14, ®s->dll_xform_dqs14); + writel(param->EmcDllXformDqs15, ®s->dll_xform_dqs15); + writel(param->EmcDllXformQUse0, ®s->dll_xform_quse0); + writel(param->EmcDllXformQUse1, ®s->dll_xform_quse1); + writel(param->EmcDllXformQUse2, ®s->dll_xform_quse2); + writel(param->EmcDllXformQUse3, ®s->dll_xform_quse3); + writel(param->EmcDllXformQUse4, ®s->dll_xform_quse4); + writel(param->EmcDllXformQUse5, ®s->dll_xform_quse5); + writel(param->EmcDllXformQUse6, ®s->dll_xform_quse6); + writel(param->EmcDllXformQUse7, ®s->dll_xform_quse7); + writel(param->EmcDllXformQUse8, ®s->dll_xform_quse8); + writel(param->EmcDllXformQUse9, ®s->dll_xform_quse9); + writel(param->EmcDllXformQUse10, ®s->dll_xform_quse10); + writel(param->EmcDllXformQUse11, ®s->dll_xform_quse11); + writel(param->EmcDllXformQUse12, ®s->dll_xform_quse12); + writel(param->EmcDllXformQUse13, ®s->dll_xform_quse13); + writel(param->EmcDllXformQUse14, ®s->dll_xform_quse14); + writel(param->EmcDllXformQUse15, ®s->dll_xform_quse15); + writel(param->EmcDllXformDq0, ®s->dll_xform_dq0); + writel(param->EmcDllXformDq1, ®s->dll_xform_dq1); + writel(param->EmcDllXformDq2, ®s->dll_xform_dq2); + writel(param->EmcDllXformDq3, ®s->dll_xform_dq3); + writel(param->EmcDllXformDq4, ®s->dll_xform_dq4); + writel(param->EmcDllXformDq5, ®s->dll_xform_dq5); + writel(param->EmcDllXformDq6, ®s->dll_xform_dq6); + writel(param->EmcDllXformDq7, ®s->dll_xform_dq7); + writel(param->EmcDllXformAddr0, ®s->dll_xform_addr0); + writel(param->EmcDllXformAddr1, ®s->dll_xform_addr1); + writel(param->EmcDllXformAddr2, ®s->dll_xform_addr2); + writel(param->EmcDllXformAddr3, ®s->dll_xform_addr3); + writel(param->EmcDllXformAddr4, ®s->dll_xform_addr4); + writel(param->EmcDllXformAddr5, ®s->dll_xform_addr5); + writel(param->EmcAcpdControl, ®s->acpd_control); + writel(param->EmcDsrVttgenDrv, ®s->dsr_vttgen_drv); + writel(param->EmcTxdsrvttgen, ®s->txdsrvttgen); + writel(param->EmcBgbiasCtl0, ®s->bgbias_ctl0); + + /* + * Set pipe bypass enable bits before sending any DRAM commands. + * Note other bits in EMC_CFG must be set AFTER REFCTRL is configured. + */ + writebits(param->EmcCfg, ®s->cfg, + (EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK | + EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK)); +} + +static void sdram_patch_bootrom(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + if (param->BootRomPatchControl & BOOT_ROM_PATCH_CONTROL_ENABLE_MASK) { + uintptr_t addr = ((param->BootRomPatchControl & + BOOT_ROM_PATCH_CONTROL_OFFSET_MASK) >> + BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT); + addr = BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS + (addr << 2); + writel(param->BootRomPatchData, (uint32_t *)addr); + writel(1, ®s->timing_control); + } +} + +static void sdram_set_dpd3(const struct sdram_params *param, + struct tegra_pmc_regs *regs) +{ + /* Program DPD request */ + writel(param->PmcIoDpd3Req, ®s->io_dpd3_req); + udelay(param->PmcIoDpd3ReqWait); +} + +static void sdram_set_dli_trims(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Program DLI trims */ + writel(param->EmcDliTrimTxDqs0, ®s->dli_trim_txdqs0); + writel(param->EmcDliTrimTxDqs1, ®s->dli_trim_txdqs1); + writel(param->EmcDliTrimTxDqs2, ®s->dli_trim_txdqs2); + writel(param->EmcDliTrimTxDqs3, ®s->dli_trim_txdqs3); + writel(param->EmcDliTrimTxDqs4, ®s->dli_trim_txdqs4); + writel(param->EmcDliTrimTxDqs5, ®s->dli_trim_txdqs5); + writel(param->EmcDliTrimTxDqs6, ®s->dli_trim_txdqs6); + writel(param->EmcDliTrimTxDqs7, ®s->dli_trim_txdqs7); + writel(param->EmcDliTrimTxDqs8, ®s->dli_trim_txdqs8); + writel(param->EmcDliTrimTxDqs9, ®s->dli_trim_txdqs9); + writel(param->EmcDliTrimTxDqs10, ®s->dli_trim_txdqs10); + writel(param->EmcDliTrimTxDqs11, ®s->dli_trim_txdqs11); + writel(param->EmcDliTrimTxDqs12, ®s->dli_trim_txdqs12); + writel(param->EmcDliTrimTxDqs13, ®s->dli_trim_txdqs13); + writel(param->EmcDliTrimTxDqs14, ®s->dli_trim_txdqs14); + writel(param->EmcDliTrimTxDqs15, ®s->dli_trim_txdqs15); + + writel(param->EmcCaTrainingTimingCntl1, + ®s->ca_training_timing_cntl1); + writel(param->EmcCaTrainingTimingCntl2, + ®s->ca_training_timing_cntl2); + + sdram_trigger_emc_timing_update(regs); + udelay(param->EmcTimingControlWait); +} + +static void sdram_set_clock_enable_signal(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + volatile uint32_t dummy = 0; + clrbits_le32(®s->pin, (EMC_PIN_RESET_MASK | EMC_PIN_DQM_MASK | + EMC_PIN_CKE_MASK)); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(200 + param->EmcPinExtraWait); + + /* Deassert reset */ + setbits_le32(®s->pin, EMC_PIN_RESET_INACTIVE); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(500 + param->EmcPinExtraWait); + + /* Enable clock enable signal */ + setbits_le32(®s->pin, EMC_PIN_CKE_NORMAL); + /* + * Assert dummy read of PIN register to ensure above write to PIN + * register went through. 200 is the recommended value by NVIDIA. + */ + dummy |= readl(®s->pin); + udelay(param->EmcPinProgramWait); + + if (!dummy) { + die("Failed to program EMC pin."); + } + + /* Send NOP (trigger) */ + writebits(((1 << EMC_NOP_NOP_CMD_SHIFT) | + (param->EmcDevSelect << EMC_NOP_NOP_DEV_SELECTN_SHIFT)), + ®s->nop, + EMC_NOP_NOP_CMD_MASK | EMC_NOP_NOP_DEV_SELECTN_MASK); +} + +static void sdram_init_ddr3(const struct sdram_params *param, struct tegra_emc_regs *regs) +{ + /* Write mode registers */ + writel(param->EmcEmrs2, ®s->emrs2); + writel(param->EmcEmrs3, ®s->emrs3); + writel(param->EmcEmrs, ®s->emrs); + writel(param->EmcMrs, ®s->mrs); + + if (param->EmcExtraModeRegWriteEnable) { + writel(param->EmcMrsExtra, ®s->mrs); + } + + writel(param->EmcZcalInitDev0, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + + if ((param->EmcDevSelect & 2) == 0) { + writel(param->EmcZcalInitDev1, ®s->zq_cal); + udelay(param->EmcZcalInitWait); + } +} + +static void sdram_init_lpddr3(const struct sdram_params *param, struct tegra_emc_regs *regs) +{ + /* Precharge all banks. DEV_SELECTN = 0 => Select all devices */ + writel(((param->EmcDevSelect << EMC_REF_DEV_SELECTN_SHIFT) | 1), ®s->pre); + + /* Send Reset MRW command */ + writel(param->EmcMrwResetCommand, ®s->mrw); + udelay(param->EmcMrwResetNInitWait); + + writel(param->EmcZcalInitDev0, ®s->mrw); + udelay(param->EmcZcalInitWait); + + if ((param->EmcDevSelect & 2) == 0) + { + writel(param->EmcZcalInitDev1, ®s->mrw); + udelay(param->EmcZcalInitWait); + } + + /* Write mode registers */ + writel(param->EmcMrw2, ®s->mrw2); + writel(param->EmcMrw1, ®s->mrw); + writel(param->EmcMrw3, ®s->mrw3); + writel(param->EmcMrw4, ®s->mrw4); + + if (param->EmcExtraModeRegWriteEnable) { + writel(param->EmcMrwExtra, ®s->mrw); + } +} + +static void sdram_init_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + if ((param->EmcZcalWarmColdBootEnables & + EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK) == 1) { + /* Need to initialize ZCAL on coldboot. */ + if (param->MemoryType == NvBootMemoryType_Ddr3) + sdram_init_ddr3(param, regs); + else if (param->MemoryType == NvBootMemoryType_LpDdr2) + sdram_init_lpddr3(param, regs); + } else { + /* Wait for DLL stablization time even without ZCAL */ + udelay(param->EmcZcalInitWait); + } +} + +static void sdram_set_zq_calibration(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Start periodic ZQ calibration */ + writel(param->EmcZcalInterval, ®s->zcal_interval); + writel(param->EmcZcalWaitCnt, ®s->zcal_wait_cnt); + writel(param->EmcZcalMrwCmd, ®s->zcal_mrw_cmd); +} + +static void sdram_set_refresh(const struct sdram_params *param, + struct tegra_emc_regs *regs) +{ + /* Insert burst refresh */ + if (param->EmcExtraRefreshNum > 0) { + uint32_t refresh_num = (1 << param->EmcExtraRefreshNum) - 1; + writebits((EMC_REF_CMD_REFRESH | EMC_REF_NORMAL_ENABLED | + (refresh_num << EMC_REF_NUM_SHIFT) | + (param->EmcDevSelect << EMC_REF_DEV_SELECTN_SHIFT)), + ®s->ref, (EMC_REF_CMD_MASK | EMC_REF_NORMAL_MASK | + EMC_REF_NUM_MASK | + EMC_REF_DEV_SELECTN_MASK)); + } + + /* Enable refresh */ + writel((param->EmcDevSelect | EMC_REFCTRL_REF_VALID_ENABLED), + ®s->refctrl); + + writel(param->EmcDynSelfRefControl, ®s->dyn_self_ref_control); + writel(param->EmcCfg, ®s->cfg); + writel(param->EmcSelDpdCtrl, ®s->sel_dpd_ctrl); + + /* Write addr swizzle lock bit */ + writel(param->EmcFbioSpare, ®s->fbio_spare); + + /* Re-trigger timing to latch power saving functions */ + sdram_trigger_emc_timing_update(regs); +} + +static void sdram_enable_arbiter(const struct sdram_params *param) +{ + /* TODO(hungte) Move values here to standalone header file. */ + uint32_t *AHB_ARBITRATION_XBAR_CTRL = (uint32_t*)(0x6000c000 + 0xe0); + setbits_le32(AHB_ARBITRATION_XBAR_CTRL, + param->AhbArbitrationXbarCtrlMemInitDone << 16); +} + +static void sdram_lock_carveouts(const struct sdram_params *param, + struct tegra_mc_regs *regs) +{ + /* Lock carveouts, and emem_cfg registers */ + writel(param->McVideoProtectWriteAccess, ®s->video_protect_reg_ctrl); + writel(MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED, + ®s->emem_cfg_access_ctrl); + writel(param->McSecCarveoutProtectWriteAccess, + ®s->sec_carveout_reg_ctrl); + writel(param->McMtsCarveoutRegCtrl, ®s->mts_carveout_reg_ctrl); +} + +void sdram_init(const struct sdram_params *param) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + struct tegra_mc_regs *mc = (struct tegra_mc_regs*)TEGRA_MC_BASE; + struct tegra_emc_regs *emc = (struct tegra_emc_regs*)TEGRA_EMC_BASE; + + printk(BIOS_DEBUG, "Initializing SDRAM of type %d with %dKHz\n", + param->MemoryType, clock_get_pll_input_khz() * + param->PllMFeedbackDivider / param->PllMInputDivider / + (1 + param->PllMSelectDiv2)); + if (param->MemoryType != NvBootMemoryType_Ddr3 && + param->MemoryType != NvBootMemoryType_LpDdr2) + die("Unsupported memory type!\n"); + + sdram_configure_pmc(param, pmc); + sdram_patch(param->EmcBctSpare0, param->EmcBctSpare1); + + sdram_start_clocks(param); + sdram_patch(param->EmcBctSpare2, param->EmcBctSpare3); + + sdram_deassert_sel_dpd(param, pmc); + sdram_set_swizzle(param, emc); + sdram_set_pad_controls(param, emc); + sdram_patch(param->EmcBctSpare4, param->EmcBctSpare5); + + sdram_trigger_emc_timing_update(emc); + sdram_init_mc(param, mc); + sdram_init_emc(param, emc); + sdram_patch(param->EmcBctSpare6, param->EmcBctSpare7); + + sdram_set_emc_timing(param, emc); + sdram_patch_bootrom(param, mc); + sdram_set_dpd3(param, pmc); + sdram_set_dli_trims(param, emc); + sdram_deassert_clock_enable_signal(param, pmc); + sdram_set_clock_enable_signal(param, emc); + sdram_init_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare8, param->EmcBctSpare9); + + sdram_set_zq_calibration(param, emc); + sdram_patch(param->EmcBctSpare10, param->EmcBctSpare11); + + sdram_trigger_emc_timing_update(emc); + sdram_set_refresh(param, emc); + sdram_enable_arbiter(param); + sdram_lock_carveouts(param, mc); + + sdram_lp0_save_params(param); +} + +uint32_t sdram_get_ram_code(void) +{ + struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; + return ((readl(&pmc->strapping_opt_a) & + PMC_STRAPPING_OPT_A_RAM_CODE_MASK) >> + PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT); +} diff --git a/src/soc/nvidia/tegra132/sdram_lp0.c b/src/soc/nvidia/tegra132/sdram_lp0.c new file mode 100644 index 0000000000..c63b823006 --- /dev/null +++ b/src/soc/nvidia/tegra132/sdram_lp0.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * This function reads SDRAM parameters (and a few CLK_RST regsiter values) from + * the common BCT format and writes them into PMC scratch registers (where the + * BootROM expects them on LP0 resume). Since those store the same values in a + * different format, we follow a "translation table" taken from Nvidia's U-Boot + * implementation to shift bits into the right position. + * + * Contrary to U-Boot, we transform the same macros directly into hardcoded + * assignments (without any pesky function calls or volatile qualifiers) to give + * the compiler as much room for optimization as possible. For that reason, we + * also intentionally avoid read/write macros, under the assumption + * that PMC scratch register accesses should not have side effects and can be + * arbitrarily reordered. For the few accesses that do have side-effects, the + * code must contain explicit memory barriers. + */ +void sdram_lp0_save_params(const struct sdram_params *sdram) +{ + struct tegra_pmc_regs * pmc = (void *)TEGRA_PMC_BASE; + struct clk_rst_ctlr * clk_rst = (void *)TEGRA_CLK_RST_BASE; + +#define pack(src, src_bits, dst, dst_bits) { \ + _Static_assert((1 ? src_bits) >= (0 ? src_bits) && (1 ? dst_bits) >= \ + (0 ? dst_bits), "byte range flipped (must be MSB:LSB)" ); \ + _Static_assert((1 ? src_bits) - (0 ? src_bits) == (1 ? dst_bits) - \ + (0 ? dst_bits), "src and dst byte range lengths differ" ); \ + u32 mask = 0xffffffff >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \ + dst &= ~(mask << (0 ? dst_bits)); \ + dst |= ((src >> (0 ? src_bits)) & mask) << (0 ? dst_bits); \ +} + +#define s(param, src_bits, pmcreg, dst_bits) \ + pack(sdram->param, src_bits, pmc->pmcreg, dst_bits) + +#define m(clkreg, src_bits, pmcreg, dst_bits) \ + pack(clk_rst->clkreg, src_bits, pmc->pmcreg, dst_bits) + +#define c(value, pmcreg, dst_bits) \ + pack(value, (1 ? dst_bits) - (0 ? dst_bits) : 0, pmc->pmcreg, dst_bits) + + s(EmcClockSource, 7:0, scratch6, 15:8); + s(EmcClockSource, 31:29, scratch6, 18:16); + s(EmcClockSource, 26:26, scratch6, 19:19); + s(EmcOdtWrite, 5:0, scratch6, 25:20); + s(EmcOdtWrite, 11:8, scratch6, 29:26); + s(EmcOdtWrite, 30:30, scratch6, 30:30); + s(EmcOdtWrite, 31:31, scratch6, 31:31); + s(EmcXm2DqPadCtrl2, 18:16, scratch7, 22:20); + s(EmcXm2DqPadCtrl2, 22:20, scratch7, 25:23); + s(EmcXm2DqPadCtrl2, 26:24, scratch7, 28:26); + s(EmcXm2DqPadCtrl2, 30:28, scratch7, 31:29); + s(EmcXm2DqPadCtrl3, 18:16, scratch8, 22:20); + s(EmcXm2DqPadCtrl3, 22:20, scratch8, 25:23); + s(EmcXm2DqPadCtrl3, 26:24, scratch8, 28:26); + s(EmcXm2DqPadCtrl3, 30:28, scratch8, 31:29); + s(EmcTxsrDll, 11:0, scratch9, 31:20); + c(0, scratch10, 31:0); + s(EmcDsrVttgenDrv, 5:0, scratch10, 25:20); + s(EmcDsrVttgenDrv, 18:16, scratch10, 28:26); + s(EmcDsrVttgenDrv, 26:24, scratch10, 31:29); + s(EmcFbioSpare, 31:24, scratch11, 7:0); + s(EmcFbioSpare, 23:16, scratch11, 15:8); + s(EmcFbioSpare, 15:8, scratch11, 23:16); + s(EmcFbioSpare, 7:0, scratch11, 31:24); + s(EmcCfgRsv, 31:0, scratch12, 31:0); + s(EmcCdbCntl2, 31:0, scratch13, 31:0); + s(McEmemArbDaTurns, 31:0, scratch14, 31:0); + s(EmcCfgDigDll, 0:0, scratch17, 0:0); + s(EmcCfgDigDll, 25:2, scratch17, 24:1); + s(EmcCfgDigDll, 31:27, scratch17, 29:25); + s(EmcCdbCntl1, 29:0, scratch18, 29:0); + s(McEmemArbMisc0, 14:0, scratch19, 14:0); + s(McEmemArbMisc0, 30:16, scratch19, 29:15); + s(EmcXm2DqsPadCtrl, 4:0, scratch22, 4:0); + s(EmcXm2DqsPadCtrl, 12:8, scratch22, 9:5); + s(EmcXm2DqsPadCtrl, 31:14, scratch22, 27:10); + s(EmcRrd, 3:0, scratch22, 31:28); + s(EmcXm2DqPadCtrl, 31:4, scratch23, 27:0); + s(EmcRext, 3:0, scratch23, 31:28); + s(EmcXm2CompPadCtrl, 16:0, scratch24, 16:0); + s(EmcXm2CompPadCtrl, 24:20, scratch24, 21:17); + s(EmcXm2CompPadCtrl, 27:27, scratch24, 22:22); + s(EmcXm2CompPadCtrl, 31:28, scratch24, 26:23); + s(EmcR2w, 4:0, scratch24, 31:27); + s(EmcCfg, 9:1, scratch25, 8:0); + s(EmcCfg, 26:16, scratch25, 19:9); + s(EmcCfg, 31:28, scratch25, 23:20); + s(EmcXm2VttGenPadCtrl, 0:0, scratch25, 24:24); + s(EmcXm2VttGenPadCtrl, 2:2, scratch25, 25:25); + s(EmcXm2VttGenPadCtrl, 18:16, scratch25, 28:26); + s(EmcXm2VttGenPadCtrl, 26:24, scratch25, 31:29); + s(EmcZcalInterval, 23:10, scratch26, 13:0); + s(EmcZcalInterval, 9:0, scratch26, 23:14); + s(EmcSelDpdCtrl, 5:2, scratch26, 27:24); + s(EmcSelDpdCtrl, 8:8, scratch26, 28:28); + s(EmcSelDpdCtrl, 18:16, scratch26, 31:29); + s(EmcXm2VttGenPadCtrl3, 22:0, scratch27, 22:0); + s(EmcXm2VttGenPadCtrl3, 24:24, scratch27, 23:23); + s(EmcSwizzleRank0ByteCfg, 1:0, scratch27, 25:24); + s(EmcSwizzleRank0ByteCfg, 5:4, scratch27, 27:26); + s(EmcSwizzleRank0ByteCfg, 9:8, scratch27, 29:28); + s(EmcSwizzleRank0ByteCfg, 13:12, scratch27, 31:30); + s(EmcXm2ClkPadCtrl2, 5:0, scratch28, 5:0); + s(EmcXm2ClkPadCtrl2, 13:8, scratch28, 11:6); + s(EmcXm2ClkPadCtrl2, 20:16, scratch28, 16:12); + s(EmcXm2ClkPadCtrl2, 23:23, scratch28, 17:17); + s(EmcXm2ClkPadCtrl2, 28:24, scratch28, 22:18); + s(EmcXm2ClkPadCtrl2, 31:31, scratch28, 23:23); + s(EmcSwizzleRank1ByteCfg, 1:0, scratch28, 25:24); + s(EmcSwizzleRank1ByteCfg, 5:4, scratch28, 27:26); + s(EmcSwizzleRank1ByteCfg, 9:8, scratch28, 29:28); + s(EmcSwizzleRank1ByteCfg, 13:12, scratch28, 31:30); + s(McEmemArbDaCovers, 23:0, scratch29, 23:0); + s(McEmemArbRsv, 7:0, scratch29, 31:24); + s(EmcAutoCalConfig, 4:0, scratch30, 4:0); + s(EmcAutoCalConfig, 12:8, scratch30, 9:5); + s(EmcAutoCalConfig, 18:16, scratch30, 12:10); + s(EmcAutoCalConfig, 25:20, scratch30, 18:13); + s(EmcAutoCalConfig, 31:28, scratch30, 22:19); + s(EmcRfc, 8:0, scratch30, 31:23); + s(EmcXm2DqsPadCtrl2, 21:0, scratch31, 21:0); + s(EmcXm2DqsPadCtrl2, 24:24, scratch31, 22:22); + s(EmcAr2Pden, 8:0, scratch31, 31:23); + s(EmcXm2ClkPadCtrl, 0:0, scratch32, 0:0); + s(EmcXm2ClkPadCtrl, 4:2, scratch32, 3:1); + s(EmcXm2ClkPadCtrl, 7:7, scratch32, 4:4); + s(EmcXm2ClkPadCtrl, 31:14, scratch32, 22:5); + s(EmcRfcSlr, 8:0, scratch32, 31:23); + s(EmcXm2DqsPadCtrl3, 0:0, scratch33, 0:0); + s(EmcXm2DqsPadCtrl3, 5:5, scratch33, 1:1); + s(EmcXm2DqsPadCtrl3, 12:8, scratch33, 6:2); + s(EmcXm2DqsPadCtrl3, 18:14, scratch33, 11:7); + s(EmcXm2DqsPadCtrl3, 24:20, scratch33, 16:12); + s(EmcXm2DqsPadCtrl3, 30:26, scratch33, 21:17); + s(EmcTxsr, 9:0, scratch33, 31:22); + s(McEmemArbCfg, 8:0, scratch40, 8:0); + s(McEmemArbCfg, 20:16, scratch40, 13:9); + s(McEmemArbCfg, 27:24, scratch40, 17:14); + s(McEmemArbCfg, 31:28, scratch40, 21:18); + s(EmcMc2EmcQ, 2:0, scratch40, 24:22); + s(EmcMc2EmcQ, 10:8, scratch40, 27:25); + s(EmcMc2EmcQ, 27:24, scratch40, 31:28); + s(EmcAutoCalInterval, 20:0, scratch42, 20:0); + s(McEmemArbOutstandingReq, 8:0, scratch42, 29:21); + s(McEmemArbOutstandingReq, 31:30, scratch42, 31:30); + s(EmcMrsWaitCnt2, 9:0, scratch44, 9:0); + s(EmcMrsWaitCnt2, 25:16, scratch44, 19:10); + s(EmcTxdsrvttgen, 11:0, scratch44, 31:20); + s(EmcMrsWaitCnt, 9:0, scratch45, 9:0); + s(EmcMrsWaitCnt, 25:16, scratch45, 19:10); + s(EmcCfgPipe, 1:0, scratch45, 21:20); + s(EmcCfgPipe, 9:4, scratch45, 27:22); + s(EmcCfgPipe, 15:12, scratch45, 31:28); + s(EmcXm2DqsPadCtrl4, 22:18, scratch46, 4:0); + s(EmcXm2DqsPadCtrl4, 16:12, scratch46, 9:5); + s(EmcXm2DqsPadCtrl4, 10:6, scratch46, 14:10); + s(EmcXm2DqsPadCtrl4, 4:0, scratch46, 19:15); + s(EmcZcalWaitCnt, 9:0, scratch46, 29:20); + s(EmcXm2DqsPadCtrl5, 22:18, scratch47, 4:0); + s(EmcXm2DqsPadCtrl5, 16:12, scratch47, 9:5); + s(EmcXm2DqsPadCtrl5, 10:6, scratch47, 14:10); + s(EmcXm2DqsPadCtrl5, 4:0, scratch47, 19:15); + s(EmcXm2VttGenPadCtrl2, 5:0, scratch47, 25:20); + s(EmcXm2VttGenPadCtrl2, 31:28, scratch47, 29:26); + s(EmcXm2DqsPadCtrl6, 12:8, scratch48, 4:0); + s(EmcXm2DqsPadCtrl6, 18:14, scratch48, 9:5); + s(EmcXm2DqsPadCtrl6, 24:20, scratch48, 14:10); + s(EmcXm2DqsPadCtrl6, 30:26, scratch48, 19:15); + s(EmcAutoCalConfig3, 4:0, scratch48, 24:20); + s(EmcAutoCalConfig3, 12:8, scratch48, 29:25); + s(EmcFbioCfg5, 1:0, scratch48, 31:30); + s(EmcDllXformQUse8, 4:0, scratch50, 4:0); + s(EmcDllXformQUse8, 22:8, scratch50, 19:5); + s(McEmemArbRing1Throttle, 4:0, scratch50, 24:20); + s(McEmemArbRing1Throttle, 20:16, scratch50, 29:25); + s(EmcFbioCfg5, 3:2, scratch50, 31:30); + s(EmcDllXformQUse9, 4:0, scratch51, 4:0); + s(EmcDllXformQUse9, 22:8, scratch51, 19:5); + s(EmcCttTermCtrl, 2:0, scratch51, 22:20); + s(EmcCttTermCtrl, 12:8, scratch51, 27:23); + s(EmcCttTermCtrl, 31:31, scratch51, 28:28); + s(EmcFbioCfg6, 2:0, scratch51, 31:29); + s(EmcDllXformQUse10, 4:0, scratch56, 4:0); + s(EmcDllXformQUse10, 22:8, scratch56, 19:5); + s(EmcXm2CmdPadCtrl, 10:3, scratch56, 27:20); + s(EmcXm2CmdPadCtrl, 28:28, scratch56, 28:28); + s(EmcPutermAdj, 1:0, scratch56, 30:29); + s(EmcPutermAdj, 7:7, scratch56, 31:31); + s(EmcDllXformQUse11, 4:0, scratch57, 4:0); + s(EmcDllXformQUse11, 22:8, scratch57, 19:5); + s(EmcWdv, 3:0, scratch57, 31:28); + s(EmcDllXformQUse12, 4:0, scratch58, 4:0); + s(EmcDllXformQUse12, 22:8, scratch58, 19:5); + s(EmcBurstRefreshNum, 3:0, scratch58, 31:28); + s(EmcDllXformQUse13, 4:0, scratch59, 4:0); + s(EmcDllXformQUse13, 22:8, scratch59, 19:5); + s(EmcWext, 3:0, scratch59, 31:28); + s(EmcDllXformQUse14, 4:0, scratch60, 4:0); + s(EmcDllXformQUse14, 22:8, scratch60, 19:5); + s(EmcClkenOverride, 3:1, scratch60, 30:28); + s(EmcClkenOverride, 6:6, scratch60, 31:31); + s(EmcDllXformQUse15, 4:0, scratch61, 4:0); + s(EmcDllXformQUse15, 22:8, scratch61, 19:5); + s(EmcR2r, 3:0, scratch61, 31:28); + s(EmcDllXformDq4, 4:0, scratch62, 4:0); + s(EmcDllXformDq4, 22:8, scratch62, 19:5); + s(EmcRc, 6:0, scratch62, 26:20); + s(EmcW2r, 4:0, scratch62, 31:27); + s(EmcDllXformDq5, 4:0, scratch63, 4:0); + s(EmcDllXformDq5, 22:8, scratch63, 19:5); + s(EmcTfaw, 6:0, scratch63, 26:20); + s(EmcR2p, 4:0, scratch63, 31:27); + s(EmcDllXformDq6, 4:0, scratch64, 4:0); + s(EmcDllXformDq6, 22:8, scratch64, 19:5); + s(EmcDliTrimTxDqs0, 6:0, scratch64, 26:20); + s(EmcQSafe, 4:0, scratch64, 31:27); + s(EmcDllXformDq7, 4:0, scratch65, 4:0); + s(EmcDllXformDq7, 22:8, scratch65, 19:5); + s(EmcDliTrimTxDqs1, 6:0, scratch65, 26:20); + s(EmcTClkStable, 4:0, scratch65, 31:27); + s(EmcAutoCalConfig2, 4:0, scratch66, 4:0); + s(EmcAutoCalConfig2, 12:8, scratch66, 9:5); + s(EmcAutoCalConfig2, 20:16, scratch66, 14:10); + s(EmcAutoCalConfig2, 28:24, scratch66, 19:15); + s(EmcDliTrimTxDqs2, 6:0, scratch66, 26:20); + s(EmcTClkStop, 4:0, scratch66, 31:27); + s(McEmemArbMisc1, 1:0, scratch67, 1:0); + s(McEmemArbMisc1, 12:4, scratch67, 10:2); + s(McEmemArbMisc1, 25:21, scratch67, 15:11); + s(McEmemArbMisc1, 31:28, scratch67, 19:16); + s(EmcDliTrimTxDqs3, 6:0, scratch67, 26:20); + s(EmcEInputDuration, 4:0, scratch67, 31:27); + s(EmcZcalMrwCmd, 7:0, scratch68, 7:0); + s(EmcZcalMrwCmd, 23:16, scratch68, 15:8); + s(EmcZcalMrwCmd, 31:30, scratch68, 17:16); + s(EmcTRefBw, 13:0, scratch68, 31:18); + s(EmcXm2CmdPadCtrl2, 31:14, scratch69, 17:0); + s(EmcDliTrimTxDqs4, 6:0, scratch69, 24:18); + s(EmcDliTrimTxDqs5, 6:0, scratch69, 31:25); + s(EmcXm2CmdPadCtrl3, 31:14, scratch70, 17:0); + s(EmcDliTrimTxDqs6, 6:0, scratch70, 24:18); + s(EmcDliTrimTxDqs7, 6:0, scratch70, 31:25); + s(EmcXm2CmdPadCtrl5, 2:0, scratch71, 2:0); + s(EmcXm2CmdPadCtrl5, 6:4, scratch71, 5:3); + s(EmcXm2CmdPadCtrl5, 10:8, scratch71, 8:6); + s(EmcXm2CmdPadCtrl5, 14:12, scratch71, 11:9); + s(EmcXm2CmdPadCtrl5, 18:16, scratch71, 14:12); + s(EmcXm2CmdPadCtrl5, 22:20, scratch71, 17:15); + s(EmcDliTrimTxDqs8, 6:0, scratch71, 24:18); + s(EmcDliTrimTxDqs9, 6:0, scratch71, 31:25); + s(EmcCdbCntl3, 17:0, scratch72, 17:0); + s(EmcDliTrimTxDqs10, 6:0, scratch72, 24:18); + s(EmcDliTrimTxDqs11, 6:0, scratch72, 31:25); + s(EmcSwizzleRank0Byte0, 2:0, scratch73, 2:0); + s(EmcSwizzleRank0Byte0, 6:4, scratch73, 5:3); + s(EmcSwizzleRank0Byte0, 10:8, scratch73, 8:6); + s(EmcSwizzleRank0Byte0, 14:12, scratch73, 11:9); + s(EmcSwizzleRank0Byte0, 18:16, scratch73, 14:12); + s(EmcSwizzleRank0Byte0, 22:20, scratch73, 17:15); + s(EmcDliTrimTxDqs12, 6:0, scratch73, 24:18); + s(EmcDliTrimTxDqs13, 6:0, scratch73, 31:25); + s(EmcSwizzleRank0Byte1, 2:0, scratch74, 2:0); + s(EmcSwizzleRank0Byte1, 6:4, scratch74, 5:3); + s(EmcSwizzleRank0Byte1, 10:8, scratch74, 8:6); + s(EmcSwizzleRank0Byte1, 14:12, scratch74, 11:9); + s(EmcSwizzleRank0Byte1, 18:16, scratch74, 14:12); + s(EmcSwizzleRank0Byte1, 22:20, scratch74, 17:15); + s(EmcDliTrimTxDqs14, 6:0, scratch74, 24:18); + s(EmcDliTrimTxDqs15, 6:0, scratch74, 31:25); + s(EmcSwizzleRank0Byte2, 2:0, scratch75, 2:0); + s(EmcSwizzleRank0Byte2, 6:4, scratch75, 5:3); + s(EmcSwizzleRank0Byte2, 10:8, scratch75, 8:6); + s(EmcSwizzleRank0Byte2, 14:12, scratch75, 11:9); + s(EmcSwizzleRank0Byte2, 18:16, scratch75, 14:12); + s(EmcSwizzleRank0Byte2, 22:20, scratch75, 17:15); + s(McEmemArbTimingRp, 6:0, scratch75, 24:18); + s(McEmemArbTimingRc, 6:0, scratch75, 31:25); + s(EmcSwizzleRank0Byte3, 2:0, scratch76, 2:0); + s(EmcSwizzleRank0Byte3, 6:4, scratch76, 5:3); + s(EmcSwizzleRank0Byte3, 10:8, scratch76, 8:6); + s(EmcSwizzleRank0Byte3, 14:12, scratch76, 11:9); + s(EmcSwizzleRank0Byte3, 18:16, scratch76, 14:12); + s(EmcSwizzleRank0Byte3, 22:20, scratch76, 17:15); + s(McEmemArbTimingFaw, 6:0, scratch76, 24:18); + s(McEmemArbTimingWap2Pre, 6:0, scratch76, 31:25); + s(EmcSwizzleRank1Byte0, 2:0, scratch77, 2:0); + s(EmcSwizzleRank1Byte0, 6:4, scratch77, 5:3); + s(EmcSwizzleRank1Byte0, 10:8, scratch77, 8:6); + s(EmcSwizzleRank1Byte0, 14:12, scratch77, 11:9); + s(EmcSwizzleRank1Byte0, 18:16, scratch77, 14:12); + s(EmcSwizzleRank1Byte0, 22:20, scratch77, 17:15); + s(EmcRas, 5:0, scratch77, 23:18); + s(EmcRp, 5:0, scratch77, 29:24); + s(EmcCfg2, 9:8, scratch77, 31:30); + s(EmcSwizzleRank1Byte1, 2:0, scratch78, 2:0); + s(EmcSwizzleRank1Byte1, 6:4, scratch78, 5:3); + s(EmcSwizzleRank1Byte1, 10:8, scratch78, 8:6); + s(EmcSwizzleRank1Byte1, 14:12, scratch78, 11:9); + s(EmcSwizzleRank1Byte1, 18:16, scratch78, 14:12); + s(EmcSwizzleRank1Byte1, 22:20, scratch78, 17:15); + s(EmcW2p, 5:0, scratch78, 23:18); + s(EmcRdRcd, 5:0, scratch78, 29:24); + s(EmcCfg2, 27:26, scratch78, 31:30); + s(EmcSwizzleRank1Byte2, 2:0, scratch79, 2:0); + s(EmcSwizzleRank1Byte2, 6:4, scratch79, 5:3); + s(EmcSwizzleRank1Byte2, 10:8, scratch79, 8:6); + s(EmcSwizzleRank1Byte2, 14:12, scratch79, 11:9); + s(EmcSwizzleRank1Byte2, 18:16, scratch79, 14:12); + s(EmcSwizzleRank1Byte2, 22:20, scratch79, 17:15); + s(EmcWrRcd, 5:0, scratch79, 23:18); + s(EmcQUse, 5:0, scratch79, 29:24); + s(EmcFbioCfg5, 4:4, scratch79, 31:31); + s(EmcSwizzleRank1Byte3, 2:0, scratch80, 2:0); + s(EmcSwizzleRank1Byte3, 6:4, scratch80, 5:3); + s(EmcSwizzleRank1Byte3, 10:8, scratch80, 8:6); + s(EmcSwizzleRank1Byte3, 14:12, scratch80, 11:9); + s(EmcSwizzleRank1Byte3, 18:16, scratch80, 14:12); + s(EmcSwizzleRank1Byte3, 22:20, scratch80, 17:15); + s(EmcQRst, 5:0, scratch80, 23:18); + s(EmcRdv, 5:0, scratch80, 29:24); + s(EmcFbioCfg5, 6:5, scratch80, 31:30); + s(EmcDynSelfRefControl, 15:0, scratch81, 15:0); + s(EmcDynSelfRefControl, 31:31, scratch81, 16:16); + s(EmcPdEx2Wr, 5:0, scratch81, 22:17); + s(EmcPdEx2Rd, 5:0, scratch81, 28:23); + s(EmcRefresh, 5:0, scratch82, 5:0); + s(EmcRefresh, 15:6, scratch82, 15:6); + s(EmcCmdQ, 4:0, scratch82, 20:16); + s(EmcCmdQ, 10:8, scratch82, 23:21); + s(EmcCmdQ, 14:12, scratch82, 26:24); + s(EmcCmdQ, 28:24, scratch82, 31:27); + s(EmcAcpdControl, 15:0, scratch83, 15:0); + s(EmcCfgDigDllPeriod, 15:0, scratch83, 31:16); + s(EmcDllXformDqs0, 4:0, scratch84, 4:0); + s(EmcDllXformDqs0, 22:12, scratch84, 15:5); + s(EmcDllXformDqs1, 4:0, scratch84, 20:16); + s(EmcDllXformDqs1, 22:12, scratch84, 31:21); + s(EmcDllXformDqs2, 4:0, scratch85, 4:0); + s(EmcDllXformDqs2, 22:12, scratch85, 15:5); + s(EmcDllXformDqs3, 4:0, scratch85, 20:16); + s(EmcDllXformDqs3, 22:12, scratch85, 31:21); + s(EmcDllXformDqs4, 4:0, scratch86, 4:0); + s(EmcDllXformDqs4, 22:12, scratch86, 15:5); + s(EmcDllXformDqs5, 4:0, scratch86, 20:16); + s(EmcDllXformDqs5, 22:12, scratch86, 31:21); + s(EmcDllXformDqs6, 4:0, scratch87, 4:0); + s(EmcDllXformDqs6, 22:12, scratch87, 15:5); + s(EmcDllXformDqs7, 4:0, scratch87, 20:16); + s(EmcDllXformDqs7, 22:12, scratch87, 31:21); + s(EmcDllXformDqs8, 4:0, scratch88, 4:0); + s(EmcDllXformDqs8, 22:12, scratch88, 15:5); + s(EmcDllXformDqs9, 4:0, scratch88, 20:16); + s(EmcDllXformDqs9, 22:12, scratch88, 31:21); + s(EmcDllXformDqs10, 4:0, scratch89, 4:0); + s(EmcDllXformDqs10, 22:12, scratch89, 15:5); + s(EmcDllXformDqs11, 4:0, scratch89, 20:16); + s(EmcDllXformDqs11, 22:12, scratch89, 31:21); + s(EmcDllXformDqs12, 4:0, scratch90, 4:0); + s(EmcDllXformDqs12, 22:12, scratch90, 15:5); + s(EmcDllXformDqs13, 4:0, scratch90, 20:16); + s(EmcDllXformDqs13, 22:12, scratch90, 31:21); + s(EmcDllXformDqs14, 4:0, scratch91, 4:0); + s(EmcDllXformDqs14, 22:12, scratch91, 15:5); + s(EmcDllXformDqs15, 4:0, scratch91, 20:16); + s(EmcDllXformDqs15, 22:12, scratch91, 31:21); + s(EmcDllXformQUse0, 4:0, scratch92, 4:0); + s(EmcDllXformQUse0, 22:12, scratch92, 15:5); + s(EmcDllXformQUse1, 4:0, scratch92, 20:16); + s(EmcDllXformQUse1, 22:12, scratch92, 31:21); + s(EmcDllXformQUse2, 4:0, scratch93, 4:0); + s(EmcDllXformQUse2, 22:12, scratch93, 15:5); + s(EmcDllXformQUse3, 4:0, scratch93, 20:16); + s(EmcDllXformQUse3, 22:12, scratch93, 31:21); + s(EmcDllXformQUse4, 4:0, scratch94, 4:0); + s(EmcDllXformQUse4, 22:12, scratch94, 15:5); + s(EmcDllXformQUse5, 4:0, scratch94, 20:16); + s(EmcDllXformQUse5, 22:12, scratch94, 31:21); + s(EmcDllXformQUse6, 4:0, scratch95, 4:0); + s(EmcDllXformQUse6, 22:12, scratch95, 15:5); + s(EmcDllXformQUse7, 4:0, scratch95, 20:16); + s(EmcDllXformQUse7, 22:12, scratch95, 31:21); + s(EmcDllXformDq0, 4:0, scratch96, 4:0); + s(EmcDllXformDq0, 22:12, scratch96, 15:5); + s(EmcDllXformDq1, 4:0, scratch96, 20:16); + s(EmcDllXformDq1, 22:12, scratch96, 31:21); + s(EmcDllXformDq2, 4:0, scratch97, 4:0); + s(EmcDllXformDq2, 22:12, scratch97, 15:5); + s(EmcDllXformDq3, 4:0, scratch97, 20:16); + s(EmcDllXformDq3, 22:12, scratch97, 31:21); + s(EmcPreRefreshReqCnt, 15:0, scratch98, 15:0); + s(EmcDllXformAddr0, 4:0, scratch98, 20:16); + s(EmcDllXformAddr0, 22:12, scratch98, 31:21); + s(EmcDllXformAddr1, 4:0, scratch99, 4:0); + s(EmcDllXformAddr1, 22:12, scratch99, 15:5); + s(EmcDllXformAddr2, 4:0, scratch99, 20:16); + s(EmcDllXformAddr2, 22:12, scratch99, 31:21); + s(EmcDllXformAddr3, 4:0, scratch100, 4:0); + s(EmcDllXformAddr3, 22:12, scratch100, 15:5); + s(EmcDllXformAddr4, 4:0, scratch100, 20:16); + s(EmcDllXformAddr4, 22:12, scratch100, 31:21); + s(EmcDllXformAddr5, 4:0, scratch101, 4:0); + s(EmcDllXformAddr5, 22:12, scratch101, 15:5); + s(EmcPChg2Pden, 5:0, scratch102, 5:0); + s(EmcAct2Pden, 5:0, scratch102, 11:6); + s(EmcRw2Pden, 5:0, scratch102, 17:12); + s(EmcTcke, 5:0, scratch102, 23:18); + s(EmcTrpab, 5:0, scratch102, 29:24); + s(EmcFbioCfg5, 8:7, scratch102, 31:30); + s(EmcCtt, 5:0, scratch103, 5:0); + s(EmcEInput, 5:0, scratch103, 11:6); + s(EmcPutermExtra, 21:16, scratch103, 17:12); + s(EmcTckesr, 5:0, scratch103, 23:18); + s(EmcTpd, 5:0, scratch103, 29:24); + s(EmcFbioCfg5, 10:9, scratch103, 31:30); + s(EmcRdvMask, 5:0, scratch104, 5:0); + s(EmcXm2CmdPadCtrl4, 0:0, scratch104, 6:6); + s(EmcXm2CmdPadCtrl4, 2:2, scratch104, 7:7); + s(EmcXm2CmdPadCtrl4, 4:4, scratch104, 8:8); + s(EmcXm2CmdPadCtrl4, 6:6, scratch104, 9:9); + s(EmcXm2CmdPadCtrl4, 8:8, scratch104, 10:10); + s(EmcXm2CmdPadCtrl4, 10:10, scratch104, 11:11); + s(EmcQpop, 5:0, scratch104, 17:12); + s(McEmemArbTimingRcd, 5:0, scratch104, 23:18); + s(McEmemArbTimingRas, 5:0, scratch104, 29:24); + s(EmcFbioCfg5, 12:11, scratch104, 31:30); + s(McEmemArbTimingRap2Pre, 5:0, scratch105, 5:0); + s(McEmemArbTimingR2W, 5:0, scratch105, 11:6); + s(McEmemArbTimingW2R, 5:0, scratch105, 17:12); + s(EmcIbdly, 4:0, scratch105, 22:18); + s(McEmemArbTimingR2R, 4:0, scratch105, 27:23); + s(EmcW2w, 3:0, scratch105, 31:28); + s(McEmemArbTimingW2W, 4:0, scratch106, 4:0); + s(McEmemArbOverride, 27:27, scratch106, 5:5); + s(McEmemArbOverride, 26:26, scratch106, 6:6); + s(McEmemArbOverride, 16:16, scratch106, 7:7); + s(McEmemArbOverride, 10:10, scratch106, 8:8); + s(McEmemArbOverride, 4:4, scratch106, 9:9); + s(EmcWdvMask, 3:0, scratch106, 13:10); + s(EmcCttDuration, 3:0, scratch106, 17:14); + s(EmcQuseWidth, 3:0, scratch106, 21:18); + s(EmcPutermWidth, 3:0, scratch106, 25:22); + s(EmcBgbiasCtl0, 3:0, scratch106, 29:26); + s(EmcFbioCfg5, 25:24, scratch106, 31:30); + s(McEmemArbTimingRrd, 3:0, scratch107, 3:0); + s(EmcFbioCfg5, 23:20, scratch107, 10:7); + s(EmcFbioCfg5, 15:13, scratch107, 13:11); + s(EmcCfg2, 5:3, scratch107, 16:14); + s(EmcFbioCfg5, 26:26, scratch107, 17:17); + s(EmcFbioCfg5, 28:28, scratch107, 18:18); + s(EmcCfg2, 2:0, scratch107, 21:19); + s(EmcCfg2, 7:6, scratch107, 23:22); + s(EmcCfg2, 15:10, scratch107, 29:24); + s(EmcCfg2, 23:22, scratch107, 31:30); + s(EmcCfg2, 25:24, scratch108, 1:0); + s(EmcCfg2, 31:28, scratch108, 5:2); + s(BootRomPatchData, 31:0, scratch15, 31:0); + s(BootRomPatchControl, 31:0, scratch16, 31:0); + s(EmcDevSelect, 1:0, scratch17, 31:30); + s(EmcZcalWarmColdBootEnables, 1:0, scratch18, 31:30); + s(EmcCfgDigDllPeriodWarmBoot, 1:0, scratch19, 31:30); + s(EmcWarmBootExtraModeRegWriteEnable, 0:0, scratch46, 30:30); + s(McClkenOverrideAllWarmBoot, 0:0, scratch46, 31:31); + s(EmcClkenOverrideAllWarmBoot, 0:0, scratch47, 30:30); + s(EmcMrsWarmBootEnable, 0:0, scratch47, 31:31); + s(EmcTimingControlWait, 7:0, scratch57, 27:20); + s(EmcZcalWarmBootWait, 7:0, scratch58, 27:20); + s(EmcAutoCalWait, 7:0, scratch59, 27:20); + s(WarmBootWait, 7:0, scratch60, 27:20); + s(EmcPinProgramWait, 7:0, scratch61, 27:20); + s(AhbArbitrationXbarCtrlMemInitDone, 0:0, scratch79, 30:30); + s(EmcExtraRefreshNum, 2:0, scratch81, 31:29); + s(SwizzleRankByteEncode, 15:0, scratch101, 31:16); + s(MemoryType, 2:0, scratch107, 6:4); + + switch (sdram->MemoryType) { + case NvBootMemoryType_LpDdr2: + s(EmcMrwLpddr2ZcalWarmBoot, 23:16, scratch5, 7:0); + s(EmcMrwLpddr2ZcalWarmBoot, 7:0, scratch5, 15:8); + s(EmcWarmBootMrwExtra, 23:16, scratch5, 23:16); + s(EmcWarmBootMrwExtra, 7:0, scratch5, 31:24); + s(EmcMrwLpddr2ZcalWarmBoot, 31:30, scratch6, 1:0); + s(EmcWarmBootMrwExtra, 31:30, scratch6, 3:2); + s(EmcMrwLpddr2ZcalWarmBoot, 27:26, scratch6, 5:4); + s(EmcWarmBootMrwExtra, 27:26, scratch6, 7:6); + s(EmcMrw1, 7:0, scratch7, 7:0); + s(EmcMrw1, 23:16, scratch7, 15:8); + s(EmcMrw1, 27:26, scratch7, 17:16); + s(EmcMrw1, 31:30, scratch7, 19:18); + s(EmcMrw2, 7:0, scratch8, 7:0); + s(EmcMrw2, 23:16, scratch8, 15:8); + s(EmcMrw2, 27:26, scratch8, 17:16); + s(EmcMrw2, 31:30, scratch8, 19:18); + s(EmcMrw3, 7:0, scratch9, 7:0); + s(EmcMrw3, 23:16, scratch9, 15:8); + s(EmcMrw3, 27:26, scratch9, 17:16); + s(EmcMrw3, 31:30, scratch9, 19:18); + s(EmcMrw4, 7:0, scratch10, 7:0); + s(EmcMrw4, 23:16, scratch10, 15:8); + s(EmcMrw4, 27:26, scratch10, 17:16); + s(EmcMrw4, 31:30, scratch10, 19:18); + break; + case NvBootMemoryType_Ddr3: + s(EmcMrs, 13:0, scratch5, 13:0); + s(EmcEmrs, 13:0, scratch5, 27:14); + s(EmcMrs, 21:20, scratch5, 29:28); + s(EmcMrs, 31:30, scratch5, 31:30); + s(EmcEmrs2, 13:0, scratch7, 13:0); + s(EmcEmrs, 21:20, scratch7, 15:14); + s(EmcEmrs, 31:30, scratch7, 17:16); + s(EmcEmrs2, 21:20, scratch7, 19:18); + s(EmcEmrs3, 13:0, scratch8, 13:0); + s(EmcEmrs2, 31:30, scratch8, 15:14); + s(EmcEmrs3, 21:20, scratch8, 17:16); + s(EmcEmrs3, 31:30, scratch8, 19:18); + s(EmcWarmBootMrsExtra, 13:0, scratch9, 13:0); + s(EmcWarmBootMrsExtra, 31:30, scratch9, 15:14); + s(EmcWarmBootMrsExtra, 21:20, scratch9, 17:16); + s(EmcZqCalDdr3WarmBoot, 31:30, scratch9, 19:18); + s(EmcMrs, 27:26, scratch10, 1:0); + s(EmcEmrs, 27:26, scratch10, 3:2); + s(EmcEmrs2, 27:26, scratch10, 5:4); + s(EmcEmrs3, 27:26, scratch10, 7:6); + s(EmcWarmBootMrsExtra, 27:27, scratch10, 8:8); + s(EmcWarmBootMrsExtra, 26:26, scratch10, 9:9); + s(EmcZqCalDdr3WarmBoot, 0:0, scratch10, 10:10); + s(EmcZqCalDdr3WarmBoot, 4:4, scratch10, 11:11); + c(0, scratch116, 31:0); + c(0, scratch117, 31:0); + break; + default: + printk(BIOS_CRIT, "ERROR: %s() unrecognized MemoryType %d!\n", + __func__, sdram->MemoryType); + } + + s(McVideoProtectGpuOverride0, 31:0, secure_scratch8, 31:0); + s(McVideoProtectVprOverride, 3:0, secure_scratch9, 3:0); + s(McVideoProtectVprOverride, 11:6, secure_scratch9, 9:4); + s(McVideoProtectVprOverride, 23:14, secure_scratch9, 19:10); + s(McVideoProtectVprOverride, 26:26, secure_scratch9, 20:20); + s(McVideoProtectVprOverride, 31:29, secure_scratch9, 23:21); + s(EmcFbioCfg5, 19:16, secure_scratch9, 27:24); + s(McDisplaySnapRing, 1:0, secure_scratch9, 29:28); + s(McDisplaySnapRing, 31:31, secure_scratch9, 30:30); + s(EmcAdrCfg, 0:0, secure_scratch9, 31:31); + s(McVideoProtectGpuOverride1, 15:0, secure_scratch10, 15:0); + s(McEmemAdrCfgBankMask0, 15:0, secure_scratch10, 31:16); + s(McEmemAdrCfgBankMask1, 15:0, secure_scratch11, 15:0); + s(McEmemAdrCfgBankMask2, 15:0, secure_scratch11, 31:16); + s(McEmemCfg, 13:0, secure_scratch12, 13:0); + s(McEmemCfg, 31:31, secure_scratch12, 14:14); + s(McVideoProtectBom, 31:20, secure_scratch12, 26:15); + s(McVideoProtectVprOverride1, 1:0, secure_scratch12, 28:27); + s(McVideoProtectVprOverride1, 4:4, secure_scratch12, 29:29); + s(McVideoProtectBomAdrHi, 1:0, secure_scratch12, 31:30); + s(McVideoProtectSizeMb, 11:0, secure_scratch13, 11:0); + s(McSecCarveoutBom, 31:20, secure_scratch13, 23:12); + s(McEmemAdrCfgBankSwizzle3, 2:0, secure_scratch13, 26:24); + s(McVideoProtectWriteAccess, 1:0, secure_scratch13, 28:27); + s(McSecCarveoutAdrHi, 1:0, secure_scratch13, 30:29); + s(McEmemAdrCfg, 0:0, secure_scratch13, 31:31); + s(McSecCarveoutSizeMb, 11:0, secure_scratch14, 11:0); + s(McMtsCarveoutBom, 31:20, secure_scratch14, 23:12); + s(McMtsCarveoutAdrHi, 1:0, secure_scratch14, 25:24); + s(McSecCarveoutProtectWriteAccess, 0:0, secure_scratch14, 26:26); + s(McMtsCarveoutRegCtrl, 0:0, secure_scratch14, 27:27); + s(McMtsCarveoutSizeMb, 11:0, secure_scratch15, 11:0); + s(McEmemAdrCfgDev0, 2:0, secure_scratch15, 14:12); + s(McEmemAdrCfgDev0, 9:8, secure_scratch15, 16:15); + s(McEmemAdrCfgDev0, 19:16, secure_scratch15, 20:17); + s(McEmemAdrCfgDev1, 2:0, secure_scratch15, 23:21); + s(McEmemAdrCfgDev1, 9:8, secure_scratch15, 25:24); + s(McEmemAdrCfgDev1, 19:16, secure_scratch15, 29:26); + + c(0x1555555, sec_disable2, 25:0); + c(0xff, sec_disable, 19:12); + + c(0, scratch2, 31:0); + m(pllm_base, 15:0, scratch2, 15:0); + m(pllm_base, 20:20, scratch2, 16:16); + m(pllm_misc2, 2:0, scratch2, 19:17); + c(0, scratch35, 31:0); + m(pllm_misc1, 23:0, scratch35, 23:0); + m(pllm_misc1, 30:28, scratch35, 30:28); + c(0, scratch3, 31:0); + s(PllMInputDivider, 7:0, scratch3, 7:0); + c(0x3e, scratch3, 15:8); + c(0, scratch3, 19:16); + s(PllMKVCO, 0:0, scratch3, 20:20); + s(PllMKCP, 1:0, scratch3, 22:21); + c(0, scratch36, 31:0); + s(PllMSetupControl, 23:0, scratch36, 23:0); + c(0, scratch4, 31:0); + s(PllMStableTime, 9:0, scratch4, 9:0); + s(PllMStableTime, 9:0, scratch4, 19:10); + + s(PllMSelectDiv2, 0:0, pllm_wb0_override2, 27:27); + s(PllMKVCO, 0:0, pllm_wb0_override2, 26:26); + s(PllMKCP, 1:0, pllm_wb0_override2, 25:24); + s(PllMSetupControl, 23:0, pllm_wb0_override2, 23:0); + s(PllMFeedbackDivider, 7:0, pllm_wb0_override_freq, 15:8); + s(PllMInputDivider, 7:0, pllm_wb0_override_freq, 7:0); + + c(3, pllp_wb0_override, 12:11); +} diff --git a/src/soc/nvidia/tegra132/secmon.c b/src/soc/nvidia/tegra132/secmon.c new file mode 100644 index 0000000000..42f471e82a --- /dev/null +++ b/src/soc/nvidia/tegra132/secmon.c @@ -0,0 +1,50 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +static void soc_get_secure_mem(uint64_t *base, size_t *size) +{ + uintptr_t tz_base_mib; + size_t tz_size_mib; + + carveout_range(CARVEOUT_TZ, &tz_base_mib, &tz_size_mib); + + tz_base_mib *= MiB; + tz_size_mib *= MiB; + + *base = tz_base_mib; + *size = tz_size_mib; +} + +void soc_get_secmon_base_size(uint64_t *base, size_t *size) +{ + uintptr_t tz_base; + size_t ttb_size, tz_size; + + soc_get_secure_mem(&tz_base, &tz_size); + + ttb_size = TTB_SIZE * MiB; + + *base = tz_base + ttb_size; + *size = tz_size - ttb_size; +} diff --git a/src/soc/nvidia/tegra132/soc.c b/src/soc/nvidia/tegra132/soc.c new file mode 100644 index 0000000000..a171577ae7 --- /dev/null +++ b/src/soc/nvidia/tegra132/soc.c @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static void soc_read_resources(device_t dev) +{ + unsigned long index = 0; + int i; uintptr_t begin, end; + size_t size; + + for (i = 0; i < CARVEOUT_NUM; i++) { + carveout_range(i, &begin, &size); + if (size == 0) + continue; + reserved_ram_resource(dev, index++, begin * KiB, size * KiB); + } + + memory_in_range_below_4gb(&begin, &end); + size = end - begin; + ram_resource(dev, index++, begin * KiB, size * KiB); + + memory_in_range_above_4gb(&begin, &end); + size = end - begin; + ram_resource(dev, index++, begin * KiB, size * KiB); +} + +static size_t cntrl_total_cpus(void) +{ + return CONFIG_MAX_CPUS; +} + +static int cntrl_start_cpu(unsigned int id, void (*entry)(void)) +{ + if (id != 1) + return -1; + start_cpu(1, entry); + return 0; +} + +static struct cpu_control_ops cntrl_ops = { + .total_cpus = cntrl_total_cpus, + .start_cpu = cntrl_start_cpu, +}; + +static void soc_init(device_t dev) +{ + struct soc_nvidia_tegra132_config *cfg; + + clock_init_arm_generic_timer(); + + cfg = dev->chip_info; + spintable_init((void *)cfg->spintable_addr); + arch_initialize_cpus(dev, &cntrl_ops); + +#if IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) + if (vboot_skip_display_init()) + printk(BIOS_INFO, "Skipping display init.\n"); + else + display_startup(dev); +#endif +} + +static void soc_noop(device_t dev) +{ +} + +static struct device_operations soc_ops = { + .read_resources = soc_read_resources, + .set_resources = soc_noop, + .enable_resources = soc_noop, + .init = soc_init, + .scan_bus = NULL, +}; + +static void enable_tegra132_dev(device_t dev) +{ + if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) + dev->ops = &soc_ops; +} + +static void tegra132_init(void *chip_info) +{ + struct tegra_revision rev; + + tegra_revision_info(&rev); + + printk(BIOS_INFO, "chip %x rev %02x.%x\n", + rev.chip_id, rev.major, rev.minor); + + printk(BIOS_INFO, "MTS build %u\n", raw_read_aidr_el1()); +} + +struct chip_operations soc_nvidia_tegra132_ops = { + CHIP_NAME("SOC Nvidia Tegra132") + .init = tegra132_init, + .enable_dev = enable_tegra132_dev, +}; + +static void tegra132_cpu_init(device_t cpu) +{ +} + +static const struct cpu_device_id ids[] = { + { 0x4e0f0000 }, + { CPU_ID_END }, +}; + +static struct device_operations cpu_dev_ops = { + .init = tegra132_cpu_init, +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = ids, +}; + +static void enable_plld(void *unused) +{ + /* + * Configure a conservative 300MHz clock for PLLD. The kernel cannot + * handle PLLD not being configured so enable PLLD unconditionally + * with a default clock rate. + */ + clock_configure_plld(300 * MHz); +} + +/* + * The PLLD being enabled is done at BS_DEV_INIT time because mainboard_init() + * is the first thing called. This ensures PLLD is up and functional before + * anything that mainboard can do that implicitly relies on PLLD. + */ +BOOT_STATE_INIT_ENTRIES(enable_plld_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, enable_plld, NULL), +}; diff --git a/src/soc/nvidia/tegra132/spi.c b/src/soc/nvidia/tegra132/spi.c new file mode 100644 index 0000000000..7a2ab11b52 --- /dev/null +++ b/src/soc/nvidia/tegra132/spi.c @@ -0,0 +1,948 @@ +/* + * NVIDIA Tegra SPI controller (T114 and later) + * + * Copyright (c) 2010-2013 NVIDIA Corporation + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI +# define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "TEGRA_SPI: " x) +#else +# define DEBUG_SPI(x,...) +#endif + +/* + * 64 packets in FIFO mode, BLOCK_SIZE packets in DMA mode. Packets can vary + * in size from 4 to 32 bits. To keep things simple we'll use 8-bit packets. + */ +#define SPI_PACKET_SIZE_BYTES 1 +#define SPI_MAX_TRANSFER_BYTES_FIFO (64 * SPI_PACKET_SIZE_BYTES) +#define SPI_MAX_TRANSFER_BYTES_DMA (65535 * SPI_PACKET_SIZE_BYTES) + +/* + * This is used to workaround an issue seen where it may take some time for + * packets to show up in the FIFO after they have been received and the + * BLOCK_COUNT has been incremented. + */ +#define SPI_FIFO_XFER_TIMEOUT_US 1000 + +/* COMMAND1 */ +#define SPI_CMD1_GO (1 << 31) +#define SPI_CMD1_M_S (1 << 30) +#define SPI_CMD1_MODE_MASK 0x3 +#define SPI_CMD1_MODE_SHIFT 28 +#define SPI_CMD1_CS_SEL_MASK 0x3 +#define SPI_CMD1_CS_SEL_SHIFT 26 +#define SPI_CMD1_CS_POL_INACTIVE3 (1 << 25) +#define SPI_CMD1_CS_POL_INACTIVE2 (1 << 24) +#define SPI_CMD1_CS_POL_INACTIVE1 (1 << 23) +#define SPI_CMD1_CS_POL_INACTIVE0 (1 << 22) +#define SPI_CMD1_CS_SW_HW (1 << 21) +#define SPI_CMD1_CS_SW_VAL (1 << 20) +#define SPI_CMD1_IDLE_SDA_MASK 0x3 +#define SPI_CMD1_IDLE_SDA_SHIFT 18 +#define SPI_CMD1_BIDIR (1 << 17) +#define SPI_CMD1_LSBI_FE (1 << 16) +#define SPI_CMD1_LSBY_FE (1 << 15) +#define SPI_CMD1_BOTH_EN_BIT (1 << 14) +#define SPI_CMD1_BOTH_EN_BYTE (1 << 13) +#define SPI_CMD1_RX_EN (1 << 12) +#define SPI_CMD1_TX_EN (1 << 11) +#define SPI_CMD1_PACKED (1 << 5) +#define SPI_CMD1_BIT_LEN_MASK 0x1f +#define SPI_CMD1_BIT_LEN_SHIFT 0 + +/* COMMAND2 */ +#define SPI_CMD2_TX_CLK_TAP_DELAY (1 << 6) +#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK (0x3F << 6) +#define SPI_CMD2_RX_CLK_TAP_DELAY (1 << 0) +#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK (0x3F << 0) + +/* SPI_TRANS_STATUS */ +#define SPI_STATUS_RDY (1 << 30) +#define SPI_STATUS_SLV_IDLE_COUNT_MASK 0xff +#define SPI_STATUS_SLV_IDLE_COUNT_SHIFT 16 +#define SPI_STATUS_BLOCK_COUNT 0xffff +#define SPI_STATUS_BLOCK_COUNT_SHIFT 0 + +/* SPI_FIFO_STATUS */ +#define SPI_FIFO_STATUS_CS_INACTIVE (1 << 31) +#define SPI_FIFO_STATUS_FRAME_END (1 << 30) +#define SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_MASK 0x7f +#define SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_SHIFT 23 +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY_COUNT_MASK 0x7f +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY_COUNT_SHIFT 16 +#define SPI_FIFO_STATUS_RX_FIFO_FLUSH (1 << 15) +#define SPI_FIFO_STATUS_TX_FIFO_FLUSH (1 << 14) +#define SPI_FIFO_STATUS_ERR (1 << 8) +#define SPI_FIFO_STATUS_TX_FIFO_OVF (1 << 7) +#define SPI_FIFO_STATUS_TX_FIFO_UNR (1 << 6) +#define SPI_FIFO_STATUS_RX_FIFO_OVF (1 << 5) +#define SPI_FIFO_STATUS_RX_FIFO_UNR (1 << 4) +#define SPI_FIFO_STATUS_TX_FIFO_FULL (1 << 3) +#define SPI_FIFO_STATUS_TX_FIFO_EMPTY (1 << 2) +#define SPI_FIFO_STATUS_RX_FIFO_FULL (1 << 1) +#define SPI_FIFO_STATUS_RX_FIFO_EMPTY (1 << 0) + +/* SPI_DMA_CTL */ +#define SPI_DMA_CTL_DMA (1 << 31) +#define SPI_DMA_CTL_CONT (1 << 30) +#define SPI_DMA_CTL_IE_RX (1 << 29) +#define SPI_DMA_CTL_IE_TX (1 << 28) +#define SPI_DMA_CTL_RX_TRIG_MASK 0x3 +#define SPI_DMA_CTL_RX_TRIG_SHIFT 19 +#define SPI_DMA_CTL_TX_TRIG_MASK 0x3 +#define SPI_DMA_CTL_TX_TRIG_SHIFT 15 + +/* SPI_DMA_BLK */ +#define SPI_DMA_CTL_BLOCK_SIZE_MASK 0xffff +#define SPI_DMA_CTL_BLOCK_SIZE_SHIFT 0 + +static struct tegra_spi_channel tegra_spi_channels[] = { + /* + * Note: Tegra pinmux must be setup for corresponding SPI channel in + * order for its registers to be accessible. If pinmux has not been + * set up, access to the channel's registers will simply hang. + * + * TODO(dhendrix): Clarify or remove this comment (is clock setup + * necessary first, or just pinmux, or both?) + */ + { + .slave = { .bus = 1, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI1_BASE, + .req_sel = APBDMA_SLAVE_SL2B1, + }, + { + .slave = { .bus = 2, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI2_BASE, + .req_sel = APBDMA_SLAVE_SL2B2, + }, + { + .slave = { .bus = 3, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI3_BASE, + .req_sel = APBDMA_SLAVE_SL2B3, + }, + { + .slave = { .bus = 4, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI4_BASE, + .req_sel = APBDMA_SLAVE_SL2B4, + }, + { + .slave = { .bus = 5, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI5_BASE, + .req_sel = APBDMA_SLAVE_SL2B5, + }, + { + .slave = { .bus = 6, }, + .regs = (struct tegra_spi_regs *)TEGRA_SPI6_BASE, + .req_sel = APBDMA_SLAVE_SL2B6, + }, +}; + +enum spi_direction { + SPI_SEND, + SPI_RECEIVE, +}; + +struct tegra_spi_channel *tegra_spi_init(unsigned int bus) +{ + int i; + struct tegra_spi_channel *spi = NULL; + + for (i = 0; i < ARRAY_SIZE(tegra_spi_channels); i++) { + if (tegra_spi_channels[i].slave.bus == bus) { + spi = &tegra_spi_channels[i]; + break; + } + } + if (!spi) + return NULL; + + /* software drives chip-select, set value to high */ + setbits_le32(&spi->regs->command1, + SPI_CMD1_CS_SW_HW | SPI_CMD1_CS_SW_VAL); + + /* 8-bit transfers, unpacked mode, most significant bit first */ + clrbits_le32(&spi->regs->command1, + SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED); + setbits_le32(&spi->regs->command1, 7 << SPI_CMD1_BIT_LEN_SHIFT); + + return spi; +} + +static struct tegra_spi_channel * const to_tegra_spi(int bus) { + return &tegra_spi_channels[bus - 1]; +} + +static unsigned int tegra_spi_speed(unsigned int bus) +{ + /* FIXME: implement this properly, for now use max value (50MHz) */ + return 50000000; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs; + u32 val; + + tegra_spi_init(slave->bus); + + val = read32(®s->command1); + + /* select appropriate chip-select line */ + val &= ~(SPI_CMD1_CS_SEL_MASK << SPI_CMD1_CS_SEL_SHIFT); + val |= (slave->cs << SPI_CMD1_CS_SEL_SHIFT); + + /* drive chip-select with the inverse of the "inactive" value */ + if (val & (SPI_CMD1_CS_POL_INACTIVE0 << slave->cs)) + val &= ~SPI_CMD1_CS_SW_VAL; + else + val |= SPI_CMD1_CS_SW_VAL; + + write32(val, ®s->command1); + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs; + u32 val; + + val = read32(®s->command1); + + if (val & (SPI_CMD1_CS_POL_INACTIVE0 << slave->cs)) + val |= SPI_CMD1_CS_SW_VAL; + else + val &= ~SPI_CMD1_CS_SW_VAL; + + write32(val, ®s->command1); +} + +static void dump_fifo_status(struct tegra_spi_channel *spi) +{ + u32 status = read32(&spi->regs->fifo_status); + + printk(BIOS_INFO, "Raw FIFO status: 0x%08x\n", status); + if (status & SPI_FIFO_STATUS_TX_FIFO_OVF) + printk(BIOS_INFO, "\tTx overflow detected\n"); + if (status & SPI_FIFO_STATUS_TX_FIFO_UNR) + printk(BIOS_INFO, "\tTx underrun detected\n"); + if (status & SPI_FIFO_STATUS_RX_FIFO_OVF) + printk(BIOS_INFO, "\tRx overflow detected\n"); + if (status & SPI_FIFO_STATUS_RX_FIFO_UNR) + printk(BIOS_INFO, "\tRx underrun detected\n"); + + printk(BIOS_INFO, "TX_FIFO: 0x%08x, TX_DATA: 0x%08x\n", + read32(&spi->regs->tx_fifo), read32(&spi->regs->tx_data)); + printk(BIOS_INFO, "RX_FIFO: 0x%08x, RX_DATA: 0x%08x\n", + read32(&spi->regs->rx_fifo), read32(&spi->regs->rx_data)); +} + +static void clear_fifo_status(struct tegra_spi_channel *spi) +{ + clrbits_le32(&spi->regs->fifo_status, + SPI_FIFO_STATUS_ERR | + SPI_FIFO_STATUS_TX_FIFO_OVF | + SPI_FIFO_STATUS_TX_FIFO_UNR | + SPI_FIFO_STATUS_RX_FIFO_OVF | + SPI_FIFO_STATUS_RX_FIFO_UNR); +} + +static void dump_spi_regs(struct tegra_spi_channel *spi) +{ + printk(BIOS_INFO, "SPI regs:\n" + "\tdma_blk: 0x%08x\n" + "\tcommand1: 0x%08x\n" + "\tdma_ctl: 0x%08x\n" + "\ttrans_status: 0x%08x\n", + read32(&spi->regs->dma_blk), + read32(&spi->regs->command1), + read32(&spi->regs->dma_ctl), + read32(&spi->regs->trans_status)); +} + +static void dump_dma_regs(struct apb_dma_channel *dma) +{ + printk(BIOS_INFO, "DMA regs:\n" + "\tahb_ptr: 0x%08x\n" + "\tapb_ptr: 0x%08x\n" + "\tahb_seq: 0x%08x\n" + "\tapb_seq: 0x%08x\n" + "\tcsr: 0x%08x\n" + "\tcsre: 0x%08x\n" + "\twcount: 0x%08x\n" + "\tdma_byte_sta: 0x%08x\n" + "\tword_transfer: 0x%08x\n", + read32(&dma->regs->ahb_ptr), + read32(&dma->regs->apb_ptr), + read32(&dma->regs->ahb_seq), + read32(&dma->regs->apb_seq), + read32(&dma->regs->csr), + read32(&dma->regs->csre), + read32(&dma->regs->wcount), + read32(&dma->regs->dma_byte_sta), + read32(&dma->regs->word_transfer)); +} + +static inline unsigned int spi_byte_count(struct tegra_spi_channel *spi) +{ + /* FIXME: Make this take total packet size into account */ + return read32(&spi->regs->trans_status) & + (SPI_STATUS_BLOCK_COUNT << SPI_STATUS_BLOCK_COUNT_SHIFT); +} + +/* + * This calls udelay() with a calculated value based on the SPI speed and + * number of bytes remaining to be transferred. It assumes that if the + * calculated delay period is less than MIN_DELAY_US then it is probably + * not worth the overhead of yielding. + */ +#define MIN_DELAY_US 250 +static void spi_delay(struct tegra_spi_channel *spi, + unsigned int bytes_remaining) +{ + unsigned int ns_per_byte, delay_us; + + ns_per_byte = 1000000000 / (tegra_spi_speed(spi->slave.bus) / 8); + delay_us = (ns_per_byte * bytes_remaining) / 1000; + + if (delay_us < MIN_DELAY_US) + return; + + udelay(delay_us); +} + +static void tegra_spi_wait(struct tegra_spi_channel *spi) +{ + unsigned int count, dma_blk; + + dma_blk = 1 + (read32(&spi->regs->dma_blk) & + (SPI_DMA_CTL_BLOCK_SIZE_MASK << SPI_DMA_CTL_BLOCK_SIZE_SHIFT)); + + while ((count = spi_byte_count(spi)) != dma_blk) + spi_delay(spi, dma_blk - count); +} + + +static int fifo_error(struct tegra_spi_channel *spi) +{ + return read32(&spi->regs->fifo_status) & SPI_FIFO_STATUS_ERR ? 1 : 0; +} + +static int tegra_spi_pio_prepare(struct tegra_spi_channel *spi, + unsigned int bytes, enum spi_direction dir) +{ + u8 *p = spi->out_buf; + unsigned int todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_FIFO); + u32 flush_mask, enable_mask; + + if (dir == SPI_SEND) { + flush_mask = SPI_FIFO_STATUS_TX_FIFO_FLUSH; + enable_mask = SPI_CMD1_TX_EN; + } else { + flush_mask = SPI_FIFO_STATUS_RX_FIFO_FLUSH; + enable_mask = SPI_CMD1_RX_EN; + } + + setbits_le32(&spi->regs->fifo_status, flush_mask); + while (read32(&spi->regs->fifo_status) & flush_mask) + ; + + setbits_le32(&spi->regs->command1, enable_mask); + + /* BLOCK_SIZE in SPI_DMA_BLK register applies to both DMA and + * PIO transfers */ + write32(todo - 1, &spi->regs->dma_blk); + + if (dir == SPI_SEND) { + unsigned int to_fifo = bytes; + while (to_fifo) { + write32(*p, &spi->regs->tx_fifo); + p++; + to_fifo--; + } + } + + return todo; +} + +static void tegra_spi_pio_start(struct tegra_spi_channel *spi) +{ + setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY); + setbits_le32(&spi->regs->command1, SPI_CMD1_GO); + /* Make sure the write to command1 completes. */ + read32(&spi->regs->command1); +} + +static inline u32 rx_fifo_count(struct tegra_spi_channel *spi) +{ + return (read32(&spi->regs->fifo_status) >> + SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_SHIFT) & + SPI_FIFO_STATUS_RX_FIFO_FULL_COUNT_MASK; +} + +static int tegra_spi_pio_finish(struct tegra_spi_channel *spi) +{ + u8 *p = spi->in_buf; + struct stopwatch sw; + + clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN | SPI_CMD1_TX_EN); + + /* + * Allow some time in case the Rx FIFO does not yet have + * all packets pushed into it. See chrome-os-partner:24215. + */ + stopwatch_init_usecs_expire(&sw, SPI_FIFO_XFER_TIMEOUT_US); + do { + if (rx_fifo_count(spi) == spi_byte_count(spi)) + break; + } while (!stopwatch_expired(&sw)); + + while (!(read32(&spi->regs->fifo_status) & + SPI_FIFO_STATUS_RX_FIFO_EMPTY)) { + *p = read8(&spi->regs->rx_fifo); + p++; + } + + if (fifo_error(spi)) { + printk(BIOS_ERR, "%s: ERROR:\n", __func__); + dump_spi_regs(spi); + dump_fifo_status(spi); + return -1; + } + + return 0; +} + +static void setup_dma_params(struct tegra_spi_channel *spi, + struct apb_dma_channel *dma) +{ + /* APB bus width = 8-bits, address wrap for each word */ + clrbits_le32(&dma->regs->apb_seq, + APB_BUS_WIDTH_MASK << APB_BUS_WIDTH_SHIFT); + /* AHB 1 word burst, bus width = 32 bits (fixed in hardware), + * no address wrapping */ + clrsetbits_le32(&dma->regs->ahb_seq, + (AHB_BURST_MASK << AHB_BURST_SHIFT), + 4 << AHB_BURST_SHIFT); + + /* Set ONCE mode to transfer one "block" at a time (64KB) and enable + * flow control. */ + clrbits_le32(&dma->regs->csr, + APB_CSR_REQ_SEL_MASK << APB_CSR_REQ_SEL_SHIFT); + setbits_le32(&dma->regs->csr, APB_CSR_ONCE | APB_CSR_FLOW | + (spi->req_sel << APB_CSR_REQ_SEL_SHIFT)); +} + +static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi, + unsigned int bytes, enum spi_direction dir) +{ + unsigned int todo, wcount; + + /* + * For DMA we need to think of things in terms of word count. + * AHB width is fixed at 32-bits. To avoid overrunning + * the in/out buffers we must align down. (Note: lowest 2-bits + * in WCOUNT register are ignored, and WCOUNT seems to count + * words starting at n-1) + * + * Example: If "bytes" is 7 and we are transferring 1-byte at a time, + * WCOUNT should be 4. The remaining 3 bytes must be transferred + * using PIO. + */ + todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_DMA - TEGRA_DMA_ALIGN_BYTES); + todo = ALIGN_DOWN(todo, TEGRA_DMA_ALIGN_BYTES); + wcount = ALIGN_DOWN(todo - TEGRA_DMA_ALIGN_BYTES, TEGRA_DMA_ALIGN_BYTES); + + if (dir == SPI_SEND) { + spi->dma_out = dma_claim(); + if (!spi->dma_out) + return -1; + + /* ensure bytes to send will be visible to DMA controller */ + dcache_clean_by_mva(spi->out_buf, bytes); + + write32((uintptr_t)&spi->regs->tx_fifo, &spi->dma_out->regs->apb_ptr); + write32((uintptr_t)spi->out_buf, &spi->dma_out->regs->ahb_ptr); + setbits_le32(&spi->dma_out->regs->csr, APB_CSR_DIR); + setup_dma_params(spi, spi->dma_out); + write32(wcount, &spi->dma_out->regs->wcount); + } else { + spi->dma_in = dma_claim(); + if (!spi->dma_in) + return -1; + + /* avoid data collisions */ + dcache_clean_invalidate_by_mva(spi->in_buf, bytes); + + write32((uintptr_t)&spi->regs->rx_fifo, &spi->dma_in->regs->apb_ptr); + write32((uintptr_t)spi->in_buf, &spi->dma_in->regs->ahb_ptr); + clrbits_le32(&spi->dma_in->regs->csr, APB_CSR_DIR); + setup_dma_params(spi, spi->dma_in); + write32(wcount, &spi->dma_in->regs->wcount); + } + + /* BLOCK_SIZE starts at n-1 */ + write32(todo - 1, &spi->regs->dma_blk); + return todo; +} + +static void tegra_spi_dma_start(struct tegra_spi_channel *spi) +{ + /* + * The RDY bit in SPI_TRANS_STATUS needs to be cleared manually + * (set bit to clear) between each transaction. Otherwise the next + * transaction does not start. + */ + setbits_le32(&spi->regs->trans_status, SPI_STATUS_RDY); + + /* + * The DMA triggers have units of packets. As each packet is currently + * 1 byte the triggers need to be set to 4 packets (0b01) to match + * the AHB 32-bit (4 byte) tranfser. Otherwise the FIFO errors can + * occur. + */ + if (spi->dma_out) { + clrsetbits_le32(&spi->regs->dma_ctl, + SPI_DMA_CTL_TX_TRIG_MASK << SPI_DMA_CTL_TX_TRIG_SHIFT, + 1 << SPI_DMA_CTL_TX_TRIG_SHIFT); + setbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN); + } + if (spi->dma_in) { + clrsetbits_le32(&spi->regs->dma_ctl, + SPI_DMA_CTL_RX_TRIG_MASK << SPI_DMA_CTL_RX_TRIG_SHIFT, + 1 << SPI_DMA_CTL_RX_TRIG_SHIFT); + setbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN); + } + + /* + * To avoid underrun conditions, enable APB DMA before SPI DMA for + * Tx and enable SPI DMA before APB DMA before Rx. + */ + if (spi->dma_out) + dma_start(spi->dma_out); + setbits_le32(&spi->regs->dma_ctl, SPI_DMA_CTL_DMA); + if (spi->dma_in) + dma_start(spi->dma_in); + + +} + +static int tegra_spi_dma_finish(struct tegra_spi_channel *spi) +{ + int ret; + unsigned int todo; + + todo = read32(&spi->dma_in->regs->wcount); + + if (spi->dma_in) { + while ((read32(&spi->dma_in->regs->dma_byte_sta) < todo) || + dma_busy(spi->dma_in)) + ; /* this shouldn't take long, no udelay */ + dma_stop(spi->dma_in); + clrbits_le32(&spi->regs->command1, SPI_CMD1_RX_EN); + dma_release(spi->dma_in); + } + + if (spi->dma_out) { + while ((read32(&spi->dma_out->regs->dma_byte_sta) < todo) || + dma_busy(spi->dma_out)) + spi_delay(spi, todo - spi_byte_count(spi)); + clrbits_le32(&spi->regs->command1, SPI_CMD1_TX_EN); + dma_stop(spi->dma_out); + dma_release(spi->dma_out); + } + + if (fifo_error(spi)) { + printk(BIOS_ERR, "%s: ERROR:\n", __func__); + dump_dma_regs(spi->dma_out); + dump_dma_regs(spi->dma_in); + dump_spi_regs(spi); + dump_fifo_status(spi); + ret = -1; + goto done; + } + + ret = 0; +done: + spi->dma_in = NULL; + spi->dma_out = NULL; + return ret; +} + +/* + * xfer_setup() prepares a transfer. It does sanity checking, alignment, and + * sets transfer mode used by this channel (if not set already). + * + * A few caveats to watch out for: + * - The number of bytes which can be transferred may be smaller than the + * number of bytes the caller specifies. The number of bytes ready for + * a transfer will be returned (unless an error occurs). + * + * - Only one mode can be used for both RX and TX. The transfer mode of the + * SPI channel (spi->xfer_mode) is checked each time this function is called. + * If conflicting modes are detected, spi->xfer_mode will be set to + * XFER_MODE_NONE and an error will be returned. + * + * Returns bytes ready for transfer if successful, <0 to indicate error. + */ +static int xfer_setup(struct tegra_spi_channel *spi, void *buf, + unsigned int bytes, enum spi_direction dir) +{ + unsigned int line_size = dcache_line_bytes(); + unsigned int align; + int ret = -1; + + if (!bytes) + return 0; + + if (dir == SPI_SEND) + spi->out_buf = buf; + else if (dir == SPI_RECEIVE) + spi->in_buf = buf; + + /* + * Alignment consideratons: + * When we enable caching we'll need to clean/invalidate portions of + * memory. So we need to be careful about memory alignment. Also, DMA + * likes to operate on 4-bytes at a time on the AHB side. So for + * example, if we only want to receive 1 byte, 4 bytes will be be + * written in memory even if those extra 3 bytes are beyond the length + * we want. + * + * For now we'll use PIO to send/receive unaligned bytes. We may + * consider setting aside some space for a kind of bounce buffer to + * stay in DMA mode once we have a chance to benchmark the two + * approaches. + */ + + if (bytes < line_size) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, bytes, dir); + } + goto done; + } + + /* transfer bytes before the aligned boundary */ + align = line_size - ((uintptr_t)buf % line_size); + if ((align != 0) && (align != line_size)) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, align, dir); + } + goto done; + } + + /* do aligned DMA transfer */ + align = (((uintptr_t)buf + bytes) % line_size); + if (bytes - align > 0) { + unsigned int dma_bytes = bytes - align; + + if (spi->xfer_mode == XFER_MODE_PIO) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_DMA; + ret = tegra_spi_dma_prepare(spi, dma_bytes, dir); + } + + goto done; + } + + /* transfer any remaining unaligned bytes */ + if (align) { + if (spi->xfer_mode == XFER_MODE_DMA) { + spi->xfer_mode = XFER_MODE_NONE; + ret = -1; + } else { + spi->xfer_mode = XFER_MODE_PIO; + ret = tegra_spi_pio_prepare(spi, align, dir); + } + goto done; + } + +done: + return ret; +} + +static void xfer_start(struct tegra_spi_channel *spi) +{ + if (spi->xfer_mode == XFER_MODE_DMA) + tegra_spi_dma_start(spi); + else + tegra_spi_pio_start(spi); +} + +static void xfer_wait(struct tegra_spi_channel *spi) +{ + tegra_spi_wait(spi); +} + +static int xfer_finish(struct tegra_spi_channel *spi) +{ + int ret; + + if (spi->xfer_mode == XFER_MODE_DMA) + ret = tegra_spi_dma_finish(spi); + else + ret = tegra_spi_pio_finish(spi); + + spi->xfer_mode = XFER_MODE_NONE; + return ret; +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int out_bytes, void *din, unsigned int in_bytes) +{ + struct tegra_spi_channel *spi = to_tegra_spi(slave->bus); + u8 *out_buf = (u8 *)dout; + u8 *in_buf = (u8 *)din; + unsigned int todo; + int ret = 0; + + /* tegra bus numbers start at 1 */ + ASSERT(slave->bus >= 1 && slave->bus <= ARRAY_SIZE(tegra_spi_channels)); + + while (out_bytes || in_bytes) { + int x = 0; + + if (out_bytes == 0) + todo = in_bytes; + else if (in_bytes == 0) + todo = out_bytes; + else + todo = MIN(out_bytes, in_bytes); + + if (out_bytes) { + x = xfer_setup(spi, out_buf, todo, SPI_SEND); + if (x < 0) { + if (spi->xfer_mode == XFER_MODE_NONE) { + spi->xfer_mode = XFER_MODE_PIO; + continue; + } else { + ret = -1; + break; + } + } + } + if (in_bytes) { + x = xfer_setup(spi, in_buf, todo, SPI_RECEIVE); + if (x < 0) { + if (spi->xfer_mode == XFER_MODE_NONE) { + spi->xfer_mode = XFER_MODE_PIO; + continue; + } else { + ret = -1; + break; + } + } + } + + /* + * Note: Some devices (such as Chrome EC) are sensitive to + * delays, so be careful when adding debug prints not to + * cause timeouts between transfers. + */ + xfer_start(spi); + xfer_wait(spi); + if (xfer_finish(spi)) { + ret = -1; + break; + } + + /* Post-processing. */ + if (out_bytes) { + out_bytes -= x; + out_buf += x; + } + if (in_bytes) { + in_bytes -= x; + in_buf += x; + } + } + + if (ret < 0) { + printk(BIOS_ERR, "%s: Error detected\n", __func__); + printk(BIOS_ERR, "Transaction size: %u, bytes remaining: " + "%u out / %u in\n", todo, out_bytes, in_bytes); + clear_fifo_status(spi); + } + return ret; +} + +/* SPI as CBFS media. */ +struct tegra_spi_media { + struct spi_slave *slave; + struct cbfs_simple_buffer buffer; +}; + +static int tegra_spi_cbfs_open(struct cbfs_media *media) +{ + DEBUG_SPI("tegra_spi_cbfs_open\n"); + return 0; +} + +static int tegra_spi_cbfs_close(struct cbfs_media *media) +{ + DEBUG_SPI("tegra_spi_cbfs_close\n"); + return 0; +} + +#define JEDEC_READ 0x03 +#define JEDEC_READ_OUTSIZE 0x04 +#define JEDEC_FAST_READ_DUAL 0x3b +#define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05 + +static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context; + u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE]; + unsigned int read_cmd_bytes; + int ret = count; + struct tegra_spi_channel *channel; + + channel = to_tegra_spi(spi->slave->bus); + + if (channel->dual_mode) { + /* + * Command 0x3b will interleave data only, command 0xbb will + * interleave the address as well. It's nice to see the address + * plainly when debugging, and we're mostly concerned with + * large transfers so the optimization of using 0xbb isn't + * really worthwhile. + */ + spi_read_cmd[0] = JEDEC_FAST_READ_DUAL; + spi_read_cmd[4] = 0x00; /* dummy byte */ + read_cmd_bytes = JEDEC_FAST_READ_DUAL_OUTSIZE; + } else { + spi_read_cmd[0] = JEDEC_READ; + read_cmd_bytes = JEDEC_READ_OUTSIZE; + } + spi_read_cmd[1] = (offset >> 16) & 0xff; + spi_read_cmd[2] = (offset >> 8) & 0xff; + spi_read_cmd[3] = offset & 0xff; + + spi_claim_bus(spi->slave); + + if (spi_xfer(spi->slave, spi_read_cmd, + read_cmd_bytes, NULL, 0) < 0) { + ret = -1; + printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n", + __func__, sizeof(spi_read_cmd)); + goto tegra_spi_cbfs_read_exit; + } + + if (channel->dual_mode) { + setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); + } + if (spi_xfer(spi->slave, NULL, 0, dest, count)) { + ret = -1; + printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n", + __func__, count); + } + if (channel->dual_mode) + clrbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); + +tegra_spi_cbfs_read_exit: + /* de-assert /CS */ + spi_release_bus(spi->slave); + return (ret < 0) ? 0 : ret; +} + +static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; + void *map; + DEBUG_SPI("tegra_spi_cbfs_map\n"); + map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count); + return map; +} + +static void *tegra_spi_cbfs_unmap(struct cbfs_media *media, + const void *address) +{ + struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; + DEBUG_SPI("tegra_spi_cbfs_unmap\n"); + return cbfs_simple_buffer_unmap(&spi->buffer, address); +} + +int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size) +{ + // TODO Replace static variable to support multiple streams. + static struct tegra_spi_media context; + static struct tegra_spi_channel *channel; + + channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; + channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT; + + DEBUG_SPI("Initializing CBFS media on SPI\n"); + + context.slave = &channel->slave; + context.buffer.allocated = context.buffer.last_allocate = 0; + context.buffer.buffer = buffer_address; + context.buffer.size = buffer_size; + media->context = (void*)&context; + media->open = tegra_spi_cbfs_open; + media->close = tegra_spi_cbfs_close; + media->read = tegra_spi_cbfs_read; + media->map = tegra_spi_cbfs_map; + media->unmap = tegra_spi_cbfs_unmap; + +#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1 + channel->dual_mode = 1; +#endif + + return 0; +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + struct tegra_spi_channel *channel = to_tegra_spi(bus); + if (!channel) + return NULL; + + return &channel->slave; +} diff --git a/src/soc/nvidia/tegra132/stack.S b/src/soc/nvidia/tegra132/stack.S new file mode 100644 index 0000000000..3b877e4be6 --- /dev/null +++ b/src/soc/nvidia/tegra132/stack.S @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Macro to initialize stack, perform seeding if required and finally call the + * function provided + * @stack_top : First address above the stack + * @stack_bottom : Lowest address on the stack + * @seed : Stack seeding required (1=yes/otherwise=no) + * @func : Function to call after initializing stack + */ +.macro stack_init stack_top, stack_bottom, seed, func + /* Check if stack seeding is required */ + mov r0, #\seed + cmp r0, #1 + bne call_func + /* Stack seeding */ + ldr r0, =\stack_bottom + ldr r1, =\stack_top + ldr r2, =0xdeadbeef +init_stack_loop: + str r2, [r0] + add r0, #4 + cmp r0, r1 + bne init_stack_loop + +call_func: + ldr sp, =\stack_top /* Set up stack pointer */ + bl \func +.endm diff --git a/src/soc/nvidia/tegra132/uart.c b/src/soc/nvidia/tegra132/uart.c new file mode 100644 index 0000000000..a3d5c7acab --- /dev/null +++ b/src/soc/nvidia/tegra132/uart.c @@ -0,0 +1,138 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include /* for __console definition */ +#include +#include +#include + +struct tegra132_uart { + union { + uint32_t thr; // Transmit holding register. + uint32_t rbr; // Receive buffer register. + uint32_t dll; // Divisor latch lsb. + }; + union { + uint32_t ier; // Interrupt enable register. + uint32_t dlm; // Divisor latch msb. + }; + union { + uint32_t iir; // Interrupt identification register. + uint32_t fcr; // FIFO control register. + }; + uint32_t lcr; // Line control register. + uint32_t mcr; // Modem control register. + uint32_t lsr; // Line status register. + uint32_t msr; // Modem status register. +} __attribute__ ((packed)); + + +static struct tegra132_uart * const uart_ptr = + (void *)CONFIG_CONSOLE_SERIAL_TEGRA132_UART_ADDRESS; + +static void tegra132_uart_tx_flush(void); +static int tegra132_uart_tst_byte(void); + +static void tegra132_uart_init(void) +{ + // Use a hardcoded divisor for now. + const unsigned divisor = 221; + const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1 + + tegra132_uart_tx_flush(); + + // Disable interrupts. + write8(0, &uart_ptr->ier); + // Force DTR and RTS to high. + write8(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr); + // Set line configuration, access divisor latches. + write8(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr); + // Set the divisor. + write8(divisor & 0xff, &uart_ptr->dll); + write8((divisor >> 8) & 0xff, &uart_ptr->dlm); + // Hide the divisor latches. + write8(line_config, &uart_ptr->lcr); + // Enable FIFOs, and clear receive and transmit. + write8(UART8250_FCR_FIFO_EN | + UART8250_FCR_CLEAR_RCVR | + UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr); +} + +static void tegra132_uart_tx_byte(unsigned char data) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE)); + write8(data, &uart_ptr->thr); +} + +static void tegra132_uart_tx_flush(void) +{ + while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT)); +} + +static unsigned char tegra132_uart_rx_byte(void) +{ + if (!tegra132_uart_tst_byte()) + return 0; + return read8(&uart_ptr->rbr); +} + +static int tegra132_uart_tst_byte(void) +{ + return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR; +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver tegra132_uart_console __console = { + .init = tegra132_uart_init, + .tx_byte = tegra132_uart_tx_byte, + .tx_flush = tegra132_uart_tx_flush, + .rx_byte = tegra132_uart_rx_byte, + .tst_byte = tegra132_uart_tst_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return (uintptr_t)uart_ptr; +} + +#else + +void uart_init(void) +{ + tegra132_uart_init(); +} + +void uart_tx_byte(unsigned char data) +{ + tegra132_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ + tegra132_uart_tx_flush(); +} + +unsigned char uart_rx_byte(void) +{ + return tegra132_uart_rx_byte(); +} + +#endif diff --git a/src/soc/nvidia/tegra132/verstage.c b/src/soc/nvidia/tegra132/verstage.c new file mode 100644 index 0000000000..2f036696a9 --- /dev/null +++ b/src/soc/nvidia/tegra132/verstage.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void __attribute__((weak)) verstage_mainboard_init(void) +{ + /* Default empty implementation. */ +} + +static void verstage(void) +{ + void *entry; + + console_init(); + timestamp_add_now(TS_START_VBOOT); + exception_init(); + verstage_mainboard_init(); + + entry = vboot2_verify_firmware(); + if (entry != (void *)-1) + stage_exit(entry); +} + +void main(void) +{ + verstage(); + hlt(); +} diff --git a/src/soc/qualcomm/Kconfig b/src/soc/qualcomm/Kconfig new file mode 100644 index 0000000000..b7a12d4f9c --- /dev/null +++ b/src/soc/qualcomm/Kconfig @@ -0,0 +1 @@ +source src/soc/qualcomm/ipq806x/Kconfig diff --git a/src/soc/qualcomm/Makefile.inc b/src/soc/qualcomm/Makefile.inc new file mode 100644 index 0000000000..06b2f2f2c3 --- /dev/null +++ b/src/soc/qualcomm/Makefile.inc @@ -0,0 +1 @@ +subdirs-$(CONFIG_SOC_QC_IPQ806X) += ipq806x diff --git a/src/soc/qualcomm/ipq806x/Kconfig b/src/soc/qualcomm/ipq806x/Kconfig new file mode 100644 index 0000000000..eb840f0814 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/Kconfig @@ -0,0 +1,32 @@ +config SOC_QC_IPQ806X + bool + default n + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_VERSTAGE_ARM_V7 + select BOOTBLOCK_CONSOLE + select DYNAMIC_CBMEM + select EARLY_CONSOLE + select HAVE_UART_MEMORY_MAPPED + select HAVE_UART_SPECIAL + select SPI_ATOMIC_SEQUENCING + select GENERIC_GPIO_LIB + +if SOC_QC_IPQ806X + +config MBN_ENCAPSULATION + depends on USE_BLOBS + bool "bootblock encapsulation for ipq8064" + default y + +config SBL_BLOB + depends on USE_BLOBS + string "file name of the Qualcomm SBL blob" + default "3rdparty/cpu/qualcomm/ipq806x/uber-sbl.mbn" + help + The path and filename of the binary blob containing + ipq806x early initialization code, as supplied by the + vendor. + +endif diff --git a/src/soc/qualcomm/ipq806x/Makefile.inc b/src/soc/qualcomm/ipq806x/Makefile.inc new file mode 100644 index 0000000000..aad4a54944 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/Makefile.inc @@ -0,0 +1,86 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Google Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +bootblock-y += clock.c +bootblock-y += gpio.c +bootblock-$(CONFIG_SPI_FLASH) += spi.c +bootblock-y += timer.c +bootblock-$(CONFIG_CONSOLE_SERIAL_IPQ806X) += uart.c + +verstage-y += clock.c +verstage-y += gpio.c +verstage-y += spi.c +verstage-y += timer.c +verstage-$(CONFIG_CONSOLE_SERIAL_IPQ806X) += uart.c + +romstage-y += clock.c +romstage-y += gpio.c +romstage-$(CONFIG_SPI_FLASH) += spi.c +romstage-y += timer.c +romstage-$(CONFIG_CONSOLE_SERIAL_IPQ806X) += uart.c +romstage-$(CONFIG_DYNAMIC_CBMEM) += cbmem.c + +ramstage-y += cbmem.c +ramstage-y += clock.c +ramstage-y += gpio.c +ramstage-y += soc.c +ramstage-$(CONFIG_SPI_FLASH) += spi.c +ramstage-y += timer.c +ramstage-$(CONFIG_CONSOLE_SERIAL_IPQ806X) += uart.c +ramstage-y += usb.c + +INCLUDES += -Isrc/soc/qualcomm/ipq806x/include/ + +ifeq ($(CONFIG_USE_BLOBS),y) + +# Generate the actual coreboot bootblock code +$(objcbfs)/bootblock.raw: $(objcbfs)/bootblock.elf + @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" + $(OBJCOPY_bootblock) -O binary $< $@.tmp + @mv $@.tmp $@ + +# Add MBN header to allow SBL3 to start coreboot bootblock +$(objcbfs)/bootblock.mbn: $(objcbfs)/bootblock.raw + @printf " ADD MBN $(subst $(obj)/,,$(@))\n" + ./util/ipqheader/ipqheader.py $(call loadaddr,bootblock) $< $@.tmp + @mv $@.tmp $@ + +# Create a complete bootblock which will start up the system +$(objcbfs)/bootblock.bin: $(call strip_quotes,$(CONFIG_SBL_BLOB)) \ + $(objcbfs)/bootblock.mbn + @printf " MBNCAT $(subst $(obj)/,,$(@))\n" + @util/ipqheader/mbncat.py -o $@.tmp $^ + @mv $@.tmp $@ + +endif + +INCLUDES += -Isrc/soc/qualcomm/ipq806x/include + +# List of binary blobs coreboot needs in CBFS to be able to boot up this SOC +mbn-files := cdt.mbn ddr.mbn rpm.mbn tz.mbn + +# Location of the binary blobs +mbn-root := 3rdparty/cpu/qualcomm/ipq806x + +# Create make variables to aid cbfs-files-handler in processing the blobs (add +# them all as raw binaries at the root level). +$(foreach f,$(mbn-files),$(eval cbfs-files-y += $(f))\ + $(eval $(f)-file := $(mbn-root)/$(f))\ + $(eval $(f)-type := raw)) + diff --git a/src/soc/qualcomm/ipq806x/cbmem.c b/src/soc/qualcomm/ipq806x/cbmem.c new file mode 100644 index 0000000000..fdf2605147 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/cbmem.c @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void *cbmem_top(void) +{ + return (void *)((uintptr_t)_dram + CONFIG_DRAM_SIZE_MB*MiB); +} diff --git a/src/soc/qualcomm/ipq806x/clock.c b/src/soc/qualcomm/ipq806x/clock.c new file mode 100644 index 0000000000..5cdb9bef65 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/clock.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved. + */ + +#include +#include + +/** + * uart_pll_vote_clk_enable - enables PLL8 + */ +void uart_pll_vote_clk_enable(unsigned int clk_dummy) +{ + setbits_le32(BB_PLL_ENA_SC0_REG, BIT(8)); + + if (!clk_dummy) + while((readl(PLL_LOCK_DET_STATUS_REG) & BIT(8)) == 0); +} + +/** + * uart_set_rate_mnd - configures divider M and D values + * + * Sets the M, D parameters of the divider to generate the GSBI UART + * apps clock. + */ +static void uart_set_rate_mnd(unsigned int gsbi_port, unsigned int m, + unsigned int n) +{ + /* Assert MND reset. */ + setbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(7)); + /* Program M and D values. */ + writel(MD16(m, n), GSBIn_UART_APPS_MD_REG(gsbi_port)); + /* Deassert MND reset. */ + clrbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(7)); +} + +/** + * uart_branch_clk_enable_reg - enables branch clock + * + * Enables branch clock for GSBI UART port. + */ +static void uart_branch_clk_enable_reg(unsigned int gsbi_port) +{ + setbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(9)); +} + +/** + * uart_local_clock_enable - configures N value and enables root clocks + * + * Sets the N parameter of the divider and enables root clock and + * branch clocks for GSBI UART port. + */ +static void uart_local_clock_enable(unsigned int gsbi_port, unsigned int n, + unsigned int m) +{ + unsigned int reg_val, uart_ns_val; + void *const reg = (void *)GSBIn_UART_APPS_NS_REG(gsbi_port); + + /* + * Program the NS register, if applicable. NS registers are not + * set in the set_rate path because power can be saved by deferring + * the selection of a clocked source until the clock is enabled. + */ + reg_val = readl(reg); // REG(0x29D4+(0x20*((n)-1))) + reg_val &= ~(Uart_clk_ns_mask); + uart_ns_val = NS(BIT_POS_31,BIT_POS_16,n,m, 5, 4, 3, 1, 2, 0,3); + reg_val |= (uart_ns_val & Uart_clk_ns_mask); + writel(reg_val,reg); + + /* enable MNCNTR_EN */ + reg_val = readl(reg); + reg_val |= BIT(8); + writel(reg_val, reg); + + /* set source to PLL8 running @384MHz */ + reg_val = readl(reg); + reg_val |= 0x3; + writel(reg_val, reg); + + /* Enable root. */ + reg_val |= Uart_en_mask; + writel(reg_val, reg); + uart_branch_clk_enable_reg(gsbi_port); +} + +/** + * uart_set_gsbi_clk - enables HCLK for UART GSBI port + */ +static void uart_set_gsbi_clk(unsigned int gsbi_port) +{ + setbits_le32(GSBIn_HCLK_CTL_REG(gsbi_port), BIT(4)); +} + +/** + * uart_clock_config - configures UART clocks + * + * Configures GSBI UART dividers, enable root and branch clocks. + */ +void uart_clock_config(unsigned int gsbi_port, unsigned int m, + unsigned int n, unsigned int d, unsigned int clk_dummy) +{ + uart_set_rate_mnd(gsbi_port, m, d); + uart_pll_vote_clk_enable(clk_dummy); + uart_local_clock_enable(gsbi_port, n, m); + uart_set_gsbi_clk(gsbi_port); +} + +/** + * nand_clock_config - configure NAND controller clocks + * + * Enable clocks to EBI2. Must be invoked before touching EBI2 + * registers. + */ +void nand_clock_config(void) +{ + writel(CLK_BRANCH_ENA(1) | ALWAYS_ON_CLK_BRANCH_ENA(1), + EBI2_CLK_CTL_REG); + + /* Wait for clock to stabilize. */ + udelay(10); +} + +/** + * usb_clock_config - configure USB controller clocks and reset the controller + */ +void usb_clock_config(void) +{ + /* Magic clock initialization numbers, nobody knows how they work... */ + write32(0x10, USB30_MASTER_CLK_CTL_REG); + write32(0x10, USB30_1_MASTER_CLK_CTL_REG); + write32(0x500DF, USB30_MASTER_CLK_MD); + write32(0xE40942, USB30_MASTER_CLK_NS); + write32(0x100D7, USB30_MOC_UTMI_CLK_MD); + write32(0xD80942, USB30_MOC_UTMI_CLK_NS); + write32(0x10, USB30_MOC_UTMI_CLK_CTL); + write32(0x10, USB30_1_MOC_UTMI_CLK_CTL); + + write32(1 << 5 | /* assert port2 HS PHY async reset */ + 1 << 4 | /* assert master async reset */ + 1 << 3 | /* assert sleep async reset */ + 1 << 2 | /* assert MOC UTMI async reset */ + 1 << 1 | /* assert power-on async reset */ + 1 << 0 | /* assert PHY async reset */ + 0, USB30_RESET); + udelay(5); + write32(0, USB30_RESET); /* deassert all USB resets again */ +} diff --git a/src/soc/qualcomm/ipq806x/gpio.c b/src/soc/qualcomm/ipq806x/gpio.c new file mode 100644 index 0000000000..a0a3df9495 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/gpio.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +/******************************************************* +Function description: check for invalid GPIO # +Arguments : +gpio_t gpio - Gpio number + +Return : GPIO Valid(0)/Invalid(1) +*******************************************************/ + +static inline int gpio_not_valid(gpio_t gpio) +{ + return (gpio > GPIO_MAX_NUM); +} + + +/******************************************************* +Function description: configure GPIO functinality +Arguments : +gpio_t gpio - Gpio number +unsigned func - Functionality number +unsigned pull - pull up/down, no pull range(0-3) +unsigned drvstr - range (0 - 7)-> (2- 16)MA steps of 2 +unsigned enable - 0 Disable, 1 - Enable. + +Return : None +*******************************************************/ + + +void gpio_tlmm_config_set(gpio_t gpio, unsigned func, + unsigned pull, unsigned drvstr, + unsigned enable) +{ + unsigned val = 0; + + if (gpio_not_valid(gpio)) + return; + + val |= (pull & GPIO_CFG_PULL_MASK) << GPIO_CFG_PULL_SHIFT; + val |= (func & GPIO_CFG_FUNC_MASK) << GPIO_CFG_FUNC_SHIFT; + val |= (drvstr & GPIO_CFG_DRV_MASK) << GPIO_CFG_DRV_SHIFT; + val |= (enable & GPIO_CFG_OE_MASK) << GPIO_CFG_OE_SHIFT; + + writel(val, GPIO_CONFIG_ADDR(gpio)); +} + +/******************************************************* +Function description: Get GPIO configuration +Arguments : +gpio_t gpio - Gpio number +unsigned *func - Functionality number +unsigned *pull - pull up/down, no pull range(0-3) +unsigned *drvstr - range (0 - 7)-> (2- 16)MA steps of 2 +unsigned *enable - 0 - Disable, 1- Enable. + +Return : None +*******************************************************/ + + +void gpio_tlmm_config_get(gpio_t gpio, unsigned *func, + unsigned *pull, unsigned *drvstr, + unsigned *enable) +{ + unsigned val; + void *addr = GPIO_CONFIG_ADDR(gpio); + + if (gpio_not_valid(gpio)) + return; + + val = readl(addr); + + *pull = (val >> GPIO_CFG_PULL_SHIFT) & GPIO_CFG_PULL_MASK; + *func = (val >> GPIO_CFG_FUNC_SHIFT) & GPIO_CFG_FUNC_MASK; + *drvstr = (val >> GPIO_CFG_DRV_SHIFT) & GPIO_CFG_DRV_MASK; + *enable = (val >> GPIO_CFG_OE_SHIFT) & GPIO_CFG_OE_MASK; +} + +/******************************************************* +Function description: get GPIO IO functinality details +Arguments : +gpio_t gpio - Gpio number +unsigned *in - Value of GPIO input +unsigned *out - Value of GPIO output + +Return : None +*******************************************************/ +int gpio_get(gpio_t gpio) +{ + if (gpio_not_valid(gpio)) + return -1; + + + return (readl(GPIO_IN_OUT_ADDR(gpio)) >> GPIO_IO_IN_SHIFT) & + GPIO_IO_IN_MASK; +} + +void gpio_set(gpio_t gpio, int value) +{ + if (gpio_not_valid(gpio)) + return; + + writel((value & 1) << GPIO_IO_OUT_SHIFT, GPIO_IN_OUT_ADDR(gpio)); +} + +void gpio_input_pulldown(gpio_t gpio) +{ + gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE, + GPIO_PULL_DOWN, GPIO_2MA, GPIO_DISABLE); +} + +void gpio_input_pullup(gpio_t gpio) +{ + gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE, + GPIO_PULL_UP, GPIO_2MA, GPIO_DISABLE); +} + +void gpio_input(gpio_t gpio) +{ + gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE, + GPIO_NO_PULL, GPIO_2MA, GPIO_DISABLE); +} + diff --git a/src/soc/qualcomm/ipq806x/gsbi.c b/src/soc/qualcomm/ipq806x/gsbi.c new file mode 100644 index 0000000000..be75d9a043 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/gsbi.c @@ -0,0 +1,115 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "drivers/gpio/ipq806x.h" +#include "ipq806x_gsbi.h" + +//TODO: To be implemented as part of the iomap. +static int gsbi_base[] = { + 0x12440000, /*GSBI1*/ + 0x12480000, /*GSBI2*/ + 0x16200000, /*GSBI3*/ + 0x16300000, /*GSBI4*/ + 0x1A200000, /*GSBI5*/ + 0x16500000, /*GSBI6*/ + 0x16600000 /*GSBI7*/ +}; + +#define QUP_APPS_ADDR(N, os) ((void *)((0x009029C8+os)+(32*(N-1)))) +#define GSBI_HCLK_CTL(N) ((void *)(0x009029C0 + (32*(N-1)))) +#define GSBI_RESET(N) ((void *)(0x009029DC + (32*(N-1)))) +#define GSBI_CTL(N) ((void *)(gsbi_base[N-1])) + +#define GSBI_APPS_MD_OFFSET 0x0 +#define GSBI_APPS_NS_OFFSET 0x4 +#define GSBI_APPS_MAX_OFFSET 0xff + +#define GPIO_FUNC_I2C 0x1 + +gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol) +{ + unsigned i = 0; + unsigned qup_apps_ini[] = { + GSBI_APPS_NS_OFFSET, 0xf80b43, + GSBI_APPS_NS_OFFSET, 0xfc095b, + GSBI_APPS_NS_OFFSET, 0xfc015b, + GSBI_APPS_NS_OFFSET, 0xfc005b, + GSBI_APPS_NS_OFFSET, 0xA05, + GSBI_APPS_NS_OFFSET, 0x185, + GSBI_APPS_MD_OFFSET, 0x100fb, + GSBI_APPS_NS_OFFSET, 0xA05, + GSBI_APPS_NS_OFFSET, 0xfc015b, + GSBI_APPS_NS_OFFSET, 0xfc015b, + GSBI_APPS_NS_OFFSET, 0xfc095b, + GSBI_APPS_NS_OFFSET, 0xfc0b5b, + GSBI_APPS_MAX_OFFSET, 0x0 + }; + + gsbi_return_t ret = GSBI_SUCCESS; + + writel(0, GSBI_RESET(gsbi_id)); + + switch (gsbi_id) { + case GSBI_ID_4: { + /* Configure GPIOs 13 - SCL, 12 - SDA, 2mA gpio_en */ + gpio_tlmm_config_set(12, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + gpio_tlmm_config_set(13, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + } + break; + case GSBI_ID_1: { + /* Configure GPIOs 54 - SCL, 53 - SDA, 2mA gpio_en */ + gpio_tlmm_config_set(54, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + gpio_tlmm_config_set(53, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + } + break; + default: { + ret = GSBI_UNSUPPORTED; + goto bail_out; + } + } + + /*Select i2c protocol*/ + writel((2 << 4), GSBI_CTL(gsbi_id)); + + //TODO: Make use of clock API when available instead of the hardcoding. + /* Clock set to 24Mhz */ + for (i = 0; GSBI_APPS_MAX_OFFSET != qup_apps_ini[i]; i += 2) + writel(qup_apps_ini[i+1], + QUP_APPS_ADDR(gsbi_id, qup_apps_ini[i])); + + writel(((1 << 6)|(1 << 4)), GSBI_HCLK_CTL(gsbi_id)); + +bail_out: + return ret; +} diff --git a/src/soc/qualcomm/ipq806x/gsbi.h b/src/soc/qualcomm/ipq806x/gsbi.h new file mode 100644 index 0000000000..0da7a4796e --- /dev/null +++ b/src/soc/qualcomm/ipq806x/gsbi.h @@ -0,0 +1,60 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __GSBI_TYPES_H__ +#define __GSBI_TYPES_H__ + +typedef enum { + GSBI_ID_1 = 1, + GSBI_ID_2, + GSBI_ID_3, + GSBI_ID_4, + GSBI_ID_5, + GSBI_ID_6, + GSBI_ID_7, +} gsbi_id_t; + +typedef enum { + GSBI_SUCCESS = 0, + GSBI_ID_ERROR, + GSBI_ERROR, + GSBI_UNSUPPORTED +} gsbi_return_t; + +typedef enum { + GSBI_PROTO_I2C_UIM = 1, + GSBI_PROTO_I2C_ONLY, + GSBI_PROTO_SPI_ONLY, + GSBI_PROTO_UART_FLOW_CTL, + GSBI_PROTO_UIM, + GSBI_PROTO_I2C_UART, +} gsbi_protocol_t; + +gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol); +#endif diff --git a/src/soc/qualcomm/ipq806x/i2c.c b/src/soc/qualcomm/ipq806x/i2c.c new file mode 100644 index 0000000000..9bae822a8e --- /dev/null +++ b/src/soc/qualcomm/ipq806x/i2c.c @@ -0,0 +1,143 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "base/container_of.h" +#include "drivers/bus/i2c/i2c.h" +#include "drivers/bus/i2c/ipq806x_qup.h" +#include "drivers/bus/i2c/ipq806x_gsbi.h" +#include "drivers/bus/i2c/ipq806x.h" + +static int i2c_init(unsigned gsbi_id) +{ + gsbi_return_t gsbi_ret = 0; + qup_return_t qup_ret = 0; + qup_config_t gsbi4_qup_config = { + QUP_MINICORE_I2C_MASTER, + 100000, + 24000000, + QUP_MODE_FIFO + }; + + gsbi_ret = gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY); + if (GSBI_SUCCESS != gsbi_ret) + return 1; + + qup_ret = qup_init(gsbi_id, &gsbi4_qup_config); + if (QUP_SUCCESS != qup_ret) + return 1; + + qup_ret = qup_reset_i2c_master_status(gsbi_id); + if (QUP_SUCCESS != qup_ret) + return 1; + + return 0; +} + +static int i2c_read(uint32_t gsbi_id, uint8_t slave, + uint8_t *data, int data_len) +{ + qup_data_t obj; + qup_return_t qup_ret = 0; + + memset(&obj, 0, sizeof(obj)); + obj.protocol = QUP_MINICORE_I2C_MASTER; + obj.p.iic.addr = slave; + obj.p.iic.data_len = data_len; + obj.p.iic.data = data; + qup_ret = qup_recv_data(gsbi_id, &obj); + + if (QUP_SUCCESS != qup_ret) + return 1; + else + return 0; +} + +static int i2c_write(uint32_t gsbi_id, uint8_t slave, + uint8_t *data, int data_len, uint8_t stop_seq) +{ + qup_data_t obj; + qup_return_t qup_ret = 0; + + memset(&obj, 0, sizeof(obj)); + obj.protocol = QUP_MINICORE_I2C_MASTER; + obj.p.iic.addr = slave; + obj.p.iic.data_len = data_len; + obj.p.iic.data = data; + qup_ret = qup_send_data(gsbi_id, &obj, stop_seq); + + if (QUP_SUCCESS != qup_ret) + return 1; + else + return 0; +} + +static int i2c_transfer(struct I2cOps *me, I2cSeg *segments, int seg_count) +{ + Ipq806xI2c *bus = container_of(me, Ipq806xI2c, ops); + I2cSeg *seg = segments; + int ret = 0; + + if (!bus->initialized) + if (0 != i2c_init(bus->gsbi_id)) + return 1; + + while (seg_count--) { + if (seg->read) + ret = i2c_read(bus->gsbi_id, seg->chip, + seg->buf, seg->len); + else + ret = i2c_write(bus->gsbi_id, seg->chip, + seg->buf, seg->len, + (seg_count ? 0 : 1)); + seg++; + } + + if (QUP_SUCCESS != ret) { + qup_set_state(bus->gsbi_id, QUP_STATE_RESET); + return 1; + } + + return 0; +} + +Ipq806xI2c *new_ipq806x_i2c(unsigned gsbi_id) +{ + Ipq806xI2c *bus = 0; + + if (!i2c_init(gsbi_id)) { + bus = xzalloc(sizeof(*bus)); + bus->gsbi_id = gsbi_id; + bus->initialized = 1; + bus->ops.transfer = &i2c_transfer; + } + return bus; +} diff --git a/src/soc/qualcomm/ipq806x/include/soc/cdp.h b/src/soc/qualcomm/ipq806x/include/soc/cdp.h new file mode 100644 index 0000000000..b705f3e909 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/cdp.h @@ -0,0 +1,149 @@ +/* * Copyright (c) 2012 The Linux Foundation. All rights reserved.* */ + + +#ifndef _IPQ806X_CDP_H_ +#define _IPQ806X_CDP_H_ + +#include + +unsigned smem_get_board_machtype(void); + +typedef enum { + PHY_INTERFACE_MODE_MII, + PHY_INTERFACE_MODE_GMII, + PHY_INTERFACE_MODE_SGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TBI, + PHY_INTERFACE_MODE_RMII, + PHY_INTERFACE_MODE_RGMII, + PHY_INTERFACE_MODE_RGMII_ID, + PHY_INTERFACE_MODE_RGMII_RXID, + PHY_INTERFACE_MODE_RGMII_TXID, + PHY_INTERFACE_MODE_RTBI, + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_NONE /* Must be last */ +} phy_interface_t; + +typedef struct { + unsigned int gpio; + unsigned int func; + unsigned int dir; + unsigned int pull; + unsigned int drvstr; + unsigned int enable; +} gpio_func_data_t; + +typedef struct { + unsigned int m_value; + unsigned int n_value; + unsigned int d_value; +} uart_clk_mnd_t; + +/* SPI Mode */ + +typedef enum { + NOR_SPI_MODE_0, + NOR_SPI_MODE_1, + NOR_SPI_MODE_2, + NOR_SPI_MODE_3, +} spi_mode; + +/* SPI GSBI Bus number */ + +typedef enum { + GSBI_BUS_5 = 0, + GSBI_BUS_6, + GSBI_BUS_7, +} spi_gsbi_bus_num; + +/* SPI Chip selects */ + +typedef enum { + SPI_CS_0 , + SPI_CS_1, + SPI_CS_2, + SPI_CS_3, +} spi_cs; + +/* Flash Types */ + +typedef enum { + ONLY_NAND, + ONLY_NOR, + NAND_NOR, + NOR_MMC, +} flash_desc; + +#define NO_OF_DBG_UART_GPIOS 2 + +#define SPI_NOR_FLASH_VENDOR_MICRON 0x1 +#define SPI_NOR_FLASH_VENDOR_SPANSION 0x2 + +/* SPI parameters */ + +typedef struct { + spi_mode mode; + spi_gsbi_bus_num bus_number; + spi_cs chip_select; + int vendor; +} spinorflash_params_t; + +typedef struct { + unsigned count; + uint8_t addr[7]; +} ipq_gmac_phy_addr_t; + +typedef struct { + unsigned base; + int unit; + unsigned is_macsec; + unsigned mac_pwr0; + unsigned mac_pwr1; + unsigned mac_conn_to_phy; + phy_interface_t phy; + ipq_gmac_phy_addr_t phy_addr; +} ipq_gmac_board_cfg_t; + +#define IPQ_GMAC_NMACS 4 + +enum storm_board_id { + BOARD_ID_PROTO_0 = 0, + BOARD_ID_PROTO_0_2 = 1, + BOARD_ID_WHIRLWIND = 2, + BOARD_ID_PROTO_0_2_NAND = 26, +}; + +/* Board specific parameters */ +typedef struct { +#if 0 + unsigned int gmac_gpio_count; + gpio_func_data_t *gmac_gpio; + ipq_gmac_board_cfg_t gmac_cfg[IPQ_GMAC_NMACS]; + flash_desc flashdesc; + spinorflash_params_t flash_param; +#endif +} __attribute__ ((__packed__)) board_ipq806x_params_t; + +extern board_ipq806x_params_t *gboard_param; + +#if 0 +static inline int gmac_cfg_is_valid(ipq_gmac_board_cfg_t *cfg) +{ + /* + * 'cfg' is valid if and only if + * unit number is non-negative and less than IPQ_GMAC_NMACS. + * 'cfg' pointer lies within the array range of + * board_ipq806x_params_t->gmac_cfg[] + */ + return ((cfg >= &gboard_param->gmac_cfg[0]) && + (cfg < &gboard_param->gmac_cfg[IPQ_GMAC_NMACS]) && + (cfg->unit >= 0) && (cfg->unit < IPQ_GMAC_NMACS)); +} +#endif + +unsigned int get_board_index(unsigned machid); +void ipq_configure_gpio(const gpio_func_data_t *gpio, unsigned count); + +void board_nand_init(void); + +#endif /* _IPQ806X_CDP_H_ */ diff --git a/src/soc/qualcomm/ipq806x/include/soc/clock.h b/src/soc/qualcomm/ipq806x/include/soc/clock.h new file mode 100644 index 0000000000..e92277a7a5 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/clock.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Source : APQ8064 LK Boot + * + * Copyright (c) 2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __IPQ860X_CLOCK_H_ +#define __IPQ860X_CLOCK_H_ + +#include + +/* UART clock @ 7.3728 MHz */ +#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC + +/* UART specific definitions */ + +#define BIT(s) (1<> (31-m+l)) << l) +#define BVAL(m, l, val) (((val) << l) & BM(m, l)) + +/* MD Registers */ +#define MD4(m_lsb, m, n_lsb, n) \ + (BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) + +#define MD8(m_lsb, m, n_lsb, n) \ + (BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) + +/* NS Registers */ +#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \ + (BVAL(n_msb, n_lsb, ~(n-m)) \ + | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \ + | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s)) + +#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \ + (BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \ + | BVAL(s_msb, s_lsb, s)) + +#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \ + (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s)) + +#define NS_DIV(d_msb , d_lsb, d) \ + BVAL(d_msb, d_lsb, (d-1)) + +#define NS_SRC_SEL(s_msb, s_lsb, s) \ + BVAL(s_msb, s_lsb, s) + +#define GMAC_AHB_RESET 0x903E24 + +#define SRC_SEL_PLL0 (0x2 << 0) +#define MNCNTR_MODE_DUAL_EDGE (0x2 << 5) +#define MNCNTR_ENABLE (0x1 << 8) +#define MNCNTR_RST_ACTIVE (0x1 << 7) +#define N_VAL 15 + +#define GMAC_CORE_RESET(n) \ + ((void *)(0x903CBC + ((n) * 0x20))) + +#define GMACSEC_CORE_RESET(n) \ + ((void *)(0x903E28 + ((n - 1) * 4))) + +#define GMAC_COREn_CLCK_SRC_CTL(N) \ + (0x00900000 + (0x3CA0 + (32*(N-1)))) + +#define GMAC_COREn_CLCK_SRC0_MD(N) \ + (0x00900000 + (0x3CA4 + (32*(N-1)))) + +#define GMAC_COREn_CLCK_SRC1_MD(N) \ + (0x00900000 + (0x3CA8 + (32*(N-1)))) + +#define GMAC_COREn_CLCK_SRC0_NS(N) \ + (0x00900000 + (0x3CAC + (32*(N-1)))) + +#define GMAC_COREn_CLCK_SRC1_NS(N) \ + (0x00900000 + (0x3CB0 + (32*(N-1)))) + +#define DISABLE_DUAL_MN8_SEL (0) +#define DISABLE_CLK_LOW_PWR (0 << 2) +#define GMAC_CORE_CLCK_ROOT_ENABLE (1 << 1) + +/* GMAC_COREn_CLK_SRC[0,1]_MD register bits (Assuming 133MHz) */ +#define GMAC_CORE_CLCK_M 0x32 +#define GMAC_CORE_CLCK_D 0 /* NOT(2*D) value */ +#define GMAC_CORE_CLCK_M_SHIFT 16 +#define GMAC_CORE_CLCK_D_SHIFT 0 +#define GMAC_CORE_CLCK_M_VAL (GMAC_CORE_CLCK_M << GMAC_CORE_CLCK_M_SHIFT) +#define GMAC_CORE_CLCK_D_VAL (GMAC_CORE_CLCK_D << GMAC_CORE_CLCK_D_SHIFT) + +/* GMAC_COREn_CLK_SRC[0,1]_NS register bits (Assuming 133MHz) */ +#define GMAC_CORE_CLCK_N 0x4 /* NOT(N-M) value, N=301 */ +#define GMAC_CORE_CLCK_N_SHIFT 16 +#define GMAC_CORE_CLCK_N_VAL (GMAC_CORE_CLCK_N << GMAC_CORE_CLCK_N_SHIFT) +#define GMAC_CORE_CLCK_MNCNTR_EN 0x00000100 /* Enable M/N counter */ +#define GMAC_CORE_CLCK_MNCNTR_RST 0x00000080 /* Activate reset for M/N counter */ +#define GMAC_CORE_CLCK_MNCNTR_MODE_MASK 0x00000060 /* M/N counter mode mask */ +#define GMAC_CORE_CLCK_MNCNTR_MODE_SHIFT 5 +#define GMAC_CORE_CLCK_MNCNTR_MODE_DUAL (2 << GMAC_CORE_CLCK_MNCNTR_MODE_SHIFT) /* M/N counter mode dual-edge */ +#define GMAC_CORE_CLCK_PRE_DIV_SEL_MASK 0x00000018 /* Pre divider select mask */ +#define GMAC_CORE_CLCK_PRE_DIV_SEL_SHIFT 3 +#define GMAC_CORE_CLCK_PRE_DIV_SEL_BYP (0 << GMAC_CORE_CLCK_PRE_DIV_SEL_SHIFT) /* Pre divider bypass */ +#define GMAC_CORE_CLCK_SRC_SEL_MASK 0x00000007 /* clk source Mux select mask */ +#define GMAC_CORE_CLCK_SRC_SEL_SHIFT 0 +#define GMAC_CORE_CLCK_SRC_SEL_PLL0 (2 << GMAC_CORE_CLCK_SRC_SEL_SHIFT) /* output of clk source Mux is PLL0 */ +#define GMAC_COREn_CLCK_CTL(N) (0x00900000 + (0x3CB4 + (32*(N-1)))) + +#define GMAC_COREn_CLCK_INV_DISABLE (0 << 5) +#define GMAC_COREn_CLCK_BRANCH_ENA (1 << 4) + + +/* Uart specific clock settings */ + +void uart_pll_vote_clk_enable(unsigned int); +void uart_clock_config(unsigned int gsbi_port, unsigned int m, unsigned int n, + unsigned int d, unsigned int clk_dummy); +void nand_clock_config(void); +void usb_clock_config(void); + +#endif /* __PLATFORM_IPQ860X_CLOCK_H_ */ diff --git a/src/soc/qualcomm/ipq806x/include/soc/ebi2.h b/src/soc/qualcomm/ipq806x/include/soc/ebi2.h new file mode 100644 index 0000000000..23333c2048 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/ebi2.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + */ +#ifndef __SOC_QUALCOMM_IPQ806X_EBI2_H_ +#define __SOC_QUALCOMM_IPQ806X_EBI2_H_ + +#define EBI2CR_BASE (0x1A600000) + +struct ebi2cr_regs { + uint32_t chip_select_cfg0; /* 0x00000000 */ + uint32_t cfg; /* 0x00000004 */ + uint32_t hw_info; /* 0x00000008 */ + uint8_t reserved0[20]; + uint32_t lcd_cfg0; /* 0x00000020 */ + uint32_t lcd_cfg1; /* 0x00000024 */ + uint8_t reserved1[8]; + uint32_t arbiter_cfg; /* 0x00000030 */ + uint8_t reserved2[28]; + uint32_t debug_sel; /* 0x00000050 */ + uint32_t crc_cfg; /* 0x00000054 */ + uint32_t crc_reminder_cfg; /* 0x00000058 */ + uint32_t nand_adm_mux; /* 0x0000005C */ + uint32_t mutex_addr_offset; /* 0x00000060 */ + uint32_t misr_value; /* 0x00000064 */ + uint32_t clkon_cfg; /* 0x00000068 */ + uint32_t core_clkon_cfg; /* 0x0000006C */ +}; + +/* Register: EBI2_CHIP_SELECT_CFG0 */ +#define CS7_CFG_MASK 0x00001000 +#define CS7_CFG_DISABLE 0x00000000 +#define CS7_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00001000 +#define CS7_CFG(i) ((i) << 12) + +#define CS6_CFG_MASK 0x00000800 +#define CS6_CFG_DISABLE 0x00000000 +#define CS6_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000800 +#define CS6_CFG(i) ((i) << 11) + +#define ETM_CS_CFG_MASK 0x00000400 +#define ETM_CS_CFG_DISABLE 0x00000000 +#define ETM_CS_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000400 +#define ETM_CS_CFG(i) ((i) << 10) + +#define CS5_CFG_MASK 0x00000300 +#define CS5_CFG_DISABLE 0x00000000 +#define CS5_CFG_LCD_DEVICE_CONNECTED 0x00000100 +#define CS5_CFG_LCD_DEVICE_CHIP_ENABLE 0x00000200 +#define CS5_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000300 +#define CS5_CFG(i) ((i) << 8) + +#define CS4_CFG_MASK 0x000000c0 +#define CS4_CFG_DISABLE 0x00000000 +#define CS4_CFG_LCD_DEVICE_CONNECTED 0x00000040 +#define CS4_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x000000C0 +#define CS4_CFG(i) ((i) << 6) + +#define CS3_CFG_MASK 0x00000020 +#define CS3_CFG_DISABLE 0x00000000 +#define CS3_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000020 +#define CS3_CFG(i) ((i) << 5) + +#define CS2_CFG_MASK 0x00000010 +#define CS2_CFG_DISABLE 0x00000000 +#define CS2_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000010 +#define CS2_CFG(i) ((i) << 4) + +#define CS1_CFG_MASK 0x0000000c +#define CS1_CFG_DISABLE 0x00000000 +#define CS1_CFG_SERIAL_FLASH_DEVICE 0x00000004 +#define CS1_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000008 +#define CS1_CFG(i) ((i) << 2) + +#define CS0_CFG_MASK 0x00000003 +#define CS0_CFG_DISABLE 0x00000000 +#define CS0_CFG_SERIAL_FLASH_DEVICE 0x00000001 +#define CS0_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000002 +#define CS0_CFG(i) ((i) << 0) + +#endif diff --git a/src/soc/qualcomm/ipq806x/include/soc/gpio.h b/src/soc/qualcomm/ipq806x/include/soc/gpio.h new file mode 100644 index 0000000000..35429917ed --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/gpio.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved.* + Source : APQ8064 LK Boot + + * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SOC_QUALCOMM_IPQ806X_GPIO_H_ +#define __SOC_QUALCOMM_IPQ806X_GPIO_H_ + +#include + +#define GPIO_FUNC_ENABLE 1 +#define GPIO_FUNC_DISABLE 0 +#define FUNC_SEL_1 1 +#define FUNC_SEL_3 3 +#define FUNC_SEL_GPIO 0 +#define GPIO_DRV_STR_10MA 0x4 +#define GPIO_DRV_STR_11MA 0x7 + +/* GPIO TLMM: Direction */ +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 + +/* GPIO TLMM: Pullup/Pulldown */ +#define GPIO_NO_PULL 0 +#define GPIO_PULL_DOWN 1 +#define GPIO_KEEPER 2 +#define GPIO_PULL_UP 3 + +/* GPIO TLMM: Drive Strength */ +#define GPIO_2MA 0 +#define GPIO_4MA 1 +#define GPIO_6MA 2 +#define GPIO_8MA 3 +#define GPIO_10MA 4 +#define GPIO_12MA 5 +#define GPIO_14MA 6 +#define GPIO_16MA 7 + +/* GPIO TLMM: Status */ +#define GPIO_DISABLE 0 +#define GPIO_ENABLE 1 + +/* GPIO MAX Valid # */ +#define GPIO_MAX_NUM 68 + +/* GPIO TLMM: Mask */ +#define GPIO_CFG_PULL_MASK 0x3 +#define GPIO_CFG_FUNC_MASK 0xF +#define GPIO_CFG_DRV_MASK 0x7 +#define GPIO_CFG_OE_MASK 0x1 + +/* GPIO TLMM: Shift */ +#define GPIO_CFG_PULL_SHIFT 0 +#define GPIO_CFG_FUNC_SHIFT 2 +#define GPIO_CFG_DRV_SHIFT 6 +#define GPIO_CFG_OE_SHIFT 9 + +/* GPIO IO: Mask */ +#define GPIO_IO_IN_MASK 0x1 +#define GPIO_IO_OUT_MASK 0x1 + +/* GPIO IO: Shift */ +#define GPIO_IO_IN_SHIFT 0 +#define GPIO_IO_OUT_SHIFT 1 + +typedef u32 gpio_t; + +void gpio_tlmm_config_set(gpio_t gpio, unsigned int func, + unsigned int pull, unsigned int drvstr, + unsigned int enable); + +void gpio_tlmm_config_get(gpio_t gpio, unsigned int *func, + unsigned int *pull, unsigned int *drvstr, + unsigned int *enable); + +void gpio_io_config_set(gpio_t gpio, unsigned int out); + +/* Keep this to maintain backwards compatibility with the vendor API. */ +static inline void gpio_tlmm_config(unsigned int gpio, unsigned int func, + unsigned int dir, unsigned int pull, + unsigned int drvstr, unsigned int enable) +{ + gpio_tlmm_config_set(gpio, func, pull, drvstr, enable); +} +#endif // __SOC_QUALCOMM_IPQ806X_GPIO_H_ diff --git a/src/soc/qualcomm/ipq806x/include/soc/gsbi.h b/src/soc/qualcomm/ipq806x/include/soc/gsbi.h new file mode 100644 index 0000000000..c12d6fd7b4 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/gsbi.h @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2004-2011 Atheros Communications Inc. +* Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. +* +* Permission to use, copy, modify, and/or distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + + +#ifndef __GSBI_H_ +#define __GSBI_H_ + +/* GSBI Registers */ +#define GSBI_CTRL_REG(base) ((base) + 0x0) + +#define GSBI_CTRL_REG_PROTOCOL_CODE_S 4 +#define GSBI_PROTOCOL_CODE_I2C 0x2 +#define GSBI_PROTOCOL_CODE_SPI 0x3 +#define GSBI_PROTOCOL_CODE_UART_FLOW 0x4 +#define GSBI_PROTOCOL_CODE_I2C_UART 0x6 + +#define GSBI_HCLK_CTL_S 4 +#define GSBI_HCLK_CTL_CLK_ENA 0x1 + +#endif + diff --git a/src/soc/qualcomm/ipq806x/include/soc/iomap.h b/src/soc/qualcomm/ipq806x/include/soc/iomap.h new file mode 100644 index 0000000000..ad7056e0fe --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/iomap.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved. + * + * Copyright (c) 2008, Google Inc. + * All rights reserved. + * + * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __SOC_QUALCOMM_IPQ806X_IOMAP_H_ +#define __SOC_QUALCOMM_IPQ806X_IOMAP_H_ + +#include +#include + +/* Typecast to allow integers being passed as address + This needs to be included because vendor code is not compliant with our + macros for read/write. Hence, special macros for readl_i and writel_i are + included to do this in one place for all occurrences in vendor code + */ +#define readl_i(a) read32((const void *)(a)) +#define writel_i(v,a) write32(v,(void *)a) +#define clrsetbits_le32_i(addr, clear, set) \ + clrsetbits_le32(((void *)(addr)), (clear), (set)) + +#define MSM_CLK_CTL_BASE 0x00900000 + +#define MSM_TMR_BASE 0x0200A000 +#define MSM_GPT_BASE (MSM_TMR_BASE + 0x04) +#define MSM_DGT_BASE (MSM_TMR_BASE + 0x24) + +#define GPT_REG(off) ((void *)(MSM_GPT_BASE + (off))) +#define DGT_REG(off) (MSM_DGT_BASE + (off)) + +#define APCS_WDT0_EN (MSM_TMR_BASE + 0x0040) +#define APCS_WDT0_RST (MSM_TMR_BASE + 0x0038) +#define APCS_WDT0_BARK_TIME (MSM_TMR_BASE + 0x004C) +#define APCS_WDT0_BITE_TIME (MSM_TMR_BASE + 0x005C) + +#define APCS_WDT0_CPU0_WDOG_EXPIRED_ENABLE (MSM_CLK_CTL_BASE + 0x3820) + +#define GPT_MATCH_VAL GPT_REG(0x0000) +#define GPT_COUNT_VAL GPT_REG(0x0004) +#define GPT_ENABLE GPT_REG(0x0008) +#define GPT_CLEAR GPT_REG(0x000C) + +#define GPT1_MATCH_VAL GPT_REG(0x00010) +#define GPT1_COUNT_VAL GPT_REG(0x00014) +#define GPT1_ENABLE GPT_REG(0x00018) +#define GPT1_CLEAR GPT_REG(0x0001C) + +#define DGT_MATCH_VAL DGT_REG(0x0000) +#define DGT_COUNT_VAL DGT_REG(0x0004) +#define DGT_ENABLE DGT_REG(0x0008) +#define DGT_CLEAR DGT_REG(0x000C) +#define DGT_CLK_CTL DGT_REG(0x0010) + +#define TLMM_BASE_ADDR ((char *)0x00800000) +#define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + 0x1000 + (x)*0x10) +#define GPIO_IN_OUT_ADDR(x) (GPIO_CONFIG_ADDR(x) + 4) + +/* Yes, this is not a typo... host2 is actually mapped before host1. */ +#define USB_HOST2_XHCI_BASE 0x10000000 +#define USB_HOST2_DWC3_BASE 0x1000C100 +#define USB_HOST2_PHY_BASE 0x100F8800 +#define USB_HOST1_XHCI_BASE 0x11000000 +#define USB_HOST1_DWC3_BASE 0x1100C100 +#define USB_HOST1_PHY_BASE 0x110F8800 + +#define GSBI_1 1 +#define GSBI_2 2 +#define GSBI_4 4 +#define GSBI_2 2 +#define UART1_DM_BASE 0x12450000 +#define UART_GSBI1_BASE 0x12440000 +#define UART2_DM_BASE 0x12490000 +#define UART_GSBI2_BASE 0x12480000 +#define UART4_DM_BASE 0x16340000 +#define UART_GSBI4_BASE 0x16300000 + +#define UART2_DM_BASE 0x12490000 +#define UART_GSBI2_BASE 0x12480000 + +#endif // __SOC_QUALCOMM_IPQ806X_IOMAP_H_ diff --git a/src/soc/qualcomm/ipq806x/include/soc/ipq_timer.h b/src/soc/qualcomm/ipq806x/include/soc/ipq_timer.h new file mode 100644 index 0000000000..4e1ef34294 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/ipq_timer.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define TIMER_LOAD_VAL 0x21 + +#define GPT_ENABLE_CLR_ON_MATCH_EN 2 +#define GPT_ENABLE_EN 1 +#define DGT_ENABLE_CLR_ON_MATCH_EN 2 +#define DGT_ENABLE_EN 1 + +#define SPSS_TIMER_STATUS_DGT_EN (1 << 0) + + diff --git a/src/soc/qualcomm/ipq806x/include/soc/ipq_uart.h b/src/soc/qualcomm/ipq806x/include/soc/ipq_uart.h new file mode 100644 index 0000000000..90ca7047a2 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/ipq_uart.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved.* + * + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __UART_DM_H__ +#define __UART_DM_H__ + +#define PERIPH_BLK_BLSP 0 + +#define MSM_BOOT_UART_DM_EXTR_BITS(value, start_pos, end_pos) \ + ((value << (32 - end_pos))\ + >> (32 - (end_pos - start_pos))) + +extern void __udelay(unsigned long usec); + + +enum MSM_BOOT_UART_DM_PARITY_MODE { + MSM_BOOT_UART_DM_NO_PARITY, + MSM_BOOT_UART_DM_ODD_PARITY, + MSM_BOOT_UART_DM_EVEN_PARITY, + MSM_BOOT_UART_DM_SPACE_PARITY +}; + +/* UART Stop Bit Length */ +enum MSM_BOOT_UART_DM_STOP_BIT_LEN { + MSM_BOOT_UART_DM_SBL_9_16, + MSM_BOOT_UART_DM_SBL_1, + MSM_BOOT_UART_DM_SBL_1_9_16, + MSM_BOOT_UART_DM_SBL_2 +}; + +/* UART Bits per Char */ +enum MSM_BOOT_UART_DM_BITS_PER_CHAR { + MSM_BOOT_UART_DM_5_BPS, + MSM_BOOT_UART_DM_6_BPS, + MSM_BOOT_UART_DM_7_BPS, + MSM_BOOT_UART_DM_8_BPS +}; + +/* 8-N-1 Configuration */ +#define MSM_BOOT_UART_DM_8_N_1_MODE (MSM_BOOT_UART_DM_NO_PARITY | \ + (MSM_BOOT_UART_DM_SBL_1 << 2) | \ + (MSM_BOOT_UART_DM_8_BPS << 4)) + +/* UART_DM Registers */ + +/* UART Operational Mode Register */ +#define MSM_BOOT_UART_DM_MR1(base) ((base) + 0x00) +#define MSM_BOOT_UART_DM_MR2(base) ((base) + 0x04) +#define MSM_BOOT_UART_DM_RXBRK_ZERO_CHAR_OFF (1 << 8) +#define MSM_BOOT_UART_DM_LOOPBACK (1 << 7) + +/* UART Clock Selection Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_CSR(base) ((base) + 0xA0) +#else +#define MSM_BOOT_UART_DM_CSR(base) ((base) + 0x08) +#endif + +/* UART DM TX FIFO Registers - 4 */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_TF(base, x) ((base) + 0x100+(4*(x))) +#else +#define MSM_BOOT_UART_DM_TF(base, x) ((base) + 0x70+(4*(x))) +#endif + +/* UART Command Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_CR(base) ((base) + 0xA8) +#else +#define MSM_BOOT_UART_DM_CR(base) ((base) + 0x10) +#endif +#define MSM_BOOT_UART_DM_CR_RX_ENABLE (1 << 0) +#define MSM_BOOT_UART_DM_CR_RX_DISABLE (1 << 1) +#define MSM_BOOT_UART_DM_CR_TX_ENABLE (1 << 2) +#define MSM_BOOT_UART_DM_CR_TX_DISABLE (1 << 3) + +/* UART Channel Command */ +#define MSM_BOOT_UART_DM_CR_CH_CMD_LSB(x) ((x & 0x0f) << 4) +#define MSM_BOOT_UART_DM_CR_CH_CMD_MSB(x) ((x >> 4 ) << 11 ) +#define MSM_BOOT_UART_DM_CR_CH_CMD(x) (MSM_BOOT_UART_DM_CR_CH_CMD_LSB(x)\ + | MSM_BOOT_UART_DM_CR_CH_CMD_MSB(x)) +#define MSM_BOOT_UART_DM_CMD_NULL MSM_BOOT_UART_DM_CR_CH_CMD(0) +#define MSM_BOOT_UART_DM_CMD_RESET_RX MSM_BOOT_UART_DM_CR_CH_CMD(1) +#define MSM_BOOT_UART_DM_CMD_RESET_TX MSM_BOOT_UART_DM_CR_CH_CMD(2) +#define MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT MSM_BOOT_UART_DM_CR_CH_CMD(3) +#define MSM_BOOT_UART_DM_CMD_RES_BRK_CHG_INT MSM_BOOT_UART_DM_CR_CH_CMD(4) +#define MSM_BOOT_UART_DM_CMD_START_BRK MSM_BOOT_UART_DM_CR_CH_CMD(5) +#define MSM_BOOT_UART_DM_CMD_STOP_BRK MSM_BOOT_UART_DM_CR_CH_CMD(6) +#define MSM_BOOT_UART_DM_CMD_RES_CTS_N MSM_BOOT_UART_DM_CR_CH_CMD(7) +#define MSM_BOOT_UART_DM_CMD_RES_STALE_INT MSM_BOOT_UART_DM_CR_CH_CMD(8) +#define MSM_BOOT_UART_DM_CMD_PACKET_MODE MSM_BOOT_UART_DM_CR_CH_CMD(9) +#define MSM_BOOT_UART_DM_CMD_MODE_RESET MSM_BOOT_UART_DM_CR_CH_CMD(C) +#define MSM_BOOT_UART_DM_CMD_SET_RFR_N MSM_BOOT_UART_DM_CR_CH_CMD(D) +#define MSM_BOOT_UART_DM_CMD_RES_RFR_N MSM_BOOT_UART_DM_CR_CH_CMD(E) +#define MSM_BOOT_UART_DM_CMD_RES_TX_ERR MSM_BOOT_UART_DM_CR_CH_CMD(10) +#define MSM_BOOT_UART_DM_CMD_CLR_TX_DONE MSM_BOOT_UART_DM_CR_CH_CMD(11) +#define MSM_BOOT_UART_DM_CMD_RES_BRKSTRT_INT MSM_BOOT_UART_DM_CR_CH_CMD(12) +#define MSM_BOOT_UART_DM_CMD_RES_BRKEND_INT MSM_BOOT_UART_DM_CR_CH_CMD(13) +#define MSM_BOOT_UART_DM_CMD_RES_PER_FRM_INT MSM_BOOT_UART_DM_CR_CH_CMD(14) + +/*UART General Command */ +#define MSM_BOOT_UART_DM_CR_GENERAL_CMD(x) ((x) << 8) + +#define MSM_BOOT_UART_DM_GCMD_NULL MSM_BOOT_UART_DM_CR_GENERAL_CMD(0) +#define MSM_BOOT_UART_DM_GCMD_CR_PROT_EN MSM_BOOT_UART_DM_CR_GENERAL_CMD(1) +#define MSM_BOOT_UART_DM_GCMD_CR_PROT_DIS MSM_BOOT_UART_DM_CR_GENERAL_CMD(2) +#define MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT MSM_BOOT_UART_DM_CR_GENERAL_CMD(3) +#define MSM_BOOT_UART_DM_GCMD_SW_FORCE_STALE MSM_BOOT_UART_DM_CR_GENERAL_CMD(4) +#define MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT MSM_BOOT_UART_DM_CR_GENERAL_CMD(5) +#define MSM_BOOT_UART_DM_GCMD_DIS_STALE_EVT MSM_BOOT_UART_DM_CR_GENERAL_CMD(6) + +/* UART Interrupt Mask Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_IMR(base) ((base) + 0xB0) +#else +#define MSM_BOOT_UART_DM_IMR(base) ((base) + 0x14) +#endif + +#define MSM_BOOT_UART_DM_TXLEV (1 << 0) +#define MSM_BOOT_UART_DM_RXHUNT (1 << 1) +#define MSM_BOOT_UART_DM_RXBRK_CHNG (1 << 2) +#define MSM_BOOT_UART_DM_RXSTALE (1 << 3) +#define MSM_BOOT_UART_DM_RXLEV (1 << 4) +#define MSM_BOOT_UART_DM_DELTA_CTS (1 << 5) +#define MSM_BOOT_UART_DM_CURRENT_CTS (1 << 6) +#define MSM_BOOT_UART_DM_TX_READY (1 << 7) +#define MSM_BOOT_UART_DM_TX_ERROR (1 << 8) +#define MSM_BOOT_UART_DM_TX_DONE (1 << 9) +#define MSM_BOOT_UART_DM_RXBREAK_START (1 << 10) +#define MSM_BOOT_UART_DM_RXBREAK_END (1 << 11) +#define MSM_BOOT_UART_DM_PAR_FRAME_ERR_IRQ (1 << 12) + +#define MSM_BOOT_UART_DM_IMR_ENABLED (MSM_BOOT_UART_DM_TX_READY | \ + MSM_BOOT_UART_DM_TXLEV | \ + MSM_BOOT_UART_DM_RXSTALE) + +/* UART Interrupt Programming Register */ +#define MSM_BOOT_UART_DM_IPR(base) ((base) + 0x18) +#define MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB 0x0f +#define MSM_BOOT_UART_DM_STALE_TIMEOUT_MSB 0 /* Not used currently */ + +/* UART Transmit/Receive FIFO Watermark Register */ +#define MSM_BOOT_UART_DM_TFWR(base) ((base) + 0x1C) +/* Interrupt is generated when FIFO level is less than or equal to this value */ +#define MSM_BOOT_UART_DM_TFW_VALUE 0 + +#define MSM_BOOT_UART_DM_RFWR(base) ((base) + 0x20) +/*Interrupt generated when no of words in RX FIFO is greater than this value */ +#define MSM_BOOT_UART_DM_RFW_VALUE 0 + +/* UART Hunt Character Register */ +#define MSM_BOOT_UART_DM_HCR(base) ((base) + 0x24) + +/* Used for RX transfer initialization */ +#define MSM_BOOT_UART_DM_DMRX(base) ((base) + 0x34) + +/* Default DMRX value - any value bigger than FIFO size would be fine */ +#define MSM_BOOT_UART_DM_DMRX_DEF_VALUE 0x220 + +/* Register to enable IRDA function */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_IRDA(base) ((base) + 0xB8) +#else +#define MSM_BOOT_UART_DM_IRDA(base) ((base) + 0x38) +#endif + +/* UART Data Mover Enable Register */ +#define MSM_BOOT_UART_DM_DMEN(base) ((base) + 0x3C) + +/* Number of characters for Transmission */ +#define MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base) ((base) + 0x040) + +/* UART RX FIFO Base Address */ +#define MSM_BOOT_UART_DM_BADR(base) ((base) + 0x44) + +/* UART Status Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_SR(base) ((base) + 0x0A4) +#else +#define MSM_BOOT_UART_DM_SR(base) ((base) + 0x008) +#endif +#define MSM_BOOT_UART_DM_SR_RXRDY (1 << 0) +#define MSM_BOOT_UART_DM_SR_RXFULL (1 << 1) +#define MSM_BOOT_UART_DM_SR_TXRDY (1 << 2) +#define MSM_BOOT_UART_DM_SR_TXEMT (1 << 3) +#define MSM_BOOT_UART_DM_SR_UART_OVERRUN (1 << 4) +#define MSM_BOOT_UART_DM_SR_PAR_FRAME_ERR (1 << 5) +#define MSM_BOOT_UART_DM_RX_BREAK (1 << 6) +#define MSM_BOOT_UART_DM_HUNT_CHAR (1 << 7) +#define MSM_BOOT_UART_DM_RX_BRK_START_LAST (1 << 8) + +/* UART Receive FIFO Registers - 4 in numbers */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_RF(base, x) ((base) + 0x140 + (4*(x))) +#else +#define MSM_BOOT_UART_DM_RF(base, x) ((base) + 0x70 + (4*(x))) +#endif + +/* UART Masked Interrupt Status Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_MISR(base) ((base) + 0xAC) +#else +#define MSM_BOOT_UART_DM_MISR(base) ((base) + 0x10) +#endif + +/* UART Interrupt Status Register */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_ISR(base) ((base) + 0xB4) +#else +#define MSM_BOOT_UART_DM_ISR(base) ((base) + 0x14) +#endif + +/* Number of characters received since the end of last RX transfer */ +#if PERIPH_BLK_BLSP +#define MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base) ((base) + 0xBC) +#else +#define MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base) ((base) + 0x38) +#endif + +/* UART TX FIFO Status Register */ +#define MSM_BOOT_UART_DM_TXFS(base) ((base) + 0x4C) +#define MSM_BOOT_UART_DM_TXFS_STATE_LSB(x) MSM_BOOT_UART_DM_EXTR_BITS(x,0,6) +#define MSM_BOOT_UART_DM_TXFS_STATE_MSB(x) MSM_BOOT_UART_DM_EXTR_BITS(x,14,31) +#define MSM_BOOT_UART_DM_TXFS_BUF_STATE(x) MSM_BOOT_UART_DM_EXTR_BITS(x,7,9) +#define MSM_BOOT_UART_DM_TXFS_ASYNC_STATE(x) MSM_BOOT_UART_DM_EXTR_BITS(x,10,13) + +/* UART RX FIFO Status Register */ +#define MSM_BOOT_UART_DM_RXFS(base) ((base) + 0x50) +#define MSM_BOOT_UART_DM_RXFS_STATE_LSB(x) MSM_BOOT_UART_DM_EXTR_BITS(x,0,6) +#define MSM_BOOT_UART_DM_RXFS_STATE_MSB(x) MSM_BOOT_UART_DM_EXTR_BITS(x,14,31) +#define MSM_BOOT_UART_DM_RXFS_BUF_STATE(x) MSM_BOOT_UART_DM_EXTR_BITS(x,7,9) +#define MSM_BOOT_UART_DM_RXFS_ASYNC_STATE(x) MSM_BOOT_UART_DM_EXTR_BITS(x,10,13) + +/* Macros for Common Errors */ +#define MSM_BOOT_UART_DM_E_SUCCESS 0 +#define MSM_BOOT_UART_DM_E_FAILURE 1 +#define MSM_BOOT_UART_DM_E_TIMEOUT 2 +#define MSM_BOOT_UART_DM_E_INVAL 3 +#define MSM_BOOT_UART_DM_E_MALLOC_FAIL 4 +#define MSM_BOOT_UART_DM_E_RX_NOT_READY 5 + +#endif /* __UART_DM_H__ */ + diff --git a/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld new file mode 100644 index 0000000000..9019b232da --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +SECTIONS +{ + SRAM_START(0x2A000000) + /* This includes bootblock image, can be reused after bootblock starts */ +/* UBER_SBL(0x2A000000, 48K) */ +/* DDR(0x2A000000, 48K) */ + BOOTBLOCK(0x2A00C000, 24K) + OVERLAP_VERSTAGE_ROMSTAGE(0x2A012000, 64K) + VBOOT2_WORK(0x2A022000, 16K) + PRERAM_CBMEM_CONSOLE(0x2A026000, 32K) +/* 0x2e000..0x3F000 68 KB free */ + +/* Keep the below area reserved at all times, it is used by various QCA + components as shared data + QCA_SHARED_RAM(2A03F000, 4K) +*/ + STACK(0x2A040000, 16K) + CBFS_CACHE(0x2A044000, 96K) + TTB(0x2A05C000, 16K) + SRAM_END(0x2A060000) + + DRAM_START(0x40000000) + RAMSTAGE(0x40640000, 128K) + DMA_COHERENT(0x5A000000, 2M) +} diff --git a/src/soc/qualcomm/ipq806x/include/soc/spi.h b/src/soc/qualcomm/ipq806x/include/soc/spi.h new file mode 100644 index 0000000000..f7dda07a51 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/spi.h @@ -0,0 +1,282 @@ +/* + * Register definitions for the IPQ GSBI Controller + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + */ + +#ifndef _IPQ806X_SPI_H_ +#define _IPQ806X_SPI_H_ + +#include + +#define QUP5_BASE 0x1a280000 +#define QUP6_BASE 0x16580000 +#define QUP7_BASE 0x16680000 + +#define GSBI5_BASE 0x1a200000 +#define GSBI6_BASE 0x16500000 +#define GSBI7_BASE 0x16600000 + +#define GSBI5_QUP5_REG_BASE (QUP5_BASE + 0x00000000) +#define GSBI6_QUP6_REG_BASE (QUP6_BASE + 0x00000000) +#define GSBI7_QUP7_REG_BASE (QUP7_BASE + 0x00000000) + +#define GSBI5_REG_BASE (GSBI5_BASE + 0x00000000) +#define GSBI6_REG_BASE (GSBI6_BASE + 0x00000000) +#define GSBI7_REG_BASE (GSBI7_BASE + 0x00000000) + +#define BOOT_SPI_PORT5_BASE QUP5_BASE +#define BOOT_SPI_PORT6_BASE QUP6_BASE +#define BOOT_SPI_PORT7_BASE QUP7_BASE + +#define GSBI5_SPI_CONFIG_REG (GSBI5_QUP5_REG_BASE + 0x00000300) +#define GSBI6_SPI_CONFIG_REG (GSBI6_QUP6_REG_BASE + 0x00000300) +#define GSBI7_SPI_CONFIG_REG (GSBI7_QUP7_REG_BASE + 0x00000300) + +#define GSBI5_SPI_IO_CONTROL_REG (GSBI5_QUP5_REG_BASE + 0x00000304) +#define GSBI6_SPI_IO_CONTROL_REG (GSBI6_QUP6_REG_BASE + 0x00000304) +#define GSBI7_SPI_IO_CONTROL_REG (GSBI7_QUP7_REG_BASE + 0x00000304) + +#define GSBI5_SPI_ERROR_FLAGS_REG (GSBI5_QUP5_REG_BASE + 0x00000308) +#define GSBI6_SPI_ERROR_FLAGS_REG (GSBI6_QUP6_REG_BASE + 0x00000308) +#define GSBI7_SPI_ERROR_FLAGS_REG (GSBI7_QUP7_REG_BASE + 0x00000308) + +#define GSBI5_SPI_ERROR_FLAGS_EN_REG (GSBI5_QUP5_REG_BASE + 0x0000030c) +#define GSBI6_SPI_ERROR_FLAGS_EN_REG (GSBI6_QUP6_REG_BASE + 0x0000030c) +#define GSBI7_SPI_ERROR_FLAGS_EN_REG (GSBI7_QUP7_REG_BASE + 0x0000030c) + +#define GSBI5_GSBI_CTRL_REG_REG (GSBI5_REG_BASE + 0x00000000) +#define GSBI6_GSBI_CTRL_REG_REG (GSBI6_REG_BASE + 0x00000000) +#define GSBI7_GSBI_CTRL_REG_REG (GSBI7_REG_BASE + 0x00000000) + +#define GSBI5_QUP_CONFIG_REG (GSBI5_QUP5_REG_BASE + 0x00000000) +#define GSBI6_QUP_CONFIG_REG (GSBI6_QUP6_REG_BASE + 0x00000000) +#define GSBI7_QUP_CONFIG_REG (GSBI7_QUP7_REG_BASE + 0x00000000) + +#define GSBI5_QUP_ERROR_FLAGS_REG (GSBI5_QUP5_REG_BASE + 0x0000001c) +#define GSBI6_QUP_ERROR_FLAGS_REG (GSBI6_QUP6_REG_BASE + 0x0000001c) +#define GSBI7_QUP_ERROR_FLAGS_REG (GSBI7_QUP7_REG_BASE + 0x0000001c) + +#define GSBI5_QUP_ERROR_FLAGS_EN_REG (GSBI5_QUP5_REG_BASE + 0x00000020) +#define GSBI6_QUP_ERROR_FLAGS_EN_REG (GSBI6_QUP6_REG_BASE + 0x00000020) +#define GSBI7_QUP_ERROR_FLAGS_EN_REG (GSBI7_QUP7_REG_BASE + 0x00000020) + +#define GSBI5_QUP_OPERATIONAL_REG (GSBI5_QUP5_REG_BASE + 0x00000018) +#define GSBI6_QUP_OPERATIONAL_REG (GSBI6_QUP6_REG_BASE + 0x00000018) +#define GSBI7_QUP_OPERATIONAL_REG (GSBI7_QUP7_REG_BASE + 0x00000018) + +#define GSBI5_QUP_IO_MODES_REG (GSBI5_QUP5_REG_BASE + 0x00000008) +#define GSBI6_QUP_IO_MODES_REG (GSBI6_QUP6_REG_BASE + 0x00000008) +#define GSBI7_QUP_IO_MODES_REG (GSBI7_QUP7_REG_BASE + 0x00000008) + +#define GSBI5_QUP_STATE_REG (GSBI5_QUP5_REG_BASE + 0x00000004) +#define GSBI6_QUP_STATE_REG (GSBI6_QUP6_REG_BASE + 0x00000004) +#define GSBI7_QUP_STATE_REG (GSBI7_QUP7_REG_BASE + 0x00000004) + +#define GSBI5_QUP_OUT_FIFO_WORD_CNT_REG (GSBI5_QUP5_REG_BASE + 0x0000010c) +#define GSBI6_QUP_OUT_FIFO_WORD_CNT_REG (GSBI6_QUP6_REG_BASE + 0x0000010c) +#define GSBI7_QUP_OUT_FIFO_WORD_CNT_REG (GSBI7_QUP7_REG_BASE + 0x0000010c) + +#define GSBI5_QUP_IN_FIFO_WORD_CNT_REG (GSBI5_QUP5_REG_BASE + 0x00000214) +#define GSBI6_QUP_IN_FIFO_WORD_CNT_REG (GSBI6_QUP6_REG_BASE + 0x00000214) +#define GSBI7_QUP_IN_FIFO_WORD_CNT_REG (GSBI7_QUP7_REG_BASE + 0x00000214) + +#define GSBI5_QUP_INPUT_FIFOc_REG(c) \ + (GSBI5_QUP5_REG_BASE + 0x00000218 + 4 * (c)) +#define GSBI6_QUP_INPUT_FIFOc_REG(c) \ + (GSBI6_QUP6_REG_BASE + 0x00000218 + 4 * (c)) +#define GSBI7_QUP_INPUT_FIFOc_REG(c) \ + (GSBI7_QUP7_REG_BASE + 0x00000218 + 4 * (c)) + +#define GSBI5_QUP_OUTPUT_FIFOc_REG(c) \ + (GSBI5_QUP5_REG_BASE + 0x00000110 + 4 * (c)) +#define GSBI6_QUP_OUTPUT_FIFOc_REG(c) \ + (GSBI6_QUP6_REG_BASE + 0x00000110 + 4 * (c)) +#define GSBI7_QUP_OUTPUT_FIFOc_REG(c) \ + (GSBI7_QUP7_REG_BASE + 0x00000110 + 4 * (c)) + +#define GSBI5_QUP_MX_INPUT_COUNT_REG (GSBI5_QUP5_REG_BASE + 0x00000200) +#define GSBI6_QUP_MX_INPUT_COUNT_REG (GSBI6_QUP6_REG_BASE + 0x00000200) +#define GSBI7_QUP_MX_INPUT_COUNT_REG (GSBI7_QUP7_REG_BASE + 0x00000200) + +#define GSBI5_QUP_MX_OUTPUT_COUNT_REG (GSBI5_QUP5_REG_BASE + 0x00000100) +#define GSBI6_QUP_MX_OUTPUT_COUNT_REG (GSBI6_QUP6_REG_BASE + 0x00000100) +#define GSBI7_QUP_MX_OUTPUT_COUNT_REG (GSBI7_QUP7_REG_BASE + 0x00000100) + +#define GSBI5_QUP_SW_RESET_REG (GSBI5_QUP5_REG_BASE + 0x0000000c) +#define GSBI6_QUP_SW_RESET_REG (GSBI6_QUP6_REG_BASE + 0x0000000c) +#define GSBI7_QUP_SW_RESET_REG (GSBI7_QUP7_REG_BASE + 0x0000000c) + +#define CLK_CTL_REG_BASE 0x00900000 +#define GSBIn_RESET_REG(n) \ + (CLK_CTL_REG_BASE + 0x000029dc + 32 * ((n)-1)) + +#define SFAB_AHB_S3_FCLK_CTL_REG \ + (CLK_CTL_REG_BASE + 0x0000216c) +#define CFPB_CLK_NS_REG \ + (CLK_CTL_REG_BASE + 0x0000264c) +#define SFAB_CFPB_S_HCLK_CTL_REG \ + (CLK_CTL_REG_BASE + 0x000026c0) +#define CFPB_SPLITTER_HCLK_CTL_REG \ + (CLK_CTL_REG_BASE + 0x000026e0) +#define CFPB0_HCLK_CTL_REG \ + (CLK_CTL_REG_BASE + 0x00002650) +#define CFPB2_HCLK_CTL_REG \ + (CLK_CTL_REG_BASE + 0x00002658) +#define GSBIn_HCLK_CTL_REG(n) \ + (CLK_CTL_REG_BASE + 0x000029c0 + 32 * ((n)-1)) +#define GSBIn_QUP_APPS_NS_REG(n) \ + (CLK_CTL_REG_BASE + 0x000029cc + 32 * ((n)-1)) +#define GSBIn_QUP_APPS_MD_REG(n) \ + (CLK_CTL_REG_BASE + 0x000029c8 + 32 * ((n)-1)) +#define CLK_HALT_CFPB_STATEB_REG \ + (CLK_CTL_REG_BASE + 0x00002fd0) + +#define GSBI5_HCLK 23 +#define GSBI6_HCLK 19 +#define GSBI7_HCLK 15 +#define GSBI5_QUP_APPS_CLK 20 +#define GSBI6_QUP_APPS_CLK 16 +#define GSBI7_QUP_APPS_CLK 12 +#define GSBI_CLK_BRANCH_ENA_MSK (1 << 4) +#define GSBI_CLK_BRANCH_ENA (1 << 4) +#define GSBI_CLK_BRANCH_DIS (0 << 4) +#define QUP_CLK_BRANCH_ENA_MSK (1 << 9) +#define QUP_CLK_BRANCH_ENA (1 << 9) +#define QUP_CLK_BRANCH_DIS (0 << 9) +#define CLK_ROOT_ENA_MSK (1 << 11) +#define CLK_ROOT_ENA (1 << 11) +#define CLK_ROOT_DIS (0 << 11) + +#define QUP_STATE_VALID_BIT 2 +#define QUP_STATE_VALID 1 +#define QUP_STATE_MASK 0x3 +#define QUP_CONFIG_MINI_CORE_MSK (0x0F << 8) +#define QUP_CONFIG_MINI_CORE_SPI (1 << 8) +#define SPI_QUP_CONF_INPUT_MSK (1 << 7) +#define SPI_QUP_CONF_INPUT_ENA (0 << 7) +#define SPI_QUP_CONF_NO_INPUT (1 << 7) +#define SPI_QUP_CONF_OUTPUT_MSK (1 << 6) +#define SPI_QUP_CONF_OUTPUT_ENA (0 << 6) +#define SPI_QUP_CONF_NO_OUTPUT (1 << 6) +#define SPI_QUP_CONF_OUTPUT_ENA (0 << 6) +#define QUP_STATE_RESET_STATE 0x0 +#define QUP_STATE_RUN_STATE 0x1 +#define QUP_STATE_PAUSE_STATE 0x3 +#define SPI_BIT_WORD_MSK 0x1F +#define SPI_8_BIT_WORD 0x07 +#define PROTOCOL_CODE_MSK (0x07 << 4) +#define PROTOCOL_CODE_SPI (0x03 << 4) +#define LOOP_BACK_MSK (1 << 8) +#define NO_LOOP_BACK (0 << 8) +#define SLAVE_OPERATION_MSK (1 << 5) +#define SLAVE_OPERATION (0 << 5) +#define CLK_ALWAYS_ON (0 << 9) +#define MX_CS_MODE (0 << 8) +#define NO_TRI_STATE (1 << 0) +#define OUTPUT_BIT_SHIFT_MSK (1 << 16) +#define OUTPUT_BIT_SHIFT_EN (1 << 16) +#define INPUT_BLOCK_MODE_MSK (0x03 << 12) +#define INPUT_BLOCK_MODE (0x01 << 12) +#define OUTPUT_BLOCK_MODE_MSK (0x03 << 10) +#define OUTPUT_BLOCK_MODE (0x01 << 10) +#define GSBI1_RESET (1 << 0) +#define GSBI1_RESET_MSK 0x1 + +#define GSBI_M_VAL_SHFT 16 +#define GSBIn_M_VAL_MSK (0xFF << GSBI_M_VAL_SHFT) +#define GSBI_N_VAL_SHFT 16 +#define GSBIn_N_VAL_MSK (0xFF << GSBI_N_VAL_SHFT) +#define GSBI_D_VAL_SHFT 0 +#define GSBIn_D_VAL_MSK (0xFF << GSBI_D_VAL_SHFT) +#define MNCNTR_RST_MSK (1 << 7) +#define MNCNTR_RST_ENA (1 << 7) +#define MNCNTR_RST_DIS (0 << 7) +#define MNCNTR_MSK (1 << 8) +#define MNCNTR_EN (1 << 8) +#define MNCNTR_DIS (0 << 8) +#define MNCNTR_MODE_MSK (0x3 << 5) +#define MNCNTR_MODE_BYPASS (0 << 5) +#define MNCNTR_MODE_DUAL_EDGE (0x2 << 5) +#define GSBI_PRE_DIV_SEL_SHFT 3 +#define GSBIn_PRE_DIV_SEL_MSK (0x3 << GSBI_PRE_DIV_SEL_SHFT) +#define GSBIn_PLL_SRC_MSK (0x03 << 0) +#define GSBIn_PLL_SRC_PXO (0 << 0) +#define GSBIn_PLL_SRC_PLL8 (0x3 << 0) + +#define SPI_INPUT_FIRST_MODE (1 << 9) +#define SPI_IO_CONTROL_CLOCK_IDLE_HIGH (1 << 10) +#define QUP_DATA_AVAILABLE_FOR_READ (1 << 5) +#define QUP_OUTPUT_FIFO_NOT_EMPTY (1 << 4) +#define OUTPUT_SERVICE_FLAG (1 << 8) +#define INPUT_SERVICE_FLAG (1 << 9) +#define QUP_OUTPUT_FIFO_FULL (1 << 6) +#define QUP_INPUT_FIFO_NOT_EMPTY (1 << 5) +#define SPI_INPUT_BLOCK_SIZE 4 +#define SPI_OUTPUT_BLOCK_SIZE 4 +#define GSBI5_SPI_CLK 21 +#define GSBI5_SPI_MISO 19 +#define GSBI5_SPI_MOSI 18 +#define GSBI5_SPI_CS_0 20 +#define GSBI5_SPI_CS_1 61 +#define GSBI5_SPI_CS_2 62 +#define GSBI5_SPI_CS_3 2 +#define GSBI6_SPI_CLK 30 +#define GSBI6_SPI_CS_0 29 +#define GSBI6_SPI_MISO 28 +#define GSBI6_SPI_MOSI 27 +#define GSBI7_SPI_CLK 9 +#define GSBI7_SPI_CS_0 8 +#define GSBI7_SPI_MISO 7 +#define GSBI7_SPI_MOSI 6 + +#define MSM_GSBI_MAX_FREQ 51200000 + +#define SPI_RESET_STATE 0 +#define SPI_RUN_STATE 1 +#define SPI_PAUSE_STATE 3 +#define SPI_CORE_RESET 0 +#define SPI_CORE_RUNNING 1 +#define GSBI_SPI_MODE_0 0 +#define GSBI_SPI_MODE_1 1 +#define GSBI_SPI_MODE_2 2 +#define GSBI_SPI_MODE_3 3 +#define GSBI5_SPI 0 +#define GSBI6_SPI 1 +#define GSBI7_SPI 2 + +struct gsbi_spi { + unsigned int spi_config; + unsigned int io_control; + unsigned int error_flags; + unsigned int error_flags_en; + unsigned int gsbi_ctrl; + unsigned int qup_config; + unsigned int qup_error_flags; + unsigned int qup_error_flags_en; + unsigned int qup_operational; + unsigned int qup_io_modes; + unsigned int qup_state; + unsigned int qup_input_fifo; + unsigned int qup_output_fifo; + unsigned int qup_mx_input_count; + unsigned int qup_mx_output_count; + unsigned int qup_sw_reset; + unsigned int qup_ns_reg; + unsigned int qup_md_reg; +}; + +struct ipq_spi_slave { + struct spi_slave slave; + const struct gsbi_spi *regs; + unsigned int mode; + unsigned int initialized; + unsigned long freq; + int allocated; +}; + +static inline struct ipq_spi_slave *to_ipq_spi(struct spi_slave *slave) +{ + return container_of(slave, struct ipq_spi_slave, slave); +} + +#endif /* _IPQ_SPI_H_ */ diff --git a/src/soc/qualcomm/ipq806x/include/soc/usb.h b/src/soc/qualcomm/ipq806x/include/soc/usb.h new file mode 100644 index 0000000000..c3c4c48ce9 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/include/soc/usb.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _IPQ806X_USB_H_ +#define _IPQ806X_USB_H_ + +void setup_usb_host1(void); +void setup_usb_host2(void); + +#endif /* _IPQ806X_USB_H_ */ diff --git a/src/soc/qualcomm/ipq806x/qup.c b/src/soc/qualcomm/ipq806x/qup.c new file mode 100644 index 0000000000..5ac7f07e58 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/qup.c @@ -0,0 +1,483 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include "ipq806x_qup.h" + +//TODO: refactor the following array to iomap driver. +static unsigned gsbi_qup_base[] = { + 0x12460000, /*gsbi 1*/ + 0x124A0000, /*gsbi 2*/ + 0x16280000, /*gsbi 3*/ + 0x16380000, /*gsbi 4*/ + 0x1A280000, /*gsbi 5*/ + 0x16580000, /*gsbi 6*/ + 0x16680000, /*gsbi 7*/ +}; + +#define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg))) +#define MAX_DELAY_MS 100 + +static char *get_error_string(qup_return_t error) +{ + char *msg; + switch (error) { + case QUP_ERR_BAD_PARAM: + msg = "bad parameter"; + break; + case QUP_ERR_STATE_SET: + msg = "setting state failed"; + break; + case QUP_ERR_TIMEOUT: + msg = "timeout"; + break; + case QUP_ERR_UNSUPPORTED: + msg = "unsupported"; + break; + case QUP_ERR_I2C_INVALID_SLAVE_ADDR: + msg = "invalid slave address"; + break; + case QUP_ERR_XFER_FAIL: + msg = "transfer failed"; + break; + case QUP_ERR_UNDEFINED: + default: + msg = "undefined"; + break; + } + return msg; +} + +static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id) +{ + qup_return_t ret = QUP_SUCCESS; + uint32_t reg_val = readl(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS)); + + if (readl(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS))) + ret = QUP_ERR_XFER_FAIL; + else if (reg_val & QUP_I2C_INVALID_READ_ADDR) + ret = QUP_ERR_I2C_INVALID_SLAVE_ADDR; + else if (reg_val & (QUP_I2C_FAILED_MASK | + QUP_I2C_ARB_LOST | + QUP_I2C_BUS_ERROR)) + ret = QUP_ERR_XFER_FAIL; + + return ret; +} + +static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned wait_for) +{ + qup_return_t ret = QUP_ERR_STATE_SET; + uint32_t val = 0; + uint32_t start_ts; + uint32_t d = MAX_DELAY_MS * timer_hz() / 1000; + uint8_t final_state = 0; + + start_ts = timer_raw_value(); + do { + val = readl(QUP_ADDR(gsbi_id, QUP_STATE)); + final_state = ((val & (QUP_STATE_VALID_MASK|QUP_STATE_MASK)) + == (QUP_STATE_VALID|wait_for)); + } while ((!final_state) && (start_ts > (timer_raw_value() - d))); + + if (final_state) + ret = QUP_SUCCESS; + + return ret; +} + +static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode, + qup_data_t *p_tx_obj, uint8_t stop_seq) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + uint32_t start_ts; + uint32_t d = MAX_DELAY_MS * timer_hz() / 1000; + + switch (mode) { + case QUP_MODE_FIFO: { + uint8_t addr = p_tx_obj->p.iic.addr; + uint8_t *data_ptr = p_tx_obj->p.iic.data; + unsigned data_len = p_tx_obj->p.iic.data_len; + unsigned idx = 0; + + writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)); + writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN)); + qup_reset_i2c_master_status(gsbi_id); + qup_set_state(gsbi_id, QUP_STATE_RUN); + + writel((QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)), + QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO)); + + while (data_len) { + if (data_len == 1 && stop_seq) { + writel((QUP_I2C_STOP_SEQ | + QUP_I2C_DATA(data_ptr[idx])), + QUP_ADDR(gsbi_id, + QUP_OUTPUT_FIFO)); + } else { + writel((QUP_I2C_DATA_SEQ | + QUP_I2C_DATA(data_ptr[idx])), + QUP_ADDR(gsbi_id, + QUP_OUTPUT_FIFO)); + } + data_len--; + idx++; + start_ts = timer_raw_value(); + while (data_len && readl(QUP_ADDR(gsbi_id, + QUP_OPERATIONAL)) & + OUTPUT_FIFO_FULL) { + ret = qup_i2c_master_status(gsbi_id); + if (QUP_SUCCESS != ret) + goto bailout; + if (start_ts < (timer_raw_value() - d)) { + ret = QUP_ERR_TIMEOUT; + goto bailout; + } + } + /* Hardware sets the OUTPUT_SERVICE_FLAG flag to 1 when + OUTPUT_FIFO_NOT_EMPTY flag in the QUP_OPERATIONAL + register changes from 1 to 0, indicating that software + can write more data to the output FIFO. Software should + set OUTPUT_SERVICE_FLAG to 1 to clear it to 0, which + means that software knows to return to fill the output + FIFO with data. + */ + if (readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & + OUTPUT_SERVICE_FLAG) { + writel(OUTPUT_SERVICE_FLAG, + QUP_ADDR(gsbi_id, + QUP_OPERATIONAL)); + } + } + + start_ts = timer_raw_value(); + while (((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL))) & + OUTPUT_FIFO_NOT_EMPTY)) { + ret = qup_i2c_master_status(gsbi_id); + if (QUP_SUCCESS != ret) + goto bailout; + if (start_ts < (timer_raw_value() - d)) { + ret = QUP_ERR_TIMEOUT; + goto bailout; + } + } + + qup_set_state(gsbi_id, QUP_STATE_PAUSE); + ret = QUP_SUCCESS; + } + break; + + default: + ret = QUP_ERR_UNSUPPORTED; + } + +bailout: + if (QUP_SUCCESS != ret) { + qup_set_state(gsbi_id, QUP_STATE_RESET); + printf("%s() returns %s\n", __func__, get_error_string(ret)); + } + + return ret; +} + +static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode, + qup_data_t *p_tx_obj) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + uint32_t start_ts; + uint32_t d = MAX_DELAY_MS * timer_hz() / 1000; + + switch (mode) { + case QUP_MODE_FIFO: { + uint8_t addr = p_tx_obj->p.iic.addr; + uint8_t *data_ptr = p_tx_obj->p.iic.data; + unsigned data_len = p_tx_obj->p.iic.data_len; + unsigned idx = 0; + + writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)); + writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN)); + qup_reset_i2c_master_status(gsbi_id); + qup_set_state(gsbi_id, QUP_STATE_RUN); + + writel((QUP_I2C_START_SEQ | + (QUP_I2C_ADDR(addr)| + QUP_I2C_SLAVE_READ)), + QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO)); + + writel((QUP_I2C_RECV_SEQ | data_len), + QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO)); + + start_ts = timer_raw_value(); + while ((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & + OUTPUT_FIFO_NOT_EMPTY)) { + ret = qup_i2c_master_status(gsbi_id); + if (QUP_SUCCESS != ret) + goto bailout; + if (start_ts < (timer_raw_value() - d)) { + ret = QUP_ERR_TIMEOUT; + goto bailout; + } + } + + writel(OUTPUT_SERVICE_FLAG, + QUP_ADDR(gsbi_id, QUP_OPERATIONAL)); + + while (data_len) { + unsigned data; + start_ts = timer_raw_value(); + while ((!((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL))) & + INPUT_SERVICE_FLAG))) { + ret = qup_i2c_master_status(gsbi_id); + if (QUP_SUCCESS != ret) + goto bailout; + if (start_ts < (timer_raw_value() - d)) { + ret = QUP_ERR_TIMEOUT; + goto bailout; + } + } + + data = readl(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO)); + + /*Process tag and corresponding data value. + For I2C master mini-core, data in FIFO is composed of + 16 bits and is divided into an 8-bit tag for the upper + bits and 8-bit data for the lower bits. + The 8-bit tag indicates whether the byte is the last + byte, or if a bus error happened during the receipt of + the byte.*/ + if ((QUP_I2C_MI_TAG(data)) == QUP_I2C_MIDATA_SEQ) { + /* Tag: MIDATA = Master input data.*/ + data_ptr[idx] = QUP_I2C_DATA(data); + idx++; + data_len--; + writel(INPUT_SERVICE_FLAG, QUP_ADDR(gsbi_id, + QUP_OPERATIONAL)); + } else if (QUP_I2C_MI_TAG(data) == + QUP_I2C_MISTOP_SEQ) { + /* Tag: MISTOP: Last byte of master input. */ + data_ptr[idx] = QUP_I2C_DATA(data); + idx++; + data_len--; + goto recv_done; + } else { + /* Tag: MINACK: Invalid master input data.*/ + goto recv_done; + } + } +recv_done: + writel(INPUT_SERVICE_FLAG, + QUP_ADDR(gsbi_id, QUP_OPERATIONAL)); + p_tx_obj->p.iic.data_len = idx; + qup_set_state(gsbi_id, QUP_STATE_PAUSE); + ret = QUP_SUCCESS; + } + break; + + default: + ret = QUP_ERR_UNSUPPORTED; + } + +bailout: + if (QUP_SUCCESS != ret) { + qup_set_state(gsbi_id, QUP_STATE_RESET); + printf("%s() returns %s\n", __func__, get_error_string(ret)); + } + + return ret; +} + +qup_return_t qup_init(gsbi_id_t gsbi_id, qup_config_t *config_ptr) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + uint32_t reg_val; + + /* Reset the QUP core.*/ + writel(0x1, QUP_ADDR(gsbi_id, QUP_SW_RESET)); + + /*Wait till the reset takes effect */ + ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET); + + if (QUP_SUCCESS != ret) + return ret; + + /*Reset the config*/ + writel(0, QUP_ADDR(gsbi_id, QUP_CONFIG)); + + /*Program the config register*/ + /*Set N value*/ + reg_val = 0x0F; + /*Set protocol*/ + switch (config_ptr->protocol) { + case QUP_MINICORE_I2C_MASTER: { + reg_val |= ((config_ptr->protocol & + QUP_MINI_CORE_PROTO_MASK) << + QUP_MINI_CORE_PROTO_SHFT); + } + break; + default: { + ret = QUP_ERR_UNSUPPORTED; + goto bailout; + } + } + writel(reg_val, QUP_ADDR(gsbi_id, QUP_CONFIG)); + + /*Reset i2c clk cntl register*/ + writel(0, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL)); + + /*Set QUP IO Mode*/ + switch (config_ptr->mode) { + case QUP_MODE_FIFO: { + reg_val = QUP_OUTPUT_BIT_SHIFT_EN | + ((config_ptr->mode & QUP_MODE_MASK) << + QUP_OUTPUT_MODE_SHFT) | + ((config_ptr->mode & QUP_MODE_MASK) << + QUP_INPUT_MODE_SHFT); + } + break; + default: { + ret = QUP_ERR_UNSUPPORTED; + goto bailout; + } + } + writel(reg_val, QUP_ADDR(gsbi_id, QUP_IO_MODES)); + + /*Set i2c clk cntl*/ + reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT); + reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency) + / 2) - QUP_DIVIDER_MIN_VAL) & + QUP_FS_DIVIDER_MASK); + writel(reg_val, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL)); + +bailout: + if (QUP_SUCCESS != ret) + printf("%s() returns %s\n", __func__, get_error_string(ret)); + + return ret; +} + +qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + unsigned curr_state = readl(QUP_ADDR(gsbi_id, QUP_STATE)); + + if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE) + && (curr_state & QUP_STATE_VALID_MASK)) { + /* + * For PAUSE_STATE to RESET_STATE transition, + * two writes of 10[binary]) are required for the + * transition to complete. + */ + if (QUP_STATE_PAUSE == curr_state && + QUP_STATE_RESET == state) { + writel(0x2, QUP_ADDR(gsbi_id, QUP_STATE)); + writel(0x2, QUP_ADDR(gsbi_id, QUP_STATE)); + } else { + writel(state, QUP_ADDR(gsbi_id, QUP_STATE)); + } + ret = qup_wait_for_state(gsbi_id, state); + } + return ret; +} + +qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id) +{ + /* + * Writing a one clears the status bits. + * Bit31-25, Bit1 and Bit0 are reserved. + */ + //TODO: Define each status bit. OR all status bits in a single macro. + writel(0x3FFFFFC, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS)); + return QUP_SUCCESS; +} + +qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj, + uint8_t stop_seq) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + + if (p_tx_obj->protocol == ((readl(QUP_ADDR(gsbi_id, QUP_CONFIG)) >> + QUP_MINI_CORE_PROTO_SHFT) & + QUP_MINI_CORE_PROTO_MASK)) { + switch (p_tx_obj->protocol) { + case QUP_MINICORE_I2C_MASTER: { + uint8_t mode = (readl(QUP_ADDR(gsbi_id, + QUP_IO_MODES)) >> + QUP_OUTPUT_MODE_SHFT) & + QUP_MODE_MASK; + ret = qup_i2c_write(gsbi_id, mode, p_tx_obj, stop_seq); + if (0) { + int i; + printf("i2c tx bus %d device %2.2x:", + gsbi_id, p_tx_obj->p.iic.addr); + for (i = 0; i < p_tx_obj->p.iic.data_len; i++) + printf(" %2.2x", + p_tx_obj->p.iic.data[i]); + printf("\n"); + } + break; + } + + default: + ret = QUP_ERR_UNSUPPORTED; + } + } + return ret; +} + +qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj) +{ + qup_return_t ret = QUP_ERR_UNDEFINED; + if (p_rx_obj->protocol == ((readl(QUP_ADDR(gsbi_id, QUP_CONFIG)) >> + QUP_MINI_CORE_PROTO_SHFT) & + QUP_MINI_CORE_PROTO_MASK)) { + switch (p_rx_obj->protocol) { + case QUP_MINICORE_I2C_MASTER: { + uint8_t mode = (readl(QUP_ADDR(gsbi_id, + QUP_IO_MODES)) >> + QUP_INPUT_MODE_SHFT) & + QUP_MODE_MASK; + ret = qup_i2c_read(gsbi_id, mode, p_rx_obj); + if (0) { + int i; + printf("i2c rxed on bus %d device %2.2x:", + gsbi_id, p_rx_obj->p.iic.addr); + for (i = 0; i < p_rx_obj->p.iic.data_len; i++) + printf(" %2.2x", + p_rx_obj->p.iic.data[i]); + printf("\n"); + } + break; + } + default: + ret = QUP_ERR_UNSUPPORTED; + } + } + return ret; +} diff --git a/src/soc/qualcomm/ipq806x/qup.h b/src/soc/qualcomm/ipq806x/qup.h new file mode 100644 index 0000000000..f848cf6413 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/qup.h @@ -0,0 +1,207 @@ +/* + * This file is part of the depthcharge project. + * + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __QUP_H__ +#define __QUP_H__ +#include "ipq806x_gsbi.h" + +/* QUP block registers */ +#define QUP_CONFIG 0x0 +#define QUP_STATE 0x4 +#define QUP_IO_MODES 0x8 +#define QUP_SW_RESET 0xc +#define QUP_TIME_OUT 0x10 +#define QUP_TIME_OUT_CURRENT 0x14 +#define QUP_OPERATIONAL 0x18 +#define QUP_ERROR_FLAGS 0x1c +#define QUP_ERROR_FLAGS_EN 0x20 +#define QUP_TEST_CTRL 0x24 +#define QUP_MX_OUTPUT_COUNT 0x100 +#define QUP_MX_OUTPUT_CNT_CURRENT 0x104 +#define QUP_OUTPUT_DEBUG 0x108 +#define QUP_OUTPUT_FIFO_WORD_CNT 0x10c +#define QUP_OUTPUT_FIFO 0x110 +#define QUP_MX_WRITE_COUNT 0x150 +#define QUP_WRITE_CNT_CURRENT 0x154 +#define QUP_MX_INPUT_COUNT 0x200 +#define QUP_READ_COUNT 0x208 +#define QUP_MX_READ_CNT_CURRENT 0x20c +#define QUP_INPUT_DEBUG 0x210 +#define QUP_INPUT_FIFO_WORD_CNT 0x214 +#define QUP_INPUT_FIFO 0x218 +#define QUP_I2C_MASTER_CLK_CTL 0x400 +#define QUP_I2C_MASTER_STATUS 0x404 + +#define OUTPUT_FIFO_FULL (1<<6) +#define INPUT_FIFO_NOT_EMPTY (1<<5) +#define OUTPUT_FIFO_NOT_EMPTY (1<<4) +#define INPUT_SERVICE_FLAG (1<<9) +#define OUTPUT_SERVICE_FLAG (1<<8) +#define QUP_OUTPUT_BIT_SHIFT_EN (1<<16) + +#define QUP_MODE_MASK (0x03) +#define QUP_OUTPUT_MODE_SHFT (10) +#define QUP_INPUT_MODE_SHFT (12) + +#define QUP_FS_DIVIDER_MASK (0xFF) + +#define QUP_MINI_CORE_PROTO_SHFT (8) +#define QUP_MINI_CORE_PROTO_MASK (0x0F) + +/* Mini-core states */ +#define QUP_STATE_RESET 0x0 +#define QUP_STATE_RUN 0x1 +#define QUP_STATE_PAUSE 0x3 +#define QUP_STATE_VALID (1<<2) +#define QUP_STATE_MASK 0x3 +#define QUP_STATE_VALID_MASK (1<<2) + +/* Tags for output FIFO */ +#define QUP_I2C_1CLK_NOOP_SEQ 0x1 /*MSB 8-bit NOP, LSB 8-bits 1 clk.*/ +#define QUP_I2C_START_SEQ (0x1 << 8) +#define QUP_I2C_DATA_SEQ (0x2 << 8) +#define QUP_I2C_STOP_SEQ (0x3 << 8) +#define QUP_I2C_RECV_SEQ (0x4 << 8) + +/* Tags for input FIFO */ +#define QUP_I2C_MIDATA_SEQ (0x5 << 8) +#define QUP_I2C_MISTOP_SEQ (0x6 << 8) +#define QUP_I2C_MINACK_SEQ (0x7 << 8) + +#define QUP_I2C_ADDR(x) ((x & 0xFF) << 1) +#define QUP_I2C_DATA(x) (x & 0xFF) +#define QUP_I2C_MI_TAG(x) (x & 0xFF00) +#define QUP_I2C_SLAVE_READ (0x1) + +/*Bit vals for I2C_MASTER_CLK_CTL register */ +#define QUP_HS_DIVIDER_SHFT (8) +#define QUP_DIVIDER_MIN_VAL (0x3) + +/* Bit masks for I2C_MASTER_STATUS register */ +#define QUP_I2C_INVALID_READ_SEQ (1 << 25) +#define QUP_I2C_INVALID_READ_ADDR (1 << 24) +#define QUP_I2C_INVALID_TAG (1 << 23) +#define QUP_I2C_FAILED_MASK (0x3 << 6) +#define QUP_I2C_ARB_LOST (1 << 4) +#define QUP_I2C_BUS_ERROR (1 << 2) + +typedef enum { + QUP_SUCCESS = 0, + QUP_ERR_BAD_PARAM, + QUP_ERR_STATE_SET, + QUP_ERR_TIMEOUT, + QUP_ERR_UNSUPPORTED, + QUP_ERR_I2C_INVALID_SLAVE_ADDR, + QUP_ERR_XFER_FAIL, + QUP_ERR_UNDEFINED, +} qup_return_t; + +typedef enum { + QUP_MINICORE_SPI = 1, + QUP_MINICORE_I2C_MASTER, + QUP_MINICORE_I2C_SLAVE +} qup_protocol_t; + +typedef enum { + QUP_MODE_FIFO = 0, + QUP_MODE_BLOCK, + QUP_MODE_DATAMOVER, +} qup_mode_t; + +typedef struct { + qup_protocol_t protocol; + unsigned clk_frequency; + unsigned src_frequency; + qup_mode_t mode; +} qup_config_t; + +typedef struct { + qup_protocol_t protocol; + union { + struct { + uint8_t addr; + uint8_t *data; + unsigned data_len; + } iic; + struct { + void *in; + void *out; + unsigned size; + } spi; + } p; +} qup_data_t; + +/* + * Initialize GSBI QUP block for FIFO I2C transfers. + * gsbi_id[IN]: GSBI for which QUP is to be initialized. + * config_ptr[IN]: configurations parameters for the QUP. + * + * return: QUP_SUCCESS, if initialization succeeds. + */ +qup_return_t qup_init(gsbi_id_t gsbi_id, qup_config_t *config_ptr); + +/* + * Set QUP state to run, pause, reset. + * gsbi_id[IN]: GSBI block for which QUP state is to be set. + * state[IN]: New state to transition to. + * + * return: QUP_SUCCESS, if state transition succeeds. + */ +qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state); + +/* + * Reset the status bits set during an i2c transfer. + * gsbi_id[IN]: GSBI block for which i2c status bits are to be cleared. + * + * return: QUP_SUCCESS, if status bits are cleared successfully. + */ +qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id); + +/* + * Send data to the peripheral on the bus. + * gsbi_id[IN]: GSBI block for which data is to be sent. + * p_tx_obj[IN]: Data to be sent to the slave on the bus. + * stop_seq[IN]: When set to non-zero QUP engine sends i2c stop sequnce. + * + * return: QUP_SUCCESS, when data is sent successfully to the peripheral. + */ +qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj, + uint8_t stop_seq); + +/* + * Receive data from peripheral on the bus. + * gsbi_id[IN]: GSBI block from which data is to be received. + * p_tx_obj[IN]: length of data to be received, slave address. + * [OUT]: buffer filled with data from slave. + * + * return: QUP_SUCCESS, when data is received successfully. + */ +qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj); + +#endif //__QUP_H__ diff --git a/src/soc/qualcomm/ipq806x/soc.c b/src/soc/qualcomm/ipq806x/soc.c new file mode 100644 index 0000000000..1d63cacf60 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/soc.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#define RESERVED_SIZE_KB (0x01500000 / KiB) + +static void soc_read_resources(device_t dev) +{ + /* Reserve bottom 0x150_0000 bytes for NSS, SMEM, etc. */ + reserved_ram_resource(dev, 0, (uintptr_t)_dram / KiB, RESERVED_SIZE_KB); + ram_resource(dev, 0, (uintptr_t)_dram / KiB + RESERVED_SIZE_KB, + (CONFIG_DRAM_SIZE_MB * KiB) - RESERVED_SIZE_KB); +} + +static void soc_init(device_t dev) +{ + printk(BIOS_INFO, "CPU: Qualcomm 8064\n"); +} + +static struct device_operations soc_ops = { + .read_resources = soc_read_resources, + .init = soc_init, +}; + +static void enable_soc_dev(device_t dev) +{ + dev->ops = &soc_ops; +} + +struct chip_operations soc_qualcomm_ipq806x_ops = { + CHIP_NAME("SOC Qualcomm 8064") + .enable_dev = enable_soc_dev, +}; diff --git a/src/soc/qualcomm/ipq806x/spi.c b/src/soc/qualcomm/ipq806x/spi.c new file mode 100644 index 0000000000..0f72cac6be --- /dev/null +++ b/src/soc/qualcomm/ipq806x/spi.c @@ -0,0 +1,775 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SUCCESS 0 + +#define DUMMY_DATA_VAL 0 +#define TIMEOUT_CNT 100 +#define CS_ASSERT 1 +#define CS_DEASSERT 0 +#define NUM_PORTS 3 +#define NUM_GSBI_PINS 3 +#define TLMM_ARGS 6 +#define NUM_CS 4 +#define GSBI_PIN_IDX 0 +#define FUNC_SEL_IDX 1 +#define GPIO_DIR_IDX 2 +#define PULL_CONF_IDX 3 +#define DRV_STR_IDX 4 +#define GPIO_EN_IDX 5 + +/* Arbitrarily assigned error code values */ +#define ETIMEDOUT -10 +#define EINVAL -11 +#define EIO -12 + +#define GSBI_IDX_TO_GSBI(idx) (idx + 5) + + +/* MX_INPUT_COUNT and MX_OUTPUT_COUNT are 16-bits. Zero has a special meaning + * (count function disabled) and does not hold significance in the count. */ +#define MAX_PACKET_COUNT ((64 * KiB) - 1) + +/* + * TLMM Configuration for SPI NOR + * gsbi_pin_conf[bus_num][GPIO_NUM, FUNC_SEL, I/O, + * PULL UP/DOWN, DRV_STR, GPIO_FUNC] + * gsbi_pin_conf[0][x][y] -- GSBI5 + * gsbi_pin_conf[1][x][y] -- GSBI6 + * gsbi_pin_conf[2][x][y] -- GSBI7 +*/ +static unsigned int gsbi_pin_conf[NUM_PORTS][NUM_GSBI_PINS][TLMM_ARGS] = { + { + /* GSBI5 CLK */ + { + GSBI5_SPI_CLK, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE + }, + /* GSBI5 MISO */ + { + GSBI5_SPI_MISO, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + }, + /* GSBI5 MOSI */ + { + GSBI5_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + } + }, + { + /* GSBI6 CLK */ + { + GSBI6_SPI_CLK, FUNC_SEL_3, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE + }, + /* GSBI6 MISO */ + { + GSBI6_SPI_MISO, FUNC_SEL_3, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + }, + /* GSBI6 MOSI */ + { + GSBI6_SPI_MOSI, FUNC_SEL_3, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + } + }, + { + /* GSBI7 CLK */ + { + GSBI7_SPI_CLK, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE + }, + /* GSBI7 MISO */ + { + GSBI7_SPI_MISO, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + }, + /* GSBI7 MOSI */ + { + GSBI7_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT, + GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE + } + } +}; + +/* + * CS GPIO number array cs_gpio_array[port_num][cs_num] + * cs_gpio_array[0][x] -- GSBI5 + * cs_gpio_array[1][x] -- GSBI6 + * cs_gpio_array[2][x] -- GSBI7 + */ +static unsigned int cs_gpio_array[NUM_PORTS][NUM_CS] = { + { + GSBI5_SPI_CS_0, GSBI5_SPI_CS_1, GSBI5_SPI_CS_2, GSBI5_SPI_CS_3 + }, + { + GSBI6_SPI_CS_0, 0, 0, 0 + }, + { + GSBI7_SPI_CS_0, 0, 0, 0 + } +}; + +/* + * GSBI HCLK state register bit + * hclk_state[0] -- GSBI5 + * hclk_state[1] -- GSBI6 + * hclk_state[2] -- GSBI7 +*/ +static unsigned int hclk_state[NUM_PORTS] = { + GSBI5_HCLK, + GSBI6_HCLK, + GSBI7_HCLK +}; + +/* + * GSBI QUP_APPS_CLK state register bit + * qup_apps_clk_state[0] -- GSBI5 + * qup_apps_clk_state[1] -- GSBI6 + * qup_apps_clk_state[2] -- GSBI7 +*/ +static unsigned int qup_apps_clk_state[NUM_PORTS] = { + GSBI5_QUP_APPS_CLK, + GSBI6_QUP_APPS_CLK, + GSBI7_QUP_APPS_CLK +}; + + +static int check_bit_state(uint32_t reg_addr, int bit_num, int val, int us_delay) +{ + unsigned int count = TIMEOUT_CNT; + unsigned int bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01); + + while (bit_val != val) { + count--; + if (count == 0) + return -ETIMEDOUT; + udelay(us_delay); + bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01); + } + + return SUCCESS; +} + +/* + * Check whether GSBIn_QUP State is valid + */ +static int check_qup_state_valid(struct ipq_spi_slave *ds) +{ + + return check_bit_state(ds->regs->qup_state, QUP_STATE_VALID_BIT, + QUP_STATE_VALID, 1); + +} + +/* + * Configure GSBIn Core state + */ +static int config_spi_state(struct ipq_spi_slave *ds, unsigned int state) +{ + uint32_t val; + int ret; + uint32_t new_state; + + ret = check_qup_state_valid(ds); + if (ret != SUCCESS) + return ret; + + switch (state) { + case SPI_RUN_STATE: + new_state = QUP_STATE_RUN_STATE; + break; + + case SPI_RESET_STATE: + new_state = QUP_STATE_RESET_STATE; + break; + + case SPI_PAUSE_STATE: + new_state = QUP_STATE_PAUSE_STATE; + break; + + default: + printk(BIOS_ERR, + "err: unsupported GSBI SPI state : %d\n", state); + return -EINVAL; + } + + /* Set the state as requested */ + val = (readl_i(ds->regs->qup_state) & ~QUP_STATE_MASK) + | new_state; + writel_i(val, ds->regs->qup_state); + return check_qup_state_valid(ds); +} + +/* + * Set GSBIn SPI Mode + */ +static void spi_set_mode(struct ipq_spi_slave *ds, unsigned int mode) +{ + unsigned int clk_idle_state; + unsigned int input_first_mode; + uint32_t val; + + switch (mode) { + case GSBI_SPI_MODE_0: + clk_idle_state = 0; + input_first_mode = SPI_INPUT_FIRST_MODE; + break; + case GSBI_SPI_MODE_1: + clk_idle_state = 0; + input_first_mode = 0; + break; + case GSBI_SPI_MODE_2: + clk_idle_state = 1; + input_first_mode = SPI_INPUT_FIRST_MODE; + break; + case GSBI_SPI_MODE_3: + clk_idle_state = 1; + input_first_mode = 0; + break; + default: + printk(BIOS_ERR, + "err : unsupported spi mode : %d\n", mode); + return; + } + + val = readl_i(ds->regs->spi_config); + val |= input_first_mode; + writel_i(val, ds->regs->spi_config); + + val = readl_i(ds->regs->io_control); + if (clk_idle_state) + val |= SPI_IO_CONTROL_CLOCK_IDLE_HIGH; + else + val &= ~SPI_IO_CONTROL_CLOCK_IDLE_HIGH; + + writel_i(val, ds->regs->io_control); +} + +/* + * Check for HCLK state + */ +static int check_hclk_state(unsigned int core_num, int enable) +{ + return check_bit_state(CLK_HALT_CFPB_STATEB_REG, + hclk_state[core_num], enable, 5); +} + +/* + * Check for QUP APPS CLK state + */ +static int check_qup_clk_state(unsigned int core_num, int enable) +{ + return check_bit_state(CLK_HALT_CFPB_STATEB_REG, + qup_apps_clk_state[core_num], enable, 5); +} + +/* + * Function to assert and De-assert chip select + */ +static void CS_change(int port_num, int cs_num, int enable) +{ + unsigned int cs_gpio = cs_gpio_array[port_num][cs_num]; + void *addr = GPIO_IN_OUT_ADDR(cs_gpio); + uint32_t val = readl_i(addr); + + val &= (~(1 << GPIO_OUTPUT)); + if (!enable) + val |= (1 << GPIO_OUTPUT); + writel(val, addr); +} + +/* + * GSBIn TLMM configuration + */ +static void gsbi_pin_config(unsigned int port_num, int cs_num) +{ + unsigned int gpio; + unsigned int i; + /* Hold the GSBIn (core_num) core in reset */ + clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(port_num)), + GSBI1_RESET_MSK, GSBI1_RESET); + + /* + * Configure SPI_CLK, SPI_MISO and SPI_MOSI + */ + for (i = 0; i < NUM_GSBI_PINS; i++) { + unsigned int func_sel; + unsigned int io_config; + unsigned int pull_config; + unsigned int drv_strength; + unsigned int gpio_en; + unsigned int *ptr; + + ptr = gsbi_pin_conf[port_num][i]; + gpio = *(ptr + GSBI_PIN_IDX); + func_sel = *(ptr + FUNC_SEL_IDX); + io_config = *(ptr + GPIO_DIR_IDX); + pull_config = *(ptr + PULL_CONF_IDX); + drv_strength = *(ptr + DRV_STR_IDX); + gpio_en = *(ptr + GPIO_EN_IDX); + + gpio_tlmm_config(gpio, func_sel, io_config, + pull_config, drv_strength, gpio_en); + } + + gpio = cs_gpio_array[port_num][cs_num]; + /* configure CS */ + gpio_tlmm_config(gpio, FUNC_SEL_GPIO, GPIO_OUTPUT, GPIO_PULL_UP, + GPIO_DRV_STR_10MA, GPIO_FUNC_ENABLE); + CS_change(port_num, cs_num, CS_DEASSERT); +} + +/* + * Clock configuration for GSBIn Core + */ +static int gsbi_clock_init(struct ipq_spi_slave *ds) +{ + int ret; + + /* Hold the GSBIn (core_num) core in reset */ + clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)), + GSBI1_RESET_MSK, GSBI1_RESET); + + /* Disable GSBIn (core_num) QUP core clock branch */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK, + QUP_CLK_BRANCH_DIS); + + ret = check_qup_clk_state(ds->slave.bus, 1); + if (ret) { + printk(BIOS_ERR, + "QUP Clock Halt For GSBI%d failed!\n", ds->slave.bus); + return ret; + } + + /* Disable M/N:D counter and hold M/N:D counter in reset */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, (MNCNTR_MSK | MNCNTR_RST_MSK), + (MNCNTR_RST_ENA | MNCNTR_DIS)); + + /* Disable GSBIn (core_num) QUP core clock root */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_DIS); + + clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PLL_SRC_MSK, + GSBIn_PLL_SRC_PLL8); + clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PRE_DIV_SEL_MSK, + (0 << GSBI_PRE_DIV_SEL_SHFT)); + + /* Program M/N:D values for GSBIn_QUP_APPS_CLK @50MHz */ + clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_M_VAL_MSK, + (0x01 << GSBI_M_VAL_SHFT)); + clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_D_VAL_MSK, + (0xF7 << GSBI_D_VAL_SHFT)); + clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_N_VAL_MSK, + (0xF8 << GSBI_N_VAL_SHFT)); + + /* Set MNCNTR_MODE = 0: Bypass mode */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MODE_MSK, + MNCNTR_MODE_DUAL_EDGE); + + /* De-assert the M/N:D counter reset */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_RST_MSK, MNCNTR_RST_DIS); + clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MSK, MNCNTR_EN); + + /* + * Enable the GSBIn (core_num) QUP core clock root. + * Keep MND counter disabled + */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_ENA); + + /* Enable GSBIn (core_num) QUP core clock branch */ + clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK, + QUP_CLK_BRANCH_ENA); + + ret = check_qup_clk_state(ds->slave.bus, 0); + if (ret) { + printk(BIOS_ERR, + "QUP Clock Enable For GSBI%d" + " failed!\n", ds->slave.bus); + return ret; + } + + /* Enable GSBIn (core_num) core clock branch */ + clrsetbits_le32_i(GSBIn_HCLK_CTL_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)), + GSBI_CLK_BRANCH_ENA_MSK, GSBI_CLK_BRANCH_ENA); + + ret = check_hclk_state(ds->slave.bus, 0); + if (ret) { + printk(BIOS_ERR, + "HCLK Enable For GSBI%d failed!\n", ds->slave.bus); + return ret; + } + + /* Release GSBIn (core_num) core from reset */ + clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)), + GSBI1_RESET_MSK, 0); + udelay(50); + + return SUCCESS; +} + +/* + * Reset entire QUP and all mini cores + */ +static void spi_reset(struct ipq_spi_slave *ds) +{ + writel_i(0x1, ds->regs->qup_sw_reset); + udelay(5); +} + +static const struct gsbi_spi spi_reg[] = { + /* GSBI5 registers for SPI interface */ + { + GSBI5_SPI_CONFIG_REG, + GSBI5_SPI_IO_CONTROL_REG, + GSBI5_SPI_ERROR_FLAGS_REG, + GSBI5_SPI_ERROR_FLAGS_EN_REG, + GSBI5_GSBI_CTRL_REG_REG, + GSBI5_QUP_CONFIG_REG, + GSBI5_QUP_ERROR_FLAGS_REG, + GSBI5_QUP_ERROR_FLAGS_EN_REG, + GSBI5_QUP_OPERATIONAL_REG, + GSBI5_QUP_IO_MODES_REG, + GSBI5_QUP_STATE_REG, + GSBI5_QUP_INPUT_FIFOc_REG(0), + GSBI5_QUP_OUTPUT_FIFOc_REG(0), + GSBI5_QUP_MX_INPUT_COUNT_REG, + GSBI5_QUP_MX_OUTPUT_COUNT_REG, + GSBI5_QUP_SW_RESET_REG, + GSBIn_QUP_APPS_NS_REG(5), + GSBIn_QUP_APPS_MD_REG(5), + }, + /* GSBI6 registers for SPI interface */ + { + GSBI6_SPI_CONFIG_REG, + GSBI6_SPI_IO_CONTROL_REG, + GSBI6_SPI_ERROR_FLAGS_REG, + GSBI6_SPI_ERROR_FLAGS_EN_REG, + GSBI6_GSBI_CTRL_REG_REG, + GSBI6_QUP_CONFIG_REG, + GSBI6_QUP_ERROR_FLAGS_REG, + GSBI6_QUP_ERROR_FLAGS_EN_REG, + GSBI6_QUP_OPERATIONAL_REG, + GSBI6_QUP_IO_MODES_REG, + GSBI6_QUP_STATE_REG, + GSBI6_QUP_INPUT_FIFOc_REG(0), + GSBI6_QUP_OUTPUT_FIFOc_REG(0), + GSBI6_QUP_MX_INPUT_COUNT_REG, + GSBI6_QUP_MX_OUTPUT_COUNT_REG, + GSBI6_QUP_SW_RESET_REG, + GSBIn_QUP_APPS_NS_REG(6), + GSBIn_QUP_APPS_MD_REG(6), + }, + /* GSBI7 registers for SPI interface */ + { + GSBI7_SPI_CONFIG_REG, + GSBI7_SPI_IO_CONTROL_REG, + GSBI7_SPI_ERROR_FLAGS_REG, + GSBI7_SPI_ERROR_FLAGS_EN_REG, + GSBI7_GSBI_CTRL_REG_REG, + GSBI7_QUP_CONFIG_REG, + GSBI7_QUP_ERROR_FLAGS_REG, + GSBI7_QUP_ERROR_FLAGS_EN_REG, + GSBI7_QUP_OPERATIONAL_REG, + GSBI7_QUP_IO_MODES_REG, + GSBI7_QUP_STATE_REG, + GSBI7_QUP_INPUT_FIFOc_REG(0), + GSBI7_QUP_OUTPUT_FIFOc_REG(0), + GSBI7_QUP_MX_INPUT_COUNT_REG, + GSBI7_QUP_MX_OUTPUT_COUNT_REG, + GSBI7_QUP_SW_RESET_REG, + GSBIn_QUP_APPS_NS_REG(7), + GSBIn_QUP_APPS_MD_REG(7), + } +}; +static struct ipq_spi_slave spi_slave_pool[2]; + +void spi_init() +{ + /* just in case */ + memset(spi_slave_pool, 0, sizeof(spi_slave_pool)); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + struct ipq_spi_slave *ds = NULL; + int i; + + /* + * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash + * on different GSBI5, GSBI6 and GSBI7 + * with different number of chip selects (CS, channels): + */ + if ((bus < GSBI5_SPI) || (bus > GSBI7_SPI) + || ((bus == GSBI5_SPI) && (cs > 3)) + || ((bus == GSBI6_SPI) && (cs > 0)) + || ((bus == GSBI7_SPI) && (cs > 0))) { + printk(BIOS_ERR, "SPI error: unsupported bus %d " + "(Supported busses 0,1 and 2) or chipselect\n", bus); + } + + for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) { + if (spi_slave_pool[i].allocated) + continue; + ds = spi_slave_pool + i; + ds->slave.bus = bus; + ds->slave.cs = cs; + ds->regs = &spi_reg[bus]; + + /* + * TODO(vbendeb): + * hardcoded frequency and mode - we might need to find a way + * to configure this + */ + ds->freq = 10000000; + ds->mode = GSBI_SPI_MODE_0; + ds->allocated = 1; + + return &ds->slave; + } + + printk(BIOS_ERR, "SPI error: all %d pools busy\n", i); + return NULL; +} + +/* + * GSBIn SPI Hardware Initialisation + */ +static int spi_hw_init(struct ipq_spi_slave *ds) +{ + int ret; + + if (ds->initialized) + return 0; + + /* GSBI module configuration */ + spi_reset(ds); + + /* Set the GSBIn QUP state */ + ret = config_spi_state(ds, SPI_RESET_STATE); + if (ret) + return ret; + + /* Configure GSBI_CTRL register to set protocol_mode to SPI:011 */ + clrsetbits_le32_i(ds->regs->gsbi_ctrl, PROTOCOL_CODE_MSK, + PROTOCOL_CODE_SPI); + + /* + * Configure Mini core to SPI core with Input Output enabled, + * SPI master, N = 8 bits + */ + clrsetbits_le32_i(ds->regs->qup_config, (QUP_CONFIG_MINI_CORE_MSK | + SPI_QUP_CONF_INPUT_MSK | + SPI_QUP_CONF_OUTPUT_MSK | + SPI_BIT_WORD_MSK), + (QUP_CONFIG_MINI_CORE_SPI | + SPI_QUP_CONF_NO_INPUT | + SPI_QUP_CONF_NO_OUTPUT | + SPI_8_BIT_WORD)); + + /* + * Configure Input first SPI protocol, + * SPI master mode and no loopback + */ + clrsetbits_le32_i(ds->regs->spi_config, (LOOP_BACK_MSK | + SLAVE_OPERATION_MSK), + (NO_LOOP_BACK | + SLAVE_OPERATION)); + + /* + * Configure SPI IO Control Register + * CLK_ALWAYS_ON = 0 + * MX_CS_MODE = 0 + * NO_TRI_STATE = 1 + */ + writel_i((CLK_ALWAYS_ON | MX_CS_MODE | NO_TRI_STATE), + ds->regs->io_control); + + /* + * Configure SPI IO Modes. + * OUTPUT_BIT_SHIFT_EN = 1 + * INPUT_MODE = Block Mode + * OUTPUT MODE = Block Mode + */ + clrsetbits_le32_i(ds->regs->qup_io_modes, (OUTPUT_BIT_SHIFT_MSK | + INPUT_BLOCK_MODE_MSK | + OUTPUT_BLOCK_MODE_MSK), + (OUTPUT_BIT_SHIFT_EN | + INPUT_BLOCK_MODE | + OUTPUT_BLOCK_MODE)); + + spi_set_mode(ds, ds->mode); + + /* Disable Error mask */ + writel_i(0, ds->regs->error_flags_en); + writel_i(0, ds->regs->qup_error_flags_en); + + ds->initialized = 1; + + return SUCCESS; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct ipq_spi_slave *ds = to_ipq_spi(slave); + unsigned int ret; + + if (ds->initialized) + return SUCCESS; + + /* GPIO Configuration for SPI port */ + gsbi_pin_config(ds->slave.bus, ds->slave.cs); + + /* Clock configuration */ + ret = gsbi_clock_init(ds); + if (ret) + return ret; + + ret = spi_hw_init(ds); + if (ret) + return -EIO; + + return SUCCESS; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct ipq_spi_slave *ds = to_ipq_spi(slave); + + /* Reset the SPI hardware */ + spi_reset(ds); + ds->initialized = 0; +} + +static int spi_xfer_tx_packet(struct ipq_spi_slave *ds, + const uint8_t *dout, unsigned out_bytes) +{ + int ret; + + writel_i(out_bytes, ds->regs->qup_mx_output_count); + + ret = config_spi_state(ds, SPI_RUN_STATE); + if (ret) + return ret; + + while (out_bytes) { + if (readl_i(ds->regs->qup_operational) & QUP_OUTPUT_FIFO_FULL) + continue; + + writel_i(*dout++, ds->regs->qup_output_fifo); + out_bytes--; + + /* Wait for output FIFO to drain. */ + if (!out_bytes) + while (readl_i(ds->regs->qup_operational) & + QUP_OUTPUT_FIFO_NOT_EMPTY) + ; + } + + return config_spi_state(ds, SPI_RESET_STATE); +} + +static int spi_xfer_rx_packet(struct ipq_spi_slave *ds, + uint8_t *din, unsigned in_bytes) +{ + int ret; + + writel_i(in_bytes, ds->regs->qup_mx_input_count); + writel_i(in_bytes, ds->regs->qup_mx_output_count); + + ret = config_spi_state(ds, SPI_RUN_STATE); + if (ret) + return ret; + + /* Seed clocking */ + writel_i(0xff, ds->regs->qup_output_fifo); + while (in_bytes) { + if (!(readl_i(ds->regs->qup_operational) & + QUP_INPUT_FIFO_NOT_EMPTY)) + continue; + /* Keep it clocking */ + writel_i(0xff, ds->regs->qup_output_fifo); + + *din++ = readl_i(ds->regs->qup_input_fifo) & 0xff; + in_bytes--; + } + + return config_spi_state(ds, SPI_RESET_STATE); +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned out_bytes, void *din, unsigned in_bytes) +{ + int ret; + struct ipq_spi_slave *ds = to_ipq_spi(slave); + + /* Assert the chip select */ + CS_change(ds->slave.bus, ds->slave.cs, CS_ASSERT); + + ret = config_spi_state(ds, SPI_RESET_STATE); + if (ret) + goto out; + + if (!out_bytes) + goto spi_receive; + + /* + * Let's do the write side of the transaction first. Enable output + * FIFO. + */ + clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_OUTPUT_MSK, + SPI_QUP_CONF_OUTPUT_ENA); + + while (out_bytes) { + unsigned todo = MIN(out_bytes, MAX_PACKET_COUNT); + + ret = spi_xfer_tx_packet(ds, dout, todo); + if (ret) + break; + + out_bytes -= todo; + dout += todo; + } + + if (ret) + goto out; + +spi_receive: + if (!in_bytes) /* Nothing to read. */ + goto out; + + /* Enable input FIFO */ + clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_INPUT_MSK, + SPI_QUP_CONF_INPUT_ENA); + + while (in_bytes) { + unsigned todo = MIN(in_bytes, MAX_PACKET_COUNT); + + ret = spi_xfer_rx_packet(ds, din, todo); + if (ret) + break; + + in_bytes -= todo; + din += todo; + } + +out: + /* Deassert CS */ + CS_change(ds->slave.bus, ds->slave.cs, CS_DEASSERT); + + /* + * Put the SPI Core back in the Reset State + * to end the transfer + */ + (void)config_spi_state(ds, SPI_RESET_STATE); + + return ret; +} diff --git a/src/soc/qualcomm/ipq806x/timer.c b/src/soc/qualcomm/ipq806x/timer.c new file mode 100644 index 0000000000..33d16334aa --- /dev/null +++ b/src/soc/qualcomm/ipq806x/timer.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011 - 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * DGT runs at 25 MHz / 4, or 6.25 ticks per microsecond + */ +#define DGT_MHZ_NUM 25 +#define DGT_MHZ_DEN 4 + +#define TIMER_TICKS(us) ((DGT_MHZ_NUM*(us)+(DGT_MHZ_DEN-1))/DGT_MHZ_DEN) +#define TIMER_USECS(ticks) (DGT_MHZ_DEN*(ticks)/DGT_MHZ_NUM) + +/* Clock divider values for the timer. */ +#define DGT_CLK_DIV_1 0 +#define DGT_CLK_DIV_2 1 +#define DGT_CLK_DIV_3 2 +#define DGT_CLK_DIV_4 3 + +/** + * init_timer - initialize timer + */ +void init_timer(void) +{ + /* disable timer */ + writel_i(0, DGT_ENABLE); + + /* DGT uses TCXO source which is 25MHz. + * The timer should run at 1/4th the frequency of TCXO + * according to clock plan. + * Set clock divider to 4. + */ + writel_i(DGT_CLK_DIV_4, DGT_CLK_CTL); + + /* Enable timer */ + writel_i(0, DGT_CLEAR); + writel_i(DGT_ENABLE_EN, DGT_ENABLE); +} + +/** + * udelay - generates micro second delay. + * @usec: delay duration in microseconds + */ +void udelay(unsigned usec) +{ + uint32_t now; + uint32_t last; + uint32_t ticks; + uint32_t curr_ticks = 0; + + /* Calculate number of ticks required. */ + ticks = TIMER_TICKS(usec); + + /* Obtain the current timer value. */ + last = readl_i(DGT_COUNT_VAL); + + /* Loop until the right number of ticks. */ + while (curr_ticks < ticks) { + now = readl_i(DGT_COUNT_VAL); + curr_ticks += now - last; + last = now; + } +} + +void timer_monotonic_get(struct mono_time *mt) +{ + mono_time_set_usecs(mt, TIMER_USECS(readl_i(DGT_COUNT_VAL))); +} diff --git a/src/soc/qualcomm/ipq806x/uart.c b/src/soc/qualcomm/ipq806x/uart.c new file mode 100644 index 0000000000..b7f756fa3a --- /dev/null +++ b/src/soc/qualcomm/ipq806x/uart.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2012 The Linux Foundation. All rights reserved. + * Source : APQ8064 LK boot + * + * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIFO_DATA_SIZE 4 + +typedef struct { + unsigned uart_dm_base; + unsigned uart_gsbi_base; + unsigned uart_gsbi; + uart_clk_mnd_t mnd_value; + gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS]; +} uart_params_t; + +/* + * All constants lifted from u-boot's + * board/qcom/ipq806x_cdp/ipq806x_board_param.h + */ +static const uart_params_t uart_board_param = { + .uart_dm_base = UART4_DM_BASE, + .uart_gsbi_base = UART_GSBI4_BASE, + .uart_gsbi = GSBI_4, + .mnd_value = { 12, 625, 313 }, + .dbg_uart_gpio = { + { + .gpio = 10, + .func = 1, + .dir = GPIO_OUTPUT, + .pull = GPIO_NO_PULL, + .drvstr = GPIO_12MA, + .enable = GPIO_DISABLE + }, + { + .gpio = 11, + .func = 1, + .dir = GPIO_INPUT, + .pull = GPIO_NO_PULL, + .drvstr = GPIO_12MA, + .enable = GPIO_DISABLE + }, + } +}; + +static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base); + +/* Received data is valid or not */ +static int valid_data = 0; + +/* Received data */ +static unsigned int word = 0; + +/** + * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer + * @uart_dm_base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base) +{ + /* Reset receiver */ + writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX, + MSM_BOOT_UART_DM_CR(uart_dm_base)); + + /* Enable receiver */ + writel_i(MSM_BOOT_UART_DM_CR_RX_ENABLE, + MSM_BOOT_UART_DM_CR(uart_dm_base)); + writel_i(MSM_BOOT_UART_DM_DMRX_DEF_VALUE, + MSM_BOOT_UART_DM_DMRX(uart_dm_base)); + + /* Clear stale event */ + writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, + MSM_BOOT_UART_DM_CR(uart_dm_base)); + + /* Enable stale event */ + writel_i(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT, + MSM_BOOT_UART_DM_CR(uart_dm_base)); + + return MSM_BOOT_UART_DM_E_SUCCESS; +} + +/** + * msm_boot_uart_dm_read - reads a word from the RX FIFO. + * @data: location where the read data is stored + * @count: no of valid data in the FIFO + * @wait: indicates blocking call or not blocking call + * + * Reads a word from the RX FIFO. If no data is available blocks if + * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY. + */ +static unsigned int +msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) +{ + static int total_rx_data = 0; + static int rx_data_read = 0; + unsigned int base = 0; + uint32_t status_reg; + + base = uart_board_param.uart_dm_base; + + if (data == NULL) + return MSM_BOOT_UART_DM_E_INVAL; + + status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base)); + + /* Check for DM_RXSTALE for RX transfer to finish */ + while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) { + status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base)); + if (!wait) + return MSM_BOOT_UART_DM_E_RX_NOT_READY; + } + + /* Check for Overrun error. We'll just reset Error Status */ + if (readl_i(MSM_BOOT_UART_DM_SR(base)) & + MSM_BOOT_UART_DM_SR_UART_OVERRUN) { + writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, + MSM_BOOT_UART_DM_CR(base)); + total_rx_data = rx_data_read = 0; + msm_boot_uart_dm_init(base); + return MSM_BOOT_UART_DM_E_RX_NOT_READY; + } + + /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */ + if (total_rx_data == 0) + total_rx_data = readl_i(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base)); + + /* Data available in FIFO; read a word. */ + *data = readl_i(MSM_BOOT_UART_DM_RF(base, 0)); + + /* WAR for http://prism/CR/548280 */ + if (*data == 0) { + return MSM_BOOT_UART_DM_E_RX_NOT_READY; + } + + /* increment the total count of chars we've read so far */ + rx_data_read += FIFO_DATA_SIZE; + + /* actual count of valid data in word */ + *count = ((total_rx_data < rx_data_read) ? + (FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) : + FIFO_DATA_SIZE); + + /* If there are still data left in FIFO we'll read them before + * initializing RX Transfer again + */ + if (rx_data_read < total_rx_data) + return MSM_BOOT_UART_DM_E_SUCCESS; + + msm_boot_uart_dm_init_rx_transfer(base); + total_rx_data = rx_data_read = 0; + + return MSM_BOOT_UART_DM_E_SUCCESS; +} + +void uart_tx_byte(unsigned char data) +{ + int num_of_chars = 1; + unsigned tx_data = 0; + unsigned int base = uart_board_param.uart_dm_base; + + /* Add CR to every LF. */ + if (data == '\n') { + num_of_chars++; + tx_data = '\r' | ('\n' << 8); + } else { + tx_data = data; + } + + /* Wait until transmit FIFO is empty. */ + while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) & + MSM_BOOT_UART_DM_SR_TXEMT)) + udelay(1); + /* + * TX FIFO is ready to accept new character(s). First write number of + * characters to be transmitted. + */ + writel_i(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base)); + + /* And now write the character(s) */ + writel_i(tx_data, MSM_BOOT_UART_DM_TF(base, 0)); +} + +/* + * msm_boot_uart_dm_reset - resets UART controller + * @base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_reset(unsigned int base) +{ + writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, + MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base)); + + return MSM_BOOT_UART_DM_E_SUCCESS; +} + +/* + * msm_boot_uart_dm_init - initilaizes UART controller + * @uart_dm_base: UART controller base address + */ +static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base) +{ + /* Configure UART mode registers MR1 and MR2 */ + /* Hardware flow control isn't supported */ + writel_i(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base)); + + /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */ + writel_i(MSM_BOOT_UART_DM_8_N_1_MODE, + MSM_BOOT_UART_DM_MR2(uart_dm_base)); + + /* Configure Interrupt Mask register IMR */ + writel_i(MSM_BOOT_UART_DM_IMR_ENABLED, + MSM_BOOT_UART_DM_IMR(uart_dm_base)); + + /* + * Configure Tx and Rx watermarks configuration registers + * TX watermark value is set to 0 - interrupt is generated when + * FIFO level is less than or equal to 0 + */ + writel_i(MSM_BOOT_UART_DM_TFW_VALUE, + MSM_BOOT_UART_DM_TFWR(uart_dm_base)); + + /* RX watermark value */ + writel_i(MSM_BOOT_UART_DM_RFW_VALUE, + MSM_BOOT_UART_DM_RFWR(uart_dm_base)); + + /* Configure Interrupt Programming Register */ + /* Set initial Stale timeout value */ + writel_i(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB, + MSM_BOOT_UART_DM_IPR(uart_dm_base)); + + /* Configure IRDA if required */ + /* Disabling IRDA mode */ + writel_i(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base)); + + /* Configure hunt character value in HCR register */ + /* Keep it in reset state */ + writel_i(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base)); + + /* + * Configure Rx FIFO base address + * Both TX/RX shares same SRAM and default is half-n-half. + * Sticking with default value now. + * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries). + * We have found RAM_ADDR_WIDTH = 0x7f + */ + + /* Issue soft reset command */ + msm_boot_uart_dm_reset(uart_dm_base); + + /* Enable/Disable Rx/Tx DM interfaces */ + /* Data Mover not currently utilized. */ + writel_i(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base)); + + /* Enable transmitter */ + writel_i(MSM_BOOT_UART_DM_CR_TX_ENABLE, + MSM_BOOT_UART_DM_CR(uart_dm_base)); + + /* Initialize Receive Path */ + msm_boot_uart_dm_init_rx_transfer(uart_dm_base); + + return 0; +} + +/** + * uart_init - initializes UART + * + * Initializes clocks, GPIO and UART controller. + */ +void uart_init(void) +{ + unsigned int dm_base, gsbi_base; + + dm_base = uart_board_param.uart_dm_base; + gsbi_base = uart_board_param.uart_gsbi_base; + ipq_configure_gpio(uart_board_param.dbg_uart_gpio, + NO_OF_DBG_UART_GPIOS); + + /* Configure the uart clock */ + uart_clock_config(uart_board_param.uart_gsbi, + uart_board_param.mnd_value.m_value, + uart_board_param.mnd_value.n_value, + uart_board_param.mnd_value.d_value, + 0); + + writel_i(GSBI_PROTOCOL_CODE_I2C_UART << + GSBI_CTRL_REG_PROTOCOL_CODE_S, + GSBI_CTRL_REG(gsbi_base)); + writel_i(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(dm_base)); + + /* Intialize UART_DM */ + msm_boot_uart_dm_init(dm_base); +} + +uint32_t uartmem_getbaseaddr(void) +{ + return uart_board_param.uart_dm_base; +} + +/** + * uart_tx_flush - transmits a string of data + * @s: string to transmit + */ +void uart_tx_flush(void) +{ + unsigned int base = uart_board_param.uart_dm_base; + + while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) & + MSM_BOOT_UART_DM_SR_TXEMT)) + ; +} + +/** + * uart_can_rx_byte - checks if data available for reading + * + * Returns 1 if data available, 0 otherwise + */ +int uart_can_rx_byte(void) +{ + /* Return if data is already read */ + if (valid_data) + return 1; + + /* Read data from the FIFO */ + if (msm_boot_uart_dm_read(&word, &valid_data, 0) != + MSM_BOOT_UART_DM_E_SUCCESS) + return 0; + + return 1; +} + +/** + * ipq806x_serial_getc - reads a character + * + * Returns the character read from serial port. + */ +uint8_t uart_rx_byte(void) +{ + uint8_t byte; + + while (!uart_can_rx_byte()) { + /* wait for incoming data */ + } + + byte = (uint8_t)(word & 0xff); + word = word >> 8; + valid_data--; + + return byte; +} diff --git a/src/soc/qualcomm/ipq806x/usb.c b/src/soc/qualcomm/ipq806x/usb.c new file mode 100644 index 0000000000..fb89373953 --- /dev/null +++ b/src/soc/qualcomm/ipq806x/usb.c @@ -0,0 +1,226 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define CRPORT_TX_OVRD_DRV_LO 0x1002 +#define CRPORT_RX_OVRD_IN_HI 0x1006 +#define CRPORT_TX_ALT_BLOCK 0x102d + +static u32 * const tcsr_usb_sel = (void *)0x1a4000b0; + +struct usb_qc_phy { + u32 ipcat; + u32 ctrl; + u32 general_cfg; + u32 ram1; + u32 hs_phy_ctrl; + u32 param_ovrd; + u32 chrg_det_ctrl; + u32 chrg_det_output; + u32 alt_irq_en; + u32 hs_phy_irq_stat; + u32 cgctl; + u32 dbg_bus; + u32 ss_phy_ctrl; + u32 ss_phy_param1; + u32 ss_phy_param2; + u32 crport_data_in; + u32 crport_data_out; + u32 crport_cap_addr; + u32 crport_cap_data; + u32 crport_ack_read; + u32 crport_ack_write; +}; +check_member(usb_qc_phy, crport_ack_write, 0x50); + +static struct usb_qc_phy * const usb_host1_phy = (void *)USB_HOST1_PHY_BASE; +static struct usb_qc_phy * const usb_host2_phy = (void *)USB_HOST2_PHY_BASE; + +struct usb_dwc3 { + u32 sbuscfg0; + u32 sbuscfg1; + u32 txthrcfg; + u32 rxthrcfg; + u32 ctl; + u32 evten; + u32 sts; + u8 reserved0[4]; + u32 snpsid; + u32 gpio; + u32 uid; + u32 uctl; + u64 buserraddr; + u64 prtbimap; + u8 reserved1[32]; + u32 dbgfifospace; + u32 dbgltssm; + u32 dbglnmcc; + u32 dbgbmu; + u32 dbglspmux; + u32 dbglsp; + u32 dbgepinfo0; + u32 dbgepinfo1; + u64 prtbimap_hs; + u64 prtbimap_fs; + u8 reserved2[112]; + u32 usb2phycfg; + u8 reserved3[60]; + u32 usb2i2cctl; + u8 reserved4[60]; + u32 usb2phyacc; + u8 reserved5[60]; + u32 usb3pipectl; + u8 reserved6[60]; +}; +check_member(usb_dwc3, usb3pipectl, 0x1c0); + +static struct usb_dwc3 * const usb_host1_dwc3 = (void *)USB_HOST1_DWC3_BASE; +static struct usb_dwc3 * const usb_host2_dwc3 = (void *)USB_HOST2_DWC3_BASE; + +static void setup_dwc3(struct usb_dwc3 *dwc3) +{ + write32(0x1 << 31 | /* assert PHY soft reset */ + 0x1 << 25 | /* (default) U1/U2 exit fail -> recovery? */ + 0x1 << 24 | /* (default) activate PHY low power states */ + 0x1 << 19 | /* (default) PHY low power delay value */ + 0x1 << 18 | /* (default) activate PHY low power delay */ + 0x1 << 1 | /* (default) Tx deemphasis value */ + 0x1 << 0 | /* (default) elastic buffer mode */ + 0, &dwc3->usb3pipectl); + + write32(0x1 << 31 | /* assert PHY soft reset */ + 0x9 << 10 | /* (default) PHY clock turnaround 8-bit UTMI+ */ + 0x1 << 8 | /* (default) enable PHY sleep in L1 */ + 0x1 << 6 | /* (default) enable PHY suspend */ + 0, &dwc3->usb2phycfg); + + write32(0x2 << 19 | /* (default) suspend clock scaling */ + 0x1 << 16 | /* retry SS three times before HS downgrade */ + 0x1 << 12 | /* port capability HOST */ + 0x1 << 11 | /* assert core soft reset */ + 0x1 << 10 | /* (default) sync ITP to refclk */ + 0x1 << 2 | /* U2 exit after 8us LFPS (instead of 248ns) */ + 0, &dwc3->ctl); + + write32(0x32 << 22 | /* (default) reference clock period in ns */ + 0x1 << 15 | /* (default) XHCI compliant device addressing */ + 0x10 << 0 | /* (default) devices time out after 32us */ + 0, &dwc3->uctl); + + udelay(5); + + clrbits_le32(&dwc3->ctl, 0x1 << 11); /* deassert core soft reset */ + clrbits_le32(&dwc3->usb2phycfg, 0x1 << 31); /* PHY soft reset */ + clrbits_le32(&dwc3->usb3pipectl, 0x1 << 31); /* PHY soft reset */ +} + +static void setup_phy(struct usb_qc_phy *phy) +{ + write32(0x1 << 24 | /* Indicate VBUS power present */ + 0x1 << 8 | /* Enable USB3 ref clock to prescaler */ + 0x1 << 7 | /* assert SS PHY reset */ + 0x19 << 0 | /* (default) reference clock multiplier */ + 0, &phy->ss_phy_ctrl); + + write32(0x1 << 26 | /* (default) unclamp DPSE/DMSE VLS */ + 0x1 << 25 | /* (default) select freeclk for utmi_clk */ + 0x1 << 24 | /* (default) unclamp DMSE VLS */ + 0x1 << 21 | /* (default) enable UTMI clock */ + 0x1 << 20 | /* set OTG VBUS as valid */ + 0x1 << 18 | /* use ref clock from core */ + 0x1 << 17 | /* (default) unclamp DPSE VLS */ + 0x1 << 11 | /* force xo/bias/pll to stay on in suspend */ + 0x1 << 9 | /* (default) unclamp IDHV */ + 0x1 << 8 | /* (default) unclamp VLS (again???) */ + 0x1 << 7 | /* (default) unclamp HV VLS */ + 0x7 << 4 | /* select frequency (no idea which one) */ + 0x1 << 1 | /* (default) "retention enable" */ + 0, &phy->hs_phy_ctrl); + + write32(0x6e << 20 | /* full TX swing amplitude */ + 0x20 << 14 | /* (default) 6dB TX deemphasis */ + 0x17 << 8 | /* 3.5dB TX deemphasis */ + 0x9 << 3 | /* (default) LoS detector level */ + 0, &phy->ss_phy_param1); + + write32(0x1 << 2, &phy->general_cfg); /* set XHCI 1.00 compliance */ + + udelay(5); + clrbits_le32(&phy->ss_phy_ctrl, 0x1 << 7); /* deassert SS PHY reset */ +} + +static void crport_handshake(void *capture_reg, void *acknowledge_bit, u32 data) +{ + int usec = 100; + + if (capture_reg) + write32(data, capture_reg); + + write32(0x1 << 0, acknowledge_bit); + while (read32(acknowledge_bit) && --usec) + udelay(1); + + if (!usec) + printk(BIOS_ERR, "CRPORT handshake timed out (0x%08x)\n", data); +} + +static void crport_write(struct usb_qc_phy *phy, u16 addr, u16 data) +{ + crport_handshake(&phy->crport_data_in, &phy->crport_cap_addr, addr); + crport_handshake(&phy->crport_data_in, &phy->crport_cap_data, data); + crport_handshake(NULL, &phy->crport_ack_write, 0); +} + +static void tune_phy(struct usb_qc_phy *phy) +{ + crport_write(phy, CRPORT_RX_OVRD_IN_HI, + 0x1 << 11 | /* Set RX_EQ override? */ + 0x4 << 8 | /* Set RX_EQ to 4? */ + 0x1 << 7); /* Enable RX_EQ override */ + crport_write(phy, CRPORT_TX_OVRD_DRV_LO, + 0x1 << 14 | /* Enable amplitude (override?) */ + 0x17 << 7 | /* Set TX deemphasis to 23 */ + 0x6e << 0); /* Set amplitude to 110 */ + crport_write(phy, CRPORT_TX_ALT_BLOCK, + 0x1 << 7); /* ALT block? ("partial RX reset") */ +} + +void setup_usb_host1(void) +{ + printk(BIOS_INFO, "Setting up USB HOST1 controller...\n"); + setbits_le32(tcsr_usb_sel, 1 << 0); /* Select DWC3 controller */ + setup_phy(usb_host1_phy); + setup_dwc3(usb_host1_dwc3); + tune_phy(usb_host1_phy); +} + +void setup_usb_host2(void) +{ + printk(BIOS_INFO, "Setting up USB HOST2 controller...\n"); + setbits_le32(tcsr_usb_sel, 1 << 1); /* Select DWC3 controller */ + setup_phy(usb_host2_phy); + setup_dwc3(usb_host2_dwc3); + tune_phy(usb_host2_phy); +} diff --git a/src/soc/rockchip/Kconfig b/src/soc/rockchip/Kconfig new file mode 100644 index 0000000000..b041f89f8b --- /dev/null +++ b/src/soc/rockchip/Kconfig @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +source src/soc/rockchip/rk3288/Kconfig diff --git a/src/soc/rockchip/Makefile.inc b/src/soc/rockchip/Makefile.inc new file mode 100644 index 0000000000..aa67f5c1cf --- /dev/null +++ b/src/soc/rockchip/Makefile.inc @@ -0,0 +1,20 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +subdirs-$(CONFIG_SOC_ROCKCHIP_RK3288) += rk3288 diff --git a/src/soc/rockchip/rk3288/Kconfig b/src/soc/rockchip/rk3288/Kconfig new file mode 100644 index 0000000000..051a2e6fdb --- /dev/null +++ b/src/soc/rockchip/rk3288/Kconfig @@ -0,0 +1,55 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config SOC_ROCKCHIP_RK3288 + bool + default n + select CPU_HAS_BOOTBLOCK_INIT + select HAVE_MONOTONIC_TIMER + select GENERIC_UDELAY + select HAVE_UART_SPECIAL + select EARLY_CONSOLE + select DYNAMIC_CBMEM + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_VERSTAGE_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + select HAVE_UART_MEMORY_MAPPED + select BOOTBLOCK_CONSOLE + select HAS_PRECBMEM_TIMESTAMP_REGION + select GENERIC_GPIO_LIB + +if SOC_ROCKCHIP_RK3288 + +config BOOTBLOCK_CPU_INIT + string + default "soc/rockchip/rk3288/bootblock.c" + +config COMPRESS_RAMSTAGE + bool "Compress ramstage with LZMA" + default n + help + The ramstage is loaded from code running in uncached SRAM, you + probably don't want LZMA running on that. + +config PMIC_BUS + int + default -1 + +endif diff --git a/src/soc/rockchip/rk3288/Makefile.inc b/src/soc/rockchip/rk3288/Makefile.inc new file mode 100644 index 0000000000..2ce1352da3 --- /dev/null +++ b/src/soc/rockchip/rk3288/Makefile.inc @@ -0,0 +1,80 @@ +## +## This file is part of the coreboot project. +## +## Copyright 2014 Rockchip Inc. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +IDBTOOL = util/rockchip/make_idb.py + +bootblock-y += bootblock.c +bootblock-y += cbmem.c +ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) +bootblock-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif +bootblock-y += timer.c +bootblock-y += clock.c +bootblock-y += spi.c +bootblock-y += gpio.c +bootblock-y += i2c.c +bootblock-y += rk808.c + +verstage-y += spi.c +verstage-y += timer.c +verstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +verstage-y += gpio.c +verstage-y += clock.c +verstage-y += crypto.c +verstage-y += i2c.c + +romstage-y += cbmem.c +ifeq ($(CONFIG_EARLY_CONSOLE),y) +romstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +endif +romstage-y += timer.c +romstage-y += i2c.c +romstage-y += clock.c +romstage-y += gpio.c +romstage-y += spi.c +romstage-y += sdram.c +romstage-y += rk808.c +romstage-y += pwm.c +romstage-y += tsadc.c + +ramstage-y += soc.c +ramstage-y += cbmem.c +ramstage-y += timer.c +ramstage-y += i2c.c +ramstage-y += clock.c +ramstage-y += spi.c +ramstage-y += sdram.c +ramstage-y += gpio.c +ramstage-y += rk808.c +ramstage-y += pwm.c +ramstage-y += vop.c +ramstage-y += edp.c +ramstage-y += hdmi.c +ramstage-y += display.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c + +INCLUDES += -Isrc/soc/rockchip/rk3288/include/ + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin + @printf "Generating: $(subst $(obj)/,,$(@))\n" + @mkdir -p $(dir $@) + @$(IDBTOOL) --from=$< --to=$@ --enable-align diff --git a/src/soc/rockchip/rk3288/bootblock.c b/src/soc/rockchip/rk3288/bootblock.c new file mode 100644 index 0000000000..13498adec6 --- /dev/null +++ b/src/soc/rockchip/rk3288/bootblock.c @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void bootblock_soc_init(void) +{ + rkclk_init(); + + mmu_init(); + /* Start with a clean slate. */ + mmu_config_range(0, 4096, DCACHE_OFF); + /* SRAM is tightly wedged between registers, need to use subtables. Map + * write-through as equivalent for non-cacheable without XN on A17. */ + mmu_config_range_kb((uintptr_t)_sram/KiB, + _sram_size/KiB, DCACHE_WRITETHROUGH); + dcache_mmu_enable(); + + rkclk_configure_crypto(148500*KHz); +} diff --git a/src/soc/rockchip/rk3288/cbmem.c b/src/soc/rockchip/rk3288/cbmem.c new file mode 100644 index 0000000000..38ea365469 --- /dev/null +++ b/src/soc/rockchip/rk3288/cbmem.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void *cbmem_top(void) +{ + return _dram + sdram_size_mb()*MiB; +} diff --git a/src/soc/rockchip/rk3288/chip.h b/src/soc/rockchip/rk3288/chip.h new file mode 100644 index 0000000000..9bdc5e98f5 --- /dev/null +++ b/src/soc/rockchip/rk3288/chip.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_CHIP_H__ +#define __SOC_ROCKCHIP_RK3288_CHIP_H__ + +#include +#include /* for vop_modes enum used in devicetree.cb */ + +struct soc_rockchip_rk3288_config { + u32 vop_id; + gpio_t lcd_bl_pwm_gpio; + gpio_t lcd_bl_en_gpio; + u32 bl_power_on_udelay; + u32 bl_pwm_to_enable_udelay; + u32 framebuffer_bits_per_pixel; + u32 vop_mode; +}; + +#endif /* __SOC_ROCKCHIP_RK3288_CHIP_H__ */ diff --git a/src/soc/rockchip/rk3288/clock.c b/src/soc/rockchip/rk3288/clock.c new file mode 100644 index 0000000000..1bd8ab00e8 --- /dev/null +++ b/src/soc/rockchip/rk3288/clock.c @@ -0,0 +1,689 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pll_div { + u32 nr; + u32 nf; + u32 no; +}; + +struct rk3288_cru_reg { + u32 cru_apll_con[4]; + u32 cru_dpll_con[4]; + u32 cru_cpll_con[4]; + u32 cru_gpll_con[4]; + u32 cru_npll_con[4]; + u32 cru_mode_con; + u32 reserved0[3]; + u32 cru_clksel_con[43]; + u32 reserved1[21]; + u32 cru_clkgate_con[19]; + u32 reserved2; + u32 cru_glb_srst_fst_value; + u32 cru_glb_srst_snd_value; + u32 cru_softrst_con[12]; + u32 cru_misc_con; + u32 cru_glb_cnt_th; + u32 cru_glb_rst_con; + u32 reserved3; + u32 cru_glb_rst_st; + u32 reserved4; + u32 cru_sdmmc_con[2]; + u32 cru_sdio0_con[2]; + u32 cru_sdio1_con[2]; + u32 cru_emmc_con[2]; +}; +check_member(rk3288_cru_reg, cru_emmc_con[1], 0x021c); + +static struct rk3288_cru_reg * const cru_ptr = (void *)CRU_BASE; + +#define PLL_DIVISORS(hz, _nr, _no) {\ + .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\ + _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ + (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\ + "divisors on line " STRINGIFY(__LINE__)); + +/* Keep divisors as low as possible to reduce jitter and power usage. */ +static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2); +static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2); + +/* See linux/drivers/clk/rockchip/clk-rk3288.c for more APLL combinations */ +static const struct pll_div apll_1800_cfg = PLL_DIVISORS(1800*MHz, 1, 1); +static const struct pll_div apll_1416_cfg = PLL_DIVISORS(1416*MHz, 1, 1); +static const struct pll_div apll_600_cfg = PLL_DIVISORS(600*MHz, 1, 2); +static const struct pll_div *apll_cfgs[] = { + [APLL_1800_MHZ] = &apll_1800_cfg, + [APLL_1416_MHZ] = &apll_1416_cfg, + [APLL_600_MHZ] = &apll_600_cfg, +}; + +/*******************PLL CON0 BITS***************************/ +#define PLL_OD_MSK (0x0F) + +#define PLL_NR_MSK (0x3F << 8) +#define PLL_NR_SHIFT (8) + +/*******************PLL CON1 BITS***************************/ +#define PLL_NF_MSK (0x1FFF) + +/*******************PLL CON2 BITS***************************/ +#define PLL_BWADJ_MSK (0x0FFF) + +/*******************PLL CON3 BITS***************************/ +#define PLL_RESET_MSK (1 << 5) +#define PLL_RESET (1 << 5) +#define PLL_RESET_RESUME (0 << 5) + +/*******************CLKSEL0 BITS***************************/ +/* core clk pll sel: amr or general */ +#define CORE_SEL_PLL_MSK (1 << 15) +#define CORE_SEL_APLL (0 << 15) +#define CORE_SEL_GPLL (1 << 15) + +/* a12 core clock div: clk_core = clk_src / (div_con + 1) */ +#define A12_DIV_SHIFT (8) +#define A12_DIV_MSK (0x1F << 8) + +/* mp core axi clock div: clk = clk_src / (div_con + 1) */ +#define MP_DIV_SHIFT (4) +#define MP_DIV_MSK (0xF << 4) + +/* m0 core axi clock div: clk = clk_src / (div_con + 1) */ +#define M0_DIV_MSK (0xF) + +/*******************CLKSEL1 BITS***************************/ +/* pd bus clk pll sel: codec or general */ +#define PD_BUS_SEL_PLL_MSK (1 << 15) +#define PD_BUS_SEL_CPLL (0 << 15) +#define PD_BUS_SEL_GPLL (1 << 15) + +/* pd bus pclk div: + * pclk = pd_bus_aclk /(div + 1) + */ +#define PD_BUS_PCLK_DIV_SHIFT (12) +#define PD_BUS_PCLK_DIV_MSK (0x7 << 12) + +/* pd bus hclk div: + * aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 + */ +#define PD_BUS_HCLK_DIV_SHIFT (8) +#define PD_BUS_HCLK_DIV_MSK (0x3 << 8) + +/* pd bus aclk div: + * pd_bus_aclk = pd_bus_src_clk /(div0 * div1) + */ +#define PD_BUS_ACLK_DIV0_SHIFT (3) +#define PD_BUS_ACLK_DIV0_MASK (0x1f << 3) +#define PD_BUS_ACLK_DIV1_SHIFT (0) +#define PD_BUS_ACLK_DIV1_MASK (0x7 << 0) + +/*******************CLKSEL10 BITS***************************/ +/* peripheral bus clk pll sel: codec or general */ +#define PERI_SEL_PLL_MSK (1 << 15) +#define PERI_SEL_CPLL (0 << 15) +#define PERI_SEL_GPLL (1 << 15) + +/* peripheral bus pclk div: + * aclk_bus: pclk_bus = 1:1 or 2:1 or 4:1 or 8:1 + */ +#define PERI_PCLK_DIV_SHIFT (12) +#define PERI_PCLK_DIV_MSK (0x7 << 12) + +/* peripheral bus hclk div: + * aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 + */ +#define PERI_HCLK_DIV_SHIFT (8) +#define PERI_HCLK_DIV_MSK (0x3 << 8) + +/* peripheral bus aclk div: + * aclk_periph = + * periph_clk_src / (peri_aclk_div_con + 1) + */ +#define PERI_ACLK_DIV_SHIFT (0x0) +#define PERI_ACLK_DIV_MSK (0x1F) + +/*******************CLKSEL37 BITS***************************/ +#define L2_DIV_MSK (0x7) + +#define ATCLK_DIV_MSK (0x1F << 4) +#define ATCLK_DIV_SHIFT (4) + +#define PCLK_DBG_DIV_MSK (0x1F << 9) +#define PCLK_DBG_DIV_SHIFT (9) + +#define APLL_MODE_MSK (0x3) +#define APLL_MODE_SLOW (0) +#define APLL_MODE_NORM (1) + +#define DPLL_MODE_MSK (0x3 << 4) +#define DPLL_MODE_SLOW (0 << 4) +#define DPLL_MODE_NORM (1 << 4) + +#define CPLL_MODE_MSK (0x3 << 8) +#define CPLL_MODE_SLOW (0 << 8) +#define CPLL_MODE_NORM (1 << 8) + +#define GPLL_MODE_MSK (0x3 << 12) +#define GPLL_MODE_SLOW (0 << 12) +#define GPLL_MODE_NORM (1 << 12) + +#define NPLL_MODE_MSK (0x3 << 14) +#define NPLL_MODE_SLOW (0 << 14) +#define NPLL_MODE_NORM (1 << 14) + +#define SOCSTS_DPLL_LOCK (1 << 5) +#define SOCSTS_APLL_LOCK (1 << 6) +#define SOCSTS_CPLL_LOCK (1 << 7) +#define SOCSTS_GPLL_LOCK (1 << 8) +#define SOCSTS_NPLL_LOCK (1 << 9) + +#define VCO_MAX_KHZ (2200 * (MHz/KHz)) +#define VCO_MIN_KHZ (440 * (MHz/KHz)) +#define OUTPUT_MAX_KHZ (2200 * (MHz/KHz)) +#define OUTPUT_MIN_KHZ 27500 +#define FREF_MAX_KHZ (2200 * (MHz/KHz)) +#define FREF_MIN_KHZ 269 + +static int rkclk_set_pll(u32 *pll_con, const struct pll_div *div) +{ + /* All PLLs have same VCO and output frequency range restrictions. */ + u32 vco_khz = OSC_HZ/KHz * div->nf / div->nr; + u32 output_khz = vco_khz / div->no; + + printk(BIOS_DEBUG, "Configuring PLL at %p with NF = %d, NR = %d and " + "NO = %d (VCO = %uKHz, output = %uKHz)\n", + pll_con, div->nf, div->nr, div->no, vco_khz, output_khz); + assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ && + output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ && + (div->no == 1 || !(div->no % 2))); + + /* enter rest */ + writel(RK_SETBITS(PLL_RESET_MSK), &pll_con[3]); + + writel(RK_CLRSETBITS(PLL_NR_MSK, (div->nr - 1) << PLL_NR_SHIFT) + | RK_CLRSETBITS(PLL_OD_MSK, (div->no - 1)), &pll_con[0]); + + writel(RK_CLRSETBITS(PLL_NF_MSK, (div->nf - 1)), &pll_con[1]); + + writel(RK_CLRSETBITS(PLL_BWADJ_MSK, ((div->nf >> 1) - 1)), &pll_con[2]); + + udelay(10); + + /* return form rest */ + writel(RK_CLRBITS(PLL_RESET_MSK), &pll_con[3]); + + return 0; +} + +/* + TODO: + it should be replaced by lib.h function + 'unsigned long log2(unsigned long x)' +*/ +static unsigned int log2(unsigned int value) +{ + unsigned int div = 0; + + while (value != 1) { + div++; + value = ALIGN_UP(value, 2) / 2; + } + return div; +} + +void rkclk_init(void) +{ + u32 aclk_div; + u32 hclk_div; + u32 pclk_div; + + /* pll enter slow-mode */ + writel(RK_CLRSETBITS(GPLL_MODE_MSK, GPLL_MODE_SLOW) + | RK_CLRSETBITS(CPLL_MODE_MSK, CPLL_MODE_SLOW), + &cru_ptr->cru_mode_con); + + /* init pll */ + rkclk_set_pll(&cru_ptr->cru_gpll_con[0], &gpll_init_cfg); + rkclk_set_pll(&cru_ptr->cru_cpll_con[0], &cpll_init_cfg); + + /* waiting for pll lock */ + while (1) { + if ((readl(&rk3288_grf->soc_status[1]) + & (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) + == (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) + break; + udelay(1); + } + + /* + * pd_bus clock pll source selection and + * set up dependent divisors for PCLK/HCLK and ACLK clocks. + */ + aclk_div = GPLL_HZ / PD_BUS_ACLK_HZ - 1; + assert((aclk_div + 1) * PD_BUS_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f); + hclk_div = PD_BUS_ACLK_HZ / PD_BUS_HCLK_HZ - 1; + assert((hclk_div + 1) * PD_BUS_HCLK_HZ == + PD_BUS_ACLK_HZ && (hclk_div < 0x4) && (hclk_div != 0x2)); + + pclk_div = PD_BUS_ACLK_HZ / PD_BUS_PCLK_HZ - 1; + assert((pclk_div + 1) * PD_BUS_PCLK_HZ == + PD_BUS_ACLK_HZ && pclk_div < 0x7); + + writel(RK_SETBITS(PD_BUS_SEL_GPLL) + | RK_CLRSETBITS(PD_BUS_PCLK_DIV_MSK, + pclk_div << PD_BUS_PCLK_DIV_SHIFT) + | RK_CLRSETBITS(PD_BUS_HCLK_DIV_MSK, + hclk_div << PD_BUS_HCLK_DIV_SHIFT) + | RK_CLRSETBITS(PD_BUS_ACLK_DIV0_MASK, + aclk_div << PD_BUS_ACLK_DIV0_SHIFT) + | RK_CLRSETBITS(PD_BUS_ACLK_DIV1_MASK, 0 << 0), + &cru_ptr->cru_clksel_con[1]); + + /* + * peri clock pll source selection and + * set up dependent divisors for PCLK/HCLK and ACLK clocks. + */ + aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1; + assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f); + + hclk_div = log2(PERI_ACLK_HZ / PERI_HCLK_HZ); + assert((1 << hclk_div) * PERI_HCLK_HZ == + PERI_ACLK_HZ && (hclk_div < 0x4)); + + pclk_div = log2(PERI_ACLK_HZ / PERI_PCLK_HZ); + assert((1 << pclk_div) * PERI_PCLK_HZ == + PERI_ACLK_HZ && (pclk_div < 0x4)); + + writel(RK_SETBITS(PERI_SEL_GPLL) + | RK_CLRSETBITS(PERI_PCLK_DIV_MSK, + pclk_div << PERI_PCLK_DIV_SHIFT) + | RK_CLRSETBITS(PERI_HCLK_DIV_MSK, + hclk_div << PERI_HCLK_DIV_SHIFT) + | RK_CLRSETBITS(PERI_ACLK_DIV_MSK, + aclk_div << PERI_ACLK_DIV_SHIFT), + &cru_ptr->cru_clksel_con[10]); + + /* PLL enter normal-mode */ + writel(RK_CLRSETBITS(GPLL_MODE_MSK, GPLL_MODE_NORM) + | RK_CLRSETBITS(CPLL_MODE_MSK, CPLL_MODE_NORM), + &cru_ptr->cru_mode_con); + +} + +void rkclk_configure_cpu(enum apll_frequencies apll_freq) +{ + /* pll enter slow-mode */ + writel(RK_CLRSETBITS(APLL_MODE_MSK, APLL_MODE_SLOW), + &cru_ptr->cru_mode_con); + + rkclk_set_pll(&cru_ptr->cru_apll_con[0], apll_cfgs[apll_freq]); + + /* waiting for pll lock */ + while (1) { + if (readl(&rk3288_grf->soc_status[1]) & SOCSTS_APLL_LOCK) + break; + udelay(1); + } + + /* + * core clock pll source selection and + * set up dependent divisors for MPAXI/M0AXI and ARM clocks. + * core clock select apll, apll clk = 1800MHz + * arm clk = 1800MHz, mpclk = 450MHz, m0clk = 900MHz + */ + writel(RK_CLRBITS(CORE_SEL_PLL_MSK) + | RK_CLRSETBITS(A12_DIV_MSK, 0 << A12_DIV_SHIFT) + | RK_CLRSETBITS(MP_DIV_MSK, 3 << MP_DIV_SHIFT) + | RK_CLRSETBITS(M0_DIV_MSK, 1 << 0), + &cru_ptr->cru_clksel_con[0]); + + /* + * set up dependent divisors for L2RAM/ATCLK and PCLK clocks. + * l2ramclk = 900MHz, atclk = 450MHz, pclk_dbg = 450MHz + */ + writel(RK_CLRSETBITS(L2_DIV_MSK, 1 << 0) + | RK_CLRSETBITS(ATCLK_DIV_MSK, (3 << ATCLK_DIV_SHIFT)) + | RK_CLRSETBITS(PCLK_DBG_DIV_MSK, (3 << PCLK_DBG_DIV_SHIFT)), + &cru_ptr->cru_clksel_con[37]); + + /* PLL enter normal-mode */ + writel(RK_CLRSETBITS(APLL_MODE_MSK, APLL_MODE_NORM), + &cru_ptr->cru_mode_con); +} + +void rkclk_configure_ddr(unsigned int hz) +{ + struct pll_div dpll_cfg; + + switch (hz) { + case 300*MHz: + dpll_cfg = (struct pll_div){.nf = 50, .nr = 2, .no = 2}; + break; + case 533*MHz: /* actually 533.3P MHz */ + dpll_cfg = (struct pll_div){.nf = 400, .nr = 9, .no = 2}; + break; + case 666*MHz: /* actually 666.6P MHz */ + dpll_cfg = (struct pll_div){.nf = 500, .nr = 9, .no = 2}; + break; + case 800*MHz: + dpll_cfg = (struct pll_div){.nf = 100, .nr = 3, .no = 1}; + break; + default: + die("Unsupported SDRAM frequency, add to clock.c!"); + } + + /* pll enter slow-mode */ + writel(RK_CLRSETBITS(DPLL_MODE_MSK, DPLL_MODE_SLOW), + &cru_ptr->cru_mode_con); + + rkclk_set_pll(&cru_ptr->cru_dpll_con[0], &dpll_cfg); + + /* waiting for pll lock */ + while (1) { + if (readl(&rk3288_grf->soc_status[1]) & SOCSTS_DPLL_LOCK) + break; + udelay(1); + } + + /* PLL enter normal-mode */ + writel(RK_CLRSETBITS(DPLL_MODE_MSK, DPLL_MODE_NORM), + &cru_ptr->cru_mode_con); +} + +void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy) +{ + u32 phy_ctl_srstn_shift = 4 + 5 * ch; + u32 ctl_psrstn_shift = 3 + 5 * ch; + u32 ctl_srstn_shift = 2 + 5 * ch; + u32 phy_psrstn_shift = 1 + 5 * ch; + u32 phy_srstn_shift = 5 * ch; + + writel(RK_CLRSETBITS(1 << phy_ctl_srstn_shift, + phy << phy_ctl_srstn_shift) + | RK_CLRSETBITS(1 << ctl_psrstn_shift, ctl << ctl_psrstn_shift) + | RK_CLRSETBITS(1 << ctl_srstn_shift, ctl << ctl_srstn_shift) + | RK_CLRSETBITS(1 << phy_psrstn_shift, phy << phy_psrstn_shift) + | RK_CLRSETBITS(1 << phy_srstn_shift, phy << phy_srstn_shift), + &cru_ptr->cru_softrst_con[10]); +} + +void rkclk_ddr_phy_ctl_reset(u32 ch, u32 n) +{ + u32 phy_ctl_srstn_shift = 4 + 5 * ch; + + writel(RK_CLRSETBITS(1 << phy_ctl_srstn_shift, + n << phy_ctl_srstn_shift), + &cru_ptr->cru_softrst_con[10]); +} + +void rkclk_configure_spi(unsigned int bus, unsigned int hz) +{ + int src_clk_div = GPLL_HZ / hz; + + assert((src_clk_div - 1 < 127) && (src_clk_div * hz == GPLL_HZ)); + + switch (bus) { /*select gpll as spi src clk, and set div*/ + case 0: + writel(RK_CLRSETBITS(1 << 7 | 0x1f << 0, 1 << 7 + | (src_clk_div - 1) << 0), + &cru_ptr->cru_clksel_con[25]); + break; + case 1: + writel(RK_CLRSETBITS(1 << 15 | 0x1f << 8, 1 << 15 + | (src_clk_div - 1) << 8), + &cru_ptr->cru_clksel_con[25]); + break; + case 2: + writel(RK_CLRSETBITS(1 << 7 | 0x1f << 0, 1 << 7 + | (src_clk_div - 1) << 0), + &cru_ptr->cru_clksel_con[39]); + break; + default: + printk(BIOS_ERR, "do not support this spi bus\n"); + } +} + +static u32 clk_gcd(u32 a, u32 b) +{ + while (b != 0) { + int r = b; + b = a % b; + a = r; + } + return a; +} + +void rkclk_configure_i2s(unsigned int hz) +{ + int n, d; + int v; + + /* i2s source clock: gpll + i2s0_outclk_sel: clk_i2s + i2s0_clk_sel: divider ouput from fraction + i2s0_pll_div_con: 0*/ + writel(RK_CLRSETBITS(1 << 15 | 1 << 12 | 3 << 8 | 0x7f << 0 , + 1 << 15 | 0 << 12 | 1 << 8 | 0 << 0), + &cru_ptr->cru_clksel_con[4]); + + /* set frac divider */ + v = clk_gcd(GPLL_HZ, hz); + n = (GPLL_HZ / v) & (0xffff); + d = (hz / v) & (0xffff); + assert(hz == GPLL_HZ / n * d); + writel(d << 16 | n, &cru_ptr->cru_clksel_con[8]); +} + +void rkclk_configure_crypto(unsigned int hz) +{ + u32 div = PD_BUS_ACLK_HZ / hz; + + assert((div - 1 < 4) && (div * hz == PD_BUS_ACLK_HZ)); + assert(hz <= 150*MHz); /* Suggested max in TRM. */ + writel(RK_CLRSETBITS(0x3 << 6, (div - 1) << 6), + &cru_ptr->cru_clksel_con[26]); +} + +void rkclk_configure_tsadc(unsigned int hz) +{ + u32 div; + u32 src_clk = 32 * KHz; /* tsadc source clock is 32KHz*/ + + div = src_clk / hz; + assert((div - 1 < 64) && (div * hz == 32 * KHz)); + writel(RK_CLRSETBITS(0x3f << 0, (div - 1) << 0), + &cru_ptr->cru_clksel_con[2]); +} + +static int pll_para_config(u32 freq_hz, struct pll_div *div, u32 *ext_div) +{ + u32 ref_khz = OSC_HZ / KHz, nr, nf = 0; + u32 fref_khz; + u32 diff_khz, best_diff_khz; + const u32 max_nr = 1 << 6, max_nf = 1 << 12, max_no = 1 << 4; + u32 vco_khz; + u32 no = 1; + u32 freq_khz = freq_hz / KHz; + + if (!freq_hz) { + printk(BIOS_ERR, "%s: the frequency can not be 0 Hz\n", __func__); + return -1; + } + + no = div_round_up(VCO_MIN_KHZ, freq_khz); + if (ext_div) { + *ext_div = div_round_up(no, max_no); + no = div_round_up(no, *ext_div); + } + + /* only even divisors (and 1) are supported */ + if (no > 1) + no = div_round_up(no, 2) * 2; + + vco_khz = freq_khz * no; + if (ext_div) + vco_khz *= *ext_div; + + if (vco_khz < VCO_MIN_KHZ || vco_khz > VCO_MAX_KHZ || no > max_no) { + printk(BIOS_ERR, "%s: Cannot find out a supported VCO" + " for Frequency (%uHz).\n", __func__, freq_hz); + return -1; + } + + div->no = no; + + best_diff_khz = vco_khz; + for (nr = 1; nr < max_nr && best_diff_khz; nr++) { + fref_khz = ref_khz / nr; + if (fref_khz < FREF_MIN_KHZ) + break; + if (fref_khz > FREF_MAX_KHZ) + continue; + + nf = vco_khz / fref_khz; + if (nf >= max_nf) + continue; + diff_khz = vco_khz - nf * fref_khz; + if (nf + 1 < max_nf && diff_khz > fref_khz / 2) { + nf++; + diff_khz = fref_khz - diff_khz; + } + + if (diff_khz >= best_diff_khz) + continue; + + best_diff_khz = diff_khz; + div->nr = nr; + div->nf = nf; + } + + if (best_diff_khz > 4 * (MHz/KHz)) { + printk(BIOS_ERR, "%s: Failed to match output frequency %u, " + "difference is %u Hz,exceed 4MHZ\n", __func__, freq_hz, + best_diff_khz * KHz); + return -1; + } + + return 0; +} + +void rkclk_configure_edp(void) +{ + /* clk_edp_24M source: 24M */ + writel(RK_SETBITS(1 << 15), &cru_ptr->cru_clksel_con[28]); + + /* rst edp */ + writel(RK_SETBITS(1 << 15), &cru_ptr->cru_softrst_con[6]); + udelay(1); + writel(RK_CLRBITS(1 << 15), &cru_ptr->cru_softrst_con[6]); +} + +void rkclk_configure_hdmi(void) +{ + /* enable pclk hdmi ctrl */ + writel(RK_CLRBITS(1 << 9), &cru_ptr->cru_clkgate_con[16]); + + /* software reset hdmi */ + writel(RK_SETBITS(1 << 9), &cru_ptr->cru_softrst_con[7]); + udelay(1); + writel(RK_CLRBITS(1 << 9), &cru_ptr->cru_softrst_con[7]); +} + +void rkclk_configure_vop_aclk(u32 vop_id, u32 aclk_hz) +{ + u32 div; + + /* vop aclk source clk: cpll */ + div = CPLL_HZ / aclk_hz; + assert((div - 1 < 64) && (div * aclk_hz == CPLL_HZ)); + + switch (vop_id) { + case 0: + writel(RK_CLRSETBITS(3 << 6 | 0x1f << 0, + 0 << 6 | (div - 1) << 0), + &cru_ptr->cru_clksel_con[31]); + break; + + case 1: + writel(RK_CLRSETBITS(3 << 14 | 0x1f << 8, + 0 << 14 | (div - 1) << 8), + &cru_ptr->cru_clksel_con[31]); + break; + } +} + +int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz) +{ + struct pll_div npll_config = {0}; + u32 lcdc_div; + + if (pll_para_config(dclk_hz, &npll_config, &lcdc_div)) + return -1; + + /* npll enter slow-mode */ + writel(RK_CLRSETBITS(NPLL_MODE_MSK, NPLL_MODE_SLOW), + &cru_ptr->cru_mode_con); + + rkclk_set_pll(&cru_ptr->cru_npll_con[0], &npll_config); + + /* waiting for pll lock */ + while (1) { + if (readl(&rk3288_grf->soc_status[1]) & SOCSTS_NPLL_LOCK) + break; + udelay(1); + } + + /* npll enter normal-mode */ + writel(RK_CLRSETBITS(NPLL_MODE_MSK, NPLL_MODE_NORM), + &cru_ptr->cru_mode_con); + + /* vop dclk source clk: npll,dclk_div: 1 */ + switch (vop_id) { + case 0: + writel(RK_CLRSETBITS(0xff << 8 | 3 << 0, + (lcdc_div - 1) << 8 | 2 << 0), + &cru_ptr->cru_clksel_con[27]); + break; + + case 1: + writel(RK_CLRSETBITS(0xff << 8 | 3 << 6, + (lcdc_div - 1) << 8 | 2 << 6), + &cru_ptr->cru_clksel_con[29]); + break; + } + return 0; +} + +int rkclk_was_watchdog_reset(void) +{ + /* Bits 5 and 4 are "second" and "first" global watchdog reset. */ + return readl(&cru_ptr->cru_glb_rst_st) & 0x30; +} diff --git a/src/soc/rockchip/rk3288/crypto.c b/src/soc/rockchip/rk3288/crypto.c new file mode 100644 index 0000000000..60bfa42451 --- /dev/null +++ b/src/soc/rockchip/rk3288/crypto.c @@ -0,0 +1,134 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +enum rk3288_crypto_interrupt_bits { + PKA_DONE = 1 << 5, + HASH_DONE = 1 << 4, + HRDMA_ERR = 1 << 3, + HRDMA_DONE = 1 << 2, + BCDMA_ERR = 1 << 1, + BCDMA_DONE = 1 << 0, +}; + +struct rk3288_crypto { + u32 intsts; + u32 intena; + u32 ctrl; + u32 conf; + u32 brdmas; + u32 btdmas; + u32 btdmal; + u32 hrdmas; + u32 hrdmal; + u8 _res0[0x80 - 0x24]; + u32 aes_ctrl; + u32 aes_sts; + u32 aes_din[4]; + u32 aes_dout[4]; + u32 aes_iv[4]; + u32 aes_key[8]; + u32 aes_cnt[4]; + u8 _res1[0x100 - 0xe8]; + u32 tdes_ctrl; + u32 tdes_sts; + u32 tdes_din[2]; + u32 tdes_dout[2]; + u32 tdes_iv[2]; + u32 tdes_key[3][2]; + u8 _res2[0x180 - 0x138]; + u32 hash_ctrl; + u32 hash_sts; + u32 hash_msg_len; + u32 hash_dout[8]; + u32 hash_seed[5]; + u8 _res3[0x200 - 0x1c0]; + u32 trng_ctrl; + u32 trng_dout[8]; +} *crypto = (void *)CRYPTO_BASE; +check_member(rk3288_crypto, trng_dout[7], 0x220); + +int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, + uint32_t data_size) +{ + if (hash_alg != VB2_HASH_SHA256) { + printk(BIOS_INFO, "RK3288 doesn't support hash_alg %d!\n", + hash_alg); + return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; + } + + write32(RK_SETBITS(1 << 6), &crypto->ctrl); /* Assert HASH_FLUSH */ + udelay(1); /* for 10+ cycles to */ + write32(RK_CLRBITS(1 << 6), &crypto->ctrl); /* clear out old hash */ + + /* Enable DMA byte swapping for little-endian bus (Byteswap_??FIFO) */ + write32(1 << 5 | 1 << 4 | 1 << 3, &crypto->conf); + + write32(HRDMA_ERR | HRDMA_DONE, &crypto->intena); /* enable interrupt */ + + write32(data_size, &crypto->hash_msg_len); /* program total size */ + write32(1 << 3 | 0x2, &crypto->hash_ctrl); /* swap DOUT, SHA256 */ + + printk(BIOS_DEBUG, "Initialized RK3288 HW crypto for %u byte SHA256\n", + data_size); + return VB2_SUCCESS; +} + +int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + uint32_t intsts; + + write32(HRDMA_ERR | HRDMA_DONE, &crypto->intsts); /* clear interrupts */ + + /* NOTE: This assumes that the DMA is reading from uncached SRAM. */ + write32((uint32_t)buf, &crypto->hrdmas); + write32(size / sizeof(uint32_t), &crypto->hrdmal); + write32(RK_SETBITS(1 << 3), &crypto->ctrl); /* Set HASH_START */ + do { + intsts = read32(&crypto->intsts); + if (intsts & HRDMA_ERR) { + printk(BIOS_ERR, "ERROR: DMA error during HW crypto\n"); + return VB2_ERROR_UNKNOWN; + } + } while (!(intsts & HRDMA_DONE)); /* wait for DMA to finish */ + + return VB2_SUCCESS; +} + +int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size) +{ + uint32_t *dest = (uint32_t *)digest; + uint32_t *src = crypto->hash_dout; + assert(digest_size == sizeof(crypto->hash_dout)); + + while (!(read32(&crypto->hash_sts) & 0x1)) + /* wait for crypto engine to set HASH_DONE bit */; + + while ((uint8_t *)dest < digest + digest_size) + *dest++ = read32(src++); + + return VB2_SUCCESS; +} diff --git a/src/soc/rockchip/rk3288/display.c b/src/soc/rockchip/rk3288/display.c new file mode 100644 index 0000000000..4b5145d907 --- /dev/null +++ b/src/soc/rockchip/rk3288/display.c @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +void rk_display_init(device_t dev, u32 lcdbase, + unsigned long fb_size) +{ + struct edid edid; + struct soc_rockchip_rk3288_config *conf = dev->chip_info; + uint32_t lower = ALIGN_DOWN(lcdbase, MiB); + uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB); + enum vop_modes detected_mode = VOP_MODE_UNKNOWN; + + printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase)); + memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */ + dcache_clean_invalidate_by_mva((void *)lower, upper - lower); + mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF); + + switch (conf->vop_mode) { + case VOP_MODE_NONE: + return; + case VOP_MODE_AUTO_DETECT: + /* try EDP first, then HDMI */ + case VOP_MODE_EDP: + printk(BIOS_DEBUG, "Attempting to setup EDP display.\n"); + rkclk_configure_edp(); + rkclk_configure_vop_aclk(conf->vop_id, 192 * MHz); + rk_edp_init(conf->vop_id); + + if (rk_edp_get_edid(&edid) == 0) { + detected_mode = VOP_MODE_EDP; + break; + } else { + printk(BIOS_WARNING, "Cannot get EDID from EDP.\n"); + if (conf->vop_mode == VOP_MODE_EDP) + return; + } + /* fall thru */ + case VOP_MODE_HDMI: + printk(BIOS_DEBUG, "Attempting to setup HDMI display.\n"); + rkclk_configure_hdmi(); + rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz); + rk_hdmi_init(conf->vop_id); + + if (rk_hdmi_get_edid(&edid) == 0) { + detected_mode = VOP_MODE_HDMI; + break; + } else { + printk(BIOS_WARNING, "Cannot get EDID from HDMI.\n"); + if (conf->vop_mode == VOP_MODE_HDMI) + return; + } + /* fall thru */ + default: + printk(BIOS_WARNING, "Cannot read any edid info, aborting.\n"); + return; + } + + if (rkclk_configure_vop_dclk(conf->vop_id, edid.mode.pixel_clock * KHz)) { + printk(BIOS_WARNING, "config vop err\n"); + return; + } + + edid.framebuffer_bits_per_pixel = conf->framebuffer_bits_per_pixel; + edid.bytes_per_line = edid.mode.ha * conf->framebuffer_bits_per_pixel / 8; + edid.x_resolution = edid.mode.ha; + edid.y_resolution = edid.mode.va; + rkvop_mode_set(conf->vop_id, &edid, detected_mode); + + rkvop_enable(conf->vop_id, lcdbase, &edid); + + switch (detected_mode) { + case VOP_MODE_HDMI: + if (rk_hdmi_enable(&edid)) { + printk(BIOS_WARNING, "hdmi enable err\n"); + return; + } + + /* + * HACK: if we do remove this delay, HDMI TV may not show + * anythings. So we make an delay here, ensure TV have + * enough time to respond. + */ + mdelay(2000); + break; + + case VOP_MODE_EDP: + default: + if (rk_edp_enable()) { + printk(BIOS_WARNING, "edp enable err\n"); + return; + } + mainboard_power_on_backlight(); + break; + } + + set_vbe_mode_info_valid(&edid, (uintptr_t)lcdbase); +} diff --git a/src/soc/rockchip/rk3288/edp.c b/src/soc/rockchip/rk3288/edp.c new file mode 100644 index 0000000000..0636cf2f35 --- /dev/null +++ b/src/soc/rockchip/rk3288/edp.c @@ -0,0 +1,1036 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +#define edp_debug(x...) do {if (0) printk(BIOS_DEBUG, x); } while (0) + +static struct rk_edp rk_edp; + +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 +#define DP_LINK_STATUS_SIZE 6 + +static const char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +static const char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; + +#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 +#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 + +static void rk_edp_init_refclk(struct rk_edp *edp) +{ + writel(SEL_24M, &edp->regs->analog_ctl_2); + writel(REF_CLK_24M, &edp->regs->pll_reg_1); + + /*initial value*/ + writel(LDO_OUTPUT_V_SEL_145 | + KVCO_DEFALUT | + CHG_PUMP_CUR_SEL_5US | + V2L_CUR_SEL_1MA, &edp->regs->pll_reg_2); + + writel(LOCK_DET_CNT_SEL_256 | + LOOP_FILTER_RESET | + PALL_SSC_RESET | + LOCK_DET_BYPASS | + PLL_LOCK_DET_MODE | + PLL_LOCK_DET_FORCE, &edp->regs->pll_reg_3); + + writel(REGULATOR_V_SEL_950MV | + STANDBY_CUR_SEL | + CHG_PUMP_INOUT_CTRL_1200MV | + CHG_PUMP_INPUT_CTRL_OP, &edp->regs->pll_reg_5); + + writel(SSC_OFFSET | SSC_MODE | SSC_DEPTH, &edp->regs->ssc_reg); + + writel(TX_SWING_PRE_EMP_MODE | + PRE_DRIVER_PW_CTRL1 | + LP_MODE_CLK_REGULATOR | + RESISTOR_MSB_CTRL | + RESISTOR_CTRL, &edp->regs->tx_common); + + writel(DP_AUX_COMMON_MODE | + DP_AUX_EN | + AUX_TERM_50OHM, &edp->regs->dp_aux); + + writel(DP_BG_OUT_SEL | + DP_DB_CUR_CTRL | + DP_BG_SEL | + DP_RESISTOR_TUNE_BG, &edp->regs->dp_bias); + + writel(CH1_CH3_SWING_EMP_CTRL | + CH0_CH2_SWING_EMP_CTRL, &edp->regs->dp_reserv2); +} + +static void rk_edp_init_interrupt(struct rk_edp *edp) +{ + /* Set interrupt pin assertion polarity as high */ + writel(INT_POL, &edp->regs->int_ctl); + + /* Clear pending registers */ + writel(0xff, &edp->regs->common_int_sta_1); + writel(0x4f, &edp->regs->common_int_sta_2); + writel(0xff, &edp->regs->common_int_sta_3); + writel(0x27, &edp->regs->common_int_sta_4); + writel(0x7f, &edp->regs->dp_int_sta); + + /* 0:mask,1: unmask */ + writel(0x00, &edp->regs->common_int_mask_1); + writel(0x00, &edp->regs->common_int_mask_2); + writel(0x00, &edp->regs->common_int_mask_3); + writel(0x00, &edp->regs->common_int_mask_4); + writel(0x00, &edp->regs->int_sta_mask); +} + +static void rk_edp_enable_sw_function(struct rk_edp *edp) +{ + clrbits_le32(&edp->regs->func_en_1, SW_FUNC_EN_N); +} + +static int rk_edp_get_pll_lock_status(struct rk_edp *edp) +{ + u32 val; + + val = readl(&edp->regs->dp_debug_ctl); + return (val & PLL_LOCK) ? DP_PLL_LOCKED : DP_PLL_UNLOCKED; +} + +static void rk_edp_init_analog_func(struct rk_edp *edp) +{ + struct stopwatch sw; + + writel(0x00, &edp->regs->dp_pd); + + writel(PLL_LOCK_CHG, &edp->regs->common_int_sta_1); + + clrbits_le32(&edp->regs->dp_debug_ctl, F_PLL_LOCK | PLL_LOCK_CTRL); + + stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT); + + while (rk_edp_get_pll_lock_status(edp) == DP_PLL_UNLOCKED) { + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "%s: PLL is not locked\n", __func__); + return; + } + } + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + clrbits_le32(&edp->regs->func_en_2, SERDES_FIFO_FUNC_EN_N | + LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N | + SSC_FUNC_EN_N); +} + +static void rk_edp_init_aux(struct rk_edp *edp) +{ + /* Clear inerrupts related to AUX channel */ + writel(AUX_FUNC_EN_N, &edp->regs->dp_int_sta); + + /* Disable AUX channel module */ + setbits_le32(&edp->regs->func_en_2, AUX_FUNC_EN_N); + + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ + writel(DEFER_CTRL_EN | DEFER_COUNT(1), &edp->regs->aux_ch_defer_dtl); + + /* Enable AUX channel module */ + clrbits_le32(&edp->regs->func_en_2, AUX_FUNC_EN_N); +} + +static int rk_edp_aux_enable(struct rk_edp *edp) +{ + struct stopwatch sw; + + setbits_le32(&edp->regs->aux_ch_ctl_2, AUX_EN); + stopwatch_init_msecs_expire(&sw, 20); + do { + if (!(readl(&edp->regs->aux_ch_ctl_2) & AUX_EN)) + return 0; + } while (!stopwatch_expired(&sw)); + + return -1; + +} + +static int rk_edp_is_aux_reply(struct rk_edp *edp) +{ + struct stopwatch sw; + + stopwatch_init_msecs_expire(&sw, 10); + + while (!(readl(&edp->regs->dp_int_sta) & RPLY_RECEIV)) { + if (stopwatch_expired(&sw)) + return -1; + } + + writel(RPLY_RECEIV, &edp->regs->dp_int_sta); + + return 0; +} + +static int rk_edp_start_aux_transaction(struct rk_edp *edp) +{ + int val; + + /* Enable AUX CH operation */ + if (rk_edp_aux_enable(edp)) { + edp_debug("AUX CH enable timeout!\n"); + return -1; + } + + /* Is AUX CH command reply received? */ + if (rk_edp_is_aux_reply(edp)) { + edp_debug("AUX CH command reply failed!\n"); + return -1; + } + + /* Clear interrupt source for AUX CH access error */ + val = readl(&edp->regs->dp_int_sta); + if (val & AUX_ERR) { + writel(AUX_ERR, &edp->regs->dp_int_sta); + return -1; + } + + /* Check AUX CH error access status */ + val = readl(&edp->regs->dp_int_sta); + if ((val & AUX_STATUS_MASK) != 0) { + edp_debug("AUX CH error happens: %d\n\n", + val & AUX_STATUS_MASK); + return -1; + } + + return 0; +} + +static int rk_edp_dpcd_transfer(struct rk_edp *edp, + unsigned int val_addr, u8 *data, + unsigned int length, + enum dpcd_request request) +{ + int val; + int i, try_times; + int retval = 0; + u32 len = 0; + + while (length) { + len = MIN(length, 16); + for (try_times = 0; try_times < 10; try_times++) { + + /* Clear AUX CH data buffer */ + val = BUF_CLR; + writel(val, &edp->regs->buf_data_ctl); + + /* Select DPCD device address */ + val = AUX_ADDR_7_0(val_addr); + writel(val, &edp->regs->aux_addr_7_0); + val = AUX_ADDR_15_8(val_addr); + writel(val, &edp->regs->aux_addr_15_8); + val = AUX_ADDR_19_16(val_addr); + writel(val, &edp->regs->aux_addr_19_16); + + /* + * Set DisplayPort transaction and read 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + if (request == DPCD_WRITE) { + val = AUX_LENGTH(len) | + AUX_TX_COMM_DP_TRANSACTION | + AUX_TX_COMM_WRITE; + for (i = 0; i < len; i++) + writel(*data++, &edp->regs->buf_data[i]); + } else + val = AUX_LENGTH(len) | + AUX_TX_COMM_DP_TRANSACTION | + AUX_TX_COMM_READ; + + writel(val, &edp->regs->aux_ch_ctl_1); + + /* Start AUX transaction */ + retval = rk_edp_start_aux_transaction(edp); + if (retval == 0) + break; + else + printk(BIOS_WARNING, "read dpcd Aux Transaction fail!\n"); + + } + + if (retval) + return -1; + + if (request == DPCD_READ) { + for (i = 0; i < len; i++) + *data++ = (u8)readl(&edp->regs->buf_data[i]); + } + + length -= len; + val_addr += 16; + } + return 0; +} + +static int rk_edp_dpcd_read(struct rk_edp *edp, u32 addr, u8 *values, size_t size) +{ + return rk_edp_dpcd_transfer(edp, addr, values, size, DPCD_READ); +} + +static int rk_edp_dpcd_write(struct rk_edp *edp, u32 addr, u8 *values, size_t size) +{ + return rk_edp_dpcd_transfer(edp, addr, values, size, DPCD_WRITE); +} + + +static int rk_edp_link_power_up(struct rk_edp *edp) +{ + u8 value; + int err; + + /* DP_SET_POWER register is only available on DPCD v1.1 and later */ + if (edp->link_train.revision < 0x11) + return 0; + + err = rk_edp_dpcd_read(edp, DPCD_LINK_POWER_STATE, &value, 1); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + + err = rk_edp_dpcd_write(edp, DPCD_LINK_POWER_STATE, &value, 1); + if (err < 0) + return err; + + /* + * According to the DP 1.1 specification, a "Sink Device must exit the + * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink + * Control Field" (register 0x600). + */ + mdelay(1); + + return 0; +} + +static int rk_edp_link_configure(struct rk_edp *edp) +{ + u8 values[2]; + + values[0] = edp->link_train.link_rate; + values[1] = edp->link_train.lane_count; + + return rk_edp_dpcd_write(edp, DPCD_LINK_BW_SET, values, sizeof(values)); +} + +static void rk_edp_set_link_training(struct rk_edp *edp, + const u8 *training_values) +{ + int i; + + for (i = 0; i < edp->link_train.lane_count; i++) + writel(training_values[i], &edp->regs->ln_link_trn_ctl[i]); +} + +static u8 edp_link_status(const u8 *link_status, int r) +{ + return link_status[r - DPCD_LANE0_1_STATUS]; +} + +static int rk_edp_dpcd_read_link_status(struct rk_edp *edp, u8 *link_status) +{ + return rk_edp_dpcd_read(edp, DPCD_LANE0_1_STATUS, link_status, + DP_LINK_STATUS_SIZE); +} + +static u8 edp_get_lane_status(const u8 *link_status, int lane) +{ + int i = DPCD_LANE0_1_STATUS + (lane >> 1); + int s = (lane & 1) * 4; + u8 l = edp_link_status(link_status, i); + return (l >> s) & 0xf; +} + +static int rk_edp_clock_recovery_ok(const u8 *link_status, int lane_count) +{ + int lane; + u8 lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = edp_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return 0; + } + return 1; +} + +static int rk_edp_channel_eq_ok(const u8 *link_status, int lane_count) +{ + u8 lane_align; + u8 lane_status; + int lane; + + lane_align = edp_link_status(link_status, + DPCD_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return 0; + for (lane = 0; lane < lane_count; lane++) { + lane_status = edp_get_lane_status(link_status, lane); + if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) + return 0; + } + return 1; +} + +static u8 +rk_edp_get_adjust_request_voltage(const u8 *link_status, int lane) +{ + int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + u8 l = edp_link_status(link_status, i); + + return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; +} + +static u8 rk_edp_get_adjust_request_pre_emphasis(const u8 *link_status, + int lane) +{ + int i = DPCD_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + u8 l = edp_link_status(link_status, i); + + return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; +} + +static void edp_get_adjust_train(const u8 *link_status, int lane_count, + u8 train_set[]) +{ + u8 v = 0; + u8 p = 0; + int lane; + + for (lane = 0; lane < lane_count; lane++) { + u8 this_v = + rk_edp_get_adjust_request_voltage(link_status, lane); + u8 this_p = + rk_edp_get_adjust_request_pre_emphasis(link_status, + lane); + + printk(BIOS_DEBUG, "requested signal parameters: lane %d " + "voltage %s pre_emph %s\n", lane, + voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + if (v >= DP_VOLTAGE_MAX) + v |= DP_TRAIN_MAX_SWING_REACHED; + + if (p >= DP_PRE_EMPHASIS_MAX) + p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + printk(BIOS_DEBUG, "using signal parameters: voltage %s pre_emph %s\n", + voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) + >> DP_TRAIN_VOLTAGE_SWING_SHIFT], + pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); + + for (lane = 0; lane < 4; lane++) + train_set[lane] = v | p; +} + +static int rk_edp_link_train_cr(struct rk_edp *edp) +{ + int clock_recovery; + u8 voltage, tries = 0; + u8 status[DP_LINK_STATUS_SIZE]; + int i; + u8 value; + + value = DP_TRAINING_PATTERN_1; + writel(value, &edp->regs->dp_training_ptn_set); + rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1); + memset(edp->train_set, 0, 4); + + /* clock recovery loop */ + clock_recovery = 0; + tries = 0; + voltage = 0xff; + + while (1) { + rk_edp_set_link_training(edp, edp->train_set); + rk_edp_dpcd_write(edp, DPCD_TRAINING_LANE0_SET, + edp->train_set, + edp->link_train.lane_count); + + mdelay(1); + + if (rk_edp_dpcd_read_link_status(edp, status) < 0) { + printk(BIOS_ERR, "displayport link status failed\n"); + break; + } + + if (rk_edp_clock_recovery_ok(status, + edp->link_train.lane_count)) { + clock_recovery = 1; + break; + } + + for (i = 0; i < edp->link_train.lane_count; i++) { + if ((edp->train_set[i] & + DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + } + if (i == edp->link_train.lane_count) { + printk(BIOS_ERR, "clock recovery reached max voltage\n"); + break; + } + + if ((edp->train_set[0] & + DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++tries; + if (tries == MAX_CR_LOOP) { + printk(BIOS_ERR, "clock recovery tried 5 times\n"); + break; + } + } else + tries = 0; + + voltage = edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Compute new train_set as requested by sink */ + edp_get_adjust_train(status, edp->link_train.lane_count, + edp->train_set); + } + if (!clock_recovery) { + printk(BIOS_ERR, "clock recovery failed\n"); + return -1; + } else { + printk(BIOS_DEBUG, "clock recovery at voltage %d pre-emphasis %d\n", + edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT); + return 0; + } +} + +static int rk_edp_link_train_ce(struct rk_edp *edp) +{ + int channel_eq; + u8 value, tries = 0; + u8 status[DP_LINK_STATUS_SIZE]; + + value = DP_TRAINING_PATTERN_2; + writel(value, &edp->regs->dp_training_ptn_set); + rk_edp_dpcd_write(edp, DPCD_TRAINING_PATTERN_SET, &value, 1); + + /* channel equalization loop */ + channel_eq = 0; + for (tries = 0; tries < 5; tries++) { + rk_edp_set_link_training(edp, edp->train_set); + udelay(400); + + if (rk_edp_dpcd_read_link_status(edp, status) < 0) { + printk(BIOS_ERR, "displayport link status failed\n"); + return -1; + } + + if (rk_edp_channel_eq_ok(status, + edp->link_train.lane_count)) { + channel_eq = 1; + break; + } + edp_get_adjust_train(status, + edp->link_train.lane_count, + edp->train_set); + } + + if (!channel_eq) { + printk(BIOS_ERR, "channel eq failed\n"); + return -1; + } else { + printk(BIOS_DEBUG, "channel eq at voltage %d pre-emphasis %d\n", + edp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, + (edp->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT); + return 0; + } +} + +static int rk_edp_init_training(struct rk_edp *edp) +{ + u8 values[3]; + int err; + + err = rk_edp_dpcd_read(edp, DPCD_DPCD_REV, values, sizeof(values)); + if (err < 0) + return err; + + edp->link_train.revision = values[0]; + edp->link_train.link_rate = values[1]; + edp->link_train.lane_count = values[2] & DP_MAX_LANE_COUNT_MASK; + + edp_debug("max link rate:%d.%dGps max number of lanes:%d\n", + edp->link_train.link_rate * 27 / 100, + edp->link_train.link_rate * 27 % 100, + edp->link_train.lane_count); + + if ((edp->link_train.link_rate != LINK_RATE_1_62GBPS) && + (edp->link_train.link_rate != LINK_RATE_2_70GBPS)) { + edp_debug("Rx Max Link Rate is abnormal :%x\n", + edp->link_train.link_rate); + return -1; + } + + if (edp->link_train.lane_count == 0) { + edp_debug("Rx Max Lane count is abnormal :%x\n", + edp->link_train.lane_count); + return -1; + } + + rk_edp_link_power_up(edp); + rk_edp_link_configure(edp); + return 0; +} + +static int rk_edp_hw_link_training(struct rk_edp *edp) +{ + u32 val; + struct stopwatch sw; + + /* Set link rate and count as you want to establish*/ + writel(edp->link_train.link_rate, &edp->regs->link_bw_set); + writel(edp->link_train.lane_count, &edp->regs->lane_count_set); + + if (rk_edp_link_train_cr(edp)) + return -1; + if (rk_edp_link_train_ce(edp)) + return -1; + + writel(HW_LT_EN, &edp->regs->dp_hw_link_training); + stopwatch_init_msecs_expire(&sw, 10); + do { + val = readl(&edp->regs->dp_hw_link_training); + if (!(val & HW_LT_EN)) + break; + } while (!stopwatch_expired(&sw)); + if (val & HW_LT_ERR_CODE_MASK) { + printk(BIOS_ERR, "edp hw link training error: %d\n", + val >> HW_LT_ERR_CODE_SHIFT); + return -1; + } + return 0; + +} + +static int rk_edp_select_i2c_device(struct rk_edp *edp, + unsigned int device_addr, + unsigned int val_addr) +{ + u32 val; + int retval; + + /* Set EDID device address */ + val = device_addr; + writel(val, &edp->regs->aux_addr_7_0); + writel(0x0, &edp->regs->aux_addr_15_8); + writel(0x0, &edp->regs->aux_addr_19_16); + + /* Set offset from base address of EDID device */ + writel(val_addr, &edp->regs->buf_data[0]); + + /* + * Set I2C transaction and write address + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + val = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | + AUX_TX_COMM_WRITE; + writel(val, &edp->regs->aux_ch_ctl_1); + + /* Start AUX transaction */ + retval = rk_edp_start_aux_transaction(edp); + if (retval != 0) + edp_debug("select_i2c_device Aux Transaction fail!\n"); + + return retval; +} + +static int rk_edp_read_bytes_from_i2c(struct rk_edp *edp, + unsigned int device_addr, + unsigned int val_addr, + unsigned int count, + u8 edid[]) +{ + u32 val; + unsigned int i, j; + unsigned int cur_data_idx; + unsigned int defer = 0; + int retval = 0; + + for (i = 0; i < count; i += 16) { + for (j = 0; j < 10; j++) { /* try 10 times */ + /* Clear AUX CH data buffer */ + val = BUF_CLR; + writel(val, &edp->regs->buf_data_ctl); + + /* Set normal AUX CH command */ + clrbits_le32(&edp->regs->aux_ch_ctl_2, ADDR_ONLY); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending addres + */ + if (!defer) + retval = rk_edp_select_i2c_device(edp, + device_addr, val_addr + i); + else + defer = 0; + + /* + * Set I2C transaction and write data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + val = AUX_LENGTH(16) | AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + writel(val, &edp->regs->aux_ch_ctl_1); + + /* Start AUX transaction */ + retval = rk_edp_start_aux_transaction(edp); + if (retval == 0) + break; + else { + edp_debug("Aux Transaction fail!\n"); + continue; + } + + /* Check if Rx sends defer */ + val = readl(&edp->regs->aux_rx_comm); + if (val == AUX_RX_COMM_AUX_DEFER || + val == AUX_RX_COMM_I2C_DEFER) { + edp_debug("Defer: %d\n\n", val); + defer = 1; + } + } + + if (retval) + return -1; + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + val = readl(&edp->regs->buf_data[cur_data_idx]); + edid[i + cur_data_idx] = (u8)val; + } + } + + return retval; +} + +static int rk_edp_read_edid(struct rk_edp *edp, struct edid *edid) +{ + u8 buf[EDID_LENGTH * 2]; + u32 edid_size = EDID_LENGTH; + int retval; + + /* Read EDID data */ + retval = rk_edp_read_bytes_from_i2c(edp, EDID_ADDR, + EDID_HEADER, EDID_LENGTH, + &buf[EDID_HEADER]); + if (retval != 0) { + printk(BIOS_ERR, "EDID Read failed!\n"); + return -1; + } + + /* check if edid have extension flag, and read additional EDID data */ + if (buf[EDID_EXTENSION_FLAG]) { + edid_size += EDID_LENGTH; + retval = rk_edp_read_bytes_from_i2c(edp, EDID_ADDR, + EDID_LENGTH, EDID_LENGTH, + &buf[EDID_LENGTH]); + if (retval != 0) { + printk(BIOS_ERR, "EDID Read failed!\n"); + return -1; + } + } + + if (decode_edid(buf, edid_size, edid, 0)) { + printk(BIOS_ERR, "%s: Failed to decode EDID.\n", + __func__); + return -1; + } + + edp_debug("EDID Read success!\n"); + return 0; +} + +static int rk_edp_set_link_train(struct rk_edp *edp) +{ + int retval; + + if (rk_edp_init_training(edp)) { + printk(BIOS_ERR, "DP LT init failed!\n"); + return -1; + } + + retval = rk_edp_hw_link_training(edp); + + return retval; +} + +static void rk_edp_init_video(struct rk_edp *edp) +{ + u32 val; + + val = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + writel(val, &edp->regs->common_int_sta_1); + + val = CHA_CRI(4) | CHA_CTRL; + writel(val, &edp->regs->sys_ctl_2); + + val = VID_HRES_TH(2) | VID_VRES_TH(0); + writel(val, &edp->regs->video_ctl_8); +} + +static void rk_edp_config_video_slave_mode(struct rk_edp *edp) +{ + clrbits_le32(&edp->regs->func_en_1, + VID_FIFO_FUNC_EN_N | VID_CAP_FUNC_EN_N); +} + +static void rk_edp_set_video_cr_mn(struct rk_edp *edp, + enum clock_recovery_m_value_type type, + u32 m_value, + u32 n_value) +{ + u32 val; + + if (type == REGISTER_M) { + setbits_le32(&edp->regs->sys_ctl_4, FIX_M_VID); + val = m_value & 0xff; + writel(val, &edp->regs->m_vid_0); + val = (m_value >> 8) & 0xff; + writel(val, &edp->regs->m_vid_1); + val = (m_value >> 16) & 0xff; + writel(val, &edp->regs->m_vid_2); + + val = n_value & 0xff; + writel(val, &edp->regs->n_vid_0); + val = (n_value >> 8) & 0xff; + writel(val, &edp->regs->n_vid_1); + val = (n_value >> 16) & 0xff; + writel(val, &edp->regs->n_vid_2); + } else { + clrbits_le32(&edp->regs->sys_ctl_4, FIX_M_VID); + + writel(0x00, &edp->regs->n_vid_0); + writel(0x80, &edp->regs->n_vid_1); + writel(0x00, &edp->regs->n_vid_2); + } +} + +static int rk_edp_is_video_stream_clock_on(struct rk_edp *edp) +{ + u32 val; + struct stopwatch sw; + + stopwatch_init_msecs_expire(&sw, 100); + do { + val = readl(&edp->regs->sys_ctl_1); + + /*must write value to update DET_STA bit status*/ + writel(val, &edp->regs->sys_ctl_1); + val = readl(&edp->regs->sys_ctl_1); + if (!(val & DET_STA)) + continue; + + val = readl(&edp->regs->sys_ctl_2); + + /*must write value to update CHA_STA bit status*/ + writel(val, &edp->regs->sys_ctl_2); + val = readl(&edp->regs->sys_ctl_2); + if (!(val & CHA_STA)) + return 0; + } while (!stopwatch_expired(&sw)); + + return -1; +} + +static int rk_edp_is_video_stream_on(struct rk_edp *edp) +{ + u32 val; + struct stopwatch sw; + + stopwatch_init_msecs_expire(&sw, 100); + do { + val = readl(&edp->regs->sys_ctl_3); + + /*must write value to update STRM_VALID bit status*/ + writel(val, &edp->regs->sys_ctl_3); + + val = readl(&edp->regs->sys_ctl_3); + if (!(val & STRM_VALID)) + return 0; + } while (!stopwatch_expired(&sw)); + + return -1; +} + +static int rk_edp_config_video(struct rk_edp *edp) +{ + rk_edp_config_video_slave_mode(edp); + + if (rk_edp_get_pll_lock_status(edp) == DP_PLL_UNLOCKED) { + edp_debug("PLL is not locked yet.\n"); + return -1; + } + + if (rk_edp_is_video_stream_clock_on(edp)) + return -1; + + /* Set to use the register calculated M/N video */ + rk_edp_set_video_cr_mn(edp, CALCULATED_M, 0, 0); + + /* For video bist, Video timing must be generated by register */ + clrbits_le32(&edp->regs->video_ctl_10, F_SEL); + + /* Disable video mute */ + clrbits_le32(&edp->regs->video_ctl_1, VIDEO_MUTE); + + /* Enable video at next frame */ + setbits_le32(&edp->regs->video_ctl_1, VIDEO_EN); + + return rk_edp_is_video_stream_on(edp); +} + +static void rockchip_edp_force_hpd(struct rk_edp *edp) +{ + u32 val; + + val = readl(&edp->regs->sys_ctl_3); + val |= (F_HPD | HPD_CTRL); + writel(val, &edp->regs->sys_ctl_3); +} + +static int rockchip_edp_get_plug_in_status(struct rk_edp *edp) +{ + u32 val; + + val = readl(&edp->regs->sys_ctl_3); + if (val & HPD_STATUS) + return 1; + + return 0; +} + +/* + * support edp HPD function + * some hardware version do not support edp hdp, + * we use 200ms to try to get the hpd single now, + * if we can not get edp hpd single, it will delay 200ms, + * also meet the edp power timing request, to compatible + * all of the hardware version + */ +static void rockchip_edp_wait_hpd(struct rk_edp *edp) +{ + struct stopwatch hpd; + + stopwatch_init_msecs_expire(&hpd, 200); + do { + if (rockchip_edp_get_plug_in_status(edp)) + return; + udelay(100); + } while (!stopwatch_expired(&hpd)); + + printk(BIOS_DEBUG, "do not get hpd single, force hpd\n"); + rockchip_edp_force_hpd(edp); +} + +int rk_edp_get_edid(struct edid *edid) +{ + int i; + int retval; + + /* Read EDID */ + for (i = 0; i < 3; i++) { + retval = rk_edp_read_edid(&rk_edp, edid); + if (retval == 0) + break; + } + + return retval; +} + +int rk_edp_enable(void) +{ + int ret = 0; + + if (rk_edp_set_link_train(&rk_edp)) { + printk(BIOS_ERR, "link train failed!\n"); + return -1; + } + + rk_edp_init_video(&rk_edp); + ret = rk_edp_config_video(&rk_edp); + if (ret) + printk(BIOS_ERR, "config video failed\n"); + + return ret; +} + +void rk_edp_init(u32 vop_id) +{ + u32 val; + + rk_edp.regs = (struct rk3288_edp_regs *)EDP_BASE; + + /* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */ + writel(RK_SETBITS(1 << 4), &rk3288_grf->soc_con12); + + /* select epd signal from vop0 or vop1 */ + val = (vop_id == 1) ? RK_SETBITS(1 << 5) : RK_CLRBITS(1 << 5); + writel(val, &rk3288_grf->soc_con6); + + rockchip_edp_wait_hpd(&rk_edp); + + rk_edp_init_refclk(&rk_edp); + rk_edp_init_interrupt(&rk_edp); + rk_edp_enable_sw_function(&rk_edp); + rk_edp_init_analog_func(&rk_edp); + rk_edp_init_aux(&rk_edp); +} diff --git a/src/soc/rockchip/rk3288/gpio.c b/src/soc/rockchip/rk3288/gpio.c new file mode 100644 index 0000000000..b84d6a0821 --- /dev/null +++ b/src/soc/rockchip/rk3288/gpio.c @@ -0,0 +1,85 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +struct rk3288_gpio_regs *gpio_port[] = { + (struct rk3288_gpio_regs *)0xff750000, + (struct rk3288_gpio_regs *)0xff780000, + (struct rk3288_gpio_regs *)0xff790000, + (struct rk3288_gpio_regs *)0xff7a0000, + (struct rk3288_gpio_regs *)0xff7b0000, + (struct rk3288_gpio_regs *)0xff7c0000, + (struct rk3288_gpio_regs *)0xff7d0000, + (struct rk3288_gpio_regs *)0xff7e0000, + (struct rk3288_gpio_regs *)0xff7f0000 +}; + +enum { + PULLNONE = 0, + PULLUP, + PULLDOWN +}; + +#define PMU_GPIO_PORT 0 + +static void __gpio_input(gpio_t gpio, u32 pull) +{ + clrbits_le32(&gpio_port[gpio.port]->swporta_ddr, 1 << gpio.num); + if (gpio.port == PMU_GPIO_PORT) + clrsetbits_le32(&rk3288_pmu->gpio0pull[gpio.bank], + 3 << (gpio.idx * 2), pull << (gpio.idx * 2)); + else + writel(RK_CLRSETBITS(3 << (gpio.idx * 2), + pull << (gpio.idx * 2)), + &rk3288_grf->gpio1_p[(gpio.port - 1)][gpio.bank]); +} + +void gpio_input(gpio_t gpio) +{ + __gpio_input(gpio, PULLNONE); +} + +void gpio_input_pulldown(gpio_t gpio) +{ + __gpio_input(gpio, PULLDOWN); +} + +void gpio_input_pullup(gpio_t gpio) +{ + __gpio_input(gpio, PULLUP); +} + +int gpio_get(gpio_t gpio) +{ + return (readl(&gpio_port[gpio.port]->ext_porta) >> gpio.num) & 0x1; +} + +void gpio_output(gpio_t gpio, int value) +{ + setbits_le32(&gpio_port[gpio.port]->swporta_ddr, 1 << gpio.num); + clrsetbits_le32(&gpio_port[gpio.port]->swporta_dr, 1 << gpio.num, + !!value << gpio.num); +} diff --git a/src/soc/rockchip/rk3288/hdmi.c b/src/soc/rockchip/rk3288/hdmi.c new file mode 100644 index 0000000000..6820d8cac4 --- /dev/null +++ b/src/soc/rockchip/rk3288/hdmi.c @@ -0,0 +1,848 @@ +/* + * Copyright (C) Rockchip, Inc. + * Copyright (C) Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Designware High-Definition Multimedia Interface (HDMI) driveG + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +#define AUDIO_SAMPLERATE_DEFAULT (48*KHz) + +#define hdmi_debug(x...) do { if (0) printk(BIOS_DEBUG, x); } while (0) + +struct rk3288_hdmi_regs * const hdmi_regs = (void *)HDMI_TX_BASE; + +struct tmds_n_cts { + u32 tmds; + u32 cts; + u32 n; +}; + +static const struct tmds_n_cts n_cts_table[] = { + { + .tmds = 25175, .n = 6144, .cts = 25175, + }, { + .tmds = 25200, .n = 6144, .cts = 25200, + }, { + .tmds = 27000, .n = 6144, .cts = 27000, + }, { + .tmds = 27027, .n = 6144, .cts = 27027, + }, { + .tmds = 40000, .n = 6144, .cts = 40000, + }, { + .tmds = 54000, .n = 6144, .cts = 54000, + }, { + .tmds = 54054, .n = 6144, .cts = 54054, + }, { + .tmds = 65000, .n = 6144, .cts = 65000, + }, { + .tmds = 74176, .n = 11648, .cts = 140625, + }, { + .tmds = 74250, .n = 6144, .cts = 74250, + }, { + .tmds = 83500, .n = 6144, .cts = 83500, + }, { + .tmds = 106500, .n = 6144, .cts = 106500, + }, { + .tmds = 108000, .n = 6144, .cts = 108000, + }, { + .tmds = 148352, .n = 5824, .cts = 140625, + }, { + .tmds = 148500, .n = 6144, .cts = 148500, + }, { + .tmds = 297000, .n = 5120, .cts = 247500, + } +}; + +struct hdmi_mpll_config { + u64 mpixelclock; + /* Mode of Operation and PLL Dividers Control Register */ + u32 cpce; + /* PLL Gmp Control Register */ + u32 gmp; + /* PLL Current COntrol Register */ + u32 curr; +}; + +struct hdmi_phy_config { + u64 mpixelclock; + u32 sym_ctr; /* clock symbol and transmitter control */ + u32 term; /* transmission termination value */ + u32 vlev_ctr; /* voltage level control */ +}; + +static const struct hdmi_phy_config rockchip_phy_config[] = { + { + .mpixelclock = 74250, + .sym_ctr = 0x8009, .term = 0x0004, .vlev_ctr = 0x0272, + }, { + .mpixelclock = 148500, + .sym_ctr = 0x802b, .term = 0x0004, .vlev_ctr = 0x028d, + }, { + .mpixelclock = 297000, + .sym_ctr = 0x8039, .term = 0x0005, .vlev_ctr = 0x028d, + }, { + .mpixelclock = ~0ul, + .sym_ctr = 0x0000, .term = 0x0000, .vlev_ctr = 0x0000, + } +}; + +static const struct hdmi_mpll_config rockchip_mpll_cfg[] = { + { + .mpixelclock = 40000, + .cpce = 0x00b3, .gmp = 0x0000, .curr = 0x0018, + }, { + .mpixelclock = 65000, + .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028, + }, { + .mpixelclock = 66000, + .cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038, + }, { + .mpixelclock = 83500, + .cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028, + }, { + .mpixelclock = 146250, + .cpce = 0x0051, .gmp = 0x0002, .curr = 0x0038, + }, { + .mpixelclock = 148500, + .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000, + }, { + .mpixelclock = ~0ul, + .cpce = 0x0051, .gmp = 0x0003, .curr = 0x0000, + } +}; + +static const u32 csc_coeff_default[3][4] = { + { 0x2000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x2000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x2000, 0x0000 } +}; + +static void hdmi_set_clock_regenerator(u32 n, u32 cts) +{ + u8 cts3; + u8 n3; + + /* first set ncts_atomic_write (if present) */ + n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE; + writel(n3, &hdmi_regs->aud_n3); + + /* set cts_manual (if present) */ + cts3 = HDMI_AUD_CTS3_CTS_MANUAL; + + cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET; + cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK; + + /* write cts values; cts3 must be written first */ + writel(cts3, &hdmi_regs->aud_cts3); + writel((cts >> 8) & 0xff, &hdmi_regs->aud_cts2); + writel(cts & 0xff, &hdmi_regs->aud_cts1); + + /* write n values; n1 must be written last */ + n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK; + writel(n3, &hdmi_regs->aud_n3); + writel((n >> 8) & 0xff, &hdmi_regs->aud_n2); + writel(n & 0xff, &hdmi_regs->aud_n1); + + writel(HDMI_AUD_INPUTCLKFS_128, &hdmi_regs->aud_inputclkfs); +} + +static int hdmi_lookup_n_cts(u32 pixel_clk) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(n_cts_table); i++) + if (pixel_clk <= n_cts_table[i].tmds) + break; + + if (i >= ARRAY_SIZE(n_cts_table)) + return -1; + + return i; +} + +static void hdmi_audio_set_samplerate(u32 pixel_clk) +{ + u32 clk_n, clk_cts; + int index; + + index = hdmi_lookup_n_cts(pixel_clk); + if (index == -1) { + hdmi_debug("audio not supported for pixel clk %d\n", pixel_clk); + return; + } + + clk_n = n_cts_table[index].n; + clk_cts = n_cts_table[index].cts; + hdmi_set_clock_regenerator(clk_n, clk_cts); +} + +/* + * this submodule is responsible for the video data synchronization. + * for example, for rgb 4:4:4 input, the data map is defined as + * pin{47~40} <==> r[7:0] + * pin{31~24} <==> g[7:0] + * pin{15~8} <==> b[7:0] + */ +static void hdmi_video_sample(void) +{ + u32 color_format = 0x01; + u8 val; + + val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE | + ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) & + HDMI_TX_INVID0_VIDEO_MAPPING_MASK); + + writel(val, &hdmi_regs->tx_invid0); + + /* enable tx stuffing: when de is inactive, fix the output data to 0 */ + val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE | + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE | + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE; + writel(val, &hdmi_regs->tx_instuffing); + writel(0x0, &hdmi_regs->tx_gydata0); + writel(0x0, &hdmi_regs->tx_gydata1); + writel(0x0, &hdmi_regs->tx_rcrdata0); + writel(0x0, &hdmi_regs->tx_rcrdata1); + writel(0x0, &hdmi_regs->tx_bcbdata0); + writel(0x0, &hdmi_regs->tx_bcbdata1); +} + +static void hdmi_update_csc_coeffs(void) +{ + u32 i, j; + u32 csc_scale = 1; + + /* the csc registers are sequential, alternating msb then lsb */ + for (i = 0; i < ARRAY_SIZE(csc_coeff_default); i++) { + for (j = 0; j < ARRAY_SIZE(csc_coeff_default[0]); j++) { + u32 coeff = csc_coeff_default[i][j]; + writel(coeff >> 8, &hdmi_regs->csc_coef[i][j].msb); + writel(coeff && 0xff, &hdmi_regs->csc_coef[i][j].lsb); + } + } + + clrsetbits_le32(&hdmi_regs->csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK, + csc_scale); +} + +static void hdmi_video_csc(void) +{ + u32 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP; + u32 interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; + + /* configure the csc registers */ + writel(interpolation, &hdmi_regs->csc_cfg); + clrsetbits_le32(&hdmi_regs->csc_scale, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, color_depth); + + hdmi_update_csc_coeffs(); +} + +static void hdmi_video_packetize(void) +{ + u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; + u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT; + u32 color_depth = 0; + u8 val, vp_conf; + + /* set the packetizer registers */ + val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & + HDMI_VP_PR_CD_COLOR_DEPTH_MASK) | + ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) & + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK); + writel(val, &hdmi_regs->vp_pr_cd); + + clrsetbits_le32(&hdmi_regs->vp_stuff, HDMI_VP_STUFF_PR_STUFFING_MASK, + HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE); + + /* data from pixel repeater block */ + vp_conf = HDMI_VP_CONF_PR_EN_DISABLE | + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER; + + clrsetbits_le32(&hdmi_regs->vp_conf, HDMI_VP_CONF_PR_EN_MASK | + HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf); + + clrsetbits_le32(&hdmi_regs->vp_stuff, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, + 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET); + + writel(remap_size, &hdmi_regs->vp_remap); + + vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE | + HDMI_VP_CONF_PP_EN_DISABLE | + HDMI_VP_CONF_YCC422_EN_DISABLE; + + clrsetbits_le32(&hdmi_regs->vp_conf, HDMI_VP_CONF_BYPASS_EN_MASK | + HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK, + vp_conf); + + clrsetbits_le32(&hdmi_regs->vp_stuff, HDMI_VP_STUFF_PP_STUFFING_MASK | + HDMI_VP_STUFF_YCC422_STUFFING_MASK, + HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE | + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE); + + clrsetbits_le32(&hdmi_regs->vp_conf, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK, + output_select); +} + +static inline void hdmi_phy_test_clear(u8 bit) +{ + clrsetbits_le32(&hdmi_regs->phy_tst0, HDMI_PHY_TST0_TSTCLR_MASK, + bit << HDMI_PHY_TST0_TSTCLR_OFFSET); +} + +static int hdmi_phy_wait_i2c_done(u32 msec) +{ + struct stopwatch phyi2c_done; + u32 val; + + stopwatch_init_msecs_expire(&phyi2c_done, msec); + do { + val = readl(&hdmi_regs->ih_i2cmphy_stat0); + if (val & 0x3) { + writel(val, &hdmi_regs->ih_i2cmphy_stat0); + return 0; + } + + udelay(100); + } while (!stopwatch_expired(&phyi2c_done)); + + return 1; +} + +static void hdmi_phy_i2c_write(u16 data, u8 addr) +{ + writel(0xff, &hdmi_regs->ih_i2cmphy_stat0); + writel(addr, &hdmi_regs->phy_i2cm_address_addr); + writel((u8)(data >> 8), &hdmi_regs->phy_i2cm_datao_1_addr); + writel((u8)(data >> 0), &hdmi_regs->phy_i2cm_datao_0_addr); + writel(HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, + &hdmi_regs->phy_i2cm_operation_addr); + + hdmi_phy_wait_i2c_done(1000); +} + +static void hdmi_phy_enable_power(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, HDMI_PHY_CONF0_PDZ_MASK, + enable << HDMI_PHY_CONF0_PDZ_OFFSET); +} + +static void hdmi_phy_enable_tmds(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, HDMI_PHY_CONF0_ENTMDS_MASK, + enable << HDMI_PHY_CONF0_ENTMDS_OFFSET); +} + +static void hdmi_phy_enable_spare(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, HDMI_PHY_CONF0_SPARECTRL_MASK, + enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET); +} + +static void hdmi_phy_gen2_pddq(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK, + enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET); +} + +static void hdmi_phy_gen2_txpwron(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK, + enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET); +} + +static void hdmi_phy_sel_data_en_pol(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, + HDMI_PHY_CONF0_SELDATAENPOL_MASK, + enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET); +} + +static void hdmi_phy_sel_interface_control(u8 enable) +{ + clrsetbits_le32(&hdmi_regs->phy_conf0, HDMI_PHY_CONF0_SELDIPIF_MASK, + enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET); +} + +static int hdmi_phy_configure(u32 mpixelclock) +{ + struct stopwatch pll_ready; + u8 i, val; + + writel(HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS, + &hdmi_regs->mc_flowctrl); + + /* gen2 tx power off */ + hdmi_phy_gen2_txpwron(0); + + /* gen2 pddq */ + hdmi_phy_gen2_pddq(1); + + /* phy reset */ + writel(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi_regs->mc_phyrstz); + writel(HDMI_MC_PHYRSTZ_ASSERT, &hdmi_regs->mc_phyrstz); + writel(HDMI_MC_HEACPHY_RST_ASSERT, &hdmi_regs->mc_heacphy_rst); + + hdmi_phy_test_clear(1); + writel(HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, + &hdmi_regs->phy_i2cm_slave_addr); + hdmi_phy_test_clear(0); + + /* pll/mpll cfg - always match on final entry */ + for (i = 0; rockchip_mpll_cfg[i].mpixelclock != (~0ul); i++) + if (mpixelclock <= rockchip_mpll_cfg[i].mpixelclock) + break; + + hdmi_phy_i2c_write(rockchip_mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG); + hdmi_phy_i2c_write(rockchip_mpll_cfg[i].gmp, PHY_PLLGMPCTRL); + hdmi_phy_i2c_write(rockchip_mpll_cfg[i].curr, PHY_PLLCURRCTRL); + + hdmi_phy_i2c_write(0x0000, PHY_PLLPHBYCTRL); + hdmi_phy_i2c_write(0x0006, PHY_PLLCLKBISTPHASE); + + for (i = 0; rockchip_phy_config[i].mpixelclock != (~0ul); i++) + if (mpixelclock <= rockchip_phy_config[i].mpixelclock) + break; + + /* + * resistance term 133ohm cfg + * preemp cgf 0.00 + * tx/ck lvl 10 + */ + hdmi_phy_i2c_write(rockchip_phy_config[i].term, PHY_TXTERM); + hdmi_phy_i2c_write(rockchip_phy_config[i].sym_ctr, PHY_CKSYMTXCTRL); + hdmi_phy_i2c_write(rockchip_phy_config[i].vlev_ctr, PHY_VLEVCTRL); + + /* remove clk term */ + hdmi_phy_i2c_write(0x8000, PHY_CKCALCTRL); + + hdmi_phy_enable_power(1); + + /* toggle tmds enable */ + hdmi_phy_enable_tmds(0); + hdmi_phy_enable_tmds(1); + + /* gen2 tx power on */ + hdmi_phy_gen2_txpwron(1); + hdmi_phy_gen2_pddq(0); + + hdmi_phy_enable_spare(1); + + /* wait for phy pll lock */ + stopwatch_init_msecs_expire(&pll_ready, 5); + do { + val = readl(&hdmi_regs->phy_stat0); + if (!(val & HDMI_PHY_TX_PHY_LOCK)) + return 0; + + udelay(100); + } while (!stopwatch_expired(&pll_ready)); + + return -1; +} + +static int hdmi_phy_init(u32 mpixelclock) +{ + int i, ret; + + /* hdmi phy spec says to do the phy initialization sequence twice */ + for (i = 0; i < 2; i++) { + hdmi_phy_sel_data_en_pol(1); + hdmi_phy_sel_interface_control(0); + hdmi_phy_enable_tmds(0); + hdmi_phy_enable_power(0); + + /* enable csc */ + ret = hdmi_phy_configure(mpixelclock); + if (ret) { + hdmi_debug("hdmi phy config failure %d\n", ret); + return ret; + } + } + + return 0; +} + +static void hdmi_av_composer(const struct edid *edid) +{ + u8 mdataenablepolarity = 1; + u8 inv_val; + + /* set up hdmi_fc_invidconf */ + inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE; + + inv_val |= ((edid->mode.pvsync == '+') ? + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= ((edid->mode.phsync == '+') ? + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (mdataenablepolarity ? + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (edid->hdmi_monitor_detected ? + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE); + + inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW; + + inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; + + writel(inv_val, &hdmi_regs->fc_invidconf); + + /* set up horizontal active pixel width */ + writel(edid->mode.ha >> 8, &hdmi_regs->fc_inhactv1); + writel(edid->mode.ha, &hdmi_regs->fc_inhactv0); + + /* set up vertical active lines */ + writel(edid->mode.va >> 8, &hdmi_regs->fc_invactv1); + writel(edid->mode.va, &hdmi_regs->fc_invactv0); + + /* set up horizontal blanking pixel region width */ + writel(edid->mode.hbl >> 8, &hdmi_regs->fc_inhblank1); + writel(edid->mode.hbl, &hdmi_regs->fc_inhblank0); + + /* set up vertical blanking pixel region width */ + writel(edid->mode.vbl, &hdmi_regs->fc_invblank); + + /* set up hsync active edge delay width (in pixel clks) */ + writel(edid->mode.hso >> 8, &hdmi_regs->fc_hsyncindelay1); + writel(edid->mode.hso, &hdmi_regs->fc_hsyncindelay0); + + /* set up vsync active edge delay (in lines) */ + writel(edid->mode.vso, &hdmi_regs->fc_vsyncindelay); + + /* set up hsync active pulse width (in pixel clks) */ + writel(edid->mode.hspw >> 8, &hdmi_regs->fc_hsyncinwidth1); + writel(edid->mode.hspw, &hdmi_regs->fc_hsyncinwidth0); + + /* set up vsync active edge delay (in lines) */ + writel(edid->mode.vspw, &hdmi_regs->fc_vsyncinwidth); +} + +/* hdmi initialization step b.4 */ +static void hdmi_enable_video_path(void) +{ + u8 clkdis; + + /* control period minimum duration */ + writel(12, &hdmi_regs->fc_ctrldur); + writel(32, &hdmi_regs->fc_exctrldur); + writel(1, &hdmi_regs->fc_exctrlspac); + + /* set to fill tmds data channels */ + writel(0x0b, &hdmi_regs->fc_ch0pream); + writel(0x16, &hdmi_regs->fc_ch1pream); + writel(0x21, &hdmi_regs->fc_ch2pream); + + /* enable pixel clock and tmds data path */ + clkdis = 0x7f; + clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; + writel(clkdis, &hdmi_regs->mc_clkdis); + + clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE; + writel(clkdis, &hdmi_regs->mc_clkdis); + + clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; + writel(clkdis, &hdmi_regs->mc_clkdis); +} + +/* workaround to clear the overflow condition */ +static void hdmi_clear_overflow(void) +{ + u8 val, count; + + /* tmds software reset */ + writel((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi_regs->mc_swrstz); + + val = readl(&hdmi_regs->fc_invidconf); + + for (count = 0; count < 4; count++) + writel(val, &hdmi_regs->fc_invidconf); +} + +static void hdmi_audio_set_format(void) +{ + writel(HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0, + &hdmi_regs->aud_conf0); + + + writel(HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE | + HDMI_AUD_CONF1_I2S_WIDTH_16BIT, + &hdmi_regs->aud_conf1); + + writel(0x00, &hdmi_regs->aud_conf2); +} + +static void hdmi_audio_fifo_reset(void) +{ + writel((u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, &hdmi_regs->mc_swrstz); + writel(HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, &hdmi_regs->aud_conf0); + + writel(0x00, &hdmi_regs->aud_int); + writel(0x00, &hdmi_regs->aud_int1); +} + +static int hdmi_setup(const struct edid *edid) +{ + int ret; + + hdmi_debug("hdmi, mode info : clock %d hdis %d vdis %d\n", + edid->mode.pixel_clock, edid->mode.ha, edid->mode.va); + + hdmi_av_composer(edid); + + ret = hdmi_phy_init(edid->mode.pixel_clock); + if (ret) + return ret; + + hdmi_enable_video_path(); + + hdmi_audio_fifo_reset(); + hdmi_audio_set_format(); + hdmi_audio_set_samplerate(edid->mode.pixel_clock); + + hdmi_video_packetize(); + hdmi_video_csc(); + hdmi_video_sample(); + + hdmi_clear_overflow(); + + return 0; +} + +static void hdmi_init_interrupt(void) +{ + u8 ih_mute; + + /* + * boot up defaults are: + * hdmi_ih_mute = 0x03 (disabled) + * hdmi_ih_mute_* = 0x00 (enabled) + * + * disable top level interrupt bits in hdmi block + */ + ih_mute = readl(&hdmi_regs->ih_mute) | + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT | + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT; + + writel(ih_mute, &hdmi_regs->ih_mute); + + /* enable i2c master done irq */ + writel(~0x04, &hdmi_regs->i2cm_int); + + /* enable i2c client nack % arbitration error irq */ + writel(~0x44, &hdmi_regs->i2cm_ctlint); + + /* enable phy i2cm done irq */ + writel(HDMI_PHY_I2CM_INT_ADDR_DONE_POL, &hdmi_regs->phy_i2cm_int_addr); + + /* enable phy i2cm nack & arbitration error irq */ + writel(HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL | + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL, + &hdmi_regs->phy_i2cm_ctlint_addr); + + /* enable cable hot plug irq */ + writel((u8)~HDMI_PHY_HPD, &hdmi_regs->phy_mask0); + + /* clear hotplug interrupts */ + writel(HDMI_IH_PHY_STAT0_HPD, &hdmi_regs->ih_phy_stat0); +} + +static u8 hdmi_get_plug_in_status(void) +{ + u8 val = readl(&hdmi_regs->phy_stat0) & HDMI_PHY_HPD; + + return !!(val); +} + +static int hdmi_wait_for_hpd(void) +{ + struct stopwatch hpd; + + stopwatch_init_msecs_expire(&hpd, 30000); + do { + if (hdmi_get_plug_in_status()) + return 0; + udelay(100); + } while (!stopwatch_expired(&hpd)); + + return -1; +} + +static int hdmi_ddc_wait_i2c_done(int msec) +{ + struct stopwatch ddci2c_done; + u32 val; + + stopwatch_init_msecs_expire(&ddci2c_done, msec); + do { + val = readl(&hdmi_regs->ih_i2cm_stat0); + if (val & 0x2) { + writel(val, &hdmi_regs->ih_i2cm_stat0); + return 0; + } + + udelay(100); + } while (!stopwatch_expired(&ddci2c_done)); + + return 1; +} + +static void hdmi_ddc_reset(void) +{ + clrbits_le32(&hdmi_regs->i2cm_softrstz, HDMI_I2CM_SOFTRSTZ); +} + +static int hdmi_read_edid(int block, u8 *buff) +{ + int shift = (block % 2) * 0x80; + int edid_read_err = 0; + u32 trytime = 5; + u32 n, j, val; + + /* set ddc i2c clk which devided from ddc_clk to 100khz */ + writel(0x7a, &hdmi_regs->i2cm_ss_scl_hcnt_0_addr); + writel(0x8d, &hdmi_regs->i2cm_ss_scl_lcnt_0_addr); + clrsetbits_le32(&hdmi_regs->i2cm_div, HDMI_I2CM_DIV_FAST_STD_MODE, + HDMI_I2CM_DIV_STD_MODE); + + writel(HDMI_I2CM_SLAVE_DDC_ADDR, &hdmi_regs->i2cm_slave); + writel(HDMI_I2CM_SEGADDR_DDC, &hdmi_regs->i2cm_segaddr); + writel(block >> 1, &hdmi_regs->i2cm_segptr); + + while (trytime--) { + edid_read_err = 0; + + for (n = 0; n < HDMI_EDID_BLOCK_SIZE/8; n++) { + writel(shift + 8 * n, &hdmi_regs->i2cmess); + + if (block == 0) + clrsetbits_le32(&hdmi_regs->i2cm_operation, + HDMI_I2CM_OPT_RD8, + HDMI_I2CM_OPT_RD8); + else + clrsetbits_le32(&hdmi_regs->i2cm_operation, + HDMI_I2CM_OPT_RD8_EXT, + HDMI_I2CM_OPT_RD8_EXT); + + if (hdmi_ddc_wait_i2c_done(10)) { + hdmi_ddc_reset(); + edid_read_err = 1; + break; + } + + for (j = 0; j < 8; j++) { + val = readl(&hdmi_regs->i2cm_buf0 + j); + buff[8 * n + j] = val; + } + } + + if (!edid_read_err) + break; + } + + return edid_read_err; +} + +int rk_hdmi_get_edid(struct edid *edid) +{ + u8 edid_buf[HDMI_EDID_BLOCK_SIZE * 2]; + u32 edid_size = HDMI_EDID_BLOCK_SIZE; + gpio_t hdmi_i2c_sda = GPIO(7, C, 3); + gpio_t hdmi_i2c_scl = GPIO(7, C, 4); + int ret; + + /* If SDA is low, try to clock once to fix it */ + gpio_input_pullup(hdmi_i2c_sda); + if (gpio_get(hdmi_i2c_sda) == 0) { + gpio_output(hdmi_i2c_scl, 0); + udelay(1000); + gpio_input_pullup(hdmi_i2c_scl); + udelay(1000); + } + + /* HDMI I2C */ + writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda); + writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl); + + ret = hdmi_read_edid(0, edid_buf); + if (ret) { + hdmi_debug("failed to read edid.\n"); + return -1; + } + + if (edid_buf[0x7e] != 0) { + hdmi_read_edid(1, edid_buf + HDMI_EDID_BLOCK_SIZE); + edid_size += HDMI_EDID_BLOCK_SIZE; + } + + /* Assume usage of HDMI implies an external display in which case + * we should be lenient about errors that the EDID decoder finds. */ + if (decode_edid(edid_buf, edid_size, edid, 165000)) + hdmi_debug("failed to decode edid.\n"); + + /* Try 480p for best compatibility. */ + if (set_display_mode(edid, EDID_MODE_640x480_60Hz)) + hdmi_debug("failed to set mode to 640x480@60Hz\n"); + + return 0; +} + +int rk_hdmi_enable(const struct edid *edid) +{ + hdmi_setup(edid); + + return 0; +} + +int rk_hdmi_init(u32 vop_id) +{ + int ret; + u32 val; + + /* hdmi source select hdmi controller */ + writel(RK_SETBITS(1 << 15), &rk3288_grf->soc_con6); + + /* hdmi data from vop id */ + val = (vop_id == 1) ? RK_SETBITS(1 << 4) : RK_CLRBITS(1 << 4); + writel(val, &rk3288_grf->soc_con6); + + ret = hdmi_wait_for_hpd(); + if (ret < 0) { + hdmi_debug("hdmi can not get hpd signal\n"); + return -1; + } + + hdmi_init_interrupt(); + + hdmi_debug("hdmi init success\n"); + + return 0; +} diff --git a/src/soc/rockchip/rk3288/i2c.c b/src/soc/rockchip/rk3288/i2c.c new file mode 100644 index 0000000000..d69bb7cb78 --- /dev/null +++ b/src/soc/rockchip/rk3288/i2c.c @@ -0,0 +1,314 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RETRY_COUNT 3 +/* 100000us = 100ms */ +#define I2C_TIMEOUT_US 100000 +#define I2C_BUS_MAX 6 +#define I2C_NOACK 2 +#define I2C_TIMEOUT 3 + +#define i2c_info(x...) do {if (0) printk(BIOS_DEBUG, x); } while (0) + +struct rk3288_i2c_regs { + u32 i2c_con; + u32 i2c_clkdiv; + u32 i2c_mrxaddr; + u32 i2c_mrxraddr; + u32 i2c_mtxcnt; + u32 i2c_mrxcnt; + u32 i2c_ien; + u32 i2c_ipd; + u32 i2c_fcnt; + u32 reserved0[(0x100 - 0x24) / 4]; + u32 txdata[8]; + u32 reserved1[(0x200 - 0x120) / 4]; + u32 rxdata[8]; +}; + +struct rk3288_i2c_regs *i2c_bus[] = { + (struct rk3288_i2c_regs *)0xff650000, + (struct rk3288_i2c_regs *)0xff140000, + (struct rk3288_i2c_regs *)0xff660000, + (struct rk3288_i2c_regs *)0xff150000, + (struct rk3288_i2c_regs *)0xff160000, + (struct rk3288_i2c_regs *)0xff170000, +}; + +/* Con register bits. */ +#define I2C_ACT2NAK (1<<6) +#define I2C_NAK (1<<5) +#define I2C_STOP (1<<4) +#define I2C_START (1<<3) +#define I2C_MODE_TX (0<<1) +#define I2C_MODE_TRX (1<<1) +#define I2C_MODE_RX (2<<1) +#define I2C_EN (1<<0) + +#define I2C_8BIT (1<<24) +#define I2C_16BIT (3<<24) +#define I2C_24BIT (7<<24) + +/* Mtxcnt register bits. */ +#define I2C_CNT(cnt) ((cnt) & 0x3F) + +#define I2C_NAKRCVI (1<<6) +#define I2C_STOPI (1<<5) +#define I2C_STARTI (1<<4) +#define I2C_MBRFI (1<<3) +#define I2C_MBTFI (1<<2) +#define I2C_BRFI (1<<1) +#define I2C_BTFI (1<<0) +#define I2C_CLEANI 0x7F + +static int i2c_send_start(struct rk3288_i2c_regs *reg_addr) +{ + int res = 0; + int timeout = I2C_TIMEOUT_US; + + i2c_info("I2c Start::Send Start bit\n"); + writel(I2C_CLEANI, ®_addr->i2c_ipd); + writel(I2C_EN | I2C_START, ®_addr->i2c_con); + while (timeout--) { + if (readl(®_addr->i2c_ipd) & I2C_STARTI) + break; + udelay(1); + } + + if (timeout <= 0) { + printk(BIOS_ERR, "I2C Start::Send Start Bit Timeout\n"); + res = I2C_TIMEOUT; + } + + return res; +} + +static int i2c_send_stop(struct rk3288_i2c_regs *reg_addr) +{ + int res = 0; + int timeout = I2C_TIMEOUT_US; + + i2c_info("I2c Stop::Send Stop bit\n"); + writel(I2C_CLEANI, ®_addr->i2c_ipd); + writel(I2C_EN | I2C_STOP, ®_addr->i2c_con); + while (timeout--) { + if (readl(®_addr->i2c_ipd) & I2C_STOPI) + break; + udelay(1); + } + writel(0, ®_addr->i2c_con); + if (timeout <= 0) { + printk(BIOS_ERR, "I2C Stop::Send Stop Bit Timeout\n"); + res = I2C_TIMEOUT; + } + + return res; +} + +static int i2c_read(struct rk3288_i2c_regs *reg_addr, struct i2c_seg segment) +{ + int res = 0; + uint8_t *data = segment.buf; + int timeout = I2C_TIMEOUT_US; + unsigned int bytes_remaining = segment.len; + unsigned int bytes_transfered = 0; + unsigned int words_transfered = 0; + unsigned int rxdata = 0; + unsigned int con = 0; + unsigned int i, j; + + writel(I2C_8BIT | segment.chip << 1 | 1, ®_addr->i2c_mrxaddr); + writel(0, ®_addr->i2c_mrxraddr); + con = I2C_MODE_TRX | I2C_EN | I2C_ACT2NAK; + while (bytes_remaining) { + bytes_transfered = MIN(bytes_remaining, 32); + bytes_remaining -= bytes_transfered; + if (!bytes_remaining) + con |= I2C_EN | I2C_NAK; + words_transfered = ALIGN_UP(bytes_transfered, 4) / 4; + + writel(I2C_CLEANI, ®_addr->i2c_ipd); + writel(con, ®_addr->i2c_con); + writel(bytes_transfered, ®_addr->i2c_mrxcnt); + + timeout = I2C_TIMEOUT_US; + while (timeout--) { + if (readl(®_addr->i2c_ipd) & I2C_NAKRCVI) { + writel(0, ®_addr->i2c_mrxcnt); + writel(0, ®_addr->i2c_con); + return I2C_NOACK; + } + if (readl(®_addr->i2c_ipd) & I2C_MBRFI) + break; + udelay(1); + } + if (timeout <= 0) { + printk(BIOS_ERR, "I2C Read::Recv Data Timeout\n"); + writel(0, ®_addr->i2c_mrxcnt); + writel(0, ®_addr->i2c_con); + return I2C_TIMEOUT; + } + + for (i = 0; i < words_transfered; i++) { + rxdata = readl(®_addr->rxdata[i]); + i2c_info("I2c Read::RXDATA[%d] = 0x%x\n", i, rxdata); + for (j = 0; j < 4; j++) { + if ((i * 4 + j) == bytes_transfered) + break; + *data++ = (rxdata >> (j * 8)) & 0xff; + } + } + con = I2C_MODE_RX | I2C_EN | I2C_ACT2NAK; + } + return res; +} + +static int i2c_write(struct rk3288_i2c_regs *reg_addr, struct i2c_seg segment) +{ + int res = 0; + uint8_t *data = segment.buf; + int timeout = I2C_TIMEOUT_US; + int bytes_remaining = segment.len + 1; + int bytes_transfered = 0; + int words_transfered = 0; + unsigned int i; + unsigned int j = 1; + u32 txdata = 0; + + txdata |= (segment.chip << 1); + while (bytes_remaining) { + bytes_transfered = MIN(bytes_remaining, 32); + words_transfered = ALIGN_UP(bytes_transfered, 4) / 4; + for (i = 0; i < words_transfered; i++) { + do { + if ((i * 4 + j) == bytes_transfered) + break; + txdata |= (*data++) << (j * 8); + } while (++j < 4); + writel(txdata, ®_addr->txdata[i]); + j = 0; + i2c_info("I2c Write::TXDATA[%d] = 0x%x\n", i, txdata); + txdata = 0; + } + + writel(I2C_CLEANI, ®_addr->i2c_ipd); + writel(I2C_EN | I2C_MODE_TX | I2C_ACT2NAK, ®_addr->i2c_con); + writel(bytes_transfered, ®_addr->i2c_mtxcnt); + + timeout = I2C_TIMEOUT_US; + while (timeout--) { + if (readl(®_addr->i2c_ipd) & I2C_NAKRCVI) { + writel(0, ®_addr->i2c_mtxcnt); + writel(0, ®_addr->i2c_con); + return I2C_NOACK; + } + if (readl(®_addr->i2c_ipd) & I2C_MBTFI) + break; + udelay(1); + } + + if (timeout <= 0) { + printk(BIOS_ERR, "I2C Write::Send Data Timeout\n"); + writel(0, ®_addr->i2c_mtxcnt); + writel(0, ®_addr->i2c_con); + return I2C_TIMEOUT; + } + + bytes_remaining -= bytes_transfered; + } + return res; +} + +static int i2c_do_xfer(void *reg_addr, struct i2c_seg segment) +{ + int res = 0; + + if (i2c_send_start(reg_addr)) + return I2C_TIMEOUT; + if (segment.read) + res = i2c_read(reg_addr, segment); + else + res = i2c_write(reg_addr, segment); + return i2c_send_stop(reg_addr) || res; +} + +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count) +{ + int i; + int res = 0; + struct rk3288_i2c_regs *regs = i2c_bus[bus]; + struct i2c_seg *seg = segments; + + for (i = 0; i < seg_count; i++, seg++) { + res = i2c_do_xfer(regs, *seg); + if (res) + break; + } + return res; +} + +void i2c_init(unsigned int bus, unsigned int hz) +{ + unsigned int clk_div; + unsigned int divl; + unsigned int divh; + unsigned int i2c_src_clk = 0; + struct rk3288_i2c_regs *regs = i2c_bus[bus]; + + /*i2c0,i2c2 src clk from pd_bus_pclk + other i2c src clk from peri_pclk + */ + switch (bus) { + case 0: + case 2: + i2c_src_clk = PD_BUS_PCLK_HZ; + break; + case 1: + case 3: + case 4: + case 5: + i2c_src_clk = PERI_PCLK_HZ; + break; + default: + break; + } + + /*SCL Divisor = 8*(CLKDIVL + 1 + CLKDIVH + 1) + SCL = PCLK/ SCLK Divisor + */ + clk_div = div_round_up(i2c_src_clk, hz * 8); + divh = clk_div * 3 / 7 - 1; + divl = clk_div - divh - 2; + assert((divh < 65536) && (divl < 65536)); + writel((divh << 16) | (divl << 0), ®s->i2c_clkdiv); +} diff --git a/src/soc/rockchip/rk3288/include/soc/addressmap.h b/src/soc/rockchip/rk3288/include/soc/addressmap.h new file mode 100644 index 0000000000..14f145f8ab --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/addressmap.h @@ -0,0 +1,107 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_ADDRESSMAP_H__ +#define __SOC_ROCKCHIP_RK3288_ADDRESSMAP_H__ + +#define SDMMC1_BASE 0xFF0C0000 +#define SDMMC0_BASE 0xFF0D0000 +#define EMMC_BASE 0xFF0F0000 +#define SARADC_BASE 0xFF100000 + +#define SPI0_BASE 0xFF110000 +#define SPI1_BASE 0xFF120000 +#define SPI2_BASE 0xFF130000 + +#define I2C1_BASE 0xFF140000 +#define I2C3_BASE 0xFF150000 +#define I2C4_BASE 0xFF160000 +#define I2C5_BASE 0xFF170000 +#define UART0_BASE 0xFF180000 +#define UART1_BASE 0xFF190000 +#define DMAC_PERI_BASE 0xFF250000 +#define TSADC_BASE 0xFF280000 + +#define NANDC0_BASE 0xFF400000 +#define NANDC1_BASE 0xFF410000 + +#define USB_HOST0_EHCI_BASE 0xFF500000 +#define USB_HOST0_OHCI_BASE 0xFF520000 +#define USB_HOST1_BASE 0xFF540000 +#define USB_OTG_BASE 0xFF580000 + +#define DMAC_BUS_BASE 0xFF600000 + +#define DDR_PCTL0_BASE 0xFF610000 +#define DDR_PCTL1_BASE 0xFF630000 +#define DDR_PUBL0_BASE 0xFF620000 +#define DDR_PUBL1_BASE 0xFF640000 + +#define I2C0_BASE 0xFF650000 +#define I2C2_BASE 0xFF660000 +#define DW_PWM0123_BASE 0xFF670000 +#define RK_PWM0123_BASE 0xFF680000 +#define UART2_BASE 0xFF690000 +#define TIMER0_BASE 0xFF6B0000 + +#define SRAM_BASE 0xFF700000 +#define PMU_BASE 0xFF730000 +#define GRF_SECURE_BASE 0xFF740000 +#define GPIO0_BASE 0xFF750000 +#define CRU_BASE 0xFF760000 +#define GRF_BASE 0xFF770000 +#define GPIO1_BASE 0xFF780000 +#define GPIO2_BASE 0xFF790000 +#define GPIO3_BASE 0xFF7A0000 +#define GPIO4_BASE 0xFF7B0000 +#define GPIO5_BASE 0xFF7C0000 +#define GPIO6_BASE 0xFF7D0000 +#define GPIO7_BASE 0xFF7E0000 +#define GPIO8_BASE 0xFF7F0000 + +#define TIMER6_BASE 0xFF810000 +#define TIMER7_BASE 0xFF810020 + +#define CRYPTO_BASE 0xFF8A0000 + +#define VOP_BIG_BASE 0xFF930000 +#define VOP_LIT_BASE 0xFF940000 +#define EDP_BASE 0xFF970000 + +#define HDMI_TX_BASE 0xFF980000 + +#define SERVICE_CORE_BASE 0xFFA80000 +#define SERVICE_DMA_BASE 0xFFA90000 +#define SERVICE_GPU_BASE 0xFFAA0000 +#define SERVICE_PERI_BASE 0xFFAB0000 +#define SERVICE_BUS_BASE 0xFFAC0000 +#define SERVICE_VIO_BASE 0xFFAD0000 +#define SERVICE_VPU_BASE 0xFFAE0000 +#define SERVICE_HEVC_BASE 0xFFAF0000 + +#define EFUSE_BASE 0xFFB40000 + +#define CORE_GICD_BASE 0xFFC01000 +#define CORE_GICC_BASE 0xFFC02000 +#define CPU_AXI_BUS_BASE 0xFFE00000 + +#define BOOT_ROM_BASE 0xFFFF0000 +#define BOOT_ROM_CHIP_VER (BOOT_ROM+0x27F0) + +#endif /* __SOC_ROCKCHIP_RK3288_ADDRESSMAP_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/clock.h b/src/soc/rockchip/rk3288/include/soc/clock.h new file mode 100644 index 0000000000..671a9ffd18 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/clock.h @@ -0,0 +1,60 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_CLOCK_H__ +#define __SOC_ROCKCHIP_RK3288_CLOCK_H__ + +#include + +#define OSC_HZ (24*MHz) + +#define GPLL_HZ (594*MHz) +#define CPLL_HZ (384*MHz) +#define NPLL_HZ (384*MHz) + +enum apll_frequencies { + APLL_1800_MHZ, + APLL_1416_MHZ, + APLL_600_MHZ, +}; + +/* The SRAM is clocked off aclk_bus, so we want to max it out for boot speed. */ +#define PD_BUS_ACLK_HZ (297000*KHz) +#define PD_BUS_HCLK_HZ (148500*KHz) +#define PD_BUS_PCLK_HZ (74250*KHz) + +#define PERI_ACLK_HZ (148500*KHz) +#define PERI_HCLK_HZ (148500*KHz) +#define PERI_PCLK_HZ (74250*KHz) + +void rkclk_init(void); +void rkclk_configure_spi(unsigned int bus, unsigned int hz); +void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy); +void rkclk_ddr_phy_ctl_reset(u32 ch, u32 n); +void rkclk_configure_ddr(unsigned int hz); +void rkclk_configure_i2s(unsigned int hz); +void rkclk_configure_cpu(enum apll_frequencies apll_freq); +void rkclk_configure_crypto(unsigned int hz); +void rkclk_configure_tsadc(unsigned int hz); +void rkclk_configure_vop_aclk(u32 vop_id, u32 aclk_hz); +int rkclk_configure_vop_dclk(u32 vop_id, u32 dclk_hz); +void rkclk_configure_edp(void); +void rkclk_configure_hdmi(void); +int rkclk_was_watchdog_reset(void); +#endif /* __SOC_ROCKCHIP_RK3288_CLOCK_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/display.h b/src/soc/rockchip/rk3288/include/soc/display.h new file mode 100644 index 0000000000..b0b5e64d5e --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/display.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_DISPLAY_H__ +#define __SOC_ROCKCHIP_RK3288_DISPLAY_H__ + +void rk_display_init(device_t dev, u32 lcdbase, + unsigned long fb_size); + +void mainboard_power_on_backlight(void); + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/edp.h b/src/soc/rockchip/rk3288/include/soc/edp.h new file mode 100644 index 0000000000..fac1b81f31 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/edp.h @@ -0,0 +1,666 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __RK32_DP_H +#define __RK32_DP_H + +#include +#include + +struct rk3288_edp_regs { + u8 res0[0x10]; + u32 dp_tx_version; + u8 res1[0x4]; + u32 func_en_1; + u32 func_en_2; + u32 video_ctl_1; + u32 video_ctl_2; + u32 video_ctl_3; + u32 video_ctl_4; + u8 res2[0xc]; + u32 video_ctl_8; + u8 res3[0x4]; + u32 video_ctl_10; + u32 total_line_l; + u32 total_line_h; + u32 active_line_l; + u32 active_line_h; + u32 v_f_porch; + u32 vsync; + u32 v_b_porch; + u32 total_pixel_l; + u32 total_pixel_h; + u32 active_pixel_l; + u32 active_pixel_h; + u32 h_f_porch_l; + u32 h_f_porch_h; + u32 hsync_l; + u32 hysnc_h; + u32 h_b_porch_l; + u32 h_b_porch_h; + u32 vid_status; + u32 total_line_sta_l; + u32 total_line_sta_h; + u32 active_line_sta_l; + u32 active_line_sta_h; + u32 v_f_porch_sta; + u32 vsync_sta; + u32 v_b_porch_sta; + u32 total_pixel_sta_l; + u32 total_pixel_sta_h; + u32 active_pixel_sta_l; + u32 active_pixel_sta_h; + u32 h_f_porch_sta_l; + u32 h_f_porch_sta_h; + u32 hsync_sta_l; + u32 hsync_sta_h; + u32 h_b_porch_sta_l; + u32 h_b_porch__sta_h; + u8 res4[0x28]; + u32 pll_reg_1; + u8 res5[4]; + u32 ssc_reg; + u8 res6[0xc]; + u32 tx_common; + u32 tx_common2; + u8 res7[0x4]; + u32 dp_aux; + u32 dp_bias; + u32 dp_test; + u32 dp_pd; + u32 dp_reserv1; + u32 dp_reserv2; + u8 res8[0x224]; + u32 lane_map; + u8 res9[0x14]; + u32 analog_ctl_2; + u8 res10[0x48]; + u32 int_state; + u32 common_int_sta_1; + u32 common_int_sta_2; + u32 common_int_sta_3; + u32 common_int_sta_4; + u32 spdif_biphase_int_sta; + u8 res11[0x4]; + u32 dp_int_sta; + u32 common_int_mask_1; + u32 common_int_mask_2; + u32 common_int_mask_3; + u32 common_int_mask_4; + u8 res12[0x08]; + u32 int_sta_mask; + u32 int_ctl; + u8 res13[0x200]; + u32 sys_ctl_1; + u32 sys_ctl_2; + u32 sys_ctl_3; + u32 sys_ctl_4; + u32 dp_vid_ctl; + u8 res14[0x4]; + u32 dp_aud_ctl; + u8 res15[0x24]; + u32 pkt_send_ctl; + u8 res16[0x4]; + u32 dp_hdcp_ctl; + u8 res17[0x34]; + u32 link_bw_set; + u32 lane_count_set; + u32 dp_training_ptn_set; + u32 ln_link_trn_ctl[4]; + u8 res18[0x4]; + u32 dp_hw_link_training; + u8 res19[0x1c]; + u32 dp_debug_ctl; + u32 hpd_deglitch_l; + u32 hpd_deglitch_h; + u8 res20[0x14]; + u32 dp_link_debug_ctl; + u8 res21[0x1c]; + u32 m_vid_0; + u32 m_vid_1; + u32 m_vid_2; + u32 n_vid_0; + u32 n_vid_1; + u32 n_vid_2; + u32 m_vid_mon; + u8 res22[0x14]; + u32 dp_video_fifo_thrd; + u8 res23[0x8]; + u32 dp_audio_margin; + u8 res24[0x20]; + u32 dp_m_cal_ctl; + u32 m_vid_gen_filter_th; + u8 res25[0x10]; + u32 m_aud_gen_filter_th; + u8 res26[0x4]; + u32 aux_ch_sta; + u32 aux_err_num; + u32 aux_ch_defer_dtl; + u32 aux_rx_comm; + u32 buf_data_ctl; + u32 aux_ch_ctl_1; + u32 aux_addr_7_0; + u32 aux_addr_15_8; + u32 aux_addr_19_16; + u32 aux_ch_ctl_2; + u8 res27[0x18]; + u32 buf_data[16]; + u32 soc_general_ctl; + u8 res29[0x1e0]; + u32 pll_reg_2; + u32 pll_reg_3; + u32 pll_reg_4; + u8 res30[0x10]; + u32 pll_reg_5; +}; +check_member(rk3288_edp_regs, pll_reg_5, 0xa00); + +/* func_en_1 */ +#define VID_CAP_FUNC_EN_N (0x1 << 6) +#define VID_FIFO_FUNC_EN_N (0x1 << 5) +#define AUD_FIFO_FUNC_EN_N (0x1 << 4) +#define AUD_FUNC_EN_N (0x1 << 3) +#define HDCP_FUNC_EN_N (0x1 << 2) +#define SW_FUNC_EN_N (0x1 << 0) + +/* func_en_2 */ +#define SSC_FUNC_EN_N (0x1 << 7) +#define AUX_FUNC_EN_N (0x1 << 2) +#define SERDES_FIFO_FUNC_EN_N (0x1 << 1) +#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) + +/* video_ctl_1 */ +#define VIDEO_EN (0x1 << 7) +#define VIDEO_MUTE (0x1 << 6) + +/* video_ctl_2 */ +#define IN_D_RANGE_MASK (0x1 << 7) +#define IN_D_RANGE_SHIFT (7) +#define IN_D_RANGE_CEA (0x1 << 7) +#define IN_D_RANGE_VESA (0x0 << 7) +#define IN_BPC_MASK (0x7 << 4) +#define IN_BPC_SHIFT (4) +#define IN_BPC_12_BITS (0x3 << 4) +#define IN_BPC_10_BITS (0x2 << 4) +#define IN_BPC_8_BITS (0x1 << 4) +#define IN_BPC_6_BITS (0x0 << 4) +#define IN_COLOR_F_MASK (0x3 << 0) +#define IN_COLOR_F_SHIFT (0) +#define IN_COLOR_F_YCBCR444 (0x2 << 0) +#define IN_COLOR_F_YCBCR422 (0x1 << 0) +#define IN_COLOR_F_RGB (0x0 << 0) + +/* video_ctl_3 */ +#define IN_YC_COEFFI_MASK (0x1 << 7) +#define IN_YC_COEFFI_SHIFT (7) +#define IN_YC_COEFFI_ITU709 (0x1 << 7) +#define IN_YC_COEFFI_ITU601 (0x0 << 7) +#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_SHIFT (4) +#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) + +/* video_ctl_4 */ +#define BIST_EN (0x1 << 3) +#define BIST_WH_64 (0x1 << 2) +#define BIST_WH_32 (0x0 << 2) +#define BIST_TYPE_COLR_BAR (0x0 << 0) +#define BIST_TYPE_GRAY_BAR (0x1 << 0) +#define BIST_TYPE_MOBILE_BAR (0x2 << 0) + +/* video_ctl_8 */ +#define VID_HRES_TH(x) (((x) & 0xf) << 4) +#define VID_VRES_TH(x) (((x) & 0xf) << 0) + +/* video_ctl_10 */ +#define F_SEL (0x1 << 4) +#define INTERACE_SCAN_CFG (0x1 << 2) +#define INTERACD_SCAN_CFG_OFFSET 2 +#define VSYNC_POLARITY_CFG (0x1 << 1) +#define VSYNC_POLARITY_CFG_OFFSET 1 +#define HSYNC_POLARITY_CFG (0x1 << 0) +#define HSYNC_POLARITY_CFG_OFFSET 0 + +/* dp_pd */ +#define PD_INC_BG (0x1 << 7) +#define PD_EXP_BG (0x1 << 6) +#define PD_AUX (0x1 << 5) +#define PD_PLL (0x1 << 4) +#define PD_CH3 (0x1 << 3) +#define PD_CH2 (0x1 << 2) +#define PD_CH1 (0x1 << 1) +#define PD_CH0 (0x1 << 0) + +/* pll_reg_1 */ +#define REF_CLK_24M (0x1 << 1) +#define REF_CLK_27M (0x0 << 1) + +/* line_map */ +#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) +#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) +#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) +#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6) +#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4) +#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4) +#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4) +#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4) +#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2) +#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2) +#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2) +#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2) +#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0) +#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0) +#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) +#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) + +/* analog_ctl_2 */ +#define SEL_24M (0x1 << 3) + +/* common_int_sta_1 */ +#define VSYNC_DET (0x1 << 7) +#define PLL_LOCK_CHG (0x1 << 6) +#define SPDIF_ERR (0x1 << 5) +#define SPDIF_UNSTBL (0x1 << 4) +#define VID_FORMAT_CHG (0x1 << 3) +#define AUD_CLK_CHG (0x1 << 2) +#define VID_CLK_CHG (0x1 << 1) +#define SW_INT (0x1 << 0) + +/* common_int_sta_2 */ +#define ENC_EN_CHG (0x1 << 6) +#define HW_BKSV_RDY (0x1 << 3) +#define HW_SHA_DONE (0x1 << 2) +#define HW_AUTH_STATE_CHG (0x1 << 1) +#define HW_AUTH_DONE (0x1 << 0) + +/* common_int_sta_3 */ +#define AFIFO_UNDER (0x1 << 7) +#define AFIFO_OVER (0x1 << 6) +#define R0_CHK_FLAG (0x1 << 5) + +/* common_int_sta_4 */ +#define PSR_ACTIVE (0x1 << 7) +#define PSR_INACTIVE (0x1 << 6) +#define SPDIF_BI_PHASE_ERR (0x1 << 5) +#define HOTPLUG_CHG (0x1 << 2) +#define HPD_LOST (0x1 << 1) +#define PLUG (0x1 << 0) + +/* dp_int_sta */ +#define INT_HPD (0x1 << 6) +#define HW_LT_DONE (0x1 << 5) +#define SINK_LOST (0x1 << 3) +#define LINK_LOST (0x1 << 2) +#define RPLY_RECEIV (0x1 << 1) +#define AUX_ERR (0x1 << 0) + +/* int_ctl */ +#define SOFT_INT_CTRL (0x1 << 2) +#define INT_POL (0x1 << 0) + +/* sys_ctl_1 */ +#define DET_STA (0x1 << 2) +#define FORCE_DET (0x1 << 1) +#define DET_CTRL (0x1 << 0) + +/* sys_ctl_2 */ +#define CHA_CRI(x) (((x) & 0xf) << 4) +#define CHA_STA (0x1 << 2) +#define FORCE_CHA (0x1 << 1) +#define CHA_CTRL (0x1 << 0) + +/* sys_ctl_3 */ +#define HPD_STATUS (0x1 << 6) +#define F_HPD (0x1 << 5) +#define HPD_CTRL (0x1 << 4) +#define HDCP_RDY (0x1 << 3) +#define STRM_VALID (0x1 << 2) +#define F_VALID (0x1 << 1) +#define VALID_CTRL (0x1 << 0) + +/* sys_ctl_4 */ +#define FIX_M_AUD (0x1 << 4) +#define ENHANCED (0x1 << 3) +#define FIX_M_VID (0x1 << 2) +#define M_VID_UPDATE_CTRL (0x3 << 0) + +/* pll_reg_2 */ +#define LDO_OUTPUT_V_SEL_145 (2 << 6) +#define KVCO_DEFALUT (1 << 4) +#define CHG_PUMP_CUR_SEL_5US (1 << 2) +#define V2L_CUR_SEL_1MA (1 << 0) + +/* pll_reg_3 */ +#define LOCK_DET_CNT_SEL_256 (2 << 5) +#define LOOP_FILTER_RESET (0 << 4) +#define PALL_SSC_RESET (0 << 3) +#define LOCK_DET_BYPASS (0 << 2) +#define PLL_LOCK_DET_MODE (0 << 1) +#define PLL_LOCK_DET_FORCE (0 << 0) + +/* pll_reg_5 */ +#define REGULATOR_V_SEL_950MV (2 << 4) +#define STANDBY_CUR_SEL (0 << 3) +#define CHG_PUMP_INOUT_CTRL_1200MV (1 << 1) +#define CHG_PUMP_INPUT_CTRL_OP (0 << 0) + +/* ssc_reg */ +#define SSC_OFFSET (0 << 6) +#define SSC_MODE (1 << 4) +#define SSC_DEPTH (9 << 0) + +/* tx_common */ +#define TX_SWING_PRE_EMP_MODE (1 << 7) +#define PRE_DRIVER_PW_CTRL1 (0 << 5) +#define LP_MODE_CLK_REGULATOR (0 << 4) +#define RESISTOR_MSB_CTRL (0 << 3) +#define RESISTOR_CTRL (7 << 0) + +/* dp_aux */ +#define DP_AUX_COMMON_MODE (0 << 4) +#define DP_AUX_EN (0 << 3) +#define AUX_TERM_50OHM (3 << 0) + +/* dp_bias */ +#define DP_BG_OUT_SEL (4 << 4) +#define DP_DB_CUR_CTRL (0 << 3) +#define DP_BG_SEL (1 << 2) +#define DP_RESISTOR_TUNE_BG (2 << 0) + +/* dp_reserv2 */ +#define CH1_CH3_SWING_EMP_CTRL (5 << 4) +#define CH0_CH2_SWING_EMP_CTRL (5 << 0) + +/* dp_training_ptn_set */ +#define SCRAMBLING_DISABLE (0x1 << 5) +#define SCRAMBLING_ENABLE (0x0 << 5) +#define LINK_QUAL_PATTERN_SET_MASK (0x7 << 2) +#define LINK_QUAL_PATTERN_SET_HBR2 (0x5 << 2) +#define LINK_QUAL_PATTERN_SET_80BIT (0x4 << 2) +#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2) +#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2) +#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0) +#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0) +#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) +#define SW_TRAINING_PATTERN_SET_DISABLE (0x0 << 0) + +/* dp_hw_link_training_ctl */ +#define HW_LT_ERR_CODE_MASK 0x70 +#define HW_LT_ERR_CODE_SHIFT 4 +#define HW_LT_EN (0x1 << 0) + +/* dp_debug_ctl */ +#define PLL_LOCK (0x1 << 4) +#define F_PLL_LOCK (0x1 << 3) +#define PLL_LOCK_CTRL (0x1 << 2) +#define POLL_EN (0x1 << 1) +#define PN_INV (0x1 << 0) + +/* aux_ch_sta */ +#define AUX_BUSY (0x1 << 4) +#define AUX_STATUS_MASK (0xf << 0) + +/* aux_ch_defer_ctl */ +#define DEFER_CTRL_EN (0x1 << 7) +#define DEFER_COUNT(x) (((x) & 0x7f) << 0) + +/* aux_rx_comm */ +#define AUX_RX_COMM_I2C_DEFER (0x2 << 2) +#define AUX_RX_COMM_AUX_DEFER (0x2 << 0) + +/* buffer_data_ctl */ +#define BUF_CLR (0x1 << 7) +#define BUF_HAVE_DATA (0x1 << 4) +#define BUF_DATA_COUNT(x) (((x) & 0xf) << 0) + +/* aux_ch_ctl_1 */ +#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) +#define AUX_TX_COMM_MASK (0xf << 0) +#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) +#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3) +#define AUX_TX_COMM_MOT (0x1 << 2) +#define AUX_TX_COMM_WRITE (0x0 << 0) +#define AUX_TX_COMM_READ (0x1 << 0) + +/* aux_ch_ctl_2 */ +#define PD_AUX_IDLE (0x1 << 3) +#define ADDR_ONLY (0x1 << 1) +#define AUX_EN (0x1 << 0) + +/* tx_sw_reset */ +#define RST_DP_TX (0x1 << 0) + +/* analog_ctl_1 */ +#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) + +/* analog_ctl_3 */ +#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) +#define VCO_BIT_600_MICRO (0x5 << 0) + +/* pll_filter_ctl_1 */ +#define PD_RING_OSC (0x1 << 6) +#define AUX_TERMINAL_CTRL_37_5_OHM (0x0 << 4) +#define AUX_TERMINAL_CTRL_45_OHM (0x1 << 4) +#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) +#define AUX_TERMINAL_CTRL_65_OHM (0x3 << 4) +#define TX_CUR1_2X (0x1 << 2) +#define TX_CUR_16_MA (0x3 << 0) + +/* Definition for DPCD Register */ +#define DPCD_DPCD_REV (0x0000) +#define DPCD_MAX_LINK_RATE (0x0001) +#define DPCD_MAX_LANE_COUNT (0x0002) +#define DP_MAX_LANE_COUNT_MASK 0x1f +#define DP_TPS3_SUPPORTED (1 << 6) +#define DP_ENHANCED_FRAME_CAP (1 << 7) + +#define DPCD_LINK_BW_SET (0x0100) +#define DPCD_LANE_COUNT_SET (0x0101) + +#define DPCD_TRAINING_PATTERN_SET (0x0102) +#define DP_TRAINING_PATTERN_DISABLE 0 +#define DP_TRAINING_PATTERN_1 1 +#define DP_TRAINING_PATTERN_2 2 +#define DP_TRAINING_PATTERN_3 3 +#define DP_TRAINING_PATTERN_MASK 0x3 + +#define DPCD_TRAINING_LANE0_SET (0x0103) +#define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 +#define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 +#define DP_TRAIN_MAX_SWING_REACHED (1 << 2) +#define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) +#define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) +#define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) +#define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) + +#define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) +#define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) +#define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) +#define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) +#define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) + +#define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 +#define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) + +#define DPCD_LANE0_1_STATUS (0x0202) +#define DPCD_LANE2_3_STATUS (0x0203) +#define DP_LANE_CR_DONE (1 << 0) +#define DP_LANE_CHANNEL_EQ_DONE (1 << 1) +#define DP_LANE_SYMBOL_LOCKED (1 << 2) +#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE |\ + DP_LANE_CHANNEL_EQ_DONE |\ + DP_LANE_SYMBOL_LOCKED) + +#define DPCD_LANE_ALIGN_STATUS_UPDATED (0x0204) +#define DP_INTERLANE_ALIGN_DONE (1 << 0) +#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) +#define DP_LINK_STATUS_UPDATED (1 << 7) + +#define DPCD_ADJUST_REQUEST_LANE0_1 (0x0206) +#define DPCD_ADJUST_REQUEST_LANE2_3 (0x0207) +#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 +#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 +#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c +#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 +#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 +#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 +#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 +#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 + +#define DPCD_TEST_REQUEST (0x0218) +#define DPCD_TEST_RESPONSE (0x0260) +#define DPCD_TEST_EDID_CHECKSUM (0x0261) +#define DPCD_LINK_POWER_STATE (0x0600) +#define DP_SET_POWER_D0 0x1 +#define DP_SET_POWER_D3 0x2 +#define DP_SET_POWER_MASK 0x3 + +#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) +#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) +#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) + +#define STREAM_ON_TIMEOUT 100 +#define PLL_LOCK_TIMEOUT 10 +#define DP_INIT_TRIES 10 + +#define EDID_ADDR 0x50 +#define EDID_LENGTH 0x80 +#define EDID_HEADER 0x00 +#define EDID_EXTENSION_FLAG 0x7e + + +enum dpcd_request { + DPCD_READ, + DPCD_WRITE, +}; + +enum dp_irq_type { + DP_IRQ_TYPE_HP_CABLE_IN, + DP_IRQ_TYPE_HP_CABLE_OUT, + DP_IRQ_TYPE_HP_CHANGE, + DP_IRQ_TYPE_UNKNOWN, +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + DP_PLL_UNLOCKED, + DP_PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + CS_RGB, + CS_YCBCR422, + CS_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_CNT1 = 1, + LANE_CNT2 = 2, + LANE_CNT4 = 4 +}; + +enum link_training_state { + LT_START, + LT_CLK_RECOVERY, + LT_EQ_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + +struct link_train { + unsigned char revision; + u8 link_rate; + u8 lane_count; +}; + +struct rk_edp { + struct rk3288_edp_regs *regs; + struct link_train link_train; + u8 train_set[4]; +}; + +int rk_edp_enable(void); +void rk_edp_init(u32 vop_id); +int rk_edp_get_edid(struct edid *edid); + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/gpio.h b/src/soc/rockchip/rk3288/include/soc/gpio.h new file mode 100644 index 0000000000..6a0055ecb6 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/gpio.h @@ -0,0 +1,70 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_GPIO_H__ +#define __SOC_ROCKCHIP_RK3288_GPIO_H__ + +#include + +#define GPIO(p, b, i) ((gpio_t){.port = p, .bank = GPIO_##b, .idx = i}) + +struct rk3288_gpio_regs { + u32 swporta_dr; + u32 swporta_ddr; + u32 reserved0[(0x30 - 0x08) / 4]; + u32 inten; + u32 intmask; + u32 inttype_level; + u32 int_polarity; + u32 int_status; + u32 int_rawstatus; + u32 debounce; + u32 porta_eoi; + u32 ext_porta; + u32 reserved1[(0x60 - 0x54) / 4]; + u32 ls_sync; +}; +check_member(rk3288_gpio_regs, ls_sync, 0x60); + +typedef union { + u32 raw; + struct { + u16 port; + union { + struct { + u16 num:5; + u16 :11; + }; + struct { + u16 idx:3; + u16 bank:2; + u16 :11; + }; + }; + }; +} gpio_t; + +enum { + GPIO_A = 0, + GPIO_B, + GPIO_C, + GPIO_D, +}; + +#endif /* __SOC_ROCKCHIP_RK3288_GPIO_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/grf.h b/src/soc/rockchip/rk3288/include/soc/grf.h new file mode 100644 index 0000000000..971dcfa4e8 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/grf.h @@ -0,0 +1,227 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_GRF_H__ +#define __SOC_ROCKCHIP_RK3288_GRF_H__ + +#include +#include +#include + +struct rk3288_grf_gpio_lh { + u32 l; + u32 h; +}; +check_member(rk3288_grf_gpio_lh, h, 0x4); + +struct rk3288_grf_regs { + u32 reserved[3]; + union { + u32 gpio1d_iomux; + u32 iomux_lcdc; + }; + u32 gpio2a_iomux; + u32 gpio2b_iomux; + union { + u32 gpio2c_iomux; + u32 iomux_i2c3; + }; + u32 reserved2; + union { + u32 gpio3a_iomux; + u32 iomux_emmcdata; + }; + union { + u32 gpio3b_iomux; + u32 iomux_emmcpwren; + }; + union { + u32 gpio3c_iomux; + u32 iomux_emmccmd; + }; + u32 gpio3dl_iomux; + u32 gpio3dh_iomux; + u32 gpio4al_iomux; + u32 gpio4ah_iomux; + u32 gpio4bl_iomux; + u32 reserved3; + u32 gpio4c_iomux; + u32 gpio4d_iomux; + u32 reserved4; + union { + u32 gpio5b_iomux; + u32 iomux_spi0; + }; + u32 gpio5c_iomux; + u32 reserved5; + union { + u32 gpio6a_iomux; + u32 iomux_i2s; + }; + union { + u32 gpio6b_iomux; + u32 iomux_i2c2; + u32 iomux_i2sclk; + }; + union { + u32 gpio6c_iomux; + u32 iomux_sdmmc0; + }; + u32 reserved6; + union { + u32 gpio7a_iomux; + u32 iomux_pwm0; + u32 iomux_pwm1; + }; + union { + u32 gpio7b_iomux; + u32 iomux_edp_hotplug; + }; + union { + u32 gpio7cl_iomux; + u32 iomux_i2c5sda; + u32 iomux_i2c4; + }; + union { + u32 gpio7ch_iomux; + u32 iomux_uart2; + u32 iomux_i2c5scl; + }; + u32 reserved7; + union { + u32 gpio8a_iomux; + u32 iomux_spi2csclk; + u32 iomux_i2c1; + }; + union { + u32 gpio8b_iomux; + u32 iomux_spi2txrx; + }; + u32 reserved8[30]; + struct rk3288_grf_gpio_lh gpio_sr[8]; + u32 gpio1_p[8][4]; + u32 gpio1_e[8][4]; + u32 gpio_smt; + u32 soc_con0; + u32 soc_con1; + u32 soc_con2; + u32 soc_con3; + u32 soc_con4; + u32 soc_con5; + u32 soc_con6; + u32 soc_con7; + u32 soc_con8; + u32 soc_con9; + u32 soc_con10; + u32 soc_con11; + u32 soc_con12; + u32 soc_con13; + u32 soc_con14; + u32 soc_status[22]; + u32 reserved9[2]; + u32 peridmac_con[4]; + u32 ddrc0_con0; + u32 ddrc1_con0; + u32 cpu_con[5]; + u32 reserved10[3]; + u32 cpu_status0; + u32 reserved11; + u32 uoc0_con[5]; + u32 uoc1_con[5]; + u32 uoc2_con[4]; + u32 uoc3_con[2]; + u32 uoc4_con[2]; + u32 pvtm_con[3]; + u32 pvtm_status[3]; + u32 io_vsel; + u32 saradc_testbit; + u32 tsadc_testbit_l; + u32 tsadc_testbit_h; + u32 os_reg[4]; + u32 reserved12; + u32 soc_con15; + u32 soc_con16; +}; +check_member(rk3288_grf_regs, soc_con16, 0x3a8); + +struct rk3288_sgrf_regs { + u32 soc_con0; + u32 soc_con1; + u32 soc_con2; + u32 soc_con3; + u32 soc_con4; + u32 soc_con5; + u32 reserved1[(0x20-0x18)/4]; + u32 busdmac_con[2]; + u32 reserved2[(0x40-0x28)/4]; + u32 cpu_con[3]; + u32 reserved3[(0x50-0x4c)/4]; + u32 soc_con6; + u32 soc_con7; + u32 soc_con8; + u32 soc_con9; + u32 soc_con10; + u32 soc_con11; + u32 soc_con12; + u32 soc_con13; + u32 soc_con14; + u32 soc_con15; + u32 soc_con16; + u32 soc_con17; + u32 soc_con18; + u32 soc_con19; + u32 soc_con20; + u32 soc_con21; + u32 reserved4[(0x100-0x90)/4]; + u32 soc_status[2]; + u32 reserved5[(0x120-0x108)/4]; + u32 fast_boot_addr; +}; +check_member(rk3288_sgrf_regs, fast_boot_addr, 0x0120); + +static struct rk3288_grf_regs * const rk3288_grf = (void *)GRF_BASE; +static struct rk3288_sgrf_regs * const rk3288_sgrf = (void *)GRF_SECURE_BASE; + +#define IOMUX_I2C1 RK_CLRSETBITS(3 << 10 | 3 << 8, 1 << 10 | 1 << 8) +#define IOMUX_I2C2 RK_SETBITS(1 << 4 | 1 << 2) +#define IOMUX_I2C3 RK_SETBITS(1 << 2 | 1 << 0) +#define IOMUX_I2C4 RK_SETBITS(1 << 8 | 1 << 4) +#define IOMUX_I2C5SDA RK_CLRSETBITS(3 << 12, 1 << 12) +#define IOMUX_I2C5SCL RK_CLRSETBITS(3 << 0, 1 << 0) +#define IOMUX_SPI0 RK_CLRSETBITS(0xff << 8, 1 << 14 | 1 << 12 | \ + 1 << 10 | 1 << 8) +#define IOMUX_SPI2_CSCLK RK_CLRSETBITS(3 << 14 | 3 << 12, 1 << 14 | 1 << 12) +#define IOMUX_SPI2_TXRX RK_CLRSETBITS(3 << 2 | 3 << 0, 1 << 2 | 1 << 0) +#define IOMUX_I2S RK_SETBITS(1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0) +#define IOMUX_I2SCLK RK_SETBITS(1 << 0) +#define IOMUX_UART2 RK_CLRSETBITS(7 << 12 | 3 << 8, 1 << 12 | 1 << 8) +#define IOMUX_LCDC RK_SETBITS(1 << 6 | 1 << 4 | 1 << 2 | 1 << 0) +#define IOMUX_SDMMC0 RK_CLRSETBITS(0x17ff, 1 << 12 | 1 << 10 | 1 << 8 |\ + 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0) +#define IOMUX_EMMCDATA RK_CLRSETBITS(0xffff, 2 << 14 | 2 << 12 | 2 << 10 |\ + 2 << 8 | 2 << 6 | 2 << 4 |\ + 2 << 2 | 2 << 0) +#define IOMUX_EMMCPWREN RK_CLRSETBITS(0x3 << 2, 0x2 << 2) +#define IOMUX_EMMCCMD RK_CLRSETBITS(0x3f, 2 << 4 | 2 << 2 | 2 << 0) +#define IOMUX_PWM1 RK_SETBITS(1 << 2) +#define IOMUX_EDP_HOTPLUG RK_CLRSETBITS(0x3 << 6, 0x2 << 6) +#define IOMUX_HDMI_EDP_I2C_SDA RK_CLRSETBITS(0x3 << 12, 2 << 12) +#define IOMUX_HDMI_EDP_I2C_SCL RK_CLRSETBITS(0x3 << 0, 2 << 0) + +#endif /* __SOC_ROCKCHIP_RK3288_GRF_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/hdmi.h b/src/soc/rockchip/rk3288/include/soc/hdmi.h new file mode 100644 index 0000000000..70856e0777 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/hdmi.h @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2015 Rockchip, Inc. + * Copyright (C) 2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __SOC_HDMI_H__ +#define __SOC_HDMI_H__ + +#include +#include + +#define HDMI_EDID_BLOCK_SIZE 128 + +struct rk3288_hdmi_regs { + u32 reserved0[0x100]; + u32 ih_fc_stat0; + u32 ih_fc_stat1; + u32 ih_fc_stat2; + u32 ih_as_stat0; + u32 ih_phy_stat0; + u32 ih_i2cm_stat0; + u32 ih_cec_stat0; + u32 ih_vp_stat0; + u32 ih_i2cmphy_stat0; + u32 ih_ahbdmaaud_stat0; + u32 reserved1[0x17f-0x109]; + u32 ih_mute_fc_stat0; + u32 ih_mute_fc_stat1; + u32 ih_mute_fc_stat2; + u32 ih_mute_as_stat0; + u32 ih_mute_phy_stat0; + u32 ih_mute_i2cm_stat0; + u32 ih_mute_cec_stat0; + u32 ih_mute_vp_stat0; + u32 ih_mute_i2cmphy_stat0; + u32 ih_mute_ahbdmaaud_stat0; + u32 reserved2[0x1fe - 0x189]; + u32 ih_mute; + u32 tx_invid0; + u32 tx_instuffing; + u32 tx_gydata0; + u32 tx_gydata1; + u32 tx_rcrdata0; + u32 tx_rcrdata1; + u32 tx_bcbdata0; + u32 tx_bcbdata1; + u32 reserved3[0x7ff-0x207]; + u32 vp_status; + u32 vp_pr_cd; + u32 vp_stuff; + u32 vp_remap; + u32 vp_conf; + u32 vp_stat; + u32 vp_int; + u32 vp_mask; + u32 vp_pol; + u32 reserved4[0xfff-0x808]; + u32 fc_invidconf; + u32 fc_inhactv0; + u32 fc_inhactv1; + u32 fc_inhblank0; + u32 fc_inhblank1; + u32 fc_invactv0; + u32 fc_invactv1; + u32 fc_invblank; + u32 fc_hsyncindelay0; + u32 fc_hsyncindelay1; + u32 fc_hsyncinwidth0; + u32 fc_hsyncinwidth1; + u32 fc_vsyncindelay; + u32 fc_vsyncinwidth; + u32 fc_infreq0; + u32 fc_infreq1; + u32 fc_infreq2; + u32 fc_ctrldur; + u32 fc_exctrldur; + u32 fc_exctrlspac; + u32 fc_ch0pream; + u32 fc_ch1pream; + u32 fc_ch2pream; + u32 fc_aviconf3; + u32 fc_gcp; + u32 fc_aviconf0; + u32 fc_aviconf1; + u32 fc_aviconf2; + u32 fc_avivid; + u32 fc_avietb0; + u32 fc_avietb1; + u32 fc_avisbb0; + u32 fc_avisbb1; + u32 fc_avielb0; + u32 fc_avielb1; + u32 fc_avisrb0; + u32 fc_avisrb1; + u32 fc_audiconf0; + u32 fc_audiconf1; + u32 fc_audiconf2; + u32 fc_audiconf3; + u32 fc_vsdieeeid0; + u32 fc_vsdsize; + u32 reserved7[0x2fff-0x102a]; + u32 phy_conf0; + u32 phy_tst0; + u32 phy_tst1; + u32 phy_tst2; + u32 phy_stat0; + u32 phy_int0; + u32 phy_mask0; + u32 phy_pol0; + u32 reserved8[0x301f-0x3007]; + u32 phy_i2cm_slave_addr; + u32 phy_i2cm_address_addr; + u32 phy_i2cm_datao_1_addr; + u32 phy_i2cm_datao_0_addr; + u32 phy_i2cm_datai_1_addr; + u32 phy_i2cm_datai_0_addr; + u32 phy_i2cm_operation_addr; + u32 phy_i2cm_int_addr; + u32 phy_i2cm_ctlint_addr; + u32 phy_i2cm_div_addr; + u32 phy_i2cm_softrstz_addr; + u32 phy_i2cm_ss_scl_hcnt_1_addr; + u32 phy_i2cm_ss_scl_hcnt_0_addr; + u32 phy_i2cm_ss_scl_lcnt_1_addr; + u32 phy_i2cm_ss_scl_lcnt_0_addr; + u32 phy_i2cm_fs_scl_hcnt_1_addr; + u32 phy_i2cm_fs_scl_hcnt_0_addr; + u32 phy_i2cm_fs_scl_lcnt_1_addr; + u32 phy_i2cm_fs_scl_lcnt_0_addr; + u32 reserved9[0x30ff-0x3032]; + u32 aud_conf0; + u32 aud_conf1; + u32 aud_int; + u32 aud_conf2; + u32 aud_int1; + u32 reserved32[0x31ff-0x3104]; + u32 aud_n1; + u32 aud_n2; + u32 aud_n3; + u32 aud_cts1; + u32 aud_cts2; + u32 aud_cts3; + u32 aud_inputclkfs; + u32 reserved12[0x3fff-0x3206]; + u32 mc_sfrdiv; + u32 mc_clkdis; + u32 mc_swrstz; + u32 mc_opctrl; + u32 mc_flowctrl; + u32 mc_phyrstz; + u32 mc_lockonclock; + u32 mc_heacphy_rst; + u32 reserved13[0x40ff-0x4007]; + u32 csc_cfg; + u32 csc_scale; + struct { + u32 msb; + u32 lsb; + } csc_coef[3][4]; + u32 reserved17[0x7dff-0x4119]; + u32 i2cm_slave; + u32 i2cmess; + u32 i2cm_datao; + u32 i2cm_datai; + u32 i2cm_operation; + u32 i2cm_int; + u32 i2cm_ctlint; + u32 i2cm_div; + u32 i2cm_segaddr; + u32 i2cm_softrstz; + u32 i2cm_segptr; + u32 i2cm_ss_scl_hcnt_1_addr; + u32 i2cm_ss_scl_hcnt_0_addr; + u32 i2cm_ss_scl_lcnt_1_addr; + u32 i2cm_ss_scl_lcnt_0_addr; + u32 i2cm_fs_scl_hcnt_1_addr; + u32 i2cm_fs_scl_hcnt_0_addr; + u32 i2cm_fs_scl_lcnt_1_addr; + u32 i2cm_fs_scl_lcnt_0_addr; + u32 reserved18[0x7e1f-0x7e12]; + u32 i2cm_buf0; +}; +check_member(rk3288_hdmi_regs, i2cm_buf0, 0x1f880); + +enum { + /* HDMI PHY registers define */ + PHY_OPMODE_PLLCFG = 0x06, + PHY_CKCALCTRL = 0x05, + PHY_CKSYMTXCTRL = 0x09, + PHY_VLEVCTRL = 0x0e, + PHY_PLLCURRCTRL = 0x10, + PHY_PLLPHBYCTRL = 0x13, + PHY_PLLGMPCTRL = 0x15, + PHY_PLLCLKBISTPHASE = 0x17, + PHY_TXTERM = 0x19, + + /* ih_phy_stat0 field values */ + HDMI_IH_PHY_STAT0_HPD = 0x1, + + /* ih_mute field values */ + HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2, + HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1, + + /* tx_invid0 field values */ + HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00, + HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1f, + HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0, + + /* tx_instuffing field values */ + HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4, + HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2, + HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1, + + /* vp_pr_cd field values */ + HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xf0, + HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4, + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0f, + HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0, + + /* vp_stuff field values */ + HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20, + HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5, + HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4, + HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4, + HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2, + HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2, + HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1, + HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1, + + /* vp_conf field values */ + HDMI_VP_CONF_BYPASS_EN_MASK = 0x40, + HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40, + HDMI_VP_CONF_PP_EN_ENMASK = 0x20, + HDMI_VP_CONF_PP_EN_DISABLE = 0x00, + HDMI_VP_CONF_PR_EN_MASK = 0x10, + HDMI_VP_CONF_PR_EN_DISABLE = 0x00, + HDMI_VP_CONF_YCC422_EN_MASK = 0x8, + HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0, + HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4, + HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4, + HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3, + HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3, + + /* vp_remap field values */ + HDMI_VP_REMAP_YCC422_16BIT = 0x0, + + /* fc_invidconf field values */ + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80, + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80, + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40, + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20, + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10, + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00, + HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8, + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8, + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2, + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0, + HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1, + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1, + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0, + + + /* fc_aviconf0-fc_aviconf3 field values */ + HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03, + HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00, + HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01, + HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02, + HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40, + HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40, + HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00, + HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0c, + HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00, + HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04, + HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08, + HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0c, + HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30, + HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10, + HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20, + HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00, + + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0f, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0a, + HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0b, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10, + HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20, + HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xc0, + HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00, + HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40, + HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80, + HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xc0, + + HDMI_FC_AVICONF2_SCALING_MASK = 0x03, + HDMI_FC_AVICONF2_SCALING_NONE = 0x00, + HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01, + HDMI_FC_AVICONF2_SCALING_VERT = 0x02, + HDMI_FC_AVICONF2_SCALING_HORIZ_vert = 0x03, + HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0c, + HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00, + HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04, + HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30, + HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40, + HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80, + HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00, + HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80, + + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02, + HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03, + HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0c, + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, + + /* fc_gcp field values*/ + HDMI_FC_GCP_SET_AVMUTE = 0x02, + HDMI_FC_GCP_CLEAR_AVMUTE = 0x01, + + /* phy_conf0 field values */ + HDMI_PHY_CONF0_PDZ_MASK = 0x80, + HDMI_PHY_CONF0_PDZ_OFFSET = 7, + HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, + HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, + HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20, + HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5, + HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, + HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, + HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, + HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3, + HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2, + HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1, + HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1, + HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0, + + /* phy_tst0 field values */ + HDMI_PHY_TST0_TSTCLR_MASK = 0x20, + HDMI_PHY_TST0_TSTCLR_OFFSET = 5, + + /* phy_stat0 field values */ + HDMI_PHY_HPD = 0x02, + HDMI_PHY_TX_PHY_LOCK = 0x01, + + /* phy_i2cm_slave_addr field values */ + HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69, + + /* phy_i2cm_operation_addr field values */ + HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10, + + /* hdmi_phy_i2cm_int_addr */ + HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08, + + /* hdmi_phy_i2cm_ctlint_addr */ + HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80, + HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08, + + /* aud_conf0 field values */ + HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST = 0x80, + HDMI_AUD_CONF0_I2S_SELECT = 0x20, + HDMI_AUD_CONF0_I2S_IN_EN_0 = 0x01, + HDMI_AUD_CONF0_I2S_IN_EN_1 = 0x02, + HDMI_AUD_CONF0_I2S_IN_EN_2 = 0x04, + HDMI_AUD_CONF0_I2S_IN_EN_3 = 0x08, + + /* aud_conf0 field values */ + HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE = 0x0, + HDMI_AUD_CONF1_I2S_WIDTH_16BIT = 0x10, + + /* aud_n3 field values */ + HDMI_AUD_N3_NCTS_ATOMIC_WRITE = 0x80, + HDMI_AUD_N3_AUDN19_16_MASK = 0x0f, + + /* aud_cts3 field values */ + HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5, + HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0, + HDMI_AUD_CTS3_N_SHIFT_1 = 0, + HDMI_AUD_CTS3_N_SHIFT_16 = 0x20, + HDMI_AUD_CTS3_N_SHIFT_32 = 0x40, + HDMI_AUD_CTS3_N_SHIFT_64 = 0x60, + HDMI_AUD_CTS3_N_SHIFT_128 = 0x80, + HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0, + HDMI_AUD_CTS3_CTS_MANUAL = 0x10, + HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f, + + /* aud_inputclkfs filed values */ + HDMI_AUD_INPUTCLKFS_128 = 0x0, + + /* mc_clkdis field values */ + HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8, + HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2, + HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1, + + /* mc_swrstz field values */ + HDMI_MC_SWRSTZ_II2SSWRST_REQ = 0x08, + HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02, + + /* mc_flowctrl field values */ + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1, + HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0, + + /* mc_phyrstz field values */ + HDMI_MC_PHYRSTZ_ASSERT = 0x0, + HDMI_MC_PHYRSTZ_DEASSERT = 0x1, + + /* mc_heacphy_rst field values */ + HDMI_MC_HEACPHY_RST_ASSERT = 0x1, + + /* csc_cfg field values */ + HDMI_CSC_CFG_INTMODE_DISABLE = 0x00, + + /* csc_scale field values */ + HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xf0, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60, + HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70, + HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03, + + /* i2cm filed values */ + HDMI_I2CM_SLAVE_DDC_ADDR = 0x50, + HDMI_I2CM_SEGADDR_DDC = 0x30, + HDMI_I2CM_OPT_RD8_EXT = 0x8, + HDMI_I2CM_OPT_RD8 = 0x4, + HDMI_I2CM_DIV_FAST_STD_MODE = 0x8, + HDMI_I2CM_DIV_FAST_MODE = 0x8, + HDMI_I2CM_DIV_STD_MODE = 0x0, + HDMI_I2CM_SOFTRSTZ = 0x1, +}; + +int rk_hdmi_init(u32 vop_id); +int rk_hdmi_enable(const struct edid *edid); +int rk_hdmi_get_edid(struct edid *edid); + +#endif /* __SOC_HDMI_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/i2c.h b/src/soc/rockchip/rk3288/include/soc/i2c.h new file mode 100644 index 0000000000..84d9b7587b --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/i2c.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_I2C_H__ +#define __SOC_ROCKCHIP_RK3288_I2C_H__ + +void i2c_init(unsigned int bus, unsigned int hz); + +#endif + diff --git a/src/soc/rockchip/rk3288/include/soc/memlayout.ld b/src/soc/rockchip/rk3288/include/soc/memlayout.ld new file mode 100644 index 0000000000..dc67ee9070 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/memlayout.ld @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +/* Note: The BootROM will jump to 0xFF704004 after loading bootblock, + * so the bootblock loading address must be at 0xFF704004. + */ +SECTIONS +{ + DRAM_START(0x00000000) + RAMSTAGE(0x00200000, 128K) + POSTRAM_CBFS_CACHE(0x01000000, 1M) + DMA_COHERENT(0x10000000, 2M) + FRAMEBUFFER(0x10800000, 8M) + + SRAM_START(0xFF700000) + TTB(0xFF700000, 16K) + BOOTBLOCK(0xFF704004, 18K - 4) + PRERAM_CBMEM_CONSOLE(0xFF708800, 4K) + VBOOT2_WORK(0xFF709800, 12K) + OVERLAP_VERSTAGE_ROMSTAGE(0xFF70C800, 41K) + TTB_SUBTABLES(0xFF716C00, 1K) + PRERAM_CBFS_CACHE(0xFF717000, 1K) + TIMESTAMP(0xFF717400, 0x180) + STACK(0xFF717580, 3K - 0x180) + SRAM_END(0xFF718000) + + /* 4K of special SRAM in PMU power domain. + * Careful: only supports 32-bit wide write accesses! */ + SYMBOL(pmu_sram, 0xFF720000) + WATCHDOG_TOMBSTONE(0xFF720FFC, 4) + SYMBOL(epmu_sram, 0xFF721000) +} diff --git a/src/soc/rockchip/rk3288/include/soc/pmu.h b/src/soc/rockchip/rk3288/include/soc/pmu.h new file mode 100644 index 0000000000..2a935156a0 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/pmu.h @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_PMU_H__ +#define __SOC_ROCKCHIP_RK3288_PMU_H__ + +#include + +struct rk3288_pmu_regs { + u32 wakeup_cfg[2]; + u32 pwrdn_con; + u32 pwrdn_st; + u32 idle_req; + u32 idle_st; + u32 pwrmode_con; + u32 pwr_state; + u32 osc_cnt; + u32 pll_cnt; + u32 stabl_cnt; + u32 ddr0io_pwron_cnt; + u32 ddr1io_pwron_cnt; + u32 core_pwrdn_cnt; + u32 core_pwrup_cnt; + u32 gpu_pwrdn_cnt; + u32 gpu_pwrup_cnt; + u32 wakeup_rst_clr_cnt; + u32 sft_con; + u32 ddr_sref_st; + u32 int_con; + u32 int_st; + u32 boot_addr_sel; + u32 grf_con; + u32 gpio_sr; + u32 gpio0pull[3]; + u32 gpio0drv[3]; + u32 gpio_op; + u32 gpio0_sel18; + u32 gpio0a_iomux; + union { + u32 gpio0b_iomux; + u32 iomux_i2c0sda; + u32 iomux_tsadc_int; + }; + union { + u32 gpio0c_iomux; + u32 iomux_i2c0scl; + }; + union { + u32 gpio0d_iomux; + u32 iomux_lcdc0; + }; + u32 sys_reg[4]; +}; +check_member(rk3288_pmu_regs, sys_reg[3], 0x00a0); + +static struct rk3288_pmu_regs * const rk3288_pmu = (void *)PMU_BASE; + +#define IOMUX_I2C0SDA (1 << 14) +#define IOMUX_I2C0SCL (1 << 0) +#define IOMUX_TSADC_INT (1 << 4) + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/pwm.h b/src/soc/rockchip/rk3288/include/soc/pwm.h new file mode 100644 index 0000000000..168d8a77d4 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/pwm.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_PWM_H__ +#define __SOC_ROCKCHIP_RK3288_PWM_H__ + +void pwm_init(u32 id, u32 period_ns, u32 duty_ns); + +#endif + diff --git a/src/soc/rockchip/rk3288/include/soc/rk808.h b/src/soc/rockchip/rk3288/include/soc/rk808.h new file mode 100644 index 0000000000..ceddc52974 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/rk808.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_PMIC_H__ +#define __SOC_ROCKCHIP_RK3288_PMIC_H__ + +void rk808_configure_switch(int sw, int enabled); +void rk808_configure_ldo(int ldo, int millivolts); +void rk808_configure_buck(int buck, int millivolts); + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/sdram.h b/src/soc/rockchip/rk3288/include/soc/sdram.h new file mode 100644 index 0000000000..8f37cb7574 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/sdram.h @@ -0,0 +1,103 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_SDRAM_H__ +#define __SOC_ROCKCHIP_RK3288_SDRAM_H__ + +enum { + DDR3 = 3, + LPDDR3 = 6, + UNUSED = 0xFF, +}; + +struct rk3288_sdram_channel { + u8 rank; + u8 col; + u8 bk; + u8 bw; + u8 dbw; + u8 row_3_4; + u8 cs0_row; + u8 cs1_row; +}; + +struct rk3288_sdram_pctl_timing { + u32 togcnt1u; + u32 tinit; + u32 trsth; + u32 togcnt100n; + u32 trefi; + u32 tmrd; + u32 trfc; + u32 trp; + u32 trtw; + u32 tal; + u32 tcl; + u32 tcwl; + u32 tras; + u32 trc; + u32 trcd; + u32 trrd; + u32 trtp; + u32 twr; + u32 twtr; + u32 texsr; + u32 txp; + u32 txpdll; + u32 tzqcs; + u32 tzqcsi; + u32 tdqs; + u32 tcksre; + u32 tcksrx; + u32 tcke; + u32 tmod; + u32 trstl; + u32 tzqcl; + u32 tmrr; + u32 tckesr; + u32 tdpd; +}; +check_member(rk3288_sdram_pctl_timing, tdpd, 0x144 - 0xc0); + +struct rk3288_sdram_phy_timing { + u32 dtpr0; + u32 dtpr1; + u32 dtpr2; + u32 mr[4]; +}; + +struct rk3288_sdram_params { + struct rk3288_sdram_channel ch[2]; + struct rk3288_sdram_pctl_timing pctl_timing; + struct rk3288_sdram_phy_timing phy_timing; + u32 noc_timing; + u32 noc_activate; + u32 ddrconfig; + u32 ddr_freq; + u8 dramtype; + u8 num_channels; + u8 stride; + u8 odt; +}; + +void sdram_init(const struct rk3288_sdram_params *sdram_params); +u32 sdram_get_ram_code(void); +size_t sdram_size_mb(void); +const struct rk3288_sdram_params *get_sdram_config(void); +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/soc.h b/src/soc/rockchip/rk3288/include/soc/soc.h new file mode 100644 index 0000000000..566802ab53 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/soc.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_CPU_H__ +#define __SOC_ROCKCHIP_RK3288_CPU_H__ + +#define RK_CLRSETBITS(clr, set) ((((clr) | (set)) << 16) | set) +#define RK_SETBITS(set) RK_CLRSETBITS(0, set) +#define RK_CLRBITS(clr) RK_CLRSETBITS(clr, 0) + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/spi.h b/src/soc/rockchip/rk3288/include/soc/spi.h new file mode 100644 index 0000000000..bba38ef075 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/spi.h @@ -0,0 +1,204 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_SPI_H__ +#define __SOC_ROCKCHIP_RK3288_SPI_H__ + +/* This driver serves as a CBFS media source. */ +#include +#include +#include + +struct rockchip_spi { + u32 ctrlr0; + u32 ctrlr1; + u32 spienr; + u32 ser; + u32 baudr; + u32 txftlr; + u32 rxftlr; + u32 txflr; + u32 rxflr; + u32 sr; + u32 ipr; + u32 imr; + u32 isr; + u32 risr; + u32 icr; + u32 dmacr; + u32 damtdlr; + u32 damrdlr; + u32 reserved[(0x400-0x48)/4]; + u32 txdr[0x100]; + u32 rxdr[0x100]; +}; +check_member(rockchip_spi, rxdr, 0x800); + + +#define SF_READ_DATA_CMD 0x3 + +/* --------Bit fields in CTRLR0--------begin */ + +#define SPI_DFS_OFFSET 0 /* Data Frame Size */ +#define SPI_DFS_MASK 0x3 +#define SPI_DFS_4BIT 0x00 +#define SPI_DFS_8BIT 0x01 +#define SPI_DFS_16BIT 0x02 +#define SPI_DFS_RESV 0x03 + +/* Control Frame Size */ +#define SPI_CFS_OFFSET 2 +#define SPI_CFS_MASK 0xF + +/* Serial Clock Phase */ +#define SPI_SCPH_OFFSET 6 +#define SPI_SCPH_MASK 0x1 + +/* Serial clock toggles in middle of first data bit */ +#define SPI_SCPH_TOGMID 0 + +/* Serial clock toggles at start of first data bit */ +#define SPI_SCPH_TOGSTA 1 + +/* Serial Clock Polarity */ +#define SPI_SCOL_OFFSET 7 +#define SPI_SCOL_MASK 0x1 + +/* Inactive state of clock serial clock is low */ +#define SPI_SCOL_LOW 0 + +/* Inactive state of clock serial clock is high */ +#define SPI_SCOL_HIGH 1 + +/* Chip Select Mode */ +#define SPI_CSM_OFFSET 8 +#define SPI_CSM_MASK 0x3 + +/* ss_n keep low after every frame data is transferred */ +#define SPI_CSM_KEEP 0x00 + +/* + * ss_n be high for half sclk_out cycles after + * every frame data is transferred + */ +#define SPI_CSM_HALF 0x01 + +/* ss_n be high for one sclk_out cycle after every frame data is transferred */ +#define SPI_CSM_ONE 0x02 +#define SPI_CSM_RESV 0x03 + +/* SSN to Sclk_out delay */ +#define SPI_SSN_DELAY_OFFSET 10 +#define SPI_SSN_DELAY_MASK 0x1 +/* the peroid between ss_n active and sclk_out active is half sclk_out cycles */ +#define SPI_SSN_DELAY_HALF 0x00 +/* the peroid between ss_n active and sclk_out active is one sclk_out cycle */ +#define SPI_SSN_DELAY_ONE 0x01 + +/* Serial Endian Mode */ +#define SPI_SEM_OFFSET 11 +#define SPI_SEM_MASK 0x1 +/* little endian */ +#define SPI_SEM_LITTLE 0x00 +/* big endian */ +#define SPI_SEM_BIG 0x01 + +/* First Bit Mode */ +#define SPI_FBM_OFFSET 12 +#define SPI_FBM_MASK 0x1 +/* first bit in MSB */ +#define SPI_FBM_MSB 0x00 +/* first bit in LSB */ +#define SPI_FBM_LSB 0x01 + +/* Byte and Halfword Transform */ +#define SPI_HALF_WORLD_TX_OFFSET 13 +#define SPI_HALF_WORLD_MASK 0x1 +/* apb 16bit write/read, spi 8bit write/read */ +#define SPI_APB_16BIT 0x00 +/* apb 8bit write/read, spi 8bit write/read */ +#define SPI_APB_8BIT 0x01 + +/* Rxd Sample Delay */ +#define SPI_RXDSD_OFFSET 14 +#define SPI_RXDSD_MASK 0x3 + +/* Frame Format */ +#define SPI_FRF_OFFSET 16 +#define SPI_FRF_MASK 0x3 +/* motorola spi */ +#define SPI_FRF_SPI 0x00 +/* Texas Instruments SSP*/ +#define SPI_FRF_SSP 0x01 +/* National Semiconductors Microwire */ +#define SPI_FRF_MICROWIRE 0x02 +#define SPI_FRF_RESV 0x03 + +/* Transfer Mode */ +#define SPI_TMOD_OFFSET 18 +#define SPI_TMOD_MASK 0x3 +/* xmit & recv */ +#define SPI_TMOD_TR 0x00 +/* xmit only */ +#define SPI_TMOD_TO 0x01 +/* recv only */ +#define SPI_TMOD_RO 0x02 +#define SPI_TMOD_RESV 0x03 + +/* Operation Mode */ +#define SPI_OMOD_OFFSET 20 +#define SPI_OMOD_MASK 0x1 +/* Master Mode */ +#define SPI_OMOD_MASTER 0x00 +/* Slave Mode */ +#define SPI_OMOD_SLAVE 0x01 + +/* --------Bit fields in CTRLR0--------end */ +/* Bit fields in SR, 7 bits */ +#define SR_MASK 0x7f +#define SR_BUSY (1 << 0) +#define SR_TF_FULL (1 << 1) +#define SR_TF_EMPT (1 << 2) +#define SR_RF_EMPT (1 << 3) +#define SR_RF_FULL (1 << 4) + +/* Bit fields in ISR, IMR, RISR, 7 bits */ +#define SPI_INT_TXEI (1 << 0) +#define SPI_INT_TXOI (1 << 1) +#define SPI_INT_RXUI (1 << 2) +#define SPI_INT_RXOI (1 << 3) +#define SPI_INT_RXFI (1 << 4) + +/* Bit fields in DMACR */ +#define SPI_DMACR_TX_ENABLE (1 << 1) +#define SPI_DMACR_RX_ENABLE (1 << 0) + +/* Bit fields in ICR */ +#define SPI_CLEAR_INT_ALL (1 << 0) +#define SPI_CLEAR_INT_RXUI (1 << 1) +#define SPI_CLEAR_INT_RXOI (1 << 2) +#define SPI_CLEAR_INT_TXOI (1 << 3) + +/* Serve as CBFS media source */ +int initialize_rockchip_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size); +void rockchip_spi_init(unsigned int bus, unsigned int speed_hz); + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/timer.h b/src/soc/rockchip/rk3288/include/soc/timer.h new file mode 100644 index 0000000000..248b150ab5 --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/timer.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_TIMER_H__ +#define __SOC_ROCKCHIP_RK3288_TIMER_H__ + +#include +#include +#include +#include + +static const u32 clocks_per_usec = OSC_HZ/USECS_PER_SEC; + +struct rk3288_timer { + u32 timer_load_count0; + u32 timer_load_count1; + u32 timer_curr_value0; + u32 timer_curr_value1; + u32 timer_ctrl_reg; + u32 timer_int_status; +}; + +static struct rk3288_timer * const timer7_ptr = (void *)TIMER7_BASE; + +#define TIMER_LOAD_VAL 0xffffffff + +#endif /* __SOC_ROCKCHIP_RK3288_TIMER_H__ */ diff --git a/src/soc/rockchip/rk3288/include/soc/tsadc.h b/src/soc/rockchip/rk3288/include/soc/tsadc.h new file mode 100644 index 0000000000..7412110cab --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/tsadc.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_ROCKCHIP_RK3288_TSADC_H__ +#define __SOC_ROCKCHIP_RK3288_TSADC_H__ + +void tsadc_init(void); + +#endif diff --git a/src/soc/rockchip/rk3288/include/soc/vop.h b/src/soc/rockchip/rk3288/include/soc/vop.h new file mode 100644 index 0000000000..74ca14636b --- /dev/null +++ b/src/soc/rockchip/rk3288/include/soc/vop.h @@ -0,0 +1,368 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _RK3288_LCD_H_ +#define _RK3288_LCD_H_ +#include +#include + +struct rk3288_vop_regs { + u32 reg_cfg_done; + u32 version_info; + u32 sys_ctrl; + u32 sys_ctrl1; + u32 dsp_ctrl0; + u32 dsp_ctrl1; + u32 dsp_bg; + u32 mcu_ctrl; + u32 intr_ctrl0; + u32 intr_ctrl1; + u32 intr_reserved0; + u32 intr_reserved1; + + u32 win0_ctrl0; + u32 win0_ctrl1; + u32 win0_color_key; + u32 win0_vir; + u32 win0_yrgb_mst; + u32 win0_cbr_mst; + u32 win0_act_info; + u32 win0_dsp_info; + u32 win0_dsp_st; + u32 win0_scl_factor_yrgb; + u32 win0_scl_factor_cbr; + u32 win0_scl_offset; + u32 win0_src_alpha_ctrl; + u32 win0_dst_alpha_ctrl; + u32 win0_fading_ctrl; + u32 win0_reserved0; + + u32 win1_ctrl0; + u32 win1_ctrl1; + u32 win1_color_key; + u32 win1_vir; + u32 win1_yrgb_mst; + u32 win1_cbr_mst; + u32 win1_act_info; + u32 win1_dsp_info; + u32 win1_dsp_st; + u32 win1_scl_factor_yrgb; + u32 win1_scl_factor_cbr; + u32 win1_scl_offset; + u32 win1_src_alpha_ctrl; + u32 win1_dst_alpha_ctrl; + u32 win1_fading_ctrl; + u32 win1_reservd0; + u32 reserved2[48]; + u32 post_dsp_hact_info; + u32 post_dsp_vact_info; + u32 post_scl_factor_yrgb; + u32 post_reserved; + u32 post_scl_ctrl; + u32 post_dsp_vact_info_f1; + u32 dsp_htotal_hs_end; + u32 dsp_hact_st_end; + u32 dsp_vtotal_vs_end; + u32 dsp_vact_st_end; + u32 dsp_vs_st_end_f1; + u32 dsp_vact_st_end_f1; +}; +check_member(rk3288_vop_regs, dsp_vact_st_end_f1, 0x19c); + +enum rockchip_fb_data_format_t { + ARGB8888 = 0, + RGB888 = 1, + RGB565 = 2, +}; + +enum { + LB_YUV_3840X5 = 0x0, + LB_YUV_2560X8 = 0x1, + LB_RGB_3840X2 = 0x2, + LB_RGB_2560X4 = 0x3, + LB_RGB_1920X5 = 0x4, + LB_RGB_1280X8 = 0x5 +}; + +enum vop_modes { + /* EDP == 0 is used for early RK3288 products and is the most likely + * use case, so keep it as the default. Other desired modes should + * be set explicitly in the board's devicetree.cb. + */ + VOP_MODE_EDP = 0, + VOP_MODE_HDMI, + VOP_MODE_NONE, + VOP_MODE_AUTO_DETECT, + VOP_MODE_UNKNOWN, +}; + +/* VOP_VERSION_INFO */ +#define M_FPGA_VERSION (0xffff << 16) +#define M_RTL_VERSION (0xffff) + +/* VOP_SYS_CTRL */ +#define M_AUTO_GATING_EN (1 << 23) +#define M_STANDBY_EN (1 << 22) +#define M_DMA_STOP (1 << 21) +#define M_MMU_EN (1 << 20) +#define M_DAM_BURST_LENGTH (0x3 << 18) +#define M_MIPI_OUT_EN (1 << 15) +#define M_EDP_OUT_EN (1 << 14) +#define M_HDMI_OUT_EN (1 << 13) +#define M_RGB_OUT_EN (1 << 12) +#define M_ALL_OUT_EN (M_MIPI_OUT_EN | M_EDP_OUT_EN | M_HDMI_OUT_EN | M_RGB_OUT_EN) +#define M_EDPI_WMS_FS (1 << 10) +#define M_EDPI_WMS_MODE (1 << 9) +#define M_EDPI_HALT_EN (1 << 8) +#define M_DOUB_CH_OVERLAP_NUM (0xf << 4) +#define M_DOUB_CHANNEL_EN (1 << 3) +#define M_DIRECT_PATH_LAYER_SEL (0x3 << 1) +#define M_DIRECT_PATH_EN (1) + +#define V_AUTO_GATING_EN(x) (((x) & 1) << 23) +#define V_STANDBY_EN(x) (((x) & 1) << 22) +#define V_DMA_STOP(x) (((x) & 1) << 21) +#define V_MMU_EN(x) (((x) & 1) << 20) +#define V_DMA_BURST_LENGTH(x) (((x) & 3) << 18) +#define V_MIPI_OUT_EN(x) (((x) & 1) << 15) +#define V_EDP_OUT_EN(x) (((x) & 1) << 14) +#define V_HDMI_OUT_EN(x) (((x) & 1) << 13) +#define V_RGB_OUT_EN(x) (((x) & 1) << 12) +#define V_EDPI_WMS_FS(x) (((x) & 1) << 10) +#define V_EDPI_WMS_MODE(x) (((x) & 1) << 9) +#define V_EDPI_HALT_EN(x) (((x)&1)<<8) +#define V_DOUB_CH_OVERLAP_NUM(x) (((x) & 0xf) << 4) +#define V_DOUB_CHANNEL_EN(x) (((x) & 1) << 3) +#define V_DIRECT_PATH_LAYER_SEL(x) (((x) & 3) << 1) +#define V_DIRECT_PATH_EN(x) ((x) & 1) + +/* VOP_SYS_CTRL1 */ +#define M_AXI_OUTSTANDING_MAX_NUM (0x1f << 13) +#define M_AXI_MAX_OUTSTANDING_EN (1 << 12) +#define M_NOC_WIN_QOS (3 << 10) +#define M_NOC_QOS_EN (1 << 9) +#define M_NOC_HURRY_THRESHOLD (0x3f << 3) +#define M_NOC_HURRY_VALUE (0x3 << 1) +#define M_NOC_HURRY_EN (1) + +#define V_AXI_OUTSTANDING_MAX_NUM(x) (((x) & 0x1f) << 13) +#define V_AXI_MAX_OUTSTANDING_EN(x) (((x) & 1) << 12) +#define V_NOC_WIN_QOS(x) (((x) & 3) << 10) +#define V_NOC_QOS_EN(x) (((x) & 1) << 9) +#define V_NOC_HURRY_THRESHOLD(x) (((x) & 0x3f) << 3) +#define V_NOC_HURRY_VALUE(x) (((x) & 3) << 1) +#define V_NOC_HURRY_EN(x) ((x) & 1) + +/* VOP_DSP_CTRL0 */ +#define M_DSP_Y_MIR_EN (1 << 23) +#define M_DSP_X_MIR_EN (1 << 22) +#define M_DSP_YUV_CLIP (1 << 21) +#define M_DSP_CCIR656_AVG (1 << 20) +#define M_DSP_BLACK_EN (1 << 19) +#define M_DSP_BLANK_EN (1 << 18) +#define M_DSP_OUT_ZERO (1 << 17) +#define M_DSP_DUMMY_SWAP (1 << 16) +#define M_DSP_DELTA_SWAP (1 << 15) +#define M_DSP_RG_SWAP (1 << 14) +#define M_DSP_RB_SWAP (1 << 13) +#define M_DSP_BG_SWAP (1 << 12) +#define M_DSP_FIELD_POL (1 << 11) +#define M_DSP_INTERLACE (1 << 10) +#define M_DSP_DDR_PHASE (1 << 9) +#define M_DSP_DCLK_DDR (1 << 8) +#define M_DSP_DCLK_POL (1 << 7) +#define M_DSP_DEN_POL (1 << 6) +#define M_DSP_VSYNC_POL (1 << 5) +#define M_DSP_HSYNC_POL (1 << 4) +#define M_DSP_OUT_MODE (0xf) + +#define V_DSP_Y_MIR_EN(x) (((x) & 1) << 23) +#define V_DSP_X_MIR_EN(x) (((x) & 1) << 22) +#define V_DSP_YUV_CLIP(x) (((x) & 1) << 21) +#define V_DSP_CCIR656_AVG(x) (((x) & 1) << 20) +#define V_DSP_BLACK_EN(x) (((x) & 1) << 19) +#define V_DSP_BLANK_EN(x) (((x) & 1) << 18) +#define V_DSP_OUT_ZERO(x) (((x) & 1) << 17) +#define V_DSP_DUMMY_SWAP(x) (((x) & 1) << 16) +#define V_DSP_DELTA_SWAP(x) (((x) & 1) << 15) +#define V_DSP_RG_SWAP(x) (((x) & 1) << 14) +#define V_DSP_RB_SWAP(x) (((x) & 1) << 13) +#define V_DSP_BG_SWAP(x) (((x) & 1) << 12) +#define V_DSP_FIELD_POL(x) (((x) & 1) << 11) +#define V_DSP_INTERLACE(x) (((x) & 1) << 10) +#define V_DSP_DDR_PHASE(x) (((x) & 1) << 9) +#define V_DSP_DCLK_DDR(x) (((x) & 1) << 8) +#define V_DSP_DCLK_POL(x) (((x) & 1) << 7) +#define V_DSP_DEN_POL(x) (((x) & 1) << 6) +#define V_DSP_VSYNC_POL(x) (((x) & 1) << 5) +#define V_DSP_HSYNC_POL(x) (((x) & 1) << 4) +#define V_DSP_OUT_MODE(x) ((x) & 0xf) + +/* VOP_DSP_CTRL1 */ +#define M_DSP_LAYER3_SEL (3 << 14) +#define M_DSP_LAYER2_SEL (3 << 12) +#define M_DSP_LAYER1_SEL (3 << 10) +#define M_DSP_LAYER0_SEL (3 << 8) +#define M_DITHER_UP_EN (1 << 6) +#define M_DITHER_DOWN_SEL (1 << 4) +#define M_DITHER_DOWN_MODE (1 << 3) +#define M_DITHER_DOWN_EN (1 << 2) +#define M_PRE_DITHER_DOWN_EN (1 << 1) +#define M_DSP_LUT_EN (1) + +#define V_DSP_LAYER3_SEL(x) (((x) & 3) << 14) +#define V_DSP_LAYER2_SEL(x) (((x) & 3) << 12) +#define V_DSP_LAYER1_SEL(x) (((x) & 3) << 10) +#define V_DSP_LAYER0_SEL(x) (((x) & 3) << 8) +#define V_DITHER_UP_EN(x) (((x) & 1) << 6) +#define V_DITHER_DOWN_SEL(x) (((x) & 1) << 4) +#define V_DITHER_DOWN_MODE(x) (((x) & 1) << 3) +#define V_DITHER_DOWN_EN(x) (((x) & 1) << 2) +#define V_PRE_DITHER_DOWN_EN(x) (((x) & 1) << 1) +#define V_DSP_LUT_EN(x) ((x)&1) + +/* VOP_DSP_BG */ +#define M_DSP_BG_RED (0x3f << 20) +#define M_DSP_BG_GREEN (0x3f << 10) +#define M_DSP_BG_BLUE (0x3f << 0) + +#define V_DSP_BG_RED(x) (((x) & 0x3f) << 20) +#define V_DSP_BG_GREEN(x) (((x) & 0x3f) << 10) +#define V_DSP_BG_BLUE(x) (((x) & 0x3f) << 0) + +/* VOP_WIN0_CTRL0 */ +#define M_WIN0_YUV_CLIP (1 << 20) +#define M_WIN0_CBR_DEFLICK (1 << 19) +#define M_WIN0_YRGB_DEFLICK (1 << 18) +#define M_WIN0_PPAS_ZERO_EN (1 << 16) +#define M_WIN0_UV_SWAP (1 << 15) +#define M_WIN0_MID_SWAP (1 << 14) +#define M_WIN0_ALPHA_SWAP (1 << 13) +#define M_WIN0_RB_SWAP (1 << 12) +#define M_WIN0_CSC_MODE (3 << 10) +#define M_WIN0_NO_OUTSTANDING (1 << 9) +#define M_WIN0_INTERLACE_READ (1 << 8) +#define M_WIN0_LB_MODE (7 << 5) +#define M_WIN0_FMT_10 (1 << 4) +#define M_WIN0_DATA_FMT (7 << 1) +#define M_WIN0_EN (1 << 0) + +#define V_WIN0_YUV_CLIP(x) (((x) & 1) << 20) +#define V_WIN0_CBR_DEFLICK(x) (((x) & 1) << 19) +#define V_WIN0_YRGB_DEFLICK(x) (((x) & 1) << 18) +#define V_WIN0_PPAS_ZERO_EN(x) (((x) & 1) << 16) +#define V_WIN0_UV_SWAP(x) (((x) & 1) << 15) +#define V_WIN0_MID_SWAP(x) (((x) & 1) << 14) +#define V_WIN0_ALPHA_SWAP(x) (((x) & 1) << 13) +#define V_WIN0_RB_SWAP(x) (((x) & 1) << 12) +#define V_WIN0_CSC_MODE(x) (((x) & 3) << 10) +#define V_WIN0_NO_OUTSTANDING(x) (((x) & 1) << 9) +#define V_WIN0_INTERLACE_READ(x) (((x) & 1) << 8) +#define V_WIN0_LB_MODE(x) (((x) & 7) << 5) +#define V_WIN0_FMT_10(x) (((x) & 1) << 4) +#define V_WIN0_DATA_FMT(x) (((x) & 7) << 1) +#define V_WIN0_EN(x) ((x) & 1) + +/* VOP_WIN0_CTRL1 */ +#define M_WIN0_CBR_VSD_MODE (1 << 31) +#define M_WIN0_CBR_VSU_MODE (1 << 30) +#define M_WIN0_CBR_HSD_MODE (3 << 28) +#define M_WIN0_CBR_VER_SCL_MODE (3 << 26) +#define M_WIN0_CBR_HOR_SCL_MODE (3 << 24) +#define M_WIN0_YRGB_VSD_MODE (1 << 23) +#define M_WIN0_YRGB_VSU_MODE (1 << 22) +#define M_WIN0_YRGB_HSD_MODE (3 << 20) +#define M_WIN0_YRGB_VER_SCL_MODE (3 << 18) +#define M_WIN0_YRGB_HOR_SCL_MODE (3 << 16) +#define M_WIN0_LINE_LOAD_MODE (1 << 15) +#define M_WIN0_CBR_AXI_GATHER_NUM (7 << 12) +#define M_WIN0_YRGB_AXI_GATHER_NUM (0xf << 8) +#define M_WIN0_VSD_CBR_GT2 (1 << 7) +#define M_WIN0_VSD_CBR_GT4 (1 << 6) +#define M_WIN0_VSD_YRGB_GT2 (1 << 5) +#define M_WIN0_VSD_YRGB_GT4 (1 << 4) +#define M_WIN0_BIC_COE_SEL (3 << 2) +#define M_WIN0_CBR_AXI_GATHER_EN (1 << 1) +#define M_WIN0_YRGB_AXI_GATHER_EN (1) + +#define V_WIN0_CBR_VSD_MODE(x) (((x) & 1) << 31) +#define V_WIN0_CBR_VSU_MODE(x) (((x) & 1) << 30) +#define V_WIN0_CBR_HSD_MODE(x) (((x) & 3) << 28) +#define V_WIN0_CBR_VER_SCL_MODE(x) (((x) & 3) << 26) +#define V_WIN0_CBR_HOR_SCL_MODE(x) (((x) & 3) << 24) +#define V_WIN0_YRGB_VSD_MODE(x) (((x) & 1) << 23) +#define V_WIN0_YRGB_VSU_MODE(x) (((x) & 1) << 22) +#define V_WIN0_YRGB_HSD_MODE(x) (((x) & 3) << 20) +#define V_WIN0_YRGB_VER_SCL_MODE(x) (((x) & 3) << 18) +#define V_WIN0_YRGB_HOR_SCL_MODE(x) (((x) & 3) << 16) +#define V_WIN0_LINE_LOAD_MODE(x) (((x) & 1) << 15) +#define V_WIN0_CBR_AXI_GATHER_NUM(x) (((x) & 7) << 12) +#define V_WIN0_YRGB_AXI_GATHER_NUM(x) (((x) & 0xf) << 8) +#define V_WIN0_VSD_CBR_GT2(x) (((x) & 1) << 7) +#define V_WIN0_VSD_CBR_GT4(x) (((x) & 1) << 6) +#define V_WIN0_VSD_YRGB_GT2(x) (((x) & 1) << 5) +#define V_WIN0_VSD_YRGB_GT4(x) (((x) & 1) << 4) +#define V_WIN0_BIC_COE_SEL(x) (((x) & 3) << 2) +#define V_WIN0_CBR_AXI_GATHER_EN(x) (((x) & 1) << 1) +#define V_WIN0_YRGB_AXI_GATHER_EN(x) ((x) & 1) + +/*VOP_WIN0_COLOR_KEY*/ +#define M_WIN0_KEY_EN (1 << 31) +#define M_WIN0_KEY_COLOR (0x3fffffff) + +#define V_WIN0_KEY_EN(x) (((x) & 1) << 31) +#define V_WIN0_KEY_COLOR(x) ((x) & 0x3fffffff) + +/* VOP_WIN0_VIR */ +#define V_ARGB888_VIRWIDTH(x) (((x) & 0x3fff) << 0) +#define V_RGB888_VIRWIDTH(x) (((((x * 3) >> 2)+((x) % 3)) & 0x3fff) << 0) +#define V_RGB565_VIRWIDTH(x) (((x / 2) & 0x3fff) << 0) +#define YUV_VIRWIDTH(x) (((x / 4) & 0x3fff) << 0) + +/* VOP_WIN0_ACT_INFO */ +#define V_ACT_HEIGHT(x) (((x) & 0x1fff) << 16) +#define V_ACT_WIDTH(x) ((x) & 0x1fff) + +/* VOP_WIN0_DSP_INFO */ +#define V_DSP_HEIGHT(x) (((x) & 0xfff) << 16) +#define V_DSP_WIDTH(x) ((x) & 0xfff) + +/* VOP_WIN0_DSP_ST */ +#define V_DSP_YST(x) (((x) & 0x1fff) << 16) +#define V_DSP_XST(x) ((x) & 0x1fff) + +/* VOP_WIN0_SCL_OFFSET */ +#define V_WIN0_VS_OFFSET_CBR(x) (((x) & 0xff) << 24) +#define V_WIN0_VS_OFFSET_YRGB(x) (((x) & 0xff) << 16) +#define V_WIN0_HS_OFFSET_CBR(x) (((x) & 0xff) << 8) +#define V_WIN0_HS_OFFSET_YRGB(x) ((x) & 0xff) + +#define V_HSYNC(x) (((x)&0x1fff)<<0) /* hsync pulse width */ +#define V_HORPRD(x) (((x)&0x1fff)<<16) /* horizontal period */ +#define V_VSYNC(x) (((x)&0x1fff)<<0) +#define V_VERPRD(x) (((x)&0x1fff)<<16) + +#define V_HEAP(x) (((x)&0x1fff)<<0)/* horizontal active end */ +#define V_HASP(x) (((x)&0x1fff)<<16)/* horizontal active start */ +#define V_VAEP(x) (((x)&0x1fff)<<0) +#define V_VASP(x) (((x)&0x1fff)<<16) + +void rkvop_mode_set(u32 vop_id, const struct edid *edid, u32 mode); +void rkvop_enable(u32 vop_id, u32 fbbase, const struct edid *edid); +#endif diff --git a/src/soc/rockchip/rk3288/pwm.c b/src/soc/rockchip/rk3288/pwm.c new file mode 100644 index 0000000000..a44724959e --- /dev/null +++ b/src/soc/rockchip/rk3288/pwm.c @@ -0,0 +1,89 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pwm_ctl { + u32 pwm_cnt; + u32 pwm_period_hpr; + u32 pwm_duty_lpr; + u32 pwm_ctrl; +}; + +struct rk3288_pwm_regs { + struct pwm_ctl pwm[4]; + u32 intsts; + u32 int_en; +}; +check_member(rk3288_pwm_regs, int_en, 0x44); + +#define RK_PWM_DISABLE (0 << 0) +#define RK_PWM_ENABLE (1 << 0) + + +#define PWM_ONE_SHOT (0 << 1) +#define PWM_CONTINUOUS (1 << 1) +#define RK_PWM_CAPTURE (1 << 2) + +#define PWM_DUTY_POSTIVE (1 << 3) +#define PWM_DUTY_NEGATIVE (0 << 3) + +#define PWM_INACTIVE_POSTIVE (1 << 4) +#define PWM_INACTIVE_NEGATIVE (0 << 4) + +#define PWM_OUTPUT_LEFT (0 << 5) +#define PWM_OUTPUT_CENTER (1 << 5) + +#define PWM_LP_ENABLE (1 << 8) +#define PWM_LP_DISABLE (0 << 8) + +#define PWM_SEL_SCALE_CLK (1 << 9) +#define PWM_SEL_SRC_CLK (0 << 9) + +struct rk3288_pwm_regs *rk3288_pwm = (void *)RK_PWM0123_BASE; + +void pwm_init(u32 id, u32 period_ns, u32 duty_ns) +{ + unsigned long period, duty; + + /*use rk pwm*/ + writel(RK_SETBITS(1 << 0), &rk3288_grf->soc_con2); + + writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | + PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE | + RK_PWM_DISABLE, + &rk3288_pwm->pwm[id].pwm_ctrl); + + period = (PD_BUS_PCLK_HZ / 1000) * period_ns / USECS_PER_SEC; + duty = (PD_BUS_PCLK_HZ / 1000) * duty_ns / USECS_PER_SEC; + + writel(period, &rk3288_pwm->pwm[id].pwm_period_hpr); + writel(duty, &rk3288_pwm->pwm[id].pwm_duty_lpr); + setbits_le32(&rk3288_pwm->pwm[id].pwm_ctrl, RK_PWM_ENABLE); +} diff --git a/src/soc/rockchip/rk3288/rk808.c b/src/soc/rockchip/rk3288/rk808.c new file mode 100644 index 0000000000..d8d503f71c --- /dev/null +++ b/src/soc/rockchip/rk3288/rk808.c @@ -0,0 +1,213 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_PMIC_BUS < 0 +#error "PMIC_BUS must be set in mainboard's Kconfig." +#endif + +#define RK808_ADDR 0x1b + +#define DCDC_EN 0x23 +#define LDO_EN 0x24 +#define BUCK1SEL 0x2f +#define BUCK4SEL 0x38 +#define LDO_ONSEL(i) (0x39 + 2 * i) +#define LDO_SLPSEL(i) (0x3a + 2 * i) + +#define RTC_SECOND 0x00 +#define RTC_MINUTE 0x01 +#define RTC_HOUR 0x02 +#define RTC_DAY 0x03 +#define RTC_MONTH 0x04 +#define RTC_YEAR 0x05 +#define RTC_WEEKS 0x06 +#define RTC_CTRL 0x10 +#define RTC_STATUS 0x11 + +#define RTC_CTRL_STOP_RTC (1 << 0) +#define RTC_CTRL_GET_TIME (1 << 6) +#define RTC_CTRL_RTC_READSEL (1 << 7) + +#define DCDC_UV_ACT 0x28 +#define DCDC_ILMAX 0x90 + +static int rk808_read(uint8_t reg, uint8_t *value) +{ + return i2c_readb(CONFIG_PMIC_BUS, RK808_ADDR, reg, value); +} + +static int rk808_write(uint8_t reg, uint8_t value) +{ + return i2c_writeb(CONFIG_PMIC_BUS, RK808_ADDR, reg, value); +} + +static void rk808_clrsetbits(uint8_t reg, uint8_t clr, uint8_t set) +{ + uint8_t value; + + if (rk808_read(reg, &value) || rk808_write(reg, (value & ~clr) | set)) + printk(BIOS_ERR, "ERROR: Cannot set Rk808[%#x]!\n", reg); +} + +void rk808_configure_switch(int sw, int enabled) +{ + assert(sw == 1 || sw == 2); + rk808_clrsetbits(DCDC_EN, 1 << (sw + 4), !!enabled << (sw + 4)); +} + +void rk808_configure_ldo(int ldo, int millivolts) +{ + uint8_t vsel; + + if (!millivolts) { + rk808_clrsetbits(LDO_EN, 1 << (ldo - 1), 0); + return; + } + + switch (ldo) { + case 1: + case 2: + case 4: + case 5: + case 8: + vsel = div_round_up(millivolts, 100) - 18; + assert(vsel <= 0x10); + break; + case 3: + case 6: + case 7: + vsel = div_round_up(millivolts, 100) - 8; + assert(vsel <= 0x11); + break; + default: + die("Unknown LDO index!"); + } + + rk808_clrsetbits(LDO_ONSEL(ldo), 0x1f, vsel); + rk808_clrsetbits(LDO_EN, 0, 1 << (ldo - 1)); +} + +void rk808_configure_buck(int buck, int millivolts) +{ + uint8_t vsel; + uint8_t buck_reg; + + switch (buck) { + case 1: + case 2: + /* 25mV steps. base = 29 * 25mV = 725 */ + vsel = (div_round_up(millivolts, 25) - 29) * 2 + 1; + assert(vsel <= 0x3f); + buck_reg = BUCK1SEL + 4 * (buck - 1); + break; + case 4: + vsel = div_round_up(millivolts, 100) - 18; + assert(vsel <= 0xf); + buck_reg = BUCK4SEL; + break; + default: + die("Unknown buck index!"); + } + rk808_clrsetbits(DCDC_ILMAX, 0, 3 << ((buck - 1) * 2)); + + /* undervoltage detection may be wrong, disable it */ + rk808_clrsetbits(DCDC_UV_ACT, 1 << (buck - 1), 0); + + rk808_clrsetbits(buck_reg, 0x3f, vsel); + rk808_clrsetbits(DCDC_EN, 0, 1 << (buck - 1)); +} + +static void rk808rtc_stop(void) +{ + rk808_clrsetbits(RTC_CTRL, RTC_CTRL_STOP_RTC, 0); +} + +static void rk808rtc_start(void) +{ + rk808_clrsetbits(RTC_CTRL, 0, RTC_CTRL_STOP_RTC); +} + +int rtc_set(const struct rtc_time *time) +{ + int ret = 0; + + /* RTC time can only be set when RTC is frozen */ + rk808rtc_stop(); + + ret |= rk808_write(RTC_SECOND, bin2bcd(time->sec)); + ret |= rk808_write(RTC_MINUTE, bin2bcd(time->min)); + ret |= rk808_write(RTC_HOUR, bin2bcd(time->hour)); + ret |= rk808_write(RTC_DAY, bin2bcd(time->mday)); + ret |= rk808_write(RTC_MONTH, bin2bcd(time->mon)); + ret |= rk808_write(RTC_YEAR, bin2bcd(time->year)); + + rk808rtc_start(); + return ret; +} + +int rtc_get(struct rtc_time *time) +{ + uint8_t value; + int ret = 0; + + /* + * Set RTC_READSEL to cause reads to access shadow registers and + * transition GET_TIME from 0 to 1 to cause dynamic register content + * to be copied into shadow registers. This ensures a coherent reading + * of time values as we access each register using slow I2C transfers. + */ + rk808_clrsetbits(RTC_CTRL, RTC_CTRL_GET_TIME, 0); + rk808_clrsetbits(RTC_CTRL, 0, RTC_CTRL_GET_TIME | RTC_CTRL_RTC_READSEL); + + /* + * After we set the GET_TIME bit, the rtc time can't be read + * immediately. So we should wait up to 31.25 us. + */ + udelay(32); + + ret |= rk808_read(RTC_SECOND, &value); + time->sec = bcd2bin(value & 0x7f); + + ret |= rk808_read(RTC_MINUTE, &value); + time->min = bcd2bin(value & 0x7f); + + ret |= rk808_read(RTC_HOUR, &value); + time->hour = bcd2bin(value & 0x3f); + + ret |= rk808_read(RTC_DAY, &value); + time->mday = bcd2bin(value & 0x3f); + + ret |= rk808_read(RTC_MONTH, &value); + time->mon = bcd2bin(value & 0x1f); + + ret |= rk808_read(RTC_YEAR, &value); + time->year = bcd2bin(value); + + return ret; +} diff --git a/src/soc/rockchip/rk3288/sdram.c b/src/soc/rockchip/rk3288/sdram.c new file mode 100644 index 0000000000..4a435729db --- /dev/null +++ b/src/soc/rockchip/rk3288/sdram.c @@ -0,0 +1,1132 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rk3288_ddr_pctl_regs { + u32 scfg; + u32 sctl; + u32 stat; + u32 intrstat; + u32 reserved0[12]; + u32 mcmd; + u32 powctl; + u32 powstat; + u32 cmdtstat; + u32 tstaten; + u32 reserved1[3]; + u32 mrrcfg0; + u32 mrrstat0; + u32 mrrstat1; + u32 reserved2[4]; + u32 mcfg1; + u32 mcfg; + u32 ppcfg; + u32 mstat; + u32 lpddr2zqcfg; + u32 reserved3; + u32 dtupdes; + u32 dtuna; + u32 dtune; + u32 dtuprd0; + u32 dtuprd1; + u32 dtuprd2; + u32 dtuprd3; + u32 dtuawdt; + u32 reserved4[3]; + u32 togcnt1u; + u32 tinit; + u32 trsth; + u32 togcnt100n; + u32 trefi; + u32 tmrd; + u32 trfc; + u32 trp; + u32 trtw; + u32 tal; + u32 tcl; + u32 tcwl; + u32 tras; + u32 trc; + u32 trcd; + u32 trrd; + u32 trtp; + u32 twr; + u32 twtr; + u32 texsr; + u32 txp; + u32 txpdll; + u32 tzqcs; + u32 tzqcsi; + u32 tdqs; + u32 tcksre; + u32 tcksrx; + u32 tcke; + u32 tmod; + u32 trstl; + u32 tzqcl; + u32 tmrr; + u32 tckesr; + u32 tdpd; + u32 reserved5[14]; + u32 ecccfg; + u32 ecctst; + u32 eccclr; + u32 ecclog; + u32 reserved6[28]; + u32 dtuwactl; + u32 dturactl; + u32 dtucfg; + u32 dtuectl; + u32 dtuwd0; + u32 dtuwd1; + u32 dtuwd2; + u32 dtuwd3; + u32 dtuwdm; + u32 dturd0; + u32 dturd1; + u32 dturd2; + u32 dturd3; + u32 dtulfsrwd; + u32 dtulfsrrd; + u32 dtueaf; + u32 dfitctrldelay; + u32 dfiodtcfg; + u32 dfiodtcfg1; + u32 dfiodtrankmap; + u32 dfitphywrdata; + u32 dfitphywrlat; + u32 reserved7[2]; + u32 dfitrddataen; + u32 dfitphyrdlat; + u32 reserved8[2]; + u32 dfitphyupdtype0; + u32 dfitphyupdtype1; + u32 dfitphyupdtype2; + u32 dfitphyupdtype3; + u32 dfitctrlupdmin; + u32 dfitctrlupdmax; + u32 dfitctrlupddly; + u32 reserved9; + u32 dfiupdcfg; + u32 dfitrefmski; + u32 dfitctrlupdi; + u32 reserved10[4]; + u32 dfitrcfg0; + u32 dfitrstat0; + u32 dfitrwrlvlen; + u32 dfitrrdlvlen; + u32 dfitrrdlvlgateen; + u32 dfiststat0; + u32 dfistcfg0; + u32 dfistcfg1; + u32 reserved11; + u32 dfitdramclken; + u32 dfitdramclkdis; + u32 dfistcfg2; + u32 dfistparclr; + u32 dfistparlog; + u32 reserved12[3]; + u32 dfilpcfg0; + u32 reserved13[3]; + u32 dfitrwrlvlresp0; + u32 dfitrwrlvlresp1; + u32 dfitrwrlvlresp2; + u32 dfitrrdlvlresp0; + u32 dfitrrdlvlresp1; + u32 dfitrrdlvlresp2; + u32 dfitrwrlvldelay0; + u32 dfitrwrlvldelay1; + u32 dfitrwrlvldelay2; + u32 dfitrrdlvldelay0; + u32 dfitrrdlvldelay1; + u32 dfitrrdlvldelay2; + u32 dfitrrdlvlgatedelay0; + u32 dfitrrdlvlgatedelay1; + u32 dfitrrdlvlgatedelay2; + u32 dfitrcmd; + u32 reserved14[46]; + u32 ipvr; + u32 iptr; +}; +check_member(rk3288_ddr_pctl_regs, iptr, 0x03fc); + +struct rk3288_ddr_publ_datx { + u32 dxgcr; + u32 dxgsr[2]; + u32 dxdllcr; + u32 dxdqtr; + u32 dxdqstr; + u32 reserved[10]; +}; + +struct rk3288_ddr_publ_regs { + u32 ridr; + u32 pir; + u32 pgcr; + u32 pgsr; + u32 dllgcr; + u32 acdllcr; + u32 ptr[3]; + u32 aciocr; + u32 dxccr; + u32 dsgcr; + u32 dcr; + u32 dtpr[3]; + u32 mr[4]; + u32 odtcr; + u32 dtar; + u32 dtdr[2]; + u32 reserved1[24]; + u32 dcuar; + u32 dcudr; + u32 dcurr; + u32 dculr; + u32 dcugcr; + u32 dcutpr; + u32 dcusr[2]; + u32 reserved2[8]; + u32 bist[17]; + u32 reserved3[15]; + u32 zq0cr[2]; + u32 zq0sr[2]; + u32 zq1cr[2]; + u32 zq1sr[2]; + u32 zq2cr[2]; + u32 zq2sr[2]; + u32 zq3cr[2]; + u32 zq3sr[2]; + struct rk3288_ddr_publ_datx datx8[4]; +}; +check_member(rk3288_ddr_publ_regs, datx8[3].dxdqstr, 0x0294); + +struct rk3288_msch_regs { + u32 coreid; + u32 revisionid; + u32 ddrconf; + u32 ddrtiming; + u32 ddrmode; + u32 readlatency; + u32 reserved1[8]; + u32 activate; + u32 devtodev; +}; +check_member(rk3288_msch_regs, devtodev, 0x003c); + +static struct rk3288_ddr_pctl_regs * const rk3288_ddr_pctl[2] = { + (void *)DDR_PCTL0_BASE, (void *)DDR_PCTL1_BASE}; +static struct rk3288_ddr_publ_regs * const rk3288_ddr_publ[2] = { + (void *)DDR_PUBL0_BASE, (void *)DDR_PUBL1_BASE}; +static struct rk3288_msch_regs * const rk3288_msch[2] = { + (void *)SERVICE_BUS_BASE, (void *)SERVICE_BUS_BASE + 0x80}; + +/* PCT_DFISTCFG0 */ +#define DFI_INIT_START (1 << 0) + +/* PCT_DFISTCFG1 */ +#define DFI_DRAM_CLK_SR_EN (1 << 0) +#define DFI_DRAM_CLK_DPD_EN (1 << 1) + +/* PCT_DFISTCFG2 */ +#define DFI_PARITY_INTR_EN (1 << 0) +#define DFI_PARITY_EN (1 << 1) + +/* PCT_DFILPCFG0 */ +#define TLP_RESP_TIME(n) (n << 16) +#define LP_SR_EN (1 << 8) +#define LP_PD_EN (1 << 0) + +/* PCT_DFITCTRLDELAY */ +#define TCTRL_DELAY_TIME(n) (n << 0) + +/* PCT_DFITPHYWRDATA */ +#define TPHY_WRDATA_TIME(n) (n << 0) + +/* PCT_DFITPHYRDLAT */ +#define TPHY_RDLAT_TIME(n) (n << 0) + +/* PCT_DFITDRAMCLKDIS */ +#define TDRAM_CLK_DIS_TIME(n) (n << 0) + +/* PCT_DFITDRAMCLKEN */ +#define TDRAM_CLK_EN_TIME(n) (n << 0) + +/* PCTL_DFIODTCFG */ +#define RANK0_ODT_WRITE_SEL (1 << 3) +#define RANK1_ODT_WRITE_SEL (1 << 11) + +/* PCTL_DFIODTCFG1 */ +#define ODT_LEN_BL8_W(n) (n<<16) + +/* PUBL_ACDLLCR */ +#define ACDLLCR_DLLDIS (1 << 31) +#define ACDLLCR_DLLSRST (1 << 30) + +/* PUBL_DXDLLCR */ +#define DXDLLCR_DLLDIS (1 << 31) +#define DXDLLCR_DLLSRST (1 << 30) + +/* PUBL_DLLGCR */ +#define DLLGCR_SBIAS (1 << 30) + +/* PUBL_DXGCR */ +#define DQSRTT (1 << 9) +#define DQRTT (1 << 10) + +/* PIR */ +#define PIR_INIT (1 << 0) +#define PIR_DLLSRST (1 << 1) +#define PIR_DLLLOCK (1 << 2) +#define PIR_ZCAL (1 << 3) +#define PIR_ITMSRST (1 << 4) +#define PIR_DRAMRST (1 << 5) +#define PIR_DRAMINIT (1 << 6) +#define PIR_QSTRN (1 << 7) +#define PIR_RVTRN (1 << 8) +#define PIR_ICPC (1 << 16) +#define PIR_DLLBYP (1 << 17) +#define PIR_CTLDINIT (1 << 18) +#define PIR_CLRSR (1 << 28) +#define PIR_LOCKBYP (1 << 29) +#define PIR_ZCALBYP (1 << 30) +#define PIR_INITBYP (1u << 31) + +/* PGCR */ +#define PGCR_DFTLMT(n) ((n) << 3) +#define PGCR_DFTCMP(n) ((n) << 2) +#define PGCR_DQSCFG(n) ((n) << 1) +#define PGCR_ITMDMD(n) ((n) << 0) + +/* PGSR */ +#define PGSR_IDONE (1 << 0) +#define PGSR_DLDONE (1 << 1) +#define PGSR_ZCDONE (1 << 2) +#define PGSR_DIDONE (1 << 3) +#define PGSR_DTDONE (1 << 4) +#define PGSR_DTERR (1 << 5) +#define PGSR_DTIERR (1 << 6) +#define PGSR_DFTERR (1 << 7) +#define PGSR_RVERR (1 << 8) +#define PGSR_RVEIRR (1 << 9) + +/* PTR0 */ +#define PRT_ITMSRST(n) ((n) << 18) +#define PRT_DLLLOCK(n) ((n) << 6) +#define PRT_DLLSRST(n) ((n) << 0) + +/* PTR1 */ +#define PRT_DINIT0(n) ((n) << 0) +#define PRT_DINIT1(n) ((n) << 19) + +/* PTR2 */ +#define PRT_DINIT2(n) ((n) << 0) +#define PRT_DINIT3(n) ((n) << 17) + +/* DCR */ +#define DDRMD_LPDDR 0 +#define DDRMD_DDR 1 +#define DDRMD_DDR2 2 +#define DDRMD_DDR3 3 +#define DDRMD_LPDDR2_LPDDR3 4 +#define DDRMD_MSK (7 << 0) +#define DDRMD_CFG(n) ((n) << 0) +#define PDQ_MSK (7 << 4) +#define PDQ_CFG(n) ((n) << 4) + +/* DXCCR */ +#define DQSNRES_MSK (0x0f << 8) +#define DQSNRES_CFG(n) ((n) << 8) +#define DQSRES_MSK (0x0f << 4) +#define DQSRES_CFG(n) ((n) << 4) + +/* DTPR */ +#define TDQSCKMAX_VAL(n) (((n) >> 27) & 7) +#define TDQSCK_VAL(n) (((n) >> 24) & 7) + +/* DSGCR */ +#define DQSGX_MSK (0x07 << 5) +#define DQSGX_CFG(n) ((n) << 5) +#define DQSGE_MSK (0x07 << 8) +#define DQSGE_CFG(n) ((n) << 8) + +/* SCTL */ +#define INIT_STATE (0) +#define CFG_STATE (1) +#define GO_STATE (2) +#define SLEEP_STATE (3) +#define WAKEUP_STATE (4) + +/* STAT */ +#define LP_TRIG_VAL(n) (((n) >> 4) & 7) +#define PCTL_STAT_MSK (7) +#define INIT_MEM (0) +#define CONFIG (1) +#define CONFIG_REQ (2) +#define ACCESS (3) +#define ACCESS_REQ (4) +#define LOW_POWER (5) +#define LOW_POWER_ENTRY_REQ (6) +#define LOW_POWER_EXIT_REQ (7) + +/* ZQCR*/ +#define PD_OUTPUT(n) ((n) << 0) +#define PU_OUTPUT(n) ((n) << 5) +#define PD_ONDIE(n) ((n) << 10) +#define PU_ONDIE(n) ((n) << 15) +#define ZDEN(n) ((n) << 28) + +/* DDLGCR */ +#define SBIAS_BYPASS (1 << 23) + +/* MCFG */ +#define MDDR_LPDDR2_CLK_STOP_IDLE(n) ((n) << 24) +#define PD_IDLE(n) ((n) << 8) +#define MDDR_EN (2 << 22) +#define LPDDR2_EN (3 << 22) +#define DDR2_EN (0 << 5) +#define DDR3_EN (1 << 5) +#define LPDDR2_S2 (0 << 6) +#define LPDDR2_S4 (1 << 6) +#define MDDR_LPDDR2_BL_2 (0 << 20) +#define MDDR_LPDDR2_BL_4 (1 << 20) +#define MDDR_LPDDR2_BL_8 (2 << 20) +#define MDDR_LPDDR2_BL_16 (3 << 20) +#define DDR2_DDR3_BL_4 (0) +#define DDR2_DDR3_BL_8 (1) +#define TFAW_CFG(n) (((n)-4) << 18) +#define PD_EXIT_SLOW (0 << 17) +#define PD_EXIT_FAST (1 << 17) +#define PD_TYPE(n) ((n) << 16) +#define BURSTLENGTH_CFG(n) (((n) >> 1) << 20) + +/* POWCTL */ +#define POWER_UP_START (1 << 0) + +/* POWSTAT */ +#define POWER_UP_DONE (1 << 0) + +/* MCMD */ +#define DESELECT_CMD (0) +#define PREA_CMD (1) +#define REF_CMD (2) +#define MRS_CMD (3) +#define ZQCS_CMD (4) +#define ZQCL_CMD (5) +#define RSTL_CMD (6) +#define MRR_CMD (8) +#define DPDE_CMD (9) + +#define LPDDR2_MA(n) (((n) & 0xff) << 4) +#define LPDDR2_OP(n) (((n) & 0xff) << 12) + +#define START_CMD (1u << 31) + +/* DEVTODEV */ +#define BUSWRTORD(n) ((n) << 4) +#define BUSRDTOWR(n) ((n) << 2) +#define BUSRDTORD(n) ((n) << 0) + +/* GRF_SOC_CON0 */ +#define MSCH_MAINDDR3(ch, n) (((n) << (3 + (ch))) \ + | ((1 << (3 + (ch))) << 16)) + +/* GRF_SOC_CON2 */ +#define PCTL_LPDDR3_ODT_EN(ch, n) RK_CLRSETBITS(1 << (10 + (3 * (ch))), \ + (n) << (10 + (3 * (ch)))) +#define PCTL_BST_DISABLE(ch, n) RK_CLRSETBITS(1 << (9 + (3 * (ch))), \ + (n) << (9 + (3 * (ch)))) +#define PUBL_LPDDR3_EN(ch, n) RK_CLRSETBITS(1 << (8 + (3 * (ch))), \ + (n) << (8 + (3 * (ch)))) + +/* mr1 for ddr3 */ +#define DDR3_DLL_ENABLE (0) +#define DDR3_DLL_DISABLE (1) + +/* + * sys_reg bitfield struct + * [31] row_3_4_ch1 + * [30] row_3_4_ch0 + * [29:28] chinfo + * [27] rank_ch1 + * [26:25] col_ch1 + * [24] bk_ch1 + * [23:22] cs0_row_ch1 + * [21:20] cs1_row_ch1 + * [19:18] bw_ch1 + * [17:16] dbw_ch1; + * [15:13] ddrtype + * [12] channelnum + * [11] rank_ch0 + * [10:9] col_ch0 + * [8] bk_ch0 + * [7:6] cs0_row_ch0 + * [5:4] cs1_row_ch0 + * [3:2] bw_ch0 + * [1:0] dbw_ch0 +*/ +#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch))) +#define SYS_REG_DEC_ROW_3_4(n, ch) ((n >> (30 + ch)) & 0x1) +#define SYS_REG_ENC_CHINFO(ch) (1 << (28 + (ch))) +#define SYS_REG_ENC_DDRTYPE(n) ((n) << 13) +#define SYS_REG_ENC_NUM_CH(n) (((n) - 1) << 12) +#define SYS_REG_DEC_NUM_CH(n) (1 + ((n >> 12) & 0x1)) +#define SYS_REG_ENC_RANK(n, ch) (((n) - 1) << (11 + ((ch) * 16))) +#define SYS_REG_DEC_RANK(n, ch) (1 + ((n >> (11 + 16 * ch)) & 0x1)) +#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << (9 + ((ch) * 16))) +#define SYS_REG_DEC_COL(n, ch) (9 + ((n >> (9 + 16 * ch)) & 0x3)) +#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) \ + << (8 + ((ch) * 16))) +#define SYS_REG_DEC_BK(n, ch) (3 - ((n >> (8 + 16 * ch)) & 0x1)) +#define SYS_REG_ENC_CS0_ROW(n, ch) (((n) - 13) << (6 + ((ch) * 16))) +#define SYS_REG_DEC_CS0_ROW(n, ch) (13 + ((n >> (6 + 16 * ch)) & 0x3)) +#define SYS_REG_ENC_CS1_ROW(n, ch) (((n) - 13) << (4 + ((ch) * 16))) +#define SYS_REG_DEC_CS1_ROW(n, ch) (13 + ((n >> (4 + 16 * ch)) & 0x3)) +#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << (2 + ((ch) * 16))) +#define SYS_REG_DEC_BW(n, ch) (2 >> ((n >> (2 + 16 * ch)) & 0x3)) +#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << (0 + ((ch) * 16))) +#define SYS_REG_DEC_DBW(n, ch) (2 >> ((n >> (0 + 16 * ch)) & 0x3)) + +static void copy_to_reg(u32 *dest, const u32 *src, u32 n) +{ + int i; + for (i = 0; i < n / sizeof(u32); i++) { + writel(*src, dest); + src++; + dest++; + } +} + +static void phy_pctrl_reset(struct rk3288_ddr_publ_regs *ddr_publ_regs, + u32 channel) +{ + int i; + rkclk_ddr_reset(channel, 1, 1); + udelay(1); + clrbits_le32(&ddr_publ_regs->acdllcr, ACDLLCR_DLLSRST); + for (i = 0; i < 4; i++) + clrbits_le32(&ddr_publ_regs->datx8[i].dxdllcr, DXDLLCR_DLLSRST); + + udelay(10); + setbits_le32(&ddr_publ_regs->acdllcr, ACDLLCR_DLLSRST); + for (i = 0; i < 4; i++) + setbits_le32(&ddr_publ_regs->datx8[i].dxdllcr, DXDLLCR_DLLSRST); + + udelay(10); + rkclk_ddr_reset(channel, 1, 0); + udelay(10); + rkclk_ddr_reset(channel, 0, 0); + udelay(10); +} + +static void phy_dll_bypass_set(struct rk3288_ddr_publ_regs *ddr_publ_regs, + u32 freq) +{ + int i; + if (freq <= 250*MHz) { + if (freq <= 150*MHz) + clrbits_le32(&ddr_publ_regs->dllgcr, SBIAS_BYPASS); + else + setbits_le32(&ddr_publ_regs->dllgcr, SBIAS_BYPASS); + setbits_le32(&ddr_publ_regs->acdllcr, ACDLLCR_DLLDIS); + for (i = 0; i < 4; i++) + setbits_le32(&ddr_publ_regs->datx8[i].dxdllcr, + DXDLLCR_DLLDIS); + + setbits_le32(&ddr_publ_regs->pir, PIR_DLLBYP); + } else { + clrbits_le32(&ddr_publ_regs->dllgcr, SBIAS_BYPASS); + clrbits_le32(&ddr_publ_regs->acdllcr, ACDLLCR_DLLDIS); + for (i = 0; i < 4; i++) + clrbits_le32(&ddr_publ_regs->datx8[i].dxdllcr, + DXDLLCR_DLLDIS); + + clrbits_le32(&ddr_publ_regs->pir, PIR_DLLBYP); + } +} + +static void dfi_cfg(struct rk3288_ddr_pctl_regs *ddr_pctl_regs, u32 dramtype) +{ + writel(DFI_INIT_START, &ddr_pctl_regs->dfistcfg0); + writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, + &ddr_pctl_regs->dfistcfg1); + writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &ddr_pctl_regs->dfistcfg2); + writel(TLP_RESP_TIME(7) | LP_SR_EN | LP_PD_EN, + &ddr_pctl_regs->dfilpcfg0); + + writel(TCTRL_DELAY_TIME(2), &ddr_pctl_regs->dfitctrldelay); + writel(TPHY_WRDATA_TIME(1), &ddr_pctl_regs->dfitphywrdata); + writel(TPHY_RDLAT_TIME(0xf), &ddr_pctl_regs->dfitphyrdlat); + writel(TDRAM_CLK_DIS_TIME(2), &ddr_pctl_regs->dfitdramclkdis); + writel(TDRAM_CLK_EN_TIME(2), &ddr_pctl_regs->dfitdramclken); + writel(0x1, &ddr_pctl_regs->dfitphyupdtype0); + + /* cs0 and cs1 write odt enable */ + writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL), + &ddr_pctl_regs->dfiodtcfg); + /* odt write length */ + writel(ODT_LEN_BL8_W(7), &ddr_pctl_regs->dfiodtcfg1); + /* phyupd and ctrlupd disabled */ + writel(0, &ddr_pctl_regs->dfiupdcfg); +} + +static void pctl_cfg(u32 channel, + const struct rk3288_sdram_params *sdram_params) +{ + unsigned int burstlen; + struct rk3288_ddr_pctl_regs *ddr_pctl_regs = rk3288_ddr_pctl[channel]; + burstlen = (sdram_params->noc_timing >> 18) & 0x7; + copy_to_reg(&ddr_pctl_regs->togcnt1u, + &(sdram_params->pctl_timing.togcnt1u), + sizeof(sdram_params->pctl_timing)); + switch (sdram_params->dramtype) { + case LPDDR3: + writel(sdram_params->pctl_timing.tcl - 1, + &ddr_pctl_regs->dfitrddataen); + writel(sdram_params->pctl_timing.tcwl, + &ddr_pctl_regs->dfitphywrlat); + writel(LPDDR2_S4 | MDDR_LPDDR2_CLK_STOP_IDLE(0) | LPDDR2_EN + | BURSTLENGTH_CFG(burstlen) | TFAW_CFG(6) | PD_EXIT_FAST + | PD_TYPE(1) | PD_IDLE(0), &ddr_pctl_regs->mcfg); + writel(MSCH_MAINDDR3(channel, 0), &rk3288_grf->soc_con0); + + writel(PUBL_LPDDR3_EN(channel, 1) + | PCTL_BST_DISABLE(channel, 1) + | PCTL_LPDDR3_ODT_EN(channel, sdram_params->odt), + &rk3288_grf->soc_con2); + + break; + case DDR3: + if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) + writel(sdram_params->pctl_timing.tcl - 3, + &ddr_pctl_regs->dfitrddataen); + else + writel(sdram_params->pctl_timing.tcl - 2, + &ddr_pctl_regs->dfitrddataen); + writel(sdram_params->pctl_timing.tcwl - 1, + &ddr_pctl_regs->dfitphywrlat); + writel(MDDR_LPDDR2_CLK_STOP_IDLE(0) | DDR3_EN + | DDR2_DDR3_BL_8 | TFAW_CFG(6) | PD_EXIT_SLOW + | PD_TYPE(1) | PD_IDLE(0), &ddr_pctl_regs->mcfg); + writel(MSCH_MAINDDR3(channel, 1), &rk3288_grf->soc_con0); + + writel(PUBL_LPDDR3_EN(channel, 0) + | PCTL_BST_DISABLE(channel, 0) + | PCTL_LPDDR3_ODT_EN(channel, 0), + &rk3288_grf->soc_con2); + + break; + } + + setbits_le32(&ddr_pctl_regs->scfg, 1); +} + +static void phy_cfg(u32 channel, const struct rk3288_sdram_params *sdram_params) +{ + u32 i; + u32 dinit2 = div_round_up(sdram_params->ddr_freq/MHz * 200000, 1000); + struct rk3288_ddr_publ_regs *ddr_publ_regs = rk3288_ddr_publ[channel]; + struct rk3288_msch_regs *msch_regs = rk3288_msch[channel]; + + /* DDR PHY Timing */ + copy_to_reg(&ddr_publ_regs->dtpr[0], + &(sdram_params->phy_timing.dtpr0), + sizeof(sdram_params->phy_timing)); + writel(sdram_params->noc_timing, &msch_regs->ddrtiming); + writel(0x3f, &msch_regs->readlatency); + writel(sdram_params->noc_activate, &msch_regs->activate); + writel(BUSWRTORD(2) | BUSRDTOWR(2) | BUSRDTORD(1), + &msch_regs->devtodev); + writel(PRT_DLLLOCK(div_round_up(sdram_params->ddr_freq/MHz + * 5120, 1000)) + | PRT_DLLSRST(div_round_up(sdram_params->ddr_freq/MHz + * 50, 1000)) + | PRT_ITMSRST(8), &ddr_publ_regs->ptr[0]); + writel(PRT_DINIT0(div_round_up(sdram_params->ddr_freq/MHz + * 500000, 1000)) + | PRT_DINIT1(div_round_up(sdram_params->ddr_freq/MHz + * 400, 1000)), &ddr_publ_regs->ptr[1]); + writel(PRT_DINIT2(MIN(dinit2, 0x1ffff)) + | PRT_DINIT3(div_round_up(sdram_params->ddr_freq/MHz + * 1000, 1000)), &ddr_publ_regs->ptr[2]); + + switch (sdram_params->dramtype) { + case LPDDR3: + clrsetbits_le32(&ddr_publ_regs->pgcr, 0x1F, PGCR_DFTLMT(0) + | PGCR_DFTCMP(0) | PGCR_DQSCFG(1) | PGCR_ITMDMD(0)); + /* DDRMODE select LPDDR3 */ + clrsetbits_le32(&ddr_publ_regs->dcr, DDRMD_MSK, + DDRMD_CFG(DDRMD_LPDDR2_LPDDR3)); + clrsetbits_le32(&ddr_publ_regs->dxccr, DQSNRES_MSK | DQSRES_MSK, + DQSRES_CFG(4) | DQSNRES_CFG(0xc)); + i = TDQSCKMAX_VAL(readl(&ddr_publ_regs->dtpr[1])) + - TDQSCK_VAL(readl(&ddr_publ_regs->dtpr[1])); + clrsetbits_le32(&ddr_publ_regs->dsgcr, DQSGE_MSK | DQSGX_MSK, + DQSGE_CFG(i) | DQSGX_CFG(i)); + break; + case DDR3: + clrbits_le32(&ddr_publ_regs->pgcr, 0x1f); + clrsetbits_le32(&ddr_publ_regs->dcr, DDRMD_MSK, + DDRMD_CFG(DDRMD_DDR3)); + break; + } + if (sdram_params->odt) { + /*dynamic RTT enable */ + for (i = 0; i < 4; i++) + setbits_le32(&ddr_publ_regs->datx8[i].dxgcr, + DQSRTT | DQRTT); + } else { + /*dynamic RTT disable */ + for (i = 0; i < 4; i++) + clrbits_le32(&ddr_publ_regs->datx8[i].dxgcr, + DQSRTT | DQRTT); + + } +} + +static void phy_init(struct rk3288_ddr_publ_regs *ddr_publ_regs) +{ + setbits_le32(&ddr_publ_regs->pir, PIR_INIT | PIR_DLLSRST + | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR); + udelay(1); + while ((readl(&ddr_publ_regs->pgsr) & + (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) != + (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) + ; +} + +static void send_command(struct rk3288_ddr_pctl_regs *ddr_pctl_regs, u32 rank, + u32 cmd, u32 arg) +{ + writel((START_CMD | (rank << 20) | arg | cmd), &ddr_pctl_regs->mcmd); + udelay(1); + while (readl(&ddr_pctl_regs->mcmd) & START_CMD) + ; +} + +static void memory_init(struct rk3288_ddr_publ_regs *ddr_publ_regs, + u32 dramtype) +{ + setbits_le32(&ddr_publ_regs->pir, + (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP + | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC + | (dramtype == DDR3 ? PIR_DRAMRST : 0))); + udelay(1); + while ((readl(&ddr_publ_regs->pgsr) & (PGSR_IDONE | PGSR_DLDONE)) + != (PGSR_IDONE | PGSR_DLDONE)) + ; +} + +static void move_to_config_state(struct rk3288_ddr_publ_regs *ddr_publ_regs, + struct rk3288_ddr_pctl_regs *ddr_pctl_regs) +{ + unsigned int state; + + while (1) { + state = readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK; + + switch (state) { + case LOW_POWER: + writel(WAKEUP_STATE, &ddr_pctl_regs->sctl); + while ((readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK) + != ACCESS) + ; + /* wait DLL lock */ + while ((readl(&ddr_publ_regs->pgsr) & PGSR_DLDONE) + != PGSR_DLDONE) + ; + /* if at low power state,need wakeup first, + * and then enter the config + * so here no break. + */ + case ACCESS: + case INIT_MEM: + writel(CFG_STATE, &ddr_pctl_regs->sctl); + while ((readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK) + != CONFIG) + ; + break; + case CONFIG: + return; + default: + break; + } + } +} + +static void set_bandwidth_ratio(u32 channel, u32 n) +{ + struct rk3288_ddr_pctl_regs *ddr_pctl_regs = rk3288_ddr_pctl[channel]; + struct rk3288_ddr_publ_regs *ddr_publ_regs = rk3288_ddr_publ[channel]; + struct rk3288_msch_regs *msch_regs = rk3288_msch[channel]; + + if (n == 1) { + setbits_le32(&ddr_pctl_regs->ppcfg, 1); + writel(RK_SETBITS(1 << (8 + channel)), + &rk3288_grf->soc_con0); + setbits_le32(&msch_regs->ddrtiming, 1 << 31); + /* Data Byte disable*/ + clrbits_le32(&ddr_publ_regs->datx8[2].dxgcr, 1); + clrbits_le32(&ddr_publ_regs->datx8[3].dxgcr, 1); + /*disable DLL */ + setbits_le32(&ddr_publ_regs->datx8[2].dxdllcr, + DXDLLCR_DLLDIS); + setbits_le32(&ddr_publ_regs->datx8[3].dxdllcr, + DXDLLCR_DLLDIS); + } else { + clrbits_le32(&ddr_pctl_regs->ppcfg, 1); + writel(RK_CLRBITS(1 << (8 + channel)), + &rk3288_grf->soc_con0); + clrbits_le32(&msch_regs->ddrtiming, 1 << 31); + /* Data Byte enable*/ + setbits_le32(&ddr_publ_regs->datx8[2].dxgcr, 1); + setbits_le32(&ddr_publ_regs->datx8[3].dxgcr, 1); + + /*enable DLL */ + clrbits_le32(&ddr_publ_regs->datx8[2].dxdllcr, + DXDLLCR_DLLDIS); + clrbits_le32(&ddr_publ_regs->datx8[3].dxdllcr, + DXDLLCR_DLLDIS); + /* reset DLL */ + clrbits_le32(&ddr_publ_regs->datx8[2].dxdllcr, + DXDLLCR_DLLSRST); + clrbits_le32(&ddr_publ_regs->datx8[3].dxdllcr, + DXDLLCR_DLLSRST); + udelay(10); + setbits_le32(&ddr_publ_regs->datx8[2].dxdllcr, + DXDLLCR_DLLSRST); + setbits_le32(&ddr_publ_regs->datx8[3].dxdllcr, + DXDLLCR_DLLSRST); + } + setbits_le32(&ddr_pctl_regs->dfistcfg0, 1 << 2); + +} + +static int data_training(u32 channel, + const struct rk3288_sdram_params *sdram_params) +{ + unsigned int j; + int ret = 0; + u32 rank; + int i; + u32 step[2] = { PIR_QSTRN, PIR_RVTRN }; + struct rk3288_ddr_publ_regs *ddr_publ_regs = rk3288_ddr_publ[channel]; + struct rk3288_ddr_pctl_regs *ddr_pctl_regs = rk3288_ddr_pctl[channel]; + + /* disable auto refresh */ + writel(0, &ddr_pctl_regs->trefi); + + if (sdram_params->dramtype != LPDDR3) + setbits_le32(&ddr_publ_regs->pgcr, PGCR_DQSCFG(1)); + rank = sdram_params->ch[channel].rank | 1; + for (j = 0; j < ARRAY_SIZE(step); j++) { + /* + * trigger QSTRN and RVTRN + * clear DTDONE status + */ + setbits_le32(&ddr_publ_regs->pir, PIR_CLRSR); + + /* trigger DTT */ + setbits_le32(&ddr_publ_regs->pir, + PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP | + PIR_CLRSR); + udelay(1); + /* wait echo byte DTDONE */ + while ((readl(&ddr_publ_regs->datx8[0].dxgsr[0]) & rank) + != rank) + ; + while ((readl(&ddr_publ_regs->datx8[1].dxgsr[0]) & rank) + != rank) + ; + if (!(readl(&ddr_pctl_regs->ppcfg) & 1)) { + while ((readl(&ddr_publ_regs->datx8[2].dxgsr[0]) + & rank) != rank) + ; + while ((readl(&ddr_publ_regs->datx8[3].dxgsr[0]) + & rank) != rank) + ; + } + if (readl(&ddr_publ_regs->pgsr) & + (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) { + ret = -1; + break; + } + } + /* send some auto refresh to complement the lost while DTT */ + for (i = 0; i < (rank > 1 ? 8 : 4); i++) + send_command(ddr_pctl_regs, rank, REF_CMD, 0); + + if (sdram_params->dramtype != LPDDR3) + clrbits_le32(&ddr_publ_regs->pgcr, PGCR_DQSCFG(1)); + + /* resume auto refresh */ + writel(sdram_params->pctl_timing.trefi, &ddr_pctl_regs->trefi); + + return ret; +} + +static void move_to_access_state(u32 chnum) +{ + struct rk3288_ddr_publ_regs *ddr_publ_regs = rk3288_ddr_publ[chnum]; + struct rk3288_ddr_pctl_regs *ddr_pctl_regs = rk3288_ddr_pctl[chnum]; + + unsigned int state; + + while (1) { + state = readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK; + + switch (state) { + case LOW_POWER: + if (LP_TRIG_VAL(readl(&ddr_pctl_regs->stat)) == 1) + return; + + writel(WAKEUP_STATE, &ddr_pctl_regs->sctl); + while ((readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK) + != ACCESS) + ; + /* wait DLL lock */ + while ((readl(&ddr_publ_regs->pgsr) & PGSR_DLDONE) + != PGSR_DLDONE) + ; + break; + case INIT_MEM: + writel(CFG_STATE, &ddr_pctl_regs->sctl); + while ((readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK) + != CONFIG) + ; + case CONFIG: + writel(GO_STATE, &ddr_pctl_regs->sctl); + while ((readl(&ddr_pctl_regs->stat) & PCTL_STAT_MSK) + == CONFIG) + ; + break; + case ACCESS: + return; + default: + break; + } + } +} + +static void dram_cfg_rbc(u32 chnum, + const struct rk3288_sdram_params *sdram_params) +{ + struct rk3288_ddr_publ_regs *ddr_publ_regs = rk3288_ddr_publ[chnum]; + struct rk3288_msch_regs *msch_regs = rk3288_msch[chnum]; + + if (sdram_params->ch[chnum].bk == 3) + clrsetbits_le32(&ddr_publ_regs->dcr, PDQ_MSK, PDQ_CFG(1)); + else + clrbits_le32(&ddr_publ_regs->dcr, PDQ_MSK); + + writel(sdram_params->ddrconfig, &msch_regs->ddrconf); +} + +static void dram_all_config(const struct rk3288_sdram_params *sdram_params) +{ + u32 sys_reg = 0; + unsigned int channel; + + sys_reg |= SYS_REG_ENC_DDRTYPE(sdram_params->dramtype); + sys_reg |= SYS_REG_ENC_NUM_CH(sdram_params->num_channels); + for (channel = 0; channel < sdram_params->num_channels; channel++) { + const struct rk3288_sdram_channel *info = + &(sdram_params->ch[channel]); + sys_reg |= SYS_REG_ENC_ROW_3_4(info->row_3_4, channel); + sys_reg |= SYS_REG_ENC_CHINFO(channel); + sys_reg |= SYS_REG_ENC_RANK(info->rank, channel); + sys_reg |= SYS_REG_ENC_COL(info->col, channel); + sys_reg |= SYS_REG_ENC_BK(info->bk, channel); + sys_reg |= SYS_REG_ENC_CS0_ROW(info->cs0_row, channel); + sys_reg |= SYS_REG_ENC_CS1_ROW(info->cs1_row, channel); + sys_reg |= SYS_REG_ENC_BW(info->bw, channel); + sys_reg |= SYS_REG_ENC_DBW(info->dbw, channel); + + dram_cfg_rbc(channel, sdram_params); + } + writel(sys_reg, &rk3288_pmu->sys_reg[2]); + writel(RK_CLRSETBITS(0x1F, sdram_params->stride), + &rk3288_sgrf->soc_con2); +} + +void sdram_init(const struct rk3288_sdram_params *sdram_params) +{ + int channel; + int zqcr; + printk(BIOS_INFO, "Starting SDRAM initialization...\n"); + + if ((sdram_params->dramtype == DDR3 + && sdram_params->ddr_freq > 800*MHz) + || (sdram_params->dramtype == LPDDR3 + && sdram_params->ddr_freq > 533*MHz)) + die("SDRAM frequency is to high!"); + + rkclk_configure_ddr(sdram_params->ddr_freq); + + for (channel = 0; channel < 2; channel++) { + struct rk3288_ddr_pctl_regs *ddr_pctl_regs = + rk3288_ddr_pctl[channel]; + struct rk3288_ddr_publ_regs *ddr_publ_regs = + rk3288_ddr_publ[channel]; + + phy_pctrl_reset(ddr_publ_regs, channel); + phy_dll_bypass_set(ddr_publ_regs, sdram_params->ddr_freq); + + if (channel >= sdram_params->num_channels) + continue; + + dfi_cfg(ddr_pctl_regs, sdram_params->dramtype); + + pctl_cfg(channel, sdram_params); + + phy_cfg(channel, sdram_params); + + phy_init(ddr_publ_regs); + + writel(POWER_UP_START, &ddr_pctl_regs->powctl); + while (!(readl(&ddr_pctl_regs->powstat) & POWER_UP_DONE)) + ; + + memory_init(ddr_publ_regs, sdram_params->dramtype); + move_to_config_state(ddr_publ_regs, ddr_pctl_regs); + + if (sdram_params->dramtype == LPDDR3) { + send_command(ddr_pctl_regs, 3, DESELECT_CMD, 0); + udelay(1); + send_command(ddr_pctl_regs, 3, PREA_CMD, 0); + udelay(1); + send_command(ddr_pctl_regs, 3, MRS_CMD, LPDDR2_MA(63) | + LPDDR2_OP(0xFC)); + udelay(1); + send_command(ddr_pctl_regs, 3, MRS_CMD, LPDDR2_MA(1) | + LPDDR2_OP(sdram_params->phy_timing.mr[1])); + udelay(1); + send_command(ddr_pctl_regs, 3, MRS_CMD, LPDDR2_MA(2) | + LPDDR2_OP(sdram_params->phy_timing.mr[2])); + udelay(1); + send_command(ddr_pctl_regs, 3, MRS_CMD, LPDDR2_MA(3) | + LPDDR2_OP(sdram_params->phy_timing.mr[3])); + udelay(1); + } + + set_bandwidth_ratio(channel, sdram_params->ch[channel].bw); + /* + * set cs + * CS0, n=1 + * CS1, n=2 + * CS0 & CS1, n = 3 + */ + clrsetbits_le32(&ddr_publ_regs->pgcr, 0xF << 18, + (sdram_params->ch[channel].rank | 1) << 18); + /* DS=40ohm,ODT=155ohm */ + zqcr = ZDEN(1) | PU_ONDIE(0x2) | PD_ONDIE(0x2) + | PU_OUTPUT(0x19) | PD_OUTPUT(0x19); + writel(zqcr, &ddr_publ_regs->zq1cr[0]); + writel(zqcr, &ddr_publ_regs->zq0cr[0]); + + if (sdram_params->dramtype == LPDDR3) { + /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */ + udelay(10); + send_command(ddr_pctl_regs, + (sdram_params->ch[channel].rank | 1), + MRS_CMD, LPDDR2_MA(11) | (sdram_params->odt ? + LPDDR2_OP(0x3) : LPDDR2_OP(0x0))); + if (channel == 0) { + writel(0, &ddr_pctl_regs->mrrcfg0); + send_command(ddr_pctl_regs, 1, MRR_CMD, + LPDDR2_MA(0x8)); + /* S8 */ + if ((readl(&ddr_pctl_regs->mrrstat0) & 0x3) + != 3) + die("SDRAM initialization failed!"); + } + } + + if (-1 == data_training(channel, sdram_params)) { + if (sdram_params->dramtype == LPDDR3) { + rkclk_ddr_phy_ctl_reset(channel, 1); + udelay(10); + rkclk_ddr_phy_ctl_reset(channel, 0); + udelay(10); + } + die("SDRAM initialization failed!"); + } + + if (sdram_params->dramtype == LPDDR3) { + u32 i; + writel(0, &ddr_pctl_regs->mrrcfg0); + for (i = 0; i < 17; i++) + send_command(ddr_pctl_regs, 1, MRR_CMD, + LPDDR2_MA(i)); + } + move_to_access_state(channel); + } + dram_all_config(sdram_params); + printk(BIOS_INFO, "Finish SDRAM initialization...\n"); +} + +size_t sdram_size_mb(void) +{ + u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4; + size_t chipsize_mb = 0; + static size_t size_mb = 0; + u32 ch; + + if (!size_mb) { + + u32 sys_reg = readl(&rk3288_pmu->sys_reg[2]); + u32 ch_num = SYS_REG_DEC_NUM_CH(sys_reg); + + for (ch = 0; ch < ch_num; ch++) { + rank = SYS_REG_DEC_RANK(sys_reg, ch); + col = SYS_REG_DEC_COL(sys_reg, ch); + bk = SYS_REG_DEC_BK(sys_reg, ch); + cs0_row = SYS_REG_DEC_CS0_ROW(sys_reg, ch); + cs1_row = SYS_REG_DEC_CS1_ROW(sys_reg, ch); + bw = SYS_REG_DEC_BW(sys_reg, ch); + row_3_4 = SYS_REG_DEC_ROW_3_4(sys_reg, ch); + + chipsize_mb = (1 << (cs0_row + col + bk + bw - 20)); + + if (rank > 1) + chipsize_mb += chipsize_mb >> + (cs0_row - cs1_row); + if (row_3_4) + chipsize_mb = chipsize_mb * 3 / 4; + size_mb += chipsize_mb; + } + + /* + * we use the 0x00000000~0xfeffffff space + * since 0xff000000~0xffffffff is soc register space + * so we reserve it + */ + size_mb = MIN(size_mb, 0xff000000/MiB); + } + + return size_mb; +} diff --git a/src/soc/rockchip/rk3288/soc.c b/src/soc/rockchip/rk3288/soc.c new file mode 100644 index 0000000000..aec7406004 --- /dev/null +++ b/src/soc/rockchip/rk3288/soc.c @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static void soc_init(device_t dev) +{ + ram_resource(dev, 0, (uintptr_t)_dram/KiB, sdram_size_mb()*(MiB/KiB)); + if (vboot_skip_display_init()) + printk(BIOS_INFO, "Skipping display init.\n"); + else + rk_display_init(dev, (uintptr_t)_framebuffer, + _framebuffer_size); +} + +static void soc_noop(device_t dev) +{ + +} + +static struct device_operations soc_ops = { + .read_resources = soc_noop, + .set_resources = soc_noop, + .init = soc_init, + .scan_bus = 0, +}; + +static void enable_rk3288_dev(device_t dev) +{ + dev->ops = &soc_ops; +} + +struct chip_operations soc_rockchip_rk3288_ops = { + CHIP_NAME("SOC Rockchip 3288") + .enable_dev = enable_rk3288_dev, +}; diff --git a/src/soc/rockchip/rk3288/spi.c b/src/soc/rockchip/rk3288/spi.c new file mode 100644 index 0000000000..91b17cc1f8 --- /dev/null +++ b/src/soc/rockchip/rk3288/spi.c @@ -0,0 +1,290 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rockchip_spi_slave { + struct spi_slave slave; + struct rockchip_spi *regs; +}; + +#define SPI_TIMEOUT_US 1000 +#define SPI_SRCCLK_HZ (99*MHz) +#define SPI_FIFO_DEPTH 32 + +static struct rockchip_spi_slave rockchip_spi_slaves[3] = { + { + .slave = { + .bus = 0, + .rw = SPI_READ_FLAG | SPI_WRITE_FLAG, + }, + .regs = (void *)SPI0_BASE, + }, + { + .slave = {.bus = 1, .rw = SPI_READ_FLAG,}, + .regs = (void *)SPI1_BASE, + }, + { + .slave = { + .bus = 2, + .rw = SPI_READ_FLAG | SPI_WRITE_FLAG, + }, + .regs = (void *)SPI2_BASE, + }, + +}; + +static struct rockchip_spi_slave *to_rockchip_spi(struct spi_slave *slave) +{ + return container_of(slave, struct rockchip_spi_slave, slave); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + assert(bus >= 0 && bus < 3); + return &(rockchip_spi_slaves[bus].slave); +} + +static void spi_cs_activate(struct spi_slave *slave) +{ + struct rockchip_spi *regs = to_rockchip_spi(slave)->regs; + setbits_le32(®s->ser, 1); +} + +static void spi_cs_deactivate(struct spi_slave *slave) +{ + struct rockchip_spi *regs = to_rockchip_spi(slave)->regs; + clrbits_le32(®s->ser, 1); +} + +static void rockchip_spi_enable_chip(struct rockchip_spi *regs, int enable) +{ + if (enable == 1) + writel(1, ®s->spienr); + else + writel(0, ®s->spienr); +} + +static void rockchip_spi_set_clk(struct rockchip_spi *regs, unsigned int hz) +{ + unsigned short clk_div = SPI_SRCCLK_HZ / hz; + assert(clk_div * hz == SPI_SRCCLK_HZ && !(clk_div & 1)); + writel(clk_div, ®s->baudr); +} + +void rockchip_spi_init(unsigned int bus, unsigned int speed_hz) +{ + struct rockchip_spi *regs = rockchip_spi_slaves[bus].regs; + unsigned int ctrlr0 = 0; + + rkclk_configure_spi(bus, SPI_SRCCLK_HZ); + rockchip_spi_enable_chip(regs, 0); + rockchip_spi_set_clk(regs, speed_hz); + + /* Operation Mode */ + ctrlr0 = (SPI_OMOD_MASTER << SPI_OMOD_OFFSET); + + /* Data Frame Size */ + ctrlr0 |= SPI_DFS_8BIT << SPI_DFS_OFFSET; + + /* Chip Select Mode */ + ctrlr0 |= (SPI_CSM_KEEP << SPI_CSM_OFFSET); + + /* SSN to Sclk_out delay */ + ctrlr0 |= (SPI_SSN_DELAY_ONE << SPI_SSN_DELAY_OFFSET); + + /* Serial Endian Mode */ + ctrlr0 |= (SPI_SEM_LITTLE << SPI_SEM_OFFSET); + + /* First Bit Mode */ + ctrlr0 |= (SPI_FBM_MSB << SPI_FBM_OFFSET); + + /* Byte and Halfword Transform */ + ctrlr0 |= (SPI_APB_8BIT << SPI_HALF_WORLD_TX_OFFSET); + + /* Rxd Sample Delay */ + ctrlr0 |= (0 << SPI_RXDSD_OFFSET); + + /* Frame Format */ + ctrlr0 |= (SPI_FRF_SPI << SPI_FRF_OFFSET); + + writel(ctrlr0, ®s->ctrlr0); + + /* fifo depth */ + writel(SPI_FIFO_DEPTH / 2 - 1, ®s->txftlr); + writel(SPI_FIFO_DEPTH / 2 - 1, ®s->rxftlr); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + spi_cs_activate(slave); + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + spi_cs_deactivate(slave); +} + +static int rockchip_spi_wait_till_not_busy(struct rockchip_spi *regs) +{ + struct stopwatch sw; + + stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_US); + do { + if (!(readl(®s->sr) & SR_BUSY)) + return 0; + } while (!stopwatch_expired(&sw)); + printk(BIOS_DEBUG, + "RK SPI: Status keeps busy for 1000us after a read/write!\n"); + return -1; +} + +static void set_tmod(struct rockchip_spi *regs, unsigned int tmod) +{ + clrsetbits_le32(®s->ctrlr0, SPI_TMOD_MASK << SPI_TMOD_OFFSET, + tmod << SPI_TMOD_OFFSET); +} + +static void set_transfer_mode(struct rockchip_spi *regs, + unsigned int sout, unsigned int sin) +{ + if (!sin && !sout) + return; + else if (sin && sout) + set_tmod(regs, SPI_TMOD_TR); /* tx and rx */ + else if (!sin) + set_tmod(regs, SPI_TMOD_TO); /* tx only */ + else if (!sout) + set_tmod(regs, SPI_TMOD_RO); /* rx only */ +} + +/* returns 0 to indicate success, <0 otherwise */ +static int do_xfer(struct spi_slave *slave, const void *dout, + unsigned int *bytes_out, void *din, unsigned int *bytes_in) +{ + struct rockchip_spi *regs = to_rockchip_spi(slave)->regs; + uint8_t *in_buf = din; + uint8_t *out_buf = (uint8_t *)dout; + unsigned int min_xfer; + + if (*bytes_out == 0) + min_xfer = *bytes_in; + else if (*bytes_in == 0) + min_xfer = *bytes_out; + else + min_xfer = MIN(*bytes_in, *bytes_out); + + while (min_xfer) { + uint32_t sr = readl(®s->sr); + int xferred = 0; /* in either (or both) directions */ + + if (*bytes_out && !(sr & SR_TF_FULL)) { + writel(*out_buf, ®s->txdr); + out_buf++; + *bytes_out -= 1; + xferred = 1; + } + + if (*bytes_in && !(sr & SR_RF_EMPT)) { + *in_buf = readl(®s->rxdr) & 0xff; + in_buf++; + *bytes_in -= 1; + xferred = 1; + } + + min_xfer -= xferred; + } + + if (rockchip_spi_wait_till_not_busy(regs)) { + printk(BIOS_ERR, "Timed out waiting on SPI transfer\n"); + return -1; + } + + return 0; +} + +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int bytes_out, void *din, unsigned int bytes_in) +{ + struct rockchip_spi *regs = to_rockchip_spi(slave)->regs; + int ret = 0; + + /* + * RK3288 SPI controller can transfer up to 65536 data frames (bytes + * in our case) continuously. Break apart large requests as necessary. + * + * FIXME: And by 65536, we really mean 65535. If 0xffff is written to + * ctrlr1, all bytes that we see in rxdr end up being 0x00. 0xffff - 1 + * seems to work fine. + */ + while (bytes_out || bytes_in) { + unsigned int in_now = MIN(bytes_in, 0xffff); + unsigned int out_now = MIN(bytes_out, 0xffff); + unsigned int in_rem, out_rem; + + rockchip_spi_enable_chip(regs, 0); + + /* Enable/disable transmitter and receiver as needed to + * avoid sending or reading spurious bits. */ + set_transfer_mode(regs, bytes_out, bytes_in); + + /* MAX() in case either counter is 0 */ + writel(MAX(in_now, out_now) - 1, ®s->ctrlr1); + + rockchip_spi_enable_chip(regs, 1); + + in_rem = in_now; + out_rem = out_now; + ret = do_xfer(slave, dout, &out_rem, din, &in_rem); + if (ret < 0) + break; + + if (bytes_out) { + unsigned int sent = out_now - out_rem; + bytes_out -= sent; + dout += sent; + } + + if (bytes_in) { + unsigned int received = in_now - in_rem; + bytes_in -= received; + din += received; + } + } + + rockchip_spi_enable_chip(regs, 0); + return ret < 0 ? ret : 0; +} + +struct rockchip_spi_media { + struct spi_slave *slave; + struct cbfs_simple_buffer buffer; +}; diff --git a/src/soc/rockchip/rk3288/timer.c b/src/soc/rockchip/rk3288/timer.c new file mode 100644 index 0000000000..253d145b44 --- /dev/null +++ b/src/soc/rockchip/rk3288/timer.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static uint64_t timer_raw_value(void) +{ + uint64_t value0; + uint64_t value1; + + value0 = (uint64_t)read32(&timer7_ptr->timer_curr_value0); + value1 = (uint64_t)read32(&timer7_ptr->timer_curr_value1); + value0 = value0 | value1<<32; + return value0; +} + +void timer_monotonic_get(struct mono_time *mt) +{ + mono_time_set_usecs(mt, timer_raw_value() / clocks_per_usec); +} + +void init_timer(void) +{ + write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count0); + write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count1); + write32(1, &timer7_ptr->timer_ctrl_reg); +} diff --git a/src/soc/rockchip/rk3288/tsadc.c b/src/soc/rockchip/rk3288/tsadc.c new file mode 100644 index 0000000000..a2d6ec499a --- /dev/null +++ b/src/soc/rockchip/rk3288/tsadc.c @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rk3288_tsadc_regs { + u32 user_con; + u32 auto_con; + u32 int_en; + u32 int_pd; + u32 reserved0[(0x20 - 0x10) / 4]; + u32 data0; + u32 data1; + u32 data2; + u32 data3; + u32 comp0_int; + u32 comp1_int; + u32 comp2_int; + u32 comp3_int; + u32 comp0_shut; + u32 comp1_shut; + u32 comp2_shut; + u32 comp3_shut; + u32 reserved1[(0x60 - 0x50) / 4]; + u32 hight_int_debounce; + u32 hight_tshut_debounce; + u32 auto_period; + u32 auto_period_ht; +}; +check_member(rk3288_tsadc_regs, auto_period_ht, 0x6c); + +/* auto_con */ +#define LAST_TSHUT (1 << 24) +#define TSHUT_POL_HIGH (1 << 8) +#define SRC3_EN (1 << 7) +#define SRC2_EN (1 << 6) +#define SRC1_EN (1 << 5) +#define SRC0_EN (1 << 4) +#define AUTO_EN (1 << 0) + +/* int_en */ +#define TSHUT_CRU_EN_SRC3 (1 << 11) +#define TSHUT_CRU_EN_SRC2 (1 << 10) +#define TSHUT_CRU_EN_SRC1 (1 << 9) +#define TSHUT_CRU_EN_SRC0 (1 << 8) +#define TSHUT_GPIO_EN_SRC3 (1 << 7) +#define TSHUT_GPIO_EN_SRC2 (1 << 6) +#define TSHUT_GPIO_EN_SRC1 (1 << 5) +#define TSHUT_GPIO_EN_SRC0 (1 << 4) + +#define AUTO_PERIOD 10 +#define AUTO_DEBOUNCE 4 +#define AUTO_PERIOD_HT 10 +#define AUTO_DEBOUNCE_HT 4 +#define TSADC_CLOCK_HZ (8 * KHz) + +/* AD value, correspond to 120 degrees Celsius */ +#define TSADC_SHUT_VALUE 3437 + +struct rk3288_tsadc_regs *rk3288_tsadc = (void *)TSADC_BASE; + +void tsadc_init(void) +{ + rkclk_configure_tsadc(TSADC_CLOCK_HZ); + + setbits_le32(&rk3288_tsadc->auto_con, LAST_TSHUT); + + setbits_le32(&rk3288_tsadc->int_en, + TSHUT_CRU_EN_SRC2 | TSHUT_CRU_EN_SRC1 | + TSHUT_GPIO_EN_SRC2 | TSHUT_GPIO_EN_SRC1); + + writel(AUTO_PERIOD, &rk3288_tsadc->auto_period); + writel(AUTO_DEBOUNCE, &rk3288_tsadc->hight_int_debounce); + writel(AUTO_PERIOD_HT, &rk3288_tsadc->auto_period_ht); + writel(AUTO_DEBOUNCE_HT, &rk3288_tsadc->hight_tshut_debounce); + + writel(TSADC_SHUT_VALUE, &rk3288_tsadc->comp1_shut); + writel(TSADC_SHUT_VALUE, &rk3288_tsadc->comp2_shut); + + /* polarity set to high,channel1 for cpu,channel2 for gpu */ + setbits_le32(&rk3288_tsadc->auto_con, TSHUT_POL_HIGH | SRC2_EN | + SRC1_EN | AUTO_EN); + + /* + tsadc iomux must be set after the tshut polarity setting, + since the tshut polarity defalut low active, + so if you enable tsadc iomux,it will output high + */ + setbits_le32(&rk3288_pmu->iomux_tsadc_int, IOMUX_TSADC_INT); +} diff --git a/src/soc/rockchip/rk3288/uart.c b/src/soc/rockchip/rk3288/uart.c new file mode 100644 index 0000000000..778104a5dd --- /dev/null +++ b/src/soc/rockchip/rk3288/uart.c @@ -0,0 +1,159 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include /* for __console definition */ +#include +#include +#include + +struct rk3288_uart { + union { + uint32_t thr; /* Transmit holding register. */ + uint32_t rbr; /* Receive buffer register. */ + uint32_t dll; /* Divisor latch lsb. */ + }; + union { + uint32_t ier; /* Interrupt enable register. */ + uint32_t dlm; /* Divisor latch msb. */ + }; + union { + uint32_t iir; /* Interrupt identification register. */ + uint32_t fcr; /* FIFO control register. */ + }; + uint32_t lcr; /* Line control register. */ + uint32_t mcr; /* Modem control register. */ + uint32_t lsr; /* Line status register. */ + uint32_t msr; /* Modem status register. */ + uint32_t scr; + uint32_t reserved1[(0x30 - 0x20) / 4]; + uint32_t srbr[(0x70 - 0x30) / 4]; + uint32_t far; + uint32_t tfr; + uint32_t rfw; + uint32_t usr; + uint32_t tfl; + uint32_t rfl; + uint32_t srr; + uint32_t srts; + uint32_t sbcr; + uint32_t sdmam; + uint32_t sfe; + uint32_t srt; + uint32_t stet; + uint32_t htx; + uint32_t dmasa; + uint32_t reserver2[(0xf4 - 0xac) / 4]; + uint32_t cpr; + uint32_t ucv; + uint32_t ctr; +} __attribute__ ((packed)); + +static struct rk3288_uart * const uart_ptr = + (void *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + +static void rk3288_uart_tx_flush(void); +static int rk3288_uart_tst_byte(void); + +static void rk3288_uart_init(void) +{ + // Use a hardcoded divisor for now. + const unsigned divisor = 13; + const uint8_t line_config = UART8250_LCR_WLS_8; // 8n1 + + rk3288_uart_tx_flush(); + + // Disable interrupts. + writel(0, &uart_ptr->ier); + // Force DTR and RTS to high. + writel(UART8250_MCR_DTR | UART8250_MCR_RTS, &uart_ptr->mcr); + // Set line configuration, access divisor latches. + writel(UART8250_LCR_DLAB | line_config, &uart_ptr->lcr); + // Set the divisor. + writel(divisor & 0xff, &uart_ptr->dll); + writel((divisor >> 8) & 0xff, &uart_ptr->dlm); + // Hide the divisor latches. + writel(line_config, &uart_ptr->lcr); + // Enable FIFOs, and clear receive and transmit. + writel(UART8250_FCR_FIFO_EN | + UART8250_FCR_CLEAR_RCVR | + UART8250_FCR_CLEAR_XMIT, &uart_ptr->fcr); +} + +static void rk3288_uart_tx_byte(unsigned char data) +{ + while (!(readl(&uart_ptr->lsr) & UART8250_LSR_THRE)); + writel(data, &uart_ptr->thr); +} + +static void rk3288_uart_tx_flush(void) +{ + while (!(readl(&uart_ptr->lsr) & UART8250_LSR_TEMT)); +} + +static unsigned char rk3288_uart_rx_byte(void) +{ + if (!rk3288_uart_tst_byte()) + return 0; + return readl(&uart_ptr->rbr); +} + +static int rk3288_uart_tst_byte(void) +{ + return (readl(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR; +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver rk3288_uart_console __console = { + .init = rk3288_uart_init, + .tx_byte = rk3288_uart_tx_byte, + .tx_flush = rk3288_uart_tx_flush, + .rx_byte = rk3288_uart_rx_byte, + .tst_byte = rk3288_uart_tst_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return (uintptr_t)uart_ptr; +} + +#else + +void uart_init(void) +{ + rk3288_uart_init(); +} + +void uart_tx_byte(unsigned char data) +{ + rk3288_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ + rk3288_uart_tx_flush(); +} + +unsigned char uart_rx_byte(void) +{ + return rk3288_uart_rx_byte(); +} + +#endif diff --git a/src/soc/rockchip/rk3288/vop.c b/src/soc/rockchip/rk3288/vop.c new file mode 100644 index 0000000000..a04f4454ff --- /dev/null +++ b/src/soc/rockchip/rk3288/vop.c @@ -0,0 +1,161 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static struct rk3288_vop_regs * const vop_regs[] = { + (struct rk3288_vop_regs *)VOP_BIG_BASE, + (struct rk3288_vop_regs *)VOP_LIT_BASE +}; + +void rkvop_enable(u32 vop_id, u32 fbbase, const struct edid *edid) +{ + u32 lb_mode; + u32 rgb_mode; + u32 hactive = edid->mode.ha; + u32 vactive = edid->mode.va; + u32 hsync_len = edid->mode.hspw; + u32 hback_porch = edid->mode.hbl - edid->mode.hso - edid->mode.hspw; + u32 vsync_len = edid->mode.vspw; + u32 vback_porch = edid->mode.vbl - edid->mode.vso - edid->mode.vspw; + u32 xpos = 0, ypos = 0; + struct rk3288_vop_regs *preg = vop_regs[vop_id]; + + writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1), + &preg->win0_act_info); + + writel(V_DSP_XST(xpos + hsync_len + hback_porch) | + V_DSP_YST(ypos + vsync_len + vback_porch), + &preg->win0_dsp_st); + + writel(V_DSP_WIDTH(hactive - 1) | + V_DSP_HEIGHT(vactive - 1), + &preg->win0_dsp_info); + + clrsetbits_le32(&preg->win0_color_key, M_WIN0_KEY_EN | M_WIN0_KEY_COLOR, + V_WIN0_KEY_EN(0) | + V_WIN0_KEY_COLOR(0)); + + switch (edid->framebuffer_bits_per_pixel) { + case 16: + rgb_mode = RGB565; + writel(V_RGB565_VIRWIDTH(hactive), + &preg->win0_vir); + break; + case 24: + rgb_mode = RGB888; + writel(V_RGB888_VIRWIDTH(hactive), + &preg->win0_vir); + break; + case 32: + default: + rgb_mode = ARGB8888; + writel(V_ARGB888_VIRWIDTH(hactive), + &preg->win0_vir); + break; + } + + if (hactive > 2560) + lb_mode = LB_RGB_3840X2; + else if (hactive > 1920) + lb_mode = LB_RGB_2560X4; + else if (hactive > 1280) + lb_mode = LB_RGB_1920X5; + else + lb_mode = LB_RGB_1280X8; + + clrsetbits_le32(&preg->win0_ctrl0, + M_WIN0_LB_MODE | M_WIN0_DATA_FMT | M_WIN0_EN, + V_WIN0_LB_MODE(lb_mode) | + V_WIN0_DATA_FMT(rgb_mode) | V_WIN0_EN(1)); + + writel(fbbase, &preg->win0_yrgb_mst); + + writel(0x01, &preg->reg_cfg_done); /* enable reg config */ +} + +void rkvop_mode_set(u32 vop_id, const struct edid *edid, u32 mode) +{ + u32 hactive = edid->mode.ha; + u32 vactive = edid->mode.va; + u32 hfront_porch = edid->mode.hso; + u32 hsync_len = edid->mode.hspw; + u32 hback_porch = edid->mode.hbl - edid->mode.hso - edid->mode.hspw; + u32 vfront_porch = edid->mode.vso; + u32 vsync_len = edid->mode.vspw; + u32 vback_porch = edid->mode.vbl - edid->mode.vso - edid->mode.vspw; + struct rk3288_vop_regs *preg = vop_regs[vop_id]; + + switch (mode) { + + case VOP_MODE_HDMI: + clrsetbits_le32(&preg->sys_ctrl, + M_ALL_OUT_EN, V_HDMI_OUT_EN(1)); + break; + + case VOP_MODE_EDP: + default: + clrsetbits_le32(&preg->sys_ctrl, + M_ALL_OUT_EN, V_EDP_OUT_EN(1)); + break; + } + + clrsetbits_le32(&preg->dsp_ctrl0, + M_DSP_OUT_MODE | M_DSP_VSYNC_POL | M_DSP_HSYNC_POL, + V_DSP_OUT_MODE(15) | + V_DSP_HSYNC_POL(edid->mode.phsync == '+') | + V_DSP_VSYNC_POL(edid->mode.pvsync == '+')); + + writel(V_HSYNC(hsync_len) | + V_HORPRD(hsync_len + hback_porch + hactive + hfront_porch), + &preg->dsp_htotal_hs_end); + + writel(V_HEAP(hsync_len + hback_porch + hactive) | + V_HASP(hsync_len + hback_porch), + &preg->dsp_hact_st_end); + + writel(V_VSYNC(vsync_len) | + V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch), + &preg->dsp_vtotal_vs_end); + + writel(V_VAEP(vsync_len + vback_porch + vactive)| + V_VASP(vsync_len + vback_porch), + &preg->dsp_vact_st_end); + + writel(V_HEAP(hsync_len + hback_porch + hactive) | + V_HASP(hsync_len + hback_porch), + &preg->post_dsp_hact_info); + + writel(V_VAEP(vsync_len + vback_porch + vactive)| + V_VASP(vsync_len + vback_porch), + &preg->post_dsp_vact_info); + + writel(0x01, &preg->reg_cfg_done); /* enable reg config */ +} diff --git a/src/soc/samsung/Kconfig b/src/soc/samsung/Kconfig new file mode 100644 index 0000000000..9241d27bbf --- /dev/null +++ b/src/soc/samsung/Kconfig @@ -0,0 +1,2 @@ +source src/soc/samsung/exynos5250/Kconfig +source src/soc/samsung/exynos5420/Kconfig diff --git a/src/soc/samsung/Makefile.inc b/src/soc/samsung/Makefile.inc new file mode 100644 index 0000000000..496b5f7be3 --- /dev/null +++ b/src/soc/samsung/Makefile.inc @@ -0,0 +1,2 @@ +subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5250) += exynos5250 +subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5420) += exynos5420 diff --git a/src/soc/samsung/exynos5250/Kconfig b/src/soc/samsung/exynos5250/Kconfig new file mode 100644 index 0000000000..11a451ac2f --- /dev/null +++ b/src/soc/samsung/exynos5250/Kconfig @@ -0,0 +1,53 @@ +config CPU_SAMSUNG_EXYNOS5250 + select CPU_HAS_BOOTBLOCK_INIT + select HAVE_MONOTONIC_TIMER + select GENERIC_UDELAY + select HAVE_UART_SPECIAL + select EARLY_CONSOLE + select DYNAMIC_CBMEM + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + bool + default n + +if CPU_SAMSUNG_EXYNOS5250 + +choice CONSOLE_SERIAL_UART_CHOICES + prompt "Serial Console UART" + default CONSOLE_SERIAL_UART3 + depends on CONSOLE_SERIAL_UART + +config CONSOLE_SERIAL_UART0 + bool "UART0" + help + Serial console on UART0 + +config CONSOLE_SERIAL_UART1 + bool "UART1" + help + Serial console on UART1 + +config CONSOLE_SERIAL_UART2 + bool "UART2" + help + Serial console on UART2 + +config CONSOLE_SERIAL_UART3 + bool "UART3" + help + Serial console on UART3 + +endchoice + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0x12c00000 if CONSOLE_SERIAL_UART0 + default 0x12c10000 if CONSOLE_SERIAL_UART1 + default 0x12c20000 if CONSOLE_SERIAL_UART2 + default 0x12c30000 if CONSOLE_SERIAL_UART3 + help + Map the UART names to the respective MMIO address. + +endif diff --git a/src/soc/samsung/exynos5250/Makefile.inc b/src/soc/samsung/exynos5250/Makefile.inc new file mode 100644 index 0000000000..42618f3f74 --- /dev/null +++ b/src/soc/samsung/exynos5250/Makefile.inc @@ -0,0 +1,55 @@ +bootblock-y += spi.c alternate_cbfs.c +bootblock-y += bootblock.c +bootblock-y += pinmux.c timer.c power.c +# Clock is required for UART +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += clock_init.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += clock.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c +endif +bootblock-y += wakeup.c +bootblock-y += gpio.c + +romstage-y += spi.c alternate_cbfs.c +romstage-y += clock.c +romstage-y += clock_init.c +romstage-y += pinmux.c # required by s3c24x0_i2c and uart. +romstage-y += dmc_common.c +romstage-y += dmc_init_ddr3.c +romstage-y += power.c +romstage-y += timer.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +romstage-$(CONFIG_EARLY_CONSOLE) += uart.c +endif +romstage-y += wakeup.c +romstage-y += gpio.c +romstage-y += trustzone.c +romstage-y += i2c.c +#romstage-y += wdt.c +romstage-y += cbmem.c + +ramstage-y += spi.c alternate_cbfs.c +ramstage-y += clock.c +ramstage-y += clock_init.c +ramstage-y += pinmux.c +ramstage-y += power.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +ramstage-y += cpu.c +ramstage-y += tmu.c +ramstage-y += timer.c +ramstage-y += gpio.c +ramstage-y += i2c.c +ramstage-y += dp-reg.c +ramstage-y += fb.c +ramstage-y += usb.c +ramstage-y += cbmem.c + +INCLUDES += -Isrc/soc/samsung/exynos5250/include/ + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin + @printf " BL1, CKSUM $(subst $(obj)/,,$(@))\n" + util/exynos/fixed_cksum.py $< $<.cksum 32768 + cat 3rdparty/cpu/samsung/exynos5250/bl1.bin $<.cksum > $@ diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.c b/src/soc/samsung/exynos5250/alternate_cbfs.c new file mode 100644 index 0000000000..9f873bff9f --- /dev/null +++ b/src/soc/samsung/exynos5250/alternate_cbfs.c @@ -0,0 +1,176 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include /* This driver serves as a CBFS media source. */ +#include +#include +#include +#include +#include +#include +#include + +/* This allows USB A-A firmware upload from a compatible host in four parts: + * The first two are the bare BL1 and the Coreboot boot block, which are just + * written to their respective loading addresses. These transfers are initiated + * by the IROM / BL1, so this code has nothing to do with them. + * + * The third transfer is a valid CBFS image that contains only the romstage, + * and must be small enough to fit into the PRE_RAM CBFS cache in + * IRAM. It is loaded when this function gets called in the boot block, and + * the normal CBFS code extracts the romstage from it. + * + * The fourth transfer is also a CBFS image, but can be of arbitrary size and + * should contain all available stages/payloads/etc. It is loaded when this + * function is called a second time at the end of the romstage, and copied to + * the romstage/ramstage CBFS cache in DRAM. It will reside there for the + * rest of the firmware's lifetime and all subsequent stages (which will not + * have __PRE_RAM__ defined) can just directly reference it there. + */ +static int usb_cbfs_open(struct cbfs_media *media) +{ +#ifdef __PRE_RAM__ + static int first_run = 1; + int (*irom_load_usb)(void) = *irom_load_image_from_usb_ptr; + + if (!first_run) + return 0; + + if (!irom_load_usb()) { + printk(BIOS_EMERG, "Unable to load CBFS image via USB!\n"); + return -1; + } + + /* + * We need to trust the host/irom to copy the image to our + * _cbfs_cache address... there is no way to control or even + * check the transfer size or target address from our side. + */ + + printk(BIOS_DEBUG, "USB A-A transfer successful, CBFS image should now" + " be at %p\n", _cbfs_cache); + first_run = 0; +#endif + return 0; +} + +/* + * SDMMC works very similar to USB A-A: we copy the CBFS image into memory + * and read it from there. While SDMMC would also allow direct block by block + * on-demand reading, we might run into problems if we call back into the IROM + * in very late boot stages (e.g. after initializing/changing MMC clocks)... so + * this seems like a safer approach. It also makes it easy to pass our image + * down to payloads. + */ +static int sdmmc_cbfs_open(struct cbfs_media *media) +{ +#ifdef __PRE_RAM__ + /* + * In the bootblock, we just copy the small part that fits in the buffer + * and hope that it's enough (since the romstage is currently always the + * first component in the image, this should work out). In the romstage, + * we copy until our cache is full (currently 12M) to avoid the pain of + * figuring out the true image size from in here. Since this is mainly a + * developer/debug boot mode, those shortcomings should be bearable. + */ + const u32 count = _cbfs_cache_size / 512; + static int first_run = 1; + int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) = + *irom_sdmmc_read_blocks_ptr; + + if (!first_run) + return 0; + + if (!irom_load_sdmmc(1, count, _cbfs_cache)) { + printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n"); + return -1; + } + + printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be" + " at %p\n", _cbfs_cache); + first_run = 0; +#endif + return 0; +} + +static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } + +static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + ASSERT(offset + count < _cbfs_cache_size); + memcpy(dest, _cbfs_cache + offset, count); + return count; +} + +static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + ASSERT(offset + count < _cbfs_cache_size); + return _cbfs_cache + offset; +} + +static void *alternate_cbfs_unmap(struct cbfs_media *media, + const void *buffer) { return 0; } + +static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media) +{ + printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); + + media->open = sdmmc_cbfs_open; + media->close = alternate_cbfs_close; + media->read = alternate_cbfs_read; + media->map = alternate_cbfs_map; + media->unmap = alternate_cbfs_unmap; + + return 0; +} + +static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +{ + printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); + + media->open = usb_cbfs_open; + media->close = alternate_cbfs_close; + media->read = alternate_cbfs_read; + media->map = alternate_cbfs_map; + media->unmap = alternate_cbfs_unmap; + + return 0; +} + +int init_default_cbfs_media(struct cbfs_media *media) +{ + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) + return initialize_exynos_usb_cbfs_media(media); + + switch (exynos_power->om_stat & OM_STAT_MASK) { + case OM_STAT_SDMMC: + return initialize_exynos_sdmmc_cbfs_media(media); + case OM_STAT_SPI: + return initialize_exynos_spi_cbfs_media(media, + _cbfs_cache, _cbfs_cache_size); + default: + printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n", + exynos_power->om_stat); + return 1; + } +} diff --git a/src/soc/samsung/exynos5250/bootblock.c b/src/soc/samsung/exynos5250/bootblock.c new file mode 100644 index 0000000000..5154c5b3c8 --- /dev/null +++ b/src/soc/samsung/exynos5250/bootblock.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void bootblock_soc_init(void) +{ + if (get_wakeup_state() == WAKEUP_DIRECT) { + wakeup(); + /* Never returns. */ + } + + /* For most ARM systems, we have to initialize firmware media source + * (ex, SPI, SD/MMC, or eMMC) now; but for Exynos platform, that is + * already handled by iROM so there's no need to setup again. + */ +} diff --git a/src/soc/samsung/exynos5250/cbmem.c b/src/soc/samsung/exynos5250/cbmem.c new file mode 100644 index 0000000000..c9d751b68d --- /dev/null +++ b/src/soc/samsung/exynos5250/cbmem.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void *cbmem_top(void) +{ + return (void *)(get_fb_base_kb() * KiB); +} + diff --git a/src/cpu/samsung/exynos5250/chip.h b/src/soc/samsung/exynos5250/chip.h similarity index 88% rename from src/cpu/samsung/exynos5250/chip.h rename to src/soc/samsung/exynos5250/chip.h index 798cd26f7a..183bda2028 100644 --- a/src/cpu/samsung/exynos5250/chip.h +++ b/src/soc/samsung/exynos5250/chip.h @@ -20,7 +20,9 @@ #ifndef CPU_SAMSUNG_EXYNOS5250_H #define CPU_SAMSUNG_EXYNOS5250_H -struct cpu_samsung_exynos5250_config { +#include + +struct soc_samsung_exynos5250_config { /* special magic numbers! */ int clkval_f; int upper_margin; @@ -32,7 +34,10 @@ struct cpu_samsung_exynos5250_config { int xres; int yres; - int bpp; + int framebuffer_bits_per_pixel; + + int usb_vbus_gpio; + int usb_hsic_gpio; u32 lcdbase; }; diff --git a/src/cpu/samsung/exynos5250/clock.c b/src/soc/samsung/exynos5250/clock.c similarity index 75% rename from src/cpu/samsung/exynos5250/clock.c rename to src/soc/samsung/exynos5250/clock.c index 6b7927287f..d80a7f6c85 100644 --- a/src/cpu/samsung/exynos5250/clock.c +++ b/src/soc/samsung/exynos5250/clock.c @@ -1,14 +1,11 @@ /* + * This file is part of the coreboot project. + * * Copyright (C) 2010 Samsung Electronics - * Minkyu Kang * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,24 +14,21 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -//#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include /* input clock of PLL: SMDK5250 has 24MHz input clock */ #define CONFIG_SYS_CLK_FREQ 24000000 -struct arm_clk_ratios arm_clk_ratios[] = { +static struct arm_clk_ratios arm_clk_ratios[] = { { .arm_freq_mhz = 600, @@ -179,28 +173,26 @@ static struct st_epll_con_val epll_div[] = { /* exynos5: return pll clock frequency */ unsigned long get_pll_clk(int pllreg) { - struct exynos5_clock *clk = - samsung_get_base_clock(); unsigned long r, m, p, s, k = 0, mask, fout; unsigned int freq; switch (pllreg) { case APLL: - r = readl(&clk->apll_con0); + r = readl(&exynos_clock->apll_con0); break; case BPLL: - r = readl(&clk->bpll_con0); + r = readl(&exynos_clock->bpll_con0); break; case MPLL: - r = readl(&clk->mpll_con0); + r = readl(&exynos_clock->mpll_con0); break; case EPLL: - r = readl(&clk->epll_con0); - k = readl(&clk->epll_con1); + r = readl(&exynos_clock->epll_con0); + k = readl(&exynos_clock->epll_con1); break; case VPLL: - r = readl(&clk->vpll_con0); - k = readl(&clk->vpll_con1); + r = readl(&exynos_clock->vpll_con0); + k = readl(&exynos_clock->vpll_con1); break; default: printk(BIOS_DEBUG, "Unsupported PLL (%d)\n", pllreg); @@ -245,8 +237,6 @@ unsigned long get_pll_clk(int pllreg) unsigned long clock_get_periph_rate(enum periph_id peripheral) { - struct exynos5_clock *clk = - samsung_get_base_clock(); struct clk_bit_info *bit_info = &clk_bit_info[peripheral]; unsigned long sclk, sub_clk; unsigned int src, div, sub_div; @@ -256,41 +246,41 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral) case PERIPH_ID_UART1: case PERIPH_ID_UART2: case PERIPH_ID_UART3: - src = readl(&clk->src_peric0); - div = readl(&clk->div_peric0); + src = readl(&exynos_clock->src_peric0); + div = readl(&exynos_clock->div_peric0); break; case PERIPH_ID_PWM0: case PERIPH_ID_PWM1: case PERIPH_ID_PWM2: case PERIPH_ID_PWM3: case PERIPH_ID_PWM4: - src = readl(&clk->src_peric0); - div = readl(&clk->div_peric3); + src = readl(&exynos_clock->src_peric0); + div = readl(&exynos_clock->div_peric3); break; case PERIPH_ID_SPI0: case PERIPH_ID_SPI1: - src = readl(&clk->src_peric1); - div = readl(&clk->div_peric1); + src = readl(&exynos_clock->src_peric1); + div = readl(&exynos_clock->div_peric1); break; case PERIPH_ID_SPI2: - src = readl(&clk->src_peric1); - div = readl(&clk->div_peric2); + src = readl(&exynos_clock->src_peric1); + div = readl(&exynos_clock->div_peric2); break; case PERIPH_ID_SPI3: case PERIPH_ID_SPI4: - src = readl(&clk->sclk_src_isp); - div = readl(&clk->sclk_div_isp); + src = readl(&exynos_clock->sclk_src_isp); + div = readl(&exynos_clock->sclk_div_isp); break; case PERIPH_ID_SATA: - src = readl(&clk->src_fsys); - div = readl(&clk->div_fsys0); + src = readl(&exynos_clock->src_fsys); + div = readl(&exynos_clock->div_fsys0); break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC2: case PERIPH_ID_SDMMC3: - src = readl(&clk->src_fsys); - div = readl(&clk->div_fsys1); + src = readl(&exynos_clock->src_fsys); + div = readl(&exynos_clock->div_fsys1); break; case PERIPH_ID_I2C0: case PERIPH_ID_I2C1: @@ -301,8 +291,10 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral) case PERIPH_ID_I2C6: case PERIPH_ID_I2C7: sclk = get_pll_clk(MPLL); - sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit) & 0x7) + 1; - div = ((readl(&clk->div_top0) >> bit_info->prediv_bit) & 0x7) + 1; + sub_div = ((readl(&exynos_clock->div_top1) + >> bit_info->div_bit) & 0x7) + 1; + div = ((readl(&exynos_clock->div_top0) + >> bit_info->prediv_bit) & 0x7) + 1; return (sclk / sub_div) / div; default: printk(BIOS_DEBUG, "%s: invalid peripheral %d", __func__, peripheral); @@ -340,14 +332,12 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral) /* exynos5: return ARM clock frequency */ unsigned long get_arm_clk(void) { - struct exynos5_clock *clk = - samsung_get_base_clock(); unsigned long div; unsigned long armclk; unsigned int arm_ratio; unsigned int arm2_ratio; - div = readl(&clk->div_cpu0); + div = readl(&exynos_clock->div_cpu0); /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */ arm_ratio = (div >> 0) & 0x7; @@ -377,9 +367,7 @@ struct arm_clk_ratios *get_arm_clk_ratios(void) /* exynos5: set the mmc clock */ void set_mmc_clk(int dev_index, unsigned int div) { - struct exynos5_clock *clk = - samsung_get_base_clock(); - unsigned int addr; + unsigned int *addr; unsigned int val; /* @@ -389,9 +377,9 @@ void set_mmc_clk(int dev_index, unsigned int div) * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] */ if (dev_index < 2) { - addr = (unsigned int)&clk->div_fsys1; + addr = &exynos_clock->div_fsys1; } else { - addr = (unsigned int)&clk->div_fsys2; + addr = &exynos_clock->div_fsys2; dev_index -= 2; } @@ -403,8 +391,6 @@ void set_mmc_clk(int dev_index, unsigned int div) void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) { - struct exynos5_clock *clk = - samsung_get_base_clock(); unsigned shift; unsigned mask = 0xff; u32 *reg; @@ -419,27 +405,27 @@ void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) */ switch (periph_id) { case PERIPH_ID_SPI0: - reg = &clk->div_peric1; + reg = &exynos_clock->div_peric1; shift = 8; break; case PERIPH_ID_SPI1: - reg = &clk->div_peric1; + reg = &exynos_clock->div_peric1; shift = 24; break; case PERIPH_ID_SPI2: - reg = &clk->div_peric2; + reg = &exynos_clock->div_peric2; shift = 8; break; case PERIPH_ID_SPI3: - reg = &clk->sclk_div_isp; + reg = &exynos_clock->sclk_div_isp; shift = 4; break; case PERIPH_ID_SPI4: - reg = &clk->sclk_div_isp; + reg = &exynos_clock->sclk_div_isp; shift = 16; break; default: - debug("%s: Unsupported peripheral ID %d\n", __func__, + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, periph_id); return; } @@ -448,35 +434,33 @@ void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor) { - struct exynos5_clock *clk = - samsung_get_base_clock(); unsigned shift; unsigned mask = 0xff; u32 *reg; switch (periph_id) { case PERIPH_ID_SPI0: - reg = &clk->div_peric1; + reg = &exynos_clock->div_peric1; shift = 0; break; case PERIPH_ID_SPI1: - reg = &clk->div_peric1; + reg = &exynos_clock->div_peric1; shift = 16; break; case PERIPH_ID_SPI2: - reg = &clk->div_peric2; + reg = &exynos_clock->div_peric2; shift = 0; break; case PERIPH_ID_SPI3: - reg = &clk->sclk_div_isp; + reg = &exynos_clock->sclk_div_isp; shift = 0; break; case PERIPH_ID_SPI4: - reg = &clk->sclk_div_isp; + reg = &exynos_clock->sclk_div_isp; shift = 12; break; default: - debug("%s: Unsupported peripheral ID %d\n", __func__, + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, periph_id); return; } @@ -508,11 +492,11 @@ static int clock_calc_best_scalar(unsigned int main_scaler_bits, const unsigned int cap = (1 << fine_scalar_bits) - 1; const unsigned int loops = 1 << main_scaler_bits; - debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate, + printk(BIOS_DEBUG, "Input Rate is %u, Target is %u, Cap is %u\n", input_rate, target_rate, cap); - assert(best_fine_scalar != NULL); - assert(main_scaler_bits <= fine_scalar_bits); + ASSERT(best_fine_scalar != NULL); + ASSERT(main_scaler_bits <= fine_scalar_bits); *best_fine_scalar = 1; @@ -529,7 +513,7 @@ static int clock_calc_best_scalar(unsigned int main_scaler_bits, effective_div; const int error = target_rate - effective_rate; - debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div, + printk(BIOS_DEBUG, "%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div, effective_rate, error); if (error >= 0 && error <= best_error) { @@ -555,7 +539,7 @@ int clock_set_rate(enum periph_id periph_id, unsigned int rate) case PERIPH_ID_SPI4: main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); if (main < 0) { - debug("%s: Cannot set clock rate for periph %d", + printk(BIOS_DEBUG, "%s: Cannot set clock rate for periph %d", __func__, periph_id); return -1; } @@ -563,7 +547,7 @@ int clock_set_rate(enum periph_id periph_id, unsigned int rate) clock_ll_set_pre_ratio(periph_id, fine - 1); break; default: - debug("%s: Unsupported peripheral ID %d\n", __func__, + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, periph_id); return -1; } @@ -573,8 +557,6 @@ int clock_set_rate(enum periph_id periph_id, unsigned int rate) int clock_set_mshci(enum periph_id peripheral) { - struct exynos5_clock *clk = - samsung_get_base_clock(); u32 *addr; unsigned int clock; unsigned int tmp; @@ -591,13 +573,13 @@ int clock_set_mshci(enum periph_id peripheral) */ switch (peripheral) { case PERIPH_ID_SDMMC0: - addr = &clk->div_fsys1; + addr = &exynos_clock->div_fsys1; break; case PERIPH_ID_SDMMC2: - addr = &clk->div_fsys2; + addr = &exynos_clock->div_fsys2; break; default: - debug("invalid peripheral\n"); + printk(BIOS_DEBUG, "invalid peripheral\n"); return -1; } tmp = readl(addr) & ~0xff0f; @@ -610,34 +592,14 @@ int clock_set_mshci(enum periph_id peripheral) return 0; } -#ifdef CONFIG_OF_CONTROL -int clock_decode_periph_id(const void *blob, int node) -{ - enum periph_id id; - - /* - * For now the peripheral ID is directly encoded. Once we have clock - * support in the fdt and properly in exynos U-Boot we may have - * another way of changing the clock. - */ - id = fdtdec_get_int(blob, node, "samsung,periph-id", -1); - assert(id != PERIPH_ID_NONE); - assert(id >= 0 && id < PERIPH_ID_COUNT); - - return id; -} -#endif - int clock_epll_set_rate(unsigned long rate) { unsigned int epll_con, epll_con_k; unsigned int i; unsigned int lockcnt; - unsigned int start; - struct exynos5_clock *clk = - samsung_get_base_clock(); + struct stopwatch sw; - epll_con = readl(&clk->epll_con0); + epll_con = readl(&exynos_clock->epll_con0); epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK << EPLL_CON0_LOCK_DET_EN_SHIFT) | EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT | @@ -665,16 +627,18 @@ int clock_epll_set_rate(unsigned long rate) */ lockcnt = 3000 * epll_div[i].p_div; - writel(lockcnt, &clk->epll_lock); - writel(epll_con, &clk->epll_con0); - writel(epll_con_k, &clk->epll_con1); + writel(lockcnt, &exynos_clock->epll_lock); + writel(epll_con, &exynos_clock->epll_con0); + writel(epll_con_k, &exynos_clock->epll_con1); - start = get_timer(0); + stopwatch_init_msecs_expire(&sw, TIMEOUT_EPLL_LOCK); - while (!(readl(&clk->epll_con0) & + while (!(readl(&exynos_clock->epll_con0) & (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) { - if (get_timer(start) > TIMEOUT_EPLL_LOCK) { - printk(BIOS_DEBUG, "%s: Timeout waiting for EPLL lock\n", __func__); + if (stopwatch_expired(&sw)) { + printk(BIOS_DEBUG, + "%s: Timeout waiting for EPLL lock\n", + __func__); return -1; } } @@ -684,32 +648,27 @@ int clock_epll_set_rate(unsigned long rate) void clock_select_i2s_clk_source(void) { - struct exynos5_clock *clk = - samsung_get_base_clock(); - - clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK, + clrsetbits_le32(&exynos_clock->src_peric1, AUDIO1_SEL_MASK, (CLK_SRC_SCLK_EPLL)); } int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq) { - struct exynos5_clock *clk = - samsung_get_base_clock(); unsigned int div ; if ((dst_frq == 0) || (src_frq == 0)) { - debug("%s: Invalid requency input for prescaler\n", __func__); - debug("src frq = %d des frq = %d ", src_frq, dst_frq); + printk(BIOS_DEBUG, "%s: Invalid requency input for prescaler\n", __func__); + printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq); return -1; } div = (src_frq / dst_frq); if (div > AUDIO_1_RATIO_MASK) { - debug("%s: Frequency ratio is out of range\n", __func__); - debug("src frq = %d des frq = %d ", src_frq, dst_frq); + printk(BIOS_DEBUG, "%s: Frequency ratio is out of range\n", __func__); + printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq); return -1; } - clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK, + clrsetbits_le32(&exynos_clock->div_peric4, AUDIO_1_RATIO_MASK, (div & AUDIO_1_RATIO_MASK)); return 0; } diff --git a/src/soc/samsung/exynos5250/clock_init.c b/src/soc/samsung/exynos5250/clock_init.c new file mode 100644 index 0000000000..c78148bf47 --- /dev/null +++ b/src/soc/samsung/exynos5250/clock_init.c @@ -0,0 +1,443 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Clock setup for SMDK5250 board based on EXYNOS5 */ + +#include +#include +#include +#include +#include + +void system_clock_init(struct mem_timings *mem, + struct arm_clk_ratios *arm_clk_ratio) +{ + u32 val, tmp; + + /* Turn on the MCT as early as possible. */ + exynos_mct->g_tcon |= (1 << 8); + + clrbits_le32(&exynos_clock->src_cpu, MUX_APLL_SEL_MASK); + do { + val = readl(&exynos_clock->mux_stat_cpu); + } while ((val | MUX_APLL_SEL_MASK) != val); + + clrbits_le32(&exynos_clock->src_core1, MUX_MPLL_SEL_MASK); + do { + val = readl(&exynos_clock->mux_stat_core1); + } while ((val | MUX_MPLL_SEL_MASK) != val); + + clrbits_le32(&exynos_clock->src_top2, MUX_CPLL_SEL_MASK); + clrbits_le32(&exynos_clock->src_top2, MUX_EPLL_SEL_MASK); + clrbits_le32(&exynos_clock->src_top2, MUX_VPLL_SEL_MASK); + clrbits_le32(&exynos_clock->src_top2, MUX_GPLL_SEL_MASK); + tmp = MUX_CPLL_SEL_MASK | MUX_EPLL_SEL_MASK | MUX_VPLL_SEL_MASK + | MUX_GPLL_SEL_MASK; + do { + val = readl(&exynos_clock->mux_stat_top2); + } while ((val | tmp) != val); + + clrbits_le32(&exynos_clock->src_cdrex, MUX_BPLL_SEL_MASK); + do { + val = readl(&exynos_clock->mux_stat_cdrex); + } while ((val | MUX_BPLL_SEL_MASK) != val); + + /* PLL locktime */ + writel(APLL_LOCK_VAL, &exynos_clock->apll_lock); + + writel(MPLL_LOCK_VAL, &exynos_clock->mpll_lock); + + writel(BPLL_LOCK_VAL, &exynos_clock->bpll_lock); + + writel(CPLL_LOCK_VAL, &exynos_clock->cpll_lock); + + writel(GPLL_LOCK_VAL, &exynos_clock->gpll_lock); + + writel(EPLL_LOCK_VAL, &exynos_clock->epll_lock); + + writel(VPLL_LOCK_VAL, &exynos_clock->vpll_lock); + + writel(CLK_REG_DISABLE, &exynos_clock->pll_div2_sel); + + writel(MUX_HPM_SEL_MASK, &exynos_clock->src_cpu); + do { + val = readl(&exynos_clock->mux_stat_cpu); + } while ((val | HPM_SEL_SCLK_MPLL) != val); + + val = arm_clk_ratio->arm2_ratio << 28 + | arm_clk_ratio->apll_ratio << 24 + | arm_clk_ratio->pclk_dbg_ratio << 20 + | arm_clk_ratio->atb_ratio << 16 + | arm_clk_ratio->periph_ratio << 12 + | arm_clk_ratio->acp_ratio << 8 + | arm_clk_ratio->cpud_ratio << 4 + | arm_clk_ratio->arm_ratio; + writel(val, &exynos_clock->div_cpu0); + do { + val = readl(&exynos_clock->div_stat_cpu0); + } while (0 != val); + + writel(CLK_DIV_CPU1_VAL, &exynos_clock->div_cpu1); + do { + val = readl(&exynos_clock->div_stat_cpu1); + } while (0 != val); + + /* switch A15 clock source to OSC clock before changing APLL */ + clrbits_le32(&exynos_clock->src_cpu, APLL_FOUT); + + /* Set APLL */ + writel(APLL_CON1_VAL, &exynos_clock->apll_con1); + val = set_pll(arm_clk_ratio->apll_mdiv, arm_clk_ratio->apll_pdiv, + arm_clk_ratio->apll_sdiv); + writel(val, &exynos_clock->apll_con0); + while ((readl(&exynos_clock->apll_con0) & APLL_CON0_LOCKED) == 0) + ; + + /* now it is safe to switch to APLL */ + setbits_le32(&exynos_clock->src_cpu, APLL_FOUT); + + /* Set MPLL */ + writel(MPLL_CON1_VAL, &exynos_clock->mpll_con1); + val = set_pll(mem->mpll_mdiv, mem->mpll_pdiv, mem->mpll_sdiv); + writel(val, &exynos_clock->mpll_con0); + while ((readl(&exynos_clock->mpll_con0) & MPLL_CON0_LOCKED) == 0) + ; + + /* + * Configure MUX_MPLL_FOUT to choose the direct clock source + * path and avoid the fixed DIV/2 block to save power + */ + setbits_le32(&exynos_clock->pll_div2_sel, MUX_MPLL_FOUT_SEL); + + /* Set BPLL */ + if (mem->use_bpll) { + writel(BPLL_CON1_VAL, &exynos_clock->bpll_con1); + val = set_pll(mem->bpll_mdiv, mem->bpll_pdiv, mem->bpll_sdiv); + writel(val, &exynos_clock->bpll_con0); + while ((readl(&exynos_clock->bpll_con0) & BPLL_CON0_LOCKED) == 0) + ; + + setbits_le32(&exynos_clock->pll_div2_sel, MUX_BPLL_FOUT_SEL); + } + + /* Set CPLL */ + writel(CPLL_CON1_VAL, &exynos_clock->cpll_con1); + val = set_pll(mem->cpll_mdiv, mem->cpll_pdiv, mem->cpll_sdiv); + writel(val, &exynos_clock->cpll_con0); + while ((readl(&exynos_clock->cpll_con0) & CPLL_CON0_LOCKED) == 0) + ; + + /* Set GPLL */ + writel(GPLL_CON1_VAL, &exynos_clock->gpll_con1); + val = set_pll(mem->gpll_mdiv, mem->gpll_pdiv, mem->gpll_sdiv); + writel(val, &exynos_clock->gpll_con0); + while ((readl(&exynos_clock->gpll_con0) & GPLL_CON0_LOCKED) == 0) + ; + + /* Set EPLL */ + writel(EPLL_CON2_VAL, &exynos_clock->epll_con2); + writel(EPLL_CON1_VAL, &exynos_clock->epll_con1); + val = set_pll(mem->epll_mdiv, mem->epll_pdiv, mem->epll_sdiv); + writel(val, &exynos_clock->epll_con0); + while ((readl(&exynos_clock->epll_con0) & EPLL_CON0_LOCKED) == 0) + ; + + /* Set VPLL */ + writel(VPLL_CON2_VAL, &exynos_clock->vpll_con2); + writel(VPLL_CON1_VAL, &exynos_clock->vpll_con1); + val = set_pll(mem->vpll_mdiv, mem->vpll_pdiv, mem->vpll_sdiv); + writel(val, &exynos_clock->vpll_con0); + while ((readl(&exynos_clock->vpll_con0) & VPLL_CON0_LOCKED) == 0) + ; + + writel(CLK_SRC_CORE0_VAL, &exynos_clock->src_core0); + writel(CLK_DIV_CORE0_VAL, &exynos_clock->div_core0); + while (readl(&exynos_clock->div_stat_core0) != 0) + ; + + writel(CLK_DIV_CORE1_VAL, &exynos_clock->div_core1); + while (readl(&exynos_clock->div_stat_core1) != 0) + ; + + writel(CLK_DIV_SYSRGT_VAL, &exynos_clock->div_sysrgt); + while (readl(&exynos_clock->div_stat_sysrgt) != 0) + ; + + writel(CLK_DIV_ACP_VAL, &exynos_clock->div_acp); + while (readl(&exynos_clock->div_stat_acp) != 0) + ; + + writel(CLK_DIV_SYSLFT_VAL, &exynos_clock->div_syslft); + while (readl(&exynos_clock->div_stat_syslft) != 0) + ; + + writel(CLK_SRC_TOP0_VAL, &exynos_clock->src_top0); + writel(CLK_SRC_TOP1_VAL, &exynos_clock->src_top1); + writel(TOP2_VAL, &exynos_clock->src_top2); + writel(CLK_SRC_TOP3_VAL, &exynos_clock->src_top3); + + writel(CLK_DIV_TOP0_VAL, &exynos_clock->div_top0); + while (readl(&exynos_clock->div_stat_top0)) + ; + + writel(CLK_DIV_TOP1_VAL, &exynos_clock->div_top1); + while (readl(&exynos_clock->div_stat_top1)) + ; + + writel(CLK_SRC_LEX_VAL, &exynos_clock->src_lex); + while (1) { + val = readl(&exynos_clock->mux_stat_lex); + if (val == (val | 1)) + break; + } + + writel(CLK_DIV_LEX_VAL, &exynos_clock->div_lex); + while (readl(&exynos_clock->div_stat_lex)) + ; + + writel(CLK_DIV_R0X_VAL, &exynos_clock->div_r0x); + while (readl(&exynos_clock->div_stat_r0x)) + ; + + writel(CLK_DIV_R0X_VAL, &exynos_clock->div_r0x); + while (readl(&exynos_clock->div_stat_r0x)) + ; + + writel(CLK_DIV_R1X_VAL, &exynos_clock->div_r1x); + while (readl(&exynos_clock->div_stat_r1x)) + ; + + if (mem->use_bpll) { + writel(MUX_BPLL_SEL_MASK | MUX_MCLK_CDREX_SEL | + MUX_MCLK_DPHY_SEL, &exynos_clock->src_cdrex); + } else { + writel(CLK_REG_DISABLE, &exynos_clock->src_cdrex); + } + + writel(CLK_DIV_CDREX_VAL, &exynos_clock->div_cdrex); + while (readl(&exynos_clock->div_stat_cdrex)) + ; + + val = readl(&exynos_clock->src_cpu); + val |= CLK_SRC_CPU_VAL; + writel(val, &exynos_clock->src_cpu); + + val = readl(&exynos_clock->src_top2); + val |= CLK_SRC_TOP2_VAL; + writel(val, &exynos_clock->src_top2); + + val = readl(&exynos_clock->src_core1); + val |= CLK_SRC_CORE1_VAL; + writel(val, &exynos_clock->src_core1); + + writel(CLK_SRC_FSYS0_VAL, &exynos_clock->src_fsys); + writel(CLK_DIV_FSYS0_VAL, &exynos_clock->div_fsys0); + while (readl(&exynos_clock->div_stat_fsys0)) + ; + + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_cpu); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_core); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_acp); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_top); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_lex); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_r0x); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_r1x); + writel(CLK_REG_DISABLE, &exynos_clock->clkout_cmu_cdrex); + + writel(CLK_SRC_PERIC0_VAL, &exynos_clock->src_peric0); + writel(CLK_DIV_PERIC0_VAL, &exynos_clock->div_peric0); + + writel(CLK_SRC_PERIC1_VAL, &exynos_clock->src_peric1); + writel(CLK_DIV_PERIC1_VAL, &exynos_clock->div_peric1); + writel(CLK_DIV_PERIC2_VAL, &exynos_clock->div_peric2); + writel(SCLK_SRC_ISP_VAL, &exynos_clock->sclk_src_isp); + writel(SCLK_DIV_ISP_VAL, &exynos_clock->sclk_div_isp); + writel(CLK_DIV_ISP0_VAL, &exynos_clock->div_isp0); + writel(CLK_DIV_ISP1_VAL, &exynos_clock->div_isp1); + writel(CLK_DIV_ISP2_VAL, &exynos_clock->div_isp2); + + /* FIMD1 SRC CLK SELECTION */ + writel(CLK_SRC_DISP1_0_VAL, &exynos_clock->src_disp1_0); + + val = MMC2_PRE_RATIO_VAL << MMC2_PRE_RATIO_OFFSET + | MMC2_RATIO_VAL << MMC2_RATIO_OFFSET + | MMC3_PRE_RATIO_VAL << MMC3_PRE_RATIO_OFFSET + | MMC3_RATIO_VAL << MMC3_RATIO_OFFSET; + writel(val, &exynos_clock->div_fsys2); +} + +void clock_gate(void) +{ + /* CLK_GATE_IP_SYSRGT */ + clrbits_le32(&exynos_clock->gate_ip_sysrgt, CLK_C2C_MASK); + + /* CLK_GATE_IP_ACP */ + clrbits_le32(&exynos_clock->gate_ip_acp, CLK_SMMUG2D_MASK | + CLK_SMMUSSS_MASK | + CLK_SMMUMDMA_MASK | + CLK_ID_REMAPPER_MASK | + CLK_G2D_MASK | + CLK_SSS_MASK | + CLK_MDMA_MASK | + CLK_SECJTAG_MASK); + + /* CLK_GATE_BUS_SYSLFT */ + clrbits_le32(&exynos_clock->gate_bus_syslft, CLK_EFCLK_MASK); + + /* CLK_GATE_IP_ISP0 */ + clrbits_le32(&exynos_clock->gate_ip_isp0, CLK_UART_ISP_MASK | + CLK_WDT_ISP_MASK | + CLK_PWM_ISP_MASK | + CLK_MTCADC_ISP_MASK | + CLK_I2C1_ISP_MASK | + CLK_I2C0_ISP_MASK | + CLK_MPWM_ISP_MASK | + CLK_MCUCTL_ISP_MASK | + CLK_INT_COMB_ISP_MASK | + CLK_SMMU_MCUISP_MASK | + CLK_SMMU_SCALERP_MASK | + CLK_SMMU_SCALERC_MASK | + CLK_SMMU_FD_MASK | + CLK_SMMU_DRC_MASK | + CLK_SMMU_ISP_MASK | + CLK_GICISP_MASK | + CLK_ARM9S_MASK | + CLK_MCUISP_MASK | + CLK_SCALERP_MASK | + CLK_SCALERC_MASK | + CLK_FD_MASK | + CLK_DRC_MASK | + CLK_ISP_MASK); + + /* CLK_GATE_IP_ISP1 */ + clrbits_le32(&exynos_clock->gate_ip_isp1, CLK_SPI1_ISP_MASK | + CLK_SPI0_ISP_MASK | + CLK_SMMU3DNR_MASK | + CLK_SMMUDIS1_MASK | + CLK_SMMUDIS0_MASK | + CLK_SMMUODC_MASK | + CLK_3DNR_MASK | + CLK_DIS_MASK | + CLK_ODC_MASK); + + /* CLK_GATE_SCLK_ISP */ + clrbits_le32(&exynos_clock->gate_sclk_isp, SCLK_MPWM_ISP_MASK); + + /* CLK_GATE_IP_GSCL */ + clrbits_le32(&exynos_clock->gate_ip_gscl, CLK_SMMUFIMC_LITE2_MASK | + CLK_SMMUFIMC_LITE1_MASK | + CLK_SMMUFIMC_LITE0_MASK | + CLK_SMMUGSCL3_MASK | + CLK_SMMUGSCL2_MASK | + CLK_SMMUGSCL1_MASK | + CLK_SMMUGSCL0_MASK | + CLK_GSCL_WRAP_B_MASK | + CLK_GSCL_WRAP_A_MASK | + CLK_CAMIF_TOP_MASK | + CLK_GSCL3_MASK | + CLK_GSCL2_MASK | + CLK_GSCL1_MASK | + CLK_GSCL0_MASK); + + /* CLK_GATE_IP_DISP1 */ + clrbits_le32(&exynos_clock->gate_ip_disp1, CLK_SMMUTVX_MASK | + CLK_ASYNCTVX_MASK | + CLK_HDMI_MASK | + CLK_MIXER_MASK | + CLK_DSIM1_MASK); + + /* CLK_GATE_IP_MFC */ + clrbits_le32(&exynos_clock->gate_ip_mfc, CLK_SMMUMFCR_MASK | + CLK_SMMUMFCL_MASK | + CLK_MFC_MASK); + + /* CLK_GATE_IP_GEN */ + clrbits_le32(&exynos_clock->gate_ip_gen, CLK_SMMUMDMA1_MASK | + CLK_SMMUJPEG_MASK | + CLK_SMMUROTATOR_MASK | + CLK_MDMA1_MASK | + CLK_JPEG_MASK | + CLK_ROTATOR_MASK); + + /* CLK_GATE_IP_FSYS */ + clrbits_le32(&exynos_clock->gate_ip_fsys, CLK_WDT_IOP_MASK | + CLK_SMMUMCU_IOP_MASK | + CLK_SATA_PHY_I2C_MASK | + CLK_SATA_PHY_CTRL_MASK | + CLK_MCUCTL_MASK | + CLK_NFCON_MASK | + CLK_SMMURTIC_MASK | + CLK_RTIC_MASK | + CLK_MIPI_HSI_MASK | + CLK_USBOTG_MASK | + CLK_SATA_MASK | + CLK_PDMA1_MASK | + CLK_PDMA0_MASK | + CLK_MCU_IOP_MASK); + + /* CLK_GATE_IP_PERIC */ + clrbits_le32(&exynos_clock->gate_ip_peric, CLK_HS_I2C3_MASK | + CLK_HS_I2C2_MASK | + CLK_HS_I2C1_MASK | + CLK_HS_I2C0_MASK | + CLK_AC97_MASK | + CLK_SPDIF_MASK | + CLK_PCM2_MASK | + CLK_PCM1_MASK | + CLK_I2S2_MASK | + CLK_SPI2_MASK | + CLK_SPI0_MASK); + + /* + * CLK_GATE_IP_PERIS + * Note: Keep CHIPID_APBIF ungated to ensure reading the product ID + * register (PRO_ID) works correctly when the OS kernel determines + * which chip it is running on. + */ + clrbits_le32(&exynos_clock->gate_ip_peris, CLK_RTC_MASK | + CLK_TZPC9_MASK | + CLK_TZPC8_MASK | + CLK_TZPC7_MASK | + CLK_TZPC6_MASK | + CLK_TZPC5_MASK | + CLK_TZPC4_MASK | + CLK_TZPC3_MASK | + CLK_TZPC2_MASK | + CLK_TZPC1_MASK | + CLK_TZPC0_MASK); + + /* CLK_GATE_BLOCK */ + clrbits_le32(&exynos_clock->gate_block, CLK_ACP_MASK); + + /* CLK_GATE_IP_CDREX */ + clrbits_le32(&exynos_clock->gate_ip_cdrex, CLK_DPHY0_MASK | + CLK_DPHY1_MASK | + CLK_TZASC_DRBXR_MASK); + +} + +void clock_init_dp_clock(void) +{ + /* DP clock enable */ + setbits_le32(&exynos_clock->gate_ip_disp1, CLK_GATE_DP1_ALLOW); + + /* We run DP at 267 Mhz */ + setbits_le32(&exynos_clock->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); +} + diff --git a/src/soc/samsung/exynos5250/cpu.c b/src/soc/samsung/exynos5250/cpu.c new file mode 100644 index 0000000000..67212bba0d --- /dev/null +++ b/src/soc/samsung/exynos5250/cpu.c @@ -0,0 +1,168 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static unsigned int cpu_id; +static unsigned int cpu_rev; + +static void set_cpu_id(void) +{ + cpu_id = readl((void *)EXYNOS5_PRO_ID); + cpu_id = (0xC000 | ((cpu_id & 0x00FFF000) >> 12)); + + /* + * 0xC200: EXYNOS4210 EVT0 + * 0xC210: EXYNOS4210 EVT1 + */ + if (cpu_id == 0xC200) { + cpu_id |= 0x10; + cpu_rev = 0; + } else if (cpu_id == 0xC210) { + cpu_rev = 1; + } +} + +/* we distinguish a display port device from a raw graphics device + * because there are dramatic differences in startup depending on + * graphics usage. To make startup fast and easier to understand and + * debug we explicitly name this common case. The alternate approach, + * involving lots of machine and callbacks, is hard to debug and + * verify. + */ +static void exynos_displayport_init(device_t dev, u32 lcdbase, + unsigned long fb_size) +{ + int ret; + struct soc_samsung_exynos5250_config *conf = dev->chip_info; + /* put these on the stack. If, at some point, we want to move + * this code to a pre-ram stage, it will be much easier. + */ + struct exynos5_fimd_panel panel; + memset(&panel, 0, sizeof(panel)); + + panel.is_dp = 1; /* Display I/F is eDP */ + /* while it is true that we did a memset to zero, + * we leave some 'set to zero' entries here to make + * it clear what's going on. Graphics is confusing. + */ + panel.is_mipi = 0; + panel.fixvclk = 0; + panel.ivclk = 0; + panel.clkval_f = conf->clkval_f; + panel.upper_margin = conf->upper_margin; + panel.lower_margin = conf->lower_margin; + panel.vsync = conf->vsync; + panel.left_margin = conf->left_margin; + panel.right_margin = conf->right_margin; + panel.hsync = conf->hsync; + panel.xres = conf->xres; + panel.yres = conf->yres; + + printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase)); + memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */ + + /* + * We need to clean and invalidate the framebuffer region and disable + * caching as well. We assume that our dcache <--> memory address + * space is identity-mapped in 1MB chunks, so align accordingly. + * + * Note: We may want to do something clever to ensure the framebuffer + * region is aligned such that we don't change dcache policy for other + * stuff inadvertantly. + */ + uint32_t lower = ALIGN_DOWN(lcdbase, MiB); + uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB); + + dcache_clean_invalidate_by_mva((void *)lower, upper - lower); + mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF); + + printk(BIOS_DEBUG, "Initializing Exynos LCD.\n"); + + ret = lcd_ctrl_init(fb_size, &panel, (void *)lcdbase); +} + +static void cpu_enable(device_t dev) +{ + unsigned long fb_size = FB_SIZE_KB * KiB; + u32 lcdbase = get_fb_base_kb() * KiB; + + ram_resource(dev, 0, RAM_BASE_KB, RAM_SIZE_KB - FB_SIZE_KB); + mmio_resource(dev, 1, lcdbase / KiB, (fb_size + KiB - 1) / KiB); + + exynos_displayport_init(dev, lcdbase, fb_size); + + set_cpu_id(); +} + +static void cpu_init(device_t dev) +{ + printk(BIOS_INFO, "CPU: S5P%X @ %ldMHz\n", + cpu_id, get_arm_clk() / (1024*1024)); +} + +static void cpu_noop(device_t dev) +{ +} + +static struct device_operations cpu_ops = { + .read_resources = cpu_noop, + .set_resources = cpu_noop, + .enable_resources = cpu_enable, + .init = cpu_init, + .scan_bus = 0, +}; + +static void enable_exynos5250_dev(device_t dev) +{ + dev->ops = &cpu_ops; +} + +struct chip_operations soc_samsung_exynos5250_ops = { + CHIP_NAME("SOC Samsung Exynos 5250") + .enable_dev = enable_exynos5250_dev, +}; + +void exynos5250_config_l2_cache(void) +{ + uint32_t val; + + /* + * Bit 9 - L2 tag RAM setup (1 cycle) + * Bits 8:6 - L2 tag RAM latency (3 cycles) + * Bit 5 - L2 data RAM setup (1 cycle) + * Bits 2:0 - L2 data RAM latency (3 cycles) + */ + val = (1 << 9) | (0x2 << 6) | (1 << 5) | (0x2); + write_l2ctlr(val); +} diff --git a/src/cpu/samsung/exynos5250/dmc_common.c b/src/soc/samsung/exynos5250/dmc_common.c similarity index 84% rename from src/cpu/samsung/exynos5250/dmc_common.c rename to src/soc/samsung/exynos5250/dmc_common.c index 8c4b583a9e..0f700467e0 100644 --- a/src/cpu/samsung/exynos5250/dmc_common.c +++ b/src/soc/samsung/exynos5250/dmc_common.c @@ -1,15 +1,11 @@ /* - * Mem setup common file for different types of DDR present on SMDK5250 boards. + * This file is part of the coreboot project. * * Copyright (C) 2012 Samsung Electronics * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,21 +14,18 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mem setup common file for different types of DDR present on SMDK5250 boards. */ #include -#include -#include #include -#include -#include -#include -#include - -#include "clock_init.h" -#include "setup.h" +#include +#include +#include +#include #define ZQ_INIT_TIMEOUT 10000 @@ -75,7 +68,7 @@ int dmc_config_zq(struct mem_timings *mem, */ i = ZQ_INIT_TIMEOUT; while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { - sdelay(100); + udelay(1); i--; } if (!i) @@ -84,7 +77,7 @@ int dmc_config_zq(struct mem_timings *mem, i = ZQ_INIT_TIMEOUT; while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { - sdelay(100); + udelay(1); i--; } if (!i) @@ -135,21 +128,27 @@ void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) * delays? This one and the next were not there for * DDR3. */ - sdelay(0x10000); + udelay(100); /* Sending EMRS/MRS commands */ for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { writel(mem->direct_cmd_msr[i] | mask, &dmc->directcmd); - sdelay(0x10000); + udelay(100); } if (mem->send_zq_init) { /* Sending ZQINIT command */ writel(DIRECT_CMD_ZQINIT | mask, &dmc->directcmd); - - sdelay(10000); + /* + * FIXME: This was originally sdelay(10000) + * in the imported u-boot code. That may have + * been meant to be sdelay(0x10000) since that + * was used elsewhere in this function. Either + * way seems to work, though. + */ + udelay(12); } } } @@ -168,7 +167,7 @@ void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) /* PALL (all banks precharge) CMD */ writel(DIRECT_CMD_PALL | mask, &dmc->directcmd); - sdelay(0x10000); + udelay(100); } } } diff --git a/src/soc/samsung/exynos5250/dmc_init_ddr3.c b/src/soc/samsung/exynos5250/dmc_init_ddr3.c new file mode 100644 index 0000000000..3b26c206c1 --- /dev/null +++ b/src/soc/samsung/exynos5250/dmc_init_ddr3.c @@ -0,0 +1,250 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* DDR3 mem setup file for SMDK5250 board based on EXYNOS5 */ + +#include +#include +#include +#include +#include +#include +#include + +#define RDLVL_COMPLETE_TIMEOUT 10000 + +static void reset_phy_ctrl(void) +{ + writel(LPDDR3PHY_CTRL_PHY_RESET_ENABLE, &exynos_clock->lpddr3phy_ctrl); + writel(LPDDR3PHY_CTRL_PHY_RESET_DISABLE, &exynos_clock->lpddr3phy_ctrl); + +#if 0 + /* + * For proper memory initialization there should be a minimum delay of + * 500us after the LPDDR3PHY_CTRL_PHY_RESET signal. + * The below value is an approximate value whose calculation in done + * considering that sdelay takes 2 instruction for every 1 delay cycle. + * And assuming each instruction takes 1 clock cycle i.e 1/(1.7 Ghz)sec + * So for 500 usec, the number of delay cycle should be + * (500 * 10^-6) * (1.7 * 10^9) / 2 = 425000 + * + * TODO(hatim.rv@samsung.com): Implement the delay using timer/counter + */ + sdelay(425000); +#endif + udelay(500); +} + +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int mem_reset) +{ + unsigned int val; + int i; + + if (mem_reset) + reset_phy_ctrl(); + + /* Set Impedance Output Driver */ + val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) | + (mem->impedance << CA_CKE_DRVR_DS_OFFSET) | + (mem->impedance << CA_CS_DRVR_DS_OFFSET) | + (mem->impedance << CA_ADR_DRVR_DS_OFFSET); + writel(val, &exynos_phy0_control->phy_con39); + writel(val, &exynos_phy1_control->phy_con39); + + /* Set Read Latency and Burst Length for PHY0 and PHY1 */ + val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | + (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); + writel(val, &exynos_phy0_control->phy_con42); + writel(val, &exynos_phy1_control->phy_con42); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, exynos_phy0_control, exynos_phy1_control)){ + printk(BIOS_EMERG, "DRAM ZQ CALIBRATION FAILURE\n"); + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + } + + /* DQ Signal */ + writel(mem->phy0_pulld_dqs, &exynos_phy0_control->phy_con14); + writel(mem->phy1_pulld_dqs, &exynos_phy1_control->phy_con14); + + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) + | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT), + &exynos_dmc->concontrol); + + update_reset_dll(exynos_dmc, DDR_MODE_DDR3); + + /* DQS Signal */ + writel(mem->phy0_dqs, &exynos_phy0_control->phy_con4); + writel(mem->phy1_dqs, &exynos_phy1_control->phy_con4); + + writel(mem->phy0_dq, &exynos_phy0_control->phy_con6); + writel(mem->phy1_dq, &exynos_phy1_control->phy_con6); + + writel(mem->phy0_tFS, &exynos_phy0_control->phy_con10); + writel(mem->phy1_tFS, &exynos_phy1_control->phy_con10); + + val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &exynos_phy0_control->phy_con12); + writel(val, &exynos_phy1_control->phy_con12); + + /* Start DLL locking */ + writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), + &exynos_phy0_control->phy_con12); + writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT), + &exynos_phy1_control->phy_con12); + + update_reset_dll(exynos_dmc, DDR_MODE_DDR3); + + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &exynos_dmc->concontrol); + + /* Memory Channel Inteleaving Size */ + writel(mem->iv_size, &exynos_dmc->ivcontrol); + + /* Set DMC MEMCONTROL register */ + val = mem->memcontrol & ~DMC_MEMCONTROL_DSREF_ENABLE; + writel(val, &exynos_dmc->memcontrol); + + writel(mem->memconfig, &exynos_dmc->memconfig0); + writel(mem->memconfig, &exynos_dmc->memconfig1); + writel(mem->membaseconfig0, &exynos_dmc->membaseconfig0); + writel(mem->membaseconfig1, &exynos_dmc->membaseconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &exynos_dmc->prechconfig); + + /* Power Down mode Configuration */ + writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT | + mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT, + &exynos_dmc->pwrdnconfig); + + /* TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &exynos_dmc->timingref); + writel(mem->timing_row, &exynos_dmc->timingrow); + writel(mem->timing_data, &exynos_dmc->timingdata); + writel(mem->timing_power, &exynos_dmc->timingpower); + + /* Send PALL command */ + dmc_config_prech(mem, exynos_dmc); + + if (mem_reset) { + /* Send NOP, MRS and ZQINIT commands. + * Sending MRS command will reset the DRAM. We should not be + * reseting the DRAM after resume, this will lead to memory + * corruption as DRAM content is lost after DRAM reset + */ + dmc_config_mrs(mem, exynos_dmc); + } + + if (mem->gate_leveling_enable) { + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + writel(val, &exynos_phy0_control->phy_con0); + writel(val, &exynos_phy1_control->phy_con0); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &exynos_phy0_control->phy_con2); + writel(val, &exynos_phy1_control->phy_con2); + + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + val |= BYTE_RDLVL_EN; + writel(val, &exynos_phy0_control->phy_con0); + writel(val, &exynos_phy1_control->phy_con0); + + val = (mem->ctrl_start_point << + PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | + (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &exynos_phy0_control->phy_con12); + writel(val, &exynos_phy1_control->phy_con12); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + val |= RDLVL_GATE_EN; + writel(val, &exynos_phy0_control->phy_con2); + writel(val, &exynos_phy1_control->phy_con2); + + val = PHY_CON0_RESET_VAL; + val |= P0_CMD_EN; + val |= BYTE_RDLVL_EN; + val |= CTRL_SHGATE; + writel(val, &exynos_phy0_control->phy_con0); + writel(val, &exynos_phy1_control->phy_con0); + + val = PHY_CON1_RESET_VAL; + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &exynos_phy0_control->phy_con1); + writel(val, &exynos_phy1_control->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &exynos_dmc->rdlvl_config); + i = RDLVL_COMPLETE_TIMEOUT; + while ((readl(&exynos_dmc->phystatus) & + (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) != + (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + udelay(1); + i--; + } + if (!i){ + printk(BIOS_EMERG, "Timeout on RDLVL. No DRAM.\n"); + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + } + writel(CTRL_RDLVL_GATE_DISABLE, &exynos_dmc->rdlvl_config); + + writel(0, &exynos_phy0_control->phy_con14); + writel(0, &exynos_phy1_control->phy_con14); + + val = (mem->ctrl_start_point << + PHY_CON12_CTRL_START_POINT_SHIFT) | + (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) | + (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) | + (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) | + (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) | + (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT); + writel(val, &exynos_phy0_control->phy_con12); + writel(val, &exynos_phy1_control->phy_con12); + + update_reset_dll(exynos_dmc, DDR_MODE_DDR3); + } + + /* Send PALL command */ + dmc_config_prech(mem, exynos_dmc); + + writel(mem->memcontrol, &exynos_dmc->memcontrol); + + /* Set DMC Concontrol and enable auto-refresh counter */ + writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT) + | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), + &exynos_dmc->concontrol); + return 0; +} diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c b/src/soc/samsung/exynos5250/dp-reg.c similarity index 87% rename from src/cpu/samsung/exynos5-common/s5p-dp-reg.c rename to src/soc/samsung/exynos5250/dp-reg.c index adb64a8e10..78ca3b1bb1 100644 --- a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c +++ b/src/soc/samsung/exynos5250/dp-reg.c @@ -1,23 +1,34 @@ /* - * Samsung DP (Display port) register interface driver. + * This file is part of the coreboot project. * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Jingoo Han + * Copyright (C) 2012 Samsung Electronics * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +/* Samsung DP (Display port) register interface driver. */ + #include -#include -#include -#include -#include -#include "cpu/samsung/exynos5250/fimd.h" -#include "s5p-dp-core.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include void s5p_dp_reset(struct s5p_dp_device *dp) { @@ -109,7 +120,7 @@ unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp) int s5p_dp_init_analog_func(struct s5p_dp_device *dp) { u32 reg; - u32 start; + struct stopwatch sw; struct exynos5_dp *base = dp->base; writel(0x00, &base->dp_phy_pd); @@ -124,10 +135,12 @@ int s5p_dp_init_analog_func(struct s5p_dp_device *dp) clrbits_le32(&base->dp_pll_ctl, DP_PLL_PD); - start = get_timer(0); + stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT); + while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - if (get_timer(start) > PLL_LOCK_TIMEOUT) { - debug("%s: PLL is not locked yet\n", __func__); + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "%s: PLL is not locked\n", + __func__); return -1; } } @@ -185,6 +198,8 @@ int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp) /* Clear interrupt source for AUX CH access error */ reg = readl(&base->dp_int_sta); if (reg & AUX_ERR) { + printk(BIOS_ERR, "%s: AUX_ERR encountered, dp_int_sta: " + "0x%02x\n", __func__, reg); writel(AUX_ERR, &base->dp_int_sta); return -1; } @@ -192,7 +207,7 @@ int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp) /* Check AUX CH error access status */ reg = readl(&base->dp_int_sta); if ((reg & AUX_STATUS_MASK) != 0) { - debug("AUX CH error happens: %d\n\n", + printk(BIOS_ERR, "AUX CH error happens: %d\n\n", reg & AUX_STATUS_MASK); return -1; } @@ -241,7 +256,7 @@ int s5p_dp_write_byte_to_dpcd(struct s5p_dp_device *dp, if (retval == 0) break; else - debug("Aux Transaction fail!\n"); + printk(BIOS_DEBUG, "Aux Transaction fail!\n"); } return retval; @@ -284,7 +299,7 @@ int s5p_dp_read_byte_from_dpcd(struct s5p_dp_device *dp, if (retval == 0) break; else - debug("Aux Transaction fail!\n"); + printk(BIOS_DEBUG, "Aux Transaction fail!\n"); } /* Read data buffer */ @@ -359,7 +374,7 @@ int s5p_dp_is_slave_video_stream_clock_on(struct s5p_dp_device *dp) reg = readl(&base->sys_ctl_2); if (reg & CHA_STA) { - debug("Input stream clk is changing\n"); + printk(BIOS_DEBUG, "Input stream clk is changing\n"); return -1; } @@ -417,11 +432,12 @@ void s5p_dp_enable_video_master(struct s5p_dp_device *dp) int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp) { u32 reg, i = 0; - u32 start; + struct stopwatch sw; struct exynos5_dp *base = dp->base; /* Wait for 4 VSYNC_DET interrupts */ - start = get_timer(0); + stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT); + do { reg = readl(&base->common_int_sta_1); if (reg & VSYNC_DET) { @@ -430,10 +446,10 @@ int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp) } if (i == 4) break; - } while (get_timer(start) <= STREAM_ON_TIMEOUT); + } while (!stopwatch_expired(&sw)); if (i != 4) { - debug("s5p_dp_is_video_stream_on timeout\n"); + printk(BIOS_DEBUG, "s5p_dp_is_video_stream_on timeout\n"); return -1; } diff --git a/src/cpu/samsung/exynos5-common/exynos-fb.c b/src/soc/samsung/exynos5250/fb.c similarity index 68% rename from src/cpu/samsung/exynos5-common/exynos-fb.c rename to src/soc/samsung/exynos5250/fb.c index 30d0767923..b4b927d4a1 100644 --- a/src/cpu/samsung/exynos5-common/exynos-fb.c +++ b/src/soc/samsung/exynos5250/fb.c @@ -1,45 +1,59 @@ /* - * LCD driver for Exynos + * This file is part of the coreboot project. * * Copyright 2013 Google Inc. * Copyright (C) 2012 Samsung Electronics * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +/* LCD driver for Exynos */ + #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include -#include "device/i2c.h" -#include "cpu/samsung/exynos5-common/i2c.h" -#include "cpu/samsung/exynos5250/dsim.h" -#include "cpu/samsung/exynos5250/fimd.h" - -#include "cpu/samsung/exynos5250/s5p-dp.h" -#include "s5p-dp-core.h" +/* + * Here is the rough outline of how we bring up the display: + * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD + * 2. Source determines video mode by reading DPCD receiver capability field + * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD + * 0000Dh). + * 3. Sink replies DPCD receiver capability field. + * 4. Source starts EDID read thru I2C-over-AUX. + * 5. Sink replies EDID thru I2C-over-AUX. + * 6. Source determines link configuration, such as MAX_LINK_RATE and + * MAX_LANE_COUNT. Source also determines which type of eDP Authentication + * method to use and writes DPCD link configuration field (DPCD 00100h to + * 0010Ah) including eDP configuration set (DPCD 0010Ah). + * 7. Source starts link training. Sink does clock recovery and equalization. + * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh). + * 9. Sink replies DPCD link status field. If main link is not stable, Source + * repeats Step 7. + * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video + * parameters and recovers stream clock. + * 11. Source sends video data. + */ /* To help debug any init errors here, define a list of possible errors */ enum { @@ -62,8 +76,8 @@ enum { ERR_NO_FDT_NODE, }; -/* ok, this is stupid, but we're going to leave the variables in here until we know it works. - * one cleanup task at a time. +/* ok, this is stupid, but we're going to leave the variables in here until we + * know it works. One cleanup task at a time. */ enum stage_t { STAGE_START = 0, @@ -83,37 +97,16 @@ int lcd_line_length; int lcd_color_fg; int lcd_color_bg; -void *lcd_base; /* Start of framebuffer memory */ void *lcd_console_address; /* Start of console buffer */ short console_col; short console_row; - -#ifdef CONFIG_EXYNOS_DISPLAYPORT -static struct s5p_dp_device dp_device; - -#endif - /* Bypass FIMD of DISP1_BLK */ static void fimd_bypass(void) { - struct exynos5_sysreg *sysreg = samsung_get_base_sysreg(); - - /*setbits_le32(&sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);*/ - sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1; -} - -/* Calculate the size of Framebuffer from the resolution */ -static u32 calc_fbsize(vidinfo_t *panel_info) -{ - /* They had PAGE_SIZE here instead of 4096. - * but that's a totally arbitrary number -- everything nowadays - * has lots of page sizes. - * So keep it obvious. - */ - return ALIGN((panel_info->vl_col * panel_info->vl_row * - ((1<vl_bpix) / 8)), 4096); + setbits_le32(&exynos_sysreg->disp1blk_cfg, FIMDBYPASS_DISP1); + exynos_sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1; } /* @@ -122,63 +115,58 @@ static u32 calc_fbsize(vidinfo_t *panel_info) * @param lcdbase pointer to the base address of framebuffer. * @pd pointer to the main panel_data structure */ -void fb_init(vidinfo_t *panel_info, void *lcdbase, struct exynos5_fimd_panel *pd) +void fb_init(unsigned long int fb_size, void *lcdbase, + struct exynos5_fimd_panel *pd) { unsigned int val; - u32 fbsize; - struct exynos5_fimd *fimd = - samsung_get_base_fimd(); - struct exynos5_disp_ctrl *disp_ctrl = - samsung_get_base_disp_ctrl(); - writel(pd->ivclk | pd->fixvclk, &disp_ctrl->vidcon1); + fb_size = ALIGN(fb_size, 4096); + + writel(pd->ivclk | pd->fixvclk, &exynos_disp_ctrl->vidcon1); val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET); - writel(val, &fimd->vidcon0); + writel(val, &exynos_fimd->vidcon0); val = (pd->vsync << VSYNC_PULSE_WIDTH_OFFSET) | (pd->lower_margin << V_FRONT_PORCH_OFFSET) | (pd->upper_margin << V_BACK_PORCH_OFFSET); - writel(val, &disp_ctrl->vidtcon0); + writel(val, &exynos_disp_ctrl->vidtcon0); val = (pd->hsync << HSYNC_PULSE_WIDTH_OFFSET) | (pd->right_margin << H_FRONT_PORCH_OFFSET) | (pd->left_margin << H_BACK_PORCH_OFFSET); - writel(val, &disp_ctrl->vidtcon1); + writel(val, &exynos_disp_ctrl->vidtcon1); val = ((pd->xres - 1) << HOZVAL_OFFSET) | ((pd->yres - 1) << LINEVAL_OFFSET); - writel(val, &disp_ctrl->vidtcon2); + writel(val, &exynos_disp_ctrl->vidtcon2); - writel((unsigned int)lcd_base, &fimd->vidw00add0b0); + writel((unsigned int)lcdbase, &exynos_fimd->vidw00add0b0); + writel((unsigned int)lcdbase + fb_size, &exynos_fimd->vidw00add1b0); - fbsize = calc_fbsize(panel_info); - writel((unsigned int)lcd_base + fbsize, &fimd->vidw00add1b0); - - writel(pd->xres * 2, &fimd->vidw00add2); + writel(pd->xres * 2, &exynos_fimd->vidw00add2); val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET); val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET); - writel(val, &fimd->vidosd0b); - writel(pd->xres * pd->yres, &fimd->vidosd0c); + writel(val, &exynos_fimd->vidosd0b); + writel(pd->xres * pd->yres, &exynos_fimd->vidosd0c); - setbits_le32(&fimd->shadowcon, CHANNEL0_EN); + setbits_le32(&exynos_fimd->shadowcon, CHANNEL0_EN); val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET; val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN; - writel(val, &fimd->wincon0); + writel(val, &exynos_fimd->wincon0); /* DPCLKCON_ENABLE */ - writel(1 << 1, &fimd->dpclkcon); + writel(1 << 1, &exynos_fimd->dpclkcon); } -void exynos_fimd_disable(void); +#ifdef UNUSED_CODE void exynos_fimd_disable(void) { - struct exynos5_fimd *fimd = samsung_get_base_fimd(); - - writel(0, &fimd->wincon0); - clrbits_le32(&fimd->shadowcon, CHANNEL0_EN); + writel(0, &exynos_fimd->wincon0); + clrbits_le32(&exynos_fimd->shadowcon, CHANNEL0_EN); } +#endif /* * Configure DP in slave mode and wait for video stream. @@ -191,9 +179,8 @@ static int s5p_dp_config_video(struct s5p_dp_device *dp, struct video_info *video_info) { int timeout = 0; - u32 start; struct exynos5_dp *base = dp->base; - + struct stopwatch sw; s5p_dp_config_video_slave_mode(dp, video_info); s5p_dp_set_video_color_format(dp, video_info->color_depth, @@ -202,20 +189,21 @@ static int s5p_dp_config_video(struct s5p_dp_device *dp, video_info->ycbcr_coeff); if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - debug("PLL is not locked yet.\n"); + printk(BIOS_DEBUG, "PLL is not locked yet.\n"); return -ERR_PLL_NOT_UNLOCKED; } - start = get_timer(0); + stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT); do { if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) { timeout++; break; } - } while (get_timer(start) <= STREAM_ON_TIMEOUT); + } while (!stopwatch_expired(&sw)); if (!timeout) { - debug("Video Clock Not ok\n"); + printk(BIOS_ERR, "Video Clock Not ok after %ldus.\n", + stopwatch_duration_usecs(&sw)); return -ERR_VIDEO_CLOCK_BAD; } @@ -235,7 +223,7 @@ static int s5p_dp_config_video(struct s5p_dp_device *dp, timeout = s5p_dp_is_video_stream_on(dp); if (timeout) { - debug("Video Stream Not on\n"); + printk(BIOS_DEBUG, "Video Stream Not on\n"); return -ERR_VIDEO_STREAM_BAD; } @@ -252,14 +240,13 @@ static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp) u8 data; if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data)) { - debug("DPCD read error\n"); + printk(BIOS_DEBUG, "DPCD read error\n"); return -ERR_DPCD_READ_ERROR1; } - if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, DPCD_ENHANCED_FRAME_EN | (data & DPCD_LANE_COUNT_SET_MASK))) { - debug("DPCD write error\n"); + printk(BIOS_DEBUG, "DPCD write error\n"); return -ERR_DPCD_WRITE_ERROR1; } @@ -280,13 +267,13 @@ static int s5p_dp_enable_scramble(struct s5p_dp_device *dp) if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET, &data)) { - debug("DPCD read error\n"); + printk(BIOS_DEBUG, "DPCD read error\n"); return -ERR_DPCD_READ_ERROR2; } if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET, - (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) { - debug("DPCD write error\n"); + (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) { + printk(BIOS_DEBUG, "DPCD write error\n"); return -ERR_DPCD_WRITE_ERROR2; } @@ -313,10 +300,10 @@ static int s5p_dp_init_dp(struct s5p_dp_device *dp) break; udelay(5000); - debug("LCD retry init, attempt=%d ret=%d\n", i, ret); + printk(BIOS_DEBUG, "LCD retry init, attempt=%d ret=%d\n", i, ret); } if (i == DP_INIT_TRIES) { - debug("LCD initialization failed, ret=%d\n", ret); + printk(BIOS_DEBUG, "LCD initialization failed, ret=%d\n", ret); return ret; } @@ -355,7 +342,7 @@ static int s5p_dp_set_lane_lane_pre_emphasis(struct s5p_dp_device *dp, writel(reg, &base->ln3_link_trn_ctl); break; default: - debug("%s: Invalid lane %d\n", __func__, lane); + printk(BIOS_DEBUG, "%s: Invalid lane %d\n", __func__, lane); return -ERR_INVALID_LANE; } return 0; @@ -408,23 +395,26 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, unsigned int max_lane, unsigned int max_rate) { + int pll_is_locked = 0; u32 data; - u32 start; int lane; + struct stopwatch sw; struct exynos5_dp *base = dp->base; /* Stop Video */ clrbits_le32(&base->video_ctl_1, VIDEO_EN); - start = get_timer(0); - while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - if (get_timer(start) > PLL_LOCK_TIMEOUT) { + stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT); + + while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) { + if (stopwatch_expired(&sw)) { /* Ignore this error, and try to continue */ printk(BIOS_ERR, "PLL is not locked yet.\n"); break; } } - + printk(BIOS_SPEW, "PLL is %slocked\n", + pll_is_locked == PLL_LOCKED ? "": "not "); /* Reset Macro */ setbits_le32(&base->dp_phy_test, MACRO_RST); @@ -436,8 +426,8 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, /* Set TX pre-emphasis to minimum */ for (lane = 0; lane < max_lane; lane++) if (s5p_dp_set_lane_lane_pre_emphasis(dp, - PRE_EMPHASIS_LEVEL_0, lane)) { - debug("Unable to set pre emphasis level\n"); + PRE_EMPHASIS_LEVEL_0, lane)) { + printk(BIOS_DEBUG, "Unable to set pre emphasis level\n"); return -ERR_PRE_EMPHASIS_LEVELS; } @@ -448,16 +438,19 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); + printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__, + dp->link_train.link_rate, dp->link_train.lane_count); + if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { - debug("Rx Max Link Rate is abnormal :%x !\n", + printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); /* Not Retrying */ return -ERR_LINK_RATE_ABNORMAL; } if (dp->link_train.lane_count == 0) { - debug("Rx Max Lane count is abnormal :%x !\n", + printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n", dp->link_train.lane_count); /* Not retrying */ return -ERR_MAX_LANE_COUNT_ABNORMAL; @@ -480,13 +473,14 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, /* Start HW link training */ writel(HW_TRAINING_EN, &base->dp_hw_link_training); - /* Wait unitl HW link training done */ + /* Wait until HW link training done */ s5p_dp_wait_hw_link_training_done(dp); /* Get hardware link training status */ data = readl(&base->dp_hw_link_training); + printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data); if (data != 0) { - debug(" H/W link training failure: 0x%x\n", data); + printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data); return -ERR_LINK_TRAINING_FAILURE; } @@ -497,6 +491,8 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, data = readl(&base->lane_count_set); dp->link_train.lane_count = data; + printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n", + dp->link_train.link_rate, data); return 0; } @@ -504,30 +500,25 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, /* * Initialize DP display */ -int dp_controller_init(struct s5p_dp_device *dp_device, unsigned *wait_ms) +int dp_controller_init(struct s5p_dp_device *dp_device) { int ret; struct s5p_dp_device *dp = dp_device; struct exynos5_dp *base; - //dp->base = (struct exynos5_dp *)addr; - /* yes. we're a snow. Yet somehow our config is from a development kit? - * This Must Change */ - //dp->video_info = &smdk5250_dp_config; - clock_init_dp_clock(); power_enable_dp_phy(); ret = s5p_dp_init_dp(dp); if (ret) { - debug("%s: Could not initialize dp\n", __func__); + printk(BIOS_ERR, "%s: Could not initialize dp\n", __func__); return ret; } ret = s5p_dp_hw_link_training(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { - debug("unable to do link train\n"); + printk(BIOS_ERR, "unable to do link train\n"); return ret; } /* Minimum delay after H/w Link training */ @@ -535,13 +526,13 @@ int dp_controller_init(struct s5p_dp_device *dp_device, unsigned *wait_ms) ret = s5p_dp_enable_scramble(dp); if (ret) { - debug("unable to set scramble mode\n"); + printk(BIOS_ERR, "unable to set scramble mode\n"); return ret; } ret = s5p_dp_enable_rx_to_enhanced_mode(dp); if (ret) { - debug("unable to set enhanced mode\n"); + printk(BIOS_ERR, "unable to set enhanced mode\n"); return ret; } @@ -556,19 +547,10 @@ int dp_controller_init(struct s5p_dp_device *dp_device, unsigned *wait_ms) s5p_dp_init_video(dp); ret = s5p_dp_config_video(dp, dp->video_info); if (ret) { - debug("unable to config video\n"); + printk(BIOS_ERR, "unable to config video\n"); return ret; } - /* - * This delay is T3 in the LCD timing spec (defined as >200ms). We set - * this down to 60ms since that's the approximate maximum amount of time - * it'll take a bridge to start outputting LVDS data. The delay of - * >200ms is just a conservative value to avoid turning on the backlight - * when there's random LCD data on the screen. Shaving 140ms off the - * boot is an acceptable trade-off. - */ - *wait_ms = 60; return 0; } @@ -578,17 +560,12 @@ int dp_controller_init(struct s5p_dp_device *dp_device, unsigned *wait_ms) * @param lcdbase Base address of LCD frame buffer * @return 0 if ok, -ve error code on error */ -int lcd_ctrl_init(vidinfo_t *panel_info, struct exynos5_fimd_panel *panel_data, void *lcdbase) +int lcd_ctrl_init(unsigned long int fb_size, + struct exynos5_fimd_panel *panel_data, void *lcdbase) { int ret = 0; - //vi->res = panel_info->vl_col; - //vi->yres = panel_info->vl_row; - fimd_bypass(); - fb_init(panel_info, lcdbase, panel_data); - - /* Enable flushing after LCD writes if requested */ - // forget it. lcd_set_flush_dcache(1); + fb_init(fb_size, lcdbase, panel_data); return ret; } diff --git a/src/soc/samsung/exynos5250/gpio.c b/src/soc/samsung/exynos5250/gpio.c new file mode 100644 index 0000000000..203aa03a42 --- /dev/null +++ b/src/soc/samsung/exynos5250/gpio.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define CON_MASK(x) (0xf << ((x) << 2)) +#define CON_SFR(x, v) ((v) << ((x) << 2)) + +#define DAT_MASK(x) (0x1 << (x)) +#define DAT_SET(x) (0x1 << (x)) + +#define PULL_MASK(x) (0x3 << ((x) << 1)) +#define PULL_MODE(x, v) ((v) << ((x) << 1)) + +#define DRV_MASK(x) (0x3 << ((x) << 1)) +#define DRV_SET(x, m) ((m) << ((x) << 1)) +#define RATE_MASK(x) (0x1 << (x + 16)) +#define RATE_SET(x) (0x1 << (x + 16)) + +struct gpio_info { + unsigned int reg_addr; /* Address of register for this part */ + unsigned int max_gpio; /* Maximum GPIO in this part */ +}; + +static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { + { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, + { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, + { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, + { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 }, + { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 }, + { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT }, +}; + +/* This macro gets gpio pin offset from 0..7 */ +#define GPIO_BIT(x) ((x) & 0x7) + +static struct gpio_bank *gpio_get_bank(unsigned int gpio) +{ + const struct gpio_info *data; + unsigned int upto; + int i; + + for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS; + i++, upto = data->max_gpio, data++) { + if (gpio < data->max_gpio) { + struct gpio_bank *bank; + + bank = (struct gpio_bank *)data->reg_addr; + bank += (gpio - upto) / GPIO_PER_BANK; + return bank; + } + } + + ASSERT(gpio < GPIO_MAX_PORT); /* ...which it will not be */ + return NULL; +} + +/* Common GPIO API - only available on Exynos5 */ +void gpio_cfg_pin(int gpio, int cfg) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->con); + value &= ~CON_MASK(GPIO_BIT(gpio)); + value |= CON_SFR(GPIO_BIT(gpio), cfg); + writel(value, &bank->con); +} + +static int gpio_get_cfg(int gpio) +{ + struct gpio_bank *bank = gpio_get_bank(gpio); + int shift = GPIO_BIT(gpio) << 2; + + return (readl(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift; +} + +void gpio_set_pull(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->pull); + value &= ~PULL_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_PULL_DOWN: + case GPIO_PULL_UP: + value |= PULL_MODE(GPIO_BIT(gpio), mode); + break; + default: + break; + } + + writel(value, &bank->pull); +} + +void gpio_set_drv(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~DRV_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_DRV_1X: + case GPIO_DRV_2X: + case GPIO_DRV_3X: + case GPIO_DRV_4X: + value |= DRV_SET(GPIO_BIT(gpio), mode); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +void gpio_set_rate(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~RATE_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_DRV_FAST: + case GPIO_DRV_SLOW: + value |= RATE_SET(GPIO_BIT(gpio)); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +int gpio_direction_input(unsigned gpio) +{ + gpio_cfg_pin(gpio, GPIO_INPUT); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + unsigned int val; + struct gpio_bank *bank = gpio_get_bank(gpio); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + gpio_cfg_pin(gpio, GPIO_OUTPUT); + + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->dat); + return !!(value & DAT_MASK(GPIO_BIT(gpio))); +} + +int gpio_set_value(unsigned gpio, int value) +{ + unsigned int val; + struct gpio_bank *bank = gpio_get_bank(gpio); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + return 0; +} + +/* + * Add a delay here to give the lines time to settle + * TODO(sjg): 1us does not always work, 2 is stable, so use 5 to be safe + * Come back to this and sort out what the datasheet says + */ +#define GPIO_DELAY_US 5 + +int gpio_read_mvl3(unsigned gpio) +{ + int high, low; + enum mvl3 value; + + if (gpio >= GPIO_MAX_PORT) + return -1; + + gpio_direction_input(gpio); + gpio_set_pull(gpio, GPIO_PULL_UP); + udelay(GPIO_DELAY_US); + high = gpio_get_value(gpio); + gpio_set_pull(gpio, GPIO_PULL_DOWN); + udelay(GPIO_DELAY_US); + low = gpio_get_value(gpio); + + if (high && low) /* external pullup */ + value = LOGIC_1; + else if (!high && !low) /* external pulldown */ + value = LOGIC_0; + else /* floating */ + value = LOGIC_Z; + + /* + * Check if line is externally pulled high and + * configure the internal pullup to match. For + * floating and pulldowns, the GPIO is already + * configured with an internal pulldown from the + * above test. + */ + if (value == LOGIC_1) + gpio_set_pull(gpio, GPIO_PULL_UP); + + return value; +} + +/* + * Display Exynos GPIO information + */ +void gpio_info(void) +{ + unsigned gpio; + + for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) { + int cfg = gpio_get_cfg(gpio); + + printk(BIOS_INFO, "GPIO_%-3d: ", gpio); + if (cfg == GPIO_INPUT) + printk(BIOS_INFO, "input"); + else if (cfg == GPIO_OUTPUT) + printk(BIOS_INFO, "output"); + else + printk(BIOS_INFO, "func %d", cfg); + + if (cfg == GPIO_INPUT || cfg == GPIO_OUTPUT) + printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio)); + printk(BIOS_INFO, "\n"); + } +} diff --git a/src/soc/samsung/exynos5250/i2c.c b/src/soc/samsung/exynos5250/i2c.c new file mode 100644 index 0000000000..f92182a77a --- /dev/null +++ b/src/soc/samsung/exynos5250/i2c.c @@ -0,0 +1,296 @@ +/* + * This file is part of the coreboot project. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct __attribute__ ((packed)) i2c_regs +{ + uint8_t con; + uint8_t _1[3]; + uint8_t stat; + uint8_t _2[3]; + uint8_t add; + uint8_t _3[3]; + uint8_t ds; + uint8_t _4[3]; + uint8_t lc; + uint8_t _5[3]; +}; + +struct s3c24x0_i2c_bus { + int bus_num; + struct i2c_regs *regs; + enum periph_id periph_id; +}; + +enum { + I2cConIntPending = 0x1 << 4, + I2cConIntEn = 0x1 << 5, + I2cConAckGen = 0x1 << 7 +}; + +enum { + I2cStatAck = 0x1 << 0, + I2cStatAddrZero = 0x1 << 1, + I2cStatAddrSlave = 0x1 << 2, + I2cStatArb = 0x1 << 3, + I2cStatEnable = 0x1 << 4, + I2cStatStartStop = 0x1 << 5, + I2cStatBusy = 0x1 << 5, + + I2cStatModeMask = 0x3 << 6, + I2cStatSlaveRecv = 0x0 << 6, + I2cStatSlaveXmit = 0x1 << 6, + I2cStatMasterRecv = 0x2 << 6, + I2cStatMasterXmit = 0x3 << 6 +}; + +static struct s3c24x0_i2c_bus i2c_busses[] = { + { + .bus_num = 0, + .regs = (void *)0x12c60000, + .periph_id = PERIPH_ID_I2C0, + }, + { + .bus_num = 1, + .regs = (void *)0x12c70000, + .periph_id = PERIPH_ID_I2C1, + }, + { + .bus_num = 2, + .regs = (void *)0x12c80000, + .periph_id = PERIPH_ID_I2C2, + }, + { + .bus_num = 3, + .regs = (void *)0x12c90000, + .periph_id = PERIPH_ID_I2C3, + }, + { + .bus_num = 4, + .regs = (void *)0x12ca0000, + .periph_id = PERIPH_ID_I2C4, + }, + { + .bus_num = 5, + .regs = (void *)0x12cb0000, + .periph_id = PERIPH_ID_I2C5, + }, + { + .bus_num = 6, + .regs = (void *)0x12cc0000, + .periph_id = PERIPH_ID_I2C6, + }, + { + .bus_num = 7, + .regs = (void *)0x12cd0000, + .periph_id = PERIPH_ID_I2C7, + }, +}; + + + + +static int i2c_int_pending(struct i2c_regs *regs) +{ + return readb(®s->con) & I2cConIntPending; +} + +static void i2c_clear_int(struct i2c_regs *regs) +{ + writeb(readb(®s->con) & ~I2cConIntPending, ®s->con); +} + +static void i2c_ack_enable(struct i2c_regs *regs) +{ + writeb(readb(®s->con) | I2cConAckGen, ®s->con); +} + +static void i2c_ack_disable(struct i2c_regs *regs) +{ + writeb(readb(®s->con) & ~I2cConAckGen, ®s->con); +} + +static int i2c_got_ack(struct i2c_regs *regs) +{ + return !(readb(®s->stat) & I2cStatAck); +} + +static int i2c_wait_for_idle(struct i2c_regs *regs) +{ + int timeout = 1000 * 100; // 1s. + while (timeout--) { + if (!(readb(®s->stat) & I2cStatBusy)) + return 0; + udelay(10); + } + printk(BIOS_ERR, "I2C timeout waiting for idle.\n"); + return 1; +} + +static int i2c_wait_for_int(struct i2c_regs *regs) +{ + int timeout = 1000 * 100; // 1s. + while (timeout--) { + if (i2c_int_pending(regs)) + return 0; + udelay(10); + } + printk(BIOS_ERR, "I2C timeout waiting for I2C interrupt.\n"); + return 1; +} + + + + +static int i2c_send_stop(struct i2c_regs *regs) +{ + uint8_t mode = readb(®s->stat) & (I2cStatModeMask); + writeb(mode | I2cStatEnable, ®s->stat); + i2c_clear_int(regs); + return i2c_wait_for_idle(regs); +} + +static int i2c_send_start(struct i2c_regs *regs, int read, int chip) +{ + writeb(chip << 1, ®s->ds); + uint8_t mode = read ? I2cStatMasterRecv : I2cStatMasterXmit; + writeb(mode | I2cStatStartStop | I2cStatEnable, ®s->stat); + i2c_clear_int(regs); + + if (i2c_wait_for_int(regs)) + return 1; + + if (!i2c_got_ack(regs)) { + // Nobody home, but they may just be asleep. + return 1; + } + + return 0; +} + +static int i2c_xmit_buf(struct i2c_regs *regs, uint8_t *data, int len) +{ + ASSERT(len); + + i2c_ack_enable(regs); + + int i; + for (i = 0; i < len; i++) { + writeb(data[i], ®s->ds); + + i2c_clear_int(regs); + if (i2c_wait_for_int(regs)) + return 1; + + if (!i2c_got_ack(regs)) { + printk(BIOS_INFO, "I2c nacked.\n"); + return 1; + } + } + + return 0; +} + +static int i2c_recv_buf(struct i2c_regs *regs, uint8_t *data, int len) +{ + ASSERT(len); + + i2c_ack_enable(regs); + + int i; + for (i = 0; i < len; i++) { + if (i == len - 1) + i2c_ack_disable(regs); + + i2c_clear_int(regs); + if (i2c_wait_for_int(regs)) + return 1; + + data[i] = readb(®s->ds); + } + + return 0; +} + +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count) +{ + struct s3c24x0_i2c_bus *i2c = &i2c_busses[bus]; + struct i2c_regs *regs = i2c->regs; + int res = 0; + + if (!regs || i2c_wait_for_idle(regs)) + return 1; + + writeb(I2cStatMasterXmit | I2cStatEnable, ®s->stat); + + int i; + for (i = 0; i < seg_count; i++) { + struct i2c_seg *seg = &segments[i]; + + res = i2c_send_start(regs, seg->read, seg->chip); + if (res) + break; + if (seg->read) + res = i2c_recv_buf(regs, seg->buf, seg->len); + else + res = i2c_xmit_buf(regs, seg->buf, seg->len); + if (res) + break; + } + + return i2c_send_stop(regs) || res; +} + +void i2c_init(unsigned bus, int speed, int slaveadd) +{ + struct s3c24x0_i2c_bus *i2c = &i2c_busses[bus]; + + unsigned long freq, pres = 16, div; + unsigned long val; + + freq = clock_get_periph_rate(i2c->periph_id); + // Calculate prescaler and divisor values. + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + + while ((freq / pres / (div + 1)) > speed) + div++; + + // Set prescaler, divisor according to freq, also set ACKGEN, IRQ. + val = (div & 0x0f) | 0xa0 | ((pres == 512) ? 0x40 : 0); + writel(val, &i2c->regs->con); + + // Init to SLAVE RECEIVE mode and clear I2CADDn. + writel(0, &i2c->regs->stat); + writel(slaveadd, &i2c->regs->add); + // program Master Transmit (and implicit STOP). + writel(I2cStatMasterXmit | I2cStatEnable, &i2c->regs->stat); +} diff --git a/src/soc/samsung/exynos5250/include/soc/alternate_cbfs.h b/src/soc/samsung/exynos5250/include/soc/alternate_cbfs.h new file mode 100644 index 0000000000..fe1af46d72 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/alternate_cbfs.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_ALTERNATE_CBFS_H +#define CPU_SAMSUNG_EXYNOS5250_ALTERNATE_CBFS_H + +/* These are pointers to function pointers. Double indirection! */ +static void * * const irom_sdmmc_read_blocks_ptr = (void * *)0x02020030; +static void * * const irom_msh_read_from_fifo_emmc_ptr = (void * *)0x02020044; +static void * * const irom_msh_end_boot_op_emmc_ptr = (void * *)0x02020048; +static void * * const irom_spi_sf_read_ptr = (void * *)0x02020058; +static void * * const irom_load_image_from_usb_ptr = (void * *)0x02020070; + +#define SECONDARY_BASE_BOOT_USB 0xfeed0002 +static u32 * const iram_secondary_base = (u32 *)0x02020018; + +/* Values pulled from U-Boot, I think the manual is wrong here (for SPI) */ +#define OM_STAT_SDMMC 0x4 +#define OM_STAT_EMMC 0x8 +#define OM_STAT_SPI 0x14 +#define OM_STAT_MASK 0x7f + +#endif diff --git a/src/cpu/samsung/exynos5250/clk.h b/src/soc/samsung/exynos5250/include/soc/clk.h similarity index 85% rename from src/cpu/samsung/exynos5250/clk.h rename to src/soc/samsung/exynos5250/include/soc/clk.h index dbddce0c6d..e52a87219d 100644 --- a/src/cpu/samsung/exynos5250/clk.h +++ b/src/soc/samsung/exynos5250/include/soc/clk.h @@ -1,11 +1,12 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Minkyu Kang + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,16 +15,59 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_CLK_H__ -#define __EXYNOS5_CLK_H__ +#ifndef CPU_SAMSUNG_EXYNOS5250_CLK_H +#define CPU_SAMSUNG_EXYNOS5250_CLK_H -#include -#include +#include +#include +#include +#include + +enum periph_id; + +#define APLL 0 +#define MPLL 1 +#define EPLL 2 +#define HPLL 3 +#define VPLL 4 +#define BPLL 5 + +enum pll_src_bit { + SRC_MPLL = 6, + SRC_EPLL, + SRC_VPLL, +}; + +/* * + * This structure is to store the src bit, div bit and prediv bit + * positions of the peripheral clocks of the src and div registers + */ +struct clk_bit_info { + s8 src_bit; /* offset in register to clock source field */ + s8 n_src_bits; /* number of bits in 'src_bit' field */ + s8 div_bit; + s8 prediv_bit; +}; + +unsigned long get_pll_clk(int pllreg); +unsigned long get_arm_clk(void); +unsigned long get_pwm_clk(void); +unsigned long get_uart_clk(int dev_index); +void set_mmc_clk(int dev_index, unsigned int div); + +/** + * get the clk frequency of the required peripherial + * + * @param peripherial Peripherial id + * + * @return frequency of the peripherial clk + */ +unsigned long clock_get_periph_rate(enum periph_id peripheral); + +#define MCT_HZ 24000000 /* * Set mshci controller instances clock drivder @@ -59,8 +103,6 @@ void clock_select_i2s_clk_source(void); */ int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq); -/* FIXME(dhendrix): below is stuff from arch/arm/include/asm/arch-exynos5/clock.h - (as opposed to the two clk.h files as they were named in u-boot... */ struct exynos5_clock { unsigned int apll_lock; /* base + 0 */ unsigned char res1[0xfc]; @@ -387,7 +429,7 @@ struct exynos5_clock { unsigned int clkout_cmu_r1x_div_stat; unsigned char res98[0x3608]; - unsigned int bpll_lock; /* base + 0x2000c */ + unsigned int bpll_lock; /* base + 0x20010 */ unsigned char res99[0xfc]; unsigned int bpll_con0; unsigned int bpll_con1; @@ -417,8 +459,11 @@ struct exynos5_clock { unsigned int pll_div2_sel; unsigned char res109b[0xf5e4]; }; +check_member(exynos5_clock, pll_div2_sel, 0x20a24); -struct exynos5_mct_regs { +static struct exynos5_clock * const exynos_clock = (void *)EXYNOS5_CLOCK_BASE; + +struct exynos5_mct { uint32_t mct_cfg; uint8_t reserved0[0xfc]; uint32_t g_cnt_l; @@ -475,6 +520,10 @@ struct exynos5_mct_regs { uint8_t reserved14[0x8]; uint32_t l1_wstat; }; +check_member(exynos5_mct, l1_wstat, 0x440); + +static struct exynos5_mct * const exynos_mct = + (void *)EXYNOS5_MULTI_CORE_TIMER_BASE; #define EXYNOS5_EPLLCON0_LOCKED_SHIFT 29 /* EPLL Locked bit position*/ #define EPLL_SRC_CLOCK 24000000 /*24 MHz Cristal Input */ @@ -537,47 +586,39 @@ void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor); */ int clock_set_rate(enum periph_id periph_id, unsigned int rate); -/** - * Decode a peripheral ID from a device node. - * - * Drivers should always use this function since the actual means of - * encoding this information may change in the future as fdt support for - * exynos evolves. - * - * @param blob FDT blob to read from - * @param node Node containing the information - */ -int clock_decode_periph_id(const void *blob, int node); - /* Clock gate unused IP */ void clock_gate(void); -enum ddr_mode; -enum mem_manuf; +/* These are the ratio's for configuring ARM clock */ +struct arm_clk_ratios { + unsigned int arm_freq_mhz; /* Frequency of ARM core in MHz */ -const char *clock_get_mem_type_name(enum ddr_mode mem_type); + unsigned int apll_mdiv; + unsigned int apll_pdiv; + unsigned int apll_sdiv; -const char *clock_get_mem_manuf_name(enum mem_manuf mem_manuf); + unsigned int arm2_ratio; + unsigned int apll_ratio; + unsigned int pclk_dbg_ratio; + unsigned int atb_ratio; + unsigned int periph_ratio; + unsigned int acp_ratio; + unsigned int cpud_ratio; + unsigned int arm_ratio; +}; + +/** + * Get the clock ratios for CPU configuration + * + * @return pointer to the clock ratios that we should use + */ +struct arm_clk_ratios *get_arm_clk_ratios(void); /* - * TODO(sjg@chromium.org): Remove this when we have more SPL space. - * At present we are using 14148 of 14336 bytes. If we change this function - * to be exported in SPL, we go over the edge. + * Initialize clock for the device */ -/** - * Get the required memory type and speed (Main U-Boot version). - * - * This should use the device tree. For now we cannot since this function is - * called before the FDT is available. - * - * @param mem_type Returns memory type - * @param frequency_mhz Returns memory speed in MHz - * @param arm_freq Returns ARM clock speed in MHz - * @param mem_manuf Return Memory Manufacturer name - * @return 0 if all ok (if not, this function currently does not return) - */ -int clock_get_mem_selection(enum ddr_mode *mem_type, - unsigned *frequency_mhz, unsigned *arm_freq, - enum mem_manuf *mem_manuf); +struct mem_timings; +void system_clock_init(struct mem_timings *mem, + struct arm_clk_ratios *arm_clk_ratio); #endif diff --git a/src/soc/samsung/exynos5250/include/soc/cpu.h b/src/soc/samsung/exynos5250/include/soc/cpu.h new file mode 100644 index 0000000000..c9c5832359 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/cpu.h @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_CPU_H +#define CPU_SAMSUNG_EXYNOS5250_CPU_H + +#include +#include + +/* Base address registers */ +#define EXYNOS5_GPIO_PART6_BASE 0x03860000 /* Z<6:0> */ +#define EXYNOS5_PRO_ID 0x10000000 +#define EXYNOS5_CLOCK_BASE 0x10010000 +#define EXYNOS5_POWER_BASE 0x10040000 +#define EXYNOS5_SYSREG_BASE 0x10050000 +#define EXYNOS5_TZPC1_DECPROT1SET 0x10110810 +#define EXYNOS5_MULTI_CORE_TIMER_BASE 0x101C0000 +#define EXYNOS5_WATCHDOG_BASE 0x101D0000 +#define EXYNOS5_ACE_SFR_BASE 0x10830000 +#define EXYNOS5_DMC_PHY0_BASE 0x10C00000 +#define EXYNOS5_DMC_PHY1_BASE 0x10C10000 +#define EXYNOS5_GPIO_PART4_BASE 0x10D10000 /* V00..V37 */ +#define EXYNOS5_GPIO_PART5_BASE 0x10D100C0 /* V40..V47 */ +#define EXYNOS5_DMC_CTRL_BASE 0x10DD0000 +#define EXYNOS5_GPIO_PART1_BASE 0x11400000 /* A00..Y67 */ +#define EXYNOS5_GPIO_PART2_BASE 0x11400c00 /* X00..X37 */ +#define EXYNOS5_USB_DRD_XHCI_BASE 0x12000000 +#define EXYNOS5_USB_DRD_PHY_BASE 0x12100000 +#define EXYNOS5_USB_DRD_DWC3_BASE 0x1200C100 +#define EXYNOS5_USB_HOST_EHCI_BASE 0x12110000 +#define EXYNOS5_USB_HOST_PHY_BASE 0x12130000 +#define EXYNOS5_MMC_BASE 0x12200000 +#define EXYNOS5_MSHC_BASE 0x12240000 +#define EXYNOS5_SROMC_BASE 0x12250000 +#define EXYNOS5_UART0_BASE 0x12C00000 +#define EXYNOS5_UART1_BASE 0x12C10000 +#define EXYNOS5_UART2_BASE 0x12C20000 +#define EXYNOS5_UART3_BASE 0x12C30000 +#define EXYNOS5_I2C_BASE 0x12C60000 +#define EXYNOS5_SPI0_BASE 0x12D20000 +#define EXYNOS5_SPI1_BASE 0x12D30000 +#define EXYNOS5_I2S_BASE 0x12D60000 +#define EXYNOS5_UART_ISP_BASE 0x13190000 +#define EXYNOS5_SPI_ISP_BASE 0x131A0000 +#define EXYNOS5_GPIO_PART3_BASE 0x13400000 /* E00..H17 */ +#define EXYNOS5_FIMD_BASE 0x14400000 +#define EXYNOS5_DISP1_CTRL_BASE 0x14420000 +#define EXYNOS5_MIPI_DSI1_BASE 0x14500000 +#define EXYNOS5_DP0_BASE 0x14510000 +#define EXYNOS5_DP1_BASE 0x145B0000 + +/* Marker values stored at the bottom of IRAM stack by SPL */ +#define EXYNOS5_SPL_MARKER 0xb004f1a9 /* hexspeak word: bootflag */ + +#define EXYNOS5_SPI_NUM_CONTROLLERS 5 +#define EXYNOS_I2C_MAX_CONTROLLERS 8 + +void exynos5250_config_l2_cache(void); + +extern struct tmu_info exynos5250_tmu_info; + +/* TODO clean up defines. */ +#define FB_SIZE_KB 4096 +#define RAM_BASE_KB ((uintptr_t)_dram/KiB) +#define RAM_SIZE_KB (CONFIG_DRAM_SIZE_MB << 10UL) + +static inline u32 get_fb_base_kb(void) +{ + return RAM_BASE_KB + RAM_SIZE_KB - FB_SIZE_KB; +} + +#endif /* _EXYNOS5250_CPU_H */ diff --git a/src/cpu/samsung/exynos5250/dmc.h b/src/soc/samsung/exynos5250/include/soc/dmc.h similarity index 87% rename from src/cpu/samsung/exynos5250/dmc.h rename to src/soc/samsung/exynos5250/include/soc/dmc.h index 0814c07afb..b51daa858e 100644 --- a/src/cpu/samsung/exynos5250/dmc.h +++ b/src/soc/samsung/exynos5250/include/soc/dmc.h @@ -1,7 +1,27 @@ -#ifndef __DMC_H__ -#define __DMC_H__ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_DMC_H +#define CPU_SAMSUNG_EXYNOS5250_DMC_H #ifndef __ASSEMBLER__ + +#include + struct exynos5_dmc { unsigned int concontrol; unsigned int memcontrol; @@ -95,6 +115,9 @@ struct exynos5_dmc { unsigned char res34[0xc]; unsigned int pmcnt3_ppc_a; }; +check_member(exynos5_dmc, pmcnt3_ppc_a, 0xe140); + +static struct exynos5_dmc * const exynos_dmc = (void *)EXYNOS5_DMC_CTRL_BASE; struct exynos5_phy_control { unsigned int phy_con0; @@ -114,7 +137,7 @@ struct exynos5_phy_control { unsigned int phy_con14; unsigned int phy_con15; unsigned int phy_con16; - unsigned char res4[4]; + unsigned char res4[4]; /* NOT a mistake. Yes, it doesn't make sense. */ unsigned int phy_con17; unsigned int phy_con18; unsigned int phy_con19; @@ -142,6 +165,12 @@ struct exynos5_phy_control { unsigned int phy_con41; unsigned int phy_con42; }; +check_member(exynos5_phy_control, phy_con42, 0xac); + +static struct exynos5_phy_control * const exynos_phy0_control = + (void *)EXYNOS5_DMC_PHY0_BASE; +static struct exynos5_phy_control * const exynos_phy1_control = + (void *)EXYNOS5_DMC_PHY1_BASE; enum ddr_mode { DDR_MODE_DDR2, diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-core.h b/src/soc/samsung/exynos5250/include/soc/dp-core.h similarity index 81% rename from src/cpu/samsung/exynos5-common/s5p-dp-core.h rename to src/soc/samsung/exynos5250/include/soc/dp-core.h index 67c1990cfd..73f4638599 100644 --- a/src/cpu/samsung/exynos5-common/s5p-dp-core.h +++ b/src/soc/samsung/exynos5250/include/soc/dp-core.h @@ -1,18 +1,27 @@ /* - * Header file for Samsung DP (Display Port) interface driver. + * This file is part of the coreboot project. * * Copyright 2013 Google Inc. - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Jingoo Han + * Copyright (C) 2012 Samsung Electronics * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _S5P_DP_CORE_H -#define _S5P_DP_CORE_H +/* Header file for Samsung DP (Display Port) interface driver. */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_DP_CORE_H +#define CPU_SAMSUNG_EXYNOS5250_DP_CORE_H #define STREAM_ON_TIMEOUT 100 #define PLL_LOCK_TIMEOUT 10 @@ -108,14 +117,6 @@ struct s5p_dp_device { struct link_train link_train; }; -/* this struct is used by mainboards to pass mode info to the driver */ -typedef struct vidinfo { - u16 vl_col; - u16 vl_row; - u8 vl_bpix; - u16 *cmap; -} vidinfo_t; - /* s5p_dp_reg.c */ /* @@ -250,7 +251,10 @@ void s5p_dp_config_video_slave_mode(struct s5p_dp_device *dp, void s5p_dp_wait_hw_link_training_done(struct s5p_dp_device *dp); /* startup and init */ -void fb_init(vidinfo_t *panel_info, void *lcdbase, struct exynos5_fimd_panel *pd); -int dp_controller_init(struct s5p_dp_device *dp_device, unsigned *wait_ms); -int lcd_ctrl_init(vidinfo_t *panel_info, struct exynos5_fimd_panel *panel_data, void *lcdbase); -#endif /* _S5P_DP_CORE_H */ +struct exynos5_fimd_panel; +void fb_init(unsigned long int fb_size, void *lcdbase, + struct exynos5_fimd_panel *pd); +int dp_controller_init(struct s5p_dp_device *dp_device); +int lcd_ctrl_init(unsigned long int fb_size, + struct exynos5_fimd_panel *panel_data, void *lcdbase); +#endif /* CPU_SAMSUNG_EXYNOS5250_DP_CORE_H */ diff --git a/src/cpu/samsung/exynos5250/s5p-dp.h b/src/soc/samsung/exynos5250/include/soc/dp.h similarity index 66% rename from src/cpu/samsung/exynos5250/s5p-dp.h rename to src/soc/samsung/exynos5250/include/soc/dp.h index 5322383e82..da204f45ac 100644 --- a/src/cpu/samsung/exynos5250/s5p-dp.h +++ b/src/soc/samsung/exynos5250/include/soc/dp.h @@ -1,11 +1,12 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Register map for Exynos5 DP + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,153 +15,161 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_DP_H__ -#define __EXYNOS5_DP_H__ +/* Register map for Exynos5 DP */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_DP_H +#define CPU_SAMSUNG_EXYNOS5250_DP_H + +#include /* DSIM register map */ struct exynos5_dp { - unsigned char res1[0x10]; - unsigned int dp_tx_version; - unsigned int dp_tx_sw_reset; - unsigned int func_en_1; - unsigned int func_en_2; - unsigned int video_ctl_1; - unsigned int video_ctl_2; - unsigned int video_ctl_3; - unsigned int video_ctl_4; - unsigned int clr_blue_cb; - unsigned int clr_green_y; - unsigned int clr_red_cr; - unsigned int video_ctl_8; - unsigned char res2[0x4]; - unsigned int video_ctl_10; - unsigned int total_line_l; - unsigned int total_line_h; - unsigned int active_line_l; - unsigned int active_line_h; - unsigned int v_f_porch; - unsigned int vsync; - unsigned int v_b_porch; - unsigned int total_pixel_l; - unsigned int total_pixel_h; - unsigned int active_pixel_l; - unsigned int active_pixel_h; - unsigned int h_f_porch_l; - unsigned int h_f_porch_h; - unsigned int hsync_l; - unsigned int hysnc_h; - unsigned int h_b_porch_l; - unsigned int h_b_porch_h; - unsigned int vid_status; - unsigned int total_line_sta_l; - unsigned int total_line_sta_h; - unsigned int active_line_sta_l; - unsigned int active_line_sta_h; - unsigned int v_f_porch_sta; - unsigned int vsync_sta; - unsigned int v_b_porch_sta; - unsigned int total_pixel_sta_l; - unsigned int total_pixel_sta_h; - unsigned int active_pixel_sta_l; - unsigned int active_pixel_sta_h; - unsigned int h_f_porch_sta_l; - unsigned int h_f_porch_sta_h; - unsigned int hsync_sta_l; - unsigned int hsync_sta_h; - unsigned int h_b_porch_sta_l; - unsigned int h_b_porch__sta_h; - unsigned char res3[0x288]; - unsigned int lane_map; - unsigned char res4[0x10]; - unsigned int analog_ctl_1; - unsigned int analog_ctl_2; - unsigned int analog_ctl_3; - unsigned int pll_filter_ctl_1; - unsigned int tx_amp_tuning_ctl; - unsigned char res5[0xc]; - unsigned int aux_hw_retry_ctl; - unsigned char res6[0x2c]; - unsigned int int_state; - unsigned int common_int_sta_1; - unsigned int common_int_sta_2; - unsigned int common_int_sta_3; - unsigned int common_int_sta_4; - unsigned char res7[0x8]; - unsigned int dp_int_sta; - unsigned int common_int_mask_1; - unsigned int common_int_mask_2; - unsigned int common_int_mask_3; - unsigned int common_int_mask_4; - unsigned char res8[0x08]; - unsigned int int_sta_mask; - unsigned int int_ctl; - unsigned char res9[0x200]; - unsigned int sys_ctl_1; - unsigned int sys_ctl_2; - unsigned int sys_ctl_3; - unsigned int sys_ctl_4; - unsigned int dp_vid_ctl; - unsigned char res10[0x2c]; - unsigned int pkt_send_ctl; - unsigned char res11[0x4]; - unsigned int dp_hdcp_ctl; - unsigned char res12[0x34]; - unsigned int link_bw_set; - unsigned int lane_count_set; - unsigned int dp_training_ptn_set; - unsigned int ln0_link_trn_ctl; - unsigned int ln1_link_trn_ctl; - unsigned int ln2_link_trn_ctl; - unsigned int ln3_link_trn_ctl; - unsigned int dp_dn_spread; - unsigned int dp_hw_link_training; - unsigned char res13[0x1c]; - unsigned int dp_debug_ctl; - unsigned int dp_hpd_deglitch_l; - unsigned int dp_hpd_deglitch_h; - unsigned char res14[0x14]; - unsigned int dp_link_debug_ctl; - unsigned char res15[0x1c]; - unsigned int m_vid_0; - unsigned int m_vid_1; - unsigned int m_vid_2; - unsigned int n_vid_0; - unsigned int n_vid_1; - unsigned int n_vid_2; - unsigned int m_vid_mon; - unsigned int dp_pll_ctl; - unsigned int dp_phy_pd; - unsigned int dp_phy_test; - unsigned char res16[0x8]; - unsigned int dp_video_fifo_thrd; - unsigned char res17[0x8]; - unsigned int dp_audio_margin; - unsigned int dp_dn_spread_ctl_1; - unsigned int dp_dn_spread_ctl_2; - unsigned char res18[0x18]; - unsigned int dp_m_cal_ctl; - unsigned int m_vid_gen_filter_th; - unsigned char res19[0x14]; - unsigned int m_aud_gen_filter_th; - unsigned int aux_ch_sta; - unsigned int aux_err_num; - unsigned int aux_ch_defer_dtl; - unsigned int aux_rx_comm; - unsigned int buf_data_ctl; - unsigned int aux_ch_ctl_1; - unsigned int aux_addr_7_0; - unsigned int aux_addr_15_8; - unsigned int aux_addr_19_16; - unsigned int aux_ch_ctl_2; - unsigned char res20[0x18]; - unsigned int buf_data_0; - unsigned char res21[0x3c]; - unsigned int soc_general_ctl; + u8 res1[0x10]; + u32 dp_tx_version; + u32 dp_tx_sw_reset; + u32 func_en_1; + u32 func_en_2; + u32 video_ctl_1; + u32 video_ctl_2; + u32 video_ctl_3; + u32 video_ctl_4; + u32 clr_blue_cb; + u32 clr_green_y; + u32 clr_red_cr; + u32 video_ctl_8; + u8 res2[0x4]; + u32 video_ctl_10; + u32 total_line_l; + u32 total_line_h; + u32 active_line_l; + u32 active_line_h; + u32 v_f_porch; + u32 vsync; + u32 v_b_porch; + u32 total_pixel_l; + u32 total_pixel_h; + u32 active_pixel_l; + u32 active_pixel_h; + u32 h_f_porch_l; + u32 h_f_porch_h; + u32 hsync_l; + u32 hysnc_h; + u32 h_b_porch_l; + u32 h_b_porch_h; + u32 vid_status; + u32 total_line_sta_l; + u32 total_line_sta_h; + u32 active_line_sta_l; + u32 active_line_sta_h; + u32 v_f_porch_sta; + u32 vsync_sta; + u32 v_b_porch_sta; + u32 total_pixel_sta_l; + u32 total_pixel_sta_h; + u32 active_pixel_sta_l; + u32 active_pixel_sta_h; + u32 h_f_porch_sta_l; + u32 h_f_porch_sta_h; + u32 hsync_sta_l; + u32 hsync_sta_h; + u32 h_b_porch_sta_l; + u32 h_b_porch__sta_h; + u8 res3[0x288]; + u32 lane_map; + u8 res4[0x10]; + u32 analog_ctl_1; + u32 analog_ctl_2; + u32 analog_ctl_3; + u32 pll_filter_ctl_1; + u32 tx_amp_tuning_ctl; + u8 res5[0xc]; + u32 aux_hw_retry_ctl; + u8 res6[0x2c]; + u32 int_state; + u32 common_int_sta_1; + u32 common_int_sta_2; + u32 common_int_sta_3; + u32 common_int_sta_4; + u8 res7[0x8]; + u32 dp_int_sta; + u32 common_int_mask_1; + u32 common_int_mask_2; + u32 common_int_mask_3; + u32 common_int_mask_4; + u8 res8[0x08]; + u32 int_sta_mask; + u32 int_ctl; + u8 res9[0x200]; + u32 sys_ctl_1; + u32 sys_ctl_2; + u32 sys_ctl_3; + u32 sys_ctl_4; + u32 dp_vid_ctl; + u8 res10[0x2c]; + u32 pkt_send_ctl; + u8 res11[0x4]; + u32 dp_hdcp_ctl; + u8 res12[0x34]; + u32 link_bw_set; + u32 lane_count_set; + u32 dp_training_ptn_set; + u32 ln0_link_trn_ctl; + u32 ln1_link_trn_ctl; + u32 ln2_link_trn_ctl; + u32 ln3_link_trn_ctl; + u32 dp_dn_spread; + u32 dp_hw_link_training; + u8 res13[0x1c]; + u32 dp_debug_ctl; + u32 dp_hpd_deglitch_l; + u32 dp_hpd_deglitch_h; + u8 res14[0x14]; + u32 dp_link_debug_ctl; + u8 res15[0x1c]; + u32 m_vid_0; + u32 m_vid_1; + u32 m_vid_2; + u32 n_vid_0; + u32 n_vid_1; + u32 n_vid_2; + u32 m_vid_mon; + u32 dp_pll_ctl; + u32 dp_phy_pd; + u32 dp_phy_test; + u8 res16[0x8]; + u32 dp_video_fifo_thrd; + u8 res17[0x8]; + u32 dp_audio_margin; + u32 dp_dn_spread_ctl_1; + u32 dp_dn_spread_ctl_2; + u8 res18[0x18]; + u32 dp_m_cal_ctl; + u32 m_vid_gen_filter_th; + u8 res19[0x14]; + u32 m_aud_gen_filter_th; + u32 aux_ch_sta; + u32 aux_err_num; + u32 aux_ch_defer_dtl; + u32 aux_rx_comm; + u32 buf_data_ctl; + u32 aux_ch_ctl_1; + u32 aux_addr_7_0; + u32 aux_addr_15_8; + u32 aux_addr_19_16; + u32 aux_ch_ctl_2; + u8 res20[0x18]; + u32 buf_data_0; + u8 res21[0x3c]; + u32 soc_general_ctl; }; +check_member(exynos5_dp, soc_general_ctl, 0x800); + +static struct exynos5_dp * const exynos_dp0 = (void *)EXYNOS5_DP0_BASE; +static struct exynos5_dp * const exynos_dp1 = (void *)EXYNOS5_DP1_BASE; + /* DP_TX_SW_RESET */ #define RESET_DP_TX (1 << 0) @@ -492,22 +501,4 @@ struct exynos5_dp { /* Allow DP Gating clock and set FIMD source to 267 Mhz for DP */ void clock_init_dp_clock(void); -/** - * Perform the next stage of the LCD init if it is time to do so. - * - * LCD init can be time-consuming because of the number of delays we need - * while waiting for the backlight power supply, etc. This function can - * be called at various times during U-Boot operation to advance the - * initialization of the LCD to the next stage if sufficient time has - * passed since the last stage. It keeps track of what stage it is up to - * and the time that it is permitted to move to the next stage. - * - * The final call should have can_block=1 to complete the init. - * - * @param blob fdt blob containing LCD information - * @param can_block 1 to wait until all init is complete, and then return - * 0 to return immediately, potentially doing nothing if it - * is not yet time for the next init. - */ -int exynos_lcd_check_next_stage(const void *blob, int can_block); #endif diff --git a/src/cpu/samsung/exynos5250/dsim.h b/src/soc/samsung/exynos5250/include/soc/dsim.h similarity index 83% rename from src/cpu/samsung/exynos5250/dsim.h rename to src/soc/samsung/exynos5250/include/soc/dsim.h index 38a4c988ea..b975a106a8 100644 --- a/src/cpu/samsung/exynos5250/dsim.h +++ b/src/soc/samsung/exynos5250/include/soc/dsim.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Register map for Exynos5 MIPI-DSIM + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,12 +14,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_DSIM_H__ -#define __EXYNOS5_DSIM_H__ +/* Register map for Exynos5 MIPI-DSIM */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_DSIM_H +#define CPU_SAMSUNG_EXYNOS5250_DSIM_H /* DSIM register map */ struct exynos5_dsim { @@ -47,6 +48,7 @@ struct exynos5_dsim { unsigned int phyacchr; unsigned int phyacchr1; }; +check_member(exynos5_dsim, phyacchr1, 0x54); #define ENABLE 1 #define DISABLE 0 diff --git a/src/cpu/samsung/exynos5250/fimd.h b/src/soc/samsung/exynos5250/include/soc/fimd.h similarity index 83% rename from src/cpu/samsung/exynos5250/fimd.h rename to src/soc/samsung/exynos5250/include/soc/fimd.h index a46ad5a033..0094a116eb 100644 --- a/src/cpu/samsung/exynos5250/fimd.h +++ b/src/soc/samsung/exynos5250/include/soc/fimd.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Register map for Exynos5 FIMD + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,12 +14,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_FIMD_H__ -#define __EXYNOS5_FIMD_H__ +/* Register map for Exynos5 FIMD */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_FIMD_H +#define CPU_SAMSUNG_EXYNOS5250_FIMD_H + +#include /* FIMD register map */ struct exynos5_fimd { @@ -58,6 +61,9 @@ struct exynos5_fimd { unsigned char res9[0x18]; unsigned int dpclkcon; }; +check_member(exynos5_fimd, dpclkcon, 0x27c); + +static struct exynos5_fimd * const exynos_fimd = (void *)EXYNOS5_FIMD_BASE; #define W0_SHADOW_PROTECT (0x1 << 10) #define COMPKEY_F 0xffffff @@ -104,6 +110,10 @@ struct exynos5_disp_ctrl { unsigned char res2[0x184]; unsigned int trigcon; }; +check_member(exynos5_disp_ctrl, trigcon, 0x1a4); + +static struct exynos5_disp_ctrl * const exynos_disp_ctrl = + (void *)EXYNOS5_DISP1_CTRL_BASE; #define VCLK_RISING_EDGE (1 << 7) #define VCLK_RUNNING (1 << 9) diff --git a/src/cpu/samsung/exynos5250/gpio.h b/src/soc/samsung/exynos5250/include/soc/gpio.h similarity index 50% rename from src/cpu/samsung/exynos5250/gpio.h rename to src/soc/samsung/exynos5250/include/soc/gpio.h index 12143849f5..398e7b02de 100644 --- a/src/cpu/samsung/exynos5250/gpio.h +++ b/src/soc/samsung/exynos5250/include/soc/gpio.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2010 Samsung Electronics - * Minkyu Kang + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (C) 2010 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,70 +14,100 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef EXYNOS5250_GPIO_H_ -#define EXYNOS5250_GPIO_H_ +#ifndef CPU_SAMSUNG_EXYNOS5250_GPIO_H +#define CPU_SAMSUNG_EXYNOS5250_GPIO_H -#include +#include -struct exynos5_gpio_part1 { - struct s5p_gpio_bank a0; - struct s5p_gpio_bank a1; - struct s5p_gpio_bank a2; - struct s5p_gpio_bank b0; - struct s5p_gpio_bank b1; - struct s5p_gpio_bank b2; - struct s5p_gpio_bank b3; - struct s5p_gpio_bank c0; - struct s5p_gpio_bank c1; - struct s5p_gpio_bank c2; - struct s5p_gpio_bank c3; - struct s5p_gpio_bank d0; - struct s5p_gpio_bank d1; - struct s5p_gpio_bank y0; - struct s5p_gpio_bank y1; - struct s5p_gpio_bank y2; - struct s5p_gpio_bank y3; - struct s5p_gpio_bank y4; - struct s5p_gpio_bank y5; - struct s5p_gpio_bank y6; +/* TODO: Align interface to src/include/gpio.h! */ + +struct gpio_bank { + unsigned int con; + unsigned int dat; + unsigned int pull; + unsigned int drv; + unsigned int pdn_con; + unsigned int pdn_pull; + unsigned char res1[8]; }; -struct exynos5_gpio_part2 { - struct s5p_gpio_bank x0; - struct s5p_gpio_bank x1; - struct s5p_gpio_bank x2; - struct s5p_gpio_bank x3; -}; +/* GPIO pins per bank */ +#define GPIO_PER_BANK 8 -struct exynos5_gpio_part3 { - struct s5p_gpio_bank e0; - struct s5p_gpio_bank e1; - struct s5p_gpio_bank f0; - struct s5p_gpio_bank f1; - struct s5p_gpio_bank g0; - struct s5p_gpio_bank g1; - struct s5p_gpio_bank g2; - struct s5p_gpio_bank h0; - struct s5p_gpio_bank h1; -}; +/* Pin configurations */ +#define GPIO_INPUT 0x0 +#define GPIO_OUTPUT 0x1 +#define GPIO_IRQ 0xf +#define GPIO_FUNC(x) (x) -struct exynos5_gpio_part4 { - struct s5p_gpio_bank v0; - struct s5p_gpio_bank v1; - struct s5p_gpio_bank v2; - struct s5p_gpio_bank v3; -}; +/* Pull mode */ +#define GPIO_PULL_NONE 0x0 +#define GPIO_PULL_DOWN 0x1 +#define GPIO_PULL_UP 0x3 -struct exynos5_gpio_part5 { - struct s5p_gpio_bank v4; -}; +/* Drive Strength level */ +#define GPIO_DRV_1X 0x0 +#define GPIO_DRV_3X 0x1 +#define GPIO_DRV_2X 0x2 +#define GPIO_DRV_4X 0x3 +#define GPIO_DRV_FAST 0x0 +#define GPIO_DRV_SLOW 0x1 -struct exynos5_gpio_part6 { - struct s5p_gpio_bank z; +enum exynos5_gpio_port { + EXYNOS5_GPA0 = EXYNOS5_GPIO_PART1_BASE + 0x0000, + EXYNOS5_GPA1 = EXYNOS5_GPIO_PART1_BASE + 0x0020, + EXYNOS5_GPA2 = EXYNOS5_GPIO_PART1_BASE + 0x0040, + + EXYNOS5_GPB0 = EXYNOS5_GPIO_PART1_BASE + 0x0060, + EXYNOS5_GPB1 = EXYNOS5_GPIO_PART1_BASE + 0x0080, + EXYNOS5_GPB2 = EXYNOS5_GPIO_PART1_BASE + 0x00a0, + EXYNOS5_GPB3 = EXYNOS5_GPIO_PART1_BASE + 0x00c0, + + EXYNOS5_GPC0 = EXYNOS5_GPIO_PART1_BASE + 0x00e0, + EXYNOS5_GPC1 = EXYNOS5_GPIO_PART1_BASE + 0x0100, + EXYNOS5_GPC2 = EXYNOS5_GPIO_PART1_BASE + 0x0120, + EXYNOS5_GPC3 = EXYNOS5_GPIO_PART1_BASE + 0x0140, + + EXYNOS5_GPD0 = EXYNOS5_GPIO_PART1_BASE + 0x0160, + EXYNOS5_GPD1 = EXYNOS5_GPIO_PART1_BASE + 0x0180, + + EXYNOS5_GPY0 = EXYNOS5_GPIO_PART1_BASE + 0x01a0, + EXYNOS5_GPY1 = EXYNOS5_GPIO_PART1_BASE + 0x01c0, + EXYNOS5_GPY2 = EXYNOS5_GPIO_PART1_BASE + 0x01e0, + EXYNOS5_GPY3 = EXYNOS5_GPIO_PART1_BASE + 0x0200, + EXYNOS5_GPY4 = EXYNOS5_GPIO_PART1_BASE + 0x0220, + EXYNOS5_GPY5 = EXYNOS5_GPIO_PART1_BASE + 0x0240, + EXYNOS5_GPY6 = EXYNOS5_GPIO_PART1_BASE + 0x0260, + + EXYNOS5_GPX0 = EXYNOS5_GPIO_PART2_BASE + 0x0000, + EXYNOS5_GPX1 = EXYNOS5_GPIO_PART2_BASE + 0x0020, + EXYNOS5_GPX2 = EXYNOS5_GPIO_PART2_BASE + 0x0040, + EXYNOS5_GPX3 = EXYNOS5_GPIO_PART2_BASE + 0x0060, + + EXYNOS5_GPE0 = EXYNOS5_GPIO_PART3_BASE + 0x0000, + EXYNOS5_GPE1 = EXYNOS5_GPIO_PART3_BASE + 0x0020, + + EXYNOS5_GPF0 = EXYNOS5_GPIO_PART3_BASE + 0x0040, + EXYNOS5_GPF1 = EXYNOS5_GPIO_PART3_BASE + 0x0060, + + EXYNOS5_GPG0 = EXYNOS5_GPIO_PART3_BASE + 0x0080, + EXYNOS5_GPG1 = EXYNOS5_GPIO_PART3_BASE + 0x00a0, + EXYNOS5_GPG2 = EXYNOS5_GPIO_PART3_BASE + 0x00c0, + + EXYNOS5_GPH0 = EXYNOS5_GPIO_PART3_BASE + 0x00e0, + EXYNOS5_GPH1 = EXYNOS5_GPIO_PART3_BASE + 0x0100, + + EXYNOS5_GPV0 = EXYNOS5_GPIO_PART4_BASE + 0x0000, + EXYNOS5_GPV1 = EXYNOS5_GPIO_PART4_BASE + 0x0020, + EXYNOS5_GPV2 = EXYNOS5_GPIO_PART4_BASE + 0x0060, + EXYNOS5_GPV3 = EXYNOS5_GPIO_PART4_BASE + 0x0080, + + EXYNOS5_GPV4 = EXYNOS5_GPIO_PART5_BASE + 0x0000, + + EXYNOS5_GPZ = EXYNOS5_GPIO_PART6_BASE + 0x0000, }; enum { @@ -417,8 +447,6 @@ enum exynos5_gpio_pin { GPIO_MAX_PORT }; -#define gpio_status gpio_info - /** * Set GPIO pin configuration. * @@ -451,34 +479,8 @@ void gpio_set_drv(int gpio, int mode); */ void gpio_set_rate(int gpio, int mode); -/* FIXME(dhendrix) use generic arch/gpio.h API instead */ -//int gpio_direction_input(unsigned gpio); -//int gpio_direction_output(unsigned gpio, int value); - -/** - * Decode a list of GPIOs into an integer. - * - * TODO(sjg@chromium.org): This could perhaps become a generic function? - * - * Each GPIO pin can be put into three states using external resistors: - * - pulled up - * - pulled down - * - not connected - * - * Read each GPIO in turn to produce an integer value. The first GPIO - * produces a number 1 * (0 to 2), the second produces 3 * (0 to 2), etc. - * In this way, each GPIO increases the number of possible states by a - * factor of 3. - * - * @param gpio_list List of GPIO numbers to decode - * @param count Number of GPIOs in list - * @return -1 if the value cannot be determined, or any GPIO number is - * invalid. Otherwise returns the calculated value - */ -int gpio_decode_number(unsigned gpio_list[], int count); - /* - * similar to gpio_decode_number, but reads only a single GPIO + * reads only a single GPIO * * @param gpio GPIO to read * @return -1 if the value cannot be determined. Otherwise returns @@ -488,4 +490,80 @@ int gpio_read_mvl3(unsigned gpio); void gpio_info(void); -#endif /* EXYNOS5250_GPIO_H_ */ +/* + * Generic GPIO API for U-Boot + * + * GPIOs are numbered from 0 to GPIO_COUNT-1 which value is defined + * by the SOC/architecture. + * + * Each GPIO can be an input or output. If an input then its value can + * be read as 0 or 1. If an output then its value can be set to 0 or 1. + * If you try to write an input then the value is undefined. If you try + * to read an output, barring something very unusual, you will get + * back the value of the output that you previously set. + * + * In some cases the operation may fail, for example if the GPIO number + * is out of range, or the GPIO is not available because its pin is + * being used by another function. In that case, functions may return + * an error value of -1. + */ + +/** + * Make a GPIO an input. + * + * @param gpio GPIO number + * @return 0 if ok, -1 on error + */ +int gpio_direction_input(unsigned gpio); + +/** + * Make a GPIO an output, and set its value. + * + * @param gpio GPIO number + * @param value GPIO value (0 for low or 1 for high) + * @return 0 if ok, -1 on error + */ +int gpio_direction_output(unsigned gpio, int value); + +/** + * Get a GPIO's value. This will work whether the GPIO is an input + * or an output. + * + * @param gpio GPIO number + * @return 0 if low, 1 if high, -1 on error + */ +int gpio_get_value(unsigned gpio); + +/** + * Set an output GPIO's value. The GPIO must already be an output or + * this function may have no effect. + * + * @param gpio GPIO number + * @param value GPIO value (0 for low or 1 for high) + * @return 0 if ok, -1 on error + */ +int gpio_set_value(unsigned gpio, int value); + +/* + * Many-value logic (3 states). This can be used for inputs whereby presence + * of external pull-up or pull-down resistors can be added to overcome internal + * pull-ups/pull-downs and force a single value. + * + * Thus, external pull resistors can force a 0 or 1 and if the value changes + * along with internal pull-up/down enable then the input is floating. + * + * Vpd | Vpu | MVL + * ----------------- + * 0 | 0 | 0 + * ----------------- + * 0 | 1 | Z <-- floating input will follow internal pull up/down + * ----------------- + * 1 | 1 | 1 + */ +enum mvl3 { + LOGIC_0, + LOGIC_1, + LOGIC_Z, /* high impedence / tri-stated / floating */ +}; + +#endif /* CPU_SAMSUNG_EXYNOS5250_GPIO_H */ diff --git a/src/soc/samsung/exynos5250/include/soc/i2c.h b/src/soc/samsung/exynos5250/include/soc/i2c.h new file mode 100644 index 0000000000..af4f2160ab --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/i2c.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_I2C_H +#define CPU_SAMSUNG_EXYNOS5250_I2C_H + +void i2c_init(unsigned bus, int speed, int slaveadd); + +#endif /* CPU_SAMSUNG_EXYNOS5250_I2C_H */ diff --git a/src/cpu/samsung/exynos5250/i2s-regs.h b/src/soc/samsung/exynos5250/include/soc/i2s-regs.h similarity index 88% rename from src/cpu/samsung/exynos5250/i2s-regs.h rename to src/soc/samsung/exynos5250/include/soc/i2s-regs.h index 19267ca88a..fabd914180 100644 --- a/src/cpu/samsung/exynos5250/i2s-regs.h +++ b/src/soc/samsung/exynos5250/include/soc/i2s-regs.h @@ -1,16 +1,11 @@ /* + * This file is part of the coreboot project. + * * Copyright (C) 2012 Samsung Electronics - * R. Chandrasekar * - * Taken from the kernel code - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,12 +14,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __I2S_REGS_H__ -#define __I2S_REGS_H__ +/* Taken from the kernel code */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_I2S_REGS_H +#define CPU_SAMSUNG_EXYNOS5250_I2S_REGS_H #define I2SCON 0x0 #define I2SMOD 0x4 @@ -143,4 +139,4 @@ #define I2SSIZE_TRNMSK (0xffff) #define I2SSIZE_SHIFT (16) -#endif /* __I2S_REGS_H__ */ +#endif /* CPU_SAMSUNG_EXYNOS5250_I2S_REGS_H */ diff --git a/src/soc/samsung/exynos5250/include/soc/memlayout.ld b/src/soc/samsung/exynos5250/include/soc/memlayout.ld new file mode 100644 index 0000000000..010bb7b64d --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/memlayout.ld @@ -0,0 +1,46 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +/* + * Note: The BootROM loads the 8K BL1 at [0x2020000:0x2022000), so the bootblock + * must be placed after that. After the handoff, the space can be reclaimed. + */ + +SECTIONS +{ + SRAM_START(0x2020000) + /* 13K hole, includes BL1 */ + BOOTBLOCK(0x2023400, 32K) + /* 19K hole */ + ROMSTAGE(0x2030000, 128K) + /* 32K hole */ + TTB(0x2058000, 16K) + PRERAM_CBFS_CACHE(0x205C000, 96K) + STACK(0x2074000, 16K) + SRAM_END(0x2078000) + + DRAM_START(0x40000000) + RAMSTAGE(0x40000000, 128K) + POSTRAM_CBFS_CACHE(0x41000000, 8M) + DMA_COHERENT(0x77300000, 1M) +} diff --git a/src/cpu/samsung/exynos5250/periph.h b/src/soc/samsung/exynos5250/include/soc/periph.h similarity index 76% rename from src/cpu/samsung/exynos5250/periph.h rename to src/soc/samsung/exynos5250/include/soc/periph.h index e14829e994..7d8bf623f6 100644 --- a/src/cpu/samsung/exynos5250/periph.h +++ b/src/soc/samsung/exynos5250/include/soc/periph.h @@ -1,10 +1,11 @@ /* - * (C) Copyright 2012 The Chromium Authors + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,13 +14,11 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS_PERIPH_H -#define __EXYNOS_PERIPH_H +#ifndef CPU_SAMSUNG_EXYNOS5250_PERIPH_H +#define CPU_SAMSUNG_EXYNOS5250_PERIPH_H /* * Peripherals requiring clock/pinmux configuration. List will @@ -38,7 +37,6 @@ enum periph_id { PERIPH_ID_SDMMC2, PERIPH_ID_SDMMC3, - /* TODO: make sequential again when FDT doesn't hardcode. */ PERIPH_ID_SROMC = 9, PERIPH_ID_SPI0, PERIPH_ID_SPI1, diff --git a/src/soc/samsung/exynos5250/include/soc/pinmux.h b/src/soc/samsung/exynos5250/include/soc/pinmux.h new file mode 100644 index 0000000000..227a2807e3 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/pinmux.h @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_PINMUX_H +#define CPU_SAMSUNG_EXYNOS5250_PINMUX_H + +void exynos_pinmux_uart0(void); +void exynos_pinmux_uart1(void); +void exynos_pinmux_uart2(void); +void exynos_pinmux_uart3(void); + +void exynos_pinmux_sdmmc0(void); +void exynos_pinmux_sdmmc1(void); +void exynos_pinmux_sdmmc2(void); +void exynos_pinmux_sdmmc3(void); + +void exynos_pinmux_sromc(int bank, int sixteen_bit); + +void exynos_pinmux_spi0(void); +void exynos_pinmux_spi1(void); +void exynos_pinmux_spi2(void); +void exynos_pinmux_spi3(void); +void exynos_pinmux_spi4(void); + +void exynos_pinmux_backlight(void); +void exynos_pinmux_lcd(void); + +void exynos_pinmux_i2c0(void); +void exynos_pinmux_i2c1(void); +void exynos_pinmux_i2c2(void); +void exynos_pinmux_i2c3(void); +void exynos_pinmux_i2c4(void); +void exynos_pinmux_i2c5(void); +void exynos_pinmux_i2c6(void); +void exynos_pinmux_i2c7(void); + +void exynos_pinmux_dphpd(void); + +void exynos_pinmux_i2s0(void); +void exynos_pinmux_i2s1(void); + +#endif diff --git a/src/cpu/samsung/exynos5250/power.h b/src/soc/samsung/exynos5250/include/soc/power.h similarity index 66% rename from src/cpu/samsung/exynos5250/power.h rename to src/soc/samsung/exynos5250/include/soc/power.h index 59a02574db..7728e1d05d 100644 --- a/src/cpu/samsung/exynos5250/power.h +++ b/src/soc/samsung/exynos5250/include/soc/power.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Register map for Exynos5 PMU + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,17 +14,23 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_POWER_H__ -#define __EXYNOS5_POWER_H__ +/* Register map for Exynos5 PMU */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_POWER_H +#define CPU_SAMSUNG_EXYNOS5250_POWER_H + +#include + +/* Enable HW thermal trip with PS_HOLD_CONTROL register ENABLE_HW_TRIP bit */ +void power_enable_hw_thermal_trip(void); #define MIPI_PHY1_CONTROL_ENABLE (1 << 0) #define MIPI_PHY1_CONTROL_M_RESETN (1 << 2) -#define POWER_USB_HOST_PHY_CTRL_EN (1 << 0) +#define POWER_USB_PHY_CTRL_EN (1 << 0) #define POWER_PS_HOLD_CONTROL_DATA_HIGH (1 << 8) #define POWER_ENABLE_HW_TRIP (1UL << 31) @@ -38,9 +44,11 @@ /* Power Management Unit register map */ struct exynos5_power { /* Add registers as and when required */ - uint8_t reserved1[0x0400]; + uint32_t om_stat; /* 0x0000 */ + uint8_t reserved1[0x03fc]; uint32_t sw_reset; /* 0x0400 */ - uint8_t reserved2[0x0304]; + uint8_t reserved2[0x0300]; + uint32_t usb_drd_phy_ctrl; /* 0x0704 */ uint32_t usb_host_phy_ctrl; /* 0x0708 */ uint8_t reserved3[0x8]; uint32_t mipi_phy1_control; /* 0x0714 */ @@ -50,10 +58,15 @@ struct exynos5_power { uint32_t inform0; /* 0x0800 */ uint32_t inform1; /* 0x0804 */ uint8_t reserved6[0x1f8]; - uint32_t pmu_debug; /* 0x0A00*/ - uint8_t reserved7[0x2908]; + uint32_t pmu_debug; /* 0x0a00 */ + uint8_t reserved7[0x2724]; + uint32_t padret_uart_opt; /* 0x3128 */ + uint8_t reserved8[0x1e0]; uint32_t ps_hold_ctrl; /* 0x330c */ } __attribute__ ((__packed__)); +check_member(exynos5_power, ps_hold_ctrl, 0x330c); + +static struct exynos5_power * const exynos_power = (void*)EXYNOS5_POWER_BASE; /** * Perform a software reset. @@ -68,12 +81,6 @@ void power_shutdown(void); /* Enable DPTX PHY */ void power_enable_dp_phy(void); -void power_enable_usb_phy(void); -void power_disable_usb_phy(void); - -/* Enable HW thermal trip with PS_HOLD_CONTROL register ENABLE_HW_TRIP bit */ -void power_enable_hw_thermal_trip(void); - /* Initialize the pmic voltages to power up the system */ int power_init(void); @@ -86,4 +93,8 @@ void power_exit_wakeup(void); /* pmu debug is used for xclkout, enable xclkout with source as XXTI */ void power_enable_xclkout(void); +/* Release UART retention on resume (only for debugging, may conflict with + * kernel). */ +void power_release_uart_retention(void); + #endif diff --git a/src/cpu/samsung/exynos5250/setup.h b/src/soc/samsung/exynos5250/include/soc/setup.h similarity index 96% rename from src/cpu/samsung/exynos5250/setup.h rename to src/soc/samsung/exynos5250/include/soc/setup.h index 4f7f58cbeb..a93a56946a 100644 --- a/src/cpu/samsung/exynos5250/setup.h +++ b/src/soc/samsung/exynos5250/include/soc/setup.h @@ -1,15 +1,11 @@ /* - * Machine Specific Values for SMDK5250 board based on Exynos5 + * This file is part of the coreboot project. * * Copyright (C) 2012 Samsung Electronics * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,12 +14,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _SMDK5250_SETUP_H -#define _SMDK5250_SETUP_H +/* Machine Specific Values for SMDK5250 board based on Exynos5 */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_SETUP_H +#define CPU_SAMSUNG_EXYNOS5250_SETUP_H struct exynos5_dmc; enum ddr_mode; @@ -41,6 +38,8 @@ struct exynos5_phy_control; #define TZPC8_BASE 0x10180000 #define TZPC9_BASE 0x10190000 +#define APLL_FOUT (1 << 0) + /* APLL_CON1 */ #define APLL_CON1_VAL (0x00203800) @@ -627,8 +626,8 @@ struct exynos5_phy_control; */ #define DECPROTXSET 0xFF -#define LPDDR3PHY_CTRL_PHY_RESET (1 << 0) -#define LPDDR3PHY_CTRL_PHY_RESET_OFF (0 << 0) +#define LPDDR3PHY_CTRL_PHY_RESET_DISABLE (1 << 0) +#define LPDDR3PHY_CTRL_PHY_RESET_ENABLE (0 << 0 ) #define PHY_CON0_RESET_VAL 0x17020a40 #define P0_CMD_EN (1 << 14) @@ -687,8 +686,6 @@ enum { }; /* Functions common between LPDDR2 and DDR3 */ -/* FIXME(dhendrix): conflicts with arch system.h version of sdelay()... */ -//void sdelay(unsigned long); /* CPU info initialization code */ void cpu_info_init(void); @@ -702,11 +699,12 @@ void mem_ctrl_init(void); * which the DMC uses to decide how to split a memory * chunk into smaller chunks to support concurrent * accesses; may vary across boards. + * @param mem_reset Reset memory during initialization. * @return 0 if ok, SETUP_ERR_... if there is a problem */ -int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size); +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, + int mem_reset); -void tzpc_init(void); /* * Configure ZQ I/O interface * diff --git a/src/cpu/samsung/exynos5-common/spi.h b/src/soc/samsung/exynos5250/include/soc/spi.h similarity index 84% rename from src/cpu/samsung/exynos5-common/spi.h rename to src/soc/samsung/exynos5250/include/soc/spi.h index 156817c35b..4301d42e24 100644 --- a/src/cpu/samsung/exynos5-common/spi.h +++ b/src/soc/samsung/exynos5250/include/soc/spi.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 SAMSUNG Electronics - * Padmavathi Venna + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,15 +14,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __ASM_ARCH_EXYNOS_COMMON_SPI_H_ -#define __ASM_ARCH_EXYNOS_COMMON_SPI_H_ +#ifndef CPU_SAMSUNG_EXYNOS5250_SPI_H +#define CPU_SAMSUNG_EXYNOS5250_SPI_H -#ifndef __ASSEMBLER__ - -// This driver serves as a CBFS media source. +/* This driver serves as a CBFS media source. */ #include /* SPI peripheral register map; padded to 64KB */ @@ -41,6 +39,7 @@ struct exynos_spi { unsigned int fb_clk; /* 0x2c */ unsigned char padding[0xffd0]; }; +check_member(exynos_spi, fb_clk, 0x2c); #define EXYNOS_SPI_MAX_FREQ 50000000 @@ -93,10 +92,8 @@ int exynos_spi_open(struct exynos_spi *regs); int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off); int exynos_spi_close(struct exynos_spi *regs); -/* Serve as CBFS Media */ +/* Serve as CBFS media source */ int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, void *buffer_address, size_t buffer_size); - -#endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5250/sysreg.h b/src/soc/samsung/exynos5250/include/soc/sysreg.h similarity index 55% rename from src/cpu/samsung/exynos5250/sysreg.h rename to src/soc/samsung/exynos5250/include/soc/sysreg.h index f081495ea1..a869f3dd5f 100644 --- a/src/cpu/samsung/exynos5250/sysreg.h +++ b/src/soc/samsung/exynos5250/include/soc/sysreg.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 Samsung Electronics - * Register map for Exynos5 sysreg + * This file is part of the coreboot project. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,12 +14,15 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __EXYNOS5_SYSREG_H__ -#define __EXYNOS5_SYSREG_H__ +/* Register map for Exynos5 sysreg */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_SYSREG_H +#define CPU_SAMSUNG_EXYNOS5250_SYSREG_H + +#include /* sysreg map */ struct exynos5_sysreg { @@ -29,6 +32,10 @@ struct exynos5_sysreg { unsigned char res2[0x18]; unsigned int usb20_phy_cfg; }; +check_member(exynos5_sysreg, usb20_phy_cfg, 0x230); + +static struct exynos5_sysreg * const exynos_sysreg = + (void *)EXYNOS5_SYSREG_BASE; #define FIMDBYPASS_DISP1 (1 << 15) #define USB20_PHY_CFG_EN (1 << 0) diff --git a/src/soc/samsung/exynos5250/include/soc/tmu.h b/src/soc/samsung/exynos5250/include/soc/tmu.h new file mode 100644 index 0000000000..6ac21c8e63 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/tmu.h @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* EXYNOS - Thermal Management Unit */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_TMU_H +#define CPU_SAMSUNG_EXYNOS5250_TMU_H + +struct tmu_reg { + unsigned triminfo; + unsigned rsvd1; + unsigned rsvd2; + unsigned rsvd3; + unsigned rsvd4; + unsigned triminfo_control; + unsigned rsvd5; + unsigned rsvd6; + unsigned tmu_control; + unsigned rsvd7; + unsigned tmu_status; + unsigned sampling_internal; + unsigned counter_value0; + unsigned counter_value1; + unsigned rsvd8; + unsigned rsvd9; + unsigned current_temp; + unsigned rsvd10; + unsigned rsvd11; + unsigned rsvd12; + unsigned threshold_temp_rise; + unsigned threshold_temp_fall; + unsigned rsvd13; + unsigned rsvd14; + unsigned past_temp3_0; + unsigned past_temp7_4; + unsigned past_temp11_8; + unsigned past_temp15_12; + unsigned inten; + unsigned intstat; + unsigned intclear; + unsigned rsvd15; + unsigned emul_con; +}; +check_member(tmu_reg, emul_con, 0x80); + +enum tmu_status_t { + TMU_STATUS_INIT = 0, + TMU_STATUS_NORMAL, + TMU_STATUS_WARNING, + TMU_STATUS_TRIPPED, +}; + +/* Tmeperature threshold values for various thermal events */ +struct temperature_params { + /* minimum value in temperature code range */ + unsigned int min_val; + /* maximum value in temperature code range */ + unsigned int max_val; + /* temperature threshold to start warning */ + unsigned int start_warning; + /* temperature threshold CPU tripping */ + unsigned int start_tripping; + /* temperature threshold for HW tripping */ + unsigned int hardware_tripping; +}; + +/* Pre-defined values and thresholds for calibration of current temperature */ +struct tmu_data { + /* pre-defined temperature thresholds */ + struct temperature_params ts; + /* pre-defined efuse range minimum value */ + unsigned int efuse_min_value; + /* pre-defined efuse value for temperature calibration */ + unsigned int efuse_value; + /* pre-defined efuse range maximum value */ + unsigned int efuse_max_value; + /* current temperature sensing slope */ + unsigned int slope; +}; + +/* TMU device specific details and status */ +struct tmu_info { + /* base Address for the TMU */ + unsigned tmu_base; + /* mux Address for the TMU */ + int tmu_mux; + /* pre-defined values for calibration and thresholds */ + struct tmu_data data; + /* value required for triminfo_25 calibration */ + unsigned int te1; + /* value required for triminfo_85 calibration */ + unsigned int te2; + /* TMU DC value for threshold calculation */ + int dc_value; + /* enum value indicating status of the TMU */ + int tmu_state; +}; + +extern struct tmu_info *tmu_info; + +/* + * Monitors status of the TMU device and exynos temperature + * + * @info pointer to TMU info struct + * @temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + * and -1 on error + */ +enum tmu_status_t tmu_monitor(struct tmu_info *info, int *temp); + +/* + * Initialize TMU device + * + * @info pointer to TMU info struct + * @return int value, 0 for success + */ +int tmu_init(struct tmu_info *info); + +#endif /* CPU_SAMSUNG_EXYNOS5250_TMU_H */ diff --git a/src/soc/samsung/exynos5250/include/soc/trustzone.h b/src/soc/samsung/exynos5250/include/soc/trustzone.h new file mode 100644 index 0000000000..4cbb1aa1a5 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/trustzone.h @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_TRUSTZONE_H +#define CPU_SAMSUNG_EXYNOS5250_TRUSTZONE_H + +#include + +/* Distance between each Trust Zone PC register set */ +#define TZPC_BASE_OFFSET 0x10000 +/* TZPC : Register Offsets */ +#define TZPC0_BASE 0x10100000 +#define TZPC1_BASE 0x10110000 +#define TZPC2_BASE 0x10120000 +#define TZPC3_BASE 0x10130000 +#define TZPC4_BASE 0x10140000 +#define TZPC5_BASE 0x10150000 +#define TZPC6_BASE 0x10160000 +#define TZPC7_BASE 0x10170000 +#define TZPC8_BASE 0x10180000 +#define TZPC9_BASE 0x10190000 +#define TZPC10_BASE 0x100E0000 +#define TZPC11_BASE 0x100F0000 + +/* + * TZPC Register Value : + * R0SIZE: 0x0 : Size of secured ram + */ +#define R0SIZE 0x0 + +/* + * TZPC Decode Protection Register Value : + * DECPROTXSET: 0xFF : Set Decode region to non-secure + */ +#define DECPROTXSET 0xFF + +struct exynos_tzpc { + u32 r0size; + u8 res1[0x7FC]; + u32 decprot0stat; + u32 decprot0set; + u32 decprot0clr; + u32 decprot1stat; + u32 decprot1set; + u32 decprot1clr; + u32 decprot2stat; + u32 decprot2set; + u32 decprot2clr; + u32 decprot3stat; + u32 decprot3set; + u32 decprot3clr; + u8 res2[0x7B0]; + u32 periphid0; + u32 periphid1; + u32 periphid2; + u32 periphid3; + u32 pcellid0; + u32 pcellid1; + u32 pcellid2; + u32 pcellid3; +}; +check_member(exynos_tzpc, pcellid3, 0xffc); + +void trustzone_init(void); + +#endif /* CPU_SAMSUNG_EXYNOS5250_TRUSTZONE_H */ diff --git a/src/soc/samsung/exynos5250/include/soc/uart.h b/src/soc/samsung/exynos5250/include/soc/uart.h new file mode 100644 index 0000000000..e2514d7b6d --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/uart.h @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_UART_H +#define CPU_SAMSUNG_EXYNOS5250_UART_H + +struct s5p_uart { + unsigned int ulcon; + unsigned int ucon; + unsigned int ufcon; + unsigned int umcon; + unsigned int utrstat; + unsigned int uerstat; + unsigned int ufstat; + unsigned int umstat; + unsigned char utxh; + unsigned char res1[3]; + unsigned char urxh; + unsigned char res2[3]; + unsigned int ubrdiv; + unsigned char res3[0xffd0]; +}; +check_member(s5p_uart, ubrdiv, 0x28); + +#endif diff --git a/src/soc/samsung/exynos5250/include/soc/usb.h b/src/soc/samsung/exynos5250/include/soc/usb.h new file mode 100644 index 0000000000..efac46f181 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/usb.h @@ -0,0 +1,140 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_USB_H +#define CPU_SAMSUNG_EXYNOS5250_USB_H + +#include + +#define CLK_24MHZ 5 + +#define HOST_CTRL0_PHYSWRSTALL (1 << 31) +#define HOST_CTRL0_COMMONON_N (1 << 9) +#define HOST_CTRL0_SIDDQ (1 << 6) +#define HOST_CTRL0_FORCESLEEP (1 << 5) +#define HOST_CTRL0_FORCESUSPEND (1 << 4) +#define HOST_CTRL0_WORDINTERFACE (1 << 3) +#define HOST_CTRL0_UTMISWRST (1 << 2) +#define HOST_CTRL0_LINKSWRST (1 << 1) +#define HOST_CTRL0_PHYSWRST (1 << 0) + +#define HOST_CTRL0_FSEL_MASK (7 << 16) + +#define EHCICTRL_ENAINCRXALIGN (1 << 29) +#define EHCICTRL_ENAINCR4 (1 << 28) +#define EHCICTRL_ENAINCR8 (1 << 27) +#define EHCICTRL_ENAINCR16 (1 << 26) + +/* Register map for PHY control */ +struct exynos5_usb_host_phy { + uint32_t usbphyctrl0; + uint32_t usbphytune0; + uint8_t reserved1[8]; + uint32_t hsicphyctrl1; + uint32_t hsicphytune1; + uint8_t reserved2[8]; + uint32_t hsicphyctrl2; + uint32_t hsicphytune2; + uint8_t reserved3[8]; + uint32_t ehcictrl; + uint32_t ohcictrl; + uint32_t usbotgsys; + uint8_t reserved4[4]; + uint32_t usbotgtune; +}; +check_member(exynos5_usb_host_phy, usbotgtune, 0x40); + +static struct exynos5_usb_host_phy * const exynos_usb_host_phy = + (void *)EXYNOS5_USB_HOST_PHY_BASE; + +struct exynos5_usb_drd_phy { + uint8_t reserved1[4]; + uint32_t linksystem; + uint32_t utmi; + uint32_t pipe; + uint32_t clkrst; + uint32_t reg0; + uint32_t reg1; + uint32_t param0; + uint32_t param1; + uint32_t term; + uint32_t test; + uint32_t adp; + uint32_t utmiclksel; + uint32_t resume; + uint8_t reserved2[8]; + uint32_t linkhcbelt; + uint32_t linkport; +}; +check_member(exynos5_usb_drd_phy, linkport, 0x44); + +static struct exynos5_usb_drd_phy * const exynos_usb_drd_phy = + (void *)EXYNOS5_USB_DRD_PHY_BASE; + +struct exynos5_usb_drd_dwc3 { + uint32_t sbuscfg0; + uint32_t sbuscfg1; + uint32_t txthrcfg; + uint32_t rxthrcfg; + uint32_t ctl; + uint32_t evten; + uint32_t sts; + uint8_t reserved0[4]; + uint32_t snpsid; + uint32_t gpio; + uint32_t uid; + uint32_t uctl; + uint64_t buserraddr; + uint64_t prtbimap; + uint8_t reserved1[32]; + uint32_t dbgfifospace; + uint32_t dbgltssm; + uint32_t dbglnmcc; + uint32_t dbgbmu; + uint32_t dbglspmux; + uint32_t dbglsp; + uint32_t dbgepinfo0; + uint32_t dbgepinfo1; + uint64_t prtbimap_hs; + uint64_t prtbimap_fs; + uint8_t reserved2[112]; + uint32_t usb2phycfg; + uint8_t reserved3[60]; + uint32_t usb2i2cctl; + uint8_t reserved4[60]; + uint32_t usb2phyacc; + uint8_t reserved5[60]; + uint32_t usb3pipectl; + uint8_t reserved6[60]; +}; +check_member(exynos5_usb_drd_dwc3, usb3pipectl, 0x1c0); + +static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd_dwc3 = + (void *)EXYNOS5_USB_DRD_DWC3_BASE; + +/* Leave hsic_gpio at 0 to not enable HSIC. */ +void setup_usb_host_phy(int hsic_gpio); + +void setup_usb_drd_phy(void); + +/* Call reset_ before setup_, ensure at least 100ms pass in between. */ +void reset_usb_drd_dwc3(void); +void setup_usb_drd_dwc3(void); + +#endif diff --git a/src/soc/samsung/exynos5250/include/soc/wakeup.h b/src/soc/samsung/exynos5250/include/soc/wakeup.h new file mode 100644 index 0000000000..690c6a3262 --- /dev/null +++ b/src/soc/samsung/exynos5250/include/soc/wakeup.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5250_WAKEUP_H +#define CPU_SAMSUNG_EXYNOS5250_WAKEUP_H + +/* Power Down Modes */ +#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_DIDLE 0xBAD00000 +#define S5P_CHECK_LPA 0xABAD0000 + +enum { + // A normal boot (not suspend/resume) + IS_NOT_WAKEUP, + // A wake up event that can be resumed any time + WAKEUP_DIRECT, + // A wake up event that must be resumed only after + // clock and memory controllers are re-initialized + WAKEUP_NEED_CLOCK_RESET, +}; + +int wakeup_need_reset(void); +int get_wakeup_state(void); +void wakeup(void); +void wakeup_enable_uart(void); + +#endif /* CPU_SAMSUNG_EXYNOS5250_WAKEUP_H */ diff --git a/src/soc/samsung/exynos5250/pinmux.c b/src/soc/samsung/exynos5250/pinmux.c new file mode 100644 index 0000000000..0632394309 --- /dev/null +++ b/src/soc/samsung/exynos5250/pinmux.c @@ -0,0 +1,267 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +static void exynos_pinmux_uart(int start, int count) +{ + int i; + + for (i = start; i < start + count; i++) { + gpio_set_pull(i, GPIO_PULL_NONE); + gpio_cfg_pin(i, GPIO_FUNC(0x2)); + } +} + +void exynos_pinmux_uart0(void) +{ + exynos_pinmux_uart(GPIO_A00, 4); +} + +void exynos_pinmux_uart1(void) +{ + exynos_pinmux_uart(GPIO_D00, 4); +} + +void exynos_pinmux_uart2(void) +{ + exynos_pinmux_uart(GPIO_A10, 4); +} + +void exynos_pinmux_uart3(void) +{ + exynos_pinmux_uart(GPIO_A14, 2); +} + +static void exynos_pinmux_sdmmc(int start, int start_ext) +{ + int i; + + if (start_ext) { + for (i = 0; i <= 3; i++) { + gpio_cfg_pin(start_ext + i, GPIO_FUNC(0x2)); + gpio_set_pull(start_ext + i, GPIO_PULL_UP); + gpio_set_drv(start_ext + i, GPIO_DRV_4X); + } + } + for (i = 0; i < 2; i++) { + gpio_cfg_pin(start + i, GPIO_FUNC(0x2)); + gpio_set_pull(start + i, GPIO_PULL_NONE); + gpio_set_drv(start + i, GPIO_DRV_4X); + } + for (i = 2; i <= 6; i++) { + gpio_cfg_pin(start + i, GPIO_FUNC(0x2)); + gpio_set_pull(start + i, GPIO_PULL_UP); + gpio_set_drv(start + i, GPIO_DRV_4X); + } +} + +void exynos_pinmux_sdmmc0(void) +{ + exynos_pinmux_sdmmc(GPIO_C00, GPIO_C10); +} + +void exynos_pinmux_sdmmc1(void) +{ + exynos_pinmux_sdmmc(GPIO_C20, 0); +} + +void exynos_pinmux_sdmmc2(void) +{ + exynos_pinmux_sdmmc(GPIO_C30, 0); +} + +void exynos_pinmux_sdmmc3(void) +{ + /* + * TODO: Need to add defintions for GPC4 before + * enabling this. + */ + printk(BIOS_DEBUG, "SDMMC3 not supported yet"); +} + +void exynos_pinmux_sromc(int bank, int sixteen_bit) +{ + int i; + + if (bank > 3) { + printk(BIOS_DEBUG, "Unsupported sromc bank %d.\n", bank); + return; + } + + gpio_cfg_pin(GPIO_Y00 + bank, GPIO_FUNC(2)); + gpio_cfg_pin(GPIO_Y04, GPIO_FUNC(2)); + gpio_cfg_pin(GPIO_Y05, GPIO_FUNC(2)); + + for (i = 2; i < 4; i++) + gpio_cfg_pin(GPIO_Y10 + i, GPIO_FUNC(2)); + + for (i = 0; i < 8; i++) { + gpio_cfg_pin(GPIO_Y30 + i, GPIO_FUNC(2)); + gpio_set_pull(GPIO_Y30 + i, GPIO_PULL_UP); + + gpio_cfg_pin(GPIO_Y50 + i, GPIO_FUNC(2)); + gpio_set_pull(GPIO_Y50 + i, GPIO_PULL_UP); + + if (sixteen_bit) { + gpio_cfg_pin(GPIO_Y60 + i, GPIO_FUNC(2)); + gpio_set_pull(GPIO_Y60 + i, GPIO_PULL_UP); + } + } +} + +static void exynos_pinmux_spi(int start, int cfg) +{ + int i; + + for (i = 0; i < 4; i++) { + gpio_cfg_pin(start + i, GPIO_FUNC(cfg)); + gpio_set_pull(start + i, GPIO_PULL_NONE); + gpio_set_drv(start + i, GPIO_DRV_3X); + } +} + +void exynos_pinmux_spi0(void) +{ + exynos_pinmux_spi(GPIO_A20, 0x2); +} + +void exynos_pinmux_spi1(void) +{ + exynos_pinmux_spi(GPIO_A24, 0x2); +} + +void exynos_pinmux_spi2(void) +{ + exynos_pinmux_spi(GPIO_B11, 0x5); +} + +void exynos_pinmux_spi3(void) +{ + exynos_pinmux_spi(GPIO_E00, 0x2); +} + +void exynos_pinmux_spi4(void) +{ + int i; + + for (i = 0; i < 2; i++) + gpio_cfg_pin(GPIO_F02 + i, GPIO_FUNC(0x4)); + for (i = 2; i < 4; i++) + gpio_cfg_pin(GPIO_E02 + i, GPIO_FUNC(0x4)); +} + +void exynos_pinmux_backlight(void) +{ + gpio_cfg_pin(GPIO_B20, GPIO_OUTPUT); + gpio_set_value(GPIO_B20, 1); +} + +void exynos_pinmux_lcd(void) +{ + gpio_cfg_pin(GPIO_Y25, GPIO_OUTPUT); + gpio_set_value(GPIO_Y25, 1); + gpio_cfg_pin(GPIO_X15, GPIO_OUTPUT); + gpio_set_value(GPIO_X15, 1); + gpio_cfg_pin(GPIO_X30, GPIO_OUTPUT); + gpio_set_value(GPIO_X30, 1); +} + +static void exynos_pinmux_i2c(int start, int func) +{ + gpio_cfg_pin(start, GPIO_FUNC(func)); + gpio_cfg_pin(start + 1, GPIO_FUNC(func)); + gpio_set_pull(start, GPIO_PULL_NONE); + gpio_set_pull(start + 1, GPIO_PULL_NONE); +} + +void exynos_pinmux_i2c0(void) +{ + exynos_pinmux_i2c(GPIO_B30, 0x2); +} + +void exynos_pinmux_i2c1(void) +{ + exynos_pinmux_i2c(GPIO_B32, 0x2); +} + +void exynos_pinmux_i2c2(void) +{ + exynos_pinmux_i2c(GPIO_A06, 0x3); +} + +void exynos_pinmux_i2c3(void) +{ + exynos_pinmux_i2c(GPIO_A12, 0x3); +} + +void exynos_pinmux_i2c4(void) +{ + exynos_pinmux_i2c(GPIO_A20, 0x3); +} + +void exynos_pinmux_i2c5(void) +{ + exynos_pinmux_i2c(GPIO_A22, 0x3); +} + +void exynos_pinmux_i2c6(void) +{ + exynos_pinmux_i2c(GPIO_B13, 0x4); +} + +void exynos_pinmux_i2c7(void) +{ + exynos_pinmux_i2c(GPIO_B22, 0x3); +} + +void exynos_pinmux_dphpd(void) +{ + /* Set Hotplug detect for DP */ + gpio_cfg_pin(GPIO_X07, GPIO_FUNC(0x3)); + + /* + * Hotplug detect should have an external pullup; disable the + * internal pulldown so they don't fight. + */ + gpio_set_pull(GPIO_X07, GPIO_PULL_NONE); +} + +void exynos_pinmux_i2s0(void) +{ + int i; + + for (i = 0; i < 5; i++) { + gpio_cfg_pin(GPIO_Z0 + i, GPIO_FUNC(0x02)); + gpio_set_pull(GPIO_Z0 + i, GPIO_PULL_NONE); + } +} + +void exynos_pinmux_i2s1(void) +{ + int i; + + for (i = 0; i < 5; i++) { + gpio_cfg_pin(GPIO_B00 + i, GPIO_FUNC(0x02)); + gpio_set_pull(GPIO_B00 + i, GPIO_PULL_NONE); + } +} diff --git a/src/soc/samsung/exynos5250/power.c b/src/soc/samsung/exynos5250/power.c new file mode 100644 index 0000000000..e72e570efd --- /dev/null +++ b/src/soc/samsung/exynos5250/power.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Power setup code for EXYNOS5 */ + +#include +#include +#include +#include + +static void ps_hold_setup(void) +{ + /* Set PS-Hold high */ + setbits_le32(&exynos_power->ps_hold_ctrl, + POWER_PS_HOLD_CONTROL_DATA_HIGH); +} + +void power_reset(void) +{ + /* Clear inform1 so there's no change we think we've got a wake reset */ + exynos_power->inform1 = 0; + + setbits_le32(&exynos_power->sw_reset, 1); +} + +/* This function never returns */ +void power_shutdown(void) +{ + clrbits_le32(&exynos_power->ps_hold_ctrl, + POWER_PS_HOLD_CONTROL_DATA_HIGH); + + hlt(); +} + +void power_enable_dp_phy(void) +{ + setbits_le32(&exynos_power->dptx_phy_control, DPTX_PHY_ENABLE); +} + +void power_enable_hw_thermal_trip(void) +{ + /* Enable HW thermal trip */ + setbits_le32(&exynos_power->ps_hold_ctrl, POWER_ENABLE_HW_TRIP); +} + +uint32_t power_read_reset_status(void) +{ + return exynos_power->inform1; +} + +void power_exit_wakeup(void) +{ + typedef void (*resume_func)(void); + + ((resume_func)exynos_power->inform0)(); +} + +int power_init(void) +{ + ps_hold_setup(); + return 0; +} + +void power_enable_xclkout(void) +{ + /* use xxti for xclk out */ + clrsetbits_le32(&exynos_power->pmu_debug, PMU_DEBUG_CLKOUT_SEL_MASK, + PMU_DEBUG_XXTI); +} + +void power_release_uart_retention(void) +{ + writel(1 << 28, &exynos_power->padret_uart_opt); +} diff --git a/src/cpu/samsung/exynos5-common/spi.c b/src/soc/samsung/exynos5250/spi.c similarity index 87% rename from src/cpu/samsung/exynos5-common/spi.c rename to src/soc/samsung/exynos5250/spi.c index 33f4d99fd2..7589c22ddf 100644 --- a/src/cpu/samsung/exynos5-common/spi.c +++ b/src/soc/samsung/exynos5250/spi.c @@ -1,14 +1,12 @@ /* + * This file is part of the coreboot project. + * * Copyright (C) 2011 Samsung Electronics - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2013 Google Inc. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,22 +15,16 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - -#include +#include +#include #include - -#include -#include - -#include "spi.h" - -#define OM_STAT (0x1f << 1) -#define EXYNOS_BASE_SPI1 ((void *)0x12d30000) +#include +#include +#include +#include #if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI # define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "EXYNOS_SPI: " x) @@ -49,7 +41,7 @@ static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo, // TODO In currrent implementation, every read/write must be aligned to // 4 bytes, otherwise you may get timeout or other unexpected results. - assert(todo % 4 == 0); + ASSERT(todo % 4 == 0); out_bytes = in_bytes = todo; setbits_le32(®s->ch_cfg, SPI_CH_RST); @@ -107,7 +99,6 @@ int exynos_spi_open(struct exynos_spi *regs) /* now set rx and tx channel ON */ setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); - clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ return 0; } @@ -115,6 +106,8 @@ int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off) { int upto, todo; int i; + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ + /* Send read instruction (0x3h) followed by a 24 bit addr */ writel((SF_READ_DATA_CMD << 24) | off, ®s->tx_data); @@ -128,6 +121,11 @@ int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off) setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ + return len; +} + +int exynos_spi_close(struct exynos_spi *regs) +{ /* * Let put controller mode to BYTE as * SPI driver does not support WORD mode yet @@ -136,11 +134,6 @@ int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off) SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD); writel(0, ®s->swap_cfg); - return len; -} - -int exynos_spi_close(struct exynos_spi *regs) -{ /* * Flush spi tx, rx fifos and reset the SPI controller * and clear rx/tx channel @@ -205,7 +198,7 @@ int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, static struct exynos_spi_media context; DEBUG_SPI("initialize_exynos_spi_cbfs_media\n"); - context.regs = EXYNOS_BASE_SPI1; + context.regs = (void*)EXYNOS5_SPI1_BASE; context.buffer.allocated = context.buffer.last_allocate = 0; context.buffer.buffer = buffer_address; context.buffer.size = buffer_size; @@ -218,10 +211,3 @@ int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, return 0; } - -int init_default_cbfs_media(struct cbfs_media *media) { - return initialize_exynos_spi_cbfs_media( - media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_CBFS_CACHE_SIZE); -} diff --git a/src/soc/samsung/exynos5250/timer.c b/src/soc/samsung/exynos5250/timer.c new file mode 100644 index 0000000000..f8e9c1bc4f --- /dev/null +++ b/src/soc/samsung/exynos5250/timer.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static const uint32_t clocks_per_usec = MCT_HZ/1000000; + +static uint64_t mct_raw_value(void) +{ + uint64_t upper = readl(&exynos_mct->g_cnt_u); + uint64_t lower = readl(&exynos_mct->g_cnt_l); + + return (upper << 32) | lower; +} + +void init_timer(void) +{ + writel(readl(&exynos_mct->g_tcon) | (0x1 << 8), + &exynos_mct->g_tcon); +} + +void timer_monotonic_get(struct mono_time *mt) +{ + /* We don't have to call mct_start() here + * because it was already called int he bootblock + */ + + mono_time_set_usecs(mt, mct_raw_value() / clocks_per_usec); +} diff --git a/src/soc/samsung/exynos5250/tmu.c b/src/soc/samsung/exynos5250/tmu.c new file mode 100644 index 0000000000..a0e96b4b04 --- /dev/null +++ b/src/soc/samsung/exynos5250/tmu.c @@ -0,0 +1,215 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* EXYNOS - Thermal Management Unit */ + +#include +#include +#include +#include + +#define TRIMINFO_RELOAD 1 +#define CORE_EN 1 +#define THERM_TRIP_EN (1 << 12) + +#define INTEN_RISE0 1 +#define INTEN_RISE1 (1 << 4) +#define INTEN_RISE2 (1 << 8) +#define INTEN_FALL0 (1 << 16) +#define INTEN_FALL1 (1 << 20) +#define INTEN_FALL2 (1 << 24) + +#define TRIM_INFO_MASK 0xff + +#define INTCLEAR_RISE0 1 +#define INTCLEAR_RISE1 (1 << 4) +#define INTCLEAR_RISE2 (1 << 8) +#define INTCLEAR_FALL0 (1 << 16) +#define INTCLEAR_FALL1 (1 << 20) +#define INTCLEAR_FALL2 (1 << 24) +#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \ + INTCLEAR_RISE2 | INTCLEAR_FALL0 | \ + INTCLEAR_FALL1 | INTCLEAR_FALL2) + +struct tmu_info exynos5250_tmu_info = { + .tmu_base = 0x10060000, + .tmu_mux = 6, + .data = { + .ts = { + .min_val = 25, + .max_val = 125, + .start_warning = 95, + .start_tripping = 105, + .hardware_tripping = 110, + }, + .efuse_min_value = 40, + .efuse_value = 55, + .efuse_max_value = 100, + .slope = 0x10008802, + }, + .dc_value = 25, +}; + +/* + * After reading temperature code from register, compensating + * its value and calculating celsius temperatue, + * get current temperatue. + * + * @return current temperature of the chip as sensed by TMU + */ +static int get_cur_temp(struct tmu_info *info) +{ + int cur_temp; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Temperature code range between min 25 and max 125 */ + cur_temp = readl(®->current_temp) & 0xff; + + /* Calibrate current temperature */ + if (cur_temp) + cur_temp = cur_temp - info->te1 + info->dc_value; + + return cur_temp; +} + +/* + * Monitors status of the TMU device and exynos temperature + * + * @info TMU info + * @temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + */ +enum tmu_status_t tmu_monitor(struct tmu_info *info, int *temp) +{ + if (info->tmu_state == TMU_STATUS_INIT) + return -1; + + int cur_temp; + struct tmu_data *data = &info->data; + + /* Read current temperature of the SOC */ + cur_temp = get_cur_temp(info); + *temp = cur_temp; + + /* Temperature code lies between min 25 and max 125 */ + if (cur_temp >= data->ts.start_tripping && + cur_temp <= data->ts.max_val) + return TMU_STATUS_TRIPPED; + else if (cur_temp >= data->ts.start_warning) + return TMU_STATUS_WARNING; + else if (cur_temp < data->ts.start_warning && + cur_temp >= data->ts.min_val) + return TMU_STATUS_NORMAL; + /* Temperature code does not lie between min 25 and max 125 */ + else { + info->tmu_state = TMU_STATUS_INIT; + printk(BIOS_DEBUG, "EXYNOS_TMU: Thermal reading failed\n"); + return -1; + } + return 0; +} + +/* + * Calibrate and calculate threshold values and + * enable interrupt levels + * + * @param info pointer to the tmu_info struct + */ +static void tmu_setup_parameters(struct tmu_info *info) +{ + unsigned int te_temp, con; + unsigned int warning_code, trip_code, hwtrip_code; + unsigned int cooling_temp; + unsigned int rising_value; + struct tmu_data *data = &info->data; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Must reload for using efuse value at EXYNOS */ + writel(TRIMINFO_RELOAD, ®->triminfo_control); + + /* Get the compensation parameter */ + te_temp = readl(®->triminfo); + info->te1 = te_temp & TRIM_INFO_MASK; + info->te2 = ((te_temp >> 8) & TRIM_INFO_MASK); + + if ((data->efuse_min_value > info->te1) || + (info->te1 > data->efuse_max_value) + || (info->te2 != 0)) + info->te1 = data->efuse_value; + + /* Get RISING & FALLING Threshold value */ + warning_code = data->ts.start_warning + + info->te1 - info->dc_value; + trip_code = data->ts.start_tripping + + info->te1 - info->dc_value; + hwtrip_code = data->ts.hardware_tripping + + info->te1 - info->dc_value; + + cooling_temp = 0; + + rising_value = ((warning_code << 8) | + (trip_code << 16) | + (hwtrip_code << 24)); + + /* Set interrupt level */ + writel(rising_value, ®->threshold_temp_rise); + writel(cooling_temp, ®->threshold_temp_fall); + + /* + * Need to init all register settings after getting parameter info + * [28:23] vref [11:8] slope - Tuning parameter + * + * WARNING: this slope value writes into many bits in the tmu_control + * register, with the default FDT value of 268470274 (0x10008802) + * we are using this essentially sets the default register setting + * from the TRM for tmu_control. + * TODO(bhthompson): rewrite this code such that we are not performing + * a hard wipe of tmu_control and re verify functionality. + */ + writel(data->slope, ®->tmu_control); + + writel(INTCLEARALL, ®->intclear); + /* TMU core enable */ + con = readl(®->tmu_control); + con |= (info->tmu_mux << 20) | THERM_TRIP_EN | CORE_EN; + + writel(con, ®->tmu_control); + + /* Enable HW thermal trip */ + power_enable_hw_thermal_trip(); + + /* LEV1 LEV2 interrupt enable */ + writel(INTEN_RISE1 | INTEN_RISE2, ®->inten); +} + +/* + * Initialize TMU device + * + * @return int value, 0 for success + */ +int tmu_init(struct tmu_info *info) +{ + info->tmu_state = TMU_STATUS_INIT; + + tmu_setup_parameters(info); + info->tmu_state = TMU_STATUS_NORMAL; + + return 0; +} diff --git a/src/soc/samsung/exynos5250/trustzone.c b/src/soc/samsung/exynos5250/trustzone.c new file mode 100644 index 0000000000..c4d3bc64b6 --- /dev/null +++ b/src/soc/samsung/exynos5250/trustzone.c @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +/* Setting TZPC[TrustZone Protection Controller] */ +void trustzone_init(void) +{ + struct exynos_tzpc *tzpc; + unsigned int addr; + + for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) { + tzpc = (struct exynos_tzpc *)addr; + + if (addr == TZPC0_BASE) + writel(R0SIZE, &tzpc->r0size); + + writel(DECPROTXSET, &tzpc->decprot0set); + writel(DECPROTXSET, &tzpc->decprot1set); + + if (addr != TZPC9_BASE) { + writel(DECPROTXSET, &tzpc->decprot2set); + writel(DECPROTXSET, &tzpc->decprot3set); + } + } +} diff --git a/src/cpu/samsung/exynos5250/uart.c b/src/soc/samsung/exynos5250/uart.c similarity index 72% rename from src/cpu/samsung/exynos5250/uart.c rename to src/soc/samsung/exynos5250/uart.c index 75c576332f..7134b4e368 100644 --- a/src/cpu/samsung/exynos5250/uart.c +++ b/src/soc/samsung/exynos5250/uart.c @@ -1,14 +1,11 @@ /* - * (C) Copyright 2009 SAMSUNG Electronics - * Minkyu Kang - * Heungjun Kim + * This file is part of the coreboot project. * - * based on drivers/serial/s3c64xx.c + * Copyright (C) 2009 Samsung Electronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -17,20 +14,17 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include /* for __console definition */ +#include +#include +#include +#include #include #include -#include - -#include /* for __console definition */ - -#include -#include -#include -#include #define RX_FIFO_COUNT_MASK 0xff #define RX_FIFO_FULL_MASK (1 << 8) @@ -39,24 +33,6 @@ /* FIXME(dhendrix): exynos5 has 4 UARTs and its functions in u-boot take a base_port argument. However console_driver functions do not. */ static uint32_t base_port = CONFIG_CONSOLE_SERIAL_UART_ADDRESS; -#if 0 -/* Information about a serial port */ -struct fdt_serial { - u32 base_addr; /* address of registers in physical memory */ - u8 port_id; /* uart port number */ - u8 enabled; /* 1 if enabled, 0 if disabled */ -} config = { - -1U -}; -#endif - -#if 0 -static inline struct s5p_uart *s5p_get_base_uart(int dev_index) -{ - /* FIXME: there should be an assertion here if dev_index is >3 */ - return (struct s5p_uart *)(EXYNOS5_UART0_BASE + (0x10000 * dev_index)); -} -#endif /* * The coefficient, used to calculate the baudrate on S5P UARTs is @@ -86,15 +62,13 @@ static const int udivslot[] = { static void serial_setbrg_dev(void) { -// struct s5p_uart *const uart = s5p_get_base_uart(dev_index); struct s5p_uart *uart = (struct s5p_uart *)base_port; u32 uclk; u32 baudrate = CONFIG_TTYS0_BAUD; u32 val; - enum periph_id periph; - periph = exynos5_get_periph_id(base_port); - uclk = clock_get_periph_rate(periph); + // All UARTs share the same clock. + uclk = clock_get_periph_rate(PERIPH_ID_UART3); val = uclk / baudrate; writel(val / 16 - 1, &uart->ubrdiv); @@ -106,7 +80,7 @@ static void serial_setbrg_dev(void) */ #if 0 if (s5p_uart_divslot()) - writew(udivslot[val % 16], &uart->rest.slot); + writel(udivslot[val % 16], &uart->rest.slot); else writeb(val % 16, &uart->rest.value); #endif @@ -118,11 +92,10 @@ static void serial_setbrg_dev(void) */ static void exynos5_init_dev(void) { -// struct s5p_uart *const uart = s5p_get_base_uart(dev_index); struct s5p_uart *uart = (struct s5p_uart *)base_port; // TODO initialize with correct peripheral id by base_port. - exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); + exynos_pinmux_uart3(); /* enable FIFOs */ writel(0x1, &uart->ufcon); @@ -137,7 +110,6 @@ static void exynos5_init_dev(void) static int exynos5_uart_err_check(int op) { - //struct s5p_uart *const uart = s5p_get_base_uart(dev_index); struct s5p_uart *uart = (struct s5p_uart *)base_port; unsigned int mask; @@ -163,7 +135,6 @@ static int exynos5_uart_err_check(int op) */ static unsigned char exynos5_uart_rx_byte(void) { -// struct s5p_uart *const uart = s5p_get_base_uart(dev_index); struct s5p_uart *uart = (struct s5p_uart *)base_port; /* wait for character to arrive */ @@ -181,7 +152,6 @@ static unsigned char exynos5_uart_rx_byte(void) */ static void exynos5_uart_tx_byte(unsigned char data) { -// struct s5p_uart *const uart = s5p_get_base_uart(dev_index); struct s5p_uart *uart = (struct s5p_uart *)base_port; /* wait for room in the tx FIFO */ @@ -193,11 +163,19 @@ static void exynos5_uart_tx_byte(unsigned char data) writeb(data, &uart->utxh); } +static void exynos5_uart_tx_flush(void) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + + while (readl(&uart->ufstat) & 0x1ff0000); +} + #if !defined(__PRE_RAM__) + static const struct console_driver exynos5_uart_console __console = { .init = exynos5_init_dev, .tx_byte = exynos5_uart_tx_byte, -// .tx_flush = exynos5_uart_tx_flush, + .tx_flush = exynos5_uart_tx_flush, .rx_byte = exynos5_uart_rx_byte, // .tst_byte = exynos5_uart_tst_byte, }; @@ -206,7 +184,9 @@ uint32_t uartmem_getbaseaddr(void) { return base_port; } + #else + void uart_init(void) { exynos5_init_dev(); @@ -222,6 +202,9 @@ void uart_tx_byte(unsigned char data) exynos5_uart_tx_byte(data); } -void uart_tx_flush(void) { +void uart_tx_flush(void) +{ + exynos5_uart_tx_flush(); } + #endif diff --git a/src/soc/samsung/exynos5250/usb.c b/src/soc/samsung/exynos5250/usb.c new file mode 100644 index 0000000000..8a91497e1f --- /dev/null +++ b/src/soc/samsung/exynos5250/usb.c @@ -0,0 +1,198 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void reset_dwc3(struct exynos5_usb_drd_dwc3 *dwc3) +{ + setbits_le32(&dwc3->ctl, 0x1 << 11); /* core soft reset */ + setbits_le32(&dwc3->usb3pipectl, 0x1 << 31); /* PHY soft reset */ + setbits_le32(&dwc3->usb2phycfg, 0x1 << 31); /* PHY soft reset */ +} + +void reset_usb_drd_dwc3() +{ + printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD\n"); + reset_dwc3(exynos_usb_drd_dwc3); +} + +static void setup_dwc3(struct exynos5_usb_drd_dwc3 *dwc3) +{ + if (!(dwc3->ctl & 0x1 << 11) || + !(dwc3->usb3pipectl & 0x1 << 31) || + !(dwc3->usb2phycfg & 0x1 << 31)) { + printk(BIOS_ERR, "DWC3 at %p not in reset (you need to call " + "reset_usb_drd_dwc3() first)!\n", dwc3); + } + + /* Set relevant registers to default values (clearing all reset bits) */ + + writel(0x1 << 24 | /* activate PHY low power states */ + 0x4 << 19 | /* low power delay value */ + 0x1 << 18 | /* activate PHY low power delay */ + 0x1 << 17 | /* enable SuperSpeed PHY suspend */ + 0x1 << 1 | /* default Tx deemphasis value */ + 0, &dwc3->usb3pipectl); + + /* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */ + writel(0x9 << 10 | /* PHY clock turnaround for 8-bit UTMI+ */ + 0x1 << 8 | /* enable PHY sleep in L1 */ + 0x1 << 6 | /* enable PHY suspend */ + 0, &dwc3->usb2phycfg); + + writel(0x5dc << 19 | /* suspend clock scale for 24MHz */ + 0x1 << 16 | /* retry SS three times (bugfix from U-Boot) */ + 0x1 << 12 | /* port capability HOST */ + 0, &dwc3->ctl); +} + +void setup_usb_drd_dwc3() +{ + setup_dwc3(exynos_usb_drd_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB DRD finished\n"); +} + +static void setup_drd_phy(struct exynos5_usb_drd_phy *phy) +{ + /* Set all PHY registers to default values */ + + /* XHCI Version 1.0, Frame Length adjustment 30 MHz */ + setbits_le32(&phy->linksystem, 0x1 << 27 | 0x20 << 1); + + /* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */ + writel(1 << 6, &phy->utmi); + + writel(0x88 << 23 | /* spread spectrum refclk selector */ + 0x1 << 20 | /* enable spread spectrum */ + 0x1 << 19 | /* enable prescaler refclk */ + 0x68 << 11 | /* multiplier for 24MHz refclk */ + 0x5 << 5 | /* select 24MHz refclk (weird, from U-Boot) */ + 0x1 << 4 | /* power supply in normal operating mode */ + 0x3 << 2 | /* use external refclk (undocumented on 5420?)*/ + 0x1 << 1 | /* force port reset */ + 0x1 << 0 | /* normal operating mode */ + 0, &phy->clkrst); + + writel(0x9 << 26 | /* LOS level */ + 0x3 << 22 | /* TX VREF tune */ + 0x1 << 20 | /* TX rise tune */ + 0x1 << 18 | /* TX res tune */ + 0x3 << 13 | /* TX HS X Vtune */ + 0x3 << 9 | /* TX FS/LS tune */ + 0x3 << 6 | /* SQRX tune */ + 0x4 << 3 | /* OTG tune */ + 0x4 << 0 | /* comp disc tune */ + 0, &phy->param0); + + writel(0x7f << 19 | /* reserved */ + 0x7f << 12 | /* Tx launch amplitude */ + 0x20 << 6 | /* Tx deemphasis 6dB */ + 0x1c << 0 | /* Tx deemphasis 3.5dB (value from U-Boot) */ + 0, &phy->param1); + + /* disable all test features */ + writel(0, &phy->test); + + /* UTMI clock select? ("must be 0x1") */ + writel(0x1 << 2, &phy->utmiclksel); + + /* Samsung magic, undocumented (from U-Boot) */ + writel(0x0, &phy->resume); + + udelay(10); + clrbits_le32(&phy->clkrst, 0x1 << 1); /* deassert port reset */ +} + +void setup_usb_drd_phy() +{ + printk(BIOS_DEBUG, "Powering up USB DRD PHY\n"); + setbits_le32(&exynos_power->usb_drd_phy_ctrl, POWER_USB_PHY_CTRL_EN); + setup_drd_phy(exynos_usb_drd_phy); +} + +void setup_usb_host_phy(int hsic_gpio) +{ + unsigned int hostphy_ctrl0; + + setbits_le32(&exynos_sysreg->usb20_phy_cfg, USB20_PHY_CFG_EN); + setbits_le32(&exynos_power->usb_host_phy_ctrl, POWER_USB_PHY_CTRL_EN); + + printk(BIOS_DEBUG, "Powering up USB HOST PHY (%s HSIC)\n", + hsic_gpio ? "with" : "without"); + + hostphy_ctrl0 = readl(&exynos_usb_host_phy->usbphyctrl0); + hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK | + HOST_CTRL0_COMMONON_N | + /* HOST Phy setting */ + HOST_CTRL0_PHYSWRST | + HOST_CTRL0_PHYSWRSTALL | + HOST_CTRL0_SIDDQ | + HOST_CTRL0_FORCESUSPEND | + HOST_CTRL0_FORCESLEEP); + hostphy_ctrl0 |= (/* Setting up the ref freq */ + CLK_24MHZ << 16 | + /* HOST Phy setting */ + HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST); + writel(hostphy_ctrl0, &exynos_usb_host_phy->usbphyctrl0); + udelay(10); + clrbits_le32(&exynos_usb_host_phy->usbphyctrl0, + HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST); + udelay(20); + + /* EHCI Ctrl setting */ + setbits_le32(&exynos_usb_host_phy->ehcictrl, + EHCICTRL_ENAINCRXALIGN | + EHCICTRL_ENAINCR4 | + EHCICTRL_ENAINCR8 | + EHCICTRL_ENAINCR16); + + /* HSIC USB Hub initialization. */ + if (hsic_gpio) { + gpio_direction_output(hsic_gpio, 0); + udelay(100); + gpio_direction_output(hsic_gpio, 1); + udelay(5000); + + clrbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_SIDDQ | + HOST_CTRL0_FORCESLEEP | + HOST_CTRL0_FORCESUSPEND); + setbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_PHYSWRST); + udelay(10); + clrbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_PHYSWRST); + } + + /* At this point we need to wait for 50ms before talking to + * the USB controller (PHY clock and power setup time) + * By the time we are actually in the payload, these 50ms + * will have passed. + */ +} diff --git a/src/soc/samsung/exynos5250/wakeup.c b/src/soc/samsung/exynos5250/wakeup.c new file mode 100644 index 0000000000..e688db7e1d --- /dev/null +++ b/src/soc/samsung/exynos5250/wakeup.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void wakeup(void) +{ + if (wakeup_need_reset()) + power_reset(); + + power_init(); /* Ensure ps_hold_setup() for early wakeup. */ + power_exit_wakeup(); + /* Should never return. If we do, reset. */ + power_reset(); +} + +int get_wakeup_state(void) +{ + uint32_t status = power_read_reset_status(); + + /* DIDLE/LPA can be resumed without clock reset (ex, bootblock), + * and SLEEP requires resetting clock (should be done in ROM stage). + */ + + if (status == S5P_CHECK_DIDLE || status == S5P_CHECK_LPA) + return WAKEUP_DIRECT; + + if (status == S5P_CHECK_SLEEP) + return WAKEUP_NEED_CLOCK_RESET; + + return IS_NOT_WAKEUP; +} + +void wakeup_enable_uart(void) +{ + power_release_uart_retention(); +} diff --git a/src/soc/samsung/exynos5420/Kconfig b/src/soc/samsung/exynos5420/Kconfig new file mode 100644 index 0000000000..4641e4a1dd --- /dev/null +++ b/src/soc/samsung/exynos5420/Kconfig @@ -0,0 +1,54 @@ +config CPU_SAMSUNG_EXYNOS5420 + select CPU_HAS_BOOTBLOCK_INIT + select HAVE_MONOTONIC_TIMER + select GENERIC_UDELAY + select HAVE_UART_SPECIAL + select EARLY_CONSOLE + select RELOCATABLE_MODULES + select DYNAMIC_CBMEM + select ARCH_BOOTBLOCK_ARM_V7 + select ARCH_ROMSTAGE_ARM_V7 + select ARCH_RAMSTAGE_ARM_V7 + bool + default n + +if CPU_SAMSUNG_EXYNOS5420 + +choice CONSOLE_SERIAL_UART_CHOICES + prompt "Serial Console UART" + default CONSOLE_SERIAL_UART3 + depends on CONSOLE_SERIAL_UART + +config CONSOLE_SERIAL_UART0 + bool "UART0" + help + Serial console on UART0 + +config CONSOLE_SERIAL_UART1 + bool "UART1" + help + Serial console on UART1 + +config CONSOLE_SERIAL_UART2 + bool "UART2" + help + Serial console on UART2 + +config CONSOLE_SERIAL_UART3 + bool "UART3" + help + Serial console on UART3 + +endchoice + +config CONSOLE_SERIAL_UART_ADDRESS + hex + depends on CONSOLE_SERIAL_UART + default 0x12c00000 if CONSOLE_SERIAL_UART0 + default 0x12c10000 if CONSOLE_SERIAL_UART1 + default 0x12c20000 if CONSOLE_SERIAL_UART2 + default 0x12c30000 if CONSOLE_SERIAL_UART3 + help + Map the UART names to the respective MMIO address. + +endif diff --git a/src/soc/samsung/exynos5420/Makefile.inc b/src/soc/samsung/exynos5420/Makefile.inc new file mode 100644 index 0000000000..7261093768 --- /dev/null +++ b/src/soc/samsung/exynos5420/Makefile.inc @@ -0,0 +1,59 @@ +bootblock-y += spi.c alternate_cbfs.c +bootblock-y += bootblock.c +bootblock-y += pinmux.c timer.c power.c +# Clock is required for UART +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += clock_init.c +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += clock.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c +endif +bootblock-y += wakeup.c +bootblock-y += gpio.c + +romstage-y += spi.c alternate_cbfs.c +romstage-y += smp.c +romstage-y += clock.c +romstage-y += clock_init.c +romstage-y += pinmux.c # required by s3c24x0_i2c and uart. +romstage-y += dmc_common.c +romstage-y += dmc_init_ddr3.c +romstage-y += power.c +romstage-y += timer.c +ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) +romstage-$(CONFIG_EARLY_CONSOLE) += uart.c +endif +romstage-y += wakeup.c +romstage-y += gpio.c +romstage-y += i2c.c +#romstage-y += wdt.c +romstage-y += cbmem.c +romstage-y += trustzone.c + +ramstage-y += spi.c alternate_cbfs.c +ramstage-y += clock.c +ramstage-y += clock_init.c +ramstage-y += pinmux.c +ramstage-y += power.c +ramstage-$(CONFIG_CONSOLE_SERIAL_UART) += uart.c +ramstage-y += cpu.c +ramstage-y += tmu.c +ramstage-y += timer.c +ramstage-y += gpio.c +ramstage-y += i2c.c +ramstage-y += dp.c dp_lowlevel.c fimd.c +ramstage-y += usb.c +ramstage-y += cbmem.c + +rmodules_$(ARCH-ROMSTAGE-y)-y += timer.c + +VBOOT_STUB_DEPS += $(obj)/soc/samsung/exynos5420/timer.rmodules_$(ARCH-ROMSTAGE-y).o + +INCLUDES += -Isrc/soc/samsung/exynos5420/include/ + +$(objcbfs)/bootblock.raw.elf: $(objcbfs)/bootblock.elf + cp $< $@ + +$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin + @printf " BL1, CKSUM $(subst $(obj)/,,$(@))\n" + util/exynos/variable_cksum.py $< $<.cksum + cat 3rdparty/cpu/samsung/exynos5420/bl1.bin $<.cksum > $@ diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c new file mode 100644 index 0000000000..45489f1e19 --- /dev/null +++ b/src/soc/samsung/exynos5420/alternate_cbfs.c @@ -0,0 +1,183 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include /* This driver serves as a CBFS media source. */ +#include +#include +#include +#include +#include +#include +#include + +/* This allows USB A-A firmware upload from a compatible host in four parts: + * The first two are the bare BL1 and the Coreboot boot block, which are just + * written to their respective loading addresses. These transfers are initiated + * by the IROM / BL1, so this code has nothing to do with them. + * + * The third transfer is a valid CBFS image that contains only the romstage, + * and must be small enough to fit into the PRE_RAM CBFS cache in + * IRAM. It is loaded when this function gets called in the boot block, and + * the normal CBFS code extracts the romstage from it. + * + * The fourth transfer is also a CBFS image, but can be of arbitrary size and + * should contain all available stages/payloads/etc. It is loaded when this + * function is called a second time at the end of the romstage, and copied to + * the romstage/ramstage CBFS cache in DRAM. It will reside there for the + * rest of the firmware's lifetime and all subsequent stages (which will not + * have __PRE_RAM__ defined) can just directly reference it there. + */ +static int usb_cbfs_open(struct cbfs_media *media) +{ +#ifdef __PRE_RAM__ + static int first_run = 1; + int (*irom_load_usb)(void) = *irom_load_image_from_usb_ptr; + + if (!first_run) + return 0; + + dcache_mmu_disable(); + if (!irom_load_usb()) { + dcache_mmu_enable(); + printk(BIOS_EMERG, "Unable to load CBFS image via USB!\n"); + return -1; + } + dcache_mmu_enable(); + + /* + * We need to trust the host/irom to copy the image to our + * _cbfs_cache address... there is no way to control or even + * check the transfer size or target address from our side. + */ + + printk(BIOS_DEBUG, "USB A-A transfer successful, CBFS image should now" + " be at %p\n", _cbfs_cache); + first_run = 0; +#endif + return 0; +} + +/* + * SDMMC works very similar to USB A-A: we copy the CBFS image into memory + * and read it from there. While SDMMC would also allow direct block by block + * on-demand reading, we might run into problems if we call back into the IROM + * in very late boot stages (e.g. after initializing/changing MMC clocks)... so + * this seems like a safer approach. It also makes it easy to pass our image + * down to payloads. + */ +static int sdmmc_cbfs_open(struct cbfs_media *media) +{ +#ifdef __PRE_RAM__ + /* + * In the bootblock, we just copy the small part that fits in the buffer + * and hope that it's enough (since the romstage is currently always the + * first component in the image, this should work out). In the romstage, + * we copy until our cache is full (currently 12M) to avoid the pain of + * figuring out the true image size from in here. Since this is mainly a + * developer/debug boot mode, those shortcomings should be bearable. + */ + const u32 count = _cbfs_cache_size / 512; + static int first_run = 1; + int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) = + *irom_sdmmc_read_blocks_ptr; + + if (!first_run) + return 0; + + dcache_mmu_disable(); + if (!irom_load_sdmmc(1, count, _cbfs_cache)) { + dcache_mmu_enable(); + printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n"); + return -1; + } + dcache_mmu_enable(); + + printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be" + " at %p\n", _cbfs_cache); + first_run = 0; +#endif + return 0; +} + +static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } + +static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + ASSERT(offset + count < _cbfs_cache_size); + memcpy(dest, _cbfs_cache + offset, count); + return count; +} + +static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + ASSERT(offset + count < _cbfs_cache_size); + return _cbfs_cache + offset; +} + +static void *alternate_cbfs_unmap(struct cbfs_media *media, + const void *buffer) { return 0; } + +static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media) +{ + printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); + + media->open = sdmmc_cbfs_open; + media->close = alternate_cbfs_close; + media->read = alternate_cbfs_read; + media->map = alternate_cbfs_map; + media->unmap = alternate_cbfs_unmap; + + return 0; +} + +static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +{ + printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); + + media->open = usb_cbfs_open; + media->close = alternate_cbfs_close; + media->read = alternate_cbfs_read; + media->map = alternate_cbfs_map; + media->unmap = alternate_cbfs_unmap; + + return 0; +} + +int init_default_cbfs_media(struct cbfs_media *media) +{ + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) + return initialize_exynos_usb_cbfs_media(media); + + switch (exynos_power->om_stat & OM_STAT_MASK) { + case OM_STAT_SDMMC: + return initialize_exynos_sdmmc_cbfs_media(media); + case OM_STAT_SPI: + return initialize_exynos_spi_cbfs_media(media, + _cbfs_cache, _cbfs_cache_size); + default: + printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n", + exynos_power->om_stat); + return 1; + } +} diff --git a/src/soc/samsung/exynos5420/bootblock.c b/src/soc/samsung/exynos5420/bootblock.c new file mode 100644 index 0000000000..59bc169204 --- /dev/null +++ b/src/soc/samsung/exynos5420/bootblock.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +/* convenient shorthand (in MB) */ +#define SRAM_START (EXYNOS5_SRAM_BASE >> 20) +#define SRAM_SIZE 1 +#define SRAM_END (SRAM_START + SRAM_SIZE) /* plus one... */ + +void bootblock_soc_init(void) +{ + if (get_wakeup_state() == WAKEUP_DIRECT) { + wakeup(); + /* Never returns. */ + } + + /* set up dcache and MMU */ + mmu_init(); + mmu_disable_range(0, SRAM_START); + mmu_config_range(SRAM_START, SRAM_SIZE, DCACHE_WRITEBACK); + mmu_config_range(SRAM_END, 4096 - SRAM_END, DCACHE_OFF); + dcache_mmu_enable(); + + /* For most ARM systems, we have to initialize firmware media source + * (ex, SPI, SD/MMC, or eMMC) now; but for Exynos platform, that is + * already handled by iROM so there's no need to setup again. + */ +} diff --git a/src/soc/samsung/exynos5420/cbmem.c b/src/soc/samsung/exynos5420/cbmem.c new file mode 100644 index 0000000000..e5f9949c08 --- /dev/null +++ b/src/soc/samsung/exynos5420/cbmem.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +void *cbmem_top(void) +{ + return (void *)(get_fb_base_kb() * KiB); +} + diff --git a/src/soc/samsung/exynos5420/chip.h b/src/soc/samsung/exynos5420/chip.h new file mode 100644 index 0000000000..b552b6efdc --- /dev/null +++ b/src/soc/samsung/exynos5420/chip.h @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_H +#define CPU_SAMSUNG_EXYNOS5420_H + +#include + +struct soc_samsung_exynos5420_config { + /* special magic numbers! */ + int clkval_f; + int upper_margin; + int lower_margin; + int vsync; + int left_margin; + int right_margin; + int hsync; + + int xres; + int yres; + int framebuffer_bits_per_pixel; + + int usb_vbus_gpio; + int usb_hsic_gpio; + + u32 lcdbase; +}; + +#endif /* CPU_SAMSUNG_EXYNOS5420_H */ diff --git a/src/soc/samsung/exynos5420/clock.c b/src/soc/samsung/exynos5420/clock.c new file mode 100644 index 0000000000..fbe9a94d8e --- /dev/null +++ b/src/soc/samsung/exynos5420/clock.c @@ -0,0 +1,636 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* input clock of PLL: SMDK5420 has 24MHz input clock */ +#define CONFIG_SYS_CLK_FREQ 24000000 + +/* Epll Clock division values to achive different frequency output */ +static struct st_epll_con_val epll_div[] = { + { 192000000, 0, 48, 3, 1, 0 }, + { 180000000, 0, 45, 3, 1, 0 }, + { 73728000, 1, 73, 3, 3, 47710 }, + { 67737600, 1, 90, 4, 3, 20762 }, + { 49152000, 0, 49, 3, 3, 9961 }, + { 45158400, 0, 45, 3, 3, 10381 }, + { 180633600, 0, 45, 3, 1, 10381 } +}; + +/* exynos5: return pll clock frequency */ +unsigned long get_pll_clk(int pllreg) +{ + unsigned long r, m, p, s, k = 0, mask, fout; + unsigned int freq; + + switch (pllreg) { + case APLL: + r = readl(&exynos_clock->apll_con0); + break; + case MPLL: + r = readl(&exynos_clock->mpll_con0); + break; + case EPLL: + r = readl(&exynos_clock->epll_con0); + k = readl(&exynos_clock->epll_con1); + break; + case VPLL: + r = readl(&exynos_clock->vpll_con0); + k = readl(&exynos_clock->vpll_con1); + break; + case BPLL: + r = readl(&exynos_clock->bpll_con0); + break; + case RPLL: + r = readl(&exynos_clock->rpll_con0); + k = readl(&exynos_clock->rpll_con1); + break; + case SPLL: + r = readl(&exynos_clock->spll_con0); + break; + case CPLL: + r = readl(&exynos_clock->cpll_con0); + break; + case DPLL: + r = readl(&exynos_clock->dpll_con0); + break; + default: + printk(BIOS_DEBUG, "Unsupported PLL (%d)\n", pllreg); + return 0; + } + + /* + * APLL_CON: MIDV [25:16] + * MPLL_CON: MIDV [25:16] + * EPLL_CON: MIDV [24:16] + * VPLL_CON: MIDV [24:16] + */ + if (pllreg == APLL || pllreg == BPLL || pllreg == MPLL || + pllreg == SPLL) + mask = 0x3ff; + else + mask = 0x1ff; + + m = (r >> 16) & mask; + + /* PDIV [13:8] */ + p = (r >> 8) & 0x3f; + /* SDIV [2:0] */ + s = r & 0x7; + + freq = CONFIG_SYS_CLK_FREQ; + + if (pllreg == EPLL || pllreg == RPLL) { + k = k & 0xffff; + /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ + fout = (m + k / 65536) * (freq / (p * (1 << s))); + } else if (pllreg == VPLL) { + k = k & 0xfff; + /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */ + fout = (m + k / 1024) * (freq / (p * (1 << s))); + } else { + /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ + fout = m * (freq / (p * (1 << s))); + } + + return fout; +} + +enum peripheral_clock_select { + PERIPH_SRC_CPLL = 1, + PERIPH_SRC_DPLL = 2, + PERIPH_SRC_MPLL = 3, + PERIPH_SRC_SPLL = 4, + PERIPH_SRC_IPLL = 5, + PERIPH_SRC_EPLL = 6, + PERIPH_SRC_RPLL = 7, +}; + +static int clock_select_to_pll(enum peripheral_clock_select sel) +{ + int pll; + + switch (sel) { + case PERIPH_SRC_CPLL: + pll = CPLL; + break; + case PERIPH_SRC_DPLL: + pll = DPLL; + break; + case PERIPH_SRC_MPLL: + pll = MPLL; + break; + case PERIPH_SRC_SPLL: + pll = SPLL; + break; + case PERIPH_SRC_IPLL: + pll = IPLL; + break; + case PERIPH_SRC_EPLL: + pll = EPLL; + break; + case PERIPH_SRC_RPLL: + pll = RPLL; + break; + default: + pll = -1; + break; + } + + return pll; +} + +unsigned long clock_get_periph_rate(enum periph_id peripheral) +{ + unsigned long sclk; + unsigned int src, div; + + switch (peripheral) { + case PERIPH_ID_UART0: + src = (readl(&exynos_clock->clk_src_peric0) >> 4) & 0x7; + div = (readl(&exynos_clock->clk_div_peric0) >> 8) & 0xf; + break; + case PERIPH_ID_UART1: + src = (readl(&exynos_clock->clk_src_peric0) >> 8) & 0x7; + div = (readl(&exynos_clock->clk_div_peric0) >> 12) & 0xf; + break; + case PERIPH_ID_UART2: + src = (readl(&exynos_clock->clk_src_peric0) >> 12) & 0x7; + div = (readl(&exynos_clock->clk_div_peric0) >> 16) & 0xf; + break; + case PERIPH_ID_UART3: + src = (readl(&exynos_clock->clk_src_peric0) >> 16) & 0x7; + div = (readl(&exynos_clock->clk_div_peric0) >> 20) & 0xf; + break; + case PERIPH_ID_PWM0: + case PERIPH_ID_PWM1: + case PERIPH_ID_PWM2: + case PERIPH_ID_PWM3: + case PERIPH_ID_PWM4: + src = (readl(&exynos_clock->clk_src_peric0) >> 24) & 0x7; + div = (readl(&exynos_clock->clk_div_peric0) >> 28) & 0x7; + break; + case PERIPH_ID_SPI0: + src = (readl(&exynos_clock->clk_src_peric1) >> 20) & 0x7; + div = (readl(&exynos_clock->clk_div_peric1) >> 20) & 0xf; + break; + case PERIPH_ID_SPI1: + src = (readl(&exynos_clock->clk_src_peric1) >> 24) & 0x7; + div = (readl(&exynos_clock->clk_div_peric1) >> 24) & 0xf; + break; + case PERIPH_ID_SPI2: + src = (readl(&exynos_clock->clk_src_peric1) >> 28) & 0x7; + div = (readl(&exynos_clock->clk_div_peric1) >> 28) & 0xf; + break; + case PERIPH_ID_SPI3: /* aka SPI0_ISP */ + src = (readl(&exynos_clock->clk_src_isp) >> 16) & 0x7; + div = (readl(&exynos_clock->clk_div_isp0) >> 0) & 0x7; + break; + case PERIPH_ID_SPI4: /* aka SPI1_ISP */ + src = (readl(&exynos_clock->clk_src_isp) >> 12) & 0x7; + div = (readl(&exynos_clock->clk_div_isp1) >> 4) & 0x7; + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + case PERIPH_ID_I2C8: + case PERIPH_ID_I2C9: + case PERIPH_ID_I2C10: + /* + * I2C block parent clock selection is different from other + * peripherals, so we handle it all here. + * TODO: Add a helper function like with the peripheral clock + * select fields? + */ + src = (readl(&exynos_clock->clk_src_top1) >> 8) & 0x3; + if (src == 0x0) + src = CPLL; + else if (src == 0x1) + src = DPLL; + else if (src == 0x2) + src = MPLL; + else + return -1; + + sclk = get_pll_clk(src); + div = ((readl(&exynos_clock->clk_div_top1) >> 8) & 0x3f) + 1; + return sclk / div; + default: + printk(BIOS_DEBUG, "%s: invalid peripheral %d", + __func__, peripheral); + return -1; + }; + + src = clock_select_to_pll(src); + if (src < 0) { + printk(BIOS_DEBUG, "%s: cannot determine source PLL", __func__); + return -1; + } + + sclk = get_pll_clk(src); + + return sclk / (div + 1); +} + +/* exynos5: return ARM clock frequency */ +unsigned long get_arm_clk(void) +{ + unsigned long div; + unsigned long armclk; + unsigned int arm_ratio; + unsigned int arm2_ratio; + + div = readl(&exynos_clock->clk_div_cpu0); + + /* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */ + arm_ratio = (div >> 0) & 0x7; + arm2_ratio = (div >> 28) & 0x7; + + armclk = get_pll_clk(APLL) / (arm_ratio + 1); + armclk /= (arm2_ratio + 1); + + return armclk; +} + +/* exynos5: get the mmc clock */ +static unsigned long get_mmc_clk(int dev_index) +{ + unsigned long uclk, sclk; + unsigned int sel, ratio; + int shift = 0; + + sel = readl(&exynos_clock->clk_src_fsys); + sel = (sel >> ((dev_index * 4) + 8)) & 0x7; + + if (sel == 0x3) + sclk = get_pll_clk(MPLL); + else if (sel == 0x6) + sclk = get_pll_clk(EPLL); + else + return 0; + + ratio = readl(&exynos_clock->clk_div_fsys1); + + shift = dev_index * 10; + + ratio = (ratio >> shift) & 0x3ff; + uclk = (sclk / (ratio + 1)); + printk(BIOS_DEBUG, "%s(%d): %lu\n", __func__, dev_index, uclk); + + return uclk; +} + +/* exynos5: set the mmc clock */ +void set_mmc_clk(int dev_index, unsigned int div) +{ + void *addr; + unsigned int val, shift; + + addr = &exynos_clock->clk_div_fsys1; + shift = dev_index * 10; + + val = readl(addr); + val &= ~(0x3ff << shift); + val |= (div & 0x3ff) << shift; + writel(val, addr); +} + +/* Set DW MMC Controller clock */ +int clock_set_dwmci(enum periph_id peripheral) +{ + /* Request MMC clock value to 52MHz. */ + const unsigned long freq = 52000000; + unsigned long sdclkin, cclkin; + int device_index = (int)peripheral - (int)PERIPH_ID_SDMMC0; + + ASSERT(device_index >= 0 && device_index < 4); + sdclkin = get_mmc_clk(device_index); + if (!sdclkin) { + return -1; + } + + /* The SDCLKIN is divided insided controller by the DIVRATIO field in + * CLKSEL register, so we must calculate clock value as + * cclk_in = SDCLKIN / (DIVRATIO + 1) + * Currently the RIVRATIO must be 3 for MMC0 and MMC2 on Exynos5420 + * (and must be configured in payload). + */ + if (device_index == 0 || device_index == 2){ + int divratio = 3; + sdclkin /= (divratio + 1); + } + printk(BIOS_DEBUG, "%s(%d): sdclkin: %ld\n", __func__, device_index, sdclkin); + + cclkin = div_round_up(sdclkin, freq); + set_mmc_clk(device_index, cclkin); + return 0; +} + +void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) +{ + unsigned shift; + unsigned mask = 0xff; + u32 *reg; + + /* + * For now we only handle a very small subset of peipherals here. + * Others will need to (and do) mangle the clock registers + * themselves, At some point it is hoped that this function can work + * from a table or calculated register offset / mask. For now this + * is at least better than spreading clock control code around + * U-Boot. + */ + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &exynos_clock->clk_div_peric4; + shift = 8; + break; + case PERIPH_ID_SPI1: + reg = &exynos_clock->clk_div_peric4; + shift = 16; + break; + case PERIPH_ID_SPI2: + reg = &exynos_clock->clk_div_peric4; + shift = 24; + break; + case PERIPH_ID_SPI3: + reg = &exynos_clock->clk_div_isp1; + shift = 0; + break; + case PERIPH_ID_SPI4: + reg = &exynos_clock->clk_div_isp1; + shift = 8; + break; + default: + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return; + } + clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift); +} + +void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor) +{ + unsigned shift; + unsigned mask = 0xf; + u32 *reg; + + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &exynos_clock->clk_div_peric1; + shift = 20; + break; + case PERIPH_ID_SPI1: + reg = &exynos_clock->clk_div_peric1; + shift = 24; + break; + case PERIPH_ID_SPI2: + reg = &exynos_clock->clk_div_peric1; + shift = 28; + break; + case PERIPH_ID_SPI3: + reg = &exynos_clock->clk_div_isp1; + shift = 16; + break; + case PERIPH_ID_SPI4: + reg = &exynos_clock->clk_div_isp1; + shift = 20; + break; + default: + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return; + } + clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift); +} + +/** + * Linearly searches for the most accurate main and fine stage clock scalars + * (divisors) for a specified target frequency and scalar bit sizes by checking + * all multiples of main_scalar_bits values. Will always return scalars up to or + * slower than target. + * + * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32 + * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32 + * @param input_freq Clock frequency to be scaled in Hz + * @param target_freq Desired clock frequency in Hz + * @param best_fine_scalar Pointer to store the fine stage divisor + * + * @return best_main_scalar Main scalar for desired frequency or -1 if none + * found + */ +static int clock_calc_best_scalar(unsigned int main_scaler_bits, + unsigned int fine_scalar_bits, unsigned int input_rate, + unsigned int target_rate, unsigned int *best_fine_scalar) +{ + int i; + int best_main_scalar = -1; + unsigned int best_error = target_rate; + const unsigned int cap = (1 << fine_scalar_bits) - 1; + const unsigned int loops = 1 << main_scaler_bits; + + printk(BIOS_DEBUG, "Input Rate is %u, Target is %u, Cap is %u\n", input_rate, + target_rate, cap); + + ASSERT(best_fine_scalar != NULL); + ASSERT(main_scaler_bits <= fine_scalar_bits); + + *best_fine_scalar = 1; + + if (input_rate == 0 || target_rate == 0) + return -1; + + if (target_rate >= input_rate) + return 1; + + for (i = 1; i <= loops; i++) { + const unsigned int effective_div = MAX(MIN(input_rate / i / + target_rate, cap), 1); + const unsigned int effective_rate = input_rate / i / + effective_div; + const int error = target_rate - effective_rate; + + printk(BIOS_DEBUG, "%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div, + effective_rate, error); + + if (error >= 0 && error <= best_error) { + best_error = error; + best_main_scalar = i; + *best_fine_scalar = effective_div; + } + } + + return best_main_scalar; +} + +int clock_set_rate(enum periph_id periph_id, unsigned int rate) +{ + int main; + unsigned int fine; + + switch (periph_id) { + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + case PERIPH_ID_SPI2: + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); + if (main < 0) { + printk(BIOS_DEBUG, "%s: Cannot set clock rate for periph %d", + __func__, periph_id); + return -1; + } + clock_ll_set_ratio(periph_id, main - 1); + clock_ll_set_pre_ratio(periph_id, fine - 1); + break; + default: + printk(BIOS_DEBUG, "%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return -1; + } + + return 0; +} + +int clock_set_mshci(enum periph_id peripheral) +{ + u32 *addr; + unsigned int clock; + unsigned int tmp; + unsigned int i; + + /* get mpll clock */ + clock = get_pll_clk(MPLL) / 1000000; + + /* + * CLK_DIV_FSYS1 + * MMC0_PRE_RATIO [15:8], MMC0_RATIO [3:0] + * CLK_DIV_FSYS2 + * MMC2_PRE_RATIO [15:8], MMC2_RATIO [3:0] + */ + switch (peripheral) { + case PERIPH_ID_SDMMC0: + addr = &exynos_clock->clk_div_fsys1; + break; + case PERIPH_ID_SDMMC2: + addr = &exynos_clock->clk_div_fsys2; + break; + default: + printk(BIOS_DEBUG, "invalid peripheral\n"); + return -1; + } + tmp = readl(addr) & ~0xff0f; + for (i = 0; i <= 0xf; i++) { + if ((clock / (i + 1)) <= 400) { + writel(tmp | i << 0, addr); + break; + } + } + return 0; +} + +int clock_epll_set_rate(unsigned long rate) +{ + unsigned int epll_con, epll_con_k; + unsigned int i; + unsigned int lockcnt; + struct stopwatch sw; + + epll_con = readl(&exynos_clock->epll_con0); + epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK << + EPLL_CON0_LOCK_DET_EN_SHIFT) | + EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT | + EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT | + EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i].freq_out == rate) + break; + } + + if (i == ARRAY_SIZE(epll_div)) + return -1; + + epll_con_k = epll_div[i].k_dsm << 0; + epll_con |= epll_div[i].en_lock_det << EPLL_CON0_LOCK_DET_EN_SHIFT; + epll_con |= epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT; + epll_con |= epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT; + epll_con |= epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT; + + /* + * Required period ( in cycles) to genarate a stable clock output. + * The maximum clock time can be up to 3000 * PDIV cycles of PLLs + * frequency input (as per spec) + */ + lockcnt = 3000 * epll_div[i].p_div; + + writel(lockcnt, &exynos_clock->epll_lock); + writel(epll_con, &exynos_clock->epll_con0); + writel(epll_con_k, &exynos_clock->epll_con1); + + stopwatch_init_msecs_expire(&sw, TIMEOUT_EPLL_LOCK); + + while (!(readl(&exynos_clock->epll_con0) & + (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) { + if (stopwatch_expired(&sw)) { + printk(BIOS_DEBUG, "%s: Timeout waiting for EPLL lock\n", __func__); + return -1; + } + } + + return 0; +} + +void clock_select_i2s_clk_source(void) +{ + clrsetbits_le32(&exynos_clock->clk_src_peric1, AUDIO1_SEL_MASK, + (CLK_SRC_SCLK_EPLL)); +} + +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq) +{ + unsigned int div ; + + if ((dst_frq == 0) || (src_frq == 0)) { + printk(BIOS_DEBUG, "%s: Invalid requency input for prescaler\n", __func__); + printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq); + return -1; + } + + div = (src_frq / dst_frq); + if (div > AUDIO_1_RATIO_MASK) { + printk(BIOS_DEBUG, "%s: Frequency ratio is out of range\n", __func__); + printk(BIOS_DEBUG, "src frq = %d des frq = %d ", src_frq, dst_frq); + return -1; + } + clrsetbits_le32(&exynos_clock->clk_div_peric4, AUDIO_1_RATIO_MASK, + (div & AUDIO_1_RATIO_MASK)); + return 0; +} diff --git a/src/soc/samsung/exynos5420/clock_init.c b/src/soc/samsung/exynos5420/clock_init.c new file mode 100644 index 0000000000..25b8beecd1 --- /dev/null +++ b/src/soc/samsung/exynos5420/clock_init.c @@ -0,0 +1,223 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Clock setup for SMDK5420 board based on EXYNOS5 */ + +#include +#include +#include +#include +#include +#include +#include + +void system_clock_init(void) +{ + u32 val; + + /* Turn on the MCT as early as possible. */ + exynos_mct->g_tcon |= (1 << 8); + + /* PLL locktime */ + writel(APLL_LOCK_VAL, &exynos_clock->apll_lock); + writel(MPLL_LOCK_VAL, &exynos_clock->mpll_lock); + writel(BPLL_LOCK_VAL, &exynos_clock->bpll_lock); + writel(CPLL_LOCK_VAL, &exynos_clock->cpll_lock); + writel(DPLL_LOCK_VAL, &exynos_clock->dpll_lock); + writel(EPLL_LOCK_VAL, &exynos_clock->epll_lock); + writel(VPLL_LOCK_VAL, &exynos_clock->vpll_lock); + writel(IPLL_LOCK_VAL, &exynos_clock->ipll_lock); + writel(SPLL_LOCK_VAL, &exynos_clock->spll_lock); + writel(KPLL_LOCK_VAL, &exynos_clock->kpll_lock); + writel(RPLL_LOCK_VAL, &exynos_clock->rpll_lock); + + setbits_le32(&exynos_clock->clk_src_cpu, MUX_HPM_SEL_MASK); + + writel(0, &exynos_clock->clk_src_top6); + + writel(0, &exynos_clock->clk_src_cdrex); + writel(SRC_KFC_HPM_SEL, &exynos_clock->clk_src_kfc); + writel(HPM_RATIO, &exynos_clock->clk_div_cpu1); + writel(CLK_DIV_CPU0_VAL, &exynos_clock->clk_div_cpu0); + + /* switch A15 clock source to OSC clock before changing APLL */ + clrbits_le32(&exynos_clock->clk_src_cpu, APLL_FOUT); + + /* Set APLL */ + writel(APLL_CON1_VAL, &exynos_clock->apll_con1); + val = set_pll(225, 3, 0); /* FOUT=1800MHz */ + writel(val, &exynos_clock->apll_con0); + while ((readl(&exynos_clock->apll_con0) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to APLL */ + setbits_le32(&exynos_clock->clk_src_cpu, APLL_FOUT); + + writel(SRC_KFC_HPM_SEL, &exynos_clock->clk_src_kfc); + writel(CLK_DIV_KFC_VAL, &exynos_clock->clk_div_kfc0); + + /* switch A7 clock source to OSC clock before changing KPLL */ + clrbits_le32(&exynos_clock->clk_src_kfc, KPLL_FOUT); + + /* Set KPLL*/ + writel(KPLL_CON1_VAL, &exynos_clock->kpll_con1); + val = set_pll(0x190, 0x4, 0x2); + writel(val, &exynos_clock->kpll_con0); + while ((readl(&exynos_clock->kpll_con0) & PLL_LOCKED) == 0) + ; + + /* now it is safe to switch to KPLL */ + setbits_le32(&exynos_clock->clk_src_kfc, KPLL_FOUT); + + /* Set MPLL */ + writel(MPLL_CON1_VAL, &exynos_clock->mpll_con1); + val = set_pll(0xc8, 0x3, 0x1); + writel(val, &exynos_clock->mpll_con0); + while ((readl(&exynos_clock->mpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set DPLL */ + writel(DPLL_CON1_VAL, &exynos_clock->dpll_con1); + val = set_pll(0x190, 0x4, 0x2); + writel(val, &exynos_clock->dpll_con0); + while ((readl(&exynos_clock->dpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set EPLL */ + writel(EPLL_CON2_VAL, &exynos_clock->epll_con2); + writel(EPLL_CON1_VAL, &exynos_clock->epll_con1); + val = set_pll(0x64, 0x2, 0x1); + writel(val, &exynos_clock->epll_con0); + while ((readl(&exynos_clock->epll_con0) & PLL_LOCKED) == 0) + ; + + /* Set CPLL */ + writel(CPLL_CON1_VAL, &exynos_clock->cpll_con1); + val = set_pll(0xde, 0x4, 0x1); + writel(val, &exynos_clock->cpll_con0); + while ((readl(&exynos_clock->cpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set IPLL */ + writel(IPLL_CON1_VAL, &exynos_clock->ipll_con1); + val = set_pll(0xB9, 0x3, 0x2); + writel(val, &exynos_clock->ipll_con0); + while ((readl(&exynos_clock->ipll_con0) & PLL_LOCKED) == 0) + ; + + /* Set VPLL */ + writel(VPLL_CON1_VAL, &exynos_clock->vpll_con1); + val = set_pll(0xd7, 0x3, 0x2); + writel(val, &exynos_clock->vpll_con0); + while ((readl(&exynos_clock->vpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set BPLL */ + writel(BPLL_CON1_VAL, &exynos_clock->bpll_con1); + val = set_pll(0xc8, 0x3, 0x1); + writel(val, &exynos_clock->bpll_con0); + while ((readl(&exynos_clock->bpll_con0) & PLL_LOCKED) == 0) + ; + + /* Set SPLL */ + writel(SPLL_CON1_VAL, &exynos_clock->spll_con1); + val = set_pll(200, 0x3, 0x2); /* 400MHz */ + writel(val, &exynos_clock->spll_con0); + while ((readl(&exynos_clock->spll_con0) & PLL_LOCKED) == 0) + ; + + /* We use RPLL as the source for FIMD video stream clock */ + writel(RPLL_CON1_VAL, &exynos_clock->rpll_con1); + writel(RPLL_CON2_VAL, &exynos_clock->rpll_con2); + /* computed by gabe from first principles; u-boot is probably + * wrong again + */ + val = set_pll(0xa0, 0x3, 0x2); + writel(val, &exynos_clock->rpll_con0); + /* note: this is a meaningless exercise. The hardware lock + * detection does not work. So this just spins for some + * time and is done. NO indication of success should attach + * to this or any other spin on a con0 value. + */ + while ((readl(&exynos_clock->rpll_con0) & PLL_LOCKED) == 0) + ; + + writel(CLK_DIV_CDREX0_VAL, &exynos_clock->clk_div_cdrex0); + writel(CLK_DIV_CDREX1_VAL, &exynos_clock->clk_div_cdrex1); + + writel(CLK_SRC_TOP0_VAL, &exynos_clock->clk_src_top0); + writel(CLK_SRC_TOP1_VAL, &exynos_clock->clk_src_top1); + writel(CLK_SRC_TOP2_VAL, &exynos_clock->clk_src_top2); + writel(CLK_SRC_TOP7_VAL, &exynos_clock->clk_src_top7); + + writel(CLK_DIV_TOP0_VAL, &exynos_clock->clk_div_top0); + writel(CLK_DIV_TOP1_VAL, &exynos_clock->clk_div_top1); + writel(CLK_DIV_TOP2_VAL, &exynos_clock->clk_div_top2); + + writel(0, &exynos_clock->clk_src_top10); + writel(0, &exynos_clock->clk_src_top11); + writel(0, &exynos_clock->clk_src_top12); + + writel(CLK_SRC_TOP3_VAL, &exynos_clock->clk_src_top3); + writel(CLK_SRC_TOP4_VAL, &exynos_clock->clk_src_top4); + writel(CLK_SRC_TOP5_VAL, &exynos_clock->clk_src_top5); + + /* DISP1 BLK CLK SELECTION */ + writel(CLK_SRC_DISP1_0_VAL, &exynos_clock->clk_src_disp10); + writel(CLK_DIV_DISP1_0_VAL, &exynos_clock->clk_div_disp10); + + /* AUDIO BLK */ + writel(AUDIO0_SEL_EPLL, &exynos_clock->clk_src_mau); + writel(DIV_MAU_VAL, &exynos_clock->clk_div_mau); + + /* FSYS */ + writel(CLK_SRC_FSYS0_VAL, &exynos_clock->clk_src_fsys); + writel(CLK_DIV_FSYS0_VAL, &exynos_clock->clk_div_fsys0); + writel(CLK_DIV_FSYS1_VAL, &exynos_clock->clk_div_fsys1); + writel(CLK_DIV_FSYS2_VAL, &exynos_clock->clk_div_fsys2); + + writel(CLK_SRC_ISP_VAL, &exynos_clock->clk_src_isp); + writel(CLK_DIV_ISP0_VAL, &exynos_clock->clk_div_isp0); + writel(CLK_DIV_ISP1_VAL, &exynos_clock->clk_div_isp1); + + writel(CLK_SRC_PERIC0_VAL, &exynos_clock->clk_src_peric0); + writel(CLK_SRC_PERIC1_VAL, &exynos_clock->clk_src_peric1); + + writel(CLK_DIV_PERIC0_VAL, &exynos_clock->clk_div_peric0); + writel(CLK_DIV_PERIC1_VAL, &exynos_clock->clk_div_peric1); + writel(CLK_DIV_PERIC2_VAL, &exynos_clock->clk_div_peric2); + writel(CLK_DIV_PERIC3_VAL, &exynos_clock->clk_div_peric3); + writel(CLK_DIV_PERIC4_VAL, &exynos_clock->clk_div_peric4); + + writel(CLK_DIV_CPERI1_VAL, &exynos_clock->clk_div_cperi1); + + writel(CLK_DIV2_RATIO, &exynos_clock->clkdiv2_ratio); + writel(CLK_DIV4_RATIO, &exynos_clock->clkdiv4_ratio); + writel(CLK_DIV_G2D, &exynos_clock->clk_div_g2d); + + writel(CLK_SRC_CPU_VAL, &exynos_clock->clk_src_cpu); + writel(CLK_SRC_TOP6_VAL, &exynos_clock->clk_src_top6); + writel(CLK_SRC_CDREX_VAL, &exynos_clock->clk_src_cdrex); + writel(CLK_SRC_KFC_VAL, &exynos_clock->clk_src_kfc); +} + +void clock_gate(void) +{ + /* Not implemented for now. */ +} diff --git a/src/soc/samsung/exynos5420/cpu.c b/src/soc/samsung/exynos5420/cpu.c new file mode 100644 index 0000000000..6a7dc51e3a --- /dev/null +++ b/src/soc/samsung/exynos5420/cpu.c @@ -0,0 +1,183 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static unsigned int cpu_id; +static unsigned int cpu_rev; + +static void set_cpu_id(void) +{ + u32 pro_id = (read32((void *)EXYNOS5_PRO_ID) & 0x00FFF000) >> 12; + + switch (pro_id) { + case 0x200: + /* Exynos4210 EVT0 */ + cpu_id = 0x4210; + cpu_rev = 0; + break; + case 0x210: + /* Exynos4210 EVT1 */ + cpu_id = 0x4210; + break; + case 0x412: + /* Exynos4412 */ + cpu_id = 0x4412; + break; + case 0x520: + /* Exynos5250 */ + cpu_id = 0x5250; + break; + case 0x420: + /* Exynos5420 */ + cpu_id = 0x5420; + break; + } +} + +/* we distinguish a display port device from a raw graphics device + * because there are dramatic differences in startup depending on + * graphics usage. To make startup fast and easier to understand and + * debug we explicitly name this common case. The alternate approach, + * involving lots of machine and callbacks, is hard to debug and + * verify. + */ +static void exynos_displayport_init(device_t dev, u32 lcdbase, + unsigned long fb_size) +{ + struct soc_samsung_exynos5420_config *conf = dev->chip_info; + /* put these on the stack. If, at some point, we want to move + * this code to a pre-ram stage, it will be much easier. + */ + struct exynos5_fimd_panel panel; + memset(&panel, 0, sizeof(panel)); + + panel.is_dp = 1; /* Display I/F is eDP */ + /* while it is true that we did a memset to zero, + * we leave some 'set to zero' entries here to make + * it clear what's going on. Graphics is confusing. + */ + panel.is_mipi = 0; + panel.fixvclk = 0; + panel.ivclk = 0; + panel.clkval_f = conf->clkval_f; + panel.upper_margin = conf->upper_margin; + panel.lower_margin = conf->lower_margin; + panel.vsync = conf->vsync; + panel.left_margin = conf->left_margin; + panel.right_margin = conf->right_margin; + panel.hsync = conf->hsync; + panel.xres = conf->xres; + panel.yres = conf->yres; + + printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase)); + memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */ + + /* + * We need to clean and invalidate the framebuffer region and disable + * caching as well. We assume that our dcache <--> memory address + * space is identity-mapped in 1MB chunks, so align accordingly. + * + * Note: We may want to do something clever to ensure the framebuffer + * region is aligned such that we don't change dcache policy for other + * stuff inadvertantly. + */ + uint32_t lower = ALIGN_DOWN(lcdbase, MiB); + uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB); + + dcache_clean_invalidate_by_mva((void *)lower, upper - lower); + mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF); + + mmio_resource(dev, 1, lcdbase/KiB, (fb_size + KiB - 1)/KiB); +} + +static void tps65090_thru_ec_fet_disable(int index) +{ + uint8_t value = 0; + + if (google_chromeec_i2c_xfer(0x48, 0xe + index, 1, &value, 1, 0)) { + printk(BIOS_ERR, + "Error sending i2c pass through command to EC.\n"); + return; + } +} + +static void cpu_enable(device_t dev) +{ + unsigned long fb_size = FB_SIZE_KB * KiB; + u32 lcdbase = get_fb_base_kb() * KiB; + + ram_resource(dev, 0, RAM_BASE_KB, RAM_SIZE_KB - FB_SIZE_KB); + mmio_resource(dev, 1, lcdbase / KiB, (fb_size + KiB - 1) / KiB); + + /* + * Disable LCD FETs before we do anything with the display. + * FIXME(dhendrix): This is a gross hack and should be done + * elsewhere (romstage?). + */ + tps65090_thru_ec_fet_disable(1); + tps65090_thru_ec_fet_disable(6); + + exynos_displayport_init(dev, lcdbase, fb_size); + + set_cpu_id(); +} + +static void cpu_init(device_t dev) +{ + printk(BIOS_INFO, "CPU: S5P%X @ %ldMHz\n", + cpu_id, get_arm_clk() / 1000000); +} + +static void cpu_noop(device_t dev) +{ +} + +static struct device_operations cpu_ops = { + .read_resources = cpu_noop, + .set_resources = cpu_noop, + .enable_resources = cpu_enable, + .init = cpu_init, + .scan_bus = 0, +}; + +static void enable_exynos5420_dev(device_t dev) +{ + dev->ops = &cpu_ops; +} + +struct chip_operations soc_samsung_exynos5420_ops = { + CHIP_NAME("SOC Samsung Exynos 5420") + .enable_dev = enable_exynos5420_dev, +}; diff --git a/src/soc/samsung/exynos5420/dmc_common.c b/src/soc/samsung/exynos5420/dmc_common.c new file mode 100644 index 0000000000..7827782d51 --- /dev/null +++ b/src/soc/samsung/exynos5420/dmc_common.c @@ -0,0 +1,174 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mem setup common file for different types of DDR present on SMDK5420 boards. + */ + +#include +#include +#include +#include +#include +#include + +#define ZQ_INIT_TIMEOUT 10000 + +int dmc_config_zq(struct mem_timings *mem, + struct exynos5_phy_control *phy0_ctrl, + struct exynos5_phy_control *phy1_ctrl) +{ + unsigned long val = 0; + int i; + + /* + * ZQ Calibration: + * Select Driver Strength, + * long calibration for manual calibration + */ + val = PHY_CON16_RESET_VAL; + val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT; + val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT; + val |= ZQ_CLK_DIV_EN; + writel(val, &phy0_ctrl->phy_con16); + writel(val, &phy1_ctrl->phy_con16); + + /* Disable termination */ + if (mem->zq_mode_noterm) + val |= PHY_CON16_ZQ_MODE_NOTERM_MASK; + writel(val, &phy0_ctrl->phy_con16); + writel(val, &phy1_ctrl->phy_con16); + + /* ZQ_MANUAL_START: Enable */ + val |= ZQ_MANUAL_STR; + writel(val, &phy0_ctrl->phy_con16); + writel(val, &phy1_ctrl->phy_con16); + + /* ZQ_MANUAL_START: Disable */ + val &= ~ZQ_MANUAL_STR; + + /* + * Since we are manaully calibrating the ZQ values, + * we are looping for the ZQ_init to complete. + */ + i = ZQ_INIT_TIMEOUT; + while ((readl(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + udelay(1); + i--; + } + if (!i) + return -1; + writel(val, &phy0_ctrl->phy_con16); + + i = ZQ_INIT_TIMEOUT; + while ((readl(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) { + udelay(1); + i--; + } + if (!i) + return -1; + writel(val, &phy1_ctrl->phy_con16); + + return 0; +} + +void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode) +{ + unsigned long val; + + if (mode == DDR_MODE_DDR3) { + val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE; + writel(val, &dmc->phycontrol0); + } + + /* Update DLL Information: Force DLL Resyncronization */ + val = readl(&dmc->phycontrol0); + val |= FP_RSYNC; + writel(val, &dmc->phycontrol0); + + /* Reset Force DLL Resyncronization */ + val = readl(&dmc->phycontrol0); + val &= ~FP_RSYNC; + writel(val, &dmc->phycontrol0); +} + +void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc) +{ + int channel, chip; + + for (channel = 0; channel < mem->dmc_channels; channel++) { + unsigned long mask; + + mask = channel << DIRECT_CMD_CHANNEL_SHIFT; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + int i; + + mask |= chip << DIRECT_CMD_CHIP_SHIFT; + + /* Sending NOP command */ + writel(DIRECT_CMD_NOP | mask, &dmc->directcmd); + + /* + * TODO(alim.akhtar@samsung.com): Do we need these + * delays? This one and the next were not there for + * DDR3. + */ + udelay(100); + + /* Sending EMRS/MRS commands */ + for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { + writel(mem->direct_cmd_msr[i] | mask, + &dmc->directcmd); + udelay(100); + } + + if (mem->send_zq_init) { + /* Sending ZQINIT command */ + writel(DIRECT_CMD_ZQINIT | mask, + &dmc->directcmd); + /* + * FIXME: This was originally sdelay(10000) + * in the imported u-boot code. That may have + * been meant to be sdelay(0x10000) since that + * was used elsewhere in this function. Either + * way seems to work, though. + */ + udelay(12); + } + } + } +} + +void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc) +{ + int channel, chip; + + for (channel = 0; channel < mem->dmc_channels; channel++) { + unsigned long mask; + + mask = channel << DIRECT_CMD_CHANNEL_SHIFT; + for (chip = 0; chip < mem->chips_per_channel; chip++) { + mask |= chip << DIRECT_CMD_CHIP_SHIFT; + + /* PALL (all banks precharge) CMD */ + writel(DIRECT_CMD_PALL | mask, &dmc->directcmd); + udelay(100); + } + } +} + diff --git a/src/soc/samsung/exynos5420/dmc_init_ddr3.c b/src/soc/samsung/exynos5420/dmc_init_ddr3.c new file mode 100644 index 0000000000..dee97916cc --- /dev/null +++ b/src/soc/samsung/exynos5420/dmc_init_ddr3.c @@ -0,0 +1,350 @@ +/* + * This file is part of the coreboot project. + * + * DDR3 mem setup file for EXYNOS5 based board + * + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT 10000 + +/* 'reset' field is currently ignored. */ + +int ddr3_mem_ctrl_init(struct mem_timings *mem, int interleave_size, int reset) +{ + u32 val, nLockR, nLockW_phy0, nLockW_phy1; + int i, chip; + + /* Enable PAUSE for DREX */ + setbits_le32(&exynos_clock->pause, ENABLE_BIT); + + /* Enable BYPASS mode */ + setbits_le32(&exynos_clock->bpll_con1, BYPASS_EN); + + writel(MUX_BPLL_SEL_FOUTBPLL, &exynos_clock->clk_src_cdrex); + do { + val = readl(&exynos_clock->clk_mux_stat_cdrex); + val &= BPLL_SEL_MASK; + } while (val != FOUTBPLL); + + clrbits_le32(&exynos_clock->bpll_con1, BYPASS_EN); + + /* Specify the DDR memory type as DDR3 */ + val = readl(&exynos_phy0_control->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (mem->mem_type << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &exynos_phy0_control->phy_con0); + + val = readl(&exynos_phy1_control->phy_con0); + val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK << PHY_CON0_CTRL_DDR_MODE_SHIFT); + val |= (mem->mem_type << PHY_CON0_CTRL_DDR_MODE_SHIFT); + writel(val, &exynos_phy1_control->phy_con0); + + /* Set Read Latency and Burst Length for PHY0 and PHY1 */ + val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) | + (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT); + writel(val, &exynos_phy0_control->phy_con42); + writel(val, &exynos_phy1_control->phy_con42); + + val = readl(&exynos_phy0_control->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &exynos_phy0_control->phy_con26); + + val = readl(&exynos_phy1_control->phy_con26); + val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET); + val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET); + writel(val, &exynos_phy1_control->phy_con26); + + /* Set Driver strength for CK, CKE, CS & CA to 0x7 + * Set Driver strength for Data Slice 0~3 to 0x6 + */ + val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 << CA_CKE_DRVR_DS_OFFSET) | + (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 << CA_ADR_DRVR_DS_OFFSET); + val |= (0x7 << DA_3_DS_OFFSET) | (0x7 << DA_2_DS_OFFSET) | + (0x7 << DA_1_DS_OFFSET) | (0x7 << DA_0_DS_OFFSET); + writel(val, &exynos_phy0_control->phy_con39); + writel(val, &exynos_phy1_control->phy_con39); + + /* ZQ Calibration */ + if (dmc_config_zq(mem, exynos_phy0_control, exynos_phy1_control)) + return SETUP_ERR_ZQ_CALIBRATION_FAILURE; + + clrbits_le32(&exynos_phy0_control->phy_con16, ZQ_CLK_DIV_EN); + clrbits_le32(&exynos_phy1_control->phy_con16, ZQ_CLK_DIV_EN); + + /* DQ Signal */ + val = readl(&exynos_phy0_control->phy_con14); + val |= mem->phy0_pulld_dqs; + writel(val, &exynos_phy0_control->phy_con14); + val = readl(&exynos_phy1_control->phy_con14); + val |= mem->phy1_pulld_dqs; + writel(val, &exynos_phy1_control->phy_con14); + + val = MEM_TERM_EN | PHY_TERM_EN; + writel(val, &exynos_drex0->phycontrol0); + writel(val, &exynos_drex1->phycontrol0); + + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &exynos_drex0->concontrol); + writel(mem->concontrol | + (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT), + &exynos_drex1->concontrol); + + do { + val = readl(&exynos_drex0->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + do { + val = readl(&exynos_drex1->phystatus); + } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE); + + clrbits_le32(&exynos_drex0->concontrol, DFI_INIT_START); + clrbits_le32(&exynos_drex1->concontrol, DFI_INIT_START); + + update_reset_dll(exynos_drex0, mem->mem_type); + update_reset_dll(exynos_drex1, mem->mem_type); + + /* MEMBASECONFIG0 (CS0) */ + writel(mem->membaseconfig0, &exynos_tzasc0->membaseconfig0); + writel(mem->membaseconfig0, &exynos_tzasc1->membaseconfig0); + + /* MEMBASECONFIG1 (CS1) */ + if (mem->chips_per_channel == 2) { + writel(mem->membaseconfig1, &exynos_tzasc0->membaseconfig1); + writel(mem->membaseconfig1, &exynos_tzasc1->membaseconfig1); + } + + /* Memory Channel Inteleaving Size + * Exynos5420 Channel interleaving = 128 bytes + */ + /* MEMCONFIG0/1 */ + writel(mem->memconfig, &exynos_tzasc0->memconfig0); + writel(mem->memconfig, &exynos_tzasc1->memconfig0); + writel(mem->memconfig, &exynos_tzasc0->memconfig1); + writel(mem->memconfig, &exynos_tzasc1->memconfig1); + + /* Precharge Configuration */ + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &exynos_drex0->prechconfig0); + writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT, + &exynos_drex1->prechconfig0); + + /* TimingRow, TimingData, TimingPower and Timingaref + * values as per Memory AC parameters + */ + writel(mem->timing_ref, &exynos_drex0->timingref); + writel(mem->timing_ref, &exynos_drex1->timingref); + writel(mem->timing_row, &exynos_drex0->timingrow); + writel(mem->timing_row, &exynos_drex1->timingrow); + writel(mem->timing_data, &exynos_drex0->timingdata); + writel(mem->timing_data, &exynos_drex1->timingdata); + writel(mem->timing_power, &exynos_drex0->timingpower); + writel(mem->timing_power, &exynos_drex1->timingpower); + + if (reset) { + /* Send NOP, MRS and ZQINIT commands. + * Sending MRS command will reset the DRAM. We should not be + * reseting the DRAM after resume, this will lead to memory + * corruption as DRAM content is lost after DRAM reset. + */ + dmc_config_mrs(mem, exynos_drex0); + dmc_config_mrs(mem, exynos_drex1); + } else { + u32 ret; + + /* + * During Suspend-Resume & S/W-Reset, as soon as PMU releases + * pad retention, CKE goes high. This causes memory contents + * not to be retained during DRAM initialization. Therfore, + * there is a new control register(0x100431e8[28]) which lets us + * release pad retention and retain the memory content until the + * initialization is complete. + */ + write32(PAD_RETENTION_DRAM_COREBLK_VAL, + &exynos_power->padret_dram_cblk_opt); + do { + ret = read32(&exynos_power->padret_dram_status); + } while (ret != 0x1); + + /* + * CKE PAD retention disables DRAM self-refresh mode. + * Send auto refresh command for DRAM refresh. + */ + for (i = 0; i < 128; i++) { + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex0->directcmd); + writel(DIRECT_CMD_REFA | + (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex1->directcmd); + } + } + } + + if (mem->gate_leveling_enable) { + + writel(PHY_CON0_RESET_VAL, &exynos_phy0_control->phy_con0); + writel(PHY_CON0_RESET_VAL, &exynos_phy1_control->phy_con0); + + setbits_le32(&exynos_phy0_control->phy_con0, P0_CMD_EN); + setbits_le32(&exynos_phy1_control->phy_con0, P0_CMD_EN); + + val = PHY_CON2_RESET_VAL; + val |= INIT_DESKEW_EN; + writel(val, &exynos_phy0_control->phy_con2); + writel(val, &exynos_phy1_control->phy_con2); + + val = readl(&exynos_phy0_control->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &exynos_phy0_control->phy_con1); + + val = readl(&exynos_phy1_control->phy_con1); + val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET); + writel(val, &exynos_phy1_control->phy_con1); + + nLockR = readl(&exynos_phy0_control->phy_con13); + nLockW_phy0 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2; + nLockR = readl(&exynos_phy0_control->phy_con12); + nLockR &= ~CTRL_DLL_ON; + nLockR |= nLockW_phy0; + writel(nLockR, &exynos_phy0_control->phy_con12); + + nLockR = readl(&exynos_phy1_control->phy_con13); + nLockW_phy1 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2; + nLockR = readl(&exynos_phy1_control->phy_con12); + nLockR &= ~CTRL_DLL_ON; + nLockR |= nLockW_phy1; + writel(nLockR, &exynos_phy1_control->phy_con12); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4; + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex1->directcmd); + } + + setbits_le32(&exynos_phy0_control->phy_con2, RDLVL_GATE_EN); + setbits_le32(&exynos_phy1_control->phy_con2, RDLVL_GATE_EN); + + setbits_le32(&exynos_phy0_control->phy_con0, CTRL_SHGATE); + setbits_le32(&exynos_phy1_control->phy_con0, CTRL_SHGATE); + + val = readl(&exynos_phy0_control->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &exynos_phy0_control->phy_con1); + + val = readl(&exynos_phy1_control->phy_con1); + val &= ~(CTRL_GATEDURADJ_MASK); + writel(val, &exynos_phy1_control->phy_con1); + + writel(CTRL_RDLVL_GATE_ENABLE, &exynos_drex0->rdlvl_config); + i = TIMEOUT; + while (((readl(&exynos_drex0->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + udelay(1); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &exynos_drex0->rdlvl_config); + + writel(CTRL_RDLVL_GATE_ENABLE, &exynos_drex1->rdlvl_config); + i = TIMEOUT; + while (((readl(&exynos_drex1->phystatus) & RDLVL_COMPLETE_CHO) + != RDLVL_COMPLETE_CHO) && (i > 0)) { + /* + * TODO(waihong): Comment on how long this take to + * timeout + */ + udelay(1); + i--; + } + if (!i) + return SETUP_ERR_RDLV_COMPLETE_TIMEOUT; + writel(CTRL_RDLVL_GATE_DISABLE, &exynos_drex1->rdlvl_config); + + writel(0, &exynos_phy0_control->phy_con14); + writel(0, &exynos_phy1_control->phy_con14); + + val = (0x3 << DIRECT_CMD_BANK_SHIFT); + for (chip = 0; chip < mem->chips_to_configure; chip++) { + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex0->directcmd); + writel(val | (chip << DIRECT_CMD_CHIP_SHIFT), + &exynos_drex1->directcmd); + } + + /* Common Settings for Leveling */ + val = PHY_CON12_RESET_VAL; + writel((val + nLockW_phy0), &exynos_phy0_control->phy_con12); + writel((val + nLockW_phy1), &exynos_phy1_control->phy_con12); + + setbits_le32(&exynos_phy0_control->phy_con2, DLL_DESKEW_EN); + setbits_le32(&exynos_phy1_control->phy_con2, DLL_DESKEW_EN); + } + + /* Send PALL command */ + dmc_config_prech(mem, exynos_drex0); + dmc_config_prech(mem, exynos_drex1); + + writel(mem->memcontrol, &exynos_drex0->memcontrol); + writel(mem->memcontrol, &exynos_drex1->memcontrol); + + /* + * Set DMC Concontrol: Enable auto-refresh counter, provide + * read data fetch cycles and enable DREX auto set powerdown + * for input buffer of I/O in none read memory state. + */ + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &exynos_drex0->concontrol); + writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) | + (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)| + DMC_CONCONTROL_IO_PD_CON(0x2), + &exynos_drex1->concontrol); + + /* Enable Clock Gating Control for DMC + * this saves around 25 mw dmc power as compared to the power + * consumption without these bits enabled + */ + setbits_le32(&exynos_drex0->cgcontrol, DMC_INTERNAL_CG); + setbits_le32(&exynos_drex1->cgcontrol, DMC_INTERNAL_CG); + + return 0; +} diff --git a/src/soc/samsung/exynos5420/dp.c b/src/soc/samsung/exynos5420/dp.c new file mode 100644 index 0000000000..c9fdd76232 --- /dev/null +++ b/src/soc/samsung/exynos5420/dp.c @@ -0,0 +1,909 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Here is the rough outline of how we bring up the display: + * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD + * 2. Source determines video mode by reading DPCD receiver capability field + * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD + * 0000Dh). + * 3. Sink replies DPCD receiver capability field. + * 4. Source starts EDID read thru I2C-over-AUX. + * 5. Sink replies EDID thru I2C-over-AUX. + * 6. Source determines link configuration, such as MAX_LINK_RATE and + * MAX_LANE_COUNT. Source also determines which type of eDP Authentication + * method to use and writes DPCD link configuration field (DPCD 00100h to + * 0010Ah) including eDP configuration set (DPCD 0010Ah). + * 7. Source starts link training. Sink does clock recovery and equalization. + * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh). + * 9. Sink replies DPCD link status field. If main link is not stable, Source + * repeats Step 7. + * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video + * parameters and recovers stream clock. + * 11. Source sends video data. + */ + + +static int exynos_dp_init_dp(void) +{ + int ret; + exynos_dp_reset(); + + /* SW defined function Normal operation */ + exynos_dp_enable_sw_func(DP_ENABLE); + + ret = exynos_dp_init_analog_func(); + if (ret != EXYNOS_DP_SUCCESS) + return ret; + + exynos_dp_init_hpd(); + exynos_dp_init_aux(); + + return ret; +} + +static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) +{ + int i; + unsigned char sum = 0; + + for (i = 0; i < EDID_BLOCK_LENGTH; i++) + sum = sum + edid_data[i]; + + return sum; +} + +static unsigned int exynos_dp_read_edid(void) +{ + unsigned char edid[EDID_BLOCK_LENGTH * 2]; + unsigned int extend_block = 0; + unsigned char sum; + unsigned char test_vector; + int retval = 0; + + /* + * EDID device address is 0x50. + * However, if necessary, you must have set upper address + * into E-EDID in I2C device, 0x30. + */ + + /* Read Extension Flag, Number of 128-byte EDID extension blocks */ + if (exynos_dp_read_byte_from_i2c + (I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, &extend_block)) + return -1; + + if (extend_block > 0) { + /* Read EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + + if (retval != 0) { + printk(BIOS_ERR, "DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(edid); + if (sum != 0) { + printk(BIOS_ERR, "DP EDID bad checksum!\n"); + return -1; + } + /* Read additional EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_BLOCK_LENGTH, + EDID_BLOCK_LENGTH, + &edid[EDID_BLOCK_LENGTH]); + if (retval != 0) { + printk(BIOS_ERR, "DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); + if (sum != 0) { + printk(BIOS_ERR, "DP EDID bad checksum!\n"); + return -1; + } + exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + &test_vector); + if (test_vector & DPCD_TEST_EDID_READ) { + exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + DPCD_TEST_EDID_CHECKSUM_WRITE); + } + } else { + /* Read EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + + if (retval != 0) { + printk(BIOS_ERR, "DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(edid); + if (sum != 0) { + printk(BIOS_ERR, "DP EDID bad checksum!\n"); + return -1; + } + + exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + &test_vector); + if (test_vector & DPCD_TEST_EDID_READ) { + exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + edid[EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + DPCD_TEST_EDID_CHECKSUM_WRITE); + } + + } + + return 0; +} + +static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) +{ + unsigned char buf[12]; + unsigned int ret; + unsigned char temp; + unsigned char retry_cnt; + unsigned char dpcd_rev[16]; + unsigned char lane_bw[16]; + unsigned char lane_cnt[16]; + + memset(dpcd_rev, 0, sizeof(dpcd_rev)); + memset(lane_bw, 0, sizeof(lane_bw)); + memset(lane_cnt, 0, sizeof(lane_cnt)); + memset(buf, 0, sizeof(buf)); + + retry_cnt = 5; + while (retry_cnt) { + /* Read DPCD 0x0000-0x000b */ + ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12, + buf); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP read_byte_from_dpcd() failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + /* */ + temp = buf[DPCD_DPCD_REV]; + if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11) + edp_info->dpcd_rev = temp; + else { + printk(BIOS_ERR, "DP Wrong DPCD Rev : %x\n", temp); + return -1; + } + temp = buf[DPCD_MAX_LINK_RATE]; + if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70) + edp_info->lane_bw = temp; + else { + printk(BIOS_ERR, "DP Wrong MAX LINK RATE : %x\n", temp); + return -1; + } + /*Refer VESA Display Port Stnadard Ver1.1a Page 120 */ + if (edp_info->dpcd_rev == DP_DPCD_REV_11) { + temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f; + if (buf[DPCD_MAX_LANE_COUNT] & 0x80) + edp_info->dpcd_efc = 1; + else + edp_info->dpcd_efc = 0; + } else { + temp = buf[DPCD_MAX_LANE_COUNT]; + edp_info->dpcd_efc = 0; + } + + if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 || + temp == DP_LANE_CNT_4) { + edp_info->lane_cnt = temp; + } else { + printk(BIOS_ERR, "DP Wrong MAX LANE COUNT : %x\n", temp); + return -1; + } + + if (edp_info->raw_edid){ + ret = EXYNOS_DP_SUCCESS; + printk(BIOS_SPEW, "EDID compiled in, skipping read\n"); + } else { + ret = exynos_dp_read_edid(); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP exynos_dp_read_edid() failed\n"); + return -1; + } + } + + return ret; +} + +static void exynos_dp_init_training(void) +{ + /* + * MACRO_RST must be applied after the PLL_LOCK to avoid + * the DP inter pair skew issue for at least 10 us + */ + exynos_dp_reset_macro(); + + /* All DP analog module power up */ + exynos_dp_set_analog_power_down(POWER_ALL, 0); +} + +static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) +{ + unsigned char buf[5]; + unsigned int ret; + + edp_info->lt_info.lt_status = DP_LT_CR; + edp_info->lt_info.ep_loop = 0; + edp_info->lt_info.cr_loop[0] = 0; + edp_info->lt_info.cr_loop[1] = 0; + edp_info->lt_info.cr_loop[2] = 0; + edp_info->lt_info.cr_loop[3] = 0; + + /* Set sink to D0 (Sink Not Ready) mode. */ + ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE, + DPCD_SET_POWER_STATE_D0); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write_dpcd_byte failed\n"); + return ret; + } + + /* Set link rate and count as you want to establish*/ + exynos_dp_set_link_bandwidth(edp_info->lane_bw); + exynos_dp_set_lane_count(edp_info->lane_cnt); + + /* Setup RX configuration */ + buf[0] = edp_info->lane_bw; + buf[1] = edp_info->lane_cnt; + + ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2, + buf); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write_dpcd_byte failed\n"); + return ret; + } + + exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0, + edp_info->lane_cnt); + + /* Set training pattern 1 */ + exynos_dp_set_training_pattern(TRAINING_PTN1); + + /* Set RX training pattern */ + buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; + + buf[1] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[2] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[3] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + + ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET, + 5, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write_dpcd_byte failed\n"); + return ret; + } + return ret; +} + +static unsigned int exynos_dp_training_pattern_dis(void) +{ + unsigned int ret; + + exynos_dp_set_training_pattern(DP_NONE); + + ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + DPCD_TRAINING_PATTERN_DISABLED); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP requst_link_traninig_req failed\n"); + return -1; + } + + return ret; +} + +static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) +{ + unsigned char data; + unsigned int ret; + + ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET, + &data); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read_from_dpcd failed\n"); + return -1; + } + + if (enable) + data = DPCD_ENHANCED_FRAME_EN | DPCD_LN_COUNT_SET(data); + else + data = DPCD_LN_COUNT_SET(data); + + ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET, + data); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write_to_dpcd failed\n"); + return -1; + + } + + return ret; +} + +static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode) +{ + unsigned int ret; + + ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP rx_enhance_mode failed\n"); + return -1; + } + + exynos_dp_enable_enhanced_mode(enhance_mode); + + return ret; +} + +static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, + unsigned char *status) +{ + unsigned int ret, i; + unsigned char buf[2]; + unsigned char lane_stat[DP_LANE_CNT_4] = {0,}; + const unsigned char shift_val[] = {0, 4, 0, 4}; + + ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read lane status failed\n"); + return ret; + } + + for (i = 0; i < edp_info->lane_cnt; i++) { + lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f; + if (lane_stat[0] != lane_stat[i]) { + printk(BIOS_ERR, "Wrong lane status\n"); + return -1; + } + } + + *status = lane_stat[0]; + + return ret; +} + +static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, + unsigned char *sw, unsigned char *em) +{ + const unsigned char shift_val[] = {0, 4, 0, 4}; + unsigned int ret; + unsigned char buf; + unsigned int dpcd_addr; + + /*lane_num value is used as arry index, so this range 0 ~ 3 */ + dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); + + ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read adjust request failed\n"); + return -1; + } + + *sw = ((buf >> shift_val[lane_num]) & 0x03); + *em = ((buf >> shift_val[lane_num]) & 0x0c) >> 2; + + return ret; +} + +static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) +{ + int ret; + + ret = exynos_dp_training_pattern_dis(); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP training_patter_disable() failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP set_enhanced_mode() failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + return ret; +} + +static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) +{ + int ret; + + if (edp_info->lane_bw == DP_LANE_BW_2_70) { + edp_info->lane_bw = DP_LANE_BW_1_62; + printk(BIOS_ERR, "DP Change lane bw to 1.62Gbps\n"); + edp_info->lt_info.lt_status = DP_LT_START; + ret = EXYNOS_DP_SUCCESS; + } else { + ret = exynos_dp_training_pattern_dis(); + if (ret != EXYNOS_DP_SUCCESS) + printk(BIOS_ERR, "DP training_patter_disable() failed\n"); + + ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + if (ret != EXYNOS_DP_SUCCESS) + printk(BIOS_ERR, "DP set_enhanced_mode() failed\n"); + + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + return ret; +} + +static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info + *edp_info) +{ + unsigned int ret; + unsigned char lane_stat; + unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0, }; + unsigned int i; + unsigned char adj_req_sw; + unsigned char adj_req_em; + unsigned char buf[5]; + + mdelay(1); + + ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read lane status failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + if (lane_stat & DP_LANE_STAT_CR_DONE) { + printk(BIOS_DEBUG,"DP clock Recovery training succeed\n"); + exynos_dp_set_training_pattern(TRAINING_PTN2); + + for (i = 0; i < edp_info->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw, + &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) + || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | + MAX_PRE_EMPHASIS_REACH_3; + } + exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + } + + buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2; + buf[1] = lt_ctl_val[0]; + buf[2] = lt_ctl_val[1]; + buf[3] = lt_ctl_val[2]; + buf[4] = lt_ctl_val[3]; + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_PATTERN_SET, 5, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write training pattern1 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } else + edp_info->lt_info.lt_status = DP_LT_ET; + } else { + for (i = 0; i < edp_info->lane_cnt; i++) { + lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i); + ret = exynos_dp_read_dpcd_adj_req(i, + &adj_req_sw, &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read adj req failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) + ret = exynos_dp_reduce_link_rate(edp_info); + + if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == + adj_req_sw) && + (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) == + adj_req_em)) { + edp_info->lt_info.cr_loop[i]++; + if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) + ret = exynos_dp_reduce_link_rate( + edp_info); + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | + MAX_PRE_EMPHASIS_REACH_3; + } + exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + } + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP write training pattern2 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + } + + return ret; +} + +static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info + *edp_info) +{ + unsigned int ret; + unsigned char lane_stat, adj_req_sw, adj_req_em, i; + unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0,}; + unsigned char interlane_aligned = 0; + unsigned char f_bw; + unsigned char f_lane_cnt; + unsigned char sink_stat; + + mdelay(1); + + ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read lane status failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + printk(BIOS_DEBUG,"DP lane stat : %x\n", lane_stat); + + if (lane_stat & DP_LANE_STAT_CR_DONE) { + printk(BIOS_DEBUG, "DP_LANE_STAT_CR_DONE ok\n"); + ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED, + &sink_stat); + if (ret != EXYNOS_DP_SUCCESS) { + edp_info->lt_info.lt_status = DP_LT_FAIL; + printk(BIOS_ERR, "DP read DPCD_LN_ALIGN_UPDATED failed\n"); + return ret; + } + + interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); + printk(BIOS_DEBUG, "interlane_aligned: %d\n", interlane_aligned); + printk(BIOS_DEBUG, "Check %d lanes\n", edp_info->lane_cnt); + + for (i = 0; i < edp_info->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(i, + &adj_req_sw, &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP read adj req 1 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + + return ret; + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3; + lt_ctl_val[i] |= MAX_PRE_EMPHASIS_REACH_3; + } + } + + if (((lane_stat&DP_LANE_STAT_CE_DONE) && + (lane_stat&DP_LANE_STAT_SYM_LOCK)) + && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { + printk(BIOS_DEBUG,"DP Equalizer training succeed\n"); + + f_bw = exynos_dp_get_link_bandwidth(); + f_lane_cnt = exynos_dp_get_lane_count(); + + printk(BIOS_DEBUG,"DP final BandWidth : %x\n", f_bw); + printk(BIOS_DEBUG,"DP final Lane Count : %x\n", f_lane_cnt); + + edp_info->lt_info.lt_status = DP_LT_FINISHED; + + exynos_dp_equalizer_err_link(edp_info); + + } else { + edp_info->lt_info.ep_loop++; + + if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { + if (edp_info->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate( + edp_info); + } else { + edp_info->lt_info.lt_status = + DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + } else { + for (i = 0; i < edp_info->lane_cnt; i++) + exynos_dp_set_lanex_pre_emphasis( + lt_ctl_val[i], i); + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_LANE0_SET, + 4, lt_ctl_val); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP set lt pattern failed\n"); + edp_info->lt_info.lt_status = + DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + } + } + } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate(edp_info); + } else { + edp_info->lt_info.lt_status = DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + + return ret; +} + +static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) +{ + /* the C compiler is almost smart enough to know this gets set. + * But not quite. + */ + unsigned int ret = 0; + int training_finished; + + /* Turn off unnecessary lane */ + if (edp_info->lane_cnt == 1) + exynos_dp_set_analog_power_down(CH1_BLOCK, 1); + + training_finished = 0; + + edp_info->lt_info.lt_status = DP_LT_START; + + /* Process here */ + while (!training_finished) { + switch (edp_info->lt_info.lt_status) { + case DP_LT_START: + ret = exynos_dp_link_start(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP LT:link start failed\n"); + training_finished = 1; + } + break; + case DP_LT_CR: + ret = exynos_dp_process_clock_recovery(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP LT:clock recovery failed\n"); + training_finished = 1; + } + break; + case DP_LT_ET: + ret = exynos_dp_process_equalizer_training(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP LT:equalizer training failed\n"); + training_finished = 1; + } + break; + case DP_LT_FINISHED: + training_finished = 1; + break; + case DP_LT_FAIL: + printk(BIOS_ERR,"DP: %s: DP_LT_FAIL: failed\n", __func__); + training_finished = 1; + ret = -1; + } + } + + return ret; +} + +static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info) +{ + unsigned int ret; + + exynos_dp_init_training(); + + ret = exynos_dp_sw_link_training(edp_info); + if (ret != EXYNOS_DP_SUCCESS) + printk(BIOS_ERR, "DP dp_sw_link_traning() failed\n"); + + return ret; +} + +static void exynos_dp_enable_scramble(unsigned int enable) +{ + unsigned char data; + + if (enable) { + exynos_dp_enable_scrambling(DP_ENABLE); + + exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); + } else { + exynos_dp_enable_scrambling(DP_DISABLE); + exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + (u8)(data | DPCD_SCRAMBLING_DISABLED)); + } +} + +static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) +{ + unsigned int ret = 0; + unsigned int retry_cnt; + + mdelay(1); + + if (edp_info->video_info.master_mode) { + printk(BIOS_ERR, + "DP does not support master mode: bailing out\n"); + return -1; + } else { + /* debug slave */ + exynos_dp_config_video_slave_mode(&edp_info->video_info); + } + + exynos_dp_set_video_color_format(&edp_info->video_info); + + ret = exynos_dp_get_pll_lock_status(); + if (ret != PLL_LOCKED) { + printk(BIOS_ERR, "DP PLL is not locked yet\n"); + return -1; + } + + if (edp_info->video_info.master_mode == 0) { + retry_cnt = 10; + while (retry_cnt) { + ret = exynos_dp_is_slave_video_stream_clock_on(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP stream_clock_on failed\n"); + return ret; + } + retry_cnt--; + mdelay(1); + } else { + printk(BIOS_DEBUG, "DP stream_clock succeeds\n"); + break; + } + } + } + + /* Set to use the register calculated M/N video */ + exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0); + + /* For video bist, Video timing must be generated by register + * not clear if we still need this. We could take it out and it + * might appear to work, then fail strangely. + */ + exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE); + + /* we need to be sure this is off. */ + exynos_dp_disable_video_bist(); + + /* Disable video mute */ + exynos_dp_enable_video_mute(DP_DISABLE); + + /* Configure video Master or Slave mode */ + exynos_dp_enable_video_master(edp_info->video_info.master_mode); + + /* Enable video */ + exynos_dp_start_video(); + + if (edp_info->video_info.master_mode == 0) { + retry_cnt = 500; + while (retry_cnt) { + ret = exynos_dp_is_video_stream_on(); + if (ret != EXYNOS_DP_SUCCESS) { + retry_cnt--; + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP Timeout of video stream\n"); + } + } else { + printk(BIOS_DEBUG, "DP video stream is on\n"); + break; + } + /* this is a cheap operation, involving some register + * reads, and no AUX channel IO. A ms. delay is fine. + */ + mdelay(1); + } + } + + return ret; +} + +int exynos_init_dp(struct edp_device_info *edp_info) +{ + unsigned int ret; + + + dp_phy_control(1); + + ret = exynos_dp_init_dp(); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP exynos_dp_init_dp() failed\n"); + return ret; + } + + ret = exynos_dp_handle_edid(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "EDP handle_edid fail\n"); + return ret; + } + + ret = exynos_dp_set_link_train(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP link training fail\n"); + return ret; + } + printk(BIOS_DEBUG, "EDP link training ok\n"); + + exynos_dp_enable_scramble(DP_ENABLE); + exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE); + exynos_dp_enable_enhanced_mode(DP_ENABLE); + + exynos_dp_set_link_bandwidth(edp_info->lane_bw); + exynos_dp_set_lane_count(edp_info->lane_cnt); + + exynos_dp_init_video(); + ret = exynos_dp_config_video(edp_info); + + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "Exynos DP init failed\n"); + return ret; + } + printk(BIOS_DEBUG, "Exynos DP init done\n"); + + return ret; +} + diff --git a/src/soc/samsung/exynos5420/dp_lowlevel.c b/src/soc/samsung/exynos5420/dp_lowlevel.c new file mode 100644 index 0000000000..31a4a6d0d2 --- /dev/null +++ b/src/soc/samsung/exynos5420/dp_lowlevel.c @@ -0,0 +1,1191 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* FIXME: I think the DP controller shouldn't be hardcoded here... */ +static struct exynos_dp * const dp_regs = (void *)EXYNOS5_DP1_BASE; + +/* for debugging, it's nice to get control on a per-file basis. + * I had a bit of a discussion with myself (boring!) about + * how to do this and for the moment this is the easiest way. + * These debugging statements allowed me to find the final bugs. + */ + +#if 0 +static inline void fwadl(unsigned long l,void *v) { + writel(l, v); + printk(BIOS_SPEW, "W %p %p\n", v, (void *)l); +} +#define lwrite32(a,b) fwadl((unsigned long)(a), (void *)(b)) + +static inline unsigned long fradl(void *v) { + unsigned long l = readl(v); + printk(BIOS_SPEW, "R %p %p\n", v, (void *)l); + return l; +} + +#define lread32(a) fradl((void *)(a)) +#else +#define lwrite32(a,b) write32((unsigned long)(a), (void *)(b)) +#define lread32(a) read32((void *)(a)) +#endif + +static void exynos_dp_enable_video_input(u32 enable) +{ + u32 reg; + + reg = lread32(&dp_regs->video_ctl1); + reg &= ~VIDEO_EN_MASK; + + /* enable video input*/ + if (enable) + reg |= VIDEO_EN_MASK; + + lwrite32(reg, &dp_regs->video_ctl1); + + return; +} + +void exynos_dp_disable_video_bist(void) +{ + u32 reg; + reg = lread32(&dp_regs->video_ctl4); + reg &= ~VIDEO_BIST_MASK; + lwrite32(reg, &dp_regs->video_ctl4); +} + +void exynos_dp_enable_video_mute(unsigned int enable) +{ + u32 reg; + + reg = lread32(&dp_regs->video_ctl1); + reg &= ~(VIDEO_MUTE_MASK); + if (enable) + reg |= VIDEO_MUTE_MASK; + + lwrite32(reg, &dp_regs->video_ctl1); + + return; +} + + +static void exynos_dp_init_analog_param(void) +{ + u32 reg; + + /* + * Set termination + * Normal bandgap, Normal swing, Tx terminal registor 61 ohm + * 24M Phy clock, TX digital logic power is 100:1.0625V + */ + reg = SEL_BG_NEW_BANDGAP | TX_TERMINAL_CTRL_61_OHM | + SWING_A_30PER_G_NORMAL; + lwrite32(reg, &dp_regs->analog_ctl1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + lwrite32(reg, &dp_regs->analog_ctl2); + + /* + * Set power source for internal clk driver to 1.0625v. + * Select current reference of TX driver current to 00:Ipp/2+Ic/2. + * Set VCO range of PLL +- 0uA + */ + reg = DRIVE_DVDD_BIT_1_0625V | SEL_CURRENT_DEFAULT | VCO_BIT_000_MICRO; + lwrite32(reg, &dp_regs->analog_ctl3); + + /* + * Set AUX TX terminal resistor to 102 ohm + * Set AUX channel amplitude control + */ + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_52_OHM | TX_CUR1_2X | TX_CUR_4_MA; + lwrite32(reg, &dp_regs->pll_filter_ctl1); + + /* + * PLL loop filter bandwidth + * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz + * PLL digital power select: 1.2500V + */ + reg = CH3_AMP_0_MV | CH2_AMP_0_MV | CH1_AMP_0_MV | CH0_AMP_0_MV; + + lwrite32(reg, &dp_regs->amp_tuning_ctl); + + /* + * PLL loop filter bandwidth + * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz + * PLL digital power select: 1.1250V + */ + reg = DP_PLL_LOOP_BIT_DEFAULT | DP_PLL_REF_BIT_1_1250V; + lwrite32(reg, &dp_regs->pll_ctl); +} + +static void exynos_dp_init_interrupt(void) +{ + /* Set interrupt registers to initial states */ + + /* + * Disable interrupt + * INT pin assertion polarity. It must be configured + * correctly according to ICU setting. + * 1 = assert high, 0 = assert low + */ + lwrite32(INT_POL, &dp_regs->int_ctl); + + /* Clear pending regisers */ + lwrite32(0xff, &dp_regs->common_int_sta1); + lwrite32(0xff, &dp_regs->common_int_sta2); + lwrite32(0xff, &dp_regs->common_int_sta3); + lwrite32(0xff, &dp_regs->common_int_sta4); + lwrite32(0xff, &dp_regs->int_sta); + + /* 0:mask,1: unmask */ + lwrite32(0x00, &dp_regs->int_sta_mask1); + lwrite32(0x00, &dp_regs->int_sta_mask2); + lwrite32(0x00, &dp_regs->int_sta_mask3); + lwrite32(0x00, &dp_regs->int_sta_mask4); + lwrite32(0x00, &dp_regs->int_sta_mask); +} + +void exynos_dp_reset(void) +{ + u32 reg_func_1; + + /*dp tx sw reset*/ + lwrite32(RESET_DP_TX, &dp_regs->tx_sw_reset); + + exynos_dp_enable_video_input(DP_DISABLE); + exynos_dp_disable_video_bist(); + exynos_dp_enable_video_mute(DP_DISABLE); + + /* software reset */ + reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | + AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | + HDCP_FUNC_EN_N | SW_FUNC_EN_N; + + lwrite32(reg_func_1, &dp_regs->func_en1); + lwrite32(reg_func_1, &dp_regs->func_en2); + + mdelay(1); + + exynos_dp_init_analog_param(); + exynos_dp_init_interrupt(); + + return; +} + +void exynos_dp_enable_sw_func(unsigned int enable) +{ + u32 reg; + + reg = lread32(&dp_regs->func_en1); + reg &= ~(SW_FUNC_EN_N); + + if (!enable) + reg |= SW_FUNC_EN_N; + + lwrite32(reg, &dp_regs->func_en1); + + return; +} + +unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) +{ + u32 reg; + + reg = lread32(&dp_regs->phy_pd); + switch (block) { + case AUX_BLOCK: + reg &= ~(AUX_PD); + if (enable) + reg |= AUX_PD; + break; + case CH0_BLOCK: + reg &= ~(CH0_PD); + if (enable) + reg |= CH0_PD; + break; + case CH1_BLOCK: + reg &= ~(CH1_PD); + if (enable) + reg |= CH1_PD; + break; + case CH2_BLOCK: + reg &= ~(CH2_PD); + if (enable) + reg |= CH2_PD; + break; + case CH3_BLOCK: + reg &= ~(CH3_PD); + if (enable) + reg |= CH3_PD; + break; + case ANALOG_TOTAL: + reg &= ~PHY_PD; + if (enable) + reg |= PHY_PD; + break; + case POWER_ALL: + reg &= ~(PHY_PD | AUX_PD | CH0_PD | CH1_PD | CH2_PD | + CH3_PD); + if (enable) + reg |= (PHY_PD | AUX_PD | CH0_PD | CH1_PD | + CH2_PD | CH3_PD); + break; + default: + printk(BIOS_ERR, "DP undefined block number : %d\n", block); + return -1; + } + + lwrite32(reg, &dp_regs->phy_pd); + + return 0; +} + +unsigned int exynos_dp_get_pll_lock_status(void) +{ + u32 reg; + + reg = lread32(&dp_regs->debug_ctl); + + if (reg & PLL_LOCK) + return PLL_LOCKED; + else + return PLL_UNLOCKED; +} + +static void exynos_dp_set_pll_power(unsigned int enable) +{ + u32 reg; + + reg = lread32(&dp_regs->pll_ctl); + reg &= ~(DP_PLL_PD); + + if (!enable) + reg |= DP_PLL_PD; + + lwrite32(reg, &dp_regs->pll_ctl); +} + +int exynos_dp_init_analog_func(void) +{ + int ret = EXYNOS_DP_SUCCESS; + unsigned int retry_cnt = 10; + u32 reg; + + /*Power On All Analog block */ + exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); + + reg = PLL_LOCK_CHG; + lwrite32(reg, &dp_regs->common_int_sta1); + + reg = lread32(&dp_regs->debug_ctl); + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); + lwrite32(reg, &dp_regs->debug_ctl); + + /*Assert DP PLL Reset*/ + reg = lread32(&dp_regs->pll_ctl); + reg |= DP_PLL_RESET; + lwrite32(reg, &dp_regs->pll_ctl); + + mdelay(1); + + /*Deassert DP PLL Reset*/ + reg = lread32(&dp_regs->pll_ctl); + reg &= ~(DP_PLL_RESET); + lwrite32(reg, &dp_regs->pll_ctl); + + exynos_dp_set_pll_power(DP_ENABLE); + + while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) { + mdelay(1); + retry_cnt--; + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP dp's pll lock failed : retry : %d\n", + retry_cnt); + return -1; + } + } + + printk(BIOS_DEBUG, "dp's pll lock success(%d)\n", retry_cnt); + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + reg = lread32(&dp_regs->func_en2); + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N + | AUX_FUNC_EN_N); + lwrite32(reg, &dp_regs->func_en2); + + return ret; +} + +void exynos_dp_init_hpd(void) +{ + u32 reg; + + /* Clear interrupts releated to Hot Plug Dectect */ + reg = HOTPLUG_CHG | HPD_LOST | PLUG; + lwrite32(reg, &dp_regs->common_int_sta4); + + reg = INT_HPD; + lwrite32(reg, &dp_regs->int_sta); + + reg = lread32(&dp_regs->sys_ctl3); + reg &= ~(F_HPD | HPD_CTRL); + lwrite32(reg, &dp_regs->sys_ctl3); + + return; +} + +static inline void exynos_dp_reset_aux(void) +{ + u32 reg; + + /* Disable AUX channel module */ + reg = lread32(&dp_regs->func_en2); + reg |= AUX_FUNC_EN_N; + lwrite32(reg, &dp_regs->func_en2); + + return; +} + +void exynos_dp_init_aux(void) +{ + u32 reg; + + /* Clear inerrupts related to AUX channel */ + reg = RPLY_RECEIV | AUX_ERR; + lwrite32(reg, &dp_regs->int_sta); + + exynos_dp_reset_aux(); + + /* Disable AUX transaction H/W retry */ + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)| + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + lwrite32(reg, &dp_regs->aux_hw_retry_ctl); + + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ + reg = DEFER_CTRL_EN | DEFER_COUNT(1); + lwrite32(reg, &dp_regs->aux_ch_defer_ctl); + + /* Enable AUX channel module */ + reg = lread32(&dp_regs->func_en2); + reg &= ~AUX_FUNC_EN_N; + lwrite32(reg, &dp_regs->func_en2); + + return; +} + +void exynos_dp_config_interrupt(void) +{ + u32 reg; + + /* 0: mask, 1: unmask */ + reg = COMMON_INT_MASK_1; + lwrite32(reg, &dp_regs->common_int_mask1); + + reg = COMMON_INT_MASK_2; + lwrite32(reg, &dp_regs->common_int_mask2); + + reg = COMMON_INT_MASK_3; + lwrite32(reg, &dp_regs->common_int_mask3); + + reg = COMMON_INT_MASK_4; + lwrite32(reg, &dp_regs->common_int_mask4); + + reg = INT_STA_MASK; + lwrite32(reg, &dp_regs->int_sta_mask); + + return; +} + +unsigned int exynos_dp_get_plug_in_status(void) +{ + u32 reg; + + reg = lread32(&dp_regs->sys_ctl3); + if (reg & HPD_STATUS) + return 0; + + return -1; +} + +unsigned int exynos_dp_detect_hpd(void) +{ + int timeout_loop = DP_TIMEOUT_LOOP_COUNT; + + mdelay(2); + + while (exynos_dp_get_plug_in_status() != 0) { + if (timeout_loop == 0) + return -1; + mdelay(1); + timeout_loop--; + } + + return EXYNOS_DP_SUCCESS; +} + +unsigned int exynos_dp_start_aux_transaction(void) +{ + u32 reg; + unsigned int ret = 0; + unsigned int retry_cnt; + + /* Enable AUX CH operation */ + reg = lread32(&dp_regs->aux_ch_ctl2); + reg |= AUX_EN; + lwrite32(reg, &dp_regs->aux_ch_ctl2); + + retry_cnt = 10; + while (retry_cnt) { + reg = lread32(&dp_regs->int_sta); + if (!(reg & RPLY_RECEIV)) { + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP Reply Timeout!!\n"); + ret = -1; + return ret; + } + mdelay(1); + retry_cnt--; + } else + break; + } + + /* Clear interrupt source for AUX CH command reply */ + lwrite32(reg, &dp_regs->int_sta); + + /* Clear interrupt source for AUX CH access error */ + reg = lread32(&dp_regs->int_sta); + if (reg & AUX_ERR) { + printk(BIOS_ERR, "DP Aux Access Error\n"); + lwrite32(AUX_ERR, &dp_regs->int_sta); + ret = -1; + return ret; + } + + /* Check AUX CH error access status */ + reg = lread32(&dp_regs->aux_ch_sta); + if ((reg & AUX_STATUS_MASK) != 0) { + printk(BIOS_DEBUG, "DP AUX CH error happens: %x\n", reg & AUX_STATUS_MASK); + ret = -1; + return ret; + } + return EXYNOS_DP_SUCCESS; +} + +unsigned int exynos_dp_write_byte_to_dpcd(u32 reg_addr, u8 data) +{ + u32 reg; + unsigned int ret; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_19_16); + + /* Write data buffer */ + reg = data; + lwrite32(reg, &dp_regs->buf_data0); + + /* + * Set DisplayPort transaction and write 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + printk(BIOS_ERR, "DP Aux transaction failed\n"); + } + + return ret; +} + +unsigned int exynos_dp_read_byte_from_dpcd(u32 reg_addr, + unsigned char *data) +{ + u32 reg; + int retval; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr); + lwrite32(reg, &dp_regs->aux_addr_19_16); + + /* + * Set DisplayPort transaction and read 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval != EXYNOS_DP_SUCCESS) + printk(BIOS_DEBUG, "DP Aux Transaction fail!\n"); + + /* Read data buffer */ + reg = lread32(&dp_regs->buf_data0); + *data = (unsigned char)(reg & 0xff); + + return retval; +} + +unsigned int exynos_dp_write_bytes_to_dpcd(u32 reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + unsigned int retry_cnt; + unsigned int ret = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + retry_cnt = 5; + while (retry_cnt) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_19_16); + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = data[start_offset + cur_data_idx]; + lwrite32(reg, (void *)((unsigned int)&dp_regs->buf_data0 + + (4 * cur_data_idx))); + } + /* + * Set DisplayPort transaction and write + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP Aux Transaction failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + start_offset += cur_data_count; + } + + return ret; +} + +unsigned int exynos_dp_read_bytes_from_dpcd(u32 reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + unsigned int retry_cnt; + unsigned int ret = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + retry_cnt = 5; + while (retry_cnt) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + lwrite32(reg, &dp_regs->aux_addr_19_16); + /* + * Set DisplayPort transaction and read + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printk(BIOS_ERR, "DP Aux Transaction failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = lread32((void *)((u32)&dp_regs->buf_data0 + + 4 * cur_data_idx)); + data[start_offset + cur_data_idx] = (unsigned char)reg; + } + + start_offset += cur_data_count; + } + + return ret; +} + +int exynos_dp_select_i2c_device(u32 device_addr, + u32 reg_addr) +{ + u32 reg; + int retval; + + /* Set EDID device address */ + reg = device_addr; + lwrite32(reg, &dp_regs->aux_addr_7_0); + lwrite32(0x0, &dp_regs->aux_addr_15_8); + lwrite32(0x0, &dp_regs->aux_addr_19_16); + + /* Set offset from base address of EDID device */ + lwrite32(reg_addr, &dp_regs->buf_data0); + + /* + * Set I2C transaction and write address + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | + AUX_TX_COMM_WRITE; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval != 0) + printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__); + + return retval; +} + +int exynos_dp_read_byte_from_i2c(u32 device_addr, + u32 reg_addr, + unsigned int *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 10; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + /* Select EDID device */ + retval = exynos_dp_select_i2c_device(device_addr, reg_addr); + if (retval != 0) { + printk(BIOS_DEBUG, "DP Select EDID device fail. retry !\n"); + continue; + } + + /* + * Set I2C transaction and read data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval != EXYNOS_DP_SUCCESS) + printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__); + } + + /* Read data */ + if (retval == 0) + *data = lread32(&dp_regs->buf_data0); + + return retval; +} + +int exynos_dp_read_bytes_from_i2c(u32 device_addr, + u32 reg_addr, unsigned int count, unsigned char edid[]) +{ + u32 reg; + unsigned int i, j; + unsigned int cur_data_idx; + unsigned int defer = 0; + int retval = 0; + + for (i = 0; i < count; i += 16) { /* use 16 burst */ + for (j = 0; j < 100; j++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + lwrite32(reg, &dp_regs->buffer_data_ctl); + + /* Set normal AUX CH command */ + reg = lread32(&dp_regs->aux_ch_ctl2); + reg &= ~ADDR_ONLY; + lwrite32(reg, &dp_regs->aux_ch_ctl2); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending addres + */ + if (!defer) + retval = + exynos_dp_select_i2c_device(device_addr, + reg_addr + i); + else + defer = 0; + + if (retval == EXYNOS_DP_SUCCESS) { + /* + * Set I2C transaction and write data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(16) | + AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + lwrite32(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval == 0) + break; + else + printk(BIOS_ERR, "DP Aux Transaction fail!\n"); + } + /* Check if Rx sends defer */ + reg = lread32(&dp_regs->aux_rx_comm); + if (reg == AUX_RX_COMM_AUX_DEFER || + reg == AUX_RX_COMM_I2C_DEFER) { + printk(BIOS_ERR, "DP Defer: %d\n\n", reg); + defer = 1; + } + } + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + reg = lread32((void *)((u32)&dp_regs->buf_data0 + + 4 * cur_data_idx)); + edid[i + cur_data_idx] = (unsigned char)reg; + } + } + + return retval; +} + +void exynos_dp_reset_macro(void) +{ + u32 reg; + + reg = lread32(&dp_regs->phy_test); + reg |= MACRO_RST; + lwrite32(reg, &dp_regs->phy_test); + + /* 10 us is the minimum Macro reset time. */ + udelay(50); + + reg &= ~MACRO_RST; + lwrite32(reg, &dp_regs->phy_test); +} + +void exynos_dp_set_link_bandwidth(unsigned char bwtype) +{ + u32 reg; + + reg = (u32)bwtype; + + /* Set bandwidth to 2.7G or 1.62G */ + if ((bwtype == DP_LANE_BW_1_62) || (bwtype == DP_LANE_BW_2_70)) + lwrite32(reg, &dp_regs->link_bw_set); +} + +unsigned char exynos_dp_get_link_bandwidth(void) +{ + unsigned char ret; + u32 reg; + + reg = lread32(&dp_regs->link_bw_set); + ret = (unsigned char)reg; + + return ret; +} + +void exynos_dp_set_lane_count(unsigned char count) +{ + u32 reg; + + reg = (u32)count; + + if ((count == DP_LANE_CNT_1) || (count == DP_LANE_CNT_2) || + (count == DP_LANE_CNT_4)) + lwrite32(reg, &dp_regs->lane_count_set); +} + +unsigned int exynos_dp_get_lane_count(void) +{ + u32 reg; + + reg = lread32(&dp_regs->lane_count_set); + + return reg; +} + +unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) +{ + void *reg_list[DP_LANE_CNT_4] = { + &dp_regs->ln0_link_training_ctl, + &dp_regs->ln1_link_training_ctl, + &dp_regs->ln2_link_training_ctl, + &dp_regs->ln3_link_training_ctl, + }; + + return lread32(reg_list[lanecnt]); +} + +void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, + unsigned char lanecnt) +{ + void * reg_list[DP_LANE_CNT_4] = { + &dp_regs->ln0_link_training_ctl, + &dp_regs->ln1_link_training_ctl, + &dp_regs->ln2_link_training_ctl, + &dp_regs->ln3_link_training_ctl, + }; + + lwrite32(request_val, reg_list[lanecnt]); +} + +void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) +{ + unsigned char i; + u32 reg; + void *reg_list[DP_LANE_CNT_4] = { + &dp_regs->ln0_link_training_ctl, + &dp_regs->ln1_link_training_ctl, + &dp_regs->ln2_link_training_ctl, + &dp_regs->ln3_link_training_ctl, + }; + u32 reg_shift[DP_LANE_CNT_4] = { + PRE_EMPHASIS_SET_0_SHIFT, + PRE_EMPHASIS_SET_1_SHIFT, + PRE_EMPHASIS_SET_2_SHIFT, + PRE_EMPHASIS_SET_3_SHIFT + }; + + for (i = 0; i < lanecnt; i++) { + reg = level << reg_shift[i]; + lwrite32(reg, reg_list[i]); + } +} + +void exynos_dp_set_training_pattern(unsigned int pattern) +{ + u32 reg = 0; + + switch (pattern) { + case PRBS7: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; + break; + case D10_2: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; + break; + case TRAINING_PTN1: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; + break; + case TRAINING_PTN2: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; + break; + case DP_NONE: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_DISABLE | + SW_TRAINING_PATTERN_SET_NORMAL; + break; + default: + break; + } + + lwrite32(reg, &dp_regs->training_ptn_set); +} + +void exynos_dp_enable_enhanced_mode(unsigned char enable) +{ + u32 reg; + + reg = lread32(&dp_regs->sys_ctl4); + reg &= ~ENHANCED; + + if (enable) + reg |= ENHANCED; + + lwrite32(reg, &dp_regs->sys_ctl4); +} + +void exynos_dp_enable_scrambling(unsigned int enable) +{ + u32 reg; + + reg = lread32(&dp_regs->training_ptn_set); + reg &= ~(SCRAMBLING_DISABLE); + + if (!enable) + reg |= SCRAMBLING_DISABLE; + + lwrite32(reg, &dp_regs->training_ptn_set); +} +int exynos_dp_init_video(void) +{ + unsigned int reg; + + /* Clear VID_CLK_CHG[1] and VID_FORMAT_CHG[3] and VSYNC_DET[7] */ + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + lwrite32(reg, &dp_regs->common_int_sta1); + + /* I_STRM__CLK detect : DE_CTL : Auto detect */ + reg &= ~DET_CTRL; + lwrite32(reg, &dp_regs->sys_ctl1); + return 0; +} + + +void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) +{ + u32 reg; + + /* Video Slave mode setting */ + reg = lread32(&dp_regs->func_en1); + reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N); + reg |= MASTER_VID_FUNC_EN_N; + lwrite32(reg, &dp_regs->func_en1); + + /* Configure Interlaced for slave mode video */ + reg = lread32(&dp_regs->video_ctl10); + reg &= ~INTERACE_SCAN_CFG; + reg |= (video_info->interlaced << INTERACE_SCAN_CFG_SHIFT); + printk(BIOS_SPEW, "interlaced %d\n", video_info->interlaced); + lwrite32(reg, &dp_regs->video_ctl10); + + /* Configure V sync polarity for slave mode video */ + reg = lread32(&dp_regs->video_ctl10); + reg &= ~VSYNC_POLARITY_CFG; + reg |= (video_info->v_sync_polarity << V_S_POLARITY_CFG_SHIFT); + lwrite32(reg, &dp_regs->video_ctl10); + + /* Configure H sync polarity for slave mode video */ + reg = lread32(&dp_regs->video_ctl10); + reg &= ~HSYNC_POLARITY_CFG; + reg |= (video_info->h_sync_polarity << H_S_POLARITY_CFG_SHIFT); + lwrite32(reg, &dp_regs->video_ctl10); + + /*Set video mode to slave mode */ + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; + lwrite32(reg, &dp_regs->soc_general_ctl); +} + +void exynos_dp_set_video_color_format(struct edp_video_info *video_info) +{ + u32 reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (video_info->dynamic_range << IN_D_RANGE_SHIFT) | + (video_info->color_depth << IN_BPC_SHIFT) | + (video_info->color_space << IN_COLOR_F_SHIFT); + lwrite32(reg, &dp_regs->video_ctl2); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = lread32(&dp_regs->video_ctl3); + reg &= ~IN_YC_COEFFI_MASK; + if (video_info->ycbcr_coeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + lwrite32(reg, &dp_regs->video_ctl3); +} + +unsigned int exynos_dp_is_slave_video_stream_clock_on(void) +{ + u32 reg; + + /* Update Video stream clk detect status */ + reg = lread32(&dp_regs->sys_ctl1); + lwrite32(reg, &dp_regs->sys_ctl1); + + reg = lread32(&dp_regs->sys_ctl1); + + if (!(reg & DET_STA)) { + printk(BIOS_DEBUG, "DP Input stream clock not detected.\n"); + return -1; + } + + return EXYNOS_DP_SUCCESS; +} + +void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, + unsigned int n_value) +{ + u32 reg; + + if (type == REGISTER_M) { + reg = lread32(&dp_regs->sys_ctl4); + reg |= FIX_M_VID; + lwrite32(reg, &dp_regs->sys_ctl4); + reg = M_VID0_CFG(m_value); + lwrite32(reg, &dp_regs->m_vid0); + reg = M_VID1_CFG(m_value); + lwrite32(reg, &dp_regs->m_vid1); + reg = M_VID2_CFG(m_value); + lwrite32(reg, &dp_regs->m_vid2); + + reg = N_VID0_CFG(n_value); + lwrite32(reg, &dp_regs->n_vid0); + reg = N_VID1_CFG(n_value); + lwrite32(reg, &dp_regs->n_vid1); + reg = N_VID2_CFG(n_value); + lwrite32(reg, &dp_regs->n_vid2); + } else { + reg = lread32(&dp_regs->sys_ctl4); + reg &= ~FIX_M_VID; + lwrite32(reg, &dp_regs->sys_ctl4); + } +} + +void exynos_dp_set_video_timing_mode(unsigned int type) +{ + u32 reg; + + reg = lread32(&dp_regs->video_ctl10); + reg &= ~FORMAT_SEL; + + if (type != VIDEO_TIMING_FROM_CAPTURE) + reg |= FORMAT_SEL; + + lwrite32(reg, &dp_regs->video_ctl10); +} + +void exynos_dp_enable_video_master(unsigned int enable) +{ + u32 reg; + + reg = lread32(&dp_regs->soc_general_ctl); + if (enable) { + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; + } else { + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MODE_SLAVE_MODE; + } + + lwrite32(reg, &dp_regs->soc_general_ctl); +} + +void exynos_dp_start_video(void) +{ + u32 reg; + + /* Enable Video input and disable Mute */ + reg = lread32(&dp_regs->video_ctl1); + reg |= VIDEO_EN; + lwrite32(reg, &dp_regs->video_ctl1); +} + +unsigned int exynos_dp_is_video_stream_on(void) +{ + u32 reg; + + /* Update STRM_VALID */ + reg = lread32(&dp_regs->sys_ctl3); + lwrite32(reg, &dp_regs->sys_ctl3); + + reg = lread32(&dp_regs->sys_ctl3); + + if (!(reg & STRM_VALID)) + return -1; + + return EXYNOS_DP_SUCCESS; +} + +void dp_phy_control(unsigned int enable) +{ + u32 cfg; + + cfg = lread32(&exynos_power->dptx_phy_control); + if (enable) + cfg |= EXYNOS_DP_PHY_ENABLE; + else + cfg &= ~EXYNOS_DP_PHY_ENABLE; + lwrite32(cfg, &exynos_power->dptx_phy_control); +} diff --git a/src/soc/samsung/exynos5420/fimd.c b/src/soc/samsung/exynos5420/fimd.c new file mode 100644 index 0000000000..c432627bdb --- /dev/null +++ b/src/soc/samsung/exynos5420/fimd.c @@ -0,0 +1,432 @@ +/* + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* fairly useful debugging stuff. */ +#if 0 +static inline void fwadl(unsigned long l,void *v) { + writel(l, v); + printk(BIOS_SPEW, "W %p %p\n", v, (void *)l); +} +#define lwritel(a,b) fwadl((unsigned long)(a), (void *)(b)) + +static inline unsigned long fradl(void *v) { + unsigned long l = readl(v); + printk(BIOS_SPEW, "R %p %p\n", v, (void *)l); + return l; +} + +#define lreadl(a) fradl((void *)(a)) + +#else +#define lwritel(a,b) writel((unsigned long)(a), (void *)(b)) +#define lreadl(a) readl((void *)(a)) +#endif + +/* not sure where we want this so ... */ +static unsigned long get_lcd_clk(void) +{ + u32 pclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_DISP10 + * CLKMUX_FIMD1 [4] + * 0: SCLK_RPLL + * 1: SCLK_SPLL + */ + sel = lreadl(&exynos_clock->clk_src_disp10); + sel &= (1 << 4); + + if (sel){ + sclk = get_pll_clk(SPLL); + } else { + sclk = get_pll_clk(RPLL); + } + + /* + * CLK_DIV_DISP10 + * FIMD1_RATIO [3:0] + */ + ratio = lreadl(&exynos_clock->clk_div_disp10); + ratio = ratio & 0xf; + + pclk = sclk / (ratio + 1); + + return pclk; +} + +static void exynos_fimd_set_dualrgb(vidinfo_t *vid, unsigned int enabled) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s %s\n", __func__, enabled ? "enabled" : "not enabled"); + if (enabled) { + cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | + EXYNOS_DUALRGB_VDEN_EN_ENABLE; + + /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ + cfg |= EXYNOS_DUALRGB_SUB_CNT(vid->vl_col / 2) | + EXYNOS_DUALRGB_MAIN_CNT(0); + } + + lwritel(cfg, &FIMD_CTRL->dualrgb); +} + +static void exynos_fimd_set_dp_clkcon(unsigned int enabled) +{ + unsigned int cfg = 0; + + if (enabled){ + cfg = EXYNOS_DP_CLK_ENABLE; + } + + lwritel(cfg, &FIMD_CTRL->dp_mie_clkcon); +} + +static void exynos_fimd_set_par(vidinfo_t *vid, unsigned int win_id) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s %d\n", __func__, win_id); + /* set window control */ + cfg = lreadl(&FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | + EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | + EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | + EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); + + /* DATAPATH is DMA */ + cfg |= EXYNOS_WINCON_DATAPATH_DMA; + + cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; + + /* dma burst is 16 */ + cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; + + cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; + + lwritel(cfg, &FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + + /* set window position to x=0, y=0*/ + cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); + lwritel(cfg, &FIMD_CTRL->vidosd0a + + EXYNOS_VIDOSD(win_id)); + + cfg = EXYNOS_VIDOSD_RIGHT_X(vid->vl_col - 1) | + EXYNOS_VIDOSD_BOTTOM_Y(vid->vl_row - 1) | + EXYNOS_VIDOSD_RIGHT_X_E(1) | + EXYNOS_VIDOSD_BOTTOM_Y_E(0); + + lwritel(cfg, &FIMD_CTRL->vidosd0b + + EXYNOS_VIDOSD(win_id)); + /* set window size for window0*/ + cfg = EXYNOS_VIDOSD_SIZE(vid->vl_col * vid->vl_row); + lwritel(cfg, &FIMD_CTRL->vidosd0c + + EXYNOS_VIDOSD(win_id)); +} + +static void exynos_fimd_set_buffer_address(vidinfo_t *vid, + void *screen_base, int win_id) +{ + u32 start_addr, end_addr; + printk(BIOS_SPEW, "%s %d\n", __func__, win_id); + start_addr = (u32)screen_base; + end_addr = start_addr + ((vid->vl_col * ((1<vl_bpix) / 8)) * + vid->vl_row); + + lwritel(start_addr, &FIMD_CTRL->vidw00add0b0 + + EXYNOS_BUFFER_OFFSET(win_id)); + lwritel(end_addr, &FIMD_CTRL->vidw00add1b0 + + EXYNOS_BUFFER_OFFSET(win_id)); +} + +static void exynos_fimd_set_clock(vidinfo_t *vid) +{ + unsigned int cfg = 0, div = 0, remainder = 0, remainder_div; + unsigned long pixel_clock; + unsigned long long src_clock; + printk(BIOS_SPEW, "%s\n", __func__); + if (vid->dual_lcd_enabled) { + pixel_clock = vid->vl_freq * + (vid->vl_hspw + vid->vl_hfpd + + vid->vl_hbpd + vid->vl_col / 2) * + (vid->vl_vspw + vid->vl_vfpd + + vid->vl_vbpd + vid->vl_row); + } else if (vid->interface_mode == FIMD_CPU_INTERFACE) { + pixel_clock = vid->vl_freq * + vid->vl_width * vid->vl_height * + (vid->cs_setup + vid->wr_setup + + vid->wr_act + vid->wr_hold + 1); + } else { + pixel_clock = vid->vl_freq * + (vid->vl_hspw + vid->vl_hfpd + + vid->vl_hbpd + vid->vl_col) * + (vid->vl_vspw + vid->vl_vfpd + + vid->vl_vbpd + vid->vl_row); + } + printk(BIOS_SPEW, "Pixel clock is %lx\n", pixel_clock); + + cfg = lreadl(&FIMD_CTRL->vidcon0); + cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | + EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | + EXYNOS_VIDCON0_CLKDIR_MASK); + cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | + EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); + + src_clock = (unsigned long long) get_lcd_clk(); + + /* get quotient and remainder. */ + remainder = src_clock % pixel_clock; + src_clock /= pixel_clock; + + div = src_clock; + + remainder *= 10; + remainder_div = remainder / pixel_clock; + + /* round about one places of decimals. */ + if (remainder_div >= 5) + div++; + + /* in case of dual lcd mode. */ + if (vid->dual_lcd_enabled) + div--; + + cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); + lwritel(cfg, &FIMD_CTRL->vidcon0); +} + +void exynos_set_trigger(void) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s\n", __func__); + cfg = lreadl(&FIMD_CTRL->trigcon); + + cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); + + lwritel(cfg, &FIMD_CTRL->trigcon); +} + +int exynos_is_i80_frame_done(void) +{ + unsigned int cfg = 0; + int status; + printk(BIOS_SPEW, "%s\n", __func__); + cfg = lreadl(&FIMD_CTRL->trigcon); + + /* frame done func is valid only when TRIMODE[0] is set to 1. */ + status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == + EXYNOS_I80STATUS_TRIG_DONE; + + return status; +} + +static void exynos_fimd_lcd_on(void) +{ + unsigned int cfg = 0; + + printk(BIOS_SPEW, "%s\n", __func__); + /* display on */ + cfg = lreadl(&FIMD_CTRL->vidcon0); + cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); + lwritel(cfg, &FIMD_CTRL->vidcon0); +} + +static void exynos_fimd_window_on(unsigned int win_id) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s %d\n", __func__, win_id); + /* enable window */ + cfg = lreadl(&FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + cfg |= EXYNOS_WINCON_ENWIN_ENABLE; + lwritel(cfg, &FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = lreadl(&FIMD_CTRL->winshmap); + cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); + lwritel(cfg, &FIMD_CTRL->winshmap); + cfg = lreadl(&FIMD_CTRL->winshmap); +} + +void exynos_fimd_lcd_off(void) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s\n", __func__); + + cfg = lreadl(&FIMD_CTRL->vidcon0); + cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); + lwritel(cfg, &FIMD_CTRL->vidcon0); +} + +void exynos_fimd_window_off(unsigned int win_id) +{ + unsigned int cfg = 0; + printk(BIOS_SPEW, "%s %d\n", __func__, win_id); + + cfg = lreadl(&FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + cfg &= EXYNOS_WINCON_ENWIN_DISABLE; + lwritel(cfg, &FIMD_CTRL->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = lreadl(&FIMD_CTRL->winshmap); + cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); + lwritel(cfg, &FIMD_CTRL->winshmap); +} + +static void exynos5_set_system_display(void) +{ + unsigned int cfg = 0; + + /* + * system register path set + * 0: MIE/MDNIE + * 1: FIMD Bypass + */ + cfg = lreadl(&exynos_sysreg->disp1blk_cfg); + cfg |= (1 << 15); + lwritel(cfg, &exynos_sysreg->disp1blk_cfg); +} + +void exynos_fimd_lcd_init(vidinfo_t *vid) +{ + unsigned int cfg = 0, rgb_mode; + unsigned int offset; + + offset = exynos_fimd_get_base_offset(); + printk(BIOS_SPEW, "%s\n", __func__); + exynos5_set_system_display(); + + rgb_mode = vid->rgb_mode; + + if (vid->interface_mode == FIMD_RGB_INTERFACE) { + printk(BIOS_SPEW, "%s FIMD_RGB_INTERFACE\n", __func__); + + cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; + lwritel(cfg, &FIMD_CTRL->vidcon0); + + cfg = lreadl(&FIMD_CTRL->vidcon2); + cfg &= ~(EXYNOS_VIDCON2_WB_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); + cfg |= EXYNOS_VIDCON2_WB_DISABLE; + lwritel(cfg, &FIMD_CTRL->vidcon2); + + /* set polarity */ + cfg = 0; + if (!vid->vl_clkp) + cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; + if (!vid->vl_hsp) + cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; + if (!vid->vl_vsp) + cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; + if (!vid->vl_dp) + cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; + + lwritel(cfg, &FIMD_CTRL->vidcon1 + offset); + + /* set timing */ + cfg = EXYNOS_VIDTCON0_VFPD(vid->vl_vfpd - 1); + cfg |= EXYNOS_VIDTCON0_VBPD(vid->vl_vbpd - 1); + cfg |= EXYNOS_VIDTCON0_VSPW(vid->vl_vspw - 1); + lwritel(cfg, &FIMD_CTRL->vidtcon0 + offset); + + cfg = EXYNOS_VIDTCON1_HFPD(vid->vl_hfpd - 1); + cfg |= EXYNOS_VIDTCON1_HBPD(vid->vl_hbpd - 1); + cfg |= EXYNOS_VIDTCON1_HSPW(vid->vl_hspw - 1); + + lwritel(cfg, &FIMD_CTRL->vidtcon1 + offset); + + /* set lcd size */ + cfg = EXYNOS_VIDTCON2_HOZVAL(vid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL(vid->vl_row - 1) | + EXYNOS_VIDTCON2_HOZVAL_E(vid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL_E(vid->vl_row - 1); + + lwritel(cfg, &FIMD_CTRL->vidtcon2 + offset); + } + + /* set display mode */ + cfg = lreadl(&FIMD_CTRL->vidcon0); + cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; + cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); + lwritel(cfg, &FIMD_CTRL->vidcon0); + + /* set par */ + exynos_fimd_set_par(vid, vid->win_id); + + /* set memory address */ + exynos_fimd_set_buffer_address(vid, vid->screen_base, vid->win_id); + + /* set buffer size */ + cfg = EXYNOS_VIDADDR_PAGEWIDTH(vid->vl_col * (1<vl_bpix) / 8) | + EXYNOS_VIDADDR_PAGEWIDTH_E(vid->vl_col * (1<vl_bpix) / 8) | + EXYNOS_VIDADDR_OFFSIZE(0) | + EXYNOS_VIDADDR_OFFSIZE_E(0); + + lwritel(cfg, &FIMD_CTRL->vidw00add2 + + EXYNOS_BUFFER_SIZE(vid->win_id)); + + /* set clock */ + exynos_fimd_set_clock(vid); + + /* set rgb mode to dual lcd. */ + exynos_fimd_set_dualrgb(vid, vid->dual_lcd_enabled); + + /* display on */ + exynos_fimd_lcd_on(); + + /* window on */ + exynos_fimd_window_on(vid->win_id); + + exynos_fimd_set_dp_clkcon(vid->dp_enabled); + exynos5_set_system_display(); + printk(BIOS_SPEW, "%s: done\n", __func__); +} + +unsigned long exynos_fimd_calc_fbsize(vidinfo_t *vid) +{ + printk(BIOS_SPEW, "%s\n", __func__); + return vid->vl_col * vid->vl_row * ((1<vl_bpix) / 8); +} + +void exynos_fimd_lcd_disable(void) +{ + int i; + printk(BIOS_SPEW, "%s\n", __func__); + + for (i = 0; i < 4; i++) + exynos_fimd_window_off(i); +} diff --git a/src/soc/samsung/exynos5420/gpio.c b/src/soc/samsung/exynos5420/gpio.c new file mode 100644 index 0000000000..92cdc28fc0 --- /dev/null +++ b/src/soc/samsung/exynos5420/gpio.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#define CON_MASK(x) (0xf << ((x) << 2)) +#define CON_SFR(x, v) ((v) << ((x) << 2)) + +#define DAT_MASK(x) (0x1 << (x)) +#define DAT_SET(x) (0x1 << (x)) + +#define PULL_MASK(x) (0x3 << ((x) << 1)) +#define PULL_MODE(x, v) ((v) << ((x) << 1)) + +#define DRV_MASK(x) (0x3 << ((x) << 1)) +#define DRV_SET(x, m) ((m) << ((x) << 1)) +#define RATE_MASK(x) (0x1 << (x + 16)) +#define RATE_SET(x) (0x1 << (x + 16)) + +struct gpio_info { + unsigned int reg_addr; /* Address of register for this part */ + unsigned int max_gpio; /* Maximum GPIO in this part */ +}; + +static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { + { EXYNOS5420_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, + { EXYNOS5420_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, + { EXYNOS5420_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, + { EXYNOS5420_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 }, + { EXYNOS5420_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 }, + { EXYNOS5420_GPIO_PART6_BASE, GPIO_MAX_PORT }, +}; + +/* This macro gets gpio pin offset from 0..7 */ +#define GPIO_BIT(x) ((x) & 0x7) + +static struct gpio_bank *gpio_get_bank(unsigned int gpio) +{ + const struct gpio_info *data; + unsigned int upto; + int i; + + for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS; + i++, upto = data->max_gpio, data++) { + if (gpio < data->max_gpio) { + struct gpio_bank *bank; + + bank = (struct gpio_bank *)data->reg_addr; + bank += (gpio - upto) / GPIO_PER_BANK; + return bank; + } + } + + ASSERT(gpio < GPIO_MAX_PORT); /* ...which it will not be */ + return NULL; +} + +/* Common GPIO API - only available on Exynos5 */ +void gpio_cfg_pin(int gpio, int cfg) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->con); + value &= ~CON_MASK(GPIO_BIT(gpio)); + value |= CON_SFR(GPIO_BIT(gpio), cfg); + writel(value, &bank->con); +} + +static int gpio_get_cfg(int gpio) +{ + struct gpio_bank *bank = gpio_get_bank(gpio); + int shift = GPIO_BIT(gpio) << 2; + + return (readl(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift; +} + +void gpio_set_pull(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->pull); + value &= ~PULL_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_PULL_DOWN: + case GPIO_PULL_UP: + value |= PULL_MODE(GPIO_BIT(gpio), mode); + break; + default: + break; + } + + writel(value, &bank->pull); +} + +void gpio_set_drv(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~DRV_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_DRV_1X: + case GPIO_DRV_2X: + case GPIO_DRV_3X: + case GPIO_DRV_4X: + value |= DRV_SET(GPIO_BIT(gpio), mode); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +void gpio_set_rate(int gpio, int mode) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~RATE_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case GPIO_DRV_FAST: + case GPIO_DRV_SLOW: + value |= RATE_SET(GPIO_BIT(gpio)); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +int gpio_direction_input(unsigned gpio) +{ + gpio_cfg_pin(gpio, GPIO_INPUT); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + unsigned int val; + struct gpio_bank *bank = gpio_get_bank(gpio); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + gpio_cfg_pin(gpio, GPIO_OUTPUT); + + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + unsigned int value; + struct gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->dat); + return !!(value & DAT_MASK(GPIO_BIT(gpio))); +} + +int gpio_set_value(unsigned gpio, int value) +{ + unsigned int val; + struct gpio_bank *bank = gpio_get_bank(gpio); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + return 0; +} + +/* + * Add a delay here to give the lines time to settle + * TODO(dianders): 5us does not always work, 10 is stable, so use 15 to be safe + * Come back to this and sort out what the datasheet says + */ +#define GPIO_DELAY_US 15 + +int gpio_read_mvl3(unsigned gpio) +{ + int high, low; + enum mvl3 value; + + if (gpio >= GPIO_MAX_PORT) + return -1; + + gpio_direction_input(gpio); + gpio_set_pull(gpio, GPIO_PULL_UP); + udelay(GPIO_DELAY_US); + high = gpio_get_value(gpio); + gpio_set_pull(gpio, GPIO_PULL_DOWN); + udelay(GPIO_DELAY_US); + low = gpio_get_value(gpio); + + if (high && low) /* external pullup */ + value = LOGIC_1; + else if (!high && !low) /* external pulldown */ + value = LOGIC_0; + else /* floating */ + value = LOGIC_Z; + + /* + * Check if line is externally pulled high and + * configure the internal pullup to match. For + * floating and pulldowns, the GPIO is already + * configured with an internal pulldown from the + * above test. + */ + if (value == LOGIC_1) + gpio_set_pull(gpio, GPIO_PULL_UP); + + return value; +} + +/* + * Display Exynos GPIO information + */ +void gpio_info(void) +{ + unsigned gpio; + + for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) { + int cfg = gpio_get_cfg(gpio); + + printk(BIOS_INFO, "GPIO_%-3d: ", gpio); + if (cfg == GPIO_INPUT) + printk(BIOS_INFO, "input"); + else if (cfg == GPIO_OUTPUT) + printk(BIOS_INFO, "output"); + else + printk(BIOS_INFO, "func %d", cfg); + + if (cfg == GPIO_INPUT || cfg == GPIO_OUTPUT) + printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio)); + printk(BIOS_INFO, "\n"); + } +} diff --git a/src/soc/samsung/exynos5420/i2c.c b/src/soc/samsung/exynos5420/i2c.c new file mode 100644 index 0000000000..f1b7c6b5bb --- /dev/null +++ b/src/soc/samsung/exynos5420/i2c.c @@ -0,0 +1,663 @@ +/* + * This file is part of the coreboot project. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct __attribute__ ((packed)) i2c_regs +{ + uint8_t con; + uint8_t _1[3]; + uint8_t stat; + uint8_t _2[3]; + uint8_t add; + uint8_t _3[3]; + uint8_t ds; + uint8_t _4[3]; + uint8_t lc; + uint8_t _5[3]; +}; + +struct __attribute__ ((packed)) hsi2c_regs +{ + uint32_t usi_ctl; + uint32_t usi_fifo_ctl; + uint32_t usi_trailing_ctl; + uint32_t usi_clk_ctl; + uint32_t usi_clk_slot; + uint32_t spi_ctl; + uint32_t uart_ctl; + uint32_t res1; + uint32_t usi_int_en; + uint32_t usi_int_stat; + uint32_t modem_stat; + uint32_t error_stat; + uint32_t usi_fifo_stat; + uint32_t usi_txdata; + uint32_t usi_rxdata; + uint32_t res2; + uint32_t i2c_conf; + uint32_t i2c_auto_conf; + uint32_t i2c_timeout; + uint32_t i2c_manual_cmd; + uint32_t i2c_trans_status; + uint32_t i2c_timing_hs1; + uint32_t i2c_timing_hs2; + uint32_t i2c_timing_hs3; + uint32_t i2c_timing_fs1; + uint32_t i2c_timing_fs2; + uint32_t i2c_timing_fs3; + uint32_t i2c_timing_sla; + uint32_t i2c_addr; +}; +check_member(hsi2c_regs, i2c_addr, 0x70); + +struct i2c_bus +{ + int bus_num; + struct i2c_regs *regs; + enum periph_id periph_id; + struct hsi2c_regs *hsregs; + int is_highspeed; /* High speed type, rather than I2C */ + int id; + unsigned clk_cycle; + unsigned clk_div; +}; + + +static struct i2c_bus i2c_busses[] = { + { + .bus_num = 0, + .regs = (void *)0x12c60000, + .periph_id = PERIPH_ID_I2C0, + }, + { + .bus_num = 1, + .regs = (void *)0x12c70000, + .periph_id = PERIPH_ID_I2C1, + }, + { + .bus_num = 2, + .regs = (void *)0x12c80000, + .periph_id = PERIPH_ID_I2C2, + }, + { + .bus_num = 3, + .regs = (void *)0x12c90000, + .periph_id = PERIPH_ID_I2C3, + }, + /* I2C4-I2C10 are part of the USI block */ + { + .bus_num = 4, + .hsregs = (void *)0x12ca0000, + .periph_id = PERIPH_ID_I2C4, + .is_highspeed = 1, + }, + { + .bus_num = 5, + .hsregs = (void *)0x12cb0000, + .periph_id = PERIPH_ID_I2C5, + .is_highspeed = 1, + }, + { + .bus_num = 6, + .hsregs = (void *)0x12cc0000, + .periph_id = PERIPH_ID_I2C6, + .is_highspeed = 1, + }, + { + .bus_num = 7, + .hsregs = (void *)0x12cd0000, + .periph_id = PERIPH_ID_I2C7, + .is_highspeed = 1, + }, + { + .bus_num = 8, + .hsregs = (void *)0x12e00000, + .periph_id = PERIPH_ID_I2C8, + .is_highspeed = 1, + }, + { + .bus_num = 9, + .hsregs = (void *)0x12e10000, + .periph_id = PERIPH_ID_I2C9, + .is_highspeed = 1, + }, + { + .bus_num = 10, + .hsregs = (void *)0x12e20000, + .periph_id = PERIPH_ID_I2C10, + .is_highspeed = 1, + }, +}; + +// I2C_CTL +enum { + Hsi2cFuncModeI2c = 1 << 0, + Hsi2cMaster = 1 << 3, + Hsi2cRxchon = 1 << 6, + Hsi2cTxchon = 1 << 7, + Hsi2cSwRst = 1 << 31 +}; + +// I2C_FIFO_STAT +enum { + Hsi2cTxFifoLevel = 0x7f << 0, + Hsi2cTxFifoFull = 1 << 7, + Hsi2cTxFifoEmpty = 1 << 8, + Hsi2cRxFifoLevel = 0x7f << 16, + Hsi2cRxFifoFull = 1 << 23, + Hsi2cRxFifoEmpty = 1 << 24 +}; + +// I2C_FIFO_CTL +enum { + Hsi2cRxfifoEn = 1 << 0, + Hsi2cTxfifoEn = 1 << 1, + Hsi2cTxfifoTriggerLevel = 0x20 << 16, + Hsi2cRxfifoTriggerLevel = 0x20 << 4 +}; + +// I2C_TRAILING_CTL +enum { + Hsi2cTrailingCount = 0xff +}; + +// I2C_INT_EN +enum { + Hsi2cIntTxAlmostemptyEn = 1 << 0, + Hsi2cIntRxAlmostfullEn = 1 << 1, + Hsi2cIntTrailingEn = 1 << 6, + Hsi2cIntI2cEn = 1 << 9 +}; + +// I2C_CONF +enum { + Hsi2cAutoMode = 1 << 31, + Hsi2c10bitAddrMode = 1 << 30, + Hsi2cHsMode = 1 << 29 +}; + +// I2C_AUTO_CONF +enum { + Hsi2cReadWrite = 1 << 16, + Hsi2cStopAfterTrans = 1 << 17, + Hsi2cMasterRun = 1 << 31 +}; + +// I2C_TIMEOUT +enum { + Hsi2cTimeoutEn = 1 << 31 +}; + +// I2C_TRANS_STATUS +enum { + Hsi2cMasterBusy = 1 << 17, + Hsi2cSlaveBusy = 1 << 16, + Hsi2cTimeoutAuto = 1 << 4, + Hsi2cNoDev = 1 << 3, + Hsi2cNoDevAck = 1 << 2, + Hsi2cTransAbort = 1 << 1, + Hsi2cTransDone = 1 << 0 +}; + +#define HSI2C_SLV_ADDR_MAS(x) ((x & 0x3ff) << 10) + +enum { + Hsi2cTimeout = 100 +}; + +enum { + I2cConIntPending = 0x1 << 4, + I2cConIntEn = 0x1 << 5, + I2cConAckGen = 0x1 << 7 +}; + +enum { + I2cStatAck = 0x1 << 0, + I2cStatAddrZero = 0x1 << 1, + I2cStatAddrSlave = 0x1 << 2, + I2cStatArb = 0x1 << 3, + I2cStatEnable = 0x1 << 4, + I2cStatStartStop = 0x1 << 5, + I2cStatBusy = 0x1 << 5, + + I2cStatModeMask = 0x3 << 6, + I2cStatSlaveRecv = 0x0 << 6, + I2cStatSlaveXmit = 0x1 << 6, + I2cStatMasterRecv = 0x2 << 6, + I2cStatMasterXmit = 0x3 << 6 +}; + + + + +static int hsi2c_get_clk_details(struct i2c_bus *i2c, int *div, int *cycle, + unsigned op_clk) +{ + struct hsi2c_regs *regs = i2c->hsregs; + unsigned long clkin = clock_get_periph_rate(i2c->periph_id); + + /* + * FPCLK / FI2C = + * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE + * temp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + * temp1 = (TSCLK_L + TSCLK_H + 2) + */ + uint32_t flt_cycle = (readl(®s->i2c_conf) >> 16) & 0x7; + int temp = (clkin / op_clk) - 8 - 2 * flt_cycle; + + // CLK_DIV max is 256. + int i; + for (i = 0; i < 256; i++) { + int period = temp / (i + 1) - 2; + if (period < 512 && period >= 2) { + *cycle = period; + *div = i; + return 0; + } + } + printk(BIOS_ERR, "%s: Failed to find timing parameters.\n", __func__); + return -1; +} + +static void hsi2c_ch_init(struct i2c_bus *i2c, unsigned int frequency) +{ + struct hsi2c_regs *regs = i2c->hsregs; + + int div, cycle; + if (hsi2c_get_clk_details(i2c, &div, &cycle, frequency)) + return; + + uint32_t sr_release; + sr_release = cycle; + + uint32_t scl_l, scl_h, start_su, start_hd, stop_su; + scl_l = scl_h = start_su = start_hd = stop_su = cycle / 2; + + uint32_t data_su, data_hd; + data_su = data_hd = cycle / 4; + + uint32_t timing_fs1 = start_su << 24 | start_hd << 16 | stop_su << 8; + uint32_t timing_fs2 = data_su << 24 | scl_l << 8 | scl_h << 0; + uint32_t timing_fs3 = div << 16 | sr_release << 0; + uint32_t timing_sla = data_hd << 0; + + // Currently operating in fast speed mode. + writel(timing_fs1, ®s->i2c_timing_fs1); + writel(timing_fs2, ®s->i2c_timing_fs2); + writel(timing_fs3, ®s->i2c_timing_fs3); + writel(timing_sla, ®s->i2c_timing_sla); + + // Clear to enable timeout. + writel(readl(®s->i2c_timeout) & ~Hsi2cTimeoutEn, + ®s->i2c_timeout); + + writel(Hsi2cTrailingCount, ®s->usi_trailing_ctl); + writel(Hsi2cRxfifoEn | Hsi2cTxfifoEn, ®s->usi_fifo_ctl); + writel(readl(®s->i2c_conf) | Hsi2cAutoMode, ®s->i2c_conf); +} + +static void hsi2c_reset(struct i2c_bus *i2c) +{ + struct hsi2c_regs *regs = i2c->hsregs; + + // Set and clear the bit for reset. + writel(readl(®s->usi_ctl) | Hsi2cSwRst, ®s->usi_ctl); + writel(readl(®s->usi_ctl) & ~Hsi2cSwRst, ®s->usi_ctl); + + /* FIXME: This just assumes 100KHz as a default bus freq */ + hsi2c_ch_init(i2c, 100000); +} + +static void i2c_ch_init(struct i2c_bus *i2c, int speed) +{ + struct i2c_regs *regs = i2c->regs; + + unsigned long freq, pres = 16, div; + unsigned long val; + + freq = clock_get_periph_rate(i2c->periph_id); + // Calculate prescaler and divisor values. + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + + while ((freq / pres / (div + 1)) > speed) + div++; + + // Set prescaler, divisor according to freq, also set ACKGEN, IRQ. + val = (div & 0x0f) | 0xa0 | ((pres == 512) ? 0x40 : 0); + writel(val, ®s->con); + + // Init to SLAVE RECEIVE mode and clear I2CADDn. + writel(0, ®s->stat); + writel(0, ®s->add); + // program Master Transmit (and implicit STOP). + writel(I2cStatMasterXmit | I2cStatEnable, ®s->stat); +} + +void i2c_init(unsigned bus, int speed, int slaveadd) +{ + struct i2c_bus *i2c = &i2c_busses[bus]; + + if (i2c->is_highspeed) { + hsi2c_reset(i2c); + hsi2c_ch_init(i2c, speed); + } else { + i2c_ch_init(i2c, speed); + } +} + +/* + * Check whether the transfer is complete. + * Return values: + * 0 - transfer not done + * 1 - transfer finished successfully + * -1 - transfer failed + */ +static int hsi2c_check_transfer(struct hsi2c_regs *regs) +{ + uint32_t status = read32(®s->i2c_trans_status); + if (status & (Hsi2cTransAbort | Hsi2cNoDevAck | + Hsi2cNoDev | Hsi2cTimeoutAuto)) { + if (status & Hsi2cTransAbort) + printk(BIOS_ERR, + "%s: Transaction aborted.\n", __func__); + if (status & Hsi2cNoDevAck) + printk(BIOS_ERR, + "%s: No ack from device.\n", __func__); + if (status & Hsi2cNoDev) + printk(BIOS_ERR, + "%s: No response from device.\n", __func__); + if (status & Hsi2cTimeoutAuto) + printk(BIOS_ERR, + "%s: Transaction time out.\n", __func__); + return -1; + } + return !(status & Hsi2cMasterBusy); +} + +/* + * Wait for the transfer to finish. + * Return values: + * 0 - transfer not done + * 1 - transfer finished successfully + * -1 - transfer failed + */ +static int hsi2c_wait_for_transfer(struct hsi2c_regs *i2c) +{ + struct stopwatch sw; + + stopwatch_init_msecs_expire(&sw, Hsi2cTimeout); + while (!stopwatch_expired(&sw)) { + int ret = hsi2c_check_transfer(i2c); + if (ret) + return ret; + } + return 0; +} + +static int hsi2c_senddata(struct hsi2c_regs *regs, const uint8_t *data, int len) +{ + while (!hsi2c_check_transfer(regs) && len) { + if (!(read32(®s->usi_fifo_stat) & Hsi2cTxFifoFull)) { + write32(*data++, ®s->usi_txdata); + len--; + } + } + return len ? -1 : 0; +} + +static int hsi2c_recvdata(struct hsi2c_regs *regs, uint8_t *data, int len) +{ + while (!hsi2c_check_transfer(regs) && len) { + if (!(read32(®s->usi_fifo_stat) & Hsi2cRxFifoEmpty)) { + *data++ = read32(®s->usi_rxdata); + len--; + } + } + return len ? -1 : 0; +} + +static int hsi2c_segment(struct i2c_seg *seg, struct hsi2c_regs *regs, int stop) +{ + const uint32_t usi_ctl = Hsi2cFuncModeI2c | Hsi2cMaster; + + write32(HSI2C_SLV_ADDR_MAS(seg->chip), ®s->i2c_addr); + + /* + * We really only want to stop after this transaction (I think) if the + * "stop" parameter is true. I'm assuming that's supposed to make the + * controller issue a repeated start, but the documentation isn't very + * clear. We may need to switch to manual mode to really get the + * behavior we want. + */ + uint32_t autoconf = + seg->len | Hsi2cMasterRun | Hsi2cStopAfterTrans; + + if (seg->read) { + write32(usi_ctl | Hsi2cRxchon, ®s->usi_ctl); + write32(autoconf | Hsi2cReadWrite, ®s->i2c_auto_conf); + + if (hsi2c_recvdata(regs, seg->buf, seg->len)) + return -1; + } else { + write32(usi_ctl | Hsi2cTxchon, ®s->usi_ctl); + write32(autoconf, ®s->i2c_auto_conf); + + if (hsi2c_senddata(regs, seg->buf, seg->len)) + return -1; + } + + if (hsi2c_wait_for_transfer(regs) != 1) + return -1; + + writel(Hsi2cFuncModeI2c, ®s->usi_ctl); + return 0; +} + +static int hsi2c_transfer(struct i2c_bus *i2c, struct i2c_seg *segments, + int count) +{ + struct hsi2c_regs *regs = i2c->hsregs; + if (hsi2c_wait_for_transfer(regs) != 1) { + hsi2c_reset(i2c); + return -1; + } + + int i; + for (i = 0; i < count; i++) { + if (hsi2c_segment(&segments[i], regs, i == count - 1)) { + hsi2c_reset(i2c); + return -1; + } + } + + return 0; +} + + + + +static int i2c_int_pending(struct i2c_regs *regs) +{ + return readb(®s->con) & I2cConIntPending; +} + +static void i2c_clear_int(struct i2c_regs *regs) +{ + writeb(readb(®s->con) & ~I2cConIntPending, ®s->con); +} + +static void i2c_ack_enable(struct i2c_regs *regs) +{ + writeb(readb(®s->con) | I2cConAckGen, ®s->con); +} + +static void i2c_ack_disable(struct i2c_regs *regs) +{ + writeb(readb(®s->con) & ~I2cConAckGen, ®s->con); +} + +static int i2c_got_ack(struct i2c_regs *regs) +{ + return !(readb(®s->stat) & I2cStatAck); +} + +static int i2c_wait_for_idle(struct i2c_regs *regs) +{ + int timeout = 1000 * 100; // 1s. + while (timeout--) { + if (!(readb(®s->stat) & I2cStatBusy)) + return 0; + udelay(10); + } + printk(BIOS_ERR, "I2C timeout waiting for idle.\n"); + return 1; +} + +static int i2c_wait_for_int(struct i2c_regs *regs) +{ + int timeout = 1000 * 100; // 1s. + while (timeout--) { + if (i2c_int_pending(regs)) + return 0; + udelay(10); + } + printk(BIOS_ERR, "I2C timeout waiting for I2C interrupt.\n"); + return 1; +} + + + + +static int i2c_send_stop(struct i2c_regs *regs) +{ + uint8_t mode = readb(®s->stat) & (I2cStatModeMask); + writeb(mode | I2cStatEnable, ®s->stat); + i2c_clear_int(regs); + return i2c_wait_for_idle(regs); +} + +static int i2c_send_start(struct i2c_regs *regs, int read, int chip) +{ + writeb(chip << 1, ®s->ds); + uint8_t mode = read ? I2cStatMasterRecv : I2cStatMasterXmit; + writeb(mode | I2cStatStartStop | I2cStatEnable, ®s->stat); + i2c_clear_int(regs); + + if (i2c_wait_for_int(regs)) + return 1; + + if (!i2c_got_ack(regs)) { + // Nobody home, but they may just be asleep. + return 1; + } + + return 0; +} + +static int i2c_xmit_buf(struct i2c_regs *regs, uint8_t *data, int len) +{ + ASSERT(len); + + i2c_ack_enable(regs); + + int i; + for (i = 0; i < len; i++) { + writeb(data[i], ®s->ds); + + i2c_clear_int(regs); + if (i2c_wait_for_int(regs)) + return 1; + + if (!i2c_got_ack(regs)) { + printk(BIOS_INFO, "I2c nacked.\n"); + return 1; + } + } + + return 0; +} + +static int i2c_recv_buf(struct i2c_regs *regs, uint8_t *data, int len) +{ + ASSERT(len); + + i2c_ack_enable(regs); + + int i; + for (i = 0; i < len; i++) { + if (i == len - 1) + i2c_ack_disable(regs); + + i2c_clear_int(regs); + if (i2c_wait_for_int(regs)) + return 1; + + data[i] = readb(®s->ds); + } + + return 0; +} + +int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) +{ + struct i2c_bus *i2c = &i2c_busses[bus]; + if (i2c->is_highspeed) + return hsi2c_transfer(i2c, segments, count); + + struct i2c_regs *regs = i2c->regs; + int res = 0; + + if (!regs || i2c_wait_for_idle(regs)) + return 1; + + writeb(I2cStatMasterXmit | I2cStatEnable, ®s->stat); + + int i; + for (i = 0; i < count; i++) { + struct i2c_seg *seg = &segments[i]; + + res = i2c_send_start(regs, seg->read, seg->chip); + if (res) + break; + if (seg->read) + res = i2c_recv_buf(regs, seg->buf, seg->len); + else + res = i2c_xmit_buf(regs, seg->buf, seg->len); + if (res) + break; + } + + return i2c_send_stop(regs) || res; +} diff --git a/src/soc/samsung/exynos5420/include/soc/alternate_cbfs.h b/src/soc/samsung/exynos5420/include/soc/alternate_cbfs.h new file mode 100644 index 0000000000..2b4ef8c128 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/alternate_cbfs.h @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H +#define CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H + +/* These are pointers to function pointers. Double indirection! */ +static void * * const irom_sdmmc_read_blocks_ptr = (void * *)0x02020030; +static void * * const irom_msh_read_from_fifo_emmc_ptr = (void * *)0x02020044; +static void * * const irom_msh_end_boot_op_emmc_ptr = (void * *)0x02020048; +static void * * const irom_spi_sf_read_ptr = (void * *)0x02020058; +static void * * const irom_load_image_from_usb_ptr = (void * *)0x02020070; + +#define SECONDARY_BASE_BOOT_USB 0xfeed0002 +static u32 * const iram_secondary_base = (u32 *)0x02020018; + +/* Values pulled from U-Boot, I think the manual is wrong here (for SPI) */ +#define OM_STAT_SDMMC 0x4 +#define OM_STAT_EMMC 0x8 +#define OM_STAT_SPI 0x14 +#define OM_STAT_MASK 0x7f + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/clk.h b/src/soc/samsung/exynos5420/include/soc/clk.h new file mode 100644 index 0000000000..f2d0ed7774 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/clk.h @@ -0,0 +1,759 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_CLK_H +#define CPU_SAMSUNG_EXYNOS5420_CLK_H + +#include +#include +#include +#include + +enum periph_id; + +/* This master list of PLLs is ordered arbitrarily. */ +#define APLL 0 +#define MPLL 1 +#define EPLL 2 +#define HPLL 3 +#define VPLL 4 +#define BPLL 5 +#define RPLL 6 +#define SPLL 7 +#define CPLL 8 +#define DPLL 9 +#define IPLL 10 + +unsigned long get_pll_clk(int pllreg); +unsigned long get_arm_clk(void); +unsigned long get_pwm_clk(void); +unsigned long get_uart_clk(int dev_index); +void set_mmc_clk(int dev_index, unsigned int div); + +/** + * get the clk frequency of the required peripherial + * + * @param peripherial Peripherial id + * + * @return frequency of the peripherial clk + */ +unsigned long clock_get_periph_rate(enum periph_id peripheral); + +#define MCT_HZ 24000000 + +/* + * Set mshci controller instances clock drivder + * + * @param enum periph_id instance of the mshci controller + * + * Return 0 if ok else -1 + */ +int clock_set_mshci(enum periph_id peripheral); + +/* + * Set dwmci controller instances clock drivder + * + * @param enum periph_id instance of the dwmci controller + * + * Return 0 if ok else -1 + */ +int clock_set_dwmci(enum periph_id peripheral); + +/* + * Sets the epll clockrate + * + * @param rate Required clock rate to the presacaler in Hz + * + * Return 0 if ok else -1 + */ +int clock_epll_set_rate(unsigned long rate); + +/* + * selects the clk source for I2S MCLK + */ +void clock_select_i2s_clk_source(void); + +/* + * Set prescaler division based on input and output frequency + * for i2s audio clock + * + * @param src_frq Source frequency in Hz + * @param dst_frq Required MCLK frequency in Hz + * + * Return 0 if ok else -1 + */ +int clock_set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq); + +struct exynos5420_clock { + uint32_t apll_lock; /* 0x10010000 */ + uint8_t res1[0xfc]; + uint32_t apll_con0; + uint32_t apll_con1; + uint8_t res2[0xf8]; + uint32_t clk_src_cpu; + uint8_t res3[0x1fc]; + uint32_t clk_mux_stat_cpu; + uint8_t res4[0xfc]; + uint32_t clk_div_cpu0; /* 0x10010500 */ + uint32_t clk_div_cpu1; + uint8_t res5[0xf8]; + uint32_t clk_div_stat_cpu0; + uint32_t clk_div_stat_cpu1; + uint8_t res6[0xf8]; + uint32_t clk_gate_bus_cpu; + uint8_t res7[0xfc]; + uint32_t clk_gate_sclk_cpu; + uint8_t res8[0x1fc]; + uint32_t clkout_cmu_cpu; /* 0x10010a00 */ + uint32_t clkout_cmu_cpu_div_stat; + uint8_t res9[0x5f8]; + uint32_t armclk_stopctrl; + uint8_t res10[0x4]; + uint32_t arm_ema_ctrl; + uint32_t arm_ema_status; + uint8_t res11[0x10]; + uint32_t pwr_ctrl; + uint32_t pwr_ctrl2; + uint8_t res12[0xd8]; + uint32_t apll_con0_l8; /* 0x1001100 */ + uint32_t apll_con0_l7; + uint32_t apll_con0_l6; + uint32_t apll_con0_l5; + uint32_t apll_con0_l4; + uint32_t apll_con0_l3; + uint32_t apll_con0_l2; + uint32_t apll_con0_l1; + uint32_t iem_control; + uint8_t res13[0xdc]; + uint32_t apll_con1_l8; /* 0x10011200 */ + uint32_t apll_con1_l7; + uint32_t apll_con1_l6; + uint32_t apll_con1_l5; + uint32_t apll_con1_l4; + uint32_t apll_con1_l3; + uint32_t apll_con1_l2; + uint32_t apll_con1_l1; + uint8_t res14[0xe0]; + uint32_t clkdiv_iem_l8; + uint32_t clkdiv_iem_l7; /* 0x10011304 */ + uint32_t clkdiv_iem_l6; + uint32_t clkdiv_iem_l5; + uint32_t clkdiv_iem_l4; + uint32_t clkdiv_iem_l3; + uint32_t clkdiv_iem_l2; + uint32_t clkdiv_iem_l1; + uint8_t res15[0xe0]; + uint32_t l2_status; + uint8_t res16[0x0c]; + uint32_t cpu_status; /* 0x10011410 */ + uint8_t res17[0x0c]; + uint32_t ptm_status; + uint8_t res18[0xbdc]; + uint32_t cmu_cpu_spare0; + uint32_t cmu_cpu_spare1; + uint32_t cmu_cpu_spare2; + uint32_t cmu_cpu_spare3; + uint32_t cmu_cpu_spare4; + uint8_t res19[0x1fdc]; + uint32_t cmu_cpu_version; + uint8_t res20[0x20c]; + uint32_t clk_src_cperi0; /* 0x10014200 */ + uint32_t clk_src_cperi1; + uint8_t res21[0xf8]; + uint32_t clk_src_mask_cperi; + uint8_t res22[0x100]; + uint32_t clk_mux_stat_cperi1; + uint8_t res23[0xfc]; + uint32_t clk_div_cperi1; + uint8_t res24[0xfc]; + uint32_t clk_div_stat_cperi1; + uint8_t res25[0xf8]; + uint32_t clk_gate_bus_cperi0; /* 0x10014700 */ + uint32_t clk_gate_bus_cperi1; + uint8_t res26[0xf8]; + uint32_t clk_gate_sclk_cperi; + uint8_t res27[0xfc]; + uint32_t clk_gate_ip_cperi; + uint8_t res28[0xfc]; + uint32_t clkout_cmu_cperi; + uint32_t clkout_cmu_cperi_div_stat; + uint8_t res29[0x5f8]; + uint32_t dcgidx_map0; /* 0x10015000 */ + uint32_t dcgidx_map1; + uint32_t dcgidx_map2; + uint8_t res30[0x14]; + uint32_t dcgperf_map0; + uint32_t dcgperf_map1; + uint8_t res31[0x18]; + uint32_t dvcidx_map; + uint8_t res32[0x1c]; + uint32_t freq_cpu; + uint32_t freq_dpm; + uint8_t res33[0x18]; + uint32_t dvsemclk_en; /* 0x10015080 */ + uint32_t maxperf; + uint8_t res34[0x2e78]; + uint32_t cmu_cperi_spare0; + uint32_t cmu_cperi_spare1; + uint32_t cmu_cperi_spare2; + uint32_t cmu_cperi_spare3; + uint32_t cmu_cperi_spare4; + uint32_t cmu_cperi_spare5; + uint32_t cmu_cperi_spare6; + uint32_t cmu_cperi_spare7; + uint32_t cmu_cperi_spare8; + uint8_t res35[0xcc]; + uint32_t cmu_cperi_version; /* 0x10017ff0 */ + uint8_t res36[0x50c]; + uint32_t clk_div_g2d; + uint8_t res37[0xfc]; + uint32_t clk_div_stat_g2d; + uint8_t res38[0xfc]; + uint32_t clk_gate_bus_g2d; + uint8_t res39[0xfc]; + uint32_t clk_gate_ip_g2d; + uint8_t res40[0x1fc]; + uint32_t clkout_cmu_g2d; + uint32_t clkout_cmu_g2d_div_stat;/* 0x10018a04 */ + uint8_t res41[0xf8]; + uint32_t cmu_g2d_spare0; + uint32_t cmu_g2d_spare1; + uint32_t cmu_g2d_spare2; + uint32_t cmu_g2d_spare3; + uint32_t cmu_g2d_spare4; + uint8_t res42[0x34dc]; + uint32_t cmu_g2d_version; + uint8_t res43[0x30c]; + uint32_t clk_div_cmu_isp0; + uint32_t clk_div_cmu_isp1; + uint32_t clk_div_isp2; /* 0x1001c308 */ + uint8_t res44[0xf4]; + uint32_t clk_div_stat_cmu_isp0; + uint32_t clk_div_stat_cmu_isp1; + uint32_t clk_div_stat_isp2; + uint8_t res45[0x2f4]; + uint32_t clk_gate_bus_isp0; + uint32_t clk_gate_bus_isp1; + uint32_t clk_gate_bus_isp2; + uint32_t clk_gate_bus_isp3; + uint8_t res46[0xf0]; + uint32_t clk_gate_ip_isp0; + uint32_t clk_gate_ip_isp1; + uint8_t res47[0xf8]; + uint32_t clk_gate_sclk_isp; + uint8_t res48[0x0c]; + uint32_t mcuisp_pwr_ctrl; /* 0x1001c910 */ + uint8_t res49[0x0ec]; + uint32_t clkout_cmu_isp; + uint32_t clkout_cmu_isp_div_stat; + uint8_t res50[0xf8]; + uint32_t cmu_isp_spare0; + uint32_t cmu_isp_spare1; + uint32_t cmu_isp_spare2; + uint32_t cmu_isp_spare3; + uint8_t res51[0x34e0]; + uint32_t cmu_isp_version; + uint8_t res52[0x2c]; + uint32_t cpll_lock; /* 10020020 */ + uint8_t res53[0xc]; + uint32_t dpll_lock; + uint8_t res54[0xc]; + uint32_t epll_lock; + uint8_t res55[0xc]; + uint32_t rpll_lock; + uint8_t res56[0xc]; + uint32_t ipll_lock; + uint8_t res57[0xc]; + uint32_t spll_lock; + uint8_t res58[0xc]; + uint32_t vpll_lock; + uint8_t res59[0xc]; + uint32_t mpll_lock; + uint8_t res60[0x8c]; + uint32_t cpll_con0; /* 10020120 */ + uint32_t cpll_con1; + uint32_t dpll_con0; + uint32_t dpll_con1; + uint32_t epll_con0; + uint32_t epll_con1; + uint32_t epll_con2; + uint8_t res601[0x4]; + uint32_t rpll_con0; + uint32_t rpll_con1; + uint32_t rpll_con2; + uint8_t res602[0x4]; + uint32_t ipll_con0; + uint32_t ipll_con1; + uint8_t res61[0x8]; + uint32_t spll_con0; + uint32_t spll_con1; + uint8_t res62[0x8]; + uint32_t vpll_con0; + uint32_t vpll_con1; + uint8_t res63[0x8]; + uint32_t mpll_con0; + uint32_t mpll_con1; + uint8_t res64[0x78]; + uint32_t clk_src_top0; /* 0x10020200 */ + uint32_t clk_src_top1; + uint32_t clk_src_top2; + uint32_t clk_src_top3; + uint32_t clk_src_top4; + uint32_t clk_src_top5; + uint32_t clk_src_top6; + uint32_t clk_src_top7; + uint8_t res65[0xc]; + uint32_t clk_src_disp10; /* 0x1002022c */ + uint8_t res66[0x10]; + uint32_t clk_src_mau; + uint32_t clk_src_fsys; + uint8_t res67[0x8]; + uint32_t clk_src_peric0; + uint32_t clk_src_peric1; + uint8_t res68[0x18]; + uint32_t clk_src_isp; + uint8_t res69[0x0c]; + uint32_t clk_src_top10; + uint32_t clk_src_top11; + uint32_t clk_src_top12; + uint8_t res70[0x74]; + uint32_t clk_src_mask_top0; + uint32_t clk_src_mask_top1; + uint32_t clk_src_mask_top2; + uint8_t res71[0x10]; + uint32_t clk_src_mask_top7; + uint8_t res72[0xc]; + uint32_t clk_src_mask_disp10; /* 0x1002032c */ + uint8_t res73[0x4]; + uint32_t clk_src_mask_mau; + uint8_t res74[0x8]; + uint32_t clk_src_mask_fsys; + uint8_t res75[0xc]; + uint32_t clk_src_mask_peric0; + uint32_t clk_src_mask_peric1; + uint8_t res76[0x18]; + uint32_t clk_src_mask_isp; + uint8_t res77[0x8c]; + uint32_t clk_mux_stat_top0; /* 0x10020400 */ + uint32_t clk_mux_stat_top1; + uint32_t clk_mux_stat_top2; + uint32_t clk_mux_stat_top3; + uint32_t clk_mux_stat_top4; + uint32_t clk_mux_stat_top5; + uint32_t clk_mux_stat_top6; + uint32_t clk_mux_stat_top7; + uint8_t res78[0x60]; + uint32_t clk_mux_stat_top10; + uint32_t clk_mux_stat_top11; + uint32_t clk_mux_stat_top12; + uint8_t res79[0x74]; + uint32_t clk_div_top0; /* 0x10020500 */ + uint32_t clk_div_top1; + uint32_t clk_div_top2; + uint8_t res80[0x20]; + uint32_t clk_div_disp10; + uint8_t res81[0x14]; + uint32_t clk_div_mau; + uint32_t clk_div_fsys0; + uint32_t clk_div_fsys1; + uint32_t clk_div_fsys2; + uint8_t res82[0x4]; + uint32_t clk_div_peric0; + uint32_t clk_div_peric1; + uint32_t clk_div_peric2; + uint32_t clk_div_peric3; + uint32_t clk_div_peric4; /* 0x10020568 */ + uint8_t res83[0x14]; + uint32_t clk_div_isp0; + uint32_t clk_div_isp1; + uint8_t res84[0x8]; + uint32_t clkdiv2_ratio; + uint8_t res850[0xc]; + uint32_t clkdiv4_ratio; + uint8_t res85[0x5c]; + uint32_t clk_div_stat_top0; + uint32_t clk_div_stat_top1; + uint32_t clk_div_stat_top2; + uint8_t res86[0x20]; + uint32_t clk_div_stat_disp10; + uint8_t res87[0x14]; + uint32_t clk_div_stat_mau; /* 0x10020644 */ + uint32_t clk_div_stat_fsys0; + uint32_t clk_div_stat_fsys1; + uint32_t clk_div_stat_fsys2; + uint8_t res88[0x4]; + uint32_t clk_div_stat_peric0; + uint32_t clk_div_stat_peric1; + uint32_t clk_div_stat_peric2; + uint32_t clk_div_stat_peric3; + uint32_t clk_div_stat_peric4; + uint8_t res89[0x14]; + uint32_t clk_div_stat_isp0; + uint32_t clk_div_stat_isp1; + uint8_t res90[0x8]; + uint32_t clkdiv2_stat0; + uint8_t res91[0xc]; + uint32_t clkdiv4_stat; + uint8_t res92[0x5c]; + uint32_t clk_gate_bus_top; /* 0x10020700 */ + uint8_t res93[0xc]; + uint32_t clk_gate_bus_gscl0; + uint8_t res94[0xc]; + uint32_t clk_gate_bus_gscl1; + uint8_t res95[0x4]; + uint32_t clk_gate_bus_disp1; + uint8_t res96[0x4]; + uint32_t clk_gate_bus_wcore; + uint32_t clk_gate_bus_mfc; + uint32_t clk_gate_bus_g3d; + uint32_t clk_gate_bus_gen; + uint32_t clk_gate_bus_fsys0; + uint32_t clk_gate_bus_fsys1; + uint32_t clk_gate_bus_fsys2; + uint32_t clk_gate_bus_mscl; + uint32_t clk_gate_bus_peric; + uint32_t clk_gate_bus_peric1; + uint8_t res97[0x8]; + uint32_t clk_gate_bus_peris0; + uint32_t clk_gate_bus_peris1; /* 0x10020764 */ + uint8_t res98[0x8]; + uint32_t clk_gate_bus_noc; + uint8_t res99[0xac]; + uint32_t clk_gate_top_sclk_gscl; + uint8_t res1000[0x4]; + uint32_t clk_gate_top_sclk_disp1; + uint8_t res100[0x10]; + uint32_t clk_gate_top_sclk_mau; + uint32_t clk_gate_top_sclk_fsys; + uint8_t res101[0xc]; + uint32_t clk_gate_top_sclk_peric; + uint8_t res102[0xc]; + uint32_t clk_gate_top_sclk_cperi; + uint8_t res103[0xc]; + uint32_t clk_gate_top_sclk_isp; + uint8_t res104[0x9c]; + uint32_t clk_gate_ip_gscl0; + uint8_t res105[0xc]; + uint32_t clk_gate_ip_gscl1; + uint8_t res106[0x4]; + uint32_t clk_gate_ip_disp1; + uint32_t clk_gate_ip_mfc; + uint32_t clk_gate_ip_g3d; + uint32_t clk_gate_ip_gen; /* 0x10020934 */ + uint8_t res107[0xc]; + uint32_t clk_gate_ip_fsys; + uint8_t res108[0x8]; + uint32_t clk_gate_ip_peric; + uint8_t res109[0xc]; + uint32_t clk_gate_ip_peris; + uint8_t res110[0xc]; + uint32_t clk_gate_ip_mscl; + uint8_t res111[0xc]; + uint32_t clk_gate_ip_block; + uint8_t res112[0xc]; + uint32_t bypass; + uint8_t res113[0x6c]; + uint32_t clkout_cmu_top; + uint32_t clkout_cmu_top_div_stat; + uint8_t res114[0xf8]; + uint32_t clkout_top_spare0; + uint32_t clkout_top_spare1; + uint32_t clkout_top_spare2; + uint32_t clkout_top_spare3; + uint8_t res115[0x34e0]; + uint32_t clkout_top_version; + uint8_t res116[0xc01c]; + uint32_t bpll_lock; /* 0x10030010 */ + uint8_t res117[0xfc]; + uint32_t bpll_con0; + uint32_t bpll_con1; + uint8_t res118[0xe8]; + uint32_t clk_src_cdrex; + uint8_t res119[0x1fc]; + uint32_t clk_mux_stat_cdrex; + uint8_t res120[0xfc]; + uint32_t clk_div_cdrex0; + uint32_t clk_div_cdrex1; + uint8_t res121[0xf8]; + uint32_t clk_div_stat_cdrex; + uint8_t res1211[0xfc]; + uint32_t clk_gate_bus_cdrex; + uint32_t clk_gate_bus_cdrex1; + uint8_t res122[0x1f8]; + uint32_t clk_gate_ip_cdrex; + uint8_t res123[0x10]; + uint32_t dmc_freq_ctrl; /* 0x10030914 */ + uint8_t res124[0x4]; + uint32_t pause; + uint32_t ddrphy_lock_ctrl; + uint8_t res125[0xdc]; + uint32_t clkout_cmu_cdrex; + uint32_t clkout_cmu_cdrex_div_stat; + uint8_t res126[0x8]; + uint32_t lpddr3phy_ctrl; + uint32_t lpddr3phy_con0; + uint32_t lpddr3phy_con1; + uint32_t lpddr3phy_con2; + uint32_t lpddr3phy_con3; + uint32_t lpddr3phy_con4; + uint32_t lpddr3phy_con5; /* 0x10030a28 */ + uint32_t pll_div2_sel; + uint8_t res127[0xd0]; + uint32_t cmu_cdrex_spare0; + uint32_t cmu_cdrex_spare1; + uint32_t cmu_cdrex_spare2; + uint32_t cmu_cdrex_spare3; + uint32_t cmu_cdrex_spare4; + uint8_t res128[0x34dc]; + uint32_t cmu_cdrex_version; /* 0x10033ff0 */ + uint8_t res129[0x400c]; + uint32_t kpll_lock; + uint8_t res130[0xfc]; + uint32_t kpll_con0; + uint32_t kpll_con1; + uint8_t res131[0xf8]; + uint32_t clk_src_kfc; + uint8_t res132[0x1fc]; + uint32_t clk_mux_stat_kfc; /* 0x10038400 */ + uint8_t res133[0xfc]; + uint32_t clk_div_kfc0; + uint8_t res134[0xfc]; + uint32_t clk_div_stat_kfc0; + uint8_t res135[0xfc]; + uint32_t clk_gate_bus_cpu_kfc; + uint8_t res136[0xfc]; + uint32_t clk_gate_sclk_cpu_kfc; + uint8_t res137[0x1fc]; + uint32_t clkout_cmu_kfc; + uint32_t clkout_cmu_kfc_div_stat;/* 0x10038a04 */ + uint8_t res138[0x5f8]; + uint32_t armclk_stopctrl_kfc; + uint8_t res139[0x4]; + uint32_t armclk_ema_ctrl_kfc; + uint32_t armclk_ema_status_kfc; + uint8_t res140[0x10]; + uint32_t pwr_ctrl_kfc; + uint32_t pwr_ctrl2_kfc; + uint8_t res141[0xd8]; + uint32_t kpll_con0_l8; + uint32_t kpll_con0_l7; + uint32_t kpll_con0_l6; + uint32_t kpll_con0_l5; + uint32_t kpll_con0_l4; + uint32_t kpll_con0_l3; + uint32_t kpll_con0_l2; + uint32_t kpll_con0_l1; + uint32_t iem_control_kfc; /* 0x10039120 */ + uint8_t res142[0xdc]; + uint32_t kpll_con1_l8; + uint32_t kpll_con1_l7; + uint32_t kpll_con1_l6; + uint32_t kpll_con1_l5; + uint32_t kpll_con1_l4; + uint32_t kpll_con1_l3; + uint32_t kpll_con1_l2; + uint32_t kpll_con1_l1; + uint8_t res143[0xe0]; + uint32_t clkdiv_iem_l8_kfc; /* 0x10039300 */ + uint32_t clkdiv_iem_l7_kfc; + uint32_t clkdiv_iem_l6_kfc; + uint32_t clkdiv_iem_l5_kfc; + uint32_t clkdiv_iem_l4_kfc; + uint32_t clkdiv_iem_l3_kfc; + uint32_t clkdiv_iem_l2_kfc; + uint32_t clkdiv_iem_l1_kfc; + uint8_t res144[0xe0]; + uint32_t l2_status_kfc; + uint8_t res145[0xc]; + uint32_t cpu_status_kfc; /* 0x10039410 */ + uint8_t res146[0xc]; + uint32_t ptm_status_kfc; + uint8_t res147[0xbdc]; + uint32_t cmu_kfc_spare0; + uint32_t cmu_kfc_spare1; + uint32_t cmu_kfc_spare2; + uint32_t cmu_kfc_spare3; + uint32_t cmu_kfc_spare4; + uint8_t res148[0x1fdc]; + uint32_t cmu_kfc_version; /* 0x1003bff0 */ +}; +check_member(exynos5420_clock, cmu_kfc_version, 0x2bff0); + +static struct exynos5420_clock * const exynos_clock = + (void *)EXYNOS5_CLOCK_BASE; + +struct exynos5_mct { + uint32_t mct_cfg; + uint8_t reserved0[0xfc]; + uint32_t g_cnt_l; + uint32_t g_cnt_u; + uint8_t reserved1[0x8]; + uint32_t g_cnt_wstat; + uint8_t reserved2[0xec]; + uint32_t g_comp0_l; + uint32_t g_comp0_u; + uint32_t g_comp0_addr_incr; + uint8_t reserved3[0x4]; + uint32_t g_comp1_l; + uint32_t g_comp1_u; + uint32_t g_comp1_addr_incr; + uint8_t reserved4[0x4]; + uint32_t g_comp2_l; + uint32_t g_comp2_u; + uint32_t g_comp2_addr_incr; + uint8_t reserved5[0x4]; + uint32_t g_comp3_l; + uint32_t g_comp3_u; + uint32_t g_comp3_addr_incr; + uint8_t reserved6[0x4]; + uint32_t g_tcon; + uint32_t g_int_cstat; + uint32_t g_int_enb; + uint32_t g_wstat; + uint8_t reserved7[0xb0]; + uint32_t l0_tcntb; + uint32_t l0_tcnto; + uint32_t l0_icntb; + uint32_t l0_icnto; + uint32_t l0_frcntb; + uint32_t l0_frcnto; + uint8_t reserved8[0x8]; + uint32_t l0_tcon; + uint8_t reserved9[0xc]; + uint32_t l0_int_cstat; + uint32_t l0_int_enb; + uint8_t reserved10[0x8]; + uint32_t l0_wstat; + uint8_t reserved11[0xbc]; + uint32_t l1_tcntb; + uint32_t l1_tcnto; + uint32_t l1_icntb; + uint32_t l1_icnto; + uint32_t l1_frcntb; + uint32_t l1_frcnto; + uint8_t reserved12[0x8]; + uint32_t l1_tcon; + uint8_t reserved13[0xc]; + uint32_t l1_int_cstat; + uint32_t l1_int_enb; + uint8_t reserved14[0x8]; + uint32_t l1_wstat; +}; +check_member(exynos5_mct, l1_wstat, 0x440); + +static struct exynos5_mct * const exynos_mct = + (void *)EXYNOS5_MULTI_CORE_TIMER_BASE; + +#define EXYNOS5_EPLLCON0_LOCKED_SHIFT 29 /* EPLL Locked bit position*/ +#define EPLL_SRC_CLOCK 24000000 /*24 MHz Cristal Input */ +#define TIMEOUT_EPLL_LOCK 1000 + +#define AUDIO_0_RATIO_MASK 0x0f +#define AUDIO_1_RATIO_MASK 0x0f + +#define CLK_SRC_PERIC1 0x254 +#define AUDIO1_SEL_MASK 0xf +#define CLK_SRC_AUDIOCDCLK1 0x0 +#define CLK_SRC_XXTI 0x1 +#define CLK_SRC_SCLK_EPLL 0x7 + +/* CON0 bit-fields */ +#define EPLL_CON0_MDIV_MASK 0x1ff +#define EPLL_CON0_PDIV_MASK 0x3f +#define EPLL_CON0_SDIV_MASK 0x7 +#define EPLL_CON0_LOCKED_SHIFT 29 +#define EPLL_CON0_MDIV_SHIFT 16 +#define EPLL_CON0_PDIV_SHIFT 8 +#define EPLL_CON0_SDIV_SHIFT 0 +#define EPLL_CON0_LOCK_DET_EN_SHIFT 28 +#define EPLL_CON0_LOCK_DET_EN_MASK 1 + +/* structure for epll configuration used in audio clock configuration */ +struct st_epll_con_val { + unsigned int freq_out; /* frequency out */ + unsigned int en_lock_det; /* enable lock detect */ + unsigned int m_div; /* m divider value */ + unsigned int p_div; /* p divider value */ + unsigned int s_div; /* s divider value */ + unsigned int k_dsm; /* k value of delta signal modulator */ +}; + +/** + * Low-level function to set the clock pre-ratio for a peripheral + * + * @param periph_id Peripheral ID of peripheral to change + * @param divisor New divisor for this peripheral's clock + */ +void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor); + +/** + * Low-level function to set the clock ratio for a peripheral + * + * @param periph_id Peripheral ID of peripheral to change + * @param divisor New divisor for this peripheral's clock + */ +void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor); + +/** + * Low-level function that selects the best clock scalars for a given rate and + * sets up the given peripheral's clock accordingly. + * + * @param periph_id Peripheral ID of peripheral to change + * @param rate Desired clock rate in Hz + * + * @return zero on success, negative on error + */ +int clock_set_rate(enum periph_id periph_id, unsigned int rate); + +/* Clock gate unused IP */ +void clock_gate(void); + +/* These are the ratio's for configuring ARM clock */ +struct arm_clk_ratios { + unsigned int arm_freq_mhz; /* Frequency of ARM core in MHz */ + + unsigned int apll_mdiv; + unsigned int apll_pdiv; + unsigned int apll_sdiv; + + unsigned int arm2_ratio; + unsigned int apll_ratio; + unsigned int pclk_dbg_ratio; + unsigned int atb_ratio; + unsigned int periph_ratio; + unsigned int acp_ratio; + unsigned int cpud_ratio; + unsigned int arm_ratio; +}; + +/** + * Get the clock ratios for CPU configuration + * + * @return pointer to the clock ratios that we should use + */ +struct arm_clk_ratios *get_arm_clk_ratios(void); + +/* + * Initialize clock for the device + */ +struct mem_timings; +void system_clock_init(void); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/cpu.h b/src/soc/samsung/exynos5420/include/soc/cpu.h new file mode 100644 index 0000000000..bea7f1e1e2 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/cpu.h @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_CPU_H +#define CPU_SAMSUNG_EXYNOS5420_CPU_H + +#include +#include + +#define EXYNOS5_SRAM_BASE 0x02020000 + +/* Base address registers */ +#define EXYNOS5420_GPIO_PART6_BASE 0x03860000 /* Z0 */ +#define EXYNOS5_PRO_ID 0x10000000 +#define EXYNOS5_CLOCK_BASE 0x10010000 +#define EXYNOS5_POWER_BASE 0x10040000 +#define EXYNOS5_SYSREG_BASE 0x10050000 +#define EXYNOS5_TZPC1_DECPROT1SET 0x10110810 +#define EXYNOS5_MULTI_CORE_TIMER_BASE 0x101C0000 +#define EXYNOS5_WATCHDOG_BASE 0x101D0000 +#define EXYNOS5_ACE_SFR_BASE 0x10830000 +#define EXYNOS5_DMC_PHY0_BASE 0x10C00000 +#define EXYNOS5_DMC_PHY1_BASE 0x10C10000 +#define EXYNOS5420_DMC_DREXI_0 0x10C20000 +#define EXYNOS5420_DMC_DREXI_1 0x10C30000 +#define EXYNOS5420_DMC_TZASC_0 0x10D40000 +#define EXYNOS5420_DMC_TZASC_1 0x10D50000 +#define EXYNOS5420_USB_DRD0_XHCI_BASE 0x12000000 +#define EXYNOS5420_USB_DRD0_DWC3_BASE 0x1200C100 +#define EXYNOS5420_USB_DRD0_PHY_BASE 0x12100000 +#define EXYNOS5_USB_HOST_EHCI_BASE 0x12110000 +#define EXYNOS5_USB_HOST_PHY_BASE 0x12130000 +#define EXYNOS5_MMC_BASE 0x12200000 +#define EXYNOS5_MSHC_BASE 0x12240000 +#define EXYNOS5_SROMC_BASE 0x12250000 +#define EXYNOS5420_USB_DRD1_XHCI_BASE 0x12400000 +#define EXYNOS5420_USB_DRD1_DWC3_BASE 0x1240C100 +#define EXYNOS5420_USB_DRD1_PHY_BASE 0x12500000 +#define EXYNOS5_UART0_BASE 0x12C00000 +#define EXYNOS5_UART1_BASE 0x12C10000 +#define EXYNOS5_UART2_BASE 0x12C20000 +#define EXYNOS5_UART3_BASE 0x12C30000 +#define EXYNOS5_I2C_BASE 0x12C60000 +#define EXYNOS5_SPI0_BASE 0x12D20000 +#define EXYNOS5_SPI1_BASE 0x12D30000 +#define EXYNOS5_SPI2_BASE 0x12D40000 +#define EXYNOS5_I2S_BASE 0x12D60000 +#define EXYNOS5420_I2C_8910_BASE 0x12E00000 +#define EXYNOS5_UART_ISP_BASE 0x13190000 +#define EXYNOS5_SPI_ISP_BASE 0x131A0000 +#define EXYNOS5420_GPIO_PART1_BASE 0x13400000 /* Y0 */ +#define EXYNOS5420_GPIO_PART2_BASE 0x13400C00 /* X0..3 */ +#define EXYNOS5420_GPIO_PART3_BASE 0x13410000 /* C0..4, D1, Y0..6 */ +#define EXYNOS5420_GPIO_PART4_BASE 0x14000000 /* E0..1, F0..1, G0..2, J4 */ +#define EXYNOS5420_GPIO_PART5_BASE 0x14010000 /* A0..2, B0..4, H0 */ +#define EXYNOS5420_MIPI_DSIM_BASE 0x14500000 +#define EXYNOS5_DP0_BASE 0x14510000 +#define EXYNOS5_DP1_BASE 0x145B0000 + +/* Marker values stored at the bottom of IRAM stack by SPL */ +#define EXYNOS5_SPL_MARKER 0xb004f1a9 /* hexspeak word: bootflag */ + +#define RST_FLAG_VAL 0xfcba0d10 + +#define EXYNOS5_SPI_NUM_CONTROLLERS 5 +#define EXYNOS_I2C_MAX_CONTROLLERS 8 + +extern struct tmu_info exynos5420_tmu_info; + +/* TODO clean up defines. */ +#define FB_SIZE_KB 4096 +#define RAM_BASE_KB ((uintptr_t)_dram/KiB) +#define RAM_SIZE_KB (CONFIG_DRAM_SIZE_MB << 10UL) + +static inline u32 get_fb_base_kb(void) +{ + return RAM_BASE_KB + RAM_SIZE_KB - FB_SIZE_KB; +} + +/* Procedures to setup Exynos5420 CPU */ +void exynos5420_config_smp(void); + +#endif /* _EXYNOS5420_CPU_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/dmc.h b/src/soc/samsung/exynos5420/include/soc/dmc.h new file mode 100644 index 0000000000..e6bfa3aa0f --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/dmc.h @@ -0,0 +1,414 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_DMC_H +#define CPU_SAMSUNG_EXYNOS5420_DMC_H + +#define DMC_INTERLEAVE_SIZE 0x1f + +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 + +/* CONCONTROL register fields */ +#define CONCONTROL_DFI_INIT_START_SHIFT 28 +#define CONCONTROL_RD_FETCH_SHIFT 12 +#define CONCONTROL_RD_FETCH_MASK (0x7 << CONCONTROL_RD_FETCH_SHIFT) +#define CONCONTROL_AREF_EN_SHIFT 5 + +/* PRECHCONFIG register field */ +#define PRECHCONFIG_TP_CNT_SHIFT 24 + +/* PWRDNCONFIG register field */ +#define PWRDNCONFIG_DPWRDN_CYC_SHIFT 0 +#define PWRDNCONFIG_DSREF_CYC_SHIFT 16 + +/* PHY_CON0 register fields */ +#define PHY_CON0_T_WRRDCMD_SHIFT 17 +#define PHY_CON0_T_WRRDCMD_MASK (0x7 << PHY_CON0_T_WRRDCMD_SHIFT) +#define PHY_CON0_CTRL_DDR_MODE_MASK 0x3 +#define PHY_CON0_CTRL_DDR_MODE_SHIFT 11 + +/* PHY_CON1 register fields */ +#define PHY_CON1_RDLVL_RDDATA_ADJ_SHIFT 0 + +/* PHY_CON12 register fields */ +#define PHY_CON12_CTRL_START_POINT_SHIFT 24 +#define PHY_CON12_CTRL_INC_SHIFT 16 +#define PHY_CON12_CTRL_FORCE_SHIFT 8 +#define PHY_CON12_CTRL_START_SHIFT 6 +#define PHY_CON12_CTRL_START_MASK (1 << PHY_CON12_CTRL_START_SHIFT) +#define PHY_CON12_CTRL_DLL_ON_SHIFT 5 +#define PHY_CON12_CTRL_DLL_ON_MASK (1 << PHY_CON12_CTRL_DLL_ON_SHIFT) +#define PHY_CON12_CTRL_REF_SHIFT 1 + +/* PHY_CON16 register fields */ +#define PHY_CON16_ZQ_MODE_DDS_SHIFT 24 +#define PHY_CON16_ZQ_MODE_DDS_MASK (0x7 << PHY_CON16_ZQ_MODE_DDS_SHIFT) + +#define PHY_CON16_ZQ_MODE_TERM_SHIFT 21 +#define PHY_CON16_ZQ_MODE_TERM_MASK (0x7 << PHY_CON16_ZQ_MODE_TERM_SHIFT) + +#define PHY_CON16_ZQ_MODE_NOTERM_MASK (1 << 19) + +/* PHY_CON42 register fields */ +#define PHY_CON42_CTRL_BSTLEN_SHIFT 8 +#define PHY_CON42_CTRL_BSTLEN_MASK (0xff << PHY_CON42_CTRL_BSTLEN_SHIFT) + +#define PHY_CON42_CTRL_RDLAT_SHIFT 0 +#define PHY_CON42_CTRL_RDLAT_MASK (0x1f << PHY_CON42_CTRL_RDLAT_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +struct exynos5_dmc { + uint32_t concontrol; + uint32_t memcontrol; + uint32_t cgcontrol; + uint32_t memconfig1; + uint32_t directcmd; + uint32_t prechconfig0; + uint32_t phycontrol0; + uint32_t prechconfig1; + uint8_t res1[0x8]; + uint32_t pwrdnconfig; /* 0x0028*/ + uint32_t timingpzq; + uint32_t timingref; + uint32_t timingrow; + uint32_t timingdata; + uint32_t timingpower; + uint32_t phystatus; + uint8_t res2[0x4]; + uint32_t chipstatus_ch0; /* 0x0048 */ + uint32_t chipstatus_ch1; + uint8_t res3[0x4]; + uint32_t mrstatus; + uint8_t res4[0x8]; + uint32_t qoscontrol0; /* 0x0060 */ + uint8_t resr5[0x4]; + uint32_t qoscontrol1; + uint8_t res6[0x4]; + uint32_t qoscontrol2; + uint8_t res7[0x4]; + uint32_t qoscontrol3; + uint8_t res8[0x4]; + uint32_t qoscontrol4; + uint8_t res9[0x4]; + uint32_t qoscontrol5; + uint8_t res10[0x4]; + uint32_t qoscontrol6; + uint8_t res11[0x4]; + uint32_t qoscontrol7; + uint8_t res12[0x4]; + uint32_t qoscontrol8; + uint8_t res13[0x4]; + uint32_t qoscontrol9; + uint8_t res14[0x4]; + uint32_t qoscontrol10; + uint8_t res15[0x4]; + uint32_t qoscontrol11; + uint8_t res16[0x4]; + uint32_t qoscontrol12; + uint8_t res17[0x4]; + uint32_t qoscontrol13; + uint8_t res18[0x4]; + uint32_t qoscontrol14; + uint8_t res19[0x4]; + uint32_t qoscontrol15; + uint8_t res20[0x4]; + uint32_t timing_set_sw; /* 0x00e0 */ + uint32_t timingrow1; + uint32_t timingdata1; + uint32_t timingpower1; + uint32_t ivcontrol; + uint32_t wrtra_config; + uint32_t rdlvl_config; + uint8_t res21[0x4]; + uint32_t brbrsvcontrol; /* 0x0100*/ + uint32_t brbrsvconfig; + uint32_t brbqosconfig; + uint32_t membaseconfig0; + uint32_t membaseconfig1; /* 0x0110 */ + uint8_t res22[0xc]; + uint32_t wrlvl_config0; /* 0x0120 */ + uint32_t wrlvl_config1; + uint32_t wrlvl_status; + uint8_t res23[0x4]; + uint32_t perevcontrol; /* 0x0130 */ + uint32_t perev0config; + uint32_t perev1config; + uint32_t perev2config; + uint32_t perev3config; + uint8_t res22a[0xc]; + uint32_t ctrl_io_rdata_ch0; + uint32_t ctrl_io_rdata_ch1; + uint8_t res23a[0x8]; + uint32_t cacal_config0; + uint32_t cacal_config1; + uint32_t cacal_status; + uint8_t res24[0x94]; + uint32_t emergent_config0; /* 0x0200 */ + uint32_t emergent_config1; + uint8_t res25[0x8]; + uint32_t bp_control0; + uint32_t bp_control0_r; + uint32_t bp_control0_w; + uint8_t res26[0x4]; + uint32_t bp_control1; + uint32_t bp_control1_r; + uint32_t bp_control1_w; + uint8_t res27[0x4]; + uint32_t bp_control2; + uint32_t bp_control2_r; + uint32_t bp_control2_w; + uint8_t res28[0x4]; + uint32_t bp_control3; + uint32_t bp_control3_r; + uint32_t bp_control3_w; + uint8_t res29[0xb4]; + uint32_t winconfig_odt_w; /* 0x0300 */ + uint8_t res30[0x4]; + uint32_t winconfig_ctrl_read; + uint32_t winconfig_ctrl_gate; + uint8_t res31[0xdcf0]; + uint32_t pmnc_ppc; + uint8_t res32[0xc]; + uint32_t cntens_ppc; + uint8_t res33[0xc]; + uint32_t cntenc_ppc; + uint8_t res34[0xc]; + uint32_t intens_ppc; + uint8_t res35[0xc]; + uint32_t intenc_ppc; + uint8_t res36[0xc]; + uint32_t flag_ppc; /* 0xe050 */ + uint8_t res37[0xac]; + uint32_t ccnt_ppc; + uint8_t res38[0xc]; + uint32_t pmcnt0_ppc; + uint8_t res39[0xc]; + uint32_t pmcnt1_ppc; + uint8_t res40[0xc]; + uint32_t pmcnt2_ppc; + uint8_t res41[0xc]; + uint32_t pmcnt3_ppc; /* 0xe140 */ +} __attribute__((packed)); +check_member(exynos5_dmc, pmcnt3_ppc, 0xe140); + +static struct exynos5_dmc * const exynos_drex0 = (void *)EXYNOS5420_DMC_DREXI_0; +static struct exynos5_dmc * const exynos_drex1 = (void *)EXYNOS5420_DMC_DREXI_1; + +struct exynos5_phy_control { + uint32_t phy_con0; + uint32_t phy_con1; + uint32_t phy_con2; + uint32_t phy_con3; + uint32_t phy_con4; + uint8_t res1[4]; + uint32_t phy_con6; + uint8_t res2[4]; + uint32_t phy_con8; + uint32_t phy_con9; + uint32_t phy_con10; + uint8_t res3[4]; + uint32_t phy_con12; + uint32_t phy_con13; + uint32_t phy_con14; + uint32_t phy_con15; + uint32_t phy_con16; + uint8_t res4[4]; /* NOT a mistake. Yes, it doesn't make sense. */ + uint32_t phy_con17; + uint32_t phy_con18; + uint32_t phy_con19; + uint32_t phy_con20; + uint32_t phy_con21; + uint32_t phy_con22; + uint32_t phy_con23; + uint32_t phy_con24; + uint32_t phy_con25; + uint32_t phy_con26; + uint32_t phy_con27; + uint32_t phy_con28; + uint32_t phy_con29; + uint32_t phy_con30; + uint32_t phy_con31; + uint32_t phy_con32; + uint32_t phy_con33; + uint32_t phy_con34; + uint32_t phy_con35; + uint32_t phy_con36; + uint32_t phy_con37; + uint32_t phy_con38; + uint32_t phy_con39; + uint32_t phy_con40; + uint32_t phy_con41; + uint32_t phy_con42; +} __attribute__((packed)); +check_member(exynos5_phy_control, phy_con42, 0xac); + +static struct exynos5_phy_control * const exynos_phy0_control = + (void *)EXYNOS5_DMC_PHY0_BASE; +static struct exynos5_phy_control * const exynos_phy1_control = + (void *)EXYNOS5_DMC_PHY1_BASE; + +struct exynos5_tzasc { + uint8_t res1[0xf00]; + uint32_t membaseconfig0; + uint32_t membaseconfig1; + uint8_t res2[0x8]; + uint32_t memconfig0; + uint32_t memconfig1; +} __attribute__((packed)); + +static struct exynos5_tzasc * const exynos_tzasc0 = + (void *)EXYNOS5420_DMC_TZASC_0; +static struct exynos5_tzasc * const exynos_tzasc1 = + (void *)EXYNOS5420_DMC_TZASC_1; + +enum ddr_mode { + /* This is in order of ctrl_ddr_mode values. Do not change. */ + DDR_MODE_DDR2 = 0x0, + DDR_MODE_DDR3 = 0x1, + DDR_MODE_LPDDR2 = 0x2, + DDR_MODE_LPDDR3 = 0x3, + + DDR_MODE_COUNT, +}; + +/* For reasons unknown, people are in the habit of taking a 32-bit + * field with 2 possible values and packing it with, say, 2 bits. A + * non-robust encoding, using only 2 bits of a 32-bit field, is + * incredibly difficult to deal with when things go wrong, because + * there are a lot of things that get expressed as 0, 1, or 2. If + * you're scanning with jtag or dumping memory it is really hard to + * tell when you've hit the beginning of the struct. So, let's be a + * bit smart here. First, while it's common to let the enum count + * entries for you, when there are two of them, we can do the + * counting. And, let's set the values to something we can easily scan + * for in memory. Since '1' and '2' are rather common, we pick + * something that's actually of some value when things go wrong. This + * setup motivated by a use case: something's going wrong and having a + * manuf name of '1' or '2' is completely useless! + */ +enum mem_manuf { + MEM_MANUF_AUTODETECT, + MEM_MANUF_ELPIDA = 0xe7b1da, + MEM_MANUF_SAMSUNG = 0x5a5096, + + MEM_MANUF_COUNT = 2, // fancy that. +}; + +enum { + MEM_TIMINGS_MSR_COUNT = 5, +}; + + +/* These are the memory timings for a particular memory type and speed */ +struct mem_timings { + enum mem_manuf mem_manuf; /* Memory manufacturer */ + enum ddr_mode mem_type; /* Memory type */ + unsigned int frequency_mhz; /* Frequency of memory in MHz */ + + /* Here follow the timing parameters for the selected memory */ + uint8_t apll_mdiv; + uint8_t apll_pdiv; + uint8_t apll_sdiv; + uint8_t mpll_mdiv; + uint8_t mpll_pdiv; + uint8_t mpll_sdiv; + uint8_t cpll_mdiv; + uint8_t cpll_pdiv; + uint8_t cpll_sdiv; + uint8_t gpll_pdiv; + uint16_t gpll_mdiv; + uint8_t gpll_sdiv; + uint8_t epll_mdiv; + uint8_t epll_pdiv; + uint8_t epll_sdiv; + uint8_t vpll_mdiv; + uint8_t vpll_pdiv; + uint8_t vpll_sdiv; + uint8_t bpll_mdiv; + uint8_t bpll_pdiv; + uint8_t bpll_sdiv; + uint8_t use_bpll; /* 1 to use BPLL for cdrex, 0 to use MPLL */ + uint8_t pclk_cdrex_ratio; + unsigned int direct_cmd_msr[MEM_TIMINGS_MSR_COUNT]; + + unsigned int timing_ref; + unsigned int timing_row; + unsigned int timing_data; + unsigned int timing_power; + + /* DQS, DQ, DEBUG offsets */ + unsigned int phy0_dqs; + unsigned int phy1_dqs; + unsigned int phy0_dq; + unsigned int phy1_dq; + uint8_t phy0_tFS; + uint8_t phy1_tFS; + uint8_t phy0_pulld_dqs; + uint8_t phy1_pulld_dqs; + + uint8_t lpddr3_ctrl_phy_reset; + uint8_t ctrl_start_point; + uint8_t ctrl_inc; + uint8_t ctrl_start; + uint8_t ctrl_dll_on; + uint8_t ctrl_ref; + + uint8_t ctrl_force; + uint8_t ctrl_rdlat; + uint8_t ctrl_bstlen; + + uint8_t fp_resync; + uint8_t iv_size; + uint8_t dfi_init_start; + uint8_t aref_en; + + uint8_t rd_fetch; + + uint8_t zq_mode_dds; + uint8_t zq_mode_term; + uint8_t zq_mode_noterm; /* 1 to allow termination disable */ + + unsigned int memcontrol; + unsigned int memconfig; + + unsigned int membaseconfig0; + unsigned int membaseconfig1; + unsigned int prechconfig_tp_cnt; + unsigned int dpwrdn_cyc; + unsigned int dsref_cyc; + unsigned int concontrol; + /* Channel and Chip Selection */ + uint8_t dmc_channels; /* number of memory channels */ + uint8_t chips_per_channel; /* number of chips per channel */ + uint8_t chips_to_configure; /* number of chips to configure */ + uint8_t send_zq_init; /* 1 to send this command */ + unsigned int impedance; /* drive strength impedeance */ + uint8_t gate_leveling_enable; /* check gate leveling is enabled */ +}; + +/** + * Get the correct memory timings for our selected memory type and speed. + * + * @return pointer to the memory timings that we should use + */ +struct mem_timings *get_mem_timings(void); + +#endif +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/dp.h b/src/soc/samsung/exynos5420/include/soc/dp.h new file mode 100644 index 0000000000..73bc9b21fe --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/dp.h @@ -0,0 +1,1431 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Register map for Exynos5 DP */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_DP_H +#define CPU_SAMSUNG_EXYNOS5420_DP_H + +#include + +/* DSIM register map */ +struct exynos_dp { + u8 res1[0x10]; + u32 tx_version; + u32 tx_sw_reset; + u32 func_en1; + u32 func_en2; + u32 video_ctl1; + u32 video_ctl2; + u32 video_ctl3; + u32 video_ctl4; + u32 color_blue_cb; + u32 color_green_y; + u32 color_red_cr; + u32 video_ctl8; + u8 res2[0x4]; + u32 video_ctl10; + u32 total_ln_cfg_l; + u32 total_ln_cfg_h; + u32 active_ln_cfg_l; + u32 active_ln_cfg_h; + u32 vfp_cfg; + u32 vsw_cfg; + u32 vbp_cfg; + u32 total_pix_cfg_l; + u32 total_pix_cfg_h; + u32 active_pix_cfg_l; + u32 active_pix_cfg_h; + u32 hfp_cfg_l; + u32 hfp_cfg_h; + u32 hsw_cfg_l; + u32 hsw_cfg_h; + u32 hbp_cfg_l; + u32 hbp_cfg_h; + u32 video_status; + u32 total_ln_sta_l; + u32 total_ln_sta_h; + u32 active_ln_sta_l; + u32 active_ln_sta_h; + + u32 vfp_sta; + u32 vsw_sta; + u32 vbp_sta; + + u32 total_pix_sta_l; + u32 total_pix_sta_h; + u32 active_pix_sta_l; + u32 active_pix_sta_h; + + u32 hfp_sta_l; + u32 hfp_sta_h; + u32 hsw_sta_l; + u32 hsw_sta_h; + u32 hbp_sta_l; + u32 hbp_sta_h; + + u8 res3[0x288]; + + u32 lane_map; + u8 res4[0x10]; + u32 analog_ctl1; + u32 analog_ctl2; + u32 analog_ctl3; + + u32 pll_filter_ctl1; + u32 amp_tuning_ctl; + u8 res5[0xc]; + + u32 aux_hw_retry_ctl; + u8 res6[0x2c]; + u32 int_state; + u32 common_int_sta1; + u32 common_int_sta2; + u32 common_int_sta3; + u32 common_int_sta4; + u8 res7[0x8]; + + u32 int_sta; + u8 res8[0x1c]; + u32 int_ctl; + u8 res9[0x200]; + u32 sys_ctl1; + u32 sys_ctl2; + u32 sys_ctl3; + u32 sys_ctl4; + u32 vid_ctl; + u8 res10[0x2c]; + u32 pkt_send_ctl; + u8 res[0x4]; + u32 hdcp_ctl; + u8 res11[0x34]; + u32 link_bw_set; + + u32 lane_count_set; + u32 training_ptn_set; + u32 ln0_link_training_ctl; + u32 ln1_link_training_ctl; + u32 ln2_link_training_ctl; + u32 ln3_link_training_ctl; + u32 dn_spread_ctl; + u32 hw_link_training_ctl; + u8 res12[0x1c]; + + u32 debug_ctl; + u32 hpd_deglitch_l; + u32 hpd_deglitch_h; + + u8 res13[0x14]; + u32 link_debug_ctl; + + u8 res14[0x1c]; + + u32 m_vid0; + u32 m_vid1; + u32 m_vid2; + u32 n_vid0; + u32 n_vid1; + u32 n_vid2; + u32 m_vid_mon; + u32 pll_ctl; + u32 phy_pd; + u32 phy_test; + u8 res15[0x8]; + + u32 video_fifo_thrd; + u8 res16[0x8]; + u32 audio_margin; + + u32 dn_spread_ctl1; + u32 dn_spread_ctl2; + u8 res17[0x18]; + u32 m_cal_ctl; + u32 m_vid_gen_filter_th; + u8 res18[0x10]; + u32 m_aud_gen_filter_th; + u8 res50[0x4]; + + u32 aux_ch_sta; + u32 aux_err_num; + u32 aux_ch_defer_ctl; + u32 aux_rx_comm; + u32 buffer_data_ctl; + + u32 aux_ch_ctl1; + u32 aux_addr_7_0; + u32 aux_addr_15_8; + u32 aux_addr_19_16; + u32 aux_ch_ctl2; + u8 res19[0x18]; + u32 buf_data0; + u8 res20[0x3c]; + + u32 soc_general_ctl; + u8 res21[0x8c]; + u32 crc_con; + u32 crc_result; + u8 res22[0x8]; + + u32 common_int_mask1; + u32 common_int_mask2; + u32 common_int_mask3; + u32 common_int_mask4; + u32 int_sta_mask1; + u32 int_sta_mask2; + u32 int_sta_mask3; + u32 int_sta_mask4; + u32 int_sta_mask; + u32 crc_result2; + u32 scrambler_reset_cnt; + + u32 pn_inv; + u32 psr_config; + u32 psr_command0; + u32 psr_command1; + u32 psr_crc_mon0; + u32 psr_crc_mon1; + + u8 res24[0x30]; + u32 phy_bist_ctrl; + u8 res25[0xc]; + u32 phy_ctrl; + u8 res26[0x1c]; + u32 test_pattern_gen_en; + u32 test_pattern_gen_ctrl; +}; +check_member(exynos_dp, phy_ctrl, 0x924); + +static struct exynos_dp * const exynos_dp0 = (void *)EXYNOS5_DP0_BASE; +static struct exynos_dp * const exynos_dp1 = (void *)EXYNOS5_DP1_BASE; + +/* For DP VIDEO CTL 1 */ +#define VIDEO_EN_MASK (0x01 << 7) +#define VIDEO_MUTE_MASK (0x01 << 6) + +/* For DP VIDEO CTL 4 */ +#define VIDEO_BIST_MASK (0x1 << 3) + +/* EXYNOS_DP_ANALOG_CTL_1 */ +#define SEL_BG_NEW_BANDGAP (0x0 << 6) +#define SEL_BG_INTERNAL_RESISTOR (0x1 << 6) +#define TX_TERMINAL_CTRL_73_OHM (0x0 << 4) +#define TX_TERMINAL_CTRL_61_OHM (0x1 << 4) +#define TX_TERMINAL_CTRL_50_OHM (0x2 << 4) +#define TX_TERMINAL_CTRL_45_OHM (0x3 << 4) +#define SWING_A_30PER_G_INCREASE (0x1 << 3) +#define SWING_A_30PER_G_NORMAL (0x0 << 3) + +/* EXYNOS_DP_ANALOG_CTL_2 */ +#define CPREG_BLEED (0x1 << 4) +#define SEL_24M (0x1 << 3) +#define TX_DVDD_BIT_1_0000V (0x3 << 0) +#define TX_DVDD_BIT_1_0625V (0x4 << 0) +#define TX_DVDD_BIT_1_1250V (0x5 << 0) + +/* EXYNOS_DP_ANALOG_CTL_3 */ +#define DRIVE_DVDD_BIT_1_0000V (0x3 << 5) +#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) +#define DRIVE_DVDD_BIT_1_1250V (0x5 << 5) +#define SEL_CURRENT_DEFAULT (0x0 << 3) +#define VCO_BIT_000_MICRO (0x0 << 0) +#define VCO_BIT_200_MICRO (0x1 << 0) +#define VCO_BIT_300_MICRO (0x2 << 0) +#define VCO_BIT_400_MICRO (0x3 << 0) +#define VCO_BIT_500_MICRO (0x4 << 0) +#define VCO_BIT_600_MICRO (0x5 << 0) +#define VCO_BIT_700_MICRO (0x6 << 0) +#define VCO_BIT_900_MICRO (0x7 << 0) + +/* EXYNOS_DP_PLL_FILTER_CTL_1 */ +#define PD_RING_OSC (0x1 << 6) +#define AUX_TERMINAL_CTRL_52_OHM (0x3 << 4) +#define AUX_TERMINAL_CTRL_69_OHM (0x2 << 4) +#define AUX_TERMINAL_CTRL_102_OHM (0x1 << 4) +#define AUX_TERMINAL_CTRL_200_OHM (0x0 << 4) +#define TX_CUR1_1X (0x0 << 2) +#define TX_CUR1_2X (0x1 << 2) +#define TX_CUR1_3X (0x2 << 2) +#define TX_CUR_1_MA (0x0 << 0) +#define TX_CUR_2_MA (0x1 << 0) +#define TX_CUR_3_MA (0x2 << 0) +#define TX_CUR_4_MA (0x3 << 0) + +/* EXYNOS_DP_PLL_FILTER_CTL_2 */ +#define CH3_AMP_0_MV (0x3 << 12) +#define CH2_AMP_0_MV (0x3 << 8) +#define CH1_AMP_0_MV (0x3 << 4) +#define CH0_AMP_0_MV (0x3 << 0) + +/* EXYNOS_DP_PLL_CTL */ +#define DP_PLL_PD (0x1 << 7) +#define DP_PLL_RESET (0x1 << 6) +#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) +#define DP_PLL_REF_BIT_1_1250V (0x5 << 0) +#define DP_PLL_REF_BIT_1_2500V (0x7 << 0) + +/* EXYNOS_DP_INT_CTL */ +#define SOFT_INT_CTRL (0x1 << 2) +#define INT_POL (0x1 << 0) + +/* DP TX SW RESET */ +#define RESET_DP_TX (0x01 << 0) + +/* DP FUNC_EN_1 */ +#define MASTER_VID_FUNC_EN_N (0x1 << 7) +#define SLAVE_VID_FUNC_EN_N (0x1 << 5) +#define AUD_FIFO_FUNC_EN_N (0x1 << 4) +#define AUD_FUNC_EN_N (0x1 << 3) +#define HDCP_FUNC_EN_N (0x1 << 2) +#define CRC_FUNC_EN_N (0x1 << 1) +#define SW_FUNC_EN_N (0x1 << 0) + +/* DP FUNC_EN_2 */ +#define SSC_FUNC_EN_N (0x1 << 7) +#define AUX_FUNC_EN_N (0x1 << 2) +#define SERDES_FIFO_FUNC_EN_N (0x1 << 1) +#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) + +/* EXYNOS_DP_PHY_PD */ +#define PHY_PD (0x1 << 5) +#define AUX_PD (0x1 << 4) +#define CH3_PD (0x1 << 3) +#define CH2_PD (0x1 << 2) +#define CH1_PD (0x1 << 1) +#define CH0_PD (0x1 << 0) + +/* EXYNOS_DP_COMMON_INT_STA_1 */ +#define VSYNC_DET (0x1 << 7) +#define PLL_LOCK_CHG (0x1 << 6) +#define SPDIF_ERR (0x1 << 5) +#define SPDIF_UNSTBL (0x1 << 4) +#define VID_FORMAT_CHG (0x1 << 3) +#define AUD_CLK_CHG (0x1 << 2) +#define VID_CLK_CHG (0x1 << 1) +#define SW_INT (0x1 << 0) + +/* EXYNOS_DP_DEBUG_CTL */ +#define PLL_LOCK (0x1 << 4) +#define F_PLL_LOCK (0x1 << 3) +#define PLL_LOCK_CTRL (0x1 << 2) + +/* EXYNOS_DP_FUNC_EN_2 */ +#define SSC_FUNC_EN_N (0x1 << 7) +#define AUX_FUNC_EN_N (0x1 << 2) +#define SERDES_FIFO_FUNC_EN_N (0x1 << 1) +#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) + +/* EXYNOS_DP_COMMON_INT_STA_4 */ +#define PSR_ACTIVE (0x1 << 7) +#define PSR_INACTIVE (0x1 << 6) +#define SPDIF_BI_PHASE_ERR (0x1 << 5) +#define HOTPLUG_CHG (0x1 << 2) +#define HPD_LOST (0x1 << 1) +#define PLUG (0x1 << 0) + +/* EXYNOS_DP_INT_STA */ +#define INT_HPD (0x1 << 6) +#define HW_TRAINING_FINISH (0x1 << 5) +#define RPLY_RECEIV (0x1 << 1) +#define AUX_ERR (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_3 */ +#define HPD_STATUS (0x1 << 6) +#define F_HPD (0x1 << 5) +#define HPD_CTRL (0x1 << 4) +#define HDCP_RDY (0x1 << 3) +#define STRM_VALID (0x1 << 2) +#define F_VALID (0x1 << 1) +#define VALID_CTRL (0x1 << 0) + +/* EXYNOS_DP_AUX_HW_RETRY_CTL */ +#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) +#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) +#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3) +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3) +#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) +#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0) + +/* EXYNOS_DP_AUX_CH_DEFER_CTL */ +#define DEFER_CTRL_EN (0x1 << 7) +#define DEFER_COUNT(x) (((x) & 0x7f) << 0) + +#define COMMON_INT_MASK_1 (0) +#define COMMON_INT_MASK_2 (0) +#define COMMON_INT_MASK_3 (0) +#define COMMON_INT_MASK_4 (0) +#define INT_STA_MASK (0) + +/* EXYNOS_DP_BUFFER_DATA_CTL */ +#define BUF_CLR (0x1 << 7) +#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0) + +/* EXYNOS_DP_AUX_ADDR_7_0 */ +#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) + +/* EXYNOS_DP_AUX_ADDR_15_8 */ +#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) + +/* EXYNOS_DP_AUX_ADDR_19_16 */ +#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) + +/* EXYNOS_DP_AUX_CH_CTL_1 */ +#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) +#define AUX_TX_COMM_MASK (0xf << 0) +#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) +#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3) +#define AUX_TX_COMM_MOT (0x1 << 2) +#define AUX_TX_COMM_WRITE (0x0 << 0) +#define AUX_TX_COMM_READ (0x1 << 0) + +/* EXYNOS_DP_AUX_CH_CTL_2 */ +#define ADDR_ONLY (0x1 << 1) +#define AUX_EN (0x1 << 0) + +/* EXYNOS_DP_AUX_CH_STA */ +#define AUX_BUSY (0x1 << 4) +#define AUX_STATUS_MASK (0xf << 0) + +/* EXYNOS_DP_AUX_RX_COMM */ +#define AUX_RX_COMM_I2C_DEFER (0x2 << 2) +#define AUX_RX_COMM_AUX_DEFER (0x2 << 0) + +/* EXYNOS_DP_PHY_TEST */ +#define MACRO_RST (0x1 << 5) +#define CH1_TEST (0x1 << 1) +#define CH0_TEST (0x1 << 0) + +/* EXYNOS_DP_TRAINING_PTN_SET */ +#define SCRAMBLER_TYPE (0x1 << 9) +#define HW_LINK_TRAINING_PATTERN (0x1 << 8) +#define SCRAMBLING_DISABLE (0x1 << 5) +#define SCRAMBLING_ENABLE (0x0 << 5) +#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2) +#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2) +#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0) +#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0) +#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) +#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) + +/* EXYNOS_DP_TOTAL_LINE_CFG */ +#define TOTAL_LINE_CFG_L(x) ((x) & 0xff) +#define TOTAL_LINE_CFG_H(x) ((((x) >> 8)) & 0xff) +#define ACTIVE_LINE_CFG_L(x) ((x) & 0xff) +#define ACTIVE_LINE_CFG_H(x) (((x) >> 8) & 0xff) +#define TOTAL_PIXEL_CFG_L(x) ((x) & 0xff) +#define TOTAL_PIXEL_CFG_H(x) ((((x) >> 8)) & 0xff) +#define ACTIVE_PIXEL_CFG_L(x) ((x) & 0xff) +#define ACTIVE_PIXEL_CFG_H(x) ((((x) >> 8)) & 0xff) + +#define H_F_PORCH_CFG_L(x) ((x) & 0xff) +#define H_F_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff) +#define H_SYNC_PORCH_CFG_L(x) ((x) & 0xff) +#define H_SYNC_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff) +#define H_B_PORCH_CFG_L(x) ((x) & 0xff) +#define H_B_PORCH_CFG_H(x) ((((x) >> 8)) & 0xff) + +/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ +#define MAX_PRE_EMPHASIS_REACH_0 (0x1 << 5) +#define PRE_EMPHASIS_SET_0_SET(x) (((x) & 0x3) << 3) +#define PRE_EMPHASIS_SET_0_GET(x) (((x) >> 3) & 0x3) +#define PRE_EMPHASIS_SET_0_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_0_SHIFT (3) +#define PRE_EMPHASIS_SET_0_LEVEL_3 (0x3 << 3) +#define PRE_EMPHASIS_SET_0_LEVEL_2 (0x2 << 3) +#define PRE_EMPHASIS_SET_0_LEVEL_1 (0x1 << 3) +#define PRE_EMPHASIS_SET_0_LEVEL_0 (0x0 << 3) +#define MAX_DRIVE_CURRENT_REACH_0 (0x1 << 2) +#define DRIVE_CURRENT_SET_0_MASK (0x3 << 0) +#define DRIVE_CURRENT_SET_0_SET(x) (((x) & 0x3) << 0) +#define DRIVE_CURRENT_SET_0_GET(x) (((x) >> 0) & 0x3) +#define DRIVE_CURRENT_SET_0_LEVEL_3 (0x3 << 0) +#define DRIVE_CURRENT_SET_0_LEVEL_2 (0x2 << 0) +#define DRIVE_CURRENT_SET_0_LEVEL_1 (0x1 << 0) +#define DRIVE_CURRENT_SET_0_LEVEL_0 (0x0 << 0) + +/* EXYNOS_DP_LN1_LINK_TRAINING_CTL */ +#define MAX_PRE_EMPHASIS_REACH_1 (0x1 << 5) +#define PRE_EMPHASIS_SET_1_SET(x) (((x) & 0x3) << 3) +#define PRE_EMPHASIS_SET_1_GET(x) (((x) >> 3) & 0x3) +#define PRE_EMPHASIS_SET_1_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_1_SHIFT (3) +#define PRE_EMPHASIS_SET_1_LEVEL_3 (0x3 << 3) +#define PRE_EMPHASIS_SET_1_LEVEL_2 (0x2 << 3) +#define PRE_EMPHASIS_SET_1_LEVEL_1 (0x1 << 3) +#define PRE_EMPHASIS_SET_1_LEVEL_0 (0x0 << 3) +#define MAX_DRIVE_CURRENT_REACH_1 (0x1 << 2) +#define DRIVE_CURRENT_SET_1_MASK (0x3 << 0) +#define DRIVE_CURRENT_SET_1_SET(x) (((x) & 0x3) << 0) +#define DRIVE_CURRENT_SET_1_GET(x) (((x) >> 0) & 0x3) +#define DRIVE_CURRENT_SET_1_LEVEL_3 (0x3 << 0) +#define DRIVE_CURRENT_SET_1_LEVEL_2 (0x2 << 0) +#define DRIVE_CURRENT_SET_1_LEVEL_1 (0x1 << 0) +#define DRIVE_CURRENT_SET_1_LEVEL_0 (0x0 << 0) + +/* EXYNOS_DP_LN2_LINK_TRAINING_CTL */ +#define MAX_PRE_EMPHASIS_REACH_2 (0x1 << 5) +#define PRE_EMPHASIS_SET_2_SET(x) (((x) & 0x3) << 3) +#define PRE_EMPHASIS_SET_2_GET(x) (((x) >> 3) & 0x3) +#define PRE_EMPHASIS_SET_2_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_2_SHIFT (3) +#define PRE_EMPHASIS_SET_2_LEVEL_3 (0x3 << 3) +#define PRE_EMPHASIS_SET_2_LEVEL_2 (0x2 << 3) +#define PRE_EMPHASIS_SET_2_LEVEL_1 (0x1 << 3) +#define PRE_EMPHASIS_SET_2_LEVEL_0 (0x0 << 3) +#define MAX_DRIVE_CURRENT_REACH_2 (0x1 << 2) +#define DRIVE_CURRENT_SET_2_MASK (0x3 << 0) +#define DRIVE_CURRENT_SET_2_SET(x) (((x) & 0x3) << 0) +#define DRIVE_CURRENT_SET_2_GET(x) (((x) >> 0) & 0x3) +#define DRIVE_CURRENT_SET_2_LEVEL_3 (0x3 << 0) +#define DRIVE_CURRENT_SET_2_LEVEL_2 (0x2 << 0) +#define DRIVE_CURRENT_SET_2_LEVEL_1 (0x1 << 0) +#define DRIVE_CURRENT_SET_2_LEVEL_0 (0x0 << 0) + +/* EXYNOS_DP_LN3_LINK_TRAINING_CTL */ +#define MAX_PRE_EMPHASIS_REACH_3 (0x1 << 5) +#define PRE_EMPHASIS_SET_3_SET(x) (((x) & 0x3) << 3) +#define PRE_EMPHASIS_SET_3_GET(x) (((x) >> 3) & 0x3) +#define PRE_EMPHASIS_SET_3_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_3_SHIFT (3) +#define PRE_EMPHASIS_SET_3_LEVEL_3 (0x3 << 3) +#define PRE_EMPHASIS_SET_3_LEVEL_2 (0x2 << 3) +#define PRE_EMPHASIS_SET_3_LEVEL_1 (0x1 << 3) +#define PRE_EMPHASIS_SET_3_LEVEL_0 (0x0 << 3) +#define MAX_DRIVE_CURRENT_REACH_3 (0x1 << 2) +#define DRIVE_CURRENT_SET_3_MASK (0x3 << 0) +#define DRIVE_CURRENT_SET_3_SET(x) (((x) & 0x3) << 0) +#define DRIVE_CURRENT_SET_3_GET(x) (((x) >> 0) & 0x3) +#define DRIVE_CURRENT_SET_3_LEVEL_3 (0x3 << 0) +#define DRIVE_CURRENT_SET_3_LEVEL_2 (0x2 << 0) +#define DRIVE_CURRENT_SET_3_LEVEL_1 (0x1 << 0) +#define DRIVE_CURRENT_SET_3_LEVEL_0 (0x0 << 0) + +/* EXYNOS_DP_VIDEO_CTL_10 */ +#define FORMAT_SEL (0x1 << 4) +#define INTERACE_SCAN_CFG (0x1 << 2) +#define INTERACE_SCAN_CFG_SHIFT (2) +#define VSYNC_POLARITY_CFG (0x1 << 1) +#define V_S_POLARITY_CFG_SHIFT (1) +#define HSYNC_POLARITY_CFG (0x1 << 0) +#define H_S_POLARITY_CFG_SHIFT (0) + +/* EXYNOS_DP_SOC_GENERAL_CTL */ +#define AUDIO_MODE_SPDIF_MODE (0x1 << 8) +#define AUDIO_MODE_MASTER_MODE (0x0 << 8) +#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) +#define VIDEO_MASTER_CLK_SEL (0x1 << 2) +#define VIDEO_MASTER_MODE_EN (0x1 << 1) +#define VIDEO_MODE_MASK (0x1 << 0) +#define VIDEO_MODE_SLAVE_MODE (0x1 << 0) +#define VIDEO_MODE_MASTER_MODE (0x0 << 0) + +/* EXYNOS_DP_VIDEO_CTL_1 */ +#define VIDEO_EN (0x1 << 7) +#define HDCP_VIDEO_MUTE (0x1 << 6) + +/* EXYNOS_DP_VIDEO_CTL_2 */ +#define IN_D_RANGE_MASK (0x1 << 7) +#define IN_D_RANGE_SHIFT (7) +#define IN_D_RANGE_CEA (0x1 << 7) +#define IN_D_RANGE_VESA (0x0 << 7) +#define IN_BPC_MASK (0x7 << 4) +#define IN_BPC_SHIFT (4) +#define IN_BPC_12_BITS (0x3 << 4) +#define IN_BPC_10_BITS (0x2 << 4) +#define IN_BPC_8_BITS (0x1 << 4) +#define IN_BPC_6_BITS (0x0 << 4) +#define IN_COLOR_F_MASK (0x3 << 0) +#define IN_COLOR_F_SHIFT (0) +#define IN_COLOR_F_YCBCR444 (0x2 << 0) +#define IN_COLOR_F_YCBCR422 (0x1 << 0) +#define IN_COLOR_F_RGB (0x0 << 0) + +/* EXYNOS_DP_VIDEO_CTL_3 */ +#define IN_YC_COEFFI_MASK (0x1 << 7) +#define IN_YC_COEFFI_SHIFT (7) +#define IN_YC_COEFFI_ITU709 (0x1 << 7) +#define IN_YC_COEFFI_ITU601 (0x0 << 7) +#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_SHIFT (4) +#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) + +/* EXYNOS_DP_TEST_PATTERN_GEN_EN */ +#define TEST_PATTERN_GEN_EN (0x1 << 0) +#define TEST_PATTERN_GEN_DIS (0x0 << 0) + +/* EXYNOS_DP_TEST_PATTERN_GEN_CTRL */ +#define TEST_PATTERN_MODE_COLOR_SQUARE (0x3 << 0) +#define TEST_PATTERN_MODE_BALCK_WHITE_V_LINES (0x2 << 0) +#define TEST_PATTERN_MODE_COLOR_RAMP (0x1 << 0) + +/* EXYNOS_DP_VIDEO_CTL_4 */ +#define BIST_EN (0x1 << 3) +#define BIST_WIDTH_MASK (0x1 << 2) +#define BIST_WIDTH_BAR_32_PIXEL (0x0 << 2) +#define BIST_WIDTH_BAR_64_PIXEL (0x1 << 2) +#define BIST_TYPE_MASK (0x3 << 0) +#define BIST_TYPE_COLOR_BAR (0x0 << 0) +#define BIST_TYPE_WHITE_GRAY_BLACK_BAR (0x1 << 0) +#define BIST_TYPE_MOBILE_WHITE_BAR (0x2 << 0) + +/* EXYNOS_DP_SYS_CTL_1 */ +#define DET_STA (0x1 << 2) +#define FORCE_DET (0x1 << 1) +#define DET_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_2 */ +#define CHA_CRI(x) (((x) & 0xf) << 4) +#define CHA_STA (0x1 << 2) +#define FORCE_CHA (0x1 << 1) +#define CHA_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_3 */ +#define HPD_STATUS (0x1 << 6) +#define F_HPD (0x1 << 5) +#define HPD_CTRL (0x1 << 4) +#define HDCP_RDY (0x1 << 3) +#define STRM_VALID (0x1 << 2) +#define F_VALID (0x1 << 1) +#define VALID_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_4 */ +#define FIX_M_AUD (0x1 << 4) +#define ENHANCED (0x1 << 3) +#define FIX_M_VID (0x1 << 2) +#define M_VID_UPDATE_CTRL (0x3 << 0) + +/* EXYNOS_M_VID_X */ +#define M_VID0_CFG(x) ((x) & 0xff) +#define M_VID1_CFG(x) (((x) >> 8) & 0xff) +#define M_VID2_CFG(x) (((x) >> 16) & 0xff) + +/* EXYNOS_M_VID_X */ +#define N_VID0_CFG(x) ((x) & 0xff) +#define N_VID1_CFG(x) (((x) >> 8) & 0xff) +#define N_VID2_CFG(x) (((x) >> 16) & 0xff) + +/* DPCD_TRAINING_PATTERN_SET */ +#define DPCD_SCRAMBLING_DISABLED (0x1 << 5) +#define DPCD_SCRAMBLING_ENABLED (0x0 << 5) +#define DPCD_TRAINING_PATTERN_2 (0x2 << 0) +#define DPCD_TRAINING_PATTERN_1 (0x1 << 0) +#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0) + +/* Definition for DPCD Register */ +#define DPCD_DPCD_REV (0x0000) +#define DPCD_MAX_LINK_RATE (0x0001) +#define DPCD_MAX_LANE_COUNT (0x0002) +#define DPCD_LINK_BW_SET (0x0100) +#define DPCD_LANE_COUNT_SET (0x0101) +#define DPCD_TRAINING_PATTERN_SET (0x0102) +#define DPCD_TRAINING_LANE0_SET (0x0103) +#define DPCD_LANE0_1_STATUS (0x0202) +#define DPCD_LN_ALIGN_UPDATED (0x0204) +#define DPCD_ADJUST_REQUEST_LANE0_1 (0x0206) +#define DPCD_ADJUST_REQUEST_LANE2_3 (0x0207) +#define DPCD_TEST_REQUEST (0x0218) +#define DPCD_TEST_RESPONSE (0x0260) +#define DPCD_TEST_EDID_CHECKSUM (0x0261) +#define DPCD_SINK_POWER_STATE (0x0600) + +/* DPCD_TEST_REQUEST */ +#define DPCD_TEST_EDID_READ (0x1 << 2) + +/* DPCD_TEST_RESPONSE */ +#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2) + +/* DPCD_SINK_POWER_STATE */ +#define DPCD_SET_POWER_STATE_D0 (0x1 << 0) +#define DPCD_SET_POWER_STATE_D4 (0x2 << 0) + +/* I2C EDID Chip ID, Slave Address */ +#define I2C_EDID_DEVICE_ADDR (0x50) +#define I2C_E_EDID_DEVICE_ADDR (0x30) +#define EDID_BLOCK_LENGTH (0x80) +#define EDID_HEADER_PATTERN (0x00) +#define EDID_EXTENSION_FLAG (0x7e) +#define EDID_CHECKSUM (0x7f) + +/* DPCD_LANE0_1_STATUS */ +#define DPCD_LANE1_SYMBOL_LOCKED (0x1 << 6) +#define DPCD_LANE1_CHANNEL_EQ_DONE (0x1 << 5) +#define DPCD_LANE1_CR_DONE (0x1 << 4) +#define DPCD_LANE0_SYMBOL_LOCKED (0x1 << 2) +#define DPCD_LANE0_CHANNEL_EQ_DONE (0x1 << 1) +#define DPCD_LANE0_CR_DONE (0x1 << 0) + +/* DPCD_ADJUST_REQUEST_LANE0_1 */ +#define DPCD_PRE_EMPHASIS_LANE1_MASK (0x3 << 6) +#define DPCD_PRE_EMPHASIS_LANE1(x) (((x) >> 6) & 0x3) +#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_3 (0x3 << 6) +#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_2 (0x2 << 6) +#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_1 (0x1 << 6) +#define DPCD_PRE_EMPHASIS_LANE1_LEVEL_0 (0x0 << 6) +#define DPCD_VOLTAGE_SWING_LANE1_MASK (0x3 << 4) +#define DPCD_VOLTAGE_SWING_LANE1(x) (((x) >> 4) & 0x3) +#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_3 (0x3 << 4) +#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_2 (0x2 << 4) +#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_1 (0x1 << 4) +#define DPCD_VOLTAGE_SWING_LANE1_LEVEL_0 (0x0 << 4) +#define DPCD_PRE_EMPHASIS_LANE0_MASK (0x3 << 2) +#define DPCD_PRE_EMPHASIS_LANE0(x) (((x) >> 2) & 0x3) +#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_3 (0x3 << 2) +#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_2 (0x2 << 2) +#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_1 (0x1 << 2) +#define DPCD_PRE_EMPHASIS_LANE0_LEVEL_0 (0x0 << 2) +#define DPCD_VOLTAGE_SWING_LANE0_MASK (0x3 << 0) +#define DPCD_VOLTAGE_SWING_LANE0(x) (((x) >> 0) & 0x3) +#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_3 (0x3 << 0) +#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_2 (0x2 << 0) +#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_1 (0x1 << 0) +#define DPCD_VOLTAGE_SWING_LANE0_LEVEL_0 (0x0 << 0) + +/* DPCD_ADJUST_REQUEST_LANE2_3 */ +#define DPCD_PRE_EMPHASIS_LANE2_MASK (0x3 << 6) +#define DPCD_PRE_EMPHASIS_LANE2(x) (((x) >> 6) & 0x3) +#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_3 (0x3 << 6) +#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_2 (0x2 << 6) +#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_1 (0x1 << 6) +#define DPCD_PRE_EMPHASIS_LANE2_LEVEL_0 (0x0 << 6) +#define DPCD_VOLTAGE_SWING_LANE2_MASK (0x3 << 4) +#define DPCD_VOLTAGE_SWING_LANE2(x) (((x) >> 4) & 0x3) +#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_3 (0x3 << 4) +#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_2 (0x2 << 4) +#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_1 (0x1 << 4) +#define DPCD_VOLTAGE_SWING_LANE2_LEVEL_0 (0x0 << 4) +#define DPCD_PRE_EMPHASIS_LANE3_MASK (0x3 << 2) +#define DPCD_PRE_EMPHASIS_LANE3(x) (((x) >> 2) & 0x3) +#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_3 (0x3 << 2) +#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_2 (0x2 << 2) +#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_1 (0x1 << 2) +#define DPCD_PRE_EMPHASIS_LANE3_LEVEL_0 (0x0 << 2) +#define DPCD_VOLTAGE_SWING_LANE3_MASK (0x3 << 0) +#define DPCD_VOLTAGE_SWING_LANE3(x) (((x) >> 0) & 0x3) +#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_3 (0x3 << 0) +#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_2 (0x2 << 0) +#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_1 (0x1 << 0) +#define DPCD_VOLTAGE_SWING_LANE3_LEVEL_0 (0x0 << 0) + +/* DPCD_LANE_COUNT_SET */ +#define DPCD_ENHANCED_FRAME_EN (0x1 << 7) +#define DPCD_LN_COUNT_SET(x) ((x) & 0x1f) + +/* DPCD_LANE_ALIGN__STATUS_UPDATED */ +#define DPCD_LINK_STATUS_UPDATED (0x1 << 7) +#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6) +#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0) + +/* DPCD_TRAINING_LANE0_SET */ +#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_3 (0x3 << 3) +#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_2 (0x2 << 3) +#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_1 (0x1 << 3) +#define DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 (0x0 << 3) +#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_3 (0x3 << 0) +#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_2 (0x2 << 0) +#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_1 (0x1 << 0) +#define DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0 (0x0 << 0) + +#define DPCD_REQ_ADJ_SWING (0x00) +#define DPCD_REQ_ADJ_EMPHASIS (0x01) + +#define DP_LANE_STAT_CR_DONE (0x01 << 0) +#define DP_LANE_STAT_CE_DONE (0x01 << 1) +#define DP_LANE_STAT_SYM_LOCK (0x01 << 2) + +struct exynos_fb { + u32 vidcon0; + u32 vidcon1; + u32 vidcon2; + u32 vidcon3; + u32 vidtcon0; + u32 vidtcon1; + u32 vidtcon2; + u32 vidtcon3; + u32 wincon0; + u32 wincon1; + u32 wincon2; + u32 wincon3; + u32 wincon4; + + u32 winshmap; + u32 res1; + + u32 winchmap2; + u32 vidosd0a; + u32 vidosd0b; + u32 vidosd0c; + u32 res2; + + u32 vidosd1a; + u32 vidosd1b; + u32 vidosd1c; + u32 vidosd1d; + + u32 vidosd2a; + u32 vidosd2b; + u32 vidosd2c; + u32 vidosd2d; + + u32 vidosd3a; + u32 vidosd3b; + u32 vidosd3c; + u32 res3; + + u32 vidosd4a; + u32 vidosd4b; + u32 vidosd4c; + u32 res4[5]; + + u32 vidw00add0b0; + u32 vidw00add0b1; + u32 vidw01add0b0; + u32 vidw01add0b1; + + u32 vidw02add0b0; + u32 vidw02add0b1; + u32 vidw03add0b0; + u32 vidw03add0b1; + u32 vidw04add0b0; + u32 vidw04add0b1; + u32 res5[2]; + + u32 vidw00add1b0; + u32 vidw00add1b1; + u32 vidw01add1b0; + u32 vidw01add1b1; + + u32 vidw02add1b0; + u32 vidw02add1b1; + u32 vidw03add1b0; + u32 vidw03add1b1; + + u32 vidw04add1b0; + u32 vidw04add1b1; + u32 res7[2]; + + u32 vidw00add2; + u32 vidw01add2; + u32 vidw02add2; + u32 vidw03add2; + u32 vidw04add2; + u32 res8[7]; + + u32 vidintcon0; + u32 vidintcon1; + u32 res9[1]; + + u32 w1keycon0; + u32 w1keycon1; + u32 w2keycon0; + u32 w2keycon1; + u32 w3keycon0; + u32 w3keycon1; + u32 w4keycon0; + u32 w4keycon1; + + u32 w1keyalpha; + u32 w2keyalpha; + u32 w3keyalpha; + u32 w4keyalpha; + + u32 dithmode; + u32 res10[2]; + + u32 win0map; + u32 win1map; + u32 win2map; + u32 win3map; + u32 win4map; + u32 res11[1]; + + u32 wpalcon_h; + u32 wpalcon_l; + + u32 trigcon; + u32 res12[2]; + + u32 i80ifcona0; + u32 i80ifcona1; + u32 i80ifconb0; + u32 i80ifconb1; + + u32 colorgaincon; + u32 res13[2]; + + u32 ldi_cmdcon0; + u32 ldi_cmdcon1; + u32 res14[1]; + + /* To be updated */ + + u8 res15[156]; + u32 dualrgb; + u8 res16[16]; + u32 dp_mie_clkcon; +}; +/* TODO: can't decipher this, someone add a check_member() please */ + +/* LCD IF register offset */ +#define EXYNOS5_LCD_IF_BASE_OFFSET 0x20000 + +static inline u32 exynos_fimd_get_base_offset(void) +{ + return EXYNOS5_LCD_IF_BASE_OFFSET/4; +} + +/* + * Register offsets +*/ +#define EXYNOS_WINCON(x) (x) +#define EXYNOS_VIDOSD(x) (x * 4) +#define EXYNOS_BUFFER_OFFSET(x) (x * 2) +#define EXYNOS_BUFFER_SIZE(x) (x) + +/* + * Bit Definitions +*/ + +/* VIDCON0 */ +#define EXYNOS_VIDCON0_DSI_DISABLE (0 << 30) +#define EXYNOS_VIDCON0_DSI_ENABLE (1 << 30) +#define EXYNOS_VIDCON0_SCAN_PROGRESSIVE (0 << 29) +#define EXYNOS_VIDCON0_SCAN_INTERLACE (1 << 29) +#define EXYNOS_VIDCON0_SCAN_MASK (1 << 29) +#define EXYNOS_VIDCON0_VIDOUT_RGB (0 << 26) +#define EXYNOS_VIDCON0_VIDOUT_ITU (1 << 26) +#define EXYNOS_VIDCON0_VIDOUT_I80LDI0 (2 << 26) +#define EXYNOS_VIDCON0_VIDOUT_I80LDI1 (3 << 26) +#define EXYNOS_VIDCON0_VIDOUT_WB_RGB (4 << 26) +#define EXYNOS_VIDCON0_VIDOUT_WB_I80LDI0 (6 << 26) +#define EXYNOS_VIDCON0_VIDOUT_WB_I80LDI1 (7 << 26) +#define EXYNOS_VIDCON0_VIDOUT_MASK (7 << 26) +#define EXYNOS_VIDCON0_PNRMODE_RGB_P (0 << 17) +#define EXYNOS_VIDCON0_PNRMODE_BGR_P (1 << 17) +#define EXYNOS_VIDCON0_PNRMODE_RGB_S (2 << 17) +#define EXYNOS_VIDCON0_PNRMODE_BGR_S (3 << 17) +#define EXYNOS_VIDCON0_PNRMODE_MASK (3 << 17) +#define EXYNOS_VIDCON0_PNRMODE_SHIFT (17) +#define EXYNOS_VIDCON0_CLKVALUP_ALWAYS (0 << 16) +#define EXYNOS_VIDCON0_CLKVALUP_START_FRAME (1 << 16) +#define EXYNOS_VIDCON0_CLKVALUP_MASK (1 << 16) +#define EXYNOS_VIDCON0_CLKVAL_F(x) (((x) & 0xff) << 6) +#define EXYNOS_VIDCON0_VCLKEN_NORMAL (0 << 5) +#define EXYNOS_VIDCON0_VCLKEN_FREERUN (1 << 5) +#define EXYNOS_VIDCON0_VCLKEN_MASK (1 << 5) +#define EXYNOS_VIDCON0_CLKDIR_DIRECTED (0 << 4) +#define EXYNOS_VIDCON0_CLKDIR_DIVIDED (1 << 4) +#define EXYNOS_VIDCON0_CLKDIR_MASK (1 << 4) +#define EXYNOS_VIDCON0_CLKSEL_HCLK (0 << 2) +#define EXYNOS_VIDCON0_CLKSEL_SCLK (1 << 2) +#define EXYNOS_VIDCON0_CLKSEL_MASK (1 << 2) +#define EXYNOS_VIDCON0_ENVID_ENABLE (1 << 1) +#define EXYNOS_VIDCON0_ENVID_DISABLE (0 << 1) +#define EXYNOS_VIDCON0_ENVID_F_ENABLE (1 << 0) +#define EXYNOS_VIDCON0_ENVID_F_DISABLE (0 << 0) + +/* VIDCON1 */ +#define EXYNOS_VIDCON1_IVCLK_FALLING_EDGE (0 << 7) +#define EXYNOS_VIDCON1_IVCLK_RISING_EDGE (1 << 7) +#define EXYNOS_VIDCON1_IHSYNC_NORMAL (0 << 6) +#define EXYNOS_VIDCON1_IHSYNC_INVERT (1 << 6) +#define EXYNOS_VIDCON1_IVSYNC_NORMAL (0 << 5) +#define EXYNOS_VIDCON1_IVSYNC_INVERT (1 << 5) +#define EXYNOS_VIDCON1_IVDEN_NORMAL (0 << 4) +#define EXYNOS_VIDCON1_IVDEN_INVERT (1 << 4) + +/* VIDCON2 */ +#define EXYNOS_VIDCON2_EN601_DISABLE (0 << 23) +#define EXYNOS_VIDCON2_EN601_ENABLE (1 << 23) +#define EXYNOS_VIDCON2_EN601_MASK (1 << 23) +#define EXYNOS_VIDCON2_WB_DISABLE (0 << 15) +#define EXYNOS_VIDCON2_WB_ENABLE (1 << 15) +#define EXYNOS_VIDCON2_WB_MASK (1 << 15) +#define EXYNOS_VIDCON2_TVFORMATSEL_HW (0 << 14) +#define EXYNOS_VIDCON2_TVFORMATSEL_SW (1 << 14) +#define EXYNOS_VIDCON2_TVFORMATSEL_MASK (1 << 14) +#define EXYNOS_VIDCON2_TVFORMATSEL_YUV422 (1 << 12) +#define EXYNOS_VIDCON2_TVFORMATSEL_YUV444 (2 << 12) +#define EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK (3 << 12) +#define EXYNOS_VIDCON2_ORGYUV_YCBCR (0 << 8) +#define EXYNOS_VIDCON2_ORGYUV_CBCRY (1 << 8) +#define EXYNOS_VIDCON2_ORGYUV_MASK (1 << 8) +#define EXYNOS_VIDCON2_YUVORD_CBCR (0 << 7) +#define EXYNOS_VIDCON2_YUVORD_CRCB (1 << 7) +#define EXYNOS_VIDCON2_YUVORD_MASK (1 << 7) + +/* PRTCON */ +#define EXYNOS_PRTCON_UPDATABLE (0 << 11) +#define EXYNOS_PRTCON_PROTECT (1 << 11) + +/* VIDTCON0 */ +#define EXYNOS_VIDTCON0_VBPDE(x) (((x) & 0xff) << 24) +#define EXYNOS_VIDTCON0_VBPD(x) (((x) & 0xff) << 16) +#define EXYNOS_VIDTCON0_VFPD(x) (((x) & 0xff) << 8) +#define EXYNOS_VIDTCON0_VSPW(x) (((x) & 0xff) << 0) + +/* VIDTCON1 */ +#define EXYNOS_VIDTCON1_VFPDE(x) (((x) & 0xff) << 24) +#define EXYNOS_VIDTCON1_HBPD(x) (((x) & 0xff) << 16) +#define EXYNOS_VIDTCON1_HFPD(x) (((x) & 0xff) << 8) +#define EXYNOS_VIDTCON1_HSPW(x) (((x) & 0xff) << 0) + +/* VIDTCON2 */ +#define EXYNOS_VIDTCON2_LINEVAL(x) (((x) & 0x7ff) << 11) +#define EXYNOS_VIDTCON2_HOZVAL(x) (((x) & 0x7ff) << 0) +#define EXYNOS_VIDTCON2_LINEVAL_E(x) ((((x) & 0x800) >> 11) << 23) +#define EXYNOS_VIDTCON2_HOZVAL_E(x) ((((x) & 0x800) >> 11) << 22) + +/* Window 0~4 Control - WINCONx */ +#define EXYNOS_WINCON_DATAPATH_DMA (0 << 22) +#define EXYNOS_WINCON_DATAPATH_LOCAL (1 << 22) +#define EXYNOS_WINCON_DATAPATH_MASK (1 << 22) +#define EXYNOS_WINCON_BUFSEL_0 (0 << 20) +#define EXYNOS_WINCON_BUFSEL_1 (1 << 20) +#define EXYNOS_WINCON_BUFSEL_MASK (1 << 20) +#define EXYNOS_WINCON_BUFSEL_SHIFT (20) +#define EXYNOS_WINCON_BUFAUTO_DISABLE (0 << 19) +#define EXYNOS_WINCON_BUFAUTO_ENABLE (1 << 19) +#define EXYNOS_WINCON_BUFAUTO_MASK (1 << 19) +#define EXYNOS_WINCON_BITSWP_DISABLE (0 << 18) +#define EXYNOS_WINCON_BITSWP_ENABLE (1 << 18) +#define EXYNOS_WINCON_BITSWP_SHIFT (18) +#define EXYNOS_WINCON_BYTESWP_DISABLE (0 << 17) +#define EXYNOS_WINCON_BYTESWP_ENABLE (1 << 17) +#define EXYNOS_WINCON_BYTESWP_SHIFT (17) +#define EXYNOS_WINCON_HAWSWP_DISABLE (0 << 16) +#define EXYNOS_WINCON_HAWSWP_ENABLE (1 << 16) +#define EXYNOS_WINCON_HAWSWP_SHIFT (16) +#define EXYNOS_WINCON_WSWP_DISABLE (0 << 15) +#define EXYNOS_WINCON_WSWP_ENABLE (1 << 15) +#define EXYNOS_WINCON_WSWP_SHIFT (15) +#define EXYNOS_WINCON_INRGB_RGB (0 << 13) +#define EXYNOS_WINCON_INRGB_YUV (1 << 13) +#define EXYNOS_WINCON_INRGB_MASK (1 << 13) +#define EXYNOS_WINCON_BURSTLEN_16WORD (0 << 9) +#define EXYNOS_WINCON_BURSTLEN_8WORD (1 << 9) +#define EXYNOS_WINCON_BURSTLEN_4WORD (2 << 9) +#define EXYNOS_WINCON_BURSTLEN_MASK (3 << 9) +#define EXYNOS_WINCON_ALPHA_MULTI_DISABLE (0 << 7) +#define EXYNOS_WINCON_ALPHA_MULTI_ENABLE (1 << 7) +#define EXYNOS_WINCON_BLD_PLANE (0 << 6) +#define EXYNOS_WINCON_BLD_PIXEL (1 << 6) +#define EXYNOS_WINCON_BLD_MASK (1 << 6) +#define EXYNOS_WINCON_BPPMODE_1BPP (0 << 2) +#define EXYNOS_WINCON_BPPMODE_2BPP (1 << 2) +#define EXYNOS_WINCON_BPPMODE_4BPP (2 << 2) +#define EXYNOS_WINCON_BPPMODE_8BPP_PAL (3 << 2) +#define EXYNOS_WINCON_BPPMODE_8BPP (4 << 2) +#define EXYNOS_WINCON_BPPMODE_16BPP_565 (5 << 2) +#define EXYNOS_WINCON_BPPMODE_16BPP_A555 (6 << 2) +#define EXYNOS_WINCON_BPPMODE_18BPP_666 (8 << 2) +#define EXYNOS_WINCON_BPPMODE_18BPP_A665 (9 << 2) +#define EXYNOS_WINCON_BPPMODE_24BPP_888 (0xb << 2) +#define EXYNOS_WINCON_BPPMODE_24BPP_A887 (0xc << 2) +#define EXYNOS_WINCON_BPPMODE_32BPP (0xd << 2) +#define EXYNOS_WINCON_BPPMODE_16BPP_A444 (0xe << 2) +#define EXYNOS_WINCON_BPPMODE_15BPP_555 (0xf << 2) +#define EXYNOS_WINCON_BPPMODE_MASK (0xf << 2) +#define EXYNOS_WINCON_BPPMODE_SHIFT (2) +#define EXYNOS_WINCON_ALPHA0_SEL (0 << 1) +#define EXYNOS_WINCON_ALPHA1_SEL (1 << 1) +#define EXYNOS_WINCON_ALPHA_SEL_MASK (1 << 1) +#define EXYNOS_WINCON_ENWIN_DISABLE (0 << 0) +#define EXYNOS_WINCON_ENWIN_ENABLE (1 << 0) + +/* WINCON1 special */ +#define EXYNOS_WINCON1_VP_DISABLE (0 << 24) +#define EXYNOS_WINCON1_VP_ENABLE (1 << 24) +#define EXYNOS_WINCON1_LOCALSEL_FIMC1 (0 << 23) +#define EXYNOS_WINCON1_LOCALSEL_VP (1 << 23) +#define EXYNOS_WINCON1_LOCALSEL_MASK (1 << 23) + +/* WINSHMAP */ +#define EXYNOS_WINSHMAP_PROTECT(x) (((x) & 0x1f) << 10) +#define EXYNOS_WINSHMAP_CH_ENABLE(x) (1 << (x)) +#define EXYNOS_WINSHMAP_CH_DISABLE(x) (1 << (x)) +#define EXYNOS_WINSHMAP_LOCAL_ENABLE(x) (0x20 << (x)) +#define EXYNOS_WINSHMAP_LOCAL_DISABLE(x) (0x20 << (x)) + +/* VIDOSDxA, VIDOSDxB */ +#define EXYNOS_VIDOSD_LEFT_X(x) (((x) & 0x7ff) << 11) +#define EXYNOS_VIDOSD_TOP_Y(x) (((x) & 0x7ff) << 0) +#define EXYNOS_VIDOSD_RIGHT_X(x) (((x) & 0x7ff) << 11) +#define EXYNOS_VIDOSD_BOTTOM_Y(x) (((x) & 0x7ff) << 0) +#define EXYNOS_VIDOSD_RIGHT_X_E(x) (((x) & 0x1) << 23) +#define EXYNOS_VIDOSD_BOTTOM_Y_E(x) (((x) & 0x1) << 22) + +/* VIDOSD0C, VIDOSDxD */ +#define EXYNOS_VIDOSD_SIZE(x) (((x) & 0xffffff) << 0) + +/* VIDOSDxC (1~4) */ +#define EXYNOS_VIDOSD_ALPHA0_R(x) (((x) & 0xf) << 20) +#define EXYNOS_VIDOSD_ALPHA0_G(x) (((x) & 0xf) << 16) +#define EXYNOS_VIDOSD_ALPHA0_B(x) (((x) & 0xf) << 12) +#define EXYNOS_VIDOSD_ALPHA1_R(x) (((x) & 0xf) << 8) +#define EXYNOS_VIDOSD_ALPHA1_G(x) (((x) & 0xf) << 4) +#define EXYNOS_VIDOSD_ALPHA1_B(x) (((x) & 0xf) << 0) +#define EXYNOS_VIDOSD_ALPHA0_SHIFT (12) +#define EXYNOS_VIDOSD_ALPHA1_SHIFT (0) + +/* Start Address */ +#define EXYNOS_VIDADDR_START_VBANK(x) (((x) & 0xff) << 24) +#define EXYNOS_VIDADDR_START_VBASEU(x) (((x) & 0xffffff) << 0) + +/* End Address */ +#define EXYNOS_VIDADDR_END_VBASEL(x) (((x) & 0xffffff) << 0) + +/* Buffer Size */ +#define EXYNOS_VIDADDR_OFFSIZE(x) (((x) & 0x1fff) << 13) +#define EXYNOS_VIDADDR_PAGEWIDTH(x) (((x) & 0x1fff) << 0) +#define EXYNOS_VIDADDR_OFFSIZE_E(x) ((((x) & 0x2000) >> 13) << 27) +#define EXYNOS_VIDADDR_PAGEWIDTH_E(x) ((((x) & 0x2000) >> 13) << 26) + +/* WIN Color Map */ +#define EXYNOS_WINMAP_COLOR(x) ((x) & 0xffffff) + +/* VIDINTCON0 */ +#define EXYNOS_VIDINTCON0_SYSMAINCON_DISABLE (0 << 19) +#define EXYNOS_VIDINTCON0_SYSMAINCON_ENABLE (1 << 19) +#define EXYNOS_VIDINTCON0_SYSSUBCON_DISABLE (0 << 18) +#define EXYNOS_VIDINTCON0_SYSSUBCON_ENABLE (1 << 18) +#define EXYNOS_VIDINTCON0_SYSIFDONE_DISABLE (0 << 17) +#define EXYNOS_VIDINTCON0_SYSIFDONE_ENABLE (1 << 17) +#define EXYNOS_VIDINTCON0_FRAMESEL0_BACK (0 << 15) +#define EXYNOS_VIDINTCON0_FRAMESEL0_VSYNC (1 << 15) +#define EXYNOS_VIDINTCON0_FRAMESEL0_ACTIVE (2 << 15) +#define EXYNOS_VIDINTCON0_FRAMESEL0_FRONT (3 << 15) +#define EXYNOS_VIDINTCON0_FRAMESEL0_MASK (3 << 15) +#define EXYNOS_VIDINTCON0_FRAMESEL1_NONE (0 << 13) +#define EXYNOS_VIDINTCON0_FRAMESEL1_BACK (1 << 13) +#define EXYNOS_VIDINTCON0_FRAMESEL1_VSYNC (2 << 13) +#define EXYNOS_VIDINTCON0_FRAMESEL1_FRONT (3 << 13) +#define EXYNOS_VIDINTCON0_INTFRMEN_DISABLE (0 << 12) +#define EXYNOS_VIDINTCON0_INTFRMEN_ENABLE (1 << 12) +#define EXYNOS_VIDINTCON0_FIFOSEL_WIN4 (1 << 11) +#define EXYNOS_VIDINTCON0_FIFOSEL_WIN3 (1 << 10) +#define EXYNOS_VIDINTCON0_FIFOSEL_WIN2 (1 << 9) +#define EXYNOS_VIDINTCON0_FIFOSEL_WIN1 (1 << 6) +#define EXYNOS_VIDINTCON0_FIFOSEL_WIN0 (1 << 5) +#define EXYNOS_VIDINTCON0_FIFOSEL_ALL (0x73 << 5) +#define EXYNOS_VIDINTCON0_FIFOSEL_MASK (0x73 << 5) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_25 (0 << 2) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_50 (1 << 2) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_75 (2 << 2) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_EMPTY (3 << 2) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_FULL (4 << 2) +#define EXYNOS_VIDINTCON0_FIFOLEVEL_MASK (7 << 2) +#define EXYNOS_VIDINTCON0_INTFIFO_DISABLE (0 << 1) +#define EXYNOS_VIDINTCON0_INTFIFO_ENABLE (1 << 1) +#define EXYNOS_VIDINTCON0_INT_DISABLE (0 << 0) +#define EXYNOS_VIDINTCON0_INT_ENABLE (1 << 0) +#define EXYNOS_VIDINTCON0_INT_MASK (1 << 0) + +/* VIDINTCON1 */ +#define EXYNOS_VIDINTCON1_INTVPPEND (1 << 5) +#define EXYNOS_VIDINTCON1_INTI80PEND (1 << 2) +#define EXYNOS_VIDINTCON1_INTFRMPEND (1 << 1) +#define EXYNOS_VIDINTCON1_INTFIFOPEND (1 << 0) + +/* WINMAP */ +#define EXYNOS_WINMAP_ENABLE (1 << 24) + +/* WxKEYCON0 (1~4) */ +#define EXYNOS_KEYCON0_KEYBLEN_DISABLE (0 << 26) +#define EXYNOS_KEYCON0_KEYBLEN_ENABLE (1 << 26) +#define EXYNOS_KEYCON0_KEY_DISABLE (0 << 25) +#define EXYNOS_KEYCON0_KEY_ENABLE (1 << 25) +#define EXYNOS_KEYCON0_DIRCON_MATCH_FG (0 << 24) +#define EXYNOS_KEYCON0_DIRCON_MATCH_BG (1 << 24) +#define EXYNOS_KEYCON0_COMPKEY(x) (((x) & 0xffffff) << 0) + +/* WxKEYCON1 (1~4) */ +#define EXYNOS_KEYCON1_COLVAL(x) (((x) & 0xffffff) << 0) + +/* DUALRGB */ +#define EXYNOS_DUALRGB_BYPASS_SINGLE (0x00 << 0) +#define EXYNOS_DUALRGB_BYPASS_DUAL (0x01 << 0) +#define EXYNOS_DUALRGB_MIE_DUAL (0x10 << 0) +#define EXYNOS_DUALRGB_MIE_SINGLE (0x11 << 0) +#define EXYNOS_DUALRGB_LINESPLIT (0x0 << 2) +#define EXYNOS_DUALRGB_FRAMESPLIT (0x1 << 2) +#define EXYNOS_DUALRGB_SUB_CNT(x) ((x & 0xfff) << 4) +#define EXYNOS_DUALRGB_VDEN_EN_DISABLE (0x0 << 16) +#define EXYNOS_DUALRGB_VDEN_EN_ENABLE (0x1 << 16) +#define EXYNOS_DUALRGB_MAIN_CNT(x) ((x & 0xfff) << 18) + +/* I80IFCONA0 and I80IFCONA1 */ +#define EXYNOS_LCD_CS_SETUP(x) (((x) & 0xf) << 16) +#define EXYNOS_LCD_WR_SETUP(x) (((x) & 0xf) << 12) +#define EXYNOS_LCD_WR_ACT(x) (((x) & 0xf) << 8) +#define EXYNOS_LCD_WR_HOLD(x) (((x) & 0xf) << 4) +#define EXYNOS_RSPOL_LOW (0 << 2) +#define EXYNOS_RSPOL_HIGH (1 << 2) +#define EXYNOS_I80IFEN_DISABLE (0 << 0) +#define EXYNOS_I80IFEN_ENABLE (1 << 0) + +/* TRIGCON */ +#define EXYNOS_I80SOFT_TRIG_EN (1 << 0) +#define EXYNOS_I80START_TRIG (1 << 1) +#define EXYNOS_I80STATUS_TRIG_DONE (1 << 2) + +/* DP_MIE_CLKCON */ +#define EXYNOS_DP_MIE_DISABLE (0 << 0) +#define EXYNOS_DP_CLK_ENABLE (1 << 1) +#define EXYNOS_MIE_CLK_ENABLE (3 << 0) + +#define DP_TIMEOUT_LOOP_COUNT 1000 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 4 + +#define EXYNOS_DP_SUCCESS 0 + +enum { + DP_DISABLE, + DP_ENABLE, +}; + +struct edp_disp_info { + char *name; + unsigned int h_total; + unsigned int h_res; + unsigned int h_sync_width; + unsigned int h_back_porch; + unsigned int h_front_porch; + unsigned int v_total; + unsigned int v_res; + unsigned int v_sync_width; + unsigned int v_back_porch; + unsigned int v_front_porch; + unsigned int v_sync_rate; +}; + +struct edp_link_train_info { + unsigned int lt_status; + unsigned int ep_loop; + unsigned int cr_loop[4]; +}; + +struct edp_video_info { + unsigned int master_mode; + unsigned int bist_mode; + unsigned int bist_pattern; + unsigned int h_sync_polarity; + unsigned int v_sync_polarity; + unsigned int interlaced; + unsigned int color_space; + unsigned int dynamic_range; + unsigned int ycbcr_coeff; + unsigned int color_depth; +}; + +struct edp_device_info { + struct edp_disp_info disp_info; + struct edp_link_train_info lt_info; + struct edp_video_info video_info; + + /*below info get from panel during training*/ + u8 lane_bw; + u8 lane_cnt; + u8 dpcd_rev; + /*support enhanced frame cap */ + u8 dpcd_efc; + u8 *raw_edid; +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + +enum pll_status { + PLL_UNLOCKED = 0, + PLL_LOCKED +}; + +enum { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum { + VESA, + CEA +}; + +enum { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum { + DP_LANE_BW_1_62 = 0x06, + DP_LANE_BW_2_70 = 0x0a, +}; + +enum { + DP_LANE_CNT_1 = 1, + DP_LANE_CNT_2 = 2, + DP_LANE_CNT_4 = 4, +}; + +enum { + DP_DPCD_REV_10 = 0x10, + DP_DPCD_REV_11 = 0x11, +}; + +enum { + DP_LT_NONE, + DP_LT_START, + DP_LT_CR, + DP_LT_ET, + DP_LT_FINISHED, + DP_LT_FAIL, +}; + +enum { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pattern_type { + NO_PATTERN, + COLOR_RAMP, + BALCK_WHITE_V_LINES, + COLOR_SQUARE, + INVALID_PATTERN, + COLORBAR_32, + COLORBAR_64, + WHITE_GRAY_BALCKBAR_32, + WHITE_GRAY_BALCKBAR_64, + MOBILE_WHITEBAR_32, + MOBILE_WHITEBAR_64 +}; + +enum { + CALCULATED_M, + REGISTER_M +}; + +enum { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + + +struct exynos_dp_platform_data { + struct edp_device_info *edp_dev_info; +}; + + +int exynos_init_dp(struct edp_device_info *edp_info); + +void exynos_set_dp_platform_data(struct exynos_dp_platform_data *pd); + +void exynos_dp_disable_video_bist(void); +void exynos_dp_enable_video_mute(unsigned int enable); +void exynos_dp_reset(void); +void exynos_dp_enable_sw_func(unsigned int enable); +unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable); +unsigned int exynos_dp_get_pll_lock_status(void); +int exynos_dp_init_analog_func(void); +void exynos_dp_init_hpd(void); +void exynos_dp_init_aux(void); +void exynos_dp_config_interrupt(void); +unsigned int exynos_dp_get_plug_in_status(void); +unsigned int exynos_dp_detect_hpd(void); +unsigned int exynos_dp_start_aux_transaction(void); +unsigned int exynos_dp_write_byte_to_dpcd(u32 reg_addr, + u8 data); +unsigned int exynos_dp_read_byte_from_dpcd(u32 reg_addr, + u8 *data); +unsigned int exynos_dp_write_bytes_to_dpcd(u32 reg_addr, + unsigned int count, + u8 data[]); +u32 exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr, + unsigned int count, + u8 data[]); +int exynos_dp_select_i2c_device( u32 device_addr, + u32 reg_addr); +int exynos_dp_read_byte_from_i2c(u32 device_addr, + u32 reg_addr, unsigned int *data); +int exynos_dp_read_bytes_from_i2c(u32 device_addr, + u32 reg_addr, unsigned int count, + u8 edid[]); +void exynos_dp_reset_macro(void); +void exynos_dp_set_link_bandwidth(u8 bwtype); +u8 exynos_dp_get_link_bandwidth(void); +void exynos_dp_set_lane_count(u8 count); +unsigned int exynos_dp_get_lane_count(void); +u8 exynos_dp_get_lanex_pre_emphasis(u8 lanecnt); +void exynos_dp_set_lane_pre_emphasis(unsigned int level, + u8 lanecnt); +void exynos_dp_set_lanex_pre_emphasis(u8 request_val, + u8 lanecnt); +void exynos_dp_set_training_pattern(unsigned int pattern); +void exynos_dp_enable_enhanced_mode(u8 enable); +void exynos_dp_enable_scrambling(unsigned int enable); +int exynos_dp_init_video(void); +void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info); +void exynos_dp_set_video_color_format(struct edp_video_info *video_info); +int exynos_dp_config_video_bist(struct edp_device_info *edp_info); +unsigned int exynos_dp_is_slave_video_stream_clock_on(void); +void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, + unsigned int n_value); +void exynos_dp_set_video_timing_mode(unsigned int type); +void exynos_dp_enable_video_master(unsigned int enable); +void exynos_dp_start_video(void); +unsigned int exynos_dp_is_video_stream_on(void); +void exynos_dp_set_base_addr(void); +void dp_phy_control(unsigned int enable); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/dsim.h b/src/soc/samsung/exynos5420/include/soc/dsim.h new file mode 100644 index 0000000000..9ad55d71c9 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/dsim.h @@ -0,0 +1,110 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Register map for Exynos5 MIPI-DSIM */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_DSIM_H +#define CPU_SAMSUNG_EXYNOS5420_DSIM_H + +/* DSIM register map */ +struct exynos5_dsim { + unsigned int status; + unsigned int swrst; + unsigned int clkctrl; + unsigned int timeout; + unsigned int config; + unsigned int escmode; + unsigned int mdresol; + unsigned int mvporch; + unsigned int mhporch; + unsigned int msync; + unsigned int sdresol; + unsigned int intsrc; + unsigned int intmsk; + unsigned int pkthdr; + unsigned int payload; + unsigned int rxfifo; + unsigned int res1; + unsigned int fifoctrl; + unsigned int res2; + unsigned int pllctrl; + unsigned int plltmr; + unsigned int phyacchr; + unsigned int phyacchr1; +}; +check_member(exynos5_dsim, phyacchr1, 0x54); + +#define ENABLE 1 +#define DISABLE 0 + +#define DSIM_SWRST (1 << 0) +#define NUM_OF_DAT_LANE_IS_FOUR (3 << 5) +#define DATA_LANE_0_EN (1 << 0) +#define DATA_LANE_1_EN (1 << 1) +#define DATA_LANE_2_EN (1 << 2) +#define DATA_LANE_3_EN (1 << 3) +#define CLK_LANE_EN (1 << 4) +#define ENABLE_ALL_DATA_LANE DATA_LANE_0_EN | \ + DATA_LANE_1_EN | \ + DATA_LANE_2_EN | \ + DATA_LANE_3_EN +#define MAIN_PIX_FORMAT_OFFSET 12 +#define RGB_565_16_BIT 0x4 +#define VIDEO_MODE (1 << 25) +#define BURST_MODE (1 << 26) + + +#define DSIM_PHYACCHR_AFC_EN (1 << 14) +#define DSIM_PHYACCHR_AFC_CTL_OFFSET 5 + +#define DSIM_PLLCTRL_PMS_OFFSET 1 +#define DSIM_FREQ_BAND_OFFSET 24 + +#define LANE_ESC_CLK_EN_ALL (0x1f << 19) +#define BYTE_CLK_EN (1 << 24) +#define DSIM_ESC_CLK_EN (1 << 28) +#define TXREQUEST_HS_CLK_ON (1 << 31) + +#define LP_MODE_ENABLE (1 << 7) +#define STOP_STATE_CNT_OFFSET 21 + +#define MAIN_VBP_OFFSET 0 +#define STABLE_VFP_OFFSET 16 +#define CMD_ALLOW_OFFSET 28 + +#define MAIN_HBP_OFFSET 0 +#define MAIN_HFP_OFFSET 16 + +#define MAIN_HSA_OFFSET 0 +#define MAIN_VSA_OFFSET 22 + +#define MAIN_STANDBY (1 << 31) +#define MAIN_VRESOL_OFFSET 16 +#define MAIN_HRESOL_OFFSET 0 + +#define SFR_FIFO_EMPTY (1 << 29) + +#define DSIM_PLL_EN_SHIFT (1 << 23) +#define PLL_STABLE (1 << 31) + +#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0) +#define DSIM_STOP_STATE_CLK (1 << 8) +#define DSIM_TX_READY_HS_CLK (1 << 10) + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/fimd.h b/src/soc/samsung/exynos5420/include/soc/fimd.h new file mode 100644 index 0000000000..32c7083c00 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/fimd.h @@ -0,0 +1,217 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Register map for Exynos5 FIMD */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_FIMD_H +#define CPU_SAMSUNG_EXYNOS5420_FIMD_H + +#include + +/* FIMD register map */ +struct exynos5_fimd { + /* This is an incomplete list. Add registers as and when required */ + u32 vidcon0; + u8 res1[0x1c]; + u32 wincon0; + u32 wincon1; + u32 wincon2; + u32 wincon3; + u32 wincon4; + u32 shadowcon; + u8 res2[0x8]; + u32 vidosd0a; + u32 vidosd0b; + u32 vidosd0c; + u8 res3[0x54]; + u32 vidw00add0b0; + u8 res4[0x2c]; + u32 vidw00add1b0; + u8 res5[0x2c]; + u32 vidw00add2; + u8 res6[0x3c]; + u32 w1keycon0; + u32 w1keycon1; + u32 w2keycon0; + u32 w2keycon1; + u32 w3keycon0; + u32 w3keycon1; + u32 w4keycon0; + u32 w4keycon1; + u8 res7[0x20]; + u32 win0map; + u8 res8[0xdc]; + u32 blendcon; + u8 res9[0x18]; + u32 dpclkcon; +}; +check_member(exynos5_fimd, dpclkcon, 0x27c); + +#define W0_SHADOW_PROTECT (0x1 << 10) +#define COMPKEY_F 0xffffff +#define ENVID_F_ON (0x1 << 0) +#define ENVID_ON (0x1 << 1) +#define CLKVAL_F 0xb +#define CLKVAL_F_OFFSET 6 + +/* + * Structure containing display panel specific data for FIMD + */ +struct exynos5_fimd_panel { + unsigned int is_dp:1; /* Display Panel interface is eDP */ + unsigned int is_mipi:1; /* Display Panel interface is MIPI */ + unsigned int fixvclk:2; /* VCLK hold scheme at data underflow */ + + /* + * Polarity of the VCLK active edge + * 0-falling + * 1-rising + */ + unsigned int ivclk:1; + unsigned int clkval_f; /* Divider to create pixel clock */ + + unsigned int upper_margin; /* Vertical Backporch */ + unsigned int lower_margin; /* Vertical frontporch */ + unsigned int vsync; /* Vertical Sync Pulse Width */ + unsigned int left_margin; /* Horizontal Backporch */ + unsigned int right_margin; /* Horizontal Frontporch */ + unsigned int hsync; /* Horizontal Sync Pulse Width */ + unsigned int xres; /* X Resolution */ + unsigned int yres; /* Y Resopultion */ +}; + +/* LCDIF Register Map */ +struct exynos5_disp_ctrl { + u32 vidout_con; + u32 vidcon1; + u8 res1[0x8]; + u32 vidtcon0; + u32 vidtcon1; + u32 vidtcon2; + u32 vidtcon3; + u8 res2[0x184]; + u32 trigcon; +}; +check_member(exynos5_disp_ctrl, trigcon, 0x1a4); + +#define VCLK_RISING_EDGE (1 << 7) +#define VCLK_RUNNING (1 << 9) + +#define CHANNEL0_EN (1 << 0) + +#define VSYNC_PULSE_WIDTH_VAL 0x3 +#define VSYNC_PULSE_WIDTH_OFFSET 0 +#define V_FRONT_PORCH_VAL 0x3 +#define V_FRONT_PORCH_OFFSET 8 +#define V_BACK_PORCH_VAL 0x3 +#define V_BACK_PORCH_OFFSET 16 + +#define HSYNC_PULSE_WIDTH_VAL 0x3 +#define HSYNC_PULSE_WIDTH_OFFSET 0 +#define H_FRONT_PORCH_VAL 0x3 +#define H_FRONT_PORCH_OFFSET 8 +#define H_BACK_PORCH_VAL 0x3 +#define H_BACK_PORCH_OFFSET 16 + +#define HOZVAL_OFFSET 0 +#define LINEVAL_OFFSET 11 + +#define BPPMODE_F_RGB_16BIT_565 0x5 +#define BPPMODE_F_OFFSET 2 +#define ENWIN_F_ENABLE (1 << 0) +#define HALF_WORD_SWAP_EN (1 << 16) + +#define OSD_RIGHTBOTX_F_OFFSET 11 +#define OSD_RIGHTBOTY_F_OFFSET 0 + +#define FIMD_CTRL ((struct exynos_fb *)0x14400000) + +/* from u-boot fb.h. It needs to be merged with these dp structs maybe. */ +enum { + FIMD_RGB_INTERFACE = 1, + FIMD_CPU_INTERFACE = 2, +}; + +enum exynos_fb_rgb_mode_t { + MODE_RGB_P = 0, + MODE_BGR_P = 1, + MODE_RGB_S = 2, + MODE_BGR_S = 3, +}; + +typedef struct vidinfo { + u16 vl_col; /* Number of columns (i.e. 640) */ + u16 vl_row; /* Number of rows (i.e. 480) */ + u16 vl_width; /* Width of display area in millimeters */ + u16 vl_height; /* Height of display area in millimeters */ + + /* LCD configuration register */ + u8 vl_freq; /* Frequency */ + u8 vl_clkp; /* Clock polarity */ + u8 vl_oep; /* Output Enable polarity */ + u8 vl_hsp; /* Horizontal Sync polarity */ + u8 vl_vsp; /* Vertical Sync polarity */ + u8 vl_dp; /* Data polarity */ + u8 vl_bpix; /* Bits per pixel */ + + /* Horizontal control register. Timing from data sheet */ + u8 vl_hspw; /* Horz sync pulse width */ + u8 vl_hfpd; /* Wait before of line */ + u8 vl_hbpd; /* Wait end of line */ + + /* Vertical control register. */ + u8 vl_vspw; /* Vertical sync pulse width */ + u8 vl_vfpd; /* Wait before of frame */ + u8 vl_vbpd; /* Wait end of frame */ + u8 vl_cmd_allow_len; /* Wait end of frame */ + + unsigned int win_id; + unsigned int init_delay; + unsigned int power_on_delay; + unsigned int reset_delay; + unsigned int interface_mode; + unsigned int mipi_enabled; + unsigned int dp_enabled; + unsigned int cs_setup; + unsigned int wr_setup; + unsigned int wr_act; + unsigned int wr_hold; + unsigned int rgb_mode; + unsigned int resolution; + + /* parent clock name(MPLL, EPLL or VPLL) */ + unsigned int pclk_name; + /* ratio value for source clock from parent clock. */ + unsigned int sclk_div; + + unsigned int dual_lcd_enabled; + void *screen_base; + void *cmap; /* Points at 8 to 16 bit conversion map. */ +} vidinfo_t; + +/* fimd.c */ +void exynos_set_trigger(void); +int exynos_is_i80_frame_done(void); +void exynos_fimd_lcd_off(void); +void exynos_fimd_window_off(unsigned int win_id); +unsigned long exynos_fimd_calc_fbsize(vidinfo_t *vid); +void exynos_fimd_lcd_disable(void); +void exynos_fimd_lcd_init(vidinfo_t *vid); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/gpio.h b/src/soc/samsung/exynos5420/include/soc/gpio.h new file mode 100644 index 0000000000..8754a7058b --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/gpio.h @@ -0,0 +1,552 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_GPIO_H +#define CPU_SAMSUNG_EXYNOS5420_GPIO_H + +#include + +/* TODO: Align interface to src/include/gpio.h! */ + +struct gpio_bank { + unsigned int con; + unsigned int dat; + unsigned int pull; + unsigned int drv; + unsigned int pdn_con; + unsigned int pdn_pull; + unsigned char res1[8]; +}; + +/* GPIO pins per bank */ +#define GPIO_PER_BANK 8 + +/* Pin configurations */ +#define GPIO_INPUT 0x0 +#define GPIO_OUTPUT 0x1 +#define GPIO_IRQ 0xf +#define GPIO_FUNC(x) (x) + +/* Pull mode */ +#define GPIO_PULL_NONE 0x0 +#define GPIO_PULL_DOWN 0x1 +#define GPIO_PULL_UP 0x3 + +/* Drive Strength level */ +#define GPIO_DRV_1X 0x0 +#define GPIO_DRV_3X 0x1 +#define GPIO_DRV_2X 0x2 +#define GPIO_DRV_4X 0x3 +#define GPIO_DRV_FAST 0x0 +#define GPIO_DRV_SLOW 0x1 + +enum exynos5_gpio_port { + EXYNOS5_GPY7 = EXYNOS5420_GPIO_PART1_BASE + 0x0000, + + EXYNOS5_GPX0 = EXYNOS5420_GPIO_PART2_BASE + 0x0000, + EXYNOS5_GPX1 = EXYNOS5420_GPIO_PART2_BASE + 0x0020, + EXYNOS5_GPX2 = EXYNOS5420_GPIO_PART2_BASE + 0x0040, + EXYNOS5_GPX3 = EXYNOS5420_GPIO_PART2_BASE + 0x0060, + + EXYNOS5_GPC0 = EXYNOS5420_GPIO_PART3_BASE + 0x0000, + EXYNOS5_GPC1 = EXYNOS5420_GPIO_PART3_BASE + 0x0020, + EXYNOS5_GPC2 = EXYNOS5420_GPIO_PART3_BASE + 0x0040, + EXYNOS5_GPC3 = EXYNOS5420_GPIO_PART3_BASE + 0x0060, + EXYNOS5_GPC4 = EXYNOS5420_GPIO_PART3_BASE + 0x0080, + + EXYNOS5_GPD1 = EXYNOS5420_GPIO_PART3_BASE + 0x00a0, + + EXYNOS5_GPY0 = EXYNOS5420_GPIO_PART3_BASE + 0x00c0, + EXYNOS5_GPY1 = EXYNOS5420_GPIO_PART3_BASE + 0x00e0, + EXYNOS5_GPY2 = EXYNOS5420_GPIO_PART3_BASE + 0x0100, + EXYNOS5_GPY3 = EXYNOS5420_GPIO_PART3_BASE + 0x0120, + EXYNOS5_GPY4 = EXYNOS5420_GPIO_PART3_BASE + 0x0140, + EXYNOS5_GPY5 = EXYNOS5420_GPIO_PART3_BASE + 0x0160, + EXYNOS5_GPY6 = EXYNOS5420_GPIO_PART3_BASE + 0x0180, + + EXYNOS5_GPE0 = EXYNOS5420_GPIO_PART4_BASE + 0x0000, + EXYNOS5_GPE1 = EXYNOS5420_GPIO_PART4_BASE + 0x0020, + + EXYNOS5_GPF0 = EXYNOS5420_GPIO_PART4_BASE + 0x0040, + EXYNOS5_GPF1 = EXYNOS5420_GPIO_PART4_BASE + 0x0060, + + EXYNOS5_GPG0 = EXYNOS5420_GPIO_PART4_BASE + 0x0080, + EXYNOS5_GPG1 = EXYNOS5420_GPIO_PART4_BASE + 0x00a0, + EXYNOS5_GPG2 = EXYNOS5420_GPIO_PART4_BASE + 0x00c0, + + EXYNOS5_GPJ4 = EXYNOS5420_GPIO_PART4_BASE + 0x00e0, + + /* base == EXYNOS5420_GPIO_PART5_BASE */ + EXYNOS5_GPA0 = EXYNOS5420_GPIO_PART5_BASE + 0x0000, + EXYNOS5_GPA1 = EXYNOS5420_GPIO_PART5_BASE + 0x0020, + EXYNOS5_GPA2 = EXYNOS5420_GPIO_PART5_BASE + 0x0040, + + EXYNOS5_GPB0 = EXYNOS5420_GPIO_PART5_BASE + 0x0060, + EXYNOS5_GPB1 = EXYNOS5420_GPIO_PART5_BASE + 0x0080, + EXYNOS5_GPB2 = EXYNOS5420_GPIO_PART5_BASE + 0x00a0, + EXYNOS5_GPB3 = EXYNOS5420_GPIO_PART5_BASE + 0x00c0, + EXYNOS5_GPB4 = EXYNOS5420_GPIO_PART5_BASE + 0x00e0, + + EXYNOS5_GPH0 = EXYNOS5420_GPIO_PART5_BASE + 0x0100, + + /* base == EXYNOS5420_GPIO_PART6_BASE */ + EXYNOS5_GPZ0 = EXYNOS5420_GPIO_PART6_BASE + 0x0000, +}; + +enum { + /* GPIO banks are split into this many parts */ + EXYNOS_GPIO_NUM_PARTS = 6 +}; + +/* A list of valid GPIO numbers for the asm-generic/gpio.h interface */ +enum exynos5_gpio_pin { + /* GPIO_PART1_STARTS */ + GPIO_Y70, + GPIO_Y71, + GPIO_Y72, + GPIO_Y73, + GPIO_Y74, + GPIO_Y75, + GPIO_Y76, + GPIO_Y77, + + /* GPIO_PART2_STARTS */ + GPIO_MAX_PORT_PART_1, + GPIO_X00 = GPIO_MAX_PORT_PART_1, /* 0x08 */ + GPIO_X01, + GPIO_X02, + GPIO_X03, + GPIO_X04, + GPIO_X05, + GPIO_X06, + GPIO_X07, + GPIO_X10, + GPIO_X11, + GPIO_X12, + GPIO_X13, + GPIO_X14, + GPIO_X15, + GPIO_X16, + GPIO_X17, + GPIO_X20, + GPIO_X21, + GPIO_X22, + GPIO_X23, + GPIO_X24, + GPIO_X25, + GPIO_X26, + GPIO_X27, + GPIO_X30, + GPIO_X31, + GPIO_X32, + GPIO_X33, + GPIO_X34, + GPIO_X35, + GPIO_X36, + GPIO_X37, + + /* GPIO_PART3_STARTS */ + GPIO_MAX_PORT_PART_2, + GPIO_C00 = GPIO_MAX_PORT_PART_2, /* 0x28 */ + GPIO_C01, + GPIO_C02, + GPIO_C03, + GPIO_C04, + GPIO_C05, + GPIO_C06, + GPIO_C07, + GPIO_C10, + GPIO_C11, + GPIO_C12, + GPIO_C13, + GPIO_C14, + GPIO_C15, + GPIO_C16, + GPIO_C17, + GPIO_C20, + GPIO_C21, + GPIO_C22, + GPIO_C23, + GPIO_C24, + GPIO_C25, + GPIO_C26, + GPIO_C27, + GPIO_C30, + GPIO_C31, + GPIO_C32, + GPIO_C33, + GPIO_C34, + GPIO_C35, + GPIO_C36, + GPIO_C37, + GPIO_C40, + GPIO_C41, + GPIO_C42, + GPIO_C43, + GPIO_C44, + GPIO_C45, + GPIO_C46, + GPIO_C47, + + GPIO_D10, /* 0x50 */ + GPIO_D11, + GPIO_D12, + GPIO_D13, + GPIO_D14, + GPIO_D15, + GPIO_D16, + GPIO_D17, + + GPIO_Y00, /* 0x58 */ + GPIO_Y01, + GPIO_Y02, + GPIO_Y03, + GPIO_Y04, + GPIO_Y05, + GPIO_Y06, + GPIO_Y07, + GPIO_Y10, + GPIO_Y11, + GPIO_Y12, + GPIO_Y13, + GPIO_Y14, + GPIO_Y15, + GPIO_Y16, + GPIO_Y17, + GPIO_Y20, + GPIO_Y21, + GPIO_Y22, + GPIO_Y23, + GPIO_Y24, + GPIO_Y25, + GPIO_Y26, + GPIO_Y27, + GPIO_Y30, + GPIO_Y31, + GPIO_Y32, + GPIO_Y33, + GPIO_Y34, + GPIO_Y35, + GPIO_Y36, + GPIO_Y37, + GPIO_Y40, + GPIO_Y41, + GPIO_Y42, + GPIO_Y43, + GPIO_Y44, + GPIO_Y45, + GPIO_Y46, + GPIO_Y47, + GPIO_Y50, + GPIO_Y51, + GPIO_Y52, + GPIO_Y53, + GPIO_Y54, + GPIO_Y55, + GPIO_Y56, + GPIO_Y57, + GPIO_Y60, + GPIO_Y61, + GPIO_Y62, + GPIO_Y63, + GPIO_Y64, + GPIO_Y65, + GPIO_Y66, + GPIO_Y67, + + /* GPIO_PART4_STARTS */ + GPIO_MAX_PORT_PART_3, + GPIO_E00 = GPIO_MAX_PORT_PART_3, /* 0x90 */ + GPIO_E01, + GPIO_E02, + GPIO_E03, + GPIO_E04, + GPIO_E05, + GPIO_E06, + GPIO_E07, + GPIO_E10, + GPIO_E11, + GPIO_E12, + GPIO_E13, + GPIO_E14, + GPIO_E15, + GPIO_E16, + GPIO_E17, + + GPIO_F00, /* 0xa0 */ + GPIO_F01, + GPIO_F02, + GPIO_F03, + GPIO_F04, + GPIO_F05, + GPIO_F06, + GPIO_F07, + GPIO_F10, + GPIO_F11, + GPIO_F12, + GPIO_F13, + GPIO_F14, + GPIO_F15, + GPIO_F16, + GPIO_F17, + + GPIO_G00, /* 0xb0 */ + GPIO_G01, + GPIO_G02, + GPIO_G03, + GPIO_G04, + GPIO_G05, + GPIO_G06, + GPIO_G07, + GPIO_G10, + GPIO_G11, + GPIO_G12, + GPIO_G13, + GPIO_G14, + GPIO_G15, + GPIO_G16, + GPIO_G17, + GPIO_G20, + GPIO_G21, + GPIO_G22, + GPIO_G23, + GPIO_G24, + GPIO_G25, + GPIO_G26, + GPIO_G27, + + GPIO_J40, /* 0xc8 */ + GPIO_J41, + GPIO_J42, + GPIO_J43, + GPIO_J44, + GPIO_J45, + GPIO_J46, + GPIO_J47, + + /* GPIO_PART5_STARTS */ + GPIO_MAX_PORT_PART_4, + GPIO_A00 = GPIO_MAX_PORT_PART_4, /* 0xd0 */ + GPIO_A01, + GPIO_A02, + GPIO_A03, + GPIO_A04, + GPIO_A05, + GPIO_A06, + GPIO_A07, + GPIO_A10, + GPIO_A11, + GPIO_A12, + GPIO_A13, + GPIO_A14, + GPIO_A15, + GPIO_A16, + GPIO_A17, + GPIO_A20, + GPIO_A21, + GPIO_A22, + GPIO_A23, + GPIO_A24, + GPIO_A25, + GPIO_A26, + GPIO_A27, + + GPIO_B00, /* 0xe8 */ + GPIO_B01, + GPIO_B02, + GPIO_B03, + GPIO_B04, + GPIO_B05, + GPIO_B06, + GPIO_B07, + GPIO_B10, + GPIO_B11, + GPIO_B12, + GPIO_B13, + GPIO_B14, + GPIO_B15, + GPIO_B16, + GPIO_B17, + GPIO_B20, + GPIO_B21, + GPIO_B22, + GPIO_B23, + GPIO_B24, + GPIO_B25, + GPIO_B26, + GPIO_B27, + GPIO_B30, + GPIO_B31, + GPIO_B32, + GPIO_B33, + GPIO_B34, + GPIO_B35, + GPIO_B36, + GPIO_B37, + GPIO_B40, + GPIO_B41, + GPIO_B42, + GPIO_B43, + GPIO_B44, + GPIO_B45, + GPIO_B46, + GPIO_B47, + + GPIO_H00, /* 0x110 */ + GPIO_H01, + GPIO_H02, + GPIO_H03, + GPIO_H04, + GPIO_H05, + GPIO_H06, + GPIO_H07, + + /* GPIO_PART6_STARTS */ + GPIO_MAX_PORT_PART_5, + GPIO_Z00 = GPIO_MAX_PORT_PART_5, /* 0x118 */ + GPIO_Z01, + GPIO_Z02, + GPIO_Z03, + GPIO_Z04, + GPIO_Z05, + GPIO_Z06, + GPIO_Z07, + GPIO_MAX_PORT +}; + +/** + * Set GPIO pin configuration. + * + * @param gpio GPIO pin + * @param cfg Either GPIO_INPUT, GPIO_OUTPUT, or GPIO_IRQ + */ +void gpio_cfg_pin(int gpio, int cfg); + +/** + * Set GPIO pull mode. + * + * @param gpio GPIO pin + * @param mode Either GPIO_PULL_DOWN or GPIO_PULL_UP + */ +void gpio_set_pull(int gpio, int mode); + +/** + * Set GPIO drive strength level. + * + * @param gpio GPIO pin + * @param mode Either GPIO_DRV_1X, GPIO_DRV_2X, GPIO_DRV_3X, or GPIO_DRV_4X + */ +void gpio_set_drv(int gpio, int mode); + +/** + * Set GPIO drive rate. + * + * @param gpio GPIO pin + * @param mode Either GPIO_DRV_FAST or GPIO_DRV_SLOW + */ +void gpio_set_rate(int gpio, int mode); + +/* + * reads only a single GPIO + * + * @param gpio GPIO to read + * @return -1 if the value cannot be determined. Otherwise returns + * the corresponding MVL3 enum value. + */ +int gpio_read_mvl3(unsigned gpio); + +void gpio_info(void); + +/* + * Generic GPIO API for U-Boot + * + * GPIOs are numbered from 0 to GPIO_COUNT-1 which value is defined + * by the SOC/architecture. + * + * Each GPIO can be an input or output. If an input then its value can + * be read as 0 or 1. If an output then its value can be set to 0 or 1. + * If you try to write an input then the value is undefined. If you try + * to read an output, barring something very unusual, you will get + * back the value of the output that you previously set. + * + * In some cases the operation may fail, for example if the GPIO number + * is out of range, or the GPIO is not available because its pin is + * being used by another function. In that case, functions may return + * an error value of -1. + */ + +/** + * Make a GPIO an input. + * + * @param gpio GPIO number + * @return 0 if ok, -1 on error + */ +int gpio_direction_input(unsigned gpio); + +/** + * Make a GPIO an output, and set its value. + * + * @param gpio GPIO number + * @param value GPIO value (0 for low or 1 for high) + * @return 0 if ok, -1 on error + */ +int gpio_direction_output(unsigned gpio, int value); + +/** + * Get a GPIO's value. This will work whether the GPIO is an input + * or an output. + * + * @param gpio GPIO number + * @return 0 if low, 1 if high, -1 on error + */ +int gpio_get_value(unsigned gpio); + +/** + * Set an output GPIO's value. The GPIO must already be an output or + * this function may have no effect. + * + * @param gpio GPIO number + * @param value GPIO value (0 for low or 1 for high) + * @return 0 if ok, -1 on error + */ +int gpio_set_value(unsigned gpio, int value); + +/* + * Many-value logic (3 states). This can be used for inputs whereby presence + * of external pull-up or pull-down resistors can be added to overcome internal + * pull-ups/pull-downs and force a single value. + * + * Thus, external pull resistors can force a 0 or 1 and if the value changes + * along with internal pull-up/down enable then the input is floating. + * + * Vpd | Vpu | MVL + * ----------------- + * 0 | 0 | 0 + * ----------------- + * 0 | 1 | Z <-- floating input will follow internal pull up/down + * ----------------- + * 1 | 1 | 1 + */ +enum mvl3 { + LOGIC_0, + LOGIC_1, + LOGIC_Z, /* high impedence / tri-stated / floating */ +}; + +#endif /* CPU_SAMSUNG_EXYNOS5420_GPIO_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/i2c.h b/src/soc/samsung/exynos5420/include/soc/i2c.h new file mode 100644 index 0000000000..b9e3c0f5eb --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/i2c.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_I2C_H +#define CPU_SAMSUNG_EXYNOS5420_I2C_H + +void i2c_init(unsigned bus, int speed, int slaveadd); + +#endif /* CPU_SAMSUNG_EXYNOS5420_I2C_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/i2s-regs.h b/src/soc/samsung/exynos5420/include/soc/i2s-regs.h new file mode 100644 index 0000000000..28d2685c63 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/i2s-regs.h @@ -0,0 +1,142 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Taken from the kernel code */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_I2S_REGS_H +#define CPU_SAMSUNG_EXYNOS5420_I2S_REGS_H + +#define I2SCON 0x0 +#define I2SMOD 0x4 +#define I2SFIC 0x8 +#define I2SPSR 0xc +#define I2STXD 0x10 +#define I2SRXD 0x14 +#define I2SFICS 0x18 +#define I2STXDS 0x1c +#define I2SAHB 0x20 +#define I2SSTR0 0x24 +#define I2SSIZE 0x28 +#define I2STRNCNT 0x2c +#define I2SLVL0ADDR 0x30 +#define I2SLVL1ADDR 0x34 +#define I2SLVL2ADDR 0x38 +#define I2SLVL3ADDR 0x3c + +#define CON_RSTCLR (1 << 31) +#define CON_FRXOFSTATUS (1 << 26) +#define CON_FRXORINTEN (1 << 25) +#define CON_FTXSURSTAT (1 << 24) +#define CON_FTXSURINTEN (1 << 23) +#define CON_TXSDMA_PAUSE (1 << 20) +#define CON_TXSDMA_ACTIVE (1 << 18) + +#define CON_FTXURSTATUS (1 << 17) +#define CON_FTXURINTEN (1 << 16) +#define CON_TXFIFO2_EMPTY (1 << 15) +#define CON_TXFIFO1_EMPTY (1 << 14) +#define CON_TXFIFO2_FULL (1 << 13) +#define CON_TXFIFO1_FULL (1 << 12) + +#define CON_LRINDEX (1 << 11) +#define CON_TXFIFO_EMPTY (1 << 10) +#define CON_RXFIFO_EMPTY (1 << 9) +#define CON_TXFIFO_FULL (1 << 8) +#define CON_RXFIFO_FULL (1 << 7) +#define CON_TXDMA_PAUSE (1 << 6) +#define CON_RXDMA_PAUSE (1 << 5) +#define CON_TXCH_PAUSE (1 << 4) +#define CON_RXCH_PAUSE (1 << 3) +#define CON_TXDMA_ACTIVE (1 << 2) +#define CON_RXDMA_ACTIVE (1 << 1) +#define CON_ACTIVE (1 << 0) + +#define MOD_OPCLK_CDCLK_OUT (0 << 30) +#define MOD_OPCLK_CDCLK_IN (1 << 30) +#define MOD_OPCLK_BCLK_OUT (2 << 30) +#define MOD_OPCLK_PCLK (3 << 30) +#define MOD_OPCLK_MASK (3 << 30) +#define MOD_TXS_IDMA (1 << 28) /* Sec_TXFIFO use I-DMA */ + +#define MOD_BLCS_SHIFT 26 +#define MOD_BLCS_16BIT (0 << MOD_BLCS_SHIFT) +#define MOD_BLCS_8BIT (1 << MOD_BLCS_SHIFT) +#define MOD_BLCS_24BIT (2 << MOD_BLCS_SHIFT) +#define MOD_BLCS_MASK (3 << MOD_BLCS_SHIFT) + +#define MOD_BLCP_SHIFT 24 +#define MOD_BLCP_16BIT (0 << MOD_BLCP_SHIFT) +#define MOD_BLCP_8BIT (1 << MOD_BLCP_SHIFT) +#define MOD_BLCP_24BIT (2 << MOD_BLCP_SHIFT) +#define MOD_BLCP_MASK (3 << MOD_BLCP_SHIFT) + +#define MOD_C2DD_HHALF (1 << 21) /* Discard Higher-half */ +#define MOD_C2DD_LHALF (1 << 20) /* Discard Lower-half */ +#define MOD_C1DD_HHALF (1 << 19) +#define MOD_C1DD_LHALF (1 << 18) +#define MOD_DC2_EN (1 << 17) +#define MOD_DC1_EN (1 << 16) +#define MOD_BLC_16BIT (0 << 13) +#define MOD_BLC_8BIT (1 << 13) +#define MOD_BLC_24BIT (2 << 13) +#define MOD_BLC_MASK (3 << 13) + +#define MOD_IMS_SYSMUX (1 << 10) +#define MOD_SLAVE (1 << 11) +#define MOD_TXONLY (0 << 8) +#define MOD_RXONLY (1 << 8) +#define MOD_TXRX (2 << 8) +#define MOD_MASK (3 << 8) +#define MOD_LR_LLOW (0 << 7) +#define MOD_LR_RLOW (1 << 7) +#define MOD_SDF_IIS (0 << 5) +#define MOD_SDF_MSB (1 << 5) +#define MOD_SDF_LSB (2 << 5) +#define MOD_SDF_MASK (3 << 5) +#define MOD_RCLK_256FS (0 << 3) +#define MOD_RCLK_512FS (1 << 3) +#define MOD_RCLK_384FS (2 << 3) +#define MOD_RCLK_768FS (3 << 3) +#define MOD_RCLK_MASK (3 << 3) +#define MOD_BCLK_32FS (0 << 1) +#define MOD_BCLK_48FS (1 << 1) +#define MOD_BCLK_16FS (2 << 1) +#define MOD_BCLK_24FS (3 << 1) +#define MOD_BCLK_MASK (3 << 1) +#define MOD_8BIT (1 << 0) + +#define MOD_CDCLKCON (1 << 12) + +#define PSR_PSREN (1 << 15) + +#define FIC_TXFLUSH (1 << 15) +#define FIC_RXFLUSH (1 << 7) + +#define AHB_INTENLVL0 (1 << 24) +#define AHB_LVL0INT (1 << 20) +#define AHB_CLRLVL0INT (1 << 16) +#define AHB_DMARLD (1 << 5) +#define AHB_INTMASK (1 << 3) +#define AHB_DMAEN (1 << 0) +#define AHB_LVLINTMASK (0xf << 20) + +#define I2SSIZE_TRNMSK (0xffff) +#define I2SSIZE_SHIFT (16) + +#endif /* CPU_SAMSUNG_EXYNOS5420_I2S_REGS_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/memlayout.ld b/src/soc/samsung/exynos5420/include/soc/memlayout.ld new file mode 100644 index 0000000000..3259ff907b --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/memlayout.ld @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +/* + * Note: The BootROM loads the 8K BL1 at [0x2020000:0x2022000), so the bootblock + * must be placed after that. After the handoff, the space can be reclaimed. + */ + +SECTIONS +{ + SRAM_START(0x2020000) + /* 17K hole, includes BL1 */ + /* Bootblock is preceeded by 16 byte variable length BL2 checksum. */ + BOOTBLOCK(0x2024410, 32K - 16) + /* 15K hole */ + ROMSTAGE(0x2030000, 128K) + /* 32K hole */ + TTB(0x2058000, 16K) + PRERAM_CBFS_CACHE(0x205C000, 76K) + STACK(0x206F000, 16K) + /* 1K hole for weird kernel-shared CPU/SMP state structure that doesn't + * seem to be implemented right now? */ + SRAM_END(0x2074000) + + DRAM_START(0x20000000) + RAMSTAGE(0x20000000, 128K) + POSTRAM_CBFS_CACHE(0x21000000, 8M) + DMA_COHERENT(0x77300000, 1M) +} diff --git a/src/soc/samsung/exynos5420/include/soc/periph.h b/src/soc/samsung/exynos5420/include/soc/periph.h new file mode 100644 index 0000000000..94f150e6dd --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/periph.h @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_PERIPH_H +#define CPU_SAMSUNG_EXYNOS5420_PERIPH_H + +/* + * Peripherals requiring clock/pinmux configuration. List will + * grow with support for more devices getting added. + * + * At present the order is arbitrary - we may be able to take advantage + * of some orthogonality later. + */ +enum periph_id { + PERIPH_ID_UART0, + PERIPH_ID_UART1, + PERIPH_ID_UART2, + PERIPH_ID_UART3, + PERIPH_ID_SDMMC0, + PERIPH_ID_SDMMC1, + PERIPH_ID_SDMMC2, + PERIPH_ID_SDMMC3, + + PERIPH_ID_SROMC = 9, + PERIPH_ID_SPI0, + PERIPH_ID_SPI1, + PERIPH_ID_SPI2, + PERIPH_ID_SPI3, + PERIPH_ID_SPI4, + PERIPH_ID_LCD, + PERIPH_ID_BACKLIGHT, + PERIPH_ID_I2C0, + PERIPH_ID_I2C1, + PERIPH_ID_I2C2, + PERIPH_ID_I2C3, + PERIPH_ID_I2C4, + PERIPH_ID_I2C5, + PERIPH_ID_I2C6, + PERIPH_ID_I2C7, + PERIPH_ID_I2C8, + PERIPH_ID_I2C9, + PERIPH_ID_I2C10, + PERIPH_ID_DPHPD, /* eDP hot plug detect */ + PERIPH_ID_PWM0, + PERIPH_ID_PWM1, + PERIPH_ID_PWM2, + PERIPH_ID_PWM3, + PERIPH_ID_PWM4, + PERIPH_ID_I2S1, + PERIPH_ID_SATA, + + PERIPH_ID_COUNT, + PERIPH_ID_NONE = -1, +}; + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/pinmux.h b/src/soc/samsung/exynos5420/include/soc/pinmux.h new file mode 100644 index 0000000000..fc09fc95fb --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/pinmux.h @@ -0,0 +1,53 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_PINMUX_H +#define CPU_SAMSUNG_EXYNOS5420_PINMUX_H + +void exynos_pinmux_uart0(void); +void exynos_pinmux_uart1(void); +void exynos_pinmux_uart2(void); +void exynos_pinmux_uart3(void); + +void exynos_pinmux_sdmmc0(void); +void exynos_pinmux_sdmmc1(void); +void exynos_pinmux_sdmmc2(void); +void exynos_pinmux_sdmmc3(void); + +void exynos_pinmux_spi0(void); +void exynos_pinmux_spi1(void); +void exynos_pinmux_spi2(void); +void exynos_pinmux_spi3(void); +void exynos_pinmux_spi4(void); + +void exynos_pinmux_i2c0(void); +void exynos_pinmux_i2c1(void); +void exynos_pinmux_i2c2(void); +void exynos_pinmux_i2c3(void); +void exynos_pinmux_i2c4(void); +void exynos_pinmux_i2c5(void); +void exynos_pinmux_i2c6(void); +void exynos_pinmux_i2c7(void); +void exynos_pinmux_i2c8(void); +void exynos_pinmux_i2c9(void); +void exynos_pinmux_i2c10(void); + +void exynos_pinmux_dphpd(void); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/power.h b/src/soc/samsung/exynos5420/include/soc/power.h new file mode 100644 index 0000000000..0d31dc440b --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/power.h @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Register map for Exynos5 PMU */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_POWER_H +#define CPU_SAMSUNG_EXYNOS5420_POWER_H + +#include + +/* Enable HW thermal trip with PS_HOLD_CONTROL register ENABLE_HW_TRIP bit */ +void power_enable_hw_thermal_trip(void); + +#define MIPI_PHY1_CONTROL_ENABLE (1 << 0) +#define MIPI_PHY1_CONTROL_M_RESETN (1 << 2) + +#define POWER_USB_PHY_CTRL_EN (1 << 0) +#define POWER_PS_HOLD_CONTROL_DATA_HIGH (1 << 8) +#define POWER_ENABLE_HW_TRIP (1UL << 31) + +#define EXYNOS_DP_PHY_ENABLE (1 << 0) + +/* PMU_DEBUG bits [12:8] = 0x1000 selects XXTI clock source */ +#define PMU_DEBUG_XXTI 0x1000 +/* Mask bit[12:8] for xxti clock selection */ +#define PMU_DEBUG_CLKOUT_SEL_MASK 0x1f00 + +/* Power Management Unit register map */ +struct exynos5_power { + /* Add registers as and when required */ + uint32_t om_stat; /* 0x0000 */ + uint8_t reserved1[0x03fc]; + uint32_t sw_reset; /* 0x0400 */ + uint8_t reserved2[0x0300]; + uint32_t usb_drd0_phy_ctrl; /* 0x0704 */ + uint32_t usb_drd1_phy_ctrl; /* 0x0708 */ + uint32_t usb_host_phy_ctrl; /* 0x070c */ + uint8_t reserved3[0x4]; + uint32_t mipi_phy1_control; /* 0x0714 */ + uint8_t reserved4[0x8]; + uint32_t dptx_phy_control; /* 0x0720 */ + uint8_t reserved5[0xdc]; + uint32_t inform0; /* 0x0800 */ + uint32_t inform1; /* 0x0804 */ + uint8_t reserved6[0x0f8]; + uint32_t spare0; /* 0x0900 */ + uint8_t reserved7[0x0fc]; + uint32_t pmu_debug; /* 0x0a00 */ + uint8_t reserved8[0x15fc]; + struct { /* 0x2000 */ + uint32_t config; /* 0x00 */ + uint32_t status; /* 0x04 */ + uint8_t reserved[0x78]; + } arm_core[4]; + uint8_t reserved9[0xe04]; + uint32_t padret_dram_status; /* 0x3004 */ + uint8_t reservedA[0xe0]; + uint32_t padret_uart_opt; /* 0x30e8 */ + uint8_t reservedB[0xfc]; + uint32_t padret_dram_cblk_opt; /* 0x31e8 */ + uint8_t reservedC[0x120]; + uint32_t ps_hold_ctrl; /* 0x330c */ +} __attribute__ ((__packed__)); +check_member(exynos5_power, ps_hold_ctrl, 0x330c); + +static struct exynos5_power * const exynos_power = (void*)EXYNOS5_POWER_BASE; + +/** + * Perform a software reset. + */ +void power_reset(void); + +/** + * Power off the system; it should never return. + */ +void power_shutdown(void); + +/* Enable DPTX PHY */ +void power_enable_dp_phy(void); + +/* Initialize the pmic voltages to power up the system */ +int power_init(void); + +/* Read the reset status. */ +uint32_t power_read_reset_status(void); + +/* Read the resume function and call it. */ +void power_exit_wakeup(void); + +/* pmu debug is used for xclkout, enable xclkout with source as XXTI */ +void power_enable_xclkout(void); + +/* Release UART retention on resume (only for debugging, may conflict with + * kernel). */ +void power_release_uart_retention(void); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/setup.h b/src/soc/samsung/exynos5420/include/soc/setup.h new file mode 100644 index 0000000000..63e40a8f0f --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/setup.h @@ -0,0 +1,888 @@ + /* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Machine Specific Values for SMDK5420 board based on Exynos5 */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_SETUP_H +#define CPU_SAMSUNG_EXYNOS5420_SETUP_H + +struct exynos5_dmc; +enum ddr_mode; +struct exynos5_phy_control; + +#define NOT_AVAILABLE 0 +#define DATA_MASK 0xFFFFF + +#define ENABLE_BIT 0x1 +#define DISABLE_BIT 0x0 +#define CA_SWAP_EN (1 << 0) + +/* TZPC : Register Offsets */ +#define TZPC0_BASE 0x10100000 +#define TZPC1_BASE 0x10110000 +#define TZPC2_BASE 0x10120000 +#define TZPC3_BASE 0x10130000 +#define TZPC4_BASE 0x10140000 +#define TZPC5_BASE 0x10150000 +#define TZPC6_BASE 0x10160000 +#define TZPC7_BASE 0x10170000 +#define TZPC8_BASE 0x10180000 +#define TZPC9_BASE 0x10190000 + +#define APLL_FOUT (1 << 0) +#define KPLL_FOUT (1 << 0) + +#define CLK_DIV_CPERI1_VAL 0x3f3f0000 + +/* APLL_CON1 */ +#define APLL_CON1_VAL (0x0020f300) + +/* MPLL_CON1 */ +#define MPLL_CON1_VAL (0x0020f300) + +/* CPLL_CON1 */ +#define CPLL_CON1_VAL (0x0020f300) + +/* DPLL_CON1 */ +#define DPLL_CON1_VAL (0x0020f300) + +/* GPLL_CON1 */ +#define GPLL_CON1_VAL (NOT_AVAILABLE) + +/* EPLL_CON1, CON2 */ +#define EPLL_CON1_VAL 0x00000000 +#define EPLL_CON2_VAL 0x00000080 + +/* VPLL_CON1, CON2 */ +#define VPLL_CON1_VAL 0x0020f300 +#define VPLL_CON2_VAL NOT_AVAILABLE + +/* RPLL_CON1, CON2 */ +#define RPLL_CON1_VAL 0x00000000 +#define RPLL_CON2_VAL 0x00000080 + +/* BPLL_CON1 */ +#define BPLL_CON1_VAL 0x0020f300 + +/* SPLL_CON1 */ +#define SPLL_CON1_VAL 0x0020f300 + +/* IPLL_CON1 */ +#define IPLL_CON1_VAL 0x00000080 + +/* KPLL_CON1 */ +#define KPLL_CON1_VAL 0x200000 + +/* Set PLL */ +#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv) + +/* CLK_SRC_CPU */ +/* 0 = MOUTAPLL, 1 = SCLKMPLL */ +#define MUX_HPM_SEL 1 +#define MUX_CPU_SEL 0 +#define MUX_APLL_SEL 1 + +#define CLK_SRC_CPU_VAL ((MUX_HPM_SEL << 20) \ + | (MUX_CPU_SEL << 16) \ + | (MUX_APLL_SEL)) + +/* MEMCONTROL register bit fields */ +#define DMC_MEMCONTROL_CLK_STOP_DISABLE (0 << 0) +#define DMC_MEMCONTROL_DPWRDN_DISABLE (0 << 1) +#define DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE (0 << 2) +#define DMC_MEMCONTROL_DSREF_DISABLE (0 << 5) +#define DMC_MEMCONTROL_DSREF_ENABLE (1 << 5) +#define DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(x) (x << 6) + +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR3 (7 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_DDR3 (6 << 8) +#define DMC_MEMCONTROL_MEM_TYPE_LPDDR2 (5 << 8) + +#define DMC_MEMCONTROL_MEM_WIDTH_32BIT (2 << 12) + +#define DMC_MEMCONTROL_NUM_CHIP_1 (0 << 16) +#define DMC_MEMCONTROL_NUM_CHIP_2 (1 << 16) + +#define DMC_MEMCONTROL_BL_8 (3 << 20) +#define DMC_MEMCONTROL_BL_4 (2 << 20) + +#define DMC_MEMCONTROL_PZQ_DISABLE (0 << 24) + +#define DMC_MEMCONTROL_MRR_BYTE_7_0 (0 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_15_8 (1 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_23_16 (2 << 25) +#define DMC_MEMCONTROL_MRR_BYTE_31_24 (3 << 25) + +/* MEMCONFIG0 register bit fields */ +#define DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED (1 << 12) +#define DMC_MEMCONFIG_CHIP_MAP_SPLIT (2 << 12) +#define DMC_MEMCONFIGx_CHIP_COL_10 (3 << 8) +#define DMC_MEMCONFIGx_CHIP_ROW_14 (2 << 4) +#define DMC_MEMCONFIGx_CHIP_ROW_15 (3 << 4) +#define DMC_MEMCONFIGx_CHIP_ROW_16 (4 << 4) +#define DMC_MEMCONFIGx_CHIP_BANK_8 (3 << 0) + +#define DMC_MEMBASECONFIG0_VAL DMC_MEMBASECONFIG_VAL(0x40) +#define DMC_MEMBASECONFIG1_VAL DMC_MEMBASECONFIG_VAL(0x80) + +#define DMC_PRECHCONFIG_VAL 0xFF000000 +#define DMC_PWRDNCONFIG_VAL 0xFFFF00FF + +#define DMC_CONCONTROL_RESET_VAL 0x0FFF0000 +#define DFI_INIT_START (1 << 28) +#define EMPTY (1 << 8) +#define AREF_EN (1 << 5) + +#define DFI_INIT_COMPLETE_CHO (1 << 2) +#define DFI_INIT_COMPLETE_CH1 (1 << 3) + +#define RDLVL_COMPLETE_CHO (1 << 14) +#define RDLVL_COMPLETE_CH1 (1 << 15) + +#define CLK_STOP_EN (1 << 0) +#define DPWRDN_EN (1 << 1) +#define DSREF_EN (1 << 5) + +/* COJCONTROL register bit fields */ +#define DMC_CONCONTROL_IO_PD_CON_DISABLE (0 << 3) +#define DMC_CONCONTROL_AREF_EN_DISABLE (0 << 5) +#define DMC_CONCONTROL_RD_FETCH_DISABLE (0x0 << 12) +#define DMC_CONCONTROL_TIMEOUT_LEVEL0 (0xFFF << 16) +#define DMC_CONCONTROL_DFI_INIT_START_DISABLE (0 << 28) + +/* CLK_FSYS */ +#define CLK_SRC_FSYS0_VAL 0x33033300 +#define CLK_DIV_FSYS0_VAL 0x0 +#define CLK_DIV_FSYS1_VAL 0x04f13c4f +#define CLK_DIV_FSYS2_VAL 0x041d0000 + +#define DMC_CONCONTROL_IO_PD_CON(x) (x << 6) + +/* CLK_DIV_CPU1 */ +#define HPM_RATIO 0x2 +#define COPY_RATIO 0x0 + +/* CLK_DIV_CPU1 = 0x00000003 */ +#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) \ + | (COPY_RATIO)) + +/* CLK_SRC_CORE0 */ +#define CLK_SRC_CORE0_VAL 0x00000000 + +/* CLK_SRC_CORE1 */ +#define CLK_SRC_CORE1_VAL 0x100 + +/* CLK_DIV_CORE0 */ +#define CLK_DIV_CORE0_VAL 0x00120000 + +/* CLK_DIV_CORE1 */ +#define CLK_DIV_CORE1_VAL 0x07070700 + +/* CLK_DIV_SYSRGT */ +#define CLK_DIV_SYSRGT_VAL 0x00000111 + +/* CLK_DIV_ACP */ +#define CLK_DIV_ACP_VAL 0x12 + +/* CLK_DIV_SYSLFT */ +#define CLK_DIV_SYSLFT_VAL 0x00000311 + +/* CLK_SRC_CDREX */ +#define CLK_SRC_CDREX_VAL 0x00000001 +#define MUX_MCLK_CDR_MSPLL (1 << 4) +#define MUX_BPLL_SEL_FOUTBPLL (1 << 0) +#define BPLL_SEL_MASK 0x7 +#define FOUTBPLL 2 + +/* CLK_DIV_CDREX */ +#define CLK_DIV_CDREX0_VAL 0x30010100 +#define CLK_DIV_CDREX1_VAL 0x300 + +#define CLK_DIV_CDREX_VAL 0x17010100 + +/* CLK_DIV_CPU0_VAL */ +#define CLK_DIV_CPU0_VAL 0x01440020 + +/* CLK_SRC_TOP */ +#define CLK_SRC_TOP0_VAL 0x11101102 +#define CLK_SRC_TOP1_VAL 0x00200000 +#define CLK_SRC_TOP2_VAL 0x11101010 +#define CLK_SRC_TOP3_VAL 0x11111111 +#define CLK_SRC_TOP4_VAL 0x11110111 +#define CLK_SRC_TOP5_VAL 0x11111111 +#define CLK_SRC_TOP6_VAL 0x11110111 +#define CLK_SRC_TOP7_VAL 0x00022200 + +/* CLK_DIV_TOP */ +#define CLK_DIV_TOP0_VAL 0x22512211 +#define CLK_DIV_TOP1_VAL 0x13200900 +#define CLK_DIV_TOP2_VAL 0x11101110 + +/* APLL_LOCK */ +#define APLL_LOCK_VAL (0x320) +/* MPLL_LOCK */ +#define MPLL_LOCK_VAL (0x258) +/* BPLL_LOCK */ +#define BPLL_LOCK_VAL (0x258) +/* CPLL_LOCK */ +#define CPLL_LOCK_VAL (0x190) +/* DPLL_LOCK */ +#define DPLL_LOCK_VAL (0x190) +/* GPLL_LOCK */ +#define GPLL_LOCK_VAL NOT_AVAILABLE +/* IPLL_LOCK */ +#define IPLL_LOCK_VAL (0x320) +/* KPLL_LOCK */ +#define KPLL_LOCK_VAL (0x258) +/* SPLL_LOCK */ +#define SPLL_LOCK_VAL (0x320) +/* RPLL_LOCK */ +#define RPLL_LOCK_VAL (0x2328) +/* EPLL_LOCK */ +#define EPLL_LOCK_VAL (0x2328) +/* VPLL_LOCK */ +#define VPLL_LOCK_VAL (0x258) + +#define MUX_APLL_SEL_MASK (1 << 0) +#define MUX_MPLL_SEL_MASK (1 << 8) +#define MPLL_SEL_MOUT_MPLLFOUT (2 << 8) +#define MUX_CPLL_SEL_MASK (1 << 8) +#define MUX_EPLL_SEL_MASK (1 << 12) +#define MUX_VPLL_SEL_MASK (1 << 16) +#define MUX_GPLL_SEL_MASK (1 << 28) +#define MUX_BPLL_SEL_MASK (1 << 0) +#define MUX_HPM_SEL_MASK (1 << 20) +#define HPM_SEL_SCLK_MPLL (1 << 21) +#define PLL_LOCKED (1 << 29) +#define APLL_CON0_LOCKED (1 << 29) +#define MPLL_CON0_LOCKED (1 << 29) +#define BPLL_CON0_LOCKED (1 << 29) +#define CPLL_CON0_LOCKED (1 << 29) +#define EPLL_CON0_LOCKED (1 << 29) +#define GPLL_CON0_LOCKED (1 << 29) +#define VPLL_CON0_LOCKED (1 << 29) +#define CLK_REG_DISABLE 0x0 +#define TOP2_VAL 0x0110000 + +/* CLK_SRC_LEX */ +#define CLK_SRC_LEX_VAL 0x0 + +/* CLK_DIV_LEX */ +#define CLK_DIV_LEX_VAL 0x10 + +/* CLK_DIV_R0X */ +#define CLK_DIV_R0X_VAL 0x10 + +/* CLK_DIV_L0X */ +#define CLK_DIV_R1X_VAL 0x10 + +/* CLK_DIV_ISP2 */ +#define CLK_DIV_ISP2_VAL 0x1 + +/* CLK_SRC_KFC */ +#define SRC_KFC_HPM_SEL (1 << 15) + +/* CLK_SRC_KFC */ +#define CLK_SRC_KFC_VAL 0x00008001 + +/* CLK_DIV_KFC */ +#define CLK_DIV_KFC_VAL 0x03300110 + +/* CLK_DIV2_RATIO */ +#define CLK_DIV2_RATIO 0x10111150 + +/* CLK_DIV4_RATIO */ +#define CLK_DIV4_RATIO 0x00000003 + +/* CLK_DIV_G2D */ +#define CLK_DIV_G2D 0x00000010 + +/* CLK_SRC_PERIC0 */ +#define SPDIF_SEL 1 +#define PWM_SEL 3 +#define UART4_SEL 3 +#define UART3_SEL 3 +#define UART2_SEL 3 +#define UART1_SEL 3 +#define UART0_SEL 3 +/* SRC_CLOCK = SCLK_RPLL */ +#define CLK_SRC_PERIC0_VAL ((SPDIF_SEL << 28) \ + | (PWM_SEL << 24) \ + | (UART4_SEL << 20) \ + | (UART3_SEL << 16) \ + | (UART2_SEL << 12) \ + | (UART1_SEL << 8) \ + | (UART0_SEL << 4)) + +/* CLK_SRC_PERIC1 */ +/* SRC_CLOCK = SCLK_MPLL */ +#define SPI0_SEL 3 +#define SPI1_SEL 3 +#define SPI2_SEL 3 +/* SRC_CLOCK = SCLK_EPLL */ +#define AUDIO0_SEL 6 +#define AUDIO1_SEL 6 +#define AUDIO2_SEL 6 +#define CLK_SRC_PERIC1_VAL ((SPI2_SEL << 28) \ + | (SPI1_SEL << 24) \ + | (SPI0_SEL << 20) \ + | (AUDIO2_SEL << 16) \ + | (AUDIO2_SEL << 12) \ + | (AUDIO2_SEL << 8)) + +/* CLK_SRC_ISP */ +#define CLK_SRC_ISP_VAL 0x33366000 +#define CLK_DIV_ISP0_VAL 0x13131300 +#define CLK_DIV_ISP1_VAL 0xbb110202 + +/* SCLK_DIV_ISP - set SPI0/1 to 0xf = divide by 16 */ +#define SPI0_ISP_RATIO 0xf +#define SPI1_ISP_RATIO 0xf +#define SCLK_DIV_ISP_VAL (SPI1_ISP_RATIO << 12) \ + | (SPI0_ISP_RATIO << 0) + +/* CLK_DIV_PERIL0 */ +#define PWM_RATIO 8 +#define UART4_RATIO 9 +#define UART3_RATIO 9 +#define UART2_RATIO 9 +#define UART1_RATIO 9 +#define UART0_RATIO 9 + +#define CLK_DIV_PERIC0_VAL ((PWM_RATIO << 28) \ + | (UART4_RATIO << 24) \ + | (UART3_RATIO << 20) \ + | (UART2_RATIO << 16) \ + | (UART1_RATIO << 12) \ + | (UART0_RATIO << 8)) + +/* CLK_DIV_PERIC1 */ +#define SPI2_RATIO 0x1 +#define SPI1_RATIO 0x1 +#define SPI0_RATIO 0x1 +#define CLK_DIV_PERIC1_VAL ((SPI2_RATIO << 28) \ + | (SPI1_RATIO << 24) \ + | (SPI0_RATIO << 20)) + +/* CLK_DIV_PERIC2 */ +#define PCM2_RATIO 0x3 +#define PCM1_RATIO 0x3 +#define CLK_DIV_PERIC2_VAL ((PCM2_RATIO << 24) \ + | (PCM1_RATIO << 16)) + +/* CLK_DIV_PERIC3 */ +#define AUDIO2_RATIO 0x5 +#define AUDIO1_RATIO 0x5 +#define AUDIO0_RATIO 0x5 +#define CLK_DIV_PERIC3_VAL ((AUDIO2_RATIO << 28) \ + | (AUDIO1_RATIO << 24) \ + | (AUDIO0_RATIO << 20)) + +/* CLK_DIV_PERIC4 */ +#define SPI2_PRE_RATIO 0x3 +#define SPI1_PRE_RATIO 0x3 +#define SPI0_PRE_RATIO 0x3 +#define CLK_DIV_PERIC4_VAL ((SPI2_PRE_RATIO << 24) \ + | (SPI1_PRE_RATIO << 16) \ + | (SPI0_PRE_RATIO << 8)) + +/* CLK_DIV_FSYS2 */ +#define MMC2_RATIO_MASK 0xf +#define MMC2_RATIO_VAL 0x3 +#define MMC2_RATIO_OFFSET 0 + +#define MMC2_PRE_RATIO_MASK 0xff +#define MMC2_PRE_RATIO_VAL 0x9 +#define MMC2_PRE_RATIO_OFFSET 8 + +#define MMC3_RATIO_MASK 0xf +#define MMC3_RATIO_VAL 0x1 +#define MMC3_RATIO_OFFSET 16 + +#define MMC3_PRE_RATIO_MASK 0xff +#define MMC3_PRE_RATIO_VAL 0x0 +#define MMC3_PRE_RATIO_OFFSET 24 + +/* CLK_SRC_LEX */ +#define CLK_SRC_LEX_VAL 0x0 + +/* CLK_DIV_LEX */ +#define CLK_DIV_LEX_VAL 0x10 + +/* CLK_DIV_R0X */ +#define CLK_DIV_R0X_VAL 0x10 + +/* CLK_DIV_L0X */ +#define CLK_DIV_R1X_VAL 0x10 + +/* CLK_DIV_ISP2 */ +#define CLK_DIV_ISP2_VAL 0x1 + +/* CLK_SRC_DISP1_0 */ +#define CLK_SRC_DISP1_0_VAL 0x10006000 +#define CLK_DIV_DISP1_0_VAL 0x01050210 + +/* + * DIV_DISP1_0 + * For DP, divisor should be 2 + */ +#define CLK_DIV_DISP1_0_FIMD1 (2 << 0) + +/* CLK_GATE_IP_DISP1 */ +#define CLK_GATE_DP1_ALLOW (1 << 4) + +/* CLK_GATE_IP_SYSRGT */ +#define CLK_C2C_MASK (1 << 1) + +/* CLK_GATE_IP_ACP */ +#define CLK_SMMUG2D_MASK (1 << 7) +#define CLK_SMMUSSS_MASK (1 << 6) +#define CLK_SMMUMDMA_MASK (1 << 5) +#define CLK_ID_REMAPPER_MASK (1 << 4) +#define CLK_G2D_MASK (1 << 3) +#define CLK_SSS_MASK (1 << 2) +#define CLK_MDMA_MASK (1 << 1) +#define CLK_SECJTAG_MASK (1 << 0) + +/* CLK_GATE_BUS_SYSLFT */ +#define CLK_EFCLK_MASK (1 << 16) + +/* CLK_GATE_IP_ISP0 */ +#define CLK_UART_ISP_MASK (1 << 31) +#define CLK_WDT_ISP_MASK (1 << 30) +#define CLK_PWM_ISP_MASK (1 << 28) +#define CLK_MTCADC_ISP_MASK (1 << 27) +#define CLK_I2C1_ISP_MASK (1 << 26) +#define CLK_I2C0_ISP_MASK (1 << 25) +#define CLK_MPWM_ISP_MASK (1 << 24) +#define CLK_MCUCTL_ISP_MASK (1 << 23) +#define CLK_INT_COMB_ISP_MASK (1 << 22) +#define CLK_SMMU_MCUISP_MASK (1 << 13) +#define CLK_SMMU_SCALERP_MASK (1 << 12) +#define CLK_SMMU_SCALERC_MASK (1 << 11) +#define CLK_SMMU_FD_MASK (1 << 10) +#define CLK_SMMU_DRC_MASK (1 << 9) +#define CLK_SMMU_ISP_MASK (1 << 8) +#define CLK_GICISP_MASK (1 << 7) +#define CLK_ARM9S_MASK (1 << 6) +#define CLK_MCUISP_MASK (1 << 5) +#define CLK_SCALERP_MASK (1 << 4) +#define CLK_SCALERC_MASK (1 << 3) +#define CLK_FD_MASK (1 << 2) +#define CLK_DRC_MASK (1 << 1) +#define CLK_ISP_MASK (1 << 0) + +/* CLK_GATE_IP_ISP1 */ +#define CLK_SPI1_ISP_MASK (1 << 13) +#define CLK_SPI0_ISP_MASK (1 << 12) +#define CLK_SMMU3DNR_MASK (1 << 7) +#define CLK_SMMUDIS1_MASK (1 << 6) +#define CLK_SMMUDIS0_MASK (1 << 5) +#define CLK_SMMUODC_MASK (1 << 4) +#define CLK_3DNR_MASK (1 << 2) +#define CLK_DIS_MASK (1 << 1) +#define CLK_ODC_MASK (1 << 0) + +/* CLK_GATE_IP_GSCL */ +#define CLK_SMMUFIMC_LITE2_MASK (1 << 20) +#define CLK_SMMUFIMC_LITE1_MASK (1 << 12) +#define CLK_SMMUFIMC_LITE0_MASK (1 << 11) +#define CLK_SMMUGSCL3_MASK (1 << 10) +#define CLK_SMMUGSCL2_MASK (1 << 9) +#define CLK_SMMUGSCL1_MASK (1 << 8) +#define CLK_SMMUGSCL0_MASK (1 << 7) +#define CLK_GSCL_WRAP_B_MASK (1 << 6) +#define CLK_GSCL_WRAP_A_MASK (1 << 5) +#define CLK_CAMIF_TOP_MASK (1 << 4) +#define CLK_GSCL3_MASK (1 << 3) +#define CLK_GSCL2_MASK (1 << 2) +#define CLK_GSCL1_MASK (1 << 1) +#define CLK_GSCL0_MASK (1 << 0) + +/* CLK_GATE_IP_MFC */ +#define CLK_SMMUMFCR_MASK (1 << 2) +#define CLK_SMMUMFCL_MASK (1 << 1) +#define CLK_MFC_MASK (1 << 0) + +#define SCLK_MPWM_ISP_MASK (1 << 0) + +/* CLK_GATE_IP_DISP1 */ +#define CLK_SMMUTVX_MASK (1 << 9) +#define CLK_ASYNCTVX_MASK (1 << 7) +#define CLK_HDMI_MASK (1 << 6) +#define CLK_MIXER_MASK (1 << 5) +#define CLK_DSIM1_MASK (1 << 3) + +/* AUDIO CLK SEL */ +#define AUDIO0_SEL_EPLL (0x6 << 28) +#define AUDIO0_RATIO 0x5 +#define PCM0_RATIO 0x3 +#define DIV_MAU_VAL (PCM0_RATIO << 24 | AUDIO0_RATIO << 20) + +/* CLK_GATE_IP_GEN */ +#define CLK_SMMUMDMA1_MASK (1 << 9) +#define CLK_SMMUJPEG_MASK (1 << 7) +#define CLK_SMMUROTATOR_MASK (1 << 6) +#define CLK_MDMA1_MASK (1 << 4) +#define CLK_JPEG_MASK (1 << 2) +#define CLK_ROTATOR_MASK (1 << 1) + +/* CLK_GATE_IP_FSYS */ +#define CLK_WDT_IOP_MASK (1 << 30) +#define CLK_SMMUMCU_IOP_MASK (1 << 26) +#define CLK_SATA_PHY_I2C_MASK (1 << 25) +#define CLK_SATA_PHY_CTRL_MASK (1 << 24) +#define CLK_MCUCTL_MASK (1 << 23) +#define CLK_NFCON_MASK (1 << 22) +#define CLK_SMMURTIC_MASK (1 << 11) +#define CLK_RTIC_MASK (1 << 9) +#define CLK_MIPI_HSI_MASK (1 << 8) +#define CLK_USBOTG_MASK (1 << 7) +#define CLK_SATA_MASK (1 << 6) +#define CLK_PDMA1_MASK (1 << 2) +#define CLK_PDMA0_MASK (1 << 1) +#define CLK_MCU_IOP_MASK (1 << 0) + +/* CLK_GATE_IP_PERIC */ +#define CLK_HS_I2C3_MASK (1 << 31) +#define CLK_HS_I2C2_MASK (1 << 30) +#define CLK_HS_I2C1_MASK (1 << 29) +#define CLK_HS_I2C0_MASK (1 << 28) +#define CLK_AC97_MASK (1 << 27) +#define CLK_SPDIF_MASK (1 << 26) +#define CLK_PCM2_MASK (1 << 23) +#define CLK_PCM1_MASK (1 << 22) +#define CLK_I2S2_MASK (1 << 21) +#define CLK_I2S1_MASK (1 << 20) +#define CLK_SPI2_MASK (1 << 18) +#define CLK_SPI0_MASK (1 << 16) +#define CLK_I2CHDMI_MASK (1 << 14) +#define CLK_I2C7_MASK (1 << 13) +#define CLK_I2C6_MASK (1 << 12) +#define CLK_I2C5_MASK (1 << 11) +#define CLK_I2C4_MASK (1 << 10) +#define CLK_I2C3_MASK (1 << 9) +#define CLK_I2C2_MASK (1 << 8) +#define CLK_I2C1_MASK (1 << 7) +#define CLK_I2C0_MASK (1 << 6) + +/* CLK_GATE_IP_PERIS */ +#define CLK_RTC_MASK (1 << 20) +#define CLK_TZPC9_MASK (1 << 15) +#define CLK_TZPC8_MASK (1 << 14) +#define CLK_TZPC7_MASK (1 << 13) +#define CLK_TZPC6_MASK (1 << 12) +#define CLK_TZPC5_MASK (1 << 11) +#define CLK_TZPC4_MASK (1 << 10) +#define CLK_TZPC3_MASK (1 << 9) +#define CLK_TZPC2_MASK (1 << 8) +#define CLK_TZPC1_MASK (1 << 7) +#define CLK_TZPC0_MASK (1 << 6) +#define CLK_CHIPID_MASK (1 << 0) + +/* CLK_GATE_BLOCK */ +#define CLK_ACP_MASK (1 << 7) + +/* CLK_GATE_IP_CDREX */ +#define CLK_TZASC_DRBXW_MASK (1 << 23) +#define CLK_TZASC_DRBXR_MASK (1 << 22) +#define CLK_TZASC_XLBXW_MASK (1 << 21) +#define CLK_TZASC_XLBXR_MASK (1 << 20) +#define CLK_TZASC_XR1BXW_MASK (1 << 19) +#define CLK_TZASC_XR1BXR_MASK (1 << 18) +#define CLK_DPHY1_MASK (1 << 5) +#define CLK_DPHY0_MASK (1 << 4) + +/* + * TZPC Register Value : + * R0SIZE: 0x0 : Size of secured ram + */ +#define R0SIZE 0x0 + +/* + * TZPC Decode Protection Register Value : + * DECPROTXSET: 0xFF : Set Decode region to non-secure + */ +#define DECPROTXSET 0xFF + +#define LPDDR3PHY_CTRL_PHY_RESET (1 << 0) +#define LPDDR3PHY_CTRL_PHY_RESET_OFF (0 << 0) + +/* FIXME(dhendrix): misleading name. The reset value is 0x17021a40, bits 12:11 ++ default to 0x3 which indicates LPDDR3. We want DDR3, so we use 0x1. */ +#define PHY_CON0_RESET_VAL 0x17020a40 +#define P0_CMD_EN (1 << 14) +#define BYTE_RDLVL_EN (1 << 13) +#define CTRL_SHGATE (1 << 8) + +#define PHY_CON1_RESET_VAL 0x09210100 +#define RDLVL_PASS_ADJ_VAL 0x6 +#define RDLVL_PASS_ADJ_OFFSET 16 +#define CTRL_GATEDURADJ_MASK (0xf << 20) +#define READ_LEVELLING_DDR3 0x0100 + +#define PHY_CON2_RESET_VAL 0x00010004 +#define INIT_DESKEW_EN (1 << 6) +#define DLL_DESKEW_EN (1 << 12) +#define RDLVL_GATE_EN (1 << 24) +#define RDLVL_EN (1 << 25) +#define RDLVL_INCR_ADJ (0x1 << 16) + +/* DREX_PAUSE */ +#define DREX_PAUSE_EN (1 << 0) + +#define BYPASS_EN (1 << 22) + +/********-----MEMMORY VAL----------***/ +#define PHY_CON0_VAL 0x17021A00 + +#define PHY_CON12_RESET_VAL 0x10100070 +#define PHY_CON12_VAL 0x10107F50 +#define CTRL_START (1 << 6) +#define CTRL_DLL_ON (1 << 5) +#define CTRL_FORCE_MASK (0x7F << 8) +#define CTRL_LOCK_COARSE_MASK (0x7F << 10) + + +#define CTRL_OFFSETD_RESET_VAL 0x8 +#define CTRL_OFFSETD_VAL 0x7F + +#define CTRL_OFFSETR0 0x7F +#define CTRL_OFFSETR1 0x7F +#define CTRL_OFFSETR2 0x7F +#define CTRL_OFFSETR3 0x7F +#define PHY_CON4_VAL (CTRL_OFFSETR0 << 0 | \ + CTRL_OFFSETR1 << 8 | \ + CTRL_OFFSETR2 << 16 | \ + CTRL_OFFSETR3 << 24) +#define PHY_CON4_RESET_VAL 0x08080808 + +#define CTRL_OFFSETW0 0x7F +#define CTRL_OFFSETW1 0x7F +#define CTRL_OFFSETW2 0x7F +#define CTRL_OFFSETW3 0x7F +#define PHY_CON6_VAL (CTRL_OFFSETW0 << 0 | \ + CTRL_OFFSETW1 << 8 | \ + CTRL_OFFSETW2 << 16 | \ + CTRL_OFFSETW3 << 24) +#define PHY_CON6_RESET_VAL 0x08080808 + +#define PHY_CON14_RESET_VAL 0x001F0000 +#define CTRL_PULLD_DQS 0xF +#define CTRL_PULLD_DQS_OFFSET 0 + +/*ZQ Configurations */ +#define PHY_CON16_RESET_VAL 0x08000304 + +#define ZQ_CLK_EN (1 << 27) +#define ZQ_CLK_DIV_EN (1 << 18) +#define ZQ_MANUAL_MODE_OFFSET 2 +#define ZQ_LONG_CALIBRATION 0x1 +#define ZQ_MANUAL_STR (1 << 1) +#define ZQ_DONE (1 << 0) +#define ZQ_MODE_DDS_OFFSET 24 + +#define LONG_CALIBRATION (ZQ_LONG_CALIBRATION << ZQ_MANUAL_MODE_OFFSET) + +#define CTRL_RDLVL_GATE_ENABLE 1 +#define CTRL_RDLVL_GATE_DISABLE 0 + +#define CTRL_RDLVL_DATA_ENABLE (1 << 1) +/* Direct Command */ +#define DIRECT_CMD_NOP 0x07000000 +#define DIRECT_CMD_PALL 0x01000000 +#define DIRECT_CMD_ZQINIT 0x0a000000 +#define DIRECT_CMD_CHANNEL_SHIFT 28 +#define DIRECT_CMD_CHIP_SHIFT 20 +#define DIRECT_CMD_BANK_SHIFT 16 +#define DIRECT_CMD_REFA (5 << 24) +#define DIRECT_CMD_MRS1 0x71C00 +#define DIRECT_CMD_MRS2 0x10BFC +#define DIRECT_CMD_MRS3 0x0050C +#define DIRECT_CMD_MRS4 0x00868 +#define DIRECT_CMD_MRS5 0x00C04 + +/* Drive Strength */ +#define IMPEDANCE_48_OHM 4 +#define IMPEDANCE_40_OHM 5 +#define IMPEDANCE_34_OHM 6 +#define IMPEDANCE_30_OHM 7 +#define PHY_CON39_VAL_48_OHM 0x09240924 +#define PHY_CON39_VAL_40_OHM 0x0B6D0B6D +#define PHY_CON39_VAL_34_OHM 0x0DB60DB6 +#define PHY_CON39_VAL_30_OHM 0x0FFF0FFF + + +#define CTRL_BSTLEN_OFFSET 8 +#define CTRL_RDLAT_OFFSET 0 + +#define CMD_DEFAULT_LPDDR3 0xF +#define CMD_DEFUALT_OFFSET 0 +#define T_WRDATA_EN 0x7 +#define T_WRDATA_EN_DDR3 0x8 /* FIXME(dhendrix): 6 for DDR3? see T_wrdata_en */ +#define T_WRDATA_EN_OFFSET 16 +#define T_WRDATA_EN_MASK 0x1f + +#define PHY_CON31_VAL 0x0C183060 +#define PHY_CON32_VAL 0x60C18306 +#define PHY_CON33_VAL 0x00000030 + +#define PHY_CON31_RESET_VAL 0x0 +#define PHY_CON32_RESET_VAL 0x0 +#define PHY_CON33_RESET_VAL 0x0 + +#define SL_DLL_DYN_CON_EN (1 << 1) +#define FP_RESYNC (1 << 3) +#define CTRL_START (1 << 6) + +#define DMC_AREF_EN (1 << 5) +#define DMC_CONCONTROL_EMPTY (1 << 8) +#define DFI_INIT_START (1 << 28) + +#define DMC_MEMCONTROL_VAL 0x00312700 +#define CLK_STOP_EN (1 << 0) +#define DPWRDN_EN (1 << 1) +#define DSREF_EN (1 << 5) + +/* AXI base address mask */ +#define DMC_CHIP_MASK_256MB 0x7f0 +#define DMC_CHIP_MASK_512MB 0x7e0 +#define DMC_CHIP_MASK_1GB 0x7c0 +#define DMC_CHIP_MASK_2GB 0x780 +#define DMC_CHIP_MASK_4GB 0x700 + +#define MEMCONFIG_VAL 0x1323 +#define PRECHCONFIG_DEFAULT_VAL 0xFF000000 +#define PWRDNCONFIG_DEFAULT_VAL 0xFFFF00FF + +#define DFI_INIT_COMPLETE (1 << 3) + +#define BRBRSVCONTROL_VAL 0x00000033 +#define BRBRSVCONFIG_VAL 0x88778877 + +/* Clock Gating Control (CGCONTROL) register */ +#define MEMIF_CG_EN (1 << 3) /* Memory interface clock gating */ +#define SCG_CG_EN (1 << 2) /* Scheduler clock gating */ +#define BUSIF_WR_CG_EN (1 << 1) /* Bus interface write channel clock gating */ +#define BUSIF_RD_CG_EN (1 << 0) /* Bus interface read channel clock gating */ +#define DMC_INTERNAL_CG (MEMIF_CG_EN | SCG_CG_EN | \ + BUSIF_WR_CG_EN | BUSIF_RD_CG_EN) + +/* DMC PHY Control0 register */ +#define PHY_CONTROL0_RESET_VAL 0x0 +#define MEM_TERM_EN (1 << 31) /* Termination enable for memory */ +#define PHY_TERM_EN (1 << 30) /* Termination enable for PHY */ +#define DMC_CTRL_SHGATE (1 << 29) /* Duration of DQS gating signal */ +#define CTRL_ATGATE (1 << 6) +#define FP_RSYNC (1 << 3) /* Force DLL resyncronization */ + +/* Driver strength for CK, CKE, CS & CA */ +#define IMP_OUTPUT_DRV_40_OHM 0x5 +#define IMP_OUTPUT_DRV_30_OHM 0x7 +#define DA_3_DS_OFFSET 25 +#define DA_2_DS_OFFSET 22 +#define DA_1_DS_OFFSET 19 +#define DA_0_DS_OFFSET 16 +#define CA_CK_DRVR_DS_OFFSET 9 +#define CA_CKE_DRVR_DS_OFFSET 6 +#define CA_CS_DRVR_DS_OFFSET 3 +#define CA_ADR_DRVR_DS_OFFSET 0 + +#define PHY_CON42_CTRL_BSTLEN_SHIFT 8 +#define PHY_CON42_CTRL_RDLAT_SHIFT 0 + +struct mem_timings; + +/* Errors that we can encourter in low-level setup */ +enum { + SETUP_ERR_OK, + SETUP_ERR_RDLV_COMPLETE_TIMEOUT = -1, + SETUP_ERR_ZQ_CALIBRATION_FAILURE = -2, +}; + +/* Functions common between LPDDR2 and DDR3 */ + +/* CPU info initialization code */ +void cpu_info_init(void); + +void mem_ctrl_init(void); +/* + * Memory variant specific initialization code + * + * @param mem Memory timings for this memory type. + * @param mem_iv_size Memory interleaving size is a configurable parameter + * which the DMC uses to decide how to split a memory + * chunk into smaller chunks to support concurrent + * accesses; may vary across boards. + * @param mem_reset Reset memory during initialization. + * @return 0 if ok, SETUP_ERR_... if there is a problem + */ +int ddr3_mem_ctrl_init(struct mem_timings *mem, int interleave_size, int reset); + +/* Memory variant specific initialization code for LPDDR3 */ +int lpddr3_mem_ctrl_init(int reset); + +/* + * Configure ZQ I/O interface + * + * @param mem Memory timings for this memory type. + * @param phy0_ctrl Pointer to struct containing PHY0 control reg + * @param phy1_ctrl Pointer to struct containing PHY1 control reg + * @return 0 if ok, -1 on error + */ +int dmc_config_zq(struct mem_timings *mem, + struct exynos5_phy_control *phy0_ctrl, + struct exynos5_phy_control *phy1_ctrl); + +/* + * Send NOP and MRS/EMRS Direct commands + * + * @param mem Memory timings for this memory type. + * @param dmc Pointer to struct of DMC registers + */ +void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* + * Send PALL Direct commands + * + * @param mem Memory timings for this memory type. + * @param dmc Pointer to struct of DMC registers + */ +void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* + * Configure the memconfig and membaseconfig registers + * + * @param mem Memory timings for this memory type. + * @param exynos5_dmc Pointer to struct of DMC registers + */ +void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc); + +/* Set the PS-Hold drive value */ +void ps_hold_setup(void); +/* + * Reset the DLL. This function is common between DDR3 and LPDDR2. + * However, the reset value is different. So we are passing a flag + * ddr_mode to distinguish between LPDDR2 and DDR3. + * + * @param exynos5_dmc Pointer to struct of DMC registers + * @param ddr_mode Type of DDR memory + */ +void update_reset_dll(struct exynos5_dmc *, enum ddr_mode); +#endif diff --git a/src/cpu/samsung/exynos5250/spi.h b/src/soc/samsung/exynos5420/include/soc/spi.h similarity index 74% rename from src/cpu/samsung/exynos5250/spi.h rename to src/soc/samsung/exynos5420/include/soc/spi.h index 20f50e58c6..78cca6f416 100644 --- a/src/cpu/samsung/exynos5250/spi.h +++ b/src/soc/samsung/exynos5420/include/soc/spi.h @@ -1,11 +1,11 @@ /* - * (C) Copyright 2012 SAMSUNG Electronics - * Padmavathi Venna + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,13 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __ASM_ARCH_EXYNOS_COMMON_SPI_H_ -#define __ASM_ARCH_EXYNOS_COMMON_SPI_H_ +#ifndef CPU_SAMSUNG_EXYNOS5420_SPI_H +#define CPU_SAMSUNG_EXYNOS5420_SPI_H -#ifndef __ASSEMBLER__ +/* This driver serves as a CBFS media source. */ +#include /* SPI peripheral register map; padded to 64KB */ struct exynos_spi { @@ -38,6 +39,7 @@ struct exynos_spi { unsigned int fb_clk; /* 0x2c */ unsigned char padding[0xffd0]; }; +check_member(exynos_spi, fb_clk, 0x2c); #define EXYNOS_SPI_MAX_FREQ 50000000 @@ -55,8 +57,12 @@ struct exynos_spi { #define SPI_TX_CH_ON (1 << 0) /* SPI_MODECFG */ -#define SPI_MODE_CH_WIDTH_WORD (0x2 << 29) +#define SPI_MODE_BUS_WIDTH_BYTE (0x0 << 17) #define SPI_MODE_BUS_WIDTH_WORD (0x2 << 17) +#define SPI_MODE_BUS_WIDTH_MASK (0x3 << 17) +#define SPI_MODE_CH_WIDTH_BYTE (0x0 << 29) +#define SPI_MODE_CH_WIDTH_WORD (0x2 << 29) +#define SPI_MODE_CH_WIDTH_MASK (0x3 << 29) /* SPI_CSREG */ #define SPI_SLAVE_SIG_INACT (1 << 0) @@ -85,5 +91,8 @@ struct exynos_spi { #define SPI_RX_BYTE_SWAP (1 << 6) #define SPI_RX_HWORD_SWAP (1 << 7) -#endif /* __ASSEMBLER__ */ +/* Serve as CBFS media source */ +int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size); #endif diff --git a/src/soc/samsung/exynos5420/include/soc/sysreg.h b/src/soc/samsung/exynos5420/include/soc/sysreg.h new file mode 100644 index 0000000000..d2f1bdefea --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/sysreg.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Register map for Exynos5 sysreg */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_SYSREG_H +#define CPU_SAMSUNG_EXYNOS5420_SYSREG_H + +#include + +/* sysreg map */ +struct exynos5_sysreg { + /* Add registers as and when required */ + unsigned char res1[0x214]; + unsigned int disp1blk_cfg; + unsigned char res2[0x18]; + unsigned int usb20_phy_cfg; +}; +check_member(exynos5_sysreg, usb20_phy_cfg, 0x230); + +static struct exynos5_sysreg * const exynos_sysreg = + (void *)EXYNOS5_SYSREG_BASE; + +#define FIMDBYPASS_DISP1 (1 << 15) +#define USB20_PHY_CFG_EN (1 << 0) + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/tmu.h b/src/soc/samsung/exynos5420/include/soc/tmu.h new file mode 100644 index 0000000000..3085b0718e --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/tmu.h @@ -0,0 +1,135 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* EXYNOS - Thermal Management Unit */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_TMU_H +#define CPU_SAMSUNG_EXYNOS5420_TMU_H + +struct tmu_reg { + unsigned triminfo; + unsigned rsvd1; + unsigned rsvd2; + unsigned rsvd3; + unsigned rsvd4; + unsigned triminfo_control; + unsigned rsvd5; + unsigned rsvd6; + unsigned tmu_control; + unsigned rsvd7; + unsigned tmu_status; + unsigned sampling_internal; + unsigned counter_value0; + unsigned counter_value1; + unsigned rsvd8; + unsigned rsvd9; + unsigned current_temp; + unsigned rsvd10; + unsigned rsvd11; + unsigned rsvd12; + unsigned threshold_temp_rise; + unsigned threshold_temp_fall; + unsigned rsvd13; + unsigned rsvd14; + unsigned past_temp3_0; + unsigned past_temp7_4; + unsigned past_temp11_8; + unsigned past_temp15_12; + unsigned inten; + unsigned intstat; + unsigned intclear; + unsigned rsvd15; + unsigned emul_con; +}; +check_member(tmu_reg, emul_con, 0x80); + +enum tmu_status_t { + TMU_STATUS_INIT = 0, + TMU_STATUS_NORMAL, + TMU_STATUS_WARNING, + TMU_STATUS_TRIPPED, +}; + +/* Tmeperature threshold values for various thermal events */ +struct temperature_params { + /* minimum value in temperature code range */ + unsigned int min_val; + /* maximum value in temperature code range */ + unsigned int max_val; + /* temperature threshold to start warning */ + unsigned int start_warning; + /* temperature threshold CPU tripping */ + unsigned int start_tripping; + /* temperature threshold for HW tripping */ + unsigned int hardware_tripping; +}; + +/* Pre-defined values and thresholds for calibration of current temperature */ +struct tmu_data { + /* pre-defined temperature thresholds */ + struct temperature_params ts; + /* pre-defined efuse range minimum value */ + unsigned int efuse_min_value; + /* pre-defined efuse value for temperature calibration */ + unsigned int efuse_value; + /* pre-defined efuse range maximum value */ + unsigned int efuse_max_value; + /* current temperature sensing slope */ + unsigned int slope; +}; + +/* TMU device specific details and status */ +struct tmu_info { + /* base Address for the TMU */ + unsigned tmu_base; + /* mux Address for the TMU */ + int tmu_mux; + /* pre-defined values for calibration and thresholds */ + struct tmu_data data; + /* value required for triminfo_25 calibration */ + unsigned int te1; + /* value required for triminfo_85 calibration */ + unsigned int te2; + /* TMU DC value for threshold calculation */ + int dc_value; + /* enum value indicating status of the TMU */ + int tmu_state; +}; + +extern struct tmu_info *tmu_info; + +/* + * Monitors status of the TMU device and exynos temperature + * + * @info pointer to TMU info struct + * @temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + * and -1 on error + */ +enum tmu_status_t tmu_monitor(struct tmu_info *info, int *temp); + +/* + * Initialize TMU device + * + * @info pointer to TMU info struct + * @return int value, 0 for success + */ +int tmu_init(struct tmu_info *info); + +#endif /* CPU_SAMSUNG_EXYNOS5420_TMU_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/trustzone.h b/src/soc/samsung/exynos5420/include/soc/trustzone.h new file mode 100644 index 0000000000..209cd9f354 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/trustzone.h @@ -0,0 +1,82 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_TRUSTZONE_H +#define CPU_SAMSUNG_EXYNOS5420_TRUSTZONE_H + +#include + +/* Distance between each Trust Zone PC register set */ +#define TZPC_BASE_OFFSET 0x10000 +/* TZPC : Register Offsets */ +#define TZPC0_BASE 0x10100000 +#define TZPC1_BASE 0x10110000 +#define TZPC2_BASE 0x10120000 +#define TZPC3_BASE 0x10130000 +#define TZPC4_BASE 0x10140000 +#define TZPC5_BASE 0x10150000 +#define TZPC6_BASE 0x10160000 +#define TZPC7_BASE 0x10170000 +#define TZPC8_BASE 0x10180000 +#define TZPC9_BASE 0x10190000 +#define TZPC10_BASE 0x100E0000 +#define TZPC11_BASE 0x100F0000 + +/* + * TZPC Register Value : + * R0SIZE: 0x0 : Size of secured ram + */ +#define R0SIZE 0x0 + +/* + * TZPC Decode Protection Register Value : + * DECPROTXSET: 0xFF : Set Decode region to non-secure + */ +#define DECPROTXSET 0xFF + +struct exynos_tzpc { + u32 r0size; + u8 res1[0x7FC]; + u32 decprot0stat; + u32 decprot0set; + u32 decprot0clr; + u32 decprot1stat; + u32 decprot1set; + u32 decprot1clr; + u32 decprot2stat; + u32 decprot2set; + u32 decprot2clr; + u32 decprot3stat; + u32 decprot3set; + u32 decprot3clr; + u8 res2[0x7B0]; + u32 periphid0; + u32 periphid1; + u32 periphid2; + u32 periphid3; + u32 pcellid0; + u32 pcellid1; + u32 pcellid2; + u32 pcellid3; +}; +check_member(exynos_tzpc, pcellid3, 0xffc); + +void trustzone_init(void); + +#endif /* CPU_SAMSUNG_EXYNOS5420_TRUSTZONE_H */ diff --git a/src/soc/samsung/exynos5420/include/soc/uart.h b/src/soc/samsung/exynos5420/include/soc/uart.h new file mode 100644 index 0000000000..ed78f60cc3 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/uart.h @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2012 Google Inc. + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_UART_H +#define CPU_SAMSUNG_EXYNOS5420_UART_H + +struct s5p_uart { + unsigned int ulcon; + unsigned int ucon; + unsigned int ufcon; + unsigned int umcon; + unsigned int utrstat; + unsigned int uerstat; + unsigned int ufstat; + unsigned int umstat; + unsigned char utxh; + unsigned char res1[3]; + unsigned char urxh; + unsigned char res2[3]; + unsigned int ubrdiv; + unsigned char res3[0xffd0]; +}; +check_member(s5p_uart, ubrdiv, 0x28); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/usb.h b/src/soc/samsung/exynos5420/include/soc/usb.h new file mode 100644 index 0000000000..12571057b6 --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/usb.h @@ -0,0 +1,147 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_USB_H +#define CPU_SAMSUNG_EXYNOS5420_USB_H + +#include + +#define CLK_24MHZ 5 + +#define HOST_CTRL0_PHYSWRSTALL (1 << 31) +#define HOST_CTRL0_COMMONON_N (1 << 9) +#define HOST_CTRL0_SIDDQ (1 << 6) +#define HOST_CTRL0_FORCESLEEP (1 << 5) +#define HOST_CTRL0_FORCESUSPEND (1 << 4) +#define HOST_CTRL0_WORDINTERFACE (1 << 3) +#define HOST_CTRL0_UTMISWRST (1 << 2) +#define HOST_CTRL0_LINKSWRST (1 << 1) +#define HOST_CTRL0_PHYSWRST (1 << 0) + +#define HOST_CTRL0_FSEL_MASK (7 << 16) + +#define EHCICTRL_ENAINCRXALIGN (1 << 29) +#define EHCICTRL_ENAINCR4 (1 << 28) +#define EHCICTRL_ENAINCR8 (1 << 27) +#define EHCICTRL_ENAINCR16 (1 << 26) + +/* Register map for PHY control */ +struct exynos5_usb_host_phy { + uint32_t usbphyctrl0; + uint32_t usbphytune0; + uint8_t reserved1[8]; + uint32_t hsicphyctrl1; + uint32_t hsicphytune1; + uint8_t reserved2[8]; + uint32_t hsicphyctrl2; + uint32_t hsicphytune2; + uint8_t reserved3[8]; + uint32_t ehcictrl; + uint32_t ohcictrl; + uint32_t usbotgsys; + uint8_t reserved4[4]; + uint32_t usbotgtune; +}; +check_member(exynos5_usb_host_phy, usbotgtune, 0x40); + +static struct exynos5_usb_host_phy * const exynos_usb_host_phy = + (void *)EXYNOS5_USB_HOST_PHY_BASE; + +struct exynos5_usb_drd_phy { + uint8_t reserved1[4]; + uint32_t linksystem; + uint32_t utmi; + uint32_t pipe; + uint32_t clkrst; + uint32_t reg0; + uint32_t reg1; + uint32_t param0; + uint32_t param1; + uint32_t term; + uint32_t test; + uint32_t adp; + uint32_t utmiclksel; + uint32_t resume; + uint8_t reserved2[8]; + uint32_t linkhcbelt; + uint32_t linkport; +}; +check_member(exynos5_usb_drd_phy, linkport, 0x44); + +static struct exynos5_usb_drd_phy * const exynos_usb_drd0_phy = + (void *)EXYNOS5420_USB_DRD0_PHY_BASE; +static struct exynos5_usb_drd_phy * const exynos_usb_drd1_phy = + (void *)EXYNOS5420_USB_DRD1_PHY_BASE; + +struct exynos5_usb_drd_dwc3 { + uint32_t sbuscfg0; + uint32_t sbuscfg1; + uint32_t txthrcfg; + uint32_t rxthrcfg; + uint32_t ctl; + uint32_t evten; + uint32_t sts; + uint8_t reserved0[4]; + uint32_t snpsid; + uint32_t gpio; + uint32_t uid; + uint32_t uctl; + uint64_t buserraddr; + uint64_t prtbimap; + uint8_t reserved1[32]; + uint32_t dbgfifospace; + uint32_t dbgltssm; + uint32_t dbglnmcc; + uint32_t dbgbmu; + uint32_t dbglspmux; + uint32_t dbglsp; + uint32_t dbgepinfo0; + uint32_t dbgepinfo1; + uint64_t prtbimap_hs; + uint64_t prtbimap_fs; + uint8_t reserved2[112]; + uint32_t usb2phycfg; + uint8_t reserved3[60]; + uint32_t usb2i2cctl; + uint8_t reserved4[60]; + uint32_t usb2phyacc; + uint8_t reserved5[60]; + uint32_t usb3pipectl; + uint8_t reserved6[60]; +}; +check_member(exynos5_usb_drd_dwc3, usb3pipectl, 0x1c0); + +static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd0_dwc3 = + (void *)EXYNOS5420_USB_DRD0_DWC3_BASE; +static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd1_dwc3 = + (void *)EXYNOS5420_USB_DRD1_DWC3_BASE; + +/* Leave hsic_gpio at 0 to not enable HSIC. */ +void setup_usb_host_phy(int hsic_gpio); + +void setup_usb_drd0_phy(void); +void setup_usb_drd1_phy(void); + +/* Call reset_ before setup_, ensure at least 100ms pass in between. */ +void reset_usb_drd0_dwc3(void); +void reset_usb_drd1_dwc3(void); +void setup_usb_drd0_dwc3(void); +void setup_usb_drd1_dwc3(void); + +#endif diff --git a/src/soc/samsung/exynos5420/include/soc/wakeup.h b/src/soc/samsung/exynos5420/include/soc/wakeup.h new file mode 100644 index 0000000000..27ce8e2f2d --- /dev/null +++ b/src/soc/samsung/exynos5420/include/soc/wakeup.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CPU_SAMSUNG_EXYNOS5420_WAKEUP_H +#define CPU_SAMSUNG_EXYNOS5420_WAKEUP_H + +/* Power Down Modes */ +#define S5P_CHECK_SLEEP 0x00000BAD +#define S5P_CHECK_DIDLE 0xBAD00000 +#define S5P_CHECK_LPA 0xABAD0000 + +enum { + // A normal boot (not suspend/resume) + IS_NOT_WAKEUP, + // A wake up event that can be resumed any time + WAKEUP_DIRECT, + // A wake up event that must be resumed only after + // clock and memory controllers are re-initialized + WAKEUP_NEED_CLOCK_RESET, +}; + +int wakeup_need_reset(void); +int get_wakeup_state(void); +void wakeup(void); +void wakeup_enable_uart(void); + +#endif /* CPU_SAMSUNG_EXYNOS5420_WAKEUP_H */ diff --git a/src/soc/samsung/exynos5420/pinmux.c b/src/soc/samsung/exynos5420/pinmux.c new file mode 100644 index 0000000000..8fee096ea4 --- /dev/null +++ b/src/soc/samsung/exynos5420/pinmux.c @@ -0,0 +1,245 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static void exynos_pinmux_uart(int start, int count) +{ + int i; + + for (i = start; i < start + count; i++) { + gpio_set_pull(i, GPIO_PULL_NONE); + gpio_cfg_pin(i, GPIO_FUNC(0x2)); + } +} + +void exynos_pinmux_uart0(void) +{ + exynos_pinmux_uart(GPIO_A00, 4); +} + +void exynos_pinmux_uart1(void) +{ + exynos_pinmux_uart(GPIO_A04, 4); +} + +void exynos_pinmux_uart2(void) +{ + exynos_pinmux_uart(GPIO_A10, 4); +} + +void exynos_pinmux_uart3(void) +{ + exynos_pinmux_uart(GPIO_A14, 2); +} + +struct gpio { + enum exynos5_gpio_pin pin; + unsigned int func; + unsigned int pull; + unsigned int drv; +}; + +static void exynos_pinmux_sdmmc(struct gpio *gpios, int num_gpios) +{ + int i; + + for (i = 0; i < num_gpios; i++) { + gpio_set_drv(gpios[i].pin, gpios[i].drv); + gpio_set_pull(gpios[i].pin, gpios[i].pull); + gpio_cfg_pin(gpios[i].pin, GPIO_FUNC(gpios[i].func)); + } +} + +void exynos_pinmux_sdmmc0(void) +{ + struct gpio gpios[] = { + { GPIO_C00, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CLK */ + { GPIO_C01, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CMD */ + /* + * MMC0 is intended to be used for eMMC. The card detect + * pin is used as a VDDEN signal to power on the eMMC. The + * 5420 iROM makes this same assumption. + */ + { GPIO_C02, GPIO_OUTPUT, GPIO_PULL_NONE, GPIO_DRV_4X }, + { GPIO_C03, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[0] */ + { GPIO_C04, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[1] */ + { GPIO_C05, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[2] */ + { GPIO_C06, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[3] */ + + { GPIO_C30, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[4] */ + { GPIO_C31, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[5] */ + { GPIO_C32, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[6] */ + { GPIO_C33, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[7] */ + }; + + exynos_pinmux_sdmmc(&gpios[0], ARRAY_SIZE(gpios)); + + /* set VDDEN */ + gpio_set_value(GPIO_C02, 1); +} + +void exynos_pinmux_sdmmc1(void) +{ + struct gpio gpios[] = { + { GPIO_C10, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CLK */ + { GPIO_C11, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CMD */ + { GPIO_C12, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CDn */ + { GPIO_C13, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[0] */ + { GPIO_C14, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[1] */ + { GPIO_C15, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[2] */ + { GPIO_C16, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[3] */ + + { GPIO_D14, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[4] */ + { GPIO_D15, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[5] */ + { GPIO_D16, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[6] */ + { GPIO_D17, 0x2, GPIO_PULL_UP, GPIO_DRV_4X }, /* DATA[7] */ + }; + + exynos_pinmux_sdmmc(&gpios[0], ARRAY_SIZE(gpios)); +} + +void exynos_pinmux_sdmmc2(void) +{ + struct gpio gpios[] = { + { GPIO_C20, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CLK */ + { GPIO_C21, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CMD */ + { GPIO_C22, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* CDn */ + { GPIO_C23, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[0] */ + { GPIO_C24, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[1] */ + { GPIO_C25, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[2] */ + { GPIO_C26, 0x2, GPIO_PULL_NONE, GPIO_DRV_4X }, /* DATA[3] */ + }; + + exynos_pinmux_sdmmc(&gpios[0], ARRAY_SIZE(gpios)); +} + +static void exynos_pinmux_spi(int start, int cfg) +{ + int i; + + for (i = start; i < start + 4; i++) { + gpio_cfg_pin(i, cfg); + gpio_set_pull(i, GPIO_PULL_NONE); + gpio_set_drv(i, GPIO_DRV_3X); + } +} + +void exynos_pinmux_spi0(void) +{ + exynos_pinmux_spi(GPIO_A20, 0x2); +} + +void exynos_pinmux_spi1(void) +{ + exynos_pinmux_spi(GPIO_A24, 0x2); +} + +void exynos_pinmux_spi2(void) +{ + exynos_pinmux_spi(GPIO_B11, 0x5); +} + +void exynos_pinmux_spi3(void) +{ + exynos_pinmux_spi(GPIO_F10, 0x2); +} + +void exynos_pinmux_spi4(void) +{ + int i; + + for (i = 0; i < 2; i++) { + gpio_cfg_pin(GPIO_F02 + i, GPIO_FUNC(0x4)); + gpio_cfg_pin(GPIO_E04 + i, GPIO_FUNC(0x4)); + } +} + +static void exynos_pinmux_i2c(int start, int func) +{ + gpio_cfg_pin(start, GPIO_FUNC(func)); + gpio_cfg_pin(start + 1, GPIO_FUNC(func)); + gpio_set_pull(start, GPIO_PULL_NONE); + gpio_set_pull(start + 1, GPIO_PULL_NONE); +} + +void exynos_pinmux_i2c0(void) +{ + exynos_pinmux_i2c(GPIO_B30, 0x2); +} + +void exynos_pinmux_i2c1(void) +{ + exynos_pinmux_i2c(GPIO_B32, 0x2); +} + +void exynos_pinmux_i2c2(void) +{ + exynos_pinmux_i2c(GPIO_A06, 0x3); +} + +void exynos_pinmux_i2c3(void) +{ + exynos_pinmux_i2c(GPIO_A12, 0x3); +} + +void exynos_pinmux_i2c4(void) +{ + exynos_pinmux_i2c(GPIO_A20, 0x3); +} + +void exynos_pinmux_i2c5(void) +{ + exynos_pinmux_i2c(GPIO_A22, 0x3); +} + +void exynos_pinmux_i2c6(void) +{ + exynos_pinmux_i2c(GPIO_B13, 0x4); +} + +void exynos_pinmux_i2c7(void) +{ + exynos_pinmux_i2c(GPIO_B22, 0x3); +} + +void exynos_pinmux_i2c8(void) +{ + exynos_pinmux_i2c(GPIO_B34, 0x2); +} + +void exynos_pinmux_i2c9(void) +{ + exynos_pinmux_i2c(GPIO_B36, 0x2); +} + +void exynos_pinmux_i2c10(void) +{ + exynos_pinmux_i2c(GPIO_B40, 0x2); +} + +void exynos_pinmux_dphpd(void) +{ + gpio_cfg_pin(GPIO_X07, GPIO_FUNC(0x3)); + gpio_set_pull(GPIO_X07, GPIO_PULL_NONE); +} diff --git a/src/soc/samsung/exynos5420/power.c b/src/soc/samsung/exynos5420/power.c new file mode 100644 index 0000000000..68d580a110 --- /dev/null +++ b/src/soc/samsung/exynos5420/power.c @@ -0,0 +1,92 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Power setup code for EXYNOS5 */ + +#include +#include +#include +#include +#include +#include + +void ps_hold_setup(void) +{ + /* Set PS-Hold high */ + setbits_le32(&exynos_power->ps_hold_ctrl, + POWER_PS_HOLD_CONTROL_DATA_HIGH); +} + +void power_reset(void) +{ + /* Clear inform1 so there's no change we think we've got a wake reset */ + exynos_power->inform1 = 0; + + setbits_le32(&exynos_power->sw_reset, 1); +} + +/* This function never returns */ +void power_shutdown(void) +{ + clrbits_le32(&exynos_power->ps_hold_ctrl, + POWER_PS_HOLD_CONTROL_DATA_HIGH); + + hlt(); +} + +void power_enable_dp_phy(void) +{ + setbits_le32(&exynos_power->dptx_phy_control, EXYNOS_DP_PHY_ENABLE); +} + +void power_enable_hw_thermal_trip(void) +{ + /* Enable HW thermal trip */ + setbits_le32(&exynos_power->ps_hold_ctrl, POWER_ENABLE_HW_TRIP); +} + +uint32_t power_read_reset_status(void) +{ + return exynos_power->inform1; +} + +void power_exit_wakeup(void) +{ + typedef void (*resume_func)(void); + + ((resume_func)exynos_power->inform0)(); +} + +int power_init(void) +{ + ps_hold_setup(); + return 0; +} + +void power_enable_xclkout(void) +{ + /* use xxti for xclk out */ + clrsetbits_le32(&exynos_power->pmu_debug, PMU_DEBUG_CLKOUT_SEL_MASK, + PMU_DEBUG_XXTI); +} + +void power_release_uart_retention(void) +{ + writel(1 << 28, &exynos_power->padret_uart_opt); +} diff --git a/src/soc/samsung/exynos5420/smp.c b/src/soc/samsung/exynos5420/smp.c new file mode 100644 index 0000000000..422f44ac33 --- /dev/null +++ b/src/soc/samsung/exynos5420/smp.c @@ -0,0 +1,306 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* ACTLR, L2CTLR L2ACTLR constants used in SMP core power up. */ + +#define ACTLR_SMP (1 << 6) + +#define L2CTLR_ECC_PARITY (1 << 21) +#define L2CTLR_DATA_RAM_LATENCY_MASK (7 << 0) +#define L2CTLR_TAG_RAM_LATENCY_MASK (7 << 6) +#define L2CTLR_DATA_RAM_LATENCY_CYCLES_3 (2 << 0) +#define L2CTLR_TAG_RAM_LATENCY_CYCLES_3 (2 << 6) + +#define L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL (1 << 3) +#define L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT (1 << 7) +#define L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE (1 << 27) + +/* Part number in CPU ID (MPIDR). */ +#define PART_NUMBER_CORTEX_A15 (0xc0f) + +/* State of CPU cores in Exynos 5420. */ +#define CORE_STATE_RESET (1 << 0) +#define CORE_STATE_SECONDARY_RESET (1 << 1) +#define CORE_STATE_SWITCH_CLUSTER (1 << 4) + +/* The default address to re-power on a code. */ +#define CORE_RESET_INIT_ADDRESS ((void*)0x00000000) + +/* Vectors in BL1 (0x02020000 = base of iRAM). */ +#define VECTOR_CORE_SEV_HANDLER ((void*)(intptr_t)0x02020004) +#define VECTOR_LOW_POWER_FLAG ((void*)(intptr_t)0x02020028) +#define VECTOR_LOW_POWER_ADDRESS ((void*)(intptr_t)0x0202002C) + +/* The data structure for the "CPU state" memory page (shared with kernel) + * controlling cores in active cluster. Kernel will put starting address for one + * core in "hotplug_address" before power on. Note the address is hard-coded in + * kernel (EXYNOS5420_PA_SYSRAM_NS = 0x02073000). */ +volatile struct exynos5420_cpu_states +{ + uint32_t _reserved[2]; /* RESV, +0x00 */ + uint32_t resume_address; /* REG0, +0x08 */ + uint32_t resume_flag; /* REG1, +0x0C */ + uint32_t _reg2; /* REG2, +0x10 */ + uint32_t _reg3; /* REG3, +0x14 */ + uint32_t switch_address; /* REG4, +0x18, cluster switching */ + uint32_t hotplug_address; /* REG5, +0x1C, core hotplug */ + uint32_t _reg6; /* REG6, +0x20 */ + uint32_t c2_address; /* REG7, +0x24, C2 state change */ + + /* Managed per core status for active cluster, offset: +0x28~0x38 */ + uint32_t cpu_states[4]; + + /* Managed per core GIC status for active cluster, offset: 0x38~0x48 */ + uint32_t cpu_gic_states[4]; +} *exynos_cpu_states = (volatile struct exynos5420_cpu_states*)0x02073000; + +/* When leaving core handlers and jump to hot-plug address (or cluster + * switching), we are not sure if the destination is Thumb or ARM mode. + * So a BX command is required. + */ +inline static void jump_bx(void *address) +{ + asm volatile ("bx %0" : : "r"(address)); + /* never returns. */ +} + +/* Extracts arbitrary bits from a 32-bit unsigned int. */ +inline static uint32_t get_bits(uint32_t value, uint32_t start, uint32_t len) +{ + return ((value << (sizeof(value) * 8 - len - start)) >> + (sizeof(value) * 8 - len)); +} + +/* Waits the referenced address to be ready (non-zero) and then jump into it. */ +static void wait_and_jump(volatile uint32_t* reference) +{ + while (!*reference) { + wfe(); + } + jump_bx((void*)*reference); +} + +/* Configures L2 Control Register to use 3 cycles for DATA/TAG RAM latency. */ +static void configure_l2ctlr(void) +{ + uint32_t val; + + val = read_l2ctlr(); + val &= ~(L2CTLR_DATA_RAM_LATENCY_MASK | L2CTLR_TAG_RAM_LATENCY_MASK); + val |= (L2CTLR_DATA_RAM_LATENCY_CYCLES_3 | L2CTLR_TAG_RAM_LATENCY_CYCLES_3 | + L2CTLR_ECC_PARITY); + write_l2ctlr(val); +} + +/* Configures L2 Auxiliary Control Register for Cortex A15. */ +static void configure_l2actlr(void) +{ + uint32_t val; + + val = read_l2actlr(); + val |= (L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL | + L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT | + L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE); + write_l2actlr(val); +} + +/* Initializes the CPU states to reset state. */ +static void init_exynos_cpu_states(void) { + memset((void*)exynos_cpu_states, 0, sizeof(*exynos_cpu_states)); + exynos_cpu_states->cpu_states[0] = CORE_STATE_RESET; + exynos_cpu_states->cpu_states[1] = CORE_STATE_SECONDARY_RESET; + exynos_cpu_states->cpu_states[2] = CORE_STATE_SECONDARY_RESET; + exynos_cpu_states->cpu_states[3] = CORE_STATE_SECONDARY_RESET; +} + +/* + * Ensures that the L2 logic has been used within the previous 256 cycles + * before modifying the ACTLR.SMP bit. This is required during boot before + * MMU has been enabled, or during a specified reset or power down sequence. + */ +static void enable_smp(void) +{ + uint32_t actlr, val; + + /* Enable SMP mode */ + actlr = read_actlr(); + actlr |= ACTLR_SMP; + + /* Dummy read to assure L2 access */ + val = readl(&exynos_power->inform0); + val &= 0; + actlr |= val; + + write_actlr(actlr); + dsb(); + isb(); +} + +/* Starts the core and jumps to correct location by its state. */ +static void core_start_execution(void) +{ + u32 cpu_id, cpu_state; + + enable_smp(); + set_system_mode(); + + cpu_id = read_mpidr() & 0x3; /* up to 4 processors for one cluster. */ + cpu_state = exynos_cpu_states->cpu_states[cpu_id]; + + if (cpu_state & CORE_STATE_SWITCH_CLUSTER) { + wait_and_jump(&exynos_cpu_states->switch_address); + /* never returns. */ + } + + /* Standard Exynos suspend/resume. */ + if (exynos_power->inform1) { + exynos_power->inform1 = 0; + jump_bx((void*)exynos_power->inform0); + /* never returns. */ + } + + if (cpu_state & CORE_STATE_RESET) { + /* For Reset, U-Boot jumps to its starting address; + * on Coreboot, seems ok to ignore for now. */ + } + wait_and_jump(&exynos_cpu_states->hotplug_address); + /* never returns. */ +} + +/* The entry point for hotplug-in and cluster switching. */ +static void low_power_start(void) +{ + uint32_t sctlr, reg_val; + + /* On warm reset, because iRAM is not cleared, all cores will enter + * low_power_start, not the initial address. So we need to check reset + * status again, and jump to 0x0 in that case. */ + reg_val = readl(&exynos_power->spare0); + if (reg_val != RST_FLAG_VAL) { + writel(0x0, VECTOR_LOW_POWER_FLAG); + jump_bx(CORE_RESET_INIT_ADDRESS); + /* restart cpu execution and never returns. */ + } + + /* Workaround for iROM EVT1. A7 core execution may flow into incorrect + * path, bypassing first jump address and makes final jump address 0x0, + * so we try to make any core set again low_power_start address, if that + * becomes zero. */ + reg_val = readl(VECTOR_CORE_SEV_HANDLER); + if (reg_val != (intptr_t)low_power_start) { + writel((intptr_t)low_power_start, VECTOR_CORE_SEV_HANDLER); + dsb(); + /* ask all cores to power on again. */ + sev(); + } + + set_system_mode(); + + /* Whenever a Cortex A-15 core powers on, iROM resets its L2 cache + * so we need to configure again. */ + if (get_bits(read_midr(), 4, 12) == PART_NUMBER_CORTEX_A15) { + configure_l2ctlr(); + configure_l2actlr(); + } + + /* Invalidate L1 & TLB */ + tlbiall(); + iciallu(); + + /* Disable MMU stuff and caches */ + sctlr = read_sctlr(); + sctlr &= ~(SCTLR_V | SCTLR_M | SCTLR_C); + sctlr |= (SCTLR_I | SCTLR_Z | SCTLR_A); + write_sctlr(sctlr); + + core_start_execution(); + /* The core should not return. But in order to prevent unexpected + * errors, a WFI command will help to put CPU back to idle state. */ + wfi(); +} + +/* Callback to shutdown a core, safe to be set as hot-plug address. */ +static void power_down_core(void) +{ + uint32_t mpidr, core_id; + + /* MPIDR: 0~2=ID, 8~11=cluster. On Exynos 5420, cluster will be only 0 + * or 1. */ + mpidr = read_mpidr(); + core_id = get_bits(mpidr, 0, 2) | (get_bits(mpidr, 8, 4) << 2); + + /* Set the status of the core to low. + * S5E5420A User Manual, 8.8.1.202, ARM_CORE0_CONFIGURATION, two bits to + * control power state in each power down level. + */ + writel(0x0, &exynos_power->arm_core[core_id].config); + + /* S5E5420A User Manual, 8.4.2.5, after ARM_CORE*_CONFIGURATION has been + * set to zero, PMU will detect and wait for WFI then run power-down + * sequence. */ + wfi(); +} + +/* Configures the CPU states shard memory page and then shutdown all cores. */ +static void configure_secondary_cores(void) +{ + if (get_bits(read_midr(), 4, 12) == PART_NUMBER_CORTEX_A15) { + configure_l2ctlr(); + configure_l2actlr(); + } + + /* Currently we use power_down_core as callback for each core to + * shutdown itself, but it is also ok to directly set ARM_CORE*_CONFIG + * to zero by CPU0 because every secondary cores should be already in + * WFI state (in bootblock). The power_down_core will be more helpful + * when we want to use SMP inside firmware. */ + + /* Clear boot reg (hotplug address) in cpu states */ + writel(0, (void*)&exynos_cpu_states->hotplug_address); + + /* set low_power flag and address */ + writel((intptr_t)low_power_start, VECTOR_LOW_POWER_ADDRESS); + writel(RST_FLAG_VAL, VECTOR_LOW_POWER_FLAG); + writel(RST_FLAG_VAL, &exynos_power->spare0); + + /* On next SEV, shutdown all cores. */ + writel((intptr_t)power_down_core, VECTOR_CORE_SEV_HANDLER); + + /* Ask all cores in WFE mode to shutdown. */ + dsb(); + sev(); +} + +/* Configures the SMP cores on Exynos 5420 SOC (and shutdown all secondary + * cores) */ +void exynos5420_config_smp(void) +{ + init_exynos_cpu_states(); + configure_secondary_cores(); +} + diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c new file mode 100644 index 0000000000..6ceb92edd2 --- /dev/null +++ b/src/soc/samsung/exynos5420/spi.c @@ -0,0 +1,317 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EXYNOS_SPI_MAX_TRANSFER_BYTES (65535) + +#if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI +# define DEBUG_SPI(x,...) printk(BIOS_DEBUG, "EXYNOS_SPI: " x) +#else +# define DEBUG_SPI(x,...) +#endif + +struct exynos_spi_slave { + struct spi_slave slave; + struct exynos_spi *regs; + int initialized; +}; + +/* TODO(hungte) Move the SPI param list to per-board configuration, probably + * Kconfig or mainboard.c */ +static struct exynos_spi_slave exynos_spi_slaves[3] = { + // SPI 0 + { + .slave = { .bus = 0, }, + .regs = (void *)EXYNOS5_SPI0_BASE, + }, + // SPI 1 + { + .slave = { .bus = 1, .rw = SPI_READ_FLAG, }, + .regs = (void *)EXYNOS5_SPI1_BASE, + }, + // SPI 2 + { + .slave = { .bus = 2, + .rw = SPI_READ_FLAG | SPI_WRITE_FLAG, }, + .regs = (void *)EXYNOS5_SPI2_BASE, + }, +}; + +static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave) +{ + return container_of(slave, struct exynos_spi_slave, slave); +} + +static void spi_sw_reset(struct exynos_spi *regs, int word) +{ + const uint32_t orig_mode_cfg = readl(®s->mode_cfg); + uint32_t mode_cfg = orig_mode_cfg; + const uint32_t orig_swap_cfg = readl(®s->swap_cfg); + uint32_t swap_cfg = orig_swap_cfg; + + mode_cfg &= ~(SPI_MODE_CH_WIDTH_MASK | SPI_MODE_BUS_WIDTH_MASK); + if (word) { + mode_cfg |= SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD; + swap_cfg |= SPI_RX_SWAP_EN | + SPI_RX_BYTE_SWAP | + SPI_RX_HWORD_SWAP | + SPI_TX_SWAP_EN | + SPI_TX_BYTE_SWAP | + SPI_TX_HWORD_SWAP; + } else { + mode_cfg |= SPI_MODE_CH_WIDTH_BYTE | SPI_MODE_BUS_WIDTH_BYTE; + swap_cfg = 0; + } + + if (mode_cfg != orig_mode_cfg) + writel(mode_cfg, ®s->mode_cfg); + if (swap_cfg != orig_swap_cfg) + writel(swap_cfg, ®s->swap_cfg); + + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); +} + +void spi_init(void) +{ +} + +static void exynos_spi_init(struct exynos_spi *regs) +{ + // Set FB_CLK_SEL. + writel(SPI_FB_DELAY_180, ®s->fb_clk); + // CPOL: Active high. + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); + + // Clear rx and tx channel if set priveously. + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + + setbits_le32(®s->swap_cfg, + SPI_RX_SWAP_EN | SPI_RX_BYTE_SWAP | SPI_RX_HWORD_SWAP); + clrbits_le32(®s->ch_cfg, SPI_CH_HS_EN); + + // Do a soft reset, which will also enable both channels. + spi_sw_reset(regs, 1); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) +{ + ASSERT(bus >= 0 && bus < 3); + struct exynos_spi_slave *eslave = &exynos_spi_slaves[bus]; + if (!eslave->initialized) { + exynos_spi_init(eslave->regs); + eslave->initialized = 1; + } + return &eslave->slave; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct exynos_spi *regs = to_exynos_spi(slave)->regs; + // TODO(hungte) Add some delay if too many transactions happen at once. + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); + return 0; +} + +static void spi_transfer(struct exynos_spi *regs, void *in, const void *out, + u32 size) +{ + u8 *inb = in; + const u8 *outb = out; + + int width = (size % 4) ? 1 : 4; + + while (size) { + int packets = size / width; + // The packet count field is 16 bits wide. + packets = MIN(packets, (1 << 16) - 1); + + int out_bytes, in_bytes; + out_bytes = in_bytes = packets * width; + + spi_sw_reset(regs, width == 4); + writel(packets | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + + while (out_bytes || in_bytes) { + uint32_t spi_sts = readl(®s->spi_sts); + int rx_lvl = ((spi_sts >> 15) & 0x1ff); + int tx_lvl = ((spi_sts >> 6) & 0x1ff); + + if (tx_lvl < 32 && tx_lvl < out_bytes) { + uint32_t data = 0xffffffff; + + if (outb) { + memcpy(&data, outb, width); + outb += width; + } + writel(data, ®s->tx_data); + + out_bytes -= width; + } + + if (rx_lvl >= width) { + uint32_t data = readl(®s->rx_data); + + if (inb) { + memcpy(inb, &data, width); + inb += width; + } + + in_bytes -= width; + } + } + + size -= packets * width; + } +} + +int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytes_out, + void *din, unsigned int bytes_in) +{ + struct exynos_spi *regs = to_exynos_spi(slave)->regs; + + if (bytes_out && bytes_in) { + u32 min_size = MIN(bytes_out, bytes_in); + + spi_transfer(regs, din, dout, min_size); + + bytes_out -= min_size; + bytes_in -= min_size; + + din = (uint8_t *)din + min_size; + dout = (const uint8_t *)dout + min_size; + } + + if (bytes_in) + spi_transfer(regs, din, NULL, bytes_in); + else if (bytes_out) + spi_transfer(regs, NULL, dout, bytes_out); + + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct exynos_spi *regs = to_exynos_spi(slave)->regs; + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); +} + +static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len, + uint32_t off) +{ + struct exynos_spi *regs = to_exynos_spi(slave)->regs; + u32 command; + spi_claim_bus(slave); + + // Send address. + ASSERT(off < (1 << 24)); + command = htonl(SF_READ_DATA_CMD << 24 | off); + spi_transfer(regs, NULL, &command, sizeof(command)); + + // Read the data. + spi_transfer(regs, dest, NULL, len); + spi_release_bus(slave); + + return len; +} + +// SPI as CBFS media. +struct exynos_spi_media { + struct spi_slave *slave; + struct cbfs_simple_buffer buffer; +}; + +static int exynos_spi_cbfs_open(struct cbfs_media *media) +{ + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + DEBUG_SPI("exynos_spi_cbfs_open\n"); + return spi_claim_bus(spi->slave); +} + +static int exynos_spi_cbfs_close(struct cbfs_media *media) +{ + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + DEBUG_SPI("exynos_spi_cbfs_close\n"); + spi_release_bus(spi->slave); + return 0; +} + +static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) +{ + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + int bytes; + DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count); + bytes = exynos_spi_read(spi->slave, dest, count, offset); + return bytes; +} + +static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) +{ + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + DEBUG_SPI("exynos_spi_cbfs_map\n"); + // exynos: spi_rx_tx may work in 4 byte-width-transmission mode and + // requires buffer memory address to be aligned. + if (count % 4) + count += 4 - (count % 4); + return cbfs_simple_buffer_map(&spi->buffer, media, offset, count); +} + +static void *exynos_spi_cbfs_unmap(struct cbfs_media *media, + const void *address) +{ + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + DEBUG_SPI("exynos_spi_cbfs_unmap\n"); + return cbfs_simple_buffer_unmap(&spi->buffer, address); +} + +int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size) +{ + // TODO Replace static variable to support multiple streams. + static struct exynos_spi_media context; + static struct exynos_spi_slave *eslave = &exynos_spi_slaves[1]; + DEBUG_SPI("initialize_exynos_spi_cbfs_media\n"); + + context.slave = &eslave->slave; + context.buffer.allocated = context.buffer.last_allocate = 0; + context.buffer.buffer = buffer_address; + context.buffer.size = buffer_size; + media->context = (void*)&context; + media->open = exynos_spi_cbfs_open; + media->close = exynos_spi_cbfs_close; + media->read = exynos_spi_cbfs_read; + media->map = exynos_spi_cbfs_map; + media->unmap = exynos_spi_cbfs_unmap; + + return 0; +} diff --git a/src/soc/samsung/exynos5420/timer.c b/src/soc/samsung/exynos5420/timer.c new file mode 100644 index 0000000000..f8e9c1bc4f --- /dev/null +++ b/src/soc/samsung/exynos5420/timer.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +static const uint32_t clocks_per_usec = MCT_HZ/1000000; + +static uint64_t mct_raw_value(void) +{ + uint64_t upper = readl(&exynos_mct->g_cnt_u); + uint64_t lower = readl(&exynos_mct->g_cnt_l); + + return (upper << 32) | lower; +} + +void init_timer(void) +{ + writel(readl(&exynos_mct->g_tcon) | (0x1 << 8), + &exynos_mct->g_tcon); +} + +void timer_monotonic_get(struct mono_time *mt) +{ + /* We don't have to call mct_start() here + * because it was already called int he bootblock + */ + + mono_time_set_usecs(mt, mct_raw_value() / clocks_per_usec); +} diff --git a/src/soc/samsung/exynos5420/tmu.c b/src/soc/samsung/exynos5420/tmu.c new file mode 100644 index 0000000000..133587c3ee --- /dev/null +++ b/src/soc/samsung/exynos5420/tmu.c @@ -0,0 +1,215 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* EXYNOS - Thermal Management Unit */ + +#include +#include +#include +#include + +#define TRIMINFO_RELOAD 1 +#define CORE_EN 1 +#define THERM_TRIP_EN (1 << 12) + +#define INTEN_RISE0 1 +#define INTEN_RISE1 (1 << 4) +#define INTEN_RISE2 (1 << 8) +#define INTEN_FALL0 (1 << 16) +#define INTEN_FALL1 (1 << 20) +#define INTEN_FALL2 (1 << 24) + +#define TRIM_INFO_MASK 0xff + +#define INTCLEAR_RISE0 1 +#define INTCLEAR_RISE1 (1 << 4) +#define INTCLEAR_RISE2 (1 << 8) +#define INTCLEAR_FALL0 (1 << 16) +#define INTCLEAR_FALL1 (1 << 20) +#define INTCLEAR_FALL2 (1 << 24) +#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \ + INTCLEAR_RISE2 | INTCLEAR_FALL0 | \ + INTCLEAR_FALL1 | INTCLEAR_FALL2) + +struct tmu_info exynos5420_tmu_info = { + .tmu_base = 0x10060000, + .tmu_mux = 6, + .data = { + .ts = { + .min_val = 25, + .max_val = 125, + .start_warning = 95, + .start_tripping = 105, + .hardware_tripping = 110, + }, + .efuse_min_value = 40, + .efuse_value = 55, + .efuse_max_value = 100, + .slope = 0x10008802, + }, + .dc_value = 25, +}; + +/* + * After reading temperature code from register, compensating + * its value and calculating celsius temperatue, + * get current temperatue. + * + * @return current temperature of the chip as sensed by TMU + */ +static int get_cur_temp(struct tmu_info *info) +{ + int cur_temp; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Temperature code range between min 25 and max 125 */ + cur_temp = readl(®->current_temp) & 0xff; + + /* Calibrate current temperature */ + if (cur_temp) + cur_temp = cur_temp - info->te1 + info->dc_value; + + return cur_temp; +} + +/* + * Monitors status of the TMU device and exynos temperature + * + * @info TMU info + * @temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + */ +enum tmu_status_t tmu_monitor(struct tmu_info *info, int *temp) +{ + if (info->tmu_state == TMU_STATUS_INIT) + return -1; + + int cur_temp; + struct tmu_data *data = &info->data; + + /* Read current temperature of the SOC */ + cur_temp = get_cur_temp(info); + *temp = cur_temp; + + /* Temperature code lies between min 25 and max 125 */ + if (cur_temp >= data->ts.start_tripping && + cur_temp <= data->ts.max_val) + return TMU_STATUS_TRIPPED; + else if (cur_temp >= data->ts.start_warning) + return TMU_STATUS_WARNING; + else if (cur_temp < data->ts.start_warning && + cur_temp >= data->ts.min_val) + return TMU_STATUS_NORMAL; + /* Temperature code does not lie between min 25 and max 125 */ + else { + info->tmu_state = TMU_STATUS_INIT; + printk(BIOS_DEBUG, "EXYNOS_TMU: Thermal reading failed\n"); + return -1; + } + return 0; +} + +/* + * Calibrate and calculate threshold values and + * enable interrupt levels + * + * @param info pointer to the tmu_info struct + */ +static void tmu_setup_parameters(struct tmu_info *info) +{ + unsigned int te_temp, con; + unsigned int warning_code, trip_code, hwtrip_code; + unsigned int cooling_temp; + unsigned int rising_value; + struct tmu_data *data = &info->data; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Must reload for using efuse value at EXYNOS */ + writel(TRIMINFO_RELOAD, ®->triminfo_control); + + /* Get the compensation parameter */ + te_temp = readl(®->triminfo); + info->te1 = te_temp & TRIM_INFO_MASK; + info->te2 = ((te_temp >> 8) & TRIM_INFO_MASK); + + if ((data->efuse_min_value > info->te1) || + (info->te1 > data->efuse_max_value) + || (info->te2 != 0)) + info->te1 = data->efuse_value; + + /* Get RISING & FALLING Threshold value */ + warning_code = data->ts.start_warning + + info->te1 - info->dc_value; + trip_code = data->ts.start_tripping + + info->te1 - info->dc_value; + hwtrip_code = data->ts.hardware_tripping + + info->te1 - info->dc_value; + + cooling_temp = 0; + + rising_value = ((warning_code << 8) | + (trip_code << 16) | + (hwtrip_code << 24)); + + /* Set interrupt level */ + writel(rising_value, ®->threshold_temp_rise); + writel(cooling_temp, ®->threshold_temp_fall); + + /* + * Need to init all register settings after getting parameter info + * [28:23] vref [11:8] slope - Tuning parameter + * + * WARNING: this slope value writes into many bits in the tmu_control + * register, with the default FDT value of 268470274 (0x10008802) + * we are using this essentially sets the default register setting + * from the TRM for tmu_control. + * TODO(bhthompson): rewrite this code such that we are not performing + * a hard wipe of tmu_control and re verify functionality. + */ + writel(data->slope, ®->tmu_control); + + writel(INTCLEARALL, ®->intclear); + /* TMU core enable */ + con = readl(®->tmu_control); + con |= (info->tmu_mux << 20) | THERM_TRIP_EN | CORE_EN; + + writel(con, ®->tmu_control); + + /* Enable HW thermal trip */ + power_enable_hw_thermal_trip(); + + /* LEV1 LEV2 interrupt enable */ + writel(INTEN_RISE1 | INTEN_RISE2, ®->inten); +} + +/* + * Initialize TMU device + * + * @return int value, 0 for success + */ +int tmu_init(struct tmu_info *info) +{ + info->tmu_state = TMU_STATUS_INIT; + + tmu_setup_parameters(info); + info->tmu_state = TMU_STATUS_NORMAL; + + return 0; +} diff --git a/src/soc/samsung/exynos5420/trustzone.c b/src/soc/samsung/exynos5420/trustzone.c new file mode 100644 index 0000000000..983690dbef --- /dev/null +++ b/src/soc/samsung/exynos5420/trustzone.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +/* Setting TZPC[TrustZone Protection Controller] + * We pretty much disable it all, as the kernel + * expects it that way -- and that's not the default. + */ +void trustzone_init(void) +{ + struct exynos_tzpc *tzpc; + unsigned int addr; + + for (addr = TZPC10_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) { + tzpc = (struct exynos_tzpc *)addr; + if (addr == TZPC0_BASE) + writel(R0SIZE, &tzpc->r0size); + writel(DECPROTXSET, &tzpc->decprot0set); + writel(DECPROTXSET, &tzpc->decprot1set); + writel(DECPROTXSET, &tzpc->decprot2set); + writel(DECPROTXSET, &tzpc->decprot3set); + } +} diff --git a/src/soc/samsung/exynos5420/uart.c b/src/soc/samsung/exynos5420/uart.c new file mode 100644 index 0000000000..ea642f71a8 --- /dev/null +++ b/src/soc/samsung/exynos5420/uart.c @@ -0,0 +1,199 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include /* for __console definition */ +#include +#include +#include +#include +#include +#include + +#define RX_FIFO_COUNT_MASK 0xff +#define RX_FIFO_FULL_MASK (1 << 8) +#define TX_FIFO_FULL_MASK (1 << 24) + +/* FIXME(dhendrix): exynos5 has 4 UARTs and its functions in u-boot take a + base_port argument. However console_driver functions do not. */ +static uint32_t base_port = CONFIG_CONSOLE_SERIAL_UART_ADDRESS; + +/* + * The coefficient, used to calculate the baudrate on S5P UARTs is + * calculated as + * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT + * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1, + * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants: + */ +static const int udivslot[] = { + 0, + 0x0080, + 0x0808, + 0x0888, + 0x2222, + 0x4924, + 0x4a52, + 0x54aa, + 0x5555, + 0xd555, + 0xd5d5, + 0xddd5, + 0xdddd, + 0xdfdd, + 0xdfdf, + 0xffdf, +}; + +static void serial_setbrg_dev(void) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + u32 uclk; + u32 baudrate = CONFIG_TTYS0_BAUD; + u32 val; + + // All UARTs share the same clock. + uclk = clock_get_periph_rate(PERIPH_ID_UART3); + val = uclk / baudrate; + + writel(val / 16 - 1, &uart->ubrdiv); + + /* + * FIXME(dhendrix): the original uart.h had a "br_rest" value which + * does not seem relevant to the exynos5420... not entirely sure + * where/if we need to worry about it here + */ +#if 0 + if (s5p_uart_divslot()) + writel(udivslot[val % 16], &uart->rest.slot); + else + writeb(val % 16, &uart->rest.value); +#endif +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +static void exynos5_init_dev(void) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + + /* enable FIFOs */ + writel(0x1, &uart->ufcon); + writel(0, &uart->umcon); + /* 8N1 */ + writel(0x3, &uart->ulcon); + /* No interrupts, no DMA, pure polling */ + writel(0x245, &uart->ucon); + + serial_setbrg_dev(); +} + +static int exynos5_uart_err_check(int op) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + unsigned int mask; + + /* + * UERSTAT + * Break Detect [3] + * Frame Err [2] : receive operation + * Parity Err [1] : receive operation + * Overrun Err [0] : receive operation + */ + if (op) + mask = 0x8; + else + mask = 0xf; + + return readl(&uart->uerstat) & mask; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +static unsigned char exynos5_uart_rx_byte(void) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + + /* wait for character to arrive */ + while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | + RX_FIFO_FULL_MASK))) { + if (exynos5_uart_err_check(0)) + return 0; + } + + return readb(&uart->urxh) & 0xff; +} + +/* + * Output a single byte to the serial port. + */ +static void exynos5_uart_tx_byte(unsigned char data) +{ + struct s5p_uart *uart = (struct s5p_uart *)base_port; + + /* wait for room in the tx FIFO */ + while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { + if (exynos5_uart_err_check(1)) + return; + } + + writeb(data, &uart->utxh); +} + +#if !defined(__PRE_RAM__) + +static const struct console_driver exynos5_uart_console __console = { + .init = exynos5_init_dev, + .tx_byte = exynos5_uart_tx_byte, +// .tx_flush = exynos5_uart_tx_flush, + .rx_byte = exynos5_uart_rx_byte, +// .tst_byte = exynos5_uart_tst_byte, +}; + +uint32_t uartmem_getbaseaddr(void) +{ + return base_port; +} + +#else + +void uart_init(void) +{ + exynos5_init_dev(); +} + +unsigned char uart_rx_byte(void) +{ + return exynos5_uart_rx_byte(); +} + +void uart_tx_byte(unsigned char data) +{ + exynos5_uart_tx_byte(data); +} + +void uart_tx_flush(void) +{ +} + +#endif diff --git a/src/soc/samsung/exynos5420/usb.c b/src/soc/samsung/exynos5420/usb.c new file mode 100644 index 0000000000..0df63e2666 --- /dev/null +++ b/src/soc/samsung/exynos5420/usb.c @@ -0,0 +1,217 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Samsung Electronics + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void reset_dwc3(struct exynos5_usb_drd_dwc3 *dwc3) +{ + setbits_le32(&dwc3->ctl, 0x1 << 11); /* core soft reset */ + setbits_le32(&dwc3->usb3pipectl, 0x1 << 31); /* PHY soft reset */ + setbits_le32(&dwc3->usb2phycfg, 0x1 << 31); /* PHY soft reset */ +} + +void reset_usb_drd0_dwc3() +{ + printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD0\n"); + reset_dwc3(exynos_usb_drd0_dwc3); +} + +void reset_usb_drd1_dwc3() +{ + printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD1\n"); + reset_dwc3(exynos_usb_drd1_dwc3); +} + +static void setup_dwc3(struct exynos5_usb_drd_dwc3 *dwc3) +{ + if (!(dwc3->ctl & 0x1 << 11) || + !(dwc3->usb3pipectl & 0x1 << 31) || + !(dwc3->usb2phycfg & 0x1 << 31)) { + printk(BIOS_ERR, "DWC3 at %p not in reset (you need to call " + "reset_usb_drdX_dwc3() first)!\n", dwc3); + } + + /* Set relevant registers to default values (clearing all reset bits) */ + + writel(0x1 << 24 | /* activate PHY low power states */ + 0x4 << 19 | /* low power delay value */ + 0x1 << 18 | /* activate PHY low power delay */ + 0x1 << 17 | /* enable SuperSpeed PHY suspend */ + 0x1 << 1 | /* default Tx deemphasis value */ + 0, &dwc3->usb3pipectl); + + /* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */ + writel(0x9 << 10 | /* PHY clock turnaround for 8-bit UTMI+ */ + 0x1 << 8 | /* enable PHY sleep in L1 */ + 0x1 << 6 | /* enable PHY suspend */ + 0, &dwc3->usb2phycfg); + + writel(0x5dc << 19 | /* suspend clock scale for 24MHz */ + 0x1 << 16 | /* retry SS three times (bugfix from U-Boot) */ + 0x1 << 12 | /* port capability HOST */ + 0, &dwc3->ctl); +} + +void setup_usb_drd0_dwc3() +{ + setup_dwc3(exynos_usb_drd0_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB DRD0 finished\n"); +} + +void setup_usb_drd1_dwc3() +{ + setup_dwc3(exynos_usb_drd1_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB DRD1 finished\n"); +} + +static void setup_drd_phy(struct exynos5_usb_drd_phy *phy) +{ + /* Set all PHY registers to default values */ + + /* XHCI Version 1.0, Frame Length adjustment 30 MHz */ + setbits_le32(&phy->linksystem, 0x1 << 27 | 0x20 << 1); + + /* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */ + writel(1 << 6, &phy->utmi); + + writel(0x88 << 23 | /* spread spectrum refclk selector */ + 0x1 << 20 | /* enable spread spectrum */ + 0x1 << 19 | /* enable prescaler refclk */ + 0x68 << 11 | /* multiplier for 24MHz refclk */ + 0x5 << 5 | /* select 24MHz refclk (weird, from U-Boot) */ + 0x1 << 4 | /* power supply in normal operating mode */ + 0x3 << 2 | /* use external refclk (undocumented on 5420?)*/ + 0x1 << 1 | /* force port reset */ + 0x1 << 0 | /* normal operating mode */ + 0, &phy->clkrst); + + writel(0x9 << 26 | /* LOS level */ + 0x3 << 22 | /* TX VREF tune */ + 0x1 << 20 | /* TX rise tune */ + 0x1 << 18 | /* TX res tune */ + 0x3 << 13 | /* TX HS X Vtune */ + 0x3 << 9 | /* TX FS/LS tune */ + 0x3 << 6 | /* SQRX tune */ + 0x4 << 3 | /* OTG tune */ + 0x4 << 0 | /* comp disc tune */ + 0, &phy->param0); + + writel(0x7f << 19 | /* reserved */ + 0x7f << 12 | /* Tx launch amplitude */ + 0x20 << 6 | /* Tx deemphasis 6dB */ + 0x1c << 0 | /* Tx deemphasis 3.5dB (value from U-Boot) */ + 0, &phy->param1); + + /* disable all test features */ + writel(0, &phy->test); + + /* UTMI clock select? ("must be 0x1") */ + writel(0x1 << 2, &phy->utmiclksel); + + /* Samsung magic, undocumented (from U-Boot) */ + writel(0x0, &phy->resume); + + udelay(10); + clrbits_le32(&phy->clkrst, 0x1 << 1); /* deassert port reset */ +} + +void setup_usb_drd0_phy() +{ + printk(BIOS_DEBUG, "Powering up USB DRD0 PHY\n"); + setbits_le32(&exynos_power->usb_drd0_phy_ctrl, POWER_USB_PHY_CTRL_EN); + setup_drd_phy(exynos_usb_drd0_phy); +} + +void setup_usb_drd1_phy() +{ + printk(BIOS_DEBUG, "Powering up USB DRD1 PHY\n"); + setbits_le32(&exynos_power->usb_drd1_phy_ctrl, POWER_USB_PHY_CTRL_EN); + setup_drd_phy(exynos_usb_drd1_phy); +} + +void setup_usb_host_phy(int hsic_gpio) +{ + unsigned int hostphy_ctrl0; + + setbits_le32(&exynos_sysreg->usb20_phy_cfg, USB20_PHY_CFG_EN); + setbits_le32(&exynos_power->usb_host_phy_ctrl, POWER_USB_PHY_CTRL_EN); + + printk(BIOS_DEBUG, "Powering up USB HOST PHY (%s HSIC)\n", + hsic_gpio ? "with" : "without"); + + hostphy_ctrl0 = readl(&exynos_usb_host_phy->usbphyctrl0); + hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK | + HOST_CTRL0_COMMONON_N | + /* HOST Phy setting */ + HOST_CTRL0_PHYSWRST | + HOST_CTRL0_PHYSWRSTALL | + HOST_CTRL0_SIDDQ | + HOST_CTRL0_FORCESUSPEND | + HOST_CTRL0_FORCESLEEP); + hostphy_ctrl0 |= (/* Setting up the ref freq */ + CLK_24MHZ << 16 | + /* HOST Phy setting */ + HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST); + writel(hostphy_ctrl0, &exynos_usb_host_phy->usbphyctrl0); + udelay(10); + clrbits_le32(&exynos_usb_host_phy->usbphyctrl0, + HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST); + udelay(20); + + /* EHCI Ctrl setting */ + setbits_le32(&exynos_usb_host_phy->ehcictrl, + EHCICTRL_ENAINCRXALIGN | + EHCICTRL_ENAINCR4 | + EHCICTRL_ENAINCR8 | + EHCICTRL_ENAINCR16); + + /* HSIC USB Hub initialization. */ + if (hsic_gpio) { + gpio_direction_output(hsic_gpio, 0); + udelay(100); + gpio_direction_output(hsic_gpio, 1); + udelay(5000); + + clrbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_SIDDQ | + HOST_CTRL0_FORCESLEEP | + HOST_CTRL0_FORCESUSPEND); + setbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_PHYSWRST); + udelay(10); + clrbits_le32(&exynos_usb_host_phy->hsicphyctrl1, + HOST_CTRL0_PHYSWRST); + } + + /* At this point we need to wait for 50ms before talking to + * the USB controller (PHY clock and power setup time) + * By the time we are actually in the payload, these 50ms + * will have passed. + */ +} diff --git a/src/soc/samsung/exynos5420/wakeup.c b/src/soc/samsung/exynos5420/wakeup.c new file mode 100644 index 0000000000..cf9a46bc16 --- /dev/null +++ b/src/soc/samsung/exynos5420/wakeup.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +void wakeup(void) +{ + if (wakeup_need_reset()) + power_reset(); + + power_init(); /* Ensure ps_hold_setup() for early wakeup. */ + dcache_mmu_disable(); + power_exit_wakeup(); + /* Should never return. If we do, reset. */ + power_reset(); +} + +int get_wakeup_state(void) +{ + uint32_t status = power_read_reset_status(); + + /* DIDLE/LPA can be resumed without clock reset (ex, bootblock), + * and SLEEP requires resetting clock (should be done in ROM stage). + */ + + if (status == S5P_CHECK_DIDLE || status == S5P_CHECK_LPA) + return WAKEUP_DIRECT; + + if (status == S5P_CHECK_SLEEP) + return WAKEUP_NEED_CLOCK_RESET; + + return IS_NOT_WAKEUP; +} + +void wakeup_enable_uart(void) +{ + power_release_uart_retention(); +} diff --git a/src/southbridge/amd/agesa/hudson/lpc.c b/src/southbridge/amd/agesa/hudson/lpc.c index 3af3eb8ede..4a504cd5b8 100644 --- a/src/southbridge/amd/agesa/hudson/lpc.c +++ b/src/southbridge/amd/agesa/hudson/lpc.c @@ -68,14 +68,14 @@ static void lpc_init(device_t dev) byte |= 1 << 0 | 1 << 3; pci_write_config8(dev, 0xBB, byte); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); /* Initialize the real time clock. - * The 0 argument tells rtc_init not to + * The 0 argument tells cmos_init not to * update CMOS unless it is invalid. - * 1 tells rtc_init to always initialize the CMOS. + * 1 tells cmos_init to always initialize the CMOS. */ - rtc_init(0); + cmos_init(0); } static void hudson_lpc_read_resources(device_t dev) diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c index 1a63ce2b15..0f331645bb 100644 --- a/src/southbridge/amd/agesa/hudson/spi.c +++ b/src/southbridge/amd/agesa/hudson/spi.c @@ -56,18 +56,15 @@ void spi_init() } int spi_xfer(struct spi_slave *slave, const void *dout, - unsigned int bitsout, void *din, unsigned int bitsin) + unsigned int bytesout, void *din, unsigned int bytesin) { /* First byte is cmd which can not being sent through FIFO. */ u8 cmd = *(u8 *)dout++; u8 readoffby1; u8 readwrite; - u8 bytesout, bytesin; u8 count; - bitsout -= 8; - bytesout = bitsout / 8; - bytesin = bitsin / 8; + bytesout--; readoffby1 = bytesout ? 0 : 1; @@ -124,16 +121,7 @@ void spi_release_bus(struct spi_slave *slave) #endif } -void spi_cs_activate(struct spi_slave *slave) -{ -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { struct spi_slave *slave = malloc(sizeof(*slave)); diff --git a/src/southbridge/amd/amd8111/lpc.c b/src/southbridge/amd/amd8111/lpc.c index e9bd5fc42b..da9b4f817a 100644 --- a/src/southbridge/amd/amd8111/lpc.c +++ b/src/southbridge/amd/amd8111/lpc.c @@ -71,7 +71,7 @@ static void lpc_init(struct device *dev) } /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/amd/cimx/sb700/late.c b/src/southbridge/amd/cimx/sb700/late.c index ede9fb3a01..7b9cf61ad1 100644 --- a/src/southbridge/amd/cimx/sb700/late.c +++ b/src/southbridge/amd/cimx/sb700/late.c @@ -77,14 +77,14 @@ static void lpc_init(device_t dev) { printk(BIOS_DEBUG, "SB700 - Late.c - lpc_init - Start.\n"); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); /* Initialize the real time clock. - * The 0 argument tells rtc_init not to + * The 0 argument tells cmos_init not to * update CMOS unless it is invalid. - * 1 tells rtc_init to always initialize the CMOS. + * 1 tells cmos_init to always initialize the CMOS. */ - rtc_init(0); + cmos_init(0); printk(BIOS_DEBUG, "SB700 - Late.c - lpc_init - End.\n"); } diff --git a/src/southbridge/amd/cimx/sb800/acpi/audio.asl b/src/southbridge/amd/cimx/sb800/acpi/audio.asl new file mode 100644 index 0000000000..a7807524e4 --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/audio.asl @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device(AZHD) { + Name(_ADR, 0x00140002) + OperationRegion(AZPD, PCI_Config, 0x00, 0x100) + Field(AZPD, AnyAcc, NoLock, Preserve) { + offset (0x42), + NSDI, 1, + NSDO, 1, + NSEN, 1, + offset (0x44), + IPCR, 4, + offset (0x54), + PWST, 2, + , 6, + PMEB, 1, + , 6, + PMST, 1, + offset (0x62), + MMCR, 1, + offset (0x64), + MMLA, 32, + offset (0x68), + MMHA, 32, + offset (0x6C), + MMDT, 16, + } +} /* end AZHD */ diff --git a/src/southbridge/amd/cimx/sb800/acpi/fch.asl b/src/southbridge/amd/cimx/sb800/acpi/fch.asl new file mode 100644 index 0000000000..1e9ca640ca --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/fch.asl @@ -0,0 +1,380 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* South Bridge */ +/* _SB.PCI0 */ + +/* Operating System Capabilities Method */ +Method(_OSC,4) +{ + // Create DWord-addressable fields from the Capabilities Buffer + CreateDWordField(Arg3,0,CDW1) + CreateDWordField(Arg3,4,CDW2) + CreateDWordField(Arg3,8,CDW3) + + /* Check for proper PCI/PCIe UUID */ + If(LEqual(Arg0,ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) + { + /* Let OS control everything */ + Return (Arg3) + } Else { + Or(CDW1,4,CDW1) // Unrecognized UUID + Return(Arg3) + } +} + +Method(_BBN, 0) { /* Bus number = 0 */ + Return(0) +} +Method(_STA, 0) { + /* DBGO("\\_SB\\PCI0\\_STA\n") */ + Return(0x0B) /* Status is visible */ +} + +Method(_PRT,0) { + If(PMOD){ Return(APR0) } /* APIC mode */ + Return (PR0) /* PIC Mode */ +} /* end _PRT */ + +/* Describe the Southbridge devices */ + +#include "pcie.asl" + +/* PCI slot 1, 2, 3 */ +Device(PIBR) { + Name(_ADR, 0x00140004) + Name(_PRW, Package() {0x18, 4}) + + Method(_PRT, 0) { + Return (PCIB) + } +} + +Device(STCR) { + Name(_ADR, 0x00110000) + #include "acpi/sata.asl" +} /* end STCR */ + +#include "usb.asl" + +Device(SBUS) { + Name(_ADR, 0x00140000) +} /* end SBUS */ + +/* Primary (and only) IDE channel */ +Device(IDEC) { + Name(_ADR, 0x00140001) + #include "acpi/ide.asl" +} /* end IDEC */ + +#include "audio.asl" + +#include "lpc.asl" + +Device(HPBR) { + Name(_ADR, 0x00140004) +} /* end HostPciBr */ + +Device(ACAD) { + Name(_ADR, 0x00140005) +} /* end Ac97audio */ + +Device(ACMD) { + Name(_ADR, 0x00140006) +} /* end Ac97modem */ + +Name(CRES, ResourceTemplate() { + /* Set the Bus number and Secondary Bus number for the PCI0 device + * The Secondary bus range for PCI0 lets the system + * know what bus values are allowed on the downstream + * side of this PCI bus if there is a PCI-PCI bridge. + * PCI busses can have 256 secondary busses which + * range from [0-0xFF] but they do not need to be + * sequential. + */ + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, /* address granularity */ + 0x0000, /* range minimum */ + 0x00FF, /* range maximum */ + 0x0000, /* translation */ + 0x0100, /* length */ + ,, PSB0) /* ResourceSourceIndex, ResourceSource, DescriptorName */ + + IO(Decode16, 0x0CF8, 0x0CF8, 1, 8) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0000, /* range minimum */ + 0x0CF7, /* range maximum */ + 0x0000, /* translation */ + 0x0CF8 /* length */ + ) + + WORDIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, /* address granularity */ + 0x0D00, /* range minimum */ + 0xFFFF, /* range maximum */ + 0x0000, /* translation */ + 0xF300 /* length */ + ) + + Memory32Fixed(READONLY, 0x000A0000, 0x00020000, VGAM) /* VGA memory space */ + + /* memory space for PCI BARs below 4GB */ + Memory32Fixed(ReadOnly, 0x00000000, 0x00000000, MMIO) +}) /* End Name(_SB.PCI0.CRES) */ + +Method(_CRS, 0) { + /* DBGO("\\_SB\\PCI0\\_CRS\n") */ + CreateDWordField(CRES, ^MMIO._BAS, MM1B) + CreateDWordField(CRES, ^MMIO._LEN, MM1L) + + /* + * Declare memory between TOM1 and 4GB as available + * for PCI MMIO. + * Use ShiftLeft to avoid 64bit constant (for XP). + * This will work even if the OS does 32bit arithmetic, as + * 32bit (0x00000000 - TOM1) will wrap and give the same + * result as 64bit (0x100000000 - TOM1). + */ + Store(TOM1, MM1B) + ShiftLeft(0x10000000, 4, Local0) + Subtract(Local0, TOM1, Local0) + Store(Local0, MM1L) + + Return(CRES) /* note to change the Name buffer */ +} /* end of Method(_SB.PCI0._CRS) */ + +/* +* +* FIRST METHOD CALLED UPON BOOT +* +* 1. If debugging, print current OS and ACPI interpreter. +* 2. Get PCI Interrupt routing from ACPI VSM, this +* value is based on user choice in BIOS setup. +*/ +Method(_INI, 0) { + /* DBGO("\\_SB\\_INI\n") */ + /* DBGO(" DSDT.ASL code from ") */ + /* DBGO(__DATE__) */ + /* DBGO(" ") */ + /* DBGO(__TIME__) */ + /* DBGO("\n Sleep states supported: ") */ + /* DBGO("\n") */ + /* DBGO(" \\_OS=") */ + /* DBGO(\_OS) */ + /* DBGO("\n \\_REV=") */ + /* DBGO(\_REV) */ + /* DBGO("\n") */ + + /* Determine the OS we're running on */ + CkOT() + + /* On older chips, clear PciExpWakeDisEn */ + /*if (LLessEqual(\SBRI, 0x13)) { + * Store(0,\PWDE) + * } + */ +} /* End Method(_SB._INI) */ + +Scope(\){ + /* Client Management index/data registers */ + OperationRegion(CMT, SystemIO, 0x00000C50, 0x00000002) + Field(CMT, ByteAcc, NoLock, Preserve) { + CMTI, 8, + /* Client Management Data register */ + G64E, 1, + G64O, 1, + G32O, 2, + , 2, + GPSL, 2, + } + + /* GPM Port register */ + OperationRegion(GPT, SystemIO, 0x00000C52, 0x00000001) + Field(GPT, ByteAcc, NoLock, Preserve) { + GPB0,1, + GPB1,1, + GPB2,1, + GPB3,1, + GPB4,1, + GPB5,1, + GPB6,1, + GPB7,1, + } + + /* Flash ROM program enable register */ + OperationRegion(FRE, SystemIO, 0x00000C6F, 0x00000001) + Field(FRE, ByteAcc, NoLock, Preserve) { + , 0x00000006, + FLRE, 0x00000001, + } + + /* PM2 index/data registers */ + OperationRegion(PM2R, SystemIO, 0x00000CD0, 0x00000002) + Field(PM2R, ByteAcc, NoLock, Preserve) { + PM2I, 0x00000008, + PM2D, 0x00000008, + } + + /* Power Management I/O registers, TODO:PMIO is quite different in SB800. */ + OperationRegion(PIOR, SystemIO, 0x00000CD6, 0x00000002) + Field(PIOR, ByteAcc, NoLock, Preserve) { + PIOI, 0x00000008, + PIOD, 0x00000008, + } + IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) { + Offset(0x00), /* MiscControl */ + , 1, + T1EE, 1, + T2EE, 1, + Offset(0x01), /* MiscStatus */ + , 1, + T1E, 1, + T2E, 1, + Offset(0x04), /* SmiWakeUpEventEnable3 */ + , 7, + SSEN, 1, + Offset(0x07), /* SmiWakeUpEventStatus3 */ + , 7, + CSSM, 1, + Offset(0x10), /* AcpiEnable */ + , 6, + PWDE, 1, + Offset(0x1C), /* ProgramIoEnable */ + , 3, + MKME, 1, + IO3E, 1, + IO2E, 1, + IO1E, 1, + IO0E, 1, + Offset(0x1D), /* IOMonitorStatus */ + , 3, + MKMS, 1, + IO3S, 1, + IO2S, 1, + IO1S, 1, + IO0S,1, + Offset(0x20), /* AcpiPmEvtBlk. TODO: should be 0x60 */ + APEB, 16, + Offset(0x36), /* GEvtLevelConfig */ + , 6, + ELC6, 1, + ELC7, 1, + Offset(0x37), /* GPMLevelConfig0 */ + , 3, + PLC0, 1, + PLC1, 1, + PLC2, 1, + PLC3, 1, + PLC8, 1, + Offset(0x38), /* GPMLevelConfig1 */ + , 1, + PLC4, 1, + PLC5, 1, + , 1, + PLC6, 1, + PLC7, 1, + Offset(0x3B), /* PMEStatus1 */ + GP0S, 1, + GM4S, 1, + GM5S, 1, + APS, 1, + GM6S, 1, + GM7S, 1, + GP2S, 1, + STSS, 1, + Offset(0x55), /* SoftPciRst */ + SPRE, 1, + , 1, + , 1, + PNAT, 1, + PWMK, 1, + PWNS, 1, + + /* Offset(0x61), */ /* Options_1 */ + /* ,7, */ + /* R617,1, */ + + Offset(0x65), /* UsbPMControl */ + , 4, + URRE, 1, + Offset(0x68), /* MiscEnable68 */ + , 3, + TMTE, 1, + , 1, + Offset(0x92), /* GEVENTIN */ + , 7, + E7IS, 1, + Offset(0x96), /* GPM98IN */ + G8IS, 1, + G9IS, 1, + Offset(0x9A), /* EnhanceControl */ + ,7, + HPDE, 1, + Offset(0xA8), /* PIO7654Enable */ + IO4E, 1, + IO5E, 1, + IO6E, 1, + IO7E, 1, + Offset(0xA9), /* PIO7654Status */ + IO4S, 1, + IO5S, 1, + IO6S, 1, + IO7S, 1, + } + + /* PM1 Event Block + * First word is PM1_Status, Second word is PM1_Enable + */ + OperationRegion(P1EB, SystemIO, APEB, 0x04) + Field(P1EB, ByteAcc, NoLock, Preserve) { + TMST, 1, + , 3, + BMST, 1, + GBST, 1, + Offset(0x01), + PBST, 1, + , 1, + RTST, 1, + , 3, + PWST, 1, + SPWS, 1, + Offset(0x02), + TMEN, 1, + , 4, + GBEN, 1, + Offset(0x03), + PBEN, 1, + , 1, + RTEN, 1, + , 3, + PWDA, 1, + } +} + +Scope(\_SB) { + Device(PWRB) { /* Start Power button device */ + Name(_HID, EISAID("PNP0C0C")) + Name(_UID, 0xAA) + Name(_PRW, Package () {3, 0x04}) /* wake from S1-S4 */ + Name(_STA, 0x0B) /* sata is invisible */ + } +} /* End Scope(_SB) */ + diff --git a/src/southbridge/amd/cimx/sb800/acpi/lpc.asl b/src/southbridge/amd/cimx/sb800/acpi/lpc.asl new file mode 100644 index 0000000000..62eb9037bb --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/lpc.asl @@ -0,0 +1,85 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Device(LIBR) { + Name(_ADR, 0x00140003) + /* Method(_INI) { + * DBGO("\\_SB\\PCI0\\LpcIsaBr\\_INI\n") + } */ /* End Method(_SB.SBRDG._INI) */ + + /* Real Time Clock Device */ + Device(RTC0) { + Name(_HID, EISAID("PNP0B00")) /* AT Real Time Clock (not PIIX4 compatible) */ + Name(_CRS, ResourceTemplate() { + IRQNoFlags(){8} + IO(Decode16,0x0070, 0x0070, 0, 2) + /* IO(Decode16,0x0070, 0x0070, 0, 4) */ + }) + } /* End Device(_SB.PCI0.LpcIsaBr.RTC0) */ + + Device(TMR) { /* Timer */ + Name(_HID,EISAID("PNP0100")) /* System Timer */ + Name(_CRS, ResourceTemplate() { + IRQNoFlags(){0} + IO(Decode16, 0x0040, 0x0040, 0, 4) + /* IO(Decode16, 0x0048, 0x0048, 0, 4) */ + }) + } /* End Device(_SB.PCI0.LpcIsaBr.TMR) */ + + Device(SPKR) { /* Speaker */ + Name(_HID,EISAID("PNP0800")) /* AT style speaker */ + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x0061, 0x0061, 0, 1) + }) + } /* End Device(_SB.PCI0.LpcIsaBr.SPKR) */ + + Device(PIC) { + Name(_HID,EISAID("PNP0000")) /* AT Interrupt Controller */ + Name(_CRS, ResourceTemplate() { + IRQNoFlags(){2} + IO(Decode16,0x0020, 0x0020, 0, 2) + IO(Decode16,0x00A0, 0x00A0, 0, 2) + /* IO(Decode16, 0x00D0, 0x00D0, 0x10, 0x02) */ + /* IO(Decode16, 0x04D0, 0x04D0, 0x10, 0x02) */ + }) + } /* End Device(_SB.PCI0.LpcIsaBr.PIC) */ + + Device(MAD) { /* 8257 DMA */ + Name(_HID,EISAID("PNP0200")) /* Hardware Device ID */ + Name(_CRS, ResourceTemplate() { + DMA(Compatibility,BusMaster,Transfer8){4} + IO(Decode16, 0x0000, 0x0000, 0x10, 0x10) + IO(Decode16, 0x0081, 0x0081, 0x01, 0x03) + IO(Decode16, 0x0087, 0x0087, 0x01, 0x01) + IO(Decode16, 0x0089, 0x0089, 0x01, 0x03) + IO(Decode16, 0x008F, 0x008F, 0x01, 0x01) + IO(Decode16, 0x00C0, 0x00C0, 0x10, 0x20) + }) /* End Name(_SB.PCI0.LpcIsaBr.MAD._CRS) */ + } /* End Device(_SB.PCI0.LpcIsaBr.MAD) */ + + Device(COPR) { + Name(_HID,EISAID("PNP0C04")) /* Math Coprocessor */ + Name(_CRS, ResourceTemplate() { + IO(Decode16, 0x00F0, 0x00F0, 0, 0x10) + IRQNoFlags(){13} + }) + } /* End Device(_SB.PCI0.LpcIsaBr.COPR) */ + #include "acpi/superio.asl" +} /* end LIBR */ + diff --git a/src/southbridge/amd/cimx/sb800/acpi/pcie.asl b/src/southbridge/amd/cimx/sb800/acpi/pcie.asl new file mode 100644 index 0000000000..435bcb5824 --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/pcie.asl @@ -0,0 +1,521 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Scope(\) { + /* PCI IRQ mapping registers, C00h-C01h. */ + OperationRegion(PRQM, SystemIO, 0x00000C00, 0x00000002) + Field(PRQM, ByteAcc, NoLock, Preserve) { + PRQI, 0x00000008, + PRQD, 0x00000008, /* Offset: 1h */ + } + IndexField(PRQI, PRQD, ByteAcc, NoLock, Preserve) { + PIRA, 0x00000008, /* Index 0 */ + PIRB, 0x00000008, /* Index 1 */ + PIRC, 0x00000008, /* Index 2 */ + PIRD, 0x00000008, /* Index 3 */ + PIRE, 0x00000008, /* Index 4 */ + PIRF, 0x00000008, /* Index 5 */ + PIRG, 0x00000008, /* Index 6 */ + PIRH, 0x00000008, /* Index 7 */ + } + + /* PCI Error control register */ + OperationRegion(PERC, SystemIO, 0x00000C14, 0x00000001) + Field(PERC, ByteAcc, NoLock, Preserve) { + SENS, 0x00000001, + PENS, 0x00000001, + SENE, 0x00000001, + PENE, 0x00000001, + } +} + +Scope(\_SB) { + /* PCIe Configuration Space for 16 busses */ + OperationRegion(PCFG, SystemMemory, PCBA, 0x01000000) /* Each bus consumes 1MB */ + Field(PCFG, ByteAcc, NoLock, Preserve) { + /* Byte offsets are computed using the following technique: + * ((bus number + 1) * ((device number * 8) * 4096)) + register offset + * The 8 comes from 8 functions per device, and 4096 bytes per function config space + */ + Offset(0x00088024), /* SATA reg 24h Bus 0, Device 17, Function 0 */ + STB5, 32, + Offset(0x00098042), /* OHCI0 reg 42h - Bus 0, Device 19, Function 0 */ + PT0D, 1, + PT1D, 1, + PT2D, 1, + PT3D, 1, + PT4D, 1, + PT5D, 1, + PT6D, 1, + PT7D, 1, + PT8D, 1, + PT9D, 1, + Offset(0x000A0004), /* SMBUS reg 4h - Bus 0, Device 20, Function 0 */ + SBIE, 1, + SBME, 1, + Offset(0x000A0008), /* SMBUS reg 8h - Bus 0, Device 20, Function 0 */ + SBRI, 8, + Offset(0x000A0014), /* SMBUS reg 14h - Bus 0, Device 20, Function 0 */ + SBB1, 32, + Offset(0x000A0078), /* SMBUS reg 78h - Bus 0, Device 20, Function 0 */ + ,14, + P92E, 1, /* Port92 decode enable */ + } + + OperationRegion(SB5, SystemMemory, STB5, 0x1000) + Field(SB5, AnyAcc, NoLock, Preserve){ + /* Port 0 */ + Offset(0x120), /* Port 0 Task file status */ + P0ER, 1, + , 2, + P0DQ, 1, + , 3, + P0BY, 1, + Offset(0x128), /* Port 0 Serial ATA status */ + P0DD, 4, + , 4, + P0IS, 4, + Offset(0x12C), /* Port 0 Serial ATA control */ + P0DI, 4, + Offset(0x130), /* Port 0 Serial ATA error */ + , 16, + P0PR, 1, + + /* Port 1 */ + offset(0x1A0), /* Port 1 Task file status */ + P1ER, 1, + , 2, + P1DQ, 1, + , 3, + P1BY, 1, + Offset(0x1A8), /* Port 1 Serial ATA status */ + P1DD, 4, + , 4, + P1IS, 4, + Offset(0x1AC), /* Port 1 Serial ATA control */ + P1DI, 4, + Offset(0x1B0), /* Port 1 Serial ATA error */ + , 16, + P1PR, 1, + + /* Port 2 */ + Offset(0x220), /* Port 2 Task file status */ + P2ER, 1, + , 2, + P2DQ, 1, + , 3, + P2BY, 1, + Offset(0x228), /* Port 2 Serial ATA status */ + P2DD, 4, + , 4, + P2IS, 4, + Offset(0x22C), /* Port 2 Serial ATA control */ + P2DI, 4, + Offset(0x230), /* Port 2 Serial ATA error */ + , 16, + P2PR, 1, + + /* Port 3 */ + Offset(0x2A0), /* Port 3 Task file status */ + P3ER, 1, + , 2, + P3DQ, 1, + , 3, + P3BY, 1, + Offset(0x2A8), /* Port 3 Serial ATA status */ + P3DD, 4, + , 4, + P3IS, 4, + Offset(0x2AC), /* Port 3 Serial ATA control */ + P3DI, 4, + Offset(0x2B0), /* Port 3 Serial ATA error */ + , 16, + P3PR, 1, + } + + Method(_PIC, 0x01, NotSerialized) + { + If (Arg0) + { + \_SB.CIRQ() + } + Store(Arg0, PMOD) + } + + Method(CIRQ, 0x00, NotSerialized){ + Store(0, PIRA) + Store(0, PIRB) + Store(0, PIRC) + Store(0, PIRD) + Store(0, PIRE) + Store(0, PIRF) + Store(0, PIRG) + Store(0, PIRH) + } + + Name(IRQB, ResourceTemplate(){ + IRQ(Level,ActiveLow,Shared){15} + }) + + Name(IRQP, ResourceTemplate(){ + IRQ(Level,ActiveLow,Exclusive){3, 4, 5, 7, 10, 11, 12, 15} + }) + + Name(PITF, ResourceTemplate(){ + IRQ(Level,ActiveLow,Exclusive){9} + }) + + Device(INTA) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 1) + + Method(_STA, 0) { + if (PIRA) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTA._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKA\\_DIS\n") */ + Store(0, PIRA) + } /* End Method(_SB.INTA._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKA\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTA._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKA\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRA, IRQN) + Return(IRQB) + } /* Method(_SB.INTA._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKA\\_SRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRA) + } /* End Method(_SB.INTA._SRS) */ + } /* End Device(INTA) */ + + Device(INTB) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 2) + + Method(_STA, 0) { + if (PIRB) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTB._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKB\\_DIS\n") */ + Store(0, PIRB) + } /* End Method(_SB.INTB._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKB\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTB._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKB\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRB, IRQN) + Return(IRQB) + } /* Method(_SB.INTB._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKB\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRB) + } /* End Method(_SB.INTB._SRS) */ + } /* End Device(INTB) */ + + Device(INTC) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 3) + + Method(_STA, 0) { + if (PIRC) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTC._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKC\\_DIS\n") */ + Store(0, PIRC) + } /* End Method(_SB.INTC._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKC\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTC._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKC\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRC, IRQN) + Return(IRQB) + } /* Method(_SB.INTC._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKC\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRC) + } /* End Method(_SB.INTC._SRS) */ + } /* End Device(INTC) */ + + Device(INTD) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 4) + + Method(_STA, 0) { + if (PIRD) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTD._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKD\\_DIS\n") */ + Store(0, PIRD) + } /* End Method(_SB.INTD._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKD\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTD._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKD\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRD, IRQN) + Return(IRQB) + } /* Method(_SB.INTD._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKD\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRD) + } /* End Method(_SB.INTD._SRS) */ + } /* End Device(INTD) */ + + Device(INTE) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 5) + + Method(_STA, 0) { + if (PIRE) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTE._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKE\\_DIS\n") */ + Store(0, PIRE) + } /* End Method(_SB.INTE._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKE\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTE._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKE\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRE, IRQN) + Return(IRQB) + } /* Method(_SB.INTE._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKE\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRE) + } /* End Method(_SB.INTE._SRS) */ + } /* End Device(INTE) */ + + Device(INTF) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 6) + + Method(_STA, 0) { + if (PIRF) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTF._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKF\\_DIS\n") */ + Store(0, PIRF) + } /* End Method(_SB.INTF._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKF\\_PRS\n") */ + Return(PITF) + } /* Method(_SB.INTF._PRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKF\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRF, IRQN) + Return(IRQB) + } /* Method(_SB.INTF._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKF\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRF) + } /* End Method(_SB.INTF._SRS) */ + } /* End Device(INTF) */ + + Device(INTG) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 7) + + Method(_STA, 0) { + if (PIRG) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTG._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKG\\_DIS\n") */ + Store(0, PIRG) + } /* End Method(_SB.INTG._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKG\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTG._CRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKG\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRG, IRQN) + Return(IRQB) + } /* Method(_SB.INTG._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKG\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRG) + } /* End Method(_SB.INTG._SRS) */ + } /* End Device(INTG) */ + + Device(INTH) { + Name(_HID, EISAID("PNP0C0F")) + Name(_UID, 8) + + Method(_STA, 0) { + if (PIRH) { + Return(0x0B) /* sata is invisible */ + } else { + Return(0x09) /* sata is disabled */ + } + } /* End Method(_SB.INTH._STA) */ + + Method(_DIS ,0) { + /* DBGO("\\_SB\\LNKH\\_DIS\n") */ + Store(0, PIRH) + } /* End Method(_SB.INTH._DIS) */ + + Method(_PRS ,0) { + /* DBGO("\\_SB\\LNKH\\_PRS\n") */ + Return(IRQP) + } /* Method(_SB.INTH._CRS) */ + + Method(_CRS ,0) { + /* DBGO("\\_SB\\LNKH\\_CRS\n") */ + CreateWordField(IRQB, 0x1, IRQN) + ShiftLeft(1, PIRH, IRQN) + Return(IRQB) + } /* Method(_SB.INTH._CRS) */ + + Method(_SRS, 1) { + /* DBGO("\\_SB\\LNKH\\_CRS\n") */ + CreateWordField(ARG0, 1, IRQM) + + /* Use lowest available IRQ */ + FindSetRightBit(IRQM, Local0) + if (Local0) { + Decrement(Local0) + } + Store(Local0, PIRH) + } /* End Method(_SB.INTH._SRS) */ + } /* End Device(INTH) */ + + } /* End Scope(_SB) */ + diff --git a/src/southbridge/amd/cimx/sb800/acpi/sleepstates.asl b/src/southbridge/amd/cimx/sb800/acpi/sleepstates.asl new file mode 100644 index 0000000000..889c49902c --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/sleepstates.asl @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Supported sleep states: */ +Name(\_S0, Package () {0x00, 0x00, 0x00, 0x00} ) /* (S0) - working state */ + +If (LAnd(SSFG, 0x01)) { + Name(\_S1, Package () {0x01, 0x01, 0x00, 0x00} ) /* (S1) - sleeping w/CPU context */ +} +If (LAnd(SSFG, 0x04)) { + Name(\_S3, Package () {0x03, 0x03, 0x00, 0x00} ) /* (S3) - Suspend to RAM */ +} +If (LAnd(SSFG, 0x08)) { + Name(\_S4, Package () {0x04, 0x04, 0x00, 0x00} ) /* (S4) - Suspend to Disk */ +} + +Name(\_S5, Package () {0x05, 0x05, 0x00, 0x00} ) /* (S5) - Soft Off */ + +Name(\_SB.CSPS ,0) /* Current Sleep State (S0, S1, S2, S3, S4, S5) */ +Name(CSMS, 0) /* Current System State */ diff --git a/src/southbridge/amd/cimx/sb800/acpi/smbus.asl b/src/southbridge/amd/cimx/sb800/acpi/smbus.asl new file mode 100644 index 0000000000..4055174ed7 --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/smbus.asl @@ -0,0 +1,114 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* SMBUS Support */ +Mutex (SBX0, 0x00) +OperationRegion (SMB0, SystemIO, 0xB00, 0x0C) + Field (SMB0, ByteAcc, NoLock, Preserve) { + HSTS, 8, /* SMBUS status */ + SSTS, 8, /* SMBUS slave status */ + HCNT, 8, /* SMBUS control */ + HCMD, 8, /* SMBUS host cmd */ + HADD, 8, /* SMBUS address */ + DAT0, 8, /* SMBUS data0 */ + DAT1, 8, /* SMBUS data1 */ + BLKD, 8, /* SMBUS block data */ + SCNT, 8, /* SMBUS slave control */ + SCMD, 8, /* SMBUS shadow cmd */ + SEVT, 8, /* SMBUS slave event */ + SDAT, 8 /* SMBUS slave data */ +} + +Method (WCLR, 0, NotSerialized) { /* clear SMBUS status register */ + Store (0x1E, HSTS) + Store (0xFA, Local0) + While (LAnd (LNotEqual (And (HSTS, 0x1E), Zero), LGreater (Local0, Zero))) { + Stall (0x64) + Decrement (Local0) + } + + Return (Local0) +} + +Method (SWTC, 1, NotSerialized) { + Store (Arg0, Local0) + Store (0x07, Local2) + Store (One, Local1) + While (LEqual (Local1, One)) { + Store (And (HSTS, 0x1E), Local3) + If (LNotEqual (Local3, Zero)) { /* read sucess */ + If (LEqual (Local3, 0x02)) { + Store (Zero, Local2) + } + + Store (Zero, Local1) + } + Else { + If (LLess (Local0, 0x0A)) { /* read failure */ + Store (0x10, Local2) + Store (Zero, Local1) + } + Else { + Sleep (0x0A) /* 10 ms, try again */ + Subtract (Local0, 0x0A, Local0) + } + } + } + + Return (Local2) +} + +Method (SMBR, 3, NotSerialized) { + Store (0x07, Local0) + If (LEqual (Acquire (SBX0, 0xFFFF), Zero)) { + Store (WCLR (), Local0) /* clear SMBUS status register before read data */ + If (LEqual (Local0, Zero)) { + Release (SBX0) + Return (0x0) + } + + Store (0x1F, HSTS) + Store (Or (ShiftLeft (Arg1, One), One), HADD) + Store (Arg2, HCMD) + If (LEqual (Arg0, 0x07)) { + Store (0x48, HCNT) /* read byte */ + } + + Store (SWTC (0x03E8), Local1) /* 1000 ms */ + If (LEqual (Local1, Zero)) { + If (LEqual (Arg0, 0x07)) { + Store (DAT0, Local0) + } + } + Else { + Store (Local1, Local0) + } + + Release (SBX0) + } + + /* DBGO("the value of SMBusData0 register ") */ + /* DBGO(Arg2) */ + /* DBGO(" is ") */ + /* DBGO(Local0) */ + /* DBGO("\n") */ + + Return (Local0) +} + diff --git a/src/southbridge/amd/cimx/sb800/acpi/usb.asl b/src/southbridge/amd/cimx/sb800/acpi/usb.asl new file mode 100644 index 0000000000..84f7cd279a --- /dev/null +++ b/src/southbridge/amd/cimx/sb800/acpi/usb.asl @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +Device(UOH1) { + Name(_ADR, 0x00120000) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH1 */ + +Device(UOH2) { + Name(_ADR, 0x00120002) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH2 */ + +Device(UOH3) { + Name(_ADR, 0x00130000) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH3 */ + +Device(UOH4) { + Name(_ADR, 0x00130002) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH4 */ + +Device(UOH5) { + Name(_ADR, 0x00160000) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH5 */ + +Device(UOH6) { + Name(_ADR, 0x00160002) + Name(_PRW, Package() {0x0B, 3}) +} /* end UOH5 */ + +Device(UEH1) { + Name(_ADR, 0x00140005) + Name(_PRW, Package() {0x0B, 3}) +} /* end UEH1 */ + diff --git a/src/southbridge/amd/cimx/sb800/cfg.c b/src/southbridge/amd/cimx/sb800/cfg.c index 90ad5a9f62..fe1f877481 100644 --- a/src/southbridge/amd/cimx/sb800/cfg.c +++ b/src/southbridge/amd/cimx/sb800/cfg.c @@ -51,6 +51,24 @@ void set_cbmem_toc(struct cbmem_entry *toc) } #endif +#if CONFIG_HAVE_ACPI_RESUME +unsigned long get_top_of_ram(void); +unsigned long get_top_of_ram(void) +{ + u32 xdata = 0; + int xnvram_pos = 0xf8, xi; + if (acpi_get_sleep_type() != 3) + return 0; + for (xi = 0; xi<4; xi++) { + outb(xnvram_pos, BIOSRAM_INDEX); + xdata &= ~(0xff << (xi * 8)); + xdata |= inb(BIOSRAM_DATA) << (xi *8); + xnvram_pos++; + } + return (unsigned long) xdata; +} +#endif + struct cbmem_entry *get_cbmem_toc(void) { u32 xdata = 0; diff --git a/src/southbridge/amd/cimx/sb800/late.c b/src/southbridge/amd/cimx/sb800/late.c index cfdf9f2a40..bf1c71f2cd 100644 --- a/src/southbridge/amd/cimx/sb800/late.c +++ b/src/southbridge/amd/cimx/sb800/late.c @@ -126,14 +126,14 @@ static void lpc_init(device_t dev) { printk(BIOS_DEBUG, "SB800 - Late.c - lpc_init - Start.\n"); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); /* Initialize the real time clock. - * The 0 argument tells rtc_init not to + * The 0 argument tells cmos_init not to * update CMOS unless it is invalid. - * 1 tells rtc_init to always initialize the CMOS. + * 1 tells cmos_init to always initialize the CMOS. */ - rtc_init(0); + cmos_init(0); printk(BIOS_DEBUG, "SB800 - Late.c - lpc_init - End.\n"); } diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c index d85a515fcc..d542d3e497 100644 --- a/src/southbridge/amd/cimx/sb800/spi.c +++ b/src/southbridge/amd/cimx/sb800/spi.c @@ -57,18 +57,15 @@ void spi_init() } int spi_xfer(struct spi_slave *slave, const void *dout, - unsigned int bitsout, void *din, unsigned int bitsin) + unsigned int bytesout, void *din, unsigned int bytesin) { /* First byte is cmd which can not being sent through FIFO. */ u8 cmd = *(u8 *)dout++; u8 readoffby1; u8 readwrite; - u8 bytesout, bytesin; u8 count; - bitsout -= 8; - bytesout = bitsout / 8; - bytesin = bitsin / 8; + bytesout--; readoffby1 = bytesout ? 0 : 1; @@ -156,16 +153,7 @@ void spi_release_bus(struct spi_slave *slave) #endif } -void spi_cs_activate(struct spi_slave *slave) -{ -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { struct spi_slave *slave = malloc(sizeof(*slave)); diff --git a/src/southbridge/amd/cimx/sb900/late.c b/src/southbridge/amd/cimx/sb900/late.c index 947e882fd9..1951ad5807 100644 --- a/src/southbridge/amd/cimx/sb900/late.c +++ b/src/southbridge/amd/cimx/sb900/late.c @@ -99,14 +99,14 @@ static void lpc_init(device_t dev) printk(BIOS_DEBUG, "SB900 - Late.c - lpc_init - Start.\n"); /* SB Configure HPET base and enable bit */ //- hpetInit(sb_config, &(sb_config->BuildParameters)); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); /* Initialize the real time clock. - * The 0 argument tells rtc_init not to + * The 0 argument tells cmos_init not to * update CMOS unless it is invalid. - * 1 tells rtc_init to always initialize the CMOS. + * 1 tells cmos_init to always initialize the CMOS. */ - rtc_init(0); + cmos_init(0); printk(BIOS_DEBUG, "SB900 - Late.c - lpc_init - End.\n"); } diff --git a/src/southbridge/amd/cs5535/cs5535.h b/src/southbridge/amd/cs5535/cs5535.h index 0db7c17551..0b435637ee 100644 --- a/src/southbridge/amd/cs5535/cs5535.h +++ b/src/southbridge/amd/cs5535/cs5535.h @@ -115,7 +115,7 @@ /* Flash Memory Mask values */ #define FLASH_MEM_4K 0xFFFFF000 -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) #if defined(__PRE_RAM__) void cs5535_disable_internal_uart(void); #else diff --git a/src/southbridge/amd/cs5536/cs5536.c b/src/southbridge/amd/cs5536/cs5536.c index bec0e89252..d13273d6d4 100644 --- a/src/southbridge/amd/cs5536/cs5536.c +++ b/src/southbridge/amd/cs5536/cs5536.c @@ -245,7 +245,7 @@ static void lpc_init(struct southbridge_amd_cs5536_config *sb) msr.lo = RTC_MONA; wrmsr(MDD_RTC_MONA_IND, msr); - rtc_init(0); + cmos_init(0); isa_dma_init(); } diff --git a/src/southbridge/amd/cs5536/cs5536.h b/src/southbridge/amd/cs5536/cs5536.h index 84738a212f..c193d9d500 100644 --- a/src/southbridge/amd/cs5536/cs5536.h +++ b/src/southbridge/amd/cs5536/cs5536.h @@ -442,7 +442,7 @@ #define FLASH_IO_128B 0x0000FF80 #define FLASH_IO_256B 0x0000FF00 -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) #if defined(__PRE_RAM__) void cs5536_setup_onchipuart(int uart); void cs5536_disable_internal_uart(void); diff --git a/src/southbridge/amd/sb600/lpc.c b/src/southbridge/amd/sb600/lpc.c index 7ef49d147e..fc96b83a94 100644 --- a/src/southbridge/amd/sb600/lpc.c +++ b/src/southbridge/amd/sb600/lpc.c @@ -59,7 +59,7 @@ static void lpc_init(device_t dev) byte &= ~(1 << 1); pci_write_config8(dev, 0x78, byte); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); } static void sb600_lpc_read_resources(device_t dev) diff --git a/src/southbridge/amd/sb600/sm.c b/src/southbridge/amd/sb600/sm.c index 8de39a6429..a8e72c28f7 100644 --- a/src/southbridge/amd/sb600/sm.c +++ b/src/southbridge/amd/sb600/sm.c @@ -169,7 +169,7 @@ static void sm_init(device_t dev) /* ab index */ pci_write_config32(dev, 0xF0, AB_INDX); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /*3.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */ abcfg_reg(0x10060, 9 << 17, 9 << 17); diff --git a/src/southbridge/amd/sb700/lpc.c b/src/southbridge/amd/sb700/lpc.c index 23775b0cf2..54181fdbdc 100644 --- a/src/southbridge/amd/sb700/lpc.c +++ b/src/southbridge/amd/sb700/lpc.c @@ -81,7 +81,7 @@ static void lpc_init(device_t dev) } #endif - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); } void set_cbmem_toc(struct cbmem_entry *toc) diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c index 2c2f6d53f6..d1caa31b05 100644 --- a/src/southbridge/amd/sb700/sm.c +++ b/src/southbridge/amd/sb700/sm.c @@ -197,7 +197,7 @@ static void sm_init(device_t dev) /* ab index */ pci_write_config32(dev, 0xF0, AB_INDX); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* 4.3 Enabling Upstream DMA Access */ axcfg_reg(0x04, 1 << 2, 1 << 2); diff --git a/src/southbridge/amd/sb800/lpc.c b/src/southbridge/amd/sb800/lpc.c index 12fd96fbfa..989139f125 100644 --- a/src/southbridge/amd/sb800/lpc.c +++ b/src/southbridge/amd/sb800/lpc.c @@ -67,7 +67,7 @@ static void lpc_init(device_t dev) byte |= 1 << 0 | 1 << 3; pci_write_config8(dev, 0xBB, byte); - rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY); + cmos_check_update_date(); } static void sb800_lpc_read_resources(device_t dev) diff --git a/src/southbridge/amd/sb800/sm.c b/src/southbridge/amd/sb800/sm.c index 315bc20b72..acdfb090a6 100644 --- a/src/southbridge/amd/sb800/sm.c +++ b/src/southbridge/amd/sb800/sm.c @@ -111,7 +111,7 @@ static void sm_init(device_t dev) pm_iowrite(0xE2, (AB_INDX >> 16) & 0xFF); pm_iowrite(0xE3, (AB_INDX >> 24) & 0xFF); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); byte = pm_ioread(0x8); byte |= 1 << 2 | 1 << 4; diff --git a/src/southbridge/broadcom/bcm5785/early_setup.c b/src/southbridge/broadcom/bcm5785/early_setup.c index 60f7abbc5f..9dee295c0d 100644 --- a/src/southbridge/broadcom/bcm5785/early_setup.c +++ b/src/southbridge/broadcom/bcm5785/early_setup.c @@ -177,7 +177,7 @@ static void bcm5785_early_setup(void) byte |= (1<<0); // SATA enable pci_write_config8(dev, 0x84, byte); -// WDT and cf9 for later in coreboot_ram to call hard_reset +// WDT and cf9 for later in ramstage to call hard_reset bcm5785_enable_wdt_port_cf9(); bcm5785_enable_msg(); diff --git a/src/southbridge/broadcom/bcm5785/lpc.c b/src/southbridge/broadcom/bcm5785/lpc.c index 834f0a1a4b..af79892a7b 100644 --- a/src/southbridge/broadcom/bcm5785/lpc.c +++ b/src/southbridge/broadcom/bcm5785/lpc.c @@ -33,7 +33,7 @@ static void lpc_init(device_t dev) { /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/intel/bd82x6x/bootblock.c b/src/southbridge/intel/bd82x6x/bootblock.c index 85a940e2de..afd6280180 100644 --- a/src/southbridge/intel/bd82x6x/bootblock.c +++ b/src/southbridge/intel/bd82x6x/bootblock.c @@ -86,9 +86,8 @@ static void set_spi_speed(void) static void bootblock_southbridge_init(void) { -#if CONFIG_COLLECT_TIMESTAMPS store_initial_timestamp(); -#endif + enable_spi_prefetch(); enable_port80_on_lpc(); set_spi_speed(); diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c index df37ddc4f8..b32e09512c 100644 --- a/src/southbridge/intel/bd82x6x/lpc.c +++ b/src/southbridge/intel/bd82x6x/lpc.c @@ -303,7 +303,7 @@ static void pch_rtc_init(struct device *dev) } printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); - rtc_init(rtc_failed); + cmos_init(rtc_failed); } /* CougarPoint PCH Power Management init */ diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h index 7f64571c4b..39048662db 100644 --- a/src/southbridge/intel/bd82x6x/pch.h +++ b/src/southbridge/intel/bd82x6x/pch.h @@ -56,7 +56,7 @@ void intel_pch_finalize_smm(void); #endif -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) #if !defined(__PRE_RAM__) #if !defined(__SMM__) #include "chip.h" diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c index 545e268a9c..eaf1ce4e5e 100644 --- a/src/southbridge/intel/bd82x6x/smihandler.c +++ b/src/southbridge/intel/bd82x6x/smihandler.c @@ -626,7 +626,7 @@ static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t *state static void southbridge_smi_gpi(unsigned int node, smm_state_save_area_t *state_save) { - void (*mainboard_gpi)(u16 gpi_sts) = mainboard_smi_gpi; + void (*mainboard_gpi)(u32 gpi_sts) = mainboard_smi_gpi; u16 reg16; reg16 = inw(pmbase + ALT_GP_SMI_STS); outw(reg16, pmbase + ALT_GP_SMI_STS); diff --git a/src/southbridge/intel/bd82x6x/spi.c b/src/southbridge/intel/bd82x6x/spi.c index 09169b1bc8..9cd845acb3 100644 --- a/src/southbridge/intel/bd82x6x/spi.c +++ b/src/southbridge/intel/bd82x6x/spi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -279,14 +280,7 @@ static void ich_set_bbar(uint32_t minaddr) writel_(ichspi_bbar, cntlr.bbar); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - printk(BIOS_DEBUG, "spi_cs_is_valid used but not implemented\n"); - return 0; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { ich_spi_slave *slave = malloc(sizeof(*slave)); @@ -414,6 +408,15 @@ void spi_init(void) pci_write_config_byte(dev, 0xdc, bios_cntl | 0x1); } +static void spi_init_cb(void *unused) +{ + spi_init(); +} + +BOOT_STATE_INIT_ENTRIES(spi_init_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL), +}; + int spi_claim_bus(struct spi_slave *slave) { /* Handled by ICH automatically. */ @@ -425,16 +428,6 @@ void spi_release_bus(struct spi_slave *slave) /* Handled by ICH automatically. */ } -void spi_cs_activate(struct spi_slave *slave) -{ - /* Handled by ICH automatically. */ -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ - /* Handled by ICH automatically. */ -} - typedef struct spi_transaction { const uint8_t *out; uint32_t bytesout; @@ -592,7 +585,7 @@ static int ich_status_poll(u16 bitmask, int wait_til_set) } int spi_xfer(struct spi_slave *slave, const void *dout, - unsigned int bitsout, void *din, unsigned int bitsin) + unsigned int bytesout, void *din, unsigned int bytesin) { uint16_t control; int16_t opcode_index; @@ -600,26 +593,21 @@ int spi_xfer(struct spi_slave *slave, const void *dout, int status; spi_transaction trans = { - dout, bitsout / 8, - din, bitsin / 8, + dout, bytesout, + din, bytesin, 0xff, 0xff, 0 }; /* There has to always at least be an opcode. */ - if (!bitsout || !dout) { + if (!bytesout || !dout) { printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n"); return -1; } /* Make sure if we read something we have a place to put it. */ - if (bitsin != 0 && !din) { + if (bytesin != 0 && !din) { printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n"); return -1; } - /* Right now we don't support writing partial bytes. */ - if (bitsout % 8 || bitsin % 8) { - printk(BIOS_DEBUG, "ICH SPI: Accessing partial bytes not supported\n"); - return -1; - } if (ich_status_poll(SPIS_SCIP, 0) == -1) return -1; diff --git a/src/southbridge/intel/esb6300/lpc.c b/src/southbridge/intel/esb6300/lpc.c index 67bcadc961..b5b77efa14 100644 --- a/src/southbridge/intel/esb6300/lpc.c +++ b/src/southbridge/intel/esb6300/lpc.c @@ -297,7 +297,7 @@ static void lpc_init(struct device *dev) esb6300_gpio_init(dev); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/intel/i3100/lpc.c b/src/southbridge/intel/i3100/lpc.c index abd065300c..f0ce6a6602 100644 --- a/src/southbridge/intel/i3100/lpc.c +++ b/src/southbridge/intel/i3100/lpc.c @@ -374,7 +374,7 @@ static void lpc_init(struct device *dev) i3100_gpio_init(dev); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/intel/i82371eb/i82371eb.h b/src/southbridge/intel/i82371eb/i82371eb.h index 76d5fc7085..e6062c68e8 100644 --- a/src/southbridge/intel/i82371eb/i82371eb.h +++ b/src/southbridge/intel/i82371eb/i82371eb.h @@ -21,26 +21,19 @@ #ifndef SOUTHBRIDGE_INTEL_I82371EB_I82371EB_H #define SOUTHBRIDGE_INTEL_I82371EB_I82371EB_H -#if !defined(__ASSEMBLER__) +#if !defined(__ASSEMBLER__) && !defined(__ACPI__) #if !defined(__PRE_RAM__) -#if !defined(__ACPI__) /* dsdt include */ - #include #include #include "chip.h" - void i82371eb_enable(device_t dev); void i82371eb_hard_reset(void); - -#endif -#endif -#endif - -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#else void enable_smbus(void); int smbus_read_byte(u8 device, u8 address); void enable_pm(void); #endif +#endif /* If 'cond' is true this macro sets the bit(s) specified by 'bits' in the * 'reg' variable, otherwise it clears those bits. diff --git a/src/southbridge/intel/i82371eb/isa.c b/src/southbridge/intel/i82371eb/isa.c index 5605106ddf..5261fbafa3 100644 --- a/src/southbridge/intel/i82371eb/isa.c +++ b/src/southbridge/intel/i82371eb/isa.c @@ -64,7 +64,7 @@ static void isa_init(struct device *dev) u32 reg32; /* Initialize the real time clock (RTC). */ - rtc_init(0); + cmos_init(0); /* * Enable special cycles, needed for soft poweroff. diff --git a/src/southbridge/intel/i82801ax/i82801ax.h b/src/southbridge/intel/i82801ax/i82801ax.h index ed15bba5fd..f459f2f20a 100644 --- a/src/southbridge/intel/i82801ax/i82801ax.h +++ b/src/southbridge/intel/i82801ax/i82801ax.h @@ -24,9 +24,7 @@ #if !defined(__PRE_RAM__) #include "chip.h" void i82801ax_enable(device_t dev); -#endif - -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#else void enable_smbus(void); int smbus_read_byte(u8 device, u8 address); #endif diff --git a/src/southbridge/intel/i82801ax/lpc.c b/src/southbridge/intel/i82801ax/lpc.c index db03a5897c..7799548ddf 100644 --- a/src/southbridge/intel/i82801ax/lpc.c +++ b/src/southbridge/intel/i82801ax/lpc.c @@ -184,7 +184,7 @@ static void i82801ax_rtc_init(struct device *dev) } reg32 = pci_read_config32(dev, GEN_STA); rtc_failed |= reg32 & (1 << 2); - rtc_init(rtc_failed); + cmos_init(rtc_failed); /* Enable access to the upper 128 byte bank of CMOS RAM. */ pci_write_config8(dev, RTC_CONF, 0x04); diff --git a/src/southbridge/intel/i82801bx/i82801bx.h b/src/southbridge/intel/i82801bx/i82801bx.h index 202b41cbff..b2ee79c745 100644 --- a/src/southbridge/intel/i82801bx/i82801bx.h +++ b/src/southbridge/intel/i82801bx/i82801bx.h @@ -26,7 +26,7 @@ extern void i82801bx_enable(device_t dev); #endif -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void enable_smbus(void); int smbus_read_byte(u8 device, u8 address); #endif diff --git a/src/southbridge/intel/i82801bx/lpc.c b/src/southbridge/intel/i82801bx/lpc.c index c5e976c136..a017528451 100644 --- a/src/southbridge/intel/i82801bx/lpc.c +++ b/src/southbridge/intel/i82801bx/lpc.c @@ -199,7 +199,7 @@ static void i82801bx_rtc_init(struct device *dev) } reg32 = pci_read_config32(dev, GEN_STS); rtc_failed |= reg32 & (1 << 2); - rtc_init(rtc_failed); + cmos_init(rtc_failed); /* Enable access to the upper 128 byte bank of CMOS RAM. */ pci_write_config8(dev, RTC_CONF, 0x04); diff --git a/src/southbridge/intel/i82801cx/lpc.c b/src/southbridge/intel/i82801cx/lpc.c index 79998bc722..c751ba438d 100644 --- a/src/southbridge/intel/i82801cx/lpc.c +++ b/src/southbridge/intel/i82801cx/lpc.c @@ -102,7 +102,7 @@ static void i82801cx_rtc_init(struct device *dev) dword = pci_read_config32(dev, GEN_STS); rtc_failed |= dword & (1 << 2); - rtc_init(rtc_failed); + cmos_init(rtc_failed); } diff --git a/src/southbridge/intel/i82801dx/i82801dx.h b/src/southbridge/intel/i82801dx/i82801dx.h index dba5bd6d8d..c7d7e77e79 100644 --- a/src/southbridge/intel/i82801dx/i82801dx.h +++ b/src/southbridge/intel/i82801dx/i82801dx.h @@ -31,7 +31,7 @@ #ifndef I82801DX_H #define I82801DX_H -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) #if !defined(__PRE_RAM__) #include "chip.h" extern void i82801dx_enable(device_t dev); diff --git a/src/southbridge/intel/i82801dx/lpc.c b/src/southbridge/intel/i82801dx/lpc.c index 69ec110d6e..d703c5b8b8 100644 --- a/src/southbridge/intel/i82801dx/lpc.c +++ b/src/southbridge/intel/i82801dx/lpc.c @@ -194,7 +194,7 @@ static void i82801dx_rtc_init(struct device *dev) } reg32 = pci_read_config32(dev, GEN_STS); rtc_failed |= reg32 & (1 << 2); - rtc_init(rtc_failed); + cmos_init(rtc_failed); /* Enable access to the upper 128 byte bank of CMOS RAM. */ pci_write_config8(dev, RTC_CONF, 0x04); diff --git a/src/southbridge/intel/i82801ex/lpc.c b/src/southbridge/intel/i82801ex/lpc.c index fb1586eb12..1823e65cf4 100644 --- a/src/southbridge/intel/i82801ex/lpc.c +++ b/src/southbridge/intel/i82801ex/lpc.c @@ -308,7 +308,7 @@ static void lpc_init(struct device *dev) i82801ex_gpio_init(dev); /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h index b5df5d9d32..1064dde8a0 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -37,7 +37,7 @@ #ifndef __ACPI__ #define DEBUG_PERIODIC_SMIS 0 -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) #if !defined(__PRE_RAM__) #include "chip.h" extern void i82801gx_enable(device_t dev); diff --git a/src/southbridge/intel/i82801gx/lpc.c b/src/southbridge/intel/i82801gx/lpc.c index 3a94e84062..0559054078 100644 --- a/src/southbridge/intel/i82801gx/lpc.c +++ b/src/southbridge/intel/i82801gx/lpc.c @@ -304,7 +304,7 @@ static void i82801gx_rtc_init(struct device *dev) } printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); - rtc_init(rtc_failed); + cmos_init(rtc_failed); } static void enable_hpet(void) diff --git a/src/southbridge/intel/i82801ix/lpc.c b/src/southbridge/intel/i82801ix/lpc.c index fb0dd56ff5..23a09313df 100644 --- a/src/southbridge/intel/i82801ix/lpc.c +++ b/src/southbridge/intel/i82801ix/lpc.c @@ -323,7 +323,7 @@ static void i82801ix_rtc_init(struct device *dev) } printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); - rtc_init(rtc_failed); + cmos_init(rtc_failed); } static void enable_hpet(void) diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig index f79e963206..da968400db 100644 --- a/src/southbridge/intel/lynxpoint/Kconfig +++ b/src/southbridge/intel/lynxpoint/Kconfig @@ -58,4 +58,33 @@ config SERIRQ_CONTINUOUS_MODE If you set this option to y, the serial IRQ machine will be operated in continuous mode. +config ME_MBP_CLEAR_LATE + bool "Defer wait for ME MBP Cleared" + default y + help + If you set this option to y, the Management Engine driver + will defer waiting for the MBP Cleared indicator until the + finalize step. This can speed up boot time if the ME takes + a long time to indicate this status. + +config FINALIZE_USB_ROUTE_XHCI + bool "Route all ports to XHCI controller in finalize step" + default y + help + If you set this option to y, the USB ports will be routed + to the XHCI controller during the finalize SMM callback. + +config LOCK_MANAGEMENT_ENGINE + bool "Lock Management Engine section" + default n + help + The Intel Management Engine supports preventing write accesses + from the host to the Management Engine section in the firmware + descriptor. If the ME section is locked, it can only be overwritten + with an external SPI flash programmer. You will want this if you + want to increase security of your ROM image once you are sure + that the ME firmware is no longer going to change. + + If unsure, say N. + endif diff --git a/src/southbridge/intel/lynxpoint/Makefile.inc b/src/southbridge/intel/lynxpoint/Makefile.inc index 7d1f894385..11d4ea26ac 100644 --- a/src/southbridge/intel/lynxpoint/Makefile.inc +++ b/src/southbridge/intel/lynxpoint/Makefile.inc @@ -20,8 +20,7 @@ # Run an intermediate step when producing coreboot.rom # that adds additional components to the final firmware # image outside of CBFS -# FIXME, uncomment as soon as we have ME firmware in the blobs repo -# INTERMEDIATE:=lynxpoint_add_me +INTERMEDIATE:=lynxpoint_add_me ramstage-y += pch.c ramstage-y += azalia.c @@ -30,8 +29,10 @@ ramstage-y += pci.c ramstage-y += pcie.c ramstage-y += sata.c ramstage-y += usb_ehci.c +ramstage-y += usb_xhci.c ramstage-y += me_9.x.c ramstage-y += smbus.c +ramstage-y += hda_verb.c ramstage-$(CONFIG_INTEL_LYNXPOINT_LP) += serialio.c ramstage-y += rcba.c @@ -47,7 +48,7 @@ smm-$(CONFIG_SPI_FLASH_SMM) += spi.c ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c pmutil.c smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c me_9.x.c finalize.c pch.c -smm-$(CONFIG_HAVE_SMI_HANDLER) += pmutil.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += pmutil.c usb_ehci.c usb_xhci.c romstage-y += early_usb.c early_smbus.c early_me.c me_status.c early_pch.c romstage-$(CONFIG_USBDEBUG) += usb_debug.c @@ -56,9 +57,11 @@ romstage-y += reset.c early_spi.c rcba.c ifeq ($(CONFIG_INTEL_LYNXPOINT_LP),y) romstage-y += lp_gpio.c ramstage-y += lp_gpio.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += lp_gpio.c else romstage-y += gpio.c ramstage-y += gpio.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += gpio.c endif lynxpoint_add_me: $(obj)/coreboot.pre $(IFDTOOL) diff --git a/src/southbridge/intel/lynxpoint/acpi.c b/src/southbridge/intel/lynxpoint/acpi.c index 4118b9df6d..b619e6e822 100644 --- a/src/southbridge/intel/lynxpoint/acpi.c +++ b/src/southbridge/intel/lynxpoint/acpi.c @@ -18,9 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include +#include #include #include #include "pch.h" +#include "nvs.h" void acpi_create_intel_hpet(acpi_hpet_t * hpet) { @@ -53,3 +57,40 @@ void acpi_create_intel_hpet(acpi_hpet_t * hpet) acpi_checksum((void *) hpet, sizeof(acpi_hpet_t)); } +static int acpi_create_serialio_ssdt_entry(int id, global_nvs_t *gnvs) +{ + char sio_name[5] = {}; + sprintf(sio_name, "S%1uEN", id); + return acpigen_write_name_byte(sio_name, gnvs->s0b[id] ? 1 : 0); +} + +void acpi_create_serialio_ssdt(acpi_header_t *ssdt) +{ + unsigned long current = (unsigned long)ssdt + sizeof(acpi_header_t); + global_nvs_t *gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + int id, len = 0; + + if (!gnvs) + return; + + /* Fill the SSDT header */ + memset((void *)ssdt, 0, sizeof(acpi_header_t)); + memcpy(&ssdt->signature, "SSDT", 4); + ssdt->revision = 2; + memcpy(&ssdt->oem_id, OEM_ID, 6); + memcpy(&ssdt->oem_table_id, ACPI_TABLE_CREATOR, 8); + ssdt->oem_revision = 42; + memcpy(&ssdt->asl_compiler_id, ASLC, 4); + ssdt->asl_compiler_revision = 42; + ssdt->length = sizeof(acpi_header_t); + acpigen_set_current((char *) current); + + /* Fill the SSDT with an entry for each SerialIO device */ + for (id = 0; id < 8; id++) + len += acpi_create_serialio_ssdt_entry(id, gnvs); + + /* (Re)calculate length and checksum. */ + current = (unsigned long)acpigen_get_current(); + ssdt->length = current - (unsigned long)ssdt; + ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length); +} diff --git a/src/southbridge/intel/lynxpoint/acpi/audio.asl b/src/southbridge/intel/lynxpoint/acpi/audio.asl index a4553289f2..2bc11686fd 100644 --- a/src/southbridge/intel/lynxpoint/acpi/audio.asl +++ b/src/southbridge/intel/lynxpoint/acpi/audio.asl @@ -27,10 +27,15 @@ Device (HDEF) { Name (_ADR, 0x001b0000) - // Power Resources for Wake - Name (_PRW, Package(){ - 13, // Bit 13 of GPE - 4 // Can wake from S4 state. - }) + Name (PRWH, Package(){ 0x0d, 3 }) // LPT-H + Name (PRWL, Package(){ 0x6d, 3 }) // LPT-LP + + Method (_PRW, 0) { // Power Resources for Wake + If (\ISLP ()) { + Return (PRWL) + } Else { + Return (PRWH) + } + } } diff --git a/src/southbridge/intel/lynxpoint/acpi/globalnvs.asl b/src/southbridge/intel/lynxpoint/acpi/globalnvs.asl index 8f6c8257c1..ef05dca3c2 100644 --- a/src/southbridge/intel/lynxpoint/acpi/globalnvs.asl +++ b/src/southbridge/intel/lynxpoint/acpi/globalnvs.asl @@ -131,6 +131,9 @@ Field (GNVS, ByteAcc, NoLock, Preserve) S6B1, 32, // 0x98 - D21:F6 Serial IO UAR1 BAR1 S7B1, 32, // 0x9c - D23:F0 Serial IO SDIO BAR1 + Offset (0xa0), + CBMC, 32, // 0xa0 - coreboot mem console pointer + /* IGD OpRegion */ Offset (0xb4), ASLB, 32, // 0xb4 - IGD OpRegion Base Address diff --git a/src/southbridge/intel/lynxpoint/acpi/lpc.asl b/src/southbridge/intel/lynxpoint/acpi/lpc.asl index f9bf57830f..07b3fcf745 100644 --- a/src/southbridge/intel/lynxpoint/acpi/lpc.asl +++ b/src/southbridge/intel/lynxpoint/acpi/lpc.asl @@ -32,6 +32,8 @@ Device (LPCB) DIDH, 8, // Device ID High Byte Offset (0x40), PMBS, 16, // PMBASE + Offset (0x48), + GPBS, 16, // GPIOBASE Offset (0x60), // Interrupt Routing Registers PRTA, 8, PRTB, 8, @@ -47,24 +49,6 @@ Device (LPCB) IOD0, 8, IOD1, 8, - Offset (0xb8), // GPIO Routing Control - GR00, 2, - GR01, 2, - GR02, 2, - GR03, 2, - GR04, 2, - GR05, 2, - GR06, 2, - GR07, 2, - GR08, 2, - GR09, 2, - GR10, 2, - GR11, 2, - GR12, 2, - GR13, 2, - GR14, 2, - GR15, 2, - Offset (0xf0), // RCBA RCEN, 1, , 13, @@ -199,60 +183,22 @@ Device (LPCB) 0x1, 0xff) // GPIO region may be 128 bytes or 4096 bytes - IO (Decode16, DEFAULT_GPIOBASE, DEFAULT_GPIOBASE, - 0x1, 0x00, GPR1) - IO (Decode16, 0x0000, 0x0000, 0x1, 0x00, GPR2) - IO (Decode16, 0x0000, 0x0000, 0x1, 0x00, GPR3) - IO (Decode16, 0x0000, 0x0000, 0x1, 0x00, GPR4) + IO (Decode16, 0x0000, 0x0000, 0x1, 0x00, GPR1) }) Method (_CRS, 0, NotSerialized) { - CreateByteField (^RBUF, ^GPR1._LEN, R1LN) - CreateByteField (^RBUF, ^GPR2._LEN, R2LN) - CreateByteField (^RBUF, ^GPR3._LEN, R3LN) - CreateByteField (^RBUF, ^GPR4._LEN, R4LN) + // LynxPoint-LP GPIO resources are defined in the + // SerialIO GPIO device and LynxPoint-H GPIO resources + // are defined here. + If (LNot (\ISLP ())) { + CreateByteField (^RBUF, ^GPR1._LEN, R1LN) + CreateWordField (^RBUF, ^GPR1._MIN, R1MN) + CreateWordField (^RBUF, ^GPR1._MAX, R1MX) - CreateWordField (^RBUF, ^GPR1._MIN, R1MN) - CreateWordField (^RBUF, ^GPR2._MIN, R2MN) - CreateWordField (^RBUF, ^GPR3._MIN, R3MN) - CreateWordField (^RBUF, ^GPR4._MIN, R4MN) - - CreateWordField (^RBUF, ^GPR1._MAX, R1MX) - CreateWordField (^RBUF, ^GPR2._MAX, R2MX) - CreateWordField (^RBUF, ^GPR3._MAX, R3MX) - CreateWordField (^RBUF, ^GPR4._MAX, R4MX) - - // Update GPIO region for LynxPoint-LP - If (\ISLP ()) { - // LynxPoint-LP - Store (R1MN, Local0) - - // Update GPIO bank 1 - Store (Local0, R1MN) - Store (Local0, R1MX) - Store (0xff, R1LN) - - // Update GPIO bank 2 - Add (Local0, 0x100, Local0) - Store (Local0, R2MN) - Store (Local0, R2MX) - Store (0xff, R2LN) - - // Update GPIO bank 3 - Add (Local0, 0x100, Local0) - Store (Local0, R3MN) - Store (Local0, R3MN) - Store (0xff, R3LN) - - // Update GPIO bank 4 - Add (Local0, 0x100, Local0) - Store (Local0, R4MN) - Store (Local0, R4MN) - Store (0xff, R4LN) - } Else { - // LynxPoint-H // Update GPIO region length + Store (DEFAULT_GPIOBASE, R1MN) + Store (DEFAULT_GPIOBASE, R1MX) Store (DEFAULT_GPIOSIZE, R1LN) } Return (RBUF) diff --git a/src/southbridge/intel/lynxpoint/acpi/lpt_lp.asl b/src/southbridge/intel/lynxpoint/acpi/lpt_lp.asl new file mode 100644 index 0000000000..fd64cb8cbc --- /dev/null +++ b/src/southbridge/intel/lynxpoint/acpi/lpt_lp.asl @@ -0,0 +1,94 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* LynxPoint-H */ + +Scope (\_SB.PCI0.LPCB) +{ + // GWAK: Setup GPIO as ACPI GPE for Wake + // Arg0: GPIO Number + Method (GWAK, 1, NotSerialized) + { + // Local0 = GPIO Base Address + Store (And (GPBS, Not(0x1)), Local0) + + // Local1 = BANK, Local2 = OFFSET + Divide (Arg0, 32, Local2, Local1) + + // + // Set OWNER to ACPI + // + + // Local3 = GPIOBASE + GPIO_OWN(BANK) + Store (Add (Local0, Multiply (Local1, 0x4)), Local3) + + // GPIO_OWN(BANK) + OperationRegion (IOWN, SystemIO, Local3, 4) + Field (IOWN, AnyAcc, NoLock, Preserve) { + GOWN, 32, + } + + // GPIO_OWN[GPIO] = 0 (ACPI) + Store (And (GOWN, Not (ShiftLeft (0x1, Local2))), GOWN) + + // + // Set ROUTE to SCI + // + + // Local3 = GPIOBASE + GPIO_ROUTE(BANK) + Store (Add (Add (Local0, 0x30), Multiply (Local1, 0x4)), Local3) + + // GPIO_ROUTE(BANK) + OperationRegion (IROU, SystemIO, Local3, 4) + Field (IROU, AnyAcc, NoLock, Preserve) { + GROU, 32, + } + + // GPIO_ROUTE[GPIO] = 0 (SCI) + Store (And (GROU, Not (ShiftLeft (0x1, Local2))), GROU) + + // + // Set GPnCONFIG to GPIO|INPUT|INVERT + // + + // Local3 = GPIOBASE + GPnCONFIG0(GPIO) + Store (Add (Add (Local0, 0x100), Multiply (Arg0, 0x8)), Local3) + + // GPnCONFIG(GPIO) + OperationRegion (GPNC, SystemIO, Local3, 8) + Field (GPNC, AnyAcc, NoLock, Preserve) { + GMOD, 1, // MODE: 0=NATIVE 1=GPIO + , 1, + GIOS, 1, // IO_SEL: 0=OUTPUT 1=INPUT + GINV, 1, // INVERT: 0=NORMAL 1=INVERT + GLES, 1, // LxEB: 0=EDGE 1=LEVEL + , 24, + ILVL, 1, // INPUT: 0=LOW 1=HIGH + OLVL, 1, // OUTPUT: 0=LOW 1=HIGH + GPWP, 2, // PULLUP: 00=NONE 01=DOWN 10=UP 11=INVALID + ISEN, 1, // SENSE: 0=ENABLE 1=DISABLE + } + + Store (0x1, GMOD) // GPIO + Store (0x1, GIOS) // INPUT + Store (0x1, GINV) // INVERT + } +} \ No newline at end of file diff --git a/src/southbridge/intel/lynxpoint/acpi/pch.asl b/src/southbridge/intel/lynxpoint/acpi/pch.asl index f5cf6aecf2..8ac55eb851 100644 --- a/src/southbridge/intel/lynxpoint/acpi/pch.asl +++ b/src/southbridge/intel/lynxpoint/acpi/pch.asl @@ -42,173 +42,6 @@ Scope(\) TRP0, 8 // IO-Trap at 0x808 } - // PCH Power Management Registers, located at PMBASE (0x1f.0 0x40.l) - OperationRegion(PMIO, SystemIO, DEFAULT_PMBASE, 0xff) - Field(PMIO, ByteAcc, NoLock, Preserve) - { - Offset(0x20), // GPE0_STS - , 16, - GS00, 1, // GPIO00 SCI/Wake Status - GS01, 1, // GPIO01 SCI/Wake Status - GS02, 1, // GPIO02 SCI/Wake Status - GS03, 1, // GPIO03 SCI/Wake Status - GS04, 1, // GPIO04 SCI/Wake Status - GS05, 1, // GPIO05 SCI/Wake Status - GS06, 1, // GPIO06 SCI/Wake Status - GS07, 1, // GPIO07 SCI/Wake Status - GS08, 1, // GPIO08 SCI/Wake Status - GS09, 1, // GPIO09 SCI/Wake Status - GS10, 1, // GPIO10 SCI/Wake Status - GS11, 1, // GPIO11 SCI/Wake Status - GS12, 1, // GPIO12 SCI/Wake Status - GS13, 1, // GPIO13 SCI/Wake Status - GS14, 1, // GPIO14 SCI/Wake Status - GS15, 1, // GPIO15 SCI/Wake Status - Offset(0x28), // GPE0_EN - , 16, - GE00, 1, // GPIO00 SCI/Wake Enable - GE01, 1, // GPIO01 SCI/Wake Enable - GE02, 1, // GPIO02 SCI/Wake Enable - GE03, 1, // GPIO03 SCI/Wake Enable - GE04, 1, // GPIO04 SCI/Wake Enable - GE05, 1, // GPIO05 SCI/Wake Enable - GE06, 1, // GPIO06 SCI/Wake Enable - GE07, 1, // GPIO07 SCI/Wake Enable - GE08, 1, // GPIO08 SCI/Wake Enable - GE09, 1, // GPIO09 SCI/Wake Enable - GE10, 1, // GPIO10 SCI/Wake Enable - GE11, 1, // GPIO11 SCI/Wake Enable - GE12, 1, // GPIO12 SCI/Wake Enable - GE13, 1, // GPIO13 SCI/Wake Enable - GE14, 1, // GPIO14 SCI/Wake Enable - GE15, 1, // GPIO15 SCI/Wake Enable - Offset(0x42), // General Purpose Control - , 1, // skip 1 bit - GPEC, 1, // SWGPE_CTRL - } - - // GPIO IO mapped registers (0x1f.0 reg 0x48.l) - OperationRegion(GPIO, SystemIO, DEFAULT_GPIOBASE, 0x6c) - Field(GPIO, ByteAcc, NoLock, Preserve) - { - Offset(0x00), // GPIO Use Select - GU00, 8, - GU01, 8, - GU02, 8, - GU03, 8, - Offset(0x04), // GPIO IO Select - GIO0, 8, - GIO1, 8, - GIO2, 8, - GIO3, 8, - Offset(0x0c), // GPIO Level - GL00, 1, - GP01, 1, - GP02, 1, - GP0e, 1, - GP04, 1, - GP05, 1, - GP06, 1, - GP07, 1, - GP08, 1, - GP09, 1, - GP10, 1, - GP11, 1, - GP12, 1, - GP13, 1, - GP14, 1, - GP15, 1, - GP16, 1, - GP17, 1, - GP18, 1, - GP19, 1, - GP20, 1, - GP21, 1, - GP22, 1, - GP23, 1, - GP24, 1, - GP25, 1, - GP26, 1, - GP27, 1, - GP28, 1, - GP29, 1, - GP30, 1, - GP31, 1, - Offset(0x18), // GPIO Blink - GB00, 8, - GB01, 8, - GB02, 8, - GB03, 8, - Offset(0x2c), // GPIO Invert - GIV0, 8, - GIV1, 8, - GIV2, 8, - GIV3, 8, - Offset(0x30), // GPIO Use Select 2 - GU04, 8, - GU05, 8, - GU06, 8, - GU07, 8, - Offset(0x34), // GPIO IO Select 2 - GIO4, 8, - GIO5, 8, - GIO6, 8, - GIO7, 8, - Offset(0x38), // GPIO Level 2 - GP32, 1, - GP33, 1, - GP34, 1, - GP35, 1, - GP36, 1, - GP37, 1, - GP38, 1, - GP39, 1, - GP40, 1, - GP41, 1, - GP42, 1, - GP43, 1, - GP44, 1, - GP45, 1, - GP46, 1, - GP47, 1, - GP48, 1, - GP49, 1, - GP50, 1, - GP51, 1, - GP52, 1, - GP53, 1, - GP54, 1, - GP55, 1, - GP56, 1, - GP57, 1, - GP58, 1, - GP59, 1, - GP60, 1, - GP61, 1, - GP62, 1, - GP63, 1, - Offset(0x40), // GPIO Use Select 3 - GU08, 8, - GU09, 4, - Offset(0x44), // GPIO IO Select 3 - GIO8, 8, - GIO9, 4, - Offset(0x48), // GPIO Level 3 - GP64, 1, - GP65, 1, - GP66, 1, - GP67, 1, - GP68, 1, - GP69, 1, - GP70, 1, - GP71, 1, - GP72, 1, - GP73, 1, - GP74, 1, - GP75, 1, - } - - // ICH7 Root Complex Register Block. Memory Mapped through RCBA) OperationRegion(RCRB, SystemMemory, DEFAULT_RCBA, 0x4000) Field(RCRB, DWordAcc, Lock, Preserve) @@ -270,6 +103,7 @@ Scope(\) // Serial IO #if CONFIG_INTEL_LYNXPOINT_LP #include "serialio.asl" +#include "lpt_lp.asl" #endif Method (_OSC, 4) diff --git a/src/southbridge/intel/lynxpoint/acpi/serialio.asl b/src/southbridge/intel/lynxpoint/acpi/serialio.asl index 6ea23c69ea..3e68c133a8 100644 --- a/src/southbridge/intel/lynxpoint/acpi/serialio.asl +++ b/src/southbridge/intel/lynxpoint/acpi/serialio.asl @@ -24,6 +24,17 @@ // Serial IO Device BAR0 and BAR1 is 4KB #define SIO_BAR_LEN 0x1000 +// This is defined in SSDT2 which is generated at boot based +// on whether or not the device is enabled in ACPI mode. +External(\S0EN) +External(\S1EN) +External(\S2EN) +External(\S3EN) +External(\S4EN) +External(\S5EN) +External(\S6EN) +External(\S7EN) + // Serial IO Resource Consumption for BAR1 Device (SIOR) { @@ -143,7 +154,7 @@ Device (SDMA) Method (_STA, 0, NotSerialized) { - If (LEqual (\S0B0, 0)) { + If (LEqual (\S0EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -194,7 +205,7 @@ Device (I2C0) Method (_STA, 0, NotSerialized) { - If (LEqual (\S1B0, 0)) { + If (LEqual (\S1EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -245,7 +256,7 @@ Device (I2C1) Method (_STA, 0, NotSerialized) { - If (LEqual (\S2B0, 0)) { + If (LEqual (\S2EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -283,7 +294,7 @@ Device (SPI0) Method (_STA, 0, NotSerialized) { - If (LEqual (\S3B0, 0)) { + If (LEqual (\S3EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -334,7 +345,7 @@ Device (SPI1) Method (_STA, 0, NotSerialized) { - If (LEqual (\S4B0, 0)) { + If (LEqual (\S4EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -385,7 +396,7 @@ Device (UAR0) Method (_STA, 0, NotSerialized) { - If (LEqual (\S5B0, 0)) { + If (LEqual (\S5EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -423,7 +434,7 @@ Device (UAR1) Method (_STA, 0, NotSerialized) { - If (LEqual (\S6B0, 0)) { + If (LEqual (\S6EN, 0)) { Return (0x0) } Else { Return (0xF) @@ -461,10 +472,62 @@ Device (SDIO) Method (_STA, 0, NotSerialized) { - If (LEqual (\S7B0, 0)) { + If (LEqual (\S7EN, 0)) { Return (0x0) } Else { Return (0xF) } } } + +Device (GPIO) +{ + // GPIO Controller + Name (_HID, "INT33C7") + Name (_CID, "INT33C7") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate() + { + DWordIo (ResourceProducer, + MinFixed, // IsMinFixed + MaxFixed, // IsMaxFixed + PosDecode, // Decode + EntireRange, // ISARanges + 0x00000000, // AddressGranularity + 0x00000000, // AddressMinimum + 0x00000000, // AddressMaximum + 0x00000000, // AddressTranslation + 0x00000000, // RangeLength + , // ResourceSourceIndex + , // ResourceSource + BAR0) + Interrupt (ResourceConsumer, + Level, ActiveHigh, Shared, , , ) {14} + }) + + Method (_CRS, 0, NotSerialized) + { + If (\ISLP ()) { + CreateDwordField (^RBUF, ^BAR0._MIN, BMIN) + CreateDwordField (^RBUF, ^BAR0._MAX, BMAX) + CreateDwordField (^RBUF, ^BAR0._LEN, BLEN) + + Store (DEFAULT_GPIOSIZE, BLEN) + Store (DEFAULT_GPIOBASE, BMIN) + Store (Subtract (Add (DEFAULT_GPIOBASE, + DEFAULT_GPIOSIZE), 1), BMAX) + } + + Return (RBUF) + } + + Method (_STA, 0, NotSerialized) + { + If (\ISLP ()) { + Return (0xF) + } Else { + Return (0x0) + } + } +} diff --git a/src/southbridge/intel/lynxpoint/acpi/usb.asl b/src/southbridge/intel/lynxpoint/acpi/usb.asl index cf3e6a049f..9c9b6b0b65 100644 --- a/src/southbridge/intel/lynxpoint/acpi/usb.asl +++ b/src/southbridge/intel/lynxpoint/acpi/usb.asl @@ -23,11 +23,20 @@ // EHCI Controller 0:1d.0 -Device (EHC1) +Device (EHCI) { Name(_ADR, 0x001d0000) - Name (_PRW, Package(){ 13, 4 }) // Power Resources for Wake + Name (PRWH, Package(){ 0x0d, 3 }) // LPT-H + Name (PRWL, Package(){ 0x6d, 3 }) // LPT-LP + + Method (_PRW, 0) { // Power Resources for Wake + If (\ISLP ()) { + Return (PRWL) + } Else { + Return (PRWH) + } + } // Leave USB ports on for to allow Wake from USB @@ -55,24 +64,334 @@ Device (EHC1) } } -// EHCI #2 Controller 0:1a.0 +// XHCI Controller 0:14.0 -Device (EHC2) +Device (XHCI) { - Name(_ADR, 0x001a0000) + Name (_ADR, 0x00140000) - Name (_PRW, Package(){ 13, 4 }) // Power Resources for Wake + Name (PLSD, 5) // Port Link State - RxDetect + Name (PLSP, 7) // Port Link State - Polling + + OperationRegion (XPRT, PCI_Config, 0x00, 0x100) + Field (XPRT, AnyAcc, NoLock, Preserve) + { + Offset (0x0), + DVID, 16, + Offset (0x10), + , 16, + XMEM, 16, // MEM_BASE + Offset (0x74), + D0D3, 2, + , 6, + PMEE, 1, // PME_EN + , 6, + PMES, 1, // PME_STS + Offset (0xb0), + , 13, + MB13, 1, + MB14, 1, + Offset (0xd0), + PR2R, 32, // USB2PR + PR2M, 32, // USB2PRM + PR3R, 32, // USB3PR + PR3M, 32, // USB3PRM + } + + // Clear status bits + Method (LPCL, 0, Serialized) + { + OperationRegion (XREG, SystemMemory, + ShiftLeft (^XMEM, 16), 0x600) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x510), // PORTSCNUSB3[0] + PSC0, 32, + Offset (0x520), // PORTSCNUSB3[1] + PSC1, 32, + Offset (0x530), // PORTSCNUSB3[2] + PSC2, 32, + Offset (0x540), // PORTSCNUSB3[3] + PSC3, 32, + } + + // Port Enabled/Disabled (Bit 1) + Name (PEDB, ShiftLeft (1, 1)) + + // Change Status (Bits 23:17) + Name (CHST, ShiftLeft (0x7f, 17)) + + // Port 0 + And (PSC0, Not (PEDB), Local0) + Or (Local0, CHST, PSC0) + + // Port 1 + And (PSC1, Not (PEDB), Local0) + Or (Local0, CHST, PSC1) + + // Port 2 + And (PSC2, Not (PEDB), Local0) + Or (Local0, CHST, PSC2) + + // Port 3 + And (PSC3, Not (PEDB), Local0) + Or (Local0, CHST, PSC3) + } + + Method (LPS0, 0, Serialized) + { + OperationRegion (XREG, SystemMemory, + ShiftLeft (^XMEM, 16), 0x600) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x510), // PORTSCNUSB3 + , 5, + PLS1, 4, // [8:5] Port Link State + PPR1, 1, // [9] Port Power + , 7, + CSC1, 1, // [17] Connect Status Change + , 1, + WRC1, 1, // [19] Warm Port Reset Change + , 11, + WPR1, 1, // [31] Warm Port Reset + Offset (0x520), // PORTSCNUSB3 + , 5, + PLS2, 4, // [8:5] Port Link State + PPR2, 1, // [9] Port Power + , 7, + CSC2, 1, // [17] Connect Status Change + , 1, + WRC2, 1, // [19] Warm Port Reset Change + , 11, + WPR2, 1, // [31] Warm Port Reset + Offset (0x530), // PORTSCNUSB3 + , 5, + PLS3, 4, // [8:5] Port Link State + PPR3, 1, // [9] Port Power + , 7, + CSC3, 1, // [17] Connect Status Change + , 1, + WRC3, 1, // [19] Warm Port Reset Change + , 11, + WPR3, 1, // [31] Warm Port Reset + Offset (0x540), // PORTSCNUSB3 + , 5, + PLS4, 4, // [8:5] Port Link State + PPR4, 1, // [9] Port Power + , 7, + CSC4, 1, // [17] Connect Status Change + , 1, + WRC4, 1, // [19] Warm Port Reset Change + , 11, + WPR4, 1, // [31] Warm Port Reset + } + + // Wait for all powered ports to finish polling + Store (10, Local0) + While (LOr (LOr (LAnd (LEqual (PPR1, 1), LEqual (PLS1, PLSP)), + LAnd (LEqual (PPR2, 1), LEqual (PLS2, PLSP))), + LOr (LAnd (LEqual (PPR3, 1), LEqual (PLS3, PLSP)), + LAnd (LEqual (PPR4, 1), LEqual (PLS4, PLSP))))) + { + If (LEqual (Local0, 0)) { + Break + } + Decrement (Local0) + Stall (10) + } + + // For each USB3 Port: + // If port is disconnected (PLS=5 PP=1 CSC=0) + // 1) Issue warm reset (WPR=1) + // 2) Poll for warm reset complete (WRC=0) + // 3) Write 1 to port status to clear + + // Local# indicate if port is reset + Store (0, Local1) + Store (0, Local2) + Store (0, Local3) + Store (0, Local4) + + If (LAnd (LEqual (PLS1, PLSD), + LAnd (LEqual (CSC1, 0), LEqual (PPR1, 1)))) { + Store (1, WPR1) // Issue warm reset + Store (1, Local1) + } + If (LAnd (LEqual (PLS2, PLSD), + LAnd (LEqual (CSC2, 0), LEqual (PPR2, 1)))) { + Store (1, WPR2) // Issue warm reset + Store (1, Local2) + } + If (LAnd (LEqual (PLS3, PLSD), + LAnd (LEqual (CSC3, 0), LEqual (PPR3, 1)))) { + Store (1, WPR3) // Issue warm reset + Store (1, Local3) + } + If (LAnd (LEqual (PLS4, PLSD), + LAnd (LEqual (CSC4, 0), LEqual (PPR4, 1)))) { + Store (1, WPR4) // Issue warm reset + Store (1, Local4) + } + + // Poll for warm reset complete on all ports that were reset + Store (10, Local0) + While (LOr (LOr (LAnd (LEqual (Local1, 1), LEqual (WRC1, 0)), + LAnd (LEqual (Local2, 1), LEqual (WRC2, 0))), + LOr (LAnd (LEqual (Local3, 1), LEqual (WRC3, 0)), + LAnd (LEqual (Local4, 1), LEqual (WRC4, 0))))) + { + If (LEqual (Local0, 0)) { + Break + } + Decrement (Local0) + Stall (10) + } + + // Clear status bits in all ports + LPCL () + } + + Method (_PSC, 0, NotSerialized) + { + Return (^D0D3) + } + + Method (_PS0, 0, Serialized) + { + If (LEqual (^DVID, 0xFFFF)) { + Return () + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return () + } + + OperationRegion (XREG, SystemMemory, + Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x0e0), // AUX Reset Control 1 + , 15, + AX15, 1, + Offset (0x154), // AUX Domain PM Control Register 2 + , 31, + CLK2, 1, + Offset (0x16c), // AUX Clock Control + , 2, + CLK0, 1, + , 11, + CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable + } + + // If device is in D3, set back to D0 + Store (^D0D3, Local0) + if (LEqual (Local0, 3)) { + Store (0, ^D0D3) + } + + If (\ISLP ()) { + // Clear PCI 0xB0[14:13] + Store (0, ^MB13) + Store (0, ^MB14) + + // Clear MMIO 0x816C[14,2] + Store (0, CLK0) + Store (0, CLK1) + } + + // Set MMIO 0x8154[31] + Store (1, CLK2) + + If (\ISLP ()) { + // Handle per-port reset if needed + LPS0 () + + // Set MMIO 0x80e0[15] + Store (1, AX15) + } + + Return () + } + + Method (_PS3, 0, Serialized) + { + If (LEqual (^DVID, 0xFFFF)) { + Return () + } + If (LOr (LEqual (^XMEM, 0xFFFF), LEqual (^XMEM, 0x0000))) { + Return () + } + + OperationRegion (XREG, SystemMemory, + Add (ShiftLeft (^XMEM, 16), 0x8000), 0x200) + Field (XREG, DWordAcc, Lock, Preserve) + { + Offset (0x0e0), // AUX Reset Control 1 + , 15, + AX15, 1, + Offset (0x154), // AUX Domain PM Control Register 2 + , 31, + CLK2, 1, + Offset (0x16c), // AUX Clock Control + , 2, + CLK0, 1, + , 11, + CLK1, 1, // USB3 Port Aux/Core Clock Gating Enable + } + + Store (1, ^PMES) // Clear PME Status + Store (1, ^PMEE) // Enable PME + + // If device is in D3, set back to D0 + Store (^D0D3, Local0) + if (LEqual (Local0, 3)) { + Store (0, ^D0D3) + } + + If (\ISLP ()) { + // Set PCI 0xB0[14:13] + Store (1, ^MB13) + Store (1, ^MB14) + + // Set MMIO 0x816C[14,2] + Store (1, CLK0) + Store (1, CLK1) + } + + // Clear MMIO 0x8154[31] + Store (0, CLK2) + + If (\ISLP ()) { + // Clear MMIO 0x80e0[15] + Store (0, AX15) + } + + // Put device in D3 + Store (3, ^D0D3) + + Return () + } + + Name (PRWH, Package(){ 0x0d, 3 }) // LPT-H + Name (PRWL, Package(){ 0x6d, 3 }) // LPT-LP + + Method (_PRW, 0) { // Power Resources for Wake + If (\ISLP ()) { + Return (PRWL) + } Else { + Return (PRWH) + } + } // Leave USB ports on for to allow Wake from USB Method(_S3D,0) // Highest D State in S3 State { - Return (2) + Return (3) } Method(_S4D,0) // Highest D State in S4 State { - Return (2) + Return (3) } Device (HUB7) diff --git a/src/southbridge/intel/lynxpoint/azalia.c b/src/southbridge/intel/lynxpoint/azalia.c index ac2b79d15f..efb8e9868f 100644 --- a/src/southbridge/intel/lynxpoint/azalia.c +++ b/src/southbridge/intel/lynxpoint/azalia.c @@ -27,240 +27,47 @@ #include #include #include "pch.h" - -#define HDA_ICII_REG 0x68 -#define HDA_ICII_BUSY (1 << 0) -#define HDA_ICII_VALID (1 << 1) - -typedef struct southbridge_intel_bd82x6x_config config_t; - -static int set_bits(u32 port, u32 mask, u32 val) -{ - u32 reg32; - int count; - - /* Write (val & mask) to port */ - val &= mask; - reg32 = read32(port); - reg32 &= ~mask; - reg32 |= val; - write32(port, reg32); - - /* Wait for readback of register to - * match what was just written to it - */ - count = 50; - do { - /* Wait 1ms based on BKDG wait time */ - mdelay(1); - reg32 = read32(port); - reg32 &= mask; - } while ((reg32 != val) && --count); - - /* Timeout occurred */ - if (!count) - return -1; - return 0; -} - -static int codec_detect(u32 base) -{ - u8 reg8; - - /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ - if (set_bits(base + 0x08, 1, 1) == -1) - goto no_codec; - - /* Write back the value once reset bit is set. */ - write16(base + 0x0, read16(base + 0x0)); - - /* Read in Codec location (BAR + 0xe)[2..0]*/ - reg8 = read8(base + 0xe); - reg8 &= 0x0f; - if (!reg8) - goto no_codec; - - return reg8; - -no_codec: - /* Codec Not found */ - /* Put HDA back in reset (BAR + 0x8) [0] */ - set_bits(base + 0x08, 1, 0); - printk(BIOS_DEBUG, "Azalia: No codec!\n"); - return 0; -} +#include "hda_verb.h" const u32 * cim_verb_data = NULL; u32 cim_verb_data_size = 0; const u32 * pc_beep_verbs = NULL; u32 pc_beep_verbs_size = 0; -static u32 find_verb(struct device *dev, u32 viddid, const u32 ** verb) -{ - int idx=0; - - while (idx < (cim_verb_data_size / sizeof(u32))) { - u32 verb_size = 4 * cim_verb_data[idx+2]; // in u32 - if (cim_verb_data[idx] != viddid) { - idx += verb_size + 3; // skip verb + header - continue; - } - *verb = &cim_verb_data[idx+3]; - return verb_size; - } - - /* Not all codecs need to load another verb */ - return 0; -} - -/** - * Wait 50usec for the codec to indicate it is ready - * no response would imply that the codec is non-operative - */ - -static int wait_for_ready(u32 base) -{ - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - - while(timeout--) { - u32 reg32 = read32(base + HDA_ICII_REG); - if (!(reg32 & HDA_ICII_BUSY)) - return 0; - udelay(1); - } - - return -1; -} - -/** - * Wait 50usec for the codec to indicate that it accepted - * the previous command. No response would imply that the code - * is non-operative - */ - -static int wait_for_valid(u32 base) -{ - u32 reg32; - - /* Send the verb to the codec */ - reg32 = read32(base + HDA_ICII_REG); - reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID; - write32(base + HDA_ICII_REG, reg32); - - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - while(timeout--) { - reg32 = read32(base + HDA_ICII_REG); - if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == - HDA_ICII_VALID) - return 0; - udelay(1); - } - - return -1; -} - -static void codec_init(struct device *dev, u32 base, int addr) -{ - u32 reg32; - const u32 *verb; - u32 verb_size; - int i; - - printk(BIOS_DEBUG, "Azalia: Initializing codec #%d\n", addr); - - /* 1 */ - if (wait_for_ready(base) == -1) { - printk(BIOS_DEBUG, " codec not ready.\n"); - return; - } - - reg32 = (addr << 28) | 0x000f0000; - write32(base + 0x60, reg32); - - if (wait_for_valid(base) == -1) { - printk(BIOS_DEBUG, " codec not valid.\n"); - return; - } - - reg32 = read32(base + 0x64); - - /* 2 */ - printk(BIOS_DEBUG, "Azalia: codec viddid: %08x\n", reg32); - verb_size = find_verb(dev, reg32, &verb); - - if (!verb_size) { - printk(BIOS_DEBUG, "Azalia: No verb!\n"); - return; - } - printk(BIOS_DEBUG, "Azalia: verb_size: %d\n", verb_size); - - /* 3 */ - for (i = 0; i < verb_size; i++) { - if (wait_for_ready(base) == -1) - return; - - write32(base + 0x60, verb[i]); - - if (wait_for_valid(base) == -1) - return; - } - printk(BIOS_DEBUG, "Azalia: verb loaded.\n"); -} - -static void codecs_init(struct device *dev, u32 base, u32 codec_mask) +static void codecs_init(u32 base, u32 codec_mask) { int i; + + /* Can support up to 4 codecs */ for (i = 3; i >= 0; i--) { if (codec_mask & (1 << i)) - codec_init(dev, base, i); + hda_codec_init(base, i, + cim_verb_data_size, + cim_verb_data); } - for (i = 0; i < pc_beep_verbs_size; i++) { - if (wait_for_ready(base) == -1) - return; - - write32(base + 0x60, pc_beep_verbs[i]); - - if (wait_for_valid(base) == -1) - return; - } + if (pc_beep_verbs_size && pc_beep_verbs) + hda_codec_write(base, pc_beep_verbs_size, pc_beep_verbs); } -static void azalia_init(struct device *dev) +static void azalia_pch_init(struct device *dev, u32 base) { - u32 base; - struct resource *res; - u32 codec_mask; u8 reg8; u16 reg16; u32 reg32; - /* Find base address */ - res = find_resource(dev, PCI_BASE_ADDRESS_0); - if (!res) - return; - - // NOTE this will break as soon as the Azalia get's a bar above - // 4G. Is there anything we can do about it? - base = (u32)res->base; - printk(BIOS_DEBUG, "Azalia: base = %08x\n", (u32)base); - if (RCBA32(0x2030) & (1 << 31)) { reg32 = pci_mmio_read_config32(dev, 0x120); reg32 &= 0xf8ffff01; - reg32 |= (1 << 24); // 25 for server + reg32 |= (1 << 25); reg32 |= RCBA32(0x2030) & 0xfe; pci_mmio_write_config32(dev, 0x120, reg32); - reg16 = pci_mmio_read_config16(dev, 0x78); - reg16 &= ~(1 << 11); - pci_mmio_write_config16(dev, 0x78, reg16); + if (!pch_is_lp()) { + reg16 = pci_mmio_read_config16(dev, 0x78); + reg16 &= ~(1 << 11); + pci_mmio_write_config16(dev, 0x78, reg16); + } } else printk(BIOS_DEBUG, "Azalia: V1CTL disabled.\n"); @@ -272,73 +79,87 @@ static void azalia_init(struct device *dev) if (pci_mmio_read_config32(dev, 0x120) & ((1 << 24) | (1 << 25) | (1 << 26))) { reg32 = pci_mmio_read_config32(dev, 0x120); - reg32 |= (1 << 31); + if (pch_is_lp()) + reg32 &= ~(1 << 31); + else + reg32 |= (1 << 31); pci_mmio_write_config32(dev, 0x120, reg32); } - // Enable HDMI codec: - reg32 = pci_read_config32(dev, 0xc4); - reg32 |= (1 << 1); - pci_write_config32(dev, 0xc4, reg32); - reg8 = pci_read_config8(dev, 0x43); - reg8 |= (1 << 5) | (1 << 6) | (1 << 2) | (1 << 1) | (1 << 0); + if (pch_is_lp()) + reg8 &= ~(1 << 6); + else + reg8 |= (1 << 4); pci_write_config8(dev, 0x43, reg8); - /* Additional programming steps */ - reg32 = pci_read_config32(dev, 0xc4); - reg32 |= (1 << 13) | (1 << 10); - pci_write_config32(dev, 0xc4, reg32); - - reg32 = pci_read_config32(dev, 0xd0); - reg32 &= ~(1 << 31); - pci_write_config32(dev, 0xd0, reg32); + if (!pch_is_lp()) { + reg32 = pci_read_config32(dev, 0xc0); + reg32 |= (1 << 17); + pci_write_config32(dev, 0xc0, reg32); + } /* Additional programming steps */ reg32 = pci_read_config32(dev, 0xc4); - reg32 |= (1 << 13); + if (pch_is_lp()) + reg32 |= (1 << 24); + else + reg32 |= (1 << 14); pci_write_config32(dev, 0xc4, reg32); - reg32 = pci_read_config32(dev, 0xc4); - reg32 |= (1 << 10); - pci_write_config32(dev, 0xc4, reg32); + if (!pch_is_lp()) { + reg32 = pci_read_config32(dev, 0xd0); + reg32 &= ~(1 << 31); + pci_write_config32(dev, 0xd0, reg32); + } - reg32 = pci_read_config32(dev, 0xd0); - reg32 &= ~(1 << 31); - pci_write_config32(dev, 0xd0, reg32); - - /* Set Bus Master */ - reg32 = pci_read_config32(dev, PCI_COMMAND); - pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER); - - pci_write_config8(dev, 0x3c, 0x0a); // unused? - - /* Codec Initialization Programming Sequence */ - reg32 = read32(base + 0x08); - reg32 |= (1 << 0); - write32(base + 0x08, reg32); - - // reg8 = pci_read_config8(dev, 0x40); // Audio Control - reg8 |= 1; // Select Azalia mode. This needs to be controlled via devicetree.cb + reg8 |= 1; // Select Azalia mode pci_write_config8(dev, 0x40, reg8); reg8 = pci_read_config8(dev, 0x4d); // Docking Status reg8 &= ~(1 << 7); // Docking not supported pci_write_config8(dev, 0x4d, reg8); - codec_mask = codec_detect(base); + if (pch_is_lp()) { + reg16 = read32(base + 0x0012); + reg16 |= (1 << 0); + write32(base + 0x0012, reg16); + + /* disable Auto Voltage Detector */ + reg8 = pci_read_config8(dev, 0x42); + reg8 |= (1 << 2); + pci_write_config8(dev, 0x42, reg8); + } +} + +static void azalia_init(struct device *dev) +{ + u32 base; + struct resource *res; + u32 codec_mask; + u32 reg32; + + /* Find base address */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "Azalia: base = %08x\n", (u32)base); + + /* Set Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER); + + azalia_pch_init(dev, base); + + codec_mask = hda_codec_detect(base); if (codec_mask) { printk(BIOS_DEBUG, "Azalia: codec_mask = %02x\n", codec_mask); - codecs_init(dev, base, codec_mask); + codecs_init(base, codec_mask); } - - /* Enable dynamic clock gating */ - reg8 = pci_read_config8(dev, 0x43); - reg8 &= ~0x7; - reg8 |= (1 << 2) | (1 << 0); - pci_write_config8(dev, 0x43, reg8); } static void azalia_set_subsystem(device_t dev, unsigned vendor, unsigned device) @@ -365,7 +186,7 @@ static struct device_operations azalia_ops = { .ops_pci = &azalia_pci_ops, }; -static const unsigned short pci_device_ids[] = { 0x1c20, 0x1e20, 0 }; +static const unsigned short pci_device_ids[] = { 0x8c20, 0x9c20, 0 }; static const struct pci_driver pch_azalia __pci_driver = { .ops = &azalia_ops, diff --git a/src/southbridge/intel/lynxpoint/bootblock.c b/src/southbridge/intel/lynxpoint/bootblock.c index 96291189cd..89f23c7e17 100644 --- a/src/southbridge/intel/lynxpoint/bootblock.c +++ b/src/southbridge/intel/lynxpoint/bootblock.c @@ -87,9 +87,8 @@ static void set_spi_speed(void) static void bootblock_southbridge_init(void) { -#if CONFIG_COLLECT_TIMESTAMPS store_initial_timestamp(); -#endif + map_rcba(); enable_spi_prefetch(); enable_port80_on_lpc(); diff --git a/src/southbridge/intel/lynxpoint/chip.h b/src/southbridge/intel/lynxpoint/chip.h index 70f3e63a63..cc2cda0210 100644 --- a/src/southbridge/intel/lynxpoint/chip.h +++ b/src/southbridge/intel/lynxpoint/chip.h @@ -72,12 +72,22 @@ struct southbridge_intel_lynxpoint_config { uint8_t sata_port_map; uint32_t sata_port0_gen3_tx; uint32_t sata_port1_gen3_tx; + uint32_t sata_port0_gen3_dtle; + uint32_t sata_port1_gen3_dtle; + /* SATA DEVSLP Mux * 0 = port 0 DEVSLP on DEVSLP0/GPIO33 * 1 = port 3 DEVSLP on DEVSLP0/GPIO33 */ uint8_t sata_devslp_mux; + /* + * DEVSLP Disable + * 0: DEVSLP is enabled + * 1: DEVSLP is disabled + */ + uint8_t sata_devslp_disable; + uint32_t gen1_dec; uint32_t gen2_dec; uint32_t gen3_dec; @@ -85,6 +95,8 @@ struct southbridge_intel_lynxpoint_config { /* Enable linear PCIe Root Port function numbers starting at zero */ uint8_t pcie_port_coalesce; + /* Force root port ASPM configuration with port bitmap */ + uint8_t pcie_port_force_aspm; /* Serial IO configuration */ /* Put devices into ACPI mode instead of a PCI device */ @@ -92,6 +104,16 @@ struct southbridge_intel_lynxpoint_config { /* I2C voltage select: 0=3.3V 1=1.8V */ uint8_t sio_i2c0_voltage; uint8_t sio_i2c1_voltage; + + /* + * Clock Disable Map: + * [21:16] = CLKOUT_PCIE# 5-0 + * [24] = CLKOUT_ITPXDP + */ + uint32_t icc_clock_disable; + + /* Route USB ports to XHCI per default */ + uint8_t xhci_default; }; extern struct chip_operations southbridge_intel_lynxpoint_ops; diff --git a/src/southbridge/intel/lynxpoint/early_pch.c b/src/southbridge/intel/lynxpoint/early_pch.c index a390d737bc..29443a4e20 100644 --- a/src/southbridge/intel/lynxpoint/early_pch.c +++ b/src/southbridge/intel/lynxpoint/early_pch.c @@ -20,9 +20,11 @@ #include #include +#include #include #include #include "pch.h" +#include "chip.h" #if CONFIG_INTEL_LYNXPOINT_LP #include "lp_gpio.h" @@ -30,6 +32,8 @@ #include "gpio.h" #endif +#include + const struct rcba_config_instruction pch_early_config[] = { /* Enable IOAPIC */ RCBA_SET_REG_16(OIC, 0x0100), @@ -39,6 +43,12 @@ const struct rcba_config_instruction pch_early_config[] = { RCBA_END_CONFIG, }; +int pch_is_lp(void) +{ + u8 id = pci_read_config8(PCH_LPC_DEV, PCI_DEVICE_ID + 1); + return id == PCH_TYPE_LPT_LP; +} + static void pch_enable_bars(void) { /* Setting up Southbridge. In the northbridge code. */ @@ -82,17 +92,31 @@ static int sleep_type_s3(void) return is_s3; } -static void pch_enable_lpc(void) +void pch_enable_lpc(void) { - device_t dev = PCH_LPC_DEV; + const struct device *dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0)); + const struct southbridge_intel_lynxpoint_config *config = NULL; /* Set COM1/COM2 decode range */ - pci_write_config16(dev, LPC_IO_DEC, 0x0010); + pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); /* Enable SuperIO + MC + COM1 + PS/2 Keyboard/Mouse */ - u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN | + u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN | GAMEL_LPC_EN | COMA_LPC_EN | KBC_LPC_EN | MC_LPC_EN; - pci_write_config16(dev, LPC_EN, lpc_config); + pci_write_config16(PCH_LPC_DEV, LPC_EN, lpc_config); + + /* Set up generic decode ranges */ + if (!dev) + return; + if (dev->chip_info) + config = dev->chip_info; + if (!config) + return; + + pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, config->gen1_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, config->gen2_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, config->gen3_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, config->gen4_dec); } int early_pch_init(const void *gpio_map, @@ -110,6 +134,10 @@ int early_pch_init(const void *gpio_map, setup_pch_gpios(gpio_map); #endif +#if CONFIG_CHROMEOS + save_chromeos_gpios(); +#endif + console_init(); pch_generic_setup(); diff --git a/src/southbridge/intel/lynxpoint/early_usb.c b/src/southbridge/intel/lynxpoint/early_usb.c index ebd5c2c50a..24b991bac7 100644 --- a/src/southbridge/intel/lynxpoint/early_usb.c +++ b/src/southbridge/intel/lynxpoint/early_usb.c @@ -48,9 +48,11 @@ void enable_usb_bar(void) pci_write_config32(usb0, PCI_COMMAND, cmd); /* USB Controller 1 */ - pci_write_config32(usb1, PCI_BASE_ADDRESS_0, - PCH_EHCI1_TEMP_BAR0); - cmd = pci_read_config32(usb1, PCI_COMMAND); - cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; - pci_write_config32(usb1, PCI_COMMAND, cmd); + if (!pch_is_lp()) { + pci_write_config32(usb1, PCI_BASE_ADDRESS_0, + PCH_EHCI2_TEMP_BAR0); + cmd = pci_read_config32(usb1, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb1, PCI_COMMAND, cmd); + } } diff --git a/src/southbridge/intel/lynxpoint/finalize.c b/src/southbridge/intel/lynxpoint/finalize.c index d9bc22531c..e3f9cf0fd9 100644 --- a/src/southbridge/intel/lynxpoint/finalize.c +++ b/src/southbridge/intel/lynxpoint/finalize.c @@ -21,10 +21,14 @@ #include #include #include +#include "me.h" #include "pch.h" void intel_pch_finalize_smm(void) { + /* Lock down Management Engine */ + intel_me_finalize_smm(); + /* Set SPI opcode menu */ RCBA16(0x3894) = SPI_OPPREFIX; RCBA16(0x3896) = SPI_OPTYPE; @@ -54,6 +58,9 @@ void intel_pch_finalize_smm(void) /* GEN_PMCON Lock */ pci_or_config8(PCH_LPC_DEV, 0xa6, (1 << 1) | (1 << 2)); + /* PMSYNC */ + RCBA32_OR(PMSYNC_CONFIG, (1 << 31)); + /* R/WO registers */ RCBA32(0x21a4) = RCBA32(0x21a4); pci_write_config32(PCI_DEV(0, 27, 0), 0x74, diff --git a/src/southbridge/intel/lynxpoint/gpio.c b/src/southbridge/intel/lynxpoint/gpio.c index b492068ccd..3ae8288856 100644 --- a/src/southbridge/intel/lynxpoint/gpio.c +++ b/src/southbridge/intel/lynxpoint/gpio.c @@ -29,7 +29,7 @@ static u16 get_gpio_base(void) { -#ifdef __PRE_RAM__ +#if defined(__PRE_RAM__) || defined(__SMM__) return pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc; #else return pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), @@ -109,3 +109,41 @@ unsigned get_gpios(const int *gpio_num_array) } return vector; } + +void set_gpio(int gpio_num, int value) +{ + static const int gpio_reg_offsets[] = {0xc, 0x38, 0x48}; + u16 gpio_base = get_gpio_base(); + int index, bit; + u32 config; + + if (gpio_num > MAX_GPIO_NUMBER) + return; /* Just ignore wrong gpio numbers. */ + + index = gpio_num / 32; + bit = gpio_num % 32; + + config = inl(gpio_base + gpio_reg_offsets[index]); + config &= ~(1 << bit); + config |= value << bit; + outl(config, gpio_base + gpio_reg_offsets[index]); +} + +int gpio_is_native(int gpio_num) +{ + static const int gpio_reg_offsets[] = { + GPIO_USE_SEL, GPIO_USE_SEL2, GPIO_USE_SEL3 + }; + u16 gpio_base = get_gpio_base(); + int index, bit; + u32 config; + + if (gpio_num > MAX_GPIO_NUMBER) + return 0; /* Just ignore wrong gpio numbers. */ + + index = gpio_num / 32; + bit = gpio_num % 32; + + config = inl(gpio_base + gpio_reg_offsets[index]); + return !(config & (1 << bit)); +} diff --git a/src/southbridge/intel/lynxpoint/hda_verb.c b/src/southbridge/intel/lynxpoint/hda_verb.c new file mode 100644 index 0000000000..234a1ab439 --- /dev/null +++ b/src/southbridge/intel/lynxpoint/hda_verb.c @@ -0,0 +1,254 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "pch.h" +#include "hda_verb.h" + +/** + * Set bits in a register and wait for status + */ +static int set_bits(u32 port, u32 mask, u32 val) +{ + u32 reg32; + int count; + + /* Write (val & mask) to port */ + val &= mask; + reg32 = read32(port); + reg32 &= ~mask; + reg32 |= val; + write32(port, reg32); + + /* Wait for readback of register to + * match what was just written to it + */ + count = 50; + do { + /* Wait 1ms based on BKDG wait time */ + mdelay(1); + reg32 = read32(port); + reg32 &= mask; + } while ((reg32 != val) && --count); + + /* Timeout occurred */ + if (!count) + return -1; + return 0; +} + +/** + * Probe for supported codecs + */ +int hda_codec_detect(u32 base) +{ + u8 reg8; + + /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ + if (set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST) < 0) + goto no_codec; + + /* Write back the value once reset bit is set. */ + write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG)); + + /* Read in Codec location (BAR + 0xe)[2..0]*/ + reg8 = read8(base + HDA_STATESTS_REG); + reg8 &= 0x0f; + if (!reg8) + goto no_codec; + + return reg8; + +no_codec: + /* Codec Not found */ + /* Put HDA back in reset (BAR + 0x8) [0] */ + set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, 0); + printk(BIOS_DEBUG, "HDA: No codec!\n"); + return 0; +} + +/** + * Wait 50usec for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ +static int hda_wait_for_ready(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + + while(timeout--) { + u32 reg32 = read32(base + HDA_ICII_REG); + if (!(reg32 & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ +static int hda_wait_for_valid(u32 base) +{ + u32 reg32; + + /* Send the verb to the codec */ + reg32 = read32(base + HDA_ICII_REG); + reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID; + write32(base + HDA_ICII_REG, reg32); + + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + while(timeout--) { + reg32 = read32(base + HDA_ICII_REG); + if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Find a specific entry within a verb table + * + * @verb_table_bytes: verb table size in bytes + * @verb_table_data: verb table data + * @viddid: vendor/device to search for + * @verb_out: pointer to entry within table + * + * Returns size of the entry within the verb table, + * Returns 0 if the entry is not found + * + * The HDA verb table is composed of dwords. A set of 4 dwords is + * grouped together to form a "jack" descriptor. + * Bits 31:28 - Codec Address + * Bits 27:20 - NID + * Bits 19:8 - Verb ID + * Bits 7:0 - Payload + * + * coreboot groups different codec verb tables into a single table + * and prefixes each with a specific header consisting of 3 + * dword entries: + * 1 - Codec Vendor/Device ID + * 2 - Subsystem ID + * 3 - Number of jacks (groups of 4 dwords) for this codec + */ +static u32 hda_find_verb(u32 verb_table_bytes, + const u32 *verb_table_data, + u32 viddid, const u32 ** verb) +{ + int idx=0; + + while (idx < (verb_table_bytes / sizeof(u32))) { + u32 verb_size = 4 * verb_table_data[idx+2]; // in u32 + if (verb_table_data[idx] != viddid) { + idx += verb_size + 3; // skip verb + header + continue; + } + *verb = &verb_table_data[idx+3]; + return verb_size; + } + + /* Not all codecs need to load another verb */ + return 0; +} + +/** + * Write a supplied verb table + */ +int hda_codec_write(u32 base, u32 size, const u32 *data) +{ + int i; + + for (i = 0; i < size; i++) { + if (hda_wait_for_ready(base) < 0) + return -1; + + write32(base + HDA_IC_REG, data[i]); + + if (hda_wait_for_valid(base) < 0) + return -1; + } + + return 0; +} + +/** + * Initialize codec, then find the verb table and write it + */ +int hda_codec_init(u32 base, int addr, int verb_size, const u32 *verb_data) +{ + const u32 *verb; + u32 reg32, size; + int rc; + + printk(BIOS_DEBUG, "HDA: Initializing codec #%d\n", addr); + + if (!verb_size || !verb_data) { + printk(BIOS_DEBUG, "HDA: No verb list!\n"); + return -1; + } + + /* 1 */ + if (hda_wait_for_ready(base) < 0) { + printk(BIOS_DEBUG, " codec not ready.\n"); + return -1; + } + + reg32 = (addr << 28) | 0x000f0000; + write32(base + HDA_IC_REG, reg32); + + if (hda_wait_for_valid(base) < 0) { + printk(BIOS_DEBUG, " codec not valid.\n"); + return -1; + } + + /* 2 */ + reg32 = read32(base + HDA_IR_REG); + printk(BIOS_DEBUG, "HDA: codec viddid: %08x\n", reg32); + + size = hda_find_verb(verb_size, verb_data, reg32, &verb); + if (!size) { + printk(BIOS_DEBUG, "HDA: No verb table entry found\n"); + return -1; + } + + /* 3 */ + rc = hda_codec_write(base, size, verb); + + if (rc < 0) + printk(BIOS_DEBUG, "HDA: verb not loaded\n"); + else + printk(BIOS_DEBUG, "HDA: verb loaded.\n"); + + return rc; +} diff --git a/src/southbridge/intel/lynxpoint/hda_verb.h b/src/southbridge/intel/lynxpoint/hda_verb.h new file mode 100644 index 0000000000..8b3d27e1c2 --- /dev/null +++ b/src/southbridge/intel/lynxpoint/hda_verb.h @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LYNXPOINT_HDA_VERB_H +#define LYNXPOINT_HDA_VERB_H + +#define HDA_GCAP_REG 0x00 +#define HDA_GCTL_REG 0x08 +#define HDA_GCTL_CRST (1 << 0) +#define HDA_STATESTS_REG 0x0e +#define HDA_IC_REG 0x60 +#define HDA_IR_REG 0x64 +#define HDA_ICII_REG 0x68 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + +int hda_codec_detect(u32 base); +int hda_codec_write(u32 base, u32 size, const u32 *data); +int hda_codec_init(u32 base, int addr, int verb_size, const u32 *verb_data); + +#endif diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.c b/src/southbridge/intel/lynxpoint/lp_gpio.c index a6e4f5c998..20a9e0389f 100644 --- a/src/southbridge/intel/lynxpoint/lp_gpio.c +++ b/src/southbridge/intel/lynxpoint/lp_gpio.c @@ -28,7 +28,7 @@ static u16 get_gpio_base(void) { -#ifdef __PRE_RAM__ +#if defined(__PRE_RAM__) || defined(__SMM__) return pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc; #else return pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), @@ -36,6 +36,35 @@ static u16 get_gpio_base(void) #endif } + +/* + * This function will return a number that indicates which PIRQ + * this GPIO maps to. If this is not a PIRQ capable GPIO then + * it will return -1. The GPIO to PIRQ mapping is not linear. + */ +static int lp_gpio_to_pirq(int gpio) +{ + switch (gpio) { + case 8: return 0; /* PIRQI */ + case 9: return 1; /* PIRQJ */ + case 10: return 2; /* PIRQK */ + case 13: return 3; /* PIRQL */ + case 14: return 4; /* PIRQM */ + case 45: return 5; /* PIRQN */ + case 46: return 6; /* PIRQO */ + case 47: return 7; /* PIRQP */ + case 48: return 8; /* PIRQQ */ + case 49: return 9; /* PIRQR */ + case 50: return 10; /* PIRQS */ + case 51: return 11; /* PIRQT */ + case 52: return 12; /* PIRQU */ + case 53: return 13; /* PIRQV */ + case 54: return 14; /* PIRQW */ + case 55: return 15; /* PIRQX */ + default: return -1; + }; +} + void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) { u16 gpio_base = get_gpio_base(); @@ -45,19 +74,20 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) u32 irqen[3] = {0}; u32 reset[3] = {0}; u32 blink = 0; - int set, bit; + u16 pirq2apic = 0; + int set, bit, gpio = 0; - for (config = map; config->gpio != GPIO_LIST_END; config++) { - if (config->gpio > MAX_GPIO_NUMBER) - continue; + for (config = map; config->conf0 != GPIO_LIST_END; config++, gpio++) { + if (gpio > MAX_GPIO_NUMBER) + break; /* Setup Configuration registers 1 and 2 */ - outl(config->conf0, gpio_base + GPIO_CONFIG0(config->gpio)); - outl(config->conf1, gpio_base + GPIO_CONFIG1(config->gpio)); + outl(config->conf0, gpio_base + GPIO_CONFIG0(gpio)); + outl(config->conf1, gpio_base + GPIO_CONFIG1(gpio)); /* Determine set and bit based on GPIO number */ - set = config->gpio >> 5; - bit = config->gpio % 32; + set = gpio >> 5; + bit = gpio % 32; /* Apply settings to set specific bits */ owner[set] |= config->owner << bit; @@ -67,6 +97,13 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) if (set == 0) blink |= config->blink << bit; + + /* PIRQ to IO-APIC map */ + if (config->pirq == GPIO_PIRQ_APIC_ROUTE) { + set = lp_gpio_to_pirq(gpio); + if (set >= 0) + pirq2apic |= 1 << set; + } } for (set = 0; set <= 2; set++) { @@ -77,13 +114,14 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) } outl(blink, gpio_base + GPIO_BLINK); + outl(pirq2apic, gpio_base + GPIO_PIRQ_APIC_EN); } int get_gpio(int gpio_num) { u16 gpio_base = get_gpio_base(); - if (gpio_num < MAX_GPIO_NUMBER) + if (gpio_num > MAX_GPIO_NUMBER) return 0; return !!(inl(gpio_base + GPIO_CONFIG0(gpio_num)) & GPI_LEVEL); @@ -107,3 +145,24 @@ unsigned get_gpios(const int *gpio_num_array) } return vector; } + +void set_gpio(int gpio_num, int value) +{ + u16 gpio_base = get_gpio_base(); + u32 conf0; + + if (gpio_num > MAX_GPIO_NUMBER) + return; + + conf0 = inl(gpio_base + GPIO_CONFIG0(gpio_num)); + conf0 &= ~GPO_LEVEL_MASK; + conf0 |= value << GPO_LEVEL_SHIFT; + outl(conf0, gpio_base + GPIO_CONFIG0(gpio_num)); +} + +int gpio_is_native(int gpio_num) +{ + u16 gpio_base = get_gpio_base(); + + return !(inl(gpio_base + GPIO_CONFIG0(gpio_num)) & 1); +} diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.h b/src/southbridge/intel/lynxpoint/lp_gpio.h index 9666adc6e4..38da9e2c5c 100644 --- a/src/southbridge/intel/lynxpoint/lp_gpio.h +++ b/src/southbridge/intel/lynxpoint/lp_gpio.h @@ -36,7 +36,7 @@ #define GPIO_CONFIG1(gpio) (0x104 + ((gpio) * 8)) #define MAX_GPIO_NUMBER 94 /* zero based */ -#define GPIO_LIST_END 0xff +#define GPIO_LIST_END 0xffffffff /* conf0 */ @@ -54,8 +54,10 @@ #define GPI_LEVEL (1 << 30) -#define GPO_LEVEL_LOW (0 << 31) -#define GPO_LEVEL_HIGH (1 << 31) +#define GPO_LEVEL_SHIFT 31 +#define GPO_LEVEL_MASK (1 << GPO_LEVEL_SHIFT) +#define GPO_LEVEL_LOW (0 << GPO_LEVEL_SHIFT) +#define GPO_LEVEL_HIGH (1 << GPO_LEVEL_SHIFT) /* conf1 */ @@ -91,6 +93,65 @@ #define GPIO_RESET_PWROK 0 #define GPIO_RESET_RSMRST 1 +/* pirq route to io-apic */ + +#define GPIO_PIRQ_APIC_MASK 0 +#define GPIO_PIRQ_APIC_ROUTE 1 + +#define LP_GPIO_END \ + { .conf0 = GPIO_LIST_END } + +#define LP_GPIO_NATIVE \ + { .conf0 = GPIO_MODE_NATIVE } + +#define LP_GPIO_UNUSED \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + +#define LP_GPIO_ACPI_SCI \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_ACPI, \ + .route = GPIO_ROUTE_SCI } + +#define LP_GPIO_ACPI_SMI \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_ACPI, \ + .route = GPIO_ROUTE_SMI } + +#define LP_GPIO_INPUT \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO } + +#define LP_GPIO_INPUT_INVERT \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_INVERT, \ + .owner = GPIO_OWNER_GPIO } + +#define LP_GPIO_IRQ_EDGE \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_EDGE, \ + .owner = GPIO_OWNER_GPIO, \ + .irqen = GPIO_IRQ_ENABLE } + +#define LP_GPIO_IRQ_LEVEL \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT | GPIO_IRQ_LEVEL, \ + .owner = GPIO_OWNER_GPIO, \ + .irqen = GPIO_IRQ_ENABLE } + +#define LP_GPIO_PIRQ \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO, \ + .pirq = GPIO_PIRQ_APIC_ROUTE } + +#define LP_GPIO_OUT_HIGH \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + +#define LP_GPIO_OUT_LOW \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_LOW, \ + .owner = GPIO_OWNER_GPIO, \ + .conf1 = GPIO_SENSE_DISABLE } + struct pch_lp_gpio_map { u8 gpio; u32 conf0; @@ -100,6 +161,7 @@ struct pch_lp_gpio_map { u8 irqen; u8 reset; u8 blink; + u8 pirq; } __attribute__ ((packed)); /* Configure GPIOs with mainboard provided settings */ diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c index f6c64c56a0..10efae53f1 100644 --- a/src/southbridge/intel/lynxpoint/lpc.c +++ b/src/southbridge/intel/lynxpoint/lpc.c @@ -61,6 +61,11 @@ static void pch_enable_apic(struct device *dev) /* affirm full set of redirection table entries ("write once") */ *ioapic_index = 1; reg32 = *ioapic_data; + if (pch_is_lp()) { + /* PCH-LP has 39 redirection entries */ + reg32 &= ~0x00ff0000; + reg32 |= 0x00270000; + } *ioapic_index = 1; *ioapic_data = reg32; @@ -204,6 +209,7 @@ static void pch_power_options(device_t dev) * If the option is not existent (Laptops), use Kconfig setting. */ get_option(&pwr_on, "power_on_after_fail"); + pwr_on = MAINBOARD_POWER_KEEP; reg16 = pci_read_config16(dev, GEN_PMCON_3); reg16 &= 0xfffe; @@ -307,7 +313,7 @@ static void pch_rtc_init(struct device *dev) } printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed); - rtc_init(rtc_failed); + cmos_init(rtc_failed); } /* LynxPoint PCH Power Management init */ @@ -317,50 +323,51 @@ static void lpt_pm_init(struct device *dev) } const struct rcba_config_instruction lpt_lp_pm_rcba[] = { - RCBA_RMW_REG_32(0x232c, ~1, 0x00000000), /* 4 */ - RCBA_RMW_REG_32(0x1100, ~0, 0x0000c000), /* 5 */ - RCBA_RMW_REG_32(0x1100, ~0, 0x00000100), /* 6 */ - RCBA_RMW_REG_32(0x1100, ~0, 0x0000003f), /* 7 */ - RCBA_RMW_REG_32(0x2320, ~0x60, 0x10), /* 8? */ - RCBA_RMW_REG_32(0x3314, 0, 0x00012fff), /* 9? */ - RCBA_RMW_REG_32(0x3318, 0, 0x0dcf0400), /* 10? */ - RCBA_RMW_REG_32(0x3324, 0, 0x04000000), /* 11 */ - RCBA_RMW_REG_32(0x3368, 0, 0x00041400), /* 12? */ - RCBA_RMW_REG_32(0x3388, 0, 0x3f8ddbff), /* 13? */ - RCBA_RMW_REG_32(0x33ac, 0, 0x00007001), /* 14? */ - RCBA_RMW_REG_32(0x33b0, 0, 0x00181900), /* 15? */ - RCBA_RMW_REG_32(0x33c0, 0, 0x00060A00), /* 16? */ - RCBA_RMW_REG_32(0x33d0, 0, 0x06200840), /* 17? */ - RCBA_RMW_REG_32(0x3a28, 0, 0x01010101), /* 19 */ - RCBA_RMW_REG_32(0x3a2c, 0, 0x04040404), /* 20 */ - RCBA_RMW_REG_32(0x2b1c, 0, 0x03808033), /* 23? */ - RCBA_RMW_REG_32(0x2b34, 0, 0x80000008), /* 24 */ - RCBA_RMW_REG_32(0x3348, 0, 0x022ddfff), /* 25? */ - RCBA_RMW_REG_32(0x334c, 0, 0x00000001), /* 26 */ - RCBA_RMW_REG_32(0x3358, 0, 0x0001c000), /* 27 */ - RCBA_RMW_REG_32(0x3380, 0, 0x3f8ddbff), /* 28 */ - RCBA_RMW_REG_32(0x3384, 0, 0x0001c7e1), /* 29 */ - RCBA_RMW_REG_32(0x338c, 0, 0x0001c7e1), /* ? */ - RCBA_RMW_REG_32(0x3398, 0, 0x0001c000), /* 30 */ - RCBA_RMW_REG_32(0x33a8, 0, 0x00181900), /* 31? */ - RCBA_RMW_REG_32(0x33dc, 0, 0x00080000), /* 32 */ - RCBA_RMW_REG_32(0x33e0, 0, 0x00000001), /* 33 */ - RCBA_RMW_REG_32(0x3a20, 0, 0x00000404), /* 34 */ - RCBA_RMW_REG_32(0x3a24, 0, 0x01010101), /* 35 */ - RCBA_RMW_REG_32(0x3a30, 0, 0x01010101), /* 36 */ - RCBA_RMW_REG_32(0x0410, ~0, 0x00000003), /* 42 */ - RCBA_RMW_REG_32(0x2618, ~0, 0x08000000), /* 43 */ - RCBA_RMW_REG_32(0x2600, ~0, 0x00000008), /* 44 */ - RCBA_RMW_REG_32(0x33b4, 0, 0x00007001), /* 46? */ - RCBA_RMW_REG_32(0x3350, 0, 0x022ddfff), /* 47? */ - RCBA_RMW_REG_32(0x3354, 0, 0x00000001), /* ? */ + RCBA_RMW_REG_32(0x232c, ~1, 0x00000000), + RCBA_RMW_REG_32(0x1100, ~0xc000, 0xc000), + RCBA_RMW_REG_32(0x1100, ~0, 0x00000100), + RCBA_RMW_REG_32(0x1100, ~0, 0x0000003f), + RCBA_RMW_REG_32(0x2320, ~0x60, 0x10), + RCBA_RMW_REG_32(0x3314, 0, 0x00012fff), + RCBA_RMW_REG_32(0x3318, 0, 0x0dcf0400), + RCBA_RMW_REG_32(0x3324, 0, 0x04000000), + RCBA_RMW_REG_32(0x3368, 0, 0x00041400), + RCBA_RMW_REG_32(0x3388, 0, 0x3f8ddbff), + RCBA_RMW_REG_32(0x33ac, 0, 0x00007001), + RCBA_RMW_REG_32(0x33b0, 0, 0x00181900), + RCBA_RMW_REG_32(0x33c0, 0, 0x00060A00), + RCBA_RMW_REG_32(0x33d0, 0, 0x06200840), + RCBA_RMW_REG_32(0x3a28, 0, 0x01010101), + RCBA_RMW_REG_32(0x3a2c, 0, 0x04040404), + RCBA_RMW_REG_32(0x2b1c, 0, 0x03808033), + RCBA_RMW_REG_32(0x2b34, 0, 0x80000009), + RCBA_RMW_REG_32(0x3348, 0, 0x022ddfff), + RCBA_RMW_REG_32(0x334c, 0, 0x00000001), + RCBA_RMW_REG_32(0x3358, 0, 0x0001c000), + RCBA_RMW_REG_32(0x3380, 0, 0x3f8ddbff), + RCBA_RMW_REG_32(0x3384, 0, 0x0001c7e1), + RCBA_RMW_REG_32(0x338c, 0, 0x0001c7e1), + RCBA_RMW_REG_32(0x3398, 0, 0x0001c000), + RCBA_RMW_REG_32(0x33a8, 0, 0x00181900), + RCBA_RMW_REG_32(0x33dc, 0, 0x00080000), + RCBA_RMW_REG_32(0x33e0, 0, 0x00000001), + RCBA_RMW_REG_32(0x3a20, 0, 0x00000404), + RCBA_RMW_REG_32(0x3a24, 0, 0x01010101), + RCBA_RMW_REG_32(0x3a30, 0, 0x01010101), + RCBA_RMW_REG_32(0x0410, ~0, 0x00000003), + RCBA_RMW_REG_32(0x2618, ~0, 0x08000000), + RCBA_RMW_REG_32(0x2300, ~0, 0x00000002), + RCBA_RMW_REG_32(0x2600, ~0, 0x00000008), + RCBA_RMW_REG_32(0x33b4, 0, 0x00007001), + RCBA_RMW_REG_32(0x3350, 0, 0x022ddfff), + RCBA_RMW_REG_32(0x3354, 0, 0x00000001), RCBA_RMW_REG_32(0x33d4, ~0, 0x08000000), /* Power Optimizer */ RCBA_RMW_REG_32(0x33c8, ~0, 0x08000080), /* Power Optimizer */ RCBA_RMW_REG_32(0x2b10, 0, 0x0000883c), /* Power Optimizer */ - RCBA_RMW_REG_32(0x2b14, 0, 0x1e0a4610), /* Power Optimizer */ + RCBA_RMW_REG_32(0x2b14, 0, 0x1e0a4616), /* Power Optimizer */ RCBA_RMW_REG_32(0x2b24, 0, 0x40000005), /* Power Optimizer */ RCBA_RMW_REG_32(0x2b20, 0, 0x0005db01), /* Power Optimizer */ - RCBA_RMW_REG_32(0x3a80, 0, 0x05145005), /* 21? */ + RCBA_RMW_REG_32(0x3a80, 0, 0x05145005), RCBA_END_CONFIG }; @@ -379,6 +386,9 @@ static void lpt_lp_pm_init(struct device *dev) pci_write_config32(dev, 0xac, pci_read_config32(dev, 0xac) | (1 << 21)); + pch_iobp_update(0xED00015C, ~(1<<11), 0x00003700); + pch_iobp_update(0xED000118, ~0UL, 0x00c00000); + pch_iobp_update(0xED000120, ~0UL, 0x00240000); pch_iobp_update(0xCA000000, ~0UL, 0x00000009); /* Set RCBA CIR28 0x3A84 based on SATA port enables */ @@ -391,6 +401,10 @@ static void lpt_lp_pm_init(struct device *dev) data |= (1 << 20) | (1 << 18); RCBA32(0x3a84) = data; + /* Set RCBA 0x2b1c[29]=1 if DSP disabled */ + if (RCBA32(FD) & PCH_DISABLE_ADSPD) + RCBA32_OR(0x2b1c, (1 << 29)); + /* Lock */ RCBA32_OR(0x3a6c, 0x00000001); @@ -457,7 +471,18 @@ static void enable_lp_clock_gating(device_t dev) reg32 |= (1 << 6); pci_write_config32(dev, 0x64, reg32); + /* + * RCBA + 0x2614[27:25,14:13,10,8] = 101,11,1,1 + * RCBA + 0x2614[23:16] = 0x20 + * RCBA + 0x2614[30:28] = 0x0 + * RCBA + 0x2614[26] = 1 (IF 0:2.0@0x08 >= 0x0b) + */ RCBA32_AND_OR(0x2614, 0x8bffffff, 0x0a206500); + + /* Check for LPT-LP B2 stepping and 0:31.0@0xFA > 4 */ + if (pci_read_config8(dev_find_slot(0, PCI_DEVFN(2, 0)), 0x8) >= 0x0b) + RCBA32_OR(0x2614, (1<<26)); + RCBA32_OR(0x900, 0x0000031f); reg32 = RCBA32(CG); @@ -465,12 +490,15 @@ static void enable_lp_clock_gating(device_t dev) reg32 &= ~(1 << 29); // LPC Dynamic else reg32 |= (1 << 29); // LPC Dynamic - reg32 |= (1 << 30); // LP LPC + reg32 |= (1 << 31); // LP LPC + reg32 |= (1 << 30); // LP BLA reg32 |= (1 << 28); // GPIO Dynamic reg32 |= (1 << 27); // HPET Dynamic - reg32 |= (1 << 26); // LP LPC + reg32 |= (1 << 26); // Generic Platform Event Clock + if (RCBA32(BUC) & PCH_DISABLE_GBE) + reg32 |= (1 << 23); // GbE Static reg32 |= (1 << 22); // HDA Dynamic - reg32 |= (1 << 16); // PCIe Dynamic + reg32 |= (1 << 16); // PCI Dynamic RCBA32(CG) = reg32; RCBA32_OR(0x3434, 0x7); // LP LPC @@ -480,7 +508,7 @@ static void enable_lp_clock_gating(device_t dev) RCBA32_OR(0x38c0, 0x3c07); // SPI Dynamic pch_iobp_update(0xCF000000, ~0UL, 0x00007001); - pch_iobp_update(0xCE00C000, ~0UL, 0x00000001); + pch_iobp_update(0xCE00C000, ~1UL, 0x00000000); // bit0=0 in BWG 1.4.0 } static void pch_set_acpi_mode(void) @@ -527,18 +555,6 @@ static void pch_fixups(struct device *dev) RCBA32_OR(0x21a8, 0x3); } -static void pch_decode_init(struct device *dev) -{ - config_t *config = dev->chip_info; - - printk(BIOS_DEBUG, "pch_decode_init\n"); - - pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec); - pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec); - pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec); - pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec); -} - static void lpc_init(struct device *dev) { printk(BIOS_DEBUG, "pch: lpc_init\n"); @@ -715,16 +731,10 @@ static void pch_lpc_read_resources(device_t dev) /* Allocate ACPI NVS in CBMEM */ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(global_nvs_t)); - if (gnvs) + if (acpi_slp_type != 3 && gnvs) memset(gnvs, 0, sizeof(global_nvs_t)); } -static void pch_lpc_enable_resources(device_t dev) -{ - pch_decode_init(dev); - return pci_dev_enable_resources(dev); -} - static void pch_lpc_enable(device_t dev) { /* Enable PCH Display Port */ @@ -752,7 +762,7 @@ static struct pci_operations pci_ops = { static struct device_operations device_ops = { .read_resources = pch_lpc_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pch_lpc_enable_resources, + .enable_resources = pci_dev_enable_resources, .init = lpc_init, .enable = pch_lpc_enable, .scan_bus = scan_static_bus, diff --git a/src/southbridge/intel/lynxpoint/me.h b/src/southbridge/intel/lynxpoint/me.h index a30582293d..a72778b88f 100644 --- a/src/southbridge/intel/lynxpoint/me.h +++ b/src/southbridge/intel/lynxpoint/me.h @@ -286,6 +286,24 @@ struct me_fw_version { u16 recovery_hot_fix; } __attribute__ ((packed)); +/* ICC Messages */ +#define ICC_SET_CLOCK_ENABLES 0x3 +#define ICC_API_VERSION_LYNXPOINT 0x00030000 + +struct icc_header { + u32 api_version; + u32 icc_command; + u32 icc_status; + u32 length; + u32 reserved; +} __attribute__ ((packed)); + +struct icc_clock_enables_msg { + u32 clock_enables; + u32 clock_mask; + u32 no_response: 1; + u32 reserved: 31; +} __attribute__ ((packed)); #define HECI_EOP_STATUS_SUCCESS 0x0 #define HECI_EOP_PERFORM_GLOBAL_RESET 0x1 @@ -334,6 +352,7 @@ void intel_me8_finalize_smm(void); #define MBP_APPID_INTEL_AT 3 #define MBP_APPID_HWA 4 #define MBP_APPID_ICC 5 +#define MBP_APPID_NFC 6 /* Kernel items: */ #define MBP_KERNEL_FW_VER_ITEM 1 #define MBP_KERNEL_FW_CAP_ITEM 2 @@ -341,12 +360,15 @@ void intel_me8_finalize_smm(void); #define MBP_KERNEL_PLAT_KEY_ITEM 4 #define MBP_KERNEL_FW_TYPE_ITEM 5 #define MBP_KERNEL_MFS_FAILURE_ITEM 6 +#define MBP_KERNEL_PLAT_TIME_ITEM 7 /* Intel AT items: */ #define MBP_INTEL_AT_STATE_ITEM 1 /* ICC Items: */ #define MBP_ICC_PROFILE_ITEM 1 /* HWA Items: */ #define MBP_HWA_REQUEST_ITEM 1 +/* NFC Items: */ +#define MBP_NFC_SUPPORT_DATA_ITEM 1 #define MBP_MAKE_IDENT(appid, item) ((appid << 8) | item) #define MBP_IDENT(appid, item) \ @@ -452,6 +474,17 @@ typedef struct { tdt_state_flag flags; } __attribute__ ((packed)) mbp_at_state; +typedef struct { + u32 wake_event_mrst_time_ms; + u32 mrst_pltrst_time_ms; + u32 pltrst_cpurst_time_ms; +} __attribute__ ((packed)) mbp_plat_time; + +typedef struct { + u32 device_type : 2; + u32 reserved : 30; +} __attribute__ ((packed)) mbp_nfc_data; + typedef struct { mbp_fw_version_name *fw_version_name; mbp_mefwcaps *fw_capabilities; @@ -461,6 +494,8 @@ typedef struct { mbp_icc_profile *icc_profile; mbp_at_state *at_state; u32 *mfsintegrity; + mbp_plat_time *plat_time; + mbp_nfc_data *nfc_data; } me_bios_payload; struct me_fwcaps { diff --git a/src/southbridge/intel/lynxpoint/me_9.x.c b/src/southbridge/intel/lynxpoint/me_9.x.c index a16879b757..d3dfcfb152 100644 --- a/src/southbridge/intel/lynxpoint/me_9.x.c +++ b/src/southbridge/intel/lynxpoint/me_9.x.c @@ -62,6 +62,7 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev); /* MMIO base address for MEI interface */ static u32 mei_base_address; +void intel_me_mbp_clear(device_t dev); #if CONFIG_DEBUG_INTEL_ME static void mei_dump(void *ptr, int dword, int offset, const char *type) @@ -116,14 +117,12 @@ static inline void mei_write_dword_ptr(void *ptr, int offset) mei_dump(ptr, dword, offset, "WRITE"); } -#ifndef __SMM__ static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset) { u32 dword = pci_read_config32(dev, offset); memcpy(ptr, &dword, sizeof(dword)); mei_dump(ptr, dword, offset, "PCI READ"); } -#endif static inline void read_host_csr(struct mei_csr *csr) { @@ -194,21 +193,20 @@ static void mei_reset(void) write_host_csr(&host); } -static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, - void *req_data) +static int mei_send_packet(struct mei_header *mei, void *req_data) { struct mei_csr host; unsigned ndata, n; u32 *data; - /* Number of dwords to write, ignoring MKHI */ + /* Number of dwords to write */ ndata = mei->length >> 2; /* Pad non-dword aligned request message length */ if (mei->length & 3) ndata++; if (!ndata) { - printk(BIOS_DEBUG, "ME: request does not include MKHI\n"); + printk(BIOS_DEBUG, "ME: request has no data\n"); return -1; } ndata++; /* Add MEI header */ @@ -224,11 +222,7 @@ static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, read_host_csr(&host); } - /* - * This implementation does not handle splitting large messages - * across multiple transactions. Ensure the requested length - * will fit in the available circular buffer depth. - */ + /* Ensure the requested length will fit in the circular buffer. */ if ((host.buffer_depth - host.buffer_write_ptr) < ndata) { printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n", ndata + 2, host.buffer_depth); @@ -239,10 +233,6 @@ static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, mei_write_dword_ptr(mei, MEI_H_CB_WW); ndata--; - /* Write MKHI header */ - mei_write_dword_ptr(mkhi, MEI_H_CB_WW); - ndata--; - /* Write message data */ data = req_data; for (n = 0; n < ndata; ++n) @@ -257,21 +247,71 @@ static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, return mei_wait_for_me_ready(); } -static int mei_recv_msg(struct mkhi_header *mkhi, +static int mei_send_data(u8 me_address, u8 host_address, + void *req_data, int req_bytes) +{ + struct mei_header header = { + .client_address = me_address, + .host_address = host_address, + }; + struct mei_csr host; + int current = 0; + u8 *req_ptr = req_data; + + while (!header.is_complete) { + int remain = req_bytes - current; + int buf_len; + + read_host_csr(&host); + buf_len = host.buffer_depth - host.buffer_write_ptr; + + if (buf_len > remain) { + /* Send all remaining data as final message */ + header.length = req_bytes - current; + header.is_complete = 1; + } else { + /* Send as much data as the buffer can hold */ + header.length = buf_len; + } + + mei_send_packet(&header, req_ptr); + + req_ptr += header.length; + current += header.length; + } + + return 0; +} + +static int mei_send_header(u8 me_address, u8 host_address, + void *header, int header_len, int complete) +{ + struct mei_header mei = { + .client_address = me_address, + .host_address = host_address, + .length = header_len, + .is_complete = complete, + }; + return mei_send_packet(&mei, header); +} + +static int mei_recv_msg(void *header, int header_bytes, void *rsp_data, int rsp_bytes) { struct mei_header mei_rsp; - struct mkhi_header mkhi_rsp; struct mei_csr me, host; - unsigned ndata, n/*, me_data_len*/; + unsigned ndata, n; unsigned expected; u32 *data; /* Total number of dwords to read from circular buffer */ - expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2; + expected = (rsp_bytes + sizeof(mei_rsp) + header_bytes) >> 2; if (rsp_bytes & 3) expected++; + if (mei_wait_for_me_ready() < 0) + return -1; + /* * The interrupt status bit does not appear to indicate that the * message has actually been received. Instead we wait until the @@ -297,7 +337,7 @@ static int mei_recv_msg(struct mkhi_header *mkhi, return -1; } - /* Handle non-dword responses and expect at least MKHI header */ + /* Handle non-dword responses and expect at least the header */ ndata = mei_rsp.length >> 2; if (mei_rsp.length & 3) ndata++; @@ -307,18 +347,11 @@ static int mei_recv_msg(struct mkhi_header *mkhi, return -1; } - /* Read and verify MKHI response header from the ME */ - mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW); - if (!mkhi_rsp.is_response || - mkhi->group_id != mkhi_rsp.group_id || - mkhi->command != mkhi_rsp.command) { - printk(BIOS_ERR, "ME: invalid response, group %u ?= %u," - "command %u ?= %u, is_response %u\n", mkhi->group_id, - mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command, - mkhi_rsp.is_response); - return -1; - } - ndata--; /* MKHI header has been read */ + /* Read response header from the ME */ + data = header; + for (n = 0; n < (header_bytes >> 2); ++n) + *data++ = read_cb(); + ndata -= header_bytes >> 2; /* Make sure caller passed a buffer with enough space */ if (ndata != (rsp_bytes >> 2)) { @@ -341,16 +374,109 @@ static int mei_recv_msg(struct mkhi_header *mkhi, return mei_wait_for_me_ready(); } -static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi, - void *req_data, void *rsp_data, int rsp_bytes) +static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi, + void *req_data, int req_bytes, + void *rsp_data, int rsp_bytes) { - if (mei_send_msg(mei, mkhi, req_data) < 0) + struct mkhi_header mkhi_rsp; + + /* Send header */ + if (mei_send_header(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS, + mkhi, sizeof(*mkhi), req_bytes ? 0 : 1) < 0) return -1; - if (mei_recv_msg(mkhi, rsp_data, rsp_bytes) < 0) + + /* Send data if available */ + if (req_bytes && mei_send_data(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS, + req_data, req_bytes) < 0) return -1; + + /* Return now if no response expected */ + if (!rsp_bytes) + return 0; + + /* Read header and data */ + if (mei_recv_msg(&mkhi_rsp, sizeof(mkhi_rsp), + rsp_data, rsp_bytes) < 0) + return -1; + + if (!mkhi_rsp.is_response || + mkhi->group_id != mkhi_rsp.group_id || + mkhi->command != mkhi_rsp.command) { + printk(BIOS_ERR, "ME: invalid response, group %u ?= %u," + "command %u ?= %u, is_response %u\n", mkhi->group_id, + mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command, + mkhi_rsp.is_response); + return -1; + } + return 0; } +static inline int mei_sendrecv_icc(struct icc_header *icc, + void *req_data, int req_bytes, + void *rsp_data, int rsp_bytes) +{ + struct icc_header icc_rsp; + + /* Send header */ + if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS, + icc, sizeof(*icc), req_bytes ? 0 : 1) < 0) + return -1; + + /* Send data if available */ + if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS, + req_data, req_bytes) < 0) + return -1; + + /* Read header and data, if needed */ + if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp), + rsp_data, rsp_bytes) < 0) + return -1; + + return 0; +} + +/* + * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read + * state machine on the BIOS end doesn't match the ME's state machine. + */ +static void intel_me_mbp_give_up(device_t dev) +{ + struct mei_csr csr; + + pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP); + + read_host_csr(&csr); + csr.reset = 1; + csr.interrupt_generate = 1; + write_host_csr(&csr); +} + +/* + * mbp clear routine. This will wait for the ME to indicate that + * the MBP has been read and cleared. + */ +void intel_me_mbp_clear(device_t dev) +{ + int count; + struct me_hfs2 hfs2; + + /* Wait for the mbp_cleared indicator */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); + if (hfs2.mbp_cleared) + break; + udelay(ME_DELAY); + } + + if (count == 0) { + printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n"); + intel_me_mbp_give_up(dev); + } else { + printk(BIOS_INFO, "ME: MBP cleared\n"); + } +} + #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) && !defined(__SMM__) static inline void print_cap(const char *name, int state) { @@ -370,6 +496,7 @@ static void me_print_fw_version(mbp_fw_version_name *vers_name) vers_name->hotfix_version, vers_name->build_version); } +#if CONFIG_DEBUG_INTEL_ME /* Get ME Firmware Capabilities */ static int mkhi_get_fwcaps(mbp_mefwcaps *cap) { @@ -379,16 +506,10 @@ static int mkhi_get_fwcaps(mbp_mefwcaps *cap) .group_id = MKHI_GROUP_ID_FWCAPS, .command = MKHI_FWCAPS_GET_RULE, }; - struct mei_header mei = { - .is_complete = 1, - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - .length = sizeof(mkhi) + sizeof(rule_id), - }; /* Send request and wait for response */ - if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap_msg, sizeof(cap_msg)) - < 0) { + if (mei_sendrecv_mkhi(&mkhi, &rule_id, sizeof(u32), + &cap_msg, sizeof(cap_msg)) < 0) { printk(BIOS_ERR, "ME: GET FWCAPS message failed\n"); return -1; } @@ -423,6 +544,7 @@ static void me_print_fwcaps(mbp_mefwcaps *cap) print_cap("Wireless LAN (WLAN)", cap->wlan); } #endif +#endif #if CONFIG_CHROMEOS && 0 /* DISABLED */ /* Tell ME to issue a global reset */ @@ -436,16 +558,10 @@ static int mkhi_global_reset(void) .group_id = MKHI_GROUP_ID_CBM, .command = MKHI_GLOBAL_RESET, }; - struct mei_header mei = { - .is_complete = 1, - .length = sizeof(mkhi) + sizeof(reset), - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - }; /* Send request and wait for response */ printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__); - if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) { + if (mei_sendrecv_mkhi(&mkhi, &reset, sizeof(reset), NULL, 0) < 0) { /* No response means reset will happen shortly... */ hlt(); } @@ -465,18 +581,11 @@ static int mkhi_end_of_post(void) .group_id = MKHI_GROUP_ID_GEN, .command = MKHI_END_OF_POST, }; - struct mei_header mei = { - .is_complete = 1, - .host_address = MEI_HOST_ADDRESS, - .client_address = MEI_ADDRESS_MKHI, - .length = sizeof(mkhi), - }; - u32 eop_ack; /* Send request and wait for response */ printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__); - if (mei_sendrecv(&mei, &mkhi, NULL, &eop_ack, sizeof(eop_ack)) < 0) { + if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &eop_ack, sizeof(eop_ack)) < 0) { printk(BIOS_ERR, "ME: END OF POST message failed\n"); return -1; } @@ -497,6 +606,11 @@ void intel_me_finalize_smm(void) if (!mei_base_address || mei_base_address == 0xfffffff0) return; +#if CONFIG_ME_MBP_CLEAR_LATE + /* Wait for ME MBP Cleared indicator */ + intel_me_mbp_clear(PCH_ME_DEV); +#endif + /* Make sure ME is in a mode that expects EOP */ reg32 = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS); memcpy(&hfs, ®32, sizeof(u32)); @@ -522,6 +636,30 @@ void intel_me_finalize_smm(void) #else /* !__SMM__ */ +static int me_icc_set_clock_enables(u32 mask) +{ + struct icc_clock_enables_msg clk = { + .clock_enables = 0, /* Turn off specified clocks */ + .clock_mask = mask, + .no_response = 1, /* Do not expect response */ + }; + struct icc_header icc = { + .api_version = ICC_API_VERSION_LYNXPOINT, + .icc_command = ICC_SET_CLOCK_ENABLES, + .length = sizeof(clk), + }; + + /* Send request and wait for response */ + if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) { + printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n"); + return -1; + } else { + printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask); + } + + return 0; +} + /* Determine the path that we should take based on ME status */ static me_bios_path intel_me_path(device_t dev) { @@ -529,13 +667,6 @@ static me_bios_path intel_me_path(device_t dev) struct me_hfs hfs; struct me_hfs2 hfs2; -#if CONFIG_HAVE_ACPI_RESUME - /* S3 wake skips all MKHI messages */ - if (acpi_slp_type == 3) { - return ME_S3WAKE_BIOS_PATH; - } -#endif - pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS); pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); @@ -676,28 +807,18 @@ static int intel_me_extend_valid(device_t dev) return 0; } -/* Hide the ME virtual PCI devices */ -static void intel_me_hide(device_t dev) -{ - dev->enabled = 0; - pch_enable(dev); -} - /* Check whether ME is present and do basic init */ static void intel_me_init(device_t dev) { + struct southbridge_intel_lynxpoint_config *config = dev->chip_info; me_bios_path path = intel_me_path(dev); me_bios_payload mbp_data; /* Do initial setup and determine the BIOS path */ printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]); - if (path == ME_S3WAKE_BIOS_PATH) { - intel_me_hide(dev); - return; - } else if (path == ME_NORMAL_BIOS_PATH) { + if (path == ME_NORMAL_BIOS_PATH) { /* Validate the extend register */ - /* FIXME: force recovery mode on failure. */ intel_me_extend_valid(dev); } @@ -712,14 +833,29 @@ static void intel_me_init(device_t dev) if (intel_mei_setup(dev) < 0) return; - if(intel_me_read_mbp(&mbp_data, dev)) + if (intel_me_read_mbp(&mbp_data, dev)) return; #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) me_print_fw_version(mbp_data.fw_version_name); +#if CONFIG_DEBUG_INTEL_ME me_print_fwcaps(mbp_data.fw_capabilities); #endif + if (mbp_data.plat_time) { + printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n", + mbp_data.plat_time->wake_event_mrst_time_ms); + printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n", + mbp_data.plat_time->mrst_pltrst_time_ms); + printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n", + mbp_data.plat_time->pltrst_cpurst_time_ms); + } +#endif + + /* Set clock enables according to devicetree */ + if (config && config->icc_clock_disable) + me_icc_set_clock_enables(config->icc_clock_disable); + /* * Leave the ME unlocked. It will be locked via SMI command later. */ @@ -740,12 +876,23 @@ static struct pci_operations pci_ops = { .set_subsystem = set_subsystem, }; +static void intel_me_enable(device_t dev) +{ +#if CONFIG_HAVE_ACPI_RESUME + /* Avoid talking to the device in S3 path */ + if (acpi_slp_type == 3) { + dev->enabled = 0; + pch_disable_devfn(dev); + } +#endif +} + static struct device_operations device_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, + .enable = intel_me_enable, .init = intel_me_init, - .scan_bus = scan_static_bus, .ops_pci = &pci_ops, }; @@ -789,23 +936,6 @@ static u32 host_to_me_words_room(void) } #endif -/* - * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read - * state machine on the BIOS end doesn't match the ME's state machine. - */ -static void intel_me_mbp_give_up(device_t dev) -{ - u32 reg32; - struct mei_csr csr; - - reg32 = PCI_ME_MBP_GIVE_UP; - pci_write_config32(dev, PCI_ME_H_GS2, reg32); - read_host_csr(&csr); - csr.reset = 1; - csr.interrupt_generate = 1; - write_host_csr(&csr); -} - struct mbp_payload { mbp_header header; u32 data[0]; @@ -821,7 +951,6 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) u32 me2host_pending; struct mei_csr host; struct me_hfs2 hfs2; - int count; struct mbp_payload *mbp; int i; @@ -867,26 +996,20 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) host.interrupt_generate = 1; write_host_csr(&host); +#if !CONFIG_ME_MBP_CLEAR_LATE /* Wait for the mbp_cleared indicator. */ - for (count = ME_RETRY; count > 0; --count) { - pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); - if (hfs2.mbp_cleared) - break; - udelay(ME_DELAY); - } - - if (count == 0) { - printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n"); - intel_me_mbp_give_up(dev); - } + intel_me_mbp_clear(dev); +#endif /* Dump out the MBP contents. */ #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n", mbp->header.num_entries, mbp->header.mbp_size); +#if CONFIG_DEBUG_INTEL_ME for (i = 0; i < mbp->header.mbp_size - 1; i++) { printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]); } +#endif #endif #define ASSIGN_FIELD_PTR(field_,val_) \ @@ -923,9 +1046,15 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) case MBP_IDENT(KERNEL, MFS_FAILURE): ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]); + case MBP_IDENT(KERNEL, PLAT_TIME): + ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]); + + case MBP_IDENT(NFC, SUPPORT_DATA): + ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]); + default: - printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ dw offset 0x%x\n", - mbp->data[i], i); + printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ " + "dw offset 0x%x\n", mbp->data[i], i); break; } i += item->length; diff --git a/src/southbridge/intel/lynxpoint/nvs.h b/src/southbridge/intel/lynxpoint/nvs.h index 3df1da1f20..4283ca13d5 100644 --- a/src/southbridge/intel/lynxpoint/nvs.h +++ b/src/southbridge/intel/lynxpoint/nvs.h @@ -90,7 +90,8 @@ typedef struct { /* LynxPoint Serial IO device BARs */ u32 s0b[8]; /* 0x60 - 0x7f - BAR0 */ u32 s1b[8]; /* 0x80 - 0x9f - BAR1 */ - u8 rsvd6[20]; + u32 cbmc; /* 0xa0 - 0xa3 - coreboot memconsole */ + u8 rsvd6[16]; /* IGD OpRegion (not implemented yet) */ u32 aslb; /* 0xb4 - IGD OpRegion Base Address */ u8 ibtt; /* 0xb8 - IGD boot type */ diff --git a/src/southbridge/intel/lynxpoint/pch.c b/src/southbridge/intel/lynxpoint/pch.c index cc3718d444..d073a4b9a7 100644 --- a/src/southbridge/intel/lynxpoint/pch.c +++ b/src/southbridge/intel/lynxpoint/pch.c @@ -83,10 +83,18 @@ u16 get_gpiobase(void) #ifndef __SMM__ -/* Set bit in Function Disble register to hide this device */ -static void pch_hide_devfn(unsigned devfn) +/* Put device in D3Hot Power State */ +static void pch_enable_d3hot(device_t dev) { - switch (devfn) { + u32 reg32 = pci_read_config32(dev, PCH_PCS); + reg32 |= PCH_PCS_PS_D3HOT; + pci_write_config32(dev, PCH_PCS, reg32); +} + +/* Set bit in Function Disble register to hide this device */ +void pch_disable_devfn(device_t dev) +{ + switch (dev->path.pci.devfn) { case PCI_DEVFN(19, 0): /* Audio DSP */ RCBA32_OR(FD, PCH_DISABLE_ADSPD); break; @@ -94,24 +102,31 @@ static void pch_hide_devfn(unsigned devfn) RCBA32_OR(FD, PCH_DISABLE_XHCI); break; case PCI_DEVFN(21, 0): /* DMA */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 1): /* I2C0 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 2): /* I2C1 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 3): /* SPI0 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 4): /* SPI1 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 5): /* UART0 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(21, 6): /* UART1 */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(22, 0): /* MEI #1 */ @@ -127,6 +142,7 @@ static void pch_hide_devfn(unsigned devfn) RCBA32_OR(FD2, PCH_DISABLE_KT); break; case PCI_DEVFN(23, 0): /* SDIO */ + pch_enable_d3hot(dev); pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS); break; case PCI_DEVFN(25, 0): /* Gigabit Ethernet */ @@ -146,7 +162,7 @@ static void pch_hide_devfn(unsigned devfn) case PCI_DEVFN(28, 5): /* PCI Express Root Port 6 */ case PCI_DEVFN(28, 6): /* PCI Express Root Port 7 */ case PCI_DEVFN(28, 7): /* PCI Express Root Port 8 */ - RCBA32_OR(FD, PCH_DISABLE_PCIE(PCI_FUNC(devfn))); + RCBA32_OR(FD, PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn))); break; case PCI_DEVFN(29, 0): /* EHCI #1 */ RCBA32_OR(FD, PCH_DISABLE_EHCI1); @@ -185,7 +201,7 @@ static inline int iobp_poll(void) return 0; } -static u32 pch_iobp_read(u32 address) +u32 pch_iobp_read(u32 address) { u16 status; @@ -223,10 +239,15 @@ static u32 pch_iobp_read(u32 address) return RCBA32(IOBPD); } -void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) +void pch_iobp_write(u32 address, u32 data) { u16 status; - u32 data = pch_iobp_read(address); + + if (!iobp_poll()) + return; + + /* Set the address */ + RCBA32(IOBPIRI) = address; /* WRITE OPCODE */ status = RCBA16(IOBPS); @@ -234,9 +255,6 @@ void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) status |= IOBPS_WRITE; RCBA16(IOBPS) = status; - /* Update the data */ - data &= andvalue; - data |= orvalue; RCBA32(IOBPD) = data; /* Undocumented magic */ @@ -260,198 +278,24 @@ void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) printk(BIOS_INFO, "IOBP: set 0x%08x to 0x%08x\n", address, data); } -/* Check if any port in set X to X+3 is enabled */ -static int pch_pcie_check_set_enabled(device_t dev) +void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) { - device_t port; - int port_func; - int dev_func = PCI_FUNC(dev->path.pci.devfn); + u32 data = pch_iobp_read(address); - printk(BIOS_DEBUG, "%s: check set enabled\n", dev_path(dev)); + /* Update the data */ + data &= andvalue; + data |= orvalue; - /* Go through static device tree list of devices - * because enumeration is still in progress */ - for (port = all_devices; port; port = port->next) { - /* Only care about PCIe root ports */ - if (PCI_SLOT(port->path.pci.devfn) != - PCI_SLOT(dev->path.pci.devfn)) - continue; - - /* Check if port is in range and enabled */ - port_func = PCI_FUNC(port->path.pci.devfn); - if (port_func >= dev_func && - port_func < (dev_func + 4) && - port->enabled) - return 1; - } - - /* None of the ports in this set are enabled */ - return 0; -} - -/* RPFN is a write-once register so keep a copy until it is written */ -static u32 new_rpfn; - -/* Swap function numbers assigned to two PCIe Root Ports */ -static void pch_pcie_function_swap(u8 old_fn, u8 new_fn) -{ - u32 old_rpfn = new_rpfn; - - printk(BIOS_DEBUG, "PCH: Remap PCIe function %d to %d\n", - old_fn, new_fn); - - new_rpfn &= ~(RPFN_FNMASK(old_fn) | RPFN_FNMASK(new_fn)); - - /* Old function set to new function and disabled */ - new_rpfn |= RPFN_FNSET(old_fn, RPFN_FNGET(old_rpfn, new_fn)); - new_rpfn |= RPFN_FNSET(new_fn, RPFN_FNGET(old_rpfn, old_fn)); -} - -/* Update devicetree with new Root Port function number assignment */ -static void pch_pcie_devicetree_update(void) -{ - device_t dev; - - /* Update the function numbers in the static devicetree */ - for (dev = all_devices; dev; dev = dev->next) { - u8 new_devfn; - - /* Only care about PCH PCIe root ports */ - if (PCI_SLOT(dev->path.pci.devfn) != - PCH_PCIE_DEV_SLOT) - continue; - - /* Determine the new devfn for this port */ - new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, - RPFN_FNGET(new_rpfn, - PCI_FUNC(dev->path.pci.devfn))); - - if (dev->path.pci.devfn != new_devfn) { - printk(BIOS_DEBUG, - "PCH: PCIe map %02x.%1x -> %02x.%1x\n", - PCI_SLOT(dev->path.pci.devfn), - PCI_FUNC(dev->path.pci.devfn), - PCI_SLOT(new_devfn), PCI_FUNC(new_devfn)); - - dev->path.pci.devfn = new_devfn; - } - } -} - -/* Special handling for PCIe Root Port devices */ -static void pch_pcie_enable(device_t dev) -{ - struct southbridge_intel_lynxpoint_config *config = dev->chip_info; - u32 reg32; - - /* - * Save a copy of the Root Port Function Number map when - * starting to walk the list of PCIe Root Ports so it can - * be updated locally and written out when the last port - * has been processed. - */ - if (PCI_FUNC(dev->path.pci.devfn) == 0) { - new_rpfn = RCBA32(RPFN); - - /* - * Enable Root Port coalescing if the first port is disabled - * or the other devices will not be enumerated by the OS. - */ - if (!dev->enabled) - config->pcie_port_coalesce = 1; - - if (config->pcie_port_coalesce) - printk(BIOS_INFO, - "PCH: PCIe Root Port coalescing is enabled\n"); - } - - if (!dev->enabled) { - printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); - - /* - * PCIE Power Savings for PantherPoint and CougarPoint/B1+ - * - * If PCIe 0-3 disabled set Function 0 0xE2[0] = 1 - * If PCIe 4-7 disabled set Function 4 0xE2[0] = 1 - * - * This check is done here instead of pcie driver - * because the pcie driver enable() handler is not - * called unless the device is enabled. - */ - if ((PCI_FUNC(dev->path.pci.devfn) == 0 || - PCI_FUNC(dev->path.pci.devfn) == 4)) { - /* Handle workaround for PPT and CPT/B1+ */ - if (!pch_pcie_check_set_enabled(dev)) { - u8 reg8 = pci_read_config8(dev, 0xe2); - reg8 |= 1; - pci_write_config8(dev, 0xe2, reg8); - } - - /* - * Enable Clock Gating for shared PCIe resources - * before disabling this particular port. - */ - pci_write_config8(dev, 0xe1, 0x3c); - } - - /* Ensure memory, io, and bus master are all disabled */ - reg32 = pci_read_config32(dev, PCI_COMMAND); - reg32 &= ~(PCI_COMMAND_MASTER | - PCI_COMMAND_MEMORY | PCI_COMMAND_IO); - pci_write_config32(dev, PCI_COMMAND, reg32); - - /* Do not claim downstream transactions for PCIe ports */ - new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn)); - - /* Hide this device if possible */ - pch_hide_devfn(dev->path.pci.devfn); - } else { - int fn; - - /* - * Check if there is a lower disabled port to swap with this - * port in order to maintain linear order starting at zero. - */ - if (config->pcie_port_coalesce) { - for (fn=0; fn < PCI_FUNC(dev->path.pci.devfn); fn++) { - if (!(new_rpfn & RPFN_HIDE(fn))) - continue; - - /* Swap places with this function */ - pch_pcie_function_swap( - PCI_FUNC(dev->path.pci.devfn), fn); - break; - } - } - - /* Enable SERR */ - reg32 = pci_read_config32(dev, PCI_COMMAND); - reg32 |= PCI_COMMAND_SERR; - pci_write_config32(dev, PCI_COMMAND, reg32); - } - - /* - * When processing the last PCIe root port we can now - * update the Root Port Function Number and Hide register. - */ - if (PCI_FUNC(dev->path.pci.devfn) == 7) { - printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n", - RCBA32(RPFN), new_rpfn); - RCBA32(RPFN) = new_rpfn; - - /* Update static devictree with new function numbers */ - if (config->pcie_port_coalesce) - pch_pcie_devicetree_update(); - } + pch_iobp_write(address, data); } void pch_enable(device_t dev) { u32 reg32; - /* PCH PCIe Root Ports get special handling */ + /* PCH PCIe Root Ports are handled in PCIe driver. */ if (PCI_SLOT(dev->path.pci.devfn) == PCH_PCIE_DEV_SLOT) - return pch_pcie_enable(dev); + return; if (!dev->enabled) { printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); @@ -462,8 +306,8 @@ void pch_enable(device_t dev) PCI_COMMAND_MEMORY | PCI_COMMAND_IO); pci_write_config32(dev, PCI_COMMAND, reg32); - /* Hide this device if possible */ - pch_hide_devfn(dev->path.pci.devfn); + /* Disable this device if possible */ + pch_disable_devfn(dev); } else { /* Enable SERR */ reg32 = pci_read_config32(dev, PCI_COMMAND); diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h index 7246739bb5..982ccb3d8b 100644 --- a/src/southbridge/intel/lynxpoint/pch.h +++ b/src/southbridge/intel/lynxpoint/pch.h @@ -21,7 +21,6 @@ #ifndef SOUTHBRIDGE_INTEL_LYNXPOINT_PCH_H #define SOUTHBRIDGE_INTEL_LYNXPOINT_PCH_H - /* * Lynx Point PCH PCI Devices: * @@ -54,6 +53,13 @@ #define PCH_TYPE_LPT_LP 0x9c /* PCH stepping values for LPC device */ +#define LPT_H_STEP_B0 0x02 +#define LPT_H_STEP_C0 0x03 +#define LPT_H_STEP_C1 0x04 +#define LPT_H_STEP_C2 0x05 +#define LPT_LP_STEP_B0 0x02 +#define LPT_LP_STEP_B1 0x03 +#define LPT_LP_STEP_B2 0x04 /* * It does not matter where we put the SMBus I/O base, as long as we @@ -83,6 +89,10 @@ #if defined (__SMM__) && !defined(__ASSEMBLER__) void intel_pch_finalize_smm(void); +void usb_ehci_sleep_prepare(device_t dev, u8 slp_typ); +void usb_ehci_disable(device_t dev); +void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ); +void usb_xhci_route_all(void); #endif @@ -125,7 +135,7 @@ struct rcba_config_instruction u32 or_value; }; -#if !defined(__ASSEMBLER__) && !defined(__ROMCC__) +#if !defined(__ASSEMBLER__) void pch_config_rcba(const struct rcba_config_instruction *rcba_config); int pch_silicon_revision(void); int pch_silicon_type(void); @@ -157,17 +167,36 @@ void enable_all_gpe(u32 set1, u32 set2, u32 set3, u32 set4); void disable_all_gpe(void); void enable_gpe(u32 mask); void disable_gpe(u32 mask); +/* + * get GPIO pin value + */ +int get_gpio(int gpio_num); +/* + * Get a number comprised of multiple GPIO values. gpio_num_array points to + * the array of gpio pin numbers to scan, terminated by -1. + */ +unsigned get_gpios(const int *gpio_num_array); +/* + * Set GPIO pin value. + */ +void set_gpio(int gpio_num, int value); +/* Return non-zero if gpio is set to native function. 0 otherwise. */ +int gpio_is_native(int gpio_num); #if !defined(__PRE_RAM__) && !defined(__SMM__) #include #include #include "chip.h" void pch_enable(device_t dev); +void pch_disable_devfn(device_t dev); +u32 pch_iobp_read(u32 address); +void pch_iobp_write(u32 address, u32 data); void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue); #if CONFIG_ELOG void pch_log_state(void); #endif void acpi_create_intel_hpet(acpi_hpet_t * hpet); +void acpi_create_serialio_ssdt(acpi_header_t *ssdt); /* These helpers are for performing SMM relocation. */ void southbridge_trigger_smi(void); @@ -184,17 +213,9 @@ int smbus_read_byte(unsigned device, unsigned address); int early_spi_read(u32 offset, u32 size, u8 *buffer); int early_pch_init(const void *gpio_map, const struct rcba_config_instruction *rcba_config); -#endif -/* - * get GPIO pin value - */ -int get_gpio(int gpio_num); -/* - * get a number comprised of multiple GPIO values. gpio_num_array points to - * the array of gpio pin numbers to scan, terminated by -1. - */ -unsigned get_gpios(const int *gpio_num_array); -#endif +void pch_enable_lpc(void); +#endif /* !__PRE_RAM__ && !__SMM__ */ +#endif /* __ASSEMBLER__ */ #define MAINBOARD_POWER_OFF 0 #define MAINBOARD_POWER_ON 1 @@ -214,8 +235,13 @@ unsigned get_gpios(const int *gpio_num_array); #define SEE (1 << 1) #define PERE (1 << 0) +/* Power Management Control and Status */ +#define PCH_PCS 0x84 +#define PCH_PCS_PS_D3HOT 3 + #define PCH_EHCI1_DEV PCI_DEV(0, 0x1d, 0) #define PCH_EHCI2_DEV PCI_DEV(0, 0x1a, 0) +#define PCH_XHCI_DEV PCI_DEV(0, 0x14, 0) #define PCH_ME_DEV PCI_DEV(0, 0x16, 0) #define PCH_PCIE_DEV_SLOT 28 @@ -325,6 +351,60 @@ unsigned get_gpios(const int *gpio_num_array); /* SATA IOBP Registers */ #define SATA_IOBP_SP0G3IR 0xea000151 #define SATA_IOBP_SP1G3IR 0xea000051 +#define SATA_IOBP_SP0DTLE_DATA 0xea002550 +#define SATA_IOBP_SP0DTLE_EDGE 0xea002554 +#define SATA_IOBP_SP1DTLE_DATA 0xea002750 +#define SATA_IOBP_SP1DTLE_EDGE 0xea002754 + +#define SATA_DTLE_MASK 0xF +#define SATA_DTLE_DATA_SHIFT 24 +#define SATA_DTLE_EDGE_SHIFT 16 + +/* EHCI PCI Registers */ +#define EHCI_PWR_CTL_STS 0x54 +#define PWR_CTL_SET_MASK 0x3 +#define PWR_CTL_SET_D0 0x0 +#define PWR_CTL_SET_D3 0x3 +#define PWR_CTL_ENABLE_PME (1 << 8) +#define PWR_CTL_STATUS_PME (1 << 15) + +/* EHCI Memory Registers */ +#define EHCI_USB_CMD 0x20 +#define EHCI_USB_CMD_RUN (1 << 0) +#define EHCI_USB_CMD_PSE (1 << 4) +#define EHCI_USB_CMD_ASE (1 << 5) +#define EHCI_PORTSC(port) (0x64 + (port * 4)) +#define EHCI_PORTSC_ENABLED (1 << 2) +#define EHCI_PORTSC_SUSPEND (1 << 7) + +/* XHCI PCI Registers */ +#define XHCI_PWR_CTL_STS 0x74 +#define XHCI_USB2PR 0xd0 +#define XHCI_USB2PRM 0xd4 +#define XHCI_USB2PR_HCSEL 0x7fff +#define XHCI_USB3PR 0xd8 +#define XHCI_USB3PR_SSEN 0x3f +#define XHCI_USB3PRM 0xdc +#define XHCI_USB3FUS 0xe0 +#define XHCI_USB3FUS_SS_MASK 3 +#define XHCI_USB3FUS_SS_SHIFT 3 +#define XHCI_USB3PDO 0xe8 + +/* XHCI Memory Registers */ +#define XHCI_USB3_PORTSC(port) ((pch_is_lp() ? 0x510 : 0x570) + (port * 0x10)) +#define XHCI_USB3_PORTSC_CHST (0x7f << 17) +#define XHCI_USB3_PORTSC_WCE (1 << 25) /* Wake on Connect */ +#define XHCI_USB3_PORTSC_WDE (1 << 26) /* Wake on Disconnect */ +#define XHCI_USB3_PORTSC_WOE (1 << 27) /* Wake on Overcurrent */ +#define XHCI_USB3_PORTSC_WRC (1 << 19) /* Warm Reset Complete */ +#define XHCI_USB3_PORTSC_LWS (1 << 16) /* Link Write Strobe */ +#define XHCI_USB3_PORTSC_PED (1 << 1) /* Port Enabled/Disabled */ +#define XHCI_USB3_PORTSC_WPR (1 << 31) /* Warm Port Reset */ +#define XHCI_USB3_PORTSC_PLS (0xf << 5) /* Port Link State */ +#define XHCI_PLSR_DISABLED (4 << 5) /* Port is disabled */ +#define XHCI_PLSR_RXDETECT (5 << 5) /* Port is disconnected */ +#define XHCI_PLSR_POLLING (7 << 5) /* Port is polling */ +#define XHCI_PLSW_ENABLE (5 << 5) /* Transition from disabled */ /* Serial IO IOBP Registers */ #define SIO_IOBP_PORTCTRL0 0xcb000000 /* SDIO D23:F0 */ @@ -372,6 +452,8 @@ unsigned get_gpios(const int *gpio_num_array); #define SIO_ID_UART1 6 /* D21:F6 */ #define SIO_ID_SDIO 7 /* D23:F0 */ +#define SIO_REG_PPR_CLOCK 0x800 +#define SIO_REG_PPR_CLOCK_EN (1 << 0) #define SIO_REG_PPR_RST 0x804 #define SIO_REG_PPR_RST_ASSERT 0x3 #define SIO_REG_PPR_GEN 0x808 @@ -471,6 +553,7 @@ unsigned get_gpios(const int *gpio_num_array); #define RP6D 0x0180 /* 32bit */ #define RP6BA 0x0188 /* 64bit */ +#define RPC 0x0400 /* 32bit */ #define RPFN 0x0404 /* 32bit */ /* Root Port configuratinon space hide */ @@ -570,6 +653,8 @@ unsigned get_gpios(const int *gpio_num_array); #define D19IR 0x3168 /* 16bit */ #define ACPIIRQEN 0x31e0 /* 32bit */ #define OIC 0x31fe /* 16bit */ +#define PMSYNC_CONFIG 0x33c4 /* 32bit */ +#define PMSYNC_CONFIG2 0x33cc /* 32bit */ #define SOFT_RESET_CTRL 0x38f4 #define SOFT_RESET_DATA 0x38f8 @@ -760,4 +845,4 @@ unsigned get_gpios(const int *gpio_num_array); #define SPIBAR_FDATA(n) (0x3810 + (4 * n)) /* SPI flash data */ #endif /* __ACPI__ */ -#endif /* SOUTHBRIDGE_INTEL_LYNXPOINT_PCH_H */ +#endif /* SOUTHBRIDGE_INTEL_LYNXPOINT_PCH_H */ diff --git a/src/southbridge/intel/lynxpoint/pcie.c b/src/southbridge/intel/lynxpoint/pcie.c index 9463d0cb00..581b79d1a4 100644 --- a/src/southbridge/intel/lynxpoint/pcie.c +++ b/src/southbridge/intel/lynxpoint/pcie.c @@ -25,161 +25,652 @@ #include #include "pch.h" -static void pch_pcie_pm_early(struct device *dev) +static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or); +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or); + +/* LynxPoint-LP has 6 root ports while non-LP has 8. */ +#define MAX_NUM_ROOT_PORTS 8 +#define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS +#define LP_NUM_ROOT_PORTS (MAX_NUM_ROOT_PORTS - 2) + +struct root_port_config { + /* RPFN is a write-once register so keep a copy until it is written */ + u32 orig_rpfn; + u32 new_rpfn; + u32 pin_ownership; + u32 strpfusecfg1; + u32 strpfusecfg2; + u32 strpfusecfg3; + u32 b0d28f0_32c; + u32 b0d28f4_32c; + u32 b0d28f5_32c; + int coalesce; + int gbe_port; + int num_ports; + device_t ports[MAX_NUM_ROOT_PORTS]; +}; + +static struct root_port_config rpc; + +static inline int max_root_ports(void) { -/* RPC has been moved. It is in PCI config space now. */ -#if 0 - u16 link_width_p0, link_width_p4; - u8 slot_power_limit = 10; /* 10W for x1 */ - u32 reg32; - u8 reg8; - - reg32 = RCBA32(RPC); - - /* Port 0-3 link aggregation from PCIEPCS1[1:0] soft strap */ - switch (reg32 & 3) { - case 3: - link_width_p0 = 4; - break; - case 1: - case 2: - link_width_p0 = 2; - break; - case 0: - default: - link_width_p0 = 1; - } - - /* Port 4-7 link aggregation from PCIEPCS2[1:0] soft strap */ - switch ((reg32 >> 2) & 3) { - case 3: - link_width_p4 = 4; - break; - case 1: - case 2: - link_width_p4 = 2; - break; - case 0: - default: - link_width_p4 = 1; - } - - /* Enable dynamic clock gating where needed */ - reg8 = pci_read_config8(dev, 0xe1); - switch (PCI_FUNC(dev->path.pci.devfn)) { - case 0: /* Port 0 */ - if (link_width_p0 == 4) - slot_power_limit = 40; /* 40W for x4 */ - else if (link_width_p0 == 2) - slot_power_limit = 20; /* 20W for x2 */ - reg8 |= 0x3f; - break; - case 4: /* Port 4 */ - if (link_width_p4 == 4) - slot_power_limit = 40; /* 40W for x4 */ - else if (link_width_p4 == 2) - slot_power_limit = 20; /* 20W for x2 */ - reg8 |= 0x3f; - break; - case 1: /* Port 1 only if Port 0 is x1 */ - if (link_width_p0 == 1) - reg8 |= 0x3; - break; - case 2: /* Port 2 only if Port 0 is x1 or x2 */ - case 3: /* Port 3 only if Port 0 is x1 or x2 */ - if (link_width_p0 <= 2) - reg8 |= 0x3; - break; - case 5: /* Port 5 only if Port 4 is x1 */ - if (link_width_p4 == 1) - reg8 |= 0x3; - break; - case 6: /* Port 7 only if Port 4 is x1 or x2 */ - case 7: /* Port 7 only if Port 4 is x1 or x2 */ - if (link_width_p4 <= 2) - reg8 |= 0x3; - break; - } - pci_write_config8(dev, 0xe1, reg8); - - /* Set 0xE8[0] = 1 */ - reg32 = pci_read_config32(dev, 0xe8); - reg32 |= 1; - pci_write_config32(dev, 0xe8, reg32); - - /* Adjust Common Clock exit latency */ - reg32 = pci_read_config32(dev, 0xd8); - reg32 &= ~(1 << 17); - reg32 |= (1 << 16) | (1 << 15); - reg32 &= ~(1 << 31); /* Disable PME# SCI for native PME handling */ - pci_write_config32(dev, 0xd8, reg32); - - /* Adjust ASPM L1 exit latency */ - reg32 = pci_read_config32(dev, 0x4c); - reg32 &= ~((1 << 17) | (1 << 16) | (1 << 15)); - if (RCBA32(0x2320) & (1 << 16)) { - /* If RCBA+2320[15]=1 set ASPM L1 to 8-16us */ - reg32 |= (1 << 17); - } else { - /* Else set ASPM L1 to 2-4us */ - reg32 |= (1 << 16); - } - pci_write_config32(dev, 0x4c, reg32); - - /* Set slot power limit as configured above */ - reg32 = pci_read_config32(dev, 0x54); - reg32 &= ~((1 << 15) | (1 << 16)); /* 16:15 = Slot power scale */ - reg32 &= ~(0xff << 7); /* 14:7 = Slot power limit */ - reg32 |= (slot_power_limit << 7); - pci_write_config32(dev, 0x54, reg32); -#endif + if (pch_is_lp()) + return LP_NUM_ROOT_PORTS; + else + return H_NUM_ROOT_PORTS; } -static void pch_pcie_pm_late(struct device *dev) +static inline int root_port_is_first(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) == 0; +} + +static inline int root_port_is_last(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1); +} + +/* Root ports are numbered 1..N in the documentation. */ +static inline int root_port_number(device_t dev) +{ + return PCI_FUNC(dev->path.pci.devfn) + 1; +} + +static void root_port_config_update_gbe_port(void) +{ + /* Is the Gbe Port enabled? */ + if (!((rpc.strpfusecfg1 >> 19) & 1)) + return; + + if (pch_is_lp()) { + switch ((rpc.strpfusecfg1 >> 16) & 0x7) { + case 0: + rpc.gbe_port = 3; + break; + case 1: + rpc.gbe_port = 4; + break; + case 2: + case 3: + case 4: + case 5: + /* Lanes 0-4 of Root Port 5. */ + rpc.gbe_port = 5; + break; + default: + printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n"); + } + } else { + /* Non-LP has 1:1 mapping with root ports. */ + rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1; + } +} + +static void root_port_init_config(device_t dev) +{ + int rp; + + if (root_port_is_first(dev)) { + rpc.orig_rpfn = RCBA32(RPFN); + rpc.new_rpfn = rpc.orig_rpfn; + rpc.num_ports = max_root_ports(); + rpc.gbe_port = -1; + + rpc.pin_ownership = pci_read_config32(dev, 0x410); + root_port_config_update_gbe_port(); + + if (dev->chip_info != NULL) { + struct southbridge_intel_lynxpoint_config *config; + + config = dev->chip_info; + rpc.coalesce = config->pcie_port_coalesce; + } + } + + rp = root_port_number(dev); + if (rp > rpc.num_ports) { + printk(BIOS_ERR, "Found Root Port %d, expecting %d\n", + rp, rpc.num_ports); + return; + } + + /* Read the fuse configuration and pin ownership. */ + switch (rp) { + case 1: + rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc); + rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c); + break; + case 5: + rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc); + rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c); + break; + case 6: + rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c); + rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc); + break; + default: + break; + } + + /* Cache pci device. */ + rpc.ports[rp - 1] = dev; +} + +/* Update devicetree with new Root Port function number assignment */ +static void pch_pcie_device_set_func(int index, int pci_func) +{ + device_t dev; + unsigned new_devfn; + + dev = rpc.ports[index]; + + /* Set the new PCI function field for this Root Port. */ + rpc.new_rpfn &= ~RPFN_FNMASK(index); + rpc.new_rpfn |= RPFN_FNSET(index, pci_func); + + /* Determine the new devfn for this port */ + new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func); + + if (dev->path.pci.devfn != new_devfn) { + printk(BIOS_DEBUG, + "PCH: PCIe map %02x.%1x -> %02x.%1x\n", + PCI_SLOT(dev->path.pci.devfn), + PCI_FUNC(dev->path.pci.devfn), + PCI_SLOT(new_devfn), PCI_FUNC(new_devfn)); + + dev->path.pci.devfn = new_devfn; + } +} + +static void pcie_enable_clock_gating(void) +{ + int i; + int is_lp; + int enabled_ports; + + is_lp = pch_is_lp(); + enabled_ports = 0; + + for (i = 0; i < rpc.num_ports; i++) { + device_t dev; + int rp; + + dev = rpc.ports[i]; + rp = root_port_number(dev); + + if (!dev->enabled) { + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || (rp == 6 && is_lp)) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + + if (!is_lp) { + if (rp == 1 && !rpc.ports[1]->enabled && + !rpc.ports[2]->enabled && + !rpc.ports[3]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + if (rp == 5 && !rpc.ports[5]->enabled && + !rpc.ports[6]->enabled && + !rpc.ports[7]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + continue; + } + + pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4)); + pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31)); + + /* Per-Port CLKREQ# handling. */ + if (is_lp && gpio_is_native(18 + rp - 1)) + pcie_update_cfg(dev, 0x420, ~0, (3 << 29)); + + /* Enable static clock gating. */ + if (rp == 1 && !rpc.ports[1]->enabled && + !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } else if (rp == 5 || rp == 6) { + pcie_update_cfg8(dev, 0xe2, ~1, 1); + pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80); + } + continue; + } + + enabled_ports++; + + /* Enable dynamic clock gating. */ + pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03); + + if (is_lp) { + pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6)); + pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2)); + } + + /* Update PECR1 register. */ + pcie_update_cfg8(dev, 0xe8, ~0, 1); + + pcie_update_cfg8(dev, 0x324, ~(1 << 5), (1 < 5)); + + /* Per-Port CLKREQ# handling. */ + if (is_lp && gpio_is_native(18 + rp - 1)) + pcie_update_cfg(dev, 0x420, ~0, (3 << 29)); + + /* Configure shared resource clock gating. */ + if (rp == 1 || rp == 5 || (rp == 6 && is_lp)) + pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c); + } + + if (!enabled_ports && is_lp) + pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6)); +} + +static void root_port_commit_config(void) +{ + int i; + + /* If the first root port is disabled the coalesce ports. */ + if (!rpc.ports[0]->enabled) + rpc.coalesce = 1; + + /* Perform clock gating configuration. */ + pcie_enable_clock_gating(); + + for (i = 0; i < rpc.num_ports; i++) { + device_t dev; + u32 reg32; + + dev = rpc.ports[i]; + + if (dev == NULL) { + printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1); + continue; + } + + if (dev->enabled) + continue; + + printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev)); + + /* Ensure memory, io, and bus master are all disabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Disable this device if possible */ + pch_disable_devfn(dev); + } + + if (rpc.coalesce) { + int current_func; + + /* For all Root Ports N enabled ports get assigned the lower + * PCI function number. The disabled ones get upper PCI + * function numbers. */ + current_func = 0; + for (i = 0; i < rpc.num_ports; i++) { + if (!rpc.ports[i]->enabled) + continue; + pch_pcie_device_set_func(i, current_func); + current_func++; + } + + /* Allocate the disabled devices' PCI function number. */ + for (i = 0; i < rpc.num_ports; i++) { + if (rpc.ports[i]->enabled) + continue; + pch_pcie_device_set_func(i, current_func); + current_func++; + } + } + + printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n", + rpc.orig_rpfn, rpc.new_rpfn); + RCBA32(RPFN) = rpc.new_rpfn; +} + +static void root_port_mark_disable(device_t dev) +{ + /* Mark device as disabled. */ + dev->enabled = 0; + /* Mark device to be hidden. */ + rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn)); +} + +static void root_port_check_disable(device_t dev) +{ + int rp; + int is_lp; + + /* Device already disabled. */ + if (!dev->enabled) { + root_port_mark_disable(dev); + return; + } + + rp = root_port_number(dev); + + /* Is the GbE port mapped to this Root Port? */ + if (rp == rpc.gbe_port) { + root_port_mark_disable(dev); + return; + } + + is_lp = pch_is_lp(); + + /* Check Root Port Configuration. */ + switch (rp) { + case 2: + /* Root Port 2 is disabled for all lane configurations + * but config 00b (4x1 links). */ + if ((rpc.strpfusecfg1 >> 14) & 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 3: + /* Root Port 3 is disabled in config 11b (1x4 links). */ + if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 4: + /* Root Port 4 is disabled in configs 11b (1x4 links) + * and 10b (2x2 links). */ + if ((rpc.strpfusecfg1 >> 14) & 0x2) { + root_port_mark_disable(dev); + return; + } + break; + case 6: + if (is_lp) + break; + /* Root Port 6 is disabled for all lane configurations + * but config 00b (4x1 links). */ + if ((rpc.strpfusecfg2 >> 14) & 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 7: + if (is_lp) + break; + /* Root Port 3 is disabled in config 11b (1x4 links). */ + if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) { + root_port_mark_disable(dev); + return; + } + break; + case 8: + if (is_lp) + break; + /* Root Port 8 is disabled in configs 11b (1x4 links) + * and 10b (2x2 links). */ + if ((rpc.strpfusecfg2 >> 14) & 0x2) { + root_port_mark_disable(dev); + return; + } + break; + } + + /* Check Pin Ownership. */ + if (is_lp) { + switch (rp) { + case 1: + /* Bit 0 is Root Port 1 ownership. */ + if ((rpc.pin_ownership & 0x1) == 0) { + root_port_mark_disable(dev); + return; + } + break; + case 2: + /* Bit 2 is Root Port 2 ownership. */ + if ((rpc.pin_ownership & 0x4) == 0) { + root_port_mark_disable(dev); + return; + } + break; + case 6: + /* Bits 7:4 are Root Port 6 pin-lane ownership. */ + if ((rpc.pin_ownership & 0xf0) == 0) { + root_port_mark_disable(dev); + return; + } + break; + } + } else { + switch (rp) { + case 1: + /* Bits 4 and 0 are Root Port 1 ownership. */ + if ((rpc.pin_ownership & 0x11) == 0) { + root_port_mark_disable(dev); + return; + } + break; + case 2: + /* Bits 5 and 2 are Root Port 2 ownership. */ + if ((rpc.pin_ownership & 0x24) == 0) { + root_port_mark_disable(dev); + return; + } + break; + } + } +} + +static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or) +{ + u8 reg8; + + reg8 = pci_read_config8(dev, reg); + reg8 &= mask; + reg8 |= or; + pci_write_config8(dev, reg, reg8); +} + +static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or) { - enum aspm_type apmc; u32 reg32; - /* Set 0x314 = 0x743a361b */ - pci_mmio_write_config32(dev, 0x314, 0x743a361b); + reg32 = pci_read_config32(dev, reg); + reg32 &= mask; + reg32 |= or; + pci_write_config32(dev, reg, reg32); +} - /* Set 0x318[31:16] = 0x1414 */ - reg32 = pci_mmio_read_config32(dev, 0x318); - reg32 &= 0x0000ffff; - reg32 |= 0x14140000; - pci_mmio_write_config32(dev, 0x318, reg32); +static void pcie_add_0x0202000_iobp(u32 reg) +{ + u32 reg32; - /* Set 0x324[5] = 1 */ - reg32 = pci_mmio_read_config32(dev, 0x324); - reg32 |= (1 << 5); - pci_mmio_write_config32(dev, 0x324, reg32); + reg32 = pch_iobp_read(reg); + reg32 += (0x2 << 16) | (0x2 << 8); + pch_iobp_write(reg, reg32); +} - /* Set 0x330[7:0] = 0x40 */ - reg32 = pci_mmio_read_config32(dev, 0x330); - reg32 &= ~(0xff); - reg32 |= 0x40; - pci_mmio_write_config32(dev, 0x330, reg32); +static void pch_pcie_early(struct device *dev) +{ + int rp; + int do_aspm; + int is_lp; + struct southbridge_intel_lynxpoint_config *config = dev->chip_info; - /* Set 0x33C[24:0] = 0x854c74 */ - reg32 = pci_mmio_read_config32(dev, 0x33c); - reg32 &= 0xff000000; - reg32 |= 0x00854c74; - pci_mmio_write_config32(dev, 0x33c, reg32); + rp = root_port_number(dev); + do_aspm = 0; + is_lp = pch_is_lp(); - /* No IO-APIC, Disable EOI forwarding */ - reg32 = pci_read_config32(dev, 0xd4); - reg32 |= (1 << 1); - pci_write_config32(dev, 0xd4, reg32); - - /* Get configured ASPM state */ - apmc = pci_read_config32(dev, 0x50) & 3; - - /* If both L0s and L1 enabled then set root port 0xE8[1]=1 */ - if (apmc == PCIE_ASPM_BOTH) { - reg32 = pci_read_config32(dev, 0xe8); - reg32 |= (1 << 1); - pci_write_config32(dev, 0xe8, reg32); + if (is_lp) { + switch (rp) { + case 1: + case 2: + case 3: + case 4: + /* Bits 31:28 of b0d28f0 0x32c register correspnd to + * Root Ports 4:1. */ + do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1))); + break; + case 5: + /* Bit 28 of b0d28f4 0x32c register correspnd to + * Root Ports 4:1. */ + do_aspm = !!(rpc.b0d28f4_32c & (1 << 28)); + break; + case 6: + /* Bit 28 of b0d28f5 0x32c register correspnd to + * Root Ports 4:1. */ + do_aspm = !!(rpc.b0d28f5_32c & (1 << 28)); + break; + } + } else { + switch (rp) { + case 1: + case 2: + case 3: + case 4: + /* Bits 31:28 of b0d28f0 0x32c register correspnd to + * Root Ports 4:1. */ + do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1))); + break; + case 5: + case 6: + case 7: + case 8: + /* Bit 31:28 of b0d28f4 0x32c register correspnd to + * Root Ports 8:5. */ + do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5))); + break; + } } + + /* Allow ASPM to be forced on in devicetree */ + if (config && (config->pcie_port_force_aspm & (1 << (rp - 1)))) + do_aspm = 1; + + printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n", + rp, do_aspm ? "en" : "dis"); + + if (do_aspm) { + /* Set ASPM bits in MPC2 register. */ + pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2)); + + /* Set unique clock exit latency in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18)); + + /* Set L1 exit latency in LCAP register. */ + pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15)); + + if (is_lp) { + switch (rp) { + case 1: + pcie_add_0x0202000_iobp(0xe9002440); + break; + case 2: + pcie_add_0x0202000_iobp(0xe9002640); + break; + case 3: + pcie_add_0x0202000_iobp(0xe9000840); + break; + case 4: + pcie_add_0x0202000_iobp(0xe9000a40); + break; + case 5: + pcie_add_0x0202000_iobp(0xe9000c40); + pcie_add_0x0202000_iobp(0xe9000e40); + pcie_add_0x0202000_iobp(0xe9001040); + pcie_add_0x0202000_iobp(0xe9001240); + break; + case 6: + /* Update IOBP based on lane ownership. */ + if (rpc.pin_ownership & (1 << 4)) + pcie_add_0x0202000_iobp(0xea002040); + if (rpc.pin_ownership & (1 << 5)) + pcie_add_0x0202000_iobp(0xea002240); + if (rpc.pin_ownership & (1 << 6)) + pcie_add_0x0202000_iobp(0xea002440); + if (rpc.pin_ownership & (1 << 7)) + pcie_add_0x0202000_iobp(0xea002640); + break; + } + } else { + switch (rp) { + case 1: + if ((rpc.pin_ownership & 0x3) == 1) + pcie_add_0x0202000_iobp(0xe9002e40); + else + pcie_add_0x0202000_iobp(0xea002040); + break; + case 2: + if ((rpc.pin_ownership & 0xc) == 0x4) + pcie_add_0x0202000_iobp(0xe9002c40); + else + pcie_add_0x0202000_iobp(0xea002240); + break; + case 3: + pcie_add_0x0202000_iobp(0xe9002a40); + break; + case 4: + pcie_add_0x0202000_iobp(0xe9002840); + break; + case 5: + pcie_add_0x0202000_iobp(0xe9002640); + break; + case 6: + pcie_add_0x0202000_iobp(0xe9002440); + break; + case 7: + pcie_add_0x0202000_iobp(0xe9002240); + break; + case 8: + pcie_add_0x0202000_iobp(0xe9002040); + break; + } + } + + pcie_update_cfg(dev, 0x338, ~(1 << 26), 0); + } + + /* Enable LTR in Root Port. */ + pcie_update_cfg(dev, 0x64, ~(1 << 11), (1 << 11)); + pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10)); + + pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16)); + + /* Set L1 exit latency in LCAP register. */ + if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1)) + pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15)); + else + pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15)); + + pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b); + + /* Set Common Clock Exit Latency in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15)); + + pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74); + + /* Set Invalid Recieve Range Check Enable in MPC register. */ + pcie_update_cfg(dev, 0xd8, ~0, (1 << 25)); + + pcie_update_cfg8(dev, 0xf5, 0x3f, 0); + + if (rp == 1 || rp == 5 || (is_lp && rp == 6)) + pcie_update_cfg8(dev, 0xf7, ~0xc, 0); + + /* Set EOI forwarding disable. */ + pcie_update_cfg(dev, 0xd4, ~0, (1 << 1)); + + /* Set something involving advanced error reporting. */ + pcie_update_cfg(dev, 0x100, ~((1 << 20) - 1), 0x10001); + + if (is_lp) + pcie_update_cfg(dev, 0x100, ~0, (1 << 29)); + + /* Read and write back write-once capability registers. */ + pcie_update_cfg(dev, 0x34, ~0, 0); + pcie_update_cfg(dev, 0x40, ~0, 0); + pcie_update_cfg(dev, 0x80, ~0, 0); + pcie_update_cfg(dev, 0x90, ~0, 0); } static void pci_init(struct device *dev) @@ -189,6 +680,11 @@ static void pci_init(struct device *dev) printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n"); + /* Enable SERR */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_SERR; + pci_write_config32(dev, PCI_COMMAND, reg32); + /* Enable Bus Master */ reg32 = pci_read_config32(dev, PCI_COMMAND); reg32 |= PCI_COMMAND_MASTER; @@ -217,21 +713,29 @@ static void pci_init(struct device *dev) /* Clear errors in status registers */ reg16 = pci_read_config16(dev, 0x06); - //reg16 |= 0xf900; pci_write_config16(dev, 0x06, reg16); - reg16 = pci_read_config16(dev, 0x1e); - //reg16 |= 0xf900; pci_write_config16(dev, 0x1e, reg16); - - /* Power Management init after enumeration */ - pch_pcie_pm_late(dev); } static void pch_pcie_enable(device_t dev) { + /* Add this device to the root port config structure. */ + root_port_init_config(dev); + + /* Check to see if this Root Port should be disabled. */ + root_port_check_disable(dev); + /* Power Management init before enumeration */ - pch_pcie_pm_early(dev); + if (dev->enabled) + pch_pcie_early(dev); + + /* + * When processing the last PCIe root port we can now + * update the Root Port Function Number and Hide register. + */ + if (root_port_is_last(dev)) + root_port_commit_config(); } static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device) diff --git a/src/southbridge/intel/lynxpoint/sata.c b/src/southbridge/intel/lynxpoint/sata.c index 89128659bb..c2005402b1 100644 --- a/src/southbridge/intel/lynxpoint/sata.c +++ b/src/southbridge/intel/lynxpoint/sata.c @@ -172,10 +172,14 @@ static void sata_init(struct device *dev) /* CAP2 (HBA Capabilities Extended)*/ reg32 = read32(abar + 0x24); /* Enable DEVSLP */ - if (pch_is_lp()) - reg32 |= (1 << 5)|(1 << 4)|(1 << 3)|(1 << 2); - else + if (pch_is_lp()) { + if (config->sata_devslp_disable) + reg32 &= ~(1 << 3); + else + reg32 |= (1 << 5)|(1 << 4)|(1 << 3)|(1 << 2); + } else { reg32 &= ~0x00000002; + } write32(abar + 0x24, reg32); } else { printk(BIOS_DEBUG, "SATA: Controller in plain mode.\n"); @@ -233,6 +237,31 @@ static void sata_init(struct device *dev) pch_iobp_update(SATA_IOBP_SP1G3IR, 0, config->sata_port1_gen3_tx); + /* Set Gen3 DTLE DATA / EDGE registers if needed */ + if (config->sata_port0_gen3_dtle) { + pch_iobp_update(SATA_IOBP_SP0DTLE_DATA, + ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), + (config->sata_port0_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_DATA_SHIFT); + + pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE, + ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), + (config->sata_port0_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_EDGE_SHIFT); + } + + if (config->sata_port1_gen3_dtle) { + pch_iobp_update(SATA_IOBP_SP1DTLE_DATA, + ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), + (config->sata_port1_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_DATA_SHIFT); + + pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE, + ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), + (config->sata_port1_gen3_dtle & SATA_DTLE_MASK) + << SATA_DTLE_EDGE_SHIFT); + } + /* Additional Programming Requirements */ /* Power Optimizer */ diff --git a/src/southbridge/intel/lynxpoint/serialio.c b/src/southbridge/intel/lynxpoint/serialio.c index 11d6a36b44..8257cc2f6f 100644 --- a/src/southbridge/intel/lynxpoint/serialio.c +++ b/src/southbridge/intel/lynxpoint/serialio.c @@ -29,6 +29,22 @@ #include "pch.h" #include "nvs.h" +/* Set D3Hot Power State in ACPI mode */ +static void serialio_enable_d3hot(struct device *dev) +{ + u32 reg32 = pci_read_config32(dev, PCH_PCS); + reg32 |= PCH_PCS_PS_D3HOT; + pci_write_config32(dev, PCH_PCS, reg32); +} + +/* Enable clock in PCI mode */ +static void serialio_enable_clock(struct resource *bar0) +{ + u32 reg32 = read32(bar0->base + SIO_REG_PPR_CLOCK); + reg32 |= SIO_REG_PPR_CLOCK_EN; + write32(bar0->base + SIO_REG_PPR_CLOCK, reg32); +} + /* Put Serial IO D21:F0-F6 device into desired mode. */ static void serialio_d21_mode(int sio_index, int int_pin, int acpi_mode) { @@ -143,9 +159,15 @@ static void serialio_init(struct device *dev) struct southbridge_intel_lynxpoint_config *config = dev->chip_info; struct resource *bar0, *bar1; int sio_index = -1; + u32 reg32; printk(BIOS_DEBUG, "Initializing Serial IO device\n"); + /* Ensure memory and bus master are enabled */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(dev, PCI_COMMAND, reg32); + /* Find BAR0 and BAR1 */ bar0 = find_resource(dev, PCI_BASE_ADDRESS_0); if (!bar0) @@ -154,6 +176,11 @@ static void serialio_init(struct device *dev) if (!bar1) return; + if (!config->sio_acpi_mode) + serialio_enable_clock(bar0); + else if (dev->path.pci.devfn != PCI_DEVFN(21, 0)) + serialio_enable_d3hot(dev); /* all but SDMA */ + switch (dev->path.pci.devfn) { case PCI_DEVFN(21, 0): /* SDMA */ sio_index = SIO_ID_SDMA; @@ -241,9 +268,9 @@ static struct pci_operations pci_ops = { }; static struct device_operations device_ops = { - .read_resources = pci_bus_read_resources, + .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, - .enable_resources = pci_bus_enable_resources, + .enable_resources = pci_dev_enable_resources, .init = serialio_init, .ops_pci = &pci_ops, }; diff --git a/src/southbridge/intel/lynxpoint/smbus.c b/src/southbridge/intel/lynxpoint/smbus.c index 4786d8b6c9..fa6860568f 100644 --- a/src/southbridge/intel/lynxpoint/smbus.c +++ b/src/southbridge/intel/lynxpoint/smbus.c @@ -53,13 +53,74 @@ static int lsmbus_read_byte(device_t dev, u8 address) device = dev->path.i2c.device; pbus = get_pbus_smbus(dev); - res = find_resource(pbus->dev, 0x20); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); return do_smbus_read_byte(res->base, device, address); } +static int do_smbus_write_byte(unsigned smbus_base, unsigned device, + unsigned address, unsigned data) +{ + unsigned char global_status_register; + + if (smbus_wait_until_ready(smbus_base) < 0) + return SMBUS_WAIT_UNTIL_READY_TIMEOUT; + + /* Setup transaction */ + /* Disable interrupts */ + outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL); + /* Set the device I'm talking too */ + outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD); + /* Set the command/address... */ + outb(address & 0xff, smbus_base + SMBHSTCMD); + /* Set up for a byte data read */ + outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2), + (smbus_base + SMBHSTCTL)); + /* Clear any lingering errors, so the transaction will run */ + outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT); + + /* Clear the data byte... */ + outb(data, smbus_base + SMBHSTDAT0); + + /* Start the command */ + outb((inb(smbus_base + SMBHSTCTL) | 0x40), + smbus_base + SMBHSTCTL); + + /* Poll for transaction completion */ + if (smbus_wait_until_done(smbus_base) < 0) { + printk(BIOS_ERR, "SMBUS transaction timeout\n"); + return SMBUS_WAIT_UNTIL_DONE_TIMEOUT; + } + + global_status_register = inb(smbus_base + SMBHSTSTAT); + + /* Ignore the "In Use" status... */ + global_status_register &= ~(3 << 5); + + /* Read results of transaction */ + if (global_status_register != (1 << 1)) { + printk(BIOS_ERR, "SMBUS transaction error\n"); + return SMBUS_ERROR; + } + + return 0; +} + +static int lsmbus_write_byte(device_t dev, u8 address, u8 data) +{ + u16 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); + return do_smbus_write_byte(res->base, device, address, data); +} + static struct smbus_bus_operations lops_smbus_bus = { .read_byte = lsmbus_read_byte, + .write_byte = lsmbus_write_byte, }; static void smbus_set_subsystem(device_t dev, unsigned vendor, unsigned device) @@ -100,7 +161,7 @@ static struct device_operations smbus_ops = { .ops_pci = &smbus_pci_ops, }; -static const unsigned short pci_device_ids[] = { 0x1c22, 0x1e22, 0 }; +static const unsigned short pci_device_ids[] = { 0x1c22, 0x1e22, 0x9c22, 0 }; static const struct pci_driver pch_smbus __pci_driver = { .ops = &smbus_ops, diff --git a/src/southbridge/intel/lynxpoint/smi.c b/src/southbridge/intel/lynxpoint/smi.c index 75c3e66743..b88a70f735 100644 --- a/src/southbridge/intel/lynxpoint/smi.c +++ b/src/southbridge/intel/lynxpoint/smi.c @@ -64,14 +64,14 @@ void southbridge_smm_enable_smi(void) disable_gpe(PME_B0_EN); /* Enable SMI generation: - * - on TCO events * - on APMC writes (io 0xb2) * - on writes to SLP_EN (sleep states) * - on writes to GBL_RLS (bios commands) * No SMIs: * - on microcontroller writes (io 0x62/0x66) + * - on TCO events */ - enable_smi(TCO_EN | APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS); + enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS); } void southbridge_trigger_smi(void) diff --git a/src/southbridge/intel/lynxpoint/smihandler.c b/src/southbridge/intel/lynxpoint/smihandler.c index 203a1bbfb5..00e4a839f4 100644 --- a/src/southbridge/intel/lynxpoint/smihandler.c +++ b/src/southbridge/intel/lynxpoint/smihandler.c @@ -20,6 +20,7 @@ * MA 02110-1301 USA */ +#include #include #include #include @@ -105,6 +106,7 @@ static void busmaster_disable_on_bus(int bus) } } + static void southbridge_smi_sleep(void) { u8 reg8; @@ -132,6 +134,13 @@ static void southbridge_smi_sleep(void) /* Do any mainboard sleep handling */ mainboard_smi_sleep(slp_typ-2); + /* USB sleep preparations */ +#if !CONFIG_FINALIZE_USB_ROUTE_XHCI + usb_ehci_sleep_prepare(PCH_EHCI1_DEV, slp_typ); + usb_ehci_sleep_prepare(PCH_EHCI2_DEV, slp_typ); +#endif + usb_xhci_sleep_prepare(PCH_XHCI_DEV, slp_typ); + #if CONFIG_ELOG_GSMI /* Log S3, S4, and S5 entry */ if (slp_typ >= 5) @@ -307,6 +316,9 @@ static void southbridge_smi_apmc(void) printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs); } break; + case 0xca: + usb_xhci_route_all(); + break; #if CONFIG_ELOG_GSMI case ELOG_GSMI_APM_CNT: southbridge_smi_gsmi(); diff --git a/src/southbridge/intel/lynxpoint/spi.c b/src/southbridge/intel/lynxpoint/spi.c index eaa17d5e21..5325a23434 100644 --- a/src/southbridge/intel/lynxpoint/spi.c +++ b/src/southbridge/intel/lynxpoint/spi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -266,14 +267,7 @@ static void ich_set_bbar(uint32_t minaddr) writel_(ichspi_bbar, cntlr.bbar); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - printk(BIOS_DEBUG, "spi_cs_is_valid used but not implemented\n"); - return 0; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { ich_spi_slave *slave = malloc(sizeof(*slave)); @@ -326,6 +320,15 @@ void spi_init(void) pci_write_config_byte(dev, 0xdc, bios_cntl | 0x1); } +static void spi_init_cb(void *unused) +{ + spi_init(); +} + +BOOT_STATE_INIT_ENTRIES(spi_init_bscb) = { + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL), +}; + int spi_claim_bus(struct spi_slave *slave) { /* Handled by ICH automatically. */ @@ -337,16 +340,6 @@ void spi_release_bus(struct spi_slave *slave) /* Handled by ICH automatically. */ } -void spi_cs_activate(struct spi_slave *slave) -{ - /* Handled by ICH automatically. */ -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ - /* Handled by ICH automatically. */ -} - typedef struct spi_transaction { const uint8_t *out; uint32_t bytesout; @@ -504,7 +497,7 @@ static int ich_status_poll(u16 bitmask, int wait_til_set) } int spi_xfer(struct spi_slave *slave, const void *dout, - unsigned int bitsout, void *din, unsigned int bitsin) + unsigned int bytesout, void *din, unsigned int bytesin) { uint16_t control; int16_t opcode_index; @@ -512,26 +505,21 @@ int spi_xfer(struct spi_slave *slave, const void *dout, int status; spi_transaction trans = { - dout, bitsout / 8, - din, bitsin / 8, + dout, bytesout, + din, bytesin, 0xff, 0xff, 0 }; /* There has to always at least be an opcode. */ - if (!bitsout || !dout) { + if (!bytesout || !dout) { printk(BIOS_DEBUG, "ICH SPI: No opcode for transfer\n"); return -1; } /* Make sure if we read something we have a place to put it. */ - if (bitsin != 0 && !din) { + if (bytesin != 0 && !din) { printk(BIOS_DEBUG, "ICH SPI: Read but no target buffer\n"); return -1; } - /* Right now we don't support writing partial bytes. */ - if (bitsout % 8 || bitsin % 8) { - printk(BIOS_DEBUG, "ICH SPI: Accessing partial bytes not supported\n"); - return -1; - } if (ich_status_poll(SPIS_SCIP, 0) == -1) return -1; diff --git a/src/southbridge/intel/lynxpoint/spi_loading.c b/src/southbridge/intel/lynxpoint/spi_loading.c index 1ae7a263eb..aeab29e450 100644 --- a/src/southbridge/intel/lynxpoint/spi_loading.c +++ b/src/southbridge/intel/lynxpoint/spi_loading.c @@ -25,11 +25,7 @@ #include #include #include -#if CONFIG_VBOOT_VERIFY_FIRMWARE #include -#else -static inline void *vboot_get_payload(int *len) { return NULL; } -#endif #define CACHELINE_SIZE 64 #define INTRA_CACHELINE_MASK (CACHELINE_SIZE - 1) diff --git a/src/southbridge/intel/lynxpoint/usb_ehci.c b/src/southbridge/intel/lynxpoint/usb_ehci.c index aec230cf85..e621e25fa7 100644 --- a/src/southbridge/intel/lynxpoint/usb_ehci.c +++ b/src/southbridge/intel/lynxpoint/usb_ehci.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -26,20 +27,143 @@ #include #include -static void usb_ehci_init(struct device *dev) +#ifdef __SMM__ + +void usb_ehci_disable(device_t dev) +{ + u16 reg16; + u32 reg32; + + /* Set 0xDC[0]=1 */ + pci_or_config32(dev, 0xdc, (1 << 0)); + + /* Set D3Hot state and disable PME */ + reg16 = pci_read_config16(dev, EHCI_PWR_CTL_STS); + reg16 &= ~(PWR_CTL_ENABLE_PME | PWR_CTL_SET_MASK); + reg16 |= PWR_CTL_SET_D3; + pci_write_config16(dev, EHCI_PWR_CTL_STS, reg16); + + /* Clear memory and bus master */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0); + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Disable device */ + switch (dev) { + case PCH_EHCI1_DEV: + RCBA32_OR(FD, PCH_DISABLE_EHCI1); + break; + case PCH_EHCI2_DEV: + RCBA32_OR(FD, PCH_DISABLE_EHCI2); + break; + } +} + +/* Handler for EHCI controller on entry to S3/S4/S5 */ +void usb_ehci_sleep_prepare(device_t dev, u8 slp_typ) +{ + u32 reg32; + u32 bar0_base; + u16 pwr_state; + u16 pci_cmd; + + /* Check if the controller is disabled or not present */ + bar0_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + if (bar0_base == 0 || bar0_base == 0xffffffff) + return; + pci_cmd = pci_read_config32(dev, PCI_COMMAND); + + switch (slp_typ) { + case SLP_TYP_S4: + case SLP_TYP_S5: + /* Check if controller is in D3 power state */ + pwr_state = pci_read_config16(dev, EHCI_PWR_CTL_STS); + if ((pwr_state & PWR_CTL_SET_MASK) == PWR_CTL_SET_D3) { + /* Put in D0 */ + u32 new_state = pwr_state & ~PWR_CTL_SET_MASK; + new_state |= PWR_CTL_SET_D0; + pci_write_config16(dev, EHCI_PWR_CTL_STS, new_state); + + /* Make sure memory bar is set */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, bar0_base); + + /* Make sure memory space is enabled */ + pci_write_config16(dev, PCI_COMMAND, pci_cmd | + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + } + + /* + * If Run/Stop (bit0) is clear in USB2.0_CMD: + * - Clear Async Schedule Enable (bit5) and + * - Clear Periodic Schedule Enable (bit4) and + * - Set Run/Stop (bit0) + */ + reg32 = read32(bar0_base + EHCI_USB_CMD); + if (reg32 & EHCI_USB_CMD_RUN) { + reg32 &= ~(EHCI_USB_CMD_PSE | EHCI_USB_CMD_ASE); + reg32 |= EHCI_USB_CMD_RUN; + write32(bar0_base + EHCI_USB_CMD, reg32); + } + + /* Check for Port Enabled in PORTSC(0) (RMH) */ + reg32 = read32(bar0_base + EHCI_PORTSC(0)); + if (reg32 & EHCI_PORTSC_ENABLED) { + /* Set suspend bit in PORTSC if not already set */ + if (!(reg32 & EHCI_PORTSC_SUSPEND)) { + reg32 |= EHCI_PORTSC_SUSPEND; + write32(bar0_base + EHCI_PORTSC(0), reg32); + } + + /* Delay 25ms !! */ + udelay(25 * 1000); + + /* Clear Run/Stop bit */ + reg32 = read32(bar0_base + EHCI_USB_CMD); + reg32 &= EHCI_USB_CMD_RUN; + write32(bar0_base + EHCI_USB_CMD, reg32); + } + + /* Restore state to D3 if that is what it was at the start */ + if ((pwr_state & PWR_CTL_SET_MASK) == PWR_CTL_SET_D3) { + /* Restore pci command reg */ + pci_write_config16(dev, PCI_COMMAND, pci_cmd); + + /* Enable D3 */ + pci_write_config16(dev, EHCI_PWR_CTL_STS, pwr_state); + } + } +} + +#else /* !__SMM__ */ + +static void usb_ehci_clock_gating(struct device *dev) { u32 reg32; - /* Disable Wake on Disconnect in RMH */ - reg32 = RCBA32(0x35b0); - reg32 |= 0x22; - RCBA32(0x35b0) = reg32; + /* IOBP 0xE5004001[7:6] = 11b */ + pch_iobp_update(0xe5004001, ~0, (1 << 7)|(1 << 6)); + /* Dx:F0:DCh[5,2,1] = 111b + * Dx:F0:DCh[0] = 1b when EHCI controller is disabled */ + reg32 = pci_read_config32(dev, 0xdc); + reg32 |= (1 << 5) | (1 << 2) | (1 << 1); + pci_write_config32(dev, 0xdc, reg32); + + /* Dx:F0:78h[1:0] = 11b */ + reg32 = pci_read_config32(dev, 0x78); + reg32 |= (1 << 1) | (1 << 0); + pci_write_config32(dev, 0x78, reg32); +} + +static void usb_ehci_init(struct device *dev) +{ printk(BIOS_DEBUG, "EHCI: Setting up controller.. "); - reg32 = pci_read_config32(dev, PCI_COMMAND); - reg32 |= PCI_COMMAND_MASTER; - //reg32 |= PCI_COMMAND_SERR; - pci_write_config32(dev, PCI_COMMAND, reg32); + + usb_ehci_clock_gating(dev); + + /* Disable Wake on Disconnect in RMH */ + RCBA32_OR(0x35b0, 0x00000022); printk(BIOS_DEBUG, "done.\n"); } @@ -87,8 +211,6 @@ static void usb_ehci_set_resources(struct device *dev) #endif } - - static struct pci_operations lops_pci = { .set_subsystem = &usb_ehci_set_subsystem, }; @@ -102,11 +224,12 @@ static struct device_operations usb_ehci_ops = { .ops_pci = &lops_pci, }; -static const unsigned short pci_device_ids[] = { 0x1c26, 0x1c2d, 0x1e26, 0x1e2d, - 0 }; +static const unsigned short pci_device_ids[] = { 0x9c26, 0x8c26, 0x8c2d, 0 }; static const struct pci_driver pch_usb_ehci __pci_driver = { .ops = &usb_ehci_ops, .vendor = PCI_VENDOR_ID_INTEL, .devices = pci_device_ids, }; + +#endif /* !__SMM__ */ diff --git a/src/southbridge/intel/lynxpoint/usb_xhci.c b/src/southbridge/intel/lynxpoint/usb_xhci.c new file mode 100644 index 0000000000..41c29f9f10 --- /dev/null +++ b/src/southbridge/intel/lynxpoint/usb_xhci.c @@ -0,0 +1,403 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "pch.h" + +typedef struct southbridge_intel_lynxpoint_config config_t; + +static u32 usb_xhci_mem_base(device_t dev) +{ + u32 mem_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + + /* Check if the controller is disabled or not present */ + if (mem_base == 0 || mem_base == 0xffffffff) + return 0; + + return mem_base & ~0xf; +} + +static int usb_xhci_port_count_usb3(device_t dev) +{ + if (pch_is_lp()) { + /* LynxPoint-LP has 4 SS ports */ + return 4; + } else { + /* LynxPoint-H can have 0, 2, 4, or 6 SS ports */ + u32 mem_base = usb_xhci_mem_base(dev); + u32 fus = read32(mem_base + XHCI_USB3FUS); + fus >>= XHCI_USB3FUS_SS_SHIFT; + fus &= XHCI_USB3FUS_SS_MASK; + switch (fus) { + case 3: return 0; + case 2: return 2; + case 1: return 4; + case 0: default: return 6; + } + } + return 0; +} + +static void usb_xhci_reset_status_usb3(u32 mem_base, int port) +{ + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + u32 status = read32(portsc); + /* Do not set Port Enabled/Disabled field */ + status &= ~XHCI_USB3_PORTSC_PED; + /* Clear all change status bits */ + status |= XHCI_USB3_PORTSC_CHST; + write32(portsc, status); +} + +static void usb_xhci_reset_port_usb3(u32 mem_base, int port) +{ + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + write32(portsc, read32(portsc) | XHCI_USB3_PORTSC_WPR); +} + +#define XHCI_RESET_DELAY_US 1000 /* 1ms */ +#define XHCI_RESET_TIMEOUT 100 /* 100ms */ + +/* + * 1) Wait until port is done polling + * 2) If port is disconnected + * a) Issue warm port reset + * b) Poll for warm reset complete + * c) Write 1 to port change status bits + */ +static void usb_xhci_reset_usb3(device_t dev, int all) +{ + u32 status, port_disabled; + int timeout, port; + int port_count = usb_xhci_port_count_usb3(dev); + u32 mem_base = usb_xhci_mem_base(dev); + + if (!mem_base || !port_count) + return; + + /* Get mask of disabled ports */ + port_disabled = pci_read_config32(dev, XHCI_USB3PDO); + + /* Wait until all enabled ports are done polling */ + for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) { + int complete = 1; + for (port = 0; port < port_count; port++) { + /* Skip disabled ports */ + if (port_disabled & (1 << port)) + continue; + /* Read port link status field */ + status = read32(mem_base + XHCI_USB3_PORTSC(port)); + status &= XHCI_USB3_PORTSC_PLS; + if (status == XHCI_PLSR_POLLING) + complete = 0; + } + /* Exit if all ports not polling */ + if (complete) + break; + udelay(XHCI_RESET_DELAY_US); + } + + /* Reset all requested ports */ + for (port = 0; port < port_count; port++) { + u32 portsc = mem_base + XHCI_USB3_PORTSC(port); + /* Skip disabled ports */ + if (port_disabled & (1 << port)) + continue; + status = read32(portsc) & XHCI_USB3_PORTSC_PLS; + /* Reset all or only disconnected ports */ + if (all || (status == XHCI_PLSR_RXDETECT || + status == XHCI_PLSR_POLLING)) + usb_xhci_reset_port_usb3(mem_base, port); + else + port_disabled |= 1 << port; + } + + /* Wait for warm reset complete on all reset ports */ + for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) { + int complete = 1; + for (port = 0; port < port_count; port++) { + /* Only check ports that were reset */ + if (port_disabled & (1 << port)) + continue; + /* Check if warm reset is complete */ + status = read32(mem_base + XHCI_USB3_PORTSC(port)); + if (!(status & XHCI_USB3_PORTSC_WRC)) + complete = 0; + } + /* Check for warm reset complete in any port */ + if (complete) + break; + udelay(XHCI_RESET_DELAY_US); + } + + /* Clear port change status bits */ + for (port = 0; port < port_count; port++) + usb_xhci_reset_status_usb3(mem_base, port); +} + +#ifdef __SMM__ + +/* Handler for XHCI controller on entry to S3/S4/S5 */ +void usb_xhci_sleep_prepare(device_t dev, u8 slp_typ) +{ + u16 reg16; + u32 reg32; + u32 mem_base = usb_xhci_mem_base(dev); + + if (!mem_base || slp_typ < 3) + return; + + if (pch_is_lp()) { + /* Set D0 state */ + reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); + reg16 &= ~PWR_CTL_SET_MASK; + reg16 |= PWR_CTL_SET_D0; + pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); + + /* Clear PCI 0xB0[14:13] */ + reg32 = pci_read_config32(dev, 0xb0); + reg32 &= ~((1 << 14) | (1 << 13)); + pci_write_config32(dev, 0xb0, reg32); + + /* Clear MMIO 0x816c[14,2] */ + reg32 = read32(mem_base + 0x816c); + reg32 &= ~((1 << 14) | (1 << 2)); + write32(mem_base + 0x816c, reg32); + + /* Reset disconnected USB3 ports */ + usb_xhci_reset_usb3(dev, 0); + + /* Set MMIO 0x80e0[15] */ + reg32 = read32(mem_base + 0x80e0); + reg32 |= (1 << 15); + write32(mem_base + 0x80e0, reg32); + } + + /* Set D3Hot state and enable PME */ + pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_SET_D3); + pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_STATUS_PME); + pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_ENABLE_PME); +} + +/* Route all ports to XHCI controller */ +void usb_xhci_route_all(void) +{ + u32 port_mask, route; + u16 reg16; + + /* Skip if EHCI is already disabled */ + if (RCBA32(FD) & PCH_DISABLE_EHCI1) + return; + + /* Set D0 state */ + reg16 = pci_read_config16(PCH_XHCI_DEV, XHCI_PWR_CTL_STS); + reg16 &= ~PWR_CTL_SET_MASK; + reg16 |= PWR_CTL_SET_D0; + pci_write_config16(PCH_XHCI_DEV, XHCI_PWR_CTL_STS, reg16); + + /* Set USB3 superspeed enable */ + port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PRM); + route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PR); + route &= ~XHCI_USB3PR_SSEN; + route |= XHCI_USB3PR_SSEN & port_mask; + pci_write_config32(PCH_XHCI_DEV, XHCI_USB3PR, route); + + /* Route USB2 ports to XHCI controller */ + port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PRM); + route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PR); + route &= ~XHCI_USB2PR_HCSEL; + route |= XHCI_USB2PR_HCSEL & port_mask; + pci_write_config32(PCH_XHCI_DEV, XHCI_USB2PR, route); + + /* Disable EHCI controller */ + usb_ehci_disable(PCH_EHCI1_DEV); + + /* LynxPoint-H has a second EHCI controller */ + if (!pch_is_lp()) + usb_ehci_disable(PCH_EHCI2_DEV); + + /* Reset and clear port change status */ + usb_xhci_reset_usb3(PCH_XHCI_DEV, 1); +} + +#else /* !__SMM__ */ + +static void usb_xhci_clock_gating(device_t dev) +{ + u32 reg32; + u16 reg16; + + /* IOBP 0xE5004001[7:6] = 11b */ + pch_iobp_update(0xe5004001, ~0, (1 << 7)|(1 << 6)); + + reg32 = pci_read_config32(dev, 0x40); + reg32 &= ~(1 << 23); /* unsupported request */ + + if (pch_is_lp()) { + /* D20:F0:40h[18,17,8] = 111b */ + reg32 |= (1 << 18) | (1 << 17) | (1 << 8); + /* D20:F0:40h[21,20,19] = 110b to enable XHCI Idle L1 */ + reg32 &= ~(1 << 19); + reg32 |= (1 << 21) | (1 << 20); + } else { + /* D20:F0:40h[21,20,18,17,8] = 11111b */ + reg32 |= (1 << 21)|(1 << 20)|(1 << 18)|(1 << 17)|(1 << 8); + } + + /* Avoid writing upper byte as it is write-once */ + pci_write_config16(dev, 0x40, (u16)(reg32 & 0xffff)); + pci_write_config8(dev, 0x40 + 2, (u8)((reg32 >> 16) & 0xff)); + + /* D20:F0:44h[9,7,3] = 111b */ + reg16 = pci_read_config16(dev, 0x44); + reg16 |= (1 << 9) | (1 << 7) | (1 << 3); + pci_write_config16(dev, 0x44, reg16); + + reg32 = pci_read_config32(dev, 0xa0); + if (pch_is_lp()) { + /* D20:F0:A0h[18] = 1 */ + reg32 |= (1 << 18); + } else { + /* D20:F0:A0h[6] = 1 */ + reg32 |= (1 << 6); + } + pci_write_config32(dev, 0xa0, reg32); + + /* D20:F0:A4h[13] = 0 */ + reg32 = pci_read_config32(dev, 0xa4); + reg32 &= ~(1 << 13); + pci_write_config32(dev, 0xa4, reg32); +} + +static void usb_xhci_init(device_t dev) +{ + u32 reg32; + u16 reg16; + u32 mem_base = usb_xhci_mem_base(dev); + config_t *config = dev->chip_info; + + /* D20:F0:74h[1:0] = 00b (set D0 state) */ + reg16 = pci_read_config16(dev, XHCI_PWR_CTL_STS); + reg16 &= ~PWR_CTL_SET_MASK; + reg16 |= PWR_CTL_SET_D0; + pci_write_config16(dev, XHCI_PWR_CTL_STS, reg16); + + /* Enable clock gating first */ + usb_xhci_clock_gating(dev); + + reg32 = read32(mem_base + 0x8144); + if (pch_is_lp()) { + /* XHCIBAR + 8144h[8,7,6] = 111b */ + reg32 |= (1 << 8) | (1 << 7) | (1 << 6); + } else { + /* XHCIBAR + 8144h[8,7,6] = 100b */ + reg32 &= ~((1 << 7) | (1 << 6)); + reg32 |= (1 << 8); + } + write32(mem_base + 0x8144, reg32); + + if (pch_is_lp()) { + /* XHCIBAR + 816Ch[19:0] = 000e0038h */ + reg32 = read32(mem_base + 0x816c); + reg32 &= ~0x000fffff; + reg32 |= 0x000e0038; + write32(mem_base + 0x816c, reg32); + + /* D20:F0:B0h[17,14,13] = 100b */ + reg32 = pci_read_config32(dev, 0xb0); + reg32 &= ~((1 << 14) | (1 << 13)); + reg32 |= (1 << 17); + pci_write_config32(dev, 0xb0, reg32); + } + + reg32 = pci_read_config32(dev, 0x50); + if (pch_is_lp()) { + /* D20:F0:50h[28:0] = 0FCE2E5Fh */ + reg32 &= ~0x1fffffff; + reg32 |= 0x0fce2e5f; + } else { + /* D20:F0:50h[26:0] = 07886E9Fh */ + reg32 &= ~0x07ffffff; + reg32 |= 0x07886e9f; + } + pci_write_config32(dev, 0x50, reg32); + + /* D20:F0:44h[31] = 1 (Access Control Bit) */ + reg32 = pci_read_config32(dev, 0x44); + reg32 |= (1 << 31); + pci_write_config32(dev, 0x44, reg32); + + /* D20:F0:40h[31,23] = 10b (OC Configuration Done) */ + reg32 = pci_read_config32(dev, 0x40); + reg32 &= ~(1 << 23); /* unsupported request */ + reg32 |= (1 << 31); + pci_write_config32(dev, 0x40, reg32); + +#if CONFIG_HAVE_ACPI_RESUME + if (acpi_slp_type == 3) { + /* Reset ports that are disabled or + * polling before returning to the OS. */ + usb_xhci_reset_usb3(dev, 0); + } else +#endif + /* Route all ports to XHCI */ + if (config->xhci_default) + outb(0xca, 0xb2); +} + +static void usb_xhci_set_subsystem(device_t dev, unsigned vendor, + unsigned device) +{ + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); + } +} + +static struct pci_operations lops_pci = { + .set_subsystem = &usb_xhci_set_subsystem, +}; + +static struct device_operations usb_xhci_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_xhci_init, + .ops_pci = &lops_pci, +}; + +static const unsigned short pci_device_ids[] = { 0x8c31, /* LynxPoint-H */ + 0x9c31, /* LynxPoint-LP */ + 0 }; + +static const struct pci_driver pch_usb_xhci __pci_driver = { + .ops = &usb_xhci_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; +#endif /* !__SMM__ */ diff --git a/src/southbridge/nvidia/ck804/Makefile.inc b/src/southbridge/nvidia/ck804/Makefile.inc index bfafa23e41..be365f2f1f 100644 --- a/src/southbridge/nvidia/ck804/Makefile.inc +++ b/src/southbridge/nvidia/ck804/Makefile.inc @@ -20,6 +20,6 @@ ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c smm-$(CONFIG_USBDEBUG) += enable_usbdebug.c romstage-y += early_smbus.c -chipset_bootblock_inc += $(src)/southbridge/nvidia/ck804/romstrap.inc -chipset_bootblock_lds += $(src)/southbridge/nvidia/ck804/romstrap.lds +bootblock-y += romstrap.ld +chipset_bootblock_inc += $(src)/southbridge/nvidia/ck804/romstrap.inc diff --git a/src/southbridge/nvidia/ck804/lpc.c b/src/southbridge/nvidia/ck804/lpc.c index 1f49000094..5f62f44311 100644 --- a/src/southbridge/nvidia/ck804/lpc.c +++ b/src/southbridge/nvidia/ck804/lpc.c @@ -163,7 +163,7 @@ static void lpc_init(device_t dev) outb(byte, 0x70); /* Initialize the real time clock (RTC). */ - rtc_init(0); + cmos_init(0); /* Initialize ISA DMA. */ isa_dma_init(); diff --git a/src/southbridge/nvidia/ck804/nic.c b/src/southbridge/nvidia/ck804/nic.c index 3dccb8ea7d..ca082e7009 100644 --- a/src/southbridge/nvidia/ck804/nic.c +++ b/src/southbridge/nvidia/ck804/nic.c @@ -90,7 +90,7 @@ static void nic_init(struct device *dev) /* If that is invalid we will read that from romstrap. */ if (!eeprom_valid) { unsigned long mac_pos; - mac_pos = 0xffffffd0; /* See romstrap.inc and romstrap.lds. */ + mac_pos = 0xffffffd0; /* See romstrap.inc and romstrap.ld. */ mac_l = read32(mac_pos) + nic_index; mac_h = read32(mac_pos + 4); } diff --git a/src/southbridge/nvidia/ck804/romstrap.lds b/src/southbridge/nvidia/ck804/romstrap.ld similarity index 100% rename from src/southbridge/nvidia/ck804/romstrap.lds rename to src/southbridge/nvidia/ck804/romstrap.ld diff --git a/src/southbridge/nvidia/mcp55/Makefile.inc b/src/southbridge/nvidia/mcp55/Makefile.inc index b20804a978..358d218800 100644 --- a/src/southbridge/nvidia/mcp55/Makefile.inc +++ b/src/southbridge/nvidia/mcp55/Makefile.inc @@ -19,5 +19,6 @@ romstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c smm-$(CONFIG_USBDEBUG) += enable_usbdebug.c +bootblock-y += romstrap.ld + chipset_bootblock_inc += $(src)/southbridge/nvidia/mcp55/romstrap.inc -chipset_bootblock_lds += $(src)/southbridge/nvidia/mcp55/romstrap.lds diff --git a/src/southbridge/nvidia/mcp55/lpc.c b/src/southbridge/nvidia/mcp55/lpc.c index 585232d712..e56c4a98f0 100644 --- a/src/southbridge/nvidia/mcp55/lpc.c +++ b/src/southbridge/nvidia/mcp55/lpc.c @@ -146,7 +146,7 @@ static void lpc_init(device_t dev) outb(byte, 0x70); /* Initialize the real time clock. */ - rtc_init(0); + cmos_init(0); /* Initialize ISA DMA. */ isa_dma_init(); diff --git a/src/southbridge/nvidia/mcp55/mcp55.h b/src/southbridge/nvidia/mcp55/mcp55.h index 5454d79f9d..4fb3391079 100644 --- a/src/southbridge/nvidia/mcp55/mcp55.h +++ b/src/southbridge/nvidia/mcp55/mcp55.h @@ -33,9 +33,7 @@ void mcp55_enable(device_t dev); extern struct pci_operations mcp55_pci_ops; #else -#if !defined(__ROMCC__) void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn); #endif -#endif #endif diff --git a/src/southbridge/nvidia/mcp55/nic.c b/src/southbridge/nvidia/mcp55/nic.c index 86468fd64e..30dab05731 100644 --- a/src/southbridge/nvidia/mcp55/nic.c +++ b/src/southbridge/nvidia/mcp55/nic.c @@ -161,7 +161,7 @@ static void nic_init(struct device *dev) // if that is invalid we will read that from romstrap if(!eeprom_valid) { unsigned long mac_pos; - mac_pos = 0xffffffd0; // refer to romstrap.inc and romstrap.lds + mac_pos = 0xffffffd0; // refer to romstrap.inc and romstrap.ld mac_l = read32(mac_pos) + nic_index; // overflow? mac_h = read32(mac_pos + 4); diff --git a/src/southbridge/nvidia/mcp55/romstrap.lds b/src/southbridge/nvidia/mcp55/romstrap.ld similarity index 100% rename from src/southbridge/nvidia/mcp55/romstrap.lds rename to src/southbridge/nvidia/mcp55/romstrap.ld diff --git a/src/southbridge/sis/sis966/Makefile.inc b/src/southbridge/sis/sis966/Makefile.inc index b25aa9ed87..60aa0fbfb9 100644 --- a/src/southbridge/sis/sis966/Makefile.inc +++ b/src/southbridge/sis/sis966/Makefile.inc @@ -14,5 +14,6 @@ romstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c smm-$(CONFIG_USBDEBUG) += enable_usbdebug.c +bootblock-y += romstrap.ld + chipset_bootblock_inc += $(src)/southbridge/sis/sis966/romstrap.inc -chipset_bootblock_lds += $(src)/southbridge/sis/sis966/romstrap.lds diff --git a/src/southbridge/sis/sis966/lpc.c b/src/southbridge/sis/sis966/lpc.c index a4db1e5435..d7f4ea8d9c 100644 --- a/src/southbridge/sis/sis966/lpc.c +++ b/src/southbridge/sis/sis966/lpc.c @@ -148,7 +148,7 @@ static void lpc_init(device_t dev) } /* Initialize the real time clock */ - rtc_init(0); + cmos_init(0); /* Initialize isa dma */ isa_dma_init(); diff --git a/src/southbridge/sis/sis966/romstrap.lds b/src/southbridge/sis/sis966/romstrap.ld similarity index 100% rename from src/southbridge/sis/sis966/romstrap.lds rename to src/southbridge/sis/sis966/romstrap.ld diff --git a/src/southbridge/sis/sis966/sis966.h b/src/southbridge/sis/sis966/sis966.h index 6c1e7e2add..6085ab5a29 100644 --- a/src/southbridge/sis/sis966/sis966.h +++ b/src/southbridge/sis/sis966/sis966.h @@ -35,8 +35,6 @@ #define DEBUG_USB 0 #define DEBUG_USB2 0 -#if !defined(__ROMCC__) void sis966_enable(device_t dev); -#endif #endif /* SIS966_H */ diff --git a/src/southbridge/via/k8t890/Makefile.inc b/src/southbridge/via/k8t890/Makefile.inc index 6d9407d03b..ef04e1fe48 100644 --- a/src/southbridge/via/k8t890/Makefile.inc +++ b/src/southbridge/via/k8t890/Makefile.inc @@ -8,5 +8,6 @@ ramstage-y += traf_ctrl.c ramstage-y += error.c ramstage-y += chrome.c +bootblock-y += romstrap.ld + chipset_bootblock_inc += $(src)/southbridge/via/k8t890/romstrap.inc -chipset_bootblock_lds += $(src)/southbridge/via/k8t890/romstrap.lds diff --git a/src/southbridge/via/k8t890/romstrap.lds b/src/southbridge/via/k8t890/romstrap.ld similarity index 100% rename from src/southbridge/via/k8t890/romstrap.lds rename to src/southbridge/via/k8t890/romstrap.ld diff --git a/src/southbridge/via/vt8231/lpc.c b/src/southbridge/via/vt8231/lpc.c index 40854dbcf7..c6b74fdaa1 100644 --- a/src/southbridge/via/vt8231/lpc.c +++ b/src/southbridge/via/vt8231/lpc.c @@ -121,7 +121,7 @@ static void vt8231_init(struct device *dev) //ethernet_fixup(); // Start the rtc - rtc_init(0); + cmos_init(0); } static void vt8231_read_resources(device_t dev) diff --git a/src/southbridge/via/vt8235/lpc.c b/src/southbridge/via/vt8235/lpc.c index b355ad0d88..2c7848179a 100644 --- a/src/southbridge/via/vt8235/lpc.c +++ b/src/southbridge/via/vt8235/lpc.c @@ -209,7 +209,7 @@ static void vt8235_init(struct device *dev) pci_write_config8(dev, 0x40, 0x54); // Start the rtc - rtc_init(0); + cmos_init(0); } /* total kludge to get lxb to call our childrens set/enable functions - these are not called unless this diff --git a/src/southbridge/via/vt8237r/lpc.c b/src/southbridge/via/vt8237r/lpc.c index 01d2a9c690..4bc0b74c01 100644 --- a/src/southbridge/via/vt8237r/lpc.c +++ b/src/southbridge/via/vt8237r/lpc.c @@ -565,7 +565,7 @@ static void vt8237_common_init(struct device *dev) setup_pm(dev); /* Start the RTC. */ - rtc_init(0); + cmos_init(0); } static void vt8237r_read_resources(device_t dev) diff --git a/src/southbridge/via/vt8237r/vt8237r.h b/src/southbridge/via/vt8237r/vt8237r.h index b43ce3cb3e..3cca58d9ed 100644 --- a/src/southbridge/via/vt8237r/vt8237r.h +++ b/src/southbridge/via/vt8237r/vt8237r.h @@ -145,7 +145,6 @@ __attribute__ ((packed)) #ifdef __PRE_RAM__ -#ifndef __ROMCC__ u8 smbus_read_byte(u8 dimm, u8 offset); void smbus_write_byte(u8 dimm, u8 offset, u8 data); void enable_smbus(void); @@ -155,7 +154,6 @@ void vt8237_sb_enable_fid_vid(void); void enable_rom_decode(void); void vt8237_early_spi_init(void); int vt8237_early_network_init(struct vt8237_network_rom *rom); -#endif #else void writeback(device_t dev, u16 where, u8 what); void dump_south(device_t dev); diff --git a/src/superio/ite/it8712f/it8712f.h b/src/superio/ite/it8712f/it8712f.h index 0616c2af40..5ec6188eae 100644 --- a/src/superio/ite/it8712f/it8712f.h +++ b/src/superio/ite/it8712f/it8712f.h @@ -35,11 +35,8 @@ #define IT8712F_GAME 0x09 /* GAME port */ #define IT8712F_IR 0x0a /* Consumer IR */ -#ifndef __ROMCC__ void it8712f_kill_watchdog(void); void it8712f_enable_serial(device_t dev, u16 iobase); void it8712f_24mhz_clkin(void); void it8712f_enable_3vsbsw(void); #endif - -#endif diff --git a/src/superio/ite/it8716f/it8716f.h b/src/superio/ite/it8716f/it8716f.h index be9f720212..6657db4158 100644 --- a/src/superio/ite/it8716f/it8716f.h +++ b/src/superio/ite/it8716f/it8716f.h @@ -41,7 +41,7 @@ void init_ec(u16 base); #endif -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void it8716f_disable_dev(device_t dev); void it8716f_enable_dev(device_t dev, u16 iobase); void it8716f_enable_serial(device_t dev, u16 iobase); diff --git a/src/superio/ite/it8718f/it8718f.h b/src/superio/ite/it8718f/it8718f.h index 4da5af5d4f..527d1c2409 100644 --- a/src/superio/ite/it8718f/it8718f.h +++ b/src/superio/ite/it8718f/it8718f.h @@ -33,7 +33,7 @@ #define IT8718F_GPIO 0x07 /* GPIO */ #define IT8718F_IR 0x0a /* Consumer IR */ -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void it8718f_24mhz_clkin(void); void it8718f_disable_reboot(void); void it8718f_enable_serial(device_t dev, u16 iobase); diff --git a/src/superio/ite/it8721f/it8721f.h b/src/superio/ite/it8721f/it8721f.h index cca404af14..25300e6659 100644 --- a/src/superio/ite/it8721f/it8721f.h +++ b/src/superio/ite/it8721f/it8721f.h @@ -32,7 +32,7 @@ #define IT8721F_GPIO 0x07 /* GPIO */ #define IT8721F_IR 0x0a /* Consumer IR */ -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void it8721f_24mhz_clkin(void); void it8721f_disable_reboot(void); void it8721f_enable_serial(device_t dev, u16 iobase); diff --git a/src/superio/ite/it8772f/it8772f.h b/src/superio/ite/it8772f/it8772f.h index 343d9b36a8..fd676d536a 100644 --- a/src/superio/ite/it8772f/it8772f.h +++ b/src/superio/ite/it8772f/it8772f.h @@ -72,6 +72,7 @@ #define IT8772F_FAN_CTL_AUTO_SMOOTHING_DIS (0 << 7) #define IT8772F_FAN_CTL_AUTO_SMOOTHING_EN (1 << 7) #define IT8772F_EXTEMP_STATUS 0x88 +#define IT8772F_EXTEMP_STATUS_HOST_BUSY (1 << 0) #define IT8772F_EXTEMP_ADDRESS 0x89 #define IT8772F_EXTEMP_WRITE_LENGTH 0x8a #define IT8772F_EXTEMP_READ_LENGTH 0x8b @@ -105,7 +106,6 @@ #define GPIO_REG_ENABLE(x) (0xc0 + (x)) #define GPIO_REG_OUTPUT(x) (0xc8 + (x)) -#ifndef __ROMCC__ u8 it8772f_sio_read(u8 index); void it8772f_sio_write(u8 index, u8 value); void it8772f_enable_serial(device_t dev, u16 iobase); @@ -116,5 +116,3 @@ void it8772f_ac_resume_southbridge(void); void it8772f_gpio_setup(int set, u8 func_select, u8 polarity, u8 pullup, u8 output, u8 enable); #endif - -#endif diff --git a/src/superio/ite/it8772f/superio.c b/src/superio/ite/it8772f/superio.c index b4b54e9dc3..10729339ce 100644 --- a/src/superio/ite/it8772f/superio.c +++ b/src/superio/ite/it8772f/superio.c @@ -26,6 +26,7 @@ #include #include "chip.h" #include "it8772f.h" +#include "delay.h" static void pnp_enter_ext_func_mode(device_t dev) { @@ -54,6 +55,34 @@ static inline void it8772f_envc_write(struct resource *res, u8 addr, u8 value) outb(value, res->base + 6); } +static void it8772f_extemp_force_idle_status(struct resource *res) +{ + u8 reg; + int retries = 10; + + /* Wait up to 10ms for non-busy state. */ + while (retries > 0) { + reg = it8772f_envc_read(res, IT8772F_EXTEMP_STATUS); + + if ((reg & IT8772F_EXTEMP_STATUS_HOST_BUSY) == 0x0) + break; + + retries--; + + mdelay(1); + } + + if (retries == 0 && (reg & IT8772F_EXTEMP_STATUS_HOST_BUSY) == 0x1) { + /* + * SIO is busy due to unfinished peci transaction. + * Re-configure Register 0x8E to terminate processes. + */ + it8772f_envc_write(res, IT8772F_EXTEMP_CONTROL, + IT8772F_EXTEMP_CONTROL_AUTO_4HZ | + IT8772F_EXTEMP_CONTROL_AUTO_START); + } +} + /* * Setup External Temperature to read via PECI into TMPINx register */ @@ -156,6 +185,13 @@ static void it8772f_init(device_t dev) it8772f_enable_fan(res, 2); if (conf->fan3_enable) it8772f_enable_fan(res, 3); + + /* + * System may get wrong temperature data when SIO is in + * busy state. Therefore, check the status and terminate + * processes if needed. + */ + it8772f_extemp_force_idle_status(res); break; case IT8772F_GPIO: /* Set GPIO output levels */ @@ -224,7 +260,8 @@ static struct pnp_info pnp_dev_info[] = { /* Serial Port 1 */ { &ops, IT8772F_SP1, PNP_IO0 | PNP_IRQ0, {0x0ff8, 0}, }, /* Environmental Controller */ - { &ops, IT8772F_EC, PNP_IO0 | PNP_IO1 | PNP_IRQ0, + { &ops, IT8772F_EC, PNP_IO0 | PNP_IO1 | PNP_IRQ0 | + PNP_MSC4 | PNP_MSC10, {0x0ff8, 0}, {0x0ffc, 4}, }, /* KBC Keyboard */ { &ops, IT8772F_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, diff --git a/src/superio/nsc/pc87417/pc87417.h b/src/superio/nsc/pc87417/pc87417.h index 7208c8edda..73c1fbcd76 100644 --- a/src/superio/nsc/pc87417/pc87417.h +++ b/src/superio/nsc/pc87417/pc87417.h @@ -114,7 +114,7 @@ #define PC87417_XSCNF 0x15 #define PC87417_XWBCNF 0x16 -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void pc87417_enable_serial(device_t dev, u16 iobase); void pc87417_enable_dev(device_t dev); #endif diff --git a/src/superio/winbond/w83627ehg/w83627ehg.h b/src/superio/winbond/w83627ehg/w83627ehg.h index deab7ce106..c982603315 100644 --- a/src/superio/winbond/w83627ehg/w83627ehg.h +++ b/src/superio/winbond/w83627ehg/w83627ehg.h @@ -54,7 +54,7 @@ #define W83627EHG_GPIO4 ((2 << 8) | W83627EHG_GPIO_SUSLED_V) #define W83627EHG_GPIO5 ((3 << 8) | W83627EHG_GPIO_SUSLED_V) -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void w83627ehg_enable_dev(device_t dev, u16 iobase); void w83627ehg_disable_dev(device_t dev); void w83627ehg_enable_serial(device_t dev, u16 iobase); diff --git a/src/superio/winbond/w83627hf/w83627hf.h b/src/superio/winbond/w83627hf/w83627hf.h index 423ba8f94d..468cb55b43 100644 --- a/src/superio/winbond/w83627hf/w83627hf.h +++ b/src/superio/winbond/w83627hf/w83627hf.h @@ -113,7 +113,7 @@ #define W83627HF_XSCNF 0x15 #define W83627HF_XWBCNF 0x16 -#if defined(__PRE_RAM__) && !defined(__ROMCC__) +#if defined(__PRE_RAM__) void w83627hf_disable_dev(device_t dev); void w83627hf_enable_dev(device_t dev, u16 iobase); void w83627hf_enable_serial(device_t dev, u16 iobase); diff --git a/src/superio/winbond/w83697hf/w83697hf.h b/src/superio/winbond/w83697hf/w83697hf.h index 741d5b2122..7e353e23ce 100644 --- a/src/superio/winbond/w83697hf/w83697hf.h +++ b/src/superio/winbond/w83697hf/w83697hf.h @@ -32,8 +32,5 @@ #define W83697HF_ACPI 10 /* ACPI */ #define W83697HF_HWM 11 /* Hardware monitor */ -#ifndef __ROMCC__ void w83697hf_set_clksel_48(device_t); #endif - -#endif diff --git a/src/vendorcode/amd/agesa/f10/Makefile.inc b/src/vendorcode/amd/agesa/f10/Makefile.inc index 203efab7f4..56578bae50 100755 --- a/src/vendorcode/amd/agesa/f10/Makefile.inc +++ b/src/vendorcode/amd/agesa/f10/Makefile.inc @@ -48,5 +48,8 @@ AGESA_CFLAGS = -msse3 -fno-zero-initialized-in-bss -fno-strict-aliasing export AGESA_ROOT export AGESA_INC export AGESA_CFLAGS -CC := $(CC) $(AGESA_INC) $(AGESA_CFLAGS) +CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) +CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) diff --git a/src/vendorcode/amd/agesa/f12/Makefile.inc b/src/vendorcode/amd/agesa/f12/Makefile.inc index e1bafbe047..8589c86fac 100755 --- a/src/vendorcode/amd/agesa/f12/Makefile.inc +++ b/src/vendorcode/amd/agesa/f12/Makefile.inc @@ -86,5 +86,8 @@ AGESA_CFLAGS =-march=k8-sse3 -mtune=k8-sse3 -fno-zero-initialized-in-bss -fno-st export AGESA_ROOT := $(AGESA_ROOT) export AGESA_INC := $(AGESA_INC) export AGESA_CFLAGS := $(AGESA_CFLAGS) -CC := $(CC) $(AGESA_INC) $(AGESA_CFLAGS) +CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) +CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) ####################################################################### \ No newline at end of file diff --git a/src/vendorcode/amd/agesa/f14/Makefile.inc b/src/vendorcode/amd/agesa/f14/Makefile.inc index 6a266ec72d..986d861d75 100644 --- a/src/vendorcode/amd/agesa/f14/Makefile.inc +++ b/src/vendorcode/amd/agesa/f14/Makefile.inc @@ -67,5 +67,8 @@ AGESA_CFLAGS =-march=k8-sse3 -mtune=k8-sse3 -fno-zero-initialized-in-bss -fno-st export AGESA_ROOT := $(AGESA_ROOT) export AGESA_INC := $(AGESA_INC) export AGESA_CFLAGS := $(AGESA_CFLAGS) -CC := $(CC) $(AGESA_INC) $(AGESA_CFLAGS) +CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) +CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) ####################################################################### \ No newline at end of file diff --git a/src/vendorcode/amd/agesa/f15/Makefile.inc b/src/vendorcode/amd/agesa/f15/Makefile.inc index 2a7acce626..90a4f33eaf 100644 --- a/src/vendorcode/amd/agesa/f15/Makefile.inc +++ b/src/vendorcode/amd/agesa/f15/Makefile.inc @@ -529,5 +529,9 @@ AGESA_CFLAGS = -msse3 -fno-zero-initialized-in-bss -fno-strict-aliasing export AGESA_ROOT export AGESA_INC export AGESA_CFLAGS -CC := $(CC) $(AGESA_INC) $(AGESA_CFLAGS) +CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) +CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) + diff --git a/src/vendorcode/amd/agesa/f15tn/Makefile.inc b/src/vendorcode/amd/agesa/f15tn/Makefile.inc index f90e7b1f7c..091a0d68d2 100644 --- a/src/vendorcode/amd/agesa/f15tn/Makefile.inc +++ b/src/vendorcode/amd/agesa/f15tn/Makefile.inc @@ -91,5 +91,8 @@ AGESA_CFLAGS =-march=k8-sse3 -mtune=k8-sse3 -fno-zero-initialized-in-bss -fno-st export AGESA_ROOT := $(AGESA_ROOT) export AGESA_INC := $(AGESA_INC) export AGESA_CFLAGS := $(AGESA_CFLAGS) -CC := $(CC) $(AGESA_INC) $(AGESA_CFLAGS) +CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) +CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) ####################################################################### diff --git a/src/vendorcode/amd/cimx/rd890/Makefile.inc b/src/vendorcode/amd/cimx/rd890/Makefile.inc index feeb2cdf12..16498d7f74 100644 --- a/src/vendorcode/amd/cimx/rd890/Makefile.inc +++ b/src/vendorcode/amd/cimx/rd890/Makefile.inc @@ -113,7 +113,10 @@ NB_CIMX_CFLAGS = export CIMX_ROOT export NB_CIMX_INC export NB_CIMX_CFLAGS -CC := $(CC) $(NB_CIMX_CFLAGS) $(NB_CIMX_INC) +CC_bootblock := $(CC_bootblock) $(NB_CIMX_CFLAGS) $(NB_CIMX_INC) +CC_romstage := $(CC_romstage) $(NB_CIMX_CFLAGS) $(NB_CIMX_INC) +CC_ramstage := $(CC_ramstage) $(NB_CIMX_CFLAGS) $(NB_CIMX_INC) +CC_x86_32 := $(CC_x86_32) $(NB_CIMX_CFLAGS) $(NB_CIMX_INC) ####################################################################### diff --git a/src/vendorcode/amd/cimx/sb700/Makefile.inc b/src/vendorcode/amd/cimx/sb700/Makefile.inc index 10d03e63b6..ca2822aba8 100644 --- a/src/vendorcode/amd/cimx/sb700/Makefile.inc +++ b/src/vendorcode/amd/cimx/sb700/Makefile.inc @@ -72,7 +72,10 @@ SB_CIMX_CFLAGS = export CIMX_ROOT export SB_CIMX_INC export SB_CIMX_CFLAGS -CC := $(CC) $(SB_CIMX_CFLAGS) $(SB_CIMX_INC) +CC_bootblock := $(CC_bootblock) $(SB_CIMX_CFLAGS) $(SB_CIMX_INC) +CC_romstage := $(CC_romstage) $(SB_CIMX_CFLAGS) $(SB_CIMX_INC) +CC_ramstage := $(CC_ramstage) $(SB_CIMX_CFLAGS) $(SB_CIMX_INC) +CC_x86_32 := $(CC_x86_32) $(SB_CIMX_CFLAGS) $(SB_CIMX_INC) ####################################################################### diff --git a/src/vendorcode/amd/cimx/sb800/Makefile.inc b/src/vendorcode/amd/cimx/sb800/Makefile.inc index 3fb1d54c3f..4782b1373e 100644 --- a/src/vendorcode/amd/cimx/sb800/Makefile.inc +++ b/src/vendorcode/amd/cimx/sb800/Makefile.inc @@ -79,7 +79,10 @@ CIMX_CFLAGS = export CIMX_ROOT export CIMX_INC export CIMX_CFLAGS -CC := $(CC) $(CIMX_INC) +CC_bootblock := $(CC_bootblock) $(CIMX_INC) +CC_romstage := $(CC_romstage) $(CIMX_INC) +CC_ramstage := $(CC_ramstage) $(CIMX_INC) +CC_x86_32 := $(CC_x86_32) $(CIMX_INC) ####################################################################### diff --git a/src/vendorcode/amd/cimx/sb900/Makefile.inc b/src/vendorcode/amd/cimx/sb900/Makefile.inc index 4a3417f470..6265597fc5 100755 --- a/src/vendorcode/amd/cimx/sb900/Makefile.inc +++ b/src/vendorcode/amd/cimx/sb900/Makefile.inc @@ -82,7 +82,10 @@ CIMX_CFLAGS = export CIMX_ROOT export CIMX_INC export CIMX_CFLAGS -CC := $(CC) $(CIMX_INC) +CC_bootblock := $(CC_bootblock) $(CIMX_INC) +CC_romstage := $(CC_romstage) $(CIMX_INC) +CC_ramstage := $(CC_ramstage) $(CIMX_INC) +CC_x86_32 := $(CC_x86_32) $(CIMX_INC) ####################################################################### diff --git a/src/vendorcode/google/Makefile.inc b/src/vendorcode/google/Makefile.inc index 20d40a8b17..84abb98bdb 100644 --- a/src/vendorcode/google/Makefile.inc +++ b/src/vendorcode/google/Makefile.inc @@ -17,4 +17,4 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -subdirs-$(CONFIG_CHROMEOS) += chromeos +subdirs-$(CONFIG_CHROMEOS) += chromeos \ No newline at end of file diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig index d5ca2124ea..2cf7ec2c69 100644 --- a/src/vendorcode/google/chromeos/Kconfig +++ b/src/vendorcode/google/chromeos/Kconfig @@ -44,14 +44,39 @@ config VBNV_SIZE CMOS storage size for VbNv data. This value must match cmos.layout in the mainboard directory. +config CHROMEOS_VBNV_CMOS + def_bool n + help + VBNV is stored in CMOS + +config CHROMEOS_VBNV_EC + def_bool n + help + VBNV is stored in EC + +config CHROMEOS_VBNV_FLASH + def_bool n + help + VBNV is stored in flash storage + config CHROMEOS_RAMOOPS bool "Reserve space for Chrome OS ramoops" default y +config CHROMEOS_RAMOOPS_DYNAMIC + bool "Allocate RAM oops buffer in cbmem" + default n + depends on CHROMEOS_RAMOOPS && HAVE_ACPI_TABLES + +config CHROMEOS_RAMOOPS_NON_ACPI + bool "Allocate RAM oops buffer in cbmem passed through cb tables to payload" + default n + depends on CHROMEOS_RAMOOPS && !HAVE_ACPI_TABLES + config CHROMEOS_RAMOOPS_RAM_START hex "Physical address of preserved RAM" default 0x00f00000 - depends on CHROMEOS_RAMOOPS + depends on CHROMEOS_RAMOOPS && !CHROMEOS_RAMOOPS_DYNAMIC config CHROMEOS_RAMOOPS_RAM_SIZE hex "Size of preserved RAM" @@ -62,40 +87,53 @@ config FLASHMAP_OFFSET hex "Flash Map Offset" default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE default 0x00610000 if NORTHBRIDGE_INTEL_IVYBRIDGE + default CBFS_SIZE if !ARCH_X86 default 0 help Offset of flash map in firmware image endmenu -config VBOOT_VERIFY_FIRMWARE - bool "Verify firmware with vboot." - default n - depends on CHROMEOS - help - Enabling VBOOT_VERIFY_FIRMWARE will use vboot to verify the ramstage - and boot loader. - config EC_SOFTWARE_SYNC bool "Enable EC software sync" default n - depends on VBOOT_VERIFY_FIRMWARE + depends on VBOOT_VERIFY_FIRMWARE || VBOOT2_VERIFY_FIRMWARE help EC software sync is a mechanism where the AP helps the EC verify its firmware similar to how vboot verifies the main system firmware. This option selects whether depthcharge should support EC software sync. -config VIRTUAL_DEV_SWITCH - bool "Virtual developer switch support" +config VBOOT_EC_SLOW_UPDATE + bool "EC is slow to update" + default n + depends on EC_SOFTWARE_SYNC + help + Whether the EC (or PD) is slow to update and needs to display a + screen that informs the user the update is happening. + +config VBOOT_OPROM_MATTERS + bool "Video option ROM matters" default n depends on VBOOT_VERIFY_FIRMWARE + help + Whether the video option ROM has run matters on this platform. + +config VIRTUAL_DEV_SWITCH + bool "Virtual developer switch support" + default n + depends on VBOOT_VERIFY_FIRMWARE || VBOOT2_VERIFY_FIRMWARE help Whether this platform has a virtual developer switch. +# These VBOOT_X_INDEX are the position of X in FW_MAIN_A/B region. The index +# table is created by cros_bundle_firmware at build time based on the positions +# of the blobs listed in fmap.dts and stored at the top of FW_MAIN_A/B region. +# Unfortunately, there is no programmatical link between the blob list and the +# index number here. config VBOOT_BOOT_LOADER_INDEX hex "Bootloader component index" default 0 - depends on VBOOT_VERIFY_FIRMWARE + depends on VBOOT_VERIFY_FIRMWARE || VBOOT2_VERIFY_FIRMWARE help This is the index of the bootloader component in the verified firmware block. @@ -103,7 +141,7 @@ config VBOOT_BOOT_LOADER_INDEX config VBOOT_RAMSTAGE_INDEX hex "Ramstage component index" default 1 - depends on VBOOT_VERIFY_FIRMWARE + depends on VBOOT_VERIFY_FIRMWARE || VBOOT2_VERIFY_FIRMWARE help This is the index of the ramstage component in the verified firmware block. @@ -116,3 +154,12 @@ config NO_TPM_RESUME On some boards the TPM stays powered up in S3. On those boards, booting Windows will break if the TPM resume command is sent during an S3 resume. + +config PHYSICAL_REC_SWITCH + bool "Physical recovery switch is present" + default n + help + Whether this platform has a physical recovery switch + +source src/vendorcode/google/chromeos/vboot1/Kconfig +source src/vendorcode/google/chromeos/vboot2/Kconfig diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc index 4fa22ea931..be05003d79 100644 --- a/src/vendorcode/google/chromeos/Makefile.inc +++ b/src/vendorcode/google/chromeos/Makefile.inc @@ -17,66 +17,46 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## +bootblock-y += chromeos.c +verstage-y += chromeos.c romstage-y += chromeos.c ramstage-y += chromeos.c -romstage-$(CONFIG_ARCH_X86) += vbnv.c -ramstage-$(CONFIG_ARCH_X86) += vbnv.c -romstage-$(CONFIG_ARCH_X86) += vboot.c -ramstage-y += gnvs.c + +verstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c +romstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c +ramstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c +verstage-$(CONFIG_CHROMEOS_VBNV_EC) += vbnv_ec.c +romstage-$(CONFIG_CHROMEOS_VBNV_EC) += vbnv_ec.c +ramstage-$(CONFIG_CHROMEOS_VBNV_EC) += vbnv_ec.c +verstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c +romstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c +ramstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c + +romstage-$(CONFIG_ARCH_ROMSTAGE_X86_32) += vboot.c +ramstage-$(CONFIG_ELOG) += elog.c +ramstage-$(CONFIG_HAVE_ACPI_TABLES) += gnvs.c +verstage-y += fmap.c romstage-y += fmap.c ramstage-y += fmap.c +ramstage-$(CONFIG_CHROMEOS_RAMOOPS) += ramoops.c smm-y += fmap.c +ramstage-y += vpd_decode.c cros_vpd.c vpd_mac.c vpd_calibration.c ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/chromeos.c),) ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/chromeos.c romstage-srcs += src/mainboard/$(MAINBOARDDIR)/chromeos.c endif +ifeq ($(CONFIG_ARCH_X86)$(CONFIG_ARCH_MIPS),) +bootblock-y += watchdog.c +ramstage-y += watchdog.c +endif ifeq ($(MOCK_TPM),1) -CFLAGS += -DMOCK_TPM=1 +CFLAGS_common += -DMOCK_TPM=1 else -CFLAGS += -DMOCK_TPM=0 +CFLAGS_common += -DMOCK_TPM=0 endif -ifeq ($(CONFIG_VBOOT_VERIFY_FIRMWARE),y) -romstage-y += vboot_loader.c -rmodules-y += vboot_wrapper.c - -VB_LIB = $(obj)/external/vboot_reference/vboot_fw.a -VB_FIRMWARE_ARCH := $(ARCHDIR-y) VB_SOURCE := vboot_reference - -# Add the vboot include paths. -VB_INCLUDES += -I$(VB_SOURCE)/firmware/include -INCLUDES += $(VB_INCLUDES) - -VBOOT_STUB_ELF = $(obj)/vendorcode/google/chromeos/vbootstub.elf -VBOOT_STUB_DOTO = $(VBOOT_STUB_ELF:.elf=.o) - -# Dependency for the vboot rmodules. Ordering matters. -VBOOT_STUB_DEPS += $(obj)/vendorcode/google/chromeos/vboot_wrapper.rmodules.o -VBOOT_STUB_DEPS += $(obj)/lib/memcmp.rmodules.o -VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memset.rmodules.o -VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memcpy.rmodules.o -VBOOT_STUB_DEPS += $(VB_LIB) -# Remove the '-include' option since that will break vboot's build and ensure -# vboot_reference can get to coreboot's include files. -VBOOT_CFLAGS += $(patsubst -I%,-I../%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS))) -VBOOT_CFLAGS += -DVBOOT_DEBUG - -$(VBOOT_STUB_DOTO): $(VBOOT_STUB_DEPS) - $(CC) $(LDFLAGS) -nostdlib -r -o $@ $^ - -# Link the vbootstub module with a 64KiB-byte heap. -$(eval $(call rmodule_link,$(VBOOT_STUB_ELF), $(VBOOT_STUB_DOTO), 0x10000)) - -# Build vboot library without the default includes from coreboot proper. -$(VB_LIB): - @printf " MAKE $(subst $(obj)/,,$(@))\n" - $(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \ - CFLAGS="$(VBOOT_CFLAGS)" \ - make -C $(VB_SOURCE) \ - BUILD=../$(dir $(VB_LIB)) \ - V=$(V) \ - fwlib - -endif +subdirs-$(CONFIG_VBOOT_VERIFY_FIRMWARE) += vboot1 +subdirs-$(CONFIG_VBOOT2_VERIFY_FIRMWARE) += vboot2 +INCLUDES += -I$(VB_SOURCE)/firmware/include diff --git a/src/vendorcode/google/chromeos/acpi/chromeos.asl b/src/vendorcode/google/chromeos/acpi/chromeos.asl index 278296c939..8f63f122d5 100644 --- a/src/vendorcode/google/chromeos/acpi/chromeos.asl +++ b/src/vendorcode/google/chromeos/acpi/chromeos.asl @@ -107,3 +107,5 @@ Device (CRHW) Return (TSLM) } } + +#include "ramoops.asl" diff --git a/src/vendorcode/google/chromeos/acpi/gnvs.asl b/src/vendorcode/google/chromeos/acpi/gnvs.asl index dc4a0bfbe8..5377a8540f 100644 --- a/src/vendorcode/google/chromeos/acpi/gnvs.asl +++ b/src/vendorcode/google/chromeos/acpi/gnvs.asl @@ -34,4 +34,6 @@ VBT9, 32, // 0x196 - FMAP base address CHVD, 24576, // 0x19a - VDAT space filled by verified boot VBTA, 32, // 0xd9a - pointer to smbios FWID MEHH, 256, // 0xd9e - Management Engine Hash - // 0xdbe +RMOB, 32, // 0xdbe - RAM oops base address +RMOL, 32, // 0xdc2 - RAM oops length + // 0xdc6 diff --git a/src/vendorcode/google/chromeos/acpi/ramoops.asl b/src/vendorcode/google/chromeos/acpi/ramoops.asl new file mode 100644 index 0000000000..e43548933f --- /dev/null +++ b/src/vendorcode/google/chromeos/acpi/ramoops.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +Scope (\_SB) +{ + Device(RMOP) + { + Name (_HID, "GOOG9999") + Name (_CID, "GOOG9999") + Name (_UID, 1) + + Name (RBUF, ResourceTemplate() + { + Memory32Fixed (ReadWrite, 0, 0, MRES) + }) + + Method (_CRS) + { + CreateDwordField (^RBUF, ^MRES._BAS, RBAS) + CreateDwordField (^RBUF, ^MRES._LEN, RLEN) + Store (\RMOB, RBAS) + Store (\RMOL, RLEN) + Return (^RBUF) + } + } +} diff --git a/src/vendorcode/google/chromeos/chromeos.c b/src/vendorcode/google/chromeos/chromeos.c index 658694d577..437e128e7b 100644 --- a/src/vendorcode/google/chromeos/chromeos.c +++ b/src/vendorcode/google/chromeos/chromeos.c @@ -17,67 +17,91 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include "chromeos.h" -#if CONFIG_VBOOT_VERIFY_FIRMWARE -#include "vboot_handoff.h" -#endif #include +#include #include #include +static int vboot_enable_developer(void) +{ + struct vboot_handoff *vbho; + + vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vbho == NULL) { + printk(BIOS_ERR, "%s: Couldn't find vboot_handoff structure!\n", + __func__); + return 0; + } + + return !!(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_DEVELOPER); +} + +static int vboot_enable_recovery(void) +{ + struct vboot_handoff *vbho; + + vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vbho == NULL) + return 0; + + return !!(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_RECOVERY); +} + +int vboot_skip_display_init(void) +{ + struct vboot_handoff *vbho; + + vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vbho == NULL) + return 0; + + return !(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_DISPLAY); +} + int developer_mode_enabled(void) { - return get_developer_mode_switch(); + return get_developer_mode_switch() || vboot_enable_developer(); } int recovery_mode_enabled(void) { - /* TODO(reinauer): get information from VbInit. - * the recovery mode switch is not the only reason to go - * to recovery mode. + /* + * This is called in multiple places and has to detect + * recovery mode triggered from the EC and via shared + * recovery reason set with crossystem. + * + * If shared recovery reason is set: + * - before VbInit then get_recovery_mode_from_vbnv() is true + * - after VbInit then vboot_enable_recovery() is true + * + * Otherwise the mainboard handler for get_recovery_mode_switch() + * will detect recovery mode initiated by the EC. */ - return get_recovery_mode_switch() || get_recovery_mode_from_vbnv(); + return get_recovery_mode_switch() || get_recovery_mode_from_vbnv() || + vboot_enable_recovery(); } -#if CONFIG_VBOOT_VERIFY_FIRMWARE -void *vboot_get_payload(int *len) +int __attribute__((weak)) clear_recovery_mode_switch(void) { - struct vboot_handoff *vboot_handoff; - struct firmware_component *fwc; - - vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); - - if (vboot_handoff == NULL) - return NULL; - - if (CONFIG_VBOOT_BOOT_LOADER_INDEX >= MAX_PARSED_FW_COMPONENTS) { - printk(BIOS_ERR, "Invalid boot loader index: %d\n", - CONFIG_VBOOT_BOOT_LOADER_INDEX); - return NULL; - } - - fwc = &vboot_handoff->components[CONFIG_VBOOT_BOOT_LOADER_INDEX]; - - if (len != NULL) - *len = fwc->size; - - printk(BIOS_DEBUG, "Booting 0x%x byte payload at 0x%08x.\n", - fwc->size, fwc->address); - - return (void *)fwc->address; + // Can be implemented by a mainboard + return 0; } -int vboot_get_handoff_info(void **addr, uint32_t *size) +#ifdef __ROMSTAGE__ +void __attribute__((weak)) save_chromeos_gpios(void) { - struct vboot_handoff *vboot_handoff; + // Can be implemented by a mainboard +} - vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); - - if (vboot_handoff == NULL) - return -1; - - *addr = vboot_handoff; - *size = sizeof(*vboot_handoff); +int __attribute((weak)) vboot_get_sw_write_protect(void) +{ + // Can be implemented by a platform / mainboard return 0; } #endif diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h index d2410857ee..ce254731c6 100644 --- a/src/vendorcode/google/chromeos/chromeos.h +++ b/src/vendorcode/google/chromeos/chromeos.h @@ -18,16 +18,24 @@ */ #ifndef __CHROMEOS_H__ + #define __CHROMEOS_H__ #include +#include +#include "fmap.h" +#include "vboot_common.h" +#include "vboot_handoff.h" +#include "vboot2/misc.h" /* functions implemented per mainboard: */ int get_developer_mode_switch(void); int get_recovery_mode_switch(void); +int clear_recovery_mode_switch(void); int get_write_protect_state(void); -#ifdef __PRE_RAM__ -void save_chromeos_gpios(void); + +#ifdef __ROMSTAGE__ +void __attribute__((weak)) save_chromeos_gpios(void); #endif /* functions implemented in vbnv.c: */ @@ -38,19 +46,76 @@ extern int oprom_is_loaded; void read_vbnv(uint8_t *vbnv_copy); void save_vbnv(const uint8_t *vbnv_copy); +#if CONFIG_CHROMEOS /* functions implemented in chromeos.c: */ int developer_mode_enabled(void); int recovery_mode_enabled(void); +int vboot_skip_display_init(void); /* functions implemented in vboot.c */ void init_chromeos(int bootmode); -#if CONFIG_VBOOT_VERIFY_FIRMWARE +/* functions implemented in elog.c */ +void elog_add_boot_reason(void); + +/* functions implemented in watchdog.c */ +void elog_add_watchdog_reset(void); +void reboot_from_watchdog(void); +#else +static inline int developer_mode_enabled(void) { return 0; } +static inline int recovery_mode_enabled(void) { return 0; } +static inline int vboot_skip_display_init(void) { return 0; } +static inline void init_chromeos(int bootmode) { } +static inline void elog_add_boot_reason(void) { return; } +static inline void elog_add_watchdog_reset(void) { return; } +static inline void reboot_from_watchdog(void) { return; } +#endif /* CONFIG_CHROMEOS */ + struct romstage_handoff; + +#if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE +/* + * vboot_verify_firmware_get_entry() returns NULL if verification failed or + * the address to the next stage of firmware to run. + */ +void *vboot_verify_firmware_get_entry(struct romstage_handoff *handoff); void vboot_verify_firmware(struct romstage_handoff *handoff); void *vboot_get_payload(int *len); /* Returns 0 on success < 0 on error. */ int vboot_get_handoff_info(void **addr, uint32_t *size); -#endif -#endif +#else /* CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE */ +static inline void * +vboot_verify_firmware_get_entry(struct romstage_handoff *handoff) +{ + return NULL; +} +static inline void vboot_verify_firmware(struct romstage_handoff *h) {} +static inline void *vboot_get_payload(int *len) { return NULL; } +static inline int vboot_get_handoff_info(void **addr, uint32_t *size) +{ + return -1; +} + +#endif /* CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE */ + +int vboot_get_sw_write_protect(void); + +#include "gnvs.h" +struct device; + +#if CONFIG_CHROMEOS_RAMOOPS +void chromeos_ram_oops_init(chromeos_acpi_t *chromeos); +#if CONFIG_CHROMEOS_RAMOOPS_DYNAMIC +static inline void chromeos_reserve_ram_oops(struct device *dev, int idx) {} +#else /* CONFIG_CHROMEOS_RAMOOPS_DYNAMIC */ +void chromeos_reserve_ram_oops(struct device *dev, int idx); +#endif /* CONFIG_CHROMEOS_RAMOOPS_DYNAMIC */ +#else /* !CONFIG_CHROMEOS_RAMOOPS */ +static inline void chromeos_ram_oops_init(chromeos_acpi_t *chromeos) {} +static inline void chromeos_reserve_ram_oops(struct device *dev, int idx) {} +#endif /* CONFIG_CHROMEOS_RAMOOPS */ + +void cbmem_add_vpd_calibration_data(void); + +#endif /* __CHROMEOS_H__ */ diff --git a/src/vendorcode/google/chromeos/cros_vpd.c b/src/vendorcode/google/chromeos/cros_vpd.c new file mode 100644 index 0000000000..c0e483019b --- /dev/null +++ b/src/vendorcode/google/chromeos/cros_vpd.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +#include +#include +#include + +#include "cros_vpd.h" +#include "fmap.h" +#include "lib_vpd.h" +#include "vpd_tables.h" + +/* Currently we only support Google VPD 2.0, which has a fixed offset. */ +enum { + GOOGLE_VPD_2_0_OFFSET = 0x600, +}; + +struct vpd_gets_arg { + const uint8_t *key; + const uint8_t *value; + int32_t key_len, value_len; + int matched; +}; + +static int cros_vpd_load(uint8_t **vpd_address, int32_t *vpd_size) +{ + MAYBE_STATIC int cached = 0; + MAYBE_STATIC uint8_t *cached_address = NULL; + MAYBE_STATIC int32_t cached_size = 0; + MAYBE_STATIC int result = -1; + struct google_vpd_info info; + int32_t base; + + const struct fmap_area *area; + struct cbfs_media media; + + if (cached) { + *vpd_address = cached_address; + *vpd_size = cached_size; + return result; + } + + cached = 1; + area = find_fmap_area(fmap_find(), "RO_VPD"); + if (!area) { + printk(BIOS_ERR, "%s: No RO_VPD FMAP section.\n", __func__); + return result; + } + if (area->size <= GOOGLE_VPD_2_0_OFFSET + sizeof(info)) { + printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n", + __func__, area->size); + return result; + } + + base = area->offset + GOOGLE_VPD_2_0_OFFSET; + cached_size = area->size - GOOGLE_VPD_2_0_OFFSET; + init_default_cbfs_media(&media); + media.open(&media); + + /* Try if we can find a google_vpd_info, otherwise read whole VPD. */ + if (media.read(&media, &info, base, sizeof(info)) == sizeof(info) && + memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic)) + == 0 && cached_size >= info.size + sizeof(info)) { + base += sizeof(info); + cached_size = info.size; + } + + cached_address = media.map(&media, base, cached_size); + media.close(&media); + if (cached_address) { + *vpd_address = cached_address; + *vpd_size = cached_size; + printk(BIOS_DEBUG, "%s: Got VPD: %#x+%#x\n", __func__, base, + cached_size); + result = 0; + } + return result; +} + +static int vpd_gets_callback(const uint8_t *key, int32_t key_len, + const uint8_t *value, int32_t value_len, + void *arg) +{ + struct vpd_gets_arg *result = (struct vpd_gets_arg *)arg; + if (key_len != result->key_len || + memcmp(key, result->key, key_len) != 0) + /* Returns VPD_OK to continue parsing. */ + return VPD_OK; + + result->matched = 1; + result->value = value; + result->value_len = value_len; + /* Returns VPD_FAIL to stop parsing. */ + return VPD_FAIL; +} + +const void *cros_vpd_find(const char *key, int *size) +{ + uint8_t *vpd_address = NULL; + int32_t vpd_size = 0; + struct vpd_gets_arg arg = {0}; + int consumed = 0; + + if (cros_vpd_load(&vpd_address, &vpd_size) != 0) { + return NULL; + } + + arg.key = (const uint8_t *)key; + arg.key_len = strlen(key); + + while (VPD_OK == decodeVpdString(vpd_size, vpd_address, &consumed, + vpd_gets_callback, &arg)) { + /* Iterate until found or no more entries. */ + } + + if (!arg.matched) + return NULL; + + *size = arg.value_len; + return arg.value; +} + +char *cros_vpd_gets(const char *key, char *buffer, int size) +{ + const void *string_address; + int string_size; + + string_address = cros_vpd_find(key, &string_size); + + if (!string_address) + return NULL; + + if (size > (string_size + 1)) { + strcpy(buffer, string_address); + } else { + memcpy(buffer, string_address, size - 1); + buffer[size - 1] = '\0'; + } + return buffer; +} + diff --git a/src/vendorcode/google/chromeos/cros_vpd.h b/src/vendorcode/google/chromeos/cros_vpd.h new file mode 100644 index 0000000000..19658c2940 --- /dev/null +++ b/src/vendorcode/google/chromeos/cros_vpd.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_VPD_H__ +#define __CROS_VPD_H__ + +/* + * Reads VPD string value by key. + * + * Reads in at most one less than size characters from VPD and stores them + * into buffer. A terminating null byte ('\0') is stored after the last + * character in the buffer. + * + * Returns NULL if key is not found, otherwise buffer. + */ +char *cros_vpd_gets(const char *key, char *buffer, int size); + +/* + * Find VPD value by key. + * + * Searches for a VPD entry in the VPD cache. If found, places the size of the + * entry into '*size' and returns the pointer to the entry data. + * + * This function presumes that VPD is cached in DRAM (which is the case in the + * current implementation) and as such returns the pointer into the cache. The + * user is not supposed to modify the data, and does not have to free the + * memory. + * + * Returns NULL if key is not found. + */ + +const void *cros_vpd_find(const char *key, int *size); + +#endif /* __CROS_VPD_H__ */ diff --git a/src/vendorcode/google/chromeos/elog.c b/src/vendorcode/google/chromeos/elog.c new file mode 100644 index 0000000000..8bf9efc1ba --- /dev/null +++ b/src/vendorcode/google/chromeos/elog.c @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#if CONFIG_VBOOT_VERIFY_FIRMWARE +#include "vboot_handoff.h" +#include +#endif + +void elog_add_boot_reason(void) +{ + if (developer_mode_enabled()) { + elog_add_event(ELOG_TYPE_CROS_DEVELOPER_MODE); + printk(BIOS_DEBUG, "%s: Logged dev mode boot\n", __func__); + } else if (recovery_mode_enabled()) { + u8 reason = 0; +#if CONFIG_VBOOT_VERIFY_FIRMWARE + struct vboot_handoff *vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + reason = get_recovery_mode_from_vbnv(); + if (vbho && !reason) { + VbSharedDataHeader *sd = (VbSharedDataHeader *) + vbho->shared_data; + reason = sd->recovery_reason; + } +#endif + + elog_add_event_byte(ELOG_TYPE_CROS_RECOVERY_MODE, + reason ? reason : ELOG_CROS_RECOVERY_MODE_BUTTON); + printk(BIOS_DEBUG, "%s: Logged recovery mode boot, " + "reason: 0x%02x\n", __func__, reason); + } else { + printk(BIOS_DEBUG, "%s: Normal mode boot, nothing " + "interesting to log\n", __func__); + } +} diff --git a/src/vendorcode/google/chromeos/fmap.c b/src/vendorcode/google/chromeos/fmap.c index 538b8c359c..21d439e07d 100644 --- a/src/vendorcode/google/chromeos/fmap.c +++ b/src/vendorcode/google/chromeos/fmap.c @@ -21,8 +21,29 @@ #include #include #include +#include #include "fmap.h" +static int is_fmap_signature_valid(const struct fmap *fmap) +{ + const char reversed_sig[] = FMAP_REVERSED_SIGNATURE; + const char *p2 = reversed_sig + sizeof(FMAP_REVERSED_SIGNATURE) - 2; + const char *p1 = (char *)fmap; + + while (p2 >= reversed_sig) + if (*p1++ != *p2--) { + printk(BIOS_ERR, "No FMAP found at %p.\n", fmap); + return 1; + } + + printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %p.\n", + fmap->name, fmap->ver_major, fmap->ver_minor, fmap); + printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n", + (unsigned long long)fmap->base, fmap->size, fmap->nareas); + + return 0; +} + /* Find FMAP data structure in ROM. * See http://code.google.com/p/flashmap/ for more information on FMAP. */ @@ -35,21 +56,42 @@ const struct fmap *fmap_find(void) * master header; that would require some more changes to cbfstool * and possibly cros_bundle_firmware. */ + const struct fmap *fmap; + struct cbfs_media media; + size_t size; - /* wrapping around 0x100000000 */ - const struct fmap *fmap = (void *) - (CONFIG_FLASHMAP_OFFSET - CONFIG_ROM_SIZE); - - if (memcmp(fmap, FMAP_SIGNATURE, sizeof(FMAP_SIGNATURE)-1)) { - printk(BIOS_DEBUG, "No FMAP found at %p.\n", fmap); + if (init_default_cbfs_media(&media)) { + printk(BIOS_ERR, "failed to init default cbfs media\n"); return NULL; } - printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %p.\n", - fmap->name, fmap->ver_major, fmap->ver_minor, fmap); - printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n", - (unsigned long long)fmap->base, fmap->size, fmap->nareas); + media.open(&media); + fmap = media.map(&media, CONFIG_FLASHMAP_OFFSET, sizeof(*fmap)); + if (fmap == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + printk(BIOS_ERR, "failed to map FMAP header\n"); + media.close(&media); + return NULL; + } + + if (is_fmap_signature_valid(fmap)) { + media.unmap(&media, fmap); + media.close(&media); + return NULL; + } + + size = sizeof(*fmap) + sizeof(struct fmap_area) * fmap->nareas; + media.unmap(&media, fmap); + fmap = media.map(&media, CONFIG_FLASHMAP_OFFSET, size); + + if (fmap == CBFS_MEDIA_INVALID_MAP_ADDRESS) { + printk(BIOS_ERR, "failed to map FMAP (size=%zu)\n", size); + media.unmap(&media, fmap); + media.close(&media); + return NULL; + } + + media.close(&media); return fmap; } @@ -81,10 +123,7 @@ const struct fmap_area *find_fmap_area(const struct fmap *fmap, int find_fmap_entry(const char name[], void **pointer) { -#ifndef __PRE_RAM__ - static -#endif - const struct fmap *fmap = NULL; + MAYBE_STATIC const struct fmap *fmap = NULL; const struct fmap_area *area; void *base = NULL; @@ -104,12 +143,14 @@ int find_fmap_entry(const char name[], void **pointer) base = (void *)(unsigned long)fmap->base; printk(BIOS_DEBUG, "FMAP: %s base at %p\n", name, base); } else { +#if CONFIG_ARCH_X86 base = (void *)(0 - CONFIG_ROM_SIZE); printk(BIOS_WARNING, "FMAP: No valid base address, using" " 0x%p\n", base); +#endif } - *pointer = (void*) ((u32)base + area->offset); + *pointer = (void*) ((uintptr_t)base + area->offset); printk(BIOS_DEBUG, "FMAP: %s at %p (offset %x)\n", name, *pointer, area->offset); return area->size; diff --git a/src/vendorcode/google/chromeos/fmap.h b/src/vendorcode/google/chromeos/fmap.h index a3d2abd582..05d3fb6e1d 100644 --- a/src/vendorcode/google/chromeos/fmap.h +++ b/src/vendorcode/google/chromeos/fmap.h @@ -38,7 +38,7 @@ #include -#define FMAP_SIGNATURE "__FMAP__" +#define FMAP_REVERSED_SIGNATURE "__PAMF__" /* avoid magic number in .rodata */ #define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */ #define FMAP_VER_MINOR 1 /* this header's FMAP minor version */ #define FMAP_STRLEN 32 /* maximum length for strings, */ diff --git a/src/vendorcode/google/chromeos/gnvs.c b/src/vendorcode/google/chromeos/gnvs.c index 0d4095061d..528143c67c 100644 --- a/src/vendorcode/google/chromeos/gnvs.c +++ b/src/vendorcode/google/chromeos/gnvs.c @@ -29,6 +29,7 @@ #include "gnvs.h" #if CONFIG_VBOOT_VERIFY_FIRMWARE #include "vboot_handoff.h" +#include #endif chromeos_acpi_t *vboot_data = NULL; @@ -60,10 +61,19 @@ void chromeos_init_vboot(chromeos_acpi_t *chromeos) elog_add_event(ELOG_TYPE_CROS_DEVELOPER_MODE); if (recovery_mode_enabled()) { int reason = get_recovery_mode_from_vbnv(); +#if CONFIG_VBOOT_VERIFY_FIRMWARE + if (vboot_handoff && !reason) { + VbSharedDataHeader *sd = (VbSharedDataHeader *) + vboot_handoff->shared_data; + reason = sd->recovery_reason; + } +#endif elog_add_event_byte(ELOG_TYPE_CROS_RECOVERY_MODE, reason ? reason : ELOG_CROS_RECOVERY_MODE_BUTTON); } #endif + + chromeos_ram_oops_init(chromeos); } void chromeos_set_me_hash(u32 *hash, int len) @@ -79,8 +89,8 @@ void chromeos_set_me_hash(u32 *hash, int len) memcpy(me_hash_saved, hash, len*sizeof(u32)); } -void acpi_get_vdat_info(void **vdat_addr, uint32_t *vdat_size) +void acpi_get_vdat_info(uint64_t *vdat_addr, uint32_t *vdat_size) { - *vdat_addr = vboot_data; + *vdat_addr = (intptr_t)vboot_data; *vdat_size = sizeof(*vboot_data); } diff --git a/src/vendorcode/google/chromeos/gnvs.h b/src/vendorcode/google/chromeos/gnvs.h index 40674944fa..fe7d77abfc 100644 --- a/src/vendorcode/google/chromeos/gnvs.h +++ b/src/vendorcode/google/chromeos/gnvs.h @@ -58,12 +58,14 @@ typedef struct { u8 vdat[3072]; // 19a u32 vbt10; // d9a smbios bios version u32 mehh[8]; // d9e management engine hash - // dbe + u32 ramoops_base; // dbe ramoops base address + u32 ramoops_len; // dc2 ramoops length + u8 pad[314]; // dc6-eff } __attribute__((packed)) chromeos_acpi_t; extern chromeos_acpi_t *vboot_data; void chromeos_init_vboot(chromeos_acpi_t *chromeos); void chromeos_set_me_hash(u32*, int); -void acpi_get_vdat_info(void **vdat_addr, uint32_t *vdat_size); +void acpi_get_vdat_info(uint64_t *vdat_addr, uint32_t *vdat_size); #endif diff --git a/src/vendorcode/google/chromeos/lib_vpd.h b/src/vendorcode/google/chromeos/lib_vpd.h new file mode 100644 index 0000000000..e08cb3a654 --- /dev/null +++ b/src/vendorcode/google/chromeos/lib_vpd.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + */ + +#ifndef __LIB_VPD__ +#define __LIB_VPD__ + +#include + +enum { + VPD_OK = 0, + VPD_FAIL, +}; + +enum { + VPD_TYPE_TERMINATOR = 0, + VPD_TYPE_STRING, + VPD_TYPE_INFO = 0xfe, + VPD_TYPE_IMPLICIT_TERMINATOR = 0xff, +}; + +enum { + VPD_AS_LONG_AS = -1, +}; + +enum { /* export_type */ + VPD_EXPORT_KEY_VALUE = 1, + VPD_EXPORT_VALUE, + VPD_EXPORT_AS_PARAMETER, +}; + +/* Callback for decodeVpdString to invoke. */ +typedef int VpdDecodeCallback(const uint8_t *key, int32_t key_len, + const uint8_t *value, int32_t value_len, + void *arg); + +/* Container data types */ +struct StringPair { + uint8_t *key; + uint8_t *value; + int pad_len; + int filter_out; /* TRUE means not exported. */ + struct StringPair *next; +}; + +struct PairContainer { + struct StringPair *first; +}; + + +/*********************************************************************** + * Encode and decode VPD entries + ***********************************************************************/ + +/* Encodes the len into multiple bytes with the following format. + * + * 7 6 ............ 0 + * +----+------------------+ + * |More| Length | ... + * +----+------------------+ + * + * The encode_buf points to the actual position we are going to store. + * encoded_len will return the exact bytes we encoded in this function. + * Returns fail if the buffer is not long enough. + */ +int encodeLen( + const int32_t len, + uint8_t *encode_buf, + const int32_t max_len, + int32_t *encoded_len); + +/* Given an encoded string, this functions decodes the length field which varies + * from 1 byte to many bytes. + * + * The in points the actual byte going to be decoded. The *length returns + * the decoded length field. The number of consumed bytes will be stroed in + * decoded_len. + * + * Returns VPD_FAIL if more bit is 1, but actually reaches the end of string. + */ +int decodeLen( + const int32_t max_len, + const uint8_t *in, + int32_t *length, + int32_t *decoded_len); + + +/* Encodes the terminator. + * When calling, the output_buf should point to the start of buffer while + * *generated_len should contain how many bytes exist in buffer now. + * After return, *generated_len would be plused the number of bytes generated + * in this function. + */ +int encodeVpdTerminator( + const int max_buffer_len, + uint8_t *output_buf, + int *generated_len); + +/* Encodes the given type/key/value pair into buffer. + * + * The pad_value_len is used to control the output value length. + * When pad_value_len > 0, the value is outputted into fixed length (pad \0 + * if the value is shorter). Truncated if too long. + * pad_value_len == VPD_NO_LIMIT, output the value as long as possible. + * This is useful when we want to fix the structure layout at beginning. + * + * The encoded string will be stored in output_buf. If it is longer than + * max_buffer_len, this function returns fail. If the buffer is long enough, + * the generated_len will be updated. + * + * When calling, the output_buf should point to the start of buffer while + * *generated_len should contain how many bytes exist in buffer now. + * After return, *generated_len would be plused the number of bytes generated + * in this function. + * + * The initial value of *generated_len can be non-zero, so that this value + * can be used between multiple calls to encodeVpd2Pair(). + */ +int encodeVpdString( + const uint8_t *key, + const uint8_t *value, + const int pad_value_len, + const int max_buffer_len, + uint8_t *output_buf, + int *generated_len); + + +/* Given the encoded string, this function invokes callback with extracted + * (key, value). The *consumed will be plused the number of bytes consumed in + * this function. + * + * The input_buf points to the first byte of the input buffer. + * + * The *consumed starts from 0, which is actually the next byte to be decoded. + * It can be non-zero to be used in multiple calls. + * + * If one entry is successfully decoded, sends it to callback and returns the + * result. + */ +int decodeVpdString( + const int32_t max_len, + const uint8_t *input_buf, + int32_t *consumed, + VpdDecodeCallback callback, + void *callback_arg); + +/*********************************************************************** + * Container helpers + ***********************************************************************/ +void initContainer(struct PairContainer *container); + +struct StringPair *findString(struct PairContainer *container, + const uint8_t *key, + struct StringPair ***prev_next); + +/* If key is already existed in container, its value will be replaced. + * If not existed, creates new entry in container. + */ +void setString(struct PairContainer *container, + const uint8_t *key, + const uint8_t *value, + const int pad_len); + +/* merge all entries in src into dst. If key is duplicate, overwrite it. + */ +void mergeContainer(struct PairContainer *dst, + const struct PairContainer *src); + +/* subtract src from dst. +*/ +int subtractContainer(struct PairContainer *dst, + const struct PairContainer *src); + +/* Given a container, encode its all entries into the buffer. + */ +int encodeContainer(const struct PairContainer *container, + const int max_buf_len, + uint8_t *buf, + int *generated); + +/* Given a VPD blob, decode its entries and push into container. + */ +int decodeToContainer(struct PairContainer *container, + const int32_t max_len, + const uint8_t *input_buf, + int32_t *consumed); + +/* Set filter for exporting functions. + * If filter is NULL, resets the filter so that everything can be exported. + */ +int setContainerFilter(struct PairContainer *container, + const uint8_t *filter); + +/* + * Remove a key. + * Returns VPD_OK if deleted successfully. Otherwise, VPD_FAIL. + */ +int deleteKey(struct PairContainer *container, + const uint8_t *key); + +/* + * Returns number of pairs in container. + */ +int lenOfContainer(const struct PairContainer *container); + +/* + * Export the container content with human-readable text. + * + * The buf points to the first byte of buffer and *generated contains the number + * of bytes already existed in buffer. + * + * Afterward, the *generated will be plused on exact bytes this function has + * generated. + */ +int exportContainer(const int export_type, + const struct PairContainer *container, + const int max_buf_len, + uint8_t *buf, + int *generated); + +void destroyContainer(struct PairContainer *container); + +#endif /* __LIB_VPD__ */ diff --git a/src/vendorcode/google/chromeos/memlayout.h b/src/vendorcode/google/chromeos/memlayout.h new file mode 100644 index 0000000000..a7ea32e00e --- /dev/null +++ b/src/vendorcode/google/chromeos/memlayout.h @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file contains macro definitions for memlayout.ld linker scripts. */ + +#ifndef __CHROMEOS_MEMLAYOUT_H +#define __CHROMEOS_MEMLAYOUT_H + +/* Careful: required work buffer size depends on RW properties such as key size + * and algorithm -- what works for you might stop working after an update. Do + * NOT lower the asserted minimum without consulting vboot devs (rspangler)! */ +#define VBOOT2_WORK(addr, size) \ + REGION(vboot2_work, addr, size, 8) \ + _ = ASSERT(size >= 12K, "vboot2 work buffer must be at least 12K!"); + +#ifdef __VERSTAGE__ + #define VERSTAGE(addr, sz) \ + SET_COUNTER(VERSTAGE, addr) \ + _ = ASSERT(_everstage - _verstage <= sz, \ + STR(Verstage exceeded its allotted size! (sz))); \ + INCLUDE "vendorcode/google/chromeos/vboot2/verstage.verstage.ld" +#else + #define VERSTAGE(addr, sz) \ + SET_COUNTER(VERSTAGE, addr) \ + . += sz; +#endif + +#ifdef __VERSTAGE__ + #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) VERSTAGE(addr, size) +#else + #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) ROMSTAGE(addr, size) +#endif + +#define WATCHDOG_TOMBSTONE(addr, size) \ + REGION(watchdog_tombstone, addr, size, 4) \ + _ = ASSERT(size == 4, "watchdog tombstones should be exactly 4 byte!"); + +#endif /* __CHROMEOS_MEMLAYOUT_H */ diff --git a/src/vendorcode/google/chromeos/ramoops.c b/src/vendorcode/google/chromeos/ramoops.c new file mode 100644 index 0000000000..566770df7c --- /dev/null +++ b/src/vendorcode/google/chromeos/ramoops.c @@ -0,0 +1,136 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include "chromeos.h" + +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + +static void set_ramoops(chromeos_acpi_t *chromeos, void *ram_oops, size_t size) +{ + if (chromeos == NULL) { + printk(BIOS_DEBUG, "chromeos gnvs is NULL. ramoops not set.\n"); + return; + } + + printk(BIOS_DEBUG, "Ramoops buffer: 0x%zx@0x%p.\n", size, ram_oops); + chromeos->ramoops_base = (uintptr_t)ram_oops; + chromeos->ramoops_len = size; +} + +static void reserve_ram_oops_dynamic(chromeos_acpi_t *chromeos) +{ + const size_t size = CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE; + void *ram_oops; + + if (!IS_ENABLED(CONFIG_CHROMEOS_RAMOOPS_DYNAMIC)) + return; + + ram_oops = cbmem_add(CBMEM_ID_RAM_OOPS, size); + + set_ramoops(chromeos, ram_oops, size); +} + +#if CONFIG_CHROMEOS_RAMOOPS_DYNAMIC +static inline void set_global_chromeos_pointer(chromeos_acpi_t *chromeos) {} +#else /* !CONFIG_CHROMEOS_RAMOOPS_DYNAMIC */ + +static const unsigned long ramoops_base = CONFIG_CHROMEOS_RAMOOPS_RAM_START; +static const unsigned long ramoops_size = CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE; + +/* + * Save pointer to chromeos structure in memory. This is needed because the + * memory reservation is not done when chromeos_init() is called. However, + * the pointer to the chromeos_acpi_t structure is needed to update the + * fields with the rserved base and size. + */ +static chromeos_acpi_t *g_chromeos; + +static void set_global_chromeos_pointer(chromeos_acpi_t *chromeos) +{ + g_chromeos = chromeos; +} + +static void update_gnvs(void *arg) +{ + chromeos_acpi_t **chromeos = arg; + + set_ramoops(*chromeos, (void *)ramoops_base, ramoops_size); +} + +static BOOT_STATE_CALLBACK(bscb_ramoops, update_gnvs, &g_chromeos); + +void chromeos_reserve_ram_oops(struct device *dev, int idx) +{ + const unsigned long base = ramoops_base >> 10; + const unsigned long size = ramoops_size >> 10; + + reserved_ram_resource(dev, idx, base, size); + + boot_state_sched_on_exit(&bscb_ramoops, BS_WRITE_TABLES); +} +#endif /* CONFIG_CHROMEOS_RAMOOPS_DYNAMIC */ + +void chromeos_ram_oops_init(chromeos_acpi_t *chromeos) +{ + set_global_chromeos_pointer(chromeos); + reserve_ram_oops_dynamic(chromeos); +} + +#elif IS_ENABLED(CONFIG_CHROMEOS_RAMOOPS_NON_ACPI) + +static void ramoops_alloc(void *arg) +{ + const size_t size = CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE; + + if (size == 0) + return; + + if (cbmem_add(CBMEM_ID_RAM_OOPS, size) == NULL) + printk(BIOS_ERR, "Could not allocate RAMOOPS buffer\n"); +} + +BOOT_STATE_INIT_ENTRIES(bscb_ramoops) = { + BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, ramoops_alloc, + NULL), +}; + +#endif + +void lb_ramoops(struct lb_header *header) +{ + void *buffer = cbmem_find(CBMEM_ID_RAM_OOPS); + + if (buffer == NULL) + return; + + struct lb_range *ramoops; + ramoops = (struct lb_range *)lb_new_record(header); + ramoops->tag = LB_TAG_RAM_OOPS; + ramoops->size = sizeof(*ramoops); + ramoops->range_start = (uintptr_t)buffer; + ramoops->range_size = CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE; +} diff --git a/src/vendorcode/google/chromeos/symbols.h b/src/vendorcode/google/chromeos/symbols.h new file mode 100644 index 0000000000..77b51b8a67 --- /dev/null +++ b/src/vendorcode/google/chromeos/symbols.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef __CHROMEOS_SYMBOLS_H +#define __CHROMEOS_SYMBOLS_H + +extern u8 _vboot2_work[]; +extern u8 _evboot2_work[]; +#define _vboot2_work_size (_evboot2_work - _vboot2_work) + +/* Careful: _e and __size only defined for the current stage! */ +extern u8 _verstage[]; +extern u8 _everstage[]; +#define _verstage_size (_everstage - _verstage) + +extern u8 _watchdog_tombstone[]; +extern u8 _ewatchdog_tombstone[]; +#define _watchdog_tombstone_size (_ewatchdog_tombstone - _watchdog_tombstone) + +#endif /* __CHROMEOS_SYMBOLS_H */ diff --git a/src/vendorcode/google/chromeos/vbnv.c b/src/vendorcode/google/chromeos/vbnv_cmos.c similarity index 60% rename from src/vendorcode/google/chromeos/vbnv.c rename to src/vendorcode/google/chromeos/vbnv_cmos.c index 2a2faf9e96..f87eab76a6 100644 --- a/src/vendorcode/google/chromeos/vbnv.c +++ b/src/vendorcode/google/chromeos/vbnv_cmos.c @@ -19,41 +19,36 @@ #include #include +#include #include #include -#include +#include #include "chromeos.h" - -#define VBNV_BLOCK_SIZE 16 /* Size of NV storage block in bytes */ - -/* Constants for NV storage. We use this rather than structs and - * bitfields so the data format is consistent across platforms and - * compilers. - */ -#define HEADER_OFFSET 0 -#define HEADER_MASK 0xC0 -#define HEADER_SIGNATURE 0x40 -#define HEADER_FIRMWARE_SETTINGS_RESET 0x20 -#define HEADER_KERNEL_SETTINGS_RESET 0x10 - -#define BOOT_OFFSET 1 -#define BOOT_DEBUG_RESET_MODE 0x80 -#define BOOT_DISABLE_DEV_REQUEST 0x40 -#define BOOT_OPROM_NEEDED 0x20 -#define BOOT_TRY_B_COUNT_MASK 0x0F - -#define RECOVERY_OFFSET 2 -#define LOCALIZATION_OFFSET 3 - -#define DEV_FLAGS_OFFSET 4 -#define DEV_BOOT_USB_MASK 0x01 -#define DEV_BOOT_SIGNED_ONLY_MASK 0x02 - -#define KERNEL_FIELD_OFFSET 11 -#define CRC_OFFSET 15 +#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE) +#include "vboot_handoff.h" +#endif +#include "vbnv_layout.h" static int vbnv_initialized CAR_GLOBAL; -uint8_t vbnv[CONFIG_VBNV_SIZE] CAR_GLOBAL; +static uint8_t vbnv[CONFIG_VBNV_SIZE] CAR_GLOBAL; + +/* Wrappers for accessing the variables marked as CAR_GLOBAL. */ +static inline int is_vbnv_initialized(void) +{ + return car_get_var(vbnv_initialized); +} + +static inline uint8_t *vbnv_data_addr(int index) +{ + uint8_t *vbnv_arr = car_get_var_ptr(vbnv); + + return &vbnv_arr[index]; +} + +static inline uint8_t vbnv_data(int index) +{ + return *vbnv_data_addr(index); +} /* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A * table-based algorithm would be faster, but for only 15 bytes isn't @@ -109,27 +104,30 @@ void save_vbnv(const uint8_t *vbnv_copy) static void vbnv_setup(void) { - read_vbnv(vbnv); - vbnv_initialized = 1; + read_vbnv(vbnv_data_addr(0)); + car_set_var(vbnv_initialized, 1); } int get_recovery_mode_from_vbnv(void) { - if (!vbnv_initialized) + if (!is_vbnv_initialized()) vbnv_setup(); - return vbnv[RECOVERY_OFFSET]; + return vbnv_data(RECOVERY_OFFSET); } int vboot_wants_oprom(void) { - if (!vbnv_initialized) +#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE) + struct vboot_handoff *vbho; + + /* First check if handoff structure flag exists and is set. */ + vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + if (vbho && vbho->init_params.flags & VB_INIT_FLAG_OPROM_LOADED) + return 1; +#endif + + if (!is_vbnv_initialized()) vbnv_setup(); - /* FIXME(crosbug.com/p/8789). The following commented-out line does the - * right thing, assuming that vboot has requested the option ROM and - * rebooted if it finds that it's needed but not loaded. At the moment, - * it doesn't yet do that, so we must always say we want it. */ - - /* return (vbnv[BOOT_OFFSET] & BOOT_OPROM_NEEDED) ? 1 : 0; */ - return 1; + return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0; } diff --git a/src/vendorcode/google/chromeos/vbnv_ec.c b/src/vendorcode/google/chromeos/vbnv_ec.c new file mode 100644 index 0000000000..403b4c32c8 --- /dev/null +++ b/src/vendorcode/google/chromeos/vbnv_ec.c @@ -0,0 +1,113 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "chromeos.h" +#include "vbnv_layout.h" + +static int vbnv_initialized CAR_GLOBAL; +static uint8_t vbnv[VBNV_BLOCK_SIZE] CAR_GLOBAL; + +/* Wrappers for accessing the variables marked as CAR_GLOBAL. */ +static inline int is_vbnv_initialized(void) +{ + return car_get_var(vbnv_initialized); +} + +static inline uint8_t *vbnv_data_addr(int index) +{ + uint8_t *vbnv_arr = car_get_var_ptr(vbnv); + + return &vbnv_arr[index]; +} + +static inline uint8_t vbnv_data(int index) +{ + return *vbnv_data_addr(index); +} + +/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A + * table-based algorithm would be faster, but for only 15 bytes isn't + * worth the code size. + */ + +static uint8_t crc8(const uint8_t * data, int len) +{ + unsigned crc = 0; + int i, j; + + for (j = len; j; j--, data++) { + crc ^= (*data << 8); + for (i = 8; i; i--) { + if (crc & 0x8000) + crc ^= (0x1070 << 3); + crc <<= 1; + } + } + + return (uint8_t) (crc >> 8); +} + +void read_vbnv(uint8_t *vbnv_copy) +{ + google_chromeec_vbnv_context(1, vbnv_copy, VBNV_BLOCK_SIZE); + + /* Check data for consistency */ + if ((HEADER_SIGNATURE != (vbnv_copy[HEADER_OFFSET] & HEADER_MASK)) + || (crc8(vbnv_copy, CRC_OFFSET) != vbnv_copy[CRC_OFFSET])) { + + /* Data is inconsistent (bad CRC or header), + * so reset to defaults + */ + memset(vbnv_copy, 0, VBNV_BLOCK_SIZE); + vbnv_copy[HEADER_OFFSET] = + (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET | + HEADER_KERNEL_SETTINGS_RESET); + } +} + +void save_vbnv(const uint8_t *vbnv_copy) +{ + google_chromeec_vbnv_context(0, (uint8_t *)vbnv_copy, VBNV_BLOCK_SIZE); +} + +static void vbnv_setup(void) +{ + read_vbnv(vbnv_data_addr(0)); + car_set_var(vbnv_initialized, 1); +} + +int get_recovery_mode_from_vbnv(void) +{ + if (!is_vbnv_initialized()) + vbnv_setup(); + return vbnv_data(RECOVERY_OFFSET); +} + +int vboot_wants_oprom(void) +{ + if (!is_vbnv_initialized()) + vbnv_setup(); + + return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0; +} diff --git a/src/vendorcode/google/chromeos/vbnv_flash.c b/src/vendorcode/google/chromeos/vbnv_flash.c new file mode 100644 index 0000000000..97a2a82d1b --- /dev/null +++ b/src/vendorcode/google/chromeos/vbnv_flash.c @@ -0,0 +1,201 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * TODO: Make this CAR-friendly in case we use it on x86 some day. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "chromeos.h" +#include "vbnv_layout.h" + +#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE) +#define BLOB_SIZE VBNV_BLOCK_SIZE +#elif IS_ENABLED(CONFIG_VBOOT2_VERIFY_FIRMWARE) +#define BLOB_SIZE VB2_NVDATA_SIZE +#else +#error unable to determine BLOB_SIZE +#endif + +/* FMAP descriptor of the NVRAM area */ +static struct vboot_region nvram_region; + +/* offset of the current nvdata in SPI flash */ +static int blob_offset = -1; + +/* Offset of the topmost nvdata blob in SPI flash */ +static int top_offset; + +/* cache of the current nvdata */ +static uint8_t cache[BLOB_SIZE]; + +/* spi_flash struct used when saving data */ +static struct spi_flash *spi_flash = NULL; + +/* + * This code assumes that flash is erased to 1-bits, and write operations can + * only change 1-bits to 0-bits. So if the new contents only change 1-bits to + * 0-bits, we can reuse the current blob. + */ +static inline uint8_t erase_value(void) +{ + return 0xff; +} + +static inline int can_overwrite(uint8_t current, uint8_t new) +{ + return (current & new) == new; +} + +static inline int is_initialized(void) +{ + return blob_offset >= 0; +} + +static int init_vbnv(void) +{ + uint8_t buf[BLOB_SIZE]; + uint8_t empty_blob[BLOB_SIZE]; + int offset; + int i; + + vboot_locate_region("RW_NVRAM", &nvram_region); + if (nvram_region.size < BLOB_SIZE) { + printk(BIOS_ERR, "%s: failed to locate NVRAM\n", __func__); + return 1; + } + + /* Prepare an empty blob to compare against. */ + for (i = 0; i < BLOB_SIZE; i++) + empty_blob[i] = erase_value(); + + offset = nvram_region.offset_addr; + top_offset = nvram_region.offset_addr + nvram_region.size - BLOB_SIZE; + + /* + * after the loop, offset is supposed to point the blob right before + * the first empty blob, the last blob in the nvram if there is no + * empty blob, or the base of the region if the nvram has never been + * used. + */ + for (i = offset; i <= top_offset; i += BLOB_SIZE) { + if (vboot_get_region(i, BLOB_SIZE, buf) == NULL) { + printk(BIOS_ERR, "failed to read nvdata\n"); + return 1; + } + if (!memcmp(buf, empty_blob, BLOB_SIZE)) + break; + offset = i; + } + + /* reread the nvdata and write it to the cache */ + if (vboot_get_region(offset, BLOB_SIZE, cache) == NULL) { + printk(BIOS_ERR, "failed to read nvdata\n"); + return 1; + } + + blob_offset = offset; + + return 0; +} + +static int vbnv_flash_probe(void) +{ + if (!spi_flash) { + spi_flash = spi_flash_probe(CONFIG_BOOT_MEDIA_SPI_BUS, 0); + if (!spi_flash) { + printk(BIOS_ERR, "failed to probe spi flash\n"); + return 1; + } + } + return 0; +} + +static int erase_nvram(void) +{ + if (vbnv_flash_probe()) + return 1; + + if (spi_flash->erase(spi_flash, nvram_region.offset_addr, + nvram_region.size)) { + printk(BIOS_ERR, "failed to erase nvram\n"); + return 1; + } + + printk(BIOS_INFO, "nvram is cleared\n"); + return 0; +} + +void read_vbnv(uint8_t *vbnv_copy) +{ + if (!is_initialized()) + if (init_vbnv()) + return; /* error */ + memcpy(vbnv_copy, cache, BLOB_SIZE); +} + +void save_vbnv(const uint8_t *vbnv_copy) +{ + int new_offset; + int i; + + if (!is_initialized()) + if (init_vbnv()) + return; /* error */ + + /* Bail out if there have been no changes. */ + if (!memcmp(vbnv_copy, cache, BLOB_SIZE)) + return; + + new_offset = blob_offset; + + /* See if we can overwrite the current blob with the new one */ + for (i = 0; i < BLOB_SIZE; i++) { + if (!can_overwrite(cache[i], vbnv_copy[i])) { + /* unable to overwrite. need to use the next blob */ + new_offset += BLOB_SIZE; + if (new_offset > top_offset) { + if (erase_nvram()) + return; /* error */ + new_offset = nvram_region.offset_addr; + } + break; + } + } + + if (!vbnv_flash_probe() && + !spi_flash->write(spi_flash, new_offset, BLOB_SIZE, vbnv_copy)) { + /* write was successful. safely move pointer forward */ + blob_offset = new_offset; + memcpy(cache, vbnv_copy, BLOB_SIZE); + } else { + printk(BIOS_ERR, "failed to save nvdata\n"); + } +} + +int get_recovery_mode_from_vbnv(void) +{ + if (!is_initialized()) + init_vbnv(); + return cache[RECOVERY_OFFSET]; +} diff --git a/src/vendorcode/google/chromeos/vbnv_layout.h b/src/vendorcode/google/chromeos/vbnv_layout.h new file mode 100644 index 0000000000..66de405b3b --- /dev/null +++ b/src/vendorcode/google/chromeos/vbnv_layout.h @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef VBNV_LAYOUT_H +#define VBNV_LAYOUT_H + +#define VBNV_BLOCK_SIZE 16 /* Size of NV storage block in bytes */ + +/* Constants for NV storage. We use this rather than structs and + * bitfields so the data format is consistent across platforms and + * compilers. + */ +#define HEADER_OFFSET 0 +#define HEADER_MASK 0xC0 +#define HEADER_SIGNATURE 0x40 +#define HEADER_FIRMWARE_SETTINGS_RESET 0x20 +#define HEADER_KERNEL_SETTINGS_RESET 0x10 + +#define BOOT_OFFSET 1 +#define BOOT_DEBUG_RESET_MODE 0x80 +#define BOOT_DISABLE_DEV_REQUEST 0x40 +#define BOOT_OPROM_NEEDED 0x20 +#define BOOT_TRY_B_COUNT_MASK 0x0F + +#define RECOVERY_OFFSET 2 +#define LOCALIZATION_OFFSET 3 + +#define DEV_FLAGS_OFFSET 4 +#define DEV_BOOT_USB_MASK 0x01 +#define DEV_BOOT_SIGNED_ONLY_MASK 0x02 + +#define KERNEL_FIELD_OFFSET 11 +#define CRC_OFFSET 15 + +#endif /* VBNV_LAYOUT_H */ diff --git a/src/vendorcode/google/chromeos/vboot.c b/src/vendorcode/google/chromeos/vboot.c index 03d759cefc..44fe9e3025 100644 --- a/src/vendorcode/google/chromeos/vboot.c +++ b/src/vendorcode/google/chromeos/vboot.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include "chromeos.h" @@ -233,6 +233,7 @@ static void init_vboot(int bootmode) #if !MOCK_TPM printk(BIOS_ERR, "TPM: Error code 0x%x. Hard reset!\n", result); + post_code(POST_TPM_FAILURE); hard_reset(); #endif } diff --git a/src/vendorcode/google/chromeos/vboot1/Kconfig b/src/vendorcode/google/chromeos/vboot1/Kconfig new file mode 100644 index 0000000000..0102869797 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot1/Kconfig @@ -0,0 +1,34 @@ +## This file is part of the coreboot project. +## +## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config VBOOT_VERIFY_FIRMWARE + bool "Verify firmware with vboot." + default n + depends on CHROMEOS + select RELOCATABLE_MODULES + help + Enabling VBOOT_VERIFY_FIRMWARE will use vboot to verify the ramstage + and boot loader. + +config VBOOT_REFCODE_INDEX + hex "Reference code firmware index" + default 1 + depends on VBOOT_VERIFY_FIRMWARE + help + This is the index of the reference code component in the verified + firmware block. diff --git a/src/vendorcode/google/chromeos/vboot1/Makefile.inc b/src/vendorcode/google/chromeos/vboot1/Makefile.inc new file mode 100644 index 0000000000..a2d42b45f3 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot1/Makefile.inc @@ -0,0 +1,74 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +ramstage-y += ../vboot_common.c +romstage-y += vboot_loader.c ../vboot_common.c +rmodules_$(ARCH-ROMSTAGE-y)-y += vboot_wrapper.c ../vboot_common.c + +ifneq ($(CONFIG_SPI_FLASH_MEMORY_MAPPED),y) +VBOOT_MAKEFLAGS = REGION_READ=1 +endif + +VB_LIB = $(obj)/external/vboot_reference/vboot_fw.a +# Currently, vboot comes into picture only during the romstage, thus +# is compiled for being used in romstage only. Since, we are splitting +# up all components in one of the three stages of coreboot, vboot seems +# most logical to fall under the romstage. Thus, all references to arch +# and other compiler stuff for vboot is using the romstage arch. +VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-ROMSTAGE-y)) + +VBOOT_STUB_ELF = $(obj)/vendorcode/google/chromeos/vboot1/vbootstub.elf +VBOOT_STUB = $(VBOOT_STUB_ELF).rmod + +# Dependency for the vboot rmodules. Ordering matters. +VBOOT_STUB_DEPS += $(obj)/vendorcode/google/chromeos/vboot1/vboot_wrapper.rmodules_$(ARCH-ROMSTAGE-y).o +VBOOT_STUB_DEPS += $(obj)/lib/memcmp.rmodules_$(ARCH-ROMSTAGE-y).o +ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y) +VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memset.rmodules_$(ARCH-ROMSTAGE-y).o +VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memcpy.rmodules_$(ARCH-ROMSTAGE-y).o +endif +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM),y) +VBOOT_STUB_DEPS += $(obj)/arch/arm/memset.rmodules_$(ARCH-ROMSTAGE-y).o +VBOOT_STUB_DEPS += $(obj)/arch/arm/memcpy.rmodules_$(ARCH-ROMSTAGE-y).o +endif +ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM64),y) +VBOOT_STUB_DEPS += $(obj)/lib/memset.rmodules.o +VBOOT_STUB_DEPS += $(obj)/lib/memcpy.rmodules.o +endif +VBOOT_STUB_DEPS += $(VB_LIB) +# Remove the '-include' option since that will break vboot's build and ensure +# vboot_reference can get to coreboot's include files. +VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_romstage))) +VBOOT_CFLAGS += -DVBOOT_DEBUG +VBOOT_CFLAGS += $(rmodules_$(ARCH-ROMSTAGE-y)-c-ccopts) + +# Link the vbootstub module with a 64KiB-byte heap. +$(eval $(call rmodule_link,$(VBOOT_STUB_ELF), $(VBOOT_STUB_DEPS), 0x10000,$(ARCH-ROMSTAGE-y))) + +# Build vboot library without the default includes from coreboot proper. +$(VB_LIB): + @printf " MAKE $(subst $(obj)/,,$(@))\n" + $(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \ + CC="$(CC_romstage)" \ + CFLAGS="$(VBOOT_CFLAGS)" \ + $(MAKE) -C $(VB_SOURCE) \ + $(VBOOT_MAKEFLAGS) \ + BUILD=$(top)/$(dir $(VB_LIB)) \ + V=$(V) \ + fwlib diff --git a/src/vendorcode/google/chromeos/vboot1/vboot_loader.c b/src/vendorcode/google/chromeos/vboot1/vboot_loader.c new file mode 100644 index 0000000000..5b168fffb6 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot1/vboot_loader.c @@ -0,0 +1,432 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../chromeos.h" +#include "../vboot_context.h" +#include "../vboot_handoff.h" + +#define TEMP_CBMEM_ID_VBOOT 0xffffffff +#define TEMP_CBMEM_ID_VBLOCKS 0xfffffffe + +static void vboot_run_stub(struct vboot_context *context) +{ + struct rmod_stage_load rmod_stage = { + .cbmem_id = TEMP_CBMEM_ID_VBOOT, + .name = CONFIG_CBFS_PREFIX "/vboot", + }; + void (*entry)(struct vboot_context *context); + + if (rmodule_stage_load_from_cbfs(&rmod_stage)) { + printk(BIOS_DEBUG, "Could not load vboot stub.\n"); + goto out; + } + + entry = rmod_stage.entry; + + /* Call stub. */ + entry(context); + +out: + /* Tear down the region no longer needed. */ + if (rmod_stage.cbmem_entry != NULL) + cbmem_entry_remove(rmod_stage.cbmem_entry); +} + +/* Helper routines for the vboot stub. */ +static void log_msg(const char *fmt, va_list args) +{ + vtxprintf(console_tx_byte, fmt, args); + console_tx_flush(); +} + +static void fatal_error(void) +{ + printk(BIOS_ERR, "vboot encountered fatal error. Reseting.\n"); + hard_reset(); +} + +static int fw_region_size(struct vboot_region *r) +{ + struct vboot_components *fw_info; + int32_t size; + int i; + + fw_info = vboot_locate_components(r); + if (fw_info == NULL) + return -1; + + if (fw_info->num_components > MAX_PARSED_FW_COMPONENTS) + return -1; + + size = sizeof(*fw_info); + size += sizeof(struct vboot_component_entry) * fw_info->num_components; + + for (i = 0; i < fw_info->num_components; i++) + size += ALIGN(fw_info->entries[i].size, sizeof(uint32_t)); + + /* Check that size of comopnents does not exceed the region's size. */ + if (size > r->size) + return -1; + + /* Update region with the correct size. */ + r->size = size; + + return 0; +} + +static int vboot_fill_params(struct vboot_context *ctx) +{ + VbCommonParams *cparams; + VbSelectFirmwareParams *fparams; + + if (fw_region_size(&ctx->fw_a)) + return -1; + + if (fw_region_size(&ctx->fw_b)) + return -1; + + cparams = ctx->cparams; + fparams = ctx->fparams; + + cparams->gbb_size = ctx->gbb.size; + fparams->verification_size_A = ctx->vblock_a.size; + fparams->verification_size_B = ctx->vblock_b.size; + + if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) { + /* Get memory-mapped pointers to the regions. */ + cparams->gbb_data = vboot_get_region(ctx->gbb.offset_addr, + ctx->gbb.size, NULL); + fparams->verification_block_A = + vboot_get_region(ctx->vblock_a.offset_addr, + ctx->vblock_a.size, NULL); + fparams->verification_block_B = + vboot_get_region(ctx->vblock_b.offset_addr, + ctx->vblock_b.size, NULL); + } else { + /* + * Copy the vblock info into a buffer in cbmem. The gbb will + * be read using VbExRegionRead(). + */ + char *dest; + size_t vblck_sz; + + vblck_sz = ctx->vblock_a.size + ctx->vblock_b.size; + ctx->vblocks = cbmem_entry_add(TEMP_CBMEM_ID_VBLOCKS, vblck_sz); + if (ctx->vblocks == NULL) + return -1; + dest = cbmem_entry_start(ctx->vblocks); + if (vboot_get_region(ctx->vblock_a.offset_addr, + ctx->vblock_a.size, dest) == NULL) + return -1; + fparams->verification_block_A = (void *)dest; + dest += ctx->vblock_a.size; + if (vboot_get_region(ctx->vblock_b.offset_addr, + ctx->vblock_b.size, dest) == NULL) + return -1; + fparams->verification_block_B = (void *)dest; + } + + return 0; +} + +static void fill_handoff(struct vboot_context *context) +{ + struct vboot_components *fw_info; + struct vboot_region *region; + int i; + + /* Fix up the handoff structure. */ + context->handoff->selected_firmware = + context->fparams->selected_firmware; + + /* Parse out the components for downstream consumption. */ + if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A) + region = &context->fw_a; + else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B) + region = &context->fw_b; + else + return; + + fw_info = vboot_locate_components(region); + if (fw_info == NULL) + return; + + for (i = 0; i < fw_info->num_components; i++) { + context->handoff->components[i].address = + region->offset_addr + fw_info->entries[i].offset; + context->handoff->components[i].size = fw_info->entries[i].size; + } +} + +static void vboot_clean_up(struct vboot_context *context) +{ + if (context->vblocks != NULL) + cbmem_entry_remove(context->vblocks); +} + +static void reset(void) +{ + hard_reset(); +} + +static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff) +{ + VbCommonParams cparams; + VbSelectFirmwareParams fparams; + struct vboot_context context; + uint32_t *iflags; + + vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY; + + memset(&cparams, 0, sizeof(cparams)); + memset(&fparams, 0, sizeof(fparams)); + memset(&context, 0, sizeof(context)); + + iflags = &vboot_handoff->init_params.flags; + if (get_developer_mode_switch()) + *iflags |= VB_INIT_FLAG_DEV_SWITCH_ON; + if (get_recovery_mode_switch()) { + clear_recovery_mode_switch(); + *iflags |= VB_INIT_FLAG_REC_BUTTON_PRESSED; + } + if (get_write_protect_state()) + *iflags |= VB_INIT_FLAG_WP_ENABLED; + if (vboot_get_sw_write_protect()) + *iflags |= VB_INIT_FLAG_SW_WP_ENABLED; + if (CONFIG_VIRTUAL_DEV_SWITCH) + *iflags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH; + if (CONFIG_EC_SOFTWARE_SYNC) + *iflags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC; + if (!CONFIG_PHYSICAL_REC_SWITCH) + *iflags |= VB_INIT_FLAG_VIRTUAL_REC_SWITCH; + if (CONFIG_VBOOT_EC_SLOW_UPDATE) + *iflags |= VB_INIT_FLAG_EC_SLOW_UPDATE; + if (CONFIG_VBOOT_OPROM_MATTERS) { + *iflags |= VB_INIT_FLAG_OPROM_MATTERS; + *iflags |= VB_INIT_FLAG_BEFORE_OPROM_LOAD; + /* Will load VGA option rom during this boot */ + if (developer_mode_enabled() || recovery_mode_enabled() || + vboot_wants_oprom()) { + *iflags |= VB_INIT_FLAG_OPROM_LOADED; + } + } + + context.handoff = vboot_handoff; + context.cparams = &cparams; + context.fparams = &fparams; + + cparams.shared_data_blob = &vboot_handoff->shared_data[0]; + cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE; + cparams.caller_context = &context; + + vboot_locate_region("GBB", &context.gbb); + vboot_locate_region("VBLOCK_A", &context.vblock_a); + vboot_locate_region("VBLOCK_B", &context.vblock_b); + vboot_locate_region("FW_MAIN_A", &context.fw_a); + vboot_locate_region("FW_MAIN_B", &context.fw_b); + + /* Check all fmap entries. */ + if (context.fw_a.size < 0 || context.fw_b.size < 0 || + context.vblock_a.size < 0 || context.vblock_b.size < 0 || + context.gbb.size < 0) { + printk(BIOS_DEBUG, "Not all fmap entries found for vboot.\n"); + return; + } + + /* Fill in vboot parameters. */ + if (vboot_fill_params(&context)) { + vboot_clean_up(&context); + return; + } + + /* Initialize callbacks. */ + context.read_vbnv = &read_vbnv; + context.save_vbnv = &save_vbnv; + context.tis_init = &tis_init; + context.tis_open = &tis_open; + context.tis_close = &tis_close; + context.tis_sendrecv = &tis_sendrecv; + context.log_msg = &log_msg; + context.fatal_error = &fatal_error; + context.get_region = &vboot_get_region; + context.reset = &reset; + + vboot_run_stub(&context); + + fill_handoff(&context); + + vboot_clean_up(&context); +} + +#if CONFIG_RELOCATABLE_RAMSTAGE +static void *vboot_load_ramstage(struct vboot_handoff *vboot_handoff, + struct romstage_handoff *handoff) +{ + struct cbfs_stage *stage; + const struct firmware_component *fwc; + struct rmod_stage_load rmod_load = { + .cbmem_id = CBMEM_ID_RAMSTAGE, + .name = CONFIG_CBFS_PREFIX "/ramstage", + }; + + if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) { + printk(BIOS_ERR, "Invalid ramstage index: %d\n", + CONFIG_VBOOT_RAMSTAGE_INDEX); + return NULL; + } + + /* Check for invalid address. */ + fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX]; + if (fwc->address == 0) { + printk(BIOS_DEBUG, "RW ramstage image address invalid.\n"); + return NULL; + } + + printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n", + fwc->address, fwc->size); + + stage = (void *)fwc->address; + + timestamp_add_now(TS_START_COPYRAM); + + if (rmodule_stage_load(&rmod_load, stage)) { + vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY; + printk(BIOS_DEBUG, "Could not load ramstage region.\n"); + return NULL; + } + + cache_loaded_ramstage(handoff, rmod_load.cbmem_entry, rmod_load.entry); + + timestamp_add_now(TS_END_COPYRAM); + + return rmod_load.entry; +} +#else /* CONFIG_RELOCATABLE_RAMSTAGE */ +static void *vboot_load_ramstage(struct vboot_handoff *vboot_handoff, + struct romstage_handoff *handoff) +{ + struct cbfs_stage *stage; + const struct firmware_component *fwc; + void *entry; + void *load; + + if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) { + printk(BIOS_ERR, "Invalid ramstage index: %d\n", + CONFIG_VBOOT_RAMSTAGE_INDEX); + return NULL; + } + + /* Check for invalid address. */ + fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX]; + if (fwc->address == 0) { + printk(BIOS_DEBUG, "RW ramstage image address invalid.\n"); + return NULL; + } + + printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n", + fwc->address, fwc->size); + + /* This will leak a mapping. */ + stage = vboot_get_region(fwc->address, fwc->size, NULL); + + if (stage == NULL) { + printk(BIOS_DEBUG, "Unable to get RW ramstage region.\n"); + return NULL; + } + + load = (void *)(uintptr_t)stage->load; + entry = (void *)(uintptr_t)stage->entry; + + timestamp_add_now(TS_START_COPYRAM); + + /* Stages rely the below clearing so that the bss is initialized. */ + memset(load, 0, stage->memlen); + + if (cbfs_decompress(stage->compression, + ((unsigned char *) stage) + + sizeof(struct cbfs_stage), + load, stage->len)) + return NULL; + + timestamp_add_now(TS_END_COPYRAM); + + return entry; +} +#endif /* CONFIG_RELOCATABLE_RAMSTAGE */ + + +void *vboot_verify_firmware_get_entry(struct romstage_handoff *handoff) +{ + struct vboot_handoff *vboot_handoff; + + /* Don't go down verified boot path on S3 resume. */ + if (handoff != NULL && handoff->s3_resume) + return NULL; + + timestamp_add_now(TS_START_VBOOT); + + vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, + sizeof(*vboot_handoff)); + + if (vboot_handoff == NULL) { + printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n"); + return NULL; + } + + memset(vboot_handoff, 0, sizeof(*vboot_handoff)); + + vboot_invoke_wrapper(vboot_handoff); + + timestamp_add_now(TS_END_VBOOT); + + /* Take RO firmware path since no RW area was selected. */ + if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A && + vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) { + printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n", + vboot_handoff->selected_firmware); + return NULL; + } + + /* Load ramstage from the vboot_handoff structure. */ + return vboot_load_ramstage(vboot_handoff, handoff); +} + +void vboot_verify_firmware(struct romstage_handoff *handoff) +{ + void *entry = vboot_verify_firmware_get_entry(handoff); + + if (entry != NULL) + stage_exit(entry); +} diff --git a/src/vendorcode/google/chromeos/vboot_wrapper.c b/src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c similarity index 61% rename from src/vendorcode/google/chromeos/vboot_wrapper.c rename to src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c index 66b7cfb276..5b9dbbbb31 100644 --- a/src/vendorcode/google/chromeos/vboot_wrapper.c +++ b/src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c @@ -17,66 +17,39 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include +#if CONFIG_ARCH_X86 #include +#else +#include +#endif #include #include #include -#include "vboot_context.h" -#include "vboot_handoff.h" - -static void vboot_wrapper(struct vboot_context *context); - -DEFINE_RMODULE_HEADER(vboot_wrapper_header, vboot_wrapper, RMODULE_TYPE_VBOOT); +#include "../vboot_context.h" +#include "../vboot_handoff.h" /* Keep a global context pointer around for the callbacks to use. */ static struct vboot_context *gcontext; -/* The FW areas consist of multiple components. At the beginning of - * each area is the number of total compoments as well as the size and - * offset for each component. One needs to caculate the total size of the - * signed firmware region based off of the embedded metadata. */ -#define MAX_NUM_COMPONENTS 20 - -struct component_entry { - uint32_t offset; - uint32_t size; -} __attribute__((packed)); - -struct components { - uint32_t num_components; - struct component_entry entries[0]; -} __attribute__((packed)); - - -static void parse_component(const struct components *components, int num, - struct firmware_component *fw) +static void vboot_wrapper(void *arg) { - const char *base; - - if (num >= components->num_components) - return; - - /* Offsets are relative to the stat of the book keeping structure. */ - base = (void *)components; - - fw->address = (uint32_t)&base[components->entries[num].offset]; - fw->size = (uint32_t)components->entries[num].size; -} - -static void vboot_wrapper(struct vboot_context *context) -{ - int i; VbError_t res; - const struct components *components; + struct vboot_context *context; + context = arg; gcontext = context; VbExDebug("Calling VbInit()\n"); res = VbInit(context->cparams, &context->handoff->init_params); VbExDebug("VbInit() returned 0x%08x\n", res); - if (res != VBERROR_SUCCESS) + if (res != VBERROR_SUCCESS) { + if(res == VBERROR_TPM_REBOOT_REQUIRED) { + VbExDebug("TPM Reboot Required. Proceeding reboot.\n"); + gcontext->reset(); + } return; + } VbExDebug("Calling VbSelectFirmware()\n"); res = VbSelectFirmware(context->cparams, context->fparams); @@ -84,23 +57,6 @@ static void vboot_wrapper(struct vboot_context *context) if (res != VBERROR_SUCCESS) return; - - /* Fix up the handoff structure. */ - context->handoff->selected_firmware = - context->fparams->selected_firmware; - - /* Parse out the components for downstream consumption. */ - if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A) - components = (void *)context->fw_a; - else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B) - components = (void *)context->fw_b; - else - return; - - for (i = 0; i < MAX_PARSED_FW_COMPONENTS; i++) { - parse_component(components, i, - &context->handoff->components[i]); - } } void VbExError(const char *format, ...) @@ -125,7 +81,13 @@ void VbExDebug(const char *format, ...) uint64_t VbExGetTimer(void) { +#if CONFIG_ARCH_X86 return rdtscll(); +#else + struct mono_time mt; + timer_monotonic_get(&mt); + return mt.microseconds; +#endif } VbError_t VbExNvStorageRead(uint8_t *buf) @@ -195,43 +157,51 @@ void *Memset(void *dest, const uint8_t c, uint64_t n) return memset(dest, c, n); } +static inline size_t get_hash_block_size(size_t requested_size) +{ + if (!IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) { + const size_t block_size = 64 * 1024; + if (requested_size > block_size) + return block_size; + } + return requested_size; +} + VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, uint32_t firmware_index) { uint8_t *data; - uint32_t size; - uint32_t data_size; - struct components *components; - uint32_t i; + struct vboot_region *region; + struct vboot_context *ctx; + size_t data_size; + uintptr_t offset_addr; + + ctx = cparams->caller_context; switch (firmware_index) { case VB_SELECT_FIRMWARE_A: - data = gcontext->fw_a; - size = gcontext->fw_a_size; + region = &ctx->fw_a; break; case VB_SELECT_FIRMWARE_B: - data = gcontext->fw_b; - size = gcontext->fw_b_size; + region = &ctx->fw_b; break; default: return VBERROR_UNKNOWN; } - components = (void *)data; - data_size = sizeof(struct components); + data_size = region->size; + offset_addr = region->offset_addr; + while (data_size) { + size_t block_size; - if (components->num_components > MAX_NUM_COMPONENTS) - return VBERROR_UNKNOWN; - - data_size += - components->num_components * sizeof(struct component_entry); - - for (i = 0; i < components->num_components; i++) - data_size += ALIGN(components->entries[i].size, 4); - - if (size < data_size) + block_size = get_hash_block_size(data_size); + data = ctx->get_region(offset_addr, block_size, NULL); + if (data == NULL) return VBERROR_UNKNOWN; + VbUpdateFirmwareBodyHash(cparams, data, block_size); - VbUpdateFirmwareBodyHash(cparams, data, data_size); + data_size -= block_size; + offset_addr += block_size; + } return VBERROR_SUCCESS; } @@ -260,9 +230,37 @@ VbError_t VbExTpmOpen(void) VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length, uint8_t *response, uint32_t *response_length) { - if (gcontext->tis_sendrecv(request, request_length, - response, response_length)) + size_t len = *response_length; + if (gcontext->tis_sendrecv(request, request_length, response, &len)) return VBERROR_UNKNOWN; + /* check 64->32bit overflow and (re)check response buffer overflow */ + if (len > *response_length) + return VBERROR_UNKNOWN; + *response_length = len; return VBERROR_SUCCESS; } +#if !CONFIG_SPI_FLASH_MEMORY_MAPPED +VbError_t VbExRegionRead(VbCommonParams *cparams, + enum vb_firmware_region region, uint32_t offset, + uint32_t size, void *buf) +{ + struct vboot_context *ctx; + VbExDebug("VbExRegionRead: offset=%x size=%x, buf=%p\n", + offset, size, buf); + ctx = cparams->caller_context; + + if (region == VB_REGION_GBB) { + if (offset + size > cparams->gbb_size) + return VBERROR_REGION_READ_INVALID; + offset += ctx->gbb.offset_addr; + if (ctx->get_region(offset, size, buf) == NULL) + return VBERROR_REGION_READ_INVALID; + return VBERROR_SUCCESS; + } + + return VBERROR_UNSUPPORTED_REGION; +} +#endif /* CONFIG_SPI_FLASH_MEMORY_MAPPED */ + +RMODULE_ENTRY(vboot_wrapper); diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig b/src/vendorcode/google/chromeos/vboot2/Kconfig new file mode 100644 index 0000000000..20d2f1fc85 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/Kconfig @@ -0,0 +1,43 @@ +## This file is part of the coreboot project. +## +## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +config VBOOT2_VERIFY_FIRMWARE + bool "Firmware Verification with vboot2" + default n + depends on CHROMEOS && HAVE_HARD_RESET + help + Enabling VBOOT2_VERIFY_FIRMWARE will use vboot2 to verify the romstage + and boot loader. + +config RETURN_FROM_VERSTAGE + bool "return from verstage" + default n + depends on VBOOT2_VERIFY_FIRMWARE + help + If this is set, the verstage returns back to the bootblock instead of + exits to the romstage so that the verstage space can be reused by the + romstage. Useful if a ram space is too small to fit both the verstage + and the romstage. + +config VBOOT_ROMSTAGE_INDEX + hex + default 2 + depends on VBOOT2_VERIFY_FIRMWARE + help + This is the index of the romstage component in the verified + firmware block. diff --git a/src/vendorcode/google/chromeos/vboot2/Makefile.inc b/src/vendorcode/google/chromeos/vboot2/Makefile.inc new file mode 100644 index 0000000000..acb0472679 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/Makefile.inc @@ -0,0 +1,57 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +verstage-generic-ccopts += -D__PRE_RAM__ -D__VERSTAGE__ + +bootblock-y += ../vboot_common.c +verstage-y += ../vboot_common.c +romstage-y += ../vboot_common.c +ramstage-y += ../vboot_common.c + +bootblock-y += verstub.c +verstage-y += verstub.c +bootblock-y += common.c +verstage-y += verstage.c +verstage-y += antirollback.c common.c +romstage-y += vboot_handoff.c common.c + +verstage-y += verstage.ld + +VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-VERSTAGE-y)) +VB2_LIB = $(obj)/external/vboot_reference/vboot_fw2.a +VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_verstage))) +VBOOT_CFLAGS += $(verstage-c-ccopts) +VBOOT_CFLAGS += -include $(top)/src/include/kconfig.h -Wno-missing-prototypes +VBOOT_CFLAGS += -DVBOOT_DEBUG + +$(VB2_LIB): | $$(generic-deps) + @printf " MAKE $(subst $(obj)/,,$(@))\n" + $(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \ + CC="$(CC_verstage)" \ + CFLAGS="$(VBOOT_CFLAGS)" VBOOT2="y" \ + $(MAKE) -C $(VB_SOURCE) \ + BUILD=$(top)/$(dir $(VB2_LIB)) \ + V=$(V) \ + fwlib2 + +VERSTAGE_ELF = $(objcbfs)/verstage.elf +cbfs-files-y += $(call strip_quotes,$(CONFIG_CBFS_PREFIX))/verstage +fallback/verstage-file = $(VERSTAGE_ELF) +fallback/verstage-type = stage +fallback/verstage-compression = none \ No newline at end of file diff --git a/src/vendorcode/google/chromeos/vboot2/antirollback.c b/src/vendorcode/google/chromeos/vboot2/antirollback.c new file mode 100644 index 0000000000..407b19cecd --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/antirollback.c @@ -0,0 +1,347 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Functions for querying, manipulating and locking rollback indices + * stored in the TPM NVRAM. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef offsetof +#define offsetof(A,B) __builtin_offsetof(A,B) +#endif + +#ifdef FOR_TEST +#include +#define VBDEBUG(format, args...) printf(format, ## args) +#else +#include +#define VBDEBUG(format, args...) \ + printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args) +#endif + +#define RETURN_ON_FAILURE(tpm_cmd) do { \ + uint32_t result_; \ + if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \ + VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \ + "\n", (int)result_); \ + return result_; \ + } \ + } while (0) + + +uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, + enum vb2_pcr_digest which_digest) +{ + uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE]; + uint32_t size = sizeof(buffer); + int rv; + + rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size); + if (rv != VB2_SUCCESS) + return rv; + if (size < TPM_PCR_DIGEST) + return VB2_ERROR_UNKNOWN; + + return tlcl_extend(pcr, buffer, NULL); +} + +uint32_t tpm_clear_and_reenable(void) +{ + VBDEBUG("TPM: Clear and re-enable\n"); + RETURN_ON_FAILURE(tlcl_force_clear()); + RETURN_ON_FAILURE(tlcl_set_enable()); + RETURN_ON_FAILURE(tlcl_set_deactivated(0)); + + return TPM_SUCCESS; +} + +uint32_t safe_write(uint32_t index, const void *data, uint32_t length) +{ + uint32_t result = tlcl_write(index, data, length); + if (result == TPM_E_MAXNVWRITES) { + RETURN_ON_FAILURE(tpm_clear_and_reenable()); + return tlcl_write(index, data, length); + } else { + return result; + } +} + +uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size) +{ + uint32_t result = tlcl_define_space(index, perm, size); + if (result == TPM_E_MAXNVWRITES) { + RETURN_ON_FAILURE(tpm_clear_and_reenable()); + return tlcl_define_space(index, perm, size); + } else { + return result; + } +} + +static uint32_t read_space_firmware(struct vb2_context *ctx) +{ + int attempts = 3; + + while (attempts--) { + RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata, + VB2_SECDATA_SIZE)); + + if (vb2api_secdata_check(ctx) == VB2_SUCCESS) + return TPM_SUCCESS; + + VBDEBUG("TPM: %s() - bad CRC\n", __func__); + } + + VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__); + return TPM_E_CORRUPTED_STATE; +} + +static uint32_t write_secdata(uint32_t index, + const uint8_t *secdata, + uint32_t len) +{ + uint8_t sd[32]; + uint32_t rv; + int attempts = 3; + + if (len > sizeof(sd)) { + VBDEBUG("TPM: %s() - data is too large\n", __func__); + return TPM_E_WRITE_FAILURE; + } + + while (attempts--) { + rv = safe_write(index, secdata, len); + /* Can't write, not gonna try again */ + if (rv != TPM_SUCCESS) + return rv; + + /* Read it back to be sure it got the right values. */ + rv = tlcl_read(index, sd, len); + if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0) + return rv; + + VBDEBUG("TPM: %s() failed. trying again\n", __func__); + /* Try writing it again. Maybe it was garbled on the way out. */ + } + + VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__); + + return TPM_E_CORRUPTED_STATE; +} + +uint32_t factory_initialize_tpm(struct vb2_context *ctx) +{ + TPM_PERMANENT_FLAGS pflags; + uint32_t result; + /* this is derived from rollback_index.h of vboot_reference. see struct + * RollbackSpaceKernel for details. */ + static const uint8_t secdata_kernel[] = { + 0x02, + 0x4C, 0x57, 0x52, 0x47, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0xE8, + }; + + VBDEBUG("TPM: factory initialization\n"); + + /* + * Do a full test. This only happens the first time the device is + * turned on in the factory, so performance is not an issue. This is + * almost certainly not necessary, but it gives us more confidence + * about some code paths below that are difficult to + * test---specifically the ones that set lifetime flags, and are only + * executed once per physical TPM. + */ + result = tlcl_self_test_full(); + if (result != TPM_SUCCESS) + return result; + + result = tlcl_get_permanent_flags(&pflags); + if (result != TPM_SUCCESS) + return result; + + /* + * TPM may come from the factory without physical presence finalized. + * Fix if necessary. + */ + VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n", + pflags.physicalPresenceLifetimeLock); + if (!pflags.physicalPresenceLifetimeLock) { + VBDEBUG("TPM: Finalizing physical presence\n"); + RETURN_ON_FAILURE(tlcl_finalize_physical_presence()); + } + + /* + * The TPM will not enforce the NV authorization restrictions until the + * execution of a TPM_NV_DefineSpace with the handle of + * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already + * exist. */ + VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked); + if (!pflags.nvLocked) { + VBDEBUG("TPM: Enabling NV locking\n"); + RETURN_ON_FAILURE(tlcl_set_nv_locked()); + } + + /* Clear TPM owner, in case the TPM is already owned for some reason. */ + VBDEBUG("TPM: Clearing owner\n"); + RETURN_ON_FAILURE(tpm_clear_and_reenable()); + + /* Define the backup space. No need to initialize it, though. */ + RETURN_ON_FAILURE(safe_define_space(BACKUP_NV_INDEX, + TPM_NV_PER_PPWRITE, + VB2_NVDATA_SIZE)); + + /* Define and initialize the kernel space */ + RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX, + TPM_NV_PER_PPWRITE, + sizeof(secdata_kernel))); + RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX, + secdata_kernel, + sizeof(secdata_kernel))); + + /* Defines and sets vb2 secdata space */ + vb2api_secdata_create(ctx); + RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX, + TPM_NV_PER_GLOBALLOCK | + TPM_NV_PER_PPWRITE, + VB2_SECDATA_SIZE)); + RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX, + ctx->secdata, + VB2_SECDATA_SIZE)); + + VBDEBUG("TPM: factory initialization successful\n"); + + return TPM_SUCCESS; +} + +/* + * SetupTPM starts the TPM and establishes the root of trust for the + * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a + * TPM hardware failure. 3 An unexpected TPM state due to some attack. In + * general we cannot easily distinguish the kind of failure, so our strategy is + * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM + * again, which executes (almost) the same sequence of operations. There is a + * good chance that, if recovery mode was entered because of a TPM failure, the + * failure will repeat itself. (In general this is impossible to guarantee + * because we have no way of creating the exact TPM initial state at the + * previous boot.) In recovery mode, we ignore the failure and continue, thus + * giving the recovery kernel a chance to fix things (that's why we don't set + * bGlobalLock). The choice is between a knowingly insecure device and a + * bricked device. + * + * As a side note, observe that we go through considerable hoops to avoid using + * the STCLEAR permissions for the index spaces. We do this to avoid writing + * to the TPM flashram at every reboot or wake-up, because of concerns about + * the durability of the NVRAM. + */ +uint32_t setup_tpm(struct vb2_context *ctx) +{ + uint8_t disable; + uint8_t deactivated; + uint32_t result; + + RETURN_ON_FAILURE(tlcl_lib_init()); + +#ifdef TEGRA_SOFT_REBOOT_WORKAROUND + result = tlcl_startup(); + if (result == TPM_E_INVALID_POSTINIT) { + /* + * Some prototype hardware doesn't reset the TPM on a CPU + * reset. We do a hard reset to get around this. + */ + VBDEBUG("TPM: soft reset detected\n", result); + return TPM_E_MUST_REBOOT; + } else if (result != TPM_SUCCESS) { + VBDEBUG("TPM: tlcl_startup returned %08x\n", result); + return result; + } +#else + RETURN_ON_FAILURE(tlcl_startup()); +#endif + + /* + * Some TPMs start the self test automatically at power on. In that case + * we don't need to call ContinueSelfTest. On some (other) TPMs, + * continue_self_test may block. In that case, we definitely don't want + * to call it here. For TPMs in the intersection of these two sets, we + * are screwed. (In other words: TPMs that require manually starting the + * self-test AND block will have poor performance until we split + * tlcl_send_receive() into send() and receive(), and have a state + * machine to control setup.) + * + * This comment is likely to become obsolete in the near future, so + * don't trust it. It may have not been updated. + */ +#ifdef TPM_MANUAL_SELFTEST +#ifdef TPM_BLOCKING_CONTINUESELFTEST +#warning "lousy TPM!" +#endif + RETURN_ON_FAILURE(tlcl_continue_self_test()); +#endif + result = tlcl_assert_physical_presence(); + if (result != TPM_SUCCESS) { + /* + * It is possible that the TPM was delivered with the physical + * presence command disabled. This tries enabling it, then + * tries asserting PP again. + */ + RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable()); + RETURN_ON_FAILURE(tlcl_assert_physical_presence()); + } + + /* Check that the TPM is enabled and activated. */ + RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL)); + if (disable || deactivated) { + VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n", + disable, deactivated); + RETURN_ON_FAILURE(tlcl_set_enable()); + RETURN_ON_FAILURE(tlcl_set_deactivated(0)); + VBDEBUG("TPM: Must reboot to re-enable\n"); + return TPM_E_MUST_REBOOT; + } + + VBDEBUG("TPM: SetupTPM() succeeded\n"); + return TPM_SUCCESS; +} + +uint32_t antirollback_read_space_firmware(struct vb2_context *ctx) +{ + uint32_t rv; + + rv = setup_tpm(ctx); + if (rv) + return rv; + + /* Read the firmware space. */ + rv = read_space_firmware(ctx); + if (rv == TPM_E_BADINDEX) { + /* + * This seems the first time we've run. Initialize the TPM. + */ + VBDEBUG("TPM: Not initialized yet.\n"); + RETURN_ON_FAILURE(factory_initialize_tpm(ctx)); + } else if (rv != TPM_SUCCESS) { + VBDEBUG("TPM: Firmware space in a bad state; giving up.\n"); + //RETURN_ON_FAILURE(factory_initialize_tpm(ctx)); + return TPM_E_CORRUPTED_STATE; + } + + return TPM_SUCCESS; +} + +uint32_t antirollback_write_space_firmware(struct vb2_context *ctx) +{ + return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE); +} + +uint32_t antirollback_lock_space_firmware() +{ + return tlcl_set_global_lock(); +} diff --git a/src/vendorcode/google/chromeos/vboot2/common.c b/src/vendorcode/google/chromeos/vboot2/common.c new file mode 100644 index 0000000000..15b661a7b4 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/common.c @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "../chromeos.h" +#include "../symbols.h" +#include "../vboot_handoff.h" +#include "misc.h" + +void *vboot_load_stage(int stage_index, + struct vboot_region *fw_main, + struct vboot_components *fw_info) +{ + struct cbfs_media default_media, *media = &default_media; + uintptr_t fc_addr; + uint32_t fc_size; + void *entry; + + if (stage_index >= fw_info->num_components) { + printk(BIOS_INFO, "invalid stage index\n"); + return NULL; + } + + fc_addr = fw_main->offset_addr + fw_info->entries[stage_index].offset; + fc_size = fw_info->entries[stage_index].size; + if (fc_size == 0 || + fc_addr + fc_size > fw_main->offset_addr + fw_main->size) { + printk(BIOS_INFO, "invalid stage address or size\n"); + return NULL; + } + + init_default_cbfs_media(media); + + /* we're making cbfs access offset outside of the region managed by + * cbfs. this works because cbfs_load_stage_by_offset does not check + * the offset. */ + entry = cbfs_load_stage_by_offset(media, fc_addr); + if (entry == (void *)-1) + entry = NULL; + return entry; +} + +struct vb2_working_data * const vboot_get_working_data(void) +{ + return (struct vb2_working_data *)_vboot2_work; +} + +void *vboot_get_work_buffer(struct vb2_working_data *wd) +{ + return (void *)((uintptr_t)wd + wd->buffer_offset); +} + +void vboot_reboot(void) +{ + hard_reset(); + die("failed to reboot"); +} diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h new file mode 100644 index 0000000000..d638cfadae --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/misc.h @@ -0,0 +1,74 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __CHROMEOS_VBOOT2_MISC_H__ +#define __CHROMEOS_VBOOT2_MISC_H__ + +#include "../vboot_common.h" + +void *vboot2_verify_firmware(void); +void *vboot2_load_ramstage(void); +void verstage_main(void); +void *vboot_load_stage(int stage_index, + struct vboot_region *fw_main, + struct vboot_components *fw_info); +void vboot_reboot(void); + +/* + * this is placed at the start of the vboot work buffer. selected_region is used + * for the verstage to return the location of the selected slot. buffer is used + * by the vboot2 core. Keep the struct cpu architecture agnostic as it crosses + * stage boundaries. + */ +struct vb2_working_data { + uint32_t selected_region_offset; + uint32_t selected_region_size; + /* offset of the buffer from the start of this struct */ + uint32_t buffer_offset; + uint32_t buffer_size; +}; + +struct vb2_working_data * const vboot_get_working_data(void); +void *vboot_get_work_buffer(struct vb2_working_data *wd); + +static inline void vb2_get_selected_region(struct vb2_working_data *wd, + struct vboot_region *region) +{ + region->offset_addr = wd->selected_region_offset; + region->size = wd->selected_region_size; +} + +static inline void vb2_set_selected_region(struct vb2_working_data *wd, + struct vboot_region *region) +{ + wd->selected_region_offset = region->offset_addr; + wd->selected_region_size = region->size; +} + +static inline int vboot_is_slot_selected(struct vb2_working_data *wd) +{ + return wd->selected_region_size > 0; +} + +static inline int vboot_is_readonly_path(struct vb2_working_data *wd) +{ + return wd->selected_region_size == 0; +} + +#endif /* __CHROMEOS_VBOOT2_MISC_H__ */ diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c new file mode 100644 index 0000000000..963f3ed976 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c @@ -0,0 +1,184 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NEED_VB20_INTERNALS /* TODO: remove me! */ +#include +#include +#include "../chromeos.h" +#include "../fmap.h" +#include "../vboot_handoff.h" +#include "misc.h" + +static void *load_ramstage(struct vboot_handoff *vboot_handoff, + struct vboot_region *fw_main) +{ + struct vboot_components *fw_info; + void *ret; + int i; + + fw_info = vboot_locate_components(fw_main); + if (fw_info == NULL) + die("failed to locate firmware components\n"); + + /* these offset & size are used to load a rw boot loader */ + for (i = 0; i < fw_info->num_components; i++) { + vboot_handoff->components[i].address = + fw_main->offset_addr + fw_info->entries[i].offset; + vboot_handoff->components[i].size = fw_info->entries[i].size; + } + + timestamp_add_now(TS_START_COPYRAM); + ret = vboot_load_stage(CONFIG_VBOOT_RAMSTAGE_INDEX, fw_main, fw_info); + timestamp_add_now(TS_END_COPYRAM); + return ret; +} + +/** + * Sets vboot_handoff based on the information in vb2_shared_data + * + * TODO: Add VBSD_BOOT_FIRMWARE_SW_WP_ENABLED logic + */ +static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, + struct vb2_shared_data *vb2_sd) +{ + VbSharedDataHeader *vb_sd = + (VbSharedDataHeader *)vboot_handoff->shared_data; + uint32_t *oflags = &vboot_handoff->init_params.out_flags; + + vb_sd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2; + + vboot_handoff->selected_firmware = vb2_sd->fw_slot; + + vb_sd->firmware_index = vb2_sd->fw_slot; + + vb_sd->magic = VB_SHARED_DATA_MAGIC; + vb_sd->struct_version = VB_SHARED_DATA_VERSION; + vb_sd->struct_size = sizeof(VbSharedDataHeader); + vb_sd->data_size = VB_SHARED_DATA_MIN_SIZE; + vb_sd->data_used = sizeof(VbSharedDataHeader); + vb_sd->fw_version_tpm = vb2_sd->fw_version_secdata; + + if (get_write_protect_state()) + vb_sd->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED; + + if (vb2_sd->recovery_reason) { + vb_sd->firmware_index = 0xFF; + if (vb2_sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY) + vb_sd->flags |= VBSD_BOOT_REC_SWITCH_ON; + *oflags |= VB_INIT_OUT_ENABLE_RECOVERY; + *oflags |= VB_INIT_OUT_CLEAR_RAM; + *oflags |= VB_INIT_OUT_ENABLE_DISPLAY; + *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE; + } + if (vb2_sd->flags & VB2_SD_DEV_MODE_ENABLED) { + *oflags |= VB_INIT_OUT_ENABLE_DEVELOPER; + *oflags |= VB_INIT_OUT_CLEAR_RAM; + *oflags |= VB_INIT_OUT_ENABLE_DISPLAY; + *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE; + vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON; + vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON; + } + /* TODO: Set these in depthcharge */ + if (CONFIG_VIRTUAL_DEV_SWITCH) + vb_sd->flags |= VBSD_HONOR_VIRT_DEV_SWITCH; + if (CONFIG_EC_SOFTWARE_SYNC) + vb_sd->flags |= VBSD_EC_SOFTWARE_SYNC; + if (!CONFIG_PHYSICAL_REC_SWITCH) + vb_sd->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL; + + /* In vboot1, VBSD_FWB_TRIED is + * set only if B is booted as explicitly requested. Therefore, if B is + * booted because A was found bad, the flag should not be set. It's + * better not to touch it if we can only ambiguously control it. */ + /* if (vb2_sd->fw_slot) + vb_sd->flags |= VBSD_FWB_TRIED; */ + + /* copy kernel subkey if it's found */ + if (vb2_sd->workbuf_preamble_size) { + struct vb2_fw_preamble *fp; + uintptr_t dst, src; + printk(BIOS_INFO, "Copying FW preamble\n"); + fp = (struct vb2_fw_preamble *)((uintptr_t)vb2_sd + + vb2_sd->workbuf_preamble_offset); + src = (uintptr_t)&fp->kernel_subkey + + fp->kernel_subkey.key_offset; + dst = (uintptr_t)vb_sd + sizeof(VbSharedDataHeader); + assert(dst + fp->kernel_subkey.key_size <= + (uintptr_t)vboot_handoff + sizeof(*vboot_handoff)); + memcpy((void *)dst, (void *)src, + fp->kernel_subkey.key_size); + vb_sd->data_used += fp->kernel_subkey.key_size; + vb_sd->kernel_subkey.key_offset = + dst - (uintptr_t)&vb_sd->kernel_subkey; + vb_sd->kernel_subkey.key_size = fp->kernel_subkey.key_size; + vb_sd->kernel_subkey.algorithm = fp->kernel_subkey.algorithm; + vb_sd->kernel_subkey.key_version = + fp->kernel_subkey.key_version; + } + + vb_sd->recovery_reason = vb2_sd->recovery_reason; +} + +/** + * Load ramstage and return the entry point + */ +void *vboot2_load_ramstage(void) +{ + struct vboot_handoff *vh; + struct vb2_shared_data *sd; + struct vboot_region fw_main; + struct vb2_working_data *wd = vboot_get_working_data(); + + sd = vboot_get_work_buffer(wd); + sd->workbuf_hash_offset = 0; + sd->workbuf_hash_size = 0; + + printk(BIOS_INFO, "creating vboot_handoff structure\n"); + vh = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, sizeof(*vh)); + if (vh == NULL) + /* we don't need to failover gracefully here because this + * shouldn't happen with the image that has passed QA. */ + die("failed to allocate vboot_handoff structure\n"); + + memset(vh, 0, sizeof(*vh)); + + /* needed until we finish transtion to vboot2 for kernel verification */ + fill_vboot_handoff(vh, sd); + + if (vboot_is_readonly_path(wd)) + /* we're on recovery path. continue to ro-ramstage. */ + return NULL; + + printk(BIOS_INFO, + "loading ramstage from Slot %c\n", sd->fw_slot ? 'B' : 'A'); + vb2_get_selected_region(wd, &fw_main); + + return load_ramstage(vh, &fw_main); +} diff --git a/src/vendorcode/google/chromeos/vboot2/verstage.c b/src/vendorcode/google/chromeos/vboot2/verstage.c new file mode 100644 index 0000000000..26525b9550 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/verstage.c @@ -0,0 +1,323 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../chromeos.h" +#include "misc.h" + +#define TODO_BLOCK_SIZE 1024 + +static int is_slot_a(struct vb2_context *ctx) +{ + return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B); +} + +/* exports */ + +void vb2ex_printf(const char *func, const char *fmt, ...) +{ + va_list args; + + printk(BIOS_INFO, "VB2:%s() ", func); + va_start(args, fmt); + vprintk(BIOS_INFO, fmt, args); + va_end(args); + + return; +} + +int vb2ex_tpm_clear_owner(struct vb2_context *ctx) +{ + uint32_t rv; + printk(BIOS_INFO, "Clearing TPM owner\n"); + rv = tpm_clear_and_reenable(); + if (rv) + return VB2_ERROR_EX_TPM_CLEAR_OWNER; + return VB2_SUCCESS; +} + +int vb2ex_read_resource(struct vb2_context *ctx, + enum vb2_resource_index index, + uint32_t offset, + void *buf, + uint32_t size) +{ + struct vboot_region region; + + switch (index) { + case VB2_RES_GBB: + vboot_locate_region("GBB", ®ion); + break; + case VB2_RES_FW_VBLOCK: + if (is_slot_a(ctx)) + vboot_locate_region("VBLOCK_A", ®ion); + else + vboot_locate_region("VBLOCK_B", ®ion); + break; + default: + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + } + + if (offset + size > region.size) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; + + if (vboot_get_region(region.offset_addr + offset, size, buf) == NULL) + return VB2_ERROR_UNKNOWN; + + return VB2_SUCCESS; +} + +/* No-op stubs that can be overridden by SoCs with hardware crypto support. */ +__attribute__((weak)) +int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, + uint32_t data_size) +{ + return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; +} + +__attribute__((weak)) +int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + BUG(); /* Should never get called if init() returned an error. */ + return VB2_ERROR_UNKNOWN; +} + +__attribute__((weak)) +int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size) +{ + BUG(); /* Should never get called if init() returned an error. */ + return VB2_ERROR_UNKNOWN; +} + +static int hash_body(struct vb2_context *ctx, struct vboot_region *fw_main) +{ + uint64_t load_ts; + uint32_t expected_size; + uint8_t block[TODO_BLOCK_SIZE]; + size_t block_size = sizeof(block); + uintptr_t offset; + int rv; + + /* + * Since loading the firmware and calculating its hash is intertwined, + * we use this little trick to measure them separately and pretend it + * was first loaded and then hashed in one piece with the timestamps. + * (This split won't make sense with memory-mapped media like on x86.) + */ + load_ts = timestamp_get(); + timestamp_add(TS_START_HASH_BODY, load_ts); + + expected_size = fw_main->size; + offset = fw_main->offset_addr; + + /* Start the body hash */ + rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expected_size); + if (rv) + return rv; + + /* Extend over the body */ + while (expected_size) { + uint64_t temp_ts; + void *b; + if (block_size > expected_size) + block_size = expected_size; + + temp_ts = timestamp_get(); + b = vboot_get_region(offset, block_size, block); + if (b == NULL) + return VB2_ERROR_UNKNOWN; + load_ts += timestamp_get() - temp_ts; + + rv = vb2api_extend_hash(ctx, b, block_size); + if (rv) + return rv; + + expected_size -= block_size; + offset += block_size; + } + + timestamp_add(TS_DONE_LOADING, load_ts); + timestamp_add_now(TS_DONE_HASHING); + + /* Check the result (with RSA signature verification) */ + rv = vb2api_check_hash(ctx); + if (rv) + return rv; + + timestamp_add_now(TS_END_HASH_BODY); + + return VB2_SUCCESS; +} + +static int locate_firmware(struct vb2_context *ctx, + struct vboot_region *fw_main) +{ + if (is_slot_a(ctx)) + vboot_locate_region("FW_MAIN_A", fw_main); + else + vboot_locate_region("FW_MAIN_B", fw_main); + + if (fw_main->size < 0) + return 1; + + return 0; +} + +/** + * Save non-volatile and/or secure data if needed. + */ +static void save_if_needed(struct vb2_context *ctx) +{ + if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) { + printk(BIOS_INFO, "Saving nvdata\n"); + save_vbnv(ctx->nvdata); + ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED; + } + if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) { + printk(BIOS_INFO, "Saving secdata\n"); + antirollback_write_space_firmware(ctx); + ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED; + } +} + +static uint32_t extend_pcrs(struct vb2_context *ctx) +{ + return tpm_extend_pcr(ctx, 0, BOOT_MODE_PCR) || + tpm_extend_pcr(ctx, 1, HWID_DIGEST_PCR); +} + +/** + * Verify and select the firmware in the RW image + * + * TODO: Avoid loading a stage twice (once in hash_body & again in load_stage). + * when per-stage verification is ready. + */ +void verstage_main(void) +{ + struct vb2_context ctx; + struct vboot_region fw_main; + struct vb2_working_data *wd = vboot_get_working_data(); + int rv; + timestamp_add_now(TS_START_VBOOT); + + /* Set up context and work buffer */ + memset(&ctx, 0, sizeof(ctx)); + ctx.workbuf = vboot_get_work_buffer(wd); + ctx.workbuf_size = wd->buffer_size; + + /* Read nvdata from a non-volatile storage */ + read_vbnv(ctx.nvdata); + + /* Read secdata from TPM. Initialize TPM if secdata not found. We don't + * check the return value here because vb2api_fw_phase1 will catch + * invalid secdata and tell us what to do (=reboot). */ + timestamp_add_now(TS_START_TPMINIT); + antirollback_read_space_firmware(&ctx); + timestamp_add_now(TS_END_TPMINIT); + + if (get_developer_mode_switch()) + ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE; + if (get_recovery_mode_switch()) { + clear_recovery_mode_switch(); + ctx.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; + } + + /* Do early init (set up secdata and NVRAM, load GBB) */ + printk(BIOS_INFO, "Phase 1\n"); + rv = vb2api_fw_phase1(&ctx); + if (rv) { + printk(BIOS_INFO, "Recovery requested (%x)\n", rv); + /* If we need recovery mode, leave firmware selection now */ + save_if_needed(&ctx); + extend_pcrs(&ctx); /* ignore failures */ + timestamp_add_now(TS_END_VBOOT); + return; + } + + /* Determine which firmware slot to boot (based on NVRAM) */ + printk(BIOS_INFO, "Phase 2\n"); + rv = vb2api_fw_phase2(&ctx); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + save_if_needed(&ctx); + vboot_reboot(); + } + + /* Try that slot (verify its keyblock and preamble) */ + printk(BIOS_INFO, "Phase 3\n"); + timestamp_add_now(TS_START_VERIFY_SLOT); + rv = vb2api_fw_phase3(&ctx); + timestamp_add_now(TS_END_VERIFY_SLOT); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + save_if_needed(&ctx); + vboot_reboot(); + } + + printk(BIOS_INFO, "Phase 4\n"); + rv = locate_firmware(&ctx, &fw_main); + if (rv) + die("Failed to read FMAP to locate firmware"); + + rv = hash_body(&ctx, &fw_main); + save_if_needed(&ctx); + if (rv) { + printk(BIOS_INFO, "Reboot requested (%x)\n", rv); + vboot_reboot(); + } + + rv = extend_pcrs(&ctx); + if (rv) { + printk(BIOS_WARNING, "Failed to extend TPM PCRs (%#x)\n", rv); + vb2api_fail(&ctx, VB2_RECOVERY_RO_TPM_U_ERROR, rv); + save_if_needed(&ctx); + vboot_reboot(); + } + + /* Lock TPM */ + rv = antirollback_lock_space_firmware(); + if (rv) { + printk(BIOS_INFO, "Failed to lock TPM (%x)\n", rv); + vb2api_fail(&ctx, VB2_RECOVERY_RO_TPM_L_ERROR, 0); + save_if_needed(&ctx); + vboot_reboot(); + } + + printk(BIOS_INFO, "Slot %c is selected\n", is_slot_a(&ctx) ? 'A' : 'B'); + vb2_set_selected_region(wd, &fw_main); + timestamp_add_now(TS_END_VBOOT); +} + +#if IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE) +void main(void) +{ + console_init(); + exception_init(); + verstage_main(); +} +#endif diff --git a/src/vendorcode/google/chromeos/vboot2/verstage.ld b/src/vendorcode/google/chromeos/vboot2/verstage.ld new file mode 100644 index 0000000000..c7fd6462a3 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/verstage.ld @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This file is included inside a SECTIONS block */ + +.text . : { + _program = .; + _verstage = .; + *(.text._start); + *(.text.stage_entry); + *(.text); + *(.text.*); +} : to_load + +.data . : { + *(.rodata); + *(.rodata.*); + *(.data); + *(.data.*); + . = ALIGN(8); +} + +.bss . : { + . = ALIGN(8); + _bss = .; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + _ebss = .; + _everstage = .; + _eprogram = .; +} + +/* Discard the sections we don't need/want */ +/DISCARD/ : { + *(.comment) + *(.note) + *(.comment.*) + *(.note.*) + *(.eh_frame); +} diff --git a/src/vendorcode/google/chromeos/vboot2/verstub.c b/src/vendorcode/google/chromeos/vboot2/verstub.c new file mode 100644 index 0000000000..5630defc28 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot2/verstub.c @@ -0,0 +1,96 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "../chromeos.h" +#include "../symbols.h" +#include "misc.h" + +static struct vb2_working_data *init_vb2_working_data(void) +{ + struct vb2_working_data *wd; + + wd = vboot_get_working_data(); + memset(wd, 0, _vboot2_work_size); + /* 8-byte alignment for ARMv7 */ + wd->buffer_offset = ALIGN_UP(sizeof(*wd), 8); + wd->buffer_size = _vboot2_work_size - wd->buffer_offset; + + return wd; +} + +/** + * Verify a slot and jump to the next stage + * + * This could be either part of the (1) bootblock or the (2) verstage, depending + * on CONFIG_RETURN_FROM_VERSTAGE. + * + * 1) It jumps to the verstage and comes back, then, loads the romstage over the + * verstage space and exits to it. (note the cbfs cache is trashed on return + * from the verstage.) + * + * 2) We're already in the verstage. Verify firmware, then load the romstage and + * exits to it. + */ +void *vboot2_verify_firmware(void) +{ + void *entry; + struct vb2_working_data *wd; + + wd = init_vb2_working_data(); + + if (IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE)) { + /* load verstage from RO */ + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/verstage"); + if (entry == (void *)-1) + die("failed to load verstage"); + + /* verify and select a slot */ + stage_exit(entry); + } else { + verstage_main(); + } + + /* jump to the selected slot */ + timestamp_add_now(TS_START_COPYROM); + entry = (void *)-1; + if (vboot_is_slot_selected(wd)) { + /* RW A or B */ + struct vboot_region fw_main; + struct vboot_components *fw_info; + vb2_get_selected_region(wd, &fw_main); + fw_info = vboot_locate_components(&fw_main); + if (fw_info == NULL) + die("failed to locate firmware components\n"); + entry = vboot_load_stage(CONFIG_VBOOT_ROMSTAGE_INDEX, + &fw_main, fw_info); + } else if (vboot_is_readonly_path(wd)) { + /* RO */ + entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/romstage"); + } + timestamp_add_now(TS_END_COPYROM); + + return entry; +} diff --git a/src/vendorcode/google/chromeos/vboot_common.c b/src/vendorcode/google/chromeos/vboot_common.c new file mode 100644 index 0000000000..b2893d9fa9 --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot_common.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "chromeos.h" +#include "vboot_common.h" + +void vboot_locate_region(const char *name, struct vboot_region *region) +{ + region->size = find_fmap_entry(name, (void **)®ion->offset_addr); +} + +void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest) +{ + if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) { + if (dest != NULL) + return memcpy(dest, (void *)offset_addr, size); + else + return (void *)offset_addr; + } else { + struct cbfs_media default_media, *media = &default_media; + void *cache; + + init_default_cbfs_media(media); + media->open(media); + if (dest != NULL) { + cache = dest; + if (media->read(media, dest, offset_addr, size) != size) + cache = NULL; + } else { + cache = media->map(media, offset_addr, size); + if (cache == CBFS_MEDIA_INVALID_MAP_ADDRESS) + cache = NULL; + } + media->close(media); + return cache; + } +} + +int vboot_get_handoff_info(void **addr, uint32_t *size) +{ + struct vboot_handoff *vboot_handoff; + + vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vboot_handoff == NULL) + return -1; + + *addr = vboot_handoff; + *size = sizeof(*vboot_handoff); + return 0; +} + +/* This will leak a mapping of a fw region */ +struct vboot_components *vboot_locate_components(struct vboot_region *region) +{ + size_t req_size; + struct vboot_components *vbc; + + req_size = sizeof(*vbc); + req_size += sizeof(struct vboot_component_entry) * + MAX_PARSED_FW_COMPONENTS; + + vbc = vboot_get_region(region->offset_addr, req_size, NULL); + if (vbc && vbc->num_components > MAX_PARSED_FW_COMPONENTS) + vbc = NULL; + + return vbc; +} + +void *vboot_get_payload(int *len) +{ + struct vboot_handoff *vboot_handoff; + struct firmware_component *fwc; + + vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF); + + if (vboot_handoff == NULL) + return NULL; + + if (CONFIG_VBOOT_BOOT_LOADER_INDEX >= MAX_PARSED_FW_COMPONENTS) { + printk(BIOS_ERR, "Invalid boot loader index: %d\n", + CONFIG_VBOOT_BOOT_LOADER_INDEX); + return NULL; + } + + fwc = &vboot_handoff->components[CONFIG_VBOOT_BOOT_LOADER_INDEX]; + + /* If payload size is zero fall back to cbfs path. */ + if (fwc->size == 0) + return NULL; + + if (len != NULL) + *len = fwc->size; + + printk(BIOS_DEBUG, "Booting 0x%x byte verified payload at 0x%08x.\n", + fwc->size, fwc->address); + + /* This will leak a mapping. */ + return vboot_get_region(fwc->address, fwc->size, NULL); +} diff --git a/src/vendorcode/google/chromeos/vboot_common.h b/src/vendorcode/google/chromeos/vboot_common.h new file mode 100644 index 0000000000..b0e6e8711b --- /dev/null +++ b/src/vendorcode/google/chromeos/vboot_common.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef VBOOT_COMMON_H +#define VBOOT_COMMON_H + +/* TODO(shawnn): Remove these CONFIGs and define default weak functions + * that can be overridden in the platform / MB code. */ +struct vboot_region { + uintptr_t offset_addr; + int32_t size; +}; + +/* The FW areas consist of multiple components. At the beginning of + * each area is the number of total compoments as well as the size and + * offset for each component. One needs to caculate the total size of the + * signed firmware region based off of the embedded metadata. */ +struct vboot_component_entry { + uint32_t offset; + uint32_t size; +} __attribute__((packed)); + +struct vboot_components { + uint32_t num_components; + struct vboot_component_entry entries[0]; +} __attribute__((packed)); + +void vboot_locate_region(const char *name, struct vboot_region *region); + +struct vboot_components *vboot_locate_components(struct vboot_region *region); + +/* + * This is a dual purpose routine. If dest is non-NULL the region at + * offset_addr will be read into the area pointed to by dest. If dest + * is NULL,the region will be mapped to a memory location. NULL is + * returned on error else the location of the requested region. + */ +void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest); + +#endif /* VBOOT_COMMON_H */ diff --git a/src/vendorcode/google/chromeos/vboot_context.h b/src/vendorcode/google/chromeos/vboot_context.h index 72a05350cd..2517f63e63 100644 --- a/src/vendorcode/google/chromeos/vboot_context.h +++ b/src/vendorcode/google/chromeos/vboot_context.h @@ -21,18 +21,22 @@ #include #include +#include "chromeos.h" + +struct cbmem_entry; /* The vboot context structure provides all the necessary data for invoking * vboot. The vboot loader sets everything up for vboot module to use. */ - struct vboot_context { struct vboot_handoff *handoff; VbCommonParams *cparams; VbSelectFirmwareParams *fparams; - uint8_t *fw_a; - uint32_t fw_a_size; - uint8_t *fw_b; - uint32_t fw_b_size; + struct vboot_region gbb; + struct vboot_region vblock_a; + struct vboot_region fw_a; + struct vboot_region vblock_b; + struct vboot_region fw_b; + const struct cbmem_entry *vblocks; /* Callback implementations living in romstage. */ void (*read_vbnv)(uint8_t *vbnv_copy); void (*save_vbnv)(const uint8_t *vbnv_copy); @@ -43,6 +47,8 @@ struct vboot_context { size_t *recv_len); void (*log_msg)(const char *fmt, va_list args); void (*fatal_error)(void); + void *(*get_region)(uintptr_t offset_addr, size_t size, void *dest); + void (*reset)(void); }; #endif /* VBOOT_CONTEXT_H */ diff --git a/src/vendorcode/google/chromeos/vboot_handoff.h b/src/vendorcode/google/chromeos/vboot_handoff.h index 09c7897f54..b2769f0ffd 100644 --- a/src/vendorcode/google/chromeos/vboot_handoff.h +++ b/src/vendorcode/google/chromeos/vboot_handoff.h @@ -17,9 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef VBOOT_HANDOFF_H + #define VBOOT_HANDOFF_H #include +#include +#include "chromeos.h" +#include "vboot_common.h" /* * The vboot handoff structure keeps track of a maximum number of firmware @@ -28,7 +32,6 @@ * number of parsed firmware components (address and size) included in the * handoff structure. */ - #define MAX_PARSED_FW_COMPONENTS 5 struct firmware_component { diff --git a/src/vendorcode/google/chromeos/vboot_loader.c b/src/vendorcode/google/chromeos/vboot_loader.c deleted file mode 100644 index 10fa52d698..0000000000 --- a/src/vendorcode/google/chromeos/vboot_loader.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2013 Google, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "chromeos.h" -#include "fmap.h" -#include "vboot_context.h" -#include "vboot_handoff.h" - -static void vboot_run_stub(struct vboot_context *context) -{ - const struct cbmem_entry *vboot_entry; - struct rmodule vbootstub; - struct cbfs_stage *stage; - size_t region_size; - int rmodule_offset; - int load_offset; - char *vboot_region; - void (*entry)(struct vboot_context *context); - - stage = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - CONFIG_CBFS_PREFIX "/vboot", - CBFS_TYPE_STAGE); - - if (stage == NULL) - return; - - rmodule_offset = - rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE, - stage->memlen, ®ion_size, &load_offset); - - vboot_entry = cbmem_entry_add(0xffffffff, region_size); - - if (vboot_entry == NULL) { - printk(BIOS_DEBUG, "Couldn't get region for vboot stub.\n"); - return; - } - - vboot_region = cbmem_entry_start(vboot_entry); - - if (cbfs_decompress(stage->compression, &stage[1], - &vboot_region[rmodule_offset], stage->len)) { - printk(BIOS_DEBUG, "Couldn't decompress vboot stub.\n"); - goto out; - } - - if (rmodule_parse(&vboot_region[rmodule_offset], &vbootstub)) { - printk(BIOS_DEBUG, "Couldn't parse vboot stub rmodule.\n"); - goto out; - } - - if (rmodule_load(&vboot_region[load_offset], &vbootstub)) { - printk(BIOS_DEBUG, "Couldn't load vboot stub.\n"); - goto out; - } - - entry = rmodule_entry(&vbootstub); - - /* Call stub. */ - entry(context); - -out: - /* Tear down the region no longer needed. */ - cbmem_entry_remove(vboot_entry); -} - -/* Helper routines for the vboot stub. */ -static void log_msg(const char *fmt, va_list args) -{ - vtxprintf(console_tx_byte, fmt, args); - console_tx_flush(); -} - -static void fatal_error(void) -{ - printk(BIOS_ERR, "vboot encountered fatal error. Reseting.\n"); - hard_reset(); -} - -static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff) -{ - VbCommonParams cparams; - VbSelectFirmwareParams fparams; - struct vboot_context context; - uint32_t *iflags; - - vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY; - - memset(&cparams, 0, sizeof(cparams)); - memset(&fparams, 0, sizeof(fparams)); - memset(&context, 0, sizeof(context)); - - iflags = &vboot_handoff->init_params.flags; - if (get_developer_mode_switch()) - *iflags |= VB_INIT_FLAG_DEV_SWITCH_ON; - if (get_recovery_mode_switch()) - *iflags |= VB_INIT_FLAG_REC_BUTTON_PRESSED; - if (get_write_protect_state()) - *iflags |= VB_INIT_FLAG_WP_ENABLED; - if (CONFIG_VIRTUAL_DEV_SWITCH) - *iflags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH; - if (CONFIG_EC_SOFTWARE_SYNC) - *iflags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC; - - context.handoff = vboot_handoff; - context.cparams = &cparams; - context.fparams = &fparams; - - cparams.gbb_size = find_fmap_entry("GBB", &cparams.gbb_data); - cparams.shared_data_blob = &vboot_handoff->shared_data[0]; - cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE; - cparams.caller_context = &context; - - fparams.verification_size_A = - find_fmap_entry("VBLOCK_A", &fparams.verification_block_A); - fparams.verification_size_B = - find_fmap_entry("VBLOCK_B", &fparams.verification_block_B); - - context.fw_a_size = - find_fmap_entry("FW_MAIN_A", (void **)&context.fw_a); - context.fw_b_size = - find_fmap_entry("FW_MAIN_B", (void **)&context.fw_b); - - /* Check all fmap entries. */ - if (context.fw_a == NULL || context.fw_b == NULL || - fparams.verification_block_A == NULL || - fparams.verification_block_B == NULL || - cparams.gbb_data == NULL) { - printk(BIOS_DEBUG, "Not all fmap entries found for vboot.\n"); - return; - } - - /* Initialize callbacks. */ - context.read_vbnv = &read_vbnv; - context.save_vbnv = &save_vbnv; - context.tis_init = &tis_init; - context.tis_open = &tis_open; - context.tis_close = &tis_close; - context.tis_sendrecv = &tis_sendrecv; - context.log_msg = &log_msg; - context.fatal_error = &fatal_error; - - vboot_run_stub(&context); -} - -static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff, - struct romstage_handoff *handoff) -{ - struct cbfs_stage *stage; - struct rmodule ramstage; - void *entry_point; - size_t region_size; - char *ramstage_region; - int rmodule_offset; - int load_offset; - const struct cbmem_entry *ramstage_entry; - const struct firmware_component *fwc; - - if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) { - printk(BIOS_ERR, "Invalid ramstage index: %d\n", - CONFIG_VBOOT_RAMSTAGE_INDEX); - return; - } - - /* Check for invalid address. */ - fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX]; - if (fwc->address == 0) { - printk(BIOS_DEBUG, "RW ramstage image address invalid.\n"); - return; - } - - printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n", - fwc->address, fwc->size); - - stage = (void *)fwc->address; - - rmodule_offset = - rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE, - stage->memlen, ®ion_size, &load_offset); - - ramstage_entry = cbmem_entry_add(CBMEM_ID_RAMSTAGE, region_size); - - if (ramstage_entry == NULL) { - vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY; - printk(BIOS_DEBUG, "Could not add ramstage region.\n"); - return; - } - - timestamp_add_now(TS_START_COPYRAM); - - ramstage_region = cbmem_entry_start(ramstage_entry); - - printk(BIOS_DEBUG, "Decompressing ramstage @ 0x%p (%d bytes)\n", - &ramstage_region[rmodule_offset], stage->memlen); - - if (cbfs_decompress(stage->compression, &stage[1], - &ramstage_region[rmodule_offset], stage->len)) - return; - - if (rmodule_parse(&ramstage_region[rmodule_offset], &ramstage)) - return; - - if (rmodule_load(&ramstage_region[load_offset], &ramstage)) - return; - - entry_point = rmodule_entry(&ramstage); - - cache_loaded_ramstage(handoff, ramstage_entry, entry_point); - - timestamp_add_now(TS_END_COPYRAM); - - __asm__ volatile ( - "movl $0, %%ebp\n" - "jmp *%%edi\n" - :: "D"(entry_point) - ); -} - -void vboot_verify_firmware(struct romstage_handoff *handoff) -{ - struct vboot_handoff *vboot_handoff; - - /* Don't go down verified boot path on S3 resume. */ - if (handoff != NULL && handoff->s3_resume) - return; - - timestamp_add_now(TS_START_VBOOT); - - vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, - sizeof(*vboot_handoff)); - - if (vboot_handoff == NULL) { - printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n"); - return; - } - - memset(vboot_handoff, 0, sizeof(*vboot_handoff)); - - vboot_invoke_wrapper(vboot_handoff); - - timestamp_add_now(TS_END_VBOOT); - - /* Take RO firmware path since no RW area was selected. */ - if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A && - vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) { - printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n", - vboot_handoff->selected_firmware); - return; - } - - /* Load ramstage from the vboot_handoff structure. */ - vboot_load_ramstage(vboot_handoff, handoff); -} diff --git a/src/vendorcode/google/chromeos/vpd_calibration.c b/src/vendorcode/google/chromeos/vpd_calibration.c new file mode 100644 index 0000000000..3bfd843db0 --- /dev/null +++ b/src/vendorcode/google/chromeos/vpd_calibration.c @@ -0,0 +1,197 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include +#include + +/* + * This file provides functions looking in the VPD for WiFi calibration data, + * and if found, copying the calibration blobs into CBMEM. + * + * Per interface calibration data is stored in the VPD in opaque blobs. The + * keys of the blobs follow one of two possible patterns: + * "wifi_base64_calibration" or "wifi_calibration", where is the + * interface number. + * + * This function accommodates up to 4 interfaces. All calibration blobs found + * in the VPD are packed into a single CBMEM entry as describe by the + * structures below: + */ + +/* This structure describes a single calibration data blob */ +struct calibration_blob { + uint32_t blob_size; /* Total size. rounded up to fall on a 4 byte + boundary. */ + uint32_t key_size; /* Size of the name of this entry, \0 included. */ + uint32_t value_size; /* Size of the value of this entry */ + /* Zero terminated name(key) goes here, immediately followed by value */ +}; + +/* + * This is the structure of the CBMEM entry containing WiFi calibration blobs. + * It starts with the total size (header size included) followed by an + * arbitrary number of concatenated 4 byte aligned calibration blobs. + */ +struct calibration_entry { + uint32_t size; + struct calibration_blob entries[0]; /* A varialble size container. */ +}; + + +#define MAX_WIFI_INTERFACE_COUNT 4 + +/* + * Structure of the cache to keep information about calibration blobs present + * in the VPD, one cache entry per VPD blob. + * + * Maintaing the cache allows to scan the VPD once, determine the CBMEM entry + * memory requirements, then allocate as much room as necessary and fill it + * up. + */ +struct vpd_blob_cache_t { + /* The longest name template must fit with an extra character. */ + char key_name[40]; + const void *value_pointer; + unsigned blob_size; + unsigned key_size; + unsigned value_size; +}; + +static const char * const templates[] = { + "wifi_base64_calibrationX", + "wifi_calibrationX" +}; + +/* + * Scan the VPD for WiFi calibration data, checking for all possible key names + * and caching discovered blobs. + * + * Return the sum of sizes of all blobs, as stored in CBMEM. + */ +static size_t fill_up_entries_cache(struct vpd_blob_cache_t *cache, + size_t max_entries, size_t *filled_entries) +{ + int i; + int cbmem_entry_size = 0; + size_t used_entries = 0; + + + for (i = 0; + (i < ARRAY_SIZE(templates)) && (used_entries < max_entries); + i++) { + int j; + const int index_location = strlen(templates[i]) - 1; + const int key_length = index_location + 2; + + if (key_length > sizeof(cache->key_name)) + continue; + + for (j = 0; j < MAX_WIFI_INTERFACE_COUNT; j++) { + const void *payload; + int payload_size; + + strcpy(cache->key_name, templates[i]); + cache->key_name[index_location] = j + '0'; + + payload = cros_vpd_find(cache->key_name, &payload_size); + if (!payload) + continue; + + cache->value_pointer = payload; + cache->key_size = key_length; + cache->value_size = payload_size; + cache->blob_size = + ALIGN(sizeof(struct calibration_blob) + + cache->key_size + + cache->value_size, 4); + cbmem_entry_size += cache->blob_size; + + used_entries++; + if (used_entries == max_entries) + break; + + cache++; + } + } + + *filled_entries = used_entries; + return cbmem_entry_size; +} + +void cbmem_add_vpd_calibration_data(void) +{ + size_t cbmem_entry_size, filled_entries; + struct calibration_entry *cbmem_entry; + struct calibration_blob *cal_blob; + int i; + /* + * Allocate one more cache entry than max required, to make sure that + * the last entry can be identified by the key size of zero. + */ + struct vpd_blob_cache_t vpd_blob_cache[ARRAY_SIZE(templates) * + MAX_WIFI_INTERFACE_COUNT]; + + cbmem_entry_size = fill_up_entries_cache(vpd_blob_cache, + ARRAY_SIZE(vpd_blob_cache), + &filled_entries); + + if (!cbmem_entry_size) + return; /* No calibration data found in the VPD. */ + + cbmem_entry_size += sizeof(struct calibration_entry); + cbmem_entry = cbmem_add(CBMEM_ID_WIFI_CALIBRATION, cbmem_entry_size); + if (!cbmem_entry) { + printk(BIOS_ERR, "%s: no room in cbmem to add %zd bytes\n", + __func__, cbmem_entry_size); + return; + } + + cbmem_entry->size = cbmem_entry_size; + + /* Copy cached data into the CBMEM entry. */ + cal_blob = cbmem_entry->entries; + + for (i = 0; i < filled_entries; i++) { + /* Use this as a pointer to the current cache entry. */ + struct vpd_blob_cache_t *cache = vpd_blob_cache + i; + char *pointer; + + cal_blob->blob_size = cache->blob_size; + cal_blob->key_size = cache->key_size; + cal_blob->value_size = cache->value_size; + + /* copy the key */ + pointer = (char *)(cal_blob + 1); + memcpy(pointer, cache->key_name, cache->key_size); + + /* and the value */ + pointer += cache->key_size; + memcpy(pointer, cache->value_pointer, cache->value_size); + + printk(BIOS_INFO, "%s: added %s to CBMEM\n", + __func__, cache->key_name); + + cal_blob = (struct calibration_blob *) + ((char *)cal_blob + cal_blob->blob_size); + } +} diff --git a/src/vendorcode/google/chromeos/vpd_decode.c b/src/vendorcode/google/chromeos/vpd_decode.c new file mode 100644 index 0000000000..545fd8106f --- /dev/null +++ b/src/vendorcode/google/chromeos/vpd_decode.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + */ +#include +#include "lib_vpd.h" + +int decodeLen( + const int32_t max_len, + const uint8_t *in, + int32_t *length, + int32_t *decoded_len) { + uint8_t more; + int i = 0; + + assert(length); + assert(decoded_len); + + *length = 0; + do { + if (i >= max_len) return VPD_FAIL; + more = in[i] & 0x80; + *length <<= 7; + *length |= in[i] & 0x7f; + ++i; + } while (more); + + *decoded_len = i; + + return VPD_OK; +} + +/* Sequentially decodes type, key, and value. + */ +int decodeVpdString( + const int32_t max_len, + const uint8_t *input_buf, + int32_t *consumed, + VpdDecodeCallback callback, + void *callback_arg) { + int type; + int32_t key_len, value_len; + int32_t decoded_len; + const uint8_t *key, *value; + + /* type */ + if (*consumed >= max_len) + return VPD_FAIL; + + type = input_buf[*consumed]; + switch (type) { + case VPD_TYPE_INFO: + case VPD_TYPE_STRING: + (*consumed)++; + + /* key */ + if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed], + &key_len, &decoded_len) || + *consumed + decoded_len >= max_len) { + return VPD_FAIL; + } + + *consumed += decoded_len; + key = &input_buf[*consumed]; + *consumed += key_len; + + /* value */ + if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed], + &value_len, &decoded_len) || + *consumed + decoded_len > max_len) { + return VPD_FAIL; + } + *consumed += decoded_len; + value = &input_buf[*consumed]; + *consumed += value_len; + + if (type == VPD_TYPE_STRING) + return callback(key, key_len, value, value_len, callback_arg); + + return VPD_OK; + + default: + return VPD_FAIL; + break; + } + return VPD_OK; +} diff --git a/src/vendorcode/google/chromeos/vpd_mac.c b/src/vendorcode/google/chromeos/vpd_mac.c new file mode 100644 index 0000000000..ad4174c6bf --- /dev/null +++ b/src/vendorcode/google/chromeos/vpd_mac.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include + +void lb_table_add_macs_from_vpd(struct lb_header *header) +{ + /* + * In case there is one or more MAC addresses stored in the VPD, the + * key is "ethernet_mac{0..9}", up to 10 values. + */ + static const char mac_addr_key_base[] = "ethernet_mac0"; + char mac_addr_key[sizeof(mac_addr_key_base)]; + char mac_addr_str[13]; /* 12 symbols and the trailing zero. */ + int count; + struct lb_macs *macs = NULL; + const int index_of_index = sizeof(mac_addr_key) - 2; + + /* + * MAC addresses are stored in the VPD as strings of hex numbers, + * which need to be converted into binary for storing in the coreboot + * table. + */ + strcpy(mac_addr_key, mac_addr_key_base); + count = 0; + do { + int i; + + if (!cros_vpd_gets(mac_addr_key, mac_addr_str, + sizeof(mac_addr_str))) + break; /* No more MAC addresses in VPD */ + + if (!macs) { + macs = (struct lb_macs *)lb_new_record(header); + macs->tag = LB_TAG_MAC_ADDRS; + } + + /* MAC address in symbolic form is in mac_addr_str. */ + for (i = 0; i < sizeof(macs->mac_addrs[0].mac_addr); i++) { + int j; + uint8_t n = 0; + + for (j = 0; j < 2; j++) { + char c = mac_addr_str[i * 2 + j]; + + if (isxdigit(c)) { + if (isdigit(c)) + c -= '0'; + else + c = tolower(c) - 'a' + 10; + } else { + printk(BIOS_ERR, + "%s: non hexadecimal symbol " + "%#2.2x in the VPD field %s\n", + __func__, (uint8_t)c, + mac_addr_key); + c = 0; + } + n <<= 4; + n |= c; + } + macs->mac_addrs[count].mac_addr[i] = n; + } + count++; + mac_addr_key[index_of_index] = '0' + count; + } while (count < 10); + + if (!count) + return; /* No MAC addresses in the VPD. */ + + macs->count = count; + macs->size = sizeof(*macs) + count * sizeof(struct mac_address); +} diff --git a/src/vendorcode/google/chromeos/vpd_tables.h b/src/vendorcode/google/chromeos/vpd_tables.h new file mode 100644 index 0000000000..d58b5e846d --- /dev/null +++ b/src/vendorcode/google/chromeos/vpd_tables.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Ported from mosys project (http://code.google.com/p/mosys/). + */ + +#ifndef __LIB_VPD_TABLES_H__ +#define __LIB_VPD_TABLES_H__ + +#include + +#define VPD_ENTRY_MAGIC "_SM_" +#define VPD_INFO_MAGIC \ + "\xfe" /* type: VPD header */ \ + "\x09" /* key length, 9 = 1 + 8 */ \ + "\x01" /* info version, 1 */ \ + "gVpdInfo" /* signature, 8 bytes */ \ + "\x04" /* value length */ + +/* Google specific VPD info */ +struct google_vpd_info { + union { + struct { + uint8_t type; + uint8_t key_len; + uint8_t info_ver; + uint8_t signature[8]; + uint8_t value_len; + } tlv; + uint8_t magic[12]; + } header; + uint32_t size; +} __attribute__((packed)); + +/* Entry */ +struct vpd_entry { + uint8_t anchor_string[4]; + uint8_t entry_cksum; + uint8_t entry_length; + uint8_t major_ver; + uint8_t minor_ver; + uint16_t max_size; + uint8_t entry_rev; + uint8_t format_area[5]; + uint8_t inter_anchor_string[5]; + uint8_t inter_anchor_cksum; + uint16_t table_length; + uint32_t table_address; + uint16_t table_entry_count; + uint8_t bcd_revision; +} __attribute__ ((packed)); + +/* Header */ +struct vpd_header { + uint8_t type; + uint8_t length; + uint16_t handle; +} __attribute__ ((packed)); + +/* Type 0 - firmware information */ +struct vpd_table_firmware { + uint8_t vendor; + uint8_t version; + uint16_t start_address; + uint8_t release_date; + uint8_t rom_size_64k_blocks; + uint32_t characteristics; + uint8_t extension[2]; /* v2.4+ */ + uint8_t major_ver; /* v2.4+ */ + uint8_t minor_ver; /* v2.4+ */ + uint8_t ec_major_ver; /* v2.4+ */ + uint8_t ec_minor_ver; /* v2.4+ */ +} __attribute__ ((packed)); + +/* Type 1 - system information */ +struct vpd_table_system { + uint8_t manufacturer; + uint8_t name; + uint8_t version; + uint8_t serial_number; + uint8_t uuid[16]; + uint8_t wakeup_type; + uint8_t sku_number; /* v2.4+ */ + uint8_t family; /* v2.4+ */ +} __attribute__ ((packed)); + +/* Type 127 - end of table */ +struct vpd_table_eot { + struct vpd_header header; +} __attribute__ ((packed)); + +/* Type 241 - binary blob pointer */ +struct vpd_table_binary_blob_pointer { + uint8_t struct_major_version; + uint8_t struct_minor_version; + uint8_t vendor; + uint8_t description; + uint8_t major_version; + uint8_t minor_version; + uint8_t variant; + uint8_t reserved[5]; + uint8_t uuid[16]; + uint32_t offset; + uint32_t size; +} __attribute__ ((packed)); + +/* The length and number of strings defined here is not a limitation of VPD. + * These numbers were deemed good enough during development. */ +#define VPD_MAX_STRINGS 10 +#define VPD_MAX_STRING_LENGTH 64 + +#endif /* __LIB_VPD_TABLES_H__ */ diff --git a/src/vendorcode/google/chromeos/watchdog.c b/src/vendorcode/google/chromeos/watchdog.c new file mode 100644 index 0000000000..e4adf8a041 --- /dev/null +++ b/src/vendorcode/google/chromeos/watchdog.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "chromeos.h" +#include "symbols.h" + +#define WATCHDOG_TOMBSTONE_MAGIC 0x9d2f41a7 + +void elog_add_watchdog_reset(void) +{ + if (readl(_watchdog_tombstone) == WATCHDOG_TOMBSTONE_MAGIC) + elog_add_event(ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED); + writel(0, _watchdog_tombstone); +} + +void reboot_from_watchdog(void) +{ + printk(BIOS_INFO, "Last reset was watchdog, reboot again to reset TPM!\n"); + writel(WATCHDOG_TOMBSTONE_MAGIC, _watchdog_tombstone); + hard_reset(); +} diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Base.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Base.h new file mode 100644 index 0000000000..e403ebdedb --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Base.h @@ -0,0 +1,1026 @@ +/** @file + Root include file for Mde Package Base type modules + + This is the include file for any module of type base. Base modules only use + types defined via this include file and can be ported easily to any + environment. There are a set of base libraries in the Mde Package that can + be used to implement base modules. + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __BASE_H__ +#define __BASE_H__ + +// +// Include processor specific binding +// +#include + + +/** + Verifies the storage size of a given data type. + + This macro generates a divide by zero error or a zero size array declaration in + the preprocessor if the size is incorrect. These are declared as "extern" so + the space for these arrays will not be in the modules. + + @param TYPE The date type to determine the size of. + @param Size The expected size for the TYPE. + +**/ +#define VERIFY_SIZE_OF(TYPE, Size) extern UINT8 _VerifySizeof##TYPE[(sizeof(TYPE) == (Size)) / (sizeof(TYPE) == (Size))] + +// +// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with +// Section 2.3.1 of the UEFI 2.3 Specification. +// +VERIFY_SIZE_OF (BOOLEAN, 1); +VERIFY_SIZE_OF (INT8, 1); +VERIFY_SIZE_OF (UINT8, 1); +VERIFY_SIZE_OF (INT16, 2); +VERIFY_SIZE_OF (UINT16, 2); +VERIFY_SIZE_OF (INT32, 4); +VERIFY_SIZE_OF (UINT32, 4); +VERIFY_SIZE_OF (INT64, 8); +VERIFY_SIZE_OF (UINT64, 8); +VERIFY_SIZE_OF (CHAR8, 1); +VERIFY_SIZE_OF (CHAR16, 2); + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if defined(_MSC_EXTENSIONS) && !defined (MDE_CPU_EBC) + /// + /// Remove global variable from the linked image if there are no references to + /// it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + /// + /// Remove the global variable from the linked image if there are no references + /// to it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +// +// For symbol name in assembly code, an extra "_" is sometimes necessary +// + +/// +/// Private worker functions for ASM_PFX() +/// +#define _CONCATENATE(a, b) __CONCATENATE(a, b) +#define __CONCATENATE(a, b) a ## b + +/// +/// The __USER_LABEL_PREFIX__ macro predefined by GNUC represents the prefix +/// on symbols in assembly language. +/// +#define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name) + +#if __APPLE__ + // + // Apple extension that is used by the linker to optimize code size + // with assembly functions. Put at the end of your .S files + // + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED .subsections_via_symbols +#else + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED +#endif + +#ifdef __CC_ARM + // + // Older RVCT ARM compilers don't fully support #pragma pack and require __packed + // as a prefix for the structure. + // + #define PACKED __packed +#else + #define PACKED +#endif + +/// +/// 128 bit buffer containing a unique identifier value. +/// Unless otherwise specified, aligned on a 64 bit boundary. +/// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; + +// +// 8-bytes unsigned value that represents a physical system address. +// +typedef UINT64 PHYSICAL_ADDRESS; + +/// +/// LIST_ENTRY structure definition. +/// +typedef struct _LIST_ENTRY LIST_ENTRY; + +/// +/// _LIST_ENTRY structure definition. +/// +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; + +// +// Modifiers to abstract standard types to aid in debug of problems +// + +/// +/// Datum is read-only. +/// +#define CONST const + +/// +/// Datum is scoped to the current file or function. +/// +#define STATIC static + +/// +/// Undeclared type. +/// +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// + +/// +/// Datum is passed to the function. +/// +#define IN + +/// +/// Datum is returned from the function. +/// +#define OUT + +/// +/// Passing the datum to the function is optional, and a NULL +/// is passed if the value is not supplied. +/// +#define OPTIONAL + +// +// UEFI specification claims 1 and 0. We are concerned about the +// complier portability so we did it this way. +// + +/// +/// Boolean true value. UEFI Specification defines this value to be 1, +/// but this form is more portable. +/// +#define TRUE ((BOOLEAN)(1==1)) + +/// +/// Boolean false value. UEFI Specification defines this value to be 0, +/// but this form is more portable. +/// +#define FALSE ((BOOLEAN)(0==1)) + +/// +/// NULL pointer (VOID *) +/// +#ifndef NULL +#define NULL ((VOID *) 0) +#endif + +/// +/// Maximum values for common UEFI Data Types +/// +#define MAX_INT8 ((INT8)0x7F) +#define MAX_UINT8 ((UINT8)0xFF) +#define MAX_INT16 ((INT16)0x7FFF) +#define MAX_UINT16 ((UINT16)0xFFFF) +#define MAX_INT32 ((INT32)0x7FFFFFFF) +#define MAX_UINT32 ((UINT32)0xFFFFFFFF) +#define MAX_INT64 ((INT64)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL) + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#define BIT32 0x0000000100000000ULL +#define BIT33 0x0000000200000000ULL +#define BIT34 0x0000000400000000ULL +#define BIT35 0x0000000800000000ULL +#define BIT36 0x0000001000000000ULL +#define BIT37 0x0000002000000000ULL +#define BIT38 0x0000004000000000ULL +#define BIT39 0x0000008000000000ULL +#define BIT40 0x0000010000000000ULL +#define BIT41 0x0000020000000000ULL +#define BIT42 0x0000040000000000ULL +#define BIT43 0x0000080000000000ULL +#define BIT44 0x0000100000000000ULL +#define BIT45 0x0000200000000000ULL +#define BIT46 0x0000400000000000ULL +#define BIT47 0x0000800000000000ULL +#define BIT48 0x0001000000000000ULL +#define BIT49 0x0002000000000000ULL +#define BIT50 0x0004000000000000ULL +#define BIT51 0x0008000000000000ULL +#define BIT52 0x0010000000000000ULL +#define BIT53 0x0020000000000000ULL +#define BIT54 0x0040000000000000ULL +#define BIT55 0x0080000000000000ULL +#define BIT56 0x0100000000000000ULL +#define BIT57 0x0200000000000000ULL +#define BIT58 0x0400000000000000ULL +#define BIT59 0x0800000000000000ULL +#define BIT60 0x1000000000000000ULL +#define BIT61 0x2000000000000000ULL +#define BIT62 0x4000000000000000ULL +#define BIT63 0x8000000000000000ULL + +#define SIZE_1KB 0x00000400 +#define SIZE_2KB 0x00000800 +#define SIZE_4KB 0x00001000 +#define SIZE_8KB 0x00002000 +#define SIZE_16KB 0x00004000 +#define SIZE_32KB 0x00008000 +#define SIZE_64KB 0x00010000 +#define SIZE_128KB 0x00020000 +#define SIZE_256KB 0x00040000 +#define SIZE_512KB 0x00080000 +#define SIZE_1MB 0x00100000 +#define SIZE_2MB 0x00200000 +#define SIZE_4MB 0x00400000 +#define SIZE_8MB 0x00800000 +#define SIZE_16MB 0x01000000 +#define SIZE_32MB 0x02000000 +#define SIZE_64MB 0x04000000 +#define SIZE_128MB 0x08000000 +#define SIZE_256MB 0x10000000 +#define SIZE_512MB 0x20000000 +#define SIZE_1GB 0x40000000 +#define SIZE_2GB 0x80000000 +#define SIZE_4GB 0x0000000100000000ULL +#define SIZE_8GB 0x0000000200000000ULL +#define SIZE_16GB 0x0000000400000000ULL +#define SIZE_32GB 0x0000000800000000ULL +#define SIZE_64GB 0x0000001000000000ULL +#define SIZE_128GB 0x0000002000000000ULL +#define SIZE_256GB 0x0000004000000000ULL +#define SIZE_512GB 0x0000008000000000ULL +#define SIZE_1TB 0x0000010000000000ULL +#define SIZE_2TB 0x0000020000000000ULL +#define SIZE_4TB 0x0000040000000000ULL +#define SIZE_8TB 0x0000080000000000ULL +#define SIZE_16TB 0x0000100000000000ULL +#define SIZE_32TB 0x0000200000000000ULL +#define SIZE_64TB 0x0000400000000000ULL +#define SIZE_128TB 0x0000800000000000ULL +#define SIZE_256TB 0x0001000000000000ULL +#define SIZE_512TB 0x0002000000000000ULL +#define SIZE_1PB 0x0004000000000000ULL +#define SIZE_2PB 0x0008000000000000ULL +#define SIZE_4PB 0x0010000000000000ULL +#define SIZE_8PB 0x0020000000000000ULL +#define SIZE_16PB 0x0040000000000000ULL +#define SIZE_32PB 0x0080000000000000ULL +#define SIZE_64PB 0x0100000000000000ULL +#define SIZE_128PB 0x0200000000000000ULL +#define SIZE_256PB 0x0400000000000000ULL +#define SIZE_512PB 0x0800000000000000ULL +#define SIZE_1EB 0x1000000000000000ULL +#define SIZE_2EB 0x2000000000000000ULL +#define SIZE_4EB 0x4000000000000000ULL +#define SIZE_8EB 0x8000000000000000ULL + +#define BASE_1KB 0x00000400 +#define BASE_2KB 0x00000800 +#define BASE_4KB 0x00001000 +#define BASE_8KB 0x00002000 +#define BASE_16KB 0x00004000 +#define BASE_32KB 0x00008000 +#define BASE_64KB 0x00010000 +#define BASE_128KB 0x00020000 +#define BASE_256KB 0x00040000 +#define BASE_512KB 0x00080000 +#define BASE_1MB 0x00100000 +#define BASE_2MB 0x00200000 +#define BASE_4MB 0x00400000 +#define BASE_8MB 0x00800000 +#define BASE_16MB 0x01000000 +#define BASE_32MB 0x02000000 +#define BASE_64MB 0x04000000 +#define BASE_128MB 0x08000000 +#define BASE_256MB 0x10000000 +#define BASE_512MB 0x20000000 +#define BASE_1GB 0x40000000 +#define BASE_2GB 0x80000000 +#define BASE_4GB 0x0000000100000000ULL +#define BASE_8GB 0x0000000200000000ULL +#define BASE_16GB 0x0000000400000000ULL +#define BASE_32GB 0x0000000800000000ULL +#define BASE_64GB 0x0000001000000000ULL +#define BASE_128GB 0x0000002000000000ULL +#define BASE_256GB 0x0000004000000000ULL +#define BASE_512GB 0x0000008000000000ULL +#define BASE_1TB 0x0000010000000000ULL +#define BASE_2TB 0x0000020000000000ULL +#define BASE_4TB 0x0000040000000000ULL +#define BASE_8TB 0x0000080000000000ULL +#define BASE_16TB 0x0000100000000000ULL +#define BASE_32TB 0x0000200000000000ULL +#define BASE_64TB 0x0000400000000000ULL +#define BASE_128TB 0x0000800000000000ULL +#define BASE_256TB 0x0001000000000000ULL +#define BASE_512TB 0x0002000000000000ULL +#define BASE_1PB 0x0004000000000000ULL +#define BASE_2PB 0x0008000000000000ULL +#define BASE_4PB 0x0010000000000000ULL +#define BASE_8PB 0x0020000000000000ULL +#define BASE_16PB 0x0040000000000000ULL +#define BASE_32PB 0x0080000000000000ULL +#define BASE_64PB 0x0100000000000000ULL +#define BASE_128PB 0x0200000000000000ULL +#define BASE_256PB 0x0400000000000000ULL +#define BASE_512PB 0x0800000000000000ULL +#define BASE_1EB 0x1000000000000000ULL +#define BASE_2EB 0x2000000000000000ULL +#define BASE_4EB 0x4000000000000000ULL +#define BASE_8EB 0x8000000000000000ULL + +// +// Support for variable length argument lists using the ANSI standard. +// +// Since we are using the ANSI standard we used the standard naming and +// did not follow the coding convention +// +// VA_LIST - typedef for argument list. +// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. +// VA_END (VA_LIST Marker) - Clear Marker +// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from +// the ... list. You must know the size and pass it in this macro. +// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start. +// +// example: +// +// UINTN +// ExampleVarArg ( +// IN UINTN NumberOfArgs, +// ... +// ) +// { +// VA_LIST Marker; +// UINTN Index; +// UINTN Result; +// +// // +// // Initialize the Marker +// // +// VA_START (Marker, NumberOfArgs); +// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { +// // +// // The ... list is a series of UINTN values, so average them up. +// // +// Result += VA_ARG (Marker, UINTN); +// } +// +// VA_END (Marker); +// return Result +// } +// + +/** + Return the size of argument that has been aligned to sizeof (UINTN). + + @param n The parameter size to be aligned. + + @return The aligned size. +**/ +#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) + +#if defined(__CC_ARM) +// +// RVCT ARM variable argument list support. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +#ifdef __APCS_ADSABI + typedef int *va_list[1]; + #define VA_LIST va_list +#else + typedef struct __va_list { void *__ap; } va_list; + #define VA_LIST va_list +#endif + +#define VA_START(Marker, Parameter) __va_start(Marker, Parameter) + +#define VA_ARG(Marker, TYPE) __va_arg(Marker, TYPE) + +#define VA_END(Marker) ((void)0) + +// For some ARM RVCT compilers, __va_copy is not defined +#ifndef __va_copy + #define __va_copy(dest, src) ((void)((dest) = (src))) +#endif + +#define VA_COPY(Dest, Start) __va_copy (Dest, Start) + +#elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS) +// +// Use GCC built-in macros for variable argument lists. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef __builtin_va_list VA_LIST; + +#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter) + +#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) + +#define VA_END(Marker) __builtin_va_end (Marker) + +#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) + +#else +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef CHAR8 *VA_LIST; + +/** + Retrieves a pointer to the beginning of a variable argument list, based on + the name of the parameter that immediately precedes the variable argument list. + + This function initializes Marker to point to the beginning of the variable + argument list that immediately follows Parameter. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the + EFIAPI ABI. + + @param Marker The VA_LIST used to traverse the list of arguments. + @param Parameter The name of the parameter that immediately precedes + the variable argument list. + + @return A pointer to the beginning of a variable argument list. + +**/ +#define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter))) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI. + + @param Marker VA_LIST used to traverse the list of arguments. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE))) + +/** + Terminates the use of a variable argument list. + + This function initializes Marker so it can no longer be used with VA_ARG(). + After this macro is used, the only way to access the variable argument list is + by using VA_START() again. + + @param Marker VA_LIST used to traverse the list of arguments. + +**/ +#define VA_END(Marker) (Marker = (VA_LIST) 0) + +/** + Initializes a VA_LIST as a copy of an existing VA_LIST. + + This macro initializes Dest as a copy of Start, as if the VA_START macro had been applied to Dest + followed by the same sequence of uses of the VA_ARG macro as had previously been used to reach + the present state of Start. + + @param Dest VA_LIST used to traverse the list of arguments. + @param Start VA_LIST used to traverse the list of arguments. + +**/ +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + +#endif + +/// +/// Pointer to the start of a variable argument list stored in a memory buffer. Same as UINT8 *. +/// +typedef UINTN *BASE_LIST; + +/** + Returns the size of a data type in sizeof(UINTN) units rounded up to the nearest UINTN boundary. + + @param TYPE The date type to determine the size of. + + @return The size of TYPE in sizeof (UINTN) units rounded up to the nearest UINTN boundary. +**/ +#define _BASE_INT_SIZE_OF(TYPE) ((sizeof (TYPE) + sizeof (UINTN) - 1) / sizeof (UINTN)) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU specific following the EFIAPI ABI. + + @param Marker The pointer to the beginning of a variable argument list. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define BASE_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _BASE_INT_SIZE_OF (TYPE)) - _BASE_INT_SIZE_OF (TYPE))) + +/** + The macro that returns the byte offset of a field in a data structure. + + This function returns the offset, in bytes, of field specified by Field from the + beginning of the data structure specified by TYPE. If TYPE does not contain Field, + the module will not compile. + + @param TYPE The name of the data structure that contains the field specified by Field. + @param Field The name of the field in the data structure. + + @return Offset, in bytes, of field. + +**/ +#ifdef __GNUC__ +#if __GNUC__ >= 4 +#define OFFSET_OF(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field)) +#endif +#endif + +#ifndef OFFSET_OF +#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) +#endif + +/** + Macro that returns a pointer to the data structure that contains a specified field of + that data structure. This is a lightweight method to hide information by placing a + public data structure inside a larger private data structure and using a pointer to + the public data structure to retrieve a pointer to the private data structure. + + This function computes the offset, in bytes, of field specified by Field from the beginning + of the data structure specified by TYPE. This offset is subtracted from Record, and is + used to return a pointer to a data structure of the type specified by TYPE. If the data type + specified by TYPE does not contain the field specified by Field, then the module will not compile. + + @param Record Pointer to the field specified by Field within a data structure of type TYPE. + @param TYPE The name of the data structure type to return. This data structure must + contain the field specified by Field. + @param Field The name of the field in the data structure specified by TYPE to which Record points. + + @return A pointer to the structure from one of it's elements. + +**/ +#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +/** + Rounds a value up to the next boundary using a specified alignment. + + This function rounds Value up to the next boundary using the specified Alignment. + This aligned value is returned. + + @param Value The value to round up. + @param Alignment The alignment boundary used to return the aligned value. + + @return A value up to the next boundary. + +**/ +#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1))) + +/** + Adjust a pointer by adding the minimum offset required for it to be aligned on + a specified alignment boundary. + + This function rounds the pointer specified by Pointer to the next alignment boundary + specified by Alignment. The pointer to the aligned address is returned. + + @param Pointer The pointer to round up. + @param Alignment The alignment boundary to use to return an aligned pointer. + + @return Pointer to the aligned address. + +**/ +#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment)))) + +/** + Rounds a value up to the next natural boundary for the current CPU. + This is 4-bytes for 32-bit CPUs and 8-bytes for 64-bit CPUs. + + This function rounds the value specified by Value up to the next natural boundary for the + current CPU. This rounded value is returned. + + @param Value The value to round up. + + @return Rounded value specified by Value. + +**/ +#define ALIGN_VARIABLE(Value) ALIGN_VALUE ((Value), sizeof (UINTN)) + + +/** + Return the maximum of two operands. + + This macro returns the maximum of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. Can be any numerical type as long as is + the same type as a. + + @return Maximum of two operands. + +**/ +#ifndef MAX +#define MAX(a, b) \ + (((a) > (b)) ? (a) : (b)) +#endif + +/** + Return the minimum of two operands. + + This macro returns the minimal of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. It should be the same any numerical type with a. + + @return Minimum of two operands. + +**/ +#ifndef MIN +#define MIN(a, b) \ + (((a) < (b)) ? (a) : (b)) +#endif + +/** + Return the absolute value of a signed operand. + + This macro returns the absolute value of the signed operand specified by a. + + @param a The signed operand. + + @return The absolute value of the signed operand. + +**/ +#define ABS(a) \ + (((a) < 0) ? (-(a)) : (a)) + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +/// +/// The operation is not supported. +/// +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) + +/// +/// The buffer was not the proper size for the request. +/// +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) + +/// +/// The buffer was not large enough to hold the requested data. +/// The required buffer size is returned in the appropriate +/// parameter when this error occurs. +/// +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) + +/// +/// There is no data pending upon return. +/// +#define RETURN_NOT_READY ENCODE_ERROR (6) + +/// +/// The physical device reported an error while attempting the +/// operation. +/// +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) + +/// +/// The device can not be written to. +/// +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) + +/// +/// The resource has run out. +/// +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/// +/// An inconsistency was detected on the file system causing the +/// operation to fail. +/// +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) + +/// +/// There is no more space on the file system. +/// +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) + +/// +/// The device does not contain any medium to perform the +/// operation. +/// +#define RETURN_NO_MEDIA ENCODE_ERROR (12) + +/// +/// The medium in the device has changed since the last +/// access. +/// +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) + +/// +/// The item was not found. +/// +#define RETURN_NOT_FOUND ENCODE_ERROR (14) + +/// +/// Access was denied. +/// +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) + +/// +/// The server was not found or did not respond to the request. +/// +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) + +/// +/// A mapping to the device does not exist. +/// +#define RETURN_NO_MAPPING ENCODE_ERROR (17) + +/// +/// A timeout time expired. +/// +#define RETURN_TIMEOUT ENCODE_ERROR (18) + +/// +/// The protocol has not been started. +/// +#define RETURN_NOT_STARTED ENCODE_ERROR (19) + +/// +/// The protocol has already been started. +/// +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) + +/// +/// The operation was aborted. +/// +#define RETURN_ABORTED ENCODE_ERROR (21) + +/// +/// An ICMP error occurred during the network operation. +/// +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) + +/// +/// A TFTP error occurred during the network operation. +/// +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) + +/// +/// A protocol error occurred during the network operation. +/// +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) + +/// +/// A function encountered an internal version that was +/// incompatible with a version requested by the caller. +/// +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) + +/// +/// The function was not performed due to a security violation. +/// +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) + +/// +/// A CRC error was detected. +/// +#define RETURN_CRC_ERROR ENCODE_ERROR (27) + +/// +/// The beginning or end of media was reached. +/// +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) + +/// +/// The end of the file was reached. +/// +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +/// +/// The language specified was invalid. +/// +#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) + +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) + +/// +/// The string contained one or more characters that +/// the device could not render and were skipped. +/// +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) + +/// +/// The handle was closed, but the file was not deleted. +/// +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) + +/// +/// The handle was closed, but the data to the file was not +/// flushed properly. +/// +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) + +/// +/// The resulting buffer was too small, and the data was +/// truncated to the buffer size. +/// +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + +/** + Returns a 16-bit signature built from 2 ASCII characters. + + This macro returns a 16-bit value built from the two ASCII characters specified + by A and B. + + @param A The first ASCII character. + @param B The second ASCII character. + + @return A 16-bit value built from the two ASCII characters specified by A and B. + +**/ +#define SIGNATURE_16(A, B) ((A) | (B << 8)) + +/** + Returns a 32-bit signature built from 4 ASCII characters. + + This macro returns a 32-bit value built from the four ASCII characters specified + by A, B, C, and D. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + + @return A 32-bit value built from the two ASCII characters specified by A, B, + C and D. + +**/ +#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) + +/** + Returns a 64-bit signature built from 8 ASCII characters. + + This macro returns a 64-bit value built from the eight ASCII characters specified + by A, B, C, D, E, F, G,and H. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + @param E The fifth ASCII character. + @param F The sixth ASCII character. + @param G The seventh ASCII character. + @param H The eighth ASCII character. + + @return A 64-bit value built from the two ASCII characters specified by A, B, + C, D, E, F, G and H. + +**/ +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) + +#endif + diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Guid/WinCertificate.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Guid/WinCertificate.h new file mode 100644 index 0000000000..6dea446ba0 --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Guid/WinCertificate.h @@ -0,0 +1,128 @@ +/** @file + GUID for UEFI WIN_CERTIFICATE structure. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.0 spec. +**/ + +#ifndef __EFI_WIN_CERTIFICATE_H__ +#define __EFI_WIN_CERTIFICATE_H__ + +// +// _WIN_CERTIFICATE.wCertificateType +// +#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 +#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +/// +/// The WIN_CERTIFICATE structure is part of the PE/COFF specification. +/// +typedef struct { + /// + /// The length of the entire certificate, + /// including the length of the header, in bytes. + /// + UINT32 dwLength; + /// + /// The revision level of the WIN_CERTIFICATE + /// structure. The current revision level is 0x0200. + /// + UINT16 wRevision; + /// + /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI + /// certificate types. The UEFI specification reserves the range of + /// certificate type values from 0x0EF0 to 0x0EFF. + /// + UINT16 wCertificateType; + /// + /// The following is the actual certificate. The format of + /// the certificate depends on wCertificateType. + /// + /// UINT8 bCertificate[ANYSIZE_ARRAY]; + /// +} WIN_CERTIFICATE; + +/// +/// WIN_CERTIFICATE_UEFI_GUID.CertType +/// +#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ + {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } + +/// +/// WIN_CERTIFICATE_UEFI_GUID.CertData +/// +typedef struct { + EFI_GUID HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; +} EFI_CERT_BLOCK_RSA_2048_SHA256; + + +/// +/// Certificate which encapsulates a GUID-specific digital signature +/// +typedef struct { + /// + /// This is the standard WIN_CERTIFICATE header, where + /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID. + /// + WIN_CERTIFICATE Hdr; + /// + /// This is the unique id which determines the + /// format of the CertData. . + /// + EFI_GUID CertType; + /// + /// The following is the certificate data. The format of + /// the data is determined by the CertType. + /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID, + /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure. + /// + UINT8 CertData[1]; +} WIN_CERTIFICATE_UEFI_GUID; + + +/// +/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature. +/// +/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from +/// WIN_CERTIFICATE and encapsulate the information needed to +/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as +/// specified in RFC2437. +/// +typedef struct { + /// + /// This is the standard WIN_CERTIFICATE header, where + /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15. + /// + WIN_CERTIFICATE Hdr; + /// + /// This is the hashing algorithm which was performed on the + /// UEFI executable when creating the digital signature. + /// + EFI_GUID HashAlgorithm; + /// + /// The following is the actual digital signature. The + /// size of the signature is the same size as the key + /// (1024-bit key is 128 bytes) and can be determined by + /// subtracting the length of the other parts of this header + /// from the total length of the certificate as found in + /// Hdr.dwLength. + /// + /// UINT8 Signature[]; + /// +} WIN_CERTIFICATE_EFI_PKCS1_15; + +extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid; + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Ia32/ProcessorBind.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Ia32/ProcessorBind.h new file mode 100644 index 0000000000..268a4cfc7d --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Ia32/ProcessorBind.h @@ -0,0 +1,292 @@ +/** @file + Processor or Compiler specific defines and types for IA-32 architecture. + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices. +/// +#define MDE_CPU_IA32 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) +#pragma pack() +#endif + +#if defined(__INTEL_COMPILER) +// +// Disable ICC's remark #869: "Parameter" was never referenced warning. +// This is legal ANSI C code so we disable the remark that is turned on with -Wall +// +#pragma warning ( disable : 869 ) + +// +// Disable ICC's remark #1418: external function definition with no prior declaration. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1418 ) + +// +// Disable ICC's remark #1419: external declaration in primary source file +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1419 ) + +// +// Disable ICC's remark #593: "Variable" was set but never used. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 593 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + + // + // use Microsoft C complier dependent integer width types + // + + /// + /// 8-byte unsigned value. + /// + typedef unsigned __int64 UINT64; + /// + /// 8-byte signed value. + /// + typedef __int64 INT64; + /// + /// 4-byte unsigned value. + /// + typedef unsigned __int32 UINT32; + /// + /// 4-byte signed value. + /// + typedef __int32 INT32; + /// + /// 2-byte unsigned value. + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value. + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value. + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character. + /// + typedef char CHAR8; + /// + /// 1-byte signed value. + /// + typedef signed char INT8; +#else + /// + /// 8-byte unsigned value. + /// + typedef unsigned long long UINT64; + /// + /// 8-byte signed value. + /// + typedef long long INT64; + /// + /// 4-byte unsigned value. + /// + typedef unsigned int UINT32; + /// + /// 4-byte signed value. + /// + typedef int INT32; + /// + /// 2-byte unsigned value. + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value. + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value. + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions; +/// 8 bytes on supported 64-bit processor instructions.) +/// +typedef UINT32 UINTN; +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions; +/// 8 bytes on supported 64-bit processor instructions.) +/// +typedef INT32 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x80000000 +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC0000000 + +/// +/// Maximum legal IA-32 address. +/// +#define MAX_ADDRESS 0xFFFFFFFF + +/// +/// Maximum legal IA-32 INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFF) +#define MAX_UINTN ((UINTN)0xFFFFFFFF) + +/// +/// The stack alignment required for IA-32. +/// +#define CPU_STACK_ALIGNMENT sizeof(UINTN) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#ifdef EFIAPI + /// + /// If EFIAPI is already defined, then we use that definition. + /// +#elif defined(_MSC_EXTENSIONS) + /// + /// Microsoft* compiler specific method for EFIAPI calling convention. + /// + #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// GCC specific method for EFIAPI calling convention. + /// + #define EFIAPI __attribute__((cdecl)) +#else + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI +#endif + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On IA-32 CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#endif + diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Library/HobLib.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Library/HobLib.h new file mode 100644 index 0000000000..2cc4b1b36e --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Library/HobLib.h @@ -0,0 +1,506 @@ +/** @file + Provides services to create and parse HOBs. Only available for PEI + and DXE module types. + + The HOB Library supports the efficient creation and searching of HOBs + defined in the PI Specification. + A HOB is a Hand-Off Block, defined in the Framework architecture, that + allows the PEI phase to pass information to the DXE phase. HOBs are position + independent and can be relocated easily to different memory memory locations. + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HOB_LIB_H__ +#define __HOB_LIB_H__ + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer + to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through + the EFI System Table by looking up theHOB list GUID in the System Configuration Table. + Since the System Configuration Table does not exist that the time the DXE Core is + launched, the DXE Core uses a global variable from the DXE Core Entry Point Library + to manage the pointer to the HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ); + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ); + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ); + +/** + Returns the next instance of the matched GUID HOB from the starting HOB. + + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ); + +/** + Returns the first instance of the matched GUID HOB among the whole HOB list. + + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + + If the pointer to the HOB list is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ); + +/** + Get the system boot mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param VOID + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootModeHob ( + VOID + ); + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ); + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ); + +/** + Builds a customized HOB tagged with a GUID for identification and returns + the start address of GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ); + +/** + Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB + data field, and returns the start address of the GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification and copies the input + data to the HOB data field and returns the start address of the GUID HOB data. It can only be + invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ); + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ); + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If the platform does not support Capsule Volume HOBs, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ); + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + +/** + Returns the type of a HOB. + + This macro returns the HobType field from the HOB header for the + HOB specified by HobStart. + + @param HobStart A pointer to a HOB. + + @return HobType. + +**/ +#define GET_HOB_TYPE(HobStart) \ + ((*(EFI_HOB_GENERIC_HEADER **)&(HobStart))->HobType) + +/** + Returns the length, in bytes, of a HOB. + + This macro returns the HobLength field from the HOB header for the + HOB specified by HobStart. + + @param HobStart A pointer to a HOB. + + @return HobLength. + +**/ +#define GET_HOB_LENGTH(HobStart) \ + ((*(EFI_HOB_GENERIC_HEADER **)&(HobStart))->HobLength) + +/** + Returns a pointer to the next HOB in the HOB list. + + This macro returns a pointer to HOB that follows the + HOB specified by HobStart in the HOB List. + + @param HobStart A pointer to a HOB. + + @return A pointer to the next HOB in the HOB list. + +**/ +#define GET_NEXT_HOB(HobStart) \ + (VOID *)(*(UINT8 **)&(HobStart) + GET_HOB_LENGTH (HobStart)) + +/** + Determines if a HOB is the last HOB in the HOB list. + + This macro determine if the HOB specified by HobStart is the + last HOB in the HOB list. If HobStart is last HOB in the HOB list, + then TRUE is returned. Otherwise, FALSE is returned. + + @param HobStart A pointer to a HOB. + + @retval TRUE The HOB specified by HobStart is the last HOB in the HOB list. + @retval FALSE The HOB specified by HobStart is not the last HOB in the HOB list. + +**/ +#define END_OF_HOB_LIST(HobStart) (GET_HOB_TYPE (HobStart) == (UINT16)EFI_HOB_TYPE_END_OF_HOB_LIST) + +/** + Returns a pointer to data buffer from a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + This macro returns a pointer to the data buffer in a HOB specified by HobStart. + HobStart is assumed to be a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + @param GuidHob A pointer to a HOB. + + @return A pointer to the data buffer in a HOB. + +**/ +#define GET_GUID_HOB_DATA(HobStart) \ + (VOID *)(*(UINT8 **)&(HobStart) + sizeof (EFI_HOB_GUID_TYPE)) + +/** + Returns the size of the data buffer from a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + This macro returns the size, in bytes, of the data buffer in a HOB specified by HobStart. + HobStart is assumed to be a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + @param GuidHob A pointer to a HOB. + + @return The size of the data buffer. +**/ +#define GET_GUID_HOB_DATA_SIZE(HobStart) \ + (UINT16)(GET_HOB_LENGTH (HobStart) - sizeof (EFI_HOB_GUID_TYPE)) + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiBootMode.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiBootMode.h new file mode 100644 index 0000000000..793833bccd --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiBootMode.h @@ -0,0 +1,42 @@ +/** @file + Present the boot mode values in PI. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2.1A + +**/ + +#ifndef __PI_BOOT_MODE_H__ +#define __PI_BOOT_MODE_H__ + +/// +/// EFI boot mode +/// +typedef UINT32 EFI_BOOT_MODE; + +// +// 0x21 - 0xf..f are reserved. +// +#define BOOT_WITH_FULL_CONFIGURATION 0x00 +#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01 +#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 +#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 +#define BOOT_WITH_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_WITH_MFG_MODE_SETTINGS 0x07 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareFile.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareFile.h new file mode 100644 index 0000000000..750ba7091e --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareFile.h @@ -0,0 +1,494 @@ +/** @file + The firmware file related definitions in PI. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2. + +**/ + + +#ifndef __PI_FIRMWARE_FILE_H__ +#define __PI_FIRMWARE_FILE_H__ + +#pragma pack(1) +/// +/// Used to verify the integrity of the file. +/// +typedef union { + struct { + /// + /// The IntegrityCheck.Checksum.Header field is an 8-bit checksum of the file + /// header. The State and IntegrityCheck.Checksum.File fields are assumed + /// to be zero and the checksum is calculated such that the entire header sums to zero. + /// + UINT8 Header; + /// + /// If the FFS_ATTRIB_CHECKSUM (see definition below) bit of the Attributes + /// field is set to one, the IntegrityCheck.Checksum.File field is an 8-bit + /// checksum of the file data. + /// If the FFS_ATTRIB_CHECKSUM bit of the Attributes field is cleared to zero, + /// the IntegrityCheck.Checksum.File field must be initialized with a value of + /// 0xAA. The IntegrityCheck.Checksum.File field is valid any time the + /// EFI_FILE_DATA_VALID bit is set in the State field. + /// + UINT8 File; + } Checksum; + /// + /// This is the full 16 bits of the IntegrityCheck field. + /// + UINT16 Checksum16; +} EFI_FFS_INTEGRITY_CHECK; + +/// +/// FFS_FIXED_CHECKSUM is the checksum value used when the +/// FFS_ATTRIB_CHECKSUM attribute bit is clear. +/// +#define FFS_FIXED_CHECKSUM 0xAA + +typedef UINT8 EFI_FV_FILETYPE; +typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; +typedef UINT8 EFI_FFS_FILE_STATE; + +/// +/// File Types Definitions +/// +#define EFI_FV_FILETYPE_ALL 0x00 +#define EFI_FV_FILETYPE_RAW 0x01 +#define EFI_FV_FILETYPE_FREEFORM 0x02 +#define EFI_FV_FILETYPE_SECURITY_CORE 0x03 +#define EFI_FV_FILETYPE_PEI_CORE 0x04 +#define EFI_FV_FILETYPE_DXE_CORE 0x05 +#define EFI_FV_FILETYPE_PEIM 0x06 +#define EFI_FV_FILETYPE_DRIVER 0x07 +#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 +#define EFI_FV_FILETYPE_APPLICATION 0x09 +#define EFI_FV_FILETYPE_SMM 0x0A +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B +#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C +#define EFI_FV_FILETYPE_SMM_CORE 0x0D +#define EFI_FV_FILETYPE_OEM_MIN 0xc0 +#define EFI_FV_FILETYPE_OEM_MAX 0xdf +#define EFI_FV_FILETYPE_DEBUG_MIN 0xe0 +#define EFI_FV_FILETYPE_DEBUG_MAX 0xef +#define EFI_FV_FILETYPE_FFS_MIN 0xf0 +#define EFI_FV_FILETYPE_FFS_MAX 0xff +#define EFI_FV_FILETYPE_FFS_PAD 0xf0 +/// +/// FFS File Attributes. +/// +#define FFS_ATTRIB_LARGE_FILE 0x01 +#define FFS_ATTRIB_FIXED 0x04 +#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 +#define FFS_ATTRIB_CHECKSUM 0x40 + +/// +/// FFS File State Bits. +/// +#define EFI_FILE_HEADER_CONSTRUCTION 0x01 +#define EFI_FILE_HEADER_VALID 0x02 +#define EFI_FILE_DATA_VALID 0x04 +#define EFI_FILE_MARKED_FOR_UPDATE 0x08 +#define EFI_FILE_DELETED 0x10 +#define EFI_FILE_HEADER_INVALID 0x20 + + +/// +/// Each file begins with the header that describe the +/// contents and state of the files. +/// +typedef struct { + /// + /// This GUID is the file name. It is used to uniquely identify the file. + /// + EFI_GUID Name; + /// + /// Used to verify the integrity of the file. + /// + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + /// + /// Identifies the type of file. + /// + EFI_FV_FILETYPE Type; + /// + /// Declares various file attribute bits. + /// + EFI_FFS_FILE_ATTRIBUTES Attributes; + /// + /// The length of the file in bytes, including the FFS header. + /// + UINT8 Size[3]; + /// + /// Used to track the state of the file throughout the life of the file from creation to deletion. + /// + EFI_FFS_FILE_STATE State; +} EFI_FFS_FILE_HEADER; + +typedef struct { + /// + /// This GUID is the file name. It is used to uniquely identify the file. There may be only + /// one instance of a file with the file name GUID of Name in any given firmware + /// volume, except if the file type is EFI_FV_FILETYPE_FFS_PAD. + /// + EFI_GUID Name; + + /// + /// Used to verify the integrity of the file. + /// + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + + /// + /// Identifies the type of file. + /// + EFI_FV_FILETYPE Type; + + /// + /// Declares various file attribute bits. + /// + EFI_FFS_FILE_ATTRIBUTES Attributes; + + /// + /// The length of the file in bytes, including the FFS header. + /// The length of the file data is either (Size - sizeof(EFI_FFS_FILE_HEADER)). This calculation means a + /// zero-length file has a Size of 24 bytes, which is sizeof(EFI_FFS_FILE_HEADER). + /// Size is not required to be a multiple of 8 bytes. Given a file F, the next file header is + /// located at the next 8-byte aligned firmware volume offset following the last byte of the file F. + /// + UINT8 Size[3]; + + /// + /// Used to track the state of the file throughout the life of the file from creation to deletion. + /// + EFI_FFS_FILE_STATE State; + + /// + /// If FFS_ATTRIB_LARGE_FILE is set in Attributes, then ExtendedSize exists and Size must be set to zero. + /// If FFS_ATTRIB_LARGE_FILE is not set then EFI_FFS_FILE_HEADER is used. + /// + UINT32 ExtendedSize; +} EFI_FFS_FILE_HEADER2; + +#define IS_FFS_FILE2(FfsFileHeaderPtr) \ + (((((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Attributes) & FFS_ATTRIB_LARGE_FILE) == FFS_ATTRIB_LARGE_FILE) + +#define FFS_FILE_SIZE(FfsFileHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Size) & 0x00ffffff)) + +#define FFS_FILE2_SIZE(FfsFileHeaderPtr) \ + (((EFI_FFS_FILE_HEADER2 *) (UINTN) FfsFileHeaderPtr)->ExtendedSize) + +typedef UINT8 EFI_SECTION_TYPE; + +/// +/// Pseudo type. It is used as a wild card when retrieving sections. +/// The section type EFI_SECTION_ALL matches all section types. +/// +#define EFI_SECTION_ALL 0x00 + +/// +/// Encapsulation section Type values. +/// +#define EFI_SECTION_COMPRESSION 0x01 + +#define EFI_SECTION_GUID_DEFINED 0x02 + +#define EFI_SECTION_DISPOSABLE 0x03 + +/// +/// Leaf section Type values. +/// +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B +#define EFI_SECTION_SMM_DEPEX 0x1C + +/// +/// Common section header. +/// +typedef struct { + /// + /// A 24-bit unsigned integer that contains the total size of the section in bytes, + /// including the EFI_COMMON_SECTION_HEADER. + /// + UINT8 Size[3]; + EFI_SECTION_TYPE Type; + /// + /// Declares the section type. + /// +} EFI_COMMON_SECTION_HEADER; + +typedef struct { + /// + /// A 24-bit unsigned integer that contains the total size of the section in bytes, + /// including the EFI_COMMON_SECTION_HEADER. + /// + UINT8 Size[3]; + + EFI_SECTION_TYPE Type; + + /// + /// If Size is 0xFFFFFF, then ExtendedSize contains the size of the section. If + /// Size is not equal to 0xFFFFFF, then this field does not exist. + /// + UINT32 ExtendedSize; +} EFI_COMMON_SECTION_HEADER2; + +/// +/// Leaf section type that contains an +/// IA-32 16-bit executable image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2; + +/// +/// CompressionType of EFI_COMPRESSION_SECTION. +/// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +/// +/// An encapsulation section type in which the +/// section data is compressed. +/// +typedef struct { + /// + /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// The UINT32 that indicates the size of the section data after decompression. + /// + UINT32 UncompressedLength; + /// + /// Indicates which compression algorithm is used. + /// + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +typedef struct { + /// + /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// UINT32 that indicates the size of the section data after decompression. + /// + UINT32 UncompressedLength; + /// + /// Indicates which compression algorithm is used. + /// + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION2; + +/// +/// An encapsulation section type in which the section data is disposable. +/// A disposable section is an encapsulation section in which the section data may be disposed of during +/// the process of creating or updating a firmware image without significant impact on the usefulness of +/// the file. The Type field in the section header is set to EFI_SECTION_DISPOSABLE. This +/// allows optional or descriptive data to be included with the firmware file which can be removed in +/// order to conserve space. The contents of this section are implementation specific, but might contain +/// debug data or detailed integration instructions. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2; + +/// +/// The leaf section which could be used to determine the dispatch order of DXEs. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2; + +/// +/// The leaf section which contains a PI FV. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2; + +/// +/// The leaf section which contains a single GUID. +/// +typedef struct { + /// + /// Common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// This GUID is defined by the creator of the file. It is a vendor-defined file type. + /// + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// This GUID is defined by the creator of the file. It is a vendor-defined file type. + /// + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION2; + +/// +/// Attributes of EFI_GUID_DEFINED_SECTION. +/// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 +/// +/// The leaf section which is encapsulation defined by specific GUID. +/// +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// The GUID that defines the format of the data that follows. It is a vendor-defined section type. + /// + EFI_GUID SectionDefinitionGuid; + /// + /// Contains the offset in bytes from the beginning of the common header to the first byte of the data. + /// + UINT16 DataOffset; + /// + /// The bit field that declares some specific characteristics of the section contents. + /// + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// The GUID that defines the format of the data that follows. It is a vendor-defined section type. + /// + EFI_GUID SectionDefinitionGuid; + /// + /// Contains the offset in bytes from the beginning of the common header to the first byte of the data. + /// + UINT16 DataOffset; + /// + /// The bit field that declares some specific characteristics of the section contents. + /// + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION2; + +/// +/// The leaf section which contains PE32+ image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2; + +/// +/// The leaf section used to determine the dispatch order of PEIMs. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2; + +/// +/// A leaf section type that contains a position-independent-code (PIC) image. +/// A PIC image section is a leaf section that contains a position-independent-code (PIC) image. +/// In addition to normal PE32+ images that contain relocation information, PEIM executables may be +/// PIC and are referred to as PIC images. A PIC image is the same as a PE32+ image except that all +/// relocation information has been stripped from the image and the image can be moved and will +/// execute correctly without performing any relocation or other fix-ups. EFI_PIC_SECTION2 must +/// be used if the section is 16MB or larger. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2; + +/// +/// The leaf section which constains the position-independent-code image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2; + +/// +/// The leaf section which contains an array of zero or more bytes. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2; + +/// +/// The SMM dependency expression section is a leaf section that contains a dependency expression that +/// is used to determine the dispatch order for SMM drivers. Before the SMRAM invocation of the +/// SMM driver's entry point, this dependency expression must evaluate to TRUE. See the Platform +/// Initialization Specification, Volume 2, for details regarding the format of the dependency expression. +/// The dependency expression may refer to protocols installed in either the UEFI or the SMM protocol +/// database. EFI_SMM_DEPEX_SECTION2 must be used if the section is 16MB or larger. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2; + +/// +/// The leaf section which contains a unicode string that +/// is human readable file name. +/// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + + /// + /// Array of unicode string. + /// + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION2; + +/// +/// The leaf section which contains a numeric build number and +/// an optional unicode string that represents the file revision. +/// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + + /// + /// Array of unicode string. + /// + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// A UINT16 that represents a particular build. Subsequent builds have monotonically + /// increasing build numbers relative to earlier builds. + /// + UINT16 BuildNumber; + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION2; + +#define IS_SECTION2(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff) == 0x00ffffff) + +#define SECTION_SIZE(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff)) + +#define SECTION2_SIZE(SectionHeaderPtr) \ + (((EFI_COMMON_SECTION_HEADER2 *) (UINTN) SectionHeaderPtr)->ExtendedSize) + +#pragma pack() + +#endif + diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareVolume.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareVolume.h new file mode 100644 index 0000000000..6ef2f1fc33 --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiFirmwareVolume.h @@ -0,0 +1,234 @@ +/** @file + The firmware volume related definitions in PI. + + Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.3 + +**/ + +#ifndef __PI_FIRMWAREVOLUME_H__ +#define __PI_FIRMWAREVOLUME_H__ + +/// +/// EFI_FV_FILE_ATTRIBUTES +/// +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; + +// +// Value of EFI_FV_FILE_ATTRIBUTES. +// +#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F +#define EFI_FV_FILE_ATTRIB_FIXED 0x00000100 +#define EFI_FV_FILE_ATTRIB_MEMORY_MAPPED 0x00000200 + +/// +/// type of EFI FVB attribute +/// +typedef UINT32 EFI_FVB_ATTRIBUTES_2; + +// +// Attributes bit definitions +// +#define EFI_FVB2_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB2_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB2_READ_STATUS 0x00000004 +#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB2_WRITE_STATUS 0x00000020 +#define EFI_FVB2_LOCK_CAP 0x00000040 +#define EFI_FVB2_LOCK_STATUS 0x00000080 +#define EFI_FVB2_STICKY_WRITE 0x00000200 +#define EFI_FVB2_MEMORY_MAPPED 0x00000400 +#define EFI_FVB2_ERASE_POLARITY 0x00000800 +#define EFI_FVB2_READ_LOCK_CAP 0x00001000 +#define EFI_FVB2_READ_LOCK_STATUS 0x00002000 +#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000 +#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000 +#define EFI_FVB2_ALIGNMENT 0x001F0000 +#define EFI_FVB2_ALIGNMENT_1 0x00000000 +#define EFI_FVB2_ALIGNMENT_2 0x00010000 +#define EFI_FVB2_ALIGNMENT_4 0x00020000 +#define EFI_FVB2_ALIGNMENT_8 0x00030000 +#define EFI_FVB2_ALIGNMENT_16 0x00040000 +#define EFI_FVB2_ALIGNMENT_32 0x00050000 +#define EFI_FVB2_ALIGNMENT_64 0x00060000 +#define EFI_FVB2_ALIGNMENT_128 0x00070000 +#define EFI_FVB2_ALIGNMENT_256 0x00080000 +#define EFI_FVB2_ALIGNMENT_512 0x00090000 +#define EFI_FVB2_ALIGNMENT_1K 0x000A0000 +#define EFI_FVB2_ALIGNMENT_2K 0x000B0000 +#define EFI_FVB2_ALIGNMENT_4K 0x000C0000 +#define EFI_FVB2_ALIGNMENT_8K 0x000D0000 +#define EFI_FVB2_ALIGNMENT_16K 0x000E0000 +#define EFI_FVB2_ALIGNMENT_32K 0x000F0000 +#define EFI_FVB2_ALIGNMENT_64K 0x00100000 +#define EFI_FVB2_ALIGNMENT_128K 0x00110000 +#define EFI_FVB2_ALIGNMENT_256K 0x00120000 +#define EFI_FVB2_ALIGNMENT_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_1M 0x00140000 +#define EFI_FVB2_ALIGNMENT_2M 0x00150000 +#define EFI_FVB2_ALIGNMENT_4M 0x00160000 +#define EFI_FVB2_ALIGNMENT_8M 0x00170000 +#define EFI_FVB2_ALIGNMENT_16M 0x00180000 +#define EFI_FVB2_ALIGNMENT_32M 0x00190000 +#define EFI_FVB2_ALIGNMENT_64M 0x001A0000 +#define EFI_FVB2_ALIGNMENT_128M 0x001B0000 +#define EFI_FVB2_ALIGNMENT_256M 0x001C0000 +#define EFI_FVB2_ALIGNMENT_512M 0x001D0000 +#define EFI_FVB2_ALIGNMENT_1G 0x001E0000 +#define EFI_FVB2_ALIGNMENT_2G 0x001F0000 +#define EFI_FVB2_WEAK_ALIGNMENT 0x80000000 + +typedef struct { + /// + /// The number of sequential blocks which are of the same size. + /// + UINT32 NumBlocks; + /// + /// The size of the blocks. + /// + UINT32 Length; +} EFI_FV_BLOCK_MAP_ENTRY; + +/// +/// Describes the features and layout of the firmware volume. +/// +typedef struct { + /// + /// The first 16 bytes are reserved to allow for the reset vector of + /// processors whose reset vector is at address 0. + /// + UINT8 ZeroVector[16]; + /// + /// Declares the file system with which the firmware volume is formatted. + /// + EFI_GUID FileSystemGuid; + /// + /// Length in bytes of the complete firmware volume, including the header. + /// + UINT64 FvLength; + /// + /// Set to EFI_FVH_SIGNATURE + /// + UINT32 Signature; + /// + /// Declares capabilities and power-on defaults for the firmware volume. + /// + EFI_FVB_ATTRIBUTES_2 Attributes; + /// + /// Length in bytes of the complete firmware volume header. + /// + UINT16 HeaderLength; + /// + /// A 16-bit checksum of the firmware volume header. A valid header sums to zero. + /// + UINT16 Checksum; + /// + /// Offset, relative to the start of the header, of the extended header + /// (EFI_FIRMWARE_VOLUME_EXT_HEADER) or zero if there is no extended header. + /// + UINT16 ExtHeaderOffset; + /// + /// This field must always be set to zero. + /// + UINT8 Reserved[1]; + /// + /// Set to 2. Future versions of this specification may define new header fields and will + /// increment the Revision field accordingly. + /// + UINT8 Revision; + /// + /// An array of run-length encoded FvBlockMapEntry structures. The array is + /// terminated with an entry of {0,0}. + /// + EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; +} EFI_FIRMWARE_VOLUME_HEADER; + +#define EFI_FVH_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', 'H') + +/// +/// Firmware Volume Header Revision definition +/// +#define EFI_FVH_REVISION 0x02 + +/// +/// Extension header pointed by ExtHeaderOffset of volume header. +/// +typedef struct { + /// + /// Firmware volume name. + /// + EFI_GUID FvName; + /// + /// Size of the rest of the extension header, including this structure. + /// + UINT32 ExtHeaderSize; +} EFI_FIRMWARE_VOLUME_EXT_HEADER; + +/// +/// Entry struture for describing FV extension header +/// +typedef struct { + /// + /// Size of this header extension. + /// + UINT16 ExtEntrySize; + /// + /// Type of the header. + /// + UINT16 ExtEntryType; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY; + +#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01 +/// +/// This extension header provides a mapping between a GUID and an OEM file type. +/// +typedef struct { + /// + /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE. + /// + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + /// + /// A bit mask, one bit for each file type between 0xC0 (bit 0) and 0xDF (bit 31). If a bit + /// is '1', then the GUID entry exists in Types. If a bit is '0' then no GUID entry exists in Types. + /// + UINT32 TypeMask; + /// + /// An array of GUIDs, each GUID representing an OEM file type. + /// + /// EFI_GUID Types[1]; + /// +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE; + +#define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002 + +/// +/// This extension header EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE provides a vendor specific +/// GUID FormatType type which includes a length and a successive series of data bytes. +/// +typedef struct { + /// + /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE. + /// + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + /// + /// Vendor-specific GUID. + /// + EFI_GUID FormatType; + /// + /// An arry of bytes of length Length. + /// + /// UINT8 Data[1]; + /// +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE; + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiHob.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiHob.h new file mode 100644 index 0000000000..d7a6f2539a --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Pi/PiHob.h @@ -0,0 +1,452 @@ +/** @file + HOB related definitions in PI. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.0 + +**/ + +#ifndef __PI_HOB_H__ +#define __PI_HOB_H__ + +// +// HobType of EFI_HOB_GENERIC_HEADER. +// +#define EFI_HOB_TYPE_HANDOFF 0x0001 +#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 +#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 +#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 +#define EFI_HOB_TYPE_FV 0x0005 +#define EFI_HOB_TYPE_CPU 0x0006 +#define EFI_HOB_TYPE_MEMORY_POOL 0x0007 +#define EFI_HOB_TYPE_FV2 0x0009 +#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A +#define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B +#define EFI_HOB_TYPE_UNUSED 0xFFFE +#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF + +/// +/// Describes the format and size of the data inside the HOB. +/// All HOBs must contain this generic HOB header. +/// +typedef struct { + /// + /// Identifies the HOB data structure type. + /// + UINT16 HobType; + /// + /// The length in bytes of the HOB. + /// + UINT16 HobLength; + /// + /// This field must always be set to zero. + /// + UINT32 Reserved; +} EFI_HOB_GENERIC_HEADER; + + +/// +/// Value of version in EFI_HOB_HANDOFF_INFO_TABLE. +/// +#define EFI_HOB_HANDOFF_TABLE_VERSION 0x0009 + +/// +/// Contains general state information used by the HOB producer phase. +/// This HOB must be the first one in the HOB list. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_HANDOFF. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The version number pertaining to the PHIT HOB definition. + /// This value is four bytes in length to provide an 8-byte aligned entry + /// when it is combined with the 4-byte BootMode. + /// + UINT32 Version; + /// + /// The system boot mode as determined during the HOB producer phase. + /// + EFI_BOOT_MODE BootMode; + /// + /// The highest address location of memory that is allocated for use by the HOB producer + /// phase. This address must be 4-KB aligned to meet page restrictions of UEFI. + /// + EFI_PHYSICAL_ADDRESS EfiMemoryTop; + /// + /// The lowest address location of memory that is allocated for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiMemoryBottom; + /// + /// The highest address location of free memory that is currently available + /// for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop; + /// + /// The lowest address location of free memory that is available for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom; + /// + /// The end of the HOB list. + /// + EFI_PHYSICAL_ADDRESS EfiEndOfHobList; +} EFI_HOB_HANDOFF_INFO_TABLE; + +/// +/// EFI_HOB_MEMORY_ALLOCATION_HEADER describes the +/// various attributes of the logical memory allocation. The type field will be used for +/// subsequent inclusion in the UEFI memory map. +/// +typedef struct { + /// + /// A GUID that defines the memory allocation region's type and purpose, as well as + /// other fields within the memory allocation HOB. This GUID is used to define the + /// additional data within the HOB that may be present for the memory allocation HOB. + /// Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0 + /// specification. + /// + EFI_GUID Name; + + /// + /// The base address of memory allocated by this HOB. Type + /// EFI_PHYSICAL_ADDRESS is defined in AllocatePages() in the UEFI 2.0 + /// specification. + /// + EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + + /// + /// The length in bytes of memory allocated by this HOB. + /// + UINT64 MemoryLength; + + /// + /// Defines the type of memory allocated by this HOB. The memory type definition + /// follows the EFI_MEMORY_TYPE definition. Type EFI_MEMORY_TYPE is defined + /// in AllocatePages() in the UEFI 2.0 specification. + /// + EFI_MEMORY_TYPE MemoryType; + + /// + /// Padding for Itanium processor family + /// + UINT8 Reserved[4]; +} EFI_HOB_MEMORY_ALLOCATION_HEADER; + +/// +/// Describes all memory ranges used during the HOB producer +/// phase that exist outside the HOB list. This HOB type +/// describes how memory is used, not the physical attributes of memory. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; + // + // Additional data pertaining to the "Name" Guid memory + // may go here. + // +} EFI_HOB_MEMORY_ALLOCATION; + + +/// +/// Describes the memory stack that is produced by the HOB producer +/// phase and upon which all post-memory-installed executable +/// content in the HOB producer phase is executing. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_STACK; + +/// +/// Defines the location of the boot-strap +/// processor (BSP) BSPStore ("Backing Store Pointer Store"). +/// This HOB is valid for the Itanium processor family only +/// register overflow store. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_BSP_STORE; + +/// +/// Defines the location and entry point of the HOB consumer phase. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER MemoryAllocationHeader; + /// + /// The GUID specifying the values of the firmware file system name + /// that contains the HOB consumer phase component. + /// + EFI_GUID ModuleName; + /// + /// The address of the memory-mapped firmware volume + /// that contains the HOB consumer phase firmware file. + /// + EFI_PHYSICAL_ADDRESS EntryPoint; +} EFI_HOB_MEMORY_ALLOCATION_MODULE; + +/// +/// The resource type. +/// +typedef UINT32 EFI_RESOURCE_TYPE; + +// +// Value of ResourceType in EFI_HOB_RESOURCE_DESCRIPTOR. +// +#define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000 +#define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001 +#define EFI_RESOURCE_IO 0x00000002 +#define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003 +#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004 +#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005 +#define EFI_RESOURCE_IO_RESERVED 0x00000006 +#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000007 + +/// +/// A type of recount attribute type. +/// +typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; + +// +// These types can be ORed together as needed. +// +// The following attributes are used to describe settings +// +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 +// +// The rest of the attributes are used to describe capabilities +// +#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 +#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 +#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000 +#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 +#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000 + +/// +/// Describes the resource properties of all fixed, +/// nonrelocatable resource ranges found on the processor +/// host bus during the HOB producer phase. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// A GUID representing the owner of the resource. This GUID is used by HOB + /// consumer phase components to correlate device ownership of a resource. + /// + EFI_GUID Owner; + /// + /// The resource type enumeration as defined by EFI_RESOURCE_TYPE. + /// + EFI_RESOURCE_TYPE ResourceType; + /// + /// Resource attributes as defined by EFI_RESOURCE_ATTRIBUTE_TYPE. + /// + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + /// + /// The physical start address of the resource region. + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// The number of bytes of the resource region. + /// + UINT64 ResourceLength; +} EFI_HOB_RESOURCE_DESCRIPTOR; + +/// +/// Allows writers of executable content in the HOB producer phase to +/// maintain and manage HOBs with specific GUID. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_GUID_EXTENSION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// A GUID that defines the contents of this HOB. + /// + EFI_GUID Name; + // + // Guid specific data goes here + // +} EFI_HOB_GUID_TYPE; + +/// +/// Details the location of firmware volumes that contain firmware files. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The physical memory-mapped base address of the firmware volume. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + /// + /// The length in bytes of the firmware volume. + /// + UINT64 Length; +} EFI_HOB_FIRMWARE_VOLUME; + +/// +/// Details the location of a firmware volume that was extracted +/// from a file within another firmware volume. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV2. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The physical memory-mapped base address of the firmware volume. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + /// + /// The length in bytes of the firmware volume. + /// + UINT64 Length; + /// + /// The name of the firmware volume. + /// + EFI_GUID FvName; + /// + /// The name of the firmware file that contained this firmware volume. + /// + EFI_GUID FileName; +} EFI_HOB_FIRMWARE_VOLUME2; + + +/// +/// Describes processor information, such as address space and I/O space capabilities. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_CPU. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// Identifies the maximum physical memory addressability of the processor. + /// + UINT8 SizeOfMemorySpace; + /// + /// Identifies the maximum physical I/O addressability of the processor. + /// + UINT8 SizeOfIoSpace; + /// + /// This field will always be set to zero. + /// + UINT8 Reserved[6]; +} EFI_HOB_CPU; + + +/// +/// Describes pool memory allocations. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_POOL. + /// + EFI_HOB_GENERIC_HEADER Header; +} EFI_HOB_MEMORY_POOL; + +/// +/// Each UEFI capsule HOB details the location of a UEFI capsule. It includes a base address and length +/// which is based upon memory blocks with a EFI_CAPSULE_HEADER and the associated +/// CapsuleImageSize-based payloads. These HOB's shall be created by the PEI PI firmware +/// sometime after the UEFI UpdateCapsule service invocation with the +/// CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag set in the EFI_CAPSULE_HEADER. +/// +typedef struct { + /// + /// The HOB generic header where Header.HobType = EFI_HOB_TYPE_UEFI_CAPSULE. + /// + EFI_HOB_GENERIC_HEADER Header; + + /// + /// The physical memory-mapped base address of an UEFI capsule. This value is set to + /// point to the base of the contiguous memory of the UEFI capsule. + /// The length of the contiguous memory in bytes. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; +} EFI_HOB_UEFI_CAPSULE; + +/// +/// Union of all the possible HOB Types. +/// +typedef union { + EFI_HOB_GENERIC_HEADER *Header; + EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocation; + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore; + EFI_HOB_MEMORY_ALLOCATION_STACK *MemoryAllocationStack; + EFI_HOB_MEMORY_ALLOCATION_MODULE *MemoryAllocationModule; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor; + EFI_HOB_GUID_TYPE *Guid; + EFI_HOB_FIRMWARE_VOLUME *FirmwareVolume; + EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2; + EFI_HOB_CPU *Cpu; + EFI_HOB_MEMORY_POOL *Pool; + EFI_HOB_UEFI_CAPSULE *Capsule; + UINT8 *Raw; +} EFI_PEI_HOB_POINTERS; + + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiBaseType.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiBaseType.h new file mode 100644 index 0000000000..e0404231e1 --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiBaseType.h @@ -0,0 +1,301 @@ +/** @file + Defines data types and constants introduced in UEFI. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+ +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_BASETYPE_H__ +#define __UEFI_BASETYPE_H__ + +#include + +// +// Basic data type definitions introduced in UEFI. +// + +/// +/// 128-bit buffer containing a unique identifier value. +/// +typedef GUID EFI_GUID; +/// +/// Function return status for EFI API. +/// +typedef RETURN_STATUS EFI_STATUS; +/// +/// A collection of related interfaces. +/// +typedef VOID *EFI_HANDLE; +/// +/// Handle to an event structure. +/// +typedef VOID *EFI_EVENT; +/// +/// Task priority level. +/// +typedef UINTN EFI_TPL; +/// +/// Logical block address. +/// +typedef UINT64 EFI_LBA; + +/// +/// 64-bit physical memory address. +/// +typedef UINT64 EFI_PHYSICAL_ADDRESS; + +/// +/// 64-bit virtual memory address. +/// +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +/// +/// EFI Time Abstraction: +/// Year: 1900 - 9999 +/// Month: 1 - 12 +/// Day: 1 - 31 +/// Hour: 0 - 23 +/// Minute: 0 - 59 +/// Second: 0 - 59 +/// Nanosecond: 0 - 999,999,999 +/// TimeZone: -1440 to 1440 or 2047 +/// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + + +/// +/// 4-byte buffer. An IPv4 internet protocol address. +/// +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +/// +/// 16-byte buffer. An IPv6 internet protocol address. +/// +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +/// +/// 32-byte buffer containing a network Media Access Control address. +/// +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +/// +/// 16-byte buffer aligned on a 4-byte boundary. +/// An IPv4 or IPv6 internet protocol address. +/// +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + + +/// +/// Enumeration of EFI_STATUS. +///@{ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE +#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA +///@} + +/// +/// Define macro to encode the status code. +/// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + +/// +/// ICMP error definitions +///@{ +#define EFI_NETWORK_UNREACHABLE EFIERR(100) +#define EFI_HOST_UNREACHABLE EFIERR(101) +#define EFI_PROTOCOL_UNREACHABLE EFIERR(102) +#define EFI_PORT_UNREACHABLE EFIERR(103) +///@} + +/// +/// Tcp connection status definitions +///@{ +#define EFI_CONNECTION_FIN EFIERR(104) +#define EFI_CONNECTION_RESET EFIERR(105) +#define EFI_CONNECTION_REFUSED EFIERR(106) +///@} + +// +// The EFI memory allocation functions work in units of EFI_PAGEs that are +// 4KB. This should in no way be confused with the page size of the processor. +// An EFI_PAGE is just the quanta of memory in EFI. +// +#define EFI_PAGE_SIZE SIZE_4KB +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +/** + Macro that converts a size, in bytes, to a number of EFI_PAGESs. + + @param Size A size in bytes. This parameter is assumed to be type UINTN. + Passing in a parameter that is larger than UINTN may produce + unexpected results. + + @return The number of EFI_PAGESs associated with the number of bytes specified + by Size. + +**/ +#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0)) + +/** + Macro that converts a number of EFI_PAGEs to a size in bytes. + + @param Pages The number of EFI_PAGES. This parameter is assumed to be + type UINTN. Passing in a parameter that is larger than + UINTN may produce unexpected results. + + @return The number of bytes associated with the number of EFI_PAGEs specified + by Pages. + +**/ +#define EFI_PAGES_TO_SIZE(Pages) ((Pages) << EFI_PAGE_SHIFT) + +/// +/// PE32+ Machine type for IA32 UEFI images. +/// +#define EFI_IMAGE_MACHINE_IA32 0x014C + +/// +/// PE32+ Machine type for IA64 UEFI images. +/// +#define EFI_IMAGE_MACHINE_IA64 0x0200 + +/// +/// PE32+ Machine type for EBC UEFI images. +/// +#define EFI_IMAGE_MACHINE_EBC 0x0EBC + +/// +/// PE32+ Machine type for X64 UEFI images. +/// +#define EFI_IMAGE_MACHINE_X64 0x8664 + +/// +/// PE32+ Machine type for ARM mixed ARM and Thumb/Thumb2 images. +/// +#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2 + +/// +/// PE32+ Machine type for AARCH64 A64 images. +/// +#define EFI_IMAGE_MACHINE_AARCH64 0xAA64 + + +#if defined (MDE_CPU_IA32) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64) + +#elif defined (MDE_CPU_IPF) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#elif defined (MDE_CPU_X64) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32) + +#elif defined (MDE_CPU_ARM) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) + +#elif defined (MDE_CPU_AARCH64) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_AARCH64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#elif defined (MDE_CPU_EBC) + +/// +/// This is just to make sure you can cross compile with the EBC compiler. +/// It does not make sense to have a PE loader coded in EBC. +/// +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#else +#error Unknown Processor Type +#endif + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiMultiPhase.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiMultiPhase.h new file mode 100644 index 0000000000..8b1de79e3c --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/Uefi/UefiMultiPhase.h @@ -0,0 +1,193 @@ +/** @file + This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_MULTIPHASE_H__ +#define __UEFI_MULTIPHASE_H__ + +#include +/// +/// Enumeration of memory types introduced in UEFI. +/// +typedef enum { + /// + /// Not used. + /// + EfiReservedMemoryType, + /// + /// The code portions of a loaded application. + /// (Note that UEFI OS loaders are UEFI applications.) + /// + EfiLoaderCode, + /// + /// The data portions of a loaded application and the default data allocation + /// type used by an application to allocate pool memory. + /// + EfiLoaderData, + /// + /// The code portions of a loaded Boot Services Driver. + /// + EfiBootServicesCode, + /// + /// The data portions of a loaded Boot Serves Driver, and the default data + /// allocation type used by a Boot Services Driver to allocate pool memory. + /// + EfiBootServicesData, + /// + /// The code portions of a loaded Runtime Services Driver. + /// + EfiRuntimeServicesCode, + /// + /// The data portions of a loaded Runtime Services Driver and the default + /// data allocation type used by a Runtime Services Driver to allocate pool memory. + /// + EfiRuntimeServicesData, + /// + /// Free (unallocated) memory. + /// + EfiConventionalMemory, + /// + /// Memory in which errors have been detected. + /// + EfiUnusableMemory, + /// + /// Memory that holds the ACPI tables. + /// + EfiACPIReclaimMemory, + /// + /// Address space reserved for use by the firmware. + /// + EfiACPIMemoryNVS, + /// + /// Used by system firmware to request that a memory-mapped IO region + /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services. + /// + EfiMemoryMappedIO, + /// + /// System memory-mapped IO region that is used to translate memory + /// cycles to IO cycles by the processor. + /// + EfiMemoryMappedIOPortSpace, + /// + /// Address space reserved by the firmware for code that is part of the processor. + /// + EfiPalCode, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +/// +/// Data structure that precedes all of the standard EFI table types. +/// +typedef struct { + /// + /// A 64-bit signature that identifies the type of table that follows. + /// Unique signatures have been generated for the EFI System Table, + /// the EFI Boot Services Table, and the EFI Runtime Services Table. + /// + UINT64 Signature; + /// + /// The revision of the EFI Specification to which this table + /// conforms. The upper 16 bits of this field contain the major + /// revision value, and the lower 16 bits contain the minor revision + /// value. The minor revision values are limited to the range of 00..99. + /// + UINT32 Revision; + /// + /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER. + /// + UINT32 HeaderSize; + /// + /// The 32-bit CRC for the entire table. This value is computed by + /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes. + /// + UINT32 CRC32; + /// + /// Reserved field that must be set to 0. + /// + UINT32 Reserved; +} EFI_TABLE_HEADER; + +/// +/// Attributes of variable. +/// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +/// +/// This attribute is identified by the mnemonic 'HR' +/// elsewhere in this specification. +/// +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +/// +/// Attributes of Authenticated Variable +/// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 + + +/// +/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType +/// WIN_CERTIFICATE_UEFI_GUID and the CertType +/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies +/// authenticated access, then the Data buffer should begin with an +/// authentication descriptor prior to the data payload and DataSize +/// should reflect the the data.and descriptor size. The caller +/// shall digest the Monotonic Count value and the associated data +/// for the variable update using the SHA-256 1-way hash algorithm. +/// The ensuing the 32-byte digest will be signed using the private +/// key associated w/ the public/private 2048-bit RSA key-pair. The +/// WIN_CERTIFICATE shall be used to describe the signature of the +/// Variable data *Data. In addition, the signature will also +/// include the MonotonicCount value to guard against replay attacks. +/// +typedef struct { + /// + /// Included in the signature of + /// AuthInfo.Used to ensure freshness/no + /// replay. Incremented during each + /// "Write" access. + /// + UINT64 MonotonicCount; + /// + /// Provides the authorization for the variable + /// access. It is a signature across the + /// variable data and the Monotonic Count + /// value. Caller uses Private key that is + /// associated with a public key that has been + /// provisioned via the key exchange. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_VARIABLE_AUTHENTICATION; + +/// +/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is +/// set, then the Data buffer shall begin with an instance of a complete (and serialized) +/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new +/// variable value and DataSize shall reflect the combined size of the descriptor and the new +/// variable value. The authentication descriptor is not part of the variable data and is not +/// returned by subsequent calls to GetVariable(). +/// +typedef struct { + /// + /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and + /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT. + /// + EFI_TIME TimeStamp; + /// + /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; + } EFI_VARIABLE_AUTHENTICATION_2; + +#endif diff --git a/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/X64/ProcessorBind.h b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/X64/ProcessorBind.h new file mode 100644 index 0000000000..6744721ac4 --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include/X64/ProcessorBind.h @@ -0,0 +1,298 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel 64, AMD64). + + Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_X64 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) +#pragma pack() +#endif + + +#if defined(__INTEL_COMPILER) +// +// Disable ICC's remark #869: "Parameter" was never referenced warning. +// This is legal ANSI C code so we disable the remark that is turned on with -Wall +// +#pragma warning ( disable : 869 ) + +// +// Disable ICC's remark #1418: external function definition with no prior declaration. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1418 ) + +// +// Disable ICC's remark #1419: external declaration in primary source file +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1419 ) + +// +// Disable ICC's remark #593: "Variable" was set but never used. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 593 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + // + // use Microsoft C complier dependent integer width types + // + + /// + /// 8-byte unsigned value + /// + typedef unsigned __int64 UINT64; + /// + /// 8-byte signed value + /// + typedef __int64 INT64; + /// + /// 4-byte unsigned value + /// + typedef unsigned __int32 UINT32; + /// + /// 4-byte signed value + /// + typedef __int32 INT32; + /// + /// 2-byte unsigned value + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#else + /// + /// 8-byte unsigned value + /// + typedef unsigned long long UINT64; + /// + /// 8-byte signed value + /// + typedef long long INT64; + /// + /// 4-byte unsigned value + /// + typedef unsigned int UINT32; + /// + /// 4-byte signed value + /// + typedef int INT32; + /// + /// 2-byte unsigned value + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT64 UINTN; +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT64 INTN; + + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000ULL +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC000000000000000ULL + +/// +/// Maximum legal x64 address +/// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +/// +/// Maximum legal x64 INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL) + +/// +/// The stack alignment required for x64 +/// +#define CPU_STACK_ALIGNMENT 16 + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#ifdef EFIAPI + /// + /// If EFIAPI is already defined, then we use that definition. + /// +#elif defined(_MSC_EXTENSIONS) + /// + /// Microsoft* compiler specific method for EFIAPI calling convension + /// + #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// Define the standard calling convention reguardless of optimization level. + /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI + /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64) + /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for + /// x64. Warning the assembly code in the MDE x64 does not follow the correct + /// ABI for the standard x64 (x86-64) GCC. + /// + #define EFIAPI +#else + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI +#endif + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On x64 CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif + +#endif + diff --git a/src/vendorcode/intel/edk2/uefi_2.4/uefi_types.h b/src/vendorcode/intel/edk2/uefi_2.4/uefi_types.h new file mode 100644 index 0000000000..9479187f46 --- /dev/null +++ b/src/vendorcode/intel/edk2/uefi_2.4/uefi_types.h @@ -0,0 +1,94 @@ +/** + +Copyright (C) 2013, Intel Corporation + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#ifndef __UEFI_TYPES_H__ +#define __UEFI_TYPES_H__ + +// +// Set the UEFI types and attributes +// +#define __APPLE__ 0 +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// For GNU assembly code, .global or .globl can declare global symbols. +/// Define this macro to unify the usage. +/// +#if defined(ASM_GLOBAL) +#undef ASM_GLOBAL +#endif +#define ASM_GLOBAL .global + +// +// Define the ASSERT support +// +static inline void debug_dead_loop(void) +{ + for (;;) + ; +} + +#define _ASSERT(expression) debug_dead_loop() +#define ASSERT(expression) \ + do { \ + if (!(expression)) { \ + _ASSERT(expression); \ + } \ + } while (FALSE) + +// +// Define the known GUIDs +// +#define FSP_CACHE_AS_RAM_DATA_HOB_GUID \ +{ \ + 0xbbcff46c, 0xc8d3, 0x4113, \ + {0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e} \ +} + +#define FSP_INFO_HEADER_GUID \ +{ \ + 0x912740BE, 0x2284, 0x4734, \ + {0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C} \ +} + +#define FSP_NON_VOLATILE_STORAGE_HOB_GUID \ +{ \ + 0x721acf02, 0x4d77, 0x4c2a, \ + {0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0} \ +} + +#endif /* __UEFI_TYPES_H__*/ diff --git a/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspApi.h b/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspApi.h new file mode 100644 index 0000000000..d889adea12 --- /dev/null +++ b/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspApi.h @@ -0,0 +1,302 @@ +/** @file + Intel FSP API definition from Intel Firmware Support Package External + Architecture Specification, April 2014, revision 001. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _FSP_API_H_ +#define _FSP_API_H_ + +#define FSP_STATUS EFI_STATUS +#define FSPAPI EFIAPI + +/** + FSP Init continuation function prototype. + Control will be returned to this callback function after FspInit API call. + + @param[in] Status Status of the FSP INIT API. + @param[in] HobBufferPtr Pointer to the HOB data structure defined in the PI specification. +**/ +typedef +VOID +(* CONTINUATION_PROC) ( + IN EFI_STATUS Status, + IN VOID *HobListPtr + ); + +#pragma pack(1) + +typedef struct { + /// + /// Base address of the microcode region. + /// + UINT32 MicrocodeRegionBase; + /// + /// Length of the microcode region. + /// + UINT32 MicrocodeRegionLength; + /// + /// Base address of the cacheable flash region. + /// + UINT32 CodeRegionBase; + /// + /// Length of the cacheable flash region. + /// + UINT32 CodeRegionLength; +} FSP_TEMP_RAM_INIT_PARAMS; + +typedef struct { + /// + /// Non-volatile storage buffer pointer. + /// + VOID *NvsBufferPtr; + /// + /// Runtime buffer pointer + /// + VOID *RtBufferPtr; + /// + /// Continuation function address + /// + CONTINUATION_PROC ContinuationFunc; +} FSP_INIT_PARAMS; + +typedef struct { + /// + /// Stack top pointer used by the bootloader. + /// The new stack frame will be set up at this location after FspInit API call. + /// + UINT32 *StackTop; + /// + /// Current system boot mode. + /// + UINT32 BootMode; + /// + /// User platform configuraiton data region pointer. + /// + VOID *UpdDataRgnPtr; + /// + /// Reserved + /// + UINT32 Reserved[7]; +} FSP_INIT_RT_COMMON_BUFFER; + +typedef enum { + /// + /// Notification code for post PCI enuermation + /// + EnumInitPhaseAfterPciEnumeration = 0x20, + /// + /// Notification code before transfering control to the payload + /// + EnumInitPhaseReadyToBoot = 0x40 +} FSP_INIT_PHASE; + +typedef struct { + /// + /// Notification phase used for NotifyPhase API + /// + FSP_INIT_PHASE Phase; +} NOTIFY_PHASE_PARAMS; + +typedef struct { + /// + /// Non-volatile storage buffer pointer. + /// + VOID *NvsBufferPtr; + /// + /// Runtime buffer pointer + /// + VOID *RtBufferPtr; + /// + /// Pointer to the HOB data structure defined in the PI specification + /// + VOID **HobListPtr; +} FSP_MEMORY_INIT_PARAMS; + +#pragma pack() + +/** + This FSP API is called soon after coming out of reset and before memory and stack is + available. This FSP API will load the microcode update, enable code caching for the + region specified by the boot loader and also setup a temporary stack to be used until + main memory is initialized. + + A hardcoded stack can be set up with the following values, and the "esp" register + initialized to point to this hardcoded stack. + 1. The return address where the FSP will return control after setting up a temporary + stack. + 2. A pointer to the input parameter structure + + However, since the stack is in ROM and not writeable, this FSP API cannot be called + using the "call" instruction, but needs to be jumped to. + + @param[in] TempRaminitParamPtr Address pointer to the FSP_TEMP_RAM_INIT_PARAMS structure. + + @retval EFI_SUCCESS Temp RAM was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_NOT_FOUND No valid microcode was found in the microcode region. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR Temp RAM initialization failed. + + If this function is successful, the FSP initializes the ECX and EDX registers to point to + a temporary but writeable memory range available to the boot loader and returns with + FSP_SUCCESS in register EAX. Register ECX points to the start of this temporary + memory range and EDX points to the end of the range. Boot loader is free to use the + whole range described. Typically the boot loader can reload the ESP register to point + to the end of this returned range so that it can be used as a standard stack. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_TEMP_RAM_INIT) ( + IN FSP_TEMP_RAM_INIT_PARAMS *FspTempRamInitPtr + ); + +/** + This FSP API is called after TempRamInitEntry. This FSP API initializes the memory, + the CPU and the chipset to enable normal operation of these devices. This FSP API + accepts a pointer to a data structure that will be platform dependent and defined for + each FSP binary. This will be documented in the Integration Guide for each FSP + release. + The boot loader provides a continuation function as a parameter when calling FspInit. + After FspInit completes its execution, it does not return to the boot loader from where + it was called but instead returns control to the boot loader by calling the continuation + function which is passed to FspInit as an argument. + + @param[in] FspInitParamPtr Address pointer to the FSP_INIT_PARAMS structure. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_INIT) ( + IN OUT FSP_INIT_PARAMS *FspInitParamPtr + ); + +#define FSP_FSP_INIT FSP_INIT + +/** + This FSP API is used to notify the FSP about the different phases in the boot process. + This allows the FSP to take appropriate actions as needed during different initialization + phases. The phases will be platform dependent and will be documented with the FSP + release. The current FSP supports two notify phases: + Post PCI enumeration + Ready To Boot + + @param[in] NotifyPhaseParamPtr Address pointer to the NOTIFY_PHASE_PRAMS + + @retval EFI_SUCCESS The notification was handled successfully. + @retval EFI_UNSUPPORTED The notification was not called in the proper order. + @retval EFI_INVALID_PARAMETER The notification code is invalid. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_NOTIFY_PHASE) ( + IN NOTIFY_PHASE_PARAMS *NotifyPhaseParamPtr + ); + +/** + This FSP API is called after TempRamInit and initializes the memory. + This FSP API accepts a pointer to a data structure that will be platform dependent + and defined for each FSP binary. This will be documented in Integration guide with + each FSP release. + After FspMemInit completes its execution, it passes the pointer to the HobList and + returns to the boot loader from where it was called. Bootloader is responsible to + migrate it's stack and data to Memory. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to + complete the silicon initialization and provides bootloader an opportunity to get + control after system memory is available and before the temporary RAM is torn down. + These APIs are mutually exclusive to the FspInit API. + + @param[in][out] FspMemoryInitParamPtr Address pointer to the FSP_MEMORY_INIT_PARAMS + structure. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_MEMORY_INIT) ( + IN OUT FSP_MEMORY_INIT_PARAMS *FspMemoryInitParamPtr + ); + + +/** + This FSP API is called after FspMemoryInit API. This FSP API tears down the temporary + memory setup by TempRamInit API. This FSP API accepts a pointer to a data structure + that will be platform dependent and defined for each FSP binary. This will be + documented in Integration Guide. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to + complete the silicon initialization and provides bootloader an opportunity to get + control after system memory is available and before the temporary RAM is torn down. + These APIs are mutually exclusive to the FspInit API. + + @param[in][out] TempRamExitParamPtr Pointer to the Temp Ram Exit parameters structure. + This structure is normally defined in the Integration Guide. + And if it is not defined in the Integration Guide, pass NULL. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_TEMP_RAM_EXIT) ( + IN OUT VOID *TempRamExitParamPtr + ); + + +/** + This FSP API is called after TempRamExit API. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to complete the + silicon initialization. + These APIs are mutually exclusive to the FspInit API. + + @param[in][out] FspSiliconInitParamPtr Pointer to the Silicon Init parameters structure. + This structure is normally defined in the Integration Guide. + And if it is not defined in the Integration Guide, pass NULL. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_SILICON_INIT) ( + IN OUT VOID *FspSiliconInitParamPtr + ); + +/// +/// FSP API Return Status Code for backward compatibility with v1.0 +///@{ +#define FSP_SUCCESS EFI_SUCCESS +#define FSP_INVALID_PARAMETER EFI_INVALID_PARAMETER +#define FSP_UNSUPPORTED EFI_UNSUPPORTED +#define FSP_NOT_READY EFI_NOT_READY +#define FSP_DEVICE_ERROR EFI_DEVICE_ERROR +#define FSP_OUT_OF_RESOURCES EFI_OUT_OF_RESOURCES +#define FSP_VOLUME_CORRUPTED EFI_VOLUME_CORRUPTED +#define FSP_NOT_FOUND EFI_NOT_FOUND +#define FSP_TIMEOUT EFI_TIMEOUT +#define FSP_ABORTED EFI_ABORTED +#define FSP_INCOMPATIBLE_VERSION EFI_INCOMPATIBLE_VERSION +#define FSP_SECURITY_VIOLATION EFI_SECURITY_VIOLATION +#define FSP_CRC_ERROR EFI_CRC_ERROR +///@} + +#endif diff --git a/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspInfoHeader.h b/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspInfoHeader.h new file mode 100644 index 0000000000..96b8aaaa7a --- /dev/null +++ b/src/vendorcode/intel/fsp/fsp_1_1/IntelFspPkg/Include/FspInfoHeader.h @@ -0,0 +1,147 @@ +/** @file + Intel FSP Info Header definition from Intel Firmware Support Package External + Architecture Specification, April 2014, revision 001. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _FSP_INFO_HEADER_H_ +#define _FSP_INFO_HEADER_H_ + +#define FSP_HEADER_REVISION_1_0 1 +#define FSP_HEADER_REVISION_1_1 2 + +/// +/// Fixed FSP header offset in the FSP image +/// +#define FSP_INFO_HEADER_OFF 0x94 + +#define OFFSET_IN_FSP_INFO_HEADER(x) (UINT32)&((FSP_INFO_HEADER *)(UINTN)0)->x + +#pragma pack(1) + +typedef struct { + /// + /// Byte 0: Signature ('FSPH') for the FSP Information Header + /// + UINT32 Signature; + /// + /// Byte 4: Length of the FSP Information Header + /// + UINT32 HeaderLength; + /// + /// Byte 8: Reserved + /// + UINT8 Reserved1[3]; + /// + /// Byte 11: Revision of the FSP Information Header + /// + UINT8 HeaderRevision; + /// + /// Byte 12: Revision of the FSP binary + /// + UINT32 ImageRevision; + + + /// + /// Byte 16: Signature string that will help match the FSP Binary to a supported + /// hardware configuration. + /// + CHAR8 ImageId[8]; + /// + /// Byte 24: Size of the entire FSP binary + /// + UINT32 ImageSize; + /// + /// Byte 28: FSP binary preferred base address + /// + UINT32 ImageBase; + + + /// + /// Byte 32: Attribute for the FSP binary + /// + UINT32 ImageAttribute; + /// + /// Byte 36: Offset of the FSP configuration region + /// + UINT32 CfgRegionOffset; + /// + /// Byte 40: Size of the FSP configuration region + /// + UINT32 CfgRegionSize; + /// + /// Byte 44: Number of API entries this FSP supports + /// + UINT32 ApiEntryNum; + + /// + /// Byte 48: The offset for the API to setup a temporary stack till the memory + /// is initialized. + /// + UINT32 TempRamInitEntryOffset; + /// + /// Byte 52: The offset for the API to initialize the CPU and the chipset (SOC) + /// + UINT32 FspInitEntryOffset; + /// + /// Byte 56: The offset for the API to inform the FSP about the different stages + /// in the boot process + /// + UINT32 NotifyPhaseEntryOffset; + /// + /// Reserved + /// + //UINT32 Reserved2; + /// + /// Byte 60: The offset for the API to initialize the memory + /// + UINT32 FspMemoryInitEntryOffset; + /// + /// Byte 64: The offset for the API to tear down temporary RAM + /// + UINT32 TempRamExitEntryOffset; + /// + /// Byte 68: The offset for the API to initialize the CPU and chipset + /// + UINT32 FspSiliconInitEntryOffset; +} FSP_INFO_HEADER; + +typedef struct { + /// + /// Byte 0: Signature ('FSPE') for the FSP Extended Information Header + /// + UINT32 Signature; + /// + /// Byte 4: Length of the FSP Extended Header + /// + UINT32 HeaderLength; + /// + /// Byte 8: Revision of the FSP Extended Header + /// + UINT8 Revision; + /// + /// Byte 9: Reserved for future use. + /// + UINT8 Reserved; + /// + /// Byte 10: An OEM-supplied string that defines the OEM + /// + CHAR8 OemId[6]; + /// + /// Byte 16: An OEM-supplied revision number. Larger numbers are assumed to be newer revisions. + /// + UINT32 OemRevision; + +} FSP_EXTENTED_HEADER; +#pragma pack() + +#endif diff --git a/toolchain.inc b/toolchain.inc new file mode 100644 index 0000000000..fdb7bcb256 --- /dev/null +++ b/toolchain.inc @@ -0,0 +1,128 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2014 Google Inc +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## + +####################################################################### + +ARCH_SUPPORTED := ARM ARM64 X86_32 MIPS + +ARCH_TO_TOOLCHAIN_X86_32 := x86_32 +ARCH_TO_TOOLCHAIN_ARM := arm +ARCH_TO_TOOLCHAIN_ARM64 := arm64 +ARCH_TO_TOOLCHAIN_MIPS := mipsel + +COREBOOT_STANDARD_STAGES := bootblock verstage romstage ramstage + +ARCHDIR-i386 := x86 +ARCHDIR-arm := arm +ARCHDIR-arm64 := arm64 +ARCHDIR-x86_32 := x86 +ARCHDIR-mipsel := mips + +toolchain_to_dir = \ + $(foreach arch,$(ARCH_SUPPORTED),\ + $(eval INCLUDES_$(ARCH_TO_TOOLCHAIN_$(arch)) = \ + -Isrc/arch/$(ARCHDIR-$(ARCH_TO_TOOLCHAIN_$(arch)))/include)) + +# set_stage_toolchain: Decides the toolchain to be used by every stage +# E.g.: If bootblock is x86_32, it sets ARCH-BOOTBLOCK-y = x86_32, whereas +# ARCH-BOOTBLOCK-n = armv7. Then, ARCH-BOOTBLOCK-y can be used anywhere to +# decide the compiler toolchain for bootblock stage +# This step is essential for initializing the toolchain for coreboot standard +# stages i.e. bootblock, romstage and ramstage, since it acts as the second +# parameter to create_class_compiler below in init_standard_toolchain +set_stage_toolchain= \ + $(foreach arch,$(ARCH_SUPPORTED),$(eval ARCH-$(1)-$(CONFIG_ARCH_$(1)_$(arch)) := $(ARCH_TO_TOOLCHAIN_$(arch)))) + + +# create_class_compiler: Used to create compiler tool set for +# special classes +# @1: special class +# @2: compiler set to be used +# e.g.: smm special class uses i386 as compiler set +define create_class_compiler +CC_$(1) := $(CC_$(2)) +LD_$(1) := $(LD_$(2)) +NM_$(1) := $(NM_$(2)) +AR_$(1) := $(AR_$(2)) +OBJCOPY_$(1) := $(OBJCOPY_$(2)) +OBJDUMP_$(1) := $(OBJDUMP_$(2)) +STRIP_$(1) := $(STRIP_$(2)) +READELF_$(1) := $(READELF_$(2)) +INCLUDES_$(1) = $$(INCLUDES) -Isrc/arch/$(ARCHDIR-$(2))/include +CFLAGS_$(1) = $$(CFLAGS_common) $$(INCLUDES_$(1)) $(CFLAGS_$(2)) +LIBGCC_FILE_NAME_$(1) = $(shell test -n "$(CC_$(2))" && \ + test -r `$(CC_$(2)) -print-libgcc-file-name` && \ + $(CC_$(2)) -print-libgcc-file-name) +endef + +# define_class: Allows defining any program as dynamic class and compiler tool +# set for the same based on the architecture for which the program is to be +# compiled +# @1: program (class name) +# @2: architecture for which the program needs to be compiled +# IMP: Ensure that define_class is called before any .c or .S files are added to +# the class of the program. Check subdirs-y for order of subdirectory inclusions +define define_class +classes-y += $(1) +$(eval $(call create_class_compiler,$(1),$(2))) +endef + +# initialize standard toolchain (CC,AS and others) for given stage +# @1 : stage for which the toolchain is to be initialized +init_standard_toolchain = \ + $(eval stage_caps := $(shell printf "%s" $(1) | tr '[:lower:]' '[:upper:]' )) \ + $(eval $(call set_stage_toolchain,$(stage_caps))) \ + $(eval $(call create_class_compiler,$(1),$(ARCH-$(stage_caps)-y))) \ + $(eval $(call set_stage_libgcc,$(1))) + +init_stages = \ + $(foreach stage,$(COREBOOT_STANDARD_STAGES),$(eval $(call init_standard_toolchain,$(stage)))) + +# This mapping is created to have consistency with xcompile naming +$(eval $(call create_class_compiler,x86_32,i386)) +$(eval $(call create_class_compiler,arm64,aarch64)) + +# IMPORTANT: Toolchain variables (CFLAGS_, INCLUDES_) defined by +# create_class_compiler can be updated only after call to create_class_compiler +# is performed. DO NOT move the CFLAGS_* assignment before above call to +# create_class_compiler. + +# About -Wstack-usage: if you arrived here via grep, you were probably trying to +# do something naughty that could've caused boards with 2K stack size to have a +# very bad time somewhere down the road. Since stack overflows are both very +# dangerous and almost impossible to prevent, we're drawing the line at 1.5K +# for a single function frame (with the assumption that you hopefully don't +# chain more than one of that size together). Buffers larger than that should +# be allocated in the BSS (use MAYBE_STATIC if you need to share code with +# __PRE_RAM__ x86). Since GCCs detection of dynamic array bounds unfortunately +# seems to be very basic, you'll sometimes have to use a static upper bound +# for the size and an assert() to make sure it's honored (see gpio_base3_value() +# for an example). (If you absolutely need a larger stack frame and are 100% +# sure it cannot cause problems, you can whitelist it with #pragma diagnostic.) + +CFLAGS_nonx86 += -ffunction-sections -fdata-sections -Wstack-usage=1536 + +CFLAGS_arm += $(CFLAGS_nonx86) + +CFLAGS_arm64 += $(CFLAGS_nonx86) +CFLAGS_mipsel += $(CFLAGS_nonx86) -mips32r2 -G 0 + +$(eval $(call toolchain_to_dir)) + +$(eval $(call init_stages)) diff --git a/util/abuild/abuild b/util/abuild/abuild index 1c69eec581..bcd1327baa 100755 --- a/util/abuild/abuild +++ b/util/abuild/abuild @@ -58,9 +58,6 @@ silent= # clang mode enabled by -sb option. scanbuild=false -# stackprotect mode enabled by -ns option. -stackprotect=false - ARCH=`uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/i86pc/i386/ \ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ \ @@ -304,22 +301,6 @@ function build_target return fi - # default setting - - CC="${CROSS_COMPILE}gcc" - CROSS_COMPILE="" - found_crosscompiler=false - if which $TARCH-elf-gcc 2>/dev/null >/dev/null; then - # i386-elf target needs --divide, for i386-linux, that's the default - if [ "$TARCH" = "i386" ]; then - CC="$CC -Wa,--divide" - fi - CROSS_COMPILE="$TARCH-elf-" - CC=gcc - CROSS_TEXT=", using $CROSS_COMPILE$CC" - found_crosscompiler=true - fi - HOSTCC='gcc' printf "Building $VENDOR/$MAINBOARD; " @@ -334,67 +315,6 @@ function build_target xml " $TARCH" xml "" - if [ "$ARCH" = "$TARCH" -o $found_crosscompiler = true ]; then - printf "$TARCH: ok$CROSS_TEXT\n" - else - # FIXME this is basically the same as above. - found_crosscompiler=false - if [ "$ARCH" == amd64 -a "$TARCH" == i386 ]; then - CC="gcc -m32" - found_crosscompiler=true - fi - if [ "$ARCH" == ppc64 -a "$TARCH" == ppc ]; then - CC="gcc -m32" - found_crosscompiler=true - fi - if [ "$found_crosscompiler" == "false" -a "$TARCH" == ppc ];then - for prefix in powerpc-eabi- powerpc-linux- ppc_74xx- \ - powerpc-7450-linux-gnu- powerpc-elf-; do - if ${prefix}gcc --version > /dev/null 2> /dev/null ; then - found_crosscompiler=true - CROSS_COMPILE=$prefix - fi - done - fi - if [ "$found_crosscompiler" == "false" -a "$TARCH" == ARMV7 ];then - for prefix in armv7a-eabi- armv7a-cros-linux-gnueabi-; do - if ${prefix}gcc --version > /dev/null 2> /dev/null ; then - found_crosscompiler=true - CROSS_COMPILE=$prefix - fi - done - fi - - # TBD: look for suitable cross compiler suite - # cross-$TARCH-gcc and cross-$TARCH-ld - - # Check result: - if [ $found_crosscompiler == "false" ]; then - printf "$TARCH: skipped, we're $ARCH\n\n" - xml " notbuilt" - xml "" - xml "
" - - junit "" - junit " No cross-compiler for $TARCH found" - junit "" - - return 0 - else - printf "$TARCH: ok, $ARCH using ${CROSS_COMPILE}gcc\n" - xml " " - xml " `which ${CROSS_COMPILE}gcc`" - xml " `${CROSS_COMPILE}gcc --version | head -1`" - xml " " - xml "" - fi - fi - - CC=${CROSS_COMPILE}$CC - - if [ "$stackprotect" = "true" ]; then - CC="$CC -fno-stack-protector" - fi stime=`perl -e 'print time();' 2>/dev/null || date +%s` create_buildenv $VENDOR $MAINBOARD $CONFIG @@ -501,7 +421,6 @@ function myhelp printf " [-T|--test] submit image(s) to automated test system\n" printf " [-c|--cpus ] build on at the same time\n" printf " [-s|--silent] omit compiler calls in logs\n" - printf " [-ns|--nostackprotect] use gcc -fno-stack-protector option\n" printf " [-sb|--scan-build] use clang's static analyzer\n" printf " [-y|--ccache] use ccache\n" printf " [-C|--config] configure-only mode\n" @@ -549,7 +468,7 @@ cmdline="$* -c 1" getoptbrand="`getopt -V`" if [ "${getoptbrand:0:6}" == "getopt" ]; then # Detected GNU getopt that supports long options. - args=`getopt -l version,verbose,help,all,target:,payloads:,test,cpus:,silent,junit,xml,config,loglevel:,remove,prefix:,update,nostackprotect,scan-build,ccache,blobs -o Vvhat:p:Tc:sJxCl:rP:uyB -- "$@"` || exit 1 + args=`getopt -l version,verbose,help,all,target:,payloads:,test,cpus:,silent,junit,xml,config,loglevel:,remove,prefix:,update,scan-build,ccache,blobs -o Vvhat:p:Tc:sJxCl:rP:uyB -- "$@"` || exit 1 eval set -- $args else # Detected non-GNU getopt @@ -583,7 +502,6 @@ while true ; do expr "$1" : '-\?[0-9]\+$' > /dev/null && test 0$1 -gt 1 && cpuconfig="on $1 cpus in parallel" shift;; -s|--silent) shift; silent="-s";; - -ns|--nostackprotect) shift; stackprotect=true;; -sb|--scan-build) shift scanbuild=true customizing="${customizing}, scan-build" diff --git a/util/bimgtool/Makefile b/util/bimgtool/Makefile new file mode 100644 index 0000000000..3bd0f07a7d --- /dev/null +++ b/util/bimgtool/Makefile @@ -0,0 +1,17 @@ +obj ?= $(shell pwd) + +HOSTCC ?= gcc +CFLAGS ?= -g +CFLAGS += -D_7ZIP_ST +CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes +CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs +CFLAGS += -Wstrict-aliasing -Wshadow -Werror +LDFLAGS += -g + +all: dep $(obj)/bimgtool + +clean: + rm -f $(obj)/bimgtool + +$(obj)/bimgtool: bimgtool.c + $(HOSTCC) $(CFLAGS) -o $@ $^ diff --git a/util/bimgtool/bimgtool.c b/util/bimgtool/bimgtool.c new file mode 100644 index 0000000000..9b87b1dd79 --- /dev/null +++ b/util/bimgtool/bimgtool.c @@ -0,0 +1,432 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +struct bimg_header { + uint32_t magic; + uint16_t ver_major; + uint16_t ver_minor; + uint32_t data_size; + uint32_t entry_addr; + uint32_t flags; + uint32_t data_crc; + uint32_t crc; +} __attribute__((packed)); + +struct bimg_data_header { + uint32_t size; + uint32_t dest_addr; + uint16_t dummy; + uint16_t crc; +} __attribute__((packed)); + +struct crc_t { + uint16_t (*crc_f)(uint16_t crc, void *void_buf, size_t size); + uint32_t crc_init; + uint16_t ver_major; + uint16_t ver_minor; +}; + + +#define BIMG_MAGIC /* y */ 0xabbadaba /* doo! */ + +#define BIMG_OP_MASK (0xf << 0) +#define BIMG_OP_EXEC_RETURN (0x1 << 0) +#define BIMG_OP_EXEC_NO_RETURN (0x2 << 0) +#define BIMG_DATA_CHECKSUM (0x1 << 4) + +/* Typical use case for this utility. */ +#define BIMG_FLAGS (BIMG_OP_EXEC_NO_RETURN | BIMG_DATA_CHECKSUM) + +#define MAX_RECORD_BYTES 0x8000 + +#define CRC_16 + +#define error(msg...) fprintf(stderr, "ERROR: " msg) + +#define error_ret(ret, msg...) { \ + error(msg); \ + return ret; \ +} + +static uint16_t crc_x25(uint16_t crc, void *void_buf, size_t size) +{ + static const uint16_t crc_table[16] = { + 0x0000, 0x1021, 0x2042, 0x3063, + 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, + 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + }; + uint8_t *buf, data; + + for (buf = void_buf; size; size--) { + data = *buf++; + crc = (crc << 4) ^ crc_table[((crc >> 12) ^ (data >> 4)) & 0xf]; + crc = (crc << 4) ^ crc_table[((crc >> 12) ^ (data >> 0)) & 0xf]; + } + + return crc; +} + +static uint16_t crc_16(uint16_t crc, void *void_buf, size_t size) +{ + /* + * CRC table for the CRC-16. + * The poly is 0x8005 (x^16 + x^15 + x^2 + 1) + */ + static const uint16_t crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 + }; + uint8_t *buf, data; + + for (buf = void_buf; size; size--) { + data = *buf++; + crc = (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; + } + + return crc; + +} + +static const struct crc_t crc_type = { +#if defined(CRC_16) + .crc_f = crc_16, + .crc_init = 0, + .ver_major = 2, + .ver_minor = 0 +#elif defined(CRC_X25) + .crc_f = crc_x25, + .crc_init = 0xffff, + .ver_major = 1, + .ver_minor = 0 +#endif +}; + +static int write_binary(FILE *out, FILE *in, struct bimg_header *hdr) +{ + static uint8_t file_buf[MAX_RECORD_BYTES]; + struct bimg_data_header data_hdr; + size_t n_written; + + data_hdr.dest_addr = hdr->entry_addr; + + /* + * The read binary data has to be split in chunks of max 64KB-1 bytes + * (SPI controller limitation). Each chunk will have its own header in + * order to respect the BIMG format. + */ + while ((data_hdr.size = fread(file_buf, 1, sizeof(file_buf), in))) { + data_hdr.crc = crc_type.crc_f(crc_type.crc_init, &data_hdr, + sizeof(data_hdr) - sizeof(data_hdr.crc)); + + if (fwrite(&data_hdr, sizeof(data_hdr), 1, out) != 1) + error_ret(-EIO, "Failed to write data header: %d\n", + errno); + + n_written = fwrite(file_buf, 1, data_hdr.size, out); + if (n_written != data_hdr.size) + error_ret(-EIO, "Failed to write to output file: %d\n", + errno); + + data_hdr.dest_addr += n_written; + hdr->data_size += sizeof(data_hdr) + n_written; + hdr->data_crc = crc_type.crc_f(hdr->data_crc, + file_buf, n_written); + } + + if (ferror(in)) + error_ret(-EIO, "Failed to read input file\n"); + + return 0; +} + +static int write_final(FILE *out, struct bimg_header *hdr) +{ + struct bimg_data_header data_hdr = { + .size = 0, + .dest_addr = ~0, + }; + + data_hdr.crc = crc_type.crc_f(crc_type.crc_init, &data_hdr, + sizeof(data_hdr) - sizeof(data_hdr.crc)); + + if (fwrite(&data_hdr, sizeof(data_hdr), 1, out) != 1) + error_ret(-EIO, "Failed to write data header: %d\n", errno); + + hdr->data_size += sizeof(data_hdr); + + return 0; +} + +static const char *help_message = + "Usage: bimgtool [ ]\n" + "\n" + "This is a simple tool which generates and verifies boot images in\n" + "the BIMG format, used in systems designed by Imagination\n" + "Technologies, for example the Pistachio SoC. This version of the\n" + "tool works with BIMG images version %d.\n" + "\n" + " input: The binary file to be converted to a BIMG\n" + " or verified\n" + " output: The name of the output BIMG file\n" + " base-address: The address in memory at which you wish the " + " input binary to be loaded.\n"; + +static void usage(FILE *f) +{ + fprintf(f, help_message, crc_type.ver_major); +} + +static int verify_file(FILE *f) +{ + struct bimg_header file_header; + struct bimg_data_header data_header; + char *file_pointer; + char *file_data; + struct stat buf; + int data_size; + int fd = fileno(f); + uint32_t data_crc = crc_type.crc_init; + uint32_t crc_result; + + if (fread(&file_header, 1, sizeof(struct bimg_header), f) != + sizeof(struct bimg_header)) { + perror("Problems trying to read input file header\n"); + return -1; + } + + if (fstat(fd, &buf)) { + perror("Problems trying to stat input file\n"); + return -1; + } + + if (file_header.magic != BIMG_MAGIC) { + fprintf(stderr, "Wrong magic value %#x\n", file_header.magic); + return -1; + } + + crc_result = crc_type.crc_f(crc_type.crc_init, &file_header, + sizeof(file_header) - + sizeof(file_header.crc)); + if (file_header.crc != crc_result) { + fprintf(stderr, "File header CRC mismatch\n"); + return -1; + } + + if ((file_header.data_size + sizeof(struct bimg_header)) > + buf.st_size) { + fprintf(stderr, "Data size too big: %d > %d\n", + file_header.data_size, buf.st_size); + return -1; + } + + if (file_header.ver_major != crc_type.ver_major) { + fprintf(stderr, "Image version mismatch: %d\n", + file_header.ver_major); + return -1; + } + + if ((file_header.flags & BIMG_FLAGS) != BIMG_FLAGS) { + fprintf(stderr, "Unexpected file header flags: %#x\n", + file_header.flags); + return -1; + } + + if (file_header.ver_minor != crc_type.ver_minor) { + fprintf(stderr, + "Minor version mismatch: %d, will try anyways\n", + file_header.ver_minor); + } + + data_size = file_header.data_size; + file_pointer = malloc(data_size); + if (!file_pointer) { + fprintf(stderr, "Failed to allocate %d bytes\n", + file_header.data_size); + return -1; + } + + if (fread(file_pointer, 1, data_size, f) != data_size) { + fprintf(stderr, "Failed to read %d bytes\n", data_size); + free(file_pointer); + return -1; + } + + file_data = file_pointer; + while (data_size > 0) { + memcpy(&data_header, file_data, sizeof(data_header)); + + /* Check the data block header integrity. */ + crc_result = crc_type.crc_f(crc_type.crc_init, &data_header, + sizeof(data_header) - + sizeof(data_header.crc)); + if (data_header.crc != crc_result) { + fprintf(stderr, "Data header CRC mismatch at %d\n", + file_header.data_size - data_size); + free(file_pointer); + return -1; + } + + /* + * Add the block data to the CRC stream, the last block size + * will be zero. + */ + file_data += sizeof(data_header); + data_crc = crc_type.crc_f(data_crc, + file_data, data_header.size); + + data_size -= data_header.size + sizeof(data_header); + file_data += data_header.size; + } + + if (data_size) { + fprintf(stderr, "File size mismatch\n"); + free(file_pointer); + return -1; + } + + if (data_crc != file_header.data_crc) { + fprintf(stderr, "File data CRC mismatch\n"); + free(file_pointer); + return -1; + } + + free(file_pointer); + return 0; +} + +int main(int argc, char *argv[]) +{ + const char *in_filename, *out_filename; + FILE *in_file, *out_file; + int err; + struct bimg_header hdr = { + .magic = BIMG_MAGIC, + .ver_major = crc_type.ver_major, + .ver_minor = crc_type.ver_minor, + .flags = BIMG_FLAGS, + .data_crc = crc_type.crc_init, + }; + + if ((argc != 4) && (argc != 2)) { + usage(stderr); + goto out_err; + } + + in_filename = argv[1]; + + in_file = fopen(in_filename, "r"); + if (!in_file) { + error("Failed to open input file '%s'\n", in_filename); + goto out_err; + } + + if (argc == 2) + return verify_file(in_file); + + out_filename = argv[2]; + hdr.entry_addr = strtoul(argv[3], NULL, 16); + + out_file = fopen(out_filename, "w"); + if (!out_file) { + error("Failed to open output file '%s'\n", out_filename); + goto out_err_close_in; + } + + if (fseek(out_file, sizeof(hdr), SEEK_SET)) { + error("Failed to seek past header: %d\n", errno); + goto out_err_close_out; + } + + err = write_binary(out_file, in_file, &hdr); + if (err) { + error("Failed to write binary: %d\n", err); + goto out_err_close_out; + } + + err = write_final(out_file, &hdr); + if (err) { + error("Failed to write final record: %d\n", err); + goto out_err_close_out; + } + + hdr.crc = crc_type.crc_f(crc_type.crc_init, &hdr, + sizeof(hdr) - sizeof(hdr.crc)); + + if (fseek(out_file, 0, SEEK_SET)) { + error("Failed to seek to header: %d\n", errno); + goto out_err_close_out; + } + + if (fwrite(&hdr, sizeof(hdr), 1, out_file) != 1) { + error("Failed to write header: %d\n", errno); + goto out_err_close_out; + } + + fclose(in_file); + fclose(out_file); + return EXIT_SUCCESS; + +out_err_close_out: + fclose(out_file); +out_err_close_in: + fclose(in_file); +out_err: + return EXIT_FAILURE; +} diff --git a/util/cbfstool/Makefile b/util/cbfstool/Makefile index a0de08d2f7..fd08c56833 100644 --- a/util/cbfstool/Makefile +++ b/util/cbfstool/Makefile @@ -1,31 +1,46 @@ obj ?= $(shell pwd) -HOSTCC ?= gcc -CFLAGS ?= -g -Wall -Werror -CFLAGS += -D_7ZIP_ST +HOSTCC ?= gcc +CFLAGS ?= -g +CFLAGS += -D_7ZIP_ST +CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes +CFLAGS += -Wwrite-strings -Wredundant-decls -Wno-trigraphs +CFLAGS += -Wstrict-aliasing -Wshadow -Werror +LDFLAGS += -g -BINARY:=$(obj)/cbfstool +CBFSTOOL_BINARY:=$(obj)/cbfstool -COMMON:=cbfstool.o common.o cbfs_image.o compress.o fit.o -COMMON+=cbfs-mkstage.o cbfs-mkpayload.o +CBFSTOOL_COMMON:=cbfstool.o common.o cbfs_image.o compress.o fit.o +CBFSTOOL_COMMON+=elfheaders.o cbfs-mkstage.o cbfs-mkpayload.o xdr.o # LZMA -COMMON+=lzma/lzma.o -COMMON+=lzma/C/LzFind.o lzma/C/LzmaDec.o lzma/C/LzmaEnc.o +CBFSTOOL_COMMON+=lzma/lzma.o +CBFSTOOL_COMMON+=lzma/C/LzFind.o lzma/C/LzmaDec.o lzma/C/LzmaEnc.o -COMMON:=$(addprefix $(obj)/,$(COMMON)) +CBFSTOOL_COMMON+=linux_trampoline.o cbfs-payload-linux.o -all: dep $(BINARY) +CBFSTOOL_COMMON:=$(addprefix $(obj)/,$(CBFSTOOL_COMMON)) + +RMODTOOL_BINARY:=$(obj)/rmodtool +RMODTOOL_COMMON:=rmodtool.o rmodule.o common.o elfheaders.o xdr.o + +RMODTOOL_COMMON:=$(addprefix $(obj)/,$(RMODTOOL_COMMON)) + +all: dep $(CBFSTOOL_BINARY) $(RMODTOOL_BINARY) $(obj)/%.o: %.c $(HOSTCC) $(CFLAGS) -c -o $@ $< clean: - rm -f $(COMMON) $(BINARY) + rm -f $(CBFSTOOL_COMMON) $(CBFSTOOL_BINARY) + rm -f $(RMODTOOL_COMMON) $(RMODTOOL_BINARY) tags: ctags *.[ch] -$(obj)/cbfstool:$(COMMON) +$(obj)/cbfstool:$(CBFSTOOL_COMMON) + $(HOSTCC) $(CFLAGS) -o $@ $^ + +$(obj)/rmodtool:$(RMODTOOL_COMMON) $(HOSTCC) $(CFLAGS) -o $@ $^ dep: diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index 970620d783..616e0166c5 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -5,17 +5,28 @@ cbfsobj += compress.o cbfsobj += cbfs_image.o cbfsobj += cbfs-mkstage.o cbfsobj += cbfs-mkpayload.o +cbfsobj += elfheaders.o +cbfsobj += xdr.o cbfsobj += fit.o # LZMA cbfsobj += lzma.o cbfsobj += LzFind.o cbfsobj += LzmaDec.o cbfsobj += LzmaEnc.o +# linux as payload +cbfsobj += linux_trampoline.o +cbfsobj += cbfs-payload-linux.o -CBFSTOOLFLAGS=-D_7ZIP_ST -g +rmodobj += rmodtool.o +rmodobj += rmodule.o +rmodobj += common.o +rmodobj += elfheaders.o +rmodobj += xdr.o + +TOOLFLAGS=-D_7ZIP_ST -g ifeq ($(shell uname -s | cut -c-7 2>/dev/null), MINGW32) -CBFSTOOLFLAGS+=-mno-ms-bitfields +TOOLFLAGS+=-mno-ms-bitfields endif $(objutil)/cbfstool: @@ -23,17 +34,21 @@ $(objutil)/cbfstool: $(objutil)/cbfstool/%.o: $(top)/util/cbfstool/%.c printf " HOSTCC $(subst $(objutil)/,,$(@))\n" - $(HOSTCC) $(CBFSTOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< + $(HOSTCC) $(TOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< $(objutil)/cbfstool/%.o: $(top)/util/cbfstool/lzma/%.c printf " HOSTCC $(subst $(objutil)/,,$(@))\n" - $(HOSTCC) $(CBFSTOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< + $(HOSTCC) $(TOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< $(objutil)/cbfstool/%.o: $(top)/util/cbfstool/lzma/C/%.c printf " HOSTCC $(subst $(objutil)/,,$(@))\n" - $(HOSTCC) $(CBFSTOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< + $(HOSTCC) $(TOOLFLAGS) $(HOSTCFLAGS) -c -o $@ $< $(objutil)/cbfstool/cbfstool: $(objutil)/cbfstool $(addprefix $(objutil)/cbfstool/,$(cbfsobj)) printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" - $(HOSTCC) $(CBFSTOOLFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(cbfsobj)) + $(HOSTCC) $(TOOLFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(cbfsobj)) + +$(objutil)/cbfstool/rmodtool: $(objutil)/cbfstool $(addprefix $(objutil)/cbfstool/,$(rmodobj)) + printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" + $(HOSTCC) $(TOOLFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(rmodobj)) diff --git a/util/cbfstool/cbfs-mkpayload.c b/util/cbfstool/cbfs-mkpayload.c index 9f3dabf40f..d9e543004a 100644 --- a/util/cbfstool/cbfs-mkpayload.c +++ b/util/cbfstool/cbfs-mkpayload.c @@ -23,18 +23,39 @@ #include #include +#include "elfparsing.h" #include "common.h" #include "cbfs.h" -#include "elf.h" #include "fv.h" #include "coff.h" +/* serialize the seg array into the buffer. + * The buffer is assumed to be large enough. + */ +static void xdr_segs(struct buffer *output, + struct cbfs_payload_segment *segs, int nseg) +{ + struct buffer outheader; + int i; + + outheader.data = output->data; + outheader.size = 0; + + for(i = 0; i < nseg; i++){ + xdr_be.put32(&outheader, segs[i].type); + xdr_be.put32(&outheader, segs[i].compression); + xdr_be.put32(&outheader, segs[i].offset); + xdr_be.put64(&outheader, segs[i].load_addr); + xdr_be.put32(&outheader, segs[i].len); + xdr_be.put32(&outheader, segs[i].mem_len); + } +} int parse_elf_to_payload(const struct buffer *input, struct buffer *output, comp_algo algo) { - Elf32_Phdr *phdr; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)input->data; - Elf32_Shdr *shdr; + Elf64_Phdr *phdr; + Elf64_Ehdr ehdr; + Elf64_Shdr *shdr; char *header; char *strtab; int headers; @@ -44,39 +65,26 @@ int parse_elf_to_payload(const struct buffer *input, struct cbfs_payload_segment *segs; int i; - if(!iself((unsigned char *)input->data)){ - INFO("The payload file is not in ELF format!\n"); - return -1; - } - - // The tool may work in architecture-independent way. - if (arch != CBFS_ARCHITECTURE_UNKNOWN && - !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && - !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) { - ERROR("The payload file has the wrong architecture\n"); - return -1; - } - comp_func_ptr compress = compression_function(algo); if (!compress) return -1; + if (elf_headers(input, &ehdr, &phdr, &shdr) < 0) + return -1; + DEBUG("start: parse_elf_to_payload\n"); - headers = ehdr->e_phnum; - header = (char *)ehdr; + headers = ehdr.e_phnum; + header = input->data; - phdr = (Elf32_Phdr *) & (header[ehdr->e_phoff]); - shdr = (Elf32_Shdr *) & (header[ehdr->e_shoff]); - - strtab = &header[shdr[ehdr->e_shstrndx].sh_offset]; + strtab = &header[shdr[ehdr.e_shstrndx].sh_offset]; /* Count the number of headers - look for the .notes.pinfo * section */ - for (i = 0; i < ehdr->e_shnum; i++) { + for (i = 0; i < ehdr.e_shnum; i++) { char *name; - if (i == ehdr->e_shstrndx) + if (i == ehdr.e_shstrndx) continue; if (shdr[i].sh_size == 0) @@ -106,29 +114,39 @@ int parse_elf_to_payload(const struct buffer *input, segments++; } - + /* allocate the segment header array */ + segs = calloc(segments, sizeof(*segs)); + if (segs == NULL) + return -1; /* Allocate a block of memory to store the data in */ if (buffer_create(output, (segments * sizeof(*segs)) + isize, input->name) != 0) return -1; memset(output->data, 0, output->size); - doffset = (segments * sizeof(struct cbfs_payload_segment)); + doffset = (segments * sizeof(*segs)); - segs = (struct cbfs_payload_segment *)output->data; + /* set up for output marshaling. This is a bit + * tricky as we are marshaling the headers at the front, + * and the data starting after the headers. We need to convert + * the headers to the right format but the data + * passes through unchanged. Unlike most XDR code, + * we are doing these two concurrently. The doffset is + * used to compute the address for the raw data, and the + * outheader is used to marshal the headers. To make it simpler + * for The Reader, we set up the headers in a separate array, + * then marshal them all at once to the output. + */ segments = 0; - for (i = 0; i < ehdr->e_shnum; i++) { + for (i = 0; i < ehdr.e_shnum; i++) { char *name; - - if (i == ehdr->e_shstrndx) + if (i == ehdr.e_shstrndx) continue; if (shdr[i].sh_size == 0) continue; - name = (char *)(strtab + shdr[i].sh_name); - if (!strcmp(name, ".note.pinfo")) { segs[segments].type = PAYLOAD_SEGMENT_PARAMS; segs[segments].load_addr = 0; @@ -148,17 +166,13 @@ int parse_elf_to_payload(const struct buffer *input, for (i = 0; i < headers; i++) { if (phdr[i].p_type != PT_LOAD) continue; - if (phdr[i].p_memsz == 0) continue; - if (phdr[i].p_filesz == 0) { segs[segments].type = PAYLOAD_SEGMENT_BSS; - segs[segments].load_addr = - (uint64_t)htonll(phdr[i].p_paddr); - segs[segments].mem_len = - (uint32_t)htonl(phdr[i].p_memsz); - segs[segments].offset = htonl(doffset); + segs[segments].load_addr = phdr[i].p_paddr; + segs[segments].mem_len = phdr[i].p_memsz; + segs[segments].offset = doffset; segments++; continue; @@ -168,37 +182,39 @@ int parse_elf_to_payload(const struct buffer *input, segs[segments].type = PAYLOAD_SEGMENT_CODE; else segs[segments].type = PAYLOAD_SEGMENT_DATA; - segs[segments].load_addr = (uint64_t)htonll(phdr[i].p_paddr); - segs[segments].mem_len = (uint32_t)htonl(phdr[i].p_memsz); - segs[segments].compression = htonl(algo); - segs[segments].offset = htonl(doffset); + segs[segments].load_addr = phdr[i].p_paddr; + segs[segments].mem_len = phdr[i].p_memsz; + segs[segments].offset = doffset; + + /* If the compression failed or made the section is larger, + use the original stuff */ int len; - compress((char *)&header[phdr[i].p_offset], - phdr[i].p_filesz, output->data + doffset, &len); - segs[segments].len = htonl(len); - - /* If the compressed section is larger, then use the - original stuff */ - - if ((unsigned int)len > phdr[i].p_filesz) { + if (compress((char *)&header[phdr[i].p_offset], + phdr[i].p_filesz, output->data + doffset, &len) || + (unsigned int)len > phdr[i].p_filesz) { + WARN("Compression failed or would make the data bigger " + "- disabled.\n"); segs[segments].compression = 0; - segs[segments].len = htonl(phdr[i].p_filesz); - + segs[segments].len = phdr[i].p_filesz; memcpy(output->data + doffset, &header[phdr[i].p_offset], phdr[i].p_filesz); + } else { + segs[segments].compression = algo; + segs[segments].len = len; } - doffset += ntohl(segs[segments].len); - osize += ntohl(segs[segments].len); + doffset += segs[segments].len; + osize += segs[segments].len; segments++; } segs[segments].type = PAYLOAD_SEGMENT_ENTRY; - segs[segments++].load_addr = htonll(ehdr->e_entry); + segs[segments++].load_addr = ehdr.e_entry; - output->size = (segments * sizeof(struct cbfs_payload_segment)) + osize; + output->size = (segments * sizeof(*segs)) + osize; + xdr_segs(output, segs, segments); return 0; } @@ -209,7 +225,7 @@ int parse_flat_binary_to_payload(const struct buffer *input, comp_algo algo) { comp_func_ptr compress; - struct cbfs_payload_segment *segs; + struct cbfs_payload_segment segs[2]; int doffset, len = 0; compress = compression_function(algo); @@ -217,36 +233,36 @@ int parse_flat_binary_to_payload(const struct buffer *input, return -1; DEBUG("start: parse_flat_binary_to_payload\n"); - if (buffer_create(output, (2 * sizeof(*segs) + input->size), + if (buffer_create(output, (sizeof(segs) + input->size), input->name) != 0) return -1; memset(output->data, 0, output->size); - segs = (struct cbfs_payload_segment *)output->data; doffset = (2 * sizeof(*segs)); /* Prepare code segment */ segs[0].type = PAYLOAD_SEGMENT_CODE; - segs[0].load_addr = htonll(loadaddress); - segs[0].mem_len = htonl(input->size); - segs[0].offset = htonl(doffset); + segs[0].load_addr = loadaddress; + segs[0].mem_len = input->size; + segs[0].offset = doffset; - compress(input->data, input->size, output->data + doffset, &len); - segs[0].compression = htonl(algo); - segs[0].len = htonl(len); - - if ((unsigned int)len >= input->size) { - WARN("Compressing data would make it bigger - disabled.\n"); + if (!compress(input->data, input->size, output->data + doffset, &len) && + (unsigned int)len < input->size) { + segs[0].compression = algo; + segs[0].len = len; + } else { + WARN("Compression failed or would make the data bigger " + "- disabled.\n"); segs[0].compression = 0; - segs[0].len = htonl(input->size); + segs[0].len = input->size; memcpy(output->data + doffset, input->data, input->size); } /* prepare entry point segment */ segs[1].type = PAYLOAD_SEGMENT_ENTRY; - segs[1].load_addr = htonll(entrypoint); - output->size = doffset + ntohl(segs[0].len); - + segs[1].load_addr = entrypoint; + output->size = doffset + segs[0].len; + xdr_segs(output, segs, 2); return 0; } @@ -254,7 +270,7 @@ int parse_fv_to_payload(const struct buffer *input, struct buffer *output, comp_algo algo) { comp_func_ptr compress; - struct cbfs_payload_segment *segs; + struct cbfs_payload_segment segs[2]; int doffset, len = 0; firmware_volume_header_t *fv; ffs_file_header_t *fh; @@ -343,37 +359,37 @@ int parse_fv_to_payload(const struct buffer *input, return -1; } - if (buffer_create(output, (2 * sizeof(*segs) + input->size), + if (buffer_create(output, (sizeof(segs) + input->size), input->name) != 0) return -1; memset(output->data, 0, output->size); - segs = (struct cbfs_payload_segment *)output->data; - doffset = (2 * sizeof(*segs)); + doffset = (sizeof(segs)); /* Prepare code segment */ segs[0].type = PAYLOAD_SEGMENT_CODE; - segs[0].load_addr = htonll(loadaddress); - segs[0].mem_len = htonl(input->size); - segs[0].offset = htonl(doffset); + segs[0].load_addr = loadaddress; + segs[0].mem_len = input->size; + segs[0].offset = doffset; - compress(input->data, input->size, output->data + doffset, &len); - segs[0].compression = htonl(algo); - segs[0].len = htonl(len); - - if ((unsigned int)len >= input->size) { - WARN("Compressing data would make it bigger - disabled.\n"); + if (!compress(input->data, input->size, output->data + doffset, &len) && + (unsigned int)len < input->size) { + segs[0].compression = algo; + segs[0].len = len; + } else { + WARN("Compression failed or would make the data bigger " + "- disabled.\n"); segs[0].compression = 0; - segs[0].len = htonl(input->size); + segs[0].len = input->size; memcpy(output->data + doffset, input->data, input->size); } /* prepare entry point segment */ segs[1].type = PAYLOAD_SEGMENT_ENTRY; - segs[1].load_addr = htonll(entrypoint); - output->size = doffset + ntohl(segs[0].len); - + segs[1].load_addr = entrypoint; + output->size = doffset + segs[0].len; + xdr_segs(output, segs, 2); return 0; } diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c index 4008367d9d..3f0e0029ea 100644 --- a/util/cbfstool/cbfs-mkstage.c +++ b/util/cbfstool/cbfs-mkstage.c @@ -24,94 +24,141 @@ #include #include +#include "elfparsing.h" #include "common.h" #include "cbfs.h" -#include "elf.h" -static unsigned int idemp(unsigned int x) +/* Checks if program segment contains the ignored section */ +static int is_phdr_ignored(Elf64_Phdr *phdr, Elf64_Shdr *shdr) { - return x; + /* If no ignored section, return false. */ + if (shdr == NULL) + return 0; + + Elf64_Addr sh_start = shdr->sh_addr; + Elf64_Addr sh_end = shdr->sh_addr + shdr->sh_size; + Elf64_Addr ph_start = phdr->p_vaddr; + Elf64_Addr ph_end = phdr->p_vaddr + phdr->p_memsz; + + /* Return true only if section occupies whole of segment. */ + if ((sh_start == ph_start) && (sh_end == ph_end)) { + DEBUG("Ignoring program segment at %p\n", (void *)ph_start); + return 1; + } + + /* If shdr intersects phdr at all, its a conflict */ + if (((sh_start >= ph_start) && (sh_start <= ph_end)) || + ((sh_end >= ph_start) && (sh_end <= ph_end))) { + ERROR("Conflicting sections in segment\n"); + exit(1); + } + + /* Program header doesn't need to be ignored. */ + return 0; } -/* This is a wrapper around the swab32() macro to make it - * usable for the current implementation of parse_elf_to_stage() +/* Find section header based on ignored section name */ +static Elf64_Shdr *find_ignored_section_header(struct parsed_elf *pelf, + const char *ignore_section) +{ + int i; + const char *shstrtab; + + /* No section needs to be ignored */ + if (ignore_section == NULL) + return NULL; + + DEBUG("Section to be ignored: %s\n", ignore_section); + + /* Get pointer to string table */ + shstrtab = buffer_get(pelf->strtabs[pelf->ehdr.e_shstrndx]); + + for (i = 0; i < pelf->ehdr.e_shnum; i++) { + Elf64_Shdr *shdr; + const char *section_name; + + shdr = &pelf->shdr[i]; + section_name = &shstrtab[shdr->sh_name]; + + /* If section name matches ignored string, return shdr */ + if (strcmp(section_name, ignore_section) == 0) + return shdr; + } + + /* No section matches ignore string */ + return NULL; +} + +/* returns size of result, or -1 if error. + * Note that, with the new code, this function + * works for all elf files, not just the restricted set. */ -static unsigned int swap32(unsigned int x) -{ - return swab32(x); -} - -unsigned int (*elf32_to_native) (unsigned int) = idemp; - -/* returns size of result, or -1 if error */ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, - comp_algo algo, uint32_t *location) + comp_algo algo, uint32_t *location, + const char *ignore_section) { - Elf32_Phdr *phdr; - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)input->data; - char *header, *buffer; + struct parsed_elf pelf; + Elf64_Phdr *phdr; + Elf64_Ehdr *ehdr; + Elf64_Shdr *shdr_ignored; + char *buffer; + struct buffer outheader; + int ret = -1; int headers; - int i; - struct cbfs_stage *stage; - unsigned int data_start, data_end, mem_end; - - int elf_bigendian = 0; + int i, outlen; + uint32_t data_start, data_end, mem_end; comp_func_ptr compress = compression_function(algo); if (!compress) return -1; DEBUG("start: parse_elf_to_stage(location=0x%x)\n", *location); - if (!iself((unsigned char *)input->data)) { - ERROR("The stage file is not in ELF format!\n"); + + int flags = ELF_PARSE_PHDR | ELF_PARSE_SHDR | ELF_PARSE_STRTAB; + + if (parse_elf(input, &pelf, flags)) { + ERROR("Couldn't parse ELF\n"); return -1; } - // The tool may work in architecture-independent way. - if (arch != CBFS_ARCHITECTURE_UNKNOWN && - !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) && - !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) { - ERROR("The stage file has the wrong architecture\n"); - return -1; - } + ehdr = &pelf.ehdr; + phdr = &pelf.phdr[0]; - if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { - elf_bigendian = 1; - } - if (elf_bigendian != is_big_endian()) { - elf32_to_native = swap32; - } + /* Find the section header corresponding to ignored-section */ + shdr_ignored = find_ignored_section_header(&pelf, ignore_section); + + if (ignore_section && (shdr_ignored == NULL)) + WARN("Ignore section not found\n"); headers = ehdr->e_phnum; - header = (char *)ehdr; - phdr = (Elf32_Phdr *) & header[elf32_to_native(ehdr->e_phoff)]; + /* Ignore the program header containing ignored section */ + for (i = 0; i < headers; i++) { + if (is_phdr_ignored(&phdr[i], shdr_ignored)) + phdr[i].p_type = PT_NULL; + } - /* Now, regular headers - we only care about PT_LOAD headers, - * because thats what we're actually going to load - */ - - data_start = 0xFFFFFFFF; + data_start = ~0; data_end = 0; mem_end = 0; for (i = 0; i < headers; i++) { unsigned int start, mend, rend; - if (elf32_to_native(phdr[i].p_type) != PT_LOAD) + if (phdr[i].p_type != PT_LOAD) continue; /* Empty segments are never interesting */ - if (elf32_to_native(phdr[i].p_memsz) == 0) + if (phdr[i].p_memsz == 0) continue; /* BSS */ - start = elf32_to_native(phdr[i].p_paddr); + start = phdr[i].p_paddr; - mend = start + elf32_to_native(phdr[i].p_memsz); - rend = start + elf32_to_native(phdr[i].p_filesz); + mend = start + phdr[i].p_memsz; + rend = start + phdr[i].p_filesz; if (start < data_start) data_start = start; @@ -128,8 +175,9 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, } if (data_end <= data_start) { - ERROR("data ends before it starts. Make sure the " - "ELF file is correct and resides in ROM space.\n"); + ERROR("data ends (%08lx) before it starts(%08lx). Make sure the " + "ELF file is correct and resides in ROM space.\n", + (unsigned long)data_end, (unsigned long)data_start); exit(1); } @@ -138,7 +186,7 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, if (buffer == NULL) { ERROR("Unable to allocate memory: %m\n"); - return -1; + goto err; } /* Copy the file data into the buffer */ @@ -146,44 +194,83 @@ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, for (i = 0; i < headers; i++) { unsigned int l_start, l_offset = 0; - if (elf32_to_native(phdr[i].p_type) != PT_LOAD) + if (phdr[i].p_type != PT_LOAD) continue; - if (elf32_to_native(phdr[i].p_memsz) == 0) + if (phdr[i].p_memsz == 0) continue; - l_start = elf32_to_native(phdr[i].p_paddr); + l_start = phdr[i].p_paddr; if (l_start < *location) { l_offset = *location - l_start; l_start = *location; } + /* A legal ELF file can have a program header with + * non-zero length but zero-length file size and a + * non-zero offset which, added together, are > than + * input->size (i.e. the total file size). So we need + * to not even test in the case that p_filesz is zero. + */ + if (! phdr[i].p_filesz) + continue; + if (input->size < (phdr[i].p_offset + phdr[i].p_filesz)){ + ERROR("Underflow copying out the segment." + "File has %ld bytes left, segment end is %ld\n", + input->size, phdr[i].p_offset + phdr[i].p_filesz); + goto err; + } memcpy(buffer + (l_start - data_start), - &header[elf32_to_native(phdr[i].p_offset)+l_offset], - elf32_to_native(phdr[i].p_filesz)-l_offset); + &input->data[phdr[i].p_offset + l_offset], + phdr[i].p_filesz - l_offset); } /* Now make the output buffer */ - if (buffer_create(output, sizeof(*stage) + data_end - data_start, + if (buffer_create(output, sizeof(struct cbfs_stage) + data_end - data_start, input->name) != 0) { ERROR("Unable to allocate memory: %m\n"); - return -1; + free(buffer); + goto err; } memset(output->data, 0, output->size); - stage = (struct cbfs_stage *)output->data; - - stage->load = data_start; /* FIXME: htonll */ - stage->memlen = mem_end - data_start; - stage->compression = algo; - stage->entry = ehdr->e_entry; /* FIXME: htonll */ - - compress(buffer, data_end - data_start, (output->data + sizeof(*stage)), - (int *)&stage->len); + /* Compress the data, at which point we'll know information + * to fill out the header. This seems backward but it works because + * - the output header is a known size (not always true in many xdr's) + * - we do need to know the compressed output size first + * If compression fails or makes the data bigger, we'll warn about it + * and use the original data. + */ + if (compress(buffer, data_end - data_start, + (output->data + sizeof(struct cbfs_stage)), + &outlen) < 0 || outlen > data_end - data_start) { + WARN("Compression failed or would make the data bigger " + "- disabled.\n"); + memcpy(output->data + sizeof(struct cbfs_stage), + buffer, data_end - data_start); + algo = CBFS_COMPRESS_NONE; + } free(buffer); + /* Set up for output marshaling. */ + outheader.data = output->data; + outheader.size = 0; + /* N.B. The original plan was that SELF data was B.E. + * but: this is all L.E. + * Maybe we should just change the spec. + */ + xdr_le.put32(&outheader, algo); + xdr_le.put64(&outheader, ehdr->e_entry); + xdr_le.put64(&outheader, data_start); + xdr_le.put32(&outheader, outlen); + xdr_le.put32(&outheader, mem_end - data_start); + if (*location) *location -= sizeof(struct cbfs_stage); - output->size = sizeof(*stage) + stage->len; - return 0; + output->size = sizeof(struct cbfs_stage) + outlen; + ret = 0; + +err: + parsed_elf_destroy(&pelf); + return ret; } diff --git a/util/cbfstool/cbfs-payload-linux.c b/util/cbfstool/cbfs-payload-linux.c new file mode 100644 index 0000000000..545954cc49 --- /dev/null +++ b/util/cbfstool/cbfs-payload-linux.c @@ -0,0 +1,237 @@ +/* + * cbfs-payload-linux + * + * Copyright (C) 2013 Patrick Georgi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +#include "common.h" +#include "cbfs.h" +#include "linux.h" + +/* TODO: + * handle special arguments + * mem= argument - only affects loading decisions (kernel + initrd), not e820 -> build time + * vga= argument (FILO ignores this) + * add support for more parameters to trampoline: + * alt_mem_k, ext_mem_k (not strictly necessary since e820 takes precedence) + * framebuffer/console values + * + * larger work: + * is compress() safe to use in a size constrained buffer? ie. do(es) the + * compression algorithm(s) stop once the compression result reaches input + * size (ie. incompressible data)? + */ +int parse_bzImage_to_payload(const struct buffer *input, + struct buffer *output, const char *initrd_name, + char *cmdline, comp_algo algo) +{ + int cur_len = 0; + int num_segments = 3; /* parameter block, real kernel, and trampoline */ + + comp_func_ptr compress = compression_function(algo); + if (!compress) + return -1; + + unsigned int initrd_base = 64*1024*1024; + unsigned int initrd_size = 0; + void *initrd_data = NULL; + if (initrd_name != NULL) { + /* TODO: load initrd, set initrd_size */ + num_segments++; + FILE *initrd_file = fopen(initrd_name, "rb"); + if (!initrd_file) { + ERROR("could not open initrd.\n"); + return -1; + } + fseek(initrd_file, 0, SEEK_END); + initrd_size = ftell(initrd_file); + fseek(initrd_file, 0, SEEK_SET); + initrd_data = malloc(initrd_size); + if (!initrd_data) { + ERROR("could not allocate memory for initrd.\n"); + return -1; + } + if (fread(initrd_data, initrd_size, 1, initrd_file) != 1) { + ERROR("could not load initrd.\n"); + return -1; + } + fclose(initrd_file); + } + + unsigned int cmdline_size = 0; + if (cmdline != NULL) { + num_segments++; + cmdline_size = strlen(cmdline) + 1; + } + + struct linux_header *hdr = (struct linux_header *)input->data; + unsigned int setup_size = 4 * 512; + if (hdr->setup_sects != 0) { + setup_size = (hdr->setup_sects + 1) * 512; + } + + /* Setup parameter block. Imitate FILO. */ + struct linux_params params; + params.mount_root_rdonly = hdr->root_flags; + params.orig_root_dev = hdr->root_dev; + /* Sensible video defaults. Might be overridden on runtime by coreboot tables. */ + params.orig_video_mode = 3; + params.orig_video_cols = 80; + params.orig_video_lines = 25; + params.orig_video_isVGA = 1; + params.orig_video_points = 16; + + params.loader_type = 0xff; /* Unregistered Linux loader */ + + if (cmdline != NULL) { + if (hdr->protocol_version < 0x202) { + params.cl_magic = CL_MAGIC_VALUE; + params.cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; + } else { + params.cmd_line_ptr = COMMAND_LINE_LOC; + } + } + + unsigned long kernel_base = 0x100000; + if ((hdr->protocol_version >= 0x200) && (!hdr->loadflags & 1)) { + kernel_base = 0x1000; /* zImage kernel */ + } + /* kernel prefers an address, so listen */ + if ((hdr->protocol_version >= 0x20a) && (!(hdr->pref_address >> 32))) { + kernel_base = hdr->pref_address; + } + if (hdr->protocol_version >= 0x205) { + params.relocatable_kernel = hdr->relocatable_kernel; + params.kernel_alignment = hdr->kernel_alignment; + if (hdr->relocatable_kernel != 0) { + /* 16 MB should be way outside coreboot's playground, + * so if possible (relocatable kernel) use that to + * avoid a trampoline copy. */ + kernel_base = ALIGN(16*1024*1024, params.kernel_alignment); + } + } + + /* We have a trampoline and use that, but it can simply use + * this information for its jump to real Linux. */ + params.kernel_start = kernel_base; + + void *kernel_data = input->data + setup_size; + unsigned int kernel_size = input->size - setup_size; + + if (initrd_data != NULL) { + /* TODO: this is a bit of a hack. Linux recommends to store + * initrd near to end-of-mem, but that's hard to do on build + * time. It definitely fails to read the image if it's too + * close to the kernel, so give it some room. + */ + initrd_base = ALIGN(kernel_base + kernel_size, 16*1024*1024); + + params.initrd_start = initrd_base; + params.initrd_size = initrd_size; + } + + struct cbfs_payload_segment *segs; + unsigned long doffset = (num_segments + 1) * sizeof(*segs); + + /* Allocate a block of memory to store the data in */ + int isize = sizeof(params) + kernel_size + cmdline_size + initrd_size; + if (buffer_create(output, doffset + isize, input->name) != 0) + return -1; + memset(output->data, 0, output->size); + + segs = (struct cbfs_payload_segment *)output->data; + + /* parameter block */ + segs[0].type = PAYLOAD_SEGMENT_DATA; + segs[0].load_addr = htonll(LINUX_PARAM_LOC); + segs[0].mem_len = htonl(sizeof(params)); + segs[0].offset = htonl(doffset); + + compress((void*)¶ms, sizeof(params), output->data + doffset, &cur_len); + segs[0].compression = htonl(algo); + segs[0].len = htonl(cur_len); + + doffset += cur_len; + + /* code block */ + segs[1].type = PAYLOAD_SEGMENT_CODE; + segs[1].load_addr = htonll(kernel_base); + segs[1].mem_len = htonl(kernel_size); + segs[1].offset = htonl(doffset); + + compress(kernel_data, kernel_size, output->data + doffset, &cur_len); + segs[1].compression = htonl(algo); + segs[1].len = htonl(cur_len); + + doffset += cur_len; + + /* trampoline */ + extern void *trampoline_start; + extern long trampoline_size; + + unsigned int entrypoint = 0x40000; /* TODO: any better place? */ + + segs[2].type = PAYLOAD_SEGMENT_CODE; + segs[2].load_addr = htonll(entrypoint); + segs[2].mem_len = htonl(trampoline_size); + segs[2].offset = htonl(doffset); + + compress(trampoline_start, trampoline_size, output->data + doffset, &cur_len); + segs[2].compression = htonl(algo); + segs[2].len = htonl(cur_len); + + doffset += cur_len; + + if (cmdline_size > 0) { + /* command line block */ + segs[3].type = PAYLOAD_SEGMENT_DATA; + segs[3].load_addr = htonll(COMMAND_LINE_LOC); + segs[3].mem_len = htonl(cmdline_size); + segs[3].offset = htonl(doffset); + + compress(cmdline, cmdline_size, output->data + doffset, &cur_len); + segs[3].compression = htonl(algo); + segs[3].len = htonl(cur_len); + + doffset += cur_len; + } + + if (initrd_size > 0) { + /* setup block */ + segs[num_segments-1].type = PAYLOAD_SEGMENT_DATA; + segs[num_segments-1].load_addr = htonll(initrd_base); + segs[num_segments-1].mem_len = htonl(initrd_size); + segs[num_segments-1].offset = htonl(doffset); + + compress(initrd_data, initrd_size, output->data + doffset, &cur_len); + segs[num_segments-1].compression = htonl(algo); + segs[num_segments-1].len = htonl(cur_len); + + doffset += cur_len; + } + + /* prepare entry point segment */ + segs[num_segments].type = PAYLOAD_SEGMENT_ENTRY; + segs[num_segments].load_addr = htonll(entrypoint); + output->size = doffset; + + return 0; +} + diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h index 35d0670928..ef44ca80f5 100644 --- a/util/cbfstool/cbfs.h +++ b/util/cbfstool/cbfs.h @@ -21,6 +21,17 @@ #include +/* create a magic number in host-byte order. + * b3 is the high order byte. + * in the coreboot tools, we go with the 32-bit + * magic number convention. + * This was an inline func but that breaks anything + * that uses it in a case statement. + */ + +#define makemagic(b3, b2, b1, b0)\ + (((b3)<<24) | ((b2) << 16) | ((b1) << 8) | (b0)) + #define CBFS_HEADER_MAGIC 0x4F524243 #define CBFS_HEADPTR_ADDR_X86 0xFFFFFFFC #define CBFS_HEADER_VERSION1 0x31313131 @@ -40,7 +51,9 @@ struct cbfs_header { #define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF #define CBFS_ARCHITECTURE_X86 0x00000001 -#define CBFS_ARCHITECTURE_ARMV7 0x00000010 +#define CBFS_ARCHITECTURE_ARM 0x00000010 +#define CBFS_ARCHITECTURE_AARCH64 0x0000aa64 +#define CBFS_ARCHITECTURE_MIPS 0x00000100 #define CBFS_FILE_MAGIC "LARCHIVE" @@ -60,11 +73,11 @@ struct cbfs_stage { uint32_t memlen; } __attribute__ ((packed)); -#define PAYLOAD_SEGMENT_CODE 0x45444F43 -#define PAYLOAD_SEGMENT_DATA 0x41544144 -#define PAYLOAD_SEGMENT_BSS 0x20535342 -#define PAYLOAD_SEGMENT_PARAMS 0x41524150 -#define PAYLOAD_SEGMENT_ENTRY 0x52544E45 +#define PAYLOAD_SEGMENT_CODE makemagic('C', 'O', 'D', 'E') +#define PAYLOAD_SEGMENT_DATA makemagic('D', 'A', 'T', 'A') +#define PAYLOAD_SEGMENT_BSS makemagic(' ', 'B', 'S', 'S') +#define PAYLOAD_SEGMENT_PARAMS makemagic('P', 'A', 'R', 'A') +#define PAYLOAD_SEGMENT_ENTRY makemagic('E', 'N', 'T', 'R') struct cbfs_payload_segment { uint32_t type; @@ -107,10 +120,10 @@ struct cbfs_payload { */ #define CBFS_COMPONENT_NULL 0xFFFFFFFF -int cbfs_file_header(unsigned long physaddr); #define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file)) #define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) ) -struct cbfs_file *cbfs_create_empty_file(uint32_t physaddr, uint32_t size); +/* common.c */ +void cbfs_file_get_header(struct buffer *buf, struct cbfs_file *file); #endif diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 44a9fe8c48..02285039d6 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -62,25 +62,8 @@ static const struct typedesc_t types_cbfs_compression[] = { {0, NULL}, }; -static uint32_t align_up(uint32_t value, uint32_t align) -{ - if (value % align) - value += align - (value % align); - return value; -} - -uint32_t lookup_type_by_name(const struct typedesc_t *desc, const char *name, - uint32_t default_value) -{ - int i; - for (i = 0; desc[i].name; i++) - if (strcmp(desc[i].name, name) == 0) - return desc[i].type; - return default_value; -} - -const char *lookup_name_by_type(const struct typedesc_t *desc, uint32_t type, - const char *default_value) +static const char *lookup_name_by_type(const struct typedesc_t *desc, + uint32_t type, const char *default_value) { int i; for (i = 0; desc[i].name; i++) @@ -89,21 +72,11 @@ const char *lookup_name_by_type(const struct typedesc_t *desc, uint32_t type, return default_value; } -uint32_t get_cbfs_entry_type(const char *name, uint32_t default_value) -{ - return lookup_type_by_name(types_cbfs_entry, name, default_value); -} - -const char *get_cbfs_entry_type_name(uint32_t type) +static const char *get_cbfs_entry_type_name(uint32_t type) { return lookup_name_by_type(types_cbfs_entry, type, "(unknown)"); } -uint32_t get_cbfs_compression(const char *name, uint32_t unknown) -{ - return lookup_type_by_name(types_cbfs_compression, name, unknown); -} - /* CBFS image */ static int cbfs_calculate_file_header_size(const char *name) @@ -138,8 +111,40 @@ static int cbfs_fix_legacy_size(struct cbfs_image *image) return 0; } +void cbfs_put_header(void *dest, struct cbfs_header *header) +{ + struct buffer outheader; + + outheader.data = dest; + outheader.size = 0; + + xdr_be.put32(&outheader, header->magic); + xdr_be.put32(&outheader, header->version); + xdr_be.put32(&outheader, header->romsize); + xdr_be.put32(&outheader, header->bootblocksize); + xdr_be.put32(&outheader, header->align); + xdr_be.put32(&outheader, header->offset); + xdr_be.put32(&outheader, header->architecture); +} + +static void cbfs_decode_payload_segment(struct cbfs_payload_segment *output, + struct cbfs_payload_segment *input) +{ + struct buffer seg = { + .data = (void *)input, + .size = sizeof(*input), + }; + output->type = xdr_be.get32(&seg); + output->compression = xdr_be.get32(&seg); + output->offset = xdr_be.get32(&seg); + output->load_addr = xdr_be.get64(&seg); + output->len = xdr_be.get32(&seg); + output->mem_len = xdr_be.get32(&seg); + assert(seg.size == 0); +} + int cbfs_image_create(struct cbfs_image *image, - uint32_t arch, + uint32_t architecture, size_t size, uint32_t align, struct buffer *bootblock, @@ -147,15 +152,16 @@ int cbfs_image_create(struct cbfs_image *image, int32_t header_offset, int32_t entries_offset) { - struct cbfs_header *header; + struct cbfs_header header; struct cbfs_file *entry; + int32_t *rel_offset; uint32_t cbfs_len; size_t entry_header_len; DEBUG("cbfs_image_create: bootblock=0x%x+0x%zx, " "header=0x%x+0x%zx, entries_offset=0x%x\n", bootblock_offset, bootblock->size, - header_offset, sizeof(*header), entries_offset); + header_offset, sizeof(header), entries_offset); if (buffer_create(&image->buffer, size, "(new)") != 0) return -1; @@ -174,9 +180,6 @@ int cbfs_image_create(struct cbfs_image *image, "header=0x%x, entries_offset=0x%x\n", bootblock_offset, header_offset, entries_offset); - if (align == 0) - align = 64; // default align size. - // Prepare bootblock if (bootblock_offset + bootblock->size > size) { ERROR("Bootblock (0x%x+0x%zx) exceed ROM size (0x%zx)\n", @@ -193,20 +196,28 @@ int cbfs_image_create(struct cbfs_image *image, bootblock->size); // Prepare header - if (header_offset + sizeof(*header) > size) { + if (header_offset + sizeof(header) > size - sizeof(int32_t)) { ERROR("Header (0x%x+0x%zx) exceed ROM size (0x%zx)\n", - header_offset, sizeof(*header), size); + header_offset, sizeof(header), size); return -1; } - header = (struct cbfs_header *)(image->buffer.data + header_offset); - image->header = header; - header->magic = htonl(CBFS_HEADER_MAGIC); - header->version = htonl(CBFS_HEADER_VERSION); - header->romsize = htonl(size); - header->bootblocksize = htonl(bootblock->size); - header->align = htonl(align); - header->offset = htonl(entries_offset); - header->architecture = htonl(arch); + image->header = (struct cbfs_header *)(image->buffer.data + header_offset); + header.magic = CBFS_HEADER_MAGIC; + header.version = CBFS_HEADER_VERSION; + header.romsize = size; + header.bootblocksize = bootblock->size; + header.align = align; + header.offset = entries_offset; + header.architecture = architecture; + cbfs_put_header(image->header, &header); + + // The last 4 byte of the image contain the relative offset from the end + // of the image to the master header as a 32-bit signed integer. x86 + // relies on this also being its (memory-mapped, top-aligned) absolute + // 32-bit address by virtue of how two's complement numbers work. + assert(size % sizeof(int32_t) == 0); + rel_offset = (int32_t *)(image->buffer.data + size - sizeof(int32_t)); + *rel_offset = header_offset - size; // Prepare entries if (align_up(entries_offset, align) != entries_offset) { @@ -222,8 +233,8 @@ int cbfs_image_create(struct cbfs_image *image, } entry = (struct cbfs_file *)(image->buffer.data + entries_offset); // To calculate available length, find - // e = min(bootblock, header, size) where e > entries_offset. - cbfs_len = size; + // e = min(bootblock, header, rel_offset) where e > entries_offset. + cbfs_len = size - sizeof(int32_t); if (bootblock_offset > entries_offset && bootblock_offset < cbfs_len) cbfs_len = bootblock_offset; if (header_offset > entries_offset && header_offset < cbfs_len) @@ -247,6 +258,7 @@ int cbfs_image_from_file(struct cbfs_image *image, const char *filename) cbfs_image_delete(image); return -1; } + arch = ntohl(image->header->architecture); cbfs_fix_legacy_size(image); return 0; @@ -380,6 +392,10 @@ int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, DEBUG("cbfs_add_entry: space at 0x%x+0x%x(%d) bytes\n", addr, addr_next - addr, addr_next - addr); + + /* Will the file fit? Don't yet worry if we have space for a new + * "empty" entry. We take care of that later. + */ if (addr + need_size > addr_next) continue; @@ -399,6 +415,16 @@ int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, entry = cbfs_find_next_entry(image, entry); new_size = (cbfs_get_entry_addr(image, next) - cbfs_get_entry_addr(image, entry)); + + /* Entry was added and no space for new "empty" entry */ + if (new_size < cbfs_calculate_file_header_size("")) { + DEBUG("No need for new \"empty\" entry\n"); + /* No need to increase the size of the just + * stored file to extend to next file. Alignment + * of next file takes care of this. + */ + return 0; + } new_size -= cbfs_calculate_file_header_size(""); DEBUG("new size: %d\n", new_size); cbfs_create_empty_entry(image, entry, new_size, ""); @@ -474,7 +500,7 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name, buffer.data = CBFS_SUBHEADER(entry); buffer.size = ntohl(entry->len); - buffer.name = "(cbfs_export_entry)"; + buffer.name = (char *)"(cbfs_export_entry)"; if (buffer_write_file(&buffer, filename) != 0) { ERROR("Failed to write %s into %s.\n", entry_name, filename); @@ -513,13 +539,14 @@ int cbfs_print_header_info(struct cbfs_image *image) char *name = strdup(image->buffer.name); assert(image && image->header); printf("%s: %zd kB, bootblocksize %d, romsize %d, offset 0x%x\n" - "alignment: %d bytes\n\n", + "alignment: %d bytes, architecture: %s\n\n", basename(name), image->buffer.size / 1024, ntohl(image->header->bootblocksize), ntohl(image->header->romsize), ntohl(image->header->offset), - ntohl(image->header->align)); + ntohl(image->header->align), + arch_to_string(ntohl(image->header->architecture))); free(name); return 0; } @@ -538,34 +565,35 @@ static int cbfs_print_stage_info(struct cbfs_stage *stage, FILE* fp) return 0; } -static int cbfs_print_payload_segment_info(struct cbfs_payload_segment *payload, - FILE *fp) +static int cbfs_print_decoded_payload_segment_info( + struct cbfs_payload_segment *seg, FILE *fp) { - switch(payload->type) { + /* The input (seg) must be already decoded by + * cbfs_decode_payload_segment. + */ + switch (seg->type) { case PAYLOAD_SEGMENT_CODE: case PAYLOAD_SEGMENT_DATA: fprintf(fp, " %s (%s compression, offset: 0x%x, " "load: 0x%" PRIx64 ", length: %d/%d)\n", - (payload->type == PAYLOAD_SEGMENT_CODE ? + (seg->type == PAYLOAD_SEGMENT_CODE ? "code " : "data"), lookup_name_by_type(types_cbfs_compression, - ntohl(payload->compression), + seg->compression, "(unknown)"), - ntohl(payload->offset), - ntohll(payload->load_addr), - ntohl(payload->len), ntohl(payload->mem_len)); + seg->offset, seg->load_addr, seg->len, + seg->mem_len); break; case PAYLOAD_SEGMENT_ENTRY: fprintf(fp, " entry (0x%" PRIx64 ")\n", - ntohll(payload->load_addr)); + seg->load_addr); break; case PAYLOAD_SEGMENT_BSS: fprintf(fp, " BSS (address 0x%016" PRIx64 ", " "length 0x%x)\n", - ntohll(payload->load_addr), - ntohl(payload->len)); + seg->load_addr, seg->len); break; case PAYLOAD_SEGMENT_PARAMS: @@ -575,14 +603,12 @@ static int cbfs_print_payload_segment_info(struct cbfs_payload_segment *payload, default: fprintf(fp, " 0x%x (%s compression, offset: 0x%x, " "load: 0x%" PRIx64 ", length: %d/%d\n", - payload->type, + seg->type, lookup_name_by_type(types_cbfs_compression, - payload->compression, + seg->compression, "(unknown)"), - ntohl(payload->offset), - ntohll(payload->load_addr), - ntohl(payload->len), - ntohl(payload->mem_len)); + seg->offset, seg->load_addr, seg->len, + seg->mem_len); break; } return 0; @@ -628,8 +654,11 @@ int cbfs_print_entry_info(struct cbfs_image *image, struct cbfs_file *entry, payload = (struct cbfs_payload_segment *) CBFS_SUBHEADER(entry); while (payload) { - cbfs_print_payload_segment_info(payload, fp); - if (payload->type == PAYLOAD_SEGMENT_ENTRY) + struct cbfs_payload_segment seg; + cbfs_decode_payload_segment(&seg, payload); + cbfs_print_decoded_payload_segment_info( + &seg, fp); + if (seg.type == PAYLOAD_SEGMENT_ENTRY) break; else payload ++; @@ -712,17 +741,21 @@ struct cbfs_header *cbfs_find_header(char *data, size_t size) { size_t offset; int found = 0; - uint32_t x86sig; + int32_t rel_offset; struct cbfs_header *header, *result = NULL; - // Try x86 style (check signature in bottom) header first. - x86sig = *(uint32_t *)(data + size - sizeof(uint32_t)); - offset = (x86sig + (uint32_t)size); - DEBUG("x86sig: 0x%x, offset: 0x%zx\n", x86sig, offset); + // Try finding relative offset of master header at end of file first. + rel_offset = *(int32_t *)(data + size - sizeof(int32_t)); + offset = size + rel_offset; + DEBUG("relative offset: %#zx(-%#zx), offset: %#zx\n", + (size_t)rel_offset, (size_t)-rel_offset, offset); if (offset >= size - sizeof(*header) || ntohl(((struct cbfs_header *)(data + offset))->magic) != - CBFS_HEADER_MAGIC) + CBFS_HEADER_MAGIC) { + // Some use cases append non-CBFS data to the end of the ROM. + DEBUG("relative offset seems wrong, scanning whole image...\n"); offset = 0; + } for (; offset + sizeof(*header) < size; offset++) { header = (struct cbfs_header *)(data + offset); @@ -733,14 +766,15 @@ struct cbfs_header *cbfs_find_header(char *data, size_t size) // Probably not a real CBFS header? continue; } - found++; - result = header; + if (!found++) + result = header; } - if (found > 1) { - ERROR("multiple (%d) CBFS headers found!\n", + if (found > 1) + // Top-aligned images usually have a working relative offset + // field, so this is more likely to happen on bottom-aligned + // ones (where the first header is the "outermost" one) + WARN("Multiple (%d) CBFS headers found, using the first one.\n", found); - result = NULL; - } return result; } @@ -779,16 +813,6 @@ int cbfs_is_valid_entry(struct cbfs_image *image, struct cbfs_file *entry) sizeof(entry->magic)) == 0); } -int cbfs_init_entry(struct cbfs_file *entry, - struct buffer *buffer) -{ - memset(entry, 0, sizeof(*entry)); - memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic)); - entry->len = htonl(buffer->size); - entry->offset = htonl(sizeof(*entry) + strlen(buffer->name) + 1); - return 0; -} - int cbfs_create_empty_entry(struct cbfs_image *image, struct cbfs_file *entry, size_t len, const char *name) { diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h index 7ad418aee5..74c8f97906 100644 --- a/util/cbfstool/cbfs_image.h +++ b/util/cbfstool/cbfs_image.h @@ -31,6 +31,10 @@ struct cbfs_image { struct cbfs_header *header; }; +/* Given a pointer, serialize the header from host-native byte format + * to cbfs format, i.e. big-endian. */ +void cbfs_put_header(void *dest, struct cbfs_header *header); + /* Creates an empty CBFS image by given size, and description to its content * (bootblock, align, header location, starting offset of CBFS entries. * The output image will contain a valid cbfs_header, with one cbfs_file diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index bd34960555..973ab0ce7b 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -36,12 +36,12 @@ struct command { int (*function) (void); }; -int verbose = 0; static struct param { char *cbfs_name; char *name; char *filename; char *bootblock; + char *ignore_section; uint32_t type; uint32_t baseaddress; uint32_t baseaddress_assigned; @@ -52,10 +52,14 @@ static struct param { uint32_t size; uint32_t alignment; uint32_t pagesize; - uint32_t offset; + uint32_t cbfsoffset; + uint32_t cbfsoffset_assigned; uint32_t top_aligned; int fit_empty_entries; comp_algo algo; + /* for linux payloads */ + char *initrd; + char *cmdline; } param = { /* All variables not listed are initialized as zero. */ .algo = CBFS_COMPRESS_NONE, @@ -68,7 +72,8 @@ static int cbfs_add_component(const char *cbfs_name, const char *name, uint32_t type, uint32_t offset, - convert_buffer_t convert) { + convert_buffer_t convert) +{ struct cbfs_image image; struct buffer buffer; @@ -87,20 +92,21 @@ static int cbfs_add_component(const char *cbfs_name, return 1; } + if (cbfs_image_from_file(&image, cbfs_name) != 0) { + ERROR("Could not load ROM image '%s'.\n", cbfs_name); + return 1; + } + if (buffer_from_file(&buffer, filename) != 0) { ERROR("Could not load file '%s'.\n", filename); + cbfs_image_delete(&image); return 1; } if (convert && convert(&buffer, &offset) != 0) { ERROR("Failed to parse file '%s'.\n", filename); buffer_delete(&buffer); - return 1; - } - - if (cbfs_image_from_file(&image, cbfs_name) != 0) { - ERROR("Could not load ROM image '%s'.\n", cbfs_name); - buffer_delete(&buffer); + cbfs_image_delete(&image); return 1; } @@ -129,9 +135,11 @@ static int cbfs_add_component(const char *cbfs_name, return 0; } -static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) { +static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) +{ struct buffer output; - if (parse_elf_to_stage(buffer, &output, param.algo, offset) != 0) + if (parse_elf_to_stage(buffer, &output, param.algo, offset, + param.ignore_section) != 0) return -1; buffer_delete(buffer); // direct assign, no dupe. @@ -139,7 +147,9 @@ static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) { return 0; } -static int cbfstool_convert_mkpayload(struct buffer *buffer, uint32_t *offset) { +static int cbfstool_convert_mkpayload(struct buffer *buffer, + unused uint32_t *offset) +{ struct buffer output; int ret; /* per default, try and see if payload is an ELF binary */ @@ -149,6 +159,12 @@ static int cbfstool_convert_mkpayload(struct buffer *buffer, uint32_t *offset) { if (ret != 0) ret = parse_fv_to_payload(buffer, &output, param.algo); + + /* If it's neither ELF nor UEFI Fv, try bzImage */ + if (ret != 0) + ret = parse_bzImage_to_payload(buffer, &output, + param.initrd, param.cmdline, param.algo); + /* Not a supported payload type */ if (ret != 0) { ERROR("Not a supported payload type (ELF / FV).\n"); @@ -162,7 +178,8 @@ static int cbfstool_convert_mkpayload(struct buffer *buffer, uint32_t *offset) { } static int cbfstool_convert_mkflatpayload(struct buffer *buffer, - uint32_t *offset) { + unused uint32_t *offset) +{ struct buffer output; if (parse_flat_binary_to_payload(buffer, &output, param.loadaddress, @@ -267,41 +284,59 @@ static int cbfs_create(void) return 1; } - if (!param.bootblock) { - ERROR("You need to specify -B/--bootblock.\n"); - return 1; - } - // TODO Remove arch or pack into param. if (arch == CBFS_ARCHITECTURE_UNKNOWN) { ERROR("You need to specify -m/--machine arch.\n"); return 1; } - if (buffer_from_file(&bootblock, param.bootblock) != 0) { + if (!param.bootblock) { + DEBUG("-B not given, creating image without bootblock.\n"); + buffer_create(&bootblock, 0, "(dummy)"); + } else if (buffer_from_file(&bootblock, param.bootblock)) { return 1; } - // Setup default boot offset and header offset. + if (!param.alignment) + param.alignment = 64; // default CBFS entry alignment + + // Set default offsets. x86, as usual, needs to be a special snowflake. if (!param.baseaddress_assigned) { - // put boot block before end of ROM. - param.baseaddress = param.size - bootblock.size; - DEBUG("bootblock in end of ROM.\n"); + if (arch == CBFS_ARCHITECTURE_X86) { + // Make sure there's at least enough room for rel_offset + param.baseaddress = param.size - ( + bootblock.size > sizeof(int32_t) ? + bootblock.size : sizeof(int32_t)); + DEBUG("x86 -> bootblock lies at end of ROM (%#x).\n", + param.baseaddress); + } else { + param.baseaddress = 0; + DEBUG("bootblock starts at address 0x0.\n"); + } } if (!param.headeroffset_assigned) { - // Put header before bootblock, and make a reference in end of - // bootblock. - param.headeroffset = ( - param.baseaddress - - sizeof(struct cbfs_header)); - if (bootblock.size >= sizeof(uint32_t)) { - // TODO this only works for 32b top-aligned system now... - uint32_t ptr = param.headeroffset - param.size; - uint32_t *sig = (uint32_t *)(bootblock.data + - bootblock.size - - sizeof(ptr)); - *sig = ptr; - DEBUG("CBFS header reference in end of bootblock.\n"); + if (arch == CBFS_ARCHITECTURE_X86) { + param.headeroffset = param.baseaddress - + sizeof(struct cbfs_header); + DEBUG("x86 -> CBFS header before bootblock (%#x).\n", + param.headeroffset); + } else { + param.headeroffset = align_up(param.baseaddress + + bootblock.size, sizeof(uint32_t)); + DEBUG("CBFS header placed behind bootblock (%#x).\n", + param.headeroffset); + } + } + if (!param.cbfsoffset_assigned) { + if (arch == CBFS_ARCHITECTURE_X86) { + param.cbfsoffset = 0; + DEBUG("x86 -> CBFS entries start at address 0x0.\n"); + } else { + param.cbfsoffset = align_up(param.headeroffset + + sizeof(struct cbfs_header), + param.alignment); + DEBUG("CBFS entries start beind master header (%#x).\n", + param.cbfsoffset); } } @@ -312,7 +347,7 @@ static int cbfs_create(void) &bootblock, param.baseaddress, param.headeroffset, - param.offset) != 0) { + param.cbfsoffset) != 0) { ERROR("Failed to create %s.\n", param.cbfs_name); return 1; } @@ -449,8 +484,8 @@ static int cbfs_update_fit(void) static const struct command commands[] = { {"add", "f:n:t:b:vh?", cbfs_add}, - {"add-payload", "f:n:t:c:b:vh?", cbfs_add_payload}, - {"add-stage", "f:n:t:c:b:vh?", cbfs_add_stage}, + {"add-payload", "f:n:t:c:b:vh?C:I:", cbfs_add_payload}, + {"add-stage", "f:n:t:c:b:S:vh?", cbfs_add_stage}, {"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary}, {"remove", "n:vh?", cbfs_remove}, {"create", "s:B:b:H:a:o:m:vh?", cbfs_create}, @@ -461,24 +496,28 @@ static const struct command commands[] = { }; static struct option long_options[] = { - {"name", required_argument, 0, 'n' }, - {"type", required_argument, 0, 't' }, - {"compression", required_argument, 0, 'c' }, - {"base-address", required_argument, 0, 'b' }, - {"load-address", required_argument, 0, 'l' }, - {"top-aligned", required_argument, 0, 'T' }, - {"entry-point", required_argument, 0, 'e' }, - {"size", required_argument, 0, 's' }, - {"bootblock", required_argument, 0, 'B' }, - {"alignment", required_argument, 0, 'a' }, - {"page-size", required_argument, 0, 'P' }, - {"offset", required_argument, 0, 'o' }, - {"file", required_argument, 0, 'f' }, - {"machine", required_argument, 0, 'm' }, - {"empty-fits", required_argument, 0, 'x' }, - {"verbose", no_argument, 0, 'v' }, - {"help", no_argument, 0, 'h' }, - {NULL, 0, 0, 0 } + {"name", required_argument, 0, 'n' }, + {"type", required_argument, 0, 't' }, + {"compression", required_argument, 0, 'c' }, + {"base-address", required_argument, 0, 'b' }, + {"load-address", required_argument, 0, 'l' }, + {"top-aligned", required_argument, 0, 'T' }, + {"entry-point", required_argument, 0, 'e' }, + {"size", required_argument, 0, 's' }, + {"bootblock", required_argument, 0, 'B' }, + {"header-offset", required_argument, 0, 'H' }, + {"alignment", required_argument, 0, 'a' }, + {"page-size", required_argument, 0, 'P' }, + {"offset", required_argument, 0, 'o' }, + {"file", required_argument, 0, 'f' }, + {"machine", required_argument, 0, 'm' }, + {"empty-fits", required_argument, 0, 'x' }, + {"initrd", required_argument, 0, 'I' }, + {"cmdline", required_argument, 0, 'C' }, + {"ignore-sec", required_argument, 0, 'S' }, + {"verbose", no_argument, 0, 'v' }, + {"help", no_argument, 0, 'h' }, + {NULL, 0, 0, 0 } }; static void usage(char *name) @@ -495,14 +534,17 @@ static void usage(char *name) "Add a component\n" " add-payload -f FILE -n NAME [-c compression] [-b base] " "Add a payload to the ROM\n" - " add-stage -f FILE -n NAME [-c compression] [-b base] " + " (linux specific: [-C cmdline] [-I initrd])\n" + " add-stage -f FILE -n NAME [-c compression] [-b base] \\\n" + " [-S section-to-ignore] " "Add a stage to the ROM\n" " add-flat-binary -f FILE -n NAME -l load-address \\\n" " -e entry-point [-c compression] [-b base] " "Add a 32bit flat mode binary\n" " remove -n NAME " "Remove a component\n" - " create -s size -B bootblock -m ARCH [-a align] [-o offset] " + " create -s size -m ARCH [-B bootblock] [-b bootblock offset] \\\n" + " [-o CBFS offset] [-H header offset] [-a align] " "Create a ROM file\n" " locate -f FILE -n NAME [-P page-size] [-a align] [-T] " "Find a place for a file of that size\n" @@ -514,7 +556,7 @@ static void usage(char *name) "Updates the FIT table with microcode entries\n" "\n" "ARCHes:\n" - " armv7, x86\n" + " arm64, arm, mips, x86\n" "TYPEs:\n", name, name ); print_supported_filetypes(); @@ -586,7 +628,6 @@ int main(int argc, char **argv) break; case 'l': param.loadaddress = strtoul(optarg, NULL, 0); - break; case 'e': param.entrypoint = strtoul(optarg, NULL, 0); @@ -599,6 +640,7 @@ int main(int argc, char **argv) if (tolower(suffix[0])=='m') { param.size *= 1024 * 1024; } + break; case 'B': param.bootblock = optarg; break; @@ -614,7 +656,8 @@ int main(int argc, char **argv) param.pagesize = strtoul(optarg, NULL, 0); break; case 'o': - param.offset = strtoul(optarg, NULL, 0); + param.cbfsoffset = strtoul(optarg, NULL, 0); + param.cbfsoffset_assigned = 1; break; case 'f': param.filename = optarg; @@ -631,6 +674,15 @@ int main(int argc, char **argv) case 'm': arch = string_to_arch(optarg); break; + case 'I': + param.initrd = optarg; + break; + case 'C': + param.cmdline = optarg; + break; + case 'S': + param.ignore_section = optarg; + break; case 'h': case '?': usage(argv[0]); diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c index aa986963c1..95c60fc74c 100644 --- a/util/cbfstool/common.c +++ b/util/cbfstool/common.c @@ -25,9 +25,9 @@ #include #include "common.h" #include "cbfs.h" -#include "elf.h" /* Utilities */ +int verbose = 0; /* Small, OS/libc independent runtime check for endianess */ int is_big_endian(void) @@ -42,7 +42,8 @@ int is_big_endian(void) /* Buffer and file I/O */ -int buffer_create(struct buffer *buffer, size_t size, const char *name) { +int buffer_create(struct buffer *buffer, size_t size, const char *name) +{ buffer->name = strdup(name); buffer->size = size; buffer->data = (char *)malloc(buffer->size); @@ -53,7 +54,8 @@ int buffer_create(struct buffer *buffer, size_t size, const char *name) { return (buffer->data == NULL); } -int buffer_from_file(struct buffer *buffer, const char *filename) { +int buffer_from_file(struct buffer *buffer, const char *filename) +{ FILE *fp = fopen(filename, "rb"); if (!fp) { perror(filename); @@ -74,7 +76,8 @@ int buffer_from_file(struct buffer *buffer, const char *filename) { return 0; } -int buffer_write_file(struct buffer *buffer, const char *filename) { +int buffer_write_file(struct buffer *buffer, const char *filename) +{ FILE *fp = fopen(filename, "wb"); if (!fp) { perror(filename); @@ -90,7 +93,8 @@ int buffer_write_file(struct buffer *buffer, const char *filename) { return 0; } -void buffer_delete(struct buffer *buffer) { +void buffer_delete(struct buffer *buffer) +{ assert(buffer); if (buffer->name) { free(buffer->name); @@ -103,58 +107,24 @@ void buffer_delete(struct buffer *buffer) { buffer->size = 0; } -size_t getfilesize(const char *filename) -{ - size_t size; - FILE *file = fopen(filename, "rb"); - if (file == NULL) - return -1; - - fseek(file, 0, SEEK_END); - size = ftell(file); - fclose(file); - return size; -} - -void *loadfile(const char *filename, uint32_t * romsize_p, void *content, - int place) -{ - FILE *file = fopen(filename, "rb"); - if (file == NULL) - return NULL; - - fseek(file, 0, SEEK_END); - *romsize_p = ftell(file); - fseek(file, 0, SEEK_SET); - if (!content) { - content = malloc(*romsize_p); - if (!content) { - ERROR("Could not get %d bytes for file %s\n", - *romsize_p, filename); - exit(1); - } - } else if (place == SEEK_END) - content -= *romsize_p; - - if (!fread(content, *romsize_p, 1, file)) { - ERROR("Failed to read %s\n", filename); - return NULL; - } - fclose(file); - return content; -} - -static struct cbfs_header *master_header; -static uint32_t phys_start, phys_end, align; -uint32_t romsize; -void *offset; uint32_t arch = CBFS_ARCHITECTURE_UNKNOWN; +void cbfs_file_get_header(struct buffer *buf, struct cbfs_file *file) +{ + bgets(buf, &file->magic, sizeof(file->magic)); + file->len = xdr_be.get32(buf); + file->type = xdr_be.get32(buf); + file->checksum = xdr_be.get32(buf); + file->offset = xdr_be.get32(buf); +} + static struct { uint32_t arch; const char *name; } arch_names[] = { - { CBFS_ARCHITECTURE_ARMV7, "armv7" }, + { CBFS_ARCHITECTURE_AARCH64, "arm64" }, + { CBFS_ARCHITECTURE_ARM, "arm" }, + { CBFS_ARCHITECTURE_MIPS, "mips" }, { CBFS_ARCHITECTURE_X86, "x86" }, { CBFS_ARCHITECTURE_UNKNOWN, "unknown" } }; @@ -190,115 +160,7 @@ const char *arch_to_string(uint32_t a) } -int find_master_header(void *romarea, size_t size) -{ - size_t offset; - - if (master_header) - return 0; - - for (offset = 0; offset < size - sizeof(struct cbfs_header); offset++) { - struct cbfs_header *tmp = romarea + offset; - - if (tmp->magic == ntohl(CBFS_HEADER_MAGIC)) { - master_header = tmp; - break; - } - } - - return master_header ? 0 : 1; -} - -void recalculate_rom_geometry(void *romarea) -{ - if (find_master_header(romarea, romsize)) { - ERROR("Cannot find master header\n"); - exit(1); - } - - /* Update old headers */ - if (master_header->version == CBFS_HEADER_VERSION1 && - ntohl(master_header->architecture) == CBFS_ARCHITECTURE_UNKNOWN) { - DEBUG("Updating CBFS master header to version 2\n"); - master_header->architecture = htonl(CBFS_ARCHITECTURE_X86); - } - - arch = ntohl(master_header->architecture); - - switch (arch) { - case CBFS_ARCHITECTURE_ARMV7: - offset = romarea; - phys_start = (0 + ntohl(master_header->offset)) & 0xffffffff; - phys_end = romsize & 0xffffffff; - break; - case CBFS_ARCHITECTURE_X86: - offset = romarea + romsize - 0x100000000ULL; - phys_start = (0 - romsize + ntohl(master_header->offset)) & - 0xffffffff; - phys_end = (0 - ntohl(master_header->bootblocksize) - - sizeof(struct cbfs_header)) & 0xffffffff; - break; - default: - ERROR("Unknown architecture\n"); - exit(1); - } - - align = ntohl(master_header->align); -} - -void *loadrom(const char *filename) -{ - void *romarea = loadfile(filename, &romsize, 0, SEEK_SET); - if (romarea == NULL) - return NULL; - recalculate_rom_geometry(romarea); - return romarea; -} - -int writerom(const char *filename, void *start, uint32_t size) -{ - FILE *file = fopen(filename, "wb"); - if (!file) { - ERROR("Could not open '%s' for writing: ", filename); - perror(""); - return 1; - } - - if (fwrite(start, size, 1, file) != 1) { - ERROR("Could not write to '%s': ", filename); - perror(""); - return 1; - } - - fclose(file); - return 0; -} - -int cbfs_file_header(unsigned long physaddr) -{ - /* maybe improve this test */ - return (strncmp(phys_to_virt(physaddr), "LARCHIVE", 8) == 0); -} - -struct cbfs_file *cbfs_create_empty_file(uint32_t physaddr, uint32_t size) -{ - struct cbfs_file *nextfile = (struct cbfs_file *)phys_to_virt(physaddr); - strncpy((char *)(nextfile->magic), "LARCHIVE", 8); - nextfile->len = htonl(size); - nextfile->type = htonl(0xffffffff); - nextfile->checksum = 0; // FIXME? - nextfile->offset = htonl(sizeof(struct cbfs_file) + 16); - memset(((void *)nextfile) + sizeof(struct cbfs_file), 0, 16); - return nextfile; -} - -int iself(unsigned char *input) -{ - Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input; - return !memcmp(ehdr->e_ident, ELFMAG, 4); -} - -static struct filetypes_t { +static const struct filetypes_t { uint32_t type; const char *name; } filetypes[] = { @@ -327,15 +189,6 @@ void print_supported_filetypes(void) } } -const char *strfiletype(uint32_t number) -{ - size_t i; - for (i = 0; i < (sizeof(filetypes) / sizeof(struct filetypes_t)); i++) - if (filetypes[i].type == number) - return filetypes[i].name; - return "unknown"; -} - uint64_t intfiletype(const char *name) { size_t i; @@ -345,514 +198,3 @@ uint64_t intfiletype(const char *name) return -1; } -void print_cbfs_directory(const char *filename) -{ - char *name = strdup(filename); - printf - ("%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\n" - "alignment: %d bytes, architecture: %s\n\n", - basename(name), romsize / 1024, ntohl(master_header->bootblocksize), - romsize, ntohl(master_header->offset), align, arch_to_string(arch)); - free(name); - printf("%-30s %-10s %-12s Size\n", "Name", "Offset", "Type"); - uint32_t current = phys_start; - while (current < phys_end) { - if (!cbfs_file_header(current)) { - current += align; - continue; - } - struct cbfs_file *thisfile = - (struct cbfs_file *)phys_to_virt(current); - uint32_t length = ntohl(thisfile->len); - char *fname = (char *)(phys_to_virt(current) + sizeof(struct cbfs_file)); - if (strlen(fname) == 0) - fname = "(empty)"; - - printf("%-30s 0x%-8x %-12s %d\n", fname, - current - phys_start + ntohl(master_header->offset), - strfiletype(ntohl(thisfile->type)), length); - - /* note the components of the subheader are in host order ... */ - switch (ntohl(thisfile->type)) { - case CBFS_COMPONENT_STAGE: - { - struct cbfs_stage *stage = CBFS_SUBHEADER(thisfile); - INFO(" %s compression, entry: 0x%llx, load: 0x%llx, length: %d/%d\n", - stage->compression == CBFS_COMPRESS_LZMA ? "LZMA" : "no", - (unsigned long long)stage->entry, - (unsigned long long)stage->load, - stage->len, - stage->memlen); - break; - } - case CBFS_COMPONENT_PAYLOAD: - { - struct cbfs_payload_segment *payload = CBFS_SUBHEADER(thisfile); - while(payload) { - switch(payload->type) { - case PAYLOAD_SEGMENT_CODE: - case PAYLOAD_SEGMENT_DATA: - INFO(" %s (%s compression, offset: 0x%x, load: 0x%llx, length: %d/%d)\n", - payload->type == PAYLOAD_SEGMENT_CODE ? "code " : "data" , - payload->compression == CBFS_COMPRESS_LZMA ? "LZMA" : "no", - ntohl(payload->offset), - (unsigned long long)ntohll(payload->load_addr), - ntohl(payload->len), ntohl(payload->mem_len)); - break; - case PAYLOAD_SEGMENT_ENTRY: - INFO(" entry (0x%llx)\n", (unsigned long long)ntohll(payload->load_addr)); - break; - case PAYLOAD_SEGMENT_BSS: - INFO(" BSS (address 0x%016llx, length 0x%x)\n", (unsigned long long)ntohll(payload->load_addr), ntohl(payload->len)); - break; - case PAYLOAD_SEGMENT_PARAMS: - INFO(" parameters\n"); - break; - default: - INFO(" %x (%s compression, offset: 0x%x, load: 0x%llx, length: %d/%d\n", - payload->type, - payload->compression == CBFS_COMPRESS_LZMA ? "LZMA" : "no", - ntohl(payload->offset), - (unsigned long long)ntohll(payload->load_addr), - ntohl(payload->len), - ntohl(payload->mem_len)); - break; - } - - if(payload->type == PAYLOAD_SEGMENT_ENTRY) - payload=NULL; - else - payload++; - } - break; - } - default: - break; - } - current = - ALIGN(current + ntohl(thisfile->len) + - ntohl(thisfile->offset), align); - } -} - -int extract_file_from_cbfs(const char *filename, const char *payloadname, const char *outpath) -{ - FILE *outfile = NULL; - uint32_t current = phys_start; - while (current < phys_end) { - if (!cbfs_file_header(current)) { - current += align; - continue; - } - - // Locate the file start struct - struct cbfs_file *thisfile = - (struct cbfs_file *)phys_to_virt(current); - // And its length - uint32_t length = ntohl(thisfile->len); - // Locate the file name - char *fname = (char *)(phys_to_virt(current) + sizeof(struct cbfs_file)); - - // It's not the file we are looking for.. - if (strcmp(fname, payloadname) != 0) - { - current = - ALIGN(current + ntohl(thisfile->len) + - ntohl(thisfile->offset), align); - continue; - } - - // Else, it's our file. - LOG("Found file %.30s at 0x%x, type %.12s, size %d\n", fname, - current - phys_start, strfiletype(ntohl(thisfile->type)), - length); - - // If we are not dumping to stdout, open the out file. - outfile = fopen(outpath, "wb"); - if (!outfile) - { - ERROR("Could not open the file %s for writing.\n", outpath); - return 1; - } - - if (ntohl(thisfile->type) != CBFS_COMPONENT_RAW) - { - WARN("Only 'raw' files are safe to extract.\n"); - } - - fwrite(((char *)thisfile) - + ntohl(thisfile->offset), length, 1, outfile); - - fclose(outfile); - LOG("Successfully dumped the file.\n"); - - // We'll only dump one file. - return 0; - } - ERROR("File %s not found.\n", payloadname); - return 1; -} - - -int add_file_to_cbfs(void *content, uint32_t contentsize, uint32_t location) -{ - uint32_t current = phys_start; - while (current < phys_end) { - if (!cbfs_file_header(current)) { - current += align; - continue; - } - struct cbfs_file *thisfile = - (struct cbfs_file *)phys_to_virt(current); - uint32_t length = ntohl(thisfile->len); - - DEBUG("at %x, %x bytes\n", current, length); - /* Is this a free chunk? */ - if ((thisfile->type == CBFS_COMPONENT_DELETED) - || (thisfile->type == CBFS_COMPONENT_NULL)) { - DEBUG("null||deleted at %x, %x bytes\n", current, - length); - /* if this is the right size, and if specified, the right location, use it */ - if ((contentsize <= length) - && ((location == 0) || (current == location))) { - if (contentsize < length) { - DEBUG("this chunk is %x bytes, we need %x. create a new chunk at %x with %x bytes\n", - length, contentsize, - ALIGN(current + contentsize, - align), - length - contentsize); - uint32_t start = - ALIGN(current + contentsize, align); - uint32_t size = - current + ntohl(thisfile->offset) - + length - start - 16 - - sizeof(struct cbfs_file); - cbfs_create_empty_file(start, size); - } - DEBUG("copying data\n"); - memcpy(phys_to_virt(current), content, - contentsize); - return 0; - } - if (location != 0) { - /* CBFS has the constraint that the chain always moves up in memory. so once - we're past the place we seek, we don't need to look any further */ - if (current > location) { - ERROR("The requested space is not available\n"); - return 1; - } - - /* Is the requested location inside the current chunk? */ - if ((current < location) - && ((location + contentsize) <= - (current + length))) { - /* Split it up. In the next iteration the code will be at the right place. */ - DEBUG("split up. new length: %x\n", - location - current - - ntohl(thisfile->offset)); - thisfile->len = - htonl(location - current - - ntohl(thisfile->offset)); - cbfs_create_empty_file(location, - length - - (location - - current)); - } - } - } - current = - ALIGN(current + ntohl(thisfile->len) + - ntohl(thisfile->offset), align); - } - ERROR("Could not add the file to CBFS, it's probably too big.\n"); - ERROR("File size: %d bytes (%d KB).\n", contentsize, contentsize/1024); - return 1; -} - - -static struct cbfs_file *merge_adjacent_files(struct cbfs_file *first, - struct cbfs_file *second) -{ - uint32_t new_length = - ntohl(first->len) + ntohl(second->len) + ntohl(second->offset); - first->len = htonl(new_length); - first->checksum = 0; // FIXME? - return first; -} - -static struct cbfs_file *next_file(struct cbfs_file *prev) -{ - uint32_t pos = (prev == NULL) ? phys_start : - ALIGN(virt_to_phys(prev) + ntohl(prev->len) + ntohl(prev->offset), - align); - - for (; pos < phys_end; pos += align) { - if (cbfs_file_header(pos)) - return (struct cbfs_file *)phys_to_virt(pos); - } - return NULL; -} - - -int remove_file_from_cbfs(const char *filename) -{ - struct cbfs_file *prev = NULL; - struct cbfs_file *cur = next_file(prev); - struct cbfs_file *next = next_file(cur); - for (; cur; prev = cur, cur = next, next = next_file(next)) { - - /* Check if this is the file to remove. */ - char *name = (char *)cur + sizeof(*cur); - if (strcmp(name, filename)) - continue; - - /* Mark the file as free space and erase its name. */ - cur->type = CBFS_COMPONENT_NULL; - name[0] = '\0'; - - /* Merge it with the previous file if possible. */ - if (prev && prev->type == CBFS_COMPONENT_NULL) - cur = merge_adjacent_files(prev, cur); - - /* Merge it with the next file if possible. */ - if (next && next->type == CBFS_COMPONENT_NULL) - merge_adjacent_files(cur, next); - - return 0; - } - ERROR("CBFS file %s not found.\n", filename); - return 1; -} - - -/* returns new data block with cbfs_file header, suitable to dump into the ROM. location returns - the new location that points to the cbfs_file header */ -void *create_cbfs_file(const char *filename, void *data, uint32_t * datasize, - uint32_t type, uint32_t * location) -{ - uint32_t filename_len = ALIGN(strlen(filename) + 1, 16); - uint32_t headersize = sizeof(struct cbfs_file) + filename_len; - if ((location != 0) && (*location != 0)) { - uint32_t offset = *location % align; - /* If offset >= (headersize % align), we can stuff the header into the offset. - Otherwise the header has to be aligned itself, and put before the offset data */ - if (offset >= (headersize % align)) { - offset -= (headersize % align); - } else { - offset += align - (headersize % align); - } - headersize += offset; - *location -= headersize; - } - void *newdata = malloc(*datasize + headersize); - if (!newdata) { - ERROR("Could not get %d bytes for CBFS file.\n", *datasize + - headersize); - exit(1); - } - memset(newdata, 0xff, *datasize + headersize); - struct cbfs_file *nextfile = (struct cbfs_file *)newdata; - strncpy((char *)(nextfile->magic), "LARCHIVE", 8); - nextfile->len = htonl(*datasize); - nextfile->type = htonl(type); - nextfile->checksum = 0; // FIXME? - nextfile->offset = htonl(headersize); - strcpy(newdata + sizeof(struct cbfs_file), filename); - memcpy(newdata + headersize, data, *datasize); - *datasize += headersize; - return newdata; -} - -int create_cbfs_image(const char *romfile, uint32_t _romsize, - const char *bootblock, uint32_t align, uint32_t offs) -{ - uint32_t bootblocksize = 0; - struct cbfs_header *master_header; - unsigned char *romarea, *bootblk; - - romsize = _romsize; - romarea = malloc(romsize); - if (!romarea) { - ERROR("Could not get %d bytes of memory" - " for CBFS image.\n", romsize); - exit(1); - } - memset(romarea, 0xff, romsize); - - if (align == 0) - align = 64; - - bootblk = loadfile(bootblock, &bootblocksize, - romarea + romsize, SEEK_END); - if (!bootblk) { - ERROR("Could not load bootblock %s.\n", - bootblock); - free(romarea); - return 1; - } - - // TODO(hungte) Replace magic numbers by named constants. - switch (arch) { - case CBFS_ARCHITECTURE_ARMV7: - /* Set up physical/virtual mapping */ - offset = romarea; - - /* - * The initial jump instruction and bootblock will be placed - * before and after the master header, respectively. The - * bootblock image must contain a blank, aligned region large - * enough for the master header to fit. - * - * An anchor string must be left such that when cbfstool is run - * we can find it and insert the master header at the next - * aligned boundary. - */ - loadfile(bootblock, &bootblocksize, romarea + offs, SEEK_SET); - - unsigned char *p = romarea + offs; - while (1) { - /* FIXME: assumes little endian... */ - if (*(uint32_t *)p == 0xdeadbeef) - break; - if (p >= (romarea + _romsize)) { - ERROR("Could not determine CBFS " - "header location.\n"); - return 1; - } - p += (sizeof(unsigned int)); - } - unsigned int u = ALIGN((unsigned int)(p - romarea), align); - master_header = (struct cbfs_header *)(romarea + u); - - master_header->magic = ntohl(CBFS_HEADER_MAGIC); - master_header->version = ntohl(CBFS_HEADER_VERSION); - master_header->romsize = htonl(romsize); - master_header->bootblocksize = htonl(bootblocksize); - master_header->align = htonl(align); - master_header->offset = htonl( - ALIGN((0x40 + bootblocksize), align)); - master_header->architecture = htonl(CBFS_ARCHITECTURE_ARMV7); - - ((uint32_t *) phys_to_virt(0x4 + offs))[0] = - virt_to_phys(master_header); - - recalculate_rom_geometry(romarea); - - cbfs_create_empty_file( - offs + ALIGN((0x40 + bootblocksize), align), - romsize - offs - sizeof(struct cbfs_file) - - ALIGN((bootblocksize + 0x40), align)); - break; - - case CBFS_ARCHITECTURE_X86: - // Set up physical/virtual mapping - offset = romarea + romsize - 0x100000000ULL; - - loadfile(bootblock, &bootblocksize, romarea + romsize, - SEEK_END); - master_header = (struct cbfs_header *)(romarea + romsize - - bootblocksize - sizeof(struct cbfs_header)); - - master_header->magic = ntohl(CBFS_HEADER_MAGIC); - master_header->version = ntohl(CBFS_HEADER_VERSION); - master_header->romsize = htonl(romsize); - master_header->bootblocksize = htonl(bootblocksize); - master_header->align = htonl(align); - master_header->offset = htonl(offs); - master_header->architecture = htonl(CBFS_ARCHITECTURE_X86); - - ((uint32_t *) phys_to_virt(CBFS_HEADPTR_ADDR_X86))[0] = - virt_to_phys(master_header); - - recalculate_rom_geometry(romarea); - - cbfs_create_empty_file((0 - romsize + offs) & 0xffffffff, - romsize - offs - bootblocksize - - sizeof(struct cbfs_header) - - sizeof(struct cbfs_file) - 16); - break; - - default: - // Should not happen. - ERROR("You found a bug in cbfstool.\n"); - exit(1); - } - - writerom(romfile, romarea, romsize); - free(romarea); - return 0; -} - -static int in_segment(int addr, int size, int gran) -{ - return ((addr & ~(gran - 1)) == ((addr + size) & ~(gran - 1))); -} - -uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, - const char *filename, uint32_t alignment) -{ - void *rom; - size_t filename_size, headersize, totalsize; - int ret = 0; - uint32_t current; - - rom = loadrom(romfile); - if (rom == NULL) { - ERROR("Could not load ROM image '%s'.\n", romfile); - return 0; - } - - filename_size = strlen(filename); - headersize = sizeof(struct cbfs_file) + ALIGN(filename_size + 1, 16) + - sizeof(struct cbfs_stage); - totalsize = headersize + filesize; - - current = phys_start; - while (current < phys_end) { - uint32_t top; - struct cbfs_file *thisfile; - - if (!cbfs_file_header(current)) { - current += align; - continue; - } - - thisfile = (struct cbfs_file *)phys_to_virt(current); - - top = current + ntohl(thisfile->len) + ntohl(thisfile->offset); - - if (((ntohl(thisfile->type) == 0x0) - || (ntohl(thisfile->type) == 0xffffffff)) - && (ntohl(thisfile->len) + ntohl(thisfile->offset) >= - totalsize)) { - if (in_segment - (current + headersize, filesize, alignment)) { - ret = current + headersize; - break; - } - if ((ALIGN(current, alignment) + filesize < top) - && (ALIGN(current, alignment) - headersize > - current) - && in_segment(ALIGN(current, alignment), filesize, - alignment)) { - ret = ALIGN(current, alignment); - break; - } - if ((ALIGN(current, alignment) + alignment + filesize < - top) - && (ALIGN(current, alignment) + alignment - - headersize > current) - && in_segment(ALIGN(current, alignment) + alignment, - filesize, alignment)) { - ret = ALIGN(current, alignment) + alignment; - break; - } - } - current = - ALIGN(current + ntohl(thisfile->len) + - ntohl(thisfile->offset), align); - } - - free(rom); - return ret; -} diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h index e197143bc7..bac449ad5a 100644 --- a/util/cbfstool/common.h +++ b/util/cbfstool/common.h @@ -31,7 +31,7 @@ #endif #define ntohll(x) (is_big_endian() ? (x) : swab64(x)) #define htonll(x) (is_big_endian() ? (x) : swab64(x)) -extern int is_big_endian(void); +int is_big_endian(void); /* Message output */ extern int verbose; @@ -41,6 +41,19 @@ extern int verbose; #define INFO(x...) { if (verbose > 0) fprintf(stderr, "INFO: " x); } #define DEBUG(x...) { if (verbose > 1) fprintf(stderr, "DEBUG: " x); } +/* Helpers */ +#define ARRAY_SIZE(a) (int)(sizeof(a) / sizeof((a)[0])) +#define ALIGN(val, by) (((val) + (by)-1)&~((by)-1)) + +#define unused __attribute__((unused)) + +static inline uint32_t align_up(uint32_t value, uint32_t align) +{ + if (value % align) + value += align - (value % align); + return value; +} + /* Buffer and file I/O */ struct buffer { char *name; @@ -48,6 +61,49 @@ struct buffer { size_t size; }; +static inline void *buffer_get(const struct buffer *b) +{ + return b->data; +} + +static inline size_t buffer_size(const struct buffer *b) +{ + return b->size; +} + +static inline void buffer_set_size(struct buffer *b, size_t size) +{ + b->size = size; +} + +/* + * Splice a buffer into another buffer. If size is zero the entire buffer + * is spliced while if size is non-zero the buffer is spliced starting at + * offset for size bytes. Note that it's up to caller to bounds check. + */ +static inline void buffer_splice(struct buffer *dest, const struct buffer *src, + size_t offset, size_t size) +{ + dest->name = src->name; + dest->data = src->data; + dest->size = src->size; + if (size != 0) { + dest->data += offset; + buffer_set_size(dest, size); + } +} + +static inline void buffer_clone(struct buffer *dest, const struct buffer *src) +{ + buffer_splice(dest, src, 0, 0); +} + +static inline void buffer_seek(struct buffer *b, size_t size) +{ + b->size -= size; + b->data += size; +} + /* Creates an empty memory buffer with given size. * Returns 0 on success, otherwise non-zero. */ int buffer_create(struct buffer *buffer, size_t size, const char *name); @@ -62,46 +118,28 @@ int buffer_write_file(struct buffer *buffer, const char *filename); /* Destroys a memory buffer. */ void buffer_delete(struct buffer *buffer); -extern void *offset; -extern uint32_t romsize; -extern int host_bigendian; +/* Architecture handling */ extern uint32_t arch; const char *arch_to_string(uint32_t a); uint32_t string_to_arch(const char *arch_string); -static inline void *phys_to_virt(uint32_t addr) -{ - return offset + addr; -} - -static inline uint32_t virt_to_phys(void *addr) -{ - return (unsigned long)(addr - offset) & 0xffffffff; -} - -#define ALIGN(val, by) (((val) + (by)-1)&~((by)-1)) - -size_t getfilesize(const char *filename); -void *loadfile(const char *filename, uint32_t * romsize_p, void *content, - int place); -void *loadrom(const char *filename); -int writerom(const char *filename, void *start, uint32_t size); - -int iself(unsigned char *input); - -typedef void (*comp_func_ptr) (char *, int, char *, int *); +typedef int (*comp_func_ptr) (char *, int, char *, int *); typedef enum { CBFS_COMPRESS_NONE = 0, CBFS_COMPRESS_LZMA = 1 } comp_algo; comp_func_ptr compression_function(comp_algo algo); uint64_t intfiletype(const char *name); +void print_supported_filetypes(void); /* cbfs-mkpayload.c */ int parse_elf_to_payload(const struct buffer *input, struct buffer *output, comp_algo algo); int parse_fv_to_payload(const struct buffer *input, struct buffer *output, comp_algo algo); +int parse_bzImage_to_payload(const struct buffer *input, + struct buffer *output, const char *initrd, + char *cmdline, comp_algo algo); int parse_flat_binary_to_payload(const struct buffer *input, struct buffer *output, uint32_t loadaddress, @@ -109,25 +147,28 @@ int parse_flat_binary_to_payload(const struct buffer *input, comp_algo algo); /* cbfs-mkstage.c */ int parse_elf_to_stage(const struct buffer *input, struct buffer *output, - comp_algo algo, uint32_t *location); + comp_algo algo, uint32_t *location, + const char *ignore_section); -void *create_cbfs_file(const char *filename, void *data, uint32_t * datasize, - uint32_t type, uint32_t * location); -int create_cbfs_image(const char *romfile, uint32_t romsize, - const char *bootblock, uint32_t align, uint32_t offs); +/* lzma/lzma.c */ +int do_lzma_compress(char *in, int in_len, char *out, int *out_len); +int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len); +/* xdr.c */ +struct xdr { + uint8_t (*get8)(struct buffer *input); + uint16_t (*get16)(struct buffer *input); + uint32_t (*get32)(struct buffer *input); + uint64_t (*get64)(struct buffer *input); + void (*put8)(struct buffer *input, uint8_t val); + void (*put16)(struct buffer *input, uint16_t val); + void (*put32)(struct buffer *input, uint32_t val); + void (*put64)(struct buffer *input, uint64_t val); +}; -int add_file_to_cbfs(void *content, uint32_t contentsize, uint32_t location); -int remove_file_from_cbfs(const char *filename); -void print_cbfs_directory(const char *filename); -int extract_file_from_cbfs(const char *filename, const char *payloadname, const char *outpath); -int remove_file_from_cbfs(const char *filename); - -uint32_t cbfs_find_location(const char *romfile, uint32_t filesize, - const char *filename, uint32_t align); - -void print_supported_filetypes(void); - -#define ARRAY_SIZE(a) (int)(sizeof(a) / sizeof((a)[0])) +/* xdr.c */ +extern struct xdr xdr_le, xdr_be; +size_t bgets(struct buffer *input, void *output, size_t len); +size_t bputs(struct buffer *b, const void *data, size_t len); #endif diff --git a/util/cbfstool/compress.c b/util/cbfstool/compress.c index 9ea1487ff9..5b916cee11 100644 --- a/util/cbfstool/compress.c +++ b/util/cbfstool/compress.c @@ -26,17 +26,16 @@ #include #include "common.h" -void do_lzma_compress(char *in, int in_len, char *out, int *out_len); - -static void lzma_compress(char *in, int in_len, char *out, int *out_len) +static int lzma_compress(char *in, int in_len, char *out, int *out_len) { - do_lzma_compress(in, in_len, out, out_len); + return do_lzma_compress(in, in_len, out, out_len); } -static void none_compress(char *in, int in_len, char *out, int *out_len) +static int none_compress(char *in, int in_len, char *out, int *out_len) { memcpy(out, in, in_len); *out_len = in_len; + return 0; } comp_func_ptr compression_function(comp_algo algo) diff --git a/util/cbfstool/elf.h b/util/cbfstool/elf.h index 01af81988a..9566417e4f 100644 --- a/util/cbfstool/elf.h +++ b/util/cbfstool/elf.h @@ -244,6 +244,8 @@ typedef struct #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_NUM 95 +#define EM_AARCH64 183 /* ARM Aarch64 Architecture */ + /* If it is necessary to assign new unofficial EM_* values, please pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision with official or non-GNU unofficial values. */ @@ -2221,12 +2223,16 @@ typedef Elf32_Addr Elf32_Conflict; #define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ #define R_ARM_GOT32 26 /* 32 bit GOT entry */ #define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_THM_JUMP24 30 #define R_ARM_ALU_PCREL_7_0 32 #define R_ARM_ALU_PCREL_15_8 33 #define R_ARM_ALU_PCREL_23_15 34 #define R_ARM_LDR_SBREL_11_0 35 #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_V4BX 40 #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */ @@ -2251,6 +2257,60 @@ typedef Elf32_Addr Elf32_Conflict; /* Keep this the last entry. */ #define R_ARM_NUM 256 +/* AARCH64 Relocs */ +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_ABS16 259 +#define R_AARCH64_PREL64 260 +#define R_AARCH64_PREL32 261 +#define R_AARCH64_PREL16 262 +#define R_AARCH64_MOVW_UABS_G0 263 +#define R_AARCH64_MOVW_UABS_G0_NC 264 +#define R_AARCH64_MOVW_UABS_G1 265 +#define R_AARCH64_MOVW_UABS_G1_NC 266 +#define R_AARCH64_MOVW_UABS_G2 267 +#define R_AARCH64_MOVW_UABS_G2_NC 268 +#define R_AARCH64_MOVW_UABS_G3 269 +#define R_AARCH64_MOVW_SABS_G0 270 +#define R_AARCH64_MOVW_SABS_G1 271 +#define R_AARCH64_MOVW_SABS_G2 272 +#define R_AARCH64_LD_PREL_LO19 273 +#define R_AARCH64_ADR_PREL_LO21 274 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 +#define R_AARCH64_TSTBR14 279 +#define R_AARCH64_CONDBR19 280 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_MOVW_PREL_G0 287 +#define R_AARCH64_MOVW_PREL_G0_NC 288 +#define R_AARCH64_MOVW_PREL_G1 289 +#define R_AARCH64_MOVW_PREL_G1_NC 290 +#define R_AARCH64_MOVW_PREL_G2 291 +#define R_AARCH64_MOVW_PREL_G2_NC 292 +#define R_AARCH64_MOVW_PREL_G3 293 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 +#define R_AARCH64_MOVW_GOTOFF_G0 300 +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 +#define R_AARCH64_MOVW_GOTOFF_G1 302 +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 +#define R_AARCH64_MOVW_GOTOFF_G2 304 +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 +#define R_AARCH64_MOVW_GOTOFF_G3 306 +#define R_AARCH64_GOTREL64 307 +#define R_AARCH64_GOTREL32 308 +#define R_AARCH64_GOT_LD_PREL19 309 +#define R_AARCH64_LD64_GOTOFF_LO15 310 +#define R_AARCH64_ADR_GOT_PAGE 311 +#define R_AARCH64_LD64_GOT_LO12_NC 312 +#define R_AARCH64_LD64_GOTPAGE_LO15 313 + + /* IA-64 specific declarations. */ /* Processor specific flags for the Ehdr e_flags field. */ diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c new file mode 100644 index 0000000000..54a4861d89 --- /dev/null +++ b/util/cbfstool/elfheaders.c @@ -0,0 +1,938 @@ +/* + * elf header parsing. + * + * Copyright (C) 2013 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +#include "elfparsing.h" +#include "common.h" +#include "cbfs.h" + +/* + * Short form: this is complicated, but we've tried making it simple + * and we keep hitting problems with our ELF parsing. + * + * The ELF parsing situation has always been a bit tricky. In fact, + * we (and most others) have been getting it wrong in small ways for + * years. Recently this has caused real trouble for the ARM V8 build. + * In this file we attempt to finally get it right for all variations + * of endian-ness and word size and target architectures and + * architectures we might get run on. Phew!. To do this we borrow a + * page from the FreeBSD NFS xdr model (see elf_ehdr and elf_phdr), + * the Plan 9 endianness functions (see xdr.c), and Go interfaces (see + * how we use buffer structs in this file). This ends up being a bit + * wordy at the lowest level, but greatly simplifies the elf parsing + * code and removes a common source of bugs, namely, forgetting to + * flip type endianness when referencing a struct member. + * + * ELF files can have four combinations of data layout: 32/64, and + * big/little endian. Further, to add to the fun, depending on the + * word size, the size of the ELF structs varies. The coreboot SELF + * format is simpler in theory: it's supposed to be always BE, and the + * various struct members allow room for growth: the entry point is + * always 64 bits, for example, so the size of a SELF struct is + * constant, regardless of target architecture word size. Hence, we + * need to do some transformation of the ELF files. + * + * A given architecture, realistically, only supports one of the four + * combinations at a time as the 'native' format. Hence, our code has + * been sprinkled with every variation of [nh]to[hn][sll] over the + * years. We've never quite gotten it all right, however, and a quick + * pass over this code revealed another bug. It's all worked because, + * until now, all the working platforms that had CBFS were 32 LE. Even then, + * however, bugs crept in: we recently realized that we're not + * transforming the entry point to big format when we store into the + * SELF image. + * + * The problem is essentially an XDR operation: + * we have something in a foreign format and need to transform it. + * It's most like XDR because: + * 1) the byte order can be wrong + * 2) the word size can be wrong + * 3) the size of elements in the stream depends on the value + * of other elements in the stream + * it's not like XDR because: + * 1) the byte order can be right + * 2) the word size can be right + * 3) the struct members are all on a natural alignment + * + * Hence, this new approach. To cover word size issues, we *always* + * transform the two structs we care about, the file header and + * program header, into a native struct in the 64 bit format: + * + * [32,little] -> [Elf64_Ehdr, Elf64_Phdr] + * [64,little] -> [Elf64_Ehdr, Elf64_Phdr] + * [32,big] -> [Elf64_Ehdr, Elf64_Phdr] + * [64,big] -> [Elf64_Ehdr, Elf64_Phdr] + * Then we just use those structs, and all the need for inline ntoh* goes away, + * as well as all the chances for error. + * This works because all the SELF structs have fields large enough for + * the largest ELF 64 struct members, and all the Elf64 struct members + * are at least large enough for all ELF 32 struct members. + * We end up with one function to do all our ELF parsing, and two functions + * to transform the headers. For the put case, we also have + * XDR functions, and hopefully we'll never again spend 5 years with the + * wrong endian-ness on an output value :-) + * This should work for all word sizes and endianness we hope to target. + * I *really* don't want to be here for 128 bit addresses. + * + * The parse functions are called with a pointer to an input buffer + * struct. One might ask: are there enough bytes in the input buffer? + * We know there need to be at *least* sizeof(Elf32_Ehdr) + + * sizeof(Elf32_Phdr) bytes. Realistically, there has to be some data + * too. If we start to worry, though we have not in the past, we + * might apply the simple test: the input buffer needs to be at least + * sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) bytes because, even if it's + * ELF 32, there's got to be *some* data! This is not theoretically + * accurate but it is actually good enough in practice. It allows the + * header transformation code to ignore the possibility of underrun. + * + * We also must accomodate different ELF files, and hence formats, + * in the same cbfs invocation. We might load a 64-bit payload + * on a 32-bit machine; we might even have a mixed armv7/armv8 + * SOC or even a system with an x86/ARM! + * + * A possibly problematic (though unlikely to be so) assumption + * is that we expect the BIOS to remain in the lowest 32 bits + * of the physical address space. Since ARMV8 has standardized + * on that, and x86_64 also has, this seems a safe assumption. + * + * To repeat, ELF structs are different sizes because ELF struct + * members are different sizes, depending on values in the ELF file + * header. For this we use the functions defined in xdr.c, which + * consume bytes, convert the endianness, and advance the data pointer + * in the buffer struct. + */ + + +static int iself(const void *input) +{ + const Elf32_Ehdr *ehdr = input; + return !memcmp(ehdr->e_ident, ELFMAG, 4); +} + +/* Get the ident array, so we can figure out + * endian-ness, word size, and in future other useful + * parameters + */ +static void +elf_eident(struct buffer *input, Elf64_Ehdr *ehdr) +{ + bgets(input, ehdr->e_ident, sizeof(ehdr->e_ident)); +} + + +static int +check_size(const struct buffer *b, size_t offset, size_t size, const char *desc) +{ + if (size == 0) + return 0; + + if (offset >= buffer_size(b) || (offset + size) > buffer_size(b)) { + ERROR("The file is not large enough for the '%s'. " + "%ld bytes @ offset %zu, input %zu bytes.\n", + desc, size, offset, buffer_size(b)); + return -1; + } + return 0; +} + +static void +elf_ehdr(struct buffer *input, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64) +{ + ehdr->e_type = xdr->get16(input); + ehdr->e_machine = xdr->get16(input); + ehdr->e_version = xdr->get32(input); + if (bit64){ + ehdr->e_entry = xdr->get64(input); + ehdr->e_phoff = xdr->get64(input); + ehdr->e_shoff = xdr->get64(input); + } else { + ehdr->e_entry = xdr->get32(input); + ehdr->e_phoff = xdr->get32(input); + ehdr->e_shoff = xdr->get32(input); + } + ehdr->e_flags = xdr->get32(input); + ehdr->e_ehsize = xdr->get16(input); + ehdr->e_phentsize = xdr->get16(input); + ehdr->e_phnum = xdr->get16(input); + ehdr->e_shentsize = xdr->get16(input); + ehdr->e_shnum = xdr->get16(input); + ehdr->e_shstrndx = xdr->get16(input); +} + +static void +elf_phdr(struct buffer *pinput, Elf64_Phdr *phdr, + int entsize, struct xdr *xdr, int bit64) +{ + /* + * The entsize need not be sizeof(*phdr). + * Hence, it is easier to keep a copy of the input, + * as the xdr functions may not advance the input + * pointer the full entsize; rather than get tricky + * we just advance it below. + */ + struct buffer input; + buffer_clone(&input, pinput); + if (bit64){ + phdr->p_type = xdr->get32(&input); + phdr->p_flags = xdr->get32(&input); + phdr->p_offset = xdr->get64(&input); + phdr->p_vaddr = xdr->get64(&input); + phdr->p_paddr = xdr->get64(&input); + phdr->p_filesz = xdr->get64(&input); + phdr->p_memsz = xdr->get64(&input); + phdr->p_align = xdr->get64(&input); + } else { + phdr->p_type = xdr->get32(&input); + phdr->p_offset = xdr->get32(&input); + phdr->p_vaddr = xdr->get32(&input); + phdr->p_paddr = xdr->get32(&input); + phdr->p_filesz = xdr->get32(&input); + phdr->p_memsz = xdr->get32(&input); + phdr->p_flags = xdr->get32(&input); + phdr->p_align = xdr->get32(&input); + } + buffer_seek(pinput, entsize); +} + +static void +elf_shdr(struct buffer *pinput, Elf64_Shdr *shdr, + int entsize, struct xdr *xdr, int bit64) +{ + /* + * The entsize need not be sizeof(*shdr). + * Hence, it is easier to keep a copy of the input, + * as the xdr functions may not advance the input + * pointer the full entsize; rather than get tricky + * we just advance it below. + */ + struct buffer input = *pinput; + if (bit64){ + shdr->sh_name = xdr->get32(&input); + shdr->sh_type = xdr->get32(&input); + shdr->sh_flags = xdr->get64(&input); + shdr->sh_addr = xdr->get64(&input); + shdr->sh_offset = xdr->get64(&input); + shdr->sh_size= xdr->get64(&input); + shdr->sh_link = xdr->get32(&input); + shdr->sh_info = xdr->get32(&input); + shdr->sh_addralign = xdr->get64(&input); + shdr->sh_entsize = xdr->get64(&input); + } else { + shdr->sh_name = xdr->get32(&input); + shdr->sh_type = xdr->get32(&input); + shdr->sh_flags = xdr->get32(&input); + shdr->sh_addr = xdr->get32(&input); + shdr->sh_offset = xdr->get32(&input); + shdr->sh_size = xdr->get32(&input); + shdr->sh_link = xdr->get32(&input); + shdr->sh_info = xdr->get32(&input); + shdr->sh_addralign = xdr->get32(&input); + shdr->sh_entsize = xdr->get32(&input); + } + buffer_seek(pinput, entsize); +} + +static int +phdr_read(const struct buffer *in, struct parsed_elf *pelf, + struct xdr *xdr, int bit64) +{ + struct buffer b; + Elf64_Phdr *phdr; + Elf64_Ehdr *ehdr; + int i; + + ehdr = &pelf->ehdr; + /* cons up an input buffer for the headers. + * Note that the program headers can be anywhere, + * per the ELF spec, You'd be surprised how many ELF + * readers miss this little detail. + */ + buffer_splice(&b, in, ehdr->e_phoff, ehdr->e_phentsize * ehdr->e_phnum); + if (check_size(in, ehdr->e_phoff, buffer_size(&b), "program headers")) + return -1; + + /* gather up all the phdrs. + * We do them all at once because there is more + * than one loop over all the phdrs. + */ + phdr = calloc(ehdr->e_phnum, sizeof(*phdr)); + for (i = 0; i < ehdr->e_phnum; i++) { + DEBUG("Parsing segment %d\n", i); + elf_phdr(&b, &phdr[i], ehdr->e_phentsize, xdr, bit64); + + /* Ensure the contents are valid within the elf file. */ + if (check_size(in, phdr[i].p_offset, phdr[i].p_filesz, + "segment contents")) + return -1; + } + + pelf->phdr = phdr; + + return 0; +} + +static int +shdr_read(const struct buffer *in, struct parsed_elf *pelf, + struct xdr *xdr, int bit64) +{ + struct buffer b; + Elf64_Shdr *shdr; + Elf64_Ehdr *ehdr; + int i; + + ehdr = &pelf->ehdr; + + /* cons up an input buffer for the section headers. + * Note that the section headers can be anywhere, + * per the ELF spec, You'd be surprised how many ELF + * readers miss this little detail. + */ + buffer_splice(&b, in, ehdr->e_shoff, ehdr->e_shentsize * ehdr->e_shnum); + if (check_size(in, ehdr->e_shoff, buffer_size(&b), "section headers")) + return -1; + + /* gather up all the shdrs. */ + shdr = calloc(ehdr->e_shnum, sizeof(*shdr)); + for (i = 0; i < ehdr->e_shnum; i++) { + DEBUG("Parsing section %d\n", i); + elf_shdr(&b, &shdr[i], ehdr->e_shentsize, xdr, bit64); + } + + pelf->shdr = shdr; + + return 0; +} + +static int +reloc_read(const struct buffer *in, struct parsed_elf *pelf, + struct xdr *xdr, int bit64) +{ + struct buffer b; + Elf64_Word i; + Elf64_Ehdr *ehdr; + + ehdr = &pelf->ehdr; + pelf->relocs = calloc(ehdr->e_shnum, sizeof(Elf64_Rela *)); + + /* Allocate array for each section that contains relocation entries. */ + for (i = 0; i < ehdr->e_shnum; i++) { + Elf64_Shdr *shdr; + Elf64_Rela *rela; + Elf64_Xword j; + Elf64_Xword nrelocs; + int is_rela; + + shdr = &pelf->shdr[i]; + + /* Only process REL and RELA sections. */ + if (shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA) + continue; + + DEBUG("Checking relocation section %u\n", i); + + /* Ensure the section that relocations apply is a valid. */ + if (shdr->sh_info >= ehdr->e_shnum || + shdr->sh_info == SHN_UNDEF) { + ERROR("Relocations apply to an invalid section: %u\n", + shdr[i].sh_info); + return -1; + } + + is_rela = shdr->sh_type == SHT_RELA; + + /* Determine the number relocations in this section. */ + nrelocs = shdr->sh_size / shdr->sh_entsize; + + pelf->relocs[i] = calloc(nrelocs, sizeof(Elf64_Rela)); + + buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size); + if (check_size(in, shdr->sh_offset, buffer_size(&b), + "relocation section")) { + ERROR("Relocation section %u failed.\n", i); + return -1; + } + + rela = pelf->relocs[i]; + for (j = 0; j < nrelocs; j++) { + if (bit64) { + rela->r_offset = xdr->get64(&b); + rela->r_info = xdr->get64(&b); + if (is_rela) + rela->r_addend = xdr->get64(&b); + } else { + uint32_t r_info; + + rela->r_offset = xdr->get32(&b); + r_info = xdr->get32(&b); + rela->r_info = ELF64_R_INFO(ELF32_R_SYM(r_info), + ELF32_R_TYPE(r_info)); + if (is_rela) + rela->r_addend = xdr->get32(&b); + } + rela++; + } + } + + return 0; +} + +static int strtab_read(const struct buffer *in, struct parsed_elf *pelf) +{ + Elf64_Ehdr *ehdr; + Elf64_Word i; + + ehdr = &pelf->ehdr; + + if (ehdr->e_shstrndx >= ehdr->e_shnum) { + ERROR("Section header string table index out of range: %d\n", + ehdr->e_shstrndx); + return -1; + } + + /* For each section of type SHT_STRTAB create a symtab buffer. */ + pelf->strtabs = calloc(ehdr->e_shnum, sizeof(struct buffer *)); + + for (i = 0; i < ehdr->e_shnum; i++) { + struct buffer *b; + Elf64_Shdr *shdr = &pelf->shdr[i]; + + if (shdr->sh_type != SHT_STRTAB) + continue; + + b = calloc(1, sizeof(*b)); + buffer_splice(b, in, shdr->sh_offset, shdr->sh_size); + if (check_size(in, shdr->sh_offset, buffer_size(b), "strtab")) { + ERROR("STRTAB section not within bounds: %d\n", i); + return -1; + } + pelf->strtabs[i] = b; + } + + return 0; +} + +static int +symtab_read(const struct buffer *in, struct parsed_elf *pelf, + struct xdr *xdr, int bit64) +{ + Elf64_Ehdr *ehdr; + Elf64_Shdr *shdr; + Elf64_Half i; + Elf64_Xword nsyms; + Elf64_Sym *sym; + struct buffer b; + + ehdr = &pelf->ehdr; + + shdr = NULL; + for (i = 0; i < ehdr->e_shnum; i++) { + if (pelf->shdr[i].sh_type != SHT_SYMTAB) + continue; + + if (shdr != NULL) { + ERROR("Multiple symbol sections found. %u and %u\n", + (unsigned int)(shdr - pelf->shdr), i); + return -1; + } + + shdr = &pelf->shdr[i]; + } + + if (shdr == NULL) { + ERROR("No symbol table found.\n"); + return -1; + } + + buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size); + if (check_size(in, shdr->sh_offset, buffer_size(&b), "symtab")) + return -1; + + nsyms = shdr->sh_size / shdr->sh_entsize; + + pelf->syms = calloc(nsyms, sizeof(Elf64_Sym)); + + for (i = 0; i < nsyms; i++) { + sym = &pelf->syms[i]; + + if (bit64) { + sym->st_name = xdr->get32(&b); + sym->st_info = xdr->get8(&b); + sym->st_other = xdr->get8(&b); + sym->st_shndx = xdr->get16(&b); + sym->st_value = xdr->get64(&b); + sym->st_size = xdr->get64(&b); + } else { + sym->st_name = xdr->get32(&b); + sym->st_value = xdr->get32(&b); + sym->st_size = xdr->get32(&b); + sym->st_info = xdr->get8(&b); + sym->st_other = xdr->get8(&b); + sym->st_shndx = xdr->get16(&b); + } + } + + return 0; +} + +int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags) +{ + struct xdr *xdr = &xdr_le; + int bit64 = 0; + struct buffer input; + Elf64_Ehdr *ehdr; + + /* Zero out the parsed elf structure. */ + memset(pelf, 0, sizeof(*pelf)); + + if (!iself(buffer_get(pinput))) { + ERROR("The stage file is not in ELF format!\n"); + return -1; + } + + buffer_clone(&input, pinput); + ehdr = &pelf->ehdr; + elf_eident(&input, ehdr); + bit64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64; + /* Assume LE unless we are sure otherwise. + * We're not going to take on the task of + * fully validating the ELF file. That way + * lies madness. + */ + if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) + xdr = &xdr_be; + + elf_ehdr(&input, ehdr, xdr, bit64); + + /* Relocation processing requires section header parsing. */ + if (flags & ELF_PARSE_RELOC) + flags |= ELF_PARSE_SHDR; + + /* String table processing requires section header parsing. */ + if (flags & ELF_PARSE_STRTAB) + flags |= ELF_PARSE_SHDR; + + /* Symbole table processing requires section header parsing. */ + if (flags & ELF_PARSE_SYMTAB) + flags |= ELF_PARSE_SHDR; + + if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64)) + goto fail; + + if ((flags & ELF_PARSE_SHDR) && shdr_read(pinput, pelf, xdr, bit64)) + goto fail; + + if ((flags & ELF_PARSE_RELOC) && reloc_read(pinput, pelf, xdr, bit64)) + goto fail; + + if ((flags & ELF_PARSE_STRTAB) && strtab_read(pinput, pelf)) + goto fail; + + if ((flags & ELF_PARSE_SYMTAB) && symtab_read(pinput, pelf, xdr, bit64)) + goto fail; + + return 0; + +fail: + parsed_elf_destroy(pelf); + return -1; +} + +void parsed_elf_destroy(struct parsed_elf *pelf) +{ + Elf64_Half i; + + free(pelf->phdr); + free(pelf->shdr); + if (pelf->relocs != NULL) { + for (i = 0; i < pelf->ehdr.e_shnum; i++) + free(pelf->relocs[i]); + } + free(pelf->relocs); + + if (pelf->strtabs != NULL) { + for (i = 0; i < pelf->ehdr.e_shnum; i++) + free(pelf->strtabs[i]); + } + free(pelf->strtabs); + free(pelf->syms); +} + +/* Get the headers from the buffer. + * Return -1 in the event of an error. + * The section headers are optional; if NULL + * is passed in for pshdr they won't be parsed. + * We don't (yet) make payload parsing optional + * because we've never seen a use case. + */ +int +elf_headers(const struct buffer *pinput, + Elf64_Ehdr *ehdr, + Elf64_Phdr **pphdr, + Elf64_Shdr **pshdr) +{ + + struct parsed_elf pelf; + int flags; + + flags = ELF_PARSE_PHDR; + + if (pshdr != NULL) + flags |= ELF_PARSE_SHDR; + + if (parse_elf(pinput, &pelf, flags)) + return -1; + + /* Copy out the parsed elf header. */ + memcpy(ehdr, &pelf.ehdr, sizeof(*ehdr)); + + *pphdr = calloc(ehdr->e_phnum, sizeof(Elf64_Phdr)); + memcpy(*pphdr, pelf.phdr, ehdr->e_phnum * sizeof(Elf64_Phdr)); + + if (pshdr != NULL) { + *pshdr = calloc(ehdr->e_shnum, sizeof(Elf64_Shdr)); + memcpy(*pshdr, pelf.shdr, ehdr->e_shnum * sizeof(Elf64_Shdr)); + } + + parsed_elf_destroy(&pelf); + + return 0; +} + +/* ELF Writing Support + * + * The ELF file is written according to the following layout: + * +------------------+ + * | ELF Header | + * +------------------+ + * | Section Headers | + * +------------------+ + * | Program Headers | + * +------------------+ + * | String table | + * +------------------+ <- 4KiB Aligned + * | Code/Data | + * +------------------+ + */ + +/* Arbitray maximum number of sections. */ +#define MAX_SECTIONS 16 +struct elf_writer_section { + Elf64_Shdr shdr; + struct buffer content; + const char *name; +}; + +struct elf_writer +{ + Elf64_Ehdr ehdr; + struct xdr *xdr; + size_t num_secs; + struct elf_writer_section sections[MAX_SECTIONS]; + Elf64_Phdr *phdrs; + struct elf_writer_section *shstrtab; + int bit64; +}; + +struct elf_writer *elf_writer_init(const Elf64_Ehdr *ehdr) +{ + struct elf_writer *ew; + Elf64_Shdr shdr; + struct buffer empty_buffer; + + if (!iself(ehdr)) + return NULL; + + ew = calloc(1, sizeof(*ew)); + + memcpy(&ew->ehdr, ehdr, sizeof(ew->ehdr)); + + ew->bit64 = ew->ehdr.e_ident[EI_CLASS] == ELFCLASS64; + + /* Set the endinan ops. */ + if (ew->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) + ew->xdr = &xdr_be; + else + ew->xdr = &xdr_le; + + /* Reset count and offsets */ + ew->ehdr.e_phoff = 0; + ew->ehdr.e_shoff = 0; + ew->ehdr.e_shnum = 0; + ew->ehdr.e_phnum = 0; + + memset(&empty_buffer, 0, sizeof(empty_buffer)); + memset(&shdr, 0, sizeof(shdr)); + + /* Add SHT_NULL section header. */ + shdr.sh_type = SHT_NULL; + elf_writer_add_section(ew, &shdr, &empty_buffer, NULL); + + /* Add section header string table and maintain reference to it. */ + shdr.sh_type = SHT_STRTAB; + elf_writer_add_section(ew, &shdr, &empty_buffer, ".shstrtab"); + ew->ehdr.e_shstrndx = ew->num_secs - 1; + ew->shstrtab = &ew->sections[ew->ehdr.e_shstrndx]; + + return ew; +} + +/* + * Clean up any internal state represented by ew. Aftewards the elf_writer + * is invalid. + */ +void elf_writer_destroy(struct elf_writer *ew) +{ + if (ew->phdrs != NULL) + free(ew->phdrs); + free(ew); +} + +/* + * Add a section to the ELF file. Section type, flags, and memsize are + * maintained from the passed in Elf64_Shdr. The buffer represents the + * content of the section while the name is the name of section itself. + * Returns < 0 on error, 0 on success. + */ +int elf_writer_add_section(struct elf_writer *ew, const Elf64_Shdr *shdr, + struct buffer *contents, const char *name) +{ + struct elf_writer_section *newsh; + + if (ew->num_secs == MAX_SECTIONS) + return -1; + + newsh = &ew->sections[ew->num_secs]; + ew->num_secs++; + + memcpy(&newsh->shdr, shdr, sizeof(newsh->shdr)); + newsh->shdr.sh_offset = 0; + + newsh->name = name; + if (contents != NULL) + buffer_clone(&newsh->content, contents); + + return 0; +} + +static void ehdr_write(struct elf_writer *ew, struct buffer *m) +{ + int i; + + for (i = 0; i < EI_NIDENT; i++) + ew->xdr->put8(m, ew->ehdr.e_ident[i]); + ew->xdr->put16(m, ew->ehdr.e_type); + ew->xdr->put16(m, ew->ehdr.e_machine); + ew->xdr->put32(m, ew->ehdr.e_version); + if (ew->bit64) { + ew->xdr->put64(m, ew->ehdr.e_entry); + ew->xdr->put64(m, ew->ehdr.e_phoff); + ew->xdr->put64(m, ew->ehdr.e_shoff); + } else { + ew->xdr->put32(m, ew->ehdr.e_entry); + ew->xdr->put32(m, ew->ehdr.e_phoff); + ew->xdr->put32(m, ew->ehdr.e_shoff); + } + ew->xdr->put32(m, ew->ehdr.e_flags); + ew->xdr->put16(m, ew->ehdr.e_ehsize); + ew->xdr->put16(m, ew->ehdr.e_phentsize); + ew->xdr->put16(m, ew->ehdr.e_phnum); + ew->xdr->put16(m, ew->ehdr.e_shentsize); + ew->xdr->put16(m, ew->ehdr.e_shnum); + ew->xdr->put16(m, ew->ehdr.e_shstrndx); +} + +static void shdr_write(struct elf_writer *ew, size_t n, struct buffer *m) +{ + struct xdr *xdr = ew->xdr; + int bit64 = ew->bit64; + struct elf_writer_section *sec = &ew->sections[n]; + Elf64_Shdr *shdr = &sec->shdr; + + xdr->put32(m, shdr->sh_name); + xdr->put32(m, shdr->sh_type); + if (bit64) { + xdr->put64(m, shdr->sh_flags); + xdr->put64(m, shdr->sh_addr); + xdr->put64(m, shdr->sh_offset); + xdr->put64(m, shdr->sh_size); + xdr->put32(m, shdr->sh_link); + xdr->put32(m, shdr->sh_info); + xdr->put64(m, shdr->sh_addralign); + xdr->put64(m, shdr->sh_entsize); + } else { + xdr->put32(m, shdr->sh_flags); + xdr->put32(m, shdr->sh_addr); + xdr->put32(m, shdr->sh_offset); + xdr->put32(m, shdr->sh_size); + xdr->put32(m, shdr->sh_link); + xdr->put32(m, shdr->sh_info); + xdr->put32(m, shdr->sh_addralign); + xdr->put32(m, shdr->sh_entsize); + } +} + +static void +phdr_write(struct elf_writer *ew, struct buffer *m, Elf64_Phdr *phdr) +{ + if (ew->bit64) { + ew->xdr->put32(m, phdr->p_type); + ew->xdr->put32(m, phdr->p_flags); + ew->xdr->put64(m, phdr->p_offset); + ew->xdr->put64(m, phdr->p_vaddr); + ew->xdr->put64(m, phdr->p_paddr); + ew->xdr->put64(m, phdr->p_filesz); + ew->xdr->put64(m, phdr->p_memsz); + ew->xdr->put64(m, phdr->p_align); + } else { + ew->xdr->put32(m, phdr->p_type); + ew->xdr->put32(m, phdr->p_offset); + ew->xdr->put32(m, phdr->p_vaddr); + ew->xdr->put32(m, phdr->p_paddr); + ew->xdr->put32(m, phdr->p_filesz); + ew->xdr->put32(m, phdr->p_memsz); + ew->xdr->put32(m, phdr->p_flags); + ew->xdr->put32(m, phdr->p_align); + } + +} + +/* + * Serialize the ELF file to the output buffer. Return < 0 on error, + * 0 on success. + */ +int elf_writer_serialize(struct elf_writer *ew, struct buffer *out) +{ + Elf64_Half i; + Elf64_Xword metadata_size; + Elf64_Xword program_size; + Elf64_Off shstroffset; + size_t shstrlen; + struct buffer metadata; + struct buffer phdrs; + struct buffer data; + struct buffer *strtab; + + INFO("Writing %zu sections.\n", ew->num_secs); + + /* Determine size of sections to be written. */ + program_size = 0; + /* Start with 1 byte for first byte of section header string table. */ + shstrlen = 1; + for (i = 0; i < ew->num_secs; i++) { + struct elf_writer_section *sec = &ew->sections[i]; + + if (sec->shdr.sh_flags & SHF_ALLOC) + ew->ehdr.e_phnum++; + + program_size += buffer_size(&sec->content); + + /* Keep track of the length sections' names. */ + if (sec->name != NULL) { + sec->shdr.sh_name = shstrlen; + shstrlen += strlen(sec->name) + 1; + } + } + ew->ehdr.e_shnum = ew->num_secs; + metadata_size = 0; + metadata_size += ew->ehdr.e_ehsize; + metadata_size += ew->ehdr.e_shnum * ew->ehdr.e_shentsize; + metadata_size += ew->ehdr.e_phnum * ew->ehdr.e_phentsize; + shstroffset = metadata_size; + /* Align up section header string size and metadata size to 4KiB */ + metadata_size = ALIGN(metadata_size + shstrlen, 4096); + + if (buffer_create(out, metadata_size + program_size, "elfout")) { + ERROR("Could not create output buffer for ELF.\n"); + return -1; + } + + INFO("Created %zu output buffer for ELF file.\n", buffer_size(out)); + + /* + * Write out ELF header. Section headers come right after ELF header + * followed by the program headers. Buffers need to be created first + * to do the writing. + */ + ew->ehdr.e_shoff = ew->ehdr.e_ehsize; + ew->ehdr.e_phoff = ew->ehdr.e_shoff + + ew->ehdr.e_shnum * ew->ehdr.e_shentsize; + + buffer_splice(&metadata, out, 0, metadata_size); + buffer_splice(&phdrs, out, ew->ehdr.e_phoff, + ew->ehdr.e_phnum * ew->ehdr.e_phentsize); + buffer_splice(&data, out, metadata_size, program_size); + /* Set up the section header string table contents. */ + strtab = &ew->shstrtab->content; + buffer_splice(strtab, out, shstroffset, shstrlen); + ew->shstrtab->shdr.sh_size = shstrlen; + + /* Reset current locations. */ + buffer_set_size(&metadata, 0); + buffer_set_size(&data, 0); + buffer_set_size(&phdrs, 0); + buffer_set_size(strtab, 0); + + /* ELF Header */ + ehdr_write(ew, &metadata); + + /* Write out section headers, section strings, section content, and + * program headers. */ + ew->xdr->put8(strtab, 0); + for (i = 0; i < ew->num_secs; i++) { + Elf64_Phdr phdr; + struct elf_writer_section *sec = &ew->sections[i]; + + /* Update section offsets. Be sure to not update SHT_NULL. */ + if (sec == ew->shstrtab) + sec->shdr.sh_offset = shstroffset; + else if (i != 0) + sec->shdr.sh_offset = buffer_size(&data) + + metadata_size; + shdr_write(ew, i, &metadata); + + /* Add section name to string table. */ + if (sec->name != NULL) + bputs(strtab, sec->name, strlen(sec->name) + 1); + + if (!(sec->shdr.sh_flags & SHF_ALLOC)) + continue; + + bputs(&data, buffer_get(&sec->content), + buffer_size(&sec->content)); + + phdr.p_type = PT_LOAD; + phdr.p_offset = sec->shdr.sh_offset; + phdr.p_vaddr = sec->shdr.sh_addr; + phdr.p_paddr = sec->shdr.sh_addr; + phdr.p_filesz = buffer_size(&sec->content); + phdr.p_memsz = sec->shdr.sh_size; + phdr.p_flags = 0; + if (sec->shdr.sh_flags & SHF_EXECINSTR) + phdr.p_flags |= PF_X | PF_R; + if (sec->shdr.sh_flags & SHF_WRITE) + phdr.p_flags |= PF_W; + phdr.p_align = sec->shdr.sh_addralign; + phdr_write(ew, &phdrs, &phdr); + } + + return 0; +} diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h new file mode 100644 index 0000000000..0db1c595a2 --- /dev/null +++ b/util/cbfstool/elfparsing.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef ELFPARSING_H +#define ELFPARSING_H + +#include "elf.h" +#include "common.h" + +struct parsed_elf { + Elf64_Ehdr ehdr; + Elf64_Phdr *phdr; + Elf64_Shdr *shdr; + /* + * The relocs array contains pointers to arrays of relocation + * structures. Each index into the relocs array corresponds to its + * corresponding section index. i.e. if a section i is of type SHT_REL + * or SHT_RELA then the corresponding index into the relocs array will + * contain the associated relocations. Otherwise thee entry will be + * NULL. + */ + Elf64_Rela **relocs; + /* + * Similarly to the relocs array the strtabs array consists of an + * array of pointers where each entry represents a potential struct + * buffer pointer. Only setions of type SHT_STRTAB will have a non-NULL + * entry. + */ + struct buffer **strtabs; + /* Parsed symbols. */ + Elf64_Sym *syms; +}; + +#define ELF_PARSE_PHDR (1 << 0) +#define ELF_PARSE_SHDR (1 << 1) +#define ELF_PARSE_RELOC (1 << 2) +#define ELF_PARSE_STRTAB (1 << 3) +#define ELF_PARSE_SYMTAB (1 << 4) + +#define ELF_PARSE_ALL (-1) + +/* + * Parse an ELF file contained within provide struct buffer. The ELF header + * is always parsed while the flags value containing the ELF_PARSE_* values + * determine if other parts of the ELF file will be parsed as well. + * Returns 0 on success, < 0 error. + */ +int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags); + +/* + * Clean up memory associated with parsed_elf. + */ +void parsed_elf_destroy(struct parsed_elf *pelf); + + +int +elf_headers(const struct buffer *pinput, + Elf64_Ehdr *ehdr, + Elf64_Phdr **pphdr, + Elf64_Shdr **pshdr); + +/* ELF writing support. */ +struct elf_writer; + +/* + * Initialize a new ELF writer. Deafult machine type, endianness, etc is + * copied from the passed in Elf64_Ehdr. Returns NULL on failure, valid + * pointer on success. + */ +struct elf_writer *elf_writer_init(const Elf64_Ehdr *ehdr); + +/* + * Clean up any internal state represented by ew. Aftewards the elf_writer + * is invalid. + */ +void elf_writer_destroy(struct elf_writer *ew); + +/* + * Add a section to the ELF file. Section type, flags, and memsize are + * maintained from the passed in Elf64_Shdr. The buffer represents the + * content of the section while the name is the name of section itself. + * Returns < 0 on error, 0 on success. + */ +int elf_writer_add_section(struct elf_writer *ew, const Elf64_Shdr *shdr, + struct buffer *contents, const char *name); + +/* + * Serialize the ELF file to the output buffer. Return < 0 on error, + * 0 on success. + */ +int elf_writer_serialize(struct elf_writer *ew, struct buffer *out); + +#endif /* ELFPARSING_H */ diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index 12a7e3b49f..ed136a6cff 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -187,17 +187,28 @@ static void add_microcodde_entries(struct cbfs_image *image, } } +static int fit_header(void *ptr, uint32_t *current_offset, uint32_t *file_length) +{ + struct buffer buf; + struct cbfs_file header; + buf.data = ptr; + buf.size = sizeof(header); + cbfs_file_get_header(&buf, &header); + *current_offset = header.offset; + *file_length = header.len; + return 0; +} + static int parse_microcode_blob(struct cbfs_image *image, struct cbfs_file *mcode_file, struct microcode_entry *mcus, int *total_mcus) { int num_mcus; - int current_offset; - int file_length; + uint32_t current_offset; + uint32_t file_length; current_offset = (int)((char *)mcode_file - image->buffer.data); - current_offset += ntohl(mcode_file->offset); - file_length = ntohl(mcode_file->len); + fit_header(mcode_file, ¤t_offset, &file_length); num_mcus = 0; while (file_length > sizeof(struct microcode_header)) @@ -206,6 +217,10 @@ static int parse_microcode_blob(struct cbfs_image *image, mcu_header = rom_buffer_pointer(image, current_offset); + /* Quickly sanity check a prospective microcode update. */ + if (mcu_header->total_size < sizeof(*mcu_header)) + break; + /* FIXME: Should the checksum be validated? */ mcus[num_mcus].offset = current_offset; mcus[num_mcus].size = mcu_header->total_size; @@ -215,10 +230,6 @@ static int parse_microcode_blob(struct cbfs_image *image, num_mcus++; file_length -= mcus[num_mcus].size; - /* Can't determine any more entries. */ - if (!mcu_header->total_size) - break; - /* Reached limit of FIT entries. */ if (num_mcus == *total_mcus) break; diff --git a/util/cbfstool/linux.h b/util/cbfstool/linux.h new file mode 100644 index 0000000000..0b89b9ca06 --- /dev/null +++ b/util/cbfstool/linux.h @@ -0,0 +1,191 @@ +/* + * This file is part of coreboot.. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Linux/i386 loader + * Supports bzImage, zImage and Image format. + * + * Based on work by Steve Gehlbach. + * Portions are taken from mkelfImage. + * + * 2003-09 by SONE Takeshi + */ + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#define LINUX_PARAM_LOC 0x90000 +#define COMMAND_LINE_LOC 0x91000 +#define GDT_LOC 0x92000 +#define STACK_LOC 0x93000 + +#define E820MAX 32 /* number of entries in E820MAP */ +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 +}; + +/* The header of Linux/i386 kernel */ +struct linux_header { + u8 reserved1[0x1f1]; /* 0x000 */ + u8 setup_sects; /* 0x1f1 */ + u16 root_flags; /* 0x1f2 */ + u32 syssize; /* 0x1f4 (2.04) */ + u8 reserved2[2]; /* 0x1f8 */ + u16 vid_mode; /* 0x1fa */ + u16 root_dev; /* 0x1fc */ + u16 boot_sector_magic; /* 0x1fe */ + /* 2.00 */ + u8 reserved3[2]; /* 0x200 */ + u8 header_magic[4]; /* 0x202 */ + u16 protocol_version; /* 0x206 */ + u32 realmode_swtch; /* 0x208 */ + u16 start_sys; /* 0x20c */ + u16 kver_addr; /* 0x20e */ + u8 type_of_loader; /* 0x210 */ + u8 loadflags; /* 0x211 */ + u16 setup_move_size; /* 0x212 */ + u32 code32_start; /* 0x214 */ + u32 ramdisk_image; /* 0x218 */ + u32 ramdisk_size; /* 0x21c */ + u8 reserved4[4]; /* 0x220 */ + /* 2.01 */ + u16 heap_end_ptr; /* 0x224 */ + u8 reserved5[2]; /* 0x226 */ + /* 2.02 */ + u32 cmd_line_ptr; /* 0x228 */ + /* 2.03 */ + u32 initrd_addr_max; /* 0x22c */ + /* 2.05 */ + u32 kernel_alignment; /* 0x230 */ + u8 relocatable_kernel; /* 0x234 */ + u8 min_alignment; /* 0x235 (2.10) */ + u8 reserved6[2]; /* 0x236 */ + /* 2.06 */ + u32 cmdline_size; /* 0x238 */ + /* 2.07 */ + u32 hardware_subarch; /* 0x23c */ + u64 hardware_subarch_data;/* 0x240 */ + /* 2.08 */ + u32 payload_offset; /* 0x248 */ + u32 payload_length; /* 0x24c */ + /* 2.09 */ + u64 setup_data; /* 0x250 */ + /* 2.10 */ + u64 pref_address; /* 0x258 */ + u32 init_size; /* 0x260 */ +} __attribute__ ((packed)); + +/* Paramters passed to 32-bit part of Linux + * This is another view of the structure above.. */ +struct linux_params { + u8 orig_x; /* 0x00 */ + u8 orig_y; /* 0x01 */ + u16 ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + u16 orig_video_page; /* 0x04 */ + u8 orig_video_mode; /* 0x06 */ + u8 orig_video_cols; /* 0x07 */ + u16 unused2; /* 0x08 */ + u16 orig_video_ega_bx; /* 0x0a */ + u16 unused3; /* 0x0c */ + u8 orig_video_lines; /* 0x0e */ + u8 orig_video_isVGA; /* 0x0f */ + u16 orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + u16 lfb_width; /* 0x12 */ + u16 lfb_height; /* 0x14 */ + u16 lfb_depth; /* 0x16 */ + u32 lfb_base; /* 0x18 */ + u32 lfb_size; /* 0x1c */ + u16 cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + u16 cl_offset; /* 0x22 */ + u16 lfb_linelength; /* 0x24 */ + u8 red_size; /* 0x26 */ + u8 red_pos; /* 0x27 */ + u8 green_size; /* 0x28 */ + u8 green_pos; /* 0x29 */ + u8 blue_size; /* 0x2a */ + u8 blue_pos; /* 0x2b */ + u8 rsvd_size; /* 0x2c */ + u8 rsvd_pos; /* 0x2d */ + u16 vesapm_seg; /* 0x2e */ + u16 vesapm_off; /* 0x30 */ + u16 pages; /* 0x32 */ + u8 reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + //struct apm_bios_info apm_bios_info; /* 0x40 */ + u8 apm_bios_info[0x40]; + //struct drive_info_struct drive_info; /* 0x80 */ + u8 drive_info[0x20]; + //struct sys_desc_table sys_desc_table; /* 0xa0 */ + u8 sys_desc_table[0x140]; + u32 alt_mem_k; /* 0x1e0 */ + u8 reserved5[4]; /* 0x1e4 */ + u8 e820_map_nr; /* 0x1e8 */ + u8 reserved6[9]; /* 0x1e9 */ + u16 mount_root_rdonly; /* 0x1f2 */ + u8 reserved7[4]; /* 0x1f4 */ + u16 ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + u8 reserved8[2]; /* 0x1fa */ + u16 orig_root_dev; /* 0x1fc */ + u8 reserved9[1]; /* 0x1fe */ + u8 aux_device_info; /* 0x1ff */ + u8 reserved10[2]; /* 0x200 */ + u8 param_block_signature[4]; /* 0x202 */ + u16 param_block_version; /* 0x206 */ + u8 reserved11[8]; /* 0x208 */ + u8 loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + u8 loader_flags; /* 0x211 */ + u8 reserved12[2]; /* 0x212 */ + u32 kernel_start; /* 0x214 */ + u32 initrd_start; /* 0x218 */ + u32 initrd_size; /* 0x21c */ + u8 reserved12_5[8]; /* 0x220 */ + u32 cmd_line_ptr; /* 0x228 */ + u32 initrd_addr_max; /* 0x22c */ + u32 kernel_alignment; /* 0x230 */ + u8 relocatable_kernel; /* 0x234 */ + u8 reserved13[155]; /* 0x22c */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + u8 reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + /* Command line is copied here by 32-bit i386/kernel/head.S. + * So I will follow the boot protocol, rather than putting it + * directly here. --ts1 */ + u8 command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + u8 reserved17[1792]; /* 0x900 - 0x1000 */ +}; + diff --git a/util/cbfstool/linux_trampoline.c b/util/cbfstool/linux_trampoline.c new file mode 100644 index 0000000000..1bb6fef27c --- /dev/null +++ b/util/cbfstool/linux_trampoline.c @@ -0,0 +1,141 @@ +/* + * linux_trampoline + * + * Copyright (C) 2013 Patrick Georgi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#if 0 +/* NOTE: THIS CODE MUST REMAIN POSITION INDEPENDENT + * IT SHOULDN'T USE THE STACK + * AND IN GENERAL EXPECT NOTHING BUT RAM TO WORK + */ +.code32 +data +#define HEADER_SIG 0x4f49424c // LBIO little endian +#define CB_TAG_FORWARD 0x11 +#define CB_TAG_MEMORY 0x1 +#define CB_TAG_FRAMEBUFFER 0x12 + +#define LINUX_PARAM_LOC 0x90000 +#define E820_NR_OFFSET 0x1e8 +#define LINUX_ENTRY_OFFSET 0x214 +#define E820_OFFSET 0x2d0 + +.trampoline_start: + +cld +xor %edx, %edx +mov $0, %ecx + +.headerSearch: +mov $0x10000, %ebx +add %ecx, %ebx +mov (%ecx), %eax +cmp $HEADER_SIG, %eax +je .headerSearchDone // found the header +add $16, %ecx +cmp %ecx, %ebx +jne .headerSearch + +.headerSearchDone: +cmp %ecx, %ebx // reached the end == not found anything? +je 2f // give up + +// we assume the checksum is okay, no test +mov 4(%ecx), %ebx +add %ecx, %ebx // ebx = cb_header + header_bytes +mov 20(%ecx), %ecx // ecx = table_entries + +.tableScan: +cmp $CB_TAG_FORWARD, (%ebx) +jne .testMemory + +/* forward tag: assume 32bit pointer */ +mov 8(%ebx), %ecx +jmp .headerSearch + +.testMemory: +cmp $CB_TAG_MEMORY, (%ebx) +jne .testFramebuffer + +/* memory tag: copy e820 map and entry count. also determine alt_mem_k */ +mov 4(%ebx), %eax +sub $8, %eax +shr $2, %eax /* eax = number of dwords of e820 data */ +cmp $(32 * 5), %eax /* linux wants at most 32 entries of 5 dwords */ +jng 1f +mov $(32 * 5), %eax /* only copy 32 entries */ +1: +mov %eax, %esi +mov $5, %edi +div %edi +mov %eax, (LINUX_PARAM_LOC + E820_NR_OFFSET) +mov %esi, %eax +xchg %eax, %ecx +lea 8(%ebx), %esi /* e820 data source */ +mov $(LINUX_PARAM_LOC + E820_OFFSET), %edi +rep movsl +xchg %eax, %ecx +jmp .endScan + +.testFramebuffer: +cmp $CB_TAG_FRAMEBUFFER, (%ebx) +jne .endScan +/* TODO: handle framebuffer tag */ + +.endScan: +add 4(%ebx), %ebx +dec %ecx +jnz .tableScan + +/* finally: jump to kernel */ +mov $LINUX_PARAM_LOC, %esi +jmp *(LINUX_PARAM_LOC + LINUX_ENTRY_OFFSET) + + +2: +hlt +jmp 2b + +.trampoline_end: + +.global trampoline_start, trampoline_size +trampoline_start: +.long .trampoline_start +trampoline_size: +.long .trampoline_end - .trampoline_start +#endif + +/* The code above is hand-crafted to fit various contraints. + * To simplify porting, the below matches the above. + * When changing any code in here, compile the above as a .S + * file, objcopy it to binary and paste the result below (minus + * the last 8 bytes which are trampoline_start and trampoline_size). + */ +const unsigned char trampoline[] = { +0xfc, 0x31, 0xd2, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x01, 0xcb, 0x8b, +0x01, 0x3d, 0x4c, 0x42, 0x49, 0x4f, 0x74, 0x07, 0x83, 0xc1, 0x10, 0x39, 0xcb, 0x75, 0xe9, 0x39, +0xcb, 0x74, 0x60, 0x8b, 0x59, 0x04, 0x01, 0xcb, 0x8b, 0x49, 0x14, 0x83, 0x3b, 0x11, 0x75, 0x05, +0x8b, 0x4b, 0x08, 0xeb, 0xd3, 0x83, 0x3b, 0x01, 0x75, 0x33, 0x8b, 0x43, 0x04, 0x83, 0xe8, 0x08, +0xc1, 0xe8, 0x02, 0x3d, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0x05, 0xb8, 0xa0, 0x00, 0x00, 0x00, 0x89, +0xc6, 0xbf, 0x05, 0x00, 0x00, 0x00, 0xf7, 0xf7, 0xa3, 0xe8, 0x01, 0x09, 0x00, 0x89, 0xf0, 0x91, +0x8d, 0x73, 0x08, 0xbf, 0xd0, 0x02, 0x09, 0x00, 0xf3, 0xa5, 0x91, 0xeb, 0x05, 0x83, 0x3b, 0x12, +0x75, 0x00, 0x03, 0x5b, 0x04, 0x49, 0x75, 0xb3, 0xbe, 0x00, 0x00, 0x09, 0x00, 0xff, 0x25, 0x14, +0x02, 0x09, 0x00, 0xf4, 0xeb, 0xfd +}; + +void * const trampoline_start = &trampoline; +const unsigned long trampoline_size = sizeof trampoline; diff --git a/util/cbfstool/lzma/C/LzmaEnc.c b/util/cbfstool/lzma/C/LzmaEnc.c index aca097dae0..ea8b5ca4bb 100644 --- a/util/cbfstool/lzma/C/LzmaEnc.c +++ b/util/cbfstool/lzma/C/LzmaEnc.c @@ -88,7 +88,7 @@ UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) #define kDicLogSizeMaxCompress 30 -#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } +#define BSR2_RET(pos, res) { unsigned long _i; _BitScanReverse(&_i, (pos)); res = (_i + _i) + ((pos >> (_i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { @@ -119,9 +119,9 @@ static void LzmaEnc_FastPosInit(Byte *g_FastPos) } } -#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ +#define BSR2_RET(pos, res) { UInt32 _i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ - res = p->g_FastPos[pos >> i] + (i * 2); } + res = p->g_FastPos[pos >> _i] + (_i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ @@ -1123,11 +1123,9 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) for (;;) { - UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; - UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + UInt32 numAvailFull, newLen, posPrev, state, startLen; + UInt32 curPrice, curAnd1Price; Bool nextIsChar; - Byte curByte, matchByte; - const Byte *data; COptimal *curOpt; COptimal *nextOpt; @@ -1190,7 +1188,6 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { - UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; @@ -1199,7 +1196,6 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) } else { - UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; @@ -1396,7 +1392,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) } if (newLen >= startLen) { - UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) @@ -1454,8 +1450,6 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; - UInt32 curAndLenPrice; - COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); @@ -1663,7 +1657,6 @@ static void FillDistancesPrices(CLzmaEnc *p) { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; - UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) diff --git a/util/cbfstool/lzma/lzma.c b/util/cbfstool/lzma/lzma.c index 579784eae0..c1c9454e2c 100644 --- a/util/cbfstool/lzma/lzma.c +++ b/util/cbfstool/lzma/lzma.c @@ -47,12 +47,12 @@ static void put_64(void *p, uint64_t value) /* Memory Allocation API */ -static void *SzAlloc(void *unused, size_t size) +static void *SzAlloc(unused void *u, size_t size) { return malloc(size); } -static void SzFree(void *unused, void *address) +static void SzFree(unused void *u, void *address) { free(address); } @@ -69,7 +69,7 @@ typedef struct { static vector_t instream, outstream; -static SRes Read(void *unused, void *buf, size_t *size) +static SRes Read(unused void *u, void *buf, size_t *size) { if ((instream.size - instream.pos) < *size) *size = instream.size - instream.pos; @@ -78,7 +78,7 @@ static SRes Read(void *unused, void *buf, size_t *size) return SZ_OK; } -static size_t Write(void *unused, const void *buf, size_t size) +static size_t Write(unused void *u, const void *buf, size_t size) { if(outstream.size - outstream.pos < size) size = outstream.size - outstream.pos; @@ -99,11 +99,11 @@ static ISeqOutStream os = { Write }; * @param out_len a pointer to the compressed length of in */ -void do_lzma_compress(char *in, int in_len, char *out, int *out_len) +int do_lzma_compress(char *in, int in_len, char *out, int *out_len) { if (in_len == 0) { ERROR("LZMA: Input length is zero.\n"); - return; + return -1; } CLzmaEncProps props; @@ -135,7 +135,7 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) int res = LzmaEnc_SetProps(p, &props); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_SetProps failed.\n"); - return; + return -1; } unsigned char propsEncoded[LZMA_PROPS_SIZE + 8]; @@ -143,7 +143,7 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) res = LzmaEnc_WriteProperties(p, propsEncoded, &propsSize); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_WriteProperties failed.\n"); - return; + return -1; } instream.p = in; @@ -160,17 +160,18 @@ void do_lzma_compress(char *in, int in_len, char *out, int *out_len) res = LzmaEnc_Encode(p, &os, &is, 0, &LZMAalloc, &LZMAalloc); if (res != SZ_OK) { ERROR("LZMA: LzmaEnc_Encode failed %d.\n", res); - return; + return -1; } *out_len = outstream.pos; + return 0; } -void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) +int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) { if (src_len <= LZMA_PROPS_SIZE + 8) { ERROR("LZMA: Input length is too small.\n"); - return; + return -1; } uint64_t out_sizemax = get_64(&src[LZMA_PROPS_SIZE]); @@ -178,7 +179,7 @@ void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) if (out_sizemax > (size_t) dst_len) { ERROR("Not copying %d bytes to %d-byte buffer!\n", (unsigned int)out_sizemax, dst_len); - return; + return -1; } ELzmaStatus status; @@ -195,6 +196,8 @@ void do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len) if (res != SZ_OK) { ERROR("Error while decompressing.\n"); - return; + return -1; } + + return 0; } diff --git a/util/cbfstool/rmodtool.c b/util/cbfstool/rmodtool.c new file mode 100644 index 0000000000..1455cd9a3b --- /dev/null +++ b/util/cbfstool/rmodtool.c @@ -0,0 +1,106 @@ +/* + * cbfstool, CLI utility for creating rmodules + * + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "common.h" +#include "rmodule.h" + +static const char *optstring = "i:o:vh?"; +static struct option long_options[] = { + {"inelf", required_argument, 0, 'i' }, + {"outelf", required_argument, 0, 'o' }, + {"verbose", no_argument, 0, 'v' }, + {"help", no_argument, 0, 'h' }, + {NULL, 0, 0, 0 } +}; + +static void usage(char *name) +{ + printf( + "rmodtool: utility for creating rmodules\n\n" + "USAGE: %s [-h] [-v] <-i|--inelf name> <-o|--outelf name>\n", + name + ); +} + +int main(int argc, char *argv[]) +{ + int c; + struct buffer elfin; + struct buffer elfout; + const char *input_file = NULL; + const char *output_file = NULL; + + if (argc < 3) { + usage(argv[0]); + return 1; + } + + while (1) { + int optindex = 0; + + c = getopt_long(argc, argv, optstring, long_options, &optindex); + + if (c == -1) + break; + + switch (c) { + case 'i': + input_file = optarg; + break; + case 'h': + usage(argv[0]); + return 1; + case 'o': + output_file = optarg; + break; + case 'v': + verbose++; + break; + default: + break; + } + } + + if (input_file == NULL || output_file == NULL) { + usage(argv[0]); + return 1; + } + + if (buffer_from_file(&elfin, input_file)) { + ERROR("Couldn't read in file '%s'.\n", input_file); + return 1; + } + + if (rmodule_create(&elfin, &elfout)) { + ERROR("Unable to create rmodule from '%s'.\n", input_file); + return 1; + } + + if (buffer_write_file(&elfout, output_file)) { + ERROR("Unable to write rmodule elf '%s'.\n", output_file); + return 1; + } + + return 0; +} diff --git a/util/cbfstool/rmodule.c b/util/cbfstool/rmodule.c new file mode 100644 index 0000000000..25b5f38b7c --- /dev/null +++ b/util/cbfstool/rmodule.c @@ -0,0 +1,691 @@ +/* + ;* Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include + +#include "elfparsing.h" +#include "rmodule.h" +#include "../../src/include/rmodule-defs.h" + +struct rmod_context; + +struct arch_ops { + int arch; + /* Determine if relocation is a valid type for the architecture. */ + int (*valid_type)(struct rmod_context *ctx, Elf64_Rela *rel); + /* Determine if relocation should be emitted. */ + int (*should_emit)(struct rmod_context *ctx, Elf64_Rela *rel); +}; + +struct rmod_context { + /* Ops to process relocations. */ + struct arch_ops *ops; + + /* endian conversion ops */ + struct xdr *xdr; + + /* Parsed ELF sturcture. */ + struct parsed_elf pelf; + /* Program segment. */ + Elf64_Phdr *phdr; + + /* Collection of relocation addresses fixup in the module. */ + Elf64_Xword nrelocs; + Elf64_Addr *emitted_relocs; + + /* The following fields are addresses within the linked program. */ + Elf64_Addr link_addr; + Elf64_Addr entry; + Elf64_Addr parameters_begin; + Elf64_Addr parameters_end; + Elf64_Addr bss_begin; + Elf64_Addr bss_end; + Elf64_Xword size; +}; + +/* + * Architecture specific support operations. + */ +static int valid_reloc_386(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + /* Only these 2 relocations are expected to be found. */ + return (type == R_386_32 || type == R_386_PC32); +} + +static int should_emit_386(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + /* R_386_32 relocations are absolute. Must emit these. */ + return (type == R_386_32); +} + +static int valid_reloc_arm(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + /* Only these 6 relocations are expected to be found. */ + return (type == R_ARM_ABS32 || type == R_ARM_THM_PC22 || + type == R_ARM_THM_JUMP24 || type == R_ARM_V4BX || + type == R_ARM_CALL || type == R_ARM_JUMP24); +} + +static int should_emit_arm(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + /* R_ARM_ABS32 relocations are absolute. Must emit these. */ + return (type == R_ARM_ABS32); +} + +static int valid_reloc_aarch64(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + return (type == R_AARCH64_ADR_PREL_PG_HI21 || + type == R_AARCH64_ADD_ABS_LO12_NC || + type == R_AARCH64_LDST8_ABS_LO12_NC || + type == R_AARCH64_JUMP26 || + type == R_AARCH64_LDST32_ABS_LO12_NC || + type == R_AARCH64_LDST64_ABS_LO12_NC || + type == R_AARCH64_CALL26 || + type == R_AARCH64_ABS64 || + type == R_AARCH64_LD_PREL_LO19 || + type == R_AARCH64_ADR_PREL_LO21); +} + +static int should_emit_aarch64(struct rmod_context *ctx, Elf64_Rela *rel) +{ + int type; + + type = ELF64_R_TYPE(rel->r_info); + + return (type == R_AARCH64_ABS64); +} + +static struct arch_ops reloc_ops[] = { + { + .arch = EM_386, + .valid_type = valid_reloc_386, + .should_emit = should_emit_386, + }, + { + .arch = EM_ARM, + .valid_type = valid_reloc_arm, + .should_emit = should_emit_arm, + }, + { + .arch = EM_AARCH64, + .valid_type = valid_reloc_aarch64, + .should_emit = should_emit_aarch64, + }, +}; + +/* + * Relocation processing loops. + */ + +static int for_each_reloc(struct rmod_context *ctx, int do_emit) +{ + Elf64_Half i; + struct parsed_elf *pelf = &ctx->pelf; + + for (i = 0; i < pelf->ehdr.e_shnum; i++) { + Elf64_Shdr *shdr; + Elf64_Rela *relocs; + Elf64_Xword nrelocs; + Elf64_Xword j; + + relocs = pelf->relocs[i]; + + /* No relocations in this section. */ + if (relocs == NULL) + continue; + + shdr = &pelf->shdr[i]; + nrelocs = shdr->sh_size / shdr->sh_entsize; + + for (j = 0; j < nrelocs; j++) { + Elf64_Rela *r = &relocs[j]; + + if (!ctx->ops->valid_type(ctx, r)) { + ERROR("Invalid reloc type: %u\n", + (unsigned int)ELF64_R_TYPE(r->r_info)); + return -1; + } + + if (ctx->ops->should_emit(ctx, r)) { + int n = ctx->nrelocs; + if (do_emit) + ctx->emitted_relocs[n] = r->r_offset; + ctx->nrelocs++; + } + } + } + + return 0; +} + +static int find_program_segment(struct rmod_context *ctx) +{ + int i; + int nsegments; + struct parsed_elf *pelf; + Elf64_Phdr *phdr; + + pelf = &ctx->pelf; + + /* Silence 'may be used unitilized in this function' warnings. */ + phdr = NULL; + + /* There should only be a single loadable segment. */ + nsegments = 0; + for (i = 0; i < pelf->ehdr.e_phnum; i++) { + if (pelf->phdr[i].p_type != PT_LOAD) + continue; + phdr = &pelf->phdr[i]; + nsegments++; + } + + if (nsegments != 1) { + ERROR("Unexepcted number of loadable segments: %d.\n", + nsegments); + return -1; + } + + INFO("Segment at 0x%0llx, file size 0x%0llx, mem size 0x%0llx.\n", + (long long)phdr->p_vaddr, (long long)phdr->p_filesz, + (long long)phdr->p_memsz); + + ctx->phdr = phdr; + + return 0; +} + +static int +filter_relocation_sections(struct rmod_context *ctx) +{ + int i; + const char *shstrtab; + struct parsed_elf *pelf; + const Elf64_Phdr *phdr; + + pelf = &ctx->pelf; + phdr = ctx->phdr; + shstrtab = buffer_get(pelf->strtabs[pelf->ehdr.e_shstrndx]); + + /* + * Find all relocation sections that contain relocation entries + * for sections that fall within the bounds of the segment. For + * easier processing the pointer to the relocation array for the + * sections that don't fall within the loadable program are NULL'd + * out. + */ + for (i = 0; i < pelf->ehdr.e_shnum; i++) { + Elf64_Shdr *shdr; + Elf64_Word sh_info; + const char *section_name; + + shdr = &pelf->shdr[i]; + + /* Ignore non-relocation sections. */ + if (shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL) + continue; + + /* Obtain section which relocations apply. */ + sh_info = shdr->sh_info; + shdr = &pelf->shdr[sh_info]; + + section_name = &shstrtab[shdr->sh_name]; + DEBUG("Relocation section found for '%s' section.\n", + section_name); + + /* Do not process relocations for debug sections. */ + if (strstr(section_name, ".debug") != NULL) { + pelf->relocs[i] = NULL; + continue; + } + + /* + * If relocations apply to a non program section ignore the + * relocations for future processing. + */ + if (shdr->sh_type != SHT_PROGBITS) { + pelf->relocs[i] = NULL; + continue; + } + + if (shdr->sh_addr < phdr->p_vaddr || + ((shdr->sh_addr + shdr->sh_size) > + (phdr->p_vaddr + phdr->p_memsz))) { + ERROR("Relocations being applied to section %d not " + "within segment region.\n", sh_info); + return -1; + } + } + + return 0; +} + +static int vaddr_cmp(const void *a, const void *b) +{ + const Elf64_Addr *pa = a; + const Elf64_Addr *pb = b; + + if (*pa < *pb) + return -1; + if (*pa > *pb) + return 1; + return 0; +} + +static int collect_relocations(struct rmod_context *ctx) +{ + int nrelocs; + + /* + * The relocs array in the pelf should only contain relocations that + * apply to the program. Count the number relocations. Then collect + * them into the allocated buffer. + */ + if (for_each_reloc(ctx, 0)) + return -1; + + nrelocs = ctx->nrelocs; + INFO("%d relocations to be emitted.\n", nrelocs); + if (!nrelocs) + return 0; + + /* Reset the counter for indexing into the array. */ + ctx->nrelocs = 0; + ctx->emitted_relocs = calloc(nrelocs, sizeof(Elf64_Addr)); + /* Write out the relocations into the emitted_relocs array. */ + if (for_each_reloc(ctx, 1)) + return -1; + + if (ctx->nrelocs != nrelocs) { + ERROR("Mismatch counted and emitted relocations: %zu vs %zu.\n", + (size_t)nrelocs, (size_t)ctx->nrelocs); + return -1; + } + + /* Sort the relocations by their address. */ + qsort(ctx->emitted_relocs, nrelocs, sizeof(Elf64_Addr), vaddr_cmp); + + return 0; +} + +static int +populate_sym(struct rmod_context *ctx, const char *sym_name, Elf64_Addr *addr, + int nsyms, const char *strtab) +{ + int i; + Elf64_Sym *syms; + + syms = ctx->pelf.syms; + + for (i = 0; i < nsyms; i++) { + if (syms[i].st_name == 0) + continue; + if (strcmp(sym_name, &strtab[syms[i].st_name])) + continue; + DEBUG("%s -> 0x%llx\n", sym_name, (long long)syms[i].st_value); + *addr = syms[i].st_value; + return 0; + } + ERROR("symbol '%s' not found.\n", sym_name); + return -1; +} + +static int populate_program_info(struct rmod_context *ctx) +{ + int i; + const char *strtab; + struct parsed_elf *pelf; + Elf64_Ehdr *ehdr; + int nsyms; + + pelf = &ctx->pelf; + ehdr = &pelf->ehdr; + + /* Obtain the string table. */ + strtab = NULL; + for (i = 0; i < ehdr->e_shnum; i++) { + if (ctx->pelf.strtabs[i] == NULL) + continue; + /* Don't use the section headers' string table. */ + if (i == ehdr->e_shstrndx) + continue; + strtab = buffer_get(ctx->pelf.strtabs[i]); + break; + } + + if (strtab == NULL) { + ERROR("No string table found.\n"); + return -1; + } + + /* Determine number of symbols. */ + nsyms = 0; + for (i = 0; i < ehdr->e_shnum; i++) { + if (pelf->shdr[i].sh_type != SHT_SYMTAB) + continue; + + nsyms = pelf->shdr[i].sh_size / pelf->shdr[i].sh_entsize; + break; + } + + if (populate_sym(ctx, "_module_params_begin", &ctx->parameters_begin, + nsyms, strtab)) + return -1; + + if (populate_sym(ctx, "_module_params_end", &ctx->parameters_end, + nsyms, strtab)) + return -1; + + if (populate_sym(ctx, "_bss", &ctx->bss_begin, nsyms, strtab)) + return -1; + + if (populate_sym(ctx, "_ebss", &ctx->bss_end, nsyms, strtab)) + return -1; + + if (populate_sym(ctx, "__rmodule_entry", &ctx->entry, nsyms, strtab)) + return -1; + + /* Link address is the virtual address of the program segment. */ + ctx->link_addr = ctx->phdr->p_vaddr; + + /* The program size is the memsz of the program segment. */ + ctx->size = ctx->phdr->p_memsz; + + return 0; +} + +static int +add_section(struct elf_writer *ew, struct buffer *data, const char *name, + Elf64_Addr addr, Elf64_Word size) +{ + Elf64_Shdr shdr; + int ret; + + memset(&shdr, 0, sizeof(shdr)); + if (data != NULL) { + shdr.sh_type = SHT_PROGBITS; + shdr.sh_flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR; + } else { + shdr.sh_type = SHT_NOBITS; + shdr.sh_flags = SHF_ALLOC; + } + shdr.sh_addr = addr; + shdr.sh_offset = addr; + shdr.sh_size = size; + + ret = elf_writer_add_section(ew, &shdr, data, name); + + if (ret) + ERROR("Could not add '%s' section.\n", name); + + return ret; +} + +static int +write_elf(const struct rmod_context *ctx, const struct buffer *in, + struct buffer *out) +{ + int i; + int ret; + int bit64; + size_t loc; + size_t rmod_data_size; + struct elf_writer *ew; + struct buffer rmod_data; + struct buffer rmod_header; + struct buffer program; + struct buffer relocs; + Elf64_Xword total_size; + Elf64_Addr addr; + Elf64_Ehdr ehdr; + + bit64 = ctx->pelf.ehdr.e_ident[EI_CLASS] == ELFCLASS64; + + /* + * 3 sections will be added to the ELF file. + * +------------------+ + * | rmodule header | + * +------------------+ + * | program | + * +------------------+ + * | relocations | + * +------------------+ + */ + + /* Create buffer for header and relocations. */ + rmod_data_size = sizeof(struct rmodule_header); + if (bit64) + rmod_data_size += ctx->nrelocs * sizeof(Elf64_Addr); + else + rmod_data_size += ctx->nrelocs * sizeof(Elf32_Addr); + + if (buffer_create(&rmod_data, rmod_data_size, "rmod")) + return -1; + + buffer_splice(&rmod_header, &rmod_data, + 0, sizeof(struct rmodule_header)); + buffer_clone(&relocs, &rmod_data); + buffer_seek(&relocs, sizeof(struct rmodule_header)); + + /* Reset current location. */ + buffer_set_size(&rmod_header, 0); + buffer_set_size(&relocs, 0); + + /* Program contents. */ + buffer_splice(&program, in, ctx->phdr->p_offset, ctx->phdr->p_filesz); + + /* Create ELF writer with modified entry point. */ + memcpy(&ehdr, &ctx->pelf.ehdr, sizeof(ehdr)); + ehdr.e_entry = ctx->entry; + ew = elf_writer_init(&ehdr); + + if (ew == NULL) { + ERROR("Failed to create ELF writer.\n"); + buffer_delete(&rmod_data); + return -1; + } + + /* Write out rmodule_header. */ + ctx->xdr->put16(&rmod_header, RMODULE_MAGIC); + ctx->xdr->put8(&rmod_header, RMODULE_VERSION_1); + ctx->xdr->put8(&rmod_header, 0); + /* payload_begin_offset */ + loc = sizeof(struct rmodule_header); + ctx->xdr->put32(&rmod_header, loc); + /* payload_end_offset */ + loc += ctx->phdr->p_filesz; + ctx->xdr->put32(&rmod_header, loc); + /* relocations_begin_offset */ + ctx->xdr->put32(&rmod_header, loc); + /* relocations_end_offset */ + if (bit64) + loc += ctx->nrelocs * sizeof(Elf64_Addr); + else + loc += ctx->nrelocs * sizeof(Elf32_Addr); + ctx->xdr->put32(&rmod_header, loc); + /* module_link_start_address */ + ctx->xdr->put32(&rmod_header, ctx->link_addr); + /* module_program_size */ + ctx->xdr->put32(&rmod_header, ctx->size); + /* module_entry_point */ + ctx->xdr->put32(&rmod_header, ctx->entry); + /* parameters_begin */ + ctx->xdr->put32(&rmod_header, ctx->parameters_begin); + /* parameters_end */ + ctx->xdr->put32(&rmod_header, ctx->parameters_end); + /* bss_begin */ + ctx->xdr->put32(&rmod_header, ctx->bss_begin); + /* bss_end */ + ctx->xdr->put32(&rmod_header, ctx->bss_end); + /* padding[4] */ + ctx->xdr->put32(&rmod_header, 0); + ctx->xdr->put32(&rmod_header, 0); + ctx->xdr->put32(&rmod_header, 0); + ctx->xdr->put32(&rmod_header, 0); + + /* Write the relocations. */ + for (i = 0; i < ctx->nrelocs; i++) { + if (bit64) + ctx->xdr->put64(&relocs, ctx->emitted_relocs[i]); + else + ctx->xdr->put32(&relocs, ctx->emitted_relocs[i]); + } + + total_size = 0; + addr = 0; + + /* + * There are 2 cases to deal with. The program has a large NOBITS + * section and the relocations can fit entirely within occupied memory + * region for the program. The other is that the relocations increase + * the memory footprint of the program if it was loaded directly into + * the region it would run. The rmdoule header is a fixed cost that + * is considered a part of the program. + */ + total_size += buffer_size(&rmod_header); + if (buffer_size(&relocs) + ctx->phdr->p_filesz > ctx->phdr->p_memsz) { + total_size += buffer_size(&relocs); + total_size += ctx->phdr->p_filesz; + } else { + total_size += ctx->phdr->p_memsz; + } + + ret = add_section(ew, &rmod_header, ".header", addr, + buffer_size(&rmod_header)); + if (ret < 0) + goto out; + addr += buffer_size(&rmod_header); + + ret = add_section(ew, &program, ".program", addr, ctx->phdr->p_filesz); + if (ret < 0) + goto out; + addr += ctx->phdr->p_filesz; + + if (ctx->nrelocs) { + ret = add_section(ew, &relocs, ".relocs", addr, + buffer_size(&relocs)); + if (ret < 0) + goto out; + addr += buffer_size(&relocs); + } + + if (total_size != addr) { + ret = add_section(ew, NULL, ".empty", addr, total_size - addr); + if (ret < 0) + goto out; + } + + /* + * Ensure last section has a memory usage that meets the required + * total size of the program in memory. + */ + + ret = elf_writer_serialize(ew, out); + if (ret < 0) + ERROR("Failed to serialize ELF to buffer.\n"); + +out: + buffer_delete(&rmod_data); + elf_writer_destroy(ew); + + return ret; +} + +int rmodule_create(const struct buffer *elfin, struct buffer *elfout) +{ + struct rmod_context ctx; + struct parsed_elf *pelf; + int i; + int ret; + + ret = -1; + memset(&ctx, 0, sizeof(ctx)); + pelf = &ctx.pelf; + + if (parse_elf(elfin, pelf, ELF_PARSE_ALL)) { + ERROR("Couldn't parse ELF!\n"); + return -1; + } + + /* Only allow executables to be turned into rmodules. */ + if (pelf->ehdr.e_type != ET_EXEC) { + ERROR("ELF is not an executable: %u.\n", pelf->ehdr.e_type); + goto out; + } + + /* Determine if architecture is supported. */ + for (i = 0; i < ARRAY_SIZE(reloc_ops); i++) { + if (reloc_ops[i].arch == pelf->ehdr.e_machine) { + ctx.ops = &reloc_ops[i]; + break; + } + } + + if (ctx.ops == NULL) { + ERROR("ELF is unsupported arch: %u.\n", pelf->ehdr.e_machine); + goto out; + } + + /* Set the endian ops. */ + if (ctx.pelf.ehdr.e_ident[EI_DATA] == ELFDATA2MSB) + ctx.xdr = &xdr_be; + else + ctx.xdr = &xdr_le; + + if (find_program_segment(&ctx)) + goto out; + + if (filter_relocation_sections(&ctx)) + goto out; + + if (collect_relocations(&ctx)) + goto out; + + if (populate_program_info(&ctx)) + goto out; + + if (write_elf(&ctx, elfin, elfout)) + goto out; + + ret = 0; + +out: + free(ctx.emitted_relocs); + parsed_elf_destroy(pelf); + return ret; +} diff --git a/util/cbfstool/rmodule.h b/util/cbfstool/rmodule.h new file mode 100644 index 0000000000..94f8f3d064 --- /dev/null +++ b/util/cbfstool/rmodule.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#ifndef TOOL_RMODULE_H +#define TOOL_RMODULE_H + +#include "elf.h" +#include "common.h" + +/* + * Parse an ELF file within the elfin buffer and fill in the elfout buffer + * with a created rmodule in ELF format. Return 0 on success, < 0 on error. + */ +int rmodule_create(const struct buffer *elfin, struct buffer *elfout); + +#endif /* TOOL_RMODULE_H */ diff --git a/util/cbfstool/xdr.c b/util/cbfstool/xdr.c new file mode 100644 index 0000000000..c29e538279 --- /dev/null +++ b/util/cbfstool/xdr.c @@ -0,0 +1,157 @@ + /* + * cbfstool, CLI utility for CBFS file manipulation + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" + +size_t bgets(struct buffer *input, void *output, size_t len) +{ + len = input->size < len ? input->size : len; + memmove(output, input->data, len); + input->data += len; + input->size -= len; + return len; +} + +size_t bputs(struct buffer *b, const void *data, size_t len) +{ + memmove(&b->data[b->size], data, len); + b->size += len; + return len; +} + +/* The assumption in all this code is that we're given a pointer to enough data. + * Hence, we do not check for underflow. + */ +static uint8_t get8(struct buffer *input) +{ + uint8_t ret = *input->data++; + input->size--; + return ret; +} + +static uint16_t get16be(struct buffer *input) +{ + uint16_t ret; + ret = get8(input)<<8; + ret |= get8(input); + return ret; +} + +static uint32_t get32be(struct buffer *input) +{ + uint32_t ret; + ret = get16be(input)<<16; + ret |= get16be(input); + return ret; +} + +static uint64_t get64be(struct buffer *input) +{ + uint64_t ret; + ret = get32be(input); + ret <<= 32; + ret |= get32be(input); + return ret; +} + +static void put8(struct buffer *input, uint8_t val) +{ + input->data[input->size] = val; + input->size++; +} + +static void put16be(struct buffer *input, uint16_t val) +{ + put8(input, val>>8); + put8(input, val); +} + +static void put32be(struct buffer *input, uint32_t val) +{ + put16be(input, val>>16); + put16be(input, val); +} + +static void put64be(struct buffer *input, uint64_t val) +{ + put32be(input, val>>32); + put32be(input, val); +} + +static uint16_t get16le(struct buffer *input) +{ + uint16_t ret; + ret = get8(input); + ret |= get8(input) << 8; + return ret; +} + +static uint32_t get32le(struct buffer *input) +{ + uint32_t ret; + ret = get16le(input); + ret |= get16le(input) << 16; + return ret; +} + +static uint64_t get64le(struct buffer *input) +{ + uint64_t ret; + uint32_t low; + low = get32le(input); + ret = get32le(input); + ret <<= 32; + ret |= low; + return ret; +} + +static void put16le(struct buffer *input, uint16_t val) +{ + put8(input, val); + put8(input, val>>8); +} + +static void put32le(struct buffer *input, uint32_t val) +{ + put16le(input, val); + put16le(input, val>>16); +} + +static void put64le(struct buffer *input, uint64_t val) +{ + put32le(input, val); + put32le(input, val>>32); +} + +struct xdr xdr_be = { + get8, get16be, get32be, get64be, + put8, put16be, put32be, put64be +}; + +struct xdr xdr_le = { + get8, get16le, get32le, get64le, + put8, put16le, put32le, put64le +}; + diff --git a/util/cbmem/Makefile b/util/cbmem/Makefile index bf74e08bdf..0407af9d38 100644 --- a/util/cbmem/Makefile +++ b/util/cbmem/Makefile @@ -37,7 +37,7 @@ distclean: clean rm -f .dependencies .dependencies: - @$(CC) $(CFLAGS) -MM *.c > .dependencies + @$(CC) $(CFLAGS) $(CPPFLAGS) -MM *.c > .dependencies .PHONY: all clean distclean diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index bc6bd6b9c8..9713ffbf0c 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * Copyright 2012 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,9 +21,14 @@ #include #include #include +#include #include +#include #include #include +#include +#include +#include #include #include #include @@ -35,6 +40,7 @@ #include "boot/coreboot_tables.h" +typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; @@ -42,14 +48,14 @@ typedef uint64_t u64; #include "cbmem.h" #include "timestamp.h" -#define CBMEM_VERSION "1.0" +#define CBMEM_VERSION "1.1" /* verbose output? */ static int verbose = 0; #define debug(x...) if(verbose) printf(x) /* File handle used to access /dev/mem */ -static int fd; +static int mem_fd; /* * calculate ip checksum (16 bit quantities) on a passed in buffer. In case @@ -75,18 +81,45 @@ static u16 ipchcksum(const void *addr, unsigned size) * functions always maps 1MB at a time and can only map one area at once. */ static void *mapped_virtual; -static void *map_memory(u64 physical) +static size_t mapped_size; + +static inline size_t size_to_mib(size_t sz) +{ + return sz >> 20; +} + +static void unmap_memory(void) +{ + if (mapped_virtual == NULL) { + fprintf(stderr, "Error unmapping memory\n"); + return; + } + debug("Unmapping %zuMB of virtual memory at %p.\n", + size_to_mib(mapped_size), mapped_virtual); + munmap(mapped_virtual, mapped_size); + mapped_virtual = NULL; + mapped_size = 0; +} + +static void *map_memory_size(u64 physical, size_t size) { void *v; off_t p; - int page = getpagesize(); + u64 page = getpagesize(); + size_t padding; + + if (mapped_virtual != NULL) + unmap_memory(); /* Mapped memory must be aligned to page size */ p = physical & ~(page - 1); + padding = physical & (page-1); + size += padding; - debug("Mapping 1MB of physical memory at 0x%zx.\n", p); + debug("Mapping %zuMB of physical memory at 0x%jx.\n", + size_to_mib(size), (intmax_t)p); - v = mmap(NULL, MAP_BYTES, PROT_READ, MAP_SHARED, fd, p); + v = mmap(NULL, size, PROT_READ, MAP_SHARED, mem_fd, p); if (v == MAP_FAILED) { fprintf(stderr, "Failed to mmap /dev/mem: %s\n", @@ -96,22 +129,20 @@ static void *map_memory(u64 physical) /* Remember what we actually mapped ... */ mapped_virtual = v; + mapped_size = size; /* ... but return address to the physical memory that was requested */ - v += physical & (page-1); + if (padding) + debug(" ... padding virtual address with 0x%zx bytes.\n", + padding); + v += padding; return v; } -static void unmap_memory(void) +static void *map_memory(u64 physical) { - if (mapped_virtual == NULL) { - fprintf(stderr, "Error unmapping memory\n"); - return; - } - debug("Unmapping 1MB of virtual memory at %p.\n", mapped_virtual); - munmap(mapped_virtual, MAP_BYTES); - mapped_virtual = NULL; + return map_memory_size(physical, MAP_BYTES); } /* @@ -127,13 +158,35 @@ static struct lb_cbmem_ref timestamps; static struct lb_cbmem_ref console; static struct lb_memory_range cbmem; -static int parse_cbtable(u64 address) +/* This is a work-around for a nasty problem introduced by initially having + * pointer sized entries in the lb_cbmem_ref structures. This caused problems + * on 64bit x86 systems because coreboot is 32bit on those systems. + * When the problem was found, it was corrected, but there are a lot of + * systems out there with a firmware that does not produce the right + * lb_cbmem_ref structure. Hence we try to autocorrect this issue here. + */ +static struct lb_cbmem_ref parse_cbmem_ref(struct lb_cbmem_ref *cbmem_ref) +{ + struct lb_cbmem_ref ret; + + ret = *cbmem_ref; + + if (cbmem_ref->size < sizeof(*cbmem_ref)) + ret.cbmem_addr = (uint32_t)ret.cbmem_addr; + + debug(" cbmem_addr = %" PRIx64 "\n", ret.cbmem_addr); + + return ret; +} + +static int parse_cbtable(u64 address, size_t table_size) { int i, found = 0; void *buf; - debug("Looking for coreboot table at %lx\n", address); - buf = map_memory(address); + debug("Looking for coreboot table at %" PRIx64 " %zd bytes.\n", + address, table_size); + buf = map_memory_size(address, table_size); /* look at every 16 bytes within 4K of the base */ @@ -183,12 +236,12 @@ static int parse_cbtable(u64 address) } case LB_TAG_TIMESTAMPS: { debug(" Found timestamp table.\n"); - timestamps = *(struct lb_cbmem_ref *) lbr_p; + timestamps = parse_cbmem_ref((struct lb_cbmem_ref *) lbr_p); continue; } case LB_TAG_CBMEM_CONSOLE: { debug(" Found cbmem console.\n"); - console = *(struct lb_cbmem_ref *) lbr_p; + console = parse_cbmem_ref((struct lb_cbmem_ref *) lbr_p); continue; } case LB_TAG_FORWARD: { @@ -200,7 +253,7 @@ static int parse_cbtable(u64 address) *(struct lb_forward *) lbr_p; debug(" Found forwarding entry.\n"); unmap_memory(); - return parse_cbtable(lbf_p.forward); + return parse_cbtable(lbf_p.forward, table_size); } default: break; @@ -213,6 +266,7 @@ static int parse_cbtable(u64 address) return found; } +#if defined(__i386__) || defined(__x86_64__) /* * read CPU frequency from a sysfs file, return an frequency in Kilohertz as * an int or exit on any error. @@ -252,57 +306,165 @@ static u64 get_cpu_freq_KHz(void) exit(1); } +/* On x86 platforms timestamps are stored + * in CPU cycles (from rdtsc). Hence the + * timestamp divider is the CPU frequency + * in MHz. + */ +u64 arch_convert_raw_ts_entry(u64 ts) +{ + static u64 cpu_freq_mhz = 0; + + if (!cpu_freq_mhz) + cpu_freq_mhz = get_cpu_freq_KHz() / 1000; + + return ts / cpu_freq_mhz; +} + +#else + +/* On non-x86 platforms the timestamp entries + * are not in clock cycles but in usecs + */ +u64 arch_convert_raw_ts_entry(u64 ts) +{ + return ts; +} +#endif + /* * Print an integer in 'normalized' form - with commas separating every three - * decimal orders. The 'comma' parameter indicates if a comma is needed after - * the value is printed. + * decimal orders. */ -static void print_norm(u64 v, int comma) +static void print_norm(u64 v) { - int first_triple = 1; - - if (v > 1000) { + if (v >= 1000) { /* print the higher order sections first */ - print_norm(v / 1000, 1); - first_triple = 0; + print_norm(v / 1000); + printf(",%3.3u", (u32)(v % 1000)); + } else { + printf("%u", (u32)(v % 1000)); } - if (first_triple) - printf("%d", (u32)(v % 1000)); - else - printf("%3.3d", (u32)(v % 1000)); - if (comma) - printf(","); +} + +enum additional_timestamp_id { + // Depthcharge entry IDs start at 1000. + TS_DC_START = 1000, + + TS_RO_PARAMS_INIT = 1001, + TS_RO_VB_INIT = 1002, + TS_RO_VB_SELECT_FIRMWARE = 1003, + TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004, + + TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010, + + TS_VB_SELECT_AND_LOAD_KERNEL = 1020, + + TS_CROSSYSTEM_DATA = 1100, + TS_START_KERNEL = 1101 +}; + +static const struct timestamp_id_to_name { + u32 id; + const char *name; +} timestamp_ids[] = { + { TS_START_ROMSTAGE, "start of rom stage" }, + { TS_BEFORE_INITRAM, "before ram initialization" }, + { TS_AFTER_INITRAM, "after ram initialization" }, + { TS_END_ROMSTAGE, "end of romstage" }, + { TS_START_VBOOT, "start of verified boot" }, + { TS_END_VBOOT, "end of verified boot" }, + { TS_START_COPYRAM, "starting to load ramstage" }, + { TS_END_COPYRAM, "finished loading ramstage" }, + { TS_START_RAMSTAGE, "start of ramstage" }, + { TS_START_BOOTBLOCK, "start of bootblock" }, + { TS_END_BOOTBLOCK, "end of bootblock" }, + { TS_START_COPYROM, "starting to load romstage" }, + { TS_END_COPYROM, "finished loading romstage" }, + { TS_START_ULZMA, "starting LZMA decompress (ignore for x86)" }, + { TS_END_ULZMA, "finished LZMA decompress (ignore for x86)" }, + { TS_DEVICE_ENUMERATE, "device enumeration" }, + { TS_DEVICE_CONFIGURE, "device configuration" }, + { TS_DEVICE_ENABLE, "device enable" }, + { TS_DEVICE_INITIALIZE, "device initialization" }, + { TS_DEVICE_DONE, "device setup done" }, + { TS_CBMEM_POST, "cbmem post" }, + { TS_WRITE_TABLES, "write tables" }, + { TS_LOAD_PAYLOAD, "load payload" }, + { TS_ACPI_WAKE_JUMP, "ACPI wake jump" }, + { TS_SELFBOOT_JUMP, "selfboot jump" }, + + { TS_START_COPYVER, "starting to load verstage" }, + { TS_END_COPYVER, "finished loading verstage" }, + { TS_START_TPMINIT, "starting to initialize TPM" }, + { TS_END_TPMINIT, "finished TPM initialization" }, + { TS_START_VERIFY_SLOT, "starting to verify keyblock/preamble (RSA)" }, + { TS_END_VERIFY_SLOT, "finished verifying keyblock/preamble (RSA)" }, + { TS_START_HASH_BODY, "starting to verify body (load+SHA2+RSA) " }, + { TS_DONE_LOADING, "finished loading body (ignore for x86)" }, + { TS_DONE_HASHING, "finished calculating body hash (SHA2)" }, + { TS_END_HASH_BODY, "finished verifying body signature (RSA)" }, + + { TS_DC_START, "depthcharge start" }, + { TS_RO_PARAMS_INIT, "RO parameter init" }, + { TS_RO_VB_INIT, "RO vboot init" }, + { TS_RO_VB_SELECT_FIRMWARE, "RO vboot select firmware" }, + { TS_RO_VB_SELECT_AND_LOAD_KERNEL, "RO vboot select&load kernel" }, + { TS_RW_VB_SELECT_AND_LOAD_KERNEL, "RW vboot select&load kernel" }, + { TS_VB_SELECT_AND_LOAD_KERNEL, "vboot select&load kernel" }, + { TS_CROSSYSTEM_DATA, "crossystem data" }, + { TS_START_KERNEL, "start kernel" } +}; + +void timestamp_print_entry(uint32_t id, uint64_t stamp, uint64_t prev_stamp) +{ + int i; + const char *name; + + name = ""; + for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) { + if (timestamp_ids[i].id == id) { + name = timestamp_ids[i].name; + break; + } + } + + printf("%4d:", id); + printf("%-50s", name); + print_norm(arch_convert_raw_ts_entry(stamp)); + if (prev_stamp) { + printf(" ("); + print_norm(arch_convert_raw_ts_entry(stamp - prev_stamp)); + printf(")"); + } + printf("\n"); } /* dump the timestamp table */ static void dump_timestamps(void) { int i; - u64 cpu_freq_MHz = get_cpu_freq_KHz() / 1000; struct timestamp_table *tst_p; + size_t size; if (timestamps.tag != LB_TAG_TIMESTAMPS) { fprintf(stderr, "No timestamps found in coreboot table.\n"); return; } - tst_p = (struct timestamp_table *) - map_memory((unsigned long)timestamps.cbmem_addr); + size = sizeof(*tst_p); + tst_p = map_memory_size((unsigned long)timestamps.cbmem_addr, size); printf("%d entries total:\n\n", tst_p->num_entries); + size += tst_p->num_entries * sizeof(tst_p->entries[0]); + + unmap_memory(); + tst_p = map_memory_size((unsigned long)timestamps.cbmem_addr, size); + for (i = 0; i < tst_p->num_entries; i++) { const struct timestamp_entry *tse_p = tst_p->entries + i; - - printf("%4d:", tse_p->entry_id); - print_norm(tse_p->entry_stamp / cpu_freq_MHz, 0); - if (i) { - printf(" ("); - print_norm((tse_p->entry_stamp - - tse_p[-1].entry_stamp) / - cpu_freq_MHz, 0); - printf(")"); - } - printf("\n"); + timestamp_print_entry(tse_p->entry_id, tse_p->entry_stamp, + i ? tse_p[-1].entry_stamp : 0); } unmap_memory(); @@ -313,29 +475,35 @@ static void dump_console(void) { void *console_p; char *console_c; - uint32_t size; + uint32_t size, cursor; if (console.tag != LB_TAG_CBMEM_CONSOLE) { fprintf(stderr, "No console found in coreboot table.\n"); return; } - console_p = map_memory((unsigned long)console.cbmem_addr); + console_p = map_memory_size((unsigned long)console.cbmem_addr, + 2 * sizeof(uint32_t)); /* The in-memory format of the console area is: * u32 size * u32 cursor * char console[size] * Hence we have to add 8 to get to the actual console string. */ - size = *(uint32_t *)console_p; + size = ((uint32_t *)console_p)[0]; + cursor = ((uint32_t *)console_p)[1]; console_c = malloc(size + 1); + unmap_memory(); if (!console_c) { fprintf(stderr, "Not enough memory for console.\n"); exit(1); } + console_p = map_memory_size((unsigned long)console.cbmem_addr, + size + sizeof(size) + sizeof(cursor)); memcpy(console_c, console_p + 8, size); console_c[size] = 0; + console_c[cursor] = 0; printf("%s", console_c); @@ -344,6 +512,83 @@ static void dump_console(void) unmap_memory(); } +static void hexdump(unsigned long memory, int length) +{ + int i; + uint8_t *m; + int all_zero = 0; + + m = map_memory_size((intptr_t)memory, length); + + if (length > MAP_BYTES) { + printf("Truncating hex dump from %d to %d bytes\n\n", + length, MAP_BYTES); + length = MAP_BYTES; + } + + for (i = 0; i < length; i += 16) { + int j; + + all_zero++; + for (j = 0; j < 16; j++) { + if(m[i+j] != 0) { + all_zero = 0; + break; + } + } + + if (all_zero < 2) { + printf("%08lx:", memory + i); + for (j = 0; j < 16; j++) + printf(" %02x", m[i+j]); + printf(" "); + for (j = 0; j < 16; j++) + printf("%c", isprint(m[i+j]) ? m[i+j] : '.'); + printf("\n"); + } else if (all_zero == 2) { + printf("...\n"); + } + } + + unmap_memory(); +} + +static void dump_cbmem_hex(void) +{ + if (cbmem.type != LB_MEM_TABLE) { + fprintf(stderr, "No coreboot CBMEM area found!\n"); + return; + } + + hexdump(unpack_lb64(cbmem.start), unpack_lb64(cbmem.size)); +} + +/* The root region is at least DYN_CBMEM_ALIGN_SIZE . */ +#define DYN_CBMEM_ALIGN_SIZE (4096) +#define ROOT_MIN_SIZE DYN_CBMEM_ALIGN_SIZE +#define CBMEM_POINTER_MAGIC 0xc0389479 +#define CBMEM_ENTRY_MAGIC ~(CBMEM_POINTER_MAGIC) + +struct cbmem_root_pointer { + uint32_t magic; + uint32_t root; +} __attribute__((packed)); + +struct dynamic_cbmem_entry { + uint32_t magic; + uint32_t start; + uint32_t size; + uint32_t id; +} __attribute__((packed)); + +struct cbmem_root { + uint32_t max_entries; + uint32_t num_entries; + uint32_t locked; + uint32_t size; + struct dynamic_cbmem_entry entries[0]; +} __attribute__((packed)); + #define CBMEM_MAGIC 0x434f5245 #define MAX_CBMEM_ENTRIES 16 @@ -352,52 +597,101 @@ struct cbmem_entry { uint32_t id; uint64_t base; uint64_t size; -}; +} __attribute__((packed)); + +static const struct cbmem_id_to_name cbmem_ids[] = { CBMEM_ID_TO_NAME_TABLE }; + +void cbmem_print_entry(int n, uint32_t id, uint64_t base, uint64_t size) +{ + int i; + const char *name; + + name = NULL; + for (i = 0; i < ARRAY_SIZE(cbmem_ids); i++) { + if (cbmem_ids[i].id == id) { + name = cbmem_ids[i].name; + break; + } + } + + printf("%2d. ", n); + if (name == NULL) + printf("%08x ", id); + else + printf("%s", name); + printf(" %08" PRIx64 " ", base); + printf(" %08" PRIx64 "\n", size); +} + +static void dump_static_cbmem_toc(struct cbmem_entry *entries) +{ + int i; + + printf("CBMEM table of contents:\n"); + printf(" ID START LENGTH\n"); + + for (i=0; imax_entries, root->num_entries, root->locked, root->size); + + printf("CBMEM table of contents:\n"); + printf(" ID START LENGTH\n"); + + for (i = 0; i < root->num_entries; i++) { + if(root->entries[i].magic != CBMEM_ENTRY_MAGIC) + break; + cbmem_print_entry(i, root->entries[i].id, + root->entries[i].start, root->entries[i].size); + } +} static void dump_cbmem_toc(void) { - int i; uint64_t start; + void *cbmem_area; struct cbmem_entry *entries; if (cbmem.type != LB_MEM_TABLE) { - fprintf(stderr, "No coreboot table area found!\n"); + fprintf(stderr, "No coreboot CBMEM area found!\n"); return; } start = unpack_lb64(cbmem.start); - entries = (struct cbmem_entry *)map_memory(start); + cbmem_area = map_memory_size(start, unpack_lb64(cbmem.size)); + entries = (struct cbmem_entry *)cbmem_area; - printf("CBMEM table of contents:\n"); - printf(" ID START LENGTH\n"); - for (i=0; imagic == CBMEM_POINTER_MAGIC) { + struct cbmem_root *root; + uint64_t rootaddr = r->root; + unmap_memory(); + root = map_memory_size(rootaddr, ROOT_MIN_SIZE); + dump_dynamic_cbmem_toc(root); + } else + fprintf(stderr, "No valid coreboot CBMEM root pointer found.\n"); } + unmap_memory(); } @@ -523,11 +817,12 @@ static void print_version(void) static void print_usage(const char *name) { - printf("usage: %s [-cCltVvh?]\n", name); + printf("usage: %s [-cCltxVvh?]\n", name); printf("\n" " -c | --console: print cbmem console\n" " -C | --coverage: dump coverage information\n" " -l | --list: print cbmem table of contents\n" + " -x | --hexdump: print hexdump of cbmem area\n" " -t | --timestamps: print timestamp information\n" " -V | --verbose: verbose (debugging) output\n" " -v | --version: print the version\n" @@ -536,15 +831,128 @@ static void print_usage(const char *name) exit(1); } +#ifdef __arm__ +static void dt_update_cells(const char *name, int *addr_cells_ptr, + int *size_cells_ptr) +{ + if (*addr_cells_ptr >= 0 && *size_cells_ptr >= 0) + return; + + int buffer; + size_t nlen = strlen(name); + char *prop = alloca(nlen + sizeof("/#address-cells")); + strcpy(prop, name); + + if (*addr_cells_ptr < 0) { + strcpy(prop + nlen, "/#address-cells"); + int fd = open(prop, O_RDONLY); + if (fd < 0 && errno != ENOENT) { + perror(prop); + } else if (fd >= 0) { + if (read(fd, &buffer, sizeof(int)) < 0) + perror(prop); + else + *addr_cells_ptr = ntohl(buffer); + close(fd); + } + } + + if (*size_cells_ptr < 0) { + strcpy(prop + nlen, "/#size-cells"); + int fd = open(prop, O_RDONLY); + if (fd < 0 && errno != ENOENT) { + perror(prop); + } else if (fd >= 0) { + if (read(fd, &buffer, sizeof(int)) < 0) + perror(prop); + else + *size_cells_ptr = ntohl(buffer); + close(fd); + } + } +} + +static char *dt_find_compat(const char *parent, const char *compat, + int *addr_cells_ptr, int *size_cells_ptr) +{ + char *ret = NULL; + struct dirent *entry; + DIR *dir; + + if (!(dir = opendir(parent))) { + perror(parent); + return NULL; + } + + /* Loop through all files in the directory (DT node). */ + while ((entry = readdir(dir))) { + /* We only care about compatible props or subnodes. */ + if (entry->d_name[0] == '.' || !((entry->d_type & DT_DIR) || + !strcmp(entry->d_name, "compatible"))) + continue; + + /* Assemble the file name (on the stack, for speed). */ + size_t plen = strlen(parent); + char *name = alloca(plen + strlen(entry->d_name) + 2); + + strcpy(name, parent); + name[plen] = '/'; + strcpy(name + plen + 1, entry->d_name); + + /* If it's a subnode, recurse. */ + if (entry->d_type & DT_DIR) { + ret = dt_find_compat(name, compat, addr_cells_ptr, + size_cells_ptr); + + /* There is only one matching node to find, abort. */ + if (ret) { + /* Gather cells values on the way up. */ + dt_update_cells(parent, addr_cells_ptr, + size_cells_ptr); + break; + } + continue; + } + + /* If it's a compatible string, see if it's the right one. */ + int fd = open(name, O_RDONLY); + int clen = strlen(compat); + char *buffer = alloca(clen + 1); + + if (fd < 0) { + perror(name); + continue; + } + + if (read(fd, buffer, clen + 1) < 0) { + perror(name); + close(fd); + continue; + } + close(fd); + + if (!strcmp(compat, buffer)) { + /* Initialize these to "unset" for the way up. */ + *addr_cells_ptr = *size_cells_ptr = -1; + + /* Can't leave string on the stack or we'll lose it! */ + ret = strdup(parent); + break; + } + } + + closedir(dir); + return ret; +} +#endif /* __arm__ */ + int main(int argc, char** argv) { - int j; - static const int possible_base_addresses[] = { 0, 0xf0000 }; - int print_defaults = 1; int print_console = 0; int print_coverage = 0; int print_list = 0; + int print_hexdump = 0; int print_timestamps = 0; int opt, option_index = 0; @@ -553,12 +961,13 @@ int main(int argc, char** argv) {"coverage", 0, 0, 'C'}, {"list", 0, 0, 'l'}, {"timestamps", 0, 0, 't'}, + {"hexdump", 0, 0, 'x'}, {"verbose", 0, 0, 'V'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "cCltVvh?", + while ((opt = getopt_long(argc, argv, "cCltxVvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'c': @@ -573,6 +982,10 @@ int main(int argc, char** argv) print_list = 1; print_defaults = 0; break; + case 'x': + print_hexdump = 1; + print_defaults = 0; + break; case 't': print_timestamps = 1; print_defaults = 0; @@ -593,18 +1006,75 @@ int main(int argc, char** argv) } } - fd = open("/dev/mem", O_RDONLY, 0); - if (fd < 0) { + mem_fd = open("/dev/mem", O_RDONLY, 0); + if (mem_fd < 0) { fprintf(stderr, "Failed to gain memory access: %s\n", strerror(errno)); return 1; } +#ifdef __arm__ + int addr_cells, size_cells; + char *coreboot_node = dt_find_compat("/proc/device-tree", "coreboot", + &addr_cells, &size_cells); + + if (!coreboot_node) { + fprintf(stderr, "Could not find 'coreboot' compatible node!\n"); + return 1; + } + + if (addr_cells < 0) { + fprintf(stderr, "Warning: no #address-cells node in tree!\n"); + addr_cells = 1; + } + + int nlen = strlen(coreboot_node); + char *reg = alloca(nlen + sizeof("/reg")); + + strcpy(reg, coreboot_node); + strcpy(reg + nlen, "/reg"); + free(coreboot_node); + + int fd = open(reg, O_RDONLY); + if (fd < 0) { + perror(reg); + return 1; + } + + int i; + size_t size_to_read = addr_cells * 4 + size_cells * 4; + u8 *dtbuffer = alloca(size_to_read); + if (read(fd, dtbuffer, size_to_read) < 0) { + perror(reg); + return 1; + } + close(fd); + + /* No variable-length byte swap function anywhere in C... how sad. */ + u64 baseaddr = 0; + for (i = 0; i < addr_cells * 4; i++) { + baseaddr <<= 8; + baseaddr |= *dtbuffer; + dtbuffer++; + } + u64 cb_table_size = 0; + for (i = 0; i < size_cells * 4; i++) { + cb_table_size <<= 8; + cb_table_size |= *dtbuffer; + dtbuffer++; + } + + parse_cbtable(baseaddr, cb_table_size); +#else + int j; + static const int possible_base_addresses[] = { 0, 0xf0000 }; + /* Find and parse coreboot table */ for (j = 0; j < ARRAY_SIZE(possible_base_addresses); j++) { - if (parse_cbtable(possible_base_addresses[j])) + if (parse_cbtable(possible_base_addresses[j], MAP_BYTES)) break; } +#endif if (print_console) dump_console(); @@ -615,9 +1085,12 @@ int main(int argc, char** argv) if (print_list) dump_cbmem_toc(); + if (print_hexdump) + dump_cbmem_hex(); + if (print_defaults || print_timestamps) dump_timestamps(); - close(fd); + close(mem_fd); return 0; } diff --git a/util/crossgcc/Makefile b/util/crossgcc/Makefile index da3b36bb15..209ce67426 100644 --- a/util/crossgcc/Makefile +++ b/util/crossgcc/Makefile @@ -3,11 +3,15 @@ all: build build: bash ./buildgcc -G -p i386-elf bash ./buildgcc -G -p armv7a-eabi + bash ./buildgcc -G -p aarch64-elf + bash ./buildgcc -G -p mipsel-elf .PHONY: build-without-gdb build-without-gdb: bash ./buildgcc -p i386-elf bash ./buildgcc -p armv7a-eabi + bash ./buildgcc -p aarch64-elf + bash ./buildgcc -p mipsel-elf clean: rm -rf xgcc diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc index 34518a8027..26e4a6f2c6 100755 --- a/util/crossgcc/buildgcc +++ b/util/crossgcc/buildgcc @@ -33,7 +33,7 @@ GMP_VERSION=5.0.5 MPFR_VERSION=3.1.1 MPC_VERSION=1.0.1 LIBELF_VERSION=0.8.13 -GCC_VERSION=4.7.2 +GCC_VERSION=4.8.1 GCC_AUTOCONF_VERSION=2.64 BINUTILS_VERSION=2.23 GDB_VERSION=7.5 diff --git a/util/exynos/fixed_cksum.py b/util/exynos/fixed_cksum.py new file mode 100755 index 0000000000..66da06025d --- /dev/null +++ b/util/exynos/fixed_cksum.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Copyright (C) 2013 Google Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +""" +This utility computes and fills Exynos ROM checksum (for BL1 or BL2). +(Algorithm from U-Boot: tools/mkexynosspl.c) + +Input: IN OUT DATA_SIZE + +Output: + + IN padded out to DATA_SIZE, checksum at the end, written to OUT. +""" + +import struct +import sys + +def main(argv): + if len(argv) != 4: + exit('usage: %s IN OUT DATA_SIZE' % argv[0]) + + in_name, out_name = argv[1:3] + size = int(argv[3], 0) + checksum_format = " 0xFFFFFFFF: + raise ValueError("invalid base address") + + if base_addr + insize > 0xFFFFFFFF: + raise ValueError("invalid destination range") + + header = create_header(base_addr, insize) + with open(outfname, "wb") as outfp: + outfp.write(header) + outfp.write(image) + +def usage(msg=None): + """Print command usage. + + @arg msg: string, error message if any (default: None) + """ + if msg != None: + sys.stderr.write("%s: %s\n" % (PROG_NAME, msg)) + + print "Usage: %s " % PROG_NAME + + if msg != None: + exit(1) + +def main(): + """Main entry function""" + + if len(sys.argv) != 4: + usage("incorrect number of arguments") + + try: + base_addr = int(sys.argv[1], 0) + infname = sys.argv[2] + outfname = sys.argv[3] + except ValueError as e: + sys.stderr.write("mkheader: invalid base address '%s'\n" % sys.argv[1]) + exit(1) + + try: + mkheader(base_addr, infname, outfname) + except IOError as e: + sys.stderr.write("%s: %s\n" % (PROG_NAME, e)) + exit(1) + except ValueError as e: + sys.stderr.write("%s: %s\n" % (PROG_NAME, e)) + exit(1) + +if __name__ == "__main__": + main() + diff --git a/util/ipqheader/mbncat.py b/util/ipqheader/mbncat.py new file mode 100755 index 0000000000..39c9d80072 --- /dev/null +++ b/util/ipqheader/mbncat.py @@ -0,0 +1,200 @@ +#!/usr/bin/python +# Copyright (c) 2014, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import struct +import sys +import os + +"""A utility to generate ipq8064 uber SBL.. + +The very first blob (aka 'uber SBL') read out of NOR SPI flash by the IPQ8064 +maskrom is supposed to be a concatenation of up to three binaries: one to run +on the RPM, another one to run on the AP, and the third one - the actual +coreboot bootblock. + +The uber SBL starts with the combined header descriptor of 80 bytes, with the +first two 4 byte words set to certain values, and the total size of the +payload saved at offsets 28 and 32. + +To generate the uber SBL this utility expects two or three input file names in +the command line, the first file including the described header, and the +following one(s) - in QCA MBN format. This allows to create the uber SBL in +one or two invocations. + +The input files are concatenated together aligned at 256 byte boundary offset +from the combined header. See Usage() below for more details. + +The resulting uber SBL file is prepended by the same combined header adjusted +to reflect the new total file size. +""" + +DEFAULT_OUTPUT_FILE_NAME = 'sbl-ro.mbn' + +class NorSbl: + """Object representing the uber SBL.""" + + NOR_SBL1_HEADER = ' 3: + Usage(-1) + + nsbl = NorSbl(argv[0], verbose) + + for mbnf in argv[1:]: + nsbl.Append(mbnf) + + nsbl.Create(mbn_output) + +if __name__ == '__main__': + main() diff --git a/util/kconfig/lex.zconf.c_shipped b/util/kconfig/lex.zconf.c_shipped index 6897092b94..3a3cd03d60 100644 --- a/util/kconfig/lex.zconf.c_shipped +++ b/util/kconfig/lex.zconf.c_shipped @@ -5,25 +5,6 @@ /* A lexical scanner generated by flex */ -#define yy_create_buffer zconf_create_buffer -#define yy_delete_buffer zconf_delete_buffer -#define yy_flex_debug zconf_flex_debug -#define yy_init_buffer zconf_init_buffer -#define yy_flush_buffer zconf_flush_buffer -#define yy_load_buffer_state zconf_load_buffer_state -#define yy_switch_to_buffer zconf_switch_to_buffer -#define yyin zconfin -#define yyleng zconfleng -#define yylex zconflex -#define yylineno zconflineno -#define yyout zconfout -#define yyrestart zconfrestart -#define yytext zconftext -#define yywrap zconfwrap -#define yyalloc zconfalloc -#define yyrealloc zconfrealloc -#define yyfree zconffree - #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 @@ -354,7 +335,7 @@ void zconffree (void * ); /* Begin user sect3 */ -#define zconfwrap(n) 1 +#define zconfwrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -1535,7 +1516,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), num_to_read ); + (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -2007,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to zconflex() will * scan from a @e copy of @a str. - * @param str a NUL-terminated string to scan + * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use diff --git a/util/kconfig/lkc_proto.h b/util/kconfig/lkc_proto.h index 4d09f6ddef..8e69461313 100644 --- a/util/kconfig/lkc_proto.h +++ b/util/kconfig/lkc_proto.h @@ -21,7 +21,7 @@ P(menu_get_help,const char *,(struct menu *menu)); /* symbol.c */ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); -P(sym_lookup,struct symbol *,(const char *name, int isconst)); +P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); diff --git a/util/kconfig/lxdialog/inputbox.c b/util/kconfig/lxdialog/inputbox.c index ef4569f8a6..7c3d8182a0 100644 --- a/util/kconfig/lxdialog/inputbox.c +++ b/util/kconfig/lxdialog/inputbox.c @@ -89,7 +89,7 @@ do_resize: box_y = y + 2; box_x = (width - box_width) / 2; draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, - dlg.border.atr, dlg.dialog.atr); + dlg.dialog.atr, dlg.border.atr); print_buttons(dialog, height, width, 0); diff --git a/util/kconfig/menu.c b/util/kconfig/menu.c index 606ceb9e74..07ff8d105c 100644 --- a/util/kconfig/menu.c +++ b/util/kconfig/menu.c @@ -235,18 +235,22 @@ void menu_finalize(struct menu *parent) sym = parent->sym; if (parent->list) { if (sym && sym_is_choice(sym)) { - /* find the first choice value and find out choice type */ - for (menu = parent->list; menu; menu = menu->next) { - if (menu->sym) { - current_entry = parent; - if (sym->type == S_UNKNOWN) + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { menu_set_type(menu->sym->type); - current_entry = menu; - if (menu->sym->type == S_UNKNOWN) - menu_set_type(sym->type); - break; + break; + } } } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } parentdep = expr_alloc_symbol(sym); } else if (parent->prompt) parentdep = parent->prompt->visible.expr; @@ -313,50 +317,36 @@ void menu_finalize(struct menu *parent) } } for (menu = parent->list; menu; menu = menu->next) { - if (sym && sym_is_choice(sym) && menu->sym) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; menu->sym->flags |= SYMBOL_CHOICEVAL; if (!menu->prompt) menu_warn(menu, "choice value must have a prompt"); for (prop = menu->sym->prop; prop; prop = prop->next) { - if (prop->type == P_PROMPT && prop->menu != menu) { - prop_warn(prop, "choice values " - "currently only support a " - "single prompt"); - } if (prop->type == P_DEFAULT) prop_warn(prop, "defaults for choice " - "values not supported"); + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); } - current_entry = menu; - if (menu->sym->type == S_UNKNOWN) - menu_set_type(sym->type); /* Non-tristate choice values of tristate choices must * depend on the choice being set to Y. The choice * values' dependencies were propagated to their * properties above, so the change here must be re- - * propagated. */ + * propagated. + */ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); - basedep = expr_alloc_and(basedep, menu->dep); - basedep = expr_eliminate_dups(basedep); - menu->dep = basedep; + menu->dep = expr_alloc_and(basedep, menu->dep); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->menu != menu) continue; - dep = expr_alloc_and(expr_copy(basedep), - prop->visible.expr); - dep = expr_eliminate_dups(dep); - dep = expr_trans_bool(dep); - prop->visible.expr = dep; - if (prop->type == P_SELECT) { - struct symbol *es = prop_get_symbol(prop); - dep2 = expr_alloc_symbol(menu->sym); - dep = expr_alloc_and(dep2, - expr_copy(dep)); - dep = expr_alloc_or(es->rev_dep.expr, dep); - dep = expr_eliminate_dups(dep); - es->rev_dep.expr = dep; - } + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); } } menu_add_symbol(P_CHOICE, sym, NULL); diff --git a/util/kconfig/symbol.c b/util/kconfig/symbol.c index 2ea30089ca..06e50a0494 100644 --- a/util/kconfig/symbol.c +++ b/util/kconfig/symbol.c @@ -42,7 +42,7 @@ void sym_add_default(struct symbol *sym, const char *def) { struct property *prop = prop_alloc(P_DEFAULT, sym); - prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); } void sym_init(void) @@ -360,9 +360,6 @@ void sym_calc_value(struct symbol *sym) ; } - if (sym->flags & SYMBOL_AUTO) - sym->flags &= ~SYMBOL_WRITE; - sym->curr = newval; if (sym_is_choice(sym) && newval.tri == yes) sym->curr.val = sym_calc_choice(sym); @@ -387,6 +384,9 @@ void sym_calc_value(struct symbol *sym) sym_set_changed(choice_sym); } } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; } void sym_clear_all_valid(void) @@ -661,7 +661,7 @@ bool sym_is_changable(struct symbol *sym) return sym->visible > sym->rev_dep.tri; } -struct symbol *sym_lookup(const char *name, int isconst) +struct symbol *sym_lookup(const char *name, int flags) { struct symbol *symbol; const char *ptr; @@ -681,11 +681,10 @@ struct symbol *sym_lookup(const char *name, int isconst) hash &= 0xff; for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { - if (!strcmp(symbol->name, name)) { - if ((isconst && symbol->flags & SYMBOL_CONST) || - (!isconst && !(symbol->flags & SYMBOL_CONST))) - return symbol; - } + if (!strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; } new_name = strdup(name); } else { @@ -697,8 +696,7 @@ struct symbol *sym_lookup(const char *name, int isconst) memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; - if (isconst) - symbol->flags |= SYMBOL_CONST; + symbol->flags |= flags; symbol->next = symbol_hash[hash]; symbol_hash[hash] = symbol; @@ -772,8 +770,6 @@ struct symbol **sym_re_search(const char *pattern) } -struct symbol *sym_check_deps(struct symbol *sym); - static struct symbol *sym_check_expr_deps(struct expr *e) { struct symbol *sym; @@ -805,6 +801,65 @@ static struct symbol *sym_check_expr_deps(struct expr *e) } /* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + return sym2; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + } + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) { + fprintf(stderr, " -> %s", sym->name); + break; + } + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + return sym2; +} + struct symbol *sym_check_deps(struct symbol *sym) { struct symbol *sym2; @@ -812,33 +867,34 @@ struct symbol *sym_check_deps(struct symbol *sym) if (sym->flags & SYMBOL_CHECK) { fprintf(stderr, "%s:%d:error: found recursive dependency: %s", - sym->prop->file->name, sym->prop->lineno, sym->name); + sym->prop->file->name, sym->prop->lineno, + sym->name ? sym->name : ""); return sym; } if (sym->flags & SYMBOL_CHECKED) return NULL; - sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); - sym2 = sym_check_expr_deps(sym->rev_dep.expr); - if (sym2) - goto out; - - for (prop = sym->prop; prop; prop = prop->next) { - if (prop->type == P_CHOICE || prop->type == P_SELECT) - continue; - sym2 = sym_check_expr_deps(prop->visible.expr); - if (sym2) - goto out; - if (prop->type != P_DEFAULT || sym_is_choice(sym)) - continue; - sym2 = sym_check_expr_deps(prop->expr); - if (sym2) - goto out; + if (sym_is_choice_value(sym)) { + /* for choice groups start the check with main choice symbol */ + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; } -out: - if (sym2) - fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": ""); - sym->flags &= ~SYMBOL_CHECK; + + if (sym2) { + fprintf(stderr, " -> %s", sym->name ? sym->name : ""); + if (sym2 == sym) { + fprintf(stderr, "\n"); + zconfnerrs++; + sym2 = NULL; + } + } + return sym2; } @@ -914,7 +970,7 @@ void prop_add_env(const char *env) } prop = prop_alloc(P_ENV, sym); - prop->expr = expr_alloc_symbol(sym_lookup(env, 1)); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); sym_env_list = expr_alloc_one(E_LIST, sym_env_list); sym_env_list->right.sym = sym; diff --git a/util/kconfig/zconf.tab.c_shipped b/util/kconfig/zconf.tab.c_shipped index 34560605f5..9757250111 100644 --- a/util/kconfig/zconf.tab.c_shipped +++ b/util/kconfig/zconf.tab.c_shipped @@ -445,16 +445,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 258 +#define YYLAST 259 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 45 +#define YYNNTS 46 /* YYNRULES -- Number of rules. */ -#define YYNRULES 108 +#define YYNRULES 110 /* YYNRULES -- Number of states. */ -#define YYNSTATES 178 +#define YYNSTATES 180 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -506,13 +506,14 @@ static const yytype_uint16 yyprhs[] = 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, - 112, 117, 122, 128, 132, 133, 137, 138, 141, 144, - 147, 149, 153, 154, 157, 160, 163, 166, 169, 174, - 178, 181, 186, 187, 190, 194, 196, 200, 201, 204, - 207, 210, 214, 217, 219, 223, 224, 227, 230, 233, - 237, 241, 244, 247, 250, 251, 254, 257, 260, 265, - 266, 269, 271, 273, 276, 279, 282, 284, 287, 288, - 291, 293, 297, 301, 305, 308, 312, 316, 318 + 112, 117, 122, 128, 132, 133, 137, 138, 141, 145, + 148, 150, 154, 155, 158, 161, 164, 167, 170, 175, + 179, 182, 187, 188, 191, 195, 197, 201, 202, 205, + 208, 211, 215, 218, 220, 224, 225, 228, 231, 234, + 238, 242, 245, 248, 251, 252, 255, 258, 261, 266, + 267, 270, 272, 274, 277, 280, 283, 285, 288, 289, + 292, 294, 298, 302, 306, 309, 313, 317, 319, 321, + 322 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ @@ -532,24 +533,25 @@ static const yytype_int8 yyrhs[] = 30, -1, 20, 78, 77, 30, -1, 21, 25, 77, 30, -1, 22, 79, 79, 77, 30, -1, 23, 48, 30, -1, -1, 48, 25, 49, -1, -1, 33, 74, - -1, 7, 30, -1, 50, 54, -1, 75, -1, 51, - 56, 52, -1, -1, 54, 55, -1, 54, 72, -1, - 54, 70, -1, 54, 30, -1, 54, 40, -1, 18, - 74, 77, 30, -1, 19, 73, 30, -1, 17, 30, - -1, 20, 25, 77, 30, -1, -1, 56, 39, -1, - 14, 78, 76, -1, 75, -1, 57, 60, 58, -1, - -1, 60, 39, -1, 60, 64, -1, 60, 53, -1, - 4, 74, 30, -1, 61, 71, -1, 75, -1, 62, - 65, 63, -1, -1, 65, 39, -1, 65, 64, -1, - 65, 53, -1, 6, 74, 30, -1, 9, 74, 30, - -1, 67, 71, -1, 12, 30, -1, 69, 13, -1, - -1, 71, 72, -1, 71, 30, -1, 71, 40, -1, - 16, 24, 78, 30, -1, -1, 74, 77, -1, 25, - -1, 26, -1, 5, 30, -1, 8, 30, -1, 15, - 30, -1, 30, -1, 76, 30, -1, -1, 14, 78, - -1, 79, -1, 79, 33, 79, -1, 79, 27, 79, - -1, 29, 78, 28, -1, 34, 78, -1, 78, 31, - 78, -1, 78, 32, 78, -1, 25, -1, 26, -1 + -1, 7, 80, 30, -1, 50, 54, -1, 75, -1, + 51, 56, 52, -1, -1, 54, 55, -1, 54, 72, + -1, 54, 70, -1, 54, 30, -1, 54, 40, -1, + 18, 74, 77, 30, -1, 19, 73, 30, -1, 17, + 30, -1, 20, 25, 77, 30, -1, -1, 56, 39, + -1, 14, 78, 76, -1, 75, -1, 57, 60, 58, + -1, -1, 60, 39, -1, 60, 64, -1, 60, 53, + -1, 4, 74, 30, -1, 61, 71, -1, 75, -1, + 62, 65, 63, -1, -1, 65, 39, -1, 65, 64, + -1, 65, 53, -1, 6, 74, 30, -1, 9, 74, + 30, -1, 67, 71, -1, 12, 30, -1, 69, 13, + -1, -1, 71, 72, -1, 71, 30, -1, 71, 40, + -1, 16, 24, 78, 30, -1, -1, 74, 77, -1, + 25, -1, 26, -1, 5, 30, -1, 8, 30, -1, + 15, 30, -1, 30, -1, 76, 30, -1, -1, 14, + 78, -1, 79, -1, 79, 33, 79, -1, 79, 27, + 79, -1, 29, 78, 28, -1, 34, 78, -1, 78, + 31, 78, -1, 78, 32, 78, -1, 25, -1, 26, + -1, -1, 25, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -565,7 +567,8 @@ static const yytype_uint16 yyrline[] = 339, 344, 351, 356, 364, 367, 369, 370, 371, 374, 382, 389, 396, 402, 409, 411, 412, 413, 416, 424, 426, 431, 432, 435, 436, 437, 441, 442, 445, 446, - 449, 450, 451, 452, 453, 454, 455, 458, 459 + 449, 450, 451, 452, 453, 454, 455, 458, 459, 462, + 463 }; #endif @@ -589,7 +592,8 @@ static const char *const yytname[] = "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", "help_start", "help", "depends_list", "depends", - "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 + "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", + "word_opt", 0 }; #endif @@ -618,7 +622,8 @@ static const yytype_uint8 yyr1[] = 60, 61, 62, 63, 64, 65, 65, 65, 65, 66, 67, 68, 69, 70, 71, 71, 71, 71, 72, 73, 73, 74, 74, 75, 75, 75, 76, 76, 77, 77, - 78, 78, 78, 78, 78, 78, 78, 79, 79 + 78, 78, 78, 78, 78, 78, 78, 79, 79, 80, + 80 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -628,13 +633,14 @@ static const yytype_uint8 yyr2[] = 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, - 4, 4, 5, 3, 0, 3, 0, 2, 2, 2, + 4, 4, 5, 3, 0, 3, 0, 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, 2, 2, 4, 0, 2, 1, 1, 2, 2, 2, 1, 2, 0, 2, - 1, 3, 3, 3, 2, 3, 3, 1, 1 + 1, 3, 3, 3, 2, 3, 3, 1, 1, 0, + 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -642,69 +648,69 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, 84, 21, 8, 11, 91, 92, 0, 0, 93, 0, - 48, 94, 0, 0, 0, 107, 108, 0, 0, 0, - 100, 95, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 7, 71, 79, 80, 27, 29, 0, - 104, 0, 0, 64, 0, 0, 9, 10, 0, 0, - 0, 0, 89, 0, 0, 0, 44, 0, 37, 36, - 32, 33, 0, 35, 34, 0, 0, 89, 0, 56, - 57, 53, 55, 54, 63, 51, 50, 68, 70, 66, - 69, 65, 86, 87, 85, 76, 78, 74, 77, 73, - 97, 103, 105, 106, 102, 101, 26, 82, 0, 98, - 0, 98, 98, 98, 0, 0, 0, 83, 60, 98, - 0, 98, 0, 0, 0, 38, 90, 0, 0, 98, - 46, 43, 25, 0, 59, 0, 88, 99, 39, 40, - 41, 0, 0, 45, 58, 61, 42, 47 + 110, 0, 94, 0, 0, 0, 107, 108, 0, 0, + 0, 100, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 7, 71, 79, 48, 80, 27, + 29, 0, 104, 0, 0, 64, 0, 0, 9, 10, + 0, 0, 0, 0, 89, 0, 0, 0, 44, 0, + 37, 36, 32, 33, 0, 35, 34, 0, 0, 89, + 0, 56, 57, 53, 55, 54, 63, 51, 50, 68, + 70, 66, 69, 65, 86, 87, 85, 76, 78, 74, + 77, 73, 97, 103, 105, 106, 102, 101, 26, 82, + 0, 98, 0, 98, 98, 98, 0, 0, 0, 83, + 60, 98, 0, 98, 0, 0, 0, 38, 90, 0, + 0, 98, 46, 43, 25, 0, 59, 0, 88, 99, + 39, 40, 41, 0, 0, 45, 58, 61, 42, 47 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 25, 26, 99, 27, 28, 29, 30, - 64, 100, 101, 145, 173, 31, 32, 115, 33, 66, - 111, 67, 34, 119, 35, 68, 36, 37, 127, 38, - 70, 39, 40, 41, 102, 103, 69, 104, 140, 141, - 42, 73, 154, 59, 60 + -1, 1, 2, 25, 26, 101, 27, 28, 29, 30, + 65, 102, 103, 147, 175, 31, 32, 117, 33, 67, + 113, 68, 34, 121, 35, 69, 36, 37, 129, 38, + 71, 39, 40, 41, 104, 105, 70, 106, 142, 143, + 42, 74, 156, 60, 61, 51 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -78 +#define YYPACT_NINF -80 static const yytype_int16 yypact[] = { - -78, 33, 130, -78, -28, 73, 73, 7, 73, 36, - 41, 73, 26, 52, -4, 58, -78, -78, -78, -78, - -78, -78, -78, 90, -78, 94, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, 74, 85, -78, 96, - -78, -78, 131, 134, 147, -78, -78, -4, -4, 193, - -10, -78, 162, 164, 38, 102, 64, 148, 5, 192, - 5, 165, -78, 174, -78, -78, -78, -78, -78, 65, - -78, -4, -4, 174, 103, 103, -78, -78, 175, 185, - 197, 73, 73, -4, 194, 103, -78, 231, -78, -78, - -78, -78, 220, -78, -78, 204, 73, 73, 210, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, 205, -78, -78, -78, -78, -78, -4, 222, - 208, 222, 195, 222, 103, 2, 209, -78, -78, 222, - 211, 222, 199, -4, 212, -78, -78, 213, 214, 222, - 207, -78, -78, 215, -78, 216, -78, 111, -78, -78, - -78, 217, 73, -78, -78, -78, -78, -78 + -80, 2, 132, -80, -13, -1, -1, -2, -1, 9, + 33, -1, 27, 40, -3, 38, -80, -80, -80, -80, + -80, -80, -80, 71, -80, 77, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, 57, 61, -80, 63, + -80, 76, -80, 87, 101, 133, -80, -80, -3, -3, + 195, -6, -80, 136, 149, 39, 104, 65, 150, 5, + 194, 5, 167, -80, 176, -80, -80, -80, -80, -80, + -80, 68, -80, -3, -3, 176, 72, 72, -80, -80, + 177, 187, 78, -1, -1, -3, 196, 72, -80, 222, + -80, -80, -80, -80, 221, -80, -80, 205, -1, -1, + 211, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, 206, -80, -80, -80, -80, -80, + -3, 223, 209, 223, 197, 223, 72, 7, 210, -80, + -80, 223, 212, 223, 201, -3, 213, -80, -80, 214, + 215, 223, 208, -80, -80, 216, -80, 217, -80, 113, + -80, -80, -80, 218, -1, -80, -80, -80, -80, -80 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -78, -78, -78, -78, 121, -35, -78, -78, -78, -78, - 219, -78, -78, -78, -78, -78, -78, -78, -44, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -6, - -78, -78, -78, -78, -78, 183, 218, 21, 143, -5, - 146, 196, 69, -53, -77 + -80, -80, -80, -80, 122, -34, -80, -80, -80, -80, + 220, -80, -80, -80, -80, -80, -80, -80, 59, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, 125, + -80, -80, -80, -80, -80, 183, 219, 22, 142, -5, + 147, 192, 69, -54, -79, -80 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -714,62 +720,62 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -82 static const yytype_int16 yytable[] = { - 46, 47, 43, 49, 79, 80, 52, 134, 135, 6, - 7, 8, 9, 10, 11, 12, 13, 84, 144, 14, - 15, 55, 56, 85, 118, 57, 126, 160, 132, 133, - 58, 110, 161, 3, 123, 24, 123, 48, -28, 88, - 142, -28, -28, -28, -28, -28, -28, -28, -28, -28, - 89, 53, -28, -28, 90, -28, 91, 92, 93, 94, - 95, 96, 120, 97, 128, 88, 50, 159, 98, -49, - -49, 51, -49, -49, -49, -49, 89, 54, -49, -49, - 90, 105, 106, 107, 108, 152, 139, 113, 61, 97, - 124, 62, 124, 131, 109, 63, 81, 82, 44, 45, - 167, 149, -30, 88, 72, -30, -30, -30, -30, -30, - -30, -30, -30, -30, 89, 74, -30, -30, 90, -30, - 91, 92, 93, 94, 95, 96, 75, 97, 55, 56, - -2, 4, 98, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 81, 82, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 7, 8, 23, 10, 11, 12, 13, - 24, 76, 14, 15, 77, -81, 88, 177, -81, -81, - -81, -81, -81, -81, -81, -81, -81, 78, 24, -81, - -81, 90, -81, -81, -81, -81, -81, -81, 114, 117, - 97, 125, 86, 88, 87, 122, -72, -72, -72, -72, - -72, -72, -72, -72, 130, 136, -72, -72, 90, 153, - 156, 157, 158, 116, 121, 137, 129, 97, 163, 143, - 165, 138, 122, 72, 81, 82, 81, 82, 171, 166, - 81, 82, 146, 147, 148, 151, 153, 82, 155, 162, - 172, 164, 168, 169, 170, 174, 175, 176, 65, 112, - 150, 0, 0, 0, 0, 83, 0, 0, 71 + 46, 47, 3, 49, 81, 82, 53, 136, 137, 6, + 7, 8, 9, 10, 11, 12, 13, 43, 146, 14, + 15, 86, 56, 57, 44, 45, 58, 87, 48, 134, + 135, 59, 162, 112, 50, 24, 125, 163, 125, -28, + 90, 144, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 91, 54, -28, -28, 92, -28, 93, 94, 95, + 96, 97, 98, 52, 99, 55, 90, 161, 62, 100, + -49, -49, 63, -49, -49, -49, -49, 91, 64, -49, + -49, 92, 107, 108, 109, 110, 154, 73, 141, 115, + 99, 75, 126, 76, 126, 111, 133, 56, 57, 83, + 84, 169, 140, 151, -30, 90, 77, -30, -30, -30, + -30, -30, -30, -30, -30, -30, 91, 78, -30, -30, + 92, -30, 93, 94, 95, 96, 97, 98, 120, 99, + 128, 79, -2, 4, 100, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 83, 84, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 7, 8, 23, 10, 11, + 12, 13, 24, 80, 14, 15, 88, -81, 90, 179, + -81, -81, -81, -81, -81, -81, -81, -81, -81, 89, + 24, -81, -81, 92, -81, -81, -81, -81, -81, -81, + 116, 119, 99, 127, 122, 90, 130, 124, -72, -72, + -72, -72, -72, -72, -72, -72, 132, 138, -72, -72, + 92, 155, 158, 159, 160, 118, 123, 139, 131, 99, + 165, 145, 167, 148, 124, 73, 83, 84, 83, 84, + 173, 168, 83, 84, 149, 150, 153, 155, 84, 157, + 164, 174, 166, 170, 171, 172, 176, 177, 178, 66, + 114, 152, 85, 0, 0, 0, 0, 0, 0, 72 }; static const yytype_int16 yycheck[] = { - 5, 6, 30, 8, 57, 58, 11, 84, 85, 4, - 5, 6, 7, 8, 9, 10, 11, 27, 95, 14, - 15, 25, 26, 33, 68, 29, 70, 25, 81, 82, - 34, 66, 30, 0, 69, 30, 71, 30, 0, 1, - 93, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 25, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 68, 25, 70, 1, 30, 144, 30, 5, - 6, 30, 8, 9, 10, 11, 12, 25, 14, 15, - 16, 17, 18, 19, 20, 138, 91, 66, 30, 25, - 69, 1, 71, 28, 30, 1, 31, 32, 25, 26, - 153, 106, 0, 1, 30, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 30, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 30, 25, 25, 26, - 0, 1, 30, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 31, 32, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 5, 6, 25, 8, 9, 10, 11, - 30, 30, 14, 15, 30, 0, 1, 172, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 30, 30, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 67, 68, - 25, 70, 30, 1, 30, 30, 4, 5, 6, 7, - 8, 9, 10, 11, 30, 30, 14, 15, 16, 14, - 141, 142, 143, 67, 68, 30, 70, 25, 149, 25, - 151, 24, 30, 30, 31, 32, 31, 32, 159, 30, - 31, 32, 1, 13, 30, 25, 14, 32, 30, 30, - 33, 30, 30, 30, 30, 30, 30, 30, 29, 66, - 107, -1, -1, -1, -1, 59, -1, -1, 40 + 5, 6, 0, 8, 58, 59, 11, 86, 87, 4, + 5, 6, 7, 8, 9, 10, 11, 30, 97, 14, + 15, 27, 25, 26, 25, 26, 29, 33, 30, 83, + 84, 34, 25, 67, 25, 30, 70, 30, 72, 0, + 1, 95, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 30, 25, 25, 1, 146, 30, 30, + 5, 6, 1, 8, 9, 10, 11, 12, 1, 14, + 15, 16, 17, 18, 19, 20, 140, 30, 93, 67, + 25, 30, 70, 30, 72, 30, 28, 25, 26, 31, + 32, 155, 24, 108, 0, 1, 30, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 30, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 69, 25, + 71, 30, 0, 1, 30, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 31, 32, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 30, 0, 1, 174, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 30, + 30, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 68, 69, 25, 71, 69, 1, 71, 30, 4, 5, + 6, 7, 8, 9, 10, 11, 30, 30, 14, 15, + 16, 14, 143, 144, 145, 68, 69, 30, 71, 25, + 151, 25, 153, 1, 30, 30, 31, 32, 31, 32, + 161, 30, 31, 32, 13, 30, 25, 14, 32, 30, + 30, 33, 30, 30, 30, 30, 30, 30, 30, 29, + 67, 109, 60, -1, -1, -1, -1, -1, -1, 40 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -781,19 +787,19 @@ static const yytype_uint8 yystos[] = 20, 21, 22, 25, 30, 38, 39, 41, 42, 43, 44, 50, 51, 53, 57, 59, 61, 62, 64, 66, 67, 68, 75, 30, 25, 26, 74, 74, 30, 74, - 30, 30, 74, 25, 25, 25, 26, 29, 34, 78, - 79, 30, 1, 1, 45, 45, 54, 56, 60, 71, - 65, 71, 30, 76, 30, 30, 30, 30, 30, 78, - 78, 31, 32, 76, 27, 33, 30, 30, 1, 12, - 16, 18, 19, 20, 21, 22, 23, 25, 30, 40, - 46, 47, 69, 70, 72, 17, 18, 19, 20, 30, - 40, 55, 70, 72, 39, 52, 75, 39, 53, 58, - 64, 75, 30, 40, 72, 39, 53, 63, 64, 75, - 30, 28, 78, 78, 79, 79, 30, 30, 24, 74, - 73, 74, 78, 25, 79, 48, 1, 13, 30, 74, - 73, 25, 78, 14, 77, 30, 77, 77, 77, 79, - 25, 30, 30, 77, 30, 77, 30, 78, 30, 30, - 30, 77, 33, 49, 30, 30, 30, 74 + 25, 80, 30, 74, 25, 25, 25, 26, 29, 34, + 78, 79, 30, 1, 1, 45, 45, 54, 56, 60, + 71, 65, 71, 30, 76, 30, 30, 30, 30, 30, + 30, 78, 78, 31, 32, 76, 27, 33, 30, 30, + 1, 12, 16, 18, 19, 20, 21, 22, 23, 25, + 30, 40, 46, 47, 69, 70, 72, 17, 18, 19, + 20, 30, 40, 55, 70, 72, 39, 52, 75, 39, + 53, 58, 64, 75, 30, 40, 72, 39, 53, 63, + 64, 75, 30, 28, 78, 78, 79, 79, 30, 30, + 24, 74, 73, 74, 78, 25, 79, 48, 1, 13, + 30, 74, 73, 25, 78, 14, 77, 30, 77, 77, + 77, 79, 25, 30, 30, 77, 30, 77, 30, 78, + 30, 30, 30, 77, 33, 49, 30, 30, 30, 74 }; #define yyerrok (yyerrstatus = 0) @@ -1780,8 +1786,8 @@ yyreduce: case 48: { - struct symbol *sym = sym_lookup(NULL, 0); - sym->flags |= SYMBOL_CHOICE; + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); @@ -2013,7 +2019,12 @@ yyreduce: case 108: - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 1); free((yyvsp[(1) - (1)].string)); ;} + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 109: + + { (yyval.string) = NULL; ;} break; diff --git a/util/kconfig/zconf.y b/util/kconfig/zconf.y index eac13c326d..fbd9120ad6 100644 --- a/util/kconfig/zconf.y +++ b/util/kconfig/zconf.y @@ -91,7 +91,7 @@ static struct menu *current_menu, *current_entry; %type end %type option_name %type

if_entry menu_entry choice_entry -%type symbol_option_arg +%type symbol_option_arg word_opt %destructor { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -239,10 +239,10 @@ symbol_option_arg: /* choice entry */ -choice: T_CHOICE T_EOL +choice: T_CHOICE word_opt T_EOL { - struct symbol *sym = sym_lookup(NULL, 0); - sym->flags |= SYMBOL_CHOICE; + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); @@ -456,9 +456,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); } ; symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } - | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } ; +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + %% void conf_parse(const char *name) diff --git a/util/mkelfImage/include/elf.h b/util/mkelfImage/include/elf.h index eb9ac1d71e..8a12e7a306 100644 --- a/util/mkelfImage/include/elf.h +++ b/util/mkelfImage/include/elf.h @@ -91,6 +91,8 @@ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_NUM 95 +#define EM_AARCH64 183 /* ARM Aarch64 Architecture */ + /* Values for p_type. */ #define PT_NULL 0 /* Unused entry. */ #define PT_LOAD 1 /* Loadable segment. */ diff --git a/util/nvramtool/Makefile b/util/nvramtool/Makefile index 5f4eff5836..b1cb27cb63 100644 --- a/util/nvramtool/Makefile +++ b/util/nvramtool/Makefile @@ -60,7 +60,7 @@ distclean: clean rm -f .dependencies dep: - @$(CC) -MM *.c > .dependencies + @$(CC) -MM -MG *.c > .dependencies install: $(PROGRAM) mkdir -p $(DESTDIR)$(PREFIX)/sbin diff --git a/util/rockchip/make_idb.py b/util/rockchip/make_idb.py new file mode 100755 index 0000000000..64fb804527 --- /dev/null +++ b/util/rockchip/make_idb.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import struct +import sys +from io import SEEK_SET, SEEK_END + +class IDBTool: + def __init__(self): + print "Initialize IDBTool" + + def p_rc4(self, buf, length): + key = (124,78,3,4,85,5,9,7,45,44,123,56,23,13,23,17) + K = key * 16 + S = [i for i in range(256)] + + j = 0 + for i in range(256): + j = (j + S[i] + K[i]) % 256 + temp = S[i]; S[i] = S[j]; S[j] = temp; + + i = j = k = 0 + for x in range(length): + i = (i+1) % 256 + j = (j + S[i]) % 256 + temp = S[i]; S[i] = S[j]; S[j] = temp + k = (S[i] + S[j]) % 256 + buf[x] = struct.pack('B', ord(buf[x]) ^ S[k]) + + def makeIDB(self, from_file, to_file, rc4_flag = False, align_flag = False): + try: + fin = open(from_file, 'rb') + except: + sys.exit("Failed to open file : " + from_file) + + try: + fin.seek(0, SEEK_END) + if (fin.tell() > 4 * 1024 * 1024): + sys.exit("Input file is more than 4MB") + fin.seek(0) + data = fin.read() + finally: + fin.close() + + data_len = len(data) + SECTOR_SIZE = 512 + PAGE_ALIGN = 4 + sectors = (data_len + 4 - 1) / SECTOR_SIZE + 1 + pages = (sectors - 1) / PAGE_ALIGN + 1 + sectors = pages * PAGE_ALIGN; + + buf = [B'\0'] * sectors * SECTOR_SIZE + buf[:4] = "RK32" + buf[4 : 4+data_len] = data + + idblock = [B'\0'] * 4 * SECTOR_SIZE + blank = [B'\0'] * 4 * SECTOR_SIZE + idblock[:4] = ['\x55', '\xAA', '\xF0', '\x0F'] + + if (not rc4_flag): + idblock[8:12] = struct.pack(" 0x20234bc : blx 0x20244b8
(gdb) -main (bist=0) at src/arch/armv7/bootblock_simple.c:37 +main (bist=0) at src/arch/arm/bootblock_simple.c:37 37 { 1: x/i $pc => 0x20244b8
: push {r3, lr} diff --git a/util/sconfig/lex.yy.c_shipped b/util/sconfig/lex.yy.c_shipped index 1deb75dc17..a98ff52afc 100644 --- a/util/sconfig/lex.yy.c_shipped +++ b/util/sconfig/lex.yy.c_shipped @@ -8,7 +8,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 +#define YY_FLEX_SUBMINOR_VERSION 37 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -141,15 +141,7 @@ typedef unsigned int flex_uint32_t; /* Size of default input buffer. */ #ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else #define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -161,7 +153,12 @@ typedef unsigned int flex_uint32_t; typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif -extern int yyleng; +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; extern FILE *yyin, *yyout; @@ -187,11 +184,6 @@ extern FILE *yyin, *yyout; #define unput(c) yyunput( c, (yytext_ptr) ) -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state @@ -209,7 +201,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - int yy_n_chars; + yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -279,8 +271,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int yyleng; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; @@ -308,7 +300,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); @@ -368,8 +360,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 30 -#define YY_END_OF_BUFFER 31 +#define YY_NUM_RULES 31 +#define YY_END_OF_BUFFER 32 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -379,19 +371,19 @@ struct yy_trans_info }; static yyconst flex_int16_t yy_accept[116] = { 0, - 0, 0, 31, 29, 1, 3, 29, 29, 29, 25, - 25, 23, 26, 29, 26, 26, 26, 29, 29, 29, - 29, 29, 29, 29, 1, 3, 29, 0, 29, 0, - 2, 25, 26, 29, 29, 29, 29, 26, 29, 29, - 29, 29, 29, 18, 29, 29, 29, 7, 29, 29, - 29, 29, 28, 28, 24, 29, 29, 29, 29, 29, - 17, 22, 12, 29, 29, 16, 29, 8, 9, 11, - 29, 29, 27, 4, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 13, 29, 29, - 29, 5, 15, 29, 10, 29, 29, 29, 20, 29, + 0, 0, 32, 30, 1, 3, 30, 30, 30, 26, + 26, 24, 27, 30, 27, 27, 27, 30, 30, 30, + 30, 30, 30, 30, 1, 3, 30, 0, 30, 0, + 2, 26, 27, 30, 30, 30, 30, 27, 30, 30, + 30, 30, 30, 19, 30, 30, 30, 7, 30, 30, + 30, 30, 29, 29, 25, 30, 30, 15, 30, 30, + 18, 23, 12, 30, 30, 17, 30, 8, 9, 11, + 30, 30, 28, 4, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 13, 30, 30, + 30, 5, 16, 30, 10, 30, 30, 30, 21, 30, - 29, 29, 29, 29, 6, 29, 29, 29, 29, 29, - 19, 29, 14, 21, 0 + 30, 30, 30, 30, 6, 30, 30, 30, 30, 30, + 20, 30, 14, 22, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -599,7 +591,7 @@ FILE *yyget_out (void ); void yyset_out (FILE * out_str ); -int yyget_leng (void ); +yy_size_t yyget_leng (void ); char *yyget_text (void ); @@ -641,12 +633,7 @@ static int input (void ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else #define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -888,43 +875,43 @@ YY_RULE_SETUP YY_BREAK case 15: YY_RULE_SETUP -{yylval.number=DOMAIN; return(BUS);} +{yylval.number=CPU; return(BUS);} YY_BREAK case 16: YY_RULE_SETUP -{yylval.number=IRQ; return(RESOURCE);} +{yylval.number=DOMAIN; return(BUS);} YY_BREAK case 17: YY_RULE_SETUP -{yylval.number=DRQ; return(RESOURCE);} +{yylval.number=IRQ; return(RESOURCE);} YY_BREAK case 18: YY_RULE_SETUP -{yylval.number=IO; return(RESOURCE);} +{yylval.number=DRQ; return(RESOURCE);} YY_BREAK case 19: YY_RULE_SETUP -{return(IOAPIC_IRQ);} +{yylval.number=IO; return(RESOURCE);} YY_BREAK case 20: YY_RULE_SETUP -{return(INHERIT);} +{return(IOAPIC_IRQ);} YY_BREAK case 21: YY_RULE_SETUP -{return(SUBSYSTEMID);} +{return(INHERIT);} YY_BREAK case 22: YY_RULE_SETUP -{return(END);} +{return(SUBSYSTEMID);} YY_BREAK case 23: YY_RULE_SETUP -{return(EQUALS);} +{return(END);} YY_BREAK case 24: YY_RULE_SETUP -{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} +{return(EQUALS);} YY_BREAK case 25: YY_RULE_SETUP @@ -936,18 +923,22 @@ YY_RULE_SETUP YY_BREAK case 27: YY_RULE_SETUP -{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} +{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(NUMBER);} YY_BREAK case 28: -/* rule 28 can match eol */ +YY_RULE_SETUP +{yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(PCIINT);} + YY_BREAK +case 29: +/* rule 29 can match eol */ YY_RULE_SETUP {yylval.string = malloc(yyleng-1); strncpy(yylval.string, yytext+1, yyleng-2); yylval.string[yyleng-2]='\0'; return(STRING);} YY_BREAK -case 29: +case 30: YY_RULE_SETUP {yylval.string = malloc(yyleng+1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng]='\0'; return(STRING);} YY_BREAK -case 30: +case 31: YY_RULE_SETUP ECHO; YY_BREAK @@ -1136,21 +1127,21 @@ static int yy_get_next_buffer (void) else { - int num_to_read = + yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { - int new_size = b->yy_buf_size * 2; + yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; @@ -1181,7 +1172,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -1276,7 +1267,7 @@ static int yy_get_next_buffer (void) yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 115); - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) @@ -1291,7 +1282,7 @@ static int yy_get_next_buffer (void) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; + register yy_size_t number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = @@ -1340,7 +1331,7 @@ static int yy_get_next_buffer (void) else { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) @@ -1500,10 +1491,6 @@ static void yy_load_buffer_state (void) yyfree((void *) b ); } -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. @@ -1616,7 +1603,7 @@ void yypop_buffer_state (void) */ static void yyensure_buffer_stack (void) { - int num_to_alloc; + yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { @@ -1713,7 +1700,7 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) * * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; @@ -1800,7 +1787,7 @@ FILE *yyget_out (void) /** Get the length of the current token. * */ -int yyget_leng (void) +yy_size_t yyget_leng (void) { return yyleng; } diff --git a/util/sconfig/main.c b/util/sconfig/main.c index c3f2cdf872..cd2782883e 100644 --- a/util/sconfig/main.c +++ b/util/sconfig/main.c @@ -266,6 +266,10 @@ struct device *new_device(struct device *parent, struct device *busdev, const in new_d->path = ".type=DEVICE_PATH_CPU_CLUSTER,{.cpu_cluster={ .cluster = 0x%x }}"; break; + case CPU: + new_d->path = ".type=DEVICE_PATH_CPU,{.cpu={ .id = 0x%x }}"; + break; + case DOMAIN: new_d->path = ".type=DEVICE_PATH_DOMAIN,{.domain={ .domain = 0x%x }}"; break; diff --git a/util/sconfig/sconfig.l b/util/sconfig/sconfig.l index 3e9535ef4e..37d487cb65 100755 --- a/util/sconfig/sconfig.l +++ b/util/sconfig/sconfig.l @@ -39,6 +39,7 @@ pnp {yylval.number=PNP; return(BUS);} i2c {yylval.number=I2C; return(BUS);} lapic {yylval.number=APIC; return(BUS);} cpu_cluster {yylval.number=CPU_CLUSTER; return(BUS);} +cpu {yylval.number=CPU; return(BUS);} domain {yylval.number=DOMAIN; return(BUS);} irq {yylval.number=IRQ; return(RESOURCE);} drq {yylval.number=DRQ; return(RESOURCE);} diff --git a/util/sconfig/sconfig.tab.c_shipped b/util/sconfig/sconfig.tab.c_shipped index 3a56ac86fd..12f5ca2dac 100644 --- a/util/sconfig/sconfig.tab.c_shipped +++ b/util/sconfig/sconfig.tab.c_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.7.12-4996" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 @@ -93,10 +91,13 @@ static struct device *cur_parent, *cur_bus; -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -106,11 +107,17 @@ static struct device *cur_parent, *cur_bus; # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "sconfig.tab.h_shipped". */ +#ifndef YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED +# define YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; #endif - /* Tokens. */ #ifndef YYTOKENTYPE @@ -133,21 +140,21 @@ static struct device *cur_parent, *cur_bus; I2C = 270, APIC = 271, CPU_CLUSTER = 272, - DOMAIN = 273, - IRQ = 274, - DRQ = 275, - IO = 276, - NUMBER = 277, - SUBSYSTEMID = 278, - INHERIT = 279, - IOAPIC_IRQ = 280, - IOAPIC = 281, - PCIINT = 282 + CPU = 273, + DOMAIN = 274, + IRQ = 275, + DRQ = 276, + IO = 277, + NUMBER = 278, + SUBSYSTEMID = 279, + INHERIT = 280, + IOAPIC_IRQ = 281, + IOAPIC = 282, + PCIINT = 283 }; #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { @@ -165,6 +172,23 @@ typedef union YYSTYPE # define YYSTYPE_IS_DECLARED 1 #endif +extern YYSTYPE yylval; + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED */ /* Copy the second part of user declarations. */ @@ -221,24 +245,33 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +# define __attribute__(Spec) /* empty */ # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif + /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -274,6 +307,7 @@ YYID (yyi) # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -365,20 +399,20 @@ union yyalloc #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ while (YYID (0)) # endif # endif @@ -387,10 +421,10 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 37 +#define YYLAST 39 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 28 +#define YYNTOKENS 29 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 13 /* YYNRULES -- Number of rules. */ @@ -400,7 +434,7 @@ union yyalloc /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 282 +#define YYMAXUTOK 283 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -436,7 +470,7 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27 + 25, 26, 27, 28 }; #if YYDEBUG @@ -452,14 +486,14 @@ static const yytype_uint8 yyprhs[] = /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 29, 0, -1, -1, 30, 33, -1, 31, 35, -1, - 31, 33, -1, 31, 38, -1, -1, 32, 35, -1, - 32, 33, -1, 32, 37, -1, 32, 39, -1, 32, - 40, -1, -1, -1, 3, 12, 34, 31, 9, -1, - -1, 4, 7, 22, 6, 36, 32, 9, -1, 8, - 22, 10, 22, -1, 5, 12, 10, 12, -1, 23, - 22, 22, -1, 23, 22, 22, 24, -1, 25, 22, - 27, 22, -1 + 30, 0, -1, -1, 31, 34, -1, 32, 36, -1, + 32, 34, -1, 32, 39, -1, -1, 33, 36, -1, + 33, 34, -1, 33, 38, -1, 33, 40, -1, 33, + 41, -1, -1, -1, 3, 12, 35, 32, 9, -1, + -1, 4, 7, 23, 6, 37, 33, 9, -1, 8, + 23, 10, 23, -1, 5, 12, 10, 12, -1, 24, + 23, 23, -1, 24, 23, 23, 25, -1, 26, 23, + 28, 23, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -471,17 +505,17 @@ static const yytype_uint8 yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "CHIP", "DEVICE", "REGISTER", "BOOL", "BUS", "RESOURCE", "END", "EQUALS", "HEX", "STRING", "PCI", "PNP", "I2C", - "APIC", "CPU_CLUSTER", "DOMAIN", "IRQ", "DRQ", "IO", "NUMBER", + "APIC", "CPU_CLUSTER", "CPU", "DOMAIN", "IRQ", "DRQ", "IO", "NUMBER", "SUBSYSTEMID", "INHERIT", "IOAPIC_IRQ", "IOAPIC", "PCIINT", "$accept", "devtree", "$@1", "chipchildren", "devicechildren", "chip", "@2", - "device", "@3", "resource", "registers", "subsystemid", "ioapic_irq", 0 + "device", "@3", "resource", "registers", "subsystemid", "ioapic_irq", YY_NULL }; #endif @@ -492,16 +526,16 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282 + 275, 276, 277, 278, 279, 280, 281, 282, 283 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 28, 30, 29, 31, 31, 31, 31, 32, 32, - 32, 32, 32, 32, 34, 33, 36, 35, 37, 38, - 39, 39, 40 + 0, 29, 31, 30, 32, 32, 32, 32, 33, 33, + 33, 33, 33, 33, 35, 34, 37, 36, 38, 39, + 40, 40, 41 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -533,21 +567,21 @@ static const yytype_int8 yydefgoto[] = /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -9 +#define YYPACT_NINF -10 static const yytype_int8 yypact[] = { - -9, 3, 1, -9, -2, -9, -9, -9, 4, 5, - -1, -9, -9, -9, -9, -8, 7, 9, 6, -9, - -9, -9, -3, 2, -9, 8, 10, -9, -9, -9, - -9, -9, 11, 12, -4, 13, -5, 14, -9, -9, - -9 + -10, 3, 1, -10, -2, -10, -10, -10, 4, 5, + -1, -10, -10, -10, -10, -9, 7, 9, 6, -10, + -10, -10, -3, -4, -10, 2, 8, -10, -10, -10, + -10, -10, 10, 11, 0, 12, 13, 14, -10, -10, + -10 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -9, -9, -9, -9, -9, -6, -9, 15, -9, -9, - -9, -9, -9 + -10, -10, -10, -10, -10, -6, -10, 17, -10, -10, + -10, -10, -10 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -557,34 +591,34 @@ static const yytype_int8 yypgoto[] = static const yytype_uint8 yytable[] = { 4, 9, 12, 3, 4, 23, 24, 4, 9, 10, - 6, 16, 15, 11, 17, 19, 27, 18, 20, 39, - 25, 35, 26, 37, 32, 0, 0, 0, 0, 0, - 33, 0, 34, 0, 36, 38, 40, 28 + 6, 16, 15, 11, 17, 19, 27, 18, 20, 32, + 35, 25, 0, 26, 0, 33, 0, 0, 37, 0, + 0, 34, 0, 0, 36, 38, 0, 40, 39, 28 }; -#define yypact_value_is_default(yystate) \ - ((yystate) == (-9)) +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-10))) -#define yytable_value_is_error(yytable_value) \ +#define yytable_value_is_error(Yytable_value) \ YYID (0) static const yytype_int8 yycheck[] = { 3, 4, 8, 0, 3, 8, 9, 3, 4, 5, - 12, 12, 7, 9, 22, 6, 22, 10, 12, 24, - 23, 10, 25, 27, 22, -1, -1, -1, -1, -1, - 22, -1, 22, -1, 22, 22, 22, 22 + 12, 12, 7, 9, 23, 6, 22, 10, 12, 23, + 10, 24, -1, 26, -1, 23, -1, -1, 28, -1, + -1, 23, -1, -1, 23, 23, -1, 23, 25, 22 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 29, 30, 0, 3, 33, 12, 34, 31, 4, - 5, 9, 33, 35, 38, 7, 12, 22, 10, 6, - 12, 36, 32, 8, 9, 23, 25, 33, 35, 37, - 39, 40, 22, 22, 22, 10, 22, 27, 22, 24, - 22 + 0, 30, 31, 0, 3, 34, 12, 35, 32, 4, + 5, 9, 34, 36, 39, 7, 12, 23, 10, 6, + 12, 37, 33, 8, 9, 24, 26, 34, 36, 38, + 40, 41, 23, 23, 23, 10, 23, 28, 23, 25, + 23 }; #define yyerrok (yyerrstatus = 0) @@ -614,62 +648,35 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - /* This macro is provided for backward compatibility. */ - #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else @@ -719,6 +726,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) YYSTYPE const * const yyvaluep; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT @@ -727,11 +736,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) # else YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -970,12 +975,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULL; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1035,11 +1039,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } } } @@ -1059,10 +1065,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, # undef YYCASE_ } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } if (*yymsg_alloc < yysize) { @@ -1118,36 +1126,26 @@ yydestruct (yymsg, yytype, yyvaluep) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YYUSE (yytype); } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; + +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1187,7 +1185,7 @@ yyparse () `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1205,7 +1203,7 @@ yyparse () int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1223,9 +1221,8 @@ yyparse () Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1234,14 +1231,6 @@ yyparse () yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1382,7 +1371,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1653,7 +1644,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -1677,7 +1670,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -1721,4 +1714,3 @@ yyreturn: - diff --git a/util/sconfig/sconfig.tab.h_shipped b/util/sconfig/sconfig.tab.h_shipped index be65179901..11d792835b 100644 --- a/util/sconfig/sconfig.tab.h_shipped +++ b/util/sconfig/sconfig.tab.h_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +30,15 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED +# define YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -52,21 +61,21 @@ I2C = 270, APIC = 271, CPU_CLUSTER = 272, - DOMAIN = 273, - IRQ = 274, - DRQ = 275, - IO = 276, - NUMBER = 277, - SUBSYSTEMID = 278, - INHERIT = 279, - IOAPIC_IRQ = 280, - IOAPIC = 281, - PCIINT = 282 + CPU = 273, + DOMAIN = 274, + IRQ = 275, + DRQ = 276, + IO = 277, + NUMBER = 278, + SUBSYSTEMID = 279, + INHERIT = 280, + IOAPIC_IRQ = 281, + IOAPIC = 282, + PCIINT = 283 }; #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { @@ -86,4 +95,18 @@ typedef union YYSTYPE extern YYSTYPE yylval; +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_YY_BUILD_RAMBI_TMP_PORTAGE_SYS_BOOT_COREBOOT_9999_WORK_COREBOOT_9999_UTIL_SCONFIG_SCONFIG_TAB_H_SHIPPED_INCLUDED */ diff --git a/util/sconfig/sconfig.y b/util/sconfig/sconfig.y index 8ea702ec90..ba450b89c5 100755 --- a/util/sconfig/sconfig.y +++ b/util/sconfig/sconfig.y @@ -30,7 +30,7 @@ static struct device *cur_parent, *cur_bus; int number; } -%token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC CPU_CLUSTER DOMAIN IRQ DRQ IO NUMBER SUBSYSTEMID INHERIT IOAPIC_IRQ IOAPIC PCIINT +%token CHIP DEVICE REGISTER BOOL BUS RESOURCE END EQUALS HEX STRING PCI PNP I2C APIC CPU_CLUSTER CPU DOMAIN IRQ DRQ IO NUMBER SUBSYSTEMID INHERIT IOAPIC_IRQ IOAPIC PCIINT %% devtree: { cur_parent = cur_bus = head; } chip { postprocess_devtree(); } ; diff --git a/util/scripts/convert.sh b/util/scripts/convert.sh new file mode 100755 index 0000000000..b08d3178c7 --- /dev/null +++ b/util/scripts/convert.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# This file is part of the coreboot project. +# +# Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. +# +# Use this file to convert intel microcode represented as an assembler source +# (with `dd h' in each line) into a C source (each number +# represented as `0x, ', four per line. +# +# convert.sh 'intel asm file' > 'coreboot C file' +# + +awk ' +BEGIN { n = 0 }; +{ sub(";.*", ""); } + /^dd / { + sub ("^dd 0","dd "); + sub ("h.*$","", $2); + printf (" 0x%s,", $2); + n = n + 1; + if (n ==4) { + printf ("\n"); + n = 0; + } +}' $1 diff --git a/util/scripts/xml_converter.sh b/util/scripts/xml_converter.sh new file mode 100755 index 0000000000..e783392bc7 --- /dev/null +++ b/util/scripts/xml_converter.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# This script is a filter processing XML files. +# +# Processing is as follows: +# +# - get rid of DOS line ends; +# - place each opening tag on a separate line, with no leading spaces and the +# first attribute definition following the tag name; +# - place each attribute definition on a separate line, starting with a space; +# +# usage: +# xml_converter.sh '' > '' +# +cat $1 | sed 's/>\n